svn merge -r 12391:12419 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 (G.f & G_HIDDENHANDLES) {
1142                                                 if(bezt->f2 & 1) countsel+=3;
1143                                                 if(propmode) count+= 3;
1144                                         } else {
1145                                                 if(bezt->f1 & 1) countsel++;
1146                                                 if(bezt->f2 & 1) countsel++;
1147                                                 if(bezt->f3 & 1) countsel++;
1148                                                 if(propmode) count+= 3;
1149                                         }
1150                                 }
1151                         }
1152                 }
1153                 else {
1154                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1155                                 if(bp->hide==0) {
1156                                         if(propmode) count++;
1157                                         if(bp->f1 & 1) countsel++;
1158                                 }
1159                         }
1160                 }
1161         }
1162         /* note: in prop mode we need at least 1 selected */
1163         if (countsel==0) return;
1164         
1165         if(propmode) t->total = count; 
1166         else t->total = countsel;
1167         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1168
1169         Mat3CpyMat4(mtx, G.obedit->obmat);
1170         Mat3Inv(smtx, mtx);
1171
1172     td = t->data;
1173         for(nu= editNurb.first; nu; nu= nu->next) {
1174                 if((nu->type & 7)==CU_BEZIER) {
1175                         TransData *head, *tail;
1176                         head = tail = td;
1177                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1178                                 if(bezt->hide==0) {
1179                                         
1180                                         if(             propmode ||
1181                                                         ((bezt->f2 & 1) && (G.f & G_HIDDENHANDLES)) ||
1182                                                         ((bezt->f1 & 1) && (G.f & G_HIDDENHANDLES)==0)
1183                                           ) {
1184                                                 VECCOPY(td->iloc, bezt->vec[0]);
1185                                                 td->loc= bezt->vec[0];
1186                                                 VECCOPY(td->center, bezt->vec[1]);
1187                                                 if(bezt->f1 & 1 || G.f & G_HIDDENHANDLES) td->flag= TD_SELECTED;
1188                                                 else td->flag= 0;
1189                                                 td->ext = NULL;
1190                                                 td->tdi = NULL;
1191                                                 td->val = NULL;
1192
1193                                                 Mat3CpyMat3(td->smtx, smtx);
1194                                                 Mat3CpyMat3(td->mtx, mtx);
1195
1196                                                 td++;
1197                                                 count++;
1198                                                 tail++;
1199                                         }
1200                                         
1201                                         /* This is the Curve Point, the other two are handles */
1202                                         if(propmode || (bezt->f2 & 1)) {
1203                                                 VECCOPY(td->iloc, bezt->vec[1]);
1204                                                 td->loc= bezt->vec[1];
1205                                                 VECCOPY(td->center, td->loc);
1206                                                 if(bezt->f2 & 1) td->flag= TD_SELECTED;
1207                                                 else td->flag= 0;
1208                                                 td->ext = NULL;
1209                                                 td->tdi = NULL;
1210                                                 
1211                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1212                                                         td->val = &(bezt->radius);
1213                                                         td->ival = bezt->radius;
1214                                                 } else if (t->mode==TFM_TILT) {
1215                                                         td->val = &(bezt->alfa);
1216                                                         td->ival = bezt->alfa;
1217                                                 } else {
1218                                                         td->val = NULL;
1219                                                 }
1220
1221                                                 Mat3CpyMat3(td->smtx, smtx);
1222                                                 Mat3CpyMat3(td->mtx, mtx);
1223
1224                                                 td++;
1225                                                 count++;
1226                                                 tail++;
1227                                         }
1228                                         if(             propmode ||
1229                                                         ((bezt->f1 & 1) && (G.f & G_HIDDENHANDLES)) ||
1230                                                         ((bezt->f3 & 1) && (G.f & G_HIDDENHANDLES)==0)
1231                                           ) {
1232                                                 VECCOPY(td->iloc, bezt->vec[2]);
1233                                                 td->loc= bezt->vec[2];
1234                                                 VECCOPY(td->center, bezt->vec[1]);
1235                                                 if(bezt->f3 & 1 || (G.f & G_HIDDENHANDLES)) td->flag= TD_SELECTED;
1236                                                 else td->flag= 0;
1237                                                 td->ext = NULL;
1238                                                 td->tdi = NULL;
1239                                                 td->val = NULL;
1240
1241                                                 Mat3CpyMat3(td->smtx, smtx);
1242                                                 Mat3CpyMat3(td->mtx, mtx);
1243
1244                                                 td++;
1245                                                 count++;
1246                                                 tail++;
1247                                         }
1248                                 }
1249                                 else if (propmode && head != tail) {
1250                                         calc_distanceCurveVerts(head, tail-1);
1251                                         head = tail;
1252                                 }
1253                         }
1254                         if (propmode && head != tail)
1255                                 calc_distanceCurveVerts(head, tail-1);
1256                 }
1257                 else {
1258                         TransData *head, *tail;
1259                         head = tail = td;
1260                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1261                                 if(bp->hide==0) {
1262                                         if(propmode || (bp->f1 & 1)) {
1263                                                 VECCOPY(td->iloc, bp->vec);
1264                                                 td->loc= bp->vec;
1265                                                 VECCOPY(td->center, td->loc);
1266                                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
1267                                                 else td->flag= 0;
1268                                                 td->ext = NULL;
1269                                                 td->tdi = NULL;
1270                                                 
1271                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1272                                                         td->val = &(bp->radius);
1273                                                         td->ival = bp->radius;
1274                                                 } else {
1275                                                         td->val = &(bp->alfa);
1276                                                         td->ival = bp->alfa;
1277                                                 }
1278
1279                                                 Mat3CpyMat3(td->smtx, smtx);
1280                                                 Mat3CpyMat3(td->mtx, mtx);
1281
1282                                                 td++;
1283                                                 count++;
1284                                                 tail++;
1285                                         }
1286                                 }
1287                                 else if (propmode && head != tail) {
1288                                         calc_distanceCurveVerts(head, tail-1);
1289                                         head = tail;
1290                                 }
1291                         }
1292                         if (propmode && head != tail)
1293                                 calc_distanceCurveVerts(head, tail-1);
1294                 }
1295         }
1296 }
1297
1298 /* ********************* lattice *************** */
1299
1300 static void createTransLatticeVerts(TransInfo *t)
1301 {
1302         TransData *td = NULL;
1303         BPoint *bp;
1304         float mtx[3][3], smtx[3][3];
1305         int a;
1306         int count=0, countsel=0;
1307         int propmode = t->flag & T_PROP_EDIT;
1308
1309         bp= editLatt->def;
1310         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1311         while(a--) {
1312                 if(bp->hide==0) {
1313                         if(bp->f1 & 1) countsel++;
1314                         if(propmode) count++;
1315                 }
1316                 bp++;
1317         }
1318         
1319         /* note: in prop mode we need at least 1 selected */
1320         if (countsel==0) return;
1321         
1322         if(propmode) t->total = count; 
1323         else t->total = countsel;
1324         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1325         
1326         Mat3CpyMat4(mtx, G.obedit->obmat);
1327         Mat3Inv(smtx, mtx);
1328
1329         td = t->data;
1330         bp= editLatt->def;
1331         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1332         while(a--) {
1333                 if(propmode || (bp->f1 & 1)) {
1334                         if(bp->hide==0) {
1335                                 VECCOPY(td->iloc, bp->vec);
1336                                 td->loc= bp->vec;
1337                                 VECCOPY(td->center, td->loc);
1338                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
1339                                 else td->flag= 0;
1340                                 Mat3CpyMat3(td->smtx, smtx);
1341                                 Mat3CpyMat3(td->mtx, mtx);
1342
1343                                 td->ext = NULL;
1344                                 td->tdi = NULL;
1345                                 td->val = NULL;
1346
1347                                 td++;
1348                                 count++;
1349                         }
1350                 }
1351                 bp++;
1352         }
1353
1354
1355 /* ********************* mesh ****************** */
1356
1357 /* proportional distance based on connectivity  */
1358 #define E_VEC(a)        (vectors + (3 * (a)->tmp.l))
1359 #define E_NEAR(a)       (nears[((a)->tmp.l)])
1360 #define THRESHOLD       0.0001f
1361 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1362 {
1363         EditMesh *em = G.editMesh;
1364         EditVert *eve;
1365         EditEdge *eed;
1366         int i= 0, done= 1;
1367
1368         /* f2 flag is used for 'selection' */
1369         /* tmp.l is offset on scratch array   */
1370         for(eve= em->verts.first; eve; eve= eve->next) {
1371                 if(eve->h==0) {
1372                         eve->tmp.l = i++;
1373
1374                         if(eve->f & SELECT) {
1375                                 eve->f2= 2;
1376                                 E_NEAR(eve) = eve;
1377                                 E_VEC(eve)[0] = 0.0f;
1378                                 E_VEC(eve)[1] = 0.0f;
1379                                 E_VEC(eve)[2] = 0.0f;
1380                         }
1381                         else {
1382                                 eve->f2 = 0;
1383                         }
1384                 }
1385         }
1386
1387
1388         /* Floodfill routine */
1389         /*
1390         At worst this is n*n of complexity where n is number of edges 
1391         Best case would be n if the list is ordered perfectly.
1392         Estimate is n log n in average (so not too bad)
1393         */
1394         while(done) {
1395                 done= 0;
1396                 
1397                 for(eed= em->edges.first; eed; eed= eed->next) {
1398                         if(eed->h==0) {
1399                                 EditVert *v1= eed->v1, *v2= eed->v2;
1400                                 float *vec2 = E_VEC(v2);
1401                                 float *vec1 = E_VEC(v1);
1402
1403                                 if (v1->f2 + v2->f2 == 4)
1404                                         continue;
1405
1406                                 if (v1->f2) {
1407                                         if (v2->f2) {
1408                                                 float nvec[3];
1409                                                 float len1 = VecLength(vec1);
1410                                                 float len2 = VecLength(vec2);
1411                                                 float lenn;
1412                                                 /* for v2 if not selected */
1413                                                 if (v2->f2 != 2) {
1414                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1415                                                         lenn = VecLength(nvec);
1416                                                         /* 1 < n < 2 */
1417                                                         if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1418                                                                 VECCOPY(vec2, nvec);
1419                                                                 E_NEAR(v2) = E_NEAR(v1);
1420                                                                 done = 1;
1421                                                         }
1422                                                         /* n < 1 < 2 */
1423                                                         else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1424                                                                 VECCOPY(vec2, vec1);
1425                                                                 E_NEAR(v2) = E_NEAR(v1);
1426                                                                 done = 1;
1427                                                         }
1428                                                 }
1429                                                 /* for v1 if not selected */
1430                                                 if (v1->f2 != 2) {
1431                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1432                                                         lenn = VecLength(nvec);
1433                                                         /* 2 < n < 1 */
1434                                                         if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1435                                                                 VECCOPY(vec1, nvec);
1436                                                                 E_NEAR(v1) = E_NEAR(v2);
1437                                                                 done = 1;
1438                                                         }
1439                                                         /* n < 2 < 1 */
1440                                                         else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1441                                                                 VECCOPY(vec1, vec2);
1442                                                                 E_NEAR(v1) = E_NEAR(v2);
1443                                                                 done = 1;
1444                                                         }
1445                                                 }
1446                                         }
1447                                         else {
1448                                                 v2->f2 = 1;
1449                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1450                                                 /* 2 < 1 */
1451                                                 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1452                                                         VECCOPY(vec2, vec1);
1453                                                 }
1454                                                 E_NEAR(v2) = E_NEAR(v1);
1455                                                 done = 1;
1456                                         }
1457                                 }
1458                                 else if (v2->f2) {
1459                                         v1->f2 = 1;
1460                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1461                                         /* 2 < 1 */
1462                                         if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1463                                                 VECCOPY(vec1, vec2);
1464                                         }
1465                                         E_NEAR(v1) = E_NEAR(v2);
1466                                         done = 1;
1467                                 }
1468                         }
1469                 }
1470         }
1471 }
1472
1473 /* loop-in-a-loop I know, but we need it! (ton) */
1474 static void get_face_center(float *cent, EditVert *eve)
1475 {
1476         EditMesh *em = G.editMesh;
1477         EditFace *efa;
1478         
1479         for(efa= em->faces.first; efa; efa= efa->next)
1480                 if(efa->f & SELECT)
1481                         if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1482                                 break;
1483         if(efa) {
1484                 VECCOPY(cent, efa->cent);
1485         }
1486 }
1487
1488 static void VertsToTransData(TransData *td, EditVert *eve)
1489 {
1490         td->flag = 0;
1491         td->loc = eve->co;
1492         
1493         VECCOPY(td->center, td->loc);
1494         if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1495                 get_face_center(td->center, eve);
1496         VECCOPY(td->iloc, td->loc);
1497
1498         // Setting normals
1499         VECCOPY(td->axismtx[2], eve->no);
1500         td->axismtx[0][0]               =
1501                 td->axismtx[0][1]       =
1502                 td->axismtx[0][2]       =
1503                 td->axismtx[1][0]       =
1504                 td->axismtx[1][1]       =
1505                 td->axismtx[1][2]       = 0.0f;
1506
1507         td->ext = NULL;
1508         td->tdi = NULL;
1509         td->val = NULL;
1510         td->tdmir= NULL;
1511
1512 #ifdef WITH_VERSE
1513         if(eve->vvert) {
1514                 td->verse = (void*)eve->vvert;
1515                 td->flag |= TD_VERSE_VERT;
1516         }
1517         else
1518                 td->flag &= ~TD_VERSE_VERT;
1519 #endif
1520 }
1521
1522 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1523
1524 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1525 {
1526         float *vec = userData;
1527         
1528         vec+= 3*index;
1529         VECCOPY(vec, co);
1530 }
1531
1532 static int modifiers_disable_subsurf_temporary(Object *ob)
1533 {
1534         ModifierData *md;
1535         int disabled = 0;
1536         
1537         for(md=ob->modifiers.first; md; md=md->next)
1538                 if(md->type==eModifierType_Subsurf)
1539                         if(md->mode & eModifierMode_OnCage) {
1540                                 md->mode ^= eModifierMode_DisableTemporary;
1541                                 disabled= 1;
1542                         }
1543         
1544         return disabled;
1545 }
1546
1547 /* disable subsurf temporal, get mapped cos, and enable it */
1548 static float *get_crazy_mapped_editverts(void)
1549 {
1550         DerivedMesh *dm;
1551         float *vertexcos;
1552
1553         /* disable subsurf temporal, get mapped cos, and enable it */
1554         if(modifiers_disable_subsurf_temporary(G.obedit)) {
1555                 /* need to make new derivemesh */
1556                 makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
1557         }
1558
1559         /* now get the cage */
1560         dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
1561
1562         vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1563         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1564         
1565         dm->release(dm);
1566         
1567         /* set back the flag, no new cage needs to be built, transform does it */
1568         modifiers_disable_subsurf_temporary(G.obedit);
1569         
1570         return vertexcos;
1571 }
1572
1573 #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])
1574 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1575 {
1576         float vecu[3], vecv[3];
1577         float q1[4], q2[4];
1578         
1579         TAN_MAKE_VEC(vecu, v1, v2);
1580         TAN_MAKE_VEC(vecv, v1, v3);
1581         triatoquat(v1, vecu, vecv, q1);
1582         
1583         TAN_MAKE_VEC(vecu, def1, def2);
1584         TAN_MAKE_VEC(vecv, def1, def3);
1585         triatoquat(def1, vecu, vecv, q2);
1586         
1587         QuatSub(quat, q2, q1);
1588 }
1589 #undef TAN_MAKE_VEC
1590
1591 static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats)
1592 {
1593         EditMesh *em = G.editMesh;
1594         EditVert *eve, *prev;
1595         EditFace *efa;
1596         float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
1597         long index= 0;
1598         
1599         /* two abused locations in vertices */
1600         for(eve= em->verts.first; eve; eve= eve->next, index++) {
1601                 eve->tmp.p = NULL;
1602                 eve->prev= (EditVert *)index;
1603         }
1604         
1605         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
1606         for(efa= em->faces.first; efa; efa= efa->next) {
1607                 
1608                 /* retrieve mapped coordinates */
1609                 v1= mappedcos + 3*(long)(efa->v1->prev);
1610                 v2= mappedcos + 3*(long)(efa->v2->prev);
1611                 v3= mappedcos + 3*(long)(efa->v3->prev);
1612
1613                 co1= (origcos)? origcos + 3*(long)(efa->v1->prev): efa->v1->co;
1614                 co2= (origcos)? origcos + 3*(long)(efa->v2->prev): efa->v2->co;
1615                 co3= (origcos)? origcos + 3*(long)(efa->v3->prev): efa->v3->co;
1616
1617                 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
1618                         set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
1619                         efa->v2->tmp.p= (void*)quats;
1620                         quats+= 4;
1621                 }
1622                 
1623                 if(efa->v4) {
1624                         v4= mappedcos + 3*(long)(efa->v4->prev);
1625                         co4= (origcos)? origcos + 3*(long)(efa->v4->prev): efa->v4->co;
1626
1627                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
1628                                 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
1629                                 efa->v1->tmp.p= (void*)quats;
1630                                 quats+= 4;
1631                         }
1632                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
1633                                 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
1634                                 efa->v3->tmp.p= (void*)quats;
1635                                 quats+= 4;
1636                         }
1637                         if(efa->v4->tmp.p==NULL && efa->v4->f1) {
1638                                 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
1639                                 efa->v4->tmp.p= (void*)quats;
1640                                 quats+= 4;
1641                         }
1642                 }
1643                 else {
1644                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
1645                                 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
1646                                 efa->v1->tmp.p= (void*)quats;
1647                                 quats+= 4;
1648                         }
1649                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
1650                                 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
1651                                 efa->v3->tmp.p= (void*)quats;
1652                                 quats+= 4;
1653                         }
1654                 }
1655         }
1656
1657         /* restore abused prev pointer */
1658         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1659                 eve->prev= prev;
1660
1661 }
1662
1663 static void createTransEditVerts(TransInfo *t)
1664 {
1665         TransData *tob = NULL;
1666         EditMesh *em = G.editMesh;
1667         EditVert *eve;
1668         EditVert **nears = NULL;
1669         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1670         float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
1671         int count=0, countsel=0, a, totleft;
1672         int propmode = t->flag & T_PROP_EDIT;
1673         int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR);
1674
1675         // transform now requires awareness for select mode, so we tag the f1 flags in verts
1676         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1677                 for(eve= em->verts.first; eve; eve= eve->next) {
1678                         if(eve->h==0 && (eve->f & SELECT)) 
1679                                 eve->f1= SELECT;
1680                         else
1681                                 eve->f1= 0;
1682                 }
1683         }
1684         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1685                 EditEdge *eed;
1686                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1687                 for(eed= em->edges.first; eed; eed= eed->next) {
1688                         if(eed->h==0 && (eed->f & SELECT))
1689                                 eed->v1->f1= eed->v2->f1= SELECT;
1690                 }
1691         }
1692         else {
1693                 EditFace *efa;
1694                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1695                 for(efa= em->faces.first; efa; efa= efa->next) {
1696                         if(efa->h==0 && (efa->f & SELECT)) {
1697                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1698                                 if(efa->v4) efa->v4->f1= SELECT;
1699                         }
1700                 }
1701         }
1702         
1703         /* now we can count */
1704         for(eve= em->verts.first; eve; eve= eve->next) {
1705                 if(eve->h==0) {
1706                         if(eve->f1) countsel++;
1707                         if(propmode) count++;
1708                 }
1709         }
1710         
1711         /* note: in prop mode we need at least 1 selected */
1712         if (countsel==0) return;
1713         
1714         if(propmode) {
1715                 t->total = count; 
1716         
1717                 /* allocating scratch arrays */
1718                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1719                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1720         }
1721         else t->total = countsel;
1722         tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1723         
1724         Mat3CpyMat4(mtx, G.obedit->obmat);
1725         Mat3Inv(smtx, mtx);
1726
1727         if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1728         
1729         /* detect CrazySpace [tm] */
1730         if(propmode==0) {
1731                 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
1732                         if(modifiers_isDeformed(G.obedit)) {
1733                                 /* check if we can use deform matrices for modifier from the
1734                                    start up to stack, they are more accurate than quats */
1735                                 totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
1736
1737                                 /* if we still have more modifiers, also do crazyspace
1738                                    correction with quats, relative to the coordinates after
1739                                    the modifiers that support deform matrices (defcos) */
1740                                 if(totleft > 0) {
1741                                         mappedcos= get_crazy_mapped_editverts();
1742                                         quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
1743                                         set_crazyspace_quats((float*)defcos, mappedcos, quats);
1744                                         if(mappedcos)
1745                                                 MEM_freeN(mappedcos);
1746                                 }
1747
1748                                 if(defcos)
1749                                         MEM_freeN(defcos);
1750                         }
1751                 }
1752         }
1753         
1754         /* find out which half we do */
1755         if(mirror) {
1756                 for (eve=em->verts.first; eve; eve=eve->next) {
1757                         if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
1758                                 if(eve->co[0]<0.0f)
1759                                         mirror = -1;
1760                                 break;
1761                         }
1762                 }
1763         }
1764         
1765         for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
1766                 if(eve->h==0) {
1767                         if(propmode || eve->f1) {
1768                                 VertsToTransData(tob, eve);
1769
1770                                 if(eve->f1) tob->flag |= TD_SELECTED;
1771                                 if(propmode) {
1772                                         if (eve->f2) {
1773                                                 float vec[3];
1774                                                 VECCOPY(vec, E_VEC(eve));
1775                                                 Mat3MulVecfl(mtx, vec);
1776                                                 tob->dist= VecLength(vec);
1777                                         }
1778                                         else {
1779                                                 tob->flag |= TD_NOTCONNECTED;
1780                                                 tob->dist = MAXFLOAT;
1781                                         }
1782                                 }
1783                                 
1784                                 /* CrazySpace */
1785                                 if(defmats || (quats && eve->tmp.p)) {
1786                                         float mat[3][3], imat[3][3], qmat[3][3];
1787                                         
1788                                         /* use both or either quat and defmat correction */
1789                                         if(quats && eve->tmp.f) {
1790                                                 QuatToMat3(eve->tmp.p, qmat);
1791
1792                                                 if(defmats)
1793                                                         Mat3MulSerie(mat, mtx, qmat, defmats[a],
1794                                                                 NULL, NULL, NULL, NULL, NULL);
1795                                                 else
1796                                                         Mat3MulMat3(mat, mtx, qmat);
1797                                         }
1798                                         else
1799                                                 Mat3MulMat3(mat, mtx, defmats[a]);
1800
1801                                         Mat3Inv(imat, mat);
1802                                         
1803                                         Mat3CpyMat3(tob->smtx, imat);
1804                                         Mat3CpyMat3(tob->mtx, mat);
1805                                 }
1806                                 else {
1807                                         Mat3CpyMat3(tob->smtx, smtx);
1808                                         Mat3CpyMat3(tob->mtx, mtx);
1809                                 }
1810                                 
1811                                 /* Mirror? */
1812                                 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
1813                                         EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc);        /* initializes octree on first call */
1814                                         if(vmir!=eve) tob->tdmir= vmir;
1815                                 }
1816                                 tob++;
1817                         }
1818                 }       
1819         }
1820         if (propmode) {
1821                 MEM_freeN(vectors);
1822                 MEM_freeN(nears);
1823         }
1824         /* crazy space free */
1825         if(quats)
1826                 MEM_freeN(quats);
1827         if(defmats)
1828                 MEM_freeN(defmats);
1829 }
1830
1831 /* ********************* UV ****************** */
1832
1833 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
1834 {
1835         float aspx, aspy;
1836
1837         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1838
1839         /* uv coords are scaled by aspects. this is needed for rotations and
1840            proportional editing to be consistent with the stretchted uv coords
1841            that are displayed. this also means that for display and numinput,
1842            and when the the uv coords are flushed, these are converted each time */
1843         td2d->loc[0] = uv[0]*aspx;
1844         td2d->loc[1] = uv[1]*aspy;
1845         td2d->loc[2] = 0.0f;
1846         td2d->loc2d = uv;
1847
1848         td->flag = 0;
1849         td->loc = td2d->loc;
1850         VECCOPY(td->center, td->loc);
1851         VECCOPY(td->iloc, td->loc);
1852
1853         memset(td->axismtx, 0, sizeof(td->axismtx));
1854         td->axismtx[2][2] = 1.0f;
1855
1856         td->ext= NULL; td->tdi= NULL; td->val= NULL;
1857
1858         if(selected) {
1859                 td->flag |= TD_SELECTED;
1860                 td->dist= 0.0;
1861         }
1862         else
1863                 td->dist= MAXFLOAT;
1864         
1865         Mat3One(td->mtx);
1866         Mat3One(td->smtx);
1867 }
1868
1869 static void createTransUVs(TransInfo *t)
1870 {
1871         TransData *td = NULL;
1872         TransData2D *td2d = NULL;
1873         MTFace *tf;
1874         int count=0, countsel=0;
1875         int propmode = t->flag & T_PROP_EDIT;
1876         
1877         EditMesh *em = G.editMesh;
1878         EditFace *efa;
1879         
1880         if(is_uv_tface_editing_allowed()==0) return;
1881
1882         /* count */
1883         for (efa= em->faces.first; efa; efa= efa->next) {
1884                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1885                 if SIMA_FACEDRAW_CHECK(efa, tf) {
1886                         if (SIMA_UVSEL_CHECK(efa, tf, 0)) countsel++; 
1887                         if (SIMA_UVSEL_CHECK(efa, tf, 1)) countsel++; 
1888                         if (SIMA_UVSEL_CHECK(efa, tf, 2)) countsel++; 
1889                         if (efa->v4 && SIMA_UVSEL_CHECK(efa, tf, 3)) countsel++;
1890                         if(propmode)
1891                                 count += (efa->v4)? 4: 3;
1892                 }
1893         }
1894
1895         /* note: in prop mode we need at least 1 selected */
1896         if (countsel==0) return;
1897         
1898         t->total= (propmode)? count: countsel;
1899         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
1900         /* for each 2d uv coord a 3d vector is allocated, so that they can be
1901            treated just as if they were 3d verts */
1902         t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
1903
1904         if(G.sima->flag & SI_CLIP_UV)
1905                 t->flag |= T_CLIP_UV;
1906
1907         td= t->data;
1908         td2d= t->data2d;
1909         for (efa= em->faces.first; efa; efa= efa->next) {
1910                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1911                 if SIMA_FACEDRAW_CHECK(efa, tf) {
1912                         if(propmode || SIMA_UVSEL_CHECK(efa, tf, 0))
1913                                 UVsToTransData(td++, td2d++, tf->uv[0], SIMA_UVSEL_CHECK(efa, tf, 0));
1914                         if(propmode || SIMA_UVSEL_CHECK(efa, tf, 1))
1915                                 UVsToTransData(td++, td2d++, tf->uv[1], SIMA_UVSEL_CHECK(efa, tf, 1));
1916                         if(propmode || SIMA_UVSEL_CHECK(efa, tf, 2))
1917                                 UVsToTransData(td++, td2d++, tf->uv[2], SIMA_UVSEL_CHECK(efa, tf, 2));
1918
1919                         if(efa->v4 && (propmode || SIMA_UVSEL_CHECK(efa, tf, 3)))
1920                                 UVsToTransData(td++, td2d++, tf->uv[3], SIMA_UVSEL_CHECK(efa, tf, 3));
1921                 }
1922         }
1923
1924         if (G.sima->flag & SI_LIVE_UNWRAP)
1925                 unwrap_lscm_live_begin();
1926 }
1927
1928 void flushTransUVs(TransInfo *t)
1929 {
1930         TransData2D *td;
1931         int a, width, height;
1932         Object *ob= OBACT;
1933         EditMesh *em = G.editMesh;
1934         float aspx, aspy, invx, invy;
1935
1936         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1937         transform_width_height_tface_uv(&width, &height);
1938         invx= 1.0f/aspx;
1939         invy= 1.0f/aspy;
1940
1941         /* flush to 2d vector from internally used 3d vector */
1942         for(a=0, td= t->data2d; a<t->total; a++, td++) {
1943                 td->loc2d[0]= td->loc[0]*invx;
1944                 td->loc2d[1]= td->loc[1]*invy;
1945                 
1946                 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
1947                         td->loc2d[0]= floor(width*td->loc2d[0] + 0.5f)/width;
1948                         td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height;
1949                 }
1950         }
1951
1952         /* always call this, also for cancel (it transforms non-selected vertices...) */
1953         if((G.sima->flag & SI_BE_SQUARE))
1954                 be_square_tface_uv(em);
1955
1956         /* this is overkill if G.sima->lock is not set, but still needed */
1957         object_uvs_changed(ob);
1958 }
1959
1960 int clipUVTransform(TransInfo *t, float *vec, int resize)
1961 {
1962         TransData *td;
1963         int a, clipx=1, clipy=1;
1964         float aspx, aspy, min[2], max[2];
1965
1966         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1967         min[0]= min[1]= 0.0f;
1968         max[0]= aspx; max[1]= aspy;
1969
1970         for(a=0, td= t->data; a<t->total; a++, td++) {
1971                 DO_MINMAX2(td->loc, min, max);
1972         }
1973
1974         if(resize) {
1975                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
1976                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
1977                 else if(max[0] > aspx && t->center[0] < aspx)
1978                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
1979                 else
1980                         clipx= 0;
1981
1982                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
1983                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
1984                 else if(max[1] > aspy && t->center[1] < aspy)
1985                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
1986                 else
1987                         clipy= 0;
1988         }
1989         else {
1990                 if(min[0] < 0.0f)
1991                         vec[0] -= min[0];
1992                 else if(max[0] > aspx)
1993                         vec[0] -= max[0]-aspx;
1994                 else
1995                         clipx= 0;
1996
1997                 if(min[1] < 0.0f)
1998                         vec[1] -= min[1];
1999                 else if(max[1] > aspy)
2000                         vec[1] -= max[1]-aspy;
2001                 else
2002                         clipy= 0;
2003         }       
2004
2005         return (clipx || clipy);
2006 }
2007
2008 /* ********************* IPO EDITOR ************************* */
2009
2010 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2011  * due to bad globals that would need to be imported specially for this
2012  */
2013 static void createTransIpoData(TransInfo *t)
2014 {
2015         /* in editipo.c due to some globals that are defined in that file... */
2016         make_ipo_transdata(t);
2017 }
2018
2019 /* this function is called on recalcData to apply the transforms applied
2020  * to the transdata on to the actual keyframe data 
2021  */
2022 void flushTransIpoData(TransInfo *t)
2023 {
2024         TransData2D *td;
2025         int a;
2026         
2027         /* flush to 2d vector from internally used 3d vector */
2028         for (a=0, td= t->data2d; a<t->total; a++, td++) {
2029                 /* we need to unapply the nla-scaling from the time in some situations */
2030                 if (NLA_IPO_SCALED)
2031                         td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2032                 else
2033                         td->loc2d[0]= td->loc[0];
2034                 
2035                 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2036                 if ((t->data[a].flag & TD_TIMEONLY)==0)
2037                         td->loc2d[1]= td->loc[1];
2038         }
2039 }
2040
2041 /* ********************* ACTION/NLA EDITOR ****************** */
2042
2043
2044 static void TimeToTransData(TransData *td, float *time, Object *ob)
2045 {
2046         /* memory is calloc'ed, so that should zero everything nicely for us */
2047         td->val = time;
2048         td->ival = *(time);
2049         
2050         /* store the Object where this keyframe exists as a keyframe of the 
2051          * active action as td->ob. Usually, this member is only used for constraints 
2052          * drawing
2053          */
2054         td->ob= ob;
2055 }
2056
2057 /* This function advances the address to which td points to, so it must return
2058  * the new address so that the next time new transform data is added, it doesn't
2059  * overwrite the existing ones...  i.e.   td = IpoToTransData(td, ipo, ob);
2060  */
2061 static TransData *IpoToTransData(TransData *td, Ipo *ipo, Object *ob)
2062 {
2063         IpoCurve *icu;
2064         BezTriple *bezt;
2065         int i;
2066         
2067         if (ipo == NULL)
2068                 return td;
2069         
2070         for (icu= ipo->curve.first; icu; icu= icu->next) {
2071                 /* only add selected keyframes (for now, proportional edit is not enabled) */
2072                 for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
2073                         if (BEZSELECTED(bezt)) {
2074                                 /* each control point needs to be added separetely */
2075                                 TimeToTransData(td, bezt->vec[0], ob);
2076                                 td++;
2077                                 
2078                                 TimeToTransData(td, bezt->vec[1], ob);
2079                                 td++;
2080                                 
2081                                 TimeToTransData(td, bezt->vec[2], ob);
2082                                 td++;
2083                         }       
2084                 }
2085         }
2086         
2087         return td;
2088 }
2089
2090 static void createTransActionData(TransInfo *t)
2091 {
2092         TransData *td = NULL;
2093         Object *ob= NULL;
2094         
2095         ListBase act_data = {NULL, NULL};
2096         bActListElem *ale;
2097         void *data;
2098         short datatype;
2099         int filter;
2100         
2101         int count=0;
2102         
2103         /* determine what type of data we are operating on */
2104         data = get_action_context(&datatype);
2105         if (data == NULL) return;
2106         
2107         /* filter data */
2108         filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
2109         actdata_filter(&act_data, filter, data, datatype);
2110         
2111         /* is the action scaled? if so, the it should belong to the active object */
2112         if (NLA_ACTION_SCALED)
2113                 ob= OBACT;
2114         
2115         /* loop 1: fully select ipo-keys and count how many BezTriples are selected */
2116         for (ale= act_data.first; ale; ale= ale->next)
2117                 count += fullselect_ipo_keys(ale->key_data);
2118         
2119         /* stop if trying to build list if nothing selected */
2120         if (count == 0) {
2121                 /* cleanup temp list */
2122                 BLI_freelistN(&act_data);
2123                 return;
2124         }
2125         
2126         /* allocate memory for data */
2127         t->total= count;
2128         t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)");
2129         if (t->mode == TFM_TIME_SLIDE)
2130                 t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max");
2131         
2132         td= t->data;
2133         /* loop 2: build transdata array */
2134         for (ale= act_data.first; ale; ale= ale->next) {
2135                 Ipo *ipo= (Ipo *)ale->key_data;
2136                 
2137                 td= IpoToTransData(td, ipo, ob);
2138         }
2139         
2140         /* check if we're supposed to be setting minx/maxx for TimeSlide */
2141         if (t->mode == TFM_TIME_SLIDE) {
2142                 float min = 0, max = 0;
2143                 int i;
2144                 
2145                 td= (t->data + 1);
2146                 for (i=1; i < count; i+=3, td+=3) {
2147                         if (min > *(td->val)) min= *(td->val);
2148                         if (max < *(td->val)) max= *(td->val);
2149                 }
2150                 
2151                 /* minx/maxx values used by TimeSlide are stored as a 
2152                  * calloced 2-float array in t->customData. This gets freed
2153                  * in postTrans (T_FREE_CUSTOMDATA). 
2154                  */
2155                 *((float *)(t->customData)) = min;
2156                 *((float *)(t->customData) + 1) = max;
2157         }
2158         
2159         /* cleanup temp list */
2160         BLI_freelistN(&act_data);
2161 }
2162
2163 static void createTransNlaData(TransInfo *t)
2164 {
2165         Base *base;
2166         bActionStrip *strip;
2167         bActionChannel *achan;
2168         bConstraintChannel *conchan;
2169         
2170         TransData *td = NULL;
2171         int count=0, i;
2172         
2173         /* Ensure that partial selections result in beztriple selections */
2174         for (base=G.scene->base.first; base; base=base->next) {
2175                 /* Check object ipos */
2176                 i= fullselect_ipo_keys(base->object->ipo);
2177                 if (i) base->flag |= BA_HAS_RECALC_OB;
2178                 count += i;
2179                 
2180                 /* Check object constraint ipos */
2181                 for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
2182                         count += fullselect_ipo_keys(conchan->ipo);                     
2183                 
2184                 /* skip actions and nlastrips if object is collapsed */
2185                 if (base->object->nlaflag & OB_NLA_COLLAPSED)
2186                         continue;
2187                 
2188                 /* Check action ipos */
2189                 if (base->object->action) {
2190                         /* exclude if strip is selected too */
2191                         for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2192                                 if (strip->flag & ACTSTRIP_SELECT)
2193                                         if (strip->act == base->object->action)
2194                                                 break;
2195                         }
2196                         if (strip==NULL) {
2197                                 for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
2198                                         if (EDITABLE_ACHAN(achan)) {
2199                                                 i= fullselect_ipo_keys(achan->ipo);
2200                                                 if (i) base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
2201                                                 count += i;
2202                                                 
2203                                                 /* Check action constraint ipos */
2204                                                 if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
2205                                                         for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
2206                                                                 if (EDITABLE_CONCHAN(conchan))
2207                                                                         count += fullselect_ipo_keys(conchan->ipo);
2208                                                         }
2209                                                 }
2210                                         }
2211                                 }
2212                         }               
2213                 }
2214                 
2215                 /* Check nlastrips */
2216                 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2217                         if (strip->flag & ACTSTRIP_SELECT) {
2218                                 base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
2219                                 count += 2;
2220                         }
2221                 }
2222         }
2223         
2224         /* If nothing is selected, bail out */
2225         if (count == 0)
2226                 return;
2227         
2228         /* allocate memory for data */
2229         t->total= count;
2230         t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (NLA Editor)");
2231         
2232         /* build the transdata structure */
2233         td= t->data;
2234         for (base=G.scene->base.first; base; base=base->next) {
2235                 /* Manipulate object ipos */
2236                 /*      - no scaling of keyframe times is allowed here  */
2237                 td= IpoToTransData(td, base->object->ipo, NULL);
2238                 
2239                 /* Manipulate object constraint ipos */
2240                 /*      - no scaling of keyframe times is allowed here  */
2241                 for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
2242                         td= IpoToTransData(td, conchan->ipo, NULL);
2243                 
2244                 /* skip actions and nlastrips if object collapsed */
2245                 if (base->object->nlaflag & OB_NLA_COLLAPSED)
2246                         continue;
2247                         
2248                 /* Manipulate action ipos */
2249                 if (base->object->action) {
2250                         /* exclude if strip that active action belongs to is selected too */
2251                         for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2252                                 if (strip->flag & ACTSTRIP_SELECT)
2253                                         if (strip->act == base->object->action)
2254                                                 break;
2255                         }
2256                         
2257                         /* can include if no strip found */
2258                         if (strip==NULL) {
2259                                 for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
2260                                         if (EDITABLE_ACHAN(achan)) {
2261                                                 td= IpoToTransData(td, achan->ipo, base->object);
2262                                                 
2263                                                 /* Manipulate action constraint ipos */
2264                                                 if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
2265                                                         for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
2266                                                                 if (EDITABLE_CONCHAN(conchan))
2267                                                                         td= IpoToTransData(td, conchan->ipo, base->object);
2268                                                         }
2269                                                 }
2270                                         }
2271                                 }
2272                         }
2273                 }
2274                 
2275                 /* Manipulate nlastrips */
2276                 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2277                         if (strip->flag & ACTSTRIP_SELECT) {
2278                                 /* first TransData is the start, second is the end */
2279                                 td->val = &strip->start;
2280                                 td->ival = strip->start;
2281                                 td++;
2282                                 
2283                                 td->val = &strip->end;
2284                                 td->ival = strip->end;
2285                                 td++;
2286                         }
2287                 }
2288         }
2289 }
2290
2291 /* **************** IpoKey stuff, for Object TransData ********** */
2292
2293 /* storage of bezier triple. thats why -3 and +3! */
2294 static void set_tdi_old(float *old, float *poin)
2295 {
2296         old[0]= *(poin);
2297         old[3]= *(poin-3);
2298         old[6]= *(poin+3);
2299 }
2300
2301 /* while transforming */
2302 void add_tdi_poin(float *poin, float *old, float delta)
2303 {
2304         if(poin) {
2305                 poin[0]= old[0]+delta;
2306                 poin[-3]= old[3]+delta;
2307                 poin[3]= old[6]+delta;
2308         }
2309 }
2310
2311 /* fill ipokey transdata with old vals and pointers */
2312 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
2313 {
2314         extern int ob_ar[];             // blenkernel ipo.c
2315         TransDataIpokey *tdi= td->tdi;
2316         BezTriple *bezt;
2317         int a, delta= 0;
2318         
2319         td->val= NULL;  // is read on ESC
2320         
2321         for(a=0; a<OB_TOTIPO; a++) {
2322                 if(ik->data[a]) {
2323                         bezt= ik->data[a];
2324                         
2325                         switch( ob_ar[a] ) {
2326                                 case OB_LOC_X:
2327                                 case OB_DLOC_X:
2328                                         tdi->locx= &(bezt->vec[1][1]); break;
2329                                 case OB_LOC_Y:
2330                                 case OB_DLOC_Y:
2331                                         tdi->locy= &(bezt->vec[1][1]); break;
2332                                 case OB_LOC_Z:
2333                                 case OB_DLOC_Z:
2334                                         tdi->locz= &(bezt->vec[1][1]); break;
2335                                         
2336                                 case OB_DROT_X:
2337                                         delta= 1;
2338                                 case OB_ROT_X:
2339                                         tdi->rotx= &(bezt->vec[1][1]); break;
2340                                 case OB_DROT_Y:
2341                                         delta= 1;
2342                                 case OB_ROT_Y:
2343                                         tdi->roty= &(bezt->vec[1][1]); break;
2344                                 case OB_DROT_Z:
2345                                         delta= 1;
2346                                 case OB_ROT_Z:
2347                                         tdi->rotz= &(bezt->vec[1][1]); break;
2348                                         
2349                                 case OB_SIZE_X:
2350                                 case OB_DSIZE_X:
2351                                         tdi->sizex= &(bezt->vec[1][1]); break;
2352                                 case OB_SIZE_Y:
2353                                 case OB_DSIZE_Y:
2354                                         tdi->sizey= &(bezt->vec[1][1]); break;
2355                                 case OB_SIZE_Z:
2356                                 case OB_DSIZE_Z:
2357                                         tdi->sizez= &(bezt->vec[1][1]); break;          
2358                         }       
2359                 }
2360         }
2361         
2362         /* oldvals for e.g. undo */
2363         if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
2364         if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
2365         if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
2366         
2367         /* remember, for mapping curves ('1'=10 degrees)  */
2368         if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
2369         if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
2370         if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
2371         
2372         /* this is not allowed to be dsize! */
2373         if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
2374         if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
2375         if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
2376         
2377         tdi->flag= TOB_IPO;
2378         if(delta) tdi->flag |= TOB_IPODROT;
2379 }
2380
2381
2382 /* *************************** Object Transform data ******************* */
2383
2384 /* Little helper function for ObjectToTransData used to give certain
2385  * constraints (ChildOf, FollowPath, and others that may be added)
2386  * inverse corrections for transform, so that they aren't in CrazySpace.
2387  * These particular constraints benefit from this, but others don't, hence
2388  * this semi-hack ;-)    - Aligorith
2389  */
2390 static short constraints_list_needinv(ListBase *list)
2391 {
2392         bConstraint *con;
2393         
2394         /* loop through constraints, checking if there's one of the mentioned 
2395          * constraints needing special crazyspace corrections
2396          */
2397         if (list) {
2398                 for (con= list->first; con; con=con->next) {
2399                         /* only consider constraint if it is enabled, and has influence on result */
2400                         if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) {
2401                                 /* (affirmative) returns for specific constraints here... */
2402                                 if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1;
2403                                 if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1;
2404                                 if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1;
2405                         }
2406                 }
2407         }
2408         
2409         /* no appropriate candidates found */
2410         return 0;
2411 }
2412
2413 /* transcribe given object into TransData for Transforming */
2414 static void ObjectToTransData(TransData *td, Object *ob) 
2415 {
2416         Object *track;
2417         ListBase fakecons = {NULL, NULL};
2418         float obmtx[3][3];
2419         short constinv;
2420
2421         /* axismtx has the real orientation */
2422         Mat3CpyMat4(td->axismtx, ob->obmat);
2423         Mat3Ortho(td->axismtx);
2424
2425         /* hack: tempolarily disable tracking and/or constraints when getting 
2426          *              object matrix, if tracking is on, or if constraints don't need
2427          *              inverse correction to stop it from screwing up space conversion
2428          *              matrix later
2429          */
2430         constinv= constraints_list_needinv(&ob->constraints);
2431         if (ob->track || constinv==0) {
2432                 track= ob->track;
2433                 ob->track= NULL;
2434                 
2435                 if (constinv == 0) {
2436                         fakecons.first = ob->constraints.first;
2437                         fakecons.last = ob->constraints.last;
2438                         ob->constraints.first = ob->constraints.last = NULL;
2439                 }
2440                 
2441                 where_is_object(ob);
2442                 
2443                 if (constinv == 0) {
2444                         ob->constraints.first = fakecons.first;
2445                         ob->constraints.last = fakecons.last;
2446                 }
2447                 
2448                 ob->track= track;
2449         }
2450         else
2451                 where_is_object(ob);
2452
2453         td->ob = ob;
2454
2455         td->loc = ob->loc;
2456         VECCOPY(td->iloc, td->loc);
2457         
2458         td->ext->rot = ob->rot;
2459         VECCOPY(td->ext->irot, ob->rot);
2460         VECCOPY(td->ext->drot, ob->drot);
2461         
2462         td->ext->size = ob->size;
2463         VECCOPY(td->ext->isize, ob->size);
2464         VECCOPY(td->ext->dsize, ob->dsize);
2465
2466         VECCOPY(td->center, ob->obmat[3]);
2467
2468         /* is there a need to set the global<->data space conversion matrices? */
2469         if (ob->parent || constinv) {
2470                 float totmat[3][3], obinv[3][3];
2471                 
2472                 /* Get the effect of parenting, and/or certain constraints.
2473                  * NOTE: some Constraints, and also Tracking should never get this
2474                  *              done, as it doesn't work well.
2475                  */
2476                 object_to_mat3(ob, obmtx);
2477                 Mat3CpyMat4(totmat, ob->obmat);
2478                 Mat3Inv(obinv, totmat);
2479                 Mat3MulMat3(td->smtx, obmtx, obinv);
2480                 Mat3Inv(td->mtx, td->smtx);
2481         }
2482         else {
2483                 /* no conversion to/from dataspace */
2484                 Mat3One(td->smtx);
2485                 Mat3One(td->mtx);
2486         }
2487 #ifdef WITH_VERSE
2488         if(ob->vnode) {
2489                 td->verse = (void*)ob;
2490                 td->flag |= TD_VERSE_OBJECT;
2491         }
2492         else
2493                 td->flag &= ~TD_VERSE_OBJECT;
2494 #endif
2495 }
2496
2497
2498 /* sets flags in Bases to define whether they take part in transform */
2499 /* it deselects Bases, so we have to call the clear function always after */
2500 static void set_trans_object_base_flags(TransInfo *t)
2501 {
2502         /*
2503          if Base selected and has parent selected:
2504          base->flag= BA_WAS_SEL
2505          */
2506         Base *base;
2507         
2508         /* makes sure base flags and object flags are identical */
2509         copy_baseflags();
2510         
2511         /* handle pending update events, otherwise they got copied below */
2512         for (base= FIRSTBASE; base; base= base->next) {
2513                 if(base->object->recalc) 
2514                         object_handle_update(base->object);
2515         }
2516         
2517         for (base= FIRSTBASE; base; base= base->next) {
2518                 base->flag &= ~BA_WAS_SEL;
2519                 
2520                 if(TESTBASELIB(base)) {
2521                         Object *ob= base->object;
2522                         Object *parsel= ob->parent;
2523                         
2524                         /* if parent selected, deselect */
2525                         while(parsel) {
2526                                 if(parsel->flag & SELECT) break;
2527                                 parsel= parsel->parent;
2528                         }
2529                         
2530                         if(parsel) {
2531                                 base->flag &= ~SELECT;
2532                                 base->flag |= BA_WAS_SEL;
2533                         }
2534                         /* used for flush, depgraph will change recalcs if needed :) */
2535                         ob->recalc |= OB_RECALC_OB;
2536                 }
2537         }
2538         /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
2539         DAG_scene_flush_update(G.scene, -1);
2540         
2541         /* and we store them temporal in base (only used for transform code) */
2542         /* this because after doing updates, the object->recalc is cleared */
2543         for (base= FIRSTBASE; base; base= base->next) {
2544                 if(base->object->recalc & OB_RECALC_OB)
2545                         base->flag |= BA_HAS_RECALC_OB;
2546                 if(base->object->recalc & OB_RECALC_DATA)
2547                         base->flag |= BA_HAS_RECALC_DATA;
2548         }
2549 }
2550
2551 static void clear_trans_object_base_flags(void)
2552 {
2553         Base *base;
2554         
2555         base= FIRSTBASE;
2556         while(base) {
2557                 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
2558                 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
2559                 
2560                 base = base->next;
2561         }
2562 }
2563
2564 /* auto-keyframing feature - for objects 
2565  *      tmode: should be a transform mode 
2566  */
2567 void autokeyframe_ob_cb_func(Object *ob, int tmode)
2568 {
2569         IpoCurve *icu;
2570         char *actname="";
2571         
2572         if (G.flags & G_RECORDKEYS) {
2573                 if(ob->ipoflag & OB_ACTION_OB)
2574                         actname= "Object";
2575
2576                 if(U.uiflag & USER_KEYINSERTAVAI) {
2577                         if(ob->ipo || ob->action) {
2578                                 ID *id= (ID *)(ob);
2579                                 
2580                                 if (ob->ipo) {
2581                                         icu= ob->ipo->curve.first;
2582                                 }
2583                                 else {
2584                                         bActionChannel *achan;
2585                                         achan= get_action_channel(ob->action, actname);
2586                                         
2587                                         if (achan && achan->ipo)
2588                                                 icu= achan->ipo->curve.first;
2589                                         else
2590                                                 icu= NULL;
2591                                 }
2592                                 
2593                                 while(icu) {
2594                                         icu->flag &= ~IPO_SELECT;
2595                                         if (U.uiflag & USER_KEYINSERTNEED)
2596                                                 insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode);
2597                                         else
2598                                                 insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0);
2599                                         icu= icu->next;
2600                                 }
2601                         }
2602                 }
2603                 else if (U.uiflag & USER_KEYINSERTNEED) {
2604                         if (tmode==TFM_RESIZE) {
2605                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_X);
2606                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y);
2607                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z);
2608                         }
2609                         else if (tmode==TFM_ROTATION) {
2610                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_X);
2611                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Y);
2612                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Z);
2613                         }
2614                         else if (tmode==TFM_TRANSLATION) {
2615                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_X);
2616                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Y);
2617                                 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Z);
2618                         }
2619                 }
2620                 else {
2621                         insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_X, 0);
2622                         insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Y, 0);
2623                         insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Z, 0);
2624
2625                         insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_X, 0);
2626                         insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Y, 0);
2627                         insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Z, 0);
2628
2629                         insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_X, 0);
2630                         insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y, 0);
2631                         insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z, 0);
2632                 }
2633
2634                 remake_object_ipos(ob);
2635                 allqueue(REDRAWMARKER, 0);
2636         }
2637 }
2638
2639 /* auto-keyframing feature - for poses/pose-channels 
2640  *      tmode: should be a transform mode 
2641  *      targetless_ik: has targetless ik been done on any channels?
2642  */
2643 void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik)
2644 {
2645         bAction *act;
2646         bPose   *pose;
2647         bPoseChannel *pchan;
2648         IpoCurve *icu;
2649         
2650         pose= ob->pose;
2651         act= ob->action;
2652         
2653         if (G.flags & G_RECORDKEYS) {
2654                 if (!act)
2655                         act= ob->action= add_empty_action("Action");
2656                 
2657                 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
2658                         if (pchan->bone->flag & BONE_TRANSFORM) {
2659                                 /* clear any 'unkeyed' flag it may have */
2660                                 pchan->bone->flag &= ~BONE_UNKEYED;
2661                                 
2662                                 /* only insert into available channels? */
2663                                 if(U.uiflag & USER_KEYINSERTAVAI) {
2664                                         bActionChannel *achan; 
2665                                         
2666                                         for (achan = act->chanbase.first; achan; achan=achan->next){
2667                                                 if (achan->ipo && !strcmp (achan->name, pchan->name)){
2668                                                         for (icu = achan->ipo->curve.first; icu; icu=icu->next){
2669                                                                 /* only insert keyframe if needed? */
2670                                                                 if (U.uiflag & USER_KEYINSERTNEED)
2671                                                                         insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode);
2672                                                                 else
2673                                                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode, 0);
2674                                                         }
2675                                                         break;
2676                                                 }
2677                                         }
2678                                 }
2679                                 /* only insert keyframe if needed? */
2680                                 else if (U.uiflag & USER_KEYINSERTNEED) {
2681                                         if ((tmode==TFM_TRANSLATION) && (targetless_ik==0)) {
2682                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
2683                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
2684                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
2685                                         }
2686                                         if ((tmode==TFM_ROTATION) || ((tmode==TFM_TRANSLATION) && targetless_ik)) {
2687                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
2688                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
2689                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
2690                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
2691                                         }
2692                                         if (tmode==TFM_RESIZE) {
2693                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
2694                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
2695                                                 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
2696                                         }
2697                                 }
2698                                 /* insert keyframe in any channel that's appropriate */
2699                                 else {
2700                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0);
2701                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0);
2702                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0);
2703                                         
2704                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0);
2705                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0);
2706                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0);
2707                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0);
2708                                         
2709                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X, 0);
2710                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0);
2711                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0);
2712                                 }
2713                         }
2714                 }
2715                 
2716                 remake_action_ipos (act);
2717                 allqueue(REDRAWMARKER, 0);
2718         }
2719         else {
2720                 /* tag channels that should have unkeyed data */
2721                 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
2722                         if (pchan->bone->flag & BONE_TRANSFORM) {
2723                                 /* tag this channel */
2724                                 pchan->bone->flag |= BONE_UNKEYED;
2725                         }
2726                 }
2727         }
2728 }
2729
2730 /* very bad call!!! - copied from editnla.c!  */
2731 static void recalc_all_ipos(void)
2732 {
2733         Ipo *ipo;
2734         IpoCurve *icu;
2735         
2736         /* Go to each ipo */
2737         for (ipo=G.main->ipo.first; ipo; ipo=ipo->id.next){
2738                 for (icu = ipo->curve.first; icu; icu=icu->next){
2739                         sort_time_ipocurve(icu);
2740                         testhandles_ipocurve(icu);
2741                 }
2742         }
2743 }
2744
2745 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
2746 /* note: transdata has been freed already! */
2747 void special_aftertrans_update(TransInfo *t)
2748 {
2749         Object *ob;
2750         Base *base;
2751         short redrawipo=0, resetslowpar=1;
2752         int cancelled= (t->state == TRANS_CANCEL);
2753         
2754         if (t->spacetype==SPACE_VIEW3D)
2755                 EM_automerge(1);
2756         
2757         if(t->spacetype == SPACE_ACTION) {
2758                 void *data;
2759                 short datatype;
2760                 
2761                 /* determine what type of data we are operating on */
2762                 data = get_action_context(&datatype);
2763                 if (data == NULL) return;
2764                 ob = OBACT;
2765                 
2766                 if (datatype == ACTCONT_ACTION) {
2767                         /* Update the curve */
2768                         /* Depending on the lock status, draw necessary views */
2769                         if (ob) {
2770                                 ob->ctime= -1234567.0f;
2771                                 
2772                                 if(ob->pose || ob_get_key(ob))
2773                                         DAG_object_flush_update(G.scene, ob, OB_RECALC);
2774                                 else
2775                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
2776                         }
2777                         
2778                         remake_action_ipos((bAction *)data);
2779                         
2780                         G.saction->flag &= ~SACTION_MOVING;
2781                 }
2782                 else if (datatype == ACTCONT_SHAPEKEY) {
2783                         /* fix up the Ipocurves and redraw stuff */
2784                         Key *key= (Key *)data;
2785                         if (key->ipo) {
2786                                 IpoCurve *icu;
2787                                 
2788                                 for (icu = key->ipo->curve.first; icu; icu=icu->next) {
2789                                         sort_time_ipocurve(icu);
2790                                         testhandles_ipocurve(icu);
2791                                 }
2792                         }
2793                         
2794                         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2795                 }
2796         }
2797         else if(t->spacetype == SPACE_NLA) {
2798                 synchronize_action_strips();
2799                 
2800                 /* cleanup */
2801                 for (base=G.scene->base.first; base; base=base->next)
2802                         base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA);
2803                 
2804                 recalc_all_ipos();      // bad
2805         }
2806         else if(t->spacetype == SPACE_IPO) {
2807                 // FIXME! is there any code from the old transform_ipo that needs to be added back? 
2808                 
2809                 /* resetting slow-parents isn't really necessary when editing sequence ipo's */
2810                 if (G.sipo->blocktype==ID_SEQ)
2811                         resetslowpar= 0;
2812         }
2813         else if(G.obedit) {
2814                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2815                         allqueue(REDRAWBUTSEDIT, 0);
2816                 
2817                 /* table needs to be created for each edit command, since vertices can move etc */
2818                 mesh_octree_table(G.obedit, NULL, 'e');
2819         }
2820         else if( (t->flag & T_POSE) && t->poseobj) {
2821                 bArmature *arm;
2822                 bPose   *pose;
2823                 bPoseChannel *pchan;
2824                 short targetless_ik= 0;
2825
2826                 ob= t->poseobj;
2827                 arm= ob->data;
2828                 pose= ob->pose;
2829                 
2830                 /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
2831                 pose->flag |= POSE_DO_UNLOCK;
2832
2833                 /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
2834                 if(!cancelled && t->mode==TFM_TRANSLATION)
2835                         targetless_ik= apply_targetless_ik(ob);
2836                 else {
2837                         /* not forget to clear the auto flag */
2838                         for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
2839                                 bKinematicConstraint *data= has_targetless_ik(pchan);
2840                                 if(data) data->flag &= ~CONSTRAINT_IK_AUTO;
2841                         }
2842                 }
2843                 
2844                 if(t->mode==TFM_TRANSLATION)
2845                         pose_grab_with_ik_clear(ob);
2846                         
2847                 /* automatic inserting of keys and unkeyed tagging - only if transform wasn't cancelled (or TFM_DUMMY) */
2848                 if(!cancelled && (t->mode != TFM_DUMMY)) {
2849                         autokeyframe_pose_cb_func(ob, t->mode, targetless_ik);
2850                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2851                 }
2852                 else if(arm->flag & ARM_DELAYDEFORM) {
2853                         /* old optimize trick... this enforces to bypass the depgraph */
2854                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2855                         ob->recalc= 0;  // is set on OK position already by recalcData()
2856                 }
2857                 else 
2858                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2859                 
2860                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2861                         allqueue(REDRAWBUTSEDIT, 0);
2862                 
2863         }
2864         else {
2865                 base= FIRSTBASE;
2866                 while(base) {                                           
2867                         if(base->flag & BA_DO_IPO) redrawipo= 1;
2868                         
2869                         ob= base->object;
2870                         
2871                         if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
2872                         else if(modifiers_isClothEnabled(ob)) {
2873                                 cloth_free_modifier(modifiers_isClothEnabled(ob));
2874                         }
2875                         
2876                         /* Set autokey if necessary */
2877                         if ((!cancelled) && (t->mode != TFM_DUMMY) && (base->flag & SELECT)) {
2878                                 autokeyframe_ob_cb_func(ob, t->mode);
2879                         }
2880                         
2881                         base= base->next;
2882                 }