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