Fixed Constraint projection code in perspective mode. When using a planar constraints...
[blender.git] / source / blender / src / transform.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 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #include "BLI_winstuff.h"
46 #endif
47
48 #include "MEM_guardedalloc.h"
49
50 #include "DNA_action_types.h"
51 #include "DNA_armature_types.h"
52 #include "DNA_camera_types.h"
53 #include "DNA_curve_types.h"
54 #include "DNA_effect_types.h"
55 #include "DNA_ika_types.h"
56 #include "DNA_image_types.h"
57 #include "DNA_ipo_types.h"
58 #include "DNA_key_types.h"
59 #include "DNA_lamp_types.h"
60 #include "DNA_lattice_types.h"
61 #include "DNA_mesh_types.h"
62 #include "DNA_meshdata_types.h"
63 #include "DNA_meta_types.h"
64 #include "DNA_object_types.h"
65 #include "DNA_scene_types.h"
66 #include "DNA_screen_types.h"
67 #include "DNA_texture_types.h"
68 #include "DNA_view3d_types.h"
69 #include "DNA_world_types.h"
70 #include "DNA_userdef_types.h"
71 #include "DNA_property_types.h"
72 #include "DNA_vfont_types.h"
73 #include "DNA_constraint_types.h"
74
75 #include "BIF_editview.h"
76 #include "BIF_resources.h"
77 #include "BIF_mywindow.h"
78 #include "BIF_gl.h"
79 #include "BIF_editlattice.h"
80 #include "BIF_editarmature.h"
81 #include "BIF_editmesh.h"
82 #include "BIF_screen.h"
83 #include "BIF_space.h"
84 #include "BIF_toolbox.h"
85
86 #include "BKE_action.h"
87 #include "BKE_armature.h"
88 #include "BKE_blender.h"
89 #include "BKE_curve.h"
90 #include "BKE_displist.h"
91 #include "BKE_effect.h"
92 #include "BKE_global.h"
93 #include "BKE_ipo.h"
94 #include "BKE_lattice.h"
95 #include "BKE_mball.h"
96 #include "BKE_object.h"
97 #include "BKE_utildefines.h"
98
99 #include "BSE_view.h"
100 #include "BSE_edit.h"
101 #include "BSE_editipo.h"
102 #include "BSE_editipo_types.h"
103 #include "BDR_editobject.h"             // reset_slowparents()
104
105 #include "BLI_arithb.h"
106 #include "BLI_editVert.h"
107 #include "BLI_ghash.h"
108
109 #include "PIL_time.h"
110
111 #include "blendef.h"
112
113 #include "mydevice.h"
114
115 extern ListBase editNurb;
116 extern ListBase editelems;
117
118 extern void helpline(float *vec);
119
120
121 #include "transform.h"
122 #include "transform_generics.h"
123 #include "transform_constraints.h"
124 #include "transform_numinput.h"
125
126 /* GLOBAL VARIABLE THAT SHOULD MOVED TO SCREEN MEMBER OR SOMETHING  */
127 TransInfo Trans;
128 int     LastMode = TFM_TRANSLATION;
129
130 /* ************************** Functions *************************** */
131
132 /* ************************** CONVERSIONS ************************* */
133
134 static int allocTransData(void)
135 {
136         int count, mode=0;
137         countall();
138         
139         if(mode) count= G.totvert;
140         else count= G.totvertsel;
141         printf("count: %d\n", count);
142         if(G.totvertsel==0) {
143                 count= 0;
144                 return count;
145         }
146         
147         Trans.total = count;
148         Trans.data= MEM_mallocN(Trans.total*sizeof(TransData), "TransObData(EditMode)");
149         return count;
150 }
151
152 void createTransTexspace(void)
153 {
154         TransData *td;
155         Object *ob;
156         ID *id;
157         
158         ob= OBACT;
159         Trans.total = 1;
160         td= Trans.data= MEM_callocN(sizeof(TransData), "TransTexspace");
161         td->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
162         
163         td->flag= TD_SELECTED;
164         VECCOPY(td->center, ob->obmat[3]);
165         td->ob = ob;
166         
167         Mat3CpyMat4(td->mtx, ob->obmat);
168         Mat3Inv(td->smtx, td->mtx);
169         
170         id= ob->data;
171         if(id==0);
172         else if( GS(id->name)==ID_ME) {
173                 Mesh *me= ob->data;
174                 me->texflag &= ~AUTOSPACE;
175                 td->loc= me->loc;
176                 td->ext->rot= me->rot;
177                 td->ext->size= me->size;
178         }
179         else if( GS(id->name)==ID_CU) {
180                 Curve *cu= ob->data;
181                 cu->texflag &= ~CU_AUTOSPACE;
182                 td->loc= cu->loc;
183                 td->ext->rot= cu->rot;
184                 td->ext->size= cu->size;
185         }
186         else if( GS(id->name)==ID_MB) {
187                 MetaBall *mb= ob->data;
188                 mb->texflag &= ~MB_AUTOSPACE;
189                 td->loc= mb->loc;
190                 td->ext->rot= mb->rot;
191                 td->ext->size= mb->size;
192         }
193         
194         VECCOPY(td->iloc, td->loc);
195         VECCOPY(td->ext->irot, td->ext->rot);
196         VECCOPY(td->ext->isize, td->ext->size);
197 }
198
199
200 /* ********************* pose mode ************* */
201
202 /* callback, make sure it's identical structured as next one */
203 static void count_bone_select(ListBase *lb, int *counter) 
204 {
205         Bone *bone;
206         
207         for(bone= lb->first; bone; bone= bone->next) {
208                 if (bone->flag & BONE_SELECTED) {
209                         /* We don't let IK children get "grabbed" */
210                         /* ALERT! abusive global Trans here */
211                         if ( (Trans.mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
212                                 (*counter)++;
213                                 return; // no transform on children if one parent bone is selected
214                         }
215                 }
216                 count_bone_select( &bone->childbase, counter);
217         }
218 }
219
220 /* callback */
221 static void add_pose_transdata(ListBase *lb, Object *ob, TransData **tdp)
222 {
223         Bone *bone;
224         TransData *td= *tdp;
225         float   parmat[4][4], tempmat[4][4];
226         float tempobmat[4][4];
227         float vec[3];
228         
229         for(bone= lb->first; bone; bone= bone->next) {
230                 if (bone->flag & BONE_SELECTED) {
231                         /* We don't let IK children get "grabbed" */
232                         /* ALERT! abusive global Trans here */
233                         if ( (Trans.mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
234                                 
235                                 get_bone_root_pos (bone, vec, 1);
236                                 
237                                 //VecAddf (centroid, centroid, vec);
238                                 VECCOPY(td->center, vec);
239                                 
240                                 td->ob = ob;
241                                 td->dist= 0.0f;
242                                 td->flag= TD_SELECTED|TD_USEQUAT;
243                                 td->loc = bone->loc;
244                                 VECCOPY(td->iloc, bone->loc);
245                                 
246                                 td->ext->rot= NULL;
247                                 td->ext->quat= bone->quat;
248                                 td->ext->size= bone->size;
249                                 td->ext->bone= bone; // FIXME: Dangerous
250
251                                 QUATCOPY(td->ext->iquat, bone->quat);
252                                 VECCOPY(td->ext->isize, bone->size);
253                                 
254                                 /* Get the matrix of this bone minus the usertransform */
255                                 Mat4CpyMat4 (tempobmat, bone->obmat);
256                                 Mat4One (bone->obmat);
257                                 get_objectspace_bone_matrix(bone, tempmat, 1, 1);
258                                 Mat4CpyMat4 (bone->obmat, tempobmat);
259
260                                 Mat4MulMat4 (parmat, tempmat, ob->obmat);       /* Original */
261                                 
262                                 Mat3CpyMat4 (td->mtx, parmat);
263                                 Mat3Inv (td->smtx, td->mtx);
264                                 
265                                 (*tdp)++;
266                                 return; // see above function
267                         }
268                 }
269                 add_pose_transdata(&bone->childbase, ob, tdp);
270         }
271 }
272
273 static void createTransPose(void)
274 {
275         bArmature *arm;
276         TransData *td;
277         TransDataExtension *tdx;
278         int i;
279         
280         Trans.total= 0; // to be able to return
281         
282         /* check validity of state */
283         arm=get_armature (G.obpose);
284         if (arm==NULL) return;
285         
286         if (arm->flag & ARM_RESTPOS){
287                 notice ("Transformation not possible while Rest Position is enabled");
288                 return;
289         }
290         if (!(G.obpose->lay & G.vd->lay)) return;
291
292         /* copied from old code, no idea. we let linker solve it for now */
293         {
294                 extern void figure_bone_nocalc(Object *ob);
295                 extern void figure_pose_updating(void);
296
297                 /* figure out which bones need calculating */
298                 figure_bone_nocalc(G.obpose);
299                 figure_pose_updating();
300         }
301         
302         /* copied from old code, no idea... (ton) */
303         apply_pose_armature(arm, G.obpose->pose, 0);
304         where_is_armature (G.obpose);
305         
306         /* count total */
307         count_bone_select(&arm->bonebase, &Trans.total);
308         
309         if(Trans.total==0 && Trans.mode==TFM_TRANSLATION) {
310                 Trans.mode= TFM_ROTATION;
311                 count_bone_select(&arm->bonebase, &Trans.total);
312         }               
313         if(Trans.total==0) return;
314         
315         /* init trans data */
316     td = Trans.data = MEM_mallocN(Trans.total*sizeof(TransData), "TransPoseBone");
317     tdx = MEM_mallocN(Trans.total*sizeof(TransDataExtension), "TransPoseBoneExt");
318         for(i=0; i<Trans.total; i++, td++, tdx++) {
319                 td->ext= tdx;
320                 td->tdi = NULL;
321         }       
322         /* recursive fill trans data */
323         td= Trans.data;
324         add_pose_transdata(&arm->bonebase, G.obpose, &td);
325         
326 }
327
328 static void createTransArmatureVerts(void)
329 {
330         EditBone *ebo;
331         TransData *td;
332         float mtx[3][3], smtx[3][3];
333
334         Trans.total = 0;
335         for (ebo=G.edbo.first;ebo;ebo=ebo->next){
336                 if (ebo->flag & BONE_TIPSEL){
337                         Trans.total++;
338                 }
339                 if (ebo->flag & BONE_ROOTSEL){
340                         Trans.total++;
341                 }
342         }
343
344     if (!Trans.total) return;
345         
346         Mat3CpyMat4(mtx, G.obedit->obmat);
347         Mat3Inv(smtx, mtx);
348
349     td = Trans.data = MEM_mallocN(Trans.total*sizeof(TransData), "TransEditBone");
350         
351         for (ebo=G.edbo.first;ebo;ebo=ebo->next){
352                 if (ebo->flag & BONE_TIPSEL){
353                         VECCOPY (td->iloc, ebo->tail);
354                         td->loc= ebo->tail;
355                         td->flag= TD_SELECTED;
356
357                         Mat3CpyMat3(td->smtx, smtx);
358                         Mat3CpyMat3(td->mtx, mtx);
359
360                         td->ext = NULL;
361                         td->tdi = NULL;
362
363                         td->dist = 0.0f;
364                         
365                         td++;
366                 }
367                 if (ebo->flag & BONE_ROOTSEL){
368                         VECCOPY (td->iloc, ebo->head);
369                         td->loc= ebo->head;
370                         td->flag= TD_SELECTED;
371
372                         Mat3CpyMat3(td->smtx, smtx);
373                         Mat3CpyMat3(td->mtx, mtx);
374
375                         td->ext = NULL;
376                         td->tdi = NULL;
377
378                         td->dist = 0.0f;
379                 
380                         td++;
381                 }
382                         
383         }
384 }
385
386 static void createTransMBallVerts(void)
387 {
388         MetaElem *ml;
389         TransData *td;
390         TransDataExtension *tx;
391         float mtx[3][3], smtx[3][3];
392         int count;
393
394         count = allocTransData();
395         if (!count) return;
396
397         tx = MEM_mallocN(Trans.total*sizeof(TransDataExtension), "MetaElement_TransExtension");
398
399         Mat3CpyMat4(mtx, G.obedit->obmat);
400         Mat3Inv(smtx, mtx);
401     
402         td = Trans.data;
403     ml= editelems.first;
404         while(ml) {
405                 if(ml->flag & SELECT) {
406                         td->loc= &ml->x;
407                         VECCOPY(td->iloc, td->loc);
408                         VECCOPY(td->center, td->loc);
409                         td->flag= TD_SELECTED;
410
411                         Mat3CpyMat3(td->smtx, smtx);
412                         Mat3CpyMat3(td->mtx, mtx);
413
414                         td->ext = tx;
415                         td->tdi = NULL;
416
417                         tx->size = &ml->expx;
418                         tx->isize[0] = ml->expx;
419                         tx->isize[1] = ml->expy;
420                         tx->isize[2] = ml->expz;
421
422                         tx->rot = NULL;
423
424                         td->dist = 0.0f;
425
426                         td++;
427                         tx++;
428                 }
429                 ml= ml->next;
430         }
431
432
433 static void createTransCurveVerts(void)
434 {
435         TransData *td = NULL;
436         Nurb *nu;
437         BezTriple *bezt;
438         BPoint *bp;
439         float mtx[3][3], smtx[3][3];
440         int a;
441         int count=0;
442         int mode = 0; /*This used for. . .what?*/
443         //int proptrans= 0;
444
445         count = allocTransData();
446         if (!count) return;
447
448         Mat3CpyMat4(mtx, G.obedit->obmat);
449         Mat3Inv(smtx, mtx);
450
451     td = Trans.data;
452         nu= editNurb.first;
453         while(nu) {
454                 if((nu->type & 7)==CU_BEZIER) {
455                         a= nu->pntsu;
456                         bezt= nu->bezt;
457                         while(a--) {
458                                 if(bezt->hide==0) {
459                                         if(mode==1 || (bezt->f1 & 1)) {
460                                                 VECCOPY(td->iloc, bezt->vec[0]);
461                                                 td->loc= bezt->vec[0];
462                                                 VECCOPY(td->center, td->loc);
463                                                 td->flag= TD_SELECTED;
464                                                 td->ext = NULL;
465                                                 td->tdi = NULL;
466
467                                                 Mat3CpyMat3(td->smtx, smtx);
468                                                 Mat3CpyMat3(td->mtx, mtx);
469
470                                                 td->dist = 0.0f;
471                         
472                                                 td++;
473                                                 count++;
474                                         }
475                                         if(mode==1 || (bezt->f2 & 1)) {
476                                                 VECCOPY(td->iloc, bezt->vec[1]);
477                                                 td->loc= bezt->vec[1];
478                                                 VECCOPY(td->center, td->loc);
479                                                 td->flag= TD_SELECTED;
480                                                 td->ext = NULL;
481                                                 td->tdi = NULL;
482
483                                                 Mat3CpyMat3(td->smtx, smtx);
484                                                 Mat3CpyMat3(td->mtx, mtx);
485
486                                                 td->dist = 0.0f;
487                         
488                                                 td++;
489                                                 count++;
490                                         }
491                                         if(mode==1 || (bezt->f3 & 1)) {
492                                                 VECCOPY(td->iloc, bezt->vec[2]);
493                                                 td->loc= bezt->vec[2];
494                                                 VECCOPY(td->center, td->loc);
495                                                 td->flag= TD_SELECTED;
496                                                 td->ext = NULL;
497                                                 td->tdi = NULL;
498
499                                                 Mat3CpyMat3(td->smtx, smtx);
500                                                 Mat3CpyMat3(td->mtx, mtx);
501
502                                                 td->dist = 0.0f;
503                         
504                                                 td++;
505                                                 count++;
506                                         }
507                                 }
508                                 bezt++;
509                         }
510                 }
511                 else {
512                         a= nu->pntsu*nu->pntsv;
513                         bp= nu->bp;
514                         while(a--) {
515                                 if(bp->hide==0) {
516                                         if(mode==1 || (bp->f1 & 1)) {
517                                                 VECCOPY(td->iloc, bp->vec);
518                                                 td->loc= bp->vec;
519                                                 VECCOPY(td->center, td->loc);
520                                                 td->flag= TD_SELECTED;
521                                                 td->ext = NULL;
522                                                 td->tdi = NULL;
523
524                                                 Mat3CpyMat3(td->smtx, smtx);
525                                                 Mat3CpyMat3(td->mtx, mtx);
526
527                                                 td->dist = 0.0f;
528                         
529                                                 td++;
530                                                 count++;
531                                         }
532                                 }
533                                 bp++;
534                         }
535                 }
536                 nu= nu->next;
537         }
538 }
539
540 static void createTransLatticeVerts(void)
541 {
542         TransData *td = NULL;
543         int count = 0;
544         BPoint *bp;
545         float mtx[3][3], smtx[3][3];
546         int mode = 0; /*This used for proportional editing*/
547         /*should find a function that does this. . . what else is this used for? I DONT KNOW!*/
548         int a;
549         //int proptrans= 0;
550
551         bp= editLatt->def;
552         
553         
554         count = allocTransData();
555         
556         if (!count) return;
557         
558         Mat3CpyMat4(mtx, G.obedit->obmat);
559         Mat3Inv(smtx, mtx);
560
561         td = Trans.data;
562         bp= editLatt->def;
563         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
564         while(a--) {
565                 if(mode==1 || (bp->f1 & 1)) {
566                         if(bp->hide==0) {
567                                 VECCOPY(td->iloc, bp->vec);
568                                 td->loc= bp->vec;
569                                 VECCOPY(td->center, td->loc);
570                                 td->flag= TD_SELECTED;
571
572                                 Mat3CpyMat3(td->smtx, smtx);
573                                 Mat3CpyMat3(td->mtx, mtx);
574
575                                 td->ext = NULL;
576                                 td->tdi = NULL;
577
578                                 td->dist = 0.0f;
579
580                                 td++;
581                                 count++;
582                         }
583                 }
584                 bp++;
585         }
586
587
588 static void VertsToTransData(TransData *td, EditVert *eve)
589 {
590         td->flag = 0;
591         td->loc = eve->co;
592         VECCOPY(td->center, td->loc);
593         VECCOPY(td->iloc, td->loc);
594         td->ext = NULL;
595         td->tdi = NULL;
596 }
597
598 static void createTransEditVerts(void)
599 {
600         TransData *tob = NULL;
601         int totsel = 0;
602         EditMesh *em = G.editMesh;
603         EditVert *eve;
604         float mtx[3][3], smtx[3][3];
605         /*should find a function that does this. . .*/
606         // int proptrans= 0;
607                 
608         // transform now requires awareness for select mode, so we tag the f1 flags in verts
609         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
610                 for(eve= em->verts.first; eve; eve= eve->next) {
611                         if(eve->h==0 && (eve->f & SELECT)) {
612                                 eve->f1= SELECT;
613                                 Trans.total++;
614                         }
615                         else
616                                 eve->f1= 0;
617                 }
618         }
619         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
620                 EditEdge *eed;
621                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
622                 for(eed= em->edges.first; eed; eed= eed->next) {
623                         if(eed->h==0 && (eed->f & SELECT))
624                                 eed->v1->f1= eed->v2->f1= SELECT;
625                 }
626                 for(eve= em->verts.first; eve; eve= eve->next)
627                         if(eve->f1)
628                                 Trans.total++;
629         }
630         else {
631                 EditFace *efa;
632                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
633                 for(efa= em->faces.first; efa; efa= efa->next) {
634                         if(efa->h==0 && (efa->f & SELECT)) {
635                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
636                                 if(efa->v4) efa->v4->f1= SELECT;
637                         }
638                 }
639                 for(eve= em->verts.first; eve; eve= eve->next)
640                         if(eve->f1)
641                                 Trans.total++;
642         }
643         
644         totsel = Trans.total;
645         /* proportional edit exception... */
646         if((G.f & G_PROPORTIONAL) && Trans.total) {
647                 for(eve= em->verts.first; eve; eve= eve->next) {
648                         if(eve->h==0 && (!(eve->f1 & SELECT))) {
649                                 eve->f1 = 2;
650                                 Trans.total++;
651                         }
652                 }
653         }
654         
655         /* and now make transverts */
656     if (!Trans.total) return;
657         
658         Mat3CpyMat4(mtx, G.obedit->obmat);
659         Mat3Inv(smtx, mtx);
660
661     tob = Trans.data = MEM_mallocN(Trans.total*sizeof(TransData), "TransEditVert");
662
663         for (eve=em->verts.first; eve; eve=eve->next)
664         {
665                 if (eve->f1 == SELECT) {
666                         VertsToTransData(tob, eve);
667
668                         tob->flag |= TD_SELECTED;
669
670                         Mat3CpyMat3(tob->smtx, smtx);
671                         Mat3CpyMat3(tob->mtx, mtx);
672
673                         tob->dist = 0.0f;
674
675                         tob++;
676                 }       
677         }       
678
679         /* PROPORTIONAL*/
680         if (G.f & G_PROPORTIONAL) {
681                 for (eve=em->verts.first; eve; eve=eve->next)
682                 {
683                         TransData *td;
684                         int i;
685                         float dist, vec[3];
686                         if (eve->f1 == 2) {
687
688                                 VertsToTransData(tob, eve);
689
690                                 Mat3CpyMat3(tob->smtx, smtx);
691                                 Mat3CpyMat3(tob->mtx, mtx);
692                         
693                                 tob->dist = -1;
694
695                                 td = Trans.data;
696                                 for (i = 0; i < totsel; i++, td++) {
697                                         VecSubf(vec, tob->center, td->center);
698                                         Mat3MulVecfl(mtx, vec);
699                                         dist = Normalise(vec);
700                                         if (tob->dist == -1) {
701                                                 tob->dist = dist;
702                                         }
703                                         else if (dist < tob->dist) {
704                                                 tob->dist = dist;
705                                         }
706                                 }
707
708                                 tob++;
709                         }       
710                 }       
711         }
712 }
713
714 /* **************** IpoKey stuff, for Object TransData ********** */
715
716 /* storage of bezier triple. thats why -3 and +3! */
717 static void set_tdi_old(float *old, float *poin)
718 {
719         old[0]= *(poin);
720         old[3]= *(poin-3);
721         old[6]= *(poin+3);
722 }
723
724 /* while transforming */
725 static void add_tdi_poin(float *poin, float *old, float delta)
726 {
727         if(poin) {
728                 poin[0]= old[0]+delta;
729                 poin[-3]= old[3]+delta;
730                 poin[3]= old[6]+delta;
731         }
732 }
733
734 /* fill ipokey transdata with old vals and pointers */
735 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
736 {
737         extern int ob_ar[];             // blenkernel ipo.c
738         TransDataIpokey *tdi= td->tdi;
739         BezTriple *bezt;
740         int a, delta= 0;
741         
742         for(a=0; a<OB_TOTIPO; a++) {
743                 if(ik->data[a]) {
744                         bezt= ik->data[a];
745                         
746                         switch( ob_ar[a] ) {
747                                 case OB_LOC_X:
748                                 case OB_DLOC_X:
749                                         tdi->locx= &(bezt->vec[1][1]); break;
750                                 case OB_LOC_Y:
751                                 case OB_DLOC_Y:
752                                         tdi->locy= &(bezt->vec[1][1]); break;
753                                 case OB_LOC_Z:
754                                 case OB_DLOC_Z:
755                                         tdi->locz= &(bezt->vec[1][1]); break;
756                                         
757                                 case OB_DROT_X:
758                                         delta= 1;
759                                 case OB_ROT_X:
760                                         tdi->rotx= &(bezt->vec[1][1]); break;
761                                 case OB_DROT_Y:
762                                         delta= 1;
763                                 case OB_ROT_Y:
764                                         tdi->roty= &(bezt->vec[1][1]); break;
765                                 case OB_DROT_Z:
766                                         delta= 1;
767                                 case OB_ROT_Z:
768                                         tdi->rotz= &(bezt->vec[1][1]); break;
769                                         
770                                 case OB_SIZE_X:
771                                 case OB_DSIZE_X:
772                                         tdi->sizex= &(bezt->vec[1][1]); break;
773                                 case OB_SIZE_Y:
774                                 case OB_DSIZE_Y:
775                                         tdi->sizey= &(bezt->vec[1][1]); break;
776                                 case OB_SIZE_Z:
777                                 case OB_DSIZE_Z:
778                                         tdi->sizez= &(bezt->vec[1][1]); break;          
779                         }       
780                 }
781         }
782         
783         /* oldvals for e.g. undo */
784         if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
785         if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
786         if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
787         
788         /* remember, for mapping curves ('1'=10 degrees)  */
789         if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
790         if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
791         if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
792         
793         /* this is not allowed to be dsize! */
794         if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
795         if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
796         if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
797         
798         tdi->flag= TOB_IPO;
799         if(delta) tdi->flag |= TOB_IPODROT;
800 }
801
802
803 /* *************************** Object Transform data ******************* */
804
805 static void ObjectToTransData(TransData *td, Object *ob) 
806 {
807         float obmtx[3][3];
808         Object *tr;
809         void *cfirst, *clast;
810
811         cfirst = ob->constraints.first;
812         clast = ob->constraints.last;
813         ob->constraints.first=ob->constraints.last=NULL;
814
815         tr= ob->track;
816         ob->track= NULL;
817
818         where_is_object(ob);
819
820         ob->track= tr;
821
822         ob->constraints.first = cfirst;
823         ob->constraints.last = clast;
824
825         td->ob = ob;
826
827         td->loc = ob->loc;
828         VECCOPY(td->iloc, td->loc);
829         
830         td->ext->rot = ob->rot;
831         VECCOPY(td->ext->irot, ob->rot);
832         VECCOPY(td->ext->drot, ob->drot);
833         
834         td->ext->size = ob->size;
835         VECCOPY(td->ext->isize, ob->size);
836         VECCOPY(td->ext->dsize, ob->dsize);
837
838         VECCOPY(td->center, ob->obmat[3]);
839
840         Mat3CpyMat4(td->mtx, ob->obmat);
841
842         if (ob->parent)
843         {
844                 float totmat[3][3], obinv[3][3];
845                 
846                 /* we calculate smtx without obmat: so a parmat */
847                 object_to_mat3(ob, obmtx);
848                 Mat3CpyMat4(totmat, ob->obmat);
849                 Mat3Inv(obinv, totmat);
850                 Mat3MulMat3(td->smtx, obmtx, obinv);
851                 Mat3Inv(td->mtx, td->smtx);
852         }
853         else
854         {
855                 Mat3One(td->smtx);
856                 Mat3One(td->mtx);
857         }
858 }
859
860 /* only used in function below, stuff to be removed */
861 static Object *is_a_parent_selected_int(Object *startob, Object *ob, GHash *done_hash) 
862 {
863         if (ob!=startob && TESTBASE(ob))
864                 return ob;
865         
866         if (BLI_ghash_haskey(done_hash, ob))
867                 return NULL;
868         else
869                 BLI_ghash_insert(done_hash, ob, NULL);
870         
871         if (ob->parent) {
872                 Object *par= is_a_parent_selected_int(startob, ob->parent, done_hash);
873                 if (par)
874                         return par;
875         }
876         return NULL;
877 }
878
879 /* only used in function below, stuff to be removed */
880 static Object *is_a_parent_selected(Object *ob) 
881 {
882         GHash *gh= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
883         Object *res= is_a_parent_selected_int(ob, ob, gh);
884         BLI_ghash_free(gh, NULL, NULL);
885         
886         return res;
887 }
888
889
890
891 /* sets flags in Bases to define whether they take part in transform */
892 /* it deselects Bases, so we have to call the clear function always after */
893 static void set_trans_object_base_flags(TransInfo *t)
894 {
895         /*
896          if Base selected and has parent selected:
897          base->flag= BA_WASSEL+BA_PARSEL
898          if base not selected and parent selected:
899          base->flag= BA_PARSEL
900          */
901         GHash *object_to_base_hash= NULL; 
902         Base *base;
903         
904         /* moved to start of function, it is needed for hooks now too */
905         if (!object_to_base_hash) {
906                 Base *b;
907                 object_to_base_hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
908                 
909                 for (b= FIRSTBASE; b; b= b->next)
910                         BLI_ghash_insert(object_to_base_hash, b->object, b);
911         }
912         
913         /* makes sure base flags and object flags are identical */
914         copy_baseflags();
915         
916         for (base= FIRSTBASE; base; base= base->next) {
917                 base->flag &= ~(BA_PARSEL+BA_WASSEL);
918                 
919                 if( (base->lay & G.vd->lay) && base->object->id.lib==0) {
920                         Object *ob= base->object;
921                         Object *parsel= is_a_parent_selected(ob);
922                         
923                         /* parentkey here? */
924                         
925                         if(parsel) {
926                                 if(base->flag & SELECT) {
927                                         base->flag &= ~SELECT;
928                                         base->flag |= (BA_PARSEL+BA_WASSEL);
929                                 }
930                                 else base->flag |= BA_PARSEL;
931                         }
932                         
933                         if(t->mode==TFM_TRANSLATION)  {
934                                 if(ob->track && TESTBASE(ob->track) && (base->flag & SELECT)==0)  
935                                         base->flag |= BA_PARSEL;
936                         }
937                         
938                         /* updates? */
939                         if(ob->hooks.first) {
940                                 Base *b;
941                                 ObHook *hook= ob->hooks.first;
942                                 
943                                 while(hook) {
944                                         if(hook->parent) {
945                                                 Object *parsel= is_a_parent_selected(hook->parent);
946                                                 
947                                                 b= BLI_ghash_lookup(object_to_base_hash, hook->parent);
948                                                 if(parsel || ((base->flag | b->flag) & (SELECT | BA_PARSEL)) ) {
949                                                         base->flag |= BA_DISP_UPDATE;
950                                                 }
951                                         }
952                                         hook= hook->next;
953                                 }
954                         }
955                         
956                         if(ob->parent && ob->parent->type==OB_LATTICE)
957                                 if(ob->parent->hooks.first) base->flag |= BA_DISP_UPDATE;
958                         
959                         if(base->flag & (SELECT | BA_PARSEL)) {
960                                 
961                                 base->flag |= BA_WHERE_UPDATE;
962                                 
963                                 if(ob->parent) {
964                                         if(ob->parent->type==OB_LATTICE) base->flag |= BA_DISP_UPDATE;
965                                         else if(ob->partype==PARSKEL) {
966                                                 if ELEM3(ob->parent->type, OB_IKA, OB_CURVE, OB_ARMATURE) 
967                                                         base->flag |= BA_DISP_UPDATE;
968                                         }
969                                 }
970                                 if(ob->track) {
971                                         ;
972                                 }
973                                 
974                                 if( give_parteff(ob) ) base->flag |= BA_DISP_UPDATE;
975                                 
976                                 if(ob->type==OB_MBALL) {
977                                         Base *b;
978                                         
979                                         b= BLI_ghash_lookup(object_to_base_hash, find_basis_mball(ob));
980                                         b->flag |= BA_DISP_UPDATE;
981                                 }
982                         }
983                 }
984         }
985         
986         if (object_to_base_hash)
987                 BLI_ghash_free(object_to_base_hash, NULL, NULL);
988         
989 }
990
991 static void clear_trans_object_base_flags(void)
992 {
993         Base *base;
994         
995         base= FIRSTBASE;
996         while(base) {
997                 if(base->flag & BA_WASSEL) base->flag |= SELECT;
998                 base->flag &= ~(BA_PARSEL+BA_WASSEL);
999                 
1000                 base->flag &= ~(BA_DISP_UPDATE+BA_WHERE_UPDATE+BA_DO_IPO);
1001                 
1002                 /* pose here? */
1003                 if (base->object->pose) {
1004                         Object *ob= base->object;
1005                         bPoseChannel *chan;
1006                         for (chan = ob->pose->chanbase.first; chan; chan=chan->next) {
1007                                 chan->flag &= ~PCHAN_TRANS_UPDATE;
1008                         }
1009                 }
1010                 
1011                 base= base->next;
1012         }
1013         copy_baseflags();
1014 }
1015
1016
1017 static void createTransObject(void)
1018 {
1019         TransData *td = NULL;
1020         TransDataExtension *tx;
1021         Object *ob;
1022         Base *base;
1023         IpoKey *ik;
1024         ListBase elems;
1025         
1026         /* hackish... but we have to do it somewhere */
1027         reset_slowparents();
1028         
1029         set_trans_object_base_flags(&Trans);
1030         
1031         /* count */     
1032         for(base= FIRSTBASE; base; base= base->next) {
1033                 if TESTBASELIB(base) {
1034                         ob= base->object;
1035                         
1036                         /* store ipo keys? */
1037                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1038                                 elems.first= elems.last= NULL;
1039                                 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
1040                                 
1041                                 pushdata(&elems, sizeof(ListBase));
1042                                 
1043                                 for(ik= elems.first; ik; ik= ik->next) Trans.total++;
1044
1045                                 if(elems.first==NULL) Trans.total++;
1046                         }
1047                         else {
1048                                 Trans.total++;
1049                         }
1050                 }
1051         }
1052
1053         if(!Trans.total) {
1054                 /* clear here, main transform function escapes too */
1055                 clear_trans_object_base_flags();
1056                 return;
1057         }
1058         
1059         td = Trans.data = MEM_mallocN(Trans.total*sizeof(TransData), "TransOb");
1060         tx = MEM_mallocN(Trans.total*sizeof(TransDataExtension), "TransObExtension");
1061
1062         for(base= FIRSTBASE; base; base= base->next) {
1063                 if TESTBASELIB(base) {
1064                         ob= base->object;
1065                         
1066                         td->flag= TD_SELECTED|TD_OBJECT;
1067                         td->ext = tx;
1068                         td->dist = 0.0f;
1069
1070                         /* store ipo keys? */
1071                         if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
1072                                 
1073                                 popfirst(&elems);       // bring back pushed listbase
1074                                 
1075                                 if(elems.first) {
1076                                         float cfraont;
1077                                         int ipoflag;
1078                                         
1079                                         base->flag |= BA_DO_IPO+BA_WASSEL;
1080                                         base->flag &= ~SELECT;
1081                                         
1082                                         cfraont= CFRA;
1083                                         set_no_parent_ipo(1);
1084                                         ipoflag= ob->ipoflag;
1085                                         ob->ipoflag &= ~OB_OFFS_OB;
1086                                         
1087                                         pushdata(ob->loc, 7*3*4); // tsk! tsk!
1088                                         
1089                                         for(ik= elems.first; ik; ik= ik->next) {
1090                                                 
1091                                                 /* weak... this doesn't correct for floating values, giving small errors */
1092                                                 CFRA= ik->val/G.scene->r.framelen;
1093                                                 
1094                                                 do_ob_ipo(ob);
1095                                                 ObjectToTransData(td, ob);      // does where_is_object()
1096                                                 
1097                                                 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
1098                                                 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
1099                                                 ipokey_to_transdata(ik, td);
1100                                                 
1101                                                 td++;
1102                                                 tx++;
1103                                                 if(ik->next) td->ext= tx;       // prevent corrupting mem!
1104                                         }
1105                                         free_ipokey(&elems);
1106                                         
1107                                         poplast(ob->loc);
1108                                         set_no_parent_ipo(0);
1109                                         
1110                                         CFRA= cfraont;
1111                                         ob->ipoflag= ipoflag;
1112                                 }
1113                                 else {
1114                                         ObjectToTransData(td, ob);
1115                                         td->tdi= NULL;
1116                                 }
1117                         }
1118                         else {
1119                                 ObjectToTransData(td, ob);
1120                                 td->tdi= NULL;
1121                         }
1122                         td++;
1123                         tx++;
1124                 }
1125         }
1126 }
1127
1128 static void createTransData(TransInfo *t) 
1129 {
1130         if( t->mode & TFM_TEX) {
1131                 createTransTexspace();
1132                 t->mode &= ~TFM_TEX;    // now becoming normal grab/rot/scale
1133         }
1134         else if (G.obpose) {
1135                 createTransPose();
1136         }
1137         else if (G.obedit) {
1138                 if (G.obedit->type == OB_MESH) {
1139                         createTransEditVerts(); 
1140                 }
1141                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1142                         createTransCurveVerts();
1143                 }
1144                 else if (G.obedit->type==OB_LATTICE) {
1145                         createTransLatticeVerts();
1146                 }
1147                 else if (G.obedit->type==OB_MBALL) {
1148                         createTransMBallVerts();
1149                 }
1150                 else if (G.obedit->type==OB_ARMATURE) {
1151                         createTransArmatureVerts();
1152                 }                                                       
1153                 else {
1154                         printf("not done yet! only have mesh surface curve\n");
1155                 }
1156         }
1157         else {
1158                 createTransObject();
1159         }
1160 }
1161
1162 #define TRANS_CANCEL    2
1163 #define TRANS_CONFIRM   1
1164
1165 /* ************************** TRANSFORMATIONS **************************** */
1166
1167 void Transform(int mode) 
1168 {
1169         int ret_val = 0;
1170         short pmval[2] = {0, 0}, mval[2], val;
1171         float mati[3][3];
1172         unsigned short event;
1173
1174         /*joeedh -> hopefully may be what makes the old transform() constant*/
1175         /* ton: I doubt, but it doesnt harm for now. shouldnt be needed though */
1176         areawinset(curarea->win);
1177
1178         Mat3One(mati);
1179
1180         /* stupid PET initialisation code */
1181         /* START */
1182         if (Trans.propsize == 0.0f) {
1183                 Trans.propsize = 1.0;
1184         }
1185         /* END */
1186
1187         if (mode == TFM_REPEAT) {
1188                 mode = LastMode;
1189         }
1190         else {
1191                 LastMode = mode;
1192         }
1193         
1194         initTransModeFlags(&Trans, mode);       // modal settings in struct Trans
1195
1196         initTrans(&Trans);                                      // internal data, mouse, vectors
1197
1198         createTransData(&Trans);                        // make TransData structs from selection
1199
1200         if (Trans.total == 0)
1201                 return;
1202
1203         /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */
1204         /* EVIL2: we gave as argument also texture space context bit... was cleared */
1205         mode= Trans.mode;
1206         
1207         calculatePropRatio(&Trans);
1208         calculateCenter(&Trans);
1209
1210         switch (mode) {
1211         case TFM_TRANSLATION:
1212                 initTranslation(&Trans);
1213                 break;
1214         case TFM_ROTATION:
1215                 initRotation(&Trans);
1216                 break;
1217         case TFM_RESIZE:
1218                 initResize(&Trans);
1219                 break;
1220         case TFM_TOSPHERE:
1221                 initToSphere(&Trans);
1222                 break;
1223         case TFM_SHEAR:
1224                 initShear(&Trans);
1225                 break;
1226         }
1227
1228         // Emptying event queue
1229         while( qtest() ) {
1230                 event= extern_qread(&val);
1231         }
1232
1233         Trans.redraw = 1;
1234
1235         while (ret_val == 0) {
1236                 
1237                 getmouseco_areawin(mval);
1238                 
1239                 if (mval[0] != pmval[0] || mval[1] != pmval[1]) {
1240                         Trans.redraw = 1;
1241                 }
1242                 if (Trans.redraw) {
1243                         pmval[0] = mval[0];
1244                         pmval[1] = mval[1];
1245
1246                         if (Trans.transform) {
1247                                 Trans.transform(&Trans, mval);
1248                         }
1249                         Trans.redraw = 0;
1250                 }
1251                 
1252                 /* essential for idling subloop */
1253                 if( qtest()==0) PIL_sleep_ms(2);
1254
1255                 while( qtest() ) {
1256                         event= extern_qread(&val);
1257
1258                         if(val) {
1259                                 switch (event){
1260                                 case MIDDLEMOUSE:
1261                                         selectConstraint(&Trans);
1262                                         Trans.redraw = 1;
1263                                         break;
1264                                 case ESCKEY:
1265                                 case RIGHTMOUSE:
1266                                         ret_val = TRANS_CANCEL;
1267                                         break;
1268                                 case LEFTMOUSE:
1269                                 case SPACEKEY:
1270                                 case PADENTER:
1271                                 case RETKEY:
1272                                         ret_val = TRANS_CONFIRM;
1273                                         break;
1274                                 case GKEY:
1275                                 case SKEY:
1276                                 case RKEY:
1277                                         if (G.qual == LR_CTRLKEY)
1278                                                 applyTransObjects(&Trans);
1279                                         else
1280                                                 restoreTransObjects(&Trans);
1281                                         break;
1282                                 case XKEY:
1283                                         if (G.qual == 0)
1284                                                 setConstraint(&Trans, mati, (APPLYCON|CONAXIS0));
1285                                         else if (G.qual == LR_CTRLKEY)
1286                                                 setConstraint(&Trans, mati, (APPLYCON|CONAXIS1|CONAXIS2));
1287                                         break;
1288                                         Trans.redraw = 1;
1289                                 case YKEY:
1290                                         if (G.qual == 0)
1291                                                 setConstraint(&Trans, mati, (APPLYCON|CONAXIS1));
1292                                         else if (G.qual == LR_CTRLKEY)
1293                                                 setConstraint(&Trans, mati, (APPLYCON|CONAXIS0|CONAXIS2));
1294                                         break;
1295                                         Trans.redraw = 1;
1296                                 case ZKEY:
1297                                         if (G.qual == 0)
1298                                                 setConstraint(&Trans, mati, (APPLYCON|CONAXIS2));
1299                                         else if (G.qual == LR_CTRLKEY)
1300                                                 setConstraint(&Trans, mati, (APPLYCON|CONAXIS0|CONAXIS1));
1301                                         Trans.redraw = 1;
1302                                         break;
1303                                 case OKEY:
1304                                         if (G.qual==LR_SHIFTKEY) {
1305                                                 extern int prop_mode;
1306                                                 prop_mode = (prop_mode+1)%5;
1307                                                 calculatePropRatio(&Trans);
1308                                                 Trans.redraw= 1;
1309                                         }
1310                                         break;
1311                                 case WHEELDOWNMOUSE:
1312                                 case PADPLUSKEY:
1313                                         if(G.f & G_PROPORTIONAL) {
1314                                                 Trans.propsize*= 1.1f;
1315                                                 calculatePropRatio(&Trans);
1316                                                 Trans.redraw= 1;
1317                                         }
1318                                         break;
1319                                 case WHEELUPMOUSE:
1320                                 case PADMINUS:
1321                                         if(G.f & G_PROPORTIONAL) {
1322                                                 Trans.propsize*= 0.90909090f;
1323                                                 calculatePropRatio(&Trans);
1324                                                 Trans.redraw= 1;
1325                                         }
1326                                         break;
1327                                 }
1328                                 Trans.redraw |= handleNumInput(&(Trans.num), event);
1329                                 arrows_move_cursor(event);
1330                         }
1331                         else {
1332                                 switch (event){
1333                                 case MIDDLEMOUSE:
1334                                         chooseConstraint(&Trans);
1335                                         Trans.redraw = 1;
1336                                         break;
1337                                 case LEFTMOUSE:
1338                                 case RIGHTMOUSE:
1339                                         /* commented out, doesn't work for actions started with menu */
1340                                         // ret_val = TRANS_CONFIRM;
1341                                         break;
1342                                 }
1343                         }
1344                 }
1345         }
1346         
1347         
1348         if(ret_val == TRANS_CANCEL) {
1349                 restoreTransObjects(&Trans);
1350         }
1351         else {
1352                 BIF_undo_push("Transform");
1353         }
1354         
1355         /* free data, reset vars */
1356         postTrans(&Trans);
1357         
1358         /* mess from old transform, just for now (ton) */
1359         {
1360                 char cmode='g';
1361                 
1362                 if(mode==TFM_RESIZE) cmode= 's';
1363                 else if(mode==TFM_ROTATION) cmode= 'r';
1364                 /* aftertrans does displists, ipos and action channels */
1365                 special_aftertrans_update(cmode, 0, ret_val == TRANS_CANCEL, 0 /*keyflags*/);
1366                 
1367                 if(G.obedit==NULL && G.obpose==NULL)
1368                         clear_trans_object_base_flags();
1369         }
1370         
1371         
1372         /* send events out for redraws */
1373         allqueue(REDRAWVIEW3D, 0);
1374         allqueue(REDRAWBUTSOBJECT, 0);
1375         scrarea_queue_headredraw(curarea);
1376 }
1377
1378 /* ************************** WRAP *************************** */
1379
1380 void initWrap(TransInfo *t) 
1381 {
1382         float min[3], max[3], loc[3];
1383         int i;
1384         calculateCenterCursor(t);
1385         t->num.idx_max = 0;
1386         t->transform = Wrap;
1387
1388         for(i = 0; i < t->total; i++) {
1389                 VECCOPY(loc, t->data[i].iloc);
1390                 if (G.obedit) {
1391                         Mat4MulVecfl(G.obedit->obmat, loc);
1392                 }
1393                 Mat4MulVecfl(G.vd->viewmat, loc);
1394                 if (i) {
1395                         MinMax3(min, max, loc);
1396                 }
1397                 else {
1398                         VECCOPY(max, loc);
1399                         VECCOPY(min, loc);
1400                 }
1401         }
1402
1403
1404         t->fac = (float)(t->center2d[0] - t->imval[0]);
1405 }
1406
1407
1408 int Wrap(TransInfo *t, short mval[2])
1409 {
1410         return 1;
1411 }
1412
1413 /* ************************** SHEAR *************************** */
1414
1415 void initShear(TransInfo *t) 
1416 {
1417         t->num.idx_max = 0;
1418         t->transform = Shear;
1419         t->fac = (float)(t->center2d[0] - t->imval[0]);
1420 }
1421
1422 int Shear(TransInfo *t, short mval[2]) 
1423 {
1424         float vec[3];
1425         float smat[3][3], tmat[3][3], totmat[3][3], persmat[3][3], persinv[3][3];
1426         float value;
1427         int i;
1428         char str[50];
1429         TransData *td = t->data;
1430
1431         Mat3CpyMat4(persmat, G.vd->viewmat);
1432         Mat3Inv(persinv, persmat);
1433
1434         value = -0.005f * ((float)(t->center2d[0] - mval[0]) - t->fac);
1435
1436         apply_grid1(&value, t->num.idx_max, 0.1f);
1437
1438         applyNumInput(&t->num, &value);
1439
1440         /* header print for NumInput */
1441         if (hasNumInput(&t->num)) {
1442                 char c[20];
1443
1444                 outputNumInput(&(t->num), c);
1445
1446                 sprintf(str, "Shear: %s %s", c, t->proptext);
1447         }
1448         else {
1449                 /* default header print */
1450                 sprintf(str, "Shear: %.3f %s", value, t->proptext);
1451         }
1452         
1453         Mat3One(smat);
1454         smat[1][0] = value;
1455         Mat3MulMat3(tmat, smat, persmat);
1456         Mat3MulMat3(totmat, persinv, tmat);
1457         
1458         for(i = 0 ; i < t->total; i++, td++) {
1459                 if (td->flag & TD_NOACTION)
1460                         continue;
1461                 if (G.obedit) {
1462                         float mat3[3][3];
1463                         Mat3MulMat3(mat3, totmat, td->mtx);
1464                         Mat3MulMat3(tmat, td->smtx, mat3);
1465                 }
1466                 else {
1467                         Mat3CpyMat3(tmat, totmat);
1468                 }
1469                 VecSubf(vec, td->center, t->center);
1470
1471                 Mat3MulVecfl(tmat, vec);
1472
1473                 VecAddf(vec, vec, t->center);
1474                 VecSubf(vec, vec, td->center);
1475
1476                 VecMulf(vec, td->factor);
1477
1478                 VecAddf(td->loc, td->iloc, vec);
1479         }
1480
1481         recalcData(t);
1482
1483         headerprint(str);
1484
1485         force_draw(0);
1486
1487         helpline (t->center);
1488
1489         return 1;
1490 }
1491
1492 /* ************************** RESIZE *************************** */
1493
1494 void initResize(TransInfo *t) 
1495 {
1496         Trans.fac = (float)sqrt( (float)
1497                 (
1498                         (Trans.center2d[1] - Trans.imval[1])*(Trans.center2d[1] - Trans.imval[1])
1499                 +
1500                         (Trans.center2d[0] - Trans.imval[0])*(Trans.center2d[0] - Trans.imval[0])
1501                 ) );
1502
1503         t->num.idx_max = 2;
1504         t->transform = Resize;
1505 }
1506
1507 int Resize(TransInfo *t, short mval[2]) 
1508 {
1509         TransData *td = t->data;
1510         float vec[3];
1511         float size[3], tsize[3], mat[3][3], tmat[3][3];
1512         float ratio;
1513         int i;
1514         char str[50];
1515
1516         ratio = (float)sqrt( (float)
1517                 (
1518                         (t->center2d[1] - mval[1])*(t->center2d[1] - mval[1])
1519                 +
1520                         (t->center2d[0] - mval[0])*(t->center2d[0] - mval[0])
1521                 ) ) / t->fac;
1522
1523         size[0] = size[1] = size[2] = ratio;
1524
1525         apply_grid1(size, t->num.idx_max, 0.1f);
1526
1527         if (t->con.applyVec) {
1528                 t->con.applyVec(t, NULL, size, tsize);
1529                 VECCOPY(size, tsize);
1530         }
1531
1532         applyNumInput(&t->num, size);
1533
1534         /* header print for NumInput */
1535         if (hasNumInput(&t->num)) {
1536                 char c[60];
1537
1538                 outputNumInput(&(t->num), c);
1539
1540                 sprintf(str, "Size X: %s Y: %s Z: %s %s", &c[0], &c[20], &c[40], t->proptext);
1541         }
1542         else {
1543                 /* default header print */
1544                 sprintf(str, "Size X: %.3f Y: %.3f Z: %.3f %s", size[0], size[1], size[2], t->proptext);
1545         }
1546         
1547         SizeToMat3(size, mat);
1548         for(i = 0 ; i < t->total; i++, td++) {
1549                 float smat[3][3];
1550                 if (td->flag & TD_NOACTION)
1551                         continue;
1552
1553                 if (!(td->flag & TD_OBJECT)) {
1554                         Mat3MulMat3(smat, mat, td->smtx);
1555                         Mat3MulMat3(tmat, td->mtx, smat);
1556                 }
1557                 else {
1558                         Mat3CpyMat3(tmat, mat);
1559                 }
1560
1561                 if (td->ext) {
1562                         float fsize[3];
1563
1564                         if (td->flag & TD_OBJECT) {
1565                                 float obsizemat[3][3];
1566                                 Mat3MulMat3(obsizemat, td->smtx, tmat);
1567                                 Mat3ToSize(obsizemat, fsize);
1568                         }
1569                         else {
1570                                 Mat3ToSize(tmat, fsize);
1571                         }
1572                         
1573                         /* handle ipokeys? */
1574                         if(td->tdi) {
1575                                 TransDataIpokey *tdi= td->tdi;
1576                                 /* calculate delta size (equal for size and dsize) */
1577                                 
1578                                 // commented out for now
1579                                 vec[0]= (tdi->oldsize[0])*(fsize[0] -1.0f) * td->factor;
1580                                 vec[1]= (tdi->oldsize[1])*(fsize[1] -1.0f) * td->factor;
1581                                 vec[2]= (tdi->oldsize[2])*(fsize[2] -1.0f) * td->factor;
1582                                 
1583                                 add_tdi_poin(tdi->sizex, tdi->oldsize,   vec[0]);
1584                                 add_tdi_poin(tdi->sizey, tdi->oldsize+1, vec[1]);
1585                                 add_tdi_poin(tdi->sizez, tdi->oldsize+2, vec[2]);
1586                                 
1587                         }
1588                         else {
1589                                 // TEMPORARY NAIVE CODE
1590                                 td->ext->size[0] = td->ext->isize[0] + td->ext->isize[0] * (fsize[0] - 1.0f) * td->factor;
1591                                 td->ext->size[1] = td->ext->isize[1] + td->ext->isize[1] * (fsize[1] - 1.0f) * td->factor;
1592                                 td->ext->size[2] = td->ext->isize[2] + td->ext->isize[2] * (fsize[2] - 1.0f) * td->factor;
1593                         }
1594                 }
1595                 VecSubf(vec, td->center, t->center);
1596
1597                 Mat3MulVecfl(tmat, vec);
1598
1599                 VecAddf(vec, vec, t->center);
1600                 VecSubf(vec, vec, td->center);
1601
1602                 VecMulf(vec, td->factor);
1603
1604                 if (td->flag & TD_OBJECT) {
1605                         Mat3MulVecfl(td->smtx, vec);
1606                 }
1607
1608                 VecAddf(td->loc, td->iloc, vec);
1609         }
1610
1611         recalcData(t);
1612
1613         headerprint(str);
1614
1615         force_draw(0);
1616
1617         helpline (t->center);
1618
1619         return 1;
1620 }
1621
1622 /* ************************** TOSPHERE *************************** */
1623
1624 void initToSphere(TransInfo *t) 
1625 {
1626         TransData *td = t->data;
1627         int i;
1628
1629         // Calculate average radius
1630         for(i = 0 ; i < t->total; i++, td++) {
1631                 t->val += VecLenf(t->center, td->iloc);
1632         }
1633
1634         t->val /= (float)t->total;
1635
1636         Trans.fac = (float)sqrt( (float)
1637                 (
1638                         (Trans.center2d[1] - Trans.imval[1])*(Trans.center2d[1] - Trans.imval[1])
1639                 +
1640                         (Trans.center2d[0] - Trans.imval[0])*(Trans.center2d[0] - Trans.imval[0])
1641                 ) );
1642
1643         t->num.idx_max = 0;
1644         t->transform = ToSphere;
1645 }
1646
1647
1648
1649 int ToSphere(TransInfo *t, short mval[2]) 
1650 {
1651         float vec[3];
1652         float ratio, radius;
1653         int i;
1654         char str[50];
1655         TransData *td = t->data;
1656
1657         ratio = (float)sqrt( (float)
1658                 (
1659                         (t->center2d[1] - mval[1])*(t->center2d[1] - mval[1])
1660                 +
1661                         (t->center2d[0] - mval[0])*(t->center2d[0] - mval[0])
1662                 ) ) / t->fac;
1663
1664         apply_grid1(&ratio, t->num.idx_max, 0.1f);
1665
1666         applyNumInput(&t->num, &ratio);
1667
1668         if (ratio > 1.0f)
1669                 ratio = 1.0f;
1670
1671         /* header print for NumInput */
1672         if (hasNumInput(&t->num)) {
1673                 char c[20];
1674
1675                 outputNumInput(&(t->num), c);
1676
1677                 sprintf(str, "To Sphere: %s %s", c, t->proptext);
1678         }
1679         else {
1680                 /* default header print */
1681                 sprintf(str, "To Sphere: %.4f %s", ratio, t->proptext);
1682         }
1683         
1684         
1685         for(i = 0 ; i < t->total; i++, td++) {
1686                 float tratio;
1687                 if (td->flag & TD_NOACTION)
1688                         continue;
1689                 VecSubf(vec, td->iloc, t->center);
1690
1691                 radius = Normalise(vec);
1692
1693                 tratio = 1.0f - ((1.0f - ratio) * td->factor);
1694
1695                 VecMulf(vec, radius * tratio + t->val * (1.0f - tratio));
1696
1697                 VecAddf(td->loc, t->center, vec);
1698         }
1699
1700         recalcData(t);
1701
1702         headerprint(str);
1703
1704         force_draw(0);
1705
1706         helpline (t->center);
1707
1708         return 1;
1709 }
1710
1711 /* ************************** ROTATION *************************** */
1712
1713 void initRotation(TransInfo *t) 
1714 {
1715         t->num.idx_max = 0;
1716         t->fac = 0;
1717         t->transform = Rotation;
1718 }
1719
1720 int Rotation(TransInfo *t, short mval[2]) 
1721 {
1722         TransData *td = t->data;
1723         int i;
1724         char str[50];
1725
1726         float final;
1727
1728         int dx2 = t->center2d[0] - mval[0];
1729         int dy2 = t->center2d[1] - mval[1];
1730         float B = (float)sqrt(dx2*dx2+dy2*dy2);
1731
1732         int dx1 = t->center2d[0] - t->imval[0];
1733         int dy1 = t->center2d[1] - t->imval[1];
1734         float A = (float)sqrt(dx1*dx1+dy1*dy1);
1735
1736         int dx3 = mval[0] - t->imval[0];
1737         int dy3 = mval[1] - t->imval[1];
1738
1739         float deler= ((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3))
1740                 / (2 * A * B);
1741
1742         float dphi;
1743
1744         float vec[3], axis[3];
1745         float mat[3][3], totmat[3][3], omat[3][3], smat[3][3];
1746
1747         if (G.obedit) {
1748                 Mat3CpyMat4(omat, G.obedit->obmat);
1749         }
1750
1751         VECCOPY(axis, G.vd->persinv[2]);
1752         Normalise(axis);
1753
1754         dphi = saacos(deler);
1755         if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
1756
1757         if(G.qual & LR_SHIFTKEY) t->fac += dphi/30.0f;
1758         else t->fac += dphi;
1759
1760         final = t->fac;
1761
1762         apply_grid2(&final, t->num.idx_max, (float)((5.0/180)*M_PI), 0.2f);
1763
1764         t->imval[0] = mval[0];
1765         t->imval[1] = mval[1];
1766
1767         if (t->con.applyRot) {
1768                 t->con.applyRot(t, NULL, axis);
1769         }
1770
1771         if (hasNumInput(&t->num)) {
1772                 char c[20];
1773
1774                 applyNumInput(&t->num, &final);
1775
1776                 outputNumInput(&(t->num), c);
1777
1778                 sprintf(str, "Rot: %s %s", &c[0], t->proptext);
1779
1780                 final *= (float)(M_PI / 180.0);
1781         }
1782         else {
1783                 sprintf(str, "Rot: %.2f %s", 180.0*final/M_PI, t->proptext);
1784         }
1785
1786         //printf("Axis %f %f %f\n", axis[0], axis[1], axis[2]);
1787         VecRotToMat3(axis, final * td->factor, mat);
1788
1789         for(i = 0 ; i < t->total; i++, td++) {
1790                 if (td->flag & TD_NOACTION)
1791                         continue;
1792
1793                 if (t->con.applyRot) {
1794                         t->con.applyRot(t, td, axis);
1795                         VecRotToMat3(axis, final * td->factor, mat);
1796                 }
1797                 else if (G.f & G_PROPORTIONAL) {
1798                         VecRotToMat3(axis, final * td->factor, mat);
1799                 }
1800
1801                 if (G.obedit) {
1802                         Mat3MulMat3(totmat, mat, omat);
1803                         Mat3MulMat3(smat, td->smtx, totmat);
1804
1805                         VecSubf(vec, td->iloc, t->center);
1806                         Mat3MulVecfl(smat, vec);
1807
1808                         VecAddf(td->loc, vec, t->center);
1809                 }
1810                 else {
1811                         float eul[3], fmat[3][3];
1812
1813                         /* translation */
1814                         VecSubf(vec, td->center, t->center);
1815                         Mat3MulVecfl(mat, vec);
1816                         VecAddf(vec, vec, t->center);
1817                         /* vec now is the location where the object has to be */
1818                         VecSubf(vec, vec, td->center);
1819                         Mat3MulVecfl(td->smtx, vec);
1820
1821                         VecAddf(td->loc, td->iloc, vec);
1822                         
1823                         if(td->flag & TD_USEQUAT) {
1824                                 float quat[4];
1825                                 
1826                                 Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
1827                                 
1828                                 Mat3ToQuat(fmat, quat); // Actual transform
1829                                 
1830                                 QuatMul(td->ext->quat, quat, td->ext->iquat);
1831                         }
1832                         else {
1833                                 float obmat[3][3];
1834                                 
1835                                 /* are there ipo keys? */
1836                                 if(td->tdi) {
1837                                         TransDataIpokey *tdi= td->tdi;
1838                                         float rot[3];
1839                                         
1840                                         /* calculate the total rotatation in eulers */
1841                                         VecAddf(eul, td->ext->irot, td->ext->drot);
1842                                         EulToMat3(eul, obmat);
1843                                         /* mat = transform, obmat = object rotation */
1844                                         Mat3MulMat3(fmat, mat, obmat);
1845                                         Mat3ToEul(fmat, eul);
1846                                         compatible_eul(eul, td->ext->irot);
1847                                         
1848                                         /* correct back for delta rot */
1849                                         if(tdi->flag & TOB_IPODROT) {
1850                                                 VecSubf(rot, eul, td->ext->irot);
1851                                         }
1852                                         else {
1853                                                 VecSubf(rot, eul, td->ext->drot);
1854                                         }
1855                                         
1856                                         VecMulf(rot, 9.0/M_PI_2);
1857                                         VecSubf(rot, rot, tdi->oldrot);
1858                                         
1859                                         add_tdi_poin(tdi->rotx, tdi->oldrot, rot[0]);
1860                                         add_tdi_poin(tdi->roty, tdi->oldrot+1, rot[1]);
1861                                         add_tdi_poin(tdi->rotz, tdi->oldrot+2, rot[2]);
1862                                 }
1863                                 else {
1864                                         
1865                                         /* calculate the total rotatation in eulers */
1866                                         VecAddf(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */
1867                                         EulToMat3(eul, obmat);
1868                                         /* mat = transform, obmat = object rotation */
1869                                         Mat3MulMat3(fmat, mat, obmat);
1870                                         Mat3ToEul(fmat, eul);
1871                                         compatible_eul(eul, td->ext->irot);
1872                                         
1873                                         /* correct back for delta rot */
1874                                         VecSubf(eul, eul, td->ext->drot);
1875                                         /* and apply */
1876                                         VECCOPY(td->ext->rot, eul);
1877                                 }
1878                         }
1879                 }
1880         }
1881
1882         recalcData(t);
1883
1884         headerprint(str);
1885
1886         force_draw(0);
1887
1888         helpline (t->center);
1889
1890         return 1;
1891 }
1892
1893 /* ************************** TRANSLATION *************************** */
1894         
1895 void initTranslation(TransInfo *t) 
1896 {
1897         
1898         t->num.idx_max = 2;
1899         t->transform = Translation;
1900         
1901         /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d() */
1902         if (G.obedit) {
1903                 float vec[3];
1904                 
1905                 VECCOPY(vec, t->center);
1906                 Mat4MulVecfl(G.obedit->obmat, vec);
1907                 initgrabz(vec[0], vec[1], vec[2]);
1908         }
1909         else initgrabz(t->center[0], t->center[1], t->center[2]); 
1910 }
1911
1912 int Translation(TransInfo *t, short mval[2]) 
1913 {
1914         float vec[3], tvec[3];
1915         int i;
1916         char str[70];
1917         TransData *td = t->data;
1918
1919         window_to_3d(vec, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
1920
1921         if (t->con.applyVec) {
1922                 t->con.applyVec(t, NULL, vec, tvec);
1923                 VECCOPY(vec, tvec);
1924         }
1925
1926         apply_grid1(vec, t->num.idx_max, 1.0f);
1927
1928         applyNumInput(&t->num, vec);
1929
1930         /* header print for NumInput */
1931         if (hasNumInput(&t->num)) {
1932                 char c[60];
1933
1934                 outputNumInput(&(t->num), c);
1935
1936                 sprintf(str, "Dx: %s   Dy: %s  Dz: %s %s", &c[0], &c[20], &c[40], t->proptext);
1937         }
1938         else {
1939                 /* default header print */
1940                 sprintf(str, "Dx: %.4f   Dy: %.4f  Dz: %.4f %s", vec[0], vec[1], vec[2], t->proptext);
1941         }
1942
1943
1944         for(i = 0 ; i < t->total; i++, td++) {
1945                 if (td->flag & TD_NOACTION)
1946                         continue;
1947
1948                 if (t->con.applyVec) {
1949                         t->con.applyVec(t, td, vec, tvec);
1950                 }
1951                 else {
1952                         VECCOPY(tvec, vec);
1953                 }
1954
1955                 Mat3MulVecfl(td->smtx, tvec);
1956                 VecMulf(tvec, td->factor);
1957                 
1958                 /* transdata ipokey */
1959                 if(td->tdi) {
1960                         TransDataIpokey *tdi= td->tdi;
1961                         add_tdi_poin(tdi->locx, tdi->oldloc, tvec[0]);
1962                         add_tdi_poin(tdi->locy, tdi->oldloc+1, tvec[1]);
1963                         add_tdi_poin(tdi->locz, tdi->oldloc+2, tvec[2]);
1964                 }
1965                 else VecAddf(td->loc, td->iloc, tvec);
1966         }
1967
1968
1969         recalcData(t);
1970
1971         headerprint(str);
1972
1973         force_draw(0);
1974
1975         return 1;
1976 }