98bcb5d47ce2a42337d4bb2946c054a1ca18001b
[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_mywindow.h"
104 #include "BIF_resources.h"
105 #include "BIF_screen.h"
106 #include "BIF_space.h"
107 #include "BIF_toolbox.h"
108
109 #include "BSE_view.h"
110 #include "BSE_edit.h"
111 #include "BSE_editipo.h"
112 #include "BSE_editipo_types.h"
113
114 #include "BDR_editobject.h"             // reset_slowparents()
115
116 #include "BLI_arithb.h"
117 #include "BLI_editVert.h"
118
119 #include "blendef.h"
120
121 #include "mydevice.h"
122
123 extern ListBase editNurb;
124 extern ListBase editelems;
125
126 #include "transform.h"
127
128
129 /* ************************** Functions *************************** */
130
131 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
132         TransData pivot = *head;
133         TransData *ihead = head;
134         TransData *itail = tail;
135         short connected = t->flag & T_PROP_CONNECTED;
136
137         while (head < tail)
138         {
139                 if (connected) {
140                         while ((tail->dist >= pivot.dist) && (head < tail))
141                                 tail--;
142                 }
143                 else {
144                         while ((tail->rdist >= pivot.rdist) && (head < tail))
145                                 tail--;
146                 }
147
148                 if (head != tail)
149                 {
150                         *head = *tail;
151                         head++;
152                 }
153
154                 if (connected) {
155                         while ((head->dist <= pivot.dist) && (head < tail))
156                                 head++;
157                 }
158                 else {
159                         while ((head->rdist <= pivot.rdist) && (head < tail))
160                                 head++;
161                 }
162
163                 if (head != tail)
164                 {
165                         *tail = *head;
166                         tail--;
167                 }
168         }
169
170         *head = pivot;
171         if (ihead < head) {
172                 qsort_trans_data(t, ihead, head-1);
173         }
174         if (itail > head) {
175                 qsort_trans_data(t, head+1, itail);
176         }
177 }
178
179 void sort_trans_data_dist(TransInfo *t) {
180         TransData *start = t->data;
181         int i = 1;
182
183         while(i < t->total && start->flag & TD_SELECTED) {
184                 start++;
185                 i++;
186         }
187         qsort_trans_data(t, start, t->data + t->total - 1);
188 }
189
190 static void sort_trans_data(TransInfo *t) 
191 {
192         TransData *sel, *unsel;
193         TransData temp;
194         unsel = t->data;
195         sel = t->data;
196         sel += t->total - 1;
197         while (sel > unsel) {
198                 while (unsel->flag & TD_SELECTED) {
199                         unsel++;
200                         if (unsel == sel) {
201                                 return;
202                         }
203                 }
204                 while (!(sel->flag & TD_SELECTED)) {
205                         sel--;
206                         if (unsel == sel) {
207                                 return;
208                         }
209                 }
210                 temp = *unsel;
211                 *unsel = *sel;
212                 *sel = temp;
213                 sel--;
214                 unsel++;
215         }
216 }
217
218 /* distance calculated from not-selected vertex to nearest selected vertex
219    warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
220 static void set_prop_dist(TransInfo *t, short with_dist)
221 {
222         TransData *tob;
223         int a;
224
225         for(a=0, tob= t->data; a<t->total; a++, tob++) {
226                 
227                 tob->rdist= 0.0f; // init, it was mallocced
228                 
229                 if((tob->flag & TD_SELECTED)==0) {
230                         TransData *td;
231                         int i;
232                         float dist, vec[3];
233
234                         tob->rdist = -1.0f; // signal for next loop
235                                 
236                         for (i = 0, td= t->data; i < t->total; i++, td++) {
237                                 if(td->flag & TD_SELECTED) {
238                                         VecSubf(vec, tob->center, td->center);
239                                         Mat3MulVecfl(tob->mtx, vec);
240                                         dist = Normalise(vec);
241                                         if (tob->rdist == -1.0f) {
242                                                 tob->rdist = dist;
243                                         }
244                                         else if (dist < tob->rdist) {
245                                                 tob->rdist = dist;
246                                         }
247                                 }
248                                 else break;     // by definition transdata has selected items in beginning
249                         }
250                         if (with_dist) {
251                                 tob->dist = tob->rdist;
252                         }
253                 }       
254         }
255 }
256
257 /* ************************** CONVERSIONS ************************* */
258
259 /* ********************* texture space ********* */
260
261 static void createTransTexspace(TransInfo *t)
262 {
263         TransData *td;
264         Object *ob;
265         ID *id;
266         
267         ob= OBACT;
268
269         id= ob->data;
270         if(id==NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
271                 t->total = 0;
272                 return;
273         }
274
275         t->total = 1;
276         td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
277         td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
278         
279         td->flag= TD_SELECTED;
280         VECCOPY(td->center, ob->obmat[3]);
281         td->ob = ob;
282         
283         Mat3CpyMat4(td->mtx, ob->obmat);
284         Mat3Inv(td->smtx, td->mtx);
285         
286         if( GS(id->name)==ID_ME) {
287                 Mesh *me= ob->data;
288                 me->texflag &= ~AUTOSPACE;
289                 td->loc= me->loc;
290                 td->ext->rot= me->rot;
291                 td->ext->size= me->size;
292         }
293         else if( GS(id->name)==ID_CU) {
294                 Curve *cu= ob->data;
295                 cu->texflag &= ~CU_AUTOSPACE;
296                 td->loc= cu->loc;
297                 td->ext->rot= cu->rot;
298                 td->ext->size= cu->size;
299         }
300         else if( GS(id->name)==ID_MB) {
301                 MetaBall *mb= ob->data;
302                 mb->texflag &= ~MB_AUTOSPACE;
303                 td->loc= mb->loc;
304                 td->ext->rot= mb->rot;
305                 td->ext->size= mb->size;
306         }
307         
308         VECCOPY(td->iloc, td->loc);
309         VECCOPY(td->ext->irot, td->ext->rot);
310         VECCOPY(td->ext->isize, td->ext->size);
311 }
312
313 /* ********************* edge (for crease) ***** */
314
315 static void createTransEdge(TransInfo *t) {
316         TransData *td = NULL;
317         EditMesh *em = G.editMesh;
318         EditEdge *eed;
319         float mtx[3][3], smtx[3][3];
320         int count=0, countsel=0;
321         int propmode = t->flag & T_PROP_EDIT;
322
323         for(eed= em->edges.first; eed; eed= eed->next) {
324                 if(eed->h==0) {
325                         if (eed->f & SELECT) countsel++;
326                         if (propmode) count++;
327                 }
328         }
329
330         if (countsel == 0)
331                 return;
332
333         if(propmode) {
334                 t->total = count;
335         }
336         else {
337                 t->total = countsel;
338         }
339
340         td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
341
342         Mat3CpyMat4(mtx, G.obedit->obmat);
343         Mat3Inv(smtx, mtx);
344
345         for(eed= em->edges.first; eed; eed= eed->next) {
346                 if(eed->h==0 && (eed->f & SELECT || propmode)) {
347                         /* need to set center for center calculations */
348                         VecAddf(td->center, eed->v1->co, eed->v2->co);
349                         VecMulf(td->center, 0.5f);
350
351                         td->loc= NULL;
352                         if (eed->f & SELECT)
353                                 td->flag= TD_SELECTED;
354                         else 
355                                 td->flag= 0;
356
357
358                         Mat3CpyMat3(td->smtx, smtx);
359                         Mat3CpyMat3(td->mtx, mtx);
360
361                         td->ext = NULL;
362                         td->tdi = NULL;
363                         td->val = &(eed->crease);
364                         td->ival = eed->crease;
365
366                         td++;
367                 }
368         }
369 }
370
371 /* ********************* pose mode ************* */
372
373 /* recursive, make sure it's identical structured as next one */
374 /* only counts the parent selection, and tags transform flag */
375 /* exported for manipulator */
376 void count_bone_select(TransInfo *t, ListBase *lb, int do_it) 
377 {
378         Bone *bone;
379         int do_next;
380         
381         for(bone= lb->first; bone; bone= bone->next) {
382                 bone->flag &= ~BONE_TRANSFORM;
383                 do_next= do_it;
384                 if(do_it) {
385                         if (bone->flag & BONE_SELECTED) {
386                                 /* We don't let connected children get "grabbed" */
387                                 if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_CONNECTED)==0 ) {
388                                         bone->flag |= BONE_TRANSFORM;
389                                         t->total++;
390                                         do_next= 0;     // no transform on children if one parent bone is selected
391                                 }
392                         }
393                 }
394                 count_bone_select(t, &bone->childbase, do_next);
395         }
396 }
397
398 static int add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
399 {
400         Bone *bone= pchan->bone;
401         float pmat[3][3], omat[3][3];
402         float vec[3];
403
404         if(bone) {
405                 if (bone->flag & BONE_TRANSFORM) {
406                         /* We don't let connected children get "grabbed" */
407                         if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_CONNECTED)==0 ) {
408                                 
409                                 VECCOPY(vec, pchan->pose_mat[3]);
410                                 VECCOPY(td->center, vec);
411                                 
412                                 td->ob = ob;
413                                 td->flag= TD_SELECTED|TD_USEQUAT;
414                                 td->loc = pchan->loc;
415                                 VECCOPY(td->iloc, pchan->loc);
416                                 
417                                 td->ext->rot= NULL;
418                                 td->ext->quat= pchan->quat;
419                                 td->ext->size= pchan->size;
420
421                                 QUATCOPY(td->ext->iquat, pchan->quat);
422                                 VECCOPY(td->ext->isize, pchan->size);
423
424                                 /* proper way to get the parent transform + own transform */
425                                 Mat3CpyMat4(omat, ob->obmat);
426                                 if(pchan->parent) {
427                                         if(pchan->bone->flag & BONE_HINGE)
428                                                 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
429                                         else
430                                                 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
431                                                 
432                                         Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0);    // dang mulserie swaps args
433                                 }
434                                 else {
435                                         Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat);      // huh, transposed?
436                                 }
437                                 
438                                 Mat3Inv (td->smtx, td->mtx);
439                                 
440                                 /* for axismat we use bone's own transform */
441                                 Mat3CpyMat4(pmat, pchan->pose_mat);
442                                 Mat3MulMat3(td->axismtx, omat, pmat);
443                                 Mat3Ortho(td->axismtx);
444                                 
445                                 if(t->mode==TFM_BONESIZE) {
446                                         bArmature *arm= t->poseobj->data;
447                                         
448                                         if(arm->drawtype==ARM_ENVELOPE) {
449                                                 td->loc= NULL;
450                                                 td->val= &bone->dist;
451                                                 td->ival= bone->dist;
452                                         }
453                                         else {
454                                                 // abusive storage of scale in the loc pointer :)
455                                                 td->loc= &bone->xwidth;
456                                                 VECCOPY (td->iloc, td->loc);
457                                                 td->val= NULL;
458                                         }
459                                 }
460                                 
461                                 return 1;
462                         }
463                 }
464         }
465         return 0;
466 }
467
468 /* only called with pose mode active object now */
469 static void createTransPose(Object *ob, TransInfo *t)
470 {
471         bArmature *arm;
472         bPoseChannel *pchan;
473         TransData *td;
474         TransDataExtension *tdx;
475         int i;
476         
477         t->total= 0;
478         
479         /* check validity of state */
480         arm=get_armature (ob);
481         if (arm==NULL || ob->pose==NULL) return;
482         
483         if (arm->flag & ARM_RESTPOS) {
484                 if(t->mode!=TFM_BONESIZE) {
485                         notice ("Pose edit not possible while Rest Position is enabled");
486                         return;
487                 }
488         }
489         if (!(ob->lay & G.vd->lay)) return;
490
491         /* count total */
492         count_bone_select(t, &arm->bonebase, 1);
493
494         if(t->total==0 && t->mode==TFM_TRANSLATION) {
495                 t->mode= TFM_ROTATION;
496                 count_bone_select(t, &arm->bonebase, 1);
497         }               
498         if(t->total==0) return;
499
500         t->flag |= T_POSE;
501         t->poseobj= ob; // we also allow non-active objects to be transformed, in weightpaint
502         ob->pose->flag |= POSE_LOCKED;
503         
504         /* init trans data */
505     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
506     tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
507         for(i=0; i<t->total; i++, td++, tdx++) {
508                 td->ext= tdx;
509                 td->tdi = NULL;
510                 td->val = NULL;
511         }       
512         
513         /* use pose channels to fill trans data */
514         td= t->data;
515         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
516                 if( add_pose_transdata(t, pchan, ob, td) ) td++;
517         }
518         if(td != (t->data+t->total)) printf("Bone selection count error\n");
519         
520 }
521
522 /* ********************* armature ************** */
523
524 static void createTransArmatureVerts(TransInfo *t)
525 {
526         EditBone *ebo;
527         bArmature *arm= G.obedit->data;
528         TransData *td;
529         float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
530
531         t->total = 0;
532         for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
533                 if (t->mode==TFM_BONESIZE) {
534                         if (ebo->flag & BONE_SELECTED)
535                                 t->total++;
536                 }
537                 else {
538                         if (ebo->flag & BONE_TIPSEL)
539                                 t->total++;
540                         if (ebo->flag & BONE_ROOTSEL)
541                                 t->total++;
542                 }
543         }
544
545     if (!t->total) return;
546         
547         Mat3CpyMat4(mtx, G.obedit->obmat);
548         Mat3Inv(smtx, mtx);
549
550     td = t->data = MEM_mallocN(t->total*sizeof(TransData), "TransEditBone");
551         
552         for (ebo=G.edbo.first;ebo;ebo=ebo->next){
553                 
554                 ebo->oldlength= ebo->length;    // length==0.0 on extrude, used for scaling radius of bone points
555                 
556                 if (t->mode==TFM_BONE_ENVELOPE) {
557                         
558                         if (ebo->flag & BONE_ROOTSEL){
559                                 td->val= &ebo->rad_head;
560                                 td->ival= *td->val;
561                                 
562                                 VECCOPY (td->center, ebo->head);
563                                 td->flag= TD_SELECTED;
564                                 
565                                 Mat3CpyMat3(td->smtx, smtx);
566                                 Mat3CpyMat3(td->mtx, mtx);
567                                 
568                                 td->loc = NULL;
569                                 td->ext = NULL;
570                                 td->tdi = NULL;
571                                 
572                                 td++;
573                         }
574                         if (ebo->flag & BONE_TIPSEL){
575                                 td->val= &ebo->rad_tail;
576                                 td->ival= *td->val;
577                                 VECCOPY (td->center, ebo->tail);
578                                 td->flag= TD_SELECTED;
579                                 
580                                 Mat3CpyMat3(td->smtx, smtx);
581                                 Mat3CpyMat3(td->mtx, mtx);
582                                 
583                                 td->loc = NULL;
584                                 td->ext = NULL;
585                                 td->tdi = NULL;
586                                 
587                                 td++;
588                         }
589                         
590                 }
591                 else if (t->mode==TFM_BONESIZE) {
592                         if (ebo->flag & BONE_SELECTED) {
593                                 if(arm->drawtype==ARM_ENVELOPE) {
594                                         td->loc= NULL;
595                                         td->val= &ebo->dist;
596                                         td->ival= ebo->dist;
597                                 }
598                                 else {
599                                         // abusive storage of scale in the loc pointer :)
600                                         td->loc= &ebo->xwidth;
601                                         VECCOPY (td->iloc, td->loc);
602                                         td->val= NULL;
603                                 }
604                                 VECCOPY (td->center, ebo->head);
605                                 td->flag= TD_SELECTED;
606                                 
607                                 /* use local bone matrix */
608                                 VecSubf(delta, ebo->tail, ebo->head);   
609                                 vec_roll_to_mat3(delta, ebo->roll, bonemat);
610                                 Mat3MulMat3(td->mtx, mtx, bonemat);
611                                 Mat3Inv(td->smtx, td->mtx);
612                                 
613                                 Mat3CpyMat3(td->axismtx, td->mtx);
614                                 Mat3Ortho(td->axismtx);
615
616                                 td->ext = NULL;
617                                 td->tdi = NULL;
618                                 
619                                 td++;
620                         }
621                 }
622                 else {
623                         if (ebo->flag & BONE_TIPSEL){
624                                 VECCOPY (td->iloc, ebo->tail);
625                                 VECCOPY (td->center, td->iloc);
626                                 td->loc= ebo->tail;
627                                 td->flag= TD_SELECTED;
628
629                                 Mat3CpyMat3(td->smtx, smtx);
630                                 Mat3CpyMat3(td->mtx, mtx);
631
632                                 td->ext = NULL;
633                                 td->tdi = NULL;
634                                 td->val = NULL;
635
636                                 td++;
637                         }
638                         if (ebo->flag & BONE_ROOTSEL){
639                                 VECCOPY (td->iloc, ebo->head);
640                                 VECCOPY (td->center, td->iloc);
641                                 td->loc= ebo->head;
642                                 td->flag= TD_SELECTED;
643
644                                 Mat3CpyMat3(td->smtx, smtx);
645                                 Mat3CpyMat3(td->mtx, mtx);
646
647                                 td->ext = NULL;
648                                 td->tdi = NULL;
649                                 td->val = NULL;
650
651                                 td++;
652                         }
653                 }
654         }
655 }
656
657 /* ********************* meta elements ********* */
658
659 static void createTransMBallVerts(TransInfo *t)
660 {
661         MetaElem *ml;
662         TransData *td;
663         TransDataExtension *tx;
664         float mtx[3][3], smtx[3][3];
665         int count=0, countsel=0;
666         int propmode = t->flag & T_PROP_EDIT;
667
668         /* count totals */
669         for(ml= editelems.first; ml; ml= ml->next) {
670                 if(ml->flag & SELECT) countsel++;
671                 if(propmode) count++;
672         }
673
674         /* note: in prop mode we need at least 1 selected */
675         if (countsel==0) return;
676         
677         if(propmode) t->total = count; 
678         else t->total = countsel;
679         
680         td = t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
681         tx = t->ext = MEM_mallocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
682
683         Mat3CpyMat4(mtx, G.obedit->obmat);
684         Mat3Inv(smtx, mtx);
685     
686         for(ml= editelems.first; ml; ml= ml->next) {
687                 if(propmode || (ml->flag & SELECT)) {
688                         td->loc= &ml->x;
689                         VECCOPY(td->iloc, td->loc);
690                         VECCOPY(td->center, td->loc);
691
692                         if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
693                         else td->flag= TD_USEQUAT;
694
695                         Mat3CpyMat3(td->smtx, smtx);
696                         Mat3CpyMat3(td->mtx, mtx);
697
698                         td->ext = tx;
699                         td->tdi = NULL;
700
701                         /* Radius of MetaElem (mass of MetaElem influence) */
702                         if(ml->flag & MB_SCALE_RAD){
703                                 td->val = &ml->rad;
704                                 td->ival = ml->rad;
705                         }
706                         else{
707                                 td->val = &ml->s;
708                                 td->ival = ml->s;
709                         }
710
711                         /* expx/expy/expz determine "shape" of some MetaElem types */
712                         tx->size = &ml->expx;
713                         tx->isize[0] = ml->expx;
714                         tx->isize[1] = ml->expy;
715                         tx->isize[2] = ml->expz;
716
717                         /* quat is used for rotation of MetaElem */
718                         tx->quat = ml->quat;
719                         QUATCOPY(tx->iquat, ml->quat);
720
721                         tx->rot = NULL;
722
723                         td++;
724                         tx++;
725                 }
726         }
727
728
729 /* ********************* curve/surface ********* */
730
731 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
732         TransData *td, *td_near = NULL;
733         for (td = head; td<=tail; td++) {
734                 if (td->flag & TD_SELECTED) {
735                         td_near = td;
736                         td->dist = 0.0f;
737                 }
738                 else if(td_near) {
739                         float dist;
740                         dist = VecLenf(td_near->center, td->center);
741                         if (dist < (td-1)->dist) {
742                                 td->dist = (td-1)->dist;
743                         }
744                         else {
745                                 td->dist = dist;
746                         }
747                 }
748                 else {
749                         td->dist = MAXFLOAT;
750                         td->flag |= TD_NOTCONNECTED;
751                 }
752         }
753         td_near = NULL;
754         for (td = tail; td>=head; td--) {
755                 if (td->flag & TD_SELECTED) {
756                         td_near = td;
757                         td->dist = 0.0f;
758                 }
759                 else if(td_near) {
760                         float dist;
761                         dist = VecLenf(td_near->center, td->center);
762                         if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
763                                 td->flag &= ~TD_NOTCONNECTED;
764                                 if (dist < (td+1)->dist) {
765                                         td->dist = (td+1)->dist;
766                                 }
767                                 else {
768                                         td->dist = dist;
769                                 }
770                         }
771                 }
772         }
773 }
774
775 static void createTransCurveVerts(TransInfo *t)
776 {
777         TransData *td = NULL;
778         Nurb *nu;
779         BezTriple *bezt;
780         BPoint *bp;
781         float mtx[3][3], smtx[3][3];
782         int a;
783         int count=0, countsel=0;
784         int propmode = t->flag & T_PROP_EDIT;
785
786         /* count total of vertices, check identical as in 2nd loop for making transdata! */
787         for(nu= editNurb.first; nu; nu= nu->next) {
788                 if((nu->type & 7)==CU_BEZIER) {
789                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
790                                 if(bezt->hide==0) {
791                                         if(bezt->f1 & 1) countsel++;
792                                         if(bezt->f2 & 1) countsel++;
793                                         if(bezt->f3 & 1) countsel++;
794                                         if(propmode) count+= 3;
795                                 }
796                         }
797                 }
798                 else {
799                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
800                                 if(bp->hide==0) {
801                                         if(propmode) count++;
802                                         if(bp->f1 & 1) countsel++;
803                                 }
804                         }
805                 }
806         }
807         /* note: in prop mode we need at least 1 selected */
808         if (countsel==0) return;
809         
810         if(propmode) t->total = count; 
811         else t->total = countsel;
812         t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
813
814         Mat3CpyMat4(mtx, G.obedit->obmat);
815         Mat3Inv(smtx, mtx);
816
817     td = t->data;
818         for(nu= editNurb.first; nu; nu= nu->next) {
819                 if((nu->type & 7)==CU_BEZIER) {
820                         TransData *head, *tail;
821                         head = tail = td;
822                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
823                                 if(bezt->hide==0) {
824                                         if(propmode || (bezt->f1 & 1)) {
825                                                 VECCOPY(td->iloc, bezt->vec[0]);
826                                                 td->loc= bezt->vec[0];
827                                                 VECCOPY(td->center, bezt->vec[1]);
828                                                 if(bezt->f1 & 1) td->flag= TD_SELECTED;
829                                                 else td->flag= 0;
830                                                 td->ext = NULL;
831                                                 td->tdi = NULL;
832                                                 td->val = NULL;
833
834                                                 Mat3CpyMat3(td->smtx, smtx);
835                                                 Mat3CpyMat3(td->mtx, mtx);
836
837                                                 td++;
838                                                 count++;
839                                                 tail++;
840                                         }
841                                         /* THIS IS THE CV, the other two are handles */
842                                         if(propmode || (bezt->f2 & 1)) {
843                                                 VECCOPY(td->iloc, bezt->vec[1]);
844                                                 td->loc= bezt->vec[1];
845                                                 VECCOPY(td->center, td->loc);
846                                                 if(bezt->f2 & 1) td->flag= TD_SELECTED;
847                                                 else td->flag= 0;
848                                                 td->ext = NULL;
849                                                 td->tdi = NULL;
850                                                 td->val = &(bezt->alfa);
851                                                 td->ival = bezt->alfa;
852
853                                                 Mat3CpyMat3(td->smtx, smtx);
854                                                 Mat3CpyMat3(td->mtx, mtx);
855
856                                                 td++;
857                                                 count++;
858                                                 tail++;
859                                         }
860                                         if(propmode || (bezt->f3 & 1)) {
861                                                 VECCOPY(td->iloc, bezt->vec[2]);
862                                                 td->loc= bezt->vec[2];
863                                                 VECCOPY(td->center, bezt->vec[1]);
864                                                 if(bezt->f3 & 1) td->flag= TD_SELECTED;
865                                                 else td->flag= 0;
866                                                 td->ext = NULL;
867                                                 td->tdi = NULL;
868                                                 td->val = NULL;
869
870                                                 Mat3CpyMat3(td->smtx, smtx);
871                                                 Mat3CpyMat3(td->mtx, mtx);
872
873                                                 td++;
874                                                 count++;
875                                                 tail++;
876                                         }
877                                 }
878                                 else if (propmode && head != tail) {
879                                         calc_distanceCurveVerts(head, tail-1);
880                                         head = tail;
881                                 }
882                         }
883                         if (propmode && head != tail)
884                                 calc_distanceCurveVerts(head, tail-1);
885                 }
886                 else {
887                         TransData *head, *tail;
888                         head = tail = td;
889                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
890                                 if(bp->hide==0) {
891                                         if(propmode || (bp->f1 & 1)) {
892                                                 VECCOPY(td->iloc, bp->vec);
893                                                 td->loc= bp->vec;
894                                                 VECCOPY(td->center, td->loc);
895                                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
896                                                 else td->flag= 0;
897                                                 td->ext = NULL;
898                                                 td->tdi = NULL;
899                                                 td->val = &(bp->alfa);
900                                                 td->ival = bp->alfa;
901
902                                                 Mat3CpyMat3(td->smtx, smtx);
903                                                 Mat3CpyMat3(td->mtx, mtx);
904
905                                                 td++;
906                                                 count++;
907                                                 tail++;
908                                         }
909                                 }
910                                 else if (propmode && head != tail) {
911                                         calc_distanceCurveVerts(head, tail-1);
912                                         head = tail;
913                                 }
914                         }
915                         if (propmode && head != tail)
916                                 calc_distanceCurveVerts(head, tail-1);
917                 }
918         }
919 }
920
921 /* ********************* lattice *************** */
922
923 static void createTransLatticeVerts(TransInfo *t)
924 {
925         TransData *td = NULL;
926         BPoint *bp;
927         float mtx[3][3], smtx[3][3];
928         int a;
929         int count=0, countsel=0;
930         int propmode = t->flag & T_PROP_EDIT;
931
932         bp= editLatt->def;
933         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
934         while(a--) {
935                 if(bp->f1 & 1) countsel++;
936                 if(propmode) count++;
937                 bp++;
938         }
939         
940         /* note: in prop mode we need at least 1 selected */
941         if (countsel==0) return;
942         
943         if(propmode) t->total = count; 
944         else t->total = countsel;
945         t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
946         
947         Mat3CpyMat4(mtx, G.obedit->obmat);
948         Mat3Inv(smtx, mtx);
949
950         td = t->data;
951         bp= editLatt->def;
952         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
953         while(a--) {
954                 if(propmode || (bp->f1 & 1)) {
955                         if(bp->hide==0) {
956                                 VECCOPY(td->iloc, bp->vec);
957                                 td->loc= bp->vec;
958                                 VECCOPY(td->center, td->loc);
959                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
960                                 else td->flag= 0;
961                                 Mat3CpyMat3(td->smtx, smtx);
962                                 Mat3CpyMat3(td->mtx, mtx);
963
964                                 td->ext = NULL;
965                                 td->tdi = NULL;
966                                 td->val = NULL;
967
968                                 td++;
969                                 count++;
970                         }
971                 }
972                 bp++;
973         }
974
975
976 /* ********************* mesh ****************** */
977
978 /* proportional distance based on connectivity  */
979 #define E_VEC(a)        (vectors + (3 * (int)(a)->vn))
980 #define E_NEAR(a)       (nears[((int)(a)->vn)])
981 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
982 {
983         EditMesh *em = G.editMesh;
984         EditVert *eve;
985         EditEdge *eed;
986         int i= 0, done= 1;
987
988         /* f2 flag is used for 'selection' */
989         /* vn is offset on scratch array   */
990         for(eve= em->verts.first; eve; eve= eve->next) {
991                 if(eve->h==0) {
992                         eve->vn = (EditVert *)(i++);
993
994                         if(eve->f & SELECT) {
995                                 eve->f2= 2;
996                                 E_NEAR(eve) = eve;
997                                 E_VEC(eve)[0] = 0.0f;
998                                 E_VEC(eve)[1] = 0.0f;
999                                 E_VEC(eve)[2] = 0.0f;
1000                         }
1001                         else {
1002                                 eve->f2 = 0;
1003                         }
1004                 }
1005         }
1006
1007
1008         /* Floodfill routine */
1009         /*
1010         At worst this is n*n of complexity where n is number of edges 
1011         Best case would be n if the list is ordered perfectly.
1012         Estimate is n log n in average (so not too bad)
1013         */
1014         while(done) {
1015                 done= 0;
1016                 
1017                 for(eed= em->edges.first; eed; eed= eed->next) {
1018                         if(eed->h==0) {
1019                                 EditVert *v1= eed->v1, *v2= eed->v2;
1020                                 float *vec2 = E_VEC(v2);
1021                                 float *vec1 = E_VEC(v1);
1022
1023                                 if (v1->f2 + v2->f2 == 4)
1024                                         continue;
1025
1026                                 if (v1->f2) {
1027                                         if (v2->f2) {
1028                                                 float nvec[3];
1029                                                 float len1 = VecLength(vec1);
1030                                                 float len2 = VecLength(vec2);
1031                                                 float lenn;
1032                                                 /* for v2 if not selected */
1033                                                 if (v2->f2 != 2) {
1034                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1035                                                         lenn = VecLength(nvec);
1036                                                         if (lenn - len1 > 0.00001f && len2 - lenn > 0.00001f) {
1037                                                                 VECCOPY(vec2, nvec);
1038                                                                 E_NEAR(v2) = E_NEAR(v1);
1039                                                                 done = 1;
1040                                                         }
1041                                                         else if (len2 - len1 > 0.00001f && len1 - lenn > 0.00001f) {
1042                                                                 VECCOPY(vec2, vec1);
1043                                                                 E_NEAR(v2) = E_NEAR(v1);
1044                                                                 done = 1;
1045                                                         }
1046                                                 }
1047                                                 /* for v1 if not selected */
1048                                                 if (v1->f2 != 2) {
1049                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1050                                                         lenn = VecLength(nvec);
1051                                                         if (lenn - len2 > 0.00001f && len1 - lenn > 0.00001f) {
1052                                                                 VECCOPY(vec1, nvec);
1053                                                                 E_NEAR(v1) = E_NEAR(v2);
1054                                                                 done = 1;
1055                                                         }
1056                                                         else if (len1 - len2 > 0.00001f && len2 - lenn > 0.00001f) {
1057                                                                 VECCOPY(vec1, vec2);
1058                                                                 E_NEAR(v1) = E_NEAR(v2);
1059                                                                 done = 1;
1060                                                         }
1061                                                 }
1062                                         }
1063                                         else {
1064                                                 v2->f2 = 1;
1065                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1066                                                 if (VecLength(vec1) - VecLength(vec2) > 0.00001f) {
1067                                                         VECCOPY(vec2, vec1);
1068                                                 }
1069                                                 E_NEAR(v2) = E_NEAR(v1);
1070                                                 done = 1;
1071                                         }
1072                                 }
1073                                 else if (v2->f2) {
1074                                         v1->f2 = 1;
1075                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1076                                         if (VecLength(vec2) - VecLength(vec1) > 0.00001f) {
1077                                                 VECCOPY(vec1, vec2);
1078                                         }
1079                                         E_NEAR(v1) = E_NEAR(v2);
1080                                         done = 1;
1081                                 }
1082                         }
1083                 }
1084         }
1085 }
1086
1087 static void VertsToTransData(TransData *td, EditVert *eve)
1088 {
1089         td->flag = 0;
1090         td->loc = eve->co;
1091         VECCOPY(td->center, td->loc);
1092         VECCOPY(td->iloc, td->loc);
1093
1094         // Setting normals
1095         VECCOPY(td->axismtx[2], eve->no);
1096         td->axismtx[0][0]               =
1097                 td->axismtx[0][1]       =
1098                 td->axismtx[0][2]       =
1099                 td->axismtx[1][0]       =
1100                 td->axismtx[1][1]       =
1101                 td->axismtx[1][2]       = 0.0f;
1102
1103         td->ext = NULL;
1104         td->tdi = NULL;
1105         td->val = NULL;
1106 }
1107
1108 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1109 {
1110         float *vec = userData;
1111         
1112         vec+= 3*index;
1113         VECCOPY(vec, co);
1114 }
1115
1116 static float *get_mapped_editverts(void)
1117 {
1118         int needsFree;
1119         DerivedMesh *dm= editmesh_get_derived_cage(&needsFree);
1120         float *vertexcos;
1121         
1122         vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1123         
1124         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1125         
1126         if (needsFree) dm->release(dm);
1127         return vertexcos;
1128 }
1129
1130 /* helper for below, interpolates or assigns and increments */
1131 static float *crazy_quat_blend(EditVert *eve, float *quat)
1132 {
1133         if(eve->vn==NULL) {
1134                 eve->vn= (EditVert *)quat;
1135                 QUATCOPY(quat+4, quat);
1136                 return quat+4;
1137         }
1138         else {
1139                 float *q1= (float *)eve->vn;
1140                 QuatInterpol(q1, q1, quat, 0.5f);
1141                 return quat;
1142         }
1143 }
1144
1145 static void set_crazyspace_quats(float *mappedcos, float *quats)
1146 {
1147         EditMesh *em = G.editMesh;
1148         EditVert *eve, *prev;
1149         EditFace *efa;
1150         float q1[4], q2[4];
1151         float *v1, *v2, *v3, *quatp;
1152         int index= 0;
1153         
1154         /* 2 abused locations in vertices */
1155         for(eve= em->verts.first; eve; eve= eve->next, index++) {
1156                 eve->vn= NULL;
1157                 eve->prev= (EditVert *)index;
1158         }
1159         
1160         quatp= quats;
1161         for(efa= em->faces.first; efa; efa= efa->next) {
1162                 /* vertex f1 flags were set for transform */
1163                 
1164                 if( (efa->v1->f1 && efa->v1->vn==NULL) || (efa->v2->f1 && efa->v2->vn==NULL)
1165                         || (efa->v3->f1 && efa->v3->vn==NULL) || (efa->v4 && efa->v4->f1 && efa->v4->vn==NULL) ) {
1166                 
1167                         triatoquat(efa->v1->co, efa->v2->co, efa->v3->co, q1);
1168                         
1169                         /* retrieve mapped coordinates */
1170                         v1= mappedcos + 3*( (int)(efa->v1->prev) );
1171                         v2= mappedcos + 3*( (int)(efa->v2->prev) );
1172                         v3= mappedcos + 3*( (int)(efa->v3->prev) );
1173                         triatoquat(v1, v2, v3, q2);
1174                         
1175                         QuatSub(quatp, q2, q1);
1176                         
1177                         if(efa->v1->f1) quatp= crazy_quat_blend(efa->v1, quatp);
1178                         if(efa->v2->f1) quatp= crazy_quat_blend(efa->v2, quatp);
1179                         if(efa->v3->f1) quatp= crazy_quat_blend(efa->v3, quatp);
1180                         if(efa->v4 && efa->v4->f1) quatp= crazy_quat_blend(efa->v4, quatp);
1181                 }
1182         }
1183
1184         /* restore abused prev pointer */
1185         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1186                 eve->prev= prev;
1187
1188 }
1189
1190 static void createTransEditVerts(TransInfo *t)
1191 {
1192         TransData *tob = NULL;
1193         EditMesh *em = G.editMesh;
1194         EditVert *eve;
1195         EditVert **nears = NULL;
1196         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1197         float mtx[3][3], smtx[3][3];
1198         int count=0, countsel=0;
1199         int propmode = t->flag & T_PROP_EDIT;
1200                 
1201         // transform now requires awareness for select mode, so we tag the f1 flags in verts
1202         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1203                 for(eve= em->verts.first; eve; eve= eve->next) {
1204                         if(eve->h==0 && (eve->f & SELECT)) 
1205                                 eve->f1= SELECT;
1206                         else
1207                                 eve->f1= 0;
1208                 }
1209         }
1210         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1211                 EditEdge *eed;
1212                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1213                 for(eed= em->edges.first; eed; eed= eed->next) {
1214                         if(eed->h==0 && (eed->f & SELECT))
1215                                 eed->v1->f1= eed->v2->f1= SELECT;
1216                 }
1217         }
1218         else {
1219                 EditFace *efa;
1220                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1221                 for(efa= em->faces.first; efa; efa= efa->next) {
1222                         if(efa->h==0 && (efa->f & SELECT)) {
1223                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1224                                 if(efa->v4) efa->v4->f1= SELECT;
1225                         }
1226                 }
1227         }
1228         
1229         /* now we can count */
1230         for(eve= em->verts.first; eve; eve= eve->next) {
1231                 if(eve->h==0) {
1232                         if(eve->f1) countsel++;
1233                         if(propmode) count++;
1234                 }
1235         }
1236         
1237         /* note: in prop mode we need at least 1 selected */
1238         if (countsel==0) return;
1239         
1240         if(propmode) {
1241                 t->total = count; 
1242         
1243                 /* allocating scratch arrays */
1244                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1245                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1246         }
1247         else t->total = countsel;
1248         tob= t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1249         
1250         Mat3CpyMat4(mtx, G.obedit->obmat);
1251         Mat3Inv(smtx, mtx);
1252
1253         if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1254         
1255         /* detect CrazySpace [tm] */
1256         if(propmode==0) {
1257                 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
1258                         if(modifiers_isDeformed(G.obedit)) {
1259                                 mappedcos= get_mapped_editverts();
1260                                 /* add one more quaternion, because of crazy_quat_blend */
1261                                 quats= MEM_mallocN( (t->total+1)*sizeof(float)*4, "crazy quats");
1262                                 set_crazyspace_quats(mappedcos, quats);
1263                         }
1264                 }
1265         }
1266         
1267         for (eve=em->verts.first; eve; eve=eve->next) {
1268                 if(eve->h==0) {
1269                         if(propmode || eve->f1) {
1270                                 VertsToTransData(tob, eve);
1271
1272                                 if(eve->f1) tob->flag |= TD_SELECTED;
1273                                 if(propmode) {
1274                                         if (eve->f2) {
1275                                                 float vec[3];
1276                                                 VECCOPY(vec, E_VEC(eve));
1277                                                 Mat3MulVecfl(mtx, vec);
1278                                                 tob->dist= VecLength(vec);
1279                                         }
1280                                         else {
1281                                                 tob->flag |= TD_NOTCONNECTED;
1282                                                 tob->dist = MAXFLOAT;
1283                                         }
1284                                 }
1285                                 
1286                                 /* CrazySpace */
1287                                 if(quats && eve->vn) {
1288                                         float mat[3][3], imat[3][3], qmat[3][3];
1289                                         
1290                                         QuatToMat3((float *)eve->vn, qmat);
1291                                         Mat3MulMat3(mat, mtx, qmat);
1292                                         Mat3Inv(imat, mat);
1293                                         
1294                                         Mat3CpyMat3(tob->smtx, imat);
1295                                         Mat3CpyMat3(tob->mtx, mat);
1296                                 }
1297                                 else {
1298                                         Mat3CpyMat3(tob->smtx, smtx);
1299                                         Mat3CpyMat3(tob->mtx, mtx);
1300                                 }
1301                                 tob++;
1302                         }
1303                 }       
1304         }
1305         if (propmode) {
1306                 MEM_freeN(vectors);
1307                 MEM_freeN(nears);
1308         }
1309         /* crazy space free */
1310         if(mappedcos)
1311                 MEM_freeN(mappedcos);
1312         if(quats)
1313                 MEM_freeN(quats);
1314 }
1315
1316 /* ********************* UV ****************** */
1317
1318 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
1319 {
1320         float aspx, aspy;
1321
1322         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1323
1324         /* uv coords are scaled by aspects. this is needed for rotations and
1325            proportional editing to be consistent with the stretchted uv coords
1326            that are displayed. this also means that for display and numinput,
1327            and when the the uv coords are flushed, these are converted each time */
1328         td2d->loc[0] = uv[0]*aspx;
1329         td2d->loc[1] = uv[1]*aspy;
1330         td2d->loc[2] = 0.0f;
1331         td2d->loc2d = uv;
1332
1333         td->flag = 0;
1334         td->loc = td2d->loc;
1335         VECCOPY(td->center, td->loc);
1336         VECCOPY(td->iloc, td->loc);
1337
1338         memset(td->axismtx, 0, sizeof(td->axismtx));
1339         td->axismtx[2][2] = 1.0f;
1340
1341         td->ext= NULL; td->tdi= NULL; td->val= NULL;
1342
1343         if(selected) {
1344                 td->flag |= TD_SELECTED;
1345                 td->dist= 0.0;
1346         }
1347         else
1348                 td->dist= MAXFLOAT;
1349         
1350         Mat3One(td->mtx);
1351         Mat3One(td->smtx);
1352 }
1353
1354 static void createTransUVs(TransInfo *t)
1355 {
1356         TransData *td = NULL;
1357         TransData2D *td2d = NULL;
1358         Mesh *me;
1359         TFace *tf;
1360         MFace *mf;
1361         int a, count=0, countsel=0;
1362         int propmode = t->flag & T_PROP_EDIT;
1363         
1364         if(is_uv_tface_editing_allowed()==0) return;
1365         me= get_mesh(OBACT);
1366
1367         /* count */
1368         tf= me->tface;
1369         mf= me->mface;
1370         for(a=me->totface; a>0; a--, tf++, mf++) {
1371                 if(mf->v3 && tf->flag & TF_SELECT) {
1372                         if(tf->flag & TF_SEL1) countsel++;
1373                         if(tf->flag & TF_SEL2) countsel++;
1374                         if(tf->flag & TF_SEL3) countsel++;
1375                         if(mf->v4 && (tf->flag & TF_SEL4)) countsel++;
1376                         if(propmode)
1377                                 count += (mf->v4)? 4: 3;
1378                 }
1379         }
1380
1381         /* note: in prop mode we need at least 1 selected */
1382         if (countsel==0) return;
1383         
1384         t->total= (propmode)? count: countsel;
1385         t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
1386         /* for each 2d uv coord a 3d vector is allocated, so that they can be
1387            treated just as if they were 3d verts */
1388         t->data2d= MEM_mallocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
1389
1390         if(G.sima->flag & SI_CLIP_UV)
1391                 t->flag |= T_CLIP_UV;
1392
1393         td= t->data;
1394         td2d= t->data2d;
1395         tf= me->tface;
1396         mf= me->mface;
1397         for(a=me->totface; a>0; a--, tf++, mf++) {
1398                 if(mf->v3 && tf->flag & TF_SELECT) {
1399                         if(tf->flag & TF_SEL1 || propmode)
1400                                 UVsToTransData(td++, td2d++, tf->uv[0], (tf->flag & TF_SEL1));
1401                         if(tf->flag & TF_SEL2 || propmode)
1402                                 UVsToTransData(td++, td2d++, tf->uv[1], (tf->flag & TF_SEL2));
1403                         if(tf->flag & TF_SEL3 || propmode)
1404                                 UVsToTransData(td++, td2d++, tf->uv[2], (tf->flag & TF_SEL3));
1405
1406                         if(mf->v4 && (tf->flag & TF_SEL4 || propmode))
1407                                 UVsToTransData(td++, td2d++, tf->uv[3], (tf->flag & TF_SEL4));
1408                 }
1409         }
1410 }
1411
1412 void flushTransUVs(TransInfo *t)
1413 {
1414         TransData2D *td;
1415         int a, width, height;
1416         Object *ob= OBACT;
1417         Mesh *me= get_mesh(ob);
1418         float aspx, aspy, invx, invy;
1419
1420         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1421         transform_width_height_tface_uv(&width, &height);
1422         invx= 1.0f/aspx;
1423         invy= 1.0f/aspy;
1424
1425         /* flush to 2d vector from internally used 3d vector */
1426         for(a=0, td= t->data2d; a<t->total; a++, td++) {
1427                 td->loc2d[0]= td->loc[0]*invx;
1428                 td->loc2d[1]= td->loc[1]*invy;
1429                 
1430                 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
1431                         td->loc2d[0]= floor(width*td->loc2d[0])/width;
1432                         td->loc2d[1]= floor(height*td->loc2d[1])/height;
1433                 }
1434         }
1435
1436         if((G.sima->flag & SI_BE_SQUARE) && (t->state != TRANS_CANCEL))
1437                 be_square_tface_uv(me);
1438
1439         /* this is overkill if G.sima->lock is not set, but still needed */
1440         object_uvs_changed(ob);
1441 }
1442
1443 int clipUVTransform(TransInfo *t, float *vec, int resize)
1444 {
1445         TransData *td;
1446         int a, clipx=1, clipy=1;
1447         float aspx, aspy, min[2], max[2];
1448
1449         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1450         min[0]= min[1]= 0.0f;
1451         max[0]= aspx; max[1]= aspy;
1452
1453         for(a=0, td= t->data; a<t->total; a++, td++) {
1454                 DO_MINMAX2(td->loc, min, max);
1455         }
1456
1457         if(resize) {
1458                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
1459                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
1460                 else if(max[0] > aspx && t->center[0] < aspx)
1461                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
1462                 else
1463                         clipx= 0;
1464
1465                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
1466                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
1467                 else if(max[1] > aspy && t->center[1] < aspy)
1468                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
1469                 else
1470                         clipy= 0;
1471         }
1472         else {
1473                 if(min[0] < 0.0f)
1474                         vec[0] -= min[0];
1475                 else if(max[0] > aspx)
1476                         vec[0] -= max[0]-aspx;
1477                 else
1478                         clipx= 0;
1479
1480                 if(min[1] < 0.0f)
1481                         vec[1] -= min[1];
1482                 else if(max[1] > aspy)
1483                         vec[1] -= max[1]-aspy;
1484                 else
1485                         clipy= 0;
1486         }       
1487
1488         return (clipx || clipy);
1489 }
1490
1491 /* **************** IpoKey stuff, for Object TransData ********** */
1492
1493 /* storage of bezier triple. thats why -3 and +3! */
1494 static void set_tdi_old(float *old, float *poin)
1495 {
1496         old[0]= *(poin);
1497         old[3]= *(poin-3);
1498         old[6]= *(poin+3);
1499 }
1500
1501 /* while transforming */
1502 void add_tdi_poin(float *poin, float *old, float delta)
1503 {
1504         if(poin) {
1505                 poin[0]= old[0]+delta;
1506                 poin[-3]= old[3]+delta;
1507                 poin[3]= old[6]+delta;
1508         }
1509 }
1510
1511 /* fill ipokey transdata with old vals and pointers */
1512 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
1513 {
1514         extern int ob_ar[];             // blenkernel ipo.c
1515         TransDataIpokey *tdi= td->tdi;
1516         BezTriple *bezt;
1517         int a, delta= 0;
1518         
1519         td->val= NULL;  // is read on ESC
1520         
1521         for(a=0; a<OB_TOTIPO; a++) {
1522                 if(ik->data[a]) {
1523                         bezt= ik->data[a];
1524                         
1525                         switch( ob_ar[a] ) {
1526                                 case OB_LOC_X:
1527                                 case OB_DLOC_X:
1528                                         tdi->locx= &(bezt->vec[1][1]); break;
1529                                 case OB_LOC_Y:
1530                                 case OB_DLOC_Y:
1531                                         tdi->locy= &(bezt->vec[1][1]); break;
1532                                 case OB_LOC_Z:
1533                                 case OB_DLOC_Z:
1534                                         tdi->locz= &(bezt->vec[1][1]); break;
1535                                         
1536                                 case OB_DROT_X:
1537                                         delta= 1;
1538                                 case OB_ROT_X:
1539                                         tdi->rotx= &(bezt->vec[1][1]); break;
1540                                 case OB_DROT_Y:
1541                                         delta= 1;
1542                                 case OB_ROT_Y:
1543                                         tdi->roty= &(bezt->vec[1][1]); break;
1544                                 case OB_DROT_Z:
1545                                         delta= 1;
1546                                 case OB_ROT_Z:
1547                                         tdi->rotz= &(bezt->vec[1][1]); break;
1548                                         
1549                                 case OB_SIZE_X:
1550                                 case OB_DSIZE_X:
1551                                         tdi->sizex= &(bezt->vec[1][1]); break;
1552                                 case OB_SIZE_Y:
1553                                 case OB_DSIZE_Y:
1554                                         tdi->sizey= &(bezt->vec[1][1]); break;
1555                                 case OB_SIZE_Z:
1556                                 case OB_DSIZE_Z:
1557                                         tdi->sizez= &(bezt->vec[1][1]); break;          
1558                         }       
1559                 }
1560         }
1561         
1562         /* oldvals for e.g. undo */
1563         if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
1564         if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
1565         if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
1566         
1567         /* remember, for mapping curves ('1'=10 degrees)  */
1568         if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
1569         if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
1570         if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
1571         
1572         /* this is not allowed to be dsize! */
1573         if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
1574         if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
1575         if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
1576         
1577         tdi->flag= TOB_IPO;
1578         if(delta) tdi->flag |= TOB_IPODROT;
1579 }
1580
1581
1582 /* *************************** Object Transform data ******************* */
1583
1584 static void ObjectToTransData(TransData *td, Object *ob) 
1585 {
1586         float obmtx[3][3];
1587         Object *tr;
1588         void *cfirst, *clast;
1589
1590         /* set axismtx BEFORE clearing constraints to have the real orientation */
1591         Mat3CpyMat4(td->axismtx, ob->obmat);
1592         Mat3Ortho(td->axismtx);
1593
1594         /* then why are constraints and track disabled here? 
1595                 they dont alter loc/rot/size itself (ton) */
1596         cfirst = ob->constraints.first;
1597         clast = ob->constraints.last;
1598         ob->constraints.first=ob->constraints.last=NULL;
1599
1600         tr= ob->track;
1601         ob->track= NULL;
1602
1603         where_is_object(ob);
1604
1605         ob->track= tr;
1606
1607         ob->constraints.first = cfirst;
1608         ob->constraints.last = clast;
1609
1610         td->ob = ob;
1611
1612         td->loc = ob->loc;
1613         VECCOPY(td->iloc, td->loc);
1614         
1615         td->ext->rot = ob->rot;
1616         VECCOPY(td->ext->irot, ob->rot);
1617         VECCOPY(td->ext->drot, ob->drot);
1618         
1619         td->ext->size = ob->size;
1620         VECCOPY(td->ext->isize, ob->size);
1621         VECCOPY(td->ext->dsize, ob->dsize);
1622
1623         VECCOPY(td->center, ob->obmat[3]);
1624
1625         if (ob->parent)
1626         {
1627                 float totmat[3][3], obinv[3][3];
1628                 
1629                 /* we calculate smtx without obmat: so a parmat */
1630                 object_to_mat3(ob, obmtx);
1631                 Mat3CpyMat4(totmat, ob->obmat);
1632                 Mat3Inv(obinv, totmat);
1633                 Mat3MulMat3(td->smtx, obmtx, obinv);
1634                 Mat3Inv(td->mtx, td->smtx);
1635         }
1636         else
1637         {
1638                 Mat3One(td->smtx);
1639                 Mat3One(td->mtx);
1640         }
1641 }
1642
1643
1644 /* sets flags in Bases to define whether they take part in transform */
1645 /* it deselects Bases, so we have to call the clear function always after */
1646 static void set_trans_object_base_flags(TransInfo *t)
1647 {
1648         /*
1649          if Base selected and has parent selected:
1650          base->flag= BA_WAS_SEL
1651          */
1652         Base *base;
1653         
1654         /* makes sure base flags and object flags are identical */
1655         copy_baseflags();
1656         
1657         /* handle pending update events, otherwise they got copied below */
1658         for (base= FIRSTBASE; base; base= base->next) {
1659                 if(base->object->recalc) 
1660                         object_handle_update(base->object);
1661         }
1662         
1663         for (base= FIRSTBASE; base; base= base->next) {
1664                 base->flag &= ~BA_WAS_SEL;
1665                 
1666                 if(TESTBASELIB(base)) {
1667                         Object *ob= base->object;
1668                         Object *parsel= ob->parent;
1669                         
1670                         /* if parent selected, deselect */
1671                         while(parsel) {
1672                                 if(parsel->flag & SELECT) break;
1673                                 parsel= parsel->parent;
1674                         }
1675                         
1676                         if(parsel) {
1677                                 base->flag &= ~SELECT;
1678                                 base->flag |= BA_WAS_SEL;
1679                         }
1680                         /* used for flush, depgraph will change recalcs if needed :) */
1681                         ob->recalc |= OB_RECALC_OB;
1682                 }
1683         }
1684         /* all recalc flags get flushed */
1685         DAG_scene_flush_update(G.scene, screen_view3d_layers());
1686         
1687         /* and we store them temporal in base (only used for transform code) */
1688         /* this because after doing updates, the object->recalc is cleared */
1689         for (base= FIRSTBASE; base; base= base->next) {
1690                 if(base->object->recalc & OB_RECALC_OB)
1691                         base->flag |= BA_HAS_RECALC_OB;
1692                 if(base->object->recalc & OB_RECALC_DATA)
1693                         base->flag |= BA_HAS_RECALC_DATA;
1694         }
1695 }
1696
1697 static void clear_trans_object_base_flags(void)
1698 {
1699         Base *base;
1700         
1701         base= FIRSTBASE;
1702         while(base) {
1703                 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
1704                 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
1705                 
1706                 base = base->next;
1707         }
1708 }
1709
1710 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
1711 /* note; transdata has been freed already! */
1712 void special_aftertrans_update(TransInfo *t)
1713 {
1714         Object *ob;
1715         Base *base;
1716         int redrawipo=0;
1717         int cancelled= (t->state == TRANS_CANCEL);
1718                 
1719         if(G.obedit) {
1720                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
1721                         allqueue(REDRAWBUTSEDIT, 0);
1722         }
1723         else if( (t->flag & T_POSE) && t->poseobj) {
1724                 bArmature *arm;
1725                 bAction *act;
1726                 bPose   *pose;
1727                 bPoseChannel *pchan;
1728
1729                 ob= t->poseobj;
1730                 arm= ob->data;
1731                 
1732                 /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
1733                 ob->pose->flag |= POSE_DO_UNLOCK;
1734                 
1735                 if(G.flags & G_RECORDKEYS) {
1736                         act= ob->action;
1737                         pose= ob->pose;
1738                         
1739                         if (!act)
1740                                 act= ob->action= add_empty_action(ID_PO);
1741                         
1742                         set_pose_keys(ob);  // sets chan->flag to POSE_KEY if bone selected
1743                         for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
1744                                 if (pchan->flag & POSE_KEY){
1745                                         
1746                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
1747                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
1748                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
1749                                         
1750                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
1751                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
1752                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
1753                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
1754                                         
1755                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
1756                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
1757                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
1758                                 }
1759                         }
1760                         
1761                         remake_action_ipos (act);
1762                         allspace(REMAKEIPO, 0);
1763                         allqueue(REDRAWACTION, 0);
1764                         allqueue(REDRAWIPO, 0);
1765                         allqueue(REDRAWNLA, 0);
1766                         
1767                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1768                 }
1769                 else if(arm->flag & ARM_DELAYDEFORM) {
1770                         /* old optimize trick... this enforces to bypass the depgraph */
1771                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1772                         ob->recalc= 0;  // is set on OK position already by recalcData()
1773                 }
1774                 else 
1775                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1776                 
1777                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
1778                         allqueue(REDRAWBUTSEDIT, 0);
1779
1780         }
1781         else {
1782                 base= FIRSTBASE;
1783                 while(base) {   
1784                         
1785                         if(base->flag & BA_DO_IPO) redrawipo= 1;
1786                         
1787                         ob= base->object;
1788
1789                         if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
1790                         
1791                         /* Set autokey if necessary */
1792                         if ((G.flags & G_RECORDKEYS) && (!cancelled) && (base->flag & SELECT)){
1793                                 /* note, here we have to do context still */
1794                                 insertkey(&base->object->id, ID_OB, NULL, NULL, OB_ROT_X);
1795                                 insertkey(&base->object->id, ID_OB, NULL, NULL, OB_ROT_Y);
1796                                 insertkey(&base->object->id, ID_OB, NULL, NULL, OB_ROT_Z);
1797                         
1798                                 insertkey(&base->object->id, ID_OB, NULL, NULL, OB_LOC_X);
1799                                 insertkey(&base->object->id, ID_OB, NULL, NULL, OB_LOC_Y);
1800                                 insertkey(&base->object->id, ID_OB, NULL, NULL, OB_LOC_Z);
1801                         
1802                                 insertkey(&base->object->id, ID_OB, NULL, NULL, OB_SIZE_X);
1803                                 insertkey(&base->object->id, ID_OB, NULL, NULL, OB_SIZE_Y);
1804                                 insertkey(&base->object->id, ID_OB, NULL, NULL, OB_SIZE_Z);
1805                                 
1806                                 remake_object_ipos (ob);
1807                                 allqueue(REDRAWIPO, 0);
1808                                 allspace(REMAKEIPO, 0);
1809                                 allqueue(REDRAWVIEW3D, 0);
1810                                 allqueue(REDRAWNLA, 0);
1811                         }
1812                         
1813                         base= base->next;
1814                 }
1815                 
1816         }
1817         
1818         clear_trans_object_base_flags();
1819         
1820         if(redrawipo) {
1821                 allqueue(REDRAWNLA, 0);
1822                 allqueue(REDRAWACTION, 0);
1823                 allqueue(REDRAWIPO, 0);
1824         }
1825         
1826         reset_slowparents();
1827         
1828         /* note; should actually only be done for all objects when a lamp is moved... (ton) */
1829         if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
1830                 reshadeall_displist();
1831 }
1832
1833 static void createTransObject(TransInfo *t)
1834 {
1835         TransData *td = NULL;
1836         TransDataExtension *tx;
1837         Object *ob;
1838         Base *base;
1839         IpoKey *ik;
1840         ListBase elems;
1841         
1842         set_trans_object_base_flags(t);
1843
1844         /* count */     
1845         for(base= FIRSTBASE; base; base= base->next) {
1846                 if TESTBASELIB(base) {
1847                         ob= base->object;
1848                         
1849                         /* store ipo keys? */
1850                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1851                                 elems.first= elems.last= NULL;
1852                                 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
1853                                 
1854                                 pushdata(&elems, sizeof(ListBase));
1855                                 
1856                                 for(ik= elems.first; ik; ik= ik->next) t->total++;
1857
1858                                 if(elems.first==NULL) t->total++;
1859                         }
1860                         else {
1861                                 t->total++;
1862                         }
1863                 }
1864         }
1865
1866         if(!t->total) {
1867                 /* clear here, main transform function escapes too */
1868                 clear_trans_object_base_flags();
1869                 return;
1870         }
1871         
1872         td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
1873         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
1874
1875         for(base= FIRSTBASE; base; base= base->next) {
1876                 if TESTBASELIB(base) {
1877                         ob= base->object;
1878                         
1879                         td->flag= TD_SELECTED;
1880                         td->ext = tx;
1881
1882                         /* store ipo keys? */
1883                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1884                                 
1885                                 popfirst(&elems);       // bring back pushed listbase
1886                                 
1887                                 if(elems.first) {
1888                                         float cfraont;
1889                                         int ipoflag;
1890                                         
1891                                         base->flag |= BA_DO_IPO+BA_WAS_SEL;
1892                                         base->flag &= ~SELECT;
1893                                         
1894                                         cfraont= CFRA;
1895                                         set_no_parent_ipo(1);
1896                                         ipoflag= ob->ipoflag;
1897                                         ob->ipoflag &= ~OB_OFFS_OB;
1898                                         
1899                                         pushdata(ob->loc, 7*3*4); // tsk! tsk!
1900                                         
1901                                         for(ik= elems.first; ik; ik= ik->next) {
1902                                                 
1903                                                 /* weak... this doesn't correct for floating values, giving small errors */
1904                                                 CFRA= (short)(ik->val/G.scene->r.framelen);
1905                                                 
1906                                                 do_ob_ipo(ob);
1907                                                 ObjectToTransData(td, ob);      // does where_is_object()
1908                                                 
1909                                                 td->flag= TD_SELECTED;
1910                                                 
1911                                                 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
1912                                                 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
1913                                                 ipokey_to_transdata(ik, td);
1914                                                 
1915                                                 td++;
1916                                                 tx++;
1917                                                 if(ik->next) td->ext= tx;       // prevent corrupting mem!
1918                                         }
1919                                         free_ipokey(&elems);
1920                                         
1921                                         poplast(ob->loc);
1922                                         set_no_parent_ipo(0);
1923                                         
1924                                         CFRA= (short)cfraont;
1925                                         ob->ipoflag= ipoflag;
1926                                         
1927                                         where_is_object(ob);    // restore 
1928                                 }
1929                                 else {
1930                                         ObjectToTransData(td, ob);
1931                                         td->tdi = NULL;
1932                                         td->val = NULL;
1933                                         td++;
1934                                         tx++;
1935                                 }
1936                         }
1937                         else {
1938                                 ObjectToTransData(td, ob);
1939                                 td->tdi = NULL;
1940                                 td->val = NULL;
1941                                 td++;
1942                                 tx++;
1943                         }
1944                 }
1945         }
1946 }
1947
1948 void createTransData(TransInfo *t) 
1949 {
1950         Object *ob= OBACT;
1951         
1952         if (t->context == CTX_TEXTURE) {
1953                 t->flag |= T_TEXTURE;
1954                 createTransTexspace(t);
1955         }
1956         else if (t->context == CTX_EDGE) {
1957                 t->ext = NULL;
1958                 t->flag |= T_EDIT;
1959                 createTransEdge(t);
1960                 if(t->data && t->flag & T_PROP_EDIT) {
1961                         sort_trans_data(t);     // makes selected become first in array
1962                         set_prop_dist(t, 1);
1963                         sort_trans_data_dist(t);
1964                 }
1965         }
1966         else if (t->spacetype == SPACE_IMAGE) {
1967                 t->flag |= T_POINTS|T_2D_EDIT;
1968                 createTransUVs(t);
1969                 if(t->data && (t->flag & T_PROP_EDIT)) {
1970                         sort_trans_data(t);     // makes selected become first in array
1971                         set_prop_dist(t, 1);
1972                         sort_trans_data_dist(t);
1973                 }
1974         }
1975         else if (G.obedit) {
1976                 t->ext = NULL;
1977                 if (G.obedit->type == OB_MESH) {
1978                         createTransEditVerts(t);        
1979                 }
1980                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1981                         createTransCurveVerts(t);
1982                 }
1983                 else if (G.obedit->type==OB_LATTICE) {
1984                         createTransLatticeVerts(t);
1985                 }
1986                 else if (G.obedit->type==OB_MBALL) {
1987                         createTransMBallVerts(t);
1988                 }
1989                 else if (G.obedit->type==OB_ARMATURE) {
1990                         createTransArmatureVerts(t);
1991                 }                                                       
1992                 else {
1993                         printf("not done yet! only have mesh surface curve\n");
1994                 }
1995
1996                 if(t->data && t->flag & T_PROP_EDIT) {
1997                         if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
1998                                 sort_trans_data(t);     // makes selected become first in array
1999                                 set_prop_dist(t, 0);
2000                                 sort_trans_data_dist(t);
2001                         }
2002                         else {
2003                                 sort_trans_data(t);     // makes selected become first in array
2004                                 set_prop_dist(t, 1);
2005                                 sort_trans_data_dist(t);
2006                         }
2007                 }
2008
2009                 t->flag |= T_EDIT|T_POINTS;
2010                 
2011                 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
2012                 if(t->mode==TFM_BONESIZE) {
2013                         t->flag &= ~(T_EDIT|T_POINTS);
2014                         t->flag |= T_POSE;
2015                         t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
2016                 }
2017         }
2018         else if (ob && (ob->flag & OB_POSEMODE)) {
2019                 createTransPose(OBACT, t);
2020         }
2021         else if (G.f & G_WEIGHTPAINT) {
2022                 /* exception, we look for the one selected armature */
2023                 Base *base;
2024                 for(base=FIRSTBASE; base; base= base->next) {
2025                         if(TESTBASELIB(base)) {
2026                                 if(base->object->type==OB_ARMATURE)
2027                                         if(base->object->flag & OB_POSEMODE)
2028                                                 break;
2029                         }
2030                 }
2031                 if(base) {
2032                         createTransPose(base->object, t);
2033                 }
2034         }
2035         else {
2036                 createTransObject(t);
2037                 t->flag |= T_OBJECT;
2038         }
2039
2040         if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
2041                 t->flag |= T_CAMERA;
2042         }
2043 }
2044