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