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