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