Transform widgets; Scale and Rotate versions
authorTon Roosendaal <ton@blender.org>
Sat, 19 Mar 2005 12:17:06 +0000 (12:17 +0000)
committerTon Roosendaal <ton@blender.org>
Sat, 19 Mar 2005 12:17:06 +0000 (12:17 +0000)
To use; press the (temporal) icon in header. Switching widget types is by
pressing G, R or S once, if current widget type is different it switches,
otherwise it goes to normal Transform().

Widgets need a bit test for picking accuracy, correct drawing etc.
The rotate widget has a center button for 'trackball' rotate. That latter
can also be used for hotkey-based rotate.

In current code, all widgets remain in "Global" space, also in editmode.
Also widget updates while using normal transform has to be done.

2 Bugfixes:
- rotate in PoseMode had error for 2d 'around' center
- transform in postemode could crash, due to typo (& or |)

12 files changed:
source/blender/blenloader/intern/readfile.c
source/blender/include/BDR_drawobject.h
source/blender/include/BIF_transform.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/src/drawobject.c
source/blender/src/editscreen.c
source/blender/src/space.c
source/blender/src/transform.c
source/blender/src/transform.h
source/blender/src/transform_constraints.c
source/blender/src/transform_generics.c
source/blender/src/transform_manipulator.c

index 68bd3946e557425afd5b9112cd709572a449fd0a..dcf7658ab971138c04ad9e23fb8a5cca9fda5f01 100644 (file)
@@ -4625,6 +4625,7 @@ static void do_versions(Main *main)
        if(main->versionfile <= 236) {
                Scene *sce= main->scene.first;
                Camera *cam= main->camera.first;
+               bScreen *sc;
                
                while(sce) {
                        if(sce->r.postsat==0.0) sce->r.postsat= 1.0;
@@ -4637,6 +4638,19 @@ static void do_versions(Main *main)
                        }
                        cam= cam->id.next;
                }
+               /* set manipulator type */
+               for (sc= main->screen.first; sc; sc= sc->id.next) {
+                       ScrArea *sa;
+                       for (sa= sc->areabase.first; sa; sa= sa->next) {
+                               SpaceLink *sl;
+                               for (sl= sa->spacedata.first; sl; sl= sl->next) {
+                                       if(sl->spacetype==SPACE_VIEW3D) {
+                                               View3D *v3d= (View3D *)sl;
+                                               if(v3d->twtype==0) v3d->twtype= V3D_MANIPULATOR_TRANSLATE;
+                                       }
+                               }
+                       }
+               }
        }
        
        /* don't forget to set version number in blender.c! */
index a60840813365e1981080593fd8a863e60073e5ef..10b6dc11c5cf23db9b4c5626c140194aa0e7a40a 100644 (file)
@@ -61,6 +61,7 @@ void drawcircball(float *cent, float rad, float tmat[][4]);
 void get_local_bounds(struct Object *ob, float *centre, float *size);
 void draw_object(struct Base *base);
 void draw_object_ext(struct Base *base);
+void drawsolidcube(float size);
 extern void draw_object_backbufsel(struct Object *ob);
 
 #ifdef __cplusplus
index 7846e4d315dd49df7fb32b7971e0ec9c4553a849..d6f1db700c907bf0ff4b24e3a1fc7a213257565f 100755 (executable)
@@ -33,7 +33,7 @@
 #ifndef BIF_TRANSFORM_H
 #define BIF_TRANSFORM_H
 
-#define NEWTRANSFORM   1
+//#define NEWTRANSFORM 1
 
 /* ******************** Macros & Prototypes *********************** */
 
@@ -49,6 +49,7 @@
 #define TFM_TILT                       9
 
 #define TFM_LAMP_ENERGY                10
+#define TFM_TRACKBALL          11
 
        // not sure if adding modes is the right way... context detecting could be done different (ton)
 #define TFM_TEX                                32
index 18e0fdf448d7e4c7b68aad0425f1ab3cd88fdb0c..19bee996a594569f8865d8fff56917eddf52d570 100644 (file)
@@ -147,10 +147,10 @@ typedef struct View3D {
 #define V3D_SHOW_Y                             4
 #define V3D_SHOW_Z                             8
 
-/* View3d->twtype */
-#define V3D_MANIPULATOR_TRANSLATE      0
-#define V3D_MANIPULATOR_ROTATE         1
-#define V3D_MANIPULATOR_SCALE          2
+/* View3d->twtype (bits, we can combine them) */
+#define V3D_MANIPULATOR_TRANSLATE      1
+#define V3D_MANIPULATOR_ROTATE         2
+#define V3D_MANIPULATOR_SCALE          4
 
 /* View3d->twmode */
 #define V3D_MANIPULATOR_GLOBAL         0
index 48cdd1c476350859c01b9ae448451b95c4466eb3..05968be0c4d9c6e89ec64077d2c46126e653323a 100644 (file)
@@ -318,11 +318,14 @@ void drawaxes(float size)
        }
 }
 
-#if 0
-static void drawgourcube(void)
+
+void drawsolidcube(float size)
 {
        float n[3];
 
+       glPushMatrix();
+       glScalef(size, size, size);
+       
        n[0]=0; n[1]=0; n[2]=0;
        glBegin(GL_QUADS);
                n[0]= -1.0;
@@ -364,8 +367,9 @@ static void drawgourcube(void)
                glNormal3fv(n); 
                glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
        glEnd();
+       
+       glPopMatrix();
 }
