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