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