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