-#endif
 
 static void drawcube(void)
 {
index 5c311b594ce340fdc58eb6822b4c6c46ed9362c7..572e4114c5e7b21b5705d300f43a010423ad4ed1 100644 (file)
@@ -1217,7 +1217,12 @@ void screenmain(void)
                if (event==0 || event==EXECUTE) {
                        screen_dispatch_events();
                }
-
+               
+               if(G.f & G_DEBUG) {
+                       GLenum error = glGetError();
+                       if (error)
+                               printf("GL error: %s\n", gluErrorString(error));
+               }
                /* Bizar hack. The event queue has mutated... */
                if ( (firsttime) && (event == 0) ) {
 
index b7ed74a0213a221bb014c885d6b1e713dd125878..70027f34f15a39712f0f96d01bd3aedc46b42d3f 100644 (file)
@@ -720,7 +720,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
        unsigned short event= evt->event;
        short val= evt->val;
        char ascii= evt->ascii;
-       View3D *v3d= curarea->spacedata.first;
+       View3D *v3d= sa->spacedata.first;
        Object *ob;
        float *curs;
        int doredraw= 0, pupval;
@@ -1220,12 +1220,20 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                        if(okee("Clear location")) {
                                                clear_object('g');
                                        }
-                               } else if((G.qual==0))
+                               } else if((G.qual==0)) {
+                                       if(v3d->twflag & V3D_USE_MANIPULATOR) {
+                                               if((v3d->twtype & V3D_MANIPULATOR_TRANSLATE)==0) {
+                                                       v3d->twtype= V3D_MANIPULATOR_TRANSLATE;
+                                                       doredraw= 1;
+                                                       break;
+                                               }
+                                       }
 #ifdef NEWTRANSFORM
                                        Transform(TFM_TRANSLATION);
 #else
                                        transform('g');
 #endif
+                               }
                                break;
                        case HKEY:
                                if(G.obedit) {
@@ -1485,19 +1493,35 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                                if (G.obedit->type==OB_MESH)
                                                        loopoperations(LOOP_CUT);
                                        }
-                                       else if((G.qual==0))
+                                       else if((G.qual==0)) {
+                                               if(v3d->twflag & V3D_USE_MANIPULATOR) {
+                                                       if((v3d->twtype & V3D_MANIPULATOR_ROTATE)==0) {
+                                                               v3d->twtype= V3D_MANIPULATOR_ROTATE;
+                                                               doredraw= 1;
+                                                               break;
+                                                       }
+                                               }
 #ifdef NEWTRANSFORM
                                                Transform(TFM_ROTATION);
 #else
                                                transform('r');
 #endif
+                                       }
                                }
-                               else if((G.qual==0))
+                               else if((G.qual==0)) {
+                                       if(v3d->twflag & V3D_USE_MANIPULATOR) {
+                                               if((v3d->twtype & V3D_MANIPULATOR_ROTATE)==0) {
+                                                       v3d->twtype= V3D_MANIPULATOR_ROTATE;
+                                                       doredraw= 1;
+                                                       break;
+                                               }
+                                       }
 #ifdef NEWTRANSFORM
                                        Transform(TFM_ROTATION);
 #else
                                        transform('r');
 #endif
+                               }
                                break;
                        case SKEY:
                                if(G.obedit) {
@@ -1517,14 +1541,25 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 #endif
                                        else if(G.qual==LR_SHIFTKEY)
                                                snapmenu();
-                                       else if(G.qual==0)
+                                       else if(G.qual==0) {
+                                               if(v3d->twflag & V3D_USE_MANIPULATOR) {
+                                                       if((v3d->twtype & V3D_MANIPULATOR_SCALE)==0) {
+                                                               v3d->twtype= V3D_MANIPULATOR_SCALE;
+                                                               doredraw= 1;
+                                                               break;
+                                                       }
+                                               }
 #ifdef NEWTRANSFORM
                                                Transform(TFM_RESIZE);
-                                       else if(G.qual==(LR_SHIFTKEY|LR_CTRLKEY))
-                                               Transform(TFM_TOSPHERE);
 #else
                                                transform('s');
 #endif
+                                       }
+                                       else if(G.qual==(LR_SHIFTKEY|LR_CTRLKEY))
+#ifdef NEWTRANSFORM
+                                               Transform(TFM_TOSPHERE);
+#endif
+                                       
                                }
                                else if(G.qual==LR_ALTKEY) {
                                        if(okee("Clear size")) {
@@ -1534,15 +1569,25 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                else if(G.qual==LR_SHIFTKEY) {
                                        snapmenu();
                                }
-                               else if((G.qual==0))
+                               else if((G.qual==0)) {
+                                       if(v3d->twflag & V3D_USE_MANIPULATOR) {
+                                               if((v3d->twtype & V3D_MANIPULATOR_SCALE)==0) {
+                                                       v3d->twtype= V3D_MANIPULATOR_SCALE;
+                                                       doredraw= 1;
+                                                       break;
+                                               }
+                                       }
 #ifdef NEWTRANSFORM
                                        Transform(TFM_RESIZE);
+#else
+                                       transform('s');
+#endif
+                               }
+#ifdef NEWTRANSFORM
                                else if(G.qual==(LR_SHIFTKEY|LR_CTRLKEY))
                                        Transform(TFM_TOSPHERE);
                                else if(G.qual==(LR_CTRLKEY|LR_ALTKEY))
                                        Transform(TFM_SHEAR);
-#else
-                                       transform('s');
 #endif
                                break;
                        case TKEY:
index d0ac0c95d3164e2acb497dc78c15a0f903844a72..a243dd81b6842fb4d714960e5438f017cf88c345 100755 (executable)
@@ -1227,7 +1227,7 @@ static void createTransData(TransInfo *t)
                t->mode &= ~TFM_TEX;    // now becoming normal grab/rot/scale
        }
        else if (G.obpose) {
-               t->flag &= T_POSE;
+               t->flag |= T_POSE;
                createTransPose();
        }
        else if (G.obedit) {
@@ -1338,6 +1338,9 @@ void Transform(int mode)
        case TFM_TILT:
                initTilt(&Trans);
                break;
+       case TFM_TRACKBALL:
+               initTrackball(&Trans);
+               break;
        }
 
        // Emptying event queue
@@ -1572,8 +1575,6 @@ void Transform(int mode)
        scrarea_queue_headredraw(curarea);
 }
 
