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