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