-static void draw_nothing(TransInfo *t) {}
-
 void ManipulatorTransform(int mode) 
 {
        int ret_val = 0;
@@ -1597,9 +1598,6 @@ void ManipulatorTransform(int mode)
        if (Trans.total == 0)
                return;
 
-       /* no drawing of constraint lines */
-       Trans.con.drawExtra= draw_nothing;
-       
        /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */
        /* EVIL2: we gave as argument also texture space context bit... was cleared */
        mode= Trans.mode;
@@ -1617,8 +1615,12 @@ void ManipulatorTransform(int mode)
        case TFM_RESIZE:
                initResize(&Trans);
                break;
+       case TFM_TRACKBALL:
+               initTrackball(&Trans);
+               break;
        }
-
+       
+       Trans.flag |= T_USES_MANIPULATOR;
        Trans.redraw = 1;
 
        while (ret_val == 0) {
@@ -1915,6 +1917,8 @@ void initResize(TransInfo *t)
                        (Trans.center2d[0] - Trans.imval[0])*(Trans.center2d[0] - Trans.imval[0])
                ) );
 
+       if(Trans.fac==0.0f) Trans.fac= 1.0f;    // prevent Inf
+       
        t->idx_max = 2;
        t->num.idx_max = 2;
        t->snap[0] = 0.0f;
@@ -1960,13 +1964,19 @@ int Resize(TransInfo *t, short mval[2])
        int i;
        char str[50];
 
-       ratio = (float)sqrt( (float)
-               (
-                       (t->center2d[1] - mval[1])*(t->center2d[1] - mval[1])
-               +
-                       (t->center2d[0] - mval[0])*(t->center2d[0] - mval[0])
-               ) ) / t->fac;
-
+       /* for manipulator, center handle, the scaling can't be done relative to center */
+       if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) {
+               ratio = 1.0f - ((t->center2d[0] - mval[0]) + (t->center2d[1] - mval[1]))/100.0f;
+       }
+       else {
+               ratio = (float)sqrt( (float)
+                       (
+                               (t->center2d[1] - mval[1])*(t->center2d[1] - mval[1])
+                       +
+                               (t->center2d[0] - mval[0])*(t->center2d[0] - mval[0])
+                       ) ) / t->fac;
+       }
+       
        size[0] = size[1] = size[2] = ratio;
 
        snapGrid(t, size);
@@ -1982,6 +1992,8 @@ int Resize(TransInfo *t, short mval[2])
                t->con.applySize(t, NULL, mat);
        }
 
+       Mat3CpyMat3(t->mat, mat);       // used in manipulator
+       
        headerResize(t, size, str);
 
        for(i = 0 ; i < t->total; i++, td++) {
@@ -2064,7 +2076,7 @@ int Resize(TransInfo *t, short mval[2])
 
        force_draw(0);
 
-       helpline (t->center);
+       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t->center);
 
        return 1;
 }
@@ -2249,6 +2261,8 @@ int Rotation(TransInfo *t, short mval[2])
        //printf("Axis %f %f %f\n", axis[0], axis[1], axis[2]);
        VecRotToMat3(axis, final * td->factor, mat);
 
+       Mat3CpyMat3(t->mat, mat);       // used in manipulator
+       
        for(i = 0 ; i < t->total; i++, td++) {
                if (td->flag & TD_NOACTION)
                        break;
@@ -2352,8 +2366,167 @@ int Rotation(TransInfo *t, short mval[2])
 
        force_draw(0);
 
-       helpline (t->center);
+       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t->center);
+
+       return 1;
+}
+
+
+/* ************************** TRACKBALL *************************** */
 
