2.5
[blender.git] / source / blender / editors / transform / transform_conversions.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #ifndef WIN32
31 #include <unistd.h>
32 #else
33 #include <io.h>
34 #endif
35 #include <string.h>
36 #include <math.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_action_types.h"
41 #include "DNA_armature_types.h"
42 #include "DNA_camera_types.h"
43 #include "DNA_curve_types.h"
44 #include "DNA_effect_types.h"
45 #include "DNA_image_types.h"
46 #include "DNA_ipo_types.h"
47 #include "DNA_key_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_lattice_types.h"
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_meta_types.h"
53 #include "DNA_modifier_types.h"
54 #include "DNA_nla_types.h"
55 #include "DNA_node_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_object_force.h"
58 #include "DNA_particle_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_space_types.h"
62 #include "DNA_texture_types.h"
63 #include "DNA_view3d_types.h"
64 #include "DNA_world_types.h"
65 #include "DNA_userdef_types.h"
66 #include "DNA_property_types.h"
67 #include "DNA_vfont_types.h"
68 #include "DNA_constraint_types.h"
69 #include "DNA_listBase.h"
70 #include "DNA_gpencil_types.h"
71
72 #include "BKE_action.h"
73 #include "BKE_armature.h"
74 #include "BKE_blender.h"
75 #include "BKE_cloth.h"
76 #include "BKE_context.h"
77 #include "BKE_curve.h"
78 #include "BKE_constraint.h"
79 #include "BKE_depsgraph.h"
80 #include "BKE_displist.h"
81 #include "BKE_DerivedMesh.h"
82 #include "BKE_effect.h"
83 #include "BKE_font.h"
84 #include "BKE_global.h"
85 #include "BKE_ipo.h"
86 #include "BKE_lattice.h"
87 #include "BKE_key.h"
88 #include "BKE_main.h"
89 #include "BKE_mball.h"
90 #include "BKE_mesh.h"
91 #include "BKE_modifier.h"
92 #include "BKE_object.h"
93 #include "BKE_particle.h"
94 #include "BKE_pointcache.h"
95 #include "BKE_softbody.h"
96 #include "BKE_utildefines.h"
97 #include "BKE_bmesh.h"
98 #include "BKE_context.h"
99
100 //#include "BIF_editaction.h"
101 //#include "BIF_editview.h"
102 //#include "BIF_editlattice.h"
103 //#include "BIF_editconstraint.h"
104 //#include "BIF_editmesh.h"
105 //#include "BIF_editnla.h"
106 //#include "BIF_editsima.h"
107 //#include "BIF_editparticle.h"
108 #include "BIF_gl.h"
109 //#include "BIF_keyframing.h"
110 //#include "BIF_poseobject.h"
111 //#include "BIF_meshtools.h"
112 //#include "BIF_mywindow.h"
113 //#include "BIF_resources.h"
114 #include "BIF_retopo.h"
115 //#include "BIF_screen.h"
116 //#include "BIF_space.h"
117 //#include "BIF_toolbox.h"
118
119 #include "ED_armature.h"
120 #include "ED_types.h"
121 #include "ED_anim_api.h"
122 #include "ED_keyframing.h"
123 #include "ED_keyframes_edit.h"
124 #include "ED_view3d.h"
125 #include "ED_mesh.h"
126
127 #include "UI_view2d.h"
128
129 //#include "BSE_drawipo.h"
130 //#include "BSE_edit.h"
131 //#include "BSE_editipo.h"
132 //#include "BSE_editipo_types.h"
133 //#include "BSE_editaction_types.h"
134
135 //#include "BDR_drawaction.h"           // list of keyframes in action
136 //#include "BDR_editobject.h"           // reset_slowparents()
137 //#include "BDR_gpencil.h"
138 //#include "BDR_unwrapper.h"
139
140 #include "BLI_arithb.h"
141 #include "BLI_blenlib.h"
142 #include "BLI_editVert.h"
143
144 //#include "editmesh.h"
145 //
146 //#include "blendef.h"
147 //
148 //#include "mydevice.h"
149
150 extern ListBase editelems;
151
152 #include "transform.h"
153
154 #include "BLO_sys_types.h" // for intptr_t support
155
156 /************ STUBS TO GET COMPILE ************/
157 void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
158
159
160
161 /* local function prototype - for Object/Bone Constraints */
162 static short constraints_list_needinv(TransInfo *t, ListBase *list);
163
164 /* ************************** Functions *************************** */
165
166 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
167         TransData pivot = *head;
168         TransData *ihead = head;
169         TransData *itail = tail;
170         short connected = t->flag & T_PROP_CONNECTED;
171
172         while (head < tail)
173         {
174                 if (connected) {
175                         while ((tail->dist >= pivot.dist) && (head < tail))
176                                 tail--;
177                 }
178                 else {
179                         while ((tail->rdist >= pivot.rdist) && (head < tail))
180                                 tail--;
181                 }
182
183                 if (head != tail)
184                 {
185                         *head = *tail;
186                         head++;
187                 }
188
189                 if (connected) {
190                         while ((head->dist <= pivot.dist) && (head < tail))
191                                 head++;
192                 }
193                 else {
194                         while ((head->rdist <= pivot.rdist) && (head < tail))
195                                 head++;
196                 }
197
198                 if (head != tail)
199                 {
200                         *tail = *head;
201                         tail--;
202                 }
203         }
204
205         *head = pivot;
206         if (ihead < head) {
207                 qsort_trans_data(t, ihead, head-1);
208         }
209         if (itail > head) {
210                 qsort_trans_data(t, head+1, itail);
211         }
212 }
213
214 void sort_trans_data_dist(TransInfo *t) {
215         TransData *start = t->data;
216         int i = 1;
217
218         while(i < t->total && start->flag & TD_SELECTED) {
219                 start++;
220                 i++;
221         }
222         qsort_trans_data(t, start, t->data + t->total - 1);
223 }
224
225 static void sort_trans_data(TransInfo *t) 
226 {
227         TransData *sel, *unsel;
228         TransData temp;
229         unsel = t->data;
230         sel = t->data;
231         sel += t->total - 1;
232         while (sel > unsel) {
233                 while (unsel->flag & TD_SELECTED) {
234                         unsel++;
235                         if (unsel == sel) {
236                                 return;
237                         }
238                 }
239                 while (!(sel->flag & TD_SELECTED)) {
240                         sel--;
241                         if (unsel == sel) {
242                                 return;
243                         }
244                 }
245                 temp = *unsel;
246                 *unsel = *sel;
247                 *sel = temp;
248                 sel--;
249                 unsel++;
250         }
251 }
252
253 /* distance calculated from not-selected vertex to nearest selected vertex
254    warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
255 static void set_prop_dist(TransInfo *t, short with_dist)
256 {
257         TransData *tob;
258         int a;
259
260         for(a=0, tob= t->data; a<t->total; a++, tob++) {
261                 
262                 tob->rdist= 0.0f; // init, it was mallocced
263                 
264                 if((tob->flag & TD_SELECTED)==0) {
265                         TransData *td;
266                         int i;
267                         float dist, vec[3];
268
269                         tob->rdist = -1.0f; // signal for next loop
270                                 
271                         for (i = 0, td= t->data; i < t->total; i++, td++) {
272                                 if(td->flag & TD_SELECTED) {
273                                         VecSubf(vec, tob->center, td->center);
274                                         Mat3MulVecfl(tob->mtx, vec);
275                                         dist = Normalize(vec);
276                                         if (tob->rdist == -1.0f) {
277                                                 tob->rdist = dist;
278                                         }
279                                         else if (dist < tob->rdist) {
280                                                 tob->rdist = dist;
281                                         }
282                                 }
283                                 else break;     // by definition transdata has selected items in beginning
284                         }
285                         if (with_dist) {
286                                 tob->dist = tob->rdist;
287                         }
288                 }       
289         }
290 }
291
292 /* ************************** CONVERSIONS ************************* */
293
294 /* ********************* texture space ********* */
295
296 static void createTransTexspace(bContext *C, TransInfo *t)
297 {
298         Scene *scene = CTX_data_scene(C);
299         TransData *td;
300         Object *ob;
301         ID *id;
302         int *texflag;
303         
304         ob = OBACT;
305         
306         if (ob == NULL) { // Shouldn't logically happen, but still...
307                 t->total = 0;
308                 return;
309         }
310
311         id = ob->data;
312         if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
313                 t->total = 0;
314                 return;
315         }
316
317         t->total = 1;
318         td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
319         td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
320         
321         td->flag= TD_SELECTED;
322         VECCOPY(td->center, ob->obmat[3]);
323         td->ob = ob;
324         
325         Mat3CpyMat4(td->mtx, ob->obmat);
326         Mat3CpyMat4(td->axismtx, ob->obmat);
327         Mat3Ortho(td->axismtx);
328         Mat3Inv(td->smtx, td->mtx);
329         
330         if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
331                 *texflag &= ~AUTOSPACE;
332         }
333         
334         VECCOPY(td->iloc, td->loc);
335         VECCOPY(td->ext->irot, td->ext->rot);
336         VECCOPY(td->ext->isize, td->ext->size);
337 }
338
339 /* ********************* edge (for crease) ***** */
340
341 static void createTransEdge(bContext *C, TransInfo *t) {
342 #if 0   // TRANSFORM_FIX_ME
343         TransData *td = NULL;
344         EditEdge *eed;
345         float mtx[3][3], smtx[3][3];
346         int count=0, countsel=0;
347         int propmode = t->flag & T_PROP_EDIT;
348
349         for(eed= em->edges.first; eed; eed= eed->next) {
350                 if(eed->h==0) {
351                         if (eed->f & SELECT) countsel++;
352                         if (propmode) count++;
353                 }
354         }
355
356         if (countsel == 0)
357                 return;
358
359         if(propmode) {
360                 t->total = count;
361         }
362         else {
363                 t->total = countsel;
364         }
365
366         td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
367
368         Mat3CpyMat4(mtx, t->obedit->obmat);
369         Mat3Inv(smtx, mtx);
370
371         for(eed= em->edges.first; eed; eed= eed->next) {
372                 if(eed->h==0 && (eed->f & SELECT || propmode)) {
373                         /* need to set center for center calculations */
374                         VecAddf(td->center, eed->v1->co, eed->v2->co);
375                         VecMulf(td->center, 0.5f);
376
377                         td->loc= NULL;
378                         if (eed->f & SELECT)
379                                 td->flag= TD_SELECTED;
380                         else 
381                                 td->flag= 0;
382
383
384                         Mat3CpyMat3(td->smtx, smtx);
385                         Mat3CpyMat3(td->mtx, mtx);
386
387                         td->ext = NULL;
388                         td->tdi = NULL;
389                         if (t->mode == TFM_BWEIGHT) {
390                                 td->val = &(eed->bweight);
391                                 td->ival = eed->bweight;
392                         }
393                         else {
394                                 td->val = &(eed->crease);
395                                 td->ival = eed->crease;
396                         }
397
398                         td++;
399                 }
400         }
401 #endif
402 }
403
404 /* ********************* pose mode ************* */
405
406 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
407 {
408         bConstraint *con= pchan->constraints.first;
409         
410         for(;con; con= con->next) {
411                 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
412                         bKinematicConstraint *data= con->data;
413                         
414                         if(data->tar==NULL) 
415                                 return data;
416                         if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0) 
417                                 return data;
418                 }
419         }
420         return NULL;
421 }
422
423 static short apply_targetless_ik(Object *ob)
424 {
425         bPoseChannel *pchan, *parchan, *chanlist[256];
426         bKinematicConstraint *data;
427         int segcount, apply= 0;
428         
429         /* now we got a difficult situation... we have to find the
430            target-less IK pchans, and apply transformation to the all 
431            pchans that were in the chain */
432         
433         for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
434                 data= has_targetless_ik(pchan);
435                 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
436                         
437                         /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
438                         segcount= 0;
439                         
440                         /* exclude tip from chain? */
441                         if(!(data->flag & CONSTRAINT_IK_TIP))
442                                 parchan= pchan->parent;
443                         else
444                                 parchan= pchan;
445                         
446                         /* Find the chain's root & count the segments needed */
447                         for (; parchan; parchan=parchan->parent){
448                                 chanlist[segcount]= parchan;
449                                 segcount++;
450                                 
451                                 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
452                         }
453                         for(;segcount;segcount--) {
454                                 Bone *bone;
455                                 float rmat[4][4], tmat[4][4], imat[4][4];
456                                 
457                                 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK  */
458                                 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
459                                 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat  */
460                                 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
461                                 
462                                 parchan= chanlist[segcount-1];
463                                 bone= parchan->bone;
464                                 bone->flag |= BONE_TRANSFORM;   /* ensures it gets an auto key inserted */
465                                 
466                                 if(parchan->parent) {
467                                         Bone *parbone= parchan->parent->bone;
468                                         float offs_bone[4][4];
469                                         
470                                         /* offs_bone =  yoffs(b-1) + root(b) + bonemat(b) */
471                                         Mat4CpyMat3(offs_bone, bone->bone_mat);
472                                         
473                                         /* The bone's root offset (is in the parent's coordinate system) */
474                                         VECCOPY(offs_bone[3], bone->head);
475                                         
476                                         /* Get the length translation of parent (length along y axis) */
477                                         offs_bone[3][1]+= parbone->length;
478                                         
479                                         /* pose_mat(b-1) * offs_bone */
480                                         if(parchan->bone->flag & BONE_HINGE) {
481                                                 /* the rotation of the parent restposition */
482                                                 Mat4CpyMat4(rmat, parbone->arm_mat);    /* rmat used as temp */
483                                                 
484                                                 /* the location of actual parent transform */
485                                                 VECCOPY(rmat[3], offs_bone[3]);
486                                                 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
487                                                 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
488                                                 
489                                                 Mat4MulMat4(tmat, offs_bone, rmat);
490                                         }
491                                         else if(parchan->bone->flag & BONE_NO_SCALE) {
492                                                 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
493                                                 Mat4Ortho(tmat);
494                                         }
495                                         else
496                                                 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
497                                         
498                                         Mat4Invert(imat, tmat);
499                                 }
500                                 else {
501                                         Mat4CpyMat3(tmat, bone->bone_mat);
502
503                                         VECCOPY(tmat[3], bone->head);
504                                         Mat4Invert(imat, tmat);
505                                 }
506                                 /* result matrix */
507                                 Mat4MulMat4(rmat, parchan->pose_mat, imat);
508                                 
509                                 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
510                                 {
511                                         float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
512                                         
513                                         Mat3CpyMat4(rmat3, rmat);
514                                         
515                                         /* quaternion */
516                                         Mat3ToQuat(rmat3, parchan->quat);
517                                         
518                                         /* for size, remove rotation */
519                                         /* causes problems with some constraints (so apply only if needed) */
520                                         if (data->flag & CONSTRAINT_IK_STRETCH) {
521                                                 QuatToMat3(parchan->quat, qmat);
522                                                 Mat3Inv(imat, qmat);
523                                                 Mat3MulMat3(smat, rmat3, imat);
524                                                 Mat3ToSize(smat, parchan->size);
525                                         }
526                                         
527                                         /* causes problems with some constraints (e.g. childof), so disable this */
528                                         /* as it is IK shouldn't affect location directly */
529                                         /* VECCOPY(parchan->loc, rmat[3]); */
530                                 }
531                                 
532                         }
533                         
534                         apply= 1;
535                         data->flag &= ~CONSTRAINT_IK_AUTO;
536                 }
537         }               
538         
539         return apply;
540 }
541
542 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
543 {
544         Bone *bone= pchan->bone;
545         float pmat[3][3], omat[3][3];
546         float cmat[3][3], tmat[3][3];
547         float vec[3];
548
549         VECCOPY(vec, pchan->pose_mat[3]);
550         VECCOPY(td->center, vec);
551         
552         td->ob = ob;
553         td->flag= TD_SELECTED|TD_USEQUAT;
554         if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
555         {
556                 td->flag |= TD_NOCENTER;
557         }
558         
559         if (bone->flag & BONE_TRANSFORM_CHILD)
560         {
561                 td->flag |= TD_NOCENTER;
562                 td->flag |= TD_NO_LOC;
563         }
564         
565         td->protectflag= pchan->protectflag;
566         
567         td->loc = pchan->loc;
568         VECCOPY(td->iloc, pchan->loc);
569         
570         td->ext->rot= NULL;
571         td->ext->quat= pchan->quat;
572         td->ext->size= pchan->size;
573
574         QUATCOPY(td->ext->iquat, pchan->quat);
575         VECCOPY(td->ext->isize, pchan->size);
576
577         /* proper way to get parent transform + own transform + constraints transform */
578         Mat3CpyMat4(omat, ob->obmat);
579         
580         if(pchan->parent) {      
581                 if(pchan->bone->flag & BONE_HINGE)       
582                         Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);         
583                 else     
584                         Mat3CpyMat4(pmat, pchan->parent->pose_mat);
585                 
586                 if (constraints_list_needinv(t, &pchan->constraints)) {
587                         Mat3CpyMat4(tmat, pchan->constinv);
588                         Mat3Inv(cmat, tmat);
589                         Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0);    // dang mulserie swaps args
590                 }
591                 else
592                         Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0);    // dang mulserie swaps args
593         }
594         else {
595                 if (constraints_list_needinv(t, &pchan->constraints)) {
596                         Mat3CpyMat4(tmat, pchan->constinv);
597                         Mat3Inv(cmat, tmat);
598                         Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0);    // dang mulserie swaps args
599                 }
600                 else 
601                         Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat);  // Mat3MulMat3 has swapped args! 
602         }
603         
604         Mat3Inv(td->smtx, td->mtx);
605         
606         /* for axismat we use bone's own transform */
607         Mat3CpyMat4(pmat, pchan->pose_mat);
608         Mat3MulMat3(td->axismtx, omat, pmat);
609         Mat3Ortho(td->axismtx);
610         
611         if(t->mode==TFM_BONESIZE) {
612                 bArmature *arm= t->poseobj->data;
613                 
614                 if(arm->drawtype==ARM_ENVELOPE) {
615                         td->loc= NULL;
616                         td->val= &bone->dist;
617                         td->ival= bone->dist;
618                 }
619                 else {
620                         // abusive storage of scale in the loc pointer :)
621                         td->loc= &bone->xwidth;
622                         VECCOPY (td->iloc, td->loc);
623                         td->val= NULL;
624                 }
625         }
626         
627         /* in this case we can do target-less IK grabbing */
628         if(t->mode==TFM_TRANSLATION) {
629                 bKinematicConstraint *data= has_targetless_ik(pchan);
630                 if(data) {
631                         if(data->flag & CONSTRAINT_IK_TIP) {
632                                 VECCOPY(data->grabtarget, pchan->pose_tail);
633                         }
634                         else {
635                                 VECCOPY(data->grabtarget, pchan->pose_head);
636                         }
637                         td->loc = data->grabtarget;
638                         VECCOPY(td->iloc, td->loc);
639                         data->flag |= CONSTRAINT_IK_AUTO;
640                         
641                         /* only object matrix correction */
642                         Mat3CpyMat3 (td->mtx, omat);
643                         Mat3Inv (td->smtx, td->mtx);
644                 }
645         }
646         
647         /* store reference to first constraint */
648         td->con= pchan->constraints.first;
649 }
650
651 static void bone_children_clear_transflag(TransInfo *t, ListBase *lb)
652 {
653         Bone *bone= lb->first;
654         
655         for(;bone;bone= bone->next) {
656                 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
657                 {
658                         bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
659                 }
660                 else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)) 
661                 {
662                         bone->flag |= BONE_TRANSFORM_CHILD;
663                 }
664                 else
665                 {
666                         bone->flag &= ~BONE_TRANSFORM;
667                 }
668
669                 bone_children_clear_transflag(t, &bone->childbase);
670         }
671 }
672
673 /* sets transform flags in the bones, returns total */
674 static void set_pose_transflags(TransInfo *t, Object *ob)
675 {
676         bArmature *arm= ob->data;
677         bPoseChannel *pchan;
678         Bone *bone;
679         int hastranslation;
680         
681         t->total= 0;
682         
683         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
684                 bone= pchan->bone;
685                 if(bone->layer & arm->layer) {
686                         if(bone->flag & BONE_SELECTED)
687                                 bone->flag |= BONE_TRANSFORM;
688                         else
689                                 bone->flag &= ~BONE_TRANSFORM;
690
691                         bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
692                         bone->flag &= ~BONE_TRANSFORM_CHILD;
693                 }
694         }
695         
696         /* make sure no bone can be transformed when a parent is transformed */
697         /* since pchans are depsgraph sorted, the parents are in beginning of list */
698         if(t->mode!=TFM_BONESIZE) {
699                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
700                         bone= pchan->bone;
701                         if(bone->flag & BONE_TRANSFORM)
702                                 bone_children_clear_transflag(t, &bone->childbase);
703                 }
704         }       
705         /* now count, and check if we have autoIK or have to switch from translate to rotate */
706         hastranslation= 0;
707
708         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
709                 bone= pchan->bone;
710                 if(bone->flag & BONE_TRANSFORM) {
711
712                         t->total++;
713                         
714                         if(t->mode==TFM_TRANSLATION) {
715                                 if( has_targetless_ik(pchan)==NULL ) {
716                                         if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
717                                                 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
718                                                         hastranslation= 1;
719                                         }
720                                         else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
721                                                 hastranslation= 1;
722                                 }
723                                 else
724                                         hastranslation= 1;
725                         }
726                 }
727         }
728
729         /* if there are no translatable bones, do rotation */
730         if(t->mode==TFM_TRANSLATION && !hastranslation)
731                 t->mode= TFM_ROTATION;
732 }
733
734
735 /* -------- Auto-IK ---------- */
736
737 /* adjust pose-channel's auto-ik chainlen */
738 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
739 {
740         bConstraint *con;
741         
742         /* don't bother to search if no valid constraints */
743         if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
744                 return;
745         
746         /* check if pchan has ik-constraint */
747         for (con= pchan->constraints.first; con; con= con->next) {
748                 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
749                         bKinematicConstraint *data= con->data;
750                         
751                         /* only accept if a temporary one (for auto-ik) */
752                         if (data->flag & CONSTRAINT_IK_TEMP) {
753                                 /* chainlen is new chainlen, but is limited by maximum chainlen */
754                                 if ((chainlen==0) || (chainlen > data->max_rootbone))
755                                         data->rootbone= data->max_rootbone;
756                                 else
757                                         data->rootbone= chainlen;
758                         }
759                 }
760         }
761 }
762
763 /* change the chain-length of auto-ik */
764 void transform_autoik_update (TransInfo *t, short mode)
765 {
766         short *chainlen= &t->scene->toolsettings->autoik_chainlen;
767         bPoseChannel *pchan;
768         
769         /* mode determines what change to apply to chainlen */
770         if (mode == 1) {
771                 /* mode=1 is from WHEELMOUSEDOWN... increases len */
772                 (*chainlen)++;
773         }
774         else if (mode == -1) {
775                 /* mode==-1 is from WHEELMOUSEUP... decreases len */
776                 if (*chainlen > 0) (*chainlen)--;
777         }
778         
779         /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
780         if (ELEM(NULL, t->poseobj, t->poseobj->pose))
781                 return;
782         
783         /* apply to all pose-channels */
784         for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
785                 pchan_autoik_adjust(pchan, *chainlen);
786         }       
787 }
788
789 /* frees temporal IKs */
790 static void pose_grab_with_ik_clear(Object *ob)
791 {
792         bKinematicConstraint *data;
793         bPoseChannel *pchan;
794         bConstraint *con, *next;
795         
796         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
797                 /* clear all temporary lock flags */
798                 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
799                 
800                 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
801                 /* remove all temporary IK-constraints added */
802                 for (con= pchan->constraints.first; con; con= next) {
803                         next= con->next;
804                         if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
805                                 data= con->data;
806                                 if (data->flag & CONSTRAINT_IK_TEMP) {
807                                         BLI_remlink(&pchan->constraints, con);
808                                         MEM_freeN(con->data);
809                                         MEM_freeN(con);
810                                         continue;
811                                 }
812                                 pchan->constflag |= PCHAN_HAS_IK;
813                                 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
814                                         pchan->constflag |= PCHAN_HAS_TARGET;
815                         }
816                 }
817         }
818 }
819
820 /* adds the IK to pchan - returns if added */
821 static short pose_grab_with_ik_add(bPoseChannel *pchan)
822 {
823         bKinematicConstraint *data;
824         bConstraint *con;
825         bConstraint *targetless = 0;
826         
827         /* Sanity check */
828         if (pchan == NULL) 
829                 return 0;
830         
831         /* Rule: not if there's already an IK on this channel */
832         for (con= pchan->constraints.first; con; con= con->next) {
833                 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
834                         bKinematicConstraint *data= con->data;
835                         if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) {
836                                 targetless = con;
837                                 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
838                                 if (con->enforce!=0.0) {
839                                         targetless->flag |= CONSTRAINT_IK_AUTO;
840                                         return 0;
841                                 }
842                         }
843                         if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0))
844                                 return 0;
845                 }
846         }
847         
848         // TRANSFORM_FIX_ME
849         //con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
850         BLI_addtail(&pchan->constraints, con);
851         pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET);    /* for draw, but also for detecting while pose solving */
852         data= con->data;
853         if (targetless) { /* if exists use values from last targetless IK-constraint as base */
854                 *data = *((bKinematicConstraint*)targetless->data);
855         }
856         else
857                 data->flag= CONSTRAINT_IK_TIP;
858         data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
859         VECCOPY(data->grabtarget, pchan->pose_tail);
860         data->rootbone= 1;
861         
862         /* we include only a connected chain */
863         while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
864                 /* here, we set ik-settings for bone from pchan->protectflag */
865                 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
866                 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
867                 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
868                 
869                 /* now we count this pchan as being included */
870                 data->rootbone++;
871                 pchan= pchan->parent;
872         }
873         
874         /* make a copy of maximum chain-length */
875         data->max_rootbone= data->rootbone;
876         
877         return 1;
878 }
879
880 /* bone is a candidate to get IK, but we don't do it if it has children connected */
881 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
882 {
883         Bone *bonec;
884         short wentdeeper=0, added=0;
885
886         /* go deeper if children & children are connected */
887         for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
888                 if (bonec->flag & BONE_CONNECTED) {
889                         wentdeeper= 1;
890                         added+= pose_grab_with_ik_children(pose, bonec);
891                 }
892         }
893         if (wentdeeper==0) {
894                 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
895                 if (pchan)
896                         added+= pose_grab_with_ik_add(pchan);
897         }
898         
899         return added;
900 }
901
902 /* main call which adds temporal IK chains */
903 static short pose_grab_with_ik(Object *ob)
904 {
905         bArmature *arm;
906         bPoseChannel *pchan, *parent;
907         Bone *bonec;
908         short tot_ik= 0;
909         
910         if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
911                 return 0;
912                 
913         arm = ob->data;
914         
915         /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
916         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
917                 if (pchan->bone->layer & arm->layer) {
918                         if (pchan->bone->flag & BONE_SELECTED) {
919                                 /* Rule: no IK for solitatry (unconnected) bones */
920                                 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
921                                         if (bonec->flag & BONE_CONNECTED) {
922                                                 break;
923                                         }
924                                 }
925                                 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
926                                         continue;
927                                 
928                                 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
929                                 if (pchan->parent) {
930                                         /* only adds if there's no IK yet (and no parent bone was selected) */
931                                         for (parent= pchan->parent; parent; parent= parent->parent) {
932                                                 if (parent->bone->flag & BONE_SELECTED)
933                                                         break;
934                                         }
935                                         if (parent == NULL)
936                                                 tot_ik += pose_grab_with_ik_add(pchan);
937                                 }
938                                 else {
939                                         /* rule: go over the children and add IK to the tips */
940                                         tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
941                                 }
942                         }
943                 }
944         }
945         
946         return (tot_ik) ? 1 : 0;
947 }       
948
949
950 /* only called with pose mode active object now */
951 static void createTransPose(bContext *C, TransInfo *t, Object *ob)
952 {
953         // TRANSFORM_FIX_ME
954 #if 0
955         bArmature *arm;
956         bPoseChannel *pchan;
957         TransData *td;
958         TransDataExtension *tdx;
959         short ik_on= 0;
960         int i;
961         
962         t->total= 0;
963         
964         /* check validity of state */
965         arm=get_armature (ob);
966         if (arm==NULL || ob->pose==NULL) return;
967         
968         if (arm->flag & ARM_RESTPOS) {
969                 if(ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
970                         notice("Pose edit not possible while Rest Position is enabled");
971                         return;
972                 }
973         }
974         if (!(ob->lay & G.vd->lay)) return;
975
976         /* do we need to add temporal IK chains? */
977         if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
978                 ik_on= pose_grab_with_ik(ob);
979                 if (ik_on) t->flag |= T_AUTOIK;
980         }
981         
982         /* set flags and count total (warning, can change transform to rotate) */
983         set_pose_transflags(t, ob);
984         
985         if(t->total==0) return;
986
987         t->flag |= T_POSE;
988         t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
989         
990         /* make sure the lock is set OK, unlock can be accidentally saved? */
991         ob->pose->flag |= POSE_LOCKED;
992         ob->pose->flag &= ~POSE_DO_UNLOCK;
993
994         /* init trans data */
995     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
996     tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
997         for(i=0; i<t->total; i++, td++, tdx++) {
998                 td->ext= tdx;
999                 td->tdi = NULL;
1000                 td->val = NULL;
1001         }       
1002         
1003         /* use pose channels to fill trans data */
1004         td= t->data;
1005         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1006                 if(pchan->bone->flag & BONE_TRANSFORM) {
1007                         add_pose_transdata(t, pchan, ob, td);
1008                         td++;
1009                 }
1010         }
1011         
1012         if(td != (t->data+t->total)) printf("Bone selection count error\n");
1013         
1014         /* initialise initial auto=ik chainlen's? */
1015         if (ik_on) transform_autoik_update(t, 0);
1016 #endif
1017 }
1018
1019 /* ********************* armature ************** */
1020
1021 static void createTransArmatureVerts(bContext *C, TransInfo *t)
1022 {
1023         EditBone *ebo;
1024         bArmature *arm= t->obedit->data;
1025         ListBase *edbo = arm->edbo;
1026         TransData *td;
1027         float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1028
1029         t->total = 0;
1030         for (ebo = edbo->first; ebo; ebo = ebo->next)
1031         {
1032                 if(ebo->layer & arm->layer)
1033                 {
1034                         if (t->mode==TFM_BONESIZE)
1035                         {
1036                                 if (ebo->flag & BONE_SELECTED)
1037                                         t->total++;
1038                         }
1039                         else if (t->mode==TFM_BONE_ROLL)
1040                         {
1041                                 if (ebo->flag & BONE_SELECTED)
1042                                         t->total++;
1043                         }
1044                         else
1045                         {
1046                                 if (ebo->flag & BONE_TIPSEL)
1047                                         t->total++;
1048                                 if (ebo->flag & BONE_ROOTSEL)
1049                                         t->total++;
1050                         }
1051                 }
1052         }
1053
1054     if (!t->total) return;
1055         
1056         Mat3CpyMat4(mtx, t->obedit->obmat);
1057         Mat3Inv(smtx, mtx);
1058
1059     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1060         
1061         for (ebo = edbo->first; ebo; ebo = ebo->next)
1062         {
1063                 ebo->oldlength = ebo->length;   // length==0.0 on extrude, used for scaling radius of bone points
1064                 
1065                 if(ebo->layer & arm->layer) {
1066                         if (t->mode==TFM_BONE_ENVELOPE)
1067                         {
1068                                 if (ebo->flag & BONE_ROOTSEL)
1069                                 {
1070                                         td->val= &ebo->rad_head;
1071                                         td->ival= *td->val;
1072                                         
1073                                         VECCOPY (td->center, ebo->head);
1074                                         td->flag= TD_SELECTED;
1075                                         
1076                                         Mat3CpyMat3(td->smtx, smtx);
1077                                         Mat3CpyMat3(td->mtx, mtx);
1078                                         
1079                                         td->loc = NULL;
1080                                         td->ext = NULL;
1081                                         td->tdi = NULL;
1082                                         
1083                                         td++;
1084                                 }
1085                                 if (ebo->flag & BONE_TIPSEL)
1086                                 {
1087                                         td->val= &ebo->rad_tail;
1088                                         td->ival= *td->val;
1089                                         VECCOPY (td->center, ebo->tail);
1090                                         td->flag= TD_SELECTED;
1091                                         
1092                                         Mat3CpyMat3(td->smtx, smtx);
1093                                         Mat3CpyMat3(td->mtx, mtx);
1094                                         
1095                                         td->loc = NULL;
1096                                         td->ext = NULL;
1097                                         td->tdi = NULL;
1098                                         
1099                                         td++;
1100                                 }
1101                                 
1102                         }
1103                         else if (t->mode==TFM_BONESIZE)
1104                         {
1105                                 if (ebo->flag & BONE_SELECTED) {
1106                                         if(arm->drawtype==ARM_ENVELOPE)
1107                                         {
1108                                                 td->loc= NULL;
1109                                                 td->val= &ebo->dist;
1110                                                 td->ival= ebo->dist;
1111                                         }
1112                                         else
1113                                         {
1114                                                 // abusive storage of scale in the loc pointer :)
1115                                                 td->loc= &ebo->xwidth;
1116                                                 VECCOPY (td->iloc, td->loc);
1117                                                 td->val= NULL;
1118                                         }
1119                                         VECCOPY (td->center, ebo->head);
1120                                         td->flag= TD_SELECTED;
1121                                         
1122                                         /* use local bone matrix */
1123                                         VecSubf(delta, ebo->tail, ebo->head);   
1124                                         vec_roll_to_mat3(delta, ebo->roll, bonemat);
1125                                         Mat3MulMat3(td->mtx, mtx, bonemat);
1126                                         Mat3Inv(td->smtx, td->mtx);
1127                                         
1128                                         Mat3CpyMat3(td->axismtx, td->mtx);
1129                                         Mat3Ortho(td->axismtx);
1130
1131                                         td->ext = NULL;
1132                                         td->tdi = NULL;
1133                                         
1134                                         td++;
1135                                 }
1136                         }
1137                         else if (t->mode==TFM_BONE_ROLL)
1138                         {
1139                                 if (ebo->flag & BONE_SELECTED)
1140                                 {
1141                                         td->loc= NULL;
1142                                         td->val= &(ebo->roll);
1143                                         td->ival= ebo->roll;
1144                                         
1145                                         VECCOPY (td->center, ebo->head);
1146                                         td->flag= TD_SELECTED;
1147
1148                                         td->ext = NULL;
1149                                         td->tdi = NULL;
1150                                         
1151                                         td++;
1152                                 }
1153                         }
1154                         else
1155                         {
1156                                 if (ebo->flag & BONE_TIPSEL)
1157                                 {
1158                                         VECCOPY (td->iloc, ebo->tail);
1159                                         VECCOPY (td->center, td->iloc);
1160                                         td->loc= ebo->tail;
1161                                         td->flag= TD_SELECTED;
1162                                         if (ebo->flag & BONE_EDITMODE_LOCKED)
1163                                                 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1164
1165                                         Mat3CpyMat3(td->smtx, smtx);
1166                                         Mat3CpyMat3(td->mtx, mtx);
1167
1168                                         VecSubf(delta, ebo->tail, ebo->head);   
1169                                         vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1170
1171                                         if ((ebo->flag & BONE_ROOTSEL) == 0)
1172                                         {
1173                                                 td->extra = ebo;
1174                                         }
1175
1176                                         td->ext = NULL;
1177                                         td->tdi = NULL;
1178                                         td->val = NULL;
1179
1180                                         td++;
1181                                 }
1182                                 if (ebo->flag & BONE_ROOTSEL)
1183                                 {
1184                                         VECCOPY (td->iloc, ebo->head);
1185                                         VECCOPY (td->center, td->iloc);
1186                                         td->loc= ebo->head;
1187                                         td->flag= TD_SELECTED;
1188                                         if (ebo->flag & BONE_EDITMODE_LOCKED)
1189                                                 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1190
1191                                         Mat3CpyMat3(td->smtx, smtx);
1192                                         Mat3CpyMat3(td->mtx, mtx);
1193
1194                                         VecSubf(delta, ebo->tail, ebo->head);   
1195                                         vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1196
1197                                         td->extra = ebo; /* to fix roll */
1198
1199                                         td->ext = NULL;
1200                                         td->tdi = NULL;
1201                                         td->val = NULL;
1202
1203                                         td++;
1204                                 }
1205                         }
1206                 }
1207         }
1208 }
1209
1210 /* ********************* meta elements ********* */
1211
1212 static void createTransMBallVerts(bContext *C, TransInfo *t)
1213 {
1214         // TRANSFORM_FIX_ME
1215 #if 0
1216         MetaElem *ml;
1217         TransData *td;
1218         TransDataExtension *tx;
1219         float mtx[3][3], smtx[3][3];
1220         int count=0, countsel=0;
1221         int propmode = t->flag & T_PROP_EDIT;
1222
1223         /* count totals */
1224         for(ml= editelems.first; ml; ml= ml->next) {
1225                 if(ml->flag & SELECT) countsel++;
1226                 if(propmode) count++;
1227         }
1228
1229         /* note: in prop mode we need at least 1 selected */
1230         if (countsel==0) return;
1231         
1232         if(propmode) t->total = count; 
1233         else t->total = countsel;
1234         
1235         td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1236         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1237
1238         Mat3CpyMat4(mtx, t->obedit->obmat);
1239         Mat3Inv(smtx, mtx);
1240     
1241         for(ml= editelems.first; ml; ml= ml->next) {
1242                 if(propmode || (ml->flag & SELECT)) {
1243                         td->loc= &ml->x;
1244                         VECCOPY(td->iloc, td->loc);
1245                         VECCOPY(td->center, td->loc);
1246
1247                         if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1248                         else td->flag= TD_USEQUAT;
1249
1250                         Mat3CpyMat3(td->smtx, smtx);
1251                         Mat3CpyMat3(td->mtx, mtx);
1252
1253                         td->ext = tx;
1254                         td->tdi = NULL;
1255
1256                         /* Radius of MetaElem (mass of MetaElem influence) */
1257                         if(ml->flag & MB_SCALE_RAD){
1258                                 td->val = &ml->rad;
1259                                 td->ival = ml->rad;
1260                         }
1261                         else{
1262                                 td->val = &ml->s;
1263                                 td->ival = ml->s;
1264                         }
1265
1266                         /* expx/expy/expz determine "shape" of some MetaElem types */
1267                         tx->size = &ml->expx;
1268                         tx->isize[0] = ml->expx;
1269                         tx->isize[1] = ml->expy;
1270                         tx->isize[2] = ml->expz;
1271
1272                         /* quat is used for rotation of MetaElem */
1273                         tx->quat = ml->quat;
1274                         QUATCOPY(tx->iquat, ml->quat);
1275
1276                         tx->rot = NULL;
1277
1278                         td++;
1279                         tx++;
1280                 }
1281         }
1282 #endif
1283 }
1284
1285 /* ********************* curve/surface ********* */
1286
1287 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1288         TransData *td, *td_near = NULL;
1289         for (td = head; td<=tail; td++) {
1290                 if (td->flag & TD_SELECTED) {
1291                         td_near = td;
1292                         td->dist = 0.0f;
1293                 }
1294                 else if(td_near) {
1295                         float dist;
1296                         dist = VecLenf(td_near->center, td->center);
1297                         if (dist < (td-1)->dist) {
1298                                 td->dist = (td-1)->dist;
1299                         }
1300                         else {
1301                                 td->dist = dist;
1302                         }
1303                 }
1304                 else {
1305                         td->dist = MAXFLOAT;
1306                         td->flag |= TD_NOTCONNECTED;
1307                 }
1308         }
1309         td_near = NULL;
1310         for (td = tail; td>=head; td--) {
1311                 if (td->flag & TD_SELECTED) {
1312                         td_near = td;
1313                         td->dist = 0.0f;
1314                 }
1315                 else if(td_near) {
1316                         float dist;
1317                         dist = VecLenf(td_near->center, td->center);
1318                         if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1319                                 td->flag &= ~TD_NOTCONNECTED;
1320                                 if (dist < (td+1)->dist) {
1321                                         td->dist = (td+1)->dist;
1322                                 }
1323                                 else {
1324                                         td->dist = dist;
1325                                 }
1326                         }
1327                 }
1328         }
1329 }
1330
1331 /* Utility function for getting the handle data from bezier's */
1332 TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
1333         TransDataCurveHandleFlags *hdata;
1334         td->flag |= TD_BEZTRIPLE;
1335         hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1336         hdata->ih1 = bezt->h1;
1337         hdata->h1 = &bezt->h1;
1338         hdata->ih2 = bezt->h2; /* incase the second is not selected */
1339         hdata->h2 = &bezt->h2;
1340         return hdata;
1341 }
1342
1343 static void createTransCurveVerts(bContext *C, TransInfo *t)
1344 {
1345         // TRANSFORM_FIX_ME
1346 #if 0
1347         Object *obedit= CTX_data_edit_object(C);
1348         Curve *cu= obedit->data;
1349         TransData *td = NULL;
1350         Nurb *nu;
1351         BezTriple *bezt;
1352         BPoint *bp;
1353         float mtx[3][3], smtx[3][3];
1354         int a;
1355         int count=0, countsel=0;
1356         int propmode = t->flag & T_PROP_EDIT;
1357
1358         /* to be sure */
1359         if(cu->editnurb==NULL) return;
1360         
1361         /* count total of vertices, check identical as in 2nd loop for making transdata! */
1362         for(nu= cu->editnurb->first; nu; nu= nu->next) {
1363                 if((nu->type & 7)==CU_BEZIER) {
1364                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1365                                 if(bezt->hide==0) {
1366                                         if (G.f & G_HIDDENHANDLES) {
1367                                                 if(bezt->f2 & SELECT) countsel+=3;
1368                                                 if(propmode) count+= 3;
1369                                         } else {
1370                                                 if(bezt->f1 & SELECT) countsel++;
1371                                                 if(bezt->f2 & SELECT) countsel++;
1372                                                 if(bezt->f3 & SELECT) countsel++;
1373                                                 if(propmode) count+= 3;
1374                                         }
1375                                 }
1376                         }
1377                 }
1378                 else {
1379                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1380                                 if(bp->hide==0) {
1381                                         if(propmode) count++;
1382                                         if(bp->f1 & SELECT) countsel++;
1383                                 }
1384                         }
1385                 }
1386         }
1387         /* note: in prop mode we need at least 1 selected */
1388         if (countsel==0) return;
1389         
1390         if(propmode) t->total = count; 
1391         else t->total = countsel;
1392         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1393
1394         Mat3CpyMat4(mtx, t->obedit->obmat);
1395         Mat3Inv(smtx, mtx);
1396         
1397     td = t->data;
1398         for(nu= cu->editnurb->first; nu; nu= nu->next) {
1399                 if((nu->type & 7)==CU_BEZIER) {
1400                         TransData *head, *tail;
1401                         head = tail = td;
1402                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1403                                 if(bezt->hide==0) {
1404                                         TransDataCurveHandleFlags *hdata = NULL;
1405                                         
1406                                         if(             propmode ||
1407                                                         ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1408                                                         ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1409                                           ) {
1410                                                 VECCOPY(td->iloc, bezt->vec[0]);
1411                                                 td->loc= bezt->vec[0];
1412                                                 VECCOPY(td->center, bezt->vec[1]);
1413                                                 if (G.f & G_HIDDENHANDLES) {
1414                                                         if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1415                                                         else td->flag= 0;
1416                                                 } else {
1417                                                         if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1418                                                         else td->flag= 0;
1419                                                 }
1420                                                 td->ext = NULL;
1421                                                 td->tdi = NULL;
1422                                                 td->val = NULL;
1423                                                 
1424                                                 hdata = initTransDataCurveHandes(td, bezt);
1425
1426                                                 Mat3CpyMat3(td->smtx, smtx);
1427                                                 Mat3CpyMat3(td->mtx, mtx);
1428
1429                                                 td++;
1430                                                 count++;
1431                                                 tail++;
1432                                         }
1433                                         
1434                                         /* This is the Curve Point, the other two are handles */
1435                                         if(propmode || (bezt->f2 & SELECT)) {
1436                                                 VECCOPY(td->iloc, bezt->vec[1]);
1437                                                 td->loc= bezt->vec[1];
1438                                                 VECCOPY(td->center, td->loc);
1439                                                 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1440                                                 else td->flag= 0;
1441                                                 td->ext = NULL;
1442                                                 td->tdi = NULL;
1443                                                 
1444                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1445                                                         td->val = &(bezt->radius);
1446                                                         td->ival = bezt->radius;
1447                                                 } else if (t->mode==TFM_TILT) {
1448                                                         td->val = &(bezt->alfa);
1449                                                         td->ival = bezt->alfa;
1450                                                 } else {
1451                                                         td->val = NULL;
1452                                                 }
1453
1454                                                 Mat3CpyMat3(td->smtx, smtx);
1455                                                 Mat3CpyMat3(td->mtx, mtx);
1456                                                 
1457                                                 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1458                                                 /* If the middle is selected but the sides arnt, this is needed */
1459                                                 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1460                                                         hdata = initTransDataCurveHandes(td, bezt);
1461                                                 }
1462                                                 
1463                                                 td++;
1464                                                 count++;
1465                                                 tail++;
1466                                         }
1467                                         if(             propmode ||
1468                                                         ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1469                                                         ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1470                                           ) {
1471                                                 VECCOPY(td->iloc, bezt->vec[2]);
1472                                                 td->loc= bezt->vec[2];
1473                                                 VECCOPY(td->center, bezt->vec[1]);
1474                                                 if (G.f & G_HIDDENHANDLES) {
1475                                                         if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1476                                                         else td->flag= 0;
1477                                                 } else {
1478                                                         if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1479                                                         else td->flag= 0;
1480                                                 }
1481                                                 td->ext = NULL;
1482                                                 td->tdi = NULL;
1483                                                 td->val = NULL;
1484
1485                                                 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1486                                                         hdata = initTransDataCurveHandes(td, bezt);
1487                                                 }
1488                                                 
1489                                                 Mat3CpyMat3(td->smtx, smtx);
1490                                                 Mat3CpyMat3(td->mtx, mtx);
1491
1492                                                 td++;
1493                                                 count++;
1494                                                 tail++;
1495                                         }
1496                                 }
1497                                 else if (propmode && head != tail) {
1498                                         calc_distanceCurveVerts(head, tail-1);
1499                                         head = tail;
1500                                 }
1501                         }
1502                         if (propmode && head != tail)
1503                                 calc_distanceCurveVerts(head, tail-1);
1504                         
1505                         /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1506                          * but for now just dont change handle types */
1507                         if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1508                                 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1509                 }
1510                 else {
1511                         TransData *head, *tail;
1512                         head = tail = td;
1513                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1514                                 if(bp->hide==0) {
1515                                         if(propmode || (bp->f1 & SELECT)) {
1516                                                 VECCOPY(td->iloc, bp->vec);
1517                                                 td->loc= bp->vec;
1518                                                 VECCOPY(td->center, td->loc);
1519                                                 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1520                                                 else td->flag= 0;
1521                                                 td->ext = NULL;
1522                                                 td->tdi = NULL;
1523                                                 
1524                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1525                                                         td->val = &(bp->radius);
1526                                                         td->ival = bp->radius;
1527                                                 } else {
1528                                                         td->val = &(bp->alfa);
1529                                                         td->ival = bp->alfa;
1530                                                 }
1531
1532                                                 Mat3CpyMat3(td->smtx, smtx);
1533                                                 Mat3CpyMat3(td->mtx, mtx);
1534
1535                                                 td++;
1536                                                 count++;
1537                                                 tail++;
1538                                         }
1539                                 }
1540                                 else if (propmode && head != tail) {
1541                                         calc_distanceCurveVerts(head, tail-1);
1542                                         head = tail;
1543                                 }
1544                         }
1545                         if (propmode && head != tail)
1546                                 calc_distanceCurveVerts(head, tail-1);
1547                 }
1548         }
1549 #endif
1550 }
1551
1552 /* ********************* lattice *************** */
1553
1554 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1555 {
1556         // TRANSFORM_FIX_ME
1557 #if 0
1558         TransData *td = NULL;
1559         BPoint *bp;
1560         float mtx[3][3], smtx[3][3];
1561         int a;
1562         int count=0, countsel=0;
1563         int propmode = t->flag & T_PROP_EDIT;
1564
1565         bp= editLatt->def;
1566         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1567         while(a--) {
1568                 if(bp->hide==0) {
1569                         if(bp->f1 & SELECT) countsel++;
1570                         if(propmode) count++;
1571                 }
1572                 bp++;
1573         }
1574         
1575         /* note: in prop mode we need at least 1 selected */
1576         if (countsel==0) return;
1577         
1578         if(propmode) t->total = count; 
1579         else t->total = countsel;
1580         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1581         
1582         Mat3CpyMat4(mtx, t->obedit->obmat);
1583         Mat3Inv(smtx, mtx);
1584
1585         td = t->data;
1586         bp= editLatt->def;
1587         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1588         while(a--) {
1589                 if(propmode || (bp->f1 & SELECT)) {
1590                         if(bp->hide==0) {
1591                                 VECCOPY(td->iloc, bp->vec);
1592                                 td->loc= bp->vec;
1593                                 VECCOPY(td->center, td->loc);
1594                                 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1595                                 else td->flag= 0;
1596                                 Mat3CpyMat3(td->smtx, smtx);
1597                                 Mat3CpyMat3(td->mtx, mtx);
1598
1599                                 td->ext = NULL;
1600                                 td->tdi = NULL;
1601                                 td->val = NULL;
1602
1603                                 td++;
1604                                 count++;
1605                         }
1606                 }
1607                 bp++;
1608         }
1609 #endif
1610 }
1611
1612 /* ******************* particle edit **************** */
1613 static void createTransParticleVerts(bContext *C, TransInfo *t)
1614 {
1615         // TRANSFORM_FIX_ME
1616 #if 0
1617         TransData *td = NULL;
1618         TransDataExtension *tx;
1619         Base *base = BASACT;
1620         Object *ob = OBACT;
1621         ParticleSystem *psys = PE_get_current(ob);
1622         ParticleSystemModifierData *psmd = NULL;
1623         ParticleEditSettings *pset = PE_settings();
1624         ParticleData *pa = NULL;
1625         ParticleEdit *edit;
1626         ParticleEditKey *key;
1627         float mat[4][4];
1628         int i,k, totpart, transformparticle;
1629         int count = 0, hasselected = 0;
1630         int propmode = t->flag & T_PROP_EDIT;
1631
1632         if(psys==NULL || t->scene->selectmode==SCE_SELECT_PATH) return;
1633
1634         psmd = psys_get_modifier(ob,psys);
1635
1636         edit = psys->edit;
1637         totpart = psys->totpart;
1638         base->flag |= BA_HAS_RECALC_DATA;
1639
1640         for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1641                 pa->flag &= ~PARS_TRANSFORM;
1642                 transformparticle= 0;
1643
1644                 if((pa->flag & PARS_HIDE)==0) {
1645                         for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1646                                 if((key->flag&PEK_HIDE)==0) {
1647                                         if(key->flag&PEK_SELECT) {
1648                                                 hasselected= 1;
1649                                                 transformparticle= 1;
1650                                         }
1651                                         else if(propmode)
1652                                                 transformparticle= 1;
1653                                 }
1654                         }
1655                 }
1656
1657                 if(transformparticle) {
1658                         count += pa->totkey;
1659                         pa->flag |= PARS_TRANSFORM;
1660                 }
1661         }
1662         
1663         /* note: in prop mode we need at least 1 selected */
1664         if (hasselected==0) return;
1665         
1666         t->total = count;
1667         td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1668
1669         if(t->mode == TFM_BAKE_TIME)
1670                 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1671         else
1672                 tx = t->ext = NULL;
1673
1674         Mat4One(mat);
1675
1676         Mat4Invert(ob->imat,ob->obmat);
1677
1678         for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1679                 TransData *head, *tail;
1680                 head = tail = td;
1681
1682                 if(!(pa->flag & PARS_TRANSFORM)) continue;
1683
1684                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1685
1686                 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1687                         VECCOPY(key->world_co, key->co);
1688                         Mat4MulVecfl(mat, key->world_co);
1689                         td->loc = key->world_co;
1690
1691                         VECCOPY(td->iloc, td->loc);
1692                         VECCOPY(td->center, td->loc);
1693
1694                         if(key->flag & PEK_SELECT)
1695                                 td->flag |= TD_SELECTED;
1696                         else if(!propmode)
1697                                 td->flag |= TD_SKIP;
1698
1699                         Mat3One(td->mtx);
1700                         Mat3One(td->smtx);
1701
1702                         /* don't allow moving roots */
1703                         if(k==0 && pset->flag & PE_LOCK_FIRST)
1704                                 td->protectflag |= OB_LOCK_LOC;
1705
1706                         td->ob = ob;
1707                         td->ext = tx;
1708                         td->tdi = NULL;
1709                         if(t->mode == TFM_BAKE_TIME) {
1710                                 td->val = key->time;
1711                                 td->ival = *(key->time);
1712                                 /* abuse size and quat for min/max values */
1713                                 td->flag |= TD_NO_EXT;
1714                                 if(k==0) tx->size = 0;
1715                                 else tx->size = (key - 1)->time;
1716
1717                                 if(k == pa->totkey - 1) tx->quat = 0;
1718                                 else tx->quat = (key + 1)->time;
1719                         }
1720
1721                         td++;
1722                         if(tx)
1723                                 tx++;
1724                         tail++;
1725                 }
1726                 if (propmode && head != tail)
1727                         calc_distanceCurveVerts(head, tail - 1);
1728         }
1729 #endif
1730 }
1731
1732 void flushTransParticles(TransInfo *t)
1733 {
1734 #if 0 // TRANSFORM_FIX_ME
1735         Scene *scene = t->scene;
1736         Object *ob = OBACT;
1737         ParticleSystem *psys = PE_get_current(ob);
1738         ParticleSystemModifierData *psmd;
1739         ParticleData *pa;
1740         ParticleEditKey *key;
1741         TransData *td;
1742         float mat[4][4], imat[4][4], co[3];
1743         int i, k, propmode = t->flag & T_PROP_EDIT;
1744
1745         psmd = psys_get_modifier(ob, psys);
1746
1747         /* we do transform in world space, so flush world space position
1748          * back to particle local space */
1749         td= t->data;
1750         for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1751                 if(!(pa->flag & PARS_TRANSFORM)) continue;
1752
1753                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1754                 Mat4Invert(imat,mat);
1755
1756                 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1757                         VECCOPY(co, key->world_co);
1758                         Mat4MulVecfl(imat, co);
1759
1760                         /* optimization for proportional edit */
1761                         if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1762                                 VECCOPY(key->co, co);
1763                                 pa->flag |= PARS_EDIT_RECALC;
1764                         }
1765                 }
1766         }
1767
1768         PE_update_object(OBACT, 1);
1769 #endif
1770 }
1771
1772 /* ********************* mesh ****************** */
1773
1774 /* proportional distance based on connectivity  */
1775 #define E_VEC(a)        (vectors + (3 * (a)->tmp.l))
1776 #define E_NEAR(a)       (nears[((a)->tmp.l)])
1777 #define THRESHOLD       0.0001f
1778 static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
1779 {
1780         EditVert *eve;
1781         EditEdge *eed;
1782         int i= 0, done= 1;
1783
1784         /* f2 flag is used for 'selection' */
1785         /* tmp.l is offset on scratch array   */
1786         for(eve= em->verts.first; eve; eve= eve->next) {
1787                 if(eve->h==0) {
1788                         eve->tmp.l = i++;
1789
1790                         if(eve->f & SELECT) {
1791                                 eve->f2= 2;
1792                                 E_NEAR(eve) = eve;
1793                                 E_VEC(eve)[0] = 0.0f;
1794                                 E_VEC(eve)[1] = 0.0f;
1795                                 E_VEC(eve)[2] = 0.0f;
1796                         }
1797                         else {
1798                                 eve->f2 = 0;
1799                         }
1800                 }
1801         }
1802
1803
1804         /* Floodfill routine */
1805         /*
1806         At worst this is n*n of complexity where n is number of edges 
1807         Best case would be n if the list is ordered perfectly.
1808         Estimate is n log n in average (so not too bad)
1809         */
1810         while(done) {
1811                 done= 0;
1812                 
1813                 for(eed= em->edges.first; eed; eed= eed->next) {
1814                         if(eed->h==0) {
1815                                 EditVert *v1= eed->v1, *v2= eed->v2;
1816                                 float *vec2 = E_VEC(v2);
1817                                 float *vec1 = E_VEC(v1);
1818
1819                                 if (v1->f2 + v2->f2 == 4)
1820                                         continue;
1821
1822                                 if (v1->f2) {
1823                                         if (v2->f2) {
1824                                                 float nvec[3];
1825                                                 float len1 = VecLength(vec1);
1826                                                 float len2 = VecLength(vec2);
1827                                                 float lenn;
1828                                                 /* for v2 if not selected */
1829                                                 if (v2->f2 != 2) {
1830                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1831                                                         lenn = VecLength(nvec);
1832                                                         /* 1 < n < 2 */
1833                                                         if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1834                                                                 VECCOPY(vec2, nvec);
1835                                                                 E_NEAR(v2) = E_NEAR(v1);
1836                                                                 done = 1;
1837                                                         }
1838                                                         /* n < 1 < 2 */
1839                                                         else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1840                                                                 VECCOPY(vec2, vec1);
1841                                                                 E_NEAR(v2) = E_NEAR(v1);
1842                                                                 done = 1;
1843                                                         }
1844                                                 }
1845                                                 /* for v1 if not selected */
1846                                                 if (v1->f2 != 2) {
1847                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1848                                                         lenn = VecLength(nvec);
1849                                                         /* 2 < n < 1 */
1850                                                         if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1851                                                                 VECCOPY(vec1, nvec);
1852                                                                 E_NEAR(v1) = E_NEAR(v2);
1853                                                                 done = 1;
1854                                                         }
1855                                                         /* n < 2 < 1 */
1856                                                         else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1857                                                                 VECCOPY(vec1, vec2);
1858                                                                 E_NEAR(v1) = E_NEAR(v2);
1859                                                                 done = 1;
1860                                                         }
1861                                                 }
1862                                         }
1863                                         else {
1864                                                 v2->f2 = 1;
1865                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1866                                                 /* 2 < 1 */
1867                                                 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1868                                                         VECCOPY(vec2, vec1);
1869                                                 }
1870                                                 E_NEAR(v2) = E_NEAR(v1);
1871                                                 done = 1;
1872                                         }
1873                                 }
1874                                 else if (v2->f2) {
1875                                         v1->f2 = 1;
1876                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1877                                         /* 2 < 1 */
1878                                         if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1879                                                 VECCOPY(vec1, vec2);
1880                                         }
1881                                         E_NEAR(v1) = E_NEAR(v2);
1882                                         done = 1;
1883                                 }
1884                         }
1885                 }
1886         }
1887 }
1888
1889 /* loop-in-a-loop I know, but we need it! (ton) */
1890 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
1891 {
1892         EditFace *efa;
1893         
1894         for(efa= em->faces.first; efa; efa= efa->next)
1895                 if(efa->f & SELECT)
1896                         if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1897                                 break;
1898         if(efa) {
1899                 VECCOPY(cent, efa->cent);
1900         }
1901 }
1902
1903 //way to overwrite what data is edited with transform
1904 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1905 static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
1906 {
1907         td->flag = 0;
1908         //if(key)
1909         //      td->loc = key->co;
1910         //else
1911         td->loc = eve->co;
1912         
1913         VECCOPY(td->center, td->loc);
1914         if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1915                 get_face_center(td->center, em, eve);
1916         VECCOPY(td->iloc, td->loc);
1917
1918         // Setting normals
1919         VECCOPY(td->axismtx[2], eve->no);
1920         td->axismtx[0][0]               =
1921                 td->axismtx[0][1]       =
1922                 td->axismtx[0][2]       =
1923                 td->axismtx[1][0]       =
1924                 td->axismtx[1][1]       =
1925                 td->axismtx[1][2]       = 0.0f;
1926
1927         td->ext = NULL;
1928         td->tdi = NULL;
1929         td->val = NULL;
1930         td->extra = NULL;
1931         if (t->mode == TFM_BWEIGHT) {
1932                 td->val = &(eve->bweight);
1933                 td->ival = eve->bweight;
1934         }
1935 }
1936
1937 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1938
1939 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1940 {
1941         float *vec = userData;
1942         
1943         vec+= 3*index;
1944         VECCOPY(vec, co);
1945 }
1946
1947 static int modifiers_disable_subsurf_temporary(Object *ob)
1948 {
1949         ModifierData *md;
1950         int disabled = 0;
1951         
1952         for(md=ob->modifiers.first; md; md=md->next)
1953                 if(md->type==eModifierType_Subsurf)
1954                         if(md->mode & eModifierMode_OnCage) {
1955                                 md->mode ^= eModifierMode_DisableTemporary;
1956                                 disabled= 1;
1957                         }
1958         
1959         return disabled;
1960 }
1961
1962 /* disable subsurf temporal, get mapped cos, and enable it */
1963 static float *get_crazy_mapped_editverts(TransInfo *t)
1964 {
1965         Mesh *me= t->obedit->data;
1966         DerivedMesh *dm;
1967         float *vertexcos;
1968
1969         /* disable subsurf temporal, get mapped cos, and enable it */
1970         if(modifiers_disable_subsurf_temporary(t->obedit)) {
1971                 /* need to make new derivemesh */
1972                 makeDerivedMesh(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1973         }
1974
1975         /* now get the cage */
1976         dm= editmesh_get_derived_cage(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1977
1978         vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1979         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1980         
1981         dm->release(dm);
1982         
1983         /* set back the flag, no new cage needs to be built, transform does it */
1984         modifiers_disable_subsurf_temporary(t->obedit);
1985         
1986         return vertexcos;
1987 }
1988
1989 #define TAN_MAKE_VEC(a, b, c)   a[0]= b[0] + 0.2f*(b[0]-c[0]); a[1]= b[1] + 0.2f*(b[1]-c[1]); a[2]= b[2] + 0.2f*(b[2]-c[2])
1990 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1991 {
1992         float vecu[3], vecv[3];
1993         float q1[4], q2[4];
1994         
1995         TAN_MAKE_VEC(vecu, v1, v2);
1996         TAN_MAKE_VEC(vecv, v1, v3);
1997         triatoquat(v1, vecu, vecv, q1);
1998         
1999         TAN_MAKE_VEC(vecu, def1, def2);
2000         TAN_MAKE_VEC(vecv, def1, def3);
2001         triatoquat(def1, vecu, vecv, q2);
2002         
2003         QuatSub(quat, q2, q1);
2004 }
2005 #undef TAN_MAKE_VEC
2006
2007 static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
2008 {
2009         EditVert *eve, *prev;
2010         EditFace *efa;
2011         float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2012         intptr_t index= 0;
2013         
2014         /* two abused locations in vertices */
2015         for(eve= em->verts.first; eve; eve= eve->next, index++) {
2016                 eve->tmp.p = NULL;
2017                 eve->prev= (EditVert *)index;
2018         }
2019         
2020         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2021         for(efa= em->faces.first; efa; efa= efa->next) {
2022                 
2023                 /* retrieve mapped coordinates */
2024                 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2025                 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2026                 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2027
2028                 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2029                 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2030                 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2031
2032                 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2033                         set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2034                         efa->v2->tmp.p= (void*)quats;
2035                         quats+= 4;
2036                 }
2037                 
2038                 if(efa->v4) {
2039                         v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2040                         co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2041
2042                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2043                                 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2044                                 efa->v1->tmp.p= (void*)quats;
2045                                 quats+= 4;
2046                         }
2047                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2048                                 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2049                                 efa->v3->tmp.p= (void*)quats;
2050                                 quats+= 4;
2051                         }
2052                         if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2053                                 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2054                                 efa->v4->tmp.p= (void*)quats;
2055                                 quats+= 4;
2056                         }
2057                 }
2058                 else {
2059                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2060                                 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2061                                 efa->v1->tmp.p= (void*)quats;
2062                                 quats+= 4;
2063                         }
2064                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2065                                 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2066                                 efa->v3->tmp.p= (void*)quats;
2067                                 quats+= 4;
2068                         }
2069                 }
2070         }
2071
2072         /* restore abused prev pointer */
2073         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2074                 eve->prev= prev;
2075
2076 }
2077
2078 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2079         BME_Vert *v;
2080         BME_TransData *vtd;
2081         TransData *tob;
2082         int i;
2083
2084         tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2085
2086         for (i=0,v=bm->verts.first;v;v=v->next) {
2087                 if ( (vtd = BME_get_transdata(td,v)) ) {
2088                         tob->loc = vtd->loc;
2089                         tob->val = &vtd->factor;
2090                         VECCOPY(tob->iloc,vtd->co);
2091                         VECCOPY(tob->center,vtd->org);
2092                         VECCOPY(tob->axismtx[0],vtd->vec);
2093                         tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2094                         tob++;
2095                         i++;
2096                 }
2097         }
2098         /* since td is a memarena, it can hold more transdata than actual elements
2099          * (i.e. we can't depend on td->len to determine the number of actual elements) */
2100         t->total = i;
2101 }
2102
2103 static void createTransEditVerts(bContext *C, TransInfo *t)
2104 {
2105         Scene *scene = CTX_data_scene(C);
2106         TransData *tob = NULL;
2107         EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2108         EditVert *eve;
2109         EditVert **nears = NULL;
2110         EditVert *eve_act = NULL;
2111         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2112         float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2113         int count=0, countsel=0, a, totleft;
2114         int propmode = t->flag & T_PROP_EDIT;
2115         int mirror = 0;
2116         
2117         if ((t->options & CTX_NO_MIRROR) == 0 && (scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2118         {
2119                 mirror = 1;
2120         }
2121
2122         // transform now requires awareness for select mode, so we tag the f1 flags in verts
2123         if(scene->selectmode & SCE_SELECT_VERTEX) {
2124                 for(eve= em->verts.first; eve; eve= eve->next) {
2125                         if(eve->h==0 && (eve->f & SELECT)) 
2126                                 eve->f1= SELECT;
2127                         else
2128                                 eve->f1= 0;
2129                 }
2130         }
2131         else if(scene->selectmode & SCE_SELECT_EDGE) {
2132                 EditEdge *eed;
2133                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2134                 for(eed= em->edges.first; eed; eed= eed->next) {
2135                         if(eed->h==0 && (eed->f & SELECT))
2136                                 eed->v1->f1= eed->v2->f1= SELECT;
2137                 }
2138         }
2139         else {
2140                 EditFace *efa;
2141                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2142                 for(efa= em->faces.first; efa; efa= efa->next) {
2143                         if(efa->h==0 && (efa->f & SELECT)) {
2144                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2145                                 if(efa->v4) efa->v4->f1= SELECT;
2146                         }
2147                 }
2148         }
2149         
2150         /* now we can count */
2151         for(eve= em->verts.first; eve; eve= eve->next) {
2152                 if(eve->h==0) {
2153                         if(eve->f1) countsel++;
2154                         if(propmode) count++;
2155                 }
2156         }
2157         
2158         /* note: in prop mode we need at least 1 selected */
2159         if (countsel==0) return;
2160         
2161         /* check active */
2162         if (em->selected.last) {
2163                 EditSelection *ese = em->selected.last;
2164                 if ( ese->type == EDITVERT ) {
2165                         eve_act = (EditVert *)ese->data;
2166                 }
2167         }
2168
2169         
2170         if(propmode) {
2171                 t->total = count; 
2172         
2173                 /* allocating scratch arrays */
2174                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2175                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2176         }
2177         else t->total = countsel;
2178         tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2179         
2180         Mat3CpyMat4(mtx, t->obedit->obmat);
2181         Mat3Inv(smtx, mtx);
2182
2183         if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
2184         
2185         /* detect CrazySpace [tm] */
2186         if(propmode==0) {
2187                 if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
2188                         if(modifiers_isDeformed(t->scene, t->obedit)) {
2189                                 /* check if we can use deform matrices for modifier from the
2190                                    start up to stack, they are more accurate than quats */
2191                                 totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
2192
2193                                 /* if we still have more modifiers, also do crazyspace
2194                                    correction with quats, relative to the coordinates after
2195                                    the modifiers that support deform matrices (defcos) */
2196                                 if(totleft > 0) {
2197                                         mappedcos= get_crazy_mapped_editverts(t);
2198                                         quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2199                                         set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
2200                                         if(mappedcos)
2201                                                 MEM_freeN(mappedcos);
2202                                 }
2203
2204                                 if(defcos)
2205                                         MEM_freeN(defcos);
2206                         }
2207                 }
2208         }
2209         
2210         /* find out which half we do */
2211         if(mirror) {
2212                 for (eve=em->verts.first; eve; eve=eve->next) {
2213                         if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2214                                 if(eve->co[0]<0.0f)
2215                                         mirror = -1;
2216                                 break;
2217                         }
2218                 }
2219         }
2220         
2221         for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2222                 if(eve->h==0) {
2223                         if(propmode || eve->f1) {
2224                                 VertsToTransData(t, tob, em, eve);
2225                                 
2226                                 /* selected */
2227                                 if(eve->f1) tob->flag |= TD_SELECTED;
2228                                 
2229                                 /* active */
2230                                 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2231                                 
2232                                 if(propmode) {
2233                                         if (eve->f2) {
2234                                                 float vec[3];
2235                                                 VECCOPY(vec, E_VEC(eve));
2236                                                 Mat3MulVecfl(mtx, vec);
2237                                                 tob->dist= VecLength(vec);
2238                                         }
2239                                         else {
2240                                                 tob->flag |= TD_NOTCONNECTED;
2241                                                 tob->dist = MAXFLOAT;
2242                                         }
2243                                 }
2244                                 
2245                                 /* CrazySpace */
2246                                 if(defmats || (quats && eve->tmp.p)) {
2247                                         float mat[3][3], imat[3][3], qmat[3][3];
2248                                         
2249                                         /* use both or either quat and defmat correction */
2250                                         if(quats && eve->tmp.f) {
2251                                                 QuatToMat3(eve->tmp.p, qmat);
2252
2253                                                 if(defmats)
2254                                                         Mat3MulSerie(mat, mtx, qmat, defmats[a],
2255                                                                 NULL, NULL, NULL, NULL, NULL);
2256                                                 else
2257                                                         Mat3MulMat3(mat, mtx, qmat);
2258                                         }
2259                                         else
2260                                                 Mat3MulMat3(mat, mtx, defmats[a]);
2261
2262                                         Mat3Inv(imat, mat);
2263                                         
2264                                         Mat3CpyMat3(tob->smtx, imat);
2265                                         Mat3CpyMat3(tob->mtx, mat);
2266                                 }
2267                                 else {
2268                                         Mat3CpyMat3(tob->smtx, smtx);
2269                                         Mat3CpyMat3(tob->mtx, mtx);
2270                                 }
2271                                 
2272                                 /* Mirror? */
2273                                 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2274                                         EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc);   /* initializes octree on first call */
2275                                         if(vmir != eve) tob->extra = vmir;
2276                                 }
2277                                 tob++;
2278                         }
2279                 }       
2280         }
2281         if (propmode) {
2282                 MEM_freeN(vectors);
2283                 MEM_freeN(nears);
2284         }
2285         /* crazy space free */
2286         if(quats)
2287                 MEM_freeN(quats);
2288         if(defmats)
2289                 MEM_freeN(defmats);
2290 }
2291
2292 /* *** NODE EDITOR *** */
2293 void flushTransNodes(TransInfo *t)
2294 {
2295         int a;
2296         TransData2D *td;
2297         
2298         /* flush to 2d vector from internally used 3d vector */
2299         for(a=0, td= t->data2d; a<t->total; a++, td++) {
2300                 td->loc2d[0]= td->loc[0];
2301                 td->loc2d[1]= td->loc[1];
2302         }
2303 }
2304
2305 /* ********************* UV ****************** */
2306
2307 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2308 {
2309         float aspx, aspy;
2310
2311         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2312
2313         /* uv coords are scaled by aspects. this is needed for rotations and
2314            proportional editing to be consistent with the stretchted uv coords
2315            that are displayed. this also means that for display and numinput,
2316            and when the the uv coords are flushed, these are converted each time */
2317         td2d->loc[0] = uv[0]*aspx;
2318         td2d->loc[1] = uv[1]*aspy;
2319         td2d->loc[2] = 0.0f;
2320         td2d->loc2d = uv;
2321
2322         td->flag = 0;
2323         td->loc = td2d->loc;
2324         VECCOPY(td->center, td->loc);
2325         VECCOPY(td->iloc, td->loc);
2326
2327         memset(td->axismtx, 0, sizeof(td->axismtx));
2328         td->axismtx[2][2] = 1.0f;
2329
2330         td->ext= NULL; td->tdi= NULL; td->val= NULL;
2331
2332         if(selected) {
2333                 td->flag |= TD_SELECTED;
2334                 td->dist= 0.0;
2335         }
2336         else {
2337                 td->dist= MAXFLOAT;
2338         }
2339         Mat3One(td->mtx);
2340         Mat3One(td->smtx);
2341 }
2342
2343 static void createTransUVs(bContext *C, TransInfo *t)
2344 {
2345         // TRANSFORM_FIX_ME
2346 #if 0
2347         TransData *td = NULL;
2348         TransData2D *td2d = NULL;
2349         MTFace *tf;
2350         int count=0, countsel=0;
2351         int propmode = t->flag & T_PROP_EDIT;
2352         int efa_s1,efa_s2,efa_s3,efa_s4;
2353
2354         EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2355         EditFace *efa;
2356         
2357         if(is_uv_tface_editing_allowed()==0) return;
2358
2359         /* count */
2360         if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2361                 for (efa= em->faces.first; efa; efa= efa->next) {
2362                         /* store face pointer for second loop, prevent second lookup */
2363                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2364                         if (simaFaceDraw_Check(efa, tf)) {
2365                                 efa->tmp.p = tf;
2366                                 
2367                                 efa_s1 = simaUVSel_Check(efa, tf, 0);
2368                                 efa_s2 = simaUVSel_Check(efa, tf, 1);
2369                                 efa_s3 = simaUVSel_Check(efa, tf, 2);
2370                                 if (efa->v4) {
2371                                         efa_s4 = simaUVSel_Check(efa, tf, 3);
2372                                         if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2373                                                 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2374                                         }
2375                                 } else {
2376                                         /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2377                                         if (efa_s1) countsel++; 
2378                                         if (efa_s2) countsel++; 
2379                                         if (efa_s3) countsel++;
2380                                 }
2381                         } else {
2382                                 efa->tmp.p = NULL;
2383                         }
2384                 }
2385         } else {
2386                 for (efa= em->faces.first; efa; efa= efa->next) {
2387                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2388                         if (simaFaceDraw_Check(efa, tf)) {
2389                                 efa->tmp.p = tf;
2390                                 
2391                                 if (simaUVSel_Check(efa, tf, 0)) countsel++; 
2392                                 if (simaUVSel_Check(efa, tf, 1)) countsel++; 
2393                                 if (simaUVSel_Check(efa, tf, 2)) countsel++; 
2394                                 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2395                                 if(propmode)
2396                                         count += (efa->v4)? 4: 3;
2397                         } else {
2398                                 efa->tmp.p = NULL;
2399                         }
2400                 }
2401         }
2402         
2403         /* note: in prop mode we need at least 1 selected */
2404         if (countsel==0) return;
2405         
2406         t->total= (propmode)? count: countsel;
2407         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2408         /* for each 2d uv coord a 3d vector is allocated, so that they can be
2409            treated just as if they were 3d verts */
2410         t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2411
2412         if(G.sima->flag & SI_CLIP_UV)
2413                 t->flag |= T_CLIP_UV;
2414
2415         td= t->data;
2416         td2d= t->data2d;
2417         
2418         if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2419                 for (efa= em->faces.first; efa; efa= efa->next) {
2420                         tf=(MTFace *)efa->tmp.p;
2421                         if (tf) {
2422                                 efa_s1 = simaUVSel_Check(efa, tf, 0);
2423                                 efa_s2 = simaUVSel_Check(efa, tf, 1);
2424                                 efa_s3 = simaUVSel_Check(efa, tf, 2);
2425                                 
2426                                 if (efa->v4) {
2427                                         efa_s4 = simaUVSel_Check(efa, tf, 3);
2428                                         
2429                                         if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2430                                                 /* all corners of this quad need their edges moved. so we must store TD for each */
2431
2432                                                 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2433                                                 if (!efa_s1)    td->flag |= TD_SKIP;
2434                                                 td++; td2d++;
2435
2436                                                 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2437                                                 if (!efa_s2)    td->flag |= TD_SKIP;
2438                                                 td++; td2d++;
2439
2440                                                 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2441                                                 if (!efa_s3)    td->flag |= TD_SKIP;
2442                                                 td++; td2d++;
2443
2444                                                 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2445                                                 if (!efa_s4)    td->flag |= TD_SKIP;
2446                                                 td++; td2d++;
2447                                         }
2448                                 } else {
2449                                         /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2450                                         if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1); 
2451                                         if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1); 
2452                                         if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2453                                 }
2454                         }
2455                 }
2456         } else {
2457                 for (efa= em->faces.first; efa; efa= efa->next) {
2458                         /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2459                         if (simaFaceDraw_Check(efa, tf)) {*/
2460                         if ((tf=(MTFace *)efa->tmp.p)) {
2461                                 if (propmode) {
2462                                         UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2463                                         UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2464                                         UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2465                                         if(efa->v4)
2466                                                 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2467                                 } else {
2468                                         if(simaUVSel_Check(efa, tf, 0))                         UVsToTransData(td++, td2d++, tf->uv[0], 1);
2469                                         if(simaUVSel_Check(efa, tf, 1))                         UVsToTransData(td++, td2d++, tf->uv[1], 1);
2470                                         if(simaUVSel_Check(efa, tf, 2))                         UVsToTransData(td++, td2d++, tf->uv[2], 1);
2471                                         if(efa->v4 && simaUVSel_Check(efa, tf, 3))      UVsToTransData(td++, td2d++, tf->uv[3], 1);
2472                                 }
2473                         }
2474                 }
2475         }
2476         
2477         if (G.sima->flag & SI_LIVE_UNWRAP)
2478                 unwrap_lscm_live_begin();
2479 #endif
2480 }
2481
2482 void flushTransUVs(TransInfo *t)
2483 {
2484 #if 0 // TRANSFORM_FIX_ME
2485         TransData2D *td;
2486         int a, width, height;
2487         Object *ob= OBACT;
2488         EditMesh *em = ((Mesh *)ob->data)->edit_mesh;
2489         float aspx, aspy, invx, invy;
2490
2491         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2492         transform_width_height_tface_uv(&width, &height);
2493         invx= 1.0f/aspx;
2494         invy= 1.0f/aspy;
2495
2496         /* flush to 2d vector from internally used 3d vector */
2497         for(a=0, td= t->data2d; a<t->total; a++, td++) {
2498                 td->loc2d[0]= td->loc[0]*invx;
2499                 td->loc2d[1]= td->loc[1]*invy;
2500                 
2501                 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2502                         td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2503                         td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2504                 }
2505         }
2506         
2507         if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL)) 
2508                 be_square_tface_uv(em);
2509
2510         /* this is overkill if G.sima->lock is not set, but still needed */
2511         object_uvs_changed(ob);
2512 #endif
2513 }
2514
2515 int clipUVTransform(TransInfo *t, float *vec, int resize)
2516 {
2517 #if 0 // TRANSFORM_FIX_ME
2518         TransData *td;
2519         int a, clipx=1, clipy=1;
2520         float aspx, aspy, min[2], max[2];
2521
2522         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2523         min[0]= min[1]= 0.0f;
2524         max[0]= aspx; max[1]= aspy;
2525
2526         for(a=0, td= t->data; a<t->total; a++, td++) {
2527                 DO_MINMAX2(td->loc, min, max);
2528         }
2529
2530         if(resize) {
2531                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2532                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
2533                 else if(max[0] > aspx && t->center[0] < aspx)
2534                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2535                 else
2536                         clipx= 0;
2537
2538                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2539                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
2540                 else if(max[1] > aspy && t->center[1] < aspy)
2541                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2542                 else
2543                         clipy= 0;
2544         }
2545         else {
2546                 if(min[0] < 0.0f)
2547                         vec[0] -= min[0];
2548                 else if(max[0] > aspx)
2549                         vec[0] -= max[0]-aspx;
2550                 else
2551                         clipx= 0;
2552
2553                 if(min[1] < 0.0f)
2554                         vec[1] -= min[1];
2555                 else if(max[1] > aspy)
2556                         vec[1] -= max[1]-aspy;
2557                 else
2558                         clipy= 0;
2559         }       
2560
2561         return (clipx || clipy);
2562 #endif
2563 return 0;
2564 }
2565
2566 /* ********************* IPO EDITOR ************************* */
2567
2568 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2569  * due to bad globals that would need to be imported specially for this
2570  */
2571 static void createTransIpoData(bContext *C, TransInfo *t)
2572 {
2573         // TRANSFORM_FIX_ME
2574 #if 0
2575         /* in editipo.c due to some globals that are defined in that file... */
2576         make_ipo_transdata(t);
2577 #endif
2578 }
2579
2580 /* this function is called on recalcData to apply the transforms applied
2581  * to the transdata on to the actual keyframe data 
2582  */
2583 void flushTransIpoData(TransInfo *t)
2584 {
2585 #if 0 // TRANSFORM_FIX_ME
2586         TransData2D *td;
2587         int a;
2588         
2589         /* flush to 2d vector from internally used 3d vector */
2590         for (a=0, td= t->data2d; a<t->total; a++, td++) {
2591                 // FIXME: autosnap needs to be here...
2592                 
2593                 /* we need to unapply the nla-scaling from the time in some situations */
2594                 if (NLA_IPO_SCALED)
2595                         td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2596                 else
2597                         td->loc2d[0]= td->loc[0];
2598                 
2599                 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2600                 if ((t->data[a].flag & TD_TIMEONLY)==0)
2601                         td->loc2d[1]= td->loc[1];
2602         }
2603 #endif
2604 }
2605
2606 /* ********************* ACTION/NLA EDITOR ****************** */
2607
2608 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2609  * any other gp-frames which may reside on that frame (that are not selected).
2610  * It also makes sure gp-frames are still stored in chronological order after
2611  * transform.
2612  */
2613 static void posttrans_gpd_clean (bGPdata *gpd)
2614 {
2615         bGPDlayer *gpl;
2616         
2617         for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2618                 ListBase sel_buffer = {NULL, NULL};
2619                 bGPDframe *gpf, *gpfn;
2620                 bGPDframe *gfs, *gfsn;
2621                 
2622                 /* loop 1: loop through and isolate selected gp-frames to buffer 
2623                  * (these need to be sorted as they are isolated)
2624                  */
2625                 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2626                         short added= 0;
2627                         gpfn= gpf->next;
2628                         
2629                         if (gpf->flag & GP_FRAME_SELECT) {
2630                                 BLI_remlink(&gpl->frames, gpf);
2631                                 
2632                                 /* find place to add them in buffer
2633                                  * - go backwards as most frames will still be in order,
2634                                  *   so doing it this way will be faster 
2635                                  */
2636                                 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2637                                         /* if current (gpf) occurs after this one in buffer, add! */
2638                                         if (gfs->framenum < gpf->framenum) {
2639                                                 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2640                                                 added= 1;
2641                                                 break;
2642                                         }
2643                                 }
2644                                 if (added == 0)
2645                                         BLI_addhead(&sel_buffer, gpf);
2646                         }
2647                 }
2648                 
2649                 /* error checking: it is unlikely, but may be possible to have none selected */
2650                 if (sel_buffer.first == NULL)
2651                         continue;
2652                 
2653                 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2654                 if (gpl->frames.first == NULL) {
2655                         gpl->frames.first= sel_buffer.first;
2656                         gpl->frames.last= sel_buffer.last;
2657                         
2658                         continue;
2659                 }
2660                 
2661                 /* loop 2: remove duplicates of frames in buffers */
2662                 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2663                         gpfn= gpf->next;
2664                         
2665                         /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2666                         for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2667                                 gfsn= gfs->next;
2668                                 
2669                                 /* if this buffer frame needs to go before current, add it! */
2670                                 if (gfs->framenum < gpf->framenum) {
2671                                         /* transfer buffer frame to frames list (before current) */
2672                                         BLI_remlink(&sel_buffer, gfs);
2673                                         BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2674                                 }
2675                                 /* if this buffer frame is on same frame, replace current with it and stop */
2676                                 else if (gfs->framenum == gpf->framenum) {
2677                                         /* transfer buffer frame to frames list (before current) */
2678                                         BLI_remlink(&sel_buffer, gfs);
2679                                         BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2680                                         
2681                                         /* get rid of current frame */
2682                                         // TRANSFORM_FIX_ME
2683                                         //gpencil_layer_delframe(gpl, gpf);
2684                                 }
2685                         }
2686                 }
2687                 
2688                 /* if anything is still in buffer, append to end */
2689                 for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
2690                         gfsn= gfs->next;
2691                         
2692                         BLI_remlink(&sel_buffer, gfs);
2693                         BLI_addtail(&gpl->frames, gfs);
2694                 }
2695         }
2696 }
2697
2698 /* Called during special_aftertrans_update to make sure selected keyframes replace
2699  * any other keyframes which may reside on that frame (that is not selected).
2700  */
2701 static void posttrans_icu_clean (IpoCurve *icu)
2702 {
2703         float *selcache;        /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
2704         int len, index, i;      /* number of frames in cache, item index */
2705         
2706         /* allocate memory for the cache */
2707         // TODO: investigate using GHash for this instead?
2708         if (icu->totvert == 0) 
2709                 return;
2710         selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
2711         len= 0;
2712         index= 0;
2713         
2714         /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting 
2715          * as there is no guarantee what order the keyframes are exactly, even though 
2716          * they have been sorted by time.
2717          */
2718          
2719         /*      Loop 1: find selected keyframes   */
2720         for (i = 0; i < icu->totvert; i++) {
2721                 BezTriple *bezt= &icu->bezt[i];
2722                 
2723                 if (BEZSELECTED(bezt)) {
2724                         selcache[index]= bezt->vec[1][0];
2725                         index++;
2726                         len++;
2727                 }
2728         }
2729         
2730         /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
2731         if (len) {
2732                 for (i = 0; i < icu->totvert; i++) {
2733                         BezTriple *bezt= &icu->bezt[i];
2734                         
2735                         if (BEZSELECTED(bezt) == 0) {
2736                                 /* check beztriple should be removed according to cache */
2737                                 for (index= 0; index < len; index++) {
2738                                         if (IS_EQ(bezt->vec[1][0], selcache[index])) {
2739                                                 delete_icu_key(icu, i, 0);
2740                                                 break;
2741                                         }
2742                                         else if (bezt->vec[1][0] > selcache[index])
2743                                                 break;
2744                                 }
2745                         }
2746                 }
2747                 
2748                 testhandles_ipocurve(icu);
2749         }
2750         
2751         /* free cache */
2752         MEM_freeN(selcache);
2753 }
2754
2755 /* Called by special_aftertrans_update to make sure selected keyframes replace
2756  * any other keyframes which may reside on that frame (that is not selected).
2757  * remake_action_ipos should have already been called 
2758  */
2759 static void posttrans_ipo_clean (Ipo *ipo)
2760 {
2761