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