Merge with -r 22620:23107.
[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         short hide_handles = (cu->drawflag & CU_HIDE_HANDLES);
1371         
1372         /* to be sure */
1373         if(cu->editnurb==NULL) return;
1374
1375         /* count total of vertices, check identical as in 2nd loop for making transdata! */
1376         for(nu= cu->editnurb->first; nu; nu= nu->next) {
1377                 if(nu->type == CU_BEZIER) {
1378                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1379                                 if(bezt->hide==0) {
1380                                         if (hide_handles) {
1381                                                 if(bezt->f2 & SELECT) countsel+=3;
1382                                                 if(propmode) count+= 3;
1383                                         } else {
1384                                                 if(bezt->f1 & SELECT) countsel++;
1385                                                 if(bezt->f2 & SELECT) countsel++;
1386                                                 if(bezt->f3 & SELECT) countsel++;
1387                                                 if(propmode) count+= 3;
1388                                         }
1389                                 }
1390                         }
1391                 }
1392                 else {
1393                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1394                                 if(bp->hide==0) {
1395                                         if(propmode) count++;
1396                                         if(bp->f1 & SELECT) countsel++;
1397                                 }
1398                         }
1399                 }
1400         }
1401         /* note: in prop mode we need at least 1 selected */
1402         if (countsel==0) return;
1403
1404         if(propmode) t->total = count;
1405         else t->total = countsel;
1406         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1407
1408         Mat3CpyMat4(mtx, t->obedit->obmat);
1409         Mat3Inv(smtx, mtx);
1410
1411     td = t->data;
1412         for(nu= cu->editnurb->first; nu; nu= nu->next) {
1413                 if(nu->type == CU_BEZIER) {
1414                         TransData *head, *tail;
1415                         head = tail = td;
1416                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1417                                 if(bezt->hide==0) {
1418                                         TransDataCurveHandleFlags *hdata = NULL;
1419
1420                                         if(             propmode ||
1421                                                         ((bezt->f2 & SELECT) && hide_handles) ||
1422                                                         ((bezt->f1 & SELECT) && hide_handles == 0)
1423                                           ) {
1424                                                 VECCOPY(td->iloc, bezt->vec[0]);
1425                                                 td->loc= bezt->vec[0];
1426                                                 VECCOPY(td->center, bezt->vec[1]);
1427                                                 if (hide_handles) {
1428                                                         if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1429                                                         else td->flag= 0;
1430                                                 } else {
1431                                                         if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1432                                                         else td->flag= 0;
1433                                                 }
1434                                                 td->ext = NULL;
1435                                                 td->tdi = NULL;
1436                                                 td->val = NULL;
1437
1438                                                 hdata = initTransDataCurveHandes(td, bezt);
1439
1440                                                 Mat3CpyMat3(td->smtx, smtx);
1441                                                 Mat3CpyMat3(td->mtx, mtx);
1442
1443                                                 td++;
1444                                                 count++;
1445                                                 tail++;
1446                                         }
1447
1448                                         /* This is the Curve Point, the other two are handles */
1449                                         if(propmode || (bezt->f2 & SELECT)) {
1450                                                 VECCOPY(td->iloc, bezt->vec[1]);
1451                                                 td->loc= bezt->vec[1];
1452                                                 VECCOPY(td->center, td->loc);
1453                                                 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1454                                                 else td->flag= 0;
1455                                                 td->ext = NULL;
1456                                                 td->tdi = NULL;
1457
1458                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1459                                                         td->val = &(bezt->radius);
1460                                                         td->ival = bezt->radius;
1461                                                 } else if (t->mode==TFM_TILT) {
1462                                                         td->val = &(bezt->alfa);
1463                                                         td->ival = bezt->alfa;
1464                                                 } else {
1465                                                         td->val = NULL;
1466                                                 }
1467
1468                                                 Mat3CpyMat3(td->smtx, smtx);
1469                                                 Mat3CpyMat3(td->mtx, mtx);
1470
1471                                                 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1472                                                 /* If the middle is selected but the sides arnt, this is needed */
1473                                                 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1474                                                         hdata = initTransDataCurveHandes(td, bezt);
1475                                                 }
1476
1477                                                 td++;
1478                                                 count++;
1479                                                 tail++;
1480                                         }
1481                                         if(             propmode ||
1482                                                         ((bezt->f2 & SELECT) && hide_handles) ||
1483                                                         ((bezt->f3 & SELECT) && hide_handles == 0)
1484                                           ) {
1485                                                 VECCOPY(td->iloc, bezt->vec[2]);
1486                                                 td->loc= bezt->vec[2];
1487                                                 VECCOPY(td->center, bezt->vec[1]);
1488                                                 if (hide_handles) {
1489                                                         if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1490                                                         else td->flag= 0;
1491                                                 } else {
1492                                                         if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1493                                                         else td->flag= 0;
1494                                                 }
1495                                                 td->ext = NULL;
1496                                                 td->tdi = NULL;
1497                                                 td->val = NULL;
1498
1499                                                 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1500                                                         hdata = initTransDataCurveHandes(td, bezt);
1501                                                 }
1502
1503                                                 Mat3CpyMat3(td->smtx, smtx);
1504                                                 Mat3CpyMat3(td->mtx, mtx);
1505
1506                                                 td++;
1507                                                 count++;
1508                                                 tail++;
1509                                         }
1510                                 }
1511                                 else if (propmode && head != tail) {
1512                                         calc_distanceCurveVerts(head, tail-1);
1513                                         head = tail;
1514                                 }
1515                         }
1516                         if (propmode && head != tail)
1517                                 calc_distanceCurveVerts(head, tail-1);
1518
1519                         /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1520                          * but for now just dont change handle types */
1521                         if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1522                                 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1523                 }
1524                 else {
1525                         TransData *head, *tail;
1526                         head = tail = td;
1527                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1528                                 if(bp->hide==0) {
1529                                         if(propmode || (bp->f1 & SELECT)) {
1530                                                 VECCOPY(td->iloc, bp->vec);
1531                                                 td->loc= bp->vec;
1532                                                 VECCOPY(td->center, td->loc);
1533                                                 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1534                                                 else td->flag= 0;
1535                                                 td->ext = NULL;
1536                                                 td->tdi = NULL;
1537
1538                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1539                                                         td->val = &(bp->radius);
1540                                                         td->ival = bp->radius;
1541                                                 } else {
1542                                                         td->val = &(bp->alfa);
1543                                                         td->ival = bp->alfa;
1544                                                 }
1545
1546                                                 Mat3CpyMat3(td->smtx, smtx);
1547                                                 Mat3CpyMat3(td->mtx, mtx);
1548
1549                                                 td++;
1550                                                 count++;
1551                                                 tail++;
1552                                         }
1553                                 }
1554                                 else if (propmode && head != tail) {
1555                                         calc_distanceCurveVerts(head, tail-1);
1556                                         head = tail;
1557                                 }
1558                         }
1559                         if (propmode && head != tail)
1560                                 calc_distanceCurveVerts(head, tail-1);
1561                 }
1562         }
1563 }
1564
1565 /* ********************* lattice *************** */
1566
1567 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1568 {
1569         Lattice *latt = ((Lattice*)t->obedit->data)->editlatt;
1570         TransData *td = NULL;
1571         BPoint *bp;
1572         float mtx[3][3], smtx[3][3];
1573         int a;
1574         int count=0, countsel=0;
1575         int propmode = t->flag & T_PROP_EDIT;
1576
1577         bp = latt->def;
1578         a  = latt->pntsu * latt->pntsv * latt->pntsw;
1579         while(a--) {
1580                 if(bp->hide==0) {
1581                         if(bp->f1 & SELECT) countsel++;
1582                         if(propmode) count++;
1583                 }
1584                 bp++;
1585         }
1586
1587         /* note: in prop mode we need at least 1 selected */
1588         if (countsel==0) return;
1589
1590         if(propmode) t->total = count;
1591         else t->total = countsel;
1592         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1593
1594         Mat3CpyMat4(mtx, t->obedit->obmat);
1595         Mat3Inv(smtx, mtx);
1596
1597         td = t->data;
1598         bp = latt->def;
1599         a  = latt->pntsu * latt->pntsv * latt->pntsw;
1600         while(a--) {
1601                 if(propmode || (bp->f1 & SELECT)) {
1602                         if(bp->hide==0) {
1603                                 VECCOPY(td->iloc, bp->vec);
1604                                 td->loc= bp->vec;
1605                                 VECCOPY(td->center, td->loc);
1606                                 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1607                                 else td->flag= 0;
1608                                 Mat3CpyMat3(td->smtx, smtx);
1609                                 Mat3CpyMat3(td->mtx, mtx);
1610
1611                                 td->ext = NULL;
1612                                 td->tdi = NULL;
1613                                 td->val = NULL;
1614
1615                                 td++;
1616                                 count++;
1617                         }
1618                 }
1619                 bp++;
1620         }
1621 }
1622
1623 /* ******************* particle edit **************** */
1624 static void createTransParticleVerts(bContext *C, TransInfo *t)
1625 {
1626         TransData *td = NULL;
1627         TransDataExtension *tx;
1628         Base *base = CTX_data_active_base(C);
1629         Object *ob = CTX_data_active_object(C);
1630         ParticleEditSettings *pset = PE_settings(t->scene);
1631         PTCacheEdit *edit = PE_get_current(t->scene, ob);
1632         ParticleSystem *psys = NULL;
1633         ParticleSystemModifierData *psmd = NULL;
1634         PTCacheEditPoint *point;
1635         PTCacheEditKey *key;
1636         float mat[4][4];
1637         int i,k, transformparticle;
1638         int count = 0, hasselected = 0;
1639         int propmode = t->flag & T_PROP_EDIT;
1640
1641         if(edit==NULL || t->settings->particle.selectmode==SCE_SELECT_PATH) return;
1642
1643         psys = edit->psys;
1644
1645         if(psys)
1646                 psmd = psys_get_modifier(ob,psys);
1647
1648         base->flag |= BA_HAS_RECALC_DATA;
1649
1650         for(i=0, point=edit->points; i<edit->totpoint; i++, point++) {
1651                 point->flag &= ~PEP_TRANSFORM;
1652                 transformparticle= 0;
1653
1654                 if((point->flag & PEP_HIDE)==0) {
1655                         for(k=0, key=point->keys; k<point->totkey; k++, key++) {
1656                                 if((key->flag&PEK_HIDE)==0) {
1657                                         if(key->flag&PEK_SELECT) {
1658                                                 hasselected= 1;
1659                                                 transformparticle= 1;
1660                                         }
1661                                         else if(propmode)
1662                                                 transformparticle= 1;
1663                                 }
1664                         }
1665                 }
1666
1667                 if(transformparticle) {
1668                         count += point->totkey;
1669                         point->flag |= PEP_TRANSFORM;
1670                 }
1671         }
1672
1673         /* note: in prop mode we need at least 1 selected */
1674         if (hasselected==0) return;
1675
1676         t->total = count;
1677         td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1678
1679         if(t->mode == TFM_BAKE_TIME)
1680                 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1681         else
1682                 tx = t->ext = NULL;
1683
1684         Mat4One(mat);
1685
1686         Mat4Invert(ob->imat,ob->obmat);
1687
1688         for(i=0, point=edit->points; i<edit->totpoint; i++, point++) {
1689                 TransData *head, *tail;
1690                 head = tail = td;
1691
1692                 if(!(point->flag & PEP_TRANSFORM)) continue;
1693
1694                 if(psys && !(psys->flag & PSYS_GLOBAL_HAIR))
1695                         psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
1696
1697                 for(k=0, key=point->keys; k<point->totkey; k++, key++) {
1698                         if(key->flag & PEK_USE_WCO) {
1699                                 VECCOPY(key->world_co, key->co);
1700                                 Mat4MulVecfl(mat, key->world_co);
1701                                 td->loc = key->world_co;
1702                         }
1703                         else
1704                                 td->loc = key->co;
1705
1706                         VECCOPY(td->iloc, td->loc);
1707                         VECCOPY(td->center, td->loc);
1708
1709                         if(key->flag & PEK_SELECT)
1710                                 td->flag |= TD_SELECTED;
1711                         else if(!propmode)
1712                                 td->flag |= TD_SKIP;
1713
1714                         Mat3One(td->mtx);
1715                         Mat3One(td->smtx);
1716
1717                         /* don't allow moving roots */
1718                         if(k==0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
1719                                 td->protectflag |= OB_LOCK_LOC;
1720
1721                         td->ob = ob;
1722                         td->ext = tx;
1723                         td->tdi = NULL;
1724                         if(t->mode == TFM_BAKE_TIME) {
1725                                 td->val = key->time;
1726                                 td->ival = *(key->time);
1727                                 /* abuse size and quat for min/max values */
1728                                 td->flag |= TD_NO_EXT;
1729                                 if(k==0) tx->size = 0;
1730                                 else tx->size = (key - 1)->time;
1731
1732                                 if(k == point->totkey - 1) tx->quat = 0;
1733                                 else tx->quat = (key + 1)->time;
1734                         }
1735
1736                         td++;
1737                         if(tx)
1738                                 tx++;
1739                         tail++;
1740                 }
1741                 if (propmode && head != tail)
1742                         calc_distanceCurveVerts(head, tail - 1);
1743         }
1744 }
1745
1746 void flushTransParticles(TransInfo *t)
1747 {
1748         Scene *scene = t->scene;
1749         Object *ob = OBACT;
1750         PTCacheEdit *edit = PE_get_current(scene, ob);
1751         ParticleSystem *psys = edit->psys;
1752         ParticleSystemModifierData *psmd = NULL;
1753         PTCacheEditPoint *point;
1754         PTCacheEditKey *key;
1755         TransData *td;
1756         float mat[4][4], imat[4][4], co[3];
1757         int i, k, propmode = t->flag & T_PROP_EDIT;
1758
1759         if(psys)
1760                 psmd = psys_get_modifier(ob, psys);
1761
1762         /* we do transform in world space, so flush world space position
1763          * back to particle local space (only for hair particles) */
1764         td= t->data;
1765         for(i=0, point=edit->points; i<edit->totpoint; i++, point++, td++) {
1766                 if(!(point->flag & PEP_TRANSFORM)) continue;
1767
1768                 if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
1769                         psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
1770                         Mat4Invert(imat,mat);
1771
1772                         for(k=0, key=point->keys; k<point->totkey; k++, key++) {
1773                                 VECCOPY(co, key->world_co);
1774                                 Mat4MulVecfl(imat, co);
1775
1776
1777                                 /* optimization for proportional edit */
1778                                 if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1779                                         VECCOPY(key->co, co);
1780                                         point->flag |= PEP_EDIT_RECALC;
1781                                 }
1782                         }
1783                 }
1784                 else
1785                         point->flag |= PEP_EDIT_RECALC;
1786         }
1787
1788         PE_update_object(scene, OBACT, 1);
1789 }
1790
1791 /* ********************* mesh ****************** */
1792
1793 /* proportional distance based on connectivity  */
1794 #define E_VEC(a)        (vectors + (3 * (a)->tmp.l))
1795 #define E_NEAR(a)       (nears[((a)->tmp.l)])
1796 #define THRESHOLD       0.0001f
1797 static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
1798 {
1799         EditVert *eve;
1800         EditEdge *eed;
1801         int i= 0, done= 1;
1802
1803         /* f2 flag is used for 'selection' */
1804         /* tmp.l is offset on scratch array   */
1805         for(eve= em->verts.first; eve; eve= eve->next) {
1806                 if(eve->h==0) {
1807                         eve->tmp.l = i++;
1808
1809                         if(eve->f & SELECT) {
1810                                 eve->f2= 2;
1811                                 E_NEAR(eve) = eve;
1812                                 E_VEC(eve)[0] = 0.0f;
1813                                 E_VEC(eve)[1] = 0.0f;
1814                                 E_VEC(eve)[2] = 0.0f;
1815                         }
1816                         else {
1817                                 eve->f2 = 0;
1818                         }
1819                 }
1820         }
1821
1822
1823         /* Floodfill routine */
1824         /*
1825         At worst this is n*n of complexity where n is number of edges
1826         Best case would be n if the list is ordered perfectly.
1827         Estimate is n log n in average (so not too bad)
1828         */
1829         while(done) {
1830                 done= 0;
1831
1832                 for(eed= em->edges.first; eed; eed= eed->next) {
1833                         if(eed->h==0) {
1834                                 EditVert *v1= eed->v1, *v2= eed->v2;
1835                                 float *vec2 = E_VEC(v2);
1836                                 float *vec1 = E_VEC(v1);
1837
1838                                 if (v1->f2 + v2->f2 == 4)
1839                                         continue;
1840
1841                                 if (v1->f2) {
1842                                         if (v2->f2) {
1843                                                 float nvec[3];
1844                                                 float len1 = VecLength(vec1);
1845                                                 float len2 = VecLength(vec2);
1846                                                 float lenn;
1847                                                 /* for v2 if not selected */
1848                                                 if (v2->f2 != 2) {
1849                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1850                                                         lenn = VecLength(nvec);
1851                                                         /* 1 < n < 2 */
1852                                                         if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1853                                                                 VECCOPY(vec2, nvec);
1854                                                                 E_NEAR(v2) = E_NEAR(v1);
1855                                                                 done = 1;
1856                                                         }
1857                                                         /* n < 1 < 2 */
1858                                                         else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1859                                                                 VECCOPY(vec2, vec1);
1860                                                                 E_NEAR(v2) = E_NEAR(v1);
1861                                                                 done = 1;
1862                                                         }
1863                                                 }
1864                                                 /* for v1 if not selected */
1865                                                 if (v1->f2 != 2) {
1866                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1867                                                         lenn = VecLength(nvec);
1868                                                         /* 2 < n < 1 */
1869                                                         if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1870                                                                 VECCOPY(vec1, nvec);
1871                                                                 E_NEAR(v1) = E_NEAR(v2);
1872                                                                 done = 1;
1873                                                         }
1874                                                         /* n < 2 < 1 */
1875                                                         else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1876                                                                 VECCOPY(vec1, vec2);
1877                                                                 E_NEAR(v1) = E_NEAR(v2);
1878                                                                 done = 1;
1879                                                         }
1880                                                 }
1881                                         }
1882                                         else {
1883                                                 v2->f2 = 1;
1884                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1885                                                 /* 2 < 1 */
1886                                                 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1887                                                         VECCOPY(vec2, vec1);
1888                                                 }
1889                                                 E_NEAR(v2) = E_NEAR(v1);
1890                                                 done = 1;
1891                                         }
1892                                 }
1893                                 else if (v2->f2) {
1894                                         v1->f2 = 1;
1895                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1896                                         /* 2 < 1 */
1897                                         if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1898                                                 VECCOPY(vec1, vec2);
1899                                         }
1900                                         E_NEAR(v1) = E_NEAR(v2);
1901                                         done = 1;
1902                                 }
1903                         }
1904                 }
1905         }
1906 }
1907
1908 /* loop-in-a-loop I know, but we need it! (ton) */
1909 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
1910 {
1911         EditFace *efa;
1912
1913         for(efa= em->faces.first; efa; efa= efa->next)
1914                 if(efa->f & SELECT)
1915                         if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1916                                 break;
1917         if(efa) {
1918                 VECCOPY(cent, efa->cent);
1919         }
1920 }
1921
1922 //way to overwrite what data is edited with transform
1923 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1924 static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
1925 {
1926         td->flag = 0;
1927         //if(key)
1928         //      td->loc = key->co;
1929         //else
1930         td->loc = eve->co;
1931
1932         VECCOPY(td->center, td->loc);
1933         if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1934                 get_face_center(td->center, em, eve);
1935         VECCOPY(td->iloc, td->loc);
1936
1937         // Setting normals
1938         VECCOPY(td->axismtx[2], eve->no);
1939         td->axismtx[0][0]               =
1940                 td->axismtx[0][1]       =
1941                 td->axismtx[0][2]       =
1942                 td->axismtx[1][0]       =
1943                 td->axismtx[1][1]       =
1944                 td->axismtx[1][2]       = 0.0f;
1945
1946         td->ext = NULL;
1947         td->tdi = NULL;
1948         td->val = NULL;
1949         td->extra = NULL;
1950         if (t->mode == TFM_BWEIGHT) {
1951                 td->val = &(eve->bweight);
1952                 td->ival = eve->bweight;
1953         }
1954 }
1955
1956 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1957
1958 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1959 {
1960         float *vec = userData;
1961
1962         vec+= 3*index;
1963         VECCOPY(vec, co);
1964 }
1965
1966 static int modifiers_disable_subsurf_temporary(Object *ob)
1967 {
1968         ModifierData *md;
1969         int disabled = 0;
1970
1971         for(md=ob->modifiers.first; md; md=md->next)
1972                 if(md->type==eModifierType_Subsurf)
1973                         if(md->mode & eModifierMode_OnCage) {
1974                                 md->mode ^= eModifierMode_DisableTemporary;
1975                                 disabled= 1;
1976                         }
1977
1978         return disabled;
1979 }
1980
1981 /* disable subsurf temporal, get mapped cos, and enable it */
1982 static float *get_crazy_mapped_editverts(TransInfo *t)
1983 {
1984         Mesh *me= t->obedit->data;
1985         DerivedMesh *dm;
1986         float *vertexcos;
1987
1988         /* disable subsurf temporal, get mapped cos, and enable it */
1989         if(modifiers_disable_subsurf_temporary(t->obedit)) {
1990                 /* need to make new derivemesh */
1991                 makeDerivedMesh(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1992         }
1993
1994         /* now get the cage */
1995         dm= editmesh_get_derived_cage(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1996
1997         vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_mesh->totvert, "vertexcos map");
1998         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1999
2000         dm->release(dm);
2001
2002         /* set back the flag, no new cage needs to be built, transform does it */
2003         modifiers_disable_subsurf_temporary(t->obedit);
2004
2005         return vertexcos;
2006 }
2007
2008 #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])
2009 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
2010 {
2011         float vecu[3], vecv[3];
2012         float q1[4], q2[4];
2013
2014         TAN_MAKE_VEC(vecu, v1, v2);
2015         TAN_MAKE_VEC(vecv, v1, v3);
2016         triatoquat(v1, vecu, vecv, q1);
2017
2018         TAN_MAKE_VEC(vecu, def1, def2);
2019         TAN_MAKE_VEC(vecv, def1, def3);
2020         triatoquat(def1, vecu, vecv, q2);
2021
2022         QuatSub(quat, q2, q1);
2023 }
2024 #undef TAN_MAKE_VEC
2025
2026 static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
2027 {
2028         EditVert *eve, *prev;
2029         EditFace *efa;
2030         float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2031         intptr_t index= 0;
2032
2033         /* two abused locations in vertices */
2034         for(eve= em->verts.first; eve; eve= eve->next, index++) {
2035                 eve->tmp.p = NULL;
2036                 eve->prev= (EditVert *)index;
2037         }
2038
2039         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2040         for(efa= em->faces.first; efa; efa= efa->next) {
2041
2042                 /* retrieve mapped coordinates */
2043                 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2044                 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2045                 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2046
2047                 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2048                 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2049                 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2050
2051                 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2052                         set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2053                         efa->v2->tmp.p= (void*)quats;
2054                         quats+= 4;
2055                 }
2056
2057                 if(efa->v4) {
2058                         v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2059                         co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2060
2061                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2062                                 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2063                                 efa->v1->tmp.p= (void*)quats;
2064                                 quats+= 4;
2065                         }
2066                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2067                                 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2068                                 efa->v3->tmp.p= (void*)quats;
2069                                 quats+= 4;
2070                         }
2071                         if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2072                                 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2073                                 efa->v4->tmp.p= (void*)quats;
2074                                 quats+= 4;
2075                         }
2076                 }
2077                 else {
2078                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2079                                 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2080                                 efa->v1->tmp.p= (void*)quats;
2081                                 quats+= 4;
2082                         }
2083                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2084                                 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2085                                 efa->v3->tmp.p= (void*)quats;
2086                                 quats+= 4;
2087                         }
2088                 }
2089         }
2090
2091         /* restore abused prev pointer */
2092         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2093                 eve->prev= prev;
2094
2095 }
2096
2097 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2098         BME_Vert *v;
2099         BME_TransData *vtd;
2100         TransData *tob;
2101         int i;
2102
2103         tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2104
2105         for (i=0,v=bm->verts.first;v;v=v->next) {
2106                 if ( (vtd = BME_get_transdata(td,v)) ) {
2107                         tob->loc = vtd->loc;
2108                         tob->val = &vtd->factor;
2109                         VECCOPY(tob->iloc,vtd->co);
2110                         VECCOPY(tob->center,vtd->org);
2111                         VECCOPY(tob->axismtx[0],vtd->vec);
2112                         tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2113                         tob++;
2114                         i++;
2115                 }
2116         }
2117         /* since td is a memarena, it can hold more transdata than actual elements
2118          * (i.e. we can't depend on td->len to determine the number of actual elements) */
2119         t->total = i;
2120 }
2121
2122 static void createTransEditVerts(bContext *C, TransInfo *t)
2123 {
2124         ToolSettings *ts = CTX_data_tool_settings(C);
2125         TransData *tob = NULL;
2126         EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2127         EditVert *eve;
2128         EditVert **nears = NULL;
2129         EditVert *eve_act = NULL;
2130         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2131         float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2132         int count=0, countsel=0, a, totleft;
2133         int propmode = t->flag & T_PROP_EDIT;
2134         int mirror = 0;
2135
2136         if (t->flag & T_MIRROR)
2137         {
2138                 mirror = 1;
2139         }
2140
2141         // transform now requires awareness for select mode, so we tag the f1 flags in verts
2142         if(ts->selectmode & SCE_SELECT_VERTEX) {
2143                 for(eve= em->verts.first; eve; eve= eve->next) {
2144                         if(eve->h==0 && (eve->f & SELECT))
2145                                 eve->f1= SELECT;
2146                         else
2147                                 eve->f1= 0;
2148                 }
2149         }
2150         else if(ts->selectmode & SCE_SELECT_EDGE) {
2151                 EditEdge *eed;
2152                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2153                 for(eed= em->edges.first; eed; eed= eed->next) {
2154                         if(eed->h==0 && (eed->f & SELECT))
2155                                 eed->v1->f1= eed->v2->f1= SELECT;
2156                 }
2157         }
2158         else {
2159                 EditFace *efa;
2160                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2161                 for(efa= em->faces.first; efa; efa= efa->next) {
2162                         if(efa->h==0 && (efa->f & SELECT)) {
2163                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2164                                 if(efa->v4) efa->v4->f1= SELECT;
2165                         }
2166                 }
2167         }
2168
2169         /* now we can count */
2170         for(eve= em->verts.first; eve; eve= eve->next) {
2171                 if(eve->h==0) {
2172                         if(eve->f1) countsel++;
2173                         if(propmode) count++;
2174                 }
2175         }
2176
2177         /* note: in prop mode we need at least 1 selected */
2178         if (countsel==0) return;
2179
2180         /* check active */
2181         if (em->selected.last) {
2182                 EditSelection *ese = em->selected.last;
2183                 if ( ese->type == EDITVERT ) {
2184                         eve_act = (EditVert *)ese->data;
2185                 }
2186         }
2187
2188
2189         if(propmode) {
2190                 t->total = count;
2191
2192                 /* allocating scratch arrays */
2193                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2194                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2195         }
2196         else t->total = countsel;
2197         tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2198
2199         Mat3CpyMat4(mtx, t->obedit->obmat);
2200         Mat3Inv(smtx, mtx);
2201
2202         if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
2203
2204         /* detect CrazySpace [tm] */
2205         if(propmode==0) {
2206                 if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
2207                         if(modifiers_isDeformed(t->scene, t->obedit)) {
2208                                 /* check if we can use deform matrices for modifier from the
2209                                    start up to stack, they are more accurate than quats */
2210                                 totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
2211
2212                                 /* if we still have more modifiers, also do crazyspace
2213                                    correction with quats, relative to the coordinates after
2214                                    the modifiers that support deform matrices (defcos) */
2215                                 if(totleft > 0) {
2216                                         mappedcos= get_crazy_mapped_editverts(t);
2217                                         quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2218                                         set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
2219                                         if(mappedcos)
2220                                                 MEM_freeN(mappedcos);
2221                                 }
2222
2223                                 if(defcos)
2224                                         MEM_freeN(defcos);
2225                         }
2226                 }
2227         }
2228
2229         /* find out which half we do */
2230         if(mirror) {
2231                 for (eve=em->verts.first; eve; eve=eve->next) {
2232                         if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2233                                 if(eve->co[0]<0.0f)
2234                                         mirror = -1;
2235                                 break;
2236                         }
2237                 }
2238         }
2239
2240         for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2241                 if(eve->h==0) {
2242                         if(propmode || eve->f1) {
2243                                 VertsToTransData(t, tob, em, eve);
2244
2245                                 /* selected */
2246                                 if(eve->f1) tob->flag |= TD_SELECTED;
2247
2248                                 /* active */
2249                                 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2250
2251                                 if(propmode) {
2252                                         if (eve->f2) {
2253                                                 float vec[3];
2254                                                 VECCOPY(vec, E_VEC(eve));
2255                                                 Mat3MulVecfl(mtx, vec);
2256                                                 tob->dist= VecLength(vec);
2257                                         }
2258                                         else {
2259                                                 tob->flag |= TD_NOTCONNECTED;
2260                                                 tob->dist = MAXFLOAT;
2261                                         }
2262                                 }
2263
2264                                 /* CrazySpace */
2265                                 if(defmats || (quats && eve->tmp.p)) {
2266                                         float mat[3][3], imat[3][3], qmat[3][3];
2267
2268                                         /* use both or either quat and defmat correction */
2269                                         if(quats && eve->tmp.f) {
2270                                                 QuatToMat3(eve->tmp.p, qmat);
2271
2272                                                 if(defmats)
2273                                                         Mat3MulSerie(mat, mtx, qmat, defmats[a],
2274                                                                 NULL, NULL, NULL, NULL, NULL);
2275                                                 else
2276                                                         Mat3MulMat3(mat, mtx, qmat);
2277                                         }
2278                                         else
2279                                                 Mat3MulMat3(mat, mtx, defmats[a]);
2280
2281                                         Mat3Inv(imat, mat);
2282
2283                                         Mat3CpyMat3(tob->smtx, imat);
2284                                         Mat3CpyMat3(tob->mtx, mat);
2285                                 }
2286                                 else {
2287                                         Mat3CpyMat3(tob->smtx, smtx);
2288                                         Mat3CpyMat3(tob->mtx, mtx);
2289                                 }
2290
2291                                 /* Mirror? */
2292                                 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2293                                         EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc);   /* initializes octree on first call */
2294                                         if(vmir != eve) tob->extra = vmir;
2295                                 }
2296                                 tob++;
2297                         }
2298                 }
2299         }
2300         if (propmode) {
2301                 MEM_freeN(vectors);
2302                 MEM_freeN(nears);
2303         }
2304         /* crazy space free */
2305         if(quats)
2306                 MEM_freeN(quats);
2307         if(defmats)
2308                 MEM_freeN(defmats);
2309 }
2310
2311 /* *** NODE EDITOR *** */
2312 void flushTransNodes(TransInfo *t)
2313 {
2314         int a;
2315         TransData2D *td;
2316
2317         /* flush to 2d vector from internally used 3d vector */
2318         for(a=0, td= t->data2d; a<t->total; a++, td++) {
2319                 td->loc2d[0]= td->loc[0];
2320                 td->loc2d[1]= td->loc[1];
2321         }
2322 }
2323
2324 /* *** SEQUENCE EDITOR *** */
2325 void flushTransSeq(TransInfo *t)
2326 {
2327         ListBase *seqbasep= seq_give_editing(t->scene, FALSE)->seqbasep; /* Editing null check alredy done */
2328         int a, new_frame;
2329         TransData *td= t->data;
2330         TransData2D *td2d= t->data2d;
2331         TransDataSeq *tdsq= NULL;
2332         Sequence *seq;
2333
2334
2335
2336         /* prevent updating the same seq twice
2337          * if the transdata order is changed this will mess up
2338          * but so will TransDataSeq */
2339         Sequence *seq_prev= NULL;
2340
2341         /* flush to 2d vector from internally used 3d vector */
2342         for(a=0; a<t->total; a++, td++, td2d++) {
2343
2344                 tdsq= (TransDataSeq *)td->extra;
2345                 seq= tdsq->seq;
2346                 new_frame= (int)(td2d->loc[0] + 0.5f);
2347
2348                 switch (tdsq->sel_flag) {
2349                 case SELECT:
2350                         if (seq->type != SEQ_META && seq_tx_test(seq)) /* for meta's, their children move */
2351                                 seq->start= new_frame - tdsq->start_offset;
2352
2353                         if (seq->depth==0) {
2354                                 seq->machine= (int)(td2d->loc[1] + 0.5f);
2355                                 CLAMP(seq->machine, 1, MAXSEQ);
2356                         }
2357                         break;
2358                 case SEQ_LEFTSEL: /* no vertical transform  */
2359                         seq_tx_set_final_left(seq, new_frame);
2360                         seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2361                         fix_single_seq(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2362                         break;
2363                 case SEQ_RIGHTSEL: /* no vertical transform  */
2364                         seq_tx_set_final_right(seq, new_frame);
2365                         seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2366                         fix_single_seq(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2367                         break;
2368                 }
2369
2370                 if (seq != seq_prev) {
2371                         if(seq->depth==0) {
2372                                 /* Calculate this strip and all nested strips
2373                                  * children are ALWAYS transformed first
2374                                  * so we dont need to do this in another loop. */
2375                                 calc_sequence(seq);
2376
2377                                 /* test overlap, displayes red outline */
2378                                 seq->flag &= ~SEQ_OVERLAP;
2379                                 if( seq_test_overlap(seqbasep, seq) ) {
2380                                         seq->flag |= SEQ_OVERLAP;
2381                                 }
2382                         }
2383                         else {
2384                                 calc_sequence_disp(seq);
2385                         }
2386                 }
2387                 seq_prev= seq;
2388         }
2389
2390         if (t->mode == TFM_TIME_TRANSLATE) { /* originally TFM_TIME_EXTEND, transform changes */
2391                 /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
2392                 seq= seqbasep->first;
2393
2394                 while(seq) {
2395                         if (seq->type == SEQ_META && seq->flag & SELECT)
2396                                 calc_sequence(seq);
2397                         seq= seq->next;
2398                 }
2399         }
2400 }
2401
2402 /* ********************* UV ****************** */
2403
2404 static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, float *uv, int selected)
2405 {
2406         float aspx, aspy;
2407
2408         ED_space_image_uv_aspect(sima, &aspx, &aspy);
2409
2410         /* uv coords are scaled by aspects. this is needed for rotations and
2411            proportional editing to be consistent with the stretchted uv coords
2412            that are displayed. this also means that for display and numinput,
2413            and when the the uv coords are flushed, these are converted each time */
2414         td2d->loc[0] = uv[0]*aspx;
2415         td2d->loc[1] = uv[1]*aspy;
2416         td2d->loc[2] = 0.0f;
2417         td2d->loc2d = uv;
2418
2419         td->flag = 0;
2420         td->loc = td2d->loc;
2421         VECCOPY(td->center, td->loc);
2422         VECCOPY(td->iloc, td->loc);
2423
2424         memset(td->axismtx, 0, sizeof(td->axismtx));
2425         td->axismtx[2][2] = 1.0f;
2426
2427         td->ext= NULL; td->tdi= NULL; td->val= NULL;
2428
2429         if(selected) {
2430                 td->flag |= TD_SELECTED;
2431                 td->dist= 0.0;
2432         }
2433         else {
2434                 td->dist= MAXFLOAT;
2435         }
2436         Mat3One(td->mtx);
2437         Mat3One(td->smtx);
2438 }
2439
2440 static void createTransUVs(bContext *C, TransInfo *t)
2441 {
2442         SpaceImage *sima = CTX_wm_space_image(C);
2443         Image *ima = CTX_data_edit_image(C);
2444         Scene *scene = CTX_data_scene(C);
2445         TransData *td = NULL;
2446         TransData2D *td2d = NULL;
2447         MTFace *tf;
2448         int count=0, countsel=0;
2449         int propmode = t->flag & T_PROP_EDIT;
2450
2451         EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2452         EditFace *efa;
2453
2454         if(!ED_uvedit_test(t->obedit)) return;
2455
2456         /* count */
2457         for (efa= em->faces.first; efa; efa= efa->next) {
2458                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2459
2460                 if(uvedit_face_visible(scene, ima, efa, tf)) {
2461                         efa->tmp.p = tf;
2462
2463                         if (uvedit_uv_selected(scene, efa, tf, 0)) countsel++;
2464                         if (uvedit_uv_selected(scene, efa, tf, 1)) countsel++;
2465                         if (uvedit_uv_selected(scene, efa, tf, 2)) countsel++;
2466                         if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) countsel++;
2467                         if(propmode)
2468                                 count += (efa->v4)? 4: 3;
2469                 } else {
2470                         efa->tmp.p = NULL;
2471                 }
2472         }
2473
2474         /* note: in prop mode we need at least 1 selected */
2475         if (countsel==0) return;
2476
2477         t->total= (propmode)? count: countsel;
2478         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2479         /* for each 2d uv coord a 3d vector is allocated, so that they can be
2480            treated just as if they were 3d verts */
2481         t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2482
2483         if(sima->flag & SI_CLIP_UV)
2484                 t->flag |= T_CLIP_UV;
2485
2486         td= t->data;
2487         td2d= t->data2d;
2488
2489         for (efa= em->faces.first; efa; efa= efa->next) {
2490                 if ((tf=(MTFace *)efa->tmp.p)) {
2491                         if (propmode) {
2492                                 UVsToTransData(sima, td++, td2d++, tf->uv[0], uvedit_uv_selected(scene, efa, tf, 0));
2493                                 UVsToTransData(sima, td++, td2d++, tf->uv[1], uvedit_uv_selected(scene, efa, tf, 1));
2494                                 UVsToTransData(sima, td++, td2d++, tf->uv[2], uvedit_uv_selected(scene, efa, tf, 2));
2495                                 if(efa->v4)
2496                                         UVsToTransData(sima, td++, td2d++, tf->uv[3], uvedit_uv_selected(scene, efa, tf, 3));
2497                         } else {
2498                                 if(uvedit_uv_selected(scene, efa, tf, 0))                               UVsToTransData(sima, td++, td2d++, tf->uv[0], 1);
2499                                 if(uvedit_uv_selected(scene, efa, tf, 1))                               UVsToTransData(sima, td++, td2d++, tf->uv[1], 1);
2500                                 if(uvedit_uv_selected(scene, efa, tf, 2))                               UVsToTransData(sima, td++, td2d++, tf->uv[2], 1);
2501                                 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))    UVsToTransData(sima, td++, td2d++, tf->uv[3], 1);
2502                         }
2503                 }
2504         }
2505
2506         if (sima->flag & SI_LIVE_UNWRAP)
2507                 ED_uvedit_live_unwrap_begin(t->scene, t->obedit);
2508 }
2509
2510 void flushTransUVs(TransInfo *t)
2511 {
2512         SpaceImage *sima = t->sa->spacedata.first;
2513         TransData2D *td;
2514         int a, width, height;
2515         float aspx, aspy, invx, invy;
2516
2517         ED_space_image_uv_aspect(sima, &aspx, &aspy);
2518         ED_space_image_size(sima, &width, &height);
2519         invx= 1.0f/aspx;
2520         invy= 1.0f/aspy;
2521
2522         /* flush to 2d vector from internally used 3d vector */
2523         for(a=0, td= t->data2d; a<t->total; a++, td++) {
2524                 td->loc2d[0]= td->loc[0]*invx;
2525                 td->loc2d[1]= td->loc[1]*invy;
2526
2527                 if((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2528                         td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2529                         td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2530                 }
2531         }
2532 }
2533
2534 int clipUVTransform(TransInfo *t, float *vec, int resize)
2535 {
2536         TransData *td;
2537         int a, clipx=1, clipy=1;
2538         float aspx, aspy, min[2], max[2];
2539
2540         ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
2541         min[0]= min[1]= 0.0f;
2542         max[0]= aspx; max[1]= aspy;
2543
2544         for(a=0, td= t->data; a<t->total; a++, td++) {
2545                 DO_MINMAX2(td->loc, min, max);
2546         }
2547
2548         if(resize) {
2549                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2550                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
2551                 else if(max[0] > aspx && t->center[0] < aspx)
2552                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2553                 else
2554                         clipx= 0;
2555
2556                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2557                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
2558                 else if(max[1] > aspy && t->center[1] < aspy)
2559                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2560                 else
2561                         clipy= 0;
2562         }
2563         else {
2564                 if(min[0] < 0.0f)
2565                         vec[0] -= min[0];
2566                 else if(max[0] > aspx)
2567                         vec[0] -= max[0]-aspx;
2568                 else
2569                         clipx= 0;
2570
2571                 if(min[1] < 0.0f)
2572                         vec[1] -= min[1];
2573                 else if(max[1] > aspy)
2574                         vec[1] -= max[1]-aspy;
2575                 else
2576                         clipy= 0;
2577         }
2578
2579         return (clipx || clipy);
2580 }
2581
2582 /* ********************* ANIMATION EDITORS (GENERAL) ************************* */
2583
2584 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
2585 static short FrameOnMouseSide(char side, float frame, float cframe)
2586 {
2587         /* both sides, so it doesn't matter */
2588         if (side == 'B') return 1;
2589
2590         /* only on the named side */
2591         if (side == 'R')
2592                 return (frame >= cframe) ? 1 : 0;
2593         else
2594                 return (frame <= cframe) ? 1 : 0;
2595 }
2596
2597 /* ********************* NLA EDITOR ************************* */
2598
2599 static void createTransNlaData(bContext *C, TransInfo *t)
2600 {
2601         Scene *scene= CTX_data_scene(C);
2602         TransData *td = NULL;
2603         TransDataNla *tdn = NULL;
2604         
2605         bAnimContext ac;
2606         ListBase anim_data = {NULL, NULL};
2607         bAnimListElem *ale;
2608         int filter;
2609         
2610         int count=0;
2611         char side;
2612         
2613         /* determine what type of data we are operating on */
2614         if (ANIM_animdata_get_context(C, &ac) == 0)
2615                 return;
2616         
2617         /* filter data */
2618         filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
2619         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2620         
2621         /* which side of the current frame should be allowed */
2622         if (t->mode == TFM_TIME_EXTEND) {
2623                 /* only side on which mouse is gets transformed */
2624                 float xmouse, ymouse;
2625                 
2626                 UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
2627                 side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
2628         }
2629         else {
2630                 /* normal transform - both sides of current frame are considered */
2631                 side = 'B';
2632         }
2633         
2634         /* loop 1: count how many strips are selected (consider each strip as 2 points) */
2635         for (ale= anim_data.first; ale; ale= ale->next) {
2636                 NlaTrack *nlt= (NlaTrack *)ale->data;
2637                 NlaStrip *strip;
2638                 
2639                 /* make some meta-strips for chains of selected strips */
2640                 BKE_nlastrips_make_metas(&nlt->strips, 1);
2641                 
2642                 /* only consider selected strips */
2643                 for (strip= nlt->strips.first; strip; strip= strip->next) {
2644                         // TODO: we can make strips have handles later on...
2645                         /* transition strips can't get directly transformed */
2646                         if (strip->type != NLASTRIP_TYPE_TRANSITION) {
2647                                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
2648                                         if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++;
2649                                         if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++;
2650                                 }
2651                         }
2652                 }
2653         }
2654         
2655         /* stop if trying to build list if nothing selected */
2656         if (count == 0) {
2657                 /* cleanup temp list */
2658                 BLI_freelistN(&anim_data);
2659                 return;
2660         }
2661         
2662         /* allocate memory for data */
2663         t->total= count;
2664         
2665         t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(NLA Editor)");
2666         td= t->data;
2667         t->customData= MEM_callocN(t->total*sizeof(TransDataNla), "TransDataNla (NLA Editor)");
2668         tdn= t->customData;
2669         
2670         /* loop 2: build transdata array */
2671         for (ale= anim_data.first; ale; ale= ale->next) {
2672                 /* only if a real NLA-track */
2673                 if (ale->type == ANIMTYPE_NLATRACK) {
2674                         NlaTrack *nlt= (NlaTrack *)ale->data;
2675                         NlaStrip *strip;
2676                         
2677                         /* only consider selected strips */
2678                         for (strip= nlt->strips.first; strip; strip= strip->next) {
2679                                 // TODO: we can make strips have handles later on...
2680                                 /* transition strips can't get directly transformed */
2681                                 if (strip->type != NLASTRIP_TYPE_TRANSITION) {
2682                                         if (strip->flag & NLASTRIP_FLAG_SELECT) {
2683                                                 /* our transform data is constructed as follows:
2684                                                  *      - only the handles on the right side of the current-frame get included
2685                                                  *      - td structs are transform-elements operated on by the transform system
2686                                                  *        and represent a single handle. The storage/pointer used (val or loc) depends on
2687                                                  *        whether we're scaling or transforming. Ultimately though, the handles
2688                                                  *        the td writes to will simply be a dummy in tdn
2689                                                  *      - for each strip being transformed, a single tdn struct is used, so in some
2690                                                  *        cases, there will need to be 1 of these tdn elements in the array skipped...
2691                                                  */
2692                                                 float center[3], yval;
2693                                                 
2694                                                 /* firstly, init tdn settings */
2695                                                 tdn->id= ale->id;
2696                                                 tdn->oldTrack= tdn->nlt= nlt;
2697                                                 tdn->strip= strip;
2698                                                 tdn->trackIndex= BLI_findindex(&nlt->strips, strip);
2699                                                 
2700                                                 yval= (float)(tdn->trackIndex * NLACHANNEL_STEP);
2701                                                 
2702                                                 tdn->h1[0]= strip->start;
2703                                                 tdn->h1[1]= yval;
2704                                                 tdn->h2[0]= strip->end;
2705                                                 tdn->h2[1]= yval;
2706                                                 
2707                                                 center[0]= (float)CFRA;
2708                                                 center[1]= yval;
2709                                                 center[2]= 0.0f;
2710                                                 
2711                                                 /* set td's based on which handles are applicable */
2712                                                 if (FrameOnMouseSide(side, strip->start, (float)CFRA))
2713                                                 {
2714                                                         /* just set tdn to assume that it only has one handle for now */
2715                                                         tdn->handle= -1;
2716                                                         
2717                                                         /* now, link the transform data up to this data */
2718                                                         if (t->mode == TFM_TRANSLATION) {
2719                                                                 td->loc= tdn->h1;
2720                                                                 VECCOPY(td->iloc, tdn->h1);
2721                                                                 
2722                                                                 /* store all the other gunk that is required by transform */
2723                                                                 VECCOPY(td->center, center);
2724                                                                 memset(td->axismtx, 0, sizeof(td->axismtx));
2725                                                                 td->axismtx[2][2] = 1.0f;
2726                                                                 
2727                                                                 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2728                                                                 
2729                                                                 td->flag |= TD_SELECTED;
2730                                                                 td->dist= 0.0f;
2731                                                                 
2732                                                                 Mat3One(td->mtx);
2733                                                                 Mat3One(td->smtx);
2734                                                         }
2735                                                         else {
2736                                                                 td->val= &tdn->h1[0];
2737                                                                 td->ival= tdn->h1[0];
2738                                                         }
2739                                                         
2740                                                         td->extra= tdn;
2741                                                         td++;
2742                                                 }
2743                                                 if (FrameOnMouseSide(side, strip->end, (float)CFRA))
2744                                                 {
2745                                                         /* if tdn is already holding the start handle, then we're doing both, otherwise, only end */
2746                                                         tdn->handle= (tdn->handle) ? 2 : 1;
2747                                                         
2748                                                         /* now, link the transform data up to this data */
2749                                                         if (t->mode == TFM_TRANSLATION) {
2750                                                                 td->loc= tdn->h2;
2751                                                                 VECCOPY(td->iloc, tdn->h2);
2752                                                                 
2753                                                                 /* store all the other gunk that is required by transform */
2754                                                                 VECCOPY(td->center, center);
2755                                                                 memset(td->axismtx, 0, sizeof(td->axismtx));
2756                                                                 td->axismtx[2][2] = 1.0f;
2757                                                                 
2758                                                                 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2759                                                                 
2760                                                                 td->flag |= TD_SELECTED;
2761                                                                 td->dist= 0.0f;
2762                                                                 
2763                                                                 Mat3One(td->mtx);
2764                                                                 Mat3One(td->smtx);
2765                                                         }
2766                                                         else {
2767                                                                 td->val= &tdn->h2[0];
2768                          &n