== Constraints System ==
[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, pmat);
544                 
545         Mat3Inv(td->smtx, td->mtx);
546         
547         /* for axismat we use bone's own transform */
548         Mat3CpyMat4(pmat, pchan->pose_mat);
549         Mat3MulMat3(td->axismtx, omat, pmat);
550         Mat3Ortho(td->axismtx);
551         
552         if(t->mode==TFM_BONESIZE) {
553                 bArmature *arm= t->poseobj->data;
554                 
555                 if(arm->drawtype==ARM_ENVELOPE) {
556                         td->loc= NULL;
557                         td->val= &bone->dist;
558                         td->ival= bone->dist;
559                 }
560                 else {
561                         // abusive storage of scale in the loc pointer :)
562                         td->loc= &bone->xwidth;
563                         VECCOPY (td->iloc, td->loc);
564                         td->val= NULL;
565                 }
566         }
567         
568         /* in this case we can do target-less IK grabbing */
569         if(t->mode==TFM_TRANSLATION) {
570                 bKinematicConstraint *data= has_targetless_ik(pchan);
571                 if(data) {
572                         if(data->flag & CONSTRAINT_IK_TIP) {
573                                 VECCOPY(data->grabtarget, pchan->pose_tail);
574                         }
575                         else {
576                                 VECCOPY(data->grabtarget, pchan->pose_head);
577                         }
578                         td->loc = data->grabtarget;
579                         VECCOPY(td->iloc, td->loc);
580                         data->flag |= CONSTRAINT_IK_AUTO;
581                         
582                         /* only object matrix correction */
583                         Mat3CpyMat3 (td->mtx, omat);
584                         Mat3Inv (td->smtx, td->mtx);
585                 }
586         }
587 }
588
589 static void bone_children_clear_transflag(ListBase *lb)
590 {
591         Bone *bone= lb->first;
592         
593         for(;bone;bone= bone->next) {
594                 bone->flag &= ~BONE_TRANSFORM;
595                 bone_children_clear_transflag(&bone->childbase);
596         }
597 }
598
599 /* sets transform flags in the bones, returns total */
600 static void set_pose_transflags(TransInfo *t, Object *ob)
601 {
602         bArmature *arm= ob->data;
603         bPoseChannel *pchan;
604         Bone *bone;
605         
606         t->total= 0;
607         
608         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
609                 bone= pchan->bone;
610                 if(bone->layer & arm->layer) {
611                         if(bone->flag & BONE_SELECTED)
612                                 bone->flag |= BONE_TRANSFORM;
613                         else
614                                 bone->flag &= ~BONE_TRANSFORM;
615                 }
616         }
617         
618         /* make sure no bone can be transformed when a parent is transformed */
619         /* since pchans are depsgraph sorted, the parents are in beginning of list */
620         if(t->mode!=TFM_BONESIZE) {
621                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
622                         bone= pchan->bone;
623                         if(bone->flag & BONE_TRANSFORM)
624                                 bone_children_clear_transflag(&bone->childbase);
625                 }
626         }       
627         /* now count, and check if we have autoIK or have to switch from translate to rotate */
628         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
629                 bone= pchan->bone;
630                 if(bone->flag & BONE_TRANSFORM) {
631                         t->total++;
632                         
633                         if(t->mode==TFM_TRANSLATION) {
634                                 if( has_targetless_ik(pchan)==NULL ) {
635                                         if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
636                                                 t->mode= TFM_ROTATION;
637                                         else if((pchan->protectflag & OB_LOCK_LOC)==OB_LOCK_LOC)
638                                                 t->mode= TFM_ROTATION;
639                                 }
640                         }
641                 }
642         }
643 }
644
645 /* frees temporal IKs */
646 static void pose_grab_with_ik_clear(Object *ob)
647 {
648         bKinematicConstraint *data;
649         bPoseChannel *pchan;
650         bConstraint *con;
651         
652         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
653                 for(con= pchan->constraints.first; con; con= con->next) {
654                         if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
655                                 data= con->data;
656                                 if(data->flag & CONSTRAINT_IK_TEMP) {
657                                         BLI_remlink(&pchan->constraints, con);
658                                         MEM_freeN(con->data);
659                                         MEM_freeN(con);
660                                         pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
661                                         break;
662                                 }
663                         }
664                 }
665         }
666 }
667
668 /* adds the IK to pchan */
669 static void pose_grab_with_ik_add(bPoseChannel *pchan)
670 {
671         bKinematicConstraint *data;
672         bConstraint *con;
673         
674         if (pchan == NULL) { // Sanity check
675                 return;
676         }
677         
678         /* rule: not if there's already an IK on this channel */
679         for(con= pchan->constraints.first; con; con= con->next)
680                 if(con->type==CONSTRAINT_TYPE_KINEMATIC)
681                         break;
682         
683         if(con) {
684                 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
685                 data= has_targetless_ik(pchan);
686                 if(data)
687                         data->flag |= CONSTRAINT_IK_AUTO;
688                 return;
689         }
690         
691         con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
692         BLI_addtail(&pchan->constraints, con);
693         pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET);    /* for draw, but also for detecting while pose solving */
694         data= con->data;
695         data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
696         VECCOPY(data->grabtarget, pchan->pose_tail);
697         data->rootbone= 1;
698         
699         /* we include only a connected chain */
700         while(pchan && (pchan->bone->flag & BONE_CONNECTED)) {
701                 data->rootbone++;
702                 pchan= pchan->parent;
703         }
704 }
705
706 /* bone is a canditate to get IK, but we don't do it if it has children connected */
707 static void pose_grab_with_ik_children(bPose *pose, Bone *bone)
708 {
709         Bone *bonec;
710         int wentdeeper= 0;
711
712         /* go deeper if children & children are connected */
713         for(bonec= bone->childbase.first; bonec; bonec= bonec->next) {
714                 if(bonec->flag & BONE_CONNECTED) {
715                         wentdeeper= 1;
716                         pose_grab_with_ik_children(pose, bonec);
717                 }
718         }
719         if(wentdeeper==0) {
720                 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
721                 if(pchan)
722                         pose_grab_with_ik_add(pchan);
723         }
724 }
725
726 /* main call which adds temporal IK chains */
727 static void pose_grab_with_ik(Object *ob)
728 {
729         bArmature *arm;
730         bPoseChannel *pchan, *pchansel= NULL;
731         
732         if(ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0)
733                 return;
734                 
735         arm = ob->data;
736         
737         /* rule: only one Bone */
738         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
739                 if(pchan->bone->layer & arm->layer) {
740                         if(pchan->bone->flag & BONE_SELECTED) {
741                                 if(pchansel)
742                                         break;
743                                 pchansel= pchan;
744                         }
745                 }
746         }
747         if(pchan || pchansel==NULL) return;
748         
749         /* rule: if selected Bone is not a root bone, it gets a temporal IK */
750         if(pchansel->parent) {
751                 /* only adds if there's no IK yet */
752                 pose_grab_with_ik_add(pchansel);
753         }
754         else {
755                 /* rule: go over the children and add IK to the tips */
756                 pose_grab_with_ik_children(ob->pose, pchansel->bone);
757         }
758 }       
759
760
761
762 /* only called with pose mode active object now */
763 static void createTransPose(TransInfo *t, Object *ob)
764 {
765         bArmature *arm;
766         bPoseChannel *pchan;
767         TransData *td;
768         TransDataExtension *tdx;
769         int i;
770         
771         t->total= 0;
772         
773         /* check validity of state */
774         arm=get_armature (ob);
775         if (arm==NULL || ob->pose==NULL) return;
776         
777         if (arm->flag & ARM_RESTPOS) {
778                 if(t->mode!=TFM_BONESIZE) {
779                         notice ("Pose edit not possible while Rest Position is enabled");
780                         return;
781                 }
782         }
783         if (!(ob->lay & G.vd->lay)) return;
784
785         /* do we need to add temporal IK chains? */
786         if((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION)
787                 pose_grab_with_ik(ob);
788         
789         /* set flags and count total (warning, can change transform to rotate) */
790         set_pose_transflags(t, ob);
791         
792         if(t->total==0) return;
793
794         t->flag |= T_POSE;
795         t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
796         
797         /* make sure the lock is set OK, unlock can be accidentally saved? */
798         ob->pose->flag |= POSE_LOCKED;
799         ob->pose->flag &= ~POSE_DO_UNLOCK;
800
801         /* init trans data */
802     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
803     tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
804         for(i=0; i<t->total; i++, td++, tdx++) {
805                 td->ext= tdx;
806                 td->tdi = NULL;
807                 td->val = NULL;
808         }       
809         
810         /* use pose channels to fill trans data */
811         td= t->data;
812         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
813                 if(pchan->bone->flag & BONE_TRANSFORM) {
814                         add_pose_transdata(t, pchan, ob, td);
815                         td++;
816                 }
817         }
818         
819         if(td != (t->data+t->total)) printf("Bone selection count error\n");
820         
821 }
822
823 /* ********************* armature ************** */
824
825 static void createTransArmatureVerts(TransInfo *t)
826 {
827         EditBone *ebo;
828         bArmature *arm= G.obedit->data;
829         TransData *td;
830         float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
831
832         t->total = 0;
833         for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
834                 if(ebo->layer & arm->layer) {
835                         if (t->mode==TFM_BONESIZE) {
836                                 if (ebo->flag & BONE_SELECTED)
837                                         t->total++;
838                         }
839                         else if (t->mode==TFM_BONE_ROLL) {
840                                 if (ebo->flag & BONE_SELECTED)
841                                         t->total++;
842                         }
843                         else {
844                                 if (ebo->flag & BONE_TIPSEL)
845                                         t->total++;
846                                 if (ebo->flag & BONE_ROOTSEL)
847                                         t->total++;
848                         }
849                 }
850         }
851
852     if (!t->total) return;
853         
854         Mat3CpyMat4(mtx, G.obedit->obmat);
855         Mat3Inv(smtx, mtx);
856
857     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
858         
859         for (ebo=G.edbo.first;ebo;ebo=ebo->next){
860                 ebo->oldlength= ebo->length;    // length==0.0 on extrude, used for scaling radius of bone points
861                 
862                 if(ebo->layer & arm->layer) {
863                         if (t->mode==TFM_BONE_ENVELOPE) {
864                                 
865                                 if (ebo->flag & BONE_ROOTSEL){
866                                         td->val= &ebo->rad_head;
867                                         td->ival= *td->val;
868                                         
869                                         VECCOPY (td->center, ebo->head);
870                                         td->flag= TD_SELECTED;
871                                         
872                                         Mat3CpyMat3(td->smtx, smtx);
873                                         Mat3CpyMat3(td->mtx, mtx);
874                                         
875                                         td->loc = NULL;
876                                         td->ext = NULL;
877                                         td->tdi = NULL;
878                                         
879                                         td++;
880                                 }
881                                 if (ebo->flag & BONE_TIPSEL){
882                                         td->val= &ebo->rad_tail;
883                                         td->ival= *td->val;
884                                         VECCOPY (td->center, ebo->tail);
885                                         td->flag= TD_SELECTED;
886                                         
887                                         Mat3CpyMat3(td->smtx, smtx);
888                                         Mat3CpyMat3(td->mtx, mtx);
889                                         
890                                         td->loc = NULL;
891                                         td->ext = NULL;
892                                         td->tdi = NULL;
893                                         
894                                         td++;
895                                 }
896                                 
897                         }
898                         else if (t->mode==TFM_BONESIZE) {
899                                 if (ebo->flag & BONE_SELECTED) {
900                                         if(arm->drawtype==ARM_ENVELOPE) {
901                                                 td->loc= NULL;
902                                                 td->val= &ebo->dist;
903                                                 td->ival= ebo->dist;
904                                         }
905                                         else {
906                                                 // abusive storage of scale in the loc pointer :)
907                                                 td->loc= &ebo->xwidth;
908                                                 VECCOPY (td->iloc, td->loc);
909                                                 td->val= NULL;
910                                         }
911                                         VECCOPY (td->center, ebo->head);
912                                         td->flag= TD_SELECTED;
913                                         
914                                         /* use local bone matrix */
915                                         VecSubf(delta, ebo->tail, ebo->head);   
916                                         vec_roll_to_mat3(delta, ebo->roll, bonemat);
917                                         Mat3MulMat3(td->mtx, mtx, bonemat);
918                                         Mat3Inv(td->smtx, td->mtx);
919                                         
920                                         Mat3CpyMat3(td->axismtx, td->mtx);
921                                         Mat3Ortho(td->axismtx);
922
923                                         td->ext = NULL;
924                                         td->tdi = NULL;
925                                         
926                                         td++;
927                                 }
928                         }
929                         else if (t->mode==TFM_BONE_ROLL) {
930                                 if (ebo->flag & BONE_SELECTED) {
931                                         td->loc= NULL;
932                                         td->val= &(ebo->roll);
933                                         td->ival= ebo->roll;
934                                         
935                                         VECCOPY (td->center, ebo->head);
936                                         td->flag= TD_SELECTED;
937
938                                         td->ext = NULL;
939                                         td->tdi = NULL;
940                                         
941                                         td++;
942                                 }
943                         }
944                         else {
945                                 if (ebo->flag & BONE_TIPSEL){
946                                         VECCOPY (td->iloc, ebo->tail);
947                                         VECCOPY (td->center, td->iloc);
948                                         td->loc= ebo->tail;
949                                         td->flag= TD_SELECTED;
950
951                                         Mat3CpyMat3(td->smtx, smtx);
952                                         Mat3CpyMat3(td->mtx, mtx);
953
954                                         td->ext = NULL;
955                                         td->tdi = NULL;
956                                         td->val = NULL;
957
958                                         td++;
959                                 }
960                                 if (ebo->flag & BONE_ROOTSEL){
961                                         VECCOPY (td->iloc, ebo->head);
962                                         VECCOPY (td->center, td->iloc);
963                                         td->loc= ebo->head;
964                                         td->flag= TD_SELECTED;
965
966                                         Mat3CpyMat3(td->smtx, smtx);
967                                         Mat3CpyMat3(td->mtx, mtx);
968
969                                         td->ext = NULL;
970                                         td->tdi = NULL;
971                                         td->val = NULL;
972
973                                         td++;
974                                 }
975                         }
976                 }
977         }
978 }
979
980 /* ********************* meta elements ********* */
981
982 static void createTransMBallVerts(TransInfo *t)
983 {
984         MetaElem *ml;
985         TransData *td;
986         TransDataExtension *tx;
987         float mtx[3][3], smtx[3][3];
988         int count=0, countsel=0;
989         int propmode = t->flag & T_PROP_EDIT;
990
991         /* count totals */
992         for(ml= editelems.first; ml; ml= ml->next) {
993                 if(ml->flag & SELECT) countsel++;
994                 if(propmode) count++;
995         }
996
997         /* note: in prop mode we need at least 1 selected */
998         if (countsel==0) return;
999         
1000         if(propmode) t->total = count; 
1001         else t->total = countsel;
1002         
1003         td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1004         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1005
1006         Mat3CpyMat4(mtx, G.obedit->obmat);
1007         Mat3Inv(smtx, mtx);
1008     
1009         for(ml= editelems.first; ml; ml= ml->next) {
1010                 if(propmode || (ml->flag & SELECT)) {
1011                         td->loc= &ml->x;
1012                         VECCOPY(td->iloc, td->loc);
1013                         VECCOPY(td->center, td->loc);
1014
1015                         if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1016                         else td->flag= TD_USEQUAT;
1017
1018                         Mat3CpyMat3(td->smtx, smtx);
1019                         Mat3CpyMat3(td->mtx, mtx);
1020
1021                         td->ext = tx;
1022                         td->tdi = NULL;
1023
1024                         /* Radius of MetaElem (mass of MetaElem influence) */
1025                         if(ml->flag & MB_SCALE_RAD){
1026                                 td->val = &ml->rad;
1027                                 td->ival = ml->rad;
1028                         }
1029                         else{
1030                                 td->val = &ml->s;
1031                                 td->ival = ml->s;
1032                         }
1033
1034                         /* expx/expy/expz determine "shape" of some MetaElem types */
1035                         tx->size = &ml->expx;
1036                         tx->isize[0] = ml->expx;
1037                         tx->isize[1] = ml->expy;
1038                         tx->isize[2] = ml->expz;
1039
1040                         /* quat is used for rotation of MetaElem */
1041                         tx->quat = ml->quat;
1042                         QUATCOPY(tx->iquat, ml->quat);
1043
1044                         tx->rot = NULL;
1045
1046                         td++;
1047                         tx++;
1048                 }
1049         }
1050
1051
1052 /* ********************* curve/surface ********* */
1053
1054 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1055         TransData *td, *td_near = NULL;
1056         for (td = head; td<=tail; td++) {
1057                 if (td->flag & TD_SELECTED) {
1058                         td_near = td;
1059                         td->dist = 0.0f;
1060                 }
1061                 else if(td_near) {
1062                         float dist;
1063                         dist = VecLenf(td_near->center, td->center);
1064                         if (dist < (td-1)->dist) {
1065                                 td->dist = (td-1)->dist;
1066                         }
1067                         else {
1068                                 td->dist = dist;
1069                         }
1070                 }
1071                 else {
1072                         td->dist = MAXFLOAT;
1073                         td->flag |= TD_NOTCONNECTED;
1074                 }
1075         }
1076         td_near = NULL;
1077         for (td = tail; td>=head; td--) {
1078                 if (td->flag & TD_SELECTED) {
1079                         td_near = td;
1080                         td->dist = 0.0f;
1081                 }
1082                 else if(td_near) {
1083                         float dist;
1084                         dist = VecLenf(td_near->center, td->center);
1085                         if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1086                                 td->flag &= ~TD_NOTCONNECTED;
1087                                 if (dist < (td+1)->dist) {
1088                                         td->dist = (td+1)->dist;
1089                                 }
1090                                 else {
1091                                         td->dist = dist;
1092                                 }
1093                         }
1094                 }
1095         }
1096 }
1097
1098 static void createTransCurveVerts(TransInfo *t)
1099 {
1100         TransData *td = NULL;
1101         Nurb *nu;
1102         BezTriple *bezt;
1103         BPoint *bp;
1104         float mtx[3][3], smtx[3][3];
1105         int a;
1106         int count=0, countsel=0;
1107         int propmode = t->flag & T_PROP_EDIT;
1108
1109         /* count total of vertices, check identical as in 2nd loop for making transdata! */
1110         for(nu= editNurb.first; nu; nu= nu->next) {
1111                 if((nu->type & 7)==CU_BEZIER) {
1112                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1113                                 if(bezt->hide==0) {
1114                                         if(bezt->f1 & 1) countsel++;
1115                                         if(bezt->f2 & 1) countsel++;
1116                                         if(bezt->f3 & 1) countsel++;
1117                                         if(propmode) count+= 3;
1118                                 }
1119                         }
1120                 }
1121                 else {
1122                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1123                                 if(bp->hide==0) {
1124                                         if(propmode) count++;
1125                                         if(bp->f1 & 1) countsel++;
1126                                 }
1127                         }
1128                 }
1129         }
1130         /* note: in prop mode we need at least 1 selected */
1131         if (countsel==0) return;
1132         
1133         if(propmode) t->total = count; 
1134         else t->total = countsel;
1135         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1136
1137         Mat3CpyMat4(mtx, G.obedit->obmat);
1138         Mat3Inv(smtx, mtx);
1139
1140     td = t->data;
1141         for(nu= editNurb.first; nu; nu= nu->next) {
1142                 if((nu->type & 7)==CU_BEZIER) {
1143                         TransData *head, *tail;
1144                         head = tail = td;
1145                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1146                                 if(bezt->hide==0) {
1147                                         if(propmode || (bezt->f1 & 1)) {
1148                                                 VECCOPY(td->iloc, bezt->vec[0]);
1149                                                 td->loc= bezt->vec[0];
1150                                                 VECCOPY(td->center, bezt->vec[1]);
1151                                                 if(bezt->f1 & 1) td->flag= TD_SELECTED;
1152                                                 else td->flag= 0;
1153                                                 td->ext = NULL;
1154                                                 td->tdi = NULL;
1155                                                 td->val = NULL;
1156
1157                                                 Mat3CpyMat3(td->smtx, smtx);
1158                                                 Mat3CpyMat3(td->mtx, mtx);
1159
1160                                                 td++;
1161                                                 count++;
1162                                                 tail++;
1163                                         }
1164                                         /* THIS IS THE CV, the other two are handles */
1165                                         if(propmode || (bezt->f2 & 1)) {
1166                                                 VECCOPY(td->iloc, bezt->vec[1]);
1167                                                 td->loc= bezt->vec[1];
1168                                                 VECCOPY(td->center, td->loc);
1169                                                 if(bezt->f2 & 1) td->flag= TD_SELECTED;
1170                                                 else td->flag= 0;
1171                                                 td->ext = NULL;
1172                                                 td->tdi = NULL;
1173                                                 
1174                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN) {
1175                                                         td->val = &(bezt->radius);
1176                                                         td->ival = bezt->radius;
1177                                                 } else {
1178                                                         td->val = &(bezt->alfa);
1179                                                         td->ival = bezt->alfa;
1180                                                 }
1181
1182                                                 Mat3CpyMat3(td->smtx, smtx);
1183                                                 Mat3CpyMat3(td->mtx, mtx);
1184
1185                                                 td++;
1186                                                 count++;
1187                                                 tail++;
1188                                         }
1189                                         if(propmode || (bezt->f3 & 1)) {
1190                                                 VECCOPY(td->iloc, bezt->vec[2]);
1191                                                 td->loc= bezt->vec[2];
1192                                                 VECCOPY(td->center, bezt->vec[1]);
1193                                                 if(bezt->f3 & 1) td->flag= TD_SELECTED;
1194                                                 else td->flag= 0;
1195                                                 td->ext = NULL;
1196                                                 td->tdi = NULL;
1197                                                 td->val = NULL;
1198
1199                                                 Mat3CpyMat3(td->smtx, smtx);
1200                                                 Mat3CpyMat3(td->mtx, mtx);
1201
1202                                                 td++;
1203                                                 count++;
1204                                                 tail++;
1205                                         }
1206                                 }
1207                                 else if (propmode && head != tail) {
1208                                         calc_distanceCurveVerts(head, tail-1);
1209                                         head = tail;
1210                                 }
1211                         }
1212                         if (propmode && head != tail)
1213                                 calc_distanceCurveVerts(head, tail-1);
1214                 }
1215                 else {
1216                         TransData *head, *tail;
1217                         head = tail = td;
1218                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1219                                 if(bp->hide==0) {
1220                                         if(propmode || (bp->f1 & 1)) {
1221                                                 VECCOPY(td->iloc, bp->vec);
1222                                                 td->loc= bp->vec;
1223                                                 VECCOPY(td->center, td->loc);
1224                                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
1225                                                 else td->flag= 0;
1226                                                 td->ext = NULL;
1227                                                 td->tdi = NULL;
1228                                                 
1229                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN) {
1230                                                         td->val = &(bp->radius);
1231                                                         td->ival = bp->radius;
1232                                                 } else {
1233                                                         td->val = &(bp->alfa);
1234                                                         td->ival = bp->alfa;
1235                                                 }
1236
1237                                                 Mat3CpyMat3(td->smtx, smtx);
1238                                                 Mat3CpyMat3(td->mtx, mtx);
1239
1240                                                 td++;
1241                                                 count++;
1242                                                 tail++;
1243                                         }
1244                                 }
1245                                 else if (propmode && head != tail) {
1246                                         calc_distanceCurveVerts(head, tail-1);
1247                                         head = tail;
1248                                 }
1249                         }
1250                         if (propmode && head != tail)
1251                                 calc_distanceCurveVerts(head, tail-1);
1252                 }
1253         }
1254 }
1255
1256 /* ********************* lattice *************** */
1257
1258 static void createTransLatticeVerts(TransInfo *t)
1259 {
1260         TransData *td = NULL;
1261         BPoint *bp;
1262         float mtx[3][3], smtx[3][3];
1263         int a;
1264         int count=0, countsel=0;
1265         int propmode = t->flag & T_PROP_EDIT;
1266
1267         bp= editLatt->def;
1268         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1269         while(a--) {
1270                 if(bp->hide==0) {
1271                         if(bp->f1 & 1) countsel++;
1272                         if(propmode) count++;
1273                 }
1274                 bp++;
1275         }
1276         
1277         /* note: in prop mode we need at least 1 selected */
1278         if (countsel==0) return;
1279         
1280         if(propmode) t->total = count; 
1281         else t->total = countsel;
1282         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1283         
1284         Mat3CpyMat4(mtx, G.obedit->obmat);
1285         Mat3Inv(smtx, mtx);
1286
1287         td = t->data;
1288         bp= editLatt->def;
1289         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1290         while(a--) {
1291                 if(propmode || (bp->f1 & 1)) {
1292                         if(bp->hide==0) {
1293                                 VECCOPY(td->iloc, bp->vec);
1294                                 td->loc= bp->vec;
1295                                 VECCOPY(td->center, td->loc);
1296                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
1297                                 else td->flag= 0;
1298                                 Mat3CpyMat3(td->smtx, smtx);
1299                                 Mat3CpyMat3(td->mtx, mtx);
1300
1301                                 td->ext = NULL;
1302                                 td->tdi = NULL;
1303                                 td->val = NULL;
1304
1305                                 td++;
1306                                 count++;
1307                         }
1308                 }
1309                 bp++;
1310         }
1311
1312
1313 /* ********************* mesh ****************** */
1314
1315 /* proportional distance based on connectivity  */
1316 #define E_VEC(a)        (vectors + (3 * (a)->tmp.l))
1317 #define E_NEAR(a)       (nears[((a)->tmp.l)])
1318 #define THRESHOLD       0.0001f
1319 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1320 {
1321         EditMesh *em = G.editMesh;
1322         EditVert *eve;
1323         EditEdge *eed;
1324         int i= 0, done= 1;
1325
1326         /* f2 flag is used for 'selection' */
1327         /* tmp.l is offset on scratch array   */
1328         for(eve= em->verts.first; eve; eve= eve->next) {
1329                 if(eve->h==0) {
1330                         eve->tmp.l = i++;
1331
1332                         if(eve->f & SELECT) {
1333                                 eve->f2= 2;
1334                                 E_NEAR(eve) = eve;
1335                                 E_VEC(eve)[0] = 0.0f;
1336                                 E_VEC(eve)[1] = 0.0f;
1337                                 E_VEC(eve)[2] = 0.0f;
1338                         }
1339                         else {
1340                                 eve->f2 = 0;
1341                         }
1342                 }
1343         }
1344
1345
1346         /* Floodfill routine */
1347         /*
1348         At worst this is n*n of complexity where n is number of edges 
1349         Best case would be n if the list is ordered perfectly.
1350         Estimate is n log n in average (so not too bad)
1351         */
1352         while(done) {
1353                 done= 0;
1354                 
1355                 for(eed= em->edges.first; eed; eed= eed->next) {
1356                         if(eed->h==0) {
1357                                 EditVert *v1= eed->v1, *v2= eed->v2;
1358                                 float *vec2 = E_VEC(v2);
1359                                 float *vec1 = E_VEC(v1);
1360
1361                                 if (v1->f2 + v2->f2 == 4)
1362                                         continue;
1363
1364                                 if (v1->f2) {
1365                                         if (v2->f2) {
1366                                                 float nvec[3];
1367                                                 float len1 = VecLength(vec1);
1368                                                 float len2 = VecLength(vec2);
1369                                                 float lenn;
1370                                                 /* for v2 if not selected */
1371                                                 if (v2->f2 != 2) {
1372                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1373                                                         lenn = VecLength(nvec);
1374                                                         /* 1 < n < 2 */
1375                                                         if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1376                                                                 VECCOPY(vec2, nvec);
1377                                                                 E_NEAR(v2) = E_NEAR(v1);
1378                                                                 done = 1;
1379                                                         }
1380                                                         /* n < 1 < 2 */
1381                                                         else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1382                                                                 VECCOPY(vec2, vec1);
1383                                                                 E_NEAR(v2) = E_NEAR(v1);
1384                                                                 done = 1;
1385                                                         }
1386                                                 }
1387                                                 /* for v1 if not selected */
1388                                                 if (v1->f2 != 2) {
1389                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1390                                                         lenn = VecLength(nvec);
1391                                                         /* 2 < n < 1 */
1392                                                         if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1393                                                                 VECCOPY(vec1, nvec);
1394                                                                 E_NEAR(v1) = E_NEAR(v2);
1395                                                                 done = 1;
1396                                                         }
1397                                                         /* n < 2 < 1 */
1398                                                         else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1399                                                                 VECCOPY(vec1, vec2);
1400                                                                 E_NEAR(v1) = E_NEAR(v2);
1401                                                                 done = 1;
1402                                                         }
1403                                                 }
1404                                         }
1405                                         else {
1406                                                 v2->f2 = 1;
1407                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1408                                                 /* 2 < 1 */
1409                                                 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1410                                                         VECCOPY(vec2, vec1);
1411                                                 }
1412                                                 E_NEAR(v2) = E_NEAR(v1);
1413                                                 done = 1;
1414                                         }
1415                                 }
1416                                 else if (v2->f2) {
1417                                         v1->f2 = 1;
1418                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1419                                         /* 2 < 1 */
1420                                         if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1421                                                 VECCOPY(vec1, vec2);
1422                                         }
1423                                         E_NEAR(v1) = E_NEAR(v2);
1424                                         done = 1;
1425                                 }
1426                         }
1427                 }
1428         }
1429 }
1430
1431 /* loop-in-a-loop I know, but we need it! (ton) */
1432 static void get_face_center(float *cent, EditVert *eve)
1433 {
1434         EditMesh *em = G.editMesh;
1435         EditFace *efa;
1436         
1437         for(efa= em->faces.first; efa; efa= efa->next)
1438                 if(efa->f & SELECT)
1439                         if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1440                                 break;
1441         if(efa) {
1442                 VECCOPY(cent, efa->cent);
1443         }
1444 }
1445
1446 static void VertsToTransData(TransData *td, EditVert *eve)
1447 {
1448         td->flag = 0;
1449         td->loc = eve->co;
1450         
1451         VECCOPY(td->center, td->loc);
1452         if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1453                 get_face_center(td->center, eve);
1454         VECCOPY(td->iloc, td->loc);
1455
1456         // Setting normals
1457         VECCOPY(td->axismtx[2], eve->no);
1458         td->axismtx[0][0]               =
1459                 td->axismtx[0][1]       =
1460                 td->axismtx[0][2]       =
1461                 td->axismtx[1][0]       =
1462                 td->axismtx[1][1]       =
1463                 td->axismtx[1][2]       = 0.0f;
1464
1465         td->ext = NULL;
1466         td->tdi = NULL;
1467         td->val = NULL;
1468         td->tdmir= NULL;
1469
1470 #ifdef WITH_VERSE
1471         if(eve->vvert) {
1472                 td->verse = (void*)eve->vvert;
1473                 td->flag |= TD_VERSE_VERT;
1474         }
1475         else
1476                 td->flag &= ~TD_VERSE_VERT;
1477 #endif
1478 }
1479
1480 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1481
1482 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1483 {
1484         float *vec = userData;
1485         
1486         vec+= 3*index;
1487         VECCOPY(vec, co);
1488 }
1489
1490 /* hurmf, copy from buttons_editing.c, i have to sort this out what it means... */
1491 static void modifiers_setOnCage(void *ob_v, void *md_v)
1492 {
1493         Object *ob = ob_v;
1494         ModifierData *md;
1495         
1496         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1497         
1498         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1499                 if( md == md_v ) {
1500                         if( i >= cageIndex )
1501                                 md->mode ^= eModifierMode_OnCage;
1502                         break;
1503                 }
1504 }
1505
1506
1507 /* disable subsurf temporal, get mapped cos, and enable it */
1508 static float *get_crazy_mapped_editverts(void)
1509 {
1510         DerivedMesh *dm;
1511         ModifierData *md;
1512         float *vertexcos;
1513         int i;
1514         
1515         for( i = 0, md=G.obedit->modifiers.first; md; ++i, md=md->next ) {
1516                 if(md->type==eModifierType_Subsurf)
1517                         if(md->mode & eModifierMode_OnCage)
1518                                 break;
1519         }
1520         if(md) {
1521                 /* this call disables subsurf and enables the underlying modifier to deform, apparently */
1522                 modifiers_setOnCage(G.obedit, md);
1523                 /* make it all over */
1524                 makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
1525         }
1526         
1527         /* now get the cage */
1528         dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
1529
1530         vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1531         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1532         
1533         dm->release(dm);
1534         
1535         if(md) {
1536                 /* set back the flag, no new cage needs to be built, transform does it */
1537                 modifiers_setOnCage(G.obedit, md);
1538         }
1539         
1540         return vertexcos;
1541 }
1542
1543 #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])
1544 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1545 {
1546         float vecu[3], vecv[3];
1547         float q1[4], q2[4];
1548         
1549         TAN_MAKE_VEC(vecu, v1, v2);
1550         TAN_MAKE_VEC(vecv, v1, v3);
1551         triatoquat(v1, vecu, vecv, q1);
1552         
1553         TAN_MAKE_VEC(vecu, def1, def2);
1554         TAN_MAKE_VEC(vecv, def1, def3);
1555         triatoquat(def1, vecu, vecv, q2);
1556         
1557         QuatSub(quat, q2, q1);
1558 }
1559 #undef TAN_MAKE_VEC
1560
1561 static void set_crazyspace_quats(float *mappedcos, float *quats)
1562 {
1563         EditMesh *em = G.editMesh;
1564         EditVert *eve, *prev;
1565         EditFace *efa;
1566         float *v1, *v2, *v3, *v4;
1567         long index= 0;
1568         
1569         /* two abused locations in vertices */
1570         for(eve= em->verts.first; eve; eve= eve->next, index++) {
1571                 eve->tmp.fp = NULL;
1572                 eve->prev= (EditVert *)index;
1573         }
1574         
1575         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
1576         for(efa= em->faces.first; efa; efa= efa->next) {
1577                 
1578                 /* retrieve mapped coordinates */
1579                 v1= mappedcos + 3*( (long)(efa->v1->prev) );
1580                 v2= mappedcos + 3*( (long)(efa->v2->prev) );
1581                 v3= mappedcos + 3*( (long)(efa->v3->prev) );
1582                 
1583                 if(efa->v2->tmp.fp==NULL && efa->v2->f1) {
1584                         set_crazy_vertex_quat(quats, efa->v2->co, efa->v3->co, efa->v1->co, v2, v3, v1);
1585                         efa->v2->tmp.fp= quats;
1586                         quats+= 4;
1587                 }
1588                 
1589                 if(efa->v4) {
1590                         v4= mappedcos + 3*( (long)(efa->v4->prev) );
1591                         
1592                         if(efa->v1->tmp.fp==NULL && efa->v1->f1) {
1593                                 set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v4->co, v1, v2, v4);
1594                                 efa->v1->tmp.fp= quats;
1595                                 quats+= 4;
1596                         }
1597                         if(efa->v3->tmp.fp==NULL && efa->v3->f1) {
1598                                 set_crazy_vertex_quat(quats, efa->v3->co, efa->v4->co, efa->v2->co, v3, v4, v2);
1599                                 efa->v3->tmp.fp= quats;
1600                                 quats+= 4;
1601                         }
1602                         if(efa->v4->tmp.fp==NULL && efa->v4->f1) {
1603                                 set_crazy_vertex_quat(quats, efa->v4->co, efa->v1->co, efa->v3->co, v4, v1, v3);
1604                                 efa->v4->tmp.fp= quats;
1605                                 quats+= 4;
1606                         }
1607                 }
1608                 else {
1609                         if(efa->v1->tmp.fp==NULL && efa->v1->f1) {
1610                                 set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v3->co, v1, v2, v3);
1611                                 efa->v1->tmp.fp= quats;
1612                                 quats+= 4;
1613                         }
1614                         if(efa->v3->tmp.fp==NULL && efa->v3->f1) {
1615                                 set_crazy_vertex_quat(quats, efa->v3->co, efa->v1->co, efa->v2->co, v3, v1, v2);
1616                                 efa->v3->tmp.fp= quats;
1617                                 quats+= 4;
1618                         }
1619                 }
1620         }
1621
1622         /* restore abused prev pointer */
1623         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1624                 eve->prev= prev;
1625
1626 }
1627
1628 static void createTransEditVerts(TransInfo *t)
1629 {
1630         TransData *tob = NULL;
1631         EditMesh *em = G.editMesh;
1632         EditVert *eve;
1633         EditVert **nears = NULL;
1634         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1635         float mtx[3][3], smtx[3][3];
1636         int count=0, countsel=0;
1637         int propmode = t->flag & T_PROP_EDIT;
1638         int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR);
1639
1640         // transform now requires awareness for select mode, so we tag the f1 flags in verts
1641         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1642                 for(eve= em->verts.first; eve; eve= eve->next) {
1643                         if(eve->h==0 && (eve->f & SELECT)) 
1644                                 eve->f1= SELECT;
1645                         else
1646                                 eve->f1= 0;
1647                 }
1648         }
1649         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1650                 EditEdge *eed;
1651                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1652                 for(eed= em->edges.first; eed; eed= eed->next) {
1653                         if(eed->h==0 && (eed->f & SELECT))
1654                                 eed->v1->f1= eed->v2->f1= SELECT;
1655                 }
1656         }
1657         else {
1658                 EditFace *efa;
1659                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1660                 for(efa= em->faces.first; efa; efa= efa->next) {
1661                         if(efa->h==0 && (efa->f & SELECT)) {
1662                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1663                                 if(efa->v4) efa->v4->f1= SELECT;
1664                         }
1665                 }
1666         }
1667         
1668         /* now we can count */
1669         for(eve= em->verts.first; eve; eve= eve->next) {
1670                 if(eve->h==0) {
1671                         if(eve->f1) countsel++;
1672                         if(propmode) count++;
1673                 }
1674         }
1675         
1676         /* note: in prop mode we need at least 1 selected */
1677         if (countsel==0) return;
1678         
1679         if(propmode) {
1680                 t->total = count; 
1681         
1682                 /* allocating scratch arrays */
1683                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1684                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1685         }
1686         else t->total = countsel;
1687         tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1688         
1689         Mat3CpyMat4(mtx, G.obedit->obmat);
1690         Mat3Inv(smtx, mtx);
1691
1692         if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1693         
1694         /* detect CrazySpace [tm] */
1695         if(propmode==0) {
1696                 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
1697                         if(modifiers_isDeformed(G.obedit)) {
1698                                 /* disable subsurf temporal, get mapped cos, and enable it */
1699                                 mappedcos= get_crazy_mapped_editverts();
1700                                 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
1701                                 set_crazyspace_quats(mappedcos, quats);
1702                         }
1703                 }
1704         }
1705         
1706         /* find out which half we do */
1707         if(mirror) {
1708                 for (eve=em->verts.first; eve; eve=eve->next) {
1709                         if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
1710                                 if(eve->co[0]<0.0f)
1711                                         mirror = -1;
1712                                 break;
1713                         }
1714                 }
1715         }
1716         
1717         for (eve=em->verts.first; eve; eve=eve->next) {
1718                 if(eve->h==0) {
1719                         if(propmode || eve->f1) {
1720                                 VertsToTransData(tob, eve);
1721
1722                                 if(eve->f1) tob->flag |= TD_SELECTED;
1723                                 if(propmode) {
1724                                         if (eve->f2) {
1725                                                 float vec[3];
1726                                                 VECCOPY(vec, E_VEC(eve));
1727                                                 Mat3MulVecfl(mtx, vec);
1728                                                 tob->dist= VecLength(vec);
1729                                         }
1730                                         else {
1731                                                 tob->flag |= TD_NOTCONNECTED;
1732                                                 tob->dist = MAXFLOAT;
1733                                         }
1734                                 }
1735                                 
1736                                 /* CrazySpace */
1737                                 if(quats && eve->tmp.fp) {
1738                                         float mat[3][3], imat[3][3], qmat[3][3];
1739                                         
1740                                         QuatToMat3(eve->tmp.fp, qmat);
1741                                         Mat3MulMat3(mat, mtx, qmat);
1742                                         Mat3Inv(imat, mat);
1743                                         
1744                                         Mat3CpyMat3(tob->smtx, imat);
1745                                         Mat3CpyMat3(tob->mtx, mat);
1746                                 }
1747                                 else {
1748                                         Mat3CpyMat3(tob->smtx, smtx);
1749                                         Mat3CpyMat3(tob->mtx, mtx);
1750                                 }
1751                                 
1752                                 /* Mirror? */
1753                                 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
1754                                         EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc);        /* initializes octree on first call */
1755                                         if(vmir!=eve) tob->tdmir= vmir;
1756                                 }
1757                                 tob++;
1758                         }
1759                 }       
1760         }
1761         if (propmode) {
1762                 MEM_freeN(vectors);
1763                 MEM_freeN(nears);
1764         }
1765         /* crazy space free */
1766         if(mappedcos)
1767                 MEM_freeN(mappedcos);
1768         if(quats)
1769                 MEM_freeN(quats);
1770 }
1771
1772 /* ********************* UV ****************** */
1773
1774 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
1775 {
1776         float aspx, aspy;
1777
1778         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1779
1780         /* uv coords are scaled by aspects. this is needed for rotations and
1781            proportional editing to be consistent with the stretchted uv coords
1782            that are displayed. this also means that for display and numinput,
1783            and when the the uv coords are flushed, these are converted each time */
1784         td2d->loc[0] = uv[0]*aspx;
1785         td2d->loc[1] = uv[1]*aspy;
1786         td2d->loc[2] = 0.0f;
1787         td2d->loc2d = uv;
1788
1789         td->flag = 0;
1790         td->loc = td2d->loc;
1791         VECCOPY(td->center, td->loc);
1792         VECCOPY(td->iloc, td->loc);
1793
1794         memset(td->axismtx, 0, sizeof(td->axismtx));
1795         td->axismtx[2][2] = 1.0f;
1796
1797         td->ext= NULL; td->tdi= NULL; td->val= NULL;
1798
1799         if(selected) {
1800                 td->flag |= TD_SELECTED;
1801                 td->dist= 0.0;
1802         }
1803         else
1804                 td->dist= MAXFLOAT;
1805         
1806         Mat3One(td->mtx);
1807         Mat3One(td->smtx);
1808 }
1809
1810 static void createTransUVs(TransInfo *t)
1811 {
1812         TransData *td = NULL;
1813         TransData2D *td2d = NULL;
1814         Mesh *me;
1815         MFace *mf;
1816         MTFace *tf;
1817         int a, count=0, countsel=0;
1818         int propmode = t->flag & T_PROP_EDIT;
1819         
1820         if(is_uv_tface_editing_allowed()==0) return;
1821         me= get_mesh(OBACT);
1822
1823         /* count */
1824         tf= me->mtface;
1825         mf= me->mface;
1826         for(a=me->totface; a>0; a--, tf++, mf++) {
1827                 if(mf->v3 && mf->flag & ME_FACE_SEL) {
1828                         if(tf->flag & TF_SEL1) countsel++;
1829                         if(tf->flag & TF_SEL2) countsel++;
1830                         if(tf->flag & TF_SEL3) countsel++;
1831                         if(mf->v4 && (tf->flag & TF_SEL4)) countsel++;
1832                         if(propmode)
1833                                 count += (mf->v4)? 4: 3;
1834                 }
1835         }
1836
1837         /* note: in prop mode we need at least 1 selected */
1838         if (countsel==0) return;
1839         
1840         t->total= (propmode)? count: countsel;
1841         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
1842         /* for each 2d uv coord a 3d vector is allocated, so that they can be
1843            treated just as if they were 3d verts */
1844         t->data2d= MEM_mallocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
1845
1846         if(G.sima->flag & SI_CLIP_UV)
1847                 t->flag |= T_CLIP_UV;
1848
1849         td= t->data;
1850         td2d= t->data2d;
1851         tf= me->mtface;
1852         mf= me->mface;
1853         for(a=me->totface; a>0; a--, tf++, mf++) {
1854                 if(mf->v3 && mf->flag & ME_FACE_SEL) {
1855                         if(tf->flag & TF_SEL1 || propmode)
1856                                 UVsToTransData(td++, td2d++, tf->uv[0], (tf->flag & TF_SEL1));
1857                         if(tf->flag & TF_SEL2 || propmode)
1858                                 UVsToTransData(td++, td2d++, tf->uv[1], (tf->flag & TF_SEL2));
1859                         if(tf->flag & TF_SEL3 || propmode)
1860                                 UVsToTransData(td++, td2d++, tf->uv[2], (tf->flag & TF_SEL3));
1861
1862                         if(mf->v4 && (tf->flag & TF_SEL4 || propmode))
1863                                 UVsToTransData(td++, td2d++, tf->uv[3], (tf->flag & TF_SEL4));
1864                 }
1865         }
1866
1867         if (G.sima->flag & SI_LIVE_UNWRAP)
1868                 unwrap_lscm_live_begin();
1869 }
1870
1871 void flushTransUVs(TransInfo *t)
1872 {
1873         TransData2D *td;
1874         int a, width, height;
1875         Object *ob= OBACT;
1876         Mesh *me= get_mesh(ob);
1877         float aspx, aspy, invx, invy;
1878
1879         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1880         transform_width_height_tface_uv(&width, &height);
1881         invx= 1.0f/aspx;
1882         invy= 1.0f/aspy;
1883
1884         /* flush to 2d vector from internally used 3d vector */
1885         for(a=0, td= t->data2d; a<t->total; a++, td++) {
1886                 td->loc2d[0]= td->loc[0]*invx;
1887                 td->loc2d[1]= td->loc[1]*invy;
1888                 
1889                 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
1890                         td->loc2d[0]= floor(width*td->loc2d[0] + 0.5f)/width;
1891                         td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height;
1892                 }
1893         }
1894
1895         /* always call this, also for cancel (it transforms non-selected vertices...) */
1896         if((G.sima->flag & SI_BE_SQUARE))
1897                 be_square_tface_uv(me);
1898
1899         /* this is overkill if G.sima->lock is not set, but still needed */
1900         object_uvs_changed(ob);
1901 }
1902
1903 int clipUVTransform(TransInfo *t, float *vec, int resize)
1904 {
1905         TransData *td;
1906         int a, clipx=1, clipy=1;
1907         float aspx, aspy, min[2], max[2];
1908
1909         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1910         min[0]= min[1]= 0.0f;
1911         max[0]= aspx; max[1]= aspy;
1912
1913         for(a=0, td= t->data; a<t->total; a++, td++) {
1914                 DO_MINMAX2(td->loc, min, max);
1915         }
1916
1917         if(resize) {
1918                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
1919                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
1920                 else if(max[0] > aspx && t->center[0] < aspx)
1921                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
1922                 else
1923                         clipx= 0;
1924
1925                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
1926                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
1927                 else if(max[1] > aspy && t->center[1] < aspy)
1928                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
1929                 else
1930                         clipy= 0;
1931         }
1932         else {
1933                 if(min[0] < 0.0f)
1934                         vec[0] -= min[0];
1935                 else if(max[0] > aspx)
1936                         vec[0] -= max[0]-aspx;
1937                 else
1938                         clipx= 0;
1939
1940                 if(min[1] < 0.0f)
1941                         vec[1] -= min[1];
1942                 else if(max[1] > aspy)
1943                         vec[1] -= max[1]-aspy;
1944                 else
1945                         clipy= 0;
1946         }       
1947
1948         return (clipx || clipy);
1949 }
1950
1951 /* **************** IpoKey stuff, for Object TransData ********** */
1952
1953 /* storage of bezier triple. thats why -3 and +3! */
1954 static void set_tdi_old(float *old, float *poin)
1955 {
1956         old[0]= *(poin);
1957         old[3]= *(poin-3);
1958         old[6]= *(poin+3);
1959 }
1960
1961 /* while transforming */
1962 void add_tdi_poin(float *poin, float *old, float delta)
1963 {
1964         if(poin) {
1965                 poin[0]= old[0]+delta;
1966                 poin[-3]= old[3]+delta;
1967                 poin[3]= old[6]+delta;
1968         }
1969 }
1970
1971 /* fill ipokey transdata with old vals and pointers */
1972 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
1973 {
1974         extern int ob_ar[];             // blenkernel ipo.c
1975         TransDataIpokey *tdi= td->tdi;
1976         BezTriple *bezt;
1977         int a, delta= 0;
1978         
1979         td->val= NULL;  // is read on ESC
1980         
1981         for(a=0; a<OB_TOTIPO; a++) {
1982                 if(ik->data[a]) {
1983                         bezt= ik->data[a];
1984                         
1985                         switch( ob_ar[a] ) {
1986                                 case OB_LOC_X:
1987                                 case OB_DLOC_X:
1988                                         tdi->locx= &(bezt->vec[1][1]); break;
1989                                 case OB_LOC_Y:
1990                                 case OB_DLOC_Y:
1991                                         tdi->locy= &(bezt->vec[1][1]); break;
1992                                 case OB_LOC_Z:
1993                                 case OB_DLOC_Z:
1994                                         tdi->locz= &(bezt->vec[1][1]); break;
1995                                         
1996                                 case OB_DROT_X:
1997                                         delta= 1;
1998                                 case OB_ROT_X:
1999                                         tdi->rotx= &(bezt->vec[1][1]); break;
2000                                 case OB_DROT_Y:
2001                                         delta= 1;
2002                                 case OB_ROT_Y:
2003                                         tdi->roty= &(bezt->vec[1][1]); break;
2004                                 case OB_DROT_Z:
2005                                         delta= 1;
2006                                 case OB_ROT_Z:
2007                                         tdi->rotz= &(bezt->vec[1][1]); break;
2008                                         
2009                                 case OB_SIZE_X:
2010                                 case OB_DSIZE_X:
2011                                         tdi->sizex= &(bezt->vec[1][1]); break;
2012                                 case OB_SIZE_Y:
2013                                 case OB_DSIZE_Y:
2014                                         tdi->sizey= &(bezt->vec[1][1]); break;
2015                                 case OB_SIZE_Z:
2016                                 case OB_DSIZE_Z:
2017                                         tdi->sizez= &(bezt->vec[1][1]); break;          
2018                         }       
2019                 }
2020         }
2021         
2022         /* oldvals for e.g. undo */
2023         if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
2024         if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
2025         if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
2026         
2027         /* remember, for mapping curves ('1'=10 degrees)  */
2028         if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
2029         if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
2030         if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
2031         
2032         /* this is not allowed to be dsize! */
2033         if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
2034         if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
2035         if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
2036         
2037         tdi->flag= TOB_IPO;
2038         if(delta) tdi->flag |= TOB_IPODROT;
2039 }
2040
2041
2042 /* *************************** Object Transform data ******************* */
2043
2044 static void ObjectToTransData(TransData *td, Object *ob) 
2045 {
2046         float obmtx[3][3];
2047
2048         /* axismtx has the real orientation */
2049         Mat3CpyMat4(td->axismtx, ob->obmat);
2050         Mat3Ortho(td->axismtx);
2051
2052         where_is_object(ob);
2053
2054         td->ob = ob;
2055
2056         td->loc = ob->loc;
2057         VECCOPY(td->iloc, td->loc);
2058         
2059         td->ext->rot = ob->rot;
2060         VECCOPY(td->ext->irot, ob->rot);
2061         VECCOPY(td->ext->drot, ob->drot);
2062         
2063         td->ext->size = ob->size;
2064         VECCOPY(td->ext->isize, ob->size);
2065         VECCOPY(td->ext->dsize, ob->dsize);
2066
2067         VECCOPY(td->center, ob->obmat[3]);
2068
2069         if (ob->parent || ob->track || ob->constraints.first)
2070         {
2071                 float totmat[3][3], obinv[3][3];
2072                 
2073                 /* get the effect of parenting, and/or tracking, and/or constraints */
2074                 object_to_mat3(ob, obmtx);
2075                 Mat3CpyMat4(totmat, ob->obmat);
2076                 Mat3Inv(obinv, totmat);
2077                 Mat3MulMat3(td->smtx, obmtx, obinv);
2078                 Mat3Inv(td->mtx, td->smtx);
2079         }
2080         else
2081         {
2082                 Mat3One(td->smtx);
2083                 Mat3One(td->mtx);
2084         }
2085 #ifdef WITH_VERSE
2086         if(ob->vnode) {
2087                 td->verse = (void*)ob;
2088                 td->flag |= TD_VERSE_OBJECT;
2089         }
2090         else
2091                 td->flag &= ~TD_VERSE_OBJECT;
2092 #endif
2093 }
2094
2095
2096 /* sets flags in Bases to define whether they take part in transform */
2097 /* it deselects Bases, so we have to call the clear function always after */
2098 static void set_trans_object_base_flags(TransInfo *t)
2099 {
2100         /*
2101          if Base selected and has parent selected:
2102          base->flag= BA_WAS_SEL
2103          */
2104         Base *base;
2105         
2106         /* makes sure base flags and object flags are identical */
2107         copy_baseflags();
2108         
2109         /* handle pending update events, otherwise they got copied below */
2110         for (base= FIRSTBASE; base; base= base->next) {
2111                 if(base->object->recalc) 
2112                         object_handle_update(base->object);
2113         }
2114         
2115         for (base= FIRSTBASE; base; base= base->next) {
2116                 base->flag &= ~BA_WAS_SEL;
2117                 
2118                 if(TESTBASELIB(base)) {
2119                         Object *ob= base->object;
2120                         Object *parsel= ob->parent;
2121                         
2122                         /* if parent selected, deselect */
2123                         while(parsel) {
2124                                 if(parsel->flag & SELECT) break;
2125                                 parsel= parsel->parent;
2126                         }
2127                         
2128                         if(parsel) {
2129                                 base->flag &= ~SELECT;
2130                                 base->flag |= BA_WAS_SEL;
2131                         }
2132                         /* used for flush, depgraph will change recalcs if needed :) */
2133                         ob->recalc |= OB_RECALC_OB;
2134                 }
2135         }
2136         /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
2137         DAG_scene_flush_update(G.scene, -1);
2138         
2139         /* and we store them temporal in base (only used for transform code) */
2140         /* this because after doing updates, the object->recalc is cleared */
2141         for (base= FIRSTBASE; base; base= base->next) {
2142                 if(base->object->recalc & OB_RECALC_OB)
2143                         base->flag |= BA_HAS_RECALC_OB;
2144                 if(base->object->recalc & OB_RECALC_DATA)
2145                         base->flag |= BA_HAS_RECALC_DATA;
2146         }
2147 }
2148
2149 static void clear_trans_object_base_flags(void)
2150 {
2151         Base *base;
2152         
2153         base= FIRSTBASE;
2154         while(base) {
2155                 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
2156                 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
2157                 
2158                 base = base->next;
2159         }
2160 }
2161
2162 /* auto-keyframing feature - for objects 
2163  *      tmode: should be a transform mode 
2164  */
2165 void autokeyframe_ob_cb_func(Object *ob, int tmode)
2166 {
2167         IpoCurve *icu;
2168         char *actname="";
2169         
2170         if (G.flags & G_RECORDKEYS) {
2171                 if(ob->ipoflag & OB_ACTION_OB)
2172                         actname= "Object";
2173
2174                 if(U.uiflag & USER_KEYINSERTAVAI) {
2175                         if(ob->ipo || ob->action) {
2176                                 ID *id= (ID *)(ob);
2177                                 
2178                                 if (ob->ipo) {
2179                                         icu= ob->ipo->curve.first;
2180                                 }
2181                                 else {
2182                                         bActionChannel *achan;
2183                                         achan= get_action_channel(ob->action, actname);
2184                                         
2185                                         if (achan && achan->ipo)
2186                                                 icu= achan->ipo->curve.first;
2187                                         else
2188                                                 icu= NULL;
2189                                 }
2190                                 
2191                                 while(icu) {
2192                                         icu->flag &= ~IPO_SELECT;
2193                                         if (U.uiflag & USER_KEYINSERTNEED)
2194                                                 insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode);
2195                                         else
2196                                                 insertkey(id, ID_OB, actname, NULL, icu->adrcode);
2197                                         icu= icu->next;
2198                                 }
2199                         }
2200                 }
2201                 else if (U.uiflag & USER_KEYINSERTNEED) {
2202                         if (tmode==TFM_RESIZE) {
2203                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_X);
2204                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y);
2205                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z);
2206                         }
2207                         else if (tmode==TFM_ROTATION) {
2208                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_X);
2209                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Y);
2210                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Z);
2211                         }
2212                         else if (tmode==TFM_TRANSLATION) {
2213                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_X);
2214                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Y);
2215                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Z);
2216                         }
2217                 }
2218                 else {
2219                         insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_X);
2220                         insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Y);
2221                         insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Z);
2222
2223                         insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_X);
2224                         insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Y);
2225                         insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Z);
2226
2227                         insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_X);
2228                         insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y);
2229                         insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z);
2230                 }
2231
2232                 remake_object_ipos(ob);
2233                 allqueue(REDRAWIPO, 0);
2234                 allspace(REMAKEIPO, 0);
2235                 allqueue(REDRAWVIEW3D, 0);
2236                 allqueue(REDRAWNLA, 0);
2237                 allqueue(REDRAWTIME, 0);
2238         }
2239 }
2240
2241 /* auto-keyframing feature - for poses/pose-channels 
2242  *      tmode: should be a transform mode 
2243  *      targetless_ik: has targetless ik been done on any channels?
2244  */
2245 void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik)
2246 {
2247         bAction *act;
2248         bPose   *pose;
2249         bPoseChannel *pchan;
2250         IpoCurve *icu;
2251         
2252         pose= ob->pose;
2253         act= ob->action;
2254         
2255         if (G.flags & G_RECORDKEYS) {
2256                 if (!act)
2257                         act= ob->action= add_empty_action("Action");
2258                 
2259                 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
2260                         if (pchan->bone->flag & BONE_TRANSFORM){
2261
2262                                 if(U.uiflag & USER_KEYINSERTAVAI) {
2263                                         bActionChannel *achan; 
2264
2265                                         for (achan = act->chanbase.first; achan; achan=achan->next){
2266                                                 if (achan->ipo && !strcmp (achan->name, pchan->name)){
2267                                                         for (icu = achan->ipo->curve.first; icu; icu=icu->next){
2268                                                                 if (U.uiflag & USER_KEYINSERTNEED)
2269                                                                         insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode);
2270                                                                 else
2271                                                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode);
2272                                                         }
2273                                                         break;
2274                                                 }
2275                                         }
2276                                 }
2277                                 else if (U.uiflag & USER_KEYINSERTNEED) {
2278                                         if ((tmode==TFM_TRANSLATION) && (targetless_ik==0)) {
2279                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
2280                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
2281                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
2282                                         }
2283                                         if ((tmode==TFM_ROTATION) || ((tmode==TFM_TRANSLATION) && targetless_ik)) {
2284                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
2285                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
2286                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
2287                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
2288                                         }
2289                                         if (tmode==TFM_RESIZE) {
2290                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
2291                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
2292                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
2293                                         }
2294                                 }
2295                                 else {
2296                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
2297                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
2298                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
2299
2300                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
2301                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
2302                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
2303                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
2304
2305                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
2306                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
2307                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
2308                                 }
2309                         }
2310                 }
2311                 
2312                 remake_action_ipos (act);
2313                 allspace(REMAKEIPO, 0);
2314                 allqueue(REDRAWACTION, 0);
2315                 allqueue(REDRAWIPO, 0);
2316                 allqueue(REDRAWNLA, 0);
2317                 allqueue(REDRAWTIME, 0);
2318         }
2319 }
2320
2321 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
2322 /* note; transdata has been freed already! */
2323 void special_aftertrans_update(TransInfo *t)
2324 {
2325         Object *ob;
2326         Base *base;
2327         int redrawipo=0;
2328         int cancelled= (t->state == TRANS_CANCEL);
2329                 
2330         if(G.obedit) {
2331                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2332                         allqueue(REDRAWBUTSEDIT, 0);
2333                 
2334                 /* table needs to be created for each edit command, since vertices can move etc */
2335                 mesh_octree_table(G.obedit, NULL, 'e');
2336         }
2337         else if( (t->flag & T_POSE) && t->poseobj) {
2338                 bArmature *arm;
2339                 bPose   *pose;
2340                 bPoseChannel *pchan;
2341                 short targetless_ik= 0;
2342
2343                 ob= t->poseobj;
2344                 arm= ob->data;
2345                 pose= ob->pose;
2346                 
2347                 /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
2348                 pose->flag |= POSE_DO_UNLOCK;
2349
2350                 /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
2351                 if(!cancelled && t->mode==TFM_TRANSLATION)
2352                         targetless_ik= apply_targetless_ik(ob);
2353                 else {
2354                         /* not forget to clear the auto flag */
2355                         for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
2356                                 bKinematicConstraint *data= has_targetless_ik(pchan);
2357                                 if(data) data->flag &= ~CONSTRAINT_IK_AUTO;
2358                         }
2359                 }
2360                 
2361                 if(t->mode==TFM_TRANSLATION)
2362                         pose_grab_with_ik_clear(ob);
2363                 
2364                 /* automatic inserting of keys */
2365                 if(!cancelled) {
2366                         autokeyframe_pose_cb_func(ob, t->mode, targetless_ik);
2367                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2368                 }
2369                 else if(arm->flag & ARM_DELAYDEFORM) {
2370                         /* old optimize trick... this enforces to bypass the depgraph */
2371                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2372                         ob->recalc= 0;  // is set on OK position already by recalcData()
2373                 }
2374                 else 
2375                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2376                 
2377                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2378                         allqueue(REDRAWBUTSEDIT, 0);
2379
2380         }
2381         else {
2382                 base= FIRSTBASE;
2383                 while(base) {   
2384                         
2385                         if(base->flag & BA_DO_IPO) redrawipo= 1;
2386                         
2387                         ob= base->object;
2388
2389                         if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
2390                         
2391                         /* Set autokey if necessary */
2392                         if ((!cancelled) && (base->flag & SELECT)){
2393                                 autokeyframe_ob_cb_func(ob, t->mode);
2394                         }
2395                         
2396                         base= base->next;
2397                 }
2398                 
2399         }
2400         
2401         clear_trans_object_base_flags();
2402         
2403         if(redrawipo) {
2404                 allqueue(REDRAWNLA, 0);
2405                 allqueue(REDRAWACTION, 0);
2406                 allqueue(REDRAWIPO, 0);
2407         }
2408         
2409         reset_slowparents();
2410         
2411         /* note; should actually only be done for all objects when a lamp is moved... (ton) */
2412         if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
2413                 reshadeall_displist();
2414 }
2415
2416 static void createTransObject(TransInfo *t)
2417 {
2418         TransData *td = NULL;
2419         TransDataExtension *tx;
2420         Object *ob;
2421         Base *base;
2422         IpoKey *ik;
2423         ListBase elems;
2424         
2425         set_trans_object_base_flags(t);
2426
2427         /* count */     
2428         for(base= FIRSTBASE; base; base= base->next) {
2429                 if TESTBASELIB(base) {
2430                         ob= base->object;
2431                         
2432                         /* store ipo keys? */
2433                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2434                                 elems.first= elems.last= NULL;
2435                                 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
2436                                 
2437                                 pushdata(&elems, sizeof(ListBase));
2438                                 
2439                                 for(ik= elems.first; ik; ik= ik->next) t->total++;
2440
2441                                 if(elems.first==NULL) t->total++;
2442                         }
2443                         else {
2444                                 t->total++;
2445                         }
2446                 }
2447         }
2448
2449         if(!t->total) {
2450                 /* clear here, main transform function escapes too */
2451                 clear_trans_object_base_flags();
2452                 return;
2453         }
2454         
2455         td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
2456         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
2457
2458         for(base= FIRSTBASE; base; base= base->next) {
2459                 if TESTBASELIB(base) {
2460                         ob= base->object;
2461                         
2462                         td->flag= TD_SELECTED;
2463                         td->protectflag= ob->protectflag;
2464                         td->ext = tx;
2465
2466                         /* store ipo keys? */
2467                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2468                                 
2469                                 popfirst(&elems);       // bring back pushed listbase
2470                                 
2471                                 if(elems.first) {
2472                                         int cfraont;
2473                                         int ipoflag;
2474                                         
2475                                         base->flag |= BA_DO_IPO+BA_WAS_SEL;
2476                                         base->flag &= ~SELECT;
2477                                         
2478                                         cfraont= CFRA;
2479                                         set_no_parent_ipo(1);
2480                                         ipoflag= ob->ipoflag;
2481                                         ob->ipoflag &= ~OB_OFFS_OB;
2482                                         
2483                                         /*
2484                                          * This is really EVIL code that pushes down Object values
2485                                          * (loc, dloc, orig, size, dsize, rot, drot)
2486                                          * */
2487                                          
2488                                         pushdata((void*)ob->loc, 7 * 3 * sizeof(float)); // tsk! tsk!
2489                                         
2490                                         for(ik= elems.first; ik; ik= ik->next) {
2491                                                 
2492                                                 /* weak... this doesn't correct for floating values, giving small errors */
2493                                                 CFRA= (int)(ik->val/G.scene->r.framelen);
2494                                                 
2495                                                 do_ob_ipo(ob);
2496                                                 ObjectToTransData(td, ob);      // does where_is_object()
2497                                                 
2498                                                 td->flag= TD_SELECTED;
2499                                                 
2500                                                 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
2501                                                 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
2502                                                 ipokey_to_transdata(ik, td);
2503                                                 
2504                                                 td++;
2505                                                 tx++;
2506                                                 if(ik->next) td->ext= tx;       // prevent corrupting mem!
2507                                         }
2508                                         free_ipokey(&elems);
2509                                         
2510                                         poplast(ob->loc);
2511                                         set_no_parent_ipo(0);
2512                                         
2513                                         CFRA= cfraont;
2514                                         ob->ipoflag= ipoflag;
2515                                         
2516                                         where_is_object(ob);    // restore 
2517                                 }
2518                                 else {
2519                                         ObjectToTransData(td, ob);
2520                                         td->tdi = NULL;
2521                                         td->val = NULL;
2522                                         td++;
2523                                         tx++;
2524                                 }
2525                         }
2526                         else {
2527                                 ObjectToTransData(td, ob);
2528                                 td->tdi = NULL;
2529                                 td->val = NULL;
2530                                 td++;
2531                                 tx++;
2532                         }
2533                 }
2534         }
2535 }
2536
2537 void createTransData(TransInfo *t) 
2538 {
2539         Object *ob= OBACT;
2540         
2541         if (t->context == CTX_TEXTURE) {
2542                 t->flag |= T_TEXTURE;
2543                 createTransTexspace(t);
2544         }
2545         else if (t->context == CTX_EDGE) {
2546                 t->ext = NULL;
2547                 t->flag |= T_EDIT;
2548                 createTransEdge(t);
2549                 if(t->data && t->flag & T_PROP_EDIT) {
2550                         sort_trans_data(t);     // makes selected become first in array
2551                         set_prop_dist(t, 1);
2552                         sort_trans_data_dist(t);
2553                 }
2554         }
2555         else if (t->spacetype == SPACE_IMAGE) {
2556                 t->flag |= T_POINTS|T_2D_EDIT;
2557                 createTransUVs(t);
2558                 if(t->data && (t->flag & T_PROP_EDIT)) {
2559                         sort_trans_data(t);     // makes selected become first in array
2560                         set_prop_dist(t, 1);
2561                         sort_trans_data_dist(t);
2562                 }
2563         }
2564         else if (G.obedit) {
2565                 t->ext = NULL;
2566                 if (G.obedit->type == OB_MESH) {
2567                         createTransEditVerts(t);        
2568                 }
2569                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
2570                         createTransCurveVerts(t);
2571                 }
2572                 else if (G.obedit->type==OB_LATTICE) {
2573                         createTransLatticeVerts(t);
2574                 }
2575                 else if (G.obedit->type==OB_MBALL) {
2576                         createTransMBallVerts(t);
2577                 }
2578                 else if (G.obedit->type==OB_ARMATURE) {
2579                         t->flag &= ~T_PROP_EDIT;
2580                         createTransArmatureVerts(t);
2581                 }                                                       
2582                 else {
2583                         printf("not done yet! only have mesh surface curve\n");
2584                 }
2585
2586                 if(t->data && t->flag & T_PROP_EDIT) {
2587                         if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
2588                                 sort_trans_data(t);     // makes selected become first in array
2589                                 set_prop_dist(t, 0);
2590                                 sort_trans_data_dist(t);
2591                         }
2592                         else {
2593                                 sort_trans_data(t);     // makes selected become first in array
2594                                 set_prop_dist(t, 1);
2595                                 sort_trans_data_dist(t);
2596                         }
2597                 }
2598
2599                 t->flag |= T_EDIT|T_POINTS;
2600                 
2601                 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
2602                 if(t->mode==TFM_BONESIZE) {
2603                         t->flag &= ~(T_EDIT|T_POINTS);
2604                         t->flag |= T_POSE;
2605                         t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
2606                 }
2607         }
2608         else if (ob && (ob->flag & OB_POSEMODE)) {
2609                 createTransPose(t, OBACT);
2610         }
2611         else if (G.f & G_WEIGHTPAINT) {
2612                 /* exception, we look for the one selected armature */
2613                 Base *base;
2614                 for(base=FIRSTBASE; base; base= base->next) {
2615                         if(TESTBASELIB(base)) {
2616                                 if(base->object->type==OB_ARMATURE)
2617                                         if(base->object->flag & OB_POSEMODE)
2618                                                 break;
2619                         }
2620                 }
2621                 if(base) {
2622                         createTransPose(t, base->object);
2623                 }
2624         }
2625         else {
2626                 createTransObject(t);
2627                 t->flag |= T_OBJECT;
2628         }
2629
2630         if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
2631                 t->flag |= T_CAMERA;
2632         }
2633         
2634         /* temporal...? */
2635         G.scene->recalc |= SCE_PRV_CHANGED;     /* test for 3d preview */
2636 }
2637