b8f8f0b39921e9f108d75486054cec3ccdce6091
[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         
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         /* handle pending update events, otherwise they got copied below */
1546         for (base= FIRSTBASE; base; base= base->next) {
1547                 if(base->object->recalc) 
1548                         object_handle_update(base->object);
1549         }
1550         
1551         for (base= FIRSTBASE; base; base= base->next) {
1552                 base->flag &= ~BA_WAS_SEL;
1553                 
1554                 if(TESTBASELIB(base)) {
1555                         Object *ob= base->object;
1556                         Object *parsel= ob->parent;
1557                         
1558                         /* if parent selected, deselect */
1559                         while(parsel) {
1560                                 if(parsel->flag & SELECT) break;
1561                                 parsel= parsel->parent;
1562                         }
1563                         
1564                         if(parsel) {
1565                                 base->flag &= ~SELECT;
1566                                 base->flag |= BA_WAS_SEL;
1567                         }
1568                         /* used for flush, depgraph will change recalcs if needed :) */
1569                         ob->recalc |= OB_RECALC_OB;
1570                 }
1571         }
1572         /* all recalc flags get flushed */
1573         DAG_scene_flush_update(G.scene);
1574         
1575         /* and we store them temporal in base (only used for transform code) */
1576         /* this because after doing updates, the object->recalc is cleared */
1577         for (base= FIRSTBASE; base; base= base->next) {
1578                 if(base->object->recalc & OB_RECALC_OB)
1579                         base->flag |= BA_HAS_RECALC_OB;
1580                 if(base->object->recalc & OB_RECALC_DATA)
1581                         base->flag |= BA_HAS_RECALC_DATA;
1582         }
1583 }
1584
1585 static void clear_trans_object_base_flags(void)
1586 {
1587         Base *base;
1588         
1589         base= FIRSTBASE;
1590         while(base) {
1591                 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
1592                 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
1593                 
1594                 base = base->next;
1595         }
1596 }
1597
1598 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
1599 /* note; transdata has been freed already! */
1600 void special_aftertrans_update(TransInfo *t)
1601 {
1602         Object *ob;
1603         Base *base;
1604         int redrawipo=0;
1605         int cancelled= (t->state == TRANS_CANCEL);
1606                 
1607         if(G.obedit) {
1608                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
1609                         allqueue(REDRAWBUTSEDIT, 0);
1610         }
1611         else if( (t->flag & T_POSE) && t->poseobj) {
1612                 bArmature *arm;
1613                 bAction *act;
1614                 bPose   *pose;
1615                 bPoseChannel *pchan;
1616
1617                 ob= t->poseobj;
1618                 arm= ob->data;
1619                 
1620                 if(cancelled)   /* if cancelled we do the update always */
1621                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1622                 else if(G.flags & G_RECORDKEYS) {
1623                         act= ob->action;
1624                         pose= ob->pose;
1625                         
1626                         if (!act)
1627                                 act= ob->action= add_empty_action();
1628                         
1629                         set_pose_keys(ob);  // sets chan->flag to POSE_KEY if bone selected
1630                         for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
1631                                 if (pchan->flag & POSE_KEY){
1632                                         
1633                                         set_action_key(act, pchan, AC_QUAT_X, 1);
1634                                         set_action_key(act, pchan, AC_QUAT_Y, 1);
1635                                         set_action_key(act, pchan, AC_QUAT_Z, 1);
1636                                         set_action_key(act, pchan, AC_QUAT_W, 1);
1637                                 
1638                                         set_action_key(act, pchan, AC_SIZE_X, 1);
1639                                         set_action_key(act, pchan, AC_SIZE_Y, 1);
1640                                         set_action_key(act, pchan, AC_SIZE_Z, 1);
1641                                 
1642                                         set_action_key(act, pchan, AC_LOC_X, 1);
1643                                         set_action_key(act, pchan, AC_LOC_Y, 1);
1644                                         set_action_key(act, pchan, AC_LOC_Z, 1);
1645                                 }
1646                         }
1647                         
1648                         remake_action_ipos (act);
1649                         allspace(REMAKEIPO, 0);
1650                         allqueue(REDRAWACTION, 0);
1651                         allqueue(REDRAWIPO, 0);
1652                         allqueue(REDRAWNLA, 0);
1653                         
1654                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1655                 }
1656                 else if(arm->flag & ARM_DELAYDEFORM) {
1657                         /* old optimize trick... this enforces to bypass the depgraph */
1658                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1659                         ob->recalc= 0;  // is set on OK position already by recalcData()
1660                 }
1661                 /* do not call DAG_object_flush_update always, we dont want actions to update, for inserting keys */
1662                 
1663                 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
1664                         allqueue(REDRAWBUTSEDIT, 0);
1665
1666         }
1667         else {
1668                 base= FIRSTBASE;
1669                 while(base) {   
1670                         
1671                         if(base->flag & BA_DO_IPO) redrawipo= 1;
1672                         
1673                         ob= base->object;
1674
1675                         if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
1676                         
1677                         /* Set autokey if necessary */
1678                         if ((G.flags & G_RECORDKEYS) && (!cancelled) && (base->flag & SELECT)){
1679                         
1680                                 insertkey(&base->object->id, OB_ROT_X);
1681                                 insertkey(&base->object->id, OB_ROT_Y);
1682                                 insertkey(&base->object->id, OB_ROT_Z);
1683                         
1684                                 insertkey(&base->object->id, OB_LOC_X);
1685                                 insertkey(&base->object->id, OB_LOC_Y);
1686                                 insertkey(&base->object->id, OB_LOC_Z);
1687                         
1688                                 insertkey(&base->object->id, OB_SIZE_X);
1689                                 insertkey(&base->object->id, OB_SIZE_Y);
1690                                 insertkey(&base->object->id, OB_SIZE_Z);
1691                                 
1692                                 remake_object_ipos (ob);
1693                                 allqueue(REDRAWIPO, 0);
1694                                 allspace(REMAKEIPO, 0);
1695                                 allqueue(REDRAWVIEW3D, 0);
1696                                 allqueue(REDRAWNLA, 0);
1697                         }
1698                         
1699                         base= base->next;
1700                 }
1701                 
1702         }
1703         
1704         clear_trans_object_base_flags();
1705         
1706         if(redrawipo) {
1707                 allqueue(REDRAWNLA, 0);
1708                 allqueue(REDRAWACTION, 0);
1709                 allqueue(REDRAWIPO, 0);
1710         }
1711         
1712         reset_slowparents();
1713         
1714         /* note; should actually only be done for all objects when a lamp is moved... (ton) */
1715         if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
1716                 reshadeall_displist();
1717 }
1718
1719 static void createTransObject(TransInfo *t)
1720 {
1721         TransData *td = NULL;
1722         TransDataExtension *tx;
1723         Object *ob;
1724         Base *base;
1725         IpoKey *ik;
1726         ListBase elems;
1727         
1728         set_trans_object_base_flags(t);
1729
1730         /* count */     
1731         for(base= FIRSTBASE; base; base= base->next) {
1732                 if TESTBASELIB(base) {
1733                         ob= base->object;
1734                         
1735                         /* store ipo keys? */
1736                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1737                                 elems.first= elems.last= NULL;
1738                                 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
1739                                 
1740                                 pushdata(&elems, sizeof(ListBase));
1741                                 
1742                                 for(ik= elems.first; ik; ik= ik->next) t->total++;
1743
1744                                 if(elems.first==NULL) t->total++;
1745                         }
1746                         else {
1747                                 t->total++;
1748                         }
1749                 }
1750         }
1751
1752         if(!t->total) {
1753                 /* clear here, main transform function escapes too */
1754                 clear_trans_object_base_flags();
1755                 return;
1756         }
1757         
1758         td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
1759         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
1760
1761         for(base= FIRSTBASE; base; base= base->next) {
1762                 if TESTBASELIB(base) {
1763                         ob= base->object;
1764                         
1765                         td->flag= TD_SELECTED;
1766                         td->ext = tx;
1767
1768                         /* store ipo keys? */
1769                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1770                                 
1771                                 popfirst(&elems);       // bring back pushed listbase
1772                                 
1773                                 if(elems.first) {
1774                                         float cfraont;
1775                                         int ipoflag;
1776                                         
1777                                         base->flag |= BA_DO_IPO+BA_WAS_SEL;
1778                                         base->flag &= ~SELECT;
1779                                         
1780                                         cfraont= CFRA;
1781                                         set_no_parent_ipo(1);
1782                                         ipoflag= ob->ipoflag;
1783                                         ob->ipoflag &= ~OB_OFFS_OB;
1784                                         
1785                                         pushdata(ob->loc, 7*3*4); // tsk! tsk!
1786                                         
1787                                         for(ik= elems.first; ik; ik= ik->next) {
1788                                                 
1789                                                 /* weak... this doesn't correct for floating values, giving small errors */
1790                                                 CFRA= (short)(ik->val/G.scene->r.framelen);
1791                                                 
1792                                                 do_ob_ipo(ob);
1793                                                 ObjectToTransData(td, ob);      // does where_is_object()
1794                                                 
1795                                                 td->flag= TD_SELECTED;
1796                                                 
1797                                                 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
1798                                                 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
1799                                                 ipokey_to_transdata(ik, td);
1800                                                 
1801                                                 td++;
1802                                                 tx++;
1803                                                 if(ik->next) td->ext= tx;       // prevent corrupting mem!
1804                                         }
1805                                         free_ipokey(&elems);
1806                                         
1807                                         poplast(ob->loc);
1808                                         set_no_parent_ipo(0);
1809                                         
1810                                         CFRA= (short)cfraont;
1811                                         ob->ipoflag= ipoflag;
1812                                         
1813                                         where_is_object(ob);    // restore 
1814                                 }
1815                                 else {
1816                                         ObjectToTransData(td, ob);
1817                                         td->tdi = NULL;
1818                                         td->val = NULL;
1819                                         td++;
1820                                         tx++;
1821                                 }
1822                         }
1823                         else {
1824                                 ObjectToTransData(td, ob);
1825                                 td->tdi = NULL;
1826                                 td->val = NULL;
1827                                 td++;
1828                                 tx++;
1829                         }
1830                 }
1831         }
1832 }
1833
1834 void createTransData(TransInfo *t) 
1835 {
1836         Object *ob= OBACT;
1837         
1838         if (t->context == CTX_TEXTURE) {
1839                 t->flag |= T_TEXTURE;
1840                 createTransTexspace(t);
1841         }
1842         else if (t->context == CTX_EDGE) {
1843                 t->ext = NULL;
1844                 t->flag |= T_EDIT;
1845                 createTransEdge(t);
1846                 if(t->data && t->flag & T_PROP_EDIT) {
1847                         sort_trans_data(t);     // makes selected become first in array
1848                         set_prop_dist(t, 1);
1849                         sort_trans_data_dist(t);
1850                 }
1851         }
1852         else if (t->spacetype == SPACE_IMAGE) {
1853                 t->flag |= T_POINTS|T_2D_EDIT;
1854                 createTransUVs(t);
1855                 if(t->data && (t->flag & T_PROP_EDIT)) {
1856                         sort_trans_data(t);     // makes selected become first in array
1857                         set_prop_dist(t, 1);
1858                         sort_trans_data_dist(t);
1859                 }
1860         }
1861         else if (G.obedit) {
1862                 t->ext = NULL;
1863                 if (G.obedit->type == OB_MESH) {
1864                         createTransEditVerts(t);        
1865                 }
1866                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1867                         createTransCurveVerts(t);
1868                 }
1869                 else if (G.obedit->type==OB_LATTICE) {
1870                         createTransLatticeVerts(t);
1871                 }
1872                 else if (G.obedit->type==OB_MBALL) {
1873                         createTransMBallVerts(t);
1874                 }
1875                 else if (G.obedit->type==OB_ARMATURE) {
1876                         createTransArmatureVerts(t);
1877                 }                                                       
1878                 else {
1879                         printf("not done yet! only have mesh surface curve\n");
1880                 }
1881
1882                 if(t->data && t->flag & T_PROP_EDIT) {
1883                         if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
1884                                 sort_trans_data(t);     // makes selected become first in array
1885                                 set_prop_dist(t, 0);
1886                                 sort_trans_data_dist(t);
1887                         }
1888                         else {
1889                                 sort_trans_data(t);     // makes selected become first in array
1890                                 set_prop_dist(t, 1);
1891                                 sort_trans_data_dist(t);
1892                         }
1893                 }
1894
1895                 t->flag |= T_EDIT|T_POINTS;
1896                 
1897                 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
1898                 if(t->mode==TFM_BONESIZE) {
1899                         t->flag &= ~(T_EDIT|T_POINTS);
1900                         t->flag |= T_POSE;
1901                         t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
1902                 }
1903         }
1904         else if (ob && (ob->flag & OB_POSEMODE)) {
1905                 createTransPose(OBACT, t);
1906         }
1907         else if (G.f & G_WEIGHTPAINT) {
1908                 /* exception, we look for the one selected armature */
1909                 Base *base;
1910                 for(base=FIRSTBASE; base; base= base->next) {
1911                         if(TESTBASELIB(base)) {
1912                                 if(base->object->type==OB_ARMATURE)
1913                                         if(base->object->flag & OB_POSEMODE)
1914                                                 break;
1915                         }
1916                 }
1917                 if(base) {
1918                         createTransPose(base->object, t);
1919                 }
1920         }
1921         else {
1922                 createTransObject(t);
1923                 t->flag |= T_OBJECT;
1924         }
1925
1926         if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
1927                 t->flag |= T_CAMERA;
1928         }
1929 }
1930