+void initTrackball(TransInfo *t) 
+{
+       t->idx_max = 1;
+       t->num.idx_max = 1;
+       t->snap[0] = 0.0f;
+       t->snap[1] = G.vd->grid * (float)((5.0/180)*M_PI);
+       t->snap[2] = t->snap[1] * 0.2f;
+       t->fac = 0;
+       t->transform = Trackball;
+}
+
+int Trackball(TransInfo *t, short mval[2]) 
+{
+       TransData *td = t->data;
+       int i;
+       char str[50];
+       float vec[3], axis1[3], axis2[3];
+       float mat[3][3], totmat[3][3], smat[3][3];
+       float phi[2];
+       
+       VECCOPY(axis1, G.vd->persinv[0]);
+       VECCOPY(axis2, G.vd->persinv[1]);
+       Normalise(axis1);
+       Normalise(axis2);
+       
+       /* factore has to become setting or so */
+       phi[0]= .01*(float)( t->imval[1] - mval[1] );
+       phi[1]= .01*(float)( mval[0] - t->imval[0] );
+       
+       //if(G.qual & LR_SHIFTKEY) t->fac += dphi/30.0f;
+       //else t->fac += dphi;
+       
+       snapGrid(t, phi);
+       
+       if (hasNumInput(&t->num)) {
+               //char c[20];
+               
+               //applyNumInput(&t->num, phi);
+               
+               //outputNumInput(&(t->num), c);
+               
+               //sprintf(str, "Trackball: %s %s", &c[0], t->proptext);
+               
+               //final *= (float)(M_PI / 180.0);
+       }
+       else {
+               sprintf(str, "Trackball: %.2f %.2f %s", 180.0*phi[0]/M_PI, 180.0*phi[1]/M_PI, t->proptext);
+       }
+       
+       VecRotToMat3(axis1, phi[0], smat);
+       VecRotToMat3(axis2, phi[1], totmat);
+       
+       Mat3MulMat3(mat, smat, totmat);
+       
+       Mat3CpyMat3(t->mat, mat);       // used in manipulator
+       
+       for(i = 0 ; i < t->total; i++, td++) {
+               if (td->flag & TD_NOACTION)
+                       break;
+               
+               if (G.vd->around == V3D_LOCAL) {
+                       VECCOPY(t->center, td->center);
+               }
+               
+               if (t->flag & T_EDIT) {
+                       Mat3MulMat3(totmat, mat, td->mtx);
+                       Mat3MulMat3(smat, td->smtx, totmat);
+                       
+                       VecSubf(vec, td->iloc, t->center);
+                       Mat3MulVecfl(smat, vec);
+                       
+                       VecAddf(td->loc, vec, t->center);
+               }
+               else {
+                       float eul[3], fmat[3][3];
+                       
+                       /* translation */
+                       VecSubf(vec, td->center, t->center);
+                       Mat3MulVecfl(mat, vec);
+                       VecAddf(vec, vec, t->center);
+                       /* vec now is the location where the object has to be */
+                       VecSubf(vec, vec, td->center);
+                       Mat3MulVecfl(td->smtx, vec);
+                       
+                       VecAddf(td->loc, td->iloc, vec);
+                       
+                       if(td->flag & TD_USEQUAT) {
+                               float quat[4];
+                               
+                               Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0);
+                               
+                               Mat3ToQuat(fmat, quat); // Actual transform
+                               
+                               QuatMul(td->ext->quat, quat, td->ext->iquat);
+                       }
+                       else if ((G.vd->flag & V3D_ALIGN)==0) { // align mode doesn't rotate objects itself
+                               float obmat[3][3];
+                               
+                               /* are there ipo keys? */
+                               if(td->tdi) {
+                                       TransDataIpokey *tdi= td->tdi;
+                                       float rot[3];
+                                       
+                                       /* calculate the total rotatation in eulers */
+                                       VecAddf(eul, td->ext->irot, td->ext->drot);
+                                       EulToMat3(eul, obmat);
+                                       /* mat = transform, obmat = object rotation */
+                                       Mat3MulMat3(fmat, mat, obmat);
+                                       Mat3ToEul(fmat, eul);
+                                       compatible_eul(eul, td->ext->irot);
+                                       
+                                       /* correct back for delta rot */
+                                       if(tdi->flag & TOB_IPODROT) {
+                                               VecSubf(rot, eul, td->ext->irot);
+                                       }
+                                       else {
+                                               VecSubf(rot, eul, td->ext->drot);
+                                       }
+                                       
+                                       VecMulf(rot, (float)(9.0/M_PI_2));
+                                       VecSubf(rot, rot, tdi->oldrot);
+                                       
+                                       add_tdi_poin(tdi->rotx, tdi->oldrot, rot[0]);
+                                       add_tdi_poin(tdi->roty, tdi->oldrot+1, rot[1]);
+                                       add_tdi_poin(tdi->rotz, tdi->oldrot+2, rot[2]);
+                               }
+                               else {
+                                       
+                                       /* calculate the total rotatation in eulers */
+                                       VecAddf(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */
+                                       EulToMat3(eul, obmat);
+                                       /* mat = transform, obmat = object rotation */
+                                       Mat3MulMat3(fmat, mat, obmat);
+                                       Mat3ToEul(fmat, eul);
+                                       compatible_eul(eul, td->ext->irot);
+                                       
+                                       /* correct back for delta rot */
+                                       VecSubf(eul, eul, td->ext->drot);
+                                       /* and apply */
+                                       VECCOPY(td->ext->rot, eul);
+                               }
+                       }
+               }
+       }
+       
+       recalcData(t);
+       
+       headerprint(str);
+       
+       force_draw(0);
+       
+       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t->center);
+       
        return 1;
 }
 
