6c623a23d829493c63389cca5181cbf756226729
[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
43 #include "MEM_guardedalloc.h"
44
45 #include "DNA_action_types.h"
46 #include "DNA_armature_types.h"
47 #include "DNA_camera_types.h"
48 #include "DNA_curve_types.h"
49 #include "DNA_effect_types.h"
50 #include "DNA_image_types.h"
51 #include "DNA_ipo_types.h"
52 #include "DNA_key_types.h"
53 #include "DNA_lamp_types.h"
54 #include "DNA_lattice_types.h"
55 #include "DNA_mesh_types.h"
56 #include "DNA_meshdata_types.h"
57 #include "DNA_meta_types.h"
58 #include "DNA_modifier_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_object_force.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_screen_types.h"
63 #include "DNA_texture_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_world_types.h"
66 #include "DNA_userdef_types.h"
67 #include "DNA_property_types.h"
68 #include "DNA_vfont_types.h"
69 #include "DNA_constraint_types.h"
70
71 #include "BKE_action.h"
72 #include "BKE_armature.h"
73 #include "BKE_blender.h"
74 #include "BKE_curve.h"
75 #include "BKE_constraint.h"
76 #include "BKE_depsgraph.h"
77 #include "BKE_displist.h"
78 #include "BKE_effect.h"
79 #include "BKE_font.h"
80 #include "BKE_global.h"
81 #include "BKE_ipo.h"
82 #include "BKE_lattice.h"
83 #include "BKE_mball.h"
84 #include "BKE_modifier.h"
85 #include "BKE_object.h"
86 #include "BKE_softbody.h"
87 #include "BKE_utildefines.h"
88
89 #include "BIF_editaction.h"
90 #include "BIF_editview.h"
91 #include "BIF_editlattice.h"
92 #include "BIF_editconstraint.h"
93 #include "BIF_editarmature.h"
94 #include "BIF_editmesh.h"
95 #include "BIF_gl.h"
96 #include "BIF_poseobject.h"
97 #include "BIF_mywindow.h"
98 #include "BIF_resources.h"
99 #include "BIF_screen.h"
100 #include "BIF_space.h"
101 #include "BIF_toolbox.h"
102
103 #include "BSE_view.h"
104 #include "BSE_edit.h"
105 #include "BSE_editipo.h"
106 #include "BSE_editipo_types.h"
107
108 #include "BDR_editobject.h"             // reset_slowparents()
109
110 #include "BLI_arithb.h"
111 #include "BLI_editVert.h"
112
113 #include "blendef.h"
114
115 #include "mydevice.h"
116
117 extern ListBase editNurb;
118 extern ListBase editelems;
119
120 #include "transform.h"
121
122
123 /* ************************** Functions *************************** */
124
125 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
126         TransData pivot = *head;
127         TransData *ihead = head;
128         TransData *itail = tail;
129         short connected = t->flag & T_PROP_CONNECTED;
130
131         while (head < tail)
132         {
133                 if (connected) {
134                         while ((tail->dist >= pivot.dist) && (head < tail))
135                                 tail--;
136                 }
137                 else {
138                         while ((tail->rdist >= pivot.rdist) && (head < tail))
139                                 tail--;
140                 }
141
142                 if (head != tail)
143                 {
144                         *head = *tail;
145                         head++;
146                 }
147
148                 if (connected) {
149                         while ((head->dist <= pivot.dist) && (head < tail))
150                                 head++;
151                 }
152                 else {
153                         while ((head->rdist <= pivot.rdist) && (head < tail))
154                                 head++;
155                 }
156
157                 if (head != tail)
158                 {
159                         *tail = *head;
160                         tail--;
161                 }
162         }
163
164         *head = pivot;
165         if (ihead < head) {
166                 qsort_trans_data(t, ihead, head-1);
167         }
168         if (itail > head) {
169                 qsort_trans_data(t, head+1, itail);
170         }
171 }
172
173 void sort_trans_data_dist(TransInfo *t) {
174         TransData *start = t->data;
175         int i = 1;
176
177         while(i < t->total && start->flag & TD_SELECTED) {
178                 start++;
179                 i++;
180         }
181         qsort_trans_data(t, start, t->data + t->total - 1);
182 }
183
184 static void sort_trans_data(TransInfo *t) 
185 {
186         TransData *sel, *unsel;
187         TransData temp;
188         unsel = t->data;
189         sel = t->data;
190         sel += t->total - 1;
191         while (sel > unsel) {
192                 while (unsel->flag & TD_SELECTED) {
193                         unsel++;
194                         if (unsel == sel) {
195                                 return;
196                         }
197                 }
198                 while (!(sel->flag & TD_SELECTED)) {
199                         sel--;
200                         if (unsel == sel) {
201                                 return;
202                         }
203                 }
204                 temp = *unsel;
205                 *unsel = *sel;
206                 *sel = temp;
207                 sel--;
208                 unsel++;
209         }
210 }
211
212
213 /* distance calculated from not-selected vertex to nearest selected vertex
214    warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
215 static void set_prop_dist(TransInfo *t, short with_dist)
216 {
217         TransData *tob;
218         int a;
219         
220         for(a=0, tob= t->data; a<t->total; a++, tob++) {
221                 
222                 tob->rdist= 0.0f; // init, it was mallocced
223                 
224                 if((tob->flag & TD_SELECTED)==0) {
225                         TransData *td;
226                         int i;
227                         float dist, vec[3];
228
229                         tob->rdist = -1.0f; // signal for next loop
230                                 
231                         for (i = 0, td= t->data; i < t->total; i++, td++) {
232                                 if(td->flag & TD_SELECTED) {
233                                         VecSubf(vec, tob->center, td->center);
234                                         Mat3MulVecfl(tob->mtx, vec);
235                                         dist = Normalise(vec);
236                                         if (tob->rdist == -1.0f) {
237                                                 tob->rdist = dist;
238                                         }
239                                         else if (dist < tob->rdist) {
240                                                 tob->rdist = dist;
241                                         }
242                                 }
243                                 else break;     // by definition transdata has selected items in beginning
244                         }
245                         if (with_dist) {
246                                 tob->dist = tob->rdist;
247                         }
248                 }       
249         }
250 }
251
252 /* ************************** CONVERSIONS ************************* */
253
254 /* ********************* texture space ********* */
255
256 static void createTransTexspace(TransInfo *t)
257 {
258         TransData *td;
259         Object *ob;
260         ID *id;
261         
262         ob= OBACT;
263
264         id= ob->data;
265         if(id==NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
266                 t->total = 0;
267                 return;
268         }
269
270         t->total = 1;
271         td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
272         td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
273         
274         td->flag= TD_SELECTED;
275         VECCOPY(td->center, ob->obmat[3]);
276         td->ob = ob;
277         
278         Mat3CpyMat4(td->mtx, ob->obmat);
279         Mat3Inv(td->smtx, td->mtx);
280         
281         if( GS(id->name)==ID_ME) {
282                 Mesh *me= ob->data;
283                 me->texflag &= ~AUTOSPACE;
284                 td->loc= me->loc;
285                 td->ext->rot= me->rot;
286                 td->ext->size= me->size;
287         }
288         else if( GS(id->name)==ID_CU) {
289                 Curve *cu= ob->data;
290                 cu->texflag &= ~CU_AUTOSPACE;
291                 td->loc= cu->loc;
292                 td->ext->rot= cu->rot;
293                 td->ext->size= cu->size;
294         }
295         else if( GS(id->name)==ID_MB) {
296                 MetaBall *mb= ob->data;
297                 mb->texflag &= ~MB_AUTOSPACE;
298                 td->loc= mb->loc;
299                 td->ext->rot= mb->rot;
300                 td->ext->size= mb->size;
301         }
302         
303         VECCOPY(td->iloc, td->loc);
304         VECCOPY(td->ext->irot, td->ext->rot);
305         VECCOPY(td->ext->isize, td->ext->size);
306 }
307
308 /* ********************* edge (for crease) ***** */
309
310 static void createTransEdge(TransInfo *t) {
311         TransData *td = NULL;
312         EditMesh *em = G.editMesh;
313         EditEdge *eed;
314         Mesh *me = G.obedit->data;
315         float mtx[3][3], smtx[3][3];
316         int count=0, countsel=0;
317         int propmode = t->flag & T_PROP_EDIT;
318
319         for(eed= em->edges.first; eed; eed= eed->next) {
320                 if(eed->h==0) {
321                         if (eed->f & SELECT) countsel++;
322                         if (propmode) count++;
323                 }
324         }
325
326         if (countsel == 0)
327                 return;
328
329         if(propmode) {
330                 t->total = count;
331         }
332         else {
333                 t->total = countsel;
334         }
335
336         td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
337
338         Mat3CpyMat4(mtx, G.obedit->obmat);
339         Mat3Inv(smtx, mtx);
340
341         for(eed= em->edges.first; eed; eed= eed->next) {
342                 if(eed->h==0 && (eed->f & SELECT || propmode)) {
343                         /* need to set center for center calculations */
344                         VecAddf(td->center, eed->v1->co, eed->v2->co);
345                         VecMulf(td->center, 0.5f);
346
347                         td->loc= NULL;
348                         if (eed->f & SELECT)
349                                 td->flag= TD_SELECTED;
350                         else 
351                                 td->flag= 0;
352
353
354                         Mat3CpyMat3(td->smtx, smtx);
355                         Mat3CpyMat3(td->mtx, mtx);
356
357                         td->ext = NULL;
358                         td->tdi = NULL;
359                         td->val = &(eed->crease);
360                         td->ival = eed->crease;
361
362                         td++;
363                 }
364         }
365 }
366
367 /* ********************* pose mode ************* */
368
369 /* recursive, make sure it's identical structured as next one */
370 /* only counts the parent selection, and tags transform flag */
371 /* exported for manipulator */
372 void count_bone_select(TransInfo *t, ListBase *lb, int do_it) 
373 {
374         Bone *bone;
375         int do_next;
376         
377         for(bone= lb->first; bone; bone= bone->next) {
378                 bone->flag &= ~BONE_TRANSFORM;
379                 do_next= do_it;
380                 if(do_it) {
381                         if (bone->flag & BONE_SELECTED) {
382                                 /* We don't let IK children get "grabbed" */
383                                 if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
384                                         bone->flag |= BONE_TRANSFORM;
385                                         t->total++;
386                                         do_next= 0;     // no transform on children if one parent bone is selected
387                                 }
388                         }
389                 }
390                 count_bone_select(t, &bone->childbase, do_next);
391         }
392 }
393
394 static int add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
395 {
396         Bone *bone= pchan->bone;
397         float pmat[3][3], omat[3][3];
398         float vec[3];
399
400         if(bone) {
401                 if (bone->flag & BONE_TRANSFORM) {
402                         /* We don't let IK children get "grabbed" */
403                         if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
404                                 
405                                 VECCOPY(vec, pchan->pose_mat[3]);
406                                 VECCOPY(td->center, vec);
407                                 
408                                 td->ob = ob;
409                                 td->flag= TD_SELECTED|TD_USEQUAT;
410                                 td->loc = pchan->loc;
411                                 VECCOPY(td->iloc, pchan->loc);
412                                 
413                                 td->ext->rot= NULL;
414                                 td->ext->quat= pchan->quat;
415                                 td->ext->size= pchan->size;
416
417                                 QUATCOPY(td->ext->iquat, pchan->quat);
418                                 VECCOPY(td->ext->isize, pchan->size);
419
420                                 /* proper way to get the parent transform + own transform */
421                                 Mat3CpyMat4(omat, ob->obmat);
422                                 if(pchan->parent) {
423                                         if(pchan->bone->flag & BONE_HINGE)
424                                                 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
425                                         else
426                                                 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
427                                                 
428                                         Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0);    // dang mulserie swaps args
429                                 }
430                                 else {
431                                         Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat);      // huh, transposed?
432                                 }
433                                 
434                                 Mat3Inv (td->smtx, td->mtx);
435                                 
436                                 /* for axismat we use bone's own transform */
437                                 Mat3CpyMat4(pmat, pchan->pose_mat);
438                                 Mat3MulMat3(td->axismtx, omat, pmat);
439                                 Mat3Ortho(td->axismtx);
440                                 
441                                 if(t->mode==TFM_BONESIZE) {
442                                         bArmature *arm= t->poseobj->data;
443                                         
444                                         if(arm->drawtype==ARM_ENVELOPE) {
445                                                 td->loc= NULL;
446                                                 td->val= &bone->dist;
447                                                 td->ival= bone->dist;
448                                         }
449                                         else {
450                                                 // abusive storage of scale in the loc pointer :)
451                                                 td->loc= &bone->xwidth;
452                                                 VECCOPY (td->iloc, td->loc);
453                                                 td->val= NULL;
454                                         }
455                                 }
456                                 
457                                 return 1;
458                         }
459                 }
460         }
461         return 0;
462 }
463
464 /* only called with pose mode active object now */
465 static void createTransPose(Object *ob, TransInfo *t)
466 {
467         bArmature *arm;
468         bPoseChannel *pchan;
469         TransData *td;
470         TransDataExtension *tdx;
471         int i;
472         
473         /* check validity of state */
474         arm=get_armature (ob);
475         if (arm==NULL || ob->pose==NULL) return;
476         
477         if (arm->flag & ARM_RESTPOS) {
478                 if(t->mode!=TFM_BONESIZE) {
479                         notice ("Pose edit not possible while Rest Position is enabled");
480                         return;
481                 }
482         }
483         if (!(ob->lay & G.vd->lay)) return;
484
485         /* count total */
486         count_bone_select(t, &arm->bonebase, 1);
487
488         if(t->total==0 && t->mode==TFM_TRANSLATION) {
489                 t->mode= TFM_ROTATION;
490                 count_bone_select(t, &arm->bonebase, 1);
491         }               
492         if(t->total==0) return;
493         
494         t->flag |= T_POSE;
495         t->poseobj= ob; // we also allow non-active objects to be transformed, in weightpaint
496         
497         /* init trans data */
498     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
499     tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
500         for(i=0; i<t->total; i++, td++, tdx++) {
501                 td->ext= tdx;
502                 td->tdi = NULL;
503                 td->val = NULL;
504         }       
505         
506         /* use pose channels to fill trans data */
507         td= t->data;
508         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
509                 if( add_pose_transdata(t, pchan, ob, td) ) td++;
510         }
511         if(td != (t->data+t->total)) printf("Bone selection count error\n");
512         
513 }
514
515 /* ********************* armature ************** */
516
517 static void createTransArmatureVerts(TransInfo *t)
518 {
519         EditBone *ebo;
520         bArmature *arm= G.obedit->data;
521         TransData *td;
522         float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
523
524         t->total = 0;
525         for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
526                 if (t->mode==TFM_BONESIZE) {
527                         if (ebo->flag & BONE_SELECTED)
528                                 t->total++;
529                 }
530                 else {
531                         if (ebo->flag & BONE_TIPSEL)
532                                 t->total++;
533                         if (ebo->flag & BONE_ROOTSEL)
534                                 t->total++;
535                 }
536         }
537
538     if (!t->total) return;
539         
540         Mat3CpyMat4(mtx, G.obedit->obmat);
541         Mat3Inv(smtx, mtx);
542
543     td = t->data = MEM_mallocN(t->total*sizeof(TransData), "TransEditBone");
544         
545         for (ebo=G.edbo.first;ebo;ebo=ebo->next){
546                 
547                 ebo->oldlength= ebo->length;    // length==0.0 on extrude, used for scaling radius of bone points
548                 
549                 if (t->mode==TFM_BONE_ENVELOPE) {
550                         
551                         if (ebo->flag & BONE_ROOTSEL){
552                                 td->val= &ebo->rad_head;
553                                 td->ival= *td->val;
554                                 
555                                 VECCOPY (td->center, ebo->head);
556                                 td->flag= TD_SELECTED;
557                                 
558                                 Mat3CpyMat3(td->smtx, smtx);
559                                 Mat3CpyMat3(td->mtx, mtx);
560                                 
561                                 td->loc = NULL;
562                                 td->ext = NULL;
563                                 td->tdi = NULL;
564                                 
565                                 td++;
566                         }
567                         if (ebo->flag & BONE_TIPSEL){
568                                 td->val= &ebo->rad_tail;
569                                 td->ival= *td->val;
570                                 VECCOPY (td->center, ebo->tail);
571                                 td->flag= TD_SELECTED;
572                                 
573                                 Mat3CpyMat3(td->smtx, smtx);
574                                 Mat3CpyMat3(td->mtx, mtx);
575                                 
576                                 td->loc = NULL;
577                                 td->ext = NULL;
578                                 td->tdi = NULL;
579                                 
580                                 td++;
581                         }
582                         
583                 }
584                 else if (t->mode==TFM_BONESIZE) {
585                         if (ebo->flag & BONE_SELECTED) {
586                                 if(arm->drawtype==ARM_ENVELOPE) {
587                                         td->loc= NULL;
588                                         td->val= &ebo->dist;
589                                         td->ival= ebo->dist;
590                                 }
591                                 else {
592                                         // abusive storage of scale in the loc pointer :)
593                                         td->loc= &ebo->xwidth;
594                                         VECCOPY (td->iloc, td->loc);
595                                         td->val= NULL;
596                                 }
597                                 VECCOPY (td->center, ebo->head);
598                                 td->flag= TD_SELECTED;
599                                 
600                                 /* use local bone matrix */
601                                 VecSubf(delta, ebo->tail, ebo->head);   
602                                 vec_roll_to_mat3(delta, ebo->roll, bonemat);
603                                 Mat3MulMat3(td->mtx, mtx, bonemat);
604                                 Mat3Inv(td->smtx, td->mtx);
605                                 
606                                 Mat3CpyMat3(td->axismtx, td->mtx);
607                                 Mat3Ortho(td->axismtx);
608
609                                 td->ext = NULL;
610                                 td->tdi = NULL;
611                                 
612                                 td++;
613                         }
614                 }
615                 else {
616                         if (ebo->flag & BONE_TIPSEL){
617                                 VECCOPY (td->iloc, ebo->tail);
618                                 VECCOPY (td->center, td->iloc);
619                                 td->loc= ebo->tail;
620                                 td->flag= TD_SELECTED;
621
622                                 Mat3CpyMat3(td->smtx, smtx);
623                                 Mat3CpyMat3(td->mtx, mtx);
624
625                                 td->ext = NULL;
626                                 td->tdi = NULL;
627                                 td->val = NULL;
628
629                                 td++;
630                         }
631                         if (ebo->flag & BONE_ROOTSEL){
632                                 VECCOPY (td->iloc, ebo->head);
633                                 VECCOPY (td->center, td->iloc);
634                                 td->loc= ebo->head;
635                                 td->flag= TD_SELECTED;
636
637                                 Mat3CpyMat3(td->smtx, smtx);
638                                 Mat3CpyMat3(td->mtx, mtx);
639
640                                 td->ext = NULL;
641                                 td->tdi = NULL;
642                                 td->val = NULL;
643
644                                 td++;
645                         }
646                 }
647         }
648 }
649
650 /* ********************* meta elements ********* */
651
652 static void createTransMBallVerts(TransInfo *t)
653 {
654         MetaElem *ml;
655         TransData *td;
656         TransDataExtension *tx;
657         float mtx[3][3], smtx[3][3];
658         int count=0, countsel=0;
659         int propmode = t->flag & T_PROP_EDIT;
660
661         /* count totals */
662         for(ml= editelems.first; ml; ml= ml->next) {
663                 if(ml->flag & SELECT) countsel++;
664                 if(propmode) count++;
665         }
666
667         /* note: in prop mode we need at least 1 selected */
668         if (countsel==0) return;
669         
670         if(propmode) t->total = count; 
671         else t->total = countsel;
672         
673         td = t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
674         tx = t->ext = MEM_mallocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
675
676         Mat3CpyMat4(mtx, G.obedit->obmat);
677         Mat3Inv(smtx, mtx);
678     
679         for(ml= editelems.first; ml; ml= ml->next) {
680                 if(propmode || (ml->flag & SELECT)) {
681                         td->loc= &ml->x;
682                         VECCOPY(td->iloc, td->loc);
683                         VECCOPY(td->center, td->loc);
684
685                         if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
686                         else td->flag= TD_USEQUAT;
687
688                         Mat3CpyMat3(td->smtx, smtx);
689                         Mat3CpyMat3(td->mtx, mtx);
690
691                         td->ext = tx;
692                         td->tdi = NULL;
693
694                         /* Radius of MetaElem (mass of MetaElem influence) */
695                         if(ml->flag & MB_SCALE_RAD){
696                                 td->val = &ml->rad;
697                                 td->ival = ml->rad;
698                         }
699                         else{
700                                 td->val = &ml->s;
701                                 td->ival = ml->s;
702                         }
703
704                         /* expx/expy/expz determine "shape" of some MetaElem types */
705                         tx->size = &ml->expx;
706                         tx->isize[0] = ml->expx;
707                         tx->isize[1] = ml->expy;
708                         tx->isize[2] = ml->expz;
709
710                         /* quat is used for rotation of MetaElem */
711                         tx->quat = ml->quat;
712                         QUATCOPY(tx->iquat, ml->quat);
713
714                         tx->rot = NULL;
715
716                         td++;
717                         tx++;
718                 }
719         }
720
721
722 /* ********************* curve/surface ********* */
723
724 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
725         TransData *td, *td_near = NULL;
726         for (td = head; td<=tail; td++) {
727                 if (td->flag & TD_SELECTED) {
728                         td_near = td;
729                         td->dist = 0.0f;
730                 }
731                 else if(td_near) {
732                         float dist;
733                         dist = VecLenf(td_near->center, td->center);
734                         if (dist < (td-1)->dist) {
735                                 td->dist = (td-1)->dist;
736                         }
737                         else {
738                                 td->dist = dist;
739                         }
740                 }
741                 else {
742                         td->dist = MAXFLOAT;
743                         td->flag |= TD_NOTCONNECTED;
744                 }
745         }
746         td_near = NULL;
747         for (td = tail; td>=head; td--) {
748                 if (td->flag & TD_SELECTED) {
749                         td_near = td;
750                         td->dist = 0.0f;
751                 }
752                 else if(td_near) {
753                         float dist;
754                         dist = VecLenf(td_near->center, td->center);
755                         if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
756                                 td->flag &= ~TD_NOTCONNECTED;
757                                 if (dist < (td+1)->dist) {
758                                         td->dist = (td+1)->dist;
759                                 }
760                                 else {
761                                         td->dist = dist;
762                                 }
763                         }
764                 }
765         }
766 }
767
768 static void createTransCurveVerts(TransInfo *t)
769 {
770         TransData *td = NULL;
771         Nurb *nu;
772         BezTriple *bezt;
773         BPoint *bp;
774         float mtx[3][3], smtx[3][3];
775         int a;
776         int count=0, countsel=0;
777         int propmode = t->flag & T_PROP_EDIT;
778
779         /* count total of vertices, check identical as in 2nd loop for making transdata! */
780         for(nu= editNurb.first; nu; nu= nu->next) {
781                 if((nu->type & 7)==CU_BEZIER) {
782                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
783                                 if(bezt->hide==0) {
784                                         if(bezt->f1 & 1) countsel++;
785                                         if(bezt->f2 & 1) countsel++;
786                                         if(bezt->f3 & 1) countsel++;
787                                         if(propmode) count+= 3;
788                                 }
789                         }
790                 }
791                 else {
792                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
793                                 if(bp->hide==0) {
794                                         if(propmode) count++;
795                                         if(bp->f1 & 1) countsel++;
796                                 }
797                         }
798                 }
799         }
800         /* note: in prop mode we need at least 1 selected */
801         if (countsel==0) return;
802         
803         if(propmode) t->total = count; 
804         else t->total = countsel;
805         t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
806
807         Mat3CpyMat4(mtx, G.obedit->obmat);
808         Mat3Inv(smtx, mtx);
809
810     td = t->data;
811         for(nu= editNurb.first; nu; nu= nu->next) {
812                 if((nu->type & 7)==CU_BEZIER) {
813                         TransData *head, *tail;
814                         head = tail = td;
815                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
816                                 if(bezt->hide==0) {
817                                         if(propmode || (bezt->f1 & 1)) {
818                                                 VECCOPY(td->iloc, bezt->vec[0]);
819                                                 td->loc= bezt->vec[0];
820                                                 VECCOPY(td->center, bezt->vec[1]);
821                                                 if(bezt->f1 & 1) td->flag= TD_SELECTED;
822                                                 else td->flag= 0;
823                                                 td->ext = NULL;
824                                                 td->tdi = NULL;
825                                                 td->val = NULL;
826
827                                                 Mat3CpyMat3(td->smtx, smtx);
828                                                 Mat3CpyMat3(td->mtx, mtx);
829
830                                                 td++;
831                                                 count++;
832                                                 tail++;
833                                         }
834                                         /* THIS IS THE CV, the other two are handles */
835                                         if(propmode || (bezt->f2 & 1)) {
836                                                 VECCOPY(td->iloc, bezt->vec[1]);
837                                                 td->loc= bezt->vec[1];
838                                                 VECCOPY(td->center, td->loc);
839                                                 if(bezt->f2 & 1) td->flag= TD_SELECTED;
840                                                 else td->flag= 0;
841                                                 td->ext = NULL;
842                                                 td->tdi = NULL;
843                                                 td->val = &(bezt->alfa);
844                                                 td->ival = bezt->alfa;
845
846                                                 Mat3CpyMat3(td->smtx, smtx);
847                                                 Mat3CpyMat3(td->mtx, mtx);
848
849                                                 td++;
850                                                 count++;
851                                                 tail++;
852                                         }
853                                         if(propmode || (bezt->f3 & 1)) {
854                                                 VECCOPY(td->iloc, bezt->vec[2]);
855                                                 td->loc= bezt->vec[2];
856                                                 VECCOPY(td->center, bezt->vec[1]);
857                                                 if(bezt->f3 & 1) td->flag= TD_SELECTED;
858                                                 else td->flag= 0;
859                                                 td->ext = NULL;
860                                                 td->tdi = NULL;
861                                                 td->val = NULL;
862
863                                                 Mat3CpyMat3(td->smtx, smtx);
864                                                 Mat3CpyMat3(td->mtx, mtx);
865
866                                                 td++;
867                                                 count++;
868                                                 tail++;
869                                         }
870                                 }
871                                 else if (propmode && head != tail) {
872                                         calc_distanceCurveVerts(head, tail-1);
873                                         head = tail;
874                                 }
875                         }
876                         if (propmode && head != tail)
877                                 calc_distanceCurveVerts(head, tail-1);
878                 }
879                 else {
880                         TransData *head, *tail;
881                         head = tail = td;
882                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
883                                 if(bp->hide==0) {
884                                         if(propmode || (bp->f1 & 1)) {
885                                                 VECCOPY(td->iloc, bp->vec);
886                                                 td->loc= bp->vec;
887                                                 VECCOPY(td->center, td->loc);
888                                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
889                                                 else td->flag= 0;
890                                                 td->ext = NULL;
891                                                 td->tdi = NULL;
892                                                 td->val = &(bp->alfa);
893                                                 td->ival = bp->alfa;
894
895                                                 Mat3CpyMat3(td->smtx, smtx);
896                                                 Mat3CpyMat3(td->mtx, mtx);
897
898                                                 td++;
899                                                 count++;
900                                                 tail++;
901                                         }
902                                 }
903                                 else if (propmode && head != tail) {
904                                         calc_distanceCurveVerts(head, tail-1);
905                                         head = tail;
906                                 }
907                         }
908                         if (propmode && head != tail)
909                                 calc_distanceCurveVerts(head, tail-1);
910                 }
911         }
912 }
913
914 /* ********************* lattice *************** */
915
916 static void createTransLatticeVerts(TransInfo *t)
917 {
918         TransData *td = NULL;
919         BPoint *bp;
920         float mtx[3][3], smtx[3][3];
921         int a;
922         int count=0, countsel=0;
923         int propmode = t->flag & T_PROP_EDIT;
924
925         bp= editLatt->def;
926         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
927         while(a--) {
928                 if(bp->f1 & 1) countsel++;
929                 if(propmode) count++;
930                 bp++;
931         }
932         
933         /* note: in prop mode we need at least 1 selected */
934         if (countsel==0) return;
935         
936         if(propmode) t->total = count; 
937         else t->total = countsel;
938         t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
939         
940         Mat3CpyMat4(mtx, G.obedit->obmat);
941         Mat3Inv(smtx, mtx);
942
943         td = t->data;
944         bp= editLatt->def;
945         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
946         while(a--) {
947                 if(propmode || (bp->f1 & 1)) {
948                         if(bp->hide==0) {
949                                 VECCOPY(td->iloc, bp->vec);
950                                 td->loc= bp->vec;
951                                 VECCOPY(td->center, td->loc);
952                                 if(bp->f1 & 1) td->flag= TD_SELECTED;
953                                 else td->flag= 0;
954                                 Mat3CpyMat3(td->smtx, smtx);
955                                 Mat3CpyMat3(td->mtx, mtx);
956
957                                 td->ext = NULL;
958                                 td->tdi = NULL;
959                                 td->val = NULL;
960
961                                 td++;
962                                 count++;
963                         }
964                 }
965                 bp++;
966         }
967
968
969 /* ********************* mesh ****************** */
970
971 /* proportional distance based on connectivity  */
972 #define E_VEC(a)        (vectors + (3 * (int)(a)->vn))
973 #define E_NEAR(a)       (nears[((int)(a)->vn)])
974 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
975 {
976         EditMesh *em = G.editMesh;
977         EditVert *eve;
978         EditEdge *eed;
979         int i= 0, done= 1;
980
981         /* f2 flag is used for 'selection' */
982         /* vn is offset on scratch array   */
983         for(eve= em->verts.first; eve; eve= eve->next) {
984                 if(eve->h==0) {
985                         eve->vn = (EditVert *)(i++);
986
987                         if(eve->f & SELECT) {
988                                 eve->f2= 2;
989                                 E_NEAR(eve) = eve;
990                                 E_VEC(eve)[0] = 0.0f;
991                                 E_VEC(eve)[1] = 0.0f;
992                                 E_VEC(eve)[2] = 0.0f;
993                         }
994                         else {
995                                 eve->f2 = 0;
996                         }
997                 }
998         }
999
1000
1001         /* Floodfill routine */
1002         /*
1003         At worst this is n*n of complexity where n is number of edges 
1004         Best case would be n if the list is ordered perfectly.
1005         Estimate is n log n in average (so not too bad)
1006         */
1007         while(done) {
1008                 done= 0;
1009                 
1010                 for(eed= em->edges.first; eed; eed= eed->next) {
1011                         if(eed->h==0) {
1012                                 EditVert *v1= eed->v1, *v2= eed->v2;
1013                                 float *vec2 = E_VEC(v2);
1014                                 float *vec1 = E_VEC(v1);
1015
1016                                 if (v1->f2 + v2->f2 == 4)
1017                                         continue;
1018
1019                                 if (v1->f2) {
1020                                         if (v2->f2) {
1021                                                 float nvec[3];
1022                                                 float len1 = VecLength(vec1);
1023                                                 float len2 = VecLength(vec2);
1024                                                 float lenn;
1025                                                 /* for v2 if not selected */
1026                                                 if (v2->f2 != 2) {
1027                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1028                                                         lenn = VecLength(nvec);
1029                                                         if (lenn - len1 > 0.00001f && len2 - lenn > 0.00001f) {
1030                                                                 VECCOPY(vec2, nvec);
1031                                                                 E_NEAR(v2) = E_NEAR(v1);
1032                                                                 done = 1;
1033                                                         }
1034                                                         else if (len2 - len1 > 0.00001f && len1 - lenn > 0.00001f) {
1035                                                                 VECCOPY(vec2, vec1);
1036                                                                 E_NEAR(v2) = E_NEAR(v1);
1037                                                                 done = 1;
1038                                                         }
1039                                                 }
1040                                                 /* for v1 if not selected */
1041                                                 if (v1->f2 != 2) {
1042                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1043                                                         lenn = VecLength(nvec);
1044                                                         if (lenn - len2 > 0.00001f && len1 - lenn > 0.00001f) {
1045                                                                 VECCOPY(vec1, nvec);
1046                                                                 E_NEAR(v1) = E_NEAR(v2);
1047                                                                 done = 1;
1048                                                         }
1049                                                         else if (len1 - len2 > 0.00001f && len2 - lenn > 0.00001f) {
1050                                                                 VECCOPY(vec1, vec2);
1051                                                                 E_NEAR(v1) = E_NEAR(v2);
1052                                                                 done = 1;
1053                                                         }
1054                                                 }
1055                                         }
1056                                         else {
1057                                                 v2->f2 = 1;
1058                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1059                                                 if (VecLength(vec1) - VecLength(vec2) > 0.00001f) {
1060                                                         VECCOPY(vec2, vec1);
1061                                                 }
1062                                                 E_NEAR(v2) = E_NEAR(v1);
1063                                                 done = 1;
1064                                         }
1065                                 }
1066                                 else if (v2->f2) {
1067                                         v1->f2 = 1;
1068                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1069                                         if (VecLength(vec2) - VecLength(vec1) > 0.00001f) {
1070                                                 VECCOPY(vec1, vec2);
1071                                         }
1072                                         E_NEAR(v1) = E_NEAR(v2);
1073                                         done = 1;
1074                                 }
1075                         }
1076                 }
1077         }
1078 }
1079
1080
1081 static void VertsToTransData(TransData *td, EditVert *eve)
1082 {
1083         td->flag = 0;
1084         td->loc = eve->co;
1085         VECCOPY(td->center, td->loc);
1086         VECCOPY(td->iloc, td->loc);
1087
1088         // Setting normals
1089         VECCOPY(td->axismtx[2], eve->no);
1090         td->axismtx[0][0]               =
1091                 td->axismtx[0][1]       =
1092                 td->axismtx[0][2]       =
1093                 td->axismtx[1][0]       =
1094                 td->axismtx[1][1]       =
1095                 td->axismtx[1][2]       = 0.0f;
1096
1097         td->ext = NULL;
1098         td->tdi = NULL;
1099         td->val = NULL;
1100 }
1101
1102 static void createTransEditVerts(TransInfo *t)
1103 {
1104         TransData *tob = NULL;
1105         EditMesh *em = G.editMesh;
1106         EditVert *eve;
1107         EditVert **nears = NULL;
1108         float *vectors = NULL;
1109         float mtx[3][3], smtx[3][3];
1110         int count=0, countsel=0;
1111         int propmode = t->flag & T_PROP_EDIT;
1112                 
1113         // transform now requires awareness for select mode, so we tag the f1 flags in verts
1114         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1115                 for(eve= em->verts.first; eve; eve= eve->next) {
1116                         if(eve->h==0 && (eve->f & SELECT)) 
1117                                 eve->f1= SELECT;
1118                         else
1119                                 eve->f1= 0;
1120                 }
1121         }
1122         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1123                 EditEdge *eed;
1124                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1125                 for(eed= em->edges.first; eed; eed= eed->next) {
1126                         if(eed->h==0 && (eed->f & SELECT))
1127                                 eed->v1->f1= eed->v2->f1= SELECT;
1128                 }
1129         }
1130         else {
1131                 EditFace *efa;
1132                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1133                 for(efa= em->faces.first; efa; efa= efa->next) {
1134                         if(efa->h==0 && (efa->f & SELECT)) {
1135                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1136                                 if(efa->v4) efa->v4->f1= SELECT;
1137                         }
1138                 }
1139         }
1140         
1141         /* now we can count */
1142         for(eve= em->verts.first; eve; eve= eve->next) {
1143                 if(eve->h==0) {
1144                         if(eve->f1) countsel++;
1145                         if(propmode) count++;
1146                 }
1147         }
1148         
1149         /* note: in prop mode we need at least 1 selected */
1150         if (countsel==0) return;
1151         
1152         if(propmode) {
1153                 t->total = count; 
1154         
1155                 /* allocating scratch arrays */
1156                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1157                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1158         }
1159         else t->total = countsel;
1160         tob= t->data= MEM_mallocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1161         
1162         Mat3CpyMat4(mtx, G.obedit->obmat);
1163         Mat3Inv(smtx, mtx);
1164
1165         if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1166         
1167         for (eve=em->verts.first; eve; eve=eve->next) {
1168                 if(eve->h==0) {
1169                         if(propmode || eve->f1) {
1170                                 VertsToTransData(tob, eve);
1171
1172                                 if(eve->f1) tob->flag |= TD_SELECTED;
1173                                 if(propmode) {
1174                                         if (eve->f2) {
1175                                                 float vec[3];
1176                                                 VECCOPY(vec, E_VEC(eve));
1177                                                 Mat3MulVecfl(mtx, vec);
1178                                                 tob->dist= VecLength(vec);
1179                                         }
1180                                         else {
1181                                                 tob->flag |= TD_NOTCONNECTED;
1182                                                 tob->dist = MAXFLOAT;
1183                                         }
1184                                 }
1185                                 
1186                                 Mat3CpyMat3(tob->smtx, smtx);
1187                                 Mat3CpyMat3(tob->mtx, mtx);
1188
1189                                 tob++;
1190                         }
1191                 }       
1192         }
1193         if (propmode) {
1194                 MEM_freeN(vectors);
1195                 MEM_freeN(nears);
1196         }
1197
1198 }
1199
1200 /* **************** IpoKey stuff, for Object TransData ********** */
1201
1202 /* storage of bezier triple. thats why -3 and +3! */
1203 static void set_tdi_old(float *old, float *poin)
1204 {
1205         old[0]= *(poin);
1206         old[3]= *(poin-3);
1207         old[6]= *(poin+3);
1208 }
1209
1210 /* while transforming */
1211 void add_tdi_poin(float *poin, float *old, float delta)
1212 {
1213         if(poin) {
1214                 poin[0]= old[0]+delta;
1215                 poin[-3]= old[3]+delta;
1216                 poin[3]= old[6]+delta;
1217         }
1218 }
1219
1220 /* fill ipokey transdata with old vals and pointers */
1221 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
1222 {
1223         extern int ob_ar[];             // blenkernel ipo.c
1224         TransDataIpokey *tdi= td->tdi;
1225         BezTriple *bezt;
1226         int a, delta= 0;
1227         
1228         td->val= NULL;  // is read on ESC
1229         
1230         for(a=0; a<OB_TOTIPO; a++) {
1231                 if(ik->data[a]) {
1232                         bezt= ik->data[a];
1233                         
1234                         switch( ob_ar[a] ) {
1235                                 case OB_LOC_X:
1236                                 case OB_DLOC_X:
1237                                         tdi->locx= &(bezt->vec[1][1]); break;
1238                                 case OB_LOC_Y:
1239                                 case OB_DLOC_Y:
1240                                         tdi->locy= &(bezt->vec[1][1]); break;
1241                                 case OB_LOC_Z:
1242                                 case OB_DLOC_Z:
1243                                         tdi->locz= &(bezt->vec[1][1]); break;
1244                                         
1245                                 case OB_DROT_X:
1246                                         delta= 1;
1247                                 case OB_ROT_X:
1248                                         tdi->rotx= &(bezt->vec[1][1]); break;
1249                                 case OB_DROT_Y:
1250                                         delta= 1;
1251                                 case OB_ROT_Y:
1252                                         tdi->roty= &(bezt->vec[1][1]); break;
1253                                 case OB_DROT_Z:
1254                                         delta= 1;
1255                                 case OB_ROT_Z:
1256                                         tdi->rotz= &(bezt->vec[1][1]); break;
1257                                         
1258                                 case OB_SIZE_X:
1259                                 case OB_DSIZE_X:
1260                                         tdi->sizex= &(bezt->vec[1][1]); break;
1261                                 case OB_SIZE_Y:
1262                                 case OB_DSIZE_Y:
1263                                         tdi->sizey= &(bezt->vec[1][1]); break;
1264                                 case OB_SIZE_Z:
1265                                 case OB_DSIZE_Z:
1266                                         tdi->sizez= &(bezt->vec[1][1]); break;          
1267                         }       
1268                 }
1269         }
1270         
1271         /* oldvals for e.g. undo */
1272         if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
1273         if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
1274         if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
1275         
1276         /* remember, for mapping curves ('1'=10 degrees)  */
1277         if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
1278         if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
1279         if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
1280         
1281         /* this is not allowed to be dsize! */
1282         if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
1283         if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
1284         if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
1285         
1286         tdi->flag= TOB_IPO;
1287         if(delta) tdi->flag |= TOB_IPODROT;
1288 }
1289
1290
1291 /* *************************** Object Transform data ******************* */
1292
1293 static void ObjectToTransData(TransData *td, Object *ob) 
1294 {
1295         float obmtx[3][3];
1296         Object *tr;
1297         void *cfirst, *clast;
1298
1299         /* set axismtx BEFORE clearing constraints to have the real orientation */
1300         Mat3CpyMat4(td->axismtx, ob->obmat);
1301         Mat3Ortho(td->axismtx);
1302
1303         /* then why are constraints and track disabled here? 
1304                 they dont alter loc/rot/size itself (ton) */
1305         cfirst = ob->constraints.first;
1306         clast = ob->constraints.last;
1307         ob->constraints.first=ob->constraints.last=NULL;
1308
1309         tr= ob->track;
1310         ob->track= NULL;
1311
1312         where_is_object(ob);
1313
1314         ob->track= tr;
1315
1316         ob->constraints.first = cfirst;
1317         ob->constraints.last = clast;
1318
1319         td->ob = ob;
1320
1321         td->loc = ob->loc;
1322         VECCOPY(td->iloc, td->loc);
1323         
1324         td->ext->rot = ob->rot;
1325         VECCOPY(td->ext->irot, ob->rot);
1326         VECCOPY(td->ext->drot, ob->drot);
1327         
1328         td->ext->size = ob->size;
1329         VECCOPY(td->ext->isize, ob->size);
1330         VECCOPY(td->ext->dsize, ob->dsize);
1331
1332         VECCOPY(td->center, ob->obmat[3]);
1333
1334         if (ob->parent)
1335         {
1336                 float totmat[3][3], obinv[3][3];
1337                 
1338                 /* we calculate smtx without obmat: so a parmat */
1339                 object_to_mat3(ob, obmtx);
1340                 Mat3CpyMat4(totmat, ob->obmat);
1341                 Mat3Inv(obinv, totmat);
1342                 Mat3MulMat3(td->smtx, obmtx, obinv);
1343                 Mat3Inv(td->mtx, td->smtx);
1344         }
1345         else
1346         {
1347                 Mat3One(td->smtx);
1348                 Mat3One(td->mtx);
1349         }
1350 }
1351
1352
1353 /* sets flags in Bases to define whether they take part in transform */
1354 /* it deselects Bases, so we have to call the clear function always after */
1355 static void set_trans_object_base_flags(TransInfo *t)
1356 {
1357         /*
1358          if Base selected and has parent selected:
1359          base->flag= BA_WAS_SEL
1360          */
1361         Base *base;
1362         
1363         /* makes sure base flags and object flags are identical */
1364         copy_baseflags();
1365         
1366         for (base= FIRSTBASE; base; base= base->next) {
1367                 base->flag &= ~BA_WAS_SEL;
1368                 
1369                 if(TESTBASELIB(base)) {
1370                         Object *ob= base->object;
1371                         Object *parsel= ob->parent;
1372                         
1373                         /* if parent selected, deselect */
1374                         while(parsel) {
1375                                 if(parsel->flag & SELECT) break;
1376                                 parsel= parsel->parent;
1377                         }
1378                         
1379                         if(parsel) {
1380                                 base->flag &= ~SELECT;
1381                                 base->flag |= BA_WAS_SEL;
1382                         }
1383                         /* used for flush, depgraph will change recalcs if needed :) */
1384                         ob->recalc |= OB_RECALC_OB;
1385                 }
1386         }
1387         /* all recalc flags get flushed */
1388         DAG_scene_flush_update(G.scene);
1389         
1390         /* and we store them temporal in base (only used for transform code) */
1391         /* this because after doing updates, the object->recalc is cleared */
1392         for (base= FIRSTBASE; base; base= base->next) {
1393                 if(base->object->recalc & OB_RECALC_OB)
1394                         base->flag |= BA_HAS_RECALC_OB;
1395                 if(base->object->recalc & OB_RECALC_DATA)
1396                         base->flag |= BA_HAS_RECALC_DATA;
1397         }
1398 }
1399
1400 static void clear_trans_object_base_flags(void)
1401 {
1402         Base *base;
1403         
1404         base= FIRSTBASE;
1405         while(base) {
1406                 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
1407                 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
1408                 
1409                 base = base->next;
1410         }
1411 }
1412
1413 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
1414 /* note; transdata has been freed already! */
1415 void special_aftertrans_update(TransInfo *t)
1416 {
1417         Object *ob;
1418         Base *base;
1419         int redrawipo=0;
1420         int cancelled= (t->state == TRANS_CANCEL);
1421                 
1422         if(G.obedit) {
1423                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
1424                         allqueue(REDRAWBUTSEDIT, 0);
1425         }
1426         else if( (t->flag & T_POSE) && t->poseobj) {
1427                 bArmature *arm;
1428                 bAction *act;
1429                 bPose   *pose;
1430                 bPoseChannel *pchan;
1431
1432                 ob= t->poseobj;
1433                 arm= ob->data;
1434                 
1435                 if(cancelled)   /* if cancelled we do the update always */
1436                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1437                 else if(G.flags & G_RECORDKEYS) {
1438                         act= ob->action;
1439                         pose= ob->pose;
1440                         
1441                         if (!act)
1442                                 act= ob->action= add_empty_action();
1443                         
1444                         set_pose_keys(ob);  // sets chan->flag to POSE_KEY if bone selected
1445                         for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
1446                                 if (pchan->flag & POSE_KEY){
1447                                         
1448                                         set_action_key(act, pchan, AC_QUAT_X, 1);
1449                                         set_action_key(act, pchan, AC_QUAT_Y, 1);
1450                                         set_action_key(act, pchan, AC_QUAT_Z, 1);
1451                                         set_action_key(act, pchan, AC_QUAT_W, 1);
1452                                 
1453                                         set_action_key(act, pchan, AC_SIZE_X, 1);
1454                                         set_action_key(act, pchan, AC_SIZE_Y, 1);
1455                                         set_action_key(act, pchan, AC_SIZE_Z, 1);
1456                                 
1457                                         set_action_key(act, pchan, AC_LOC_X, 1);
1458                                         set_action_key(act, pchan, AC_LOC_Y, 1);
1459                                         set_action_key(act, pchan, AC_LOC_Z, 1);
1460                                 }
1461                         }
1462                         
1463                         remake_action_ipos (act);
1464                         allspace(REMAKEIPO, 0);
1465                         allqueue(REDRAWACTION, 0);
1466                         allqueue(REDRAWIPO, 0);
1467                         allqueue(REDRAWNLA, 0);
1468                         
1469                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1470                 }
1471                 else if(arm->flag & ARM_DELAYDEFORM) {
1472                         /* old optimize trick... this enforces to bypass the depgraph */
1473                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1474                         ob->recalc= 0;  // is set on OK position already by recalcData()
1475                 }
1476                 /* do not call DAG_object_flush_update always, we dont want actions to update, for inserting keys */
1477                 
1478                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
1479                         allqueue(REDRAWBUTSEDIT, 0);
1480
1481         }
1482         else {
1483                 base= FIRSTBASE;
1484                 while(base) {   
1485                         
1486                         if(base->flag & BA_DO_IPO) redrawipo= 1;
1487                         
1488                         ob= base->object;
1489
1490                         if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_RESET;
1491                         
1492                         /* Set autokey if necessary */
1493                         if ((G.flags & G_RECORDKEYS) && (!cancelled) && (base->flag & SELECT)){
1494                         
1495                                 insertkey(&base->object->id, OB_ROT_X);
1496                                 insertkey(&base->object->id, OB_ROT_Y);
1497                                 insertkey(&base->object->id, OB_ROT_Z);
1498                         
1499                                 insertkey(&base->object->id, OB_LOC_X);
1500                                 insertkey(&base->object->id, OB_LOC_Y);
1501                                 insertkey(&base->object->id, OB_LOC_Z);
1502                         
1503                                 insertkey(&base->object->id, OB_SIZE_X);
1504                                 insertkey(&base->object->id, OB_SIZE_Y);
1505                                 insertkey(&base->object->id, OB_SIZE_Z);
1506                                 
1507                                 remake_object_ipos (ob);
1508                                 allqueue(REDRAWIPO, 0);
1509                                 allspace(REMAKEIPO, 0);
1510                                 allqueue(REDRAWVIEW3D, 0);
1511                                 allqueue(REDRAWNLA, 0);
1512                         }
1513                         
1514                         base= base->next;
1515                 }
1516                 
1517         }
1518         
1519         clear_trans_object_base_flags();
1520         
1521         if(redrawipo) {
1522                 allqueue(REDRAWNLA, 0);
1523                 allqueue(REDRAWACTION, 0);
1524                 allqueue(REDRAWIPO, 0);
1525         }
1526         
1527         reset_slowparents();
1528         
1529         /* note; should actually only be done for all objects when a lamp is moved... (ton) */
1530         if(G.vd->drawtype == OB_SHADED) reshadeall_displist();
1531         
1532 }
1533
1534 static void createTransObject(TransInfo *t)
1535 {
1536         TransData *td = NULL;
1537         TransDataExtension *tx;
1538         Object *ob;
1539         Base *base;
1540         IpoKey *ik;
1541         ListBase elems;
1542         
1543         set_trans_object_base_flags(t);
1544
1545         /* count */     
1546         for(base= FIRSTBASE; base; base= base->next) {
1547                 if TESTBASELIB(base) {
1548                         ob= base->object;
1549                         
1550                         /* store ipo keys? */
1551                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1552                                 elems.first= elems.last= NULL;
1553                                 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
1554                                 
1555                                 pushdata(&elems, sizeof(ListBase));
1556                                 
1557                                 for(ik= elems.first; ik; ik= ik->next) t->total++;
1558
1559                                 if(elems.first==NULL) t->total++;
1560                         }
1561                         else {
1562                                 t->total++;
1563                         }
1564                 }
1565         }
1566
1567         if(!t->total) {
1568                 /* clear here, main transform function escapes too */
1569                 clear_trans_object_base_flags();
1570                 return;
1571         }
1572         
1573         td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
1574         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
1575
1576         for(base= FIRSTBASE; base; base= base->next) {
1577                 if TESTBASELIB(base) {
1578                         ob= base->object;
1579                         
1580                         td->flag= TD_SELECTED;
1581                         td->ext = tx;
1582
1583                         /* store ipo keys? */
1584                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1585                                 
1586                                 popfirst(&elems);       // bring back pushed listbase
1587                                 
1588                                 if(elems.first) {
1589                                         float cfraont;
1590                                         int ipoflag;
1591                                         
1592                                         base->flag |= BA_DO_IPO+BA_WAS_SEL;
1593                                         base->flag &= ~SELECT;
1594                                         
1595                                         cfraont= CFRA;
1596                                         set_no_parent_ipo(1);
1597                                         ipoflag= ob->ipoflag;
1598                                         ob->ipoflag &= ~OB_OFFS_OB;
1599                                         
1600                                         pushdata(ob->loc, 7*3*4); // tsk! tsk!
1601                                         
1602                                         for(ik= elems.first; ik; ik= ik->next) {
1603                                                 
1604                                                 /* weak... this doesn't correct for floating values, giving small errors */
1605                                                 CFRA= (short)(ik->val/G.scene->r.framelen);
1606                                                 
1607                                                 do_ob_ipo(ob);
1608                                                 ObjectToTransData(td, ob);      // does where_is_object()
1609                                                 
1610                                                 td->flag= TD_SELECTED;
1611                                                 
1612                                                 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
1613                                                 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
1614                                                 ipokey_to_transdata(ik, td);
1615                                                 
1616                                                 td++;
1617                                                 tx++;
1618                                                 if(ik->next) td->ext= tx;       // prevent corrupting mem!
1619                                         }
1620                                         free_ipokey(&elems);
1621                                         
1622                                         poplast(ob->loc);
1623                                         set_no_parent_ipo(0);
1624                                         
1625                                         CFRA= (short)cfraont;
1626                                         ob->ipoflag= ipoflag;
1627                                         
1628                                         where_is_object(ob);    // restore 
1629                                 }
1630                                 else {
1631                                         ObjectToTransData(td, ob);
1632                                         td->tdi = NULL;
1633                                         td->val = NULL;
1634                                         td++;
1635                                         tx++;
1636                                 }
1637                         }
1638                         else {
1639                                 ObjectToTransData(td, ob);
1640                                 td->tdi = NULL;
1641                                 td->val = NULL;
1642                                 td++;
1643                                 tx++;
1644                         }
1645                 }
1646         }
1647 }
1648
1649 void createTransData(TransInfo *t) 
1650 {
1651         Object *ob= OBACT;
1652         
1653         if (t->context == CTX_TEXTURE) {
1654                 t->flag |= T_TEXTURE;
1655                 createTransTexspace(t);
1656         }
1657         else if (t->context == CTX_EDGE) {
1658                 t->ext = NULL;
1659                 t->flag |= T_EDIT;
1660                 createTransEdge(t);
1661                 if(t->data && t->flag & T_PROP_EDIT) {
1662                         sort_trans_data(t);     // makes selected become first in array
1663                         set_prop_dist(t, 1);
1664                         sort_trans_data_dist(t);
1665                 }
1666         }
1667         else if (G.obedit) {
1668                 t->ext = NULL;
1669                 if (G.obedit->type == OB_MESH) {
1670                         createTransEditVerts(t);        
1671                 }
1672                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1673                         createTransCurveVerts(t);
1674                 }
1675                 else if (G.obedit->type==OB_LATTICE) {
1676                         createTransLatticeVerts(t);
1677                 }
1678                 else if (G.obedit->type==OB_MBALL) {
1679                         createTransMBallVerts(t);
1680                 }
1681                 else if (G.obedit->type==OB_ARMATURE) {
1682                         createTransArmatureVerts(t);
1683                 }                                                       
1684                 else {
1685                         printf("not done yet! only have mesh surface curve\n");
1686                 }
1687
1688                 if(t->data && t->flag & T_PROP_EDIT) {
1689                         if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
1690                                 sort_trans_data(t);     // makes selected become first in array
1691                                 set_prop_dist(t, 0);
1692                                 sort_trans_data_dist(t);
1693                         }
1694                         else {
1695                                 sort_trans_data(t);     // makes selected become first in array
1696                                 set_prop_dist(t, 1);
1697                                 sort_trans_data_dist(t);
1698                         }
1699                 }
1700                 t->flag |= T_EDIT;
1701                 
1702                 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
1703                 if(t->mode==TFM_BONESIZE) {
1704                         t->flag &= ~T_EDIT;
1705                         t->flag |= T_POSE;
1706                         t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
1707                 }
1708         }
1709         else if (ob && (ob->flag & OB_POSEMODE)) {
1710                 createTransPose(OBACT, t);
1711         }
1712         else if (G.f & G_WEIGHTPAINT) {
1713                 /* exception, we look for the one selected armature */
1714                 Base *base;
1715                 for(base=FIRSTBASE; base; base= base->next) {
1716                         if(TESTBASELIB(base)) {
1717                                 if(base->object->type==OB_ARMATURE)
1718                                         if(base->object->flag & OB_POSEMODE)
1719                                                 break;
1720                         }
1721                 }
1722                 if(base) {
1723                         createTransPose(base->object, t);
1724                 }
1725         }
1726         else {
1727                 createTransObject(t);
1728                 t->flag |= T_OBJECT;
1729         }
1730
1731         if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
1732                 t->flag |= T_CAMERA;
1733         }
1734 }
1735