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