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