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