* Shrink/Fatten for bevelled curves
[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                                                 
1143                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN) {
1144                                                         td->val = &(bezt->radius);
1145                                                         td->ival = bezt->radius;
1146                                                 } else {
1147                                                         td->val = &(bezt->alfa);
1148                                                         td->ival = bezt->alfa;
1149                                                 }
1150
1151                                                 Mat3CpyMat3(td->smtx, smtx);
1152                                                 Mat3CpyMat3(td->mtx, mtx);
1153
1154                                                 td++;
1155                                                 count++;
1156                                                 tail++;
1157                                         }
1158                                         if(propmode || (bezt->f3 & 1)) {
1159                                                 VECCOPY(td->iloc, bezt->vec[2]);
1160                                                 td->loc= bezt->vec[2];
1161                                                 VECCOPY(td->center, bezt->vec[1]);
1162                                                 if(bezt->f3 & 1) td->flag= TD_SELECTED;
1163                                                 else td->flag= 0;
1164                                                 td->ext = NULL;
1165                                                 td->tdi = NULL;
1166                                                 td->val = NULL;
1167
1168                                                 Mat3CpyMat3(td->smtx, smtx);
1169                                                 Mat3CpyMat3(td->mtx, mtx);
1170
1171                                                 td++;
1172                                                 count++;
1173                                                 tail++;
1174                                         }
1175                                 }
1176                                 else if (propmode && head != tail) {
1177                                         calc_distanceCurveVerts(head, tail-1);
1178                                         head = tail;
1179                                 }
1180                         }
1181                         if (propmode && head != tail)
1182                                 calc_distanceCurveVerts(head, tail-1);
1183                 }
1184                 else {
1185                         TransData *head, *tail;
1186                         head = tail = td;
1187                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1188                                 if(bp->hide==0) {
1189                                         if(propmode || (bp->f1 & 1)) {
1190                                                 VECCOPY(td->iloc, bp->vec);
1191                                                 td->loc= bp->vec;
1192                                                 VECCOPY(td->center, td->loc);
1193                                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
1194                                                 else td->flag= 0;
1195                                                 td->ext = NULL;
1196                                                 td->tdi = NULL;
1197                                                 
1198                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN) {
1199                                                         td->val = &(bp->radius);
1200                                                         td->ival = bp->radius;
1201                                                 } else {
1202                                                         td->val = &(bp->alfa);
1203                                                         td->ival = bp->alfa;
1204                                                 }
1205
1206                                                 Mat3CpyMat3(td->smtx, smtx);
1207                                                 Mat3CpyMat3(td->mtx, mtx);
1208
1209                                                 td++;
1210                                                 count++;
1211                                                 tail++;
1212                                         }
1213                                 }
1214                                 else if (propmode && head != tail) {
1215                                         calc_distanceCurveVerts(head, tail-1);
1216                                         head = tail;
1217                                 }
1218                         }
1219                         if (propmode && head != tail)
1220                                 calc_distanceCurveVerts(head, tail-1);
1221                 }
1222         }
1223 }
1224
1225 /* ********************* lattice *************** */
1226
1227 static void createTransLatticeVerts(TransInfo *t)
1228 {
1229         TransData *td = NULL;
1230         BPoint *bp;
1231         float mtx[3][3], smtx[3][3];
1232         int a;
1233         int count=0, countsel=0;
1234         int propmode = t->flag & T_PROP_EDIT;
1235
1236         bp= editLatt->def;
1237         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1238         while(a--) {
1239                 if(bp->hide==0) {
1240                         if(bp->f1 & 1) countsel++;
1241                         if(propmode) count++;
1242                 }
1243                 bp++;
1244         }
1245         
1246         /* note: in prop mode we need at least 1 selected */
1247         if (countsel==0) return;
1248         
1249         if(propmode) t->total = count; 
1250         else t->total = countsel;
1251         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1252         
1253         Mat3CpyMat4(mtx, G.obedit->obmat);
1254         Mat3Inv(smtx, mtx);
1255
1256         td = t->data;
1257         bp= editLatt->def;
1258         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1259         while(a--) {
1260                 if(propmode || (bp->f1 & 1)) {
1261                         if(bp->hide==0) {
1262                                 VECCOPY(td->iloc, bp->vec);
1263                                 td->loc= bp->vec;
1264                                 VECCOPY(td->center, td->loc);
1265                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
1266                                 else td->flag= 0;
1267                                 Mat3CpyMat3(td->smtx, smtx);
1268                                 Mat3CpyMat3(td->mtx, mtx);
1269
1270                                 td->ext = NULL;
1271                                 td->tdi = NULL;
1272                                 td->val = NULL;
1273
1274                                 td++;
1275                                 count++;
1276                         }
1277                 }
1278                 bp++;
1279         }
1280
1281
1282 /* ********************* mesh ****************** */
1283
1284 /* proportional distance based on connectivity  */
1285 #define E_VEC(a)        (vectors + (3 * (a)->tmp.l))
1286 #define E_NEAR(a)       (nears[((a)->tmp.l)])
1287 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1288 {
1289         EditMesh *em = G.editMesh;
1290         EditVert *eve;
1291         EditEdge *eed;
1292         int i= 0, done= 1;
1293
1294         /* f2 flag is used for 'selection' */
1295         /* tmp.l is offset on scratch array   */
1296         for(eve= em->verts.first; eve; eve= eve->next) {
1297                 if(eve->h==0) {
1298                         eve->tmp.l = i++;
1299
1300                         if(eve->f & SELECT) {
1301                                 eve->f2= 2;
1302                                 E_NEAR(eve) = eve;
1303                                 E_VEC(eve)[0] = 0.0f;
1304                                 E_VEC(eve)[1] = 0.0f;
1305                                 E_VEC(eve)[2] = 0.0f;
1306                         }
1307                         else {
1308                                 eve->f2 = 0;
1309                         }
1310                 }
1311         }
1312
1313
1314         /* Floodfill routine */
1315         /*
1316         At worst this is n*n of complexity where n is number of edges 
1317         Best case would be n if the list is ordered perfectly.
1318         Estimate is n log n in average (so not too bad)
1319         */
1320         while(done) {
1321                 done= 0;
1322                 
1323                 for(eed= em->edges.first; eed; eed= eed->next) {
1324                         if(eed->h==0) {
1325                                 EditVert *v1= eed->v1, *v2= eed->v2;
1326                                 float *vec2 = E_VEC(v2);
1327                                 float *vec1 = E_VEC(v1);
1328
1329                                 if (v1->f2 + v2->f2 == 4)
1330                                         continue;
1331
1332                                 if (v1->f2) {
1333                                         if (v2->f2) {
1334                                                 float nvec[3];
1335                                                 float len1 = VecLength(vec1);
1336                                                 float len2 = VecLength(vec2);
1337                                                 float lenn;
1338                                                 /* for v2 if not selected */
1339                                                 if (v2->f2 != 2) {
1340                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1341                                                         lenn = VecLength(nvec);
1342                                                         if (lenn - len1 > 0.00001f && len2 - lenn > 0.00001f) {
1343                                                                 VECCOPY(vec2, nvec);
1344                                                                 E_NEAR(v2) = E_NEAR(v1);
1345                                                                 done = 1;
1346                                                         }
1347                                                         else if (len2 - len1 > 0.00001f && len1 - lenn > 0.00001f) {
1348                                                                 VECCOPY(vec2, vec1);
1349                                                                 E_NEAR(v2) = E_NEAR(v1);
1350                                                                 done = 1;
1351                                                         }
1352                                                 }
1353                                                 /* for v1 if not selected */
1354                                                 if (v1->f2 != 2) {
1355                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1356                                                         lenn = VecLength(nvec);
1357                                                         if (lenn - len2 > 0.00001f && len1 - lenn > 0.00001f) {
1358                                                                 VECCOPY(vec1, nvec);
1359                                                                 E_NEAR(v1) = E_NEAR(v2);
1360                                                                 done = 1;
1361                                                         }
1362                                                         else if (len1 - len2 > 0.00001f && len2 - lenn > 0.00001f) {
1363                                                                 VECCOPY(vec1, vec2);
1364                                                                 E_NEAR(v1) = E_NEAR(v2);
1365                                                                 done = 1;
1366                                                         }
1367                                                 }
1368                                         }
1369                                         else {
1370                                                 v2->f2 = 1;
1371                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1372                                                 if (VecLength(vec1) - VecLength(vec2) > 0.00001f) {
1373                                                         VECCOPY(vec2, vec1);
1374                                                 }
1375                                                 E_NEAR(v2) = E_NEAR(v1);
1376                                                 done = 1;
1377                                         }
1378                                 }
1379                                 else if (v2->f2) {
1380                                         v1->f2 = 1;
1381                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1382                                         if (VecLength(vec2) - VecLength(vec1) > 0.00001f) {
1383                                                 VECCOPY(vec1, vec2);
1384                                         }
1385                                         E_NEAR(v1) = E_NEAR(v2);
1386                                         done = 1;
1387                                 }
1388                         }
1389                 }
1390         }
1391 }
1392
1393 /* loop-in-a-loop I know, but we need it! (ton) */
1394 static void get_face_center(float *cent, EditVert *eve)
1395 {
1396         EditMesh *em = G.editMesh;
1397         EditFace *efa;
1398         
1399         for(efa= em->faces.first; efa; efa= efa->next)
1400                 if(efa->f & SELECT)
1401                         if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1402                                 break;
1403         if(efa) {
1404                 VECCOPY(cent, efa->cent);
1405         }
1406 }
1407
1408 static void VertsToTransData(TransData *td, EditVert *eve)
1409 {
1410         td->flag = 0;
1411         td->loc = eve->co;
1412         
1413         VECCOPY(td->center, td->loc);
1414         if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1415                 get_face_center(td->center, eve);
1416         VECCOPY(td->iloc, td->loc);
1417
1418         // Setting normals
1419         VECCOPY(td->axismtx[2], eve->no);
1420         td->axismtx[0][0]               =
1421                 td->axismtx[0][1]       =
1422                 td->axismtx[0][2]       =
1423                 td->axismtx[1][0]       =
1424                 td->axismtx[1][1]       =
1425                 td->axismtx[1][2]       = 0.0f;
1426
1427         td->ext = NULL;
1428         td->tdi = NULL;
1429         td->val = NULL;
1430         td->tdmir= NULL;
1431 }
1432
1433 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1434
1435 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1436 {
1437         float *vec = userData;
1438         
1439         vec+= 3*index;
1440         VECCOPY(vec, co);
1441 }
1442
1443 /* hurmf, copy from buttons_editing.c, i have to sort this out what it means... */
1444 static void modifiers_setOnCage(void *ob_v, void *md_v)
1445 {
1446         Object *ob = ob_v;
1447         ModifierData *md;
1448         
1449         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1450         
1451         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1452                 if( md == md_v ) {
1453                         if( i >= cageIndex )
1454                                 md->mode ^= eModifierMode_OnCage;
1455                         break;
1456                 }
1457 }
1458
1459
1460 /* disable subsurf temporal, get mapped cos, and enable it */
1461 static float *get_crazy_mapped_editverts(void)
1462 {
1463         DerivedMesh *dm;
1464         ModifierData *md;
1465         float *vertexcos;
1466         int needsFree;
1467         int i;
1468         
1469         for( i = 0, md=G.obedit->modifiers.first; md; ++i, md=md->next ) {
1470                 if(md->type==eModifierType_Subsurf)
1471                         if(md->mode & eModifierMode_OnCage)
1472                                 break;
1473         }
1474         if(md) {
1475                 /* this call disables subsurf and enables the underlying modifier to deform, apparently */
1476                 modifiers_setOnCage(G.obedit, md);
1477                 /* make it all over */
1478                 makeDispListMesh(G.obedit);
1479         }
1480         
1481         /* now get the cage */
1482         dm= editmesh_get_derived_cage(&needsFree);
1483
1484         vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1485         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1486         
1487         if (needsFree) dm->release(dm);
1488         
1489         if(md) {
1490                 /* set back the flag, no new cage needs to be built, transform does it */
1491                 modifiers_setOnCage(G.obedit, md);
1492         }
1493         
1494         return vertexcos;
1495 }
1496
1497 #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])
1498 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1499 {
1500         float vecu[3], vecv[3];
1501         float q1[4], q2[4];
1502         
1503         TAN_MAKE_VEC(vecu, v1, v2);
1504         TAN_MAKE_VEC(vecv, v1, v3);
1505         triatoquat(v1, vecu, vecv, q1);
1506         
1507         TAN_MAKE_VEC(vecu, def1, def2);
1508         TAN_MAKE_VEC(vecv, def1, def3);
1509         triatoquat(def1, vecu, vecv, q2);
1510         
1511         QuatSub(quat, q2, q1);
1512 }
1513 #undef TAN_MAKE_VEC
1514
1515 static void set_crazyspace_quats(float *mappedcos, float *quats)
1516 {
1517         EditMesh *em = G.editMesh;
1518         EditVert *eve, *prev;
1519         EditFace *efa;
1520         float *v1, *v2, *v3, *v4;
1521         int index= 0;
1522         
1523         /* two abused locations in vertices */
1524         for(eve= em->verts.first; eve; eve= eve->next, index++) {
1525                 eve->tmp.fp = NULL;
1526                 eve->prev= (EditVert *)index;
1527         }
1528         
1529         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
1530         for(efa= em->faces.first; efa; efa= efa->next) {
1531                 
1532                 /* retrieve mapped coordinates */
1533                 v1= mappedcos + 3*( (int)(efa->v1->prev) );
1534                 v2= mappedcos + 3*( (int)(efa->v2->prev) );
1535                 v3= mappedcos + 3*( (int)(efa->v3->prev) );
1536                 
1537                 if(efa->v2->tmp.fp==NULL && efa->v2->f1) {
1538                         set_crazy_vertex_quat(quats, efa->v2->co, efa->v3->co, efa->v1->co, v2, v3, v1);
1539                         efa->v2->tmp.fp= quats;
1540                         quats+= 4;
1541                 }
1542                 
1543                 if(efa->v4) {
1544                         v4= mappedcos + 3*( (int)(efa->v4->prev) );
1545                         
1546                         if(efa->v1->tmp.fp==NULL && efa->v1->f1) {
1547                                 set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v4->co, v1, v2, v4);
1548                                 efa->v1->tmp.fp= quats;
1549                                 quats+= 4;
1550                         }
1551                         if(efa->v3->tmp.fp==NULL && efa->v3->f1) {
1552                                 set_crazy_vertex_quat(quats, efa->v3->co, efa->v4->co, efa->v2->co, v3, v4, v2);
1553                                 efa->v3->tmp.fp= quats;
1554                                 quats+= 4;
1555                         }
1556                         if(efa->v4->tmp.fp==NULL && efa->v4->f1) {
1557                                 set_crazy_vertex_quat(quats, efa->v4->co, efa->v1->co, efa->v3->co, v4, v1, v3);
1558                                 efa->v4->tmp.fp= quats;
1559                                 quats+= 4;
1560                         }
1561                 }
1562                 else {
1563                         if(efa->v1->tmp.fp==NULL && efa->v1->f1) {
1564                                 set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v3->co, v1, v2, v3);
1565                                 efa->v1->tmp.fp= quats;
1566                                 quats+= 4;
1567                         }
1568                         if(efa->v3->tmp.fp==NULL && efa->v3->f1) {
1569                                 set_crazy_vertex_quat(quats, efa->v3->co, efa->v1->co, efa->v2->co, v3, v1, v2);
1570                                 efa->v3->tmp.fp= quats;
1571                                 quats+= 4;
1572                         }
1573                 }
1574         }
1575
1576         /* restore abused prev pointer */
1577         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1578                 eve->prev= prev;
1579
1580 }
1581
1582 static void createTransEditVerts(TransInfo *t)
1583 {
1584         TransData *tob = NULL;
1585         EditMesh *em = G.editMesh;
1586         EditVert *eve;
1587         EditVert **nears = NULL;
1588         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1589         float mtx[3][3], smtx[3][3];
1590         int count=0, countsel=0;
1591         int propmode = t->flag & T_PROP_EDIT;
1592         int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR);
1593
1594         // transform now requires awareness for select mode, so we tag the f1 flags in verts
1595         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1596                 for(eve= em->verts.first; eve; eve= eve->next) {
1597                         if(eve->h==0 && (eve->f & SELECT)) 
1598                                 eve->f1= SELECT;
1599                         else
1600                                 eve->f1= 0;
1601                 }
1602         }
1603         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1604                 EditEdge *eed;
1605                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1606                 for(eed= em->edges.first; eed; eed= eed->next) {
1607                         if(eed->h==0 && (eed->f & SELECT))
1608                                 eed->v1->f1= eed->v2->f1= SELECT;
1609                 }
1610         }
1611         else {
1612                 EditFace *efa;
1613                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1614                 for(efa= em->faces.first; efa; efa= efa->next) {
1615                         if(efa->h==0 && (efa->f & SELECT)) {
1616                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1617                                 if(efa->v4) efa->v4->f1= SELECT;
1618                         }
1619                 }
1620         }
1621         
1622         /* now we can count */
1623         for(eve= em->verts.first; eve; eve= eve->next) {
1624                 if(eve->h==0) {
1625                         if(eve->f1) countsel++;
1626                         if(propmode) count++;
1627                 }
1628         }
1629         
1630         /* note: in prop mode we need at least 1 selected */
1631         if (countsel==0) return;
1632         
1633         if(propmode) {
1634                 t->total = count; 
1635         
1636                 /* allocating scratch arrays */
1637                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1638                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1639         }
1640         else t->total = countsel;
1641         tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1642         
1643         Mat3CpyMat4(mtx, G.obedit->obmat);
1644         Mat3Inv(smtx, mtx);
1645
1646         if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1647         
1648         /* detect CrazySpace [tm] */
1649         if(propmode==0) {
1650                 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
1651                         if(modifiers_isDeformed(G.obedit)) {
1652                                 /* disable subsurf temporal, get mapped cos, and enable it */
1653                                 mappedcos= get_crazy_mapped_editverts();
1654                                 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
1655                                 set_crazyspace_quats(mappedcos, quats);
1656                         }
1657                 }
1658         }
1659         
1660         /* find out which half we do */
1661         if(mirror) {
1662                 for (eve=em->verts.first; eve; eve=eve->next) {
1663                         if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
1664                                 if(eve->co[0]<0.0f)
1665                                         mirror = -1;
1666                                 break;
1667                         }
1668                 }
1669         }
1670         
1671         for (eve=em->verts.first; eve; eve=eve->next) {
1672                 if(eve->h==0) {
1673                         if(propmode || eve->f1) {
1674                                 VertsToTransData(tob, eve);
1675
1676                                 if(eve->f1) tob->flag |= TD_SELECTED;
1677                                 if(propmode) {
1678                                         if (eve->f2) {
1679                                                 float vec[3];
1680                                                 VECCOPY(vec, E_VEC(eve));
1681                                                 Mat3MulVecfl(mtx, vec);
1682                                                 tob->dist= VecLength(vec);
1683                                         }
1684                                         else {
1685                                                 tob->flag |= TD_NOTCONNECTED;
1686                                                 tob->dist = MAXFLOAT;
1687                                         }
1688                                 }
1689                                 
1690                                 /* CrazySpace */
1691                                 if(quats && eve->tmp.fp) {
1692                                         float mat[3][3], imat[3][3], qmat[3][3];
1693                                         
1694                                         QuatToMat3(eve->tmp.fp, qmat);
1695                                         Mat3MulMat3(mat, mtx, qmat);
1696                                         Mat3Inv(imat, mat);
1697                                         
1698                                         Mat3CpyMat3(tob->smtx, imat);
1699                                         Mat3CpyMat3(tob->mtx, mat);
1700                                 }
1701                                 else {
1702                                         Mat3CpyMat3(tob->smtx, smtx);
1703                                         Mat3CpyMat3(tob->mtx, mtx);
1704                                 }
1705                                 
1706                                 /* Mirror? */
1707                                 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
1708                                         EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc);        /* initializes octree on first call */
1709                                         if(vmir!=eve) tob->tdmir= vmir;
1710                                 }
1711                                 tob++;
1712                         }
1713                 }       
1714         }
1715         if (propmode) {
1716                 MEM_freeN(vectors);
1717                 MEM_freeN(nears);
1718         }
1719         /* crazy space free */
1720         if(mappedcos)
1721                 MEM_freeN(mappedcos);
1722         if(quats)
1723                 MEM_freeN(quats);
1724 }
1725
1726 /* ********************* UV ****************** */
1727
1728 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
1729 {
1730         float aspx, aspy;
1731
1732         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1733
1734         /* uv coords are scaled by aspects. this is needed for rotations and
1735            proportional editing to be consistent with the stretchted uv coords
1736            that are displayed. this also means that for display and numinput,
1737            and when the the uv coords are flushed, these are converted each time */
1738         td2d->loc[0] = uv[0]*aspx;
1739         td2d->loc[1] = uv[1]*aspy;
1740         td2d->loc[2] = 0.0f;
1741         td2d->loc2d = uv;
1742
1743         td->flag = 0;
1744         td->loc = td2d->loc;
1745         VECCOPY(td->center, td->loc);
1746         VECCOPY(td->iloc, td->loc);
1747
1748         memset(td->axismtx, 0, sizeof(td->axismtx));
1749         td->axismtx[2][2] = 1.0f;
1750
1751         td->ext= NULL; td->tdi= NULL; td->val= NULL;
1752
1753         if(selected) {
1754                 td->flag |= TD_SELECTED;
1755                 td->dist= 0.0;
1756         }
1757         else
1758                 td->dist= MAXFLOAT;
1759         
1760         Mat3One(td->mtx);
1761         Mat3One(td->smtx);
1762 }
1763
1764 static void createTransUVs(TransInfo *t)
1765 {
1766         TransData *td = NULL;
1767         TransData2D *td2d = NULL;
1768         Mesh *me;
1769         TFace *tf;
1770         MFace *mf;
1771         int a, count=0, countsel=0;
1772         int propmode = t->flag & T_PROP_EDIT;
1773         
1774         if(is_uv_tface_editing_allowed()==0) return;
1775         me= get_mesh(OBACT);
1776
1777         /* count */
1778         tf= me->tface;
1779         mf= me->mface;
1780         for(a=me->totface; a>0; a--, tf++, mf++) {
1781                 if(mf->v3 && tf->flag & TF_SELECT) {
1782                         if(tf->flag & TF_SEL1) countsel++;
1783                         if(tf->flag & TF_SEL2) countsel++;
1784                         if(tf->flag & TF_SEL3) countsel++;
1785                         if(mf->v4 && (tf->flag & TF_SEL4)) countsel++;
1786                         if(propmode)
1787                                 count += (mf->v4)? 4: 3;
1788                 }
1789         }
1790
1791         /* note: in prop mode we need at least 1 selected */
1792         if (countsel==0) return;
1793         
1794         t->total= (propmode)? count: countsel;
1795         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
1796         /* for each 2d uv coord a 3d vector is allocated, so that they can be
1797            treated just as if they were 3d verts */
1798         t->data2d= MEM_mallocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
1799
1800         if(G.sima->flag & SI_CLIP_UV)
1801                 t->flag |= T_CLIP_UV;
1802
1803         td= t->data;
1804         td2d= t->data2d;
1805         tf= me->tface;
1806         mf= me->mface;
1807         for(a=me->totface; a>0; a--, tf++, mf++) {
1808                 if(mf->v3 && tf->flag & TF_SELECT) {
1809                         if(tf->flag & TF_SEL1 || propmode)
1810                                 UVsToTransData(td++, td2d++, tf->uv[0], (tf->flag & TF_SEL1));
1811                         if(tf->flag & TF_SEL2 || propmode)
1812                                 UVsToTransData(td++, td2d++, tf->uv[1], (tf->flag & TF_SEL2));
1813                         if(tf->flag & TF_SEL3 || propmode)
1814                                 UVsToTransData(td++, td2d++, tf->uv[2], (tf->flag & TF_SEL3));
1815
1816                         if(mf->v4 && (tf->flag & TF_SEL4 || propmode))
1817                                 UVsToTransData(td++, td2d++, tf->uv[3], (tf->flag & TF_SEL4));
1818                 }
1819         }
1820
1821         if (G.sima->flag & SI_LIVE_UNWRAP)
1822                 unwrap_lscm_live_begin();
1823 }
1824
1825 void flushTransUVs(TransInfo *t)
1826 {
1827         TransData2D *td;
1828         int a, width, height;
1829         Object *ob= OBACT;
1830         Mesh *me= get_mesh(ob);
1831         float aspx, aspy, invx, invy;
1832
1833         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1834         transform_width_height_tface_uv(&width, &height);
1835         invx= 1.0f/aspx;
1836         invy= 1.0f/aspy;
1837
1838         /* flush to 2d vector from internally used 3d vector */
1839         for(a=0, td= t->data2d; a<t->total; a++, td++) {
1840                 td->loc2d[0]= td->loc[0]*invx;
1841                 td->loc2d[1]= td->loc[1]*invy;
1842                 
1843                 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
1844                         td->loc2d[0]= floor(width*td->loc2d[0] + 0.5f)/width;
1845                         td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height;
1846                 }
1847         }
1848
1849         if((G.sima->flag & SI_BE_SQUARE) && (t->state != TRANS_CANCEL))
1850                 be_square_tface_uv(me);
1851
1852         /* this is overkill if G.sima->lock is not set, but still needed */
1853         object_uvs_changed(ob);
1854 }
1855
1856 int clipUVTransform(TransInfo *t, float *vec, int resize)
1857 {
1858         TransData *td;
1859         int a, clipx=1, clipy=1;
1860         float aspx, aspy, min[2], max[2];
1861
1862         transform_aspect_ratio_tface_uv(&aspx, &aspy);
1863         min[0]= min[1]= 0.0f;
1864         max[0]= aspx; max[1]= aspy;
1865
1866         for(a=0, td= t->data; a<t->total; a++, td++) {
1867                 DO_MINMAX2(td->loc, min, max);
1868         }
1869
1870         if(resize) {
1871                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
1872                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
1873                 else if(max[0] > aspx && t->center[0] < aspx)
1874                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
1875                 else
1876                         clipx= 0;
1877
1878                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
1879                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
1880                 else if(max[1] > aspy && t->center[1] < aspy)
1881                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
1882                 else
1883                         clipy= 0;
1884         }
1885         else {
1886                 if(min[0] < 0.0f)
1887                         vec[0] -= min[0];
1888                 else if(max[0] > aspx)
1889                         vec[0] -= max[0]-aspx;
1890                 else
1891                         clipx= 0;
1892
1893                 if(min[1] < 0.0f)
1894                         vec[1] -= min[1];
1895                 else if(max[1] > aspy)
1896                         vec[1] -= max[1]-aspy;
1897                 else
1898                         clipy= 0;
1899         }       
1900
1901         return (clipx || clipy);
1902 }
1903
1904 /* **************** IpoKey stuff, for Object TransData ********** */
1905
1906 /* storage of bezier triple. thats why -3 and +3! */
1907 static void set_tdi_old(float *old, float *poin)
1908 {
1909         old[0]= *(poin);
1910         old[3]= *(poin-3);
1911         old[6]= *(poin+3);
1912 }
1913
1914 /* while transforming */
1915 void add_tdi_poin(float *poin, float *old, float delta)
1916 {
1917         if(poin) {
1918                 poin[0]= old[0]+delta;
1919                 poin[-3]= old[3]+delta;
1920                 poin[3]= old[6]+delta;
1921         }
1922 }
1923
1924 /* fill ipokey transdata with old vals and pointers */
1925 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
1926 {
1927         extern int ob_ar[];             // blenkernel ipo.c
1928         TransDataIpokey *tdi= td->tdi;
1929         BezTriple *bezt;
1930         int a, delta= 0;
1931         
1932         td->val= NULL;  // is read on ESC
1933         
1934         for(a=0; a<OB_TOTIPO; a++) {
1935                 if(ik->data[a]) {
1936                         bezt= ik->data[a];
1937                         
1938                         switch( ob_ar[a] ) {
1939                                 case OB_LOC_X:
1940                                 case OB_DLOC_X:
1941                                         tdi->locx= &(bezt->vec[1][1]); break;
1942                                 case OB_LOC_Y:
1943                                 case OB_DLOC_Y:
1944                                         tdi->locy= &(bezt->vec[1][1]); break;
1945                                 case OB_LOC_Z:
1946                                 case OB_DLOC_Z:
1947                                         tdi->locz= &(bezt->vec[1][1]); break;
1948                                         
1949                                 case OB_DROT_X:
1950                                         delta= 1;
1951                                 case OB_ROT_X:
1952                                         tdi->rotx= &(bezt->vec[1][1]); break;
1953                                 case OB_DROT_Y:
1954                                         delta= 1;
1955                                 case OB_ROT_Y:
1956                                         tdi->roty= &(bezt->vec[1][1]); break;
1957                                 case OB_DROT_Z:
1958                                         delta= 1;
1959                                 case OB_ROT_Z:
1960                                         tdi->rotz= &(bezt->vec[1][1]); break;
1961                                         
1962                                 case OB_SIZE_X:
1963                                 case OB_DSIZE_X:
1964                                         tdi->sizex= &(bezt->vec[1][1]); break;
1965                                 case OB_SIZE_Y:
1966                                 case OB_DSIZE_Y:
1967                                         tdi->sizey= &(bezt->vec[1][1]); break;
1968                                 case OB_SIZE_Z:
1969                                 case OB_DSIZE_Z:
1970                                         tdi->sizez= &(bezt->vec[1][1]); break;          
1971                         }       
1972                 }
1973         }
1974         
1975         /* oldvals for e.g. undo */
1976         if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
1977         if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
1978         if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
1979         
1980         /* remember, for mapping curves ('1'=10 degrees)  */
1981         if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
1982         if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
1983         if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
1984         
1985         /* this is not allowed to be dsize! */
1986         if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
1987         if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
1988         if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
1989         
1990         tdi->flag= TOB_IPO;
1991         if(delta) tdi->flag |= TOB_IPODROT;
1992 }
1993
1994
1995 /* *************************** Object Transform data ******************* */
1996
1997 static void ObjectToTransData(TransData *td, Object *ob) 
1998 {
1999         float obmtx[3][3];
2000         Object *tr;
2001         void *cfirst, *clast;
2002
2003         /* set axismtx BEFORE clearing constraints to have the real orientation */
2004         Mat3CpyMat4(td->axismtx, ob->obmat);
2005         Mat3Ortho(td->axismtx);
2006
2007         /* then why are constraints and track disabled here? 
2008                 they dont alter loc/rot/size itself (ton) */
2009         cfirst = ob->constraints.first;
2010         clast = ob->constraints.last;
2011         ob->constraints.first=ob->constraints.last=NULL;
2012
2013         tr= ob->track;
2014         ob->track= NULL;
2015
2016         where_is_object(ob);
2017
2018         ob->track= tr;
2019
2020         ob->constraints.first = cfirst;
2021         ob->constraints.last = clast;
2022
2023         td->ob = ob;
2024
2025         td->loc = ob->loc;
2026         VECCOPY(td->iloc, td->loc);
2027         
2028         td->ext->rot = ob->rot;
2029         VECCOPY(td->ext->irot, ob->rot);
2030         VECCOPY(td->ext->drot, ob->drot);
2031         
2032         td->ext->size = ob->size;
2033         VECCOPY(td->ext->isize, ob->size);
2034         VECCOPY(td->ext->dsize, ob->dsize);
2035
2036         VECCOPY(td->center, ob->obmat[3]);
2037
2038         if (ob->parent)
2039         {
2040                 float totmat[3][3], obinv[3][3];
2041                 
2042                 /* we calculate smtx without obmat: so a parmat */
2043                 object_to_mat3(ob, obmtx);
2044                 Mat3CpyMat4(totmat, ob->obmat);
2045                 Mat3Inv(obinv, totmat);
2046                 Mat3MulMat3(td->smtx, obmtx, obinv);
2047                 Mat3Inv(td->mtx, td->smtx);
2048         }
2049         else
2050         {
2051                 Mat3One(td->smtx);
2052                 Mat3One(td->mtx);
2053         }
2054 }
2055
2056
2057 /* sets flags in Bases to define whether they take part in transform */
2058 /* it deselects Bases, so we have to call the clear function always after */
2059 static void set_trans_object_base_flags(TransInfo *t)
2060 {
2061         /*
2062          if Base selected and has parent selected:
2063          base->flag= BA_WAS_SEL
2064          */
2065         Base *base;
2066         
2067         /* makes sure base flags and object flags are identical */
2068         copy_baseflags();
2069         
2070         /* handle pending update events, otherwise they got copied below */
2071         for (base= FIRSTBASE; base; base= base->next) {
2072                 if(base->object->recalc) 
2073                         object_handle_update(base->object);
2074         }
2075         
2076         for (base= FIRSTBASE; base; base= base->next) {
2077                 base->flag &= ~BA_WAS_SEL;
2078                 
2079                 if(TESTBASELIB(base)) {
2080                         Object *ob= base->object;
2081                         Object *parsel= ob->parent;
2082                         
2083                         /* if parent selected, deselect */
2084                         while(parsel) {
2085                                 if(parsel->flag & SELECT) break;
2086                                 parsel= parsel->parent;
2087                         }
2088                         
2089                         if(parsel) {
2090                                 base->flag &= ~SELECT;
2091                                 base->flag |= BA_WAS_SEL;
2092                         }
2093                         /* used for flush, depgraph will change recalcs if needed :) */
2094                         ob->recalc |= OB_RECALC_OB;
2095                 }
2096         }
2097         /* all recalc flags get flushed */
2098         DAG_scene_flush_update(G.scene, screen_view3d_layers());
2099         
2100         /* and we store them temporal in base (only used for transform code) */
2101         /* this because after doing updates, the object->recalc is cleared */
2102         for (base= FIRSTBASE; base; base= base->next) {
2103                 if(base->object->recalc & OB_RECALC_OB)
2104                         base->flag |= BA_HAS_RECALC_OB;
2105                 if(base->object->recalc & OB_RECALC_DATA)
2106                         base->flag |= BA_HAS_RECALC_DATA;
2107         }
2108 }
2109
2110 static void clear_trans_object_base_flags(void)
2111 {
2112         Base *base;
2113         
2114         base= FIRSTBASE;
2115         while(base) {
2116                 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
2117                 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
2118                 
2119                 base = base->next;
2120         }
2121 }
2122
2123 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
2124 /* note; transdata has been freed already! */
2125 void special_aftertrans_update(TransInfo *t)
2126 {
2127         Object *ob;
2128         Base *base;
2129         IpoCurve *icu;
2130         int redrawipo=0;
2131         int cancelled= (t->state == TRANS_CANCEL);
2132                 
2133         if(G.obedit) {
2134                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2135                         allqueue(REDRAWBUTSEDIT, 0);
2136                 
2137                 /* table needs to be created for each edit command, since vertices can move etc */
2138                 mesh_octree_table(G.obedit, NULL, 'e');
2139         }
2140         else if( (t->flag & T_POSE) && t->poseobj) {
2141                 bArmature *arm;
2142                 bAction *act;
2143                 bPose   *pose;
2144                 bPoseChannel *pchan;
2145
2146                 ob= t->poseobj;
2147                 arm= ob->data;
2148                 pose= ob->pose;
2149                 
2150                 /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
2151                 pose->flag |= POSE_DO_UNLOCK;
2152
2153                 /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
2154                 if(!cancelled && t->mode==TFM_TRANSLATION)
2155                         apply_targetless_ik(ob);
2156                 else {
2157                         /* not forget to clear the auto flag */
2158                         for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
2159                                 bKinematicConstraint *data= has_targetless_ik(pchan);
2160                                 if(data) data->flag &= ~CONSTRAINT_IK_AUTO;
2161                         }
2162                 }
2163                 
2164                 if(t->mode==TFM_TRANSLATION)
2165                         pose_grab_with_ik_clear(ob);
2166                 
2167                 /* automatic inserting of keys */
2168                 if((G.flags & G_RECORDKEYS) && (!cancelled)) {
2169                         act= ob->action;
2170                         
2171                         if (!act)
2172                                 act= ob->action= add_empty_action(ID_PO);
2173                         
2174                         for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
2175                                 if (pchan->bone->flag & BONE_TRANSFORM){
2176
2177                                         if(U.uiflag & USER_KEYINSERTAVAI) {
2178                                                 bActionChannel *achan; 
2179
2180                                                 for (achan = act->chanbase.first; achan; achan=achan->next){
2181
2182                                                         if (achan->ipo && !strcmp (achan->name, pchan->name)){
2183                                                                 for (icu = achan->ipo->curve.first; icu; icu=icu->next){
2184                                                                         insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode);
2185                                                                 }
2186
2187                                                                 break;
2188                                                         }
2189                                                 }
2190                                         }
2191                                         else{
2192
2193                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
2194                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
2195                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
2196
2197                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
2198                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
2199                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
2200                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
2201
2202                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
2203                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
2204                                                 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
2205                                         }
2206                                 }
2207                         }
2208                         
2209                         remake_action_ipos (act);
2210                         allspace(REMAKEIPO, 0);
2211                         allqueue(REDRAWACTION, 0);
2212                         allqueue(REDRAWIPO, 0);
2213                         allqueue(REDRAWNLA, 0);
2214                         allqueue(REDRAWTIME, 0);
2215                         
2216                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2217                 }
2218                 else if(arm->flag & ARM_DELAYDEFORM) {
2219                         /* old optimize trick... this enforces to bypass the depgraph */
2220                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2221                         ob->recalc= 0;  // is set on OK position already by recalcData()
2222                 }
2223                 else 
2224                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2225                 
2226                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2227                         allqueue(REDRAWBUTSEDIT, 0);
2228
2229         }
2230         else {
2231                 base= FIRSTBASE;
2232                 while(base) {   
2233                         
2234                         if(base->flag & BA_DO_IPO) redrawipo= 1;
2235                         
2236                         ob= base->object;
2237
2238                         if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
2239                         
2240                         /* Set autokey if necessary */
2241                         if ((G.flags & G_RECORDKEYS) && (!cancelled) && (base->flag & SELECT)){
2242                                 char *actname="";
2243
2244                                 if(ob->ipoflag & OB_ACTION_OB)
2245                                         actname= "Object";
2246
2247                                 if(U.uiflag & USER_KEYINSERTAVAI) {
2248                                         if(base->object->ipo) {
2249                                                 ID* id= (ID *)(base->object);
2250                                                 icu= base->object->ipo->curve.first;
2251                                                 while(icu) {
2252                                                         icu->flag &= ~IPO_SELECT;
2253                                                         insertkey(id, ID_OB, actname, NULL, icu->adrcode);
2254                                                         icu= icu->next;
2255                                                 }
2256                                         }
2257                                 }
2258                                 else {
2259
2260                                         insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_X);
2261                                         insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Y);
2262                                         insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Z);
2263
2264                                         insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_X);
2265                                         insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Y);
2266                                         insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Z);
2267
2268                                         insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_X);
2269                                         insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Y);
2270                                         insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Z);
2271                                 }
2272
2273                                 remake_object_ipos (ob);
2274                                 allqueue(REDRAWIPO, 0);
2275                                 allspace(REMAKEIPO, 0);
2276                                 allqueue(REDRAWVIEW3D, 0);
2277                                 allqueue(REDRAWNLA, 0);
2278                                 allqueue(REDRAWTIME, 0);
2279                         }
2280                         
2281                         base= base->next;
2282                 }
2283                 
2284         }
2285         
2286         clear_trans_object_base_flags();
2287         
2288         if(redrawipo) {
2289                 allqueue(REDRAWNLA, 0);
2290                 allqueue(REDRAWACTION, 0);
2291                 allqueue(REDRAWIPO, 0);
2292         }
2293         
2294         reset_slowparents();
2295         
2296         /* note; should actually only be done for all objects when a lamp is moved... (ton) */
2297         if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
2298                 reshadeall_displist();
2299 }
2300
2301 static void createTransObject(TransInfo *t)
2302 {
2303         TransData *td = NULL;
2304         TransDataExtension *tx;
2305         Object *ob;
2306         Base *base;
2307         IpoKey *ik;
2308         ListBase elems;
2309         
2310         set_trans_object_base_flags(t);
2311
2312         /* count */     
2313         for(base= FIRSTBASE; base; base= base->next) {
2314                 if TESTBASELIB(base) {
2315                         ob= base->object;
2316                         
2317                         /* store ipo keys? */
2318                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2319                                 elems.first= elems.last= NULL;
2320                                 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
2321                                 
2322                                 pushdata(&elems, sizeof(ListBase));
2323                                 
2324                                 for(ik= elems.first; ik; ik= ik->next) t->total++;
2325
2326                                 if(elems.first==NULL) t->total++;
2327                         }
2328                         else {
2329                                 t->total++;
2330                         }
2331                 }
2332         }
2333
2334         if(!t->total) {
2335                 /* clear here, main transform function escapes too */
2336                 clear_trans_object_base_flags();
2337                 return;
2338         }
2339         
2340         td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
2341         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
2342
2343         for(base= FIRSTBASE; base; base= base->next) {
2344                 if TESTBASELIB(base) {
2345                         ob= base->object;
2346                         
2347                         td->flag= TD_SELECTED;
2348                         td->protectflag= ob->protectflag;
2349                         td->ext = tx;
2350
2351                         /* store ipo keys? */
2352                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2353                                 
2354                                 popfirst(&elems);       // bring back pushed listbase
2355                                 
2356                                 if(elems.first) {
2357                                         int cfraont;
2358                                         int ipoflag;
2359                                         
2360                                         base->flag |= BA_DO_IPO+BA_WAS_SEL;
2361                                         base->flag &= ~SELECT;
2362                                         
2363                                         cfraont= CFRA;
2364                                         set_no_parent_ipo(1);
2365                                         ipoflag= ob->ipoflag;
2366                                         ob->ipoflag &= ~OB_OFFS_OB;
2367                                         
2368                                         pushdata(ob->loc, 7*3*4); // tsk! tsk!
2369                                         
2370                                         for(ik= elems.first; ik; ik= ik->next) {
2371                                                 
2372                                                 /* weak... this doesn't correct for floating values, giving small errors */
2373                                                 CFRA= (int)(ik->val/G.scene->r.framelen);
2374                                                 
2375                                                 do_ob_ipo(ob);
2376                                                 ObjectToTransData(td, ob);      // does where_is_object()
2377                                                 
2378                                                 td->flag= TD_SELECTED;
2379                                                 
2380                                                 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
2381                                                 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
2382                                                 ipokey_to_transdata(ik, td);
2383                                                 
2384                                                 td++;
2385                                                 tx++;
2386                                                 if(ik->next) td->ext= tx;       // prevent corrupting mem!
2387                                         }
2388                                         free_ipokey(&elems);
2389                                         
2390                                         poplast(ob->loc);
2391                                         set_no_parent_ipo(0);
2392                                         
2393                                         CFRA= cfraont;
2394                                         ob->ipoflag= ipoflag;
2395                                         
2396                                         where_is_object(ob);    // restore 
2397                                 }
2398                                 else {
2399                                         ObjectToTransData(td, ob);
2400                                         td->tdi = NULL;
2401                                         td->val = NULL;
2402                                         td++;
2403                                         tx++;
2404                                 }
2405                         }
2406                         else {
2407                                 ObjectToTransData(td, ob);
2408                                 td->tdi = NULL;
2409                                 td->val = NULL;
2410                                 td++;
2411                                 tx++;
2412                         }
2413                 }
2414         }
2415 }
2416
2417 void createTransData(TransInfo *t) 
2418 {
2419         Object *ob= OBACT;
2420         
2421         if (t->context == CTX_TEXTURE) {
2422                 t->flag |= T_TEXTURE;
2423                 createTransTexspace(t);
2424         }
2425         else if (t->context == CTX_EDGE) {
2426                 t->ext = NULL;
2427                 t->flag |= T_EDIT;
2428                 createTransEdge(t);
2429                 if(t->data && t->flag & T_PROP_EDIT) {
2430                         sort_trans_data(t);     // makes selected become first in array
2431                         set_prop_dist(t, 1);
2432                         sort_trans_data_dist(t);
2433                 }
2434         }
2435         else if (t->spacetype == SPACE_IMAGE) {
2436                 t->flag |= T_POINTS|T_2D_EDIT;
2437                 createTransUVs(t);
2438                 if(t->data && (t->flag & T_PROP_EDIT)) {
2439                         sort_trans_data(t);     // makes selected become first in array
2440                         set_prop_dist(t, 1);
2441                         sort_trans_data_dist(t);
2442                 }
2443         }
2444         else if (G.obedit) {
2445                 t->ext = NULL;
2446                 if (G.obedit->type == OB_MESH) {
2447                         createTransEditVerts(t);        
2448                 }
2449                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
2450                         createTransCurveVerts(t);
2451                 }
2452                 else if (G.obedit->type==OB_LATTICE) {
2453                         createTransLatticeVerts(t);
2454                 }
2455                 else if (G.obedit->type==OB_MBALL) {
2456                         createTransMBallVerts(t);
2457                 }
2458                 else if (G.obedit->type==OB_ARMATURE) {
2459                         t->flag &= ~T_PROP_EDIT;
2460                         createTransArmatureVerts(t);
2461                 }                                                       
2462                 else {
2463                         printf("not done yet! only have mesh surface curve\n");
2464                 }
2465
2466                 if(t->data && t->flag & T_PROP_EDIT) {
2467                         if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
2468                                 sort_trans_data(t);     // makes selected become first in array
2469                                 set_prop_dist(t, 0);
2470                                 sort_trans_data_dist(t);
2471                         }
2472                         else {
2473                                 sort_trans_data(t);     // makes selected become first in array
2474                                 set_prop_dist(t, 1);
2475                                 sort_trans_data_dist(t);
2476                         }
2477                 }
2478
2479                 t->flag |= T_EDIT|T_POINTS;
2480                 
2481                 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
2482                 if(t->mode==TFM_BONESIZE) {
2483                         t->flag &= ~(T_EDIT|T_POINTS);
2484                         t->flag |= T_POSE;
2485                         t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
2486                 }
2487         }
2488         else if (ob && (ob->flag & OB_POSEMODE)) {
2489                 createTransPose(t, OBACT);
2490         }
2491         else if (G.f & G_WEIGHTPAINT) {
2492                 /* exception, we look for the one selected armature */
2493                 Base *base;
2494                 for(base=FIRSTBASE; base; base= base->next) {
2495                         if(TESTBASELIB(base)) {
2496                                 if(base->object->type==OB_ARMATURE)
2497                                         if(base->object->flag & OB_POSEMODE)
2498                                                 break;
2499                         }
2500                 }
2501                 if(base) {
2502                         createTransPose(t, base->object);
2503                 }
2504         }
2505         else {
2506                 createTransObject(t);
2507                 t->flag |= T_OBJECT;
2508         }
2509
2510         if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
2511                 t->flag |= T_CAMERA;
2512         }
2513         
2514         /* temporal...? */
2515         G.scene->recalc |= SCE_PRV_CHANGED;     /* test for 3d preview */
2516 }
2517