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