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