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