be89dfba240c43b56a9d663077a24284af348b30
[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         G.moving = 0; // Set moving flag off (display as usual)
355
356         MEM_freeN(t->data);
357         t->data = NULL;
358
359         if (tx) {
360                 MEM_freeN(tx);
361         }
362         
363 }
364
365 void apply_grid3(float *val, int max_index, float fac1, float fac2, float fac3)
366 {
367         /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
368         int invert = U.flag & USER_AUTOGRABGRID;
369         int ctrl;
370         int i;
371
372         for (i=0; i<=max_index; i++) {
373
374                 if(invert) {
375                         if(G.qual & LR_CTRLKEY) ctrl= 0;
376                         else ctrl= 1;
377                 }
378                 else ctrl= (G.qual & LR_CTRLKEY);
379
380                 if(ctrl && (G.qual & LR_SHIFTKEY)) {
381                         if(fac3!= 0.0) {
382                                 for (i=0; i<=max_index; i++) {
383                                         val[i]= fac3*(float)floor(val[i]/fac3 +.5);
384                                 }
385                         }
386                 }
387                 else if(ctrl) {
388                         if(fac2!= 0.0) {
389                                 for (i=0; i<=max_index; i++) {
390                                         val[i]= fac2*(float)floor(val[i]/fac2 +.5);
391                                 }
392                         }
393                 }
394                 else {
395                         if(fac1!= 0.0) {
396                                 for (i=0; i<=max_index; i++) {
397                                         val[i]= fac1*(float)floor(val[i]/fac1 +.5);
398                                 }
399                         }
400                 }
401         }
402 }
403
404 void apply_grid1(float *val, int max_index, float factor)
405 {
406         /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
407         float fac1 = 0.0;
408         float fac2 = G.vd->grid * factor;
409         float fac3 = 0.1f * fac2;
410         apply_grid3(val, max_index, fac1, fac2, fac3);
411 }
412
413 void apply_grid2(float *val, int max_index, float factor, float factor2)
414 {
415         /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
416         float fac1 = 0.0;
417         float fac2 = G.vd->grid * factor;
418         float fac3 = factor2 * fac2;
419         apply_grid3(val, max_index, fac1, fac2, fac3);
420 }
421
422 void applyTransObjects(TransInfo *t)
423 {
424     TransData *tob;
425         for (tob = t->data; tob < t->data + t->total; tob++) {
426         VECCOPY(tob->iloc, tob->loc);
427                 if (tob->ext->rot) {
428                         VECCOPY(tob->ext->irot, tob->ext->rot);
429                 }
430                 if (tob->ext->size) {
431                         VECCOPY(tob->ext->isize, tob->ext->size);
432                 }
433     }    
434         recalcData(t);
435
436
437 void restoreTransObjects(TransInfo *t)
438 {
439     TransData *tob;
440         for (tob = t->data; tob < t->data + t->total; tob++) {
441         VECCOPY(tob->loc, tob->iloc);
442                 if (tob->ext) {
443                         if (tob->ext->rot) {
444                                 VECCOPY(tob->ext->rot, tob->ext->irot);
445                         }
446                         if (tob->ext->size) {
447                                 VECCOPY(tob->ext->size, tob->ext->isize);
448                         }
449                         if(tob->flag & TD_USEQUAT) {
450                                 if (tob->ext->quat) {
451                                         QUATCOPY(tob->ext->quat, tob->ext->iquat);
452                                 }
453                         }
454                 }
455     }    
456         recalcData(t);
457
458
459 void initTrans (TransInfo *t)
460 {
461
462         G.moving = 1; // Set moving flag on (display object in white)
463
464         t->data = NULL;
465
466         getmouseco_areawin(t->imval);
467
468         t->transform            = NULL;
469         t->con.applyVec         = NULL;
470         t->con.applyRot = NULL;
471         t->con.mode             =
472                 t->total                        =
473                 t->num.idx              =
474                 t->num.idx_max  =
475                 t->num.ctrl[0]  = 
476                 t->num.ctrl[1]  = 
477                 t->num.ctrl[2]  = 0;
478
479         t->val = 0.0f;
480
481         t->num.val[0]           = 
482                 t->num.val[1]   = 
483                 t->num.val[2]   = 0.0f;
484 }
485
486 void calculateCenterCursor(TransInfo *t)
487 {
488         float *cursor;
489
490         cursor = give_cursor();
491         VECCOPY(t->center, cursor);
492
493         if(G.obedit || G.obpose) {
494                 Object *ob= G.obedit?G.obedit:G.obpose;
495                 float mat[3][3], imat[3][3];
496                 float vec[3];
497                 
498                 VecSubf(t->center, t->center, ob->obmat[3]);
499                 Mat3CpyMat4(mat, ob->obmat);
500                 Mat3Inv(imat, mat);
501                 Mat3MulVecfl(imat, t->center);
502                 
503                 VECCOPY(vec, t->center);
504                 Mat4MulVecfl(ob->obmat, vec);
505                 project_short_noclip(vec, t->center2d);
506         }
507         else {
508                 project_short_noclip(t->center, t->center2d);
509         }
510 }
511
512 void calculateCenterMedian(TransInfo *t)
513 {
514         float partial[3] = {0.0f, 0.0f, 0.0f};
515         int i;
516         for(i = 0; i < t->total; i++) {
517                 if (t->data[i].flag & TD_SELECTED) {
518                         VecAddf(partial, partial, t->data[i].center);
519                 }
520         }
521         VecMulf(partial, 1.0f / t->total);
522         VECCOPY(t->center, partial);
523
524         if (G.obedit || G.obpose) {
525                 Object *ob= G.obedit?G.obedit:G.obpose;
526                 float vec[3];
527                 
528                 VECCOPY(vec, t->center);
529                 Mat4MulVecfl(ob->obmat, vec);
530                 project_short_noclip(vec, t->center2d);
531         }
532         else {
533                 project_short_noclip(t->center, t->center2d);
534         }
535 }
536
537 void calculateCenterBound(TransInfo *t)
538 {
539         float max[3];
540         float min[3];
541         int i;
542         for(i = 0; i < t->total; i++) {
543                 if (i) {
544                         if (t->data[i].flag & TD_SELECTED) {
545                                 MinMax3(min, max, t->data[i].center);
546                         }
547                 }
548                 else {
549                         VECCOPY(max, t->data[i].center);
550                         VECCOPY(min, t->data[i].center);
551                 }
552         }
553         VecAddf(t->center, min, max);
554         VecMulf(t->center, 0.5);
555
556         if (G.obedit || G.obpose) {
557                 Object *ob= G.obedit?G.obedit:G.obpose;
558                 float vec[3];
559                 
560                 VECCOPY(vec, t->center);
561                 Mat4MulVecfl(ob->obmat, vec);
562                 project_short_noclip(vec, t->center2d);
563         }
564         else {
565                 project_short_noclip(t->center, t->center2d);
566         }
567 }
568
569 void calculateCenter(TransInfo *t) 
570 {
571         switch(G.vd->around) {
572         case V3D_CENTRE:
573                 calculateCenterBound(t);
574                 break;
575         case V3D_CENTROID:
576                 calculateCenterMedian(t);
577                 break;
578         case V3D_CURSOR:
579                 calculateCenterCursor(t);
580                 break;
581         case V3D_LOCAL:
582                 // NEED TO REPLACE THIS
583                 calculateCenterMedian(t);
584                 printf("local\n");
585                 break;
586         }
587         initgrabz(t->center[0], t->center[1], t->center[2]);
588 }
589
590 void calculatePropRatio(TransInfo *t)
591 {
592         TransData *td = t->data;
593         int i;
594         float dist;
595         extern int prop_mode;
596
597         if (G.f & G_PROPORTIONAL) {
598                 for(i = 0 ; i < t->total; i++, td++) {
599                         if (td->dist == 0.0f) {
600                                 td->factor = 1.0f;
601                         }
602                         else if (td->dist > t->propsize) {
603                                 td->factor = 0.0f;
604                         }
605                         else {
606                                 dist= (t->propsize-td->dist)/t->propsize;
607                                 switch(prop_mode) {
608                                 case PROP_SHARP:
609                                         td->factor= dist*dist;
610                                         break;
611                                 case PROP_SMOOTH:
612                                         td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
613                                         break;
614                                 case PROP_ROOT:
615                                         td->factor = (float)sqrt(dist);
616                                         break;
617                                 case PROP_LIN:
618                                         td->factor = dist;
619                                         break;
620                                 case PROP_CONST:
621                                         td->factor = 1;
622                                         break;
623                                 default:
624                                         td->factor = 1;
625                                 }
626                         }
627                 }
628                 switch(prop_mode) {
629                 case PROP_SHARP:
630                         strcpy(t->proptext, "(Quad)");
631                         break;
632                 case PROP_SMOOTH:
633                         strcpy(t->proptext, "(Smooth)");
634                         break;
635                 case PROP_ROOT:
636                         strcpy(t->proptext, "(Root)");
637                         break;
638                 case PROP_LIN:
639                         strcpy(t->proptext, "(Linear)");
640                         break;
641                 case PROP_CONST:
642                         strcpy(t->proptext, "(Constant)");
643                         break;
644                 default:
645                         strcpy(t->proptext, "");
646                 }
647         }
648         else {
649                 for(i = 0 ; i < t->total; i++, td++) {
650                         td->factor = 1.0;
651                 }
652                 strcpy(t->proptext, "");
653         }
654 }
655
656 TransInfo * BIF_GetTransInfo() {
657         return &Trans;
658 }