Transform project.
[blender.git] / source / blender / src / transform_generics.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_screen.h"
76 #include "BIF_space.h"
77 #include "BIF_editview.h"
78 #include "BIF_resources.h"
79 #include "BIF_mywindow.h"
80 #include "BIF_gl.h"
81 #include "BIF_editlattice.h"
82 #include "BIF_editarmature.h"
83 #include "BIF_editmesh.h"
84
85 #include "BKE_action.h"
86 #include "BKE_anim.h"
87 #include "BKE_armature.h"
88 #include "BKE_curve.h"
89 #include "BKE_displist.h"
90 #include "BKE_global.h"
91 #include "BKE_ipo.h"
92 #include "BKE_lattice.h"
93 #include "BKE_object.h"
94 #include "BKE_utildefines.h"
95
96 #include "BSE_edit.h"
97 #include "BSE_view.h"
98
99 #include "BLI_arithb.h"
100 #include "BLI_editVert.h"
101
102 #include "blendef.h"
103
104 #include "mydevice.h"
105
106 #include "transform.h"
107 #include "transform_generics.h"
108
109 extern ListBase editNurb;
110 extern ListBase editelems;
111
112 /* GLOBAL VARIABLE THAT SHOULD MOVED TO SCREEN MEMBER OR SOMETHING  */
113 extern TransInfo Trans;
114
115 /* ************************** Functions *************************** */
116
117 /* ************************** GENERICS **************************** */
118
119 /* called for objects updating while transform acts, once per redraw */
120 void recalcData(TransInfo *t)
121 {
122         Base *base;
123         
124         if(G.obpose) {
125                 TransData *td= t->data;
126                 bPoseChannel    *chan;
127                 int     i;
128                 
129                 if (!G.obpose->pose) G.obpose->pose= MEM_callocN(sizeof(bPose), "pose");
130                 
131                 /*      Make channels for the transforming bones (in posemode) */
132                 for (i=0; i<t->total; i++, td++) {
133                         chan = MEM_callocN (sizeof (bPoseChannel), "transPoseChannel");
134                         
135                         if (t->mode == TFM_ROTATION) {
136                                 chan->flag |= POSE_ROT;
137                                 memcpy (chan->quat, td->ext->quat, sizeof (chan->quat));
138                         }
139                         if (t->mode == TFM_TRANSLATION) {
140                                 chan->flag |= POSE_LOC;
141                                 memcpy (chan->loc, td->loc, sizeof (chan->loc));
142                         }
143                         if (t->mode == TFM_RESIZE) {
144                                 chan->flag |= POSE_SIZE;
145                                 memcpy (chan->size, td->ext->size, sizeof (chan->size));
146                         }
147                         
148                         strcpy (chan->name, ((Bone*) td->ext->bone)->name);
149                         
150                         set_pose_channel (G.obpose->pose, chan);
151
152                 }
153                 
154                 clear_pose_constraint_status(G.obpose);
155                 
156                 if (!is_delay_deform()) make_displists_by_armature(G.obpose);
157                 
158         }
159         else if (G.obedit) {
160                 if (G.obedit->type == OB_MESH) {
161                         recalc_editnormals();
162                         makeDispList(G.obedit);
163                 }
164                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
165                         Nurb *nu= editNurb.first;
166                         while(nu) {
167                                 test2DNurb(nu);
168                                 testhandlesNurb(nu); /* test for bezier too */
169                                 nu= nu->next;
170                         }
171                         makeDispList(G.obedit);
172
173                         makeBevelList(G.obedit); // might be needed for deform
174                         calc_curvepath(G.obedit);
175                         
176                         // deform, bevel, taper
177                         base= FIRSTBASE;
178                         while(base) {
179                                 if(base->lay & G.vd->lay) {
180                                         if(base->object->parent==G.obedit && base->object->partype==PARSKEL)
181                                                 makeDispList(base->object);
182                                         else if(base->object->type==OB_CURVE) {
183                                                 Curve *cu= base->object->data;
184                                                 if(G.obedit==cu->bevobj || G.obedit==cu->taperobj)
185                                                         makeDispList(base->object);
186                                         }
187                                 }
188                                 base= base->next;
189                         }
190                 }
191                 else if(G.obedit->type==OB_ARMATURE){
192                         EditBone *ebo;
193                         
194                         /* Ensure all bones are correctly adjusted */
195                         for (ebo=G.edbo.first; ebo; ebo=ebo->next){
196                                 
197                                 if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
198                                         /* If this bone has a parent tip that has been moved */
199                                         if (ebo->parent->flag & BONE_TIPSEL){
200                                                 VECCOPY (ebo->head, ebo->parent->tail);
201                                         }
202                                         /* If this bone has a parent tip that has NOT been moved */
203                                         else{
204                                                 VECCOPY (ebo->parent->tail, ebo->head);
205                                         }
206                                 }
207                         }
208                 }
209                 else if(G.obedit->type==OB_LATTICE) {
210                         
211                         if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt);
212                         
213                         base= FIRSTBASE;
214                         while(base) {
215                                 if(base->lay & G.vd->lay) {
216                                         if(base->object->parent==G.obedit) {
217                                                 makeDispList(base->object);
218                                         }
219                                 }
220                                 base= base->next;
221                         }
222                 }
223                 else if (G.obedit->type == OB_MBALL) {
224                         makeDispList(G.obedit); 
225                 }       
226         }
227         else {
228                 
229                 base= FIRSTBASE;
230                 while(base) {
231                         if(base->flag & BA_DO_IPO) {
232                                 IpoCurve *icu;
233                                 
234                                 base->object->ctime= -1234567.0;
235                                 
236                                 icu= base->object->ipo->curve.first;
237                                 while(icu) {
238                                         calchandles_ipocurve(icu);
239                                         icu= icu->next;
240                                 }
241                                 
242                         }
243                         if(base->object->partype & PARSLOW) {
244                                 base->object->partype -= PARSLOW;
245                                 where_is_object(base->object);
246                                 base->object->partype |= PARSLOW;
247                         }
248                         else if(base->flag & BA_WHERE_UPDATE) {
249                                 where_is_object(base->object);
250                         }
251                         
252                         base= base->next;
253                 } 
254                 
255                 base= FIRSTBASE;
256                 while(base) {
257                         
258                         if(base->flag & BA_DISP_UPDATE) makeDispList(base->object);
259                         
260                         base= base->next;
261                 }
262         }
263         
264         /* ugly stuff for posemode, copied from old system */
265         base= FIRSTBASE;
266         while(base) {
267                 extern int pose_flags_reset_done(Object *ob);   // linker solves
268                 
269                 if (pose_flags_reset_done(base->object)) {
270                         if (!is_delay_deform())
271                                 make_displists_by_armature(base->object);
272                 }
273                 
274                 base= base->next;
275         }
276         
277         if (G.obpose && G.obpose->type == OB_ARMATURE)
278                 clear_pose_constraint_status(G.obpose);
279         
280         if (!is_delay_deform()) make_displists_by_armature(G.obpose);
281
282         
283         /* update shaded drawmode while transform */
284         if(G.vd->drawtype == OB_SHADED) reshadeall_displist();
285         
286 }
287
288 void initTransModeFlags(TransInfo *t, int mode) 
289 {
290         t->flags = 0;
291         t->num.flags = 0;
292         t->mode = mode;
293         
294         switch (mode) {
295         case TFM_TRANSLATION:
296                 break;
297         case TFM_ROTATION:
298                 break;
299         case TFM_RESIZE:
300                 t->num.flags |= NULLONE;
301                 if (!G.obedit) {
302                         t->flags |= NOZERO;
303                         t->num.flags |= NOZERO;
304                 }
305                 break;
306         case TFM_TOSPHERE:
307                 t->num.flags |= NULLONE;
308                 t->num.flags |= NONEGATIVE;
309                 t->flags |= NOCONSTRAINT;
310                 break;
311         case TFM_SHEAR:
312                 t->flags |= NOCONSTRAINT;
313                 break;
314         }
315 }
316
317 void drawLine(float *center, float *dir, char axis)
318 {
319         extern void make_axis_color(char *col, char *col2, char axis);  // drawview.c
320         float v1[3], v2[3], v3[3];
321         char col[3], col2[3];
322         
323         //if(G.obedit) mymultmatrix(G.obedit->obmat);   // sets opengl viewing
324
325         VecCopyf(v3, dir);
326         VecMulf(v3, G.vd->far);
327         
328         VecSubf(v2, center, v3);
329         VecAddf(v1, center, v3);
330
331         if (axis > 127) {
332                 axis = -1 * (axis - 255);
333                 col[0] = col[1] = col[2] = 200;
334         }
335         else {
336                 BIF_GetThemeColor3ubv(TH_GRID, col);
337         }
338         make_axis_color(col, col2, axis);
339         glColor3ubv(col2);
340
341         setlinestyle(0);
342         glBegin(GL_LINE_STRIP); 
343                 glVertex3fv(v1); 
344                 glVertex3fv(v2); 
345         glEnd();
346         
347         myloadmatrix(G.vd->viewmat);
348 }
349
350 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
351 void postTrans (TransInfo *t) 
352 {
353         TransDataExtension *tx = t->data->ext;
354         TransData *td;
355         int a;
356         
357         G.moving = 0; // Set moving flag off (display as usual)
358
359         /* since ipokeys are optional on objects, we mallocced them per trans-data */
360         for(a=0, td= t->data; a<t->total; a++, td++) {
361                 if(td->tdi) MEM_freeN(td->tdi);
362         }
363         
364         MEM_freeN(t->data);
365         t->data = NULL;
366
367         if (tx) MEM_freeN(tx);
368         
369 }
370
371 void apply_grid3(float *val, int max_index, float fac1, float fac2, float fac3)
372 {
373         /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
374         int invert = U.flag & USER_AUTOGRABGRID;
375         int ctrl;
376         int i;
377
378         for (i=0; i<=max_index; i++) {
379
380                 if(invert) {
381                         if(G.qual & LR_CTRLKEY) ctrl= 0;
382                         else ctrl= 1;
383                 }
384                 else ctrl= (G.qual & LR_CTRLKEY);
385
386                 if(ctrl && (G.qual & LR_SHIFTKEY)) {
387                         if(fac3!= 0.0) {
388                                 for (i=0; i<=max_index; i++) {
389                                         val[i]= fac3*(float)floor(val[i]/fac3 +.5);
390                                 }
391                         }
392                 }
393                 else if(ctrl) {
394                         if(fac2!= 0.0) {
395                                 for (i=0; i<=max_index; i++) {
396                                         val[i]= fac2*(float)floor(val[i]/fac2 +.5);
397                                 }
398                         }
399                 }
400                 else {
401                         if(fac1!= 0.0) {
402                                 for (i=0; i<=max_index; i++) {
403                                         val[i]= fac1*(float)floor(val[i]/fac1 +.5);
404                                 }
405                         }
406                 }
407         }
408 }
409
410 void apply_grid1(float *val, int max_index, float factor)
411 {
412         /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
413         float fac1 = 0.0;
414         float fac2 = G.vd->grid * factor;
415         float fac3 = 0.1f * fac2;
416         apply_grid3(val, max_index, fac1, fac2, fac3);
417 }
418
419 void apply_grid2(float *val, int max_index, float factor, float factor2)
420 {
421         /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
422         float fac1 = 0.0;
423         float fac2 = G.vd->grid * factor;
424         float fac3 = factor2 * fac2;
425         apply_grid3(val, max_index, fac1, fac2, fac3);
426 }
427
428 void applyTransObjects(TransInfo *t)
429 {
430         TransData *td;
431         
432         for (td = t->data; td < t->data + t->total; td++) {
433                 VECCOPY(td->iloc, td->loc);
434                 if (td->ext->rot) {
435                         VECCOPY(td->ext->irot, td->ext->rot);
436                 }
437                 if (td->ext->size) {
438                         VECCOPY(td->ext->isize, td->ext->size);
439                 }
440         }       
441         recalcData(t);
442
443
444 /* helper for below */
445 static void restore_ipokey(float *poin, float *old)
446 {
447         if(poin) {
448                 poin[0]= old[0];
449                 poin[-3]= old[3];
450                 poin[3]= old[6];
451         }
452 }
453
454 void restoreTransObjects(TransInfo *t)
455 {
456         TransData *td;
457         
458         for (td = t->data; td < t->data + t->total; td++) {
459                 VECCOPY(td->loc, td->iloc);
460                 
461                 if (td->ext) {
462                         if (td->ext->rot) {
463                                 VECCOPY(td->ext->rot, td->ext->irot);
464                         }
465                         if (td->ext->size) {
466                                 VECCOPY(td->ext->size, td->ext->isize);
467                         }
468                         if(td->flag & TD_USEQUAT) {
469                                 if (td->ext->quat) {
470                                         QUATCOPY(td->ext->quat, td->ext->iquat);
471                                 }
472                         }
473                 }
474                 if(td->tdi) {
475                         TransDataIpokey *tdi= td->tdi;
476                         
477                         restore_ipokey(tdi->locx, tdi->oldloc);
478                         restore_ipokey(tdi->locy, tdi->oldloc+1);
479                         restore_ipokey(tdi->locz, tdi->oldloc+2);
480
481                         restore_ipokey(tdi->rotx, tdi->oldrot);
482                         restore_ipokey(tdi->roty, tdi->oldrot+1);
483                         restore_ipokey(tdi->rotz, tdi->oldrot+2);
484                         
485                         restore_ipokey(tdi->sizex, tdi->oldsize);
486                         restore_ipokey(tdi->sizey, tdi->oldsize+1);
487                         restore_ipokey(tdi->sizez, tdi->oldsize+2);
488                 }
489                 
490         }       
491         recalcData(t);
492
493
494 void initTrans (TransInfo *t)
495 {
496
497         G.moving = 1; // Set moving flag on (display object in white)
498
499         t->data = NULL;
500
501         getmouseco_areawin(t->imval);
502
503         t->transform            = NULL;
504         t->con.applyVec         = NULL;
505         t->con.applyRot = NULL;
506         t->con.mode             =
507                 t->total                        =
508                 t->num.idx              =
509                 t->num.idx_max  =
510                 t->num.ctrl[0]  = 
511                 t->num.ctrl[1]  = 
512                 t->num.ctrl[2]  = 0;
513
514         t->val = 0.0f;
515
516         t->num.val[0]           = 
517                 t->num.val[1]   = 
518                 t->num.val[2]   = 0.0f;
519 }
520
521 void calculateCenterCursor(TransInfo *t)
522 {
523         float *cursor;
524
525         cursor = give_cursor();
526         VECCOPY(t->center, cursor);
527
528         if(G.obedit || G.obpose) {
529                 Object *ob= G.obedit?G.obedit:G.obpose;
530                 float mat[3][3], imat[3][3];
531                 float vec[3];
532                 
533                 VecSubf(t->center, t->center, ob->obmat[3]);
534                 Mat3CpyMat4(mat, ob->obmat);
535                 Mat3Inv(imat, mat);
536                 Mat3MulVecfl(imat, t->center);
537                 
538                 VECCOPY(vec, t->center);
539                 Mat4MulVecfl(ob->obmat, vec);
540                 project_short_noclip(vec, t->center2d);
541         }
542         else {
543                 project_short_noclip(t->center, t->center2d);
544         }
545 }
546
547 void calculateCenterMedian(TransInfo *t)
548 {
549         float partial[3] = {0.0f, 0.0f, 0.0f};
550         int i;
551         for(i = 0; i < t->total; i++) {
552                 if (t->data[i].flag & TD_SELECTED) {
553                         VecAddf(partial, partial, t->data[i].center);
554                 }
555         }
556         VecMulf(partial, 1.0f / t->total);
557         VECCOPY(t->center, partial);
558
559         if (G.obedit || G.obpose) {
560                 Object *ob= G.obedit?G.obedit:G.obpose;
561                 float vec[3];
562                 
563                 VECCOPY(vec, t->center);
564                 Mat4MulVecfl(ob->obmat, vec);
565                 project_short_noclip(vec, t->center2d);
566         }
567         else {
568                 project_short_noclip(t->center, t->center2d);
569         }
570 }
571
572 void calculateCenterBound(TransInfo *t)
573 {
574         float max[3];
575         float min[3];
576         int i;
577         for(i = 0; i < t->total; i++) {
578                 if (i) {
579                         if (t->data[i].flag & TD_SELECTED) {
580                                 MinMax3(min, max, t->data[i].center);
581                         }
582                 }
583                 else {
584                         VECCOPY(max, t->data[i].center);
585                         VECCOPY(min, t->data[i].center);
586                 }
587         }
588         VecAddf(t->center, min, max);
589         VecMulf(t->center, 0.5);
590
591         if (G.obedit || G.obpose) {
592                 Object *ob= G.obedit?G.obedit:G.obpose;
593                 float vec[3];
594                 
595                 VECCOPY(vec, t->center);
596                 Mat4MulVecfl(ob->obmat, vec);
597                 project_short_noclip(vec, t->center2d);
598         }
599         else {
600                 project_short_noclip(t->center, t->center2d);
601         }
602 }
603
604 void calculateCenter(TransInfo *t) 
605 {
606         switch(G.vd->around) {
607         case V3D_CENTRE:
608                 calculateCenterBound(t);
609                 break;
610         case V3D_CENTROID:
611                 calculateCenterMedian(t);
612                 break;
613         case V3D_CURSOR:
614                 calculateCenterCursor(t);
615                 break;
616         case V3D_LOCAL:
617                 // NEED TO REPLACE THIS
618                 calculateCenterMedian(t);
619                 printf("local\n");
620                 break;
621         }
622         initgrabz(t->center[0], t->center[1], t->center[2]);
623 }
624
625 void calculatePropRatio(TransInfo *t)
626 {
627         TransData *td = t->data;
628         int i;
629         float dist;
630         extern int prop_mode;
631
632         if (G.f & G_PROPORTIONAL) {
633                 for(i = 0 ; i < t->total; i++, td++) {
634                         if (td->dist == 0.0f) {
635                                 td->factor = 1.0f;
636                         }
637                         else if (td->dist > t->propsize) {
638                                 td->factor = 0.0f;
639                         }
640                         else {
641                                 dist= (t->propsize-td->dist)/t->propsize;
642                                 switch(prop_mode) {
643                                 case PROP_SHARP:
644                                         td->factor= dist*dist;
645                                         break;
646                                 case PROP_SMOOTH:
647                                         td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
648                                         break;
649                                 case PROP_ROOT:
650                                         td->factor = (float)sqrt(dist);
651                                         break;
652                                 case PROP_LIN:
653                                         td->factor = dist;
654                                         break;
655                                 case PROP_CONST:
656                                         td->factor = 1;
657                                         break;
658                                 default:
659                                         td->factor = 1;
660                                 }
661                         }
662                 }
663                 switch(prop_mode) {
664                 case PROP_SHARP:
665                         strcpy(t->proptext, "(Quad)");
666                         break;
667                 case PROP_SMOOTH:
668                         strcpy(t->proptext, "(Smooth)");
669                         break;
670                 case PROP_ROOT:
671                         strcpy(t->proptext, "(Root)");
672                         break;
673                 case PROP_LIN:
674                         strcpy(t->proptext, "(Linear)");
675                         break;
676                 case PROP_CONST:
677                         strcpy(t->proptext, "(Constant)");
678                         break;
679                 default:
680                         strcpy(t->proptext, "");
681                 }
682         }
683         else {
684                 for(i = 0 ; i < t->total; i++, td++) {
685                         td->factor = 1.0;
686                 }
687                 strcpy(t->proptext, "");
688         }
689 }
690
691 TransInfo * BIF_GetTransInfo() {
692         return &Trans;
693 }