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