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