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