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