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