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