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