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