2.5
[blender.git] / source / blender / editors / transform / transform_conversions.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #ifndef WIN32
35 #include <unistd.h>
36 #else
37 #include <io.h>
38 #endif
39 #include <string.h>
40 #include <math.h>
41
42 #include "MEM_guardedalloc.h"
43
44 #include "DNA_action_types.h"
45 #include "DNA_armature_types.h"
46 #include "DNA_camera_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_effect_types.h"
49 #include "DNA_image_types.h"
50 #include "DNA_ipo_types.h"
51 #include "DNA_key_types.h"
52 #include "DNA_lamp_types.h"
53 #include "DNA_lattice_types.h"
54 #include "DNA_mesh_types.h"
55 #include "DNA_meshdata_types.h"
56 #include "DNA_meta_types.h"
57 #include "DNA_modifier_types.h"
58 #include "DNA_nla_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_object_force.h"
61 #include "DNA_particle_types.h"
62 #include "DNA_scene_types.h"
63 #include "DNA_screen_types.h"
64 #include "DNA_space_types.h"
65 #include "DNA_texture_types.h"
66 #include "DNA_view3d_types.h"
67 #include "DNA_world_types.h"
68 #include "DNA_userdef_types.h"
69 #include "DNA_property_types.h"
70 #include "DNA_vfont_types.h"
71 #include "DNA_constraint_types.h"
72 #include "DNA_listBase.h"
73 #include "DNA_gpencil_types.h"
74
75 #include "BKE_action.h"
76 #include "BKE_armature.h"
77 #include "BKE_blender.h"
78 #include "BKE_cloth.h"
79 #include "BKE_curve.h"
80 #include "BKE_constraint.h"
81 #include "BKE_depsgraph.h"
82 #include "BKE_displist.h"
83 #include "BKE_DerivedMesh.h"
84 #include "BKE_effect.h"
85 #include "BKE_font.h"
86 #include "BKE_global.h"
87 #include "BKE_ipo.h"
88 #include "BKE_lattice.h"
89 #include "BKE_key.h"
90 #include "BKE_main.h"
91 #include "BKE_mball.h"
92 #include "BKE_mesh.h"
93 #include "BKE_modifier.h"
94 #include "BKE_object.h"
95 #include "BKE_particle.h"
96 #include "BKE_pointcache.h"
97 #include "BKE_softbody.h"
98 #include "BKE_utildefines.h"
99 #include "BKE_bmesh.h"
100 #include "BKE_context.h"
101
102 //#include "BIF_editaction.h"
103 //#include "BIF_editview.h"
104 //#include "BIF_editlattice.h"
105 //#include "BIF_editconstraint.h"
106 #include "BIF_editarmature.h"
107 //#include "BIF_editmesh.h"
108 //#include "BIF_editnla.h"
109 //#include "BIF_editsima.h"
110 //#include "BIF_editparticle.h"
111 #include "BIF_gl.h"
112 //#include "BIF_keyframing.h"
113 //#include "BIF_poseobject.h"
114 //#include "BIF_meshtools.h"
115 //#include "BIF_mywindow.h"
116 //#include "BIF_resources.h"
117 #include "BIF_retopo.h"
118 //#include "BIF_screen.h"
119 //#include "BIF_space.h"
120 //#include "BIF_toolbox.h"
121
122 #include "ED_types.h"
123 #include "ED_view3d.h"
124
125 //#include "BSE_drawipo.h"
126 //#include "BSE_edit.h"
127 //#include "BSE_editipo.h"
128 //#include "BSE_editipo_types.h"
129 //#include "BSE_editaction_types.h"
130
131 //#include "BDR_drawaction.h"           // list of keyframes in action
132 //#include "BDR_editobject.h"           // reset_slowparents()
133 //#include "BDR_gpencil.h"
134 //#include "BDR_unwrapper.h"
135
136 #include "BLI_arithb.h"
137 #include "BLI_blenlib.h"
138 #include "BLI_editVert.h"
139
140 //#include "editmesh.h"
141 //
142 //#include "blendef.h"
143 //
144 //#include "mydevice.h"
145
146 extern ListBase editNurb;
147 extern ListBase editelems;
148
149 #include "transform.h"
150
151 #include "BLO_sys_types.h" // for intptr_t support
152
153 /************ STUBS TO GET COMPILE ************/
154 void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
155
156
157
158 /* local function prototype - for Object/Bone Constraints */
159 static short constraints_list_needinv(TransInfo *t, ListBase *list);
160 /* local function prototype - for finding number of keyframes that are selected for editing */
161 static int count_ipo_keys(Ipo *ipo, char side, float cfra);
162
163 /* ************************** Functions *************************** */
164
165 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
166         TransData pivot = *head;
167         TransData *ihead = head;
168         TransData *itail = tail;
169         short connected = t->flag & T_PROP_CONNECTED;
170
171         while (head < tail)
172         {
173                 if (connected) {
174                         while ((tail->dist >= pivot.dist) && (head < tail))
175                                 tail--;
176                 }
177                 else {
178                         while ((tail->rdist >= pivot.rdist) && (head < tail))
179                                 tail--;
180                 }
181
182                 if (head != tail)
183                 {
184                         *head = *tail;
185                         head++;
186                 }
187
188                 if (connected) {
189                         while ((head->dist <= pivot.dist) && (head < tail))
190                                 head++;
191                 }
192                 else {
193                         while ((head->rdist <= pivot.rdist) && (head < tail))
194                                 head++;
195                 }
196
197                 if (head != tail)
198                 {
199                         *tail = *head;
200                         tail--;
201                 }
202         }
203
204         *head = pivot;
205         if (ihead < head) {
206                 qsort_trans_data(t, ihead, head-1);
207         }
208         if (itail > head) {
209                 qsort_trans_data(t, head+1, itail);
210         }
211 }
212
213 void sort_trans_data_dist(TransInfo *t) {
214         TransData *start = t->data;
215         int i = 1;
216
217         while(i < t->total && start->flag & TD_SELECTED) {
218                 start++;
219                 i++;
220         }
221         qsort_trans_data(t, start, t->data + t->total - 1);
222 }
223
224 static void sort_trans_data(TransInfo *t) 
225 {
226         TransData *sel, *unsel;
227         TransData temp;
228         unsel = t->data;
229         sel = t->data;
230         sel += t->total - 1;
231         while (sel > unsel) {
232                 while (unsel->flag & TD_SELECTED) {
233                         unsel++;
234                         if (unsel == sel) {
235                                 return;
236                         }
237                 }
238                 while (!(sel->flag & TD_SELECTED)) {
239                         sel--;
240                         if (unsel == sel) {
241                                 return;
242                         }
243                 }
244                 temp = *unsel;
245                 *unsel = *sel;
246                 *sel = temp;
247                 sel--;
248                 unsel++;
249         }
250 }
251
252 /* distance calculated from not-selected vertex to nearest selected vertex
253    warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
254 static void set_prop_dist(TransInfo *t, short with_dist)
255 {
256         TransData *tob;
257         int a;
258
259         for(a=0, tob= t->data; a<t->total; a++, tob++) {
260                 
261                 tob->rdist= 0.0f; // init, it was mallocced
262                 
263                 if((tob->flag & TD_SELECTED)==0) {
264                         TransData *td;
265                         int i;
266                         float dist, vec[3];
267
268                         tob->rdist = -1.0f; // signal for next loop
269                                 
270                         for (i = 0, td= t->data; i < t->total; i++, td++) {
271                                 if(td->flag & TD_SELECTED) {
272                                         VecSubf(vec, tob->center, td->center);
273                                         Mat3MulVecfl(tob->mtx, vec);
274                                         dist = Normalize(vec);
275                                         if (tob->rdist == -1.0f) {
276                                                 tob->rdist = dist;
277                                         }
278                                         else if (dist < tob->rdist) {
279                                                 tob->rdist = dist;
280                                         }
281                                 }
282                                 else break;     // by definition transdata has selected items in beginning
283                         }
284                         if (with_dist) {
285                                 tob->dist = tob->rdist;
286                         }
287                 }       
288         }
289 }
290
291 /* ************************** CONVERSIONS ************************* */
292
293 /* ********************* texture space ********* */
294
295 static void createTransTexspace(bContext *C, TransInfo *t)
296 {
297         Scene *scene = CTX_data_scene(C);
298         TransData *td;
299         Object *ob;
300         ID *id;
301         int *texflag;
302         
303         ob = OBACT;
304         
305         if (ob == NULL) { // Shouldn't logically happen, but still...
306                 t->total = 0;
307                 return;
308         }
309
310         id = ob->data;
311         if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
312                 t->total = 0;
313                 return;
314         }
315
316         t->total = 1;
317         td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
318         td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
319         
320         td->flag= TD_SELECTED;
321         VECCOPY(td->center, ob->obmat[3]);
322         td->ob = ob;
323         
324         Mat3CpyMat4(td->mtx, ob->obmat);
325         Mat3CpyMat4(td->axismtx, ob->obmat);
326         Mat3Ortho(td->axismtx);
327         Mat3Inv(td->smtx, td->mtx);
328         
329         if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
330                 *texflag &= ~AUTOSPACE;
331         }
332         
333         VECCOPY(td->iloc, td->loc);
334         VECCOPY(td->ext->irot, td->ext->rot);
335         VECCOPY(td->ext->isize, td->ext->size);
336 }
337
338 /* ********************* edge (for crease) ***** */
339
340 static void createTransEdge(bContext *C, TransInfo *t) {
341 #if 0   // TRANSFORM_FIX_ME
342         TransData *td = NULL;
343         EditMesh *em = G.editMesh;
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, G.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= G.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, G.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, G.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, G.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, G.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(int total, float *vectors, EditVert **nears)
1760 {
1761         EditMesh *em = G.editMesh;
1762         EditVert *eve;
1763         EditEdge *eed;
1764         int i= 0, done= 1;
1765
1766         /* f2 flag is used for 'selection' */
1767         /* tmp.l is offset on scratch array   */
1768         for(eve= em->verts.first; eve; eve= eve->next) {
1769                 if(eve->h==0) {
1770                         eve->tmp.l = i++;
1771
1772                         if(eve->f & SELECT) {
1773                                 eve->f2= 2;
1774                                 E_NEAR(eve) = eve;
1775                                 E_VEC(eve)[0] = 0.0f;
1776                                 E_VEC(eve)[1] = 0.0f;
1777                                 E_VEC(eve)[2] = 0.0f;
1778                         }
1779                         else {
1780                                 eve->f2 = 0;
1781                         }
1782                 }
1783         }
1784
1785
1786         /* Floodfill routine */
1787         /*
1788         At worst this is n*n of complexity where n is number of edges 
1789         Best case would be n if the list is ordered perfectly.
1790         Estimate is n log n in average (so not too bad)
1791         */
1792         while(done) {
1793                 done= 0;
1794                 
1795                 for(eed= em->edges.first; eed; eed= eed->next) {
1796                         if(eed->h==0) {
1797                                 EditVert *v1= eed->v1, *v2= eed->v2;
1798                                 float *vec2 = E_VEC(v2);
1799                                 float *vec1 = E_VEC(v1);
1800
1801                                 if (v1->f2 + v2->f2 == 4)
1802                                         continue;
1803
1804                                 if (v1->f2) {
1805                                         if (v2->f2) {
1806                                                 float nvec[3];
1807                                                 float len1 = VecLength(vec1);
1808                                                 float len2 = VecLength(vec2);
1809                                                 float lenn;
1810                                                 /* for v2 if not selected */
1811                                                 if (v2->f2 != 2) {
1812                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1813                                                         lenn = VecLength(nvec);
1814                                                         /* 1 < n < 2 */
1815                                                         if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1816                                                                 VECCOPY(vec2, nvec);
1817                                                                 E_NEAR(v2) = E_NEAR(v1);
1818                                                                 done = 1;
1819                                                         }
1820                                                         /* n < 1 < 2 */
1821                                                         else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1822                                                                 VECCOPY(vec2, vec1);
1823                                                                 E_NEAR(v2) = E_NEAR(v1);
1824                                                                 done = 1;
1825                                                         }
1826                                                 }
1827                                                 /* for v1 if not selected */
1828                                                 if (v1->f2 != 2) {
1829                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1830                                                         lenn = VecLength(nvec);
1831                                                         /* 2 < n < 1 */
1832                                                         if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1833                                                                 VECCOPY(vec1, nvec);
1834                                                                 E_NEAR(v1) = E_NEAR(v2);
1835                                                                 done = 1;
1836                                                         }
1837                                                         /* n < 2 < 1 */
1838                                                         else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1839                                                                 VECCOPY(vec1, vec2);
1840                                                                 E_NEAR(v1) = E_NEAR(v2);
1841                                                                 done = 1;
1842                                                         }
1843                                                 }
1844                                         }
1845                                         else {
1846                                                 v2->f2 = 1;
1847                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1848                                                 /* 2 < 1 */
1849                                                 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1850                                                         VECCOPY(vec2, vec1);
1851                                                 }
1852                                                 E_NEAR(v2) = E_NEAR(v1);
1853                                                 done = 1;
1854                                         }
1855                                 }
1856                                 else if (v2->f2) {
1857                                         v1->f2 = 1;
1858                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1859                                         /* 2 < 1 */
1860                                         if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1861                                                 VECCOPY(vec1, vec2);
1862                                         }
1863                                         E_NEAR(v1) = E_NEAR(v2);
1864                                         done = 1;
1865                                 }
1866                         }
1867                 }
1868         }
1869 }
1870
1871 /* loop-in-a-loop I know, but we need it! (ton) */
1872 static void get_face_center(float *cent, EditVert *eve)
1873 {
1874         EditMesh *em = G.editMesh;
1875         EditFace *efa;
1876         
1877         for(efa= em->faces.first; efa; efa= efa->next)
1878                 if(efa->f & SELECT)
1879                         if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1880                                 break;
1881         if(efa) {
1882                 VECCOPY(cent, efa->cent);
1883         }
1884 }
1885
1886 //way to overwrite what data is edited with transform
1887 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1888 static void VertsToTransData(TransData *td, EditVert *eve)
1889 {
1890         td->flag = 0;
1891         //if(key)
1892         //      td->loc = key->co;
1893         //else
1894         td->loc = eve->co;
1895         
1896         VECCOPY(td->center, td->loc);
1897 // TRANSFORM_FIX_ME     
1898 //      if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1899 //              get_face_center(td->center, eve);
1900         VECCOPY(td->iloc, td->loc);
1901
1902         // Setting normals
1903         VECCOPY(td->axismtx[2], eve->no);
1904         td->axismtx[0][0]               =
1905                 td->axismtx[0][1]       =
1906                 td->axismtx[0][2]       =
1907                 td->axismtx[1][0]       =
1908                 td->axismtx[1][1]       =
1909                 td->axismtx[1][2]       = 0.0f;
1910
1911         td->ext = NULL;
1912         td->tdi = NULL;
1913         td->val = NULL;
1914         td->extra = NULL;
1915         if (BIF_GetTransInfo()->mode == TFM_BWEIGHT) {
1916                 td->val = &(eve->bweight);
1917                 td->ival = eve->bweight;
1918         }
1919
1920 #ifdef WITH_VERSE
1921         if(eve->vvert) {
1922                 td->verse = (void*)eve->vvert;
1923                 td->flag |= TD_VERSE_VERT;
1924         }
1925         else
1926                 td->flag &= ~TD_VERSE_VERT;
1927 #endif
1928 }
1929
1930 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1931
1932 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1933 {
1934         float *vec = userData;
1935         
1936         vec+= 3*index;
1937         VECCOPY(vec, co);
1938 }
1939
1940 static int modifiers_disable_subsurf_temporary(Object *ob)
1941 {
1942         ModifierData *md;
1943         int disabled = 0;
1944         
1945         for(md=ob->modifiers.first; md; md=md->next)
1946                 if(md->type==eModifierType_Subsurf)
1947                         if(md->mode & eModifierMode_OnCage) {
1948                                 md->mode ^= eModifierMode_DisableTemporary;
1949                                 disabled= 1;
1950                         }
1951         
1952         return disabled;
1953 }
1954
1955 /* disable subsurf temporal, get mapped cos, and enable it */
1956 static float *get_crazy_mapped_editverts(void)
1957 {
1958         DerivedMesh *dm;
1959         float *vertexcos;
1960
1961         /* disable subsurf temporal, get mapped cos, and enable it */
1962         if(modifiers_disable_subsurf_temporary(G.obedit)) {
1963                 /* need to make new derivemesh */
1964                 makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
1965         }
1966
1967         /* now get the cage */
1968         dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
1969
1970         vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1971         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1972         
1973         dm->release(dm);
1974         
1975         /* set back the flag, no new cage needs to be built, transform does it */
1976         modifiers_disable_subsurf_temporary(G.obedit);
1977         
1978         return vertexcos;
1979 }
1980
1981 #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])
1982 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1983 {
1984         float vecu[3], vecv[3];
1985         float q1[4], q2[4];
1986         
1987         TAN_MAKE_VEC(vecu, v1, v2);
1988         TAN_MAKE_VEC(vecv, v1, v3);
1989         triatoquat(v1, vecu, vecv, q1);
1990         
1991         TAN_MAKE_VEC(vecu, def1, def2);
1992         TAN_MAKE_VEC(vecv, def1, def3);
1993         triatoquat(def1, vecu, vecv, q2);
1994         
1995         QuatSub(quat, q2, q1);
1996 }
1997 #undef TAN_MAKE_VEC
1998
1999 static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats)
2000 {
2001         EditMesh *em = G.editMesh;
2002         EditVert *eve, *prev;
2003         EditFace *efa;
2004         float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2005         intptr_t index= 0;
2006         
2007         /* two abused locations in vertices */
2008         for(eve= em->verts.first; eve; eve= eve->next, index++) {
2009                 eve->tmp.p = NULL;
2010                 eve->prev= (EditVert *)index;
2011         }
2012         
2013         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2014         for(efa= em->faces.first; efa; efa= efa->next) {
2015                 
2016                 /* retrieve mapped coordinates */
2017                 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2018                 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2019                 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2020
2021                 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2022                 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2023                 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2024
2025                 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2026                         set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2027                         efa->v2->tmp.p= (void*)quats;
2028                         quats+= 4;
2029                 }
2030                 
2031                 if(efa->v4) {
2032                         v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2033                         co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2034
2035                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2036                                 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2037                                 efa->v1->tmp.p= (void*)quats;
2038                                 quats+= 4;
2039                         }
2040                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2041                                 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2042                                 efa->v3->tmp.p= (void*)quats;
2043                                 quats+= 4;
2044                         }
2045                         if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2046                                 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2047                                 efa->v4->tmp.p= (void*)quats;
2048                                 quats+= 4;
2049                         }
2050                 }
2051                 else {
2052                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2053                                 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2054                                 efa->v1->tmp.p= (void*)quats;
2055                                 quats+= 4;
2056                         }
2057                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2058                                 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2059                                 efa->v3->tmp.p= (void*)quats;
2060                                 quats+= 4;
2061                         }
2062                 }
2063         }
2064
2065         /* restore abused prev pointer */
2066         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2067                 eve->prev= prev;
2068
2069 }
2070
2071 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2072         BME_Vert *v;
2073         BME_TransData *vtd;
2074         TransData *tob;
2075         int i;
2076
2077         tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2078
2079         for (i=0,v=bm->verts.first;v;v=v->next) {
2080                 if ( (vtd = BME_get_transdata(td,v)) ) {
2081                         tob->loc = vtd->loc;
2082                         tob->val = &vtd->factor;
2083                         VECCOPY(tob->iloc,vtd->co);
2084                         VECCOPY(tob->center,vtd->org);
2085                         VECCOPY(tob->axismtx[0],vtd->vec);
2086                         tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2087                         tob++;
2088                         i++;
2089                 }
2090         }
2091         /* since td is a memarena, it can hold more transdata than actual elements
2092          * (i.e. we can't depend on td->len to determine the number of actual elements) */
2093         t->total = i;
2094 }
2095
2096 static void createTransEditVerts(bContext *C, TransInfo *t)
2097 {
2098         // TRANSFORM_FIX_ME
2099 #if 0
2100         TransData *tob = NULL;
2101         EditMesh *em = G.editMesh;
2102         EditVert *eve;
2103         EditVert **nears = NULL;
2104         EditVert *eve_act = NULL;
2105         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2106         float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2107         int count=0, countsel=0, a, totleft;
2108         int propmode = t->flag & T_PROP_EDIT;
2109         int mirror = 0;
2110         
2111         if ((t->context & CTX_NO_MIRROR) == 0 && (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2112         {
2113                 mirror = 1;
2114         }
2115
2116         // transform now requires awareness for select mode, so we tag the f1 flags in verts
2117         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2118                 for(eve= em->verts.first; eve; eve= eve->next) {
2119                         if(eve->h==0 && (eve->f & SELECT)) 
2120                                 eve->f1= SELECT;
2121                         else
2122                                 eve->f1= 0;
2123                 }
2124         }
2125         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
2126                 EditEdge *eed;
2127                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2128                 for(eed= em->edges.first; eed; eed= eed->next) {
2129                         if(eed->h==0 && (eed->f & SELECT))
2130                                 eed->v1->f1= eed->v2->f1= SELECT;
2131                 }
2132         }
2133         else {
2134                 EditFace *efa;
2135                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2136                 for(efa= em->faces.first; efa; efa= efa->next) {
2137                         if(efa->h==0 && (efa->f & SELECT)) {
2138                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2139                                 if(efa->v4) efa->v4->f1= SELECT;
2140                         }
2141                 }
2142         }
2143         
2144         /* now we can count */
2145         for(eve= em->verts.first; eve; eve= eve->next) {
2146                 if(eve->h==0) {
2147                         if(eve->f1) countsel++;
2148                         if(propmode) count++;
2149                 }
2150         }
2151         
2152         /* note: in prop mode we need at least 1 selected */
2153         if (countsel==0) return;
2154         
2155         /* check active */
2156         if (G.editMesh->selected.last) {
2157                 EditSelection *ese = G.editMesh->selected.last;
2158                 if ( ese->type == EDITVERT ) {
2159                         eve_act = (EditVert *)ese->data;
2160                 }
2161         }
2162
2163         
2164         if(propmode) {
2165                 t->total = count; 
2166         
2167                 /* allocating scratch arrays */
2168                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2169                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2170         }
2171         else t->total = countsel;
2172         tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2173         
2174         Mat3CpyMat4(mtx, G.obedit->obmat);
2175         Mat3Inv(smtx, mtx);
2176
2177         if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
2178         
2179         /* detect CrazySpace [tm] */
2180         if(propmode==0) {
2181                 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
2182                         if(modifiers_isDeformed(G.obedit)) {
2183                                 /* check if we can use deform matrices for modifier from the
2184                                    start up to stack, they are more accurate than quats */
2185                                 totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
2186
2187                                 /* if we still have more modifiers, also do crazyspace
2188                                    correction with quats, relative to the coordinates after
2189                                    the modifiers that support deform matrices (defcos) */
2190                                 if(totleft > 0) {
2191                                         mappedcos= get_crazy_mapped_editverts();
2192                                         quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2193                                         set_crazyspace_quats((float*)defcos, mappedcos, quats);
2194                                         if(mappedcos)
2195                                                 MEM_freeN(mappedcos);
2196                                 }
2197
2198                                 if(defcos)
2199                                         MEM_freeN(defcos);
2200                         }
2201                 }
2202         }
2203         
2204         /* find out which half we do */
2205         if(mirror) {
2206                 for (eve=em->verts.first; eve; eve=eve->next) {
2207                         if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2208                                 if(eve->co[0]<0.0f)
2209                                         mirror = -1;
2210                                 break;
2211                         }
2212                 }
2213         }
2214         
2215         for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2216                 if(eve->h==0) {
2217                         if(propmode || eve->f1) {
2218                                 VertsToTransData(tob, eve);
2219                                 
2220                                 /* selected */
2221                                 if(eve->f1) tob->flag |= TD_SELECTED;
2222                                 
2223                                 /* active */
2224                                 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2225                                 
2226                                 if(propmode) {
2227                                         if (eve->f2) {
2228                                                 float vec[3];
2229                                                 VECCOPY(vec, E_VEC(eve));
2230                                                 Mat3MulVecfl(mtx, vec);
2231                                                 tob->dist= VecLength(vec);
2232                                         }
2233                                         else {
2234                                                 tob->flag |= TD_NOTCONNECTED;
2235                                                 tob->dist = MAXFLOAT;
2236                                         }
2237                                 }
2238                                 
2239                                 /* CrazySpace */
2240                                 if(defmats || (quats && eve->tmp.p)) {
2241                                         float mat[3][3], imat[3][3], qmat[3][3];
2242                                         
2243                                         /* use both or either quat and defmat correction */
2244                                         if(quats && eve->tmp.f) {
2245                                                 QuatToMat3(eve->tmp.p, qmat);
2246
2247                                                 if(defmats)
2248                                                         Mat3MulSerie(mat, mtx, qmat, defmats[a],
2249                                                                 NULL, NULL, NULL, NULL, NULL);
2250                                                 else
2251                                                         Mat3MulMat3(mat, mtx, qmat);
2252                                         }
2253                                         else
2254                                                 Mat3MulMat3(mat, mtx, defmats[a]);
2255
2256                                         Mat3Inv(imat, mat);
2257                                         
2258                                         Mat3CpyMat3(tob->smtx, imat);
2259                                         Mat3CpyMat3(tob->mtx, mat);
2260                                 }
2261                                 else {
2262                                         Mat3CpyMat3(tob->smtx, smtx);
2263                                         Mat3CpyMat3(tob->mtx, mtx);
2264                                 }
2265                                 
2266                                 /* Mirror? */
2267                                 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2268                                         EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc);        /* initializes octree on first call */
2269                                         if(vmir != eve) tob->extra = vmir;
2270                                 }
2271                                 tob++;
2272                         }
2273                 }       
2274         }
2275         if (propmode) {
2276                 MEM_freeN(vectors);
2277                 MEM_freeN(nears);
2278         }
2279         /* crazy space free */
2280         if(quats)
2281                 MEM_freeN(quats);
2282         if(defmats)
2283                 MEM_freeN(defmats);
2284 #endif
2285 }
2286
2287 /* ********************* UV ****************** */
2288
2289 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2290 {
2291         float aspx, aspy;
2292
2293         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2294
2295         /* uv coords are scaled by aspects. this is needed for rotations and
2296            proportional editing to be consistent with the stretchted uv coords
2297            that are displayed. this also means that for display and numinput,
2298            and when the the uv coords are flushed, these are converted each time */
2299         td2d->loc[0] = uv[0]*aspx;
2300         td2d->loc[1] = uv[1]*aspy;
2301         td2d->loc[2] = 0.0f;
2302         td2d->loc2d = uv;
2303
2304         td->flag = 0;
2305         td->loc = td2d->loc;
2306         VECCOPY(td->center, td->loc);
2307         VECCOPY(td->iloc, td->loc);
2308
2309         memset(td->axismtx, 0, sizeof(td->axismtx));
2310         td->axismtx[2][2] = 1.0f;
2311
2312         td->ext= NULL; td->tdi= NULL; td->val= NULL;
2313
2314         if(selected) {
2315                 td->flag |= TD_SELECTED;
2316                 td->dist= 0.0;
2317         }
2318         else {
2319                 td->dist= MAXFLOAT;
2320         }
2321         Mat3One(td->mtx);
2322         Mat3One(td->smtx);
2323 }
2324
2325 static void createTransUVs(bContext *C, TransInfo *t)
2326 {
2327         // TRANSFORM_FIX_ME
2328 #if 0
2329         TransData *td = NULL;
2330         TransData2D *td2d = NULL;
2331         MTFace *tf;
2332         int count=0, countsel=0;
2333         int propmode = t->flag & T_PROP_EDIT;
2334         int efa_s1,efa_s2,efa_s3,efa_s4;
2335
2336         EditMesh *em = G.editMesh;
2337         EditFace *efa;
2338         
2339         if(is_uv_tface_editing_allowed()==0) return;
2340
2341         /* count */
2342         if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2343                 for (efa= em->faces.first; efa; efa= efa->next) {
2344                         /* store face pointer for second loop, prevent second lookup */
2345                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2346                         if (simaFaceDraw_Check(efa, tf)) {
2347                                 efa->tmp.p = tf;
2348                                 
2349                                 efa_s1 = simaUVSel_Check(efa, tf, 0);
2350                                 efa_s2 = simaUVSel_Check(efa, tf, 1);
2351                                 efa_s3 = simaUVSel_Check(efa, tf, 2);
2352                                 if (efa->v4) {
2353                                         efa_s4 = simaUVSel_Check(efa, tf, 3);
2354                                         if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2355                                                 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2356                                         }
2357                                 } else {
2358                                         /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2359                                         if (efa_s1) countsel++; 
2360                                         if (efa_s2) countsel++; 
2361                                         if (efa_s3) countsel++;
2362                                 }
2363                         } else {
2364                                 efa->tmp.p = NULL;
2365                         }
2366                 }
2367         } else {
2368                 for (efa= em->faces.first; efa; efa= efa->next) {
2369                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2370                         if (simaFaceDraw_Check(efa, tf)) {
2371                                 efa->tmp.p = tf;
2372                                 
2373                                 if (simaUVSel_Check(efa, tf, 0)) countsel++; 
2374                                 if (simaUVSel_Check(efa, tf, 1)) countsel++; 
2375                                 if (simaUVSel_Check(efa, tf, 2)) countsel++; 
2376                                 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2377                                 if(propmode)
2378                                         count += (efa->v4)? 4: 3;
2379                         } else {
2380                                 efa->tmp.p = NULL;
2381                         }
2382                 }
2383         }
2384         
2385         /* note: in prop mode we need at least 1 selected */
2386         if (countsel==0) return;
2387         
2388         t->total= (propmode)? count: countsel;
2389         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2390         /* for each 2d uv coord a 3d vector is allocated, so that they can be
2391            treated just as if they were 3d verts */
2392         t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2393
2394         if(G.sima->flag & SI_CLIP_UV)
2395                 t->flag |= T_CLIP_UV;
2396
2397         td= t->data;
2398         td2d= t->data2d;
2399         
2400         if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2401                 for (efa= em->faces.first; efa; efa= efa->next) {
2402                         tf=(MTFace *)efa->tmp.p;
2403                         if (tf) {
2404                                 efa_s1 = simaUVSel_Check(efa, tf, 0);
2405                                 efa_s2 = simaUVSel_Check(efa, tf, 1);
2406                                 efa_s3 = simaUVSel_Check(efa, tf, 2);
2407                                 
2408                                 if (efa->v4) {
2409                                         efa_s4 = simaUVSel_Check(efa, tf, 3);
2410                                         
2411                                         if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2412                                                 /* all corners of this quad need their edges moved. so we must store TD for each */
2413
2414                                                 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2415                                                 if (!efa_s1)    td->flag |= TD_SKIP;
2416                                                 td++; td2d++;
2417
2418                                                 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2419                                                 if (!efa_s2)    td->flag |= TD_SKIP;
2420                                                 td++; td2d++;
2421
2422                                                 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2423                                                 if (!efa_s3)    td->flag |= TD_SKIP;
2424                                                 td++; td2d++;
2425
2426                                                 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2427                                                 if (!efa_s4)    td->flag |= TD_SKIP;
2428                                                 td++; td2d++;
2429                                         }
2430                                 } else {
2431                                         /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2432                                         if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1); 
2433                                         if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1); 
2434                                         if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2435                                 }
2436                         }
2437                 }
2438         } else {
2439                 for (efa= em->faces.first; efa; efa= efa->next) {
2440                         /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2441                         if (simaFaceDraw_Check(efa, tf)) {*/
2442                         if ((tf=(MTFace *)efa->tmp.p)) {
2443                                 if (propmode) {
2444                                         UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2445                                         UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2446                                         UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2447                                         if(efa->v4)
2448                                                 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2449                                 } else {
2450                                         if(simaUVSel_Check(efa, tf, 0))                         UVsToTransData(td++, td2d++, tf->uv[0], 1);
2451                                         if(simaUVSel_Check(efa, tf, 1))                         UVsToTransData(td++, td2d++, tf->uv[1], 1);
2452                                         if(simaUVSel_Check(efa, tf, 2))                         UVsToTransData(td++, td2d++, tf->uv[2], 1);
2453                                         if(efa->v4 && simaUVSel_Check(efa, tf, 3))      UVsToTransData(td++, td2d++, tf->uv[3], 1);
2454                                 }
2455                         }
2456                 }
2457         }
2458         
2459         if (G.sima->flag & SI_LIVE_UNWRAP)
2460                 unwrap_lscm_live_begin();
2461 #endif
2462 }
2463
2464 void flushTransUVs(TransInfo *t)
2465 {
2466 #if 0 // TRANSFORM_FIX_ME
2467         TransData2D *td;
2468         int a, width, height;
2469         Object *ob= OBACT;
2470         EditMesh *em = G.editMesh;
2471         float aspx, aspy, invx, invy;
2472
2473         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2474         transform_width_height_tface_uv(&width, &height);
2475         invx= 1.0f/aspx;
2476         invy= 1.0f/aspy;
2477
2478         /* flush to 2d vector from internally used 3d vector */
2479         for(a=0, td= t->data2d; a<t->total; a++, td++) {
2480                 td->loc2d[0]= td->loc[0]*invx;
2481                 td->loc2d[1]= td->loc[1]*invy;
2482                 
2483                 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2484                         td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2485                         td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2486                 }
2487         }
2488         
2489         if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL)) 
2490                 be_square_tface_uv(em);
2491
2492         /* this is overkill if G.sima->lock is not set, but still needed */
2493         object_uvs_changed(ob);
2494 #endif
2495 }
2496
2497 int clipUVTransform(TransInfo *t, float *vec, int resize)
2498 {
2499 #if 0 // TRANSFORM_FIX_ME
2500         TransData *td;
2501         int a, clipx=1, clipy=1;
2502         float aspx, aspy, min[2], max[2];
2503
2504         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2505         min[0]= min[1]= 0.0f;
2506         max[0]= aspx; max[1]= aspy;
2507
2508         for(a=0, td= t->data; a<t->total; a++, td++) {
2509                 DO_MINMAX2(td->loc, min, max);
2510         }
2511
2512         if(resize) {
2513                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2514                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
2515                 else if(max[0] > aspx && t->center[0] < aspx)
2516                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2517                 else
2518                         clipx= 0;
2519
2520                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2521                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
2522                 else if(max[1] > aspy && t->center[1] < aspy)
2523                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2524                 else
2525                         clipy= 0;
2526         }
2527         else {
2528                 if(min[0] < 0.0f)
2529                         vec[0] -= min[0];
2530                 else if(max[0] > aspx)
2531                         vec[0] -= max[0]-aspx;
2532                 else
2533                         clipx= 0;
2534
2535                 if(min[1] < 0.0f)
2536                         vec[1] -= min[1];
2537                 else if(max[1] > aspy)
2538                         vec[1] -= max[1]-aspy;
2539                 else
2540                         clipy= 0;
2541         }       
2542
2543         return (clipx || clipy);
2544 #endif
2545 return 0;
2546 }
2547
2548 /* ********************* IPO EDITOR ************************* */
2549
2550 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2551  * due to bad globals that would need to be imported specially for this
2552  */
2553 static void createTransIpoData(bContext *C, TransInfo *t)
2554 {
2555         // TRANSFORM_FIX_ME
2556 #if 0
2557         /* in editipo.c due to some globals that are defined in that file... */
2558         make_ipo_transdata(t);
2559 #endif
2560 }
2561
2562 /* this function is called on recalcData to apply the transforms applied
2563  * to the transdata on to the actual keyframe data 
2564  */
2565 void flushTransIpoData(TransInfo *t)
2566 {
2567 #if 0 // TRANSFORM_FIX_ME
2568         TransData2D *td;
2569         int a;
2570         
2571         /* flush to 2d vector from internally used 3d vector */
2572         for (a=0, td= t->data2d; a<t->total; a++, td++) {
2573                 /* we need to unapply the nla-scaling from the time in some situations */
2574                 if (NLA_IPO_SCALED)
2575                         td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2576                 else
2577                         td->loc2d[0]= td->loc[0];
2578                 
2579                 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2580                 if ((t->data[a].flag & TD_TIMEONLY)==0)
2581                         td->loc2d[1]= td->loc[1];
2582         }
2583 #endif
2584 }
2585
2586 /* ********************* ACTION/NLA EDITOR ****************** */
2587
2588 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2589  * any other gp-frames which may reside on that frame (that are not selected).
2590  * It also makes sure gp-frames are still stored in chronological order after
2591  * transform.
2592  */
2593 static void posttrans_gpd_clean (bGPdata *gpd)
2594 {
2595         bGPDlayer *gpl;
2596         
2597         for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2598                 ListBase sel_buffer = {NULL, NULL};
2599                 bGPDframe *gpf, *gpfn;
2600                 bGPDframe *gfs, *gfsn;
2601                 
2602                 /* loop 1: loop through and isolate selected gp-frames to buffer 
2603                  * (these need to be sorted as they are isolated)
2604                  */
2605                 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2606                         short added= 0;
2607                         gpfn= gpf->next;
2608                         
2609                         if (gpf->flag & GP_FRAME_SELECT) {
2610                                 BLI_remlink(&gpl->frames, gpf);
2611                                 
2612                                 /* find place to add them in buffer
2613                                  * - go backwards as most frames will still be in order,
2614                                  *   so doing it this way will be faster 
2615                                  */
2616                                 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2617                                         /* if current (gpf) occurs after this one in buffer, add! */
2618                                         if (gfs->framenum < gpf->framenum) {
2619                                                 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2620                                                 added= 1;
2621                                                 break;
2622                                         }
2623                                 }
2624                                 if (added == 0)
2625                                         BLI_addhead(&sel_buffer, gpf);
2626                         }
2627                 }
2628                 
2629                 /* error checking: it is unlikely, but may be possible to have none selected */
2630                 if (sel_buffer.first == NULL)
2631                         continue;
2632                 
2633                 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2634                 if (gpl->frames.first == NULL) {
2635                         gpl->frames.first= sel_buffer.first;
2636                         gpl->frames.last= sel_buffer.last;
2637                         
2638                         continue;
2639                 }
2640                 
2641                 /* loop 2: remove duplicates of frames in buffers */
2642                 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2643                         gpfn= gpf->next;
2644                         
2645                         /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2646                         for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2647                                 gfsn= gfs->next;
2648                                 
2649                                 /* if this buffer frame needs to go before current, add it! */
2650                                 if (gfs->framenum < gpf->framenum) {
2651                                         /* transfer buffer frame to frames list (before current) */
2652                                         BLI_remlink(&sel_buffer, gfs);
2653                                         BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2654                                 }
2655                                 /* if this buffer frame is on same frame, replace current with it and stop */
2656                                 else if (gfs->framenum == gpf->framenum) {
2657                                         /* transfer buffer frame to frames list (before current) */
2658                                         BLI_remlink(&sel_buffer, gfs);
2659                                         BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2660                                         
2661                                         /* get rid of current frame */
2662                                         // TRANSFORM_FIX_ME
2663                                         //gpencil_layer_delframe(gpl, gpf);
2664                                 }
2665                         }
2666                 }
2667                 
2668                 /* if anything is still in buffer, append to end */
2669                 for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
2670                         gfsn= gfs->next;
2671                         
2672                         BLI_remlink(&sel_buffer, gfs);
2673                         BLI_addtail(&gpl->frames, gfs);
2674                 }
2675         }
2676 }
2677
2678 /* Called by special_aftertrans_update to make sure selected keyframes replace
2679  * any other keyframes which may reside on that frame (that is not selected).
2680  */
2681 static void posttrans_ipo_clean (Ipo *ipo)
2682 {
2683 #if 0 // TRANSFORM_FIX_ME
2684         IpoCurve *icu;
2685         int i;
2686         
2687         /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
2688         for (icu= ipo->curve.first; icu; icu= icu->next) {
2689                 float *selcache;        /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
2690                 int len, index;         /* number of frames in cache, item index */
2691                 
2692                 /* allocate memory for the cache */
2693                 // TODO: investigate using GHash for this instead?
2694                 if (icu->totvert == 0) 
2695                         continue;
2696                 selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
2697                 len= 0;
2698                 index= 0;
2699                 
2700                 /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting 
2701                  * as there is no guarantee what order the keyframes are exactly, even though 
2702                  * they have been sorted by time.
2703                  */
2704                  
2705                 /*      Loop 1: find selected keyframes   */
2706                 for (i = 0; i < icu->totvert; i++) {
2707                         BezTriple *bezt= &icu->bezt[i];
2708                         
2709                         if (BEZSELECTED(bezt)) {
2710                                 selcache[index]= bezt->vec[1][0];
2711                                 index++;
2712                                 len++;
2713                         }
2714                 }
2715                 
2716                 /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
2717                 if (len) {
2718                         for (i = 0; i < icu->totvert; i++) {
2719                                 BezTriple *bezt= &icu->bezt[i];
2720                                 
2721                                 if (BEZSELECTED(bezt) == 0) {
2722                                         /* check beztriple should be removed according to cache */
2723                                         for (index= 0; index < len; index++) {
2724                                                 if (IS_EQ(bezt->vec[1][0], selcache[index])) {
2725                                                         delete_icu_key(icu, i, 0);
2726                                                         break;
2727                                                 }
2728                                                 else if (bezt->vec[1][0] > selcache[index])
2729                                                         break;
2730                                         }
2731                                 }
2732                         }
2733                         
2734                         testhandles_ipocurve(icu);
2735                 }
2736                 
2737                 /* free cache */
2738                 MEM_freeN(selcache);
2739         }
2740 #endif
2741 }
2742
2743 /* Called by special_aftertrans_update to make sure selected keyframes replace
2744  * any other keyframes which may reside on that frame (that is not selected).
2745  * remake_action_ipos should have already been called 
2746  */
2747 static void posttrans_action_clean (bAction *act)
2748 {
2749 #if 0 // TRANSFORM_FIX_ME
2750         ListBase act_data = {NULL, NULL};
2751         bActListElem *ale;
2752         int filter;
2753         
2754         /* filter data */
2755         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
2756         actdata_filter(&act_data, filter, act, ACTCONT_ACTION);
2757         
2758         /* loop through relevant data, removing keyframes from the ipo-blocks that were attached