Transform Bugfixes Part 2 (Constraints Related):
[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 /* hurmf, copy from buttons_editing.c, i have to sort this out what it means... */
1510 static void modifiers_setOnCage(void *ob_v, void *md_v)
1511 {
1512         Object *ob = ob_v;
1513         ModifierData *md;
1514         
1515         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1516         
1517         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1518                 if( md == md_v ) {
1519                         if( i >= cageIndex )
1520                                 md->mode ^= eModifierMode_OnCage;
1521                         break;
1522                 }
1523 }
1524
1525
1526 /* disable subsurf temporal, get mapped cos, and enable it */
1527 static float *get_crazy_mapped_editverts(void)
1528 {
1529         DerivedMesh *dm;
1530         ModifierData *md;
1531         float *vertexcos;
1532         int i;
1533         
1534         for( i = 0, md=G.obedit->modifiers.first; md; ++i, md=md->next ) {
1535                 if(md->type==eModifierType_Subsurf)
1536                         if(md->mode & eModifierMode_OnCage)
1537                                 break;
1538         }
1539         if(md) {
1540                 /* this call disables subsurf and enables the underlying modifier to deform, apparently */
1541                 modifiers_setOnCage(G.obedit, md);
1542                 /* make it all over */
1543                 makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
1544         }
1545         
1546         /* now get the cage */
1547         dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
1548
1549         vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1550         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1551         
1552         dm->release(dm);
1553         
1554         if(md) {
1555                 /* set back the flag, no new cage needs to be built, transform does it */
1556                 modifiers_setOnCage(G.obedit, md);
1557         }
1558         
1559         return vertexcos;
1560 }
1561
1562 #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])
1563 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1564 {
1565         float vecu[3], vecv[3];
1566         float q1[4], q2[4];
1567         
1568         TAN_MAKE_VEC(vecu, v1, v2);
1569         TAN_MAKE_VEC(vecv, v1, v3);
1570         triatoquat(v1, vecu, vecv, q1);
1571         
1572         TAN_MAKE_VEC(vecu, def1, def2);
1573         TAN_MAKE_VEC(vecv, def1, def3);
1574         triatoquat(def1, vecu, vecv, q2);
1575         
1576         QuatSub(quat, q2, q1);
1577 }
1578 #undef TAN_MAKE_VEC
1579
1580 static void set_crazyspace_quats(float *mappedcos, float *quats)
1581 {
1582         EditMesh *em = G.editMesh;
1583         EditVert *eve, *prev;
1584         EditFace *efa;
1585         float *v1, *v2, *v3, *v4;
1586         long index= 0;
1587         
1588         /* two abused locations in vertices */
1589         for(eve= em->verts.first; eve; eve= eve->next, index++) {
1590                 eve->tmp.fp = NULL;
1591                 eve->prev= (EditVert *)index;
1592         }
1593         
1594         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
1595         for(efa= em->faces.first; efa; efa= efa->next) {
1596                 
1597                 /* retrieve mapped coordinates */
1598                 v1= mappedcos + 3*( (long)(efa->v1->prev) );
1599                 v2= mappedcos + 3*( (long)(efa->v2->prev) );
1600                 v3= mappedcos + 3*( (long)(efa->v3->prev) );
1601                 
1602                 if(efa->v2->tmp.fp==NULL && efa->v2->f1) {
1603                         set_crazy_vertex_quat(quats, efa->v2->co, efa->v3->co, efa->v1->co, v2, v3, v1);
1604                         efa->v2->tmp.fp= quats;
1605                         quats+= 4;
1606                 }
1607                 
1608                 if(efa->v4) {
1609                         v4= mappedcos + 3*( (long)(efa->v4->prev) );
1610                         
1611                         if(efa->v1->tmp.fp==NULL && efa->v1->f1) {
1612                                 set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v4->co, v1, v2, v4);
1613                                 efa->v1->tmp.fp= quats;
1614                                 quats+= 4;
1615                         }
1616                         if(efa->v3->tmp.fp==NULL && efa->v3->f1) {
1617                                 set_crazy_vertex_quat(quats, efa->v3->co, efa->v4->co, efa->v2->co, v3, v4, v2);
1618                                 efa->v3->tmp.fp= quats;
1619                                 quats+= 4;
1620                         }
1621                         if(efa->v4->tmp.fp==NULL && efa->v4->f1) {
1622                                 set_crazy_vertex_quat(quats, efa->v4->co, efa->v1->co, efa->v3->co, v4, v1, v3);
1623                                 efa->v4->tmp.fp= quats;
1624                                 quats+= 4;
1625                         }
1626                 }
1627                 else {
1628                         if(efa->v1->tmp.fp==NULL && efa->v1->f1) {
1629                                 set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v3->co, v1, v2, v3);
1630                                 efa->v1->tmp.fp= quats;
1631                                 quats+= 4;
1632                         }
1633                         if(efa->v3->tmp.fp==NULL && efa->v3->f1) {
1634                                 set_crazy_vertex_quat(quats, efa->v3->co, efa->v1->co, efa->v2->co, v3, v1, v2);
1635                                 efa->v3->tmp.fp= quats;
1636                                 quats+= 4;
1637                         }
1638                 }
1639         }
1640
1641         /* restore abused prev pointer */
1642         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1643                 eve->prev= prev;
1644
1645 }
1646
1647 static void createTransEditVerts(TransInfo *t)
1648 {
1649         TransData *tob = NULL;
1650         EditMesh *em = G.editMesh;
1651         EditVert *eve;
1652         EditVert **nears = NULL;
1653         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1654         float mtx[3][3], smtx[3][3];
1655         int count=0, countsel=0;
1656         int propmode = t->flag & T_PROP_EDIT;
1657         int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR);
1658
1659         // transform now requires awareness for select mode, so we tag the f1 flags in verts
1660         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1661                 for(eve= em->verts.first; eve; eve= eve->next) {
1662                         if(eve->h==0 && (eve->f & SELECT)) 
1663                                 eve->f1= SELECT;
1664                         else
1665                                 eve->f1= 0;
1666                 }
1667         }
1668         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1669                 EditEdge *eed;
1670                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1671                 for(eed= em->edges.first; eed; eed= eed->next) {
1672                         if(eed->h==0 && (eed->f & SELECT))
1673                                 eed->v1->f1= eed->v2->f1= SELECT;
1674                 }
1675         }
1676         else {
1677                 EditFace *efa;
1678                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1679                 for(efa= em->faces.first; efa; efa= efa->next) {
1680                         if(efa->h==0 && (efa->f & SELECT)) {
1681                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1682                                 if(efa->v4) efa->v4->f1= SELECT;
1683                         }
1684                 }
1685         }
1686         
1687         /* now we can count */
1688         for(eve= em->verts.first; eve; eve= eve->next) {
1689                 if(eve->h==0) {
1690                         if(eve->f1) countsel++;
1691                         if(propmode) count++;
1692                 }
1693         }
1694         
1695         /* note: in prop mode we need at least 1 selected */
1696         if (countsel==0) return;
1697         
1698         if(propmode) {
1699                 t->total = count; 
1700         
1701                 /* allocating scratch arrays */
1702                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1703                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1704         }
1705         else t->total = countsel;
1706         tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1707         
1708         Mat3CpyMat4(mtx, G.obedit->obmat);
1709         Mat3Inv(smtx, mtx);
1710
1711         if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1712         
1713         /* detect CrazySpace [tm] */
1714         if(propmode==0) {
1715                 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
1716                         if(modifiers_isDeformed(G.obedit)) {
1717                                 /* disable subsurf temporal, get mapped cos, and enable it */
1718                                 mappedcos= get_crazy_mapped_editverts();
1719                                 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
1720                                 set_crazyspace_quats(mappedcos, quats);
1721                         }
1722                 }
1723         }
1724         
1725         /* find out which half we do */
1726         if(mirror) {
1727                 for (eve=em->verts.first; eve; eve=eve->next) {
1728                         if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
1729                                 if(eve->co[0]<0.0f)
1730                                         mirror = -1;
1731                                 break;
1732                         }
1733                 }
1734         }
1735         
1736         for (eve=em->verts.first; eve; eve=eve->next) {
1737                 if(eve->h==0) {
1738                         if(propmode || eve->f1) {
1739                                 VertsToTransData(tob, eve);
1740
1741                                 if(eve->f1) tob->flag |= TD_SELECTED;
1742                                 if(propmode) {
1743                                         if (eve->f2) {
1744                                                 float vec[3];
1745                                                 VECCOPY(vec, E_VEC(eve));
1746                                                 Mat3MulVecfl(mtx, vec);
1747                                                 tob->dist= VecLength(vec);
1748                                         }
1749                                         else {
1750                                                 tob->flag |= TD_NOTCONNECTED;
1751                                                 tob->dist = MAXFLOAT;
1752                                         }
1753                                 }
1754                                 
1755                                 /* CrazySpace */
1756                                 if(quats && eve->tmp.fp) {
1757                                         float mat[3][3], imat[3][3], qmat[3][3];
1758                                         
1759                                         QuatToMat3(eve->tmp.fp, qmat);
1760                                         Mat3MulMat3(mat, mtx, qmat);
1761                                         Mat3Inv(imat, mat);
1762                                         
1763                                         Mat3CpyMat3(tob->smtx, imat);
1764                                         Mat3CpyMat3(tob->mtx, mat);
1765                                 }
1766                                 else {
1767                                         Mat3CpyMat3(tob->smtx, smtx);
1768                                         Mat3CpyMat3(tob->mtx, mtx);
1769                                 }
1770                                 
1771                                 /* Mirror? */
1772                                 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
1773                                         EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc);        /* initializes octree on first call */
1774                                         if(vmir!=eve) tob->tdmir= vmir;
1775                                 }
1776                                 tob++;
1777                         }
1778                 }       
1779         }
1780         if (propmode) {
1781                 MEM_freeN(vectors);
1782                 MEM_freeN(nears);
1783         }
1784         /* crazy space free */
1785         if(mappedcos)
1786                 MEM_freeN(mappedcos);
1787         if(quats)
1788                 MEM_freeN(quats);
1789 }
1790
1791 /* ********************* UV ****************** */
1792
1793 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
1794 {
1795         float aspx, aspy;
1796
1797         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1798
1799         /* uv coords are scaled by aspects. this is needed for rotations and
1800            proportional editing to be consistent with the stretchted uv coords
1801            that are displayed. this also means that for display and numinput,
1802            and when the the uv coords are flushed, these are converted each time */
1803         td2d->loc[0] = uv[0]*aspx;
1804         td2d->loc[1] = uv[1]*aspy;
1805         td2d->loc[2] = 0.0f;
1806         td2d->loc2d = uv;
1807
1808         td->flag = 0;
1809         td->loc = td2d->loc;
1810         VECCOPY(td->center, td->loc);
1811         VECCOPY(td->iloc, td->loc);
1812
1813         memset(td->axismtx, 0, sizeof(td->axismtx));
1814         td->axismtx[2][2] = 1.0f;
1815
1816         td->ext= NULL; td->tdi= NULL; td->val= NULL;
1817
1818         if(selected) {
1819                 td->flag |= TD_SELECTED;
1820                 td->dist= 0.0;
1821         }
1822         else
1823                 td->dist= MAXFLOAT;
1824         
1825         Mat3One(td->mtx);
1826         Mat3One(td->smtx);
1827 }
1828
1829 static void createTransUVs(TransInfo *t)
1830 {
1831         TransData *td = NULL;
1832         TransData2D *td2d = NULL;
1833         Mesh *me;
1834         MFace *mf;
1835         MTFace *tf;
1836         int a, count=0, countsel=0;
1837         int propmode = t->flag & T_PROP_EDIT;
1838         
1839         if(is_uv_tface_editing_allowed()==0) return;
1840         me= get_mesh(OBACT);
1841
1842         /* count */
1843         tf= me->mtface;
1844         mf= me->mface;
1845         for(a=me->totface; a>0; a--, tf++, mf++) {
1846                 if(mf->v3 && mf->flag & ME_FACE_SEL) {
1847                         if(tf->flag & TF_SEL1) countsel++;
1848                         if(tf->flag & TF_SEL2) countsel++;
1849                         if(tf->flag & TF_SEL3) countsel++;
1850                         if(mf->v4 && (tf->flag & TF_SEL4)) countsel++;
1851                         if(propmode)
1852                                 count += (mf->v4)? 4: 3;
1853                 }
1854         }
1855
1856         /* note: in prop mode we need at least 1 selected */
1857         if (countsel==0) return;
1858         
1859         t->total= (propmode)? count: countsel;
1860         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
1861         /* for each 2d uv coord a 3d vector is allocated, so that they can be
1862            treated just as if they were 3d verts */
1863         t->data2d= MEM_mallocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
1864
1865         if(G.sima->flag & SI_CLIP_UV)
1866                 t->flag |= T_CLIP_UV;
1867
1868         td= t->data;
1869         td2d= t->data2d;
1870         tf= me->mtface;
1871         mf= me->mface;
1872         for(a=me->totface; a>0; a--, tf++, mf++) {
1873                 if(mf->v3 && mf->flag & ME_FACE_SEL) {
1874                         if(tf->flag & TF_SEL1 || propmode)
1875                                 UVsToTransData(td++, td2d++, tf->uv[0], (tf->flag & TF_SEL1));
1876                         if(tf->flag & TF_SEL2 || propmode)
1877                                 UVsToTransData(td++, td2d++, tf->uv[1], (tf->flag & TF_SEL2));
1878                         if(tf->flag & TF_SEL3 || propmode)
1879                                 UVsToTransData(td++, td2d++, tf->uv[2], (tf->flag & TF_SEL3));
1880
1881                         if(mf->v4 && (tf->flag & TF_SEL4 || propmode))
1882                                 UVsToTransData(td++, td2d++, tf->uv[3], (tf->flag & TF_SEL4));
1883                 }
1884         }
1885
1886         if (G.sima->flag & SI_LIVE_UNWRAP)
1887                 unwrap_lscm_live_begin();
1888 }
1889
1890 void flushTransUVs(TransInfo *t)
1891 {
1892         TransData2D *td;
1893         int a, width, height;
1894         Object *ob= OBACT;
1895         Mesh *me= get_mesh(ob);
1896         float aspx, aspy, invx, invy;
1897
1898         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1899         transform_width_height_tface_uv(&width, &height);
1900         invx= 1.0f/aspx;
1901         invy= 1.0f/aspy;
1902
1903         /* flush to 2d vector from internally used 3d vector */
1904         for(a=0, td= t->data2d; a<t->total; a++, td++) {
1905                 td->loc2d[0]= td->loc[0]*invx;
1906                 td->loc2d[1]= td->loc[1]*invy;
1907                 
1908                 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
1909                         td->loc2d[0]= floor(width*td->loc2d[0] + 0.5f)/width;
1910                         td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height;
1911                 }
1912         }
1913
1914         /* always call this, also for cancel (it transforms non-selected vertices...) */
1915         if((G.sima->flag & SI_BE_SQUARE))
1916                 be_square_tface_uv(me);
1917
1918         /* this is overkill if G.sima->lock is not set, but still needed */
1919         object_uvs_changed(ob);
1920 }
1921
1922 int clipUVTransform(TransInfo *t, float *vec, int resize)
1923 {
1924         TransData *td;
1925         int a, clipx=1, clipy=1;
1926         float aspx, aspy, min[2], max[2];
1927
1928         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1929         min[0]= min[1]= 0.0f;
1930         max[0]= aspx; max[1]= aspy;
1931
1932         for(a=0, td= t->data; a<t->total; a++, td++) {
1933                 DO_MINMAX2(td->loc, min, max);
1934         }
1935
1936         if(resize) {
1937                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
1938                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
1939                 else if(max[0] > aspx && t->center[0] < aspx)
1940                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
1941                 else
1942                         clipx= 0;
1943
1944                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
1945                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
1946                 else if(max[1] > aspy && t->center[1] < aspy)
1947                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
1948                 else
1949                         clipy= 0;
1950         }
1951         else {
1952                 if(min[0] < 0.0f)
1953                         vec[0] -= min[0];
1954                 else if(max[0] > aspx)
1955                         vec[0] -= max[0]-aspx;
1956                 else
1957                         clipx= 0;
1958
1959                 if(min[1] < 0.0f)
1960                         vec[1] -= min[1];
1961                 else if(max[1] > aspy)
1962                         vec[1] -= max[1]-aspy;
1963                 else
1964                         clipy= 0;
1965         }       
1966
1967         return (clipx || clipy);
1968 }
1969
1970 /* **************** IpoKey stuff, for Object TransData ********** */
1971
1972 /* storage of bezier triple. thats why -3 and +3! */
1973 static void set_tdi_old(float *old, float *poin)
1974 {
1975         old[0]= *(poin);
1976         old[3]= *(poin-3);
1977         old[6]= *(poin+3);
1978 }
1979
1980 /* while transforming */
1981 void add_tdi_poin(float *poin, float *old, float delta)
1982 {
1983         if(poin) {
1984                 poin[0]= old[0]+delta;
1985                 poin[-3]= old[3]+delta;
1986                 poin[3]= old[6]+delta;
1987         }
1988 }
1989
1990 /* fill ipokey transdata with old vals and pointers */
1991 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
1992 {
1993         extern int ob_ar[];             // blenkernel ipo.c
1994         TransDataIpokey *tdi= td->tdi;
1995         BezTriple *bezt;
1996         int a, delta= 0;
1997         
1998         td->val= NULL;  // is read on ESC
1999         
2000         for(a=0; a<OB_TOTIPO; a++) {
2001                 if(ik->data[a]) {
2002                         bezt= ik->data[a];
2003                         
2004                         switch( ob_ar[a] ) {
2005                                 case OB_LOC_X:
2006                                 case OB_DLOC_X:
2007                                         tdi->locx= &(bezt->vec[1][1]); break;
2008                                 case OB_LOC_Y:
2009                                 case OB_DLOC_Y:
2010                                         tdi->locy= &(bezt->vec[1][1]); break;
2011                                 case OB_LOC_Z:
2012                                 case OB_DLOC_Z:
2013                                         tdi->locz= &(bezt->vec[1][1]); break;
2014                                         
2015                                 case OB_DROT_X:
2016                                         delta= 1;
2017                                 case OB_ROT_X:
2018                                         tdi->rotx= &(bezt->vec[1][1]); break;
2019                                 case OB_DROT_Y:
2020                                         delta= 1;
2021                                 case OB_ROT_Y:
2022                                         tdi->roty= &(bezt->vec[1][1]); break;
2023                                 case OB_DROT_Z:
2024                                         delta= 1;
2025                                 case OB_ROT_Z:
2026                                         tdi->rotz= &(bezt->vec[1][1]); break;
2027                                         
2028                                 case OB_SIZE_X:
2029                                 case OB_DSIZE_X:
2030                                         tdi->sizex= &(bezt->vec[1][1]); break;
2031                                 case OB_SIZE_Y:
2032                                 case OB_DSIZE_Y:
2033                                         tdi->sizey= &(bezt->vec[1][1]); break;
2034                                 case OB_SIZE_Z:
2035                                 case OB_DSIZE_Z:
2036                                         tdi->sizez= &(bezt->vec[1][1]); break;          
2037                         }       
2038                 }
2039         }
2040         
2041         /* oldvals for e.g. undo */
2042         if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
2043         if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
2044         if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
2045         
2046         /* remember, for mapping curves ('1'=10 degrees)  */
2047         if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
2048         if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
2049         if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
2050         
2051         /* this is not allowed to be dsize! */
2052         if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
2053         if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
2054         if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
2055         
2056         tdi->flag= TOB_IPO;
2057         if(delta) tdi->flag |= TOB_IPODROT;
2058 }
2059
2060
2061 /* *************************** Object Transform data ******************* */
2062
2063 /* Little helper function for ObjectToTransData used to give certain
2064  * constraints (ChildOf, FollowPath, and others that may be added)
2065  * inverse corrections for transform, so that they aren't in CrazySpace.
2066  * These particular constraints benefit from this, but others don't, hence
2067  * this semi-hack ;-)    - Aligorith
2068  */
2069 static short constraints_list_needinv(ListBase *list)
2070 {
2071         bConstraint *con;
2072         
2073         /* loop through constraints, checking if there's one of the mentioned 
2074          * constraints needing special crazyspace corrections
2075          */
2076         if (list) {
2077                 for (con= list->first; con; con=con->next) {
2078                         /* only consider constraint if it is enabled, and has influence on result */
2079                         if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) {
2080                                 /* (affirmative) returns for specific constraints here... */
2081                                 if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1;
2082                                 if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1;
2083                                 if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1;
2084                         }
2085                 }
2086         }
2087         
2088         /* no appropriate candidates found */
2089         return 0;
2090 }
2091
2092 /* transcribe given object into TransData for Transforming */
2093 static void ObjectToTransData(TransData *td, Object *ob) 
2094 {
2095         float obmtx[3][3];
2096
2097         /* axismtx has the real orientation */
2098         Mat3CpyMat4(td->axismtx, ob->obmat);
2099         Mat3Ortho(td->axismtx);
2100
2101         where_is_object(ob);
2102
2103         td->ob = ob;
2104
2105         td->loc = ob->loc;
2106         VECCOPY(td->iloc, td->loc);
2107         
2108         td->ext->rot = ob->rot;
2109         VECCOPY(td->ext->irot, ob->rot);
2110         VECCOPY(td->ext->drot, ob->drot);
2111         
2112         td->ext->size = ob->size;
2113         VECCOPY(td->ext->isize, ob->size);
2114         VECCOPY(td->ext->dsize, ob->dsize);
2115
2116         VECCOPY(td->center, ob->obmat[3]);
2117
2118         /* is there a need to set the global<->data space conversion matrices? */
2119         if (ob->parent || constraints_list_needinv(&ob->constraints)) {
2120                 float totmat[3][3], obinv[3][3];
2121                 
2122                 /* Get the effect of parenting, and/or certain constraints.
2123                  * NOTE: some Constraints, and also Tracking should never get this
2124                  *              done, as it doesn't work well.
2125                  */
2126                 object_to_mat3(ob, obmtx);
2127                 Mat3CpyMat4(totmat, ob->obmat);
2128                 Mat3Inv(obinv, totmat);
2129                 Mat3MulMat3(td->smtx, obmtx, obinv);
2130                 Mat3Inv(td->mtx, td->smtx);
2131         }
2132         else {
2133                 /* no conversion to/from dataspace */
2134                 Mat3One(td->smtx);
2135                 Mat3One(td->mtx);
2136         }
2137 #ifdef WITH_VERSE
2138         if(ob->vnode) {
2139                 td->verse = (void*)ob;
2140                 td->flag |= TD_VERSE_OBJECT;
2141         }
2142         else
2143                 td->flag &= ~TD_VERSE_OBJECT;
2144 #endif
2145 }
2146
2147
2148 /* sets flags in Bases to define whether they take part in transform */
2149 /* it deselects Bases, so we have to call the clear function always after */
2150 static void set_trans_object_base_flags(TransInfo *t)
2151 {
2152         /*
2153          if Base selected and has parent selected:
2154          base->flag= BA_WAS_SEL
2155          */
2156         Base *base;
2157         
2158         /* makes sure base flags and object flags are identical */
2159         copy_baseflags();
2160         
2161         /* handle pending update events, otherwise they got copied below */
2162         for (base= FIRSTBASE; base; base= base->next) {
2163                 if(base->object->recalc) 
2164                         object_handle_update(base->object);
2165         }
2166         
2167         for (base= FIRSTBASE; base; base= base->next) {
2168                 base->flag &= ~BA_WAS_SEL;
2169                 
2170                 if(TESTBASELIB(base)) {
2171                         Object *ob= base->object;
2172                         Object *parsel= ob->parent;
2173                         
2174                         /* if parent selected, deselect */
2175                         while(parsel) {
2176                                 if(parsel->flag & SELECT) break;
2177                                 parsel= parsel->parent;
2178                         }
2179                         
2180                         if(parsel) {
2181                                 base->flag &= ~SELECT;
2182                                 base->flag |= BA_WAS_SEL;
2183                         }
2184                         /* used for flush, depgraph will change recalcs if needed :) */
2185                         ob->recalc |= OB_RECALC_OB;
2186                 }
2187         }
2188         /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
2189         DAG_scene_flush_update(G.scene, -1);
2190         
2191         /* and we store them temporal in base (only used for transform code) */
2192         /* this because after doing updates, the object->recalc is cleared */
2193         for (base= FIRSTBASE; base; base= base->next) {
2194                 if(base->object->recalc & OB_RECALC_OB)
2195                         base->flag |= BA_HAS_RECALC_OB;
2196                 if(base->object->recalc & OB_RECALC_DATA)
2197                         base->flag |= BA_HAS_RECALC_DATA;
2198         }
2199 }
2200
2201 static void clear_trans_object_base_flags(void)
2202 {
2203         Base *base;
2204         
2205         base= FIRSTBASE;
2206         while(base) {
2207                 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
2208                 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
2209                 
2210                 base = base->next;
2211         }
2212 }
2213
2214 /* auto-keyframing feature - for objects 
2215  *      tmode: should be a transform mode 
2216  */
2217 void autokeyframe_ob_cb_func(Object *ob, int tmode)
2218 {
2219         IpoCurve *icu;
2220         char *actname="";
2221         
2222         if (G.flags & G_RECORDKEYS) {
2223                 if(ob->ipoflag & OB_ACTION_OB)
2224                         actname= "Object";
2225
2226                 if(U.uiflag & USER_KEYINSERTAVAI) {
2227                         if(ob->ipo || ob->action) {
2228                                 ID *id= (ID *)(ob);
2229                                 
2230                                 if (ob->ipo) {
2231                                         icu= ob->ipo->curve.first;
2232                                 }
2233                                 else {
2234                                         bActionChannel *achan;
2235                                         achan= get_action_channel(ob->action, actname);
2236                                         
2237                                         if (achan && achan->ipo)
2238                                                 icu= achan->ipo->curve.first;
2239                                         else
2240                                                 icu= NULL;
2241                                 }
2242                                 
2243                                 while(icu) {
2244                                         icu->flag &= ~IPO_SELECT;
2245                                         if (U.uiflag & USER_KEYINSERTNEED)
2246                                                 insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode);
2247                                         else
2248                                                 insertkey(id, ID_OB, actname, NULL, icu->adrcode);
2249                                         icu= icu->next;
2250                                 }
2251                         }
2252                 }
2253                 else if (U.uiflag & USER_KEYINSERTNEED) {
2254                         if (tmode==TFM_RESIZE) {
2255                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_X);
2256                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y);
2257                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z);
2258                         }
2259                         else if (tmode==TFM_ROTATION) {
2260                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_X);
2261                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Y);
2262                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Z);
2263                         }
2264                         else if (tmode==TFM_TRANSLATION) {
2265                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_X);
2266                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Y);
2267                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Z);
2268                         }
2269                 }
2270                 else {
2271                         insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_X);
2272                         insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Y);
2273                         insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Z);
2274
2275                         insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_X);
2276                         insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Y);
2277                         insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Z);
2278
2279                         insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_X);
2280                         insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y);
2281                         insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z);
2282                 }
2283
2284                 remake_object_ipos(ob);
2285                 allqueue(REDRAWIPO, 0);
2286                 allspace(REMAKEIPO, 0);
2287                 allqueue(REDRAWVIEW3D, 0);
2288                 allqueue(REDRAWNLA, 0);
2289                 allqueue(REDRAWTIME, 0);
2290         }
2291 }
2292
2293 /* auto-keyframing feature - for poses/pose-channels 
2294  *      tmode: should be a transform mode 
2295  *      targetless_ik: has targetless ik been done on any channels?
2296  */
2297 void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik)
2298 {
2299         bAction *act;
2300         bPose   *pose;
2301         bPoseChannel *pchan;
2302         IpoCurve *icu;
2303         
2304         pose= ob->pose;
2305         act= ob->action;
2306         
2307         if (G.flags & G_RECORDKEYS) {
2308                 if (!act)
2309                         act= ob->action= add_empty_action("Action");
2310                 
2311                 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
2312                         if (pchan->bone->flag & BONE_TRANSFORM){
2313
2314                                 if(U.uiflag & USER_KEYINSERTAVAI) {
2315                                         bActionChannel *achan; 
2316
2317                                         for (achan = act->chanbase.first; achan; achan=achan->next){
2318                                                 if (achan->ipo && !strcmp (achan->name, pchan->name)){
2319                                                         for (icu = achan->ipo->curve.first; icu; icu=icu->next){
2320                                                                 if (U.uiflag & USER_KEYINSERTNEED)
2321                                                                         insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode);
2322                                                                 else
2323                                                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode);
2324                                                         }
2325                                                         break;
2326                                                 }
2327                                         }
2328                                 }
2329                                 else if (U.uiflag & USER_KEYINSERTNEED) {
2330                                         if ((tmode==TFM_TRANSLATION) && (targetless_ik==0)) {
2331                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
2332                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
2333                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
2334                                         }
2335                                         if ((tmode==TFM_ROTATION) || ((tmode==TFM_TRANSLATION) && targetless_ik)) {
2336                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
2337                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
2338                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
2339                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
2340                                         }
2341                                         if (tmode==TFM_RESIZE) {
2342                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
2343                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
2344                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
2345                                         }
2346                                 }
2347                                 else {
2348                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
2349                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
2350                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
2351
2352                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
2353                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
2354                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
2355                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
2356
2357                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
2358                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
2359                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
2360                                 }
2361                         }
2362                 }
2363                 
2364                 remake_action_ipos (act);
2365                 allspace(REMAKEIPO, 0);
2366                 allqueue(REDRAWACTION, 0);
2367                 allqueue(REDRAWIPO, 0);
2368                 allqueue(REDRAWNLA, 0);
2369                 allqueue(REDRAWTIME, 0);
2370         }
2371 }
2372
2373 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
2374 /* note; transdata has been freed already! */
2375 void special_aftertrans_update(TransInfo *t)
2376 {
2377         Object *ob;
2378         Base *base;
2379         int redrawipo=0;
2380         int cancelled= (t->state == TRANS_CANCEL);
2381                 
2382         if(G.obedit) {
2383                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2384                         allqueue(REDRAWBUTSEDIT, 0);
2385                 
2386                 /* table needs to be created for each edit command, since vertices can move etc */
2387                 mesh_octree_table(G.obedit, NULL, 'e');
2388         }
2389         else if( (t->flag & T_POSE) && t->poseobj) {
2390                 bArmature *arm;
2391                 bPose   *pose;
2392                 bPoseChannel *pchan;
2393                 short targetless_ik= 0;
2394
2395                 ob= t->poseobj;
2396                 arm= ob->data;
2397                 pose= ob->pose;
2398                 
2399                 /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
2400                 pose->flag |= POSE_DO_UNLOCK;
2401
2402                 /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
2403                 if(!cancelled && t->mode==TFM_TRANSLATION)
2404                         targetless_ik= apply_targetless_ik(ob);
2405                 else {
2406                         /* not forget to clear the auto flag */
2407                         for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
2408                                 bKinematicConstraint *data= has_targetless_ik(pchan);
2409                                 if(data) data->flag &= ~CONSTRAINT_IK_AUTO;
2410                         }
2411                 }
2412                 
2413                 if(t->mode==TFM_TRANSLATION)
2414                         pose_grab_with_ik_clear(ob);
2415                 
2416                 /* automatic inserting of keys */
2417                 if(!cancelled) {
2418                         autokeyframe_pose_cb_func(ob, t->mode, targetless_ik);
2419                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2420                 }
2421                 else if(arm->flag & ARM_DELAYDEFORM) {
2422                         /* old optimize trick... this enforces to bypass the depgraph */
2423                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2424                         ob->recalc= 0;  // is set on OK position already by recalcData()
2425                 }
2426                 else 
2427                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2428                 
2429                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2430                         allqueue(REDRAWBUTSEDIT, 0);
2431
2432         }
2433         else {
2434                 base= FIRSTBASE;
2435                 while(base) {   
2436                         
2437                         if(base->flag & BA_DO_IPO) redrawipo= 1;
2438                         
2439                         ob= base->object;
2440
2441                         if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
2442                         
2443                         /* Set autokey if necessary */
2444                         if ((!cancelled) && (base->flag & SELECT)){
2445                                 autokeyframe_ob_cb_func(ob, t->mode);
2446                         }
2447                         
2448                         base= base->next;
2449                 }
2450                 
2451         }
2452         
2453         clear_trans_object_base_flags();
2454         
2455         if(redrawipo) {
2456                 allqueue(REDRAWNLA, 0);
2457                 allqueue(REDRAWACTION, 0);
2458                 allqueue(REDRAWIPO, 0);
2459         }
2460         
2461         reset_slowparents();
2462         
2463         /* note; should actually only be done for all objects when a lamp is moved... (ton) */
2464         if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
2465                 reshadeall_displist();
2466 }
2467
2468 static void createTransObject(TransInfo *t)
2469 {
2470         TransData *td = NULL;
2471         TransDataExtension *tx;
2472         Object *ob;
2473         Base *base;
2474         IpoKey *ik;
2475         ListBase elems;
2476         
2477         set_trans_object_base_flags(t);
2478
2479         /* count */     
2480         for(base= FIRSTBASE; base; base= base->next) {
2481                 if TESTBASELIB(base) {
2482                         ob= base->object;
2483                         
2484                         /* store ipo keys? */
2485                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2486                                 elems.first= elems.last= NULL;
2487                                 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
2488                                 
2489                                 pushdata(&elems, sizeof(ListBase));
2490                                 
2491                                 for(ik= elems.first; ik; ik= ik->next) t->total++;
2492
2493                                 if(elems.first==NULL) t->total++;
2494                         }
2495                         else {
2496                                 t->total++;
2497                         }
2498                 }
2499         }
2500
2501         if(!t->total) {
2502                 /* clear here, main transform function escapes too */
2503                 clear_trans_object_base_flags();
2504                 return;
2505         }
2506         
2507         td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
2508         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
2509
2510         for(base= FIRSTBASE; base; base= base->next) {
2511                 if TESTBASELIB(base) {
2512                         ob= base->object;
2513                         
2514                         td->flag= TD_SELECTED;
2515                         td->protectflag= ob->protectflag;
2516                         td->ext = tx;
2517
2518                         /* store ipo keys? */
2519                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2520                                 
2521                                 popfirst(&elems);       // bring back pushed listbase
2522                                 
2523                                 if(elems.first) {
2524                                         int cfraont;
2525                                         int ipoflag;
2526                                         
2527                                         base->flag |= BA_DO_IPO+BA_WAS_SEL;
2528                                         base->flag &= ~SELECT;
2529                                         
2530                                         cfraont= CFRA;
2531                                         set_no_parent_ipo(1);
2532                                         ipoflag= ob->ipoflag;
2533                                         ob->ipoflag &= ~OB_OFFS_OB;
2534                                         
2535                                         /*
2536                                          * This is really EVIL code that pushes down Object values
2537                                          * (loc, dloc, orig, size, dsize, rot, drot)
2538                                          * */
2539                                          
2540                                         pushdata((void*)ob->loc, 7 * 3 * sizeof(float)); // tsk! tsk!
2541                                         
2542                                         for(ik= elems.first; ik; ik= ik->next) {
2543                                                 
2544                                                 /* weak... this doesn't correct for floating values, giving small errors */
2545                                                 CFRA= (int)(ik->val/G.scene->r.framelen);
2546                                                 
2547                                                 do_ob_ipo(ob);
2548                                                 ObjectToTransData(td, ob);      // does where_is_object()
2549                                                 
2550                                                 td->flag= TD_SELECTED;
2551                                                 
2552                                                 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
2553                                                 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
2554                                                 ipokey_to_transdata(ik, td);
2555                                                 
2556                                                 td++;
2557                                                 tx++;
2558                                                 if(ik->next) td->ext= tx;       // prevent corrupting mem!
2559                                         }
2560                                         free_ipokey(&elems);
2561                                         
2562                                         poplast(ob->loc);
2563                                         set_no_parent_ipo(0);
2564                                         
2565                                         CFRA= cfraont;
2566                                         ob->ipoflag= ipoflag;
2567                                         
2568                                         where_is_object(ob);    // restore 
2569                                 }
2570                                 else {
2571                                         ObjectToTransData(td, ob);
2572                                         td->tdi = NULL;
2573                                         td->val = NULL;
2574                                         td++;
2575                                         tx++;
2576                                 }
2577                         }
2578                         else {
2579                                 ObjectToTransData(td, ob);
2580                                 td->tdi = NULL;
2581                                 td->val = NULL;
2582                                 td++;
2583                                 tx++;
2584                         }
2585                 }
2586         }
2587 }
2588
2589 void createTransData(TransInfo *t) 
2590 {
2591         Object *ob= OBACT;
2592         
2593         if (t->context == CTX_TEXTURE) {
2594                 t->flag |= T_TEXTURE;
2595                 createTransTexspace(t);
2596         }
2597         else if (t->context == CTX_EDGE) {
2598                 t->ext = NULL;
2599                 t->flag |= T_EDIT;
2600                 createTransEdge(t);
2601                 if(t->data && t->flag & T_PROP_EDIT) {
2602                         sort_trans_data(t);     // makes selected become first in array
2603                         set_prop_dist(t, 1);
2604                         sort_trans_data_dist(t);
2605                 }
2606         }
2607         else if (t->spacetype == SPACE_IMAGE) {
2608                 t->flag |= T_POINTS|T_2D_EDIT;
2609                 createTransUVs(t);
2610                 if(t->data && (t->flag & T_PROP_EDIT)) {
2611                         sort_trans_data(t);     // makes selected become first in array
2612                         set_prop_dist(t, 1);
2613                         sort_trans_data_dist(t);
2614                 }
2615         }
2616         else if (G.obedit) {
2617                 t->ext = NULL;
2618                 if (G.obedit->type == OB_MESH) {
2619                         createTransEditVerts(t);        
2620                 }
2621                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
2622                         createTransCurveVerts(t);
2623                 }
2624                 else if (G.obedit->type==OB_LATTICE) {
2625                         createTransLatticeVerts(t);
2626                 }
2627                 else if (G.obedit->type==OB_MBALL) {
2628                         createTransMBallVerts(t);
2629                 }
2630                 else if (G.obedit->type==OB_ARMATURE) {
2631                         t->flag &= ~T_PROP_EDIT;
2632                         createTransArmatureVerts(t);
2633                 }                                                       
2634                 else {
2635                         printf("not done yet! only have mesh surface curve\n");
2636                 }
2637
2638                 if(t->data && t->flag & T_PROP_EDIT) {
2639                         if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
2640                                 sort_trans_data(t);     // makes selected become first in array
2641                                 set_prop_dist(t, 0);
2642                                 sort_trans_data_dist(t);
2643                         }
2644                         else {
2645                                 sort_trans_data(t);     // makes selected become first in array
2646                                 set_prop_dist(t, 1);
2647                                 sort_trans_data_dist(t);
2648                         }
2649                 }
2650
2651                 t->flag |= T_EDIT|T_POINTS;
2652                 
2653                 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
2654                 if(t->mode==TFM_BONESIZE) {
2655                         t->flag &= ~(T_EDIT|T_POINTS);
2656                         t->flag |= T_POSE;
2657                         t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
2658                 }
2659         }
2660         else if (ob && (ob->flag & OB_POSEMODE)) {
2661                 createTransPose(t, OBACT);
2662         }
2663         else if (G.f & G_WEIGHTPAINT) {
2664                 /* exception, we look for the one selected armature */
2665                 Base *base;
2666                 for(base=FIRSTBASE; base; base= base->next) {
2667                         if(TESTBASELIB(base)) {
2668                                 if(base->object->type==OB_ARMATURE)
2669                                         if(base->object->flag & OB_POSEMODE)
2670                                                 break;
2671                         }
2672                 }
2673                 if(base) {
2674                         createTransPose(t, base->object);
2675                 }
2676         }
2677         else {
2678                 createTransObject(t);
2679                 t->flag |= T_OBJECT;
2680         }
2681
2682         if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
2683                 t->flag |= T_CAMERA;
2684         }
2685         
2686         /* temporal...? */
2687         G.scene->recalc |= SCE_PRV_CHANGED;     /* test for 3d preview */
2688 }
2689