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