diff options
author | Ton Roosendaal <ton@blender.org> | 2005-03-19 15:17:06 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2005-03-19 15:17:06 +0300 |
commit | a2ed880c9ff659f7dd488076da3104beac728d4d (patch) | |
tree | 47a6edca99c0bdf9e8387862141f9d11554003cd /source/blender | |
parent | a96ed881dc04d0a2ce6ab742f7682042e466b0a7 (diff) |
Transform widgets; Scale and Rotate versions
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 |)
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 14 | ||||
-rw-r--r-- | source/blender/include/BDR_drawobject.h | 1 | ||||
-rwxr-xr-x | source/blender/include/BIF_transform.h | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_view3d_types.h | 8 | ||||
-rw-r--r-- | source/blender/src/drawobject.c | 10 | ||||
-rw-r--r-- | source/blender/src/editscreen.c | 7 | ||||
-rw-r--r-- | source/blender/src/space.c | 65 | ||||
-rwxr-xr-x | source/blender/src/transform.c | 205 | ||||
-rwxr-xr-x | source/blender/src/transform.h | 6 | ||||
-rwxr-xr-x | source/blender/src/transform_constraints.c | 8 | ||||
-rwxr-xr-x | source/blender/src/transform_generics.c | 28 | ||||
-rw-r--r-- | source/blender/src/transform_manipulator.c | 339 |
12 files changed, 621 insertions, 73 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 68bd3946e55..dcf7658ab97 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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! */ diff --git a/source/blender/include/BDR_drawobject.h b/source/blender/include/BDR_drawobject.h index a6084081336..10b6dc11c5c 100644 --- a/source/blender/include/BDR_drawobject.h +++ b/source/blender/include/BDR_drawobject.h @@ -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 diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index 7846e4d315d..d6f1db700c9 100755 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -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 diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 18e0fdf448d..19bee996a59 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -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 diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 48cdd1c4763..05968be0c4d 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -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) { diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index 5c311b594ce..572e4114c5e 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -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) ) { diff --git a/source/blender/src/space.c b/source/blender/src/space.c index b7ed74a0213..70027f34f15 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -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: diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index d0ac0c95d31..a243dd81b68 100755 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -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; } diff --git a/source/blender/src/transform.h b/source/blender/src/transform.h index 5209ec0e519..d10c066f547 100755 --- a/source/blender/src/transform.h +++ b/source/blender/src/transform.h @@ -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 diff --git a/source/blender/src/transform_constraints.c b/source/blender/src/transform_constraints.c index 54bf3dc71fe..d3c5f12260a 100755 --- a/source/blender/src/transform_constraints.c +++ b/source/blender/src/transform_constraints.c @@ -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); diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index 0df1044940c..e4872f7d651 100755 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -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 */ diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c index 98768fc8a45..b91ef64cef8 100644 --- a/source/blender/src/transform_manipulator.c +++ b/source/blender/src/transform_manipulator.c @@ -76,6 +76,7 @@ #include "BSE_edit.h" #include "BSE_view.h" +#include "BDR_drawobject.h" #include "blendef.h" #include "transform.h" @@ -95,7 +96,14 @@ #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; |