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