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