index 5209ec0e5193320135179c6ca584ce8a4cc2b72a..d10c066f547a74b09643bef42114b361a8fc6440 100755 (executable)
@@ -146,8 +146,11 @@ typedef struct TransInfo {
 #define T_EDIT                 2
 #define T_POSE                 4
 #define T_TEXTURE              8
+               // for manipulator exceptions, like scaling using center point, drawing help lines
+#define T_USES_MANIPULATOR     128
 
 
+/* transinfo->con->mode */
 #define CON_APPLY              1
 #define CON_AXIS0              2
 #define CON_AXIS1              4
@@ -186,5 +189,8 @@ int ShrinkFatten(TransInfo *t, short mval[2]);
 void initTilt(TransInfo *t);
 int Tilt(TransInfo *t, short mval[2]);
 
+void initTrackball(TransInfo *t);
+int Trackball(TransInfo *t, short mval[2]);
+
 #endif
 
index 54bf3dc71fe1b29fb981d849ef2bbeb355026daf..d3c5f12260a9cbae637d8e34f9b8ef6ce25c8103 100755 (executable)
@@ -589,6 +589,7 @@ void BIF_setSingleAxisConstraint(float vec[3]) {
 
        Crossf(space[1], vec, v);
        Crossf(space[2], vec, space[1]);
+       Mat3Ortho(space);
 
        Mat3Ortho(space);
 
@@ -603,6 +604,8 @@ void BIF_setSingleAxisConstraint(float vec[3]) {
        t->con.applySize = applyAxisConstraintSize;
        t->con.applyRot = applyAxisConstraintRot;
        t->redraw = 1;
+       
+       startConstraint(t);
 }
 
 void BIF_setDualAxisConstraint(float vec1[3], float vec2[3]) {
@@ -612,7 +615,6 @@ void BIF_setDualAxisConstraint(float vec1[3], float vec2[3]) {
        VECCOPY(space[0], vec1);
        VECCOPY(space[1], vec2);
        Crossf(space[2], space[0], space[1]);
-
        Mat3Ortho(space);
        
        Mat3CpyMat3(t->con.mtx, space);
@@ -626,6 +628,8 @@ void BIF_setDualAxisConstraint(float vec1[3], float vec2[3]) {
        t->con.applySize = applyAxisConstraintSize;
        t->con.applyRot = applyAxisConstraintRot;
        t->redraw = 1;
+       
+       startConstraint(t);
 }
 
 
@@ -636,6 +640,8 @@ void BIF_drawConstraint(void)
 
        if (!(tc->mode & CON_APPLY))
                return;
+       if (t->flag & T_USES_MANIPULATOR)
+               return;
 
        if (tc->drawExtra) {
                tc->drawExtra(t);
index 0df1044940cdd024c5c43557b29921d6c5c86c67..e4872f7d65101675f7c44e3c0a06a4512b43d0b9 100755 (executable)
@@ -133,7 +133,7 @@ void recalcData(TransInfo *t)
                for (i=0; i<t->total; i++, td++) {
                        chan = MEM_callocN (sizeof (bPoseChannel), "transPoseChannel");
                        
-                       if (t->mode == TFM_ROTATION) {
+                       if (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) {
                                chan->flag |= POSE_ROT;
                                memcpy (chan->quat, td->ext->quat, sizeof (chan->quat));
                        }
@@ -230,16 +230,17 @@ void recalcData(TransInfo *t)
                base= FIRSTBASE;
                while(base) {
                        if(base->flag & BA_DO_IPO) {
-                               IpoCurve *icu;
-                               
-                               base->object->ctime= -1234567.0;
-                               
-                               icu= base->object->ipo->curve.first;
-                               while(icu) {
-                                       calchandles_ipocurve(icu);
-                                       icu= icu->next;
-                               }
-                               
+                               if(base->object->ipo) {
+                                       IpoCurve *icu;
+                                       
+                                       base->object->ctime= -1234567.0;
+                                       
+                                       icu= base->object->ipo->curve.first;
+                                       while(icu) {
+                                               calchandles_ipocurve(icu);
+                                               icu= icu->next;
+                                       }
+                               }                               
                        }
                        if(base->object->partype & PARSLOW) {
                                base->object->partype -= PARSLOW;
@@ -639,8 +640,9 @@ void calculateCenter(TransInfo *t)
 
        /* setting constraint center */
        VECCOPY(t->con.center, t->center);
-       if(t->flag & T_EDIT) {
-               Mat4MulVecfl(G.obedit->obmat, t->con.center);
+       if(t->flag & (T_EDIT|T_POSE)) {
+               Object *ob= G.obedit?G.obedit:G.obpose;
+               Mat4MulVecfl(ob->obmat, t->con.center);
        }
 
        /* voor panning from cameraview */
index 98768fc8a45f1b843fd0510bd223d9f10c91fb8a..b91ef64cef8183753d0705918d369d828bd692d1 100644 (file)
@@ -76,6 +76,7 @@
 
 #include "BSE_edit.h"
 #include "BSE_view.h"
+#include "BDR_drawobject.h"
 
 #include "blendef.h"
 #include "transform.h"
 #define MAN_ROT_X              8
 #define MAN_ROT_Y              16
 #define MAN_ROT_Z              32
-#define MAN_ROT_C              63
+#define MAN_ROT_V              64
+#define MAN_ROT_T              128
+#define MAN_ROT_C              248
+
+#define MAN_SCALE_X            256
+#define MAN_SCALE_Y            512
+#define MAN_SCALE_Z            1024
+#define MAN_SCALE_C            1792
 
 
 /* GLOBAL VARIABLE THAT SHOULD MOVED TO SCREEN MEMBER OR SOMETHING  */
@@ -273,9 +281,9 @@ static int calc_manipulator(ScrArea *sa)
        /* global, local or normal orientation? */
        if(ob) {
                // local....
-               if(totsel==1 || v3d->around==V3D_LOCAL) {
-                       Mat4CpyMat4(v3d->twmat, ob->obmat);
-                       Mat4Ortho(v3d->twmat);
+               if(totsel==1 || v3d->around==V3D_LOCAL || G.obedit || G.obpose) {
+                       //Mat4CpyMat4(v3d->twmat, ob->obmat);
+                       //Mat4Ortho(v3d->twmat);
                }               
        }
           
@@ -298,7 +306,7 @@ static void manipulator_setcolor(char mode)
        else {
                switch(mode) {
                case 'x':
-                       glColor3ub(255, 100, 100);
+                       glColor3ub(255, 0, 100);
                        break;
                case 'y':
                        glColor3ub(100, 255, 100);
@@ -324,14 +332,228 @@ static void manipulator_setcolor(char mode)
 
 static int Gval= 0xFFFF;       // defines drawmodus while moving...
 
+static void draw_manipulator_rotate(float mat[][4])
+{
+       double plane[4];
+       float size, vec[3], unitmat[4][4];
+       
+       /* when called while moving in mixed mode, do not draw when... */
+       if((Gval & MAN_ROT_C)==0) return;
+       
+       glDisable(GL_DEPTH_TEST);
+       Mat4One(unitmat);
+       
+       /* Screen aligned help circle */
+       glPushMatrix();
+       glTranslatef(mat[3][0], mat[3][1], mat[3][2]);
+       
+               /* clipplane makes nice handles, calc here because of multmatrix but with translate! */
+               VECCOPY(plane, G.vd->viewinv[2]);
+               plane[3]= -0.001; // clip full circle
+               glClipPlane(GL_CLIP_PLANE0, plane);
+       
+       glRotatef( -360.0*saacos(G.vd->viewquat[0])/M_PI, G.vd->viewquat[1], G.vd->viewquat[2], G.vd->viewquat[3]);
+       VECCOPY(vec, mat[0]);
+       size= Normalise(vec);
+       if((G.f & G_PICKSEL)==0) {
+               BIF_ThemeColorShade(TH_BACK, -30);
+               drawcircball(unitmat[3], size, unitmat);
+       }               
+       /* Screen aligned view rot circle */
+       if(Gval & MAN_ROT_V) {
+               if(G.f & G_PICKSEL) glLoadName(MAN_ROT_V);
+               BIF_ThemeColor(TH_TRANSFORM);
+               drawcircball(unitmat[3], 1.2*size, unitmat);
+       }
+       glPopMatrix();
+       
+       /* apply the transform delta */
+       if(G.moving) {
+               float matt[4][4];
+               Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
+               Mat4MulMat34(matt, Trans.mat, mat);
+               mymultmatrix(matt);
+       }
+       else mymultmatrix(mat);
+       
+       /* Trackball center */
+       if(Gval & MAN_ROT_T) {
+               GLUquadricObj *qobj = gluNewQuadric(); 
+               
+               if(G.f & G_PICKSEL) glLoadName(MAN_ROT_T);
+               
+               BIF_ThemeColor(TH_TRANSFORM);
+               glBegin(GL_LINES);
+               glVertex3f(0.0, 0.0, 0.0);
+               glVertex3fv(G.vd->viewinv[2]);
+               glEnd();
+               
+               BIF_GetThemeColor3fv(TH_TRANSFORM, vec);
+               glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, vec);
+               
+               /* only has to be set here */
+               gluQuadricDrawStyle(qobj, GLU_FILL); 
+               gluQuadricNormals(qobj, GLU_SMOOTH);
+               glEnable(GL_CULL_FACE);         // backface removal
+               glEnable(GL_LIGHTING);
+               glShadeModel(GL_SMOOTH);
+               
+               glTranslatef(G.vd->viewinv[2][0], G.vd->viewinv[2][1], G.vd->viewinv[2][2]);
+               
+               gluSphere(qobj, CYWID, 8, 6);
+               
+               /* restore */
+               glDisable(GL_CULL_FACE);
+               glDisable(GL_LIGHTING);
+               glTranslatef(-G.vd->viewinv[2][0], -G.vd->viewinv[2][1], -G.vd->viewinv[2][2]);
+               
+               gluDeleteQuadric(qobj);
+       }
+               
+       glEnable(GL_CLIP_PLANE0);
+
+       /* Z circle */
+       if(Gval & MAN_ROT_Z) {
+               if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
+               manipulator_setcolor('z');
+               drawcircball(unitmat[3], 1.0, unitmat);
+       }
+       /* X circle */
+       if(Gval & MAN_ROT_X) {
+               if(G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
+               glRotatef(90.0, 0.0, 1.0, 0.0);
+               manipulator_setcolor('x');
+               drawcircball(unitmat[3], 1.0, unitmat);
+               glRotatef(-90.0, 0.0, 1.0, 0.0);
+       }       
+       /* Y circle */
+       if(Gval & MAN_ROT_Y) {
+               if(G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
+               glRotatef(-90.0, 1.0, 0.0, 0.0);
+               manipulator_setcolor('y');
+               drawcircball(unitmat[3], 1.0, unitmat);
+               glRotatef(-90.0, 1.0, 0.0, 0.0);
+       }
+       
+       glDisable(GL_CLIP_PLANE0);
+       
+       myloadmatrix(G.vd->viewmat);
+       
+       if(G.zbuf) glEnable(GL_DEPTH_TEST);             // shouldn't be global, tsk!
+}
+
+static void draw_manipulator_scale(float mat[][4])
+{
+       float cusize= CYWID*0.75;
+       
+       /* when called while moving in mixed mode, do not draw when... */
+       if((Gval & MAN_SCALE_C)==0) return;
+       
+       if(G.moving) {
+               float matt[4][4];
+               
+               Mat4CpyMat4(matt, mat); // to copy the parts outside of [3][3]
+               Mat4MulMat34(matt, Trans.mat, mat);
+               mymultmatrix(matt);
+       }
+       else mymultmatrix(mat);
+
+       /* if not shiftkey, center point as first, for selectbuffer order */
+       if(G.f & G_PICKSEL) {
+               if(!(G.qual & LR_SHIFTKEY)) {
+                       glLoadName(MAN_SCALE_C);
+                       glBegin(GL_POINTS);
+                       glVertex3f(0.0, 0.0, 0.0);
+                       glEnd();
+               }
+       }
+       else {
+               float vec[3];
+               
+               glDisable(GL_DEPTH_TEST);
+               
+               /* axis */
+               glBegin(GL_LINES);
+               if(Gval & MAN_SCALE_X) {
+                       manipulator_setcolor('x');
+                       glVertex3f(0.0, 0.0, 0.0);
+                       glVertex3f(1.0, 0.0, 0.0);
+               }               
+               if(Gval & MAN_SCALE_Y) {
+                       manipulator_setcolor('y');
+                       glVertex3f(0.0, 0.0, 0.0);
+                       glVertex3f(0.0, 1.0, 0.0);
+               }               
+               if(Gval & MAN_SCALE_Z) {
+                       manipulator_setcolor('z');
+                       glVertex3f(0.0, 0.0, 0.0);
+                       glVertex3f(0.0, 0.0, 1.0);
+               }
+               glEnd();
+               
+               /* only has to be set when not in picking */
+               glEnable(GL_CULL_FACE);         // backface removal
+               glEnable(GL_LIGHTING);
+               glShadeModel(GL_SMOOTH);
+               
+               /* center cube */
+               BIF_GetThemeColor3fv(TH_TRANSFORM, vec);
+               glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, vec);
+               
+               drawsolidcube(cusize);
+       }       
+
+       /* Z cube */
+       glTranslatef(0.0, 0.0, 1.0+cusize/2);
+       if(Gval & MAN_SCALE_Z) {
+               if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Z);
+               manipulator_setcolor('Z');
+               drawsolidcube(cusize);
+       }       
+       /* X cube */
+       glTranslatef(1.0+cusize/2, 0.0, -(1.0+cusize/2));
+       if(Gval & MAN_SCALE_X) {
+               if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_X);
+               manipulator_setcolor('X');
+               drawsolidcube(cusize);
+       }       
+       /* Y cube */
+       glTranslatef(-(1.0+cusize/2), 1.0+cusize/2, 0.0);
+       if(Gval & MAN_SCALE_Y) {
+               if(G.f & G_PICKSEL) glLoadName(MAN_SCALE_Y);
+               manipulator_setcolor('Y');
+               drawsolidcube(cusize);
+       }
+       
+       glDisable(GL_CULL_FACE);
+       glDisable(GL_LIGHTING);
+       
+       /* if shiftkey, center point as last, for selectbuffer order */
+       if(G.f & G_PICKSEL) {
+               if(G.qual & LR_SHIFTKEY) {
+                       glTranslatef(0.0, -(1.0+cusize/2), 0.0);
+                       glLoadName(MAN_SCALE_C);
+                       glBegin(GL_POINTS);
+                       glVertex3f(0.0, 0.0, 0.0);
+                       glEnd();
+               }
+       }
+       
+       myloadmatrix(G.vd->viewmat);
+       
+       if(G.zbuf) glEnable(GL_DEPTH_TEST);             // shouldn't be global, tsk!
+}
 
 static void draw_manipulator_translate(float mat[][4])
 {
        GLUquadricObj *qobj = gluNewQuadric(); 
        
+       /* when called while moving in mixed mode, do not draw when... */
+       if((Gval & MAN_TRANS_C)==0) return;
+       
        if(G.moving) glTranslatef(Trans.vec[0], Trans.vec[1], Trans.vec[2]);
        
-       glMultMatrixf(mat);
+       mymultmatrix(mat);
        
        /* if not shiftkey, center point as first, for selectbuffer order */
        if(G.f & G_PICKSEL) {
@@ -482,14 +704,17 @@ void BIF_draw_manipulator(ScrArea *sa)
        
        if(v3d->twflag & V3D_DRAW_MANIPULATOR) {
                
-               if(v3d->twmode==V3D_MANIPULATOR_TRANSLATE)
+               if(v3d->twtype & V3D_MANIPULATOR_ROTATE)
+                       draw_manipulator_rotate(v3d->twmat);
+               if(v3d->twtype & V3D_MANIPULATOR_SCALE)
+                       draw_manipulator_scale(v3d->twmat);
+               if(v3d->twtype & V3D_MANIPULATOR_TRANSLATE)
                        draw_manipulator_translate(v3d->twmat);
+               
        }
 }
 
-
-
-static int manipulator_selectbuf(ScrArea *sa)
+static int manipulator_selectbuf(ScrArea *sa, float hotspot)
 {
        View3D *v3d= sa->spacedata.first;
        rctf rect;
@@ -499,37 +724,47 @@ static int manipulator_selectbuf(ScrArea *sa)
        G.f |= G_PICKSEL;
        
        getmouseco_areawin(mval);
-       rect.xmin= mval[0]-7;
-       rect.xmax= mval[0]+7;
-       rect.ymin= mval[1]-7;
-       rect.ymax= mval[1]+7;
+       rect.xmin= mval[0]-hotspot;
+       rect.xmax= mval[0]+hotspot;
+       rect.ymin= mval[1]-hotspot;
+       rect.ymax= mval[1]+hotspot;
        
        /* get rid of overlay button matrix */
        persp(PERSP_VIEW);
        
        setwinmatrixview3d(&rect);
-       Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat);
-
-       glSelectBuffer( MAXPICKBUF, (GLuint *)buffer);
+       Mat4MulMat4(G.vd->persmat, G.vd->viewmat, sa->winmat);
+       
+       glSelectBuffer( 32, buffer);
        glRenderMode(GL_SELECT);
        glInitNames();  /* these two calls whatfor? It doesnt work otherwise */
        glPushName(-1);
        
        /* do the drawing */
-       if(v3d->twmode==V3D_MANIPULATOR_TRANSLATE)
+       if(v3d->twtype & V3D_MANIPULATOR_ROTATE)
+               draw_manipulator_rotate(v3d->twmat);
+       if(v3d->twtype & V3D_MANIPULATOR_SCALE)
+               draw_manipulator_scale(v3d->twmat);
+       if(v3d->twtype & V3D_MANIPULATOR_TRANSLATE)
                draw_manipulator_translate(v3d->twmat);
        
-       
-       glPopName();    /* see above (pushname) */
        hits= glRenderMode(GL_RENDER);
        
        G.f &= ~G_PICKSEL;
        setwinmatrixview3d(0);
-       Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat);
+       Mat4MulMat4(G.vd->persmat, G.vd->viewmat, sa->winmat);
        
        persp(PERSP_WIN);
        
-       if(hits>0) {
+       if(hits==1) return buffer[3];
+       else if(hits>1) {
+               /* we compare the two first in buffer, but exclude centers */
+               
+               if(buffer[3]==MAN_TRANS_C || buffer[3]==MAN_SCALE_C);
+               else if(buffer[4+3]==MAN_TRANS_C || buffer[4+3]==MAN_SCALE_C);
+               else {
+                       if(buffer[4+1] < buffer[1]) return buffer[4+3];
+               }
                return buffer[3];
        }
        return 0;
@@ -543,8 +778,14 @@ int BIF_do_manipulator(ScrArea *sa)
        if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return 0;
        if(!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return 0;
        
-       // find the hotspots (Gval is for draw)
-       Gval=val= manipulator_selectbuf(sa);
+       // find the hotspots (Gval is for draw). first test narrow hotspot
+       // warning, Gval is ugly global defining how it draws, don't set it before doing select calls!
+       val= manipulator_selectbuf(sa, 7.0);
+       if(val) {
+               Gval= manipulator_selectbuf(sa, 3.0);
+               if(Gval) val= Gval;
+               else Gval= val;
+       }
        
        switch(val) {
                case MAN_TRANS_C:
@@ -577,6 +818,56 @@ int BIF_do_manipulator(ScrArea *sa)
                                BIF_setSingleAxisConstraint(v3d->twmat[2]);
                        ManipulatorTransform(TFM_TRANSLATION);
                        break;
+                       
+               case MAN_SCALE_C:
+                       ManipulatorTransform(TFM_RESIZE);
+                       break;
+               case MAN_SCALE_X:
+                       if(G.qual & LR_SHIFTKEY) {
+                               Gval= MAN_SCALE_Y|MAN_SCALE_Z;
+                               BIF_setDualAxisConstraint(v3d->twmat[1], v3d->twmat[2]);
+                       }
+                       else
+                               BIF_setSingleAxisConstraint(v3d->twmat[0]);
+                       ManipulatorTransform(TFM_RESIZE);
+                       break;
+               case MAN_SCALE_Y:
+                       if(G.qual & LR_SHIFTKEY) {
+                               Gval= MAN_SCALE_X|MAN_SCALE_Z;
+                               BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[2]);
+                       }
+                       else
+                               BIF_setSingleAxisConstraint(v3d->twmat[1]);
+                       ManipulatorTransform(TFM_RESIZE);
+                       break;
+               case MAN_SCALE_Z:
+                       if(G.qual & LR_SHIFTKEY) {
+                               Gval= MAN_SCALE_X|MAN_SCALE_Y;
+                               BIF_setDualAxisConstraint(v3d->twmat[0], v3d->twmat[1]);
+                       }
+                       else
+                               BIF_setSingleAxisConstraint(v3d->twmat[2]);
+                       ManipulatorTransform(TFM_RESIZE);
+                       break;
+               
+               case MAN_ROT_X:
+                       BIF_setSingleAxisConstraint(v3d->twmat[0]);
+                       ManipulatorTransform(TFM_ROTATION);
+                       break;
+               case MAN_ROT_Y:
+                       BIF_setSingleAxisConstraint(v3d->twmat[1]);
+                       ManipulatorTransform(TFM_ROTATION);
+                       break;
+               case MAN_ROT_Z:
+                       BIF_setSingleAxisConstraint(v3d->twmat[2]);
+                       ManipulatorTransform(TFM_ROTATION);
+                       break;
+               case MAN_ROT_T:
+                       ManipulatorTransform(TFM_TRACKBALL);
+                       break;                  
+               case MAN_ROT_V:
+                       ManipulatorTransform(TFM_ROTATION);
+                       break;
        }
        
        Gval= 0xFFFF;