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