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