So! Finally a show-off of the *power* of Martin P's work! :)

- Made framework for 3d Transform Manipulators (widgets)
- The Manipulators act like '2d buttons', by default with LeftMouse and with
  while-hold-move-release
- Implemented now: Translation Widget, which allows:
  - four hotspots for axis grab or view-aligned grab
  - center defined by 'around' setting
  - SHIFT+LMB gives planar constraint on other 2 axes
  - works in Object mode and Edit mode (not posemode yet)

Enable it with (temporal) icon in 3D header. All other 'normal' transforms
then keeps working btw.

On the todo for this widget:
- choice for Global, Local or Normal orientation

The way the widgets are going to work is in review still. Commit is also for
Matt for his proposal/paper on topic.
Some notes regarding this project;

- no life updates (on mouse over) like 3DS, I think that's neurotic
- on click, dominant axis changes to theme defined "Transform" color, other axes disappear, like maya
- manipulater size is fixed preset, independent zoom.
- manipulator follows selection, and is located based on 'around' mode

Unresolved;

- in maya, when you select 2 or more objects, the manipulator draws on the 'active' object, also interesting
- what to do with G,R,S hotkeys? It could switch the manipulator "mode"...
- header button/menu for manipulator mode?
This commit is contained in:
2005-03-17 21:31:49 +00:00
parent ab21276aaf
commit 17bd00a851
13 changed files with 229 additions and 20 deletions

View File

@@ -33,7 +33,7 @@
#ifndef BIF_TRANSFORM_H
#define BIF_TRANSFORM_H
// #define NEWTRANSFORM 1
#define NEWTRANSFORM 1
/* ******************** Macros & Prototypes *********************** */
@@ -67,11 +67,19 @@ void Transform(int mode);
struct TransInfo;
struct ScrArea;
struct TransInfo * BIF_GetTransInfo(void);
void BIF_setSingleAxisConstraint(float vec[3]);
void BIF_setDualAxisConstraint(float vec1[3], float vec2[3]);
void BIF_drawConstraint(void);
void BIF_drawPropCircle(void);
/* view3d manipulators */
void ManipulatorTransform(int mode);
int BIF_do_manipulator(struct ScrArea *sa);
void BIF_draw_manipulator(struct ScrArea *sa);
#endif

View File

@@ -254,9 +254,10 @@ typedef struct Scene {
struct Group *group;
float cursor[3];
float twcent[3]; /* center for transform widget */
float twmin[3], twmax[3]; /* boundbox of selection for transform widget */
unsigned int lay;
short selectmode, pad;
int pad1;
void *ed;
struct Radio *radio;

View File

@@ -106,6 +106,11 @@ typedef struct View3D {
short gridlines, viewbut;
short gridflag;
short modeselect, menunr, texnr;
/* transform widget info */
short twtype, twmode, twflag, twpad;
float twmat[4][4];
} View3D;
/* View3D->flag */
@@ -142,5 +147,22 @@ 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->twmode */
#define V3D_MANIPULATOR_GLOBAL 0
#define V3D_MANIPULATOR_LOCAL 1
#define V3D_MANIPULATOR_NORMAL 2
/* View3d->twflag */
/* USE = user setting, DRAW = based on selection */
#define V3D_USE_MANIPULATOR 1
#define V3D_DRAW_MANIPULATOR 2
#define V3D_CALC_MANIPULATOR 4
#endif

View File

@@ -1624,7 +1624,7 @@ void do_material_tex(ShadeInput *shi)
warpvec[2]= mtex->warpfac*texres.nor[2];
warpdone= 1;
}
#if 0
// rotate to global coords
if(mtex->texco==TEXCO_ORCO || mtex->texco==TEXCO_UV) {
// hrms, for sphere/tube map this rotating doesn't work nice
@@ -1639,9 +1639,9 @@ void do_material_tex(ShadeInput *shi)
}
}
}
#endif
}
/* mapping */
if(mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
float tcol[3];

View File

@@ -1951,9 +1951,10 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
base= base->next;
}
if(G.scene->radio) RAD_drawall(G.vd->drawtype>=OB_SOLID);
BIF_draw_manipulator(sa);
if(G.zbuf) {
G.zbuf= FALSE;
glDisable(GL_DEPTH_TEST);

View File

@@ -105,9 +105,6 @@
#include "BIF_editarmature.h"
#endif
/* editmball.c */
extern ListBase editelems; /* go away ! */
/* from editobject */
extern void make_trans_verts(float *min, float *max, int mode);
@@ -544,6 +541,8 @@ void count_object(Object *ob, int sel)
}
/* countall does statistics */
/* is called on most actions, like select/add/delete/layermove */
void countall()
{
/* extern Lattice *editLatt; in BKE_lattice.h*/
@@ -559,9 +558,7 @@ void countall()
/* struct BodyPoint *bop; */
struct EditVert *eve;
struct EditFace *efa;
#ifdef __NLA
struct EditBone *ebo;
#endif
int a;
G.totvert= G.totvertsel= G.totfacesel= G.totface= G.totobj=
@@ -585,7 +582,6 @@ void countall()
efa= efa->next;
}
}
#ifdef __NLA
else if (G.obedit->type==OB_ARMATURE){
for (ebo=G.edbo.first;ebo;ebo=ebo->next){
@@ -619,7 +615,6 @@ void countall()
}
}
#endif
else if ELEM3(G.obedit->type, OB_CURVE, OB_SURF, OB_FONT) {
nu= editNurb.first;
while(nu) {
@@ -647,6 +642,9 @@ void countall()
}
}
else if(G.obedit->type==OB_MBALL) {
/* editmball.c */
extern ListBase editelems; /* go away ! */
ml= editelems.first;
while(ml) {
G.totvert++;

View File

@@ -3712,6 +3712,7 @@ void do_view3d_buttons(short event)
break;
case B_AROUND:
handle_view3d_around(); // copies to other 3d windows
allqueue(REDRAWVIEW3D, 1);
break;
case B_SEL_VERT:
@@ -3963,6 +3964,11 @@ void view3d_buttons(void)
xco+= XIC+8;
uiDefIconButS(block, TOG|BIT|0, B_REDR, ICON_OBJECT,
xco,0,XIC,YIC,
&G.vd->twflag, 0, 0, 0, 0, "Use 3d transform widgets");
xco+= XIC+8;
/* LAYERS */
if(G.vd->localview==0) {

View File

@@ -494,6 +494,7 @@ int std_libbuttons(uiBlock *block, short xco, short yco,
static void do_update_for_newframe(int mute)
{
extern void audiostream_scrub(unsigned int frame); /* seqaudio.c */
ScrArea *sa;
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWACTION,0);
@@ -522,6 +523,16 @@ static void do_update_for_newframe(int mute)
test_all_displists();
/* manipulators like updates too */
for(sa=G.curscreen->areabase.first; sa; sa=sa->next) {
if(sa->spacetype==SPACE_VIEW3D) {
View3D *v3d= sa->spacedata.first;
if(v3d->twflag & V3D_USE_MANIPULATOR) break;
else break; // for now
}
}
if(sa) countall(); // does manipulator centers
if ( (CFRA>1) && (!mute) && (G.scene->audio.flag & AUDIO_SCRUB)) audiostream_scrub( CFRA );
}

View File

@@ -734,6 +734,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if(event==UI_BUT_EVENT) do_butspace(val); // temporal, view3d deserves own queue?
/* we consider manupilator a button, defaulting to leftmouse */
if(event==LEFTMOUSE) if(BIF_do_manipulator(sa)) return;
/* swap mouse buttons based on user preference */
if (U.flag & USER_LMOUSESELECT) {
if (event==LEFTMOUSE) event = RIGHTMOUSE;

View File

@@ -1564,6 +1564,134 @@ void Transform(int mode)
scrarea_queue_headredraw(curarea);
}
static void draw_nothing(TransInfo *t) {}
void ManipulatorTransform(int mode)
{
int ret_val = 0;
short pmval[2] = {0, 0}, mval[2], val;
unsigned short event;
/* stupid PET initialisation code */
/* START */
if (Trans.propsize == 0.0f) {
Trans.propsize = 1.0;
}
/* END */
initTransModeFlags(&Trans, mode); // modal settings in struct Trans
initTrans(&Trans); // internal data, mouse, vectors
createTransData(&Trans); // make TransData structs from selection
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;
calculatePropRatio(&Trans);
calculateCenter(&Trans);
switch (mode) {
case TFM_TRANSLATION:
initTranslation(&Trans);
break;
case TFM_ROTATION:
initRotation(&Trans);
break;
case TFM_RESIZE:
initResize(&Trans);
break;
}
Trans.redraw = 1;
while (ret_val == 0) {
getmouseco_areawin(mval);
if (mval[0] != pmval[0] || mval[1] != pmval[1]) {
Trans.redraw = 1;
}
if (Trans.redraw) {
pmval[0] = mval[0];
pmval[1] = mval[1];
//selectConstraint(&Trans); needed?
if (Trans.transform) {
Trans.transform(&Trans, mval);
}
Trans.redraw = 0;
}
/* essential for idling subloop */
if( qtest()==0) PIL_sleep_ms(2);
while( qtest() ) {
event= extern_qread(&val);
switch (event){
/* enforce redraw of transform when modifiers are used */
case LEFTCTRLKEY:
case RIGHTCTRLKEY:
case LEFTSHIFTKEY:
case RIGHTSHIFTKEY:
Trans.redraw = 1;
break;
case ESCKEY:
case RIGHTMOUSE:
ret_val = TRANS_CANCEL;
break;
case LEFTMOUSE:
case SPACEKEY:
case PADENTER:
case RETKEY:
ret_val = TRANS_CONFIRM;
break;
}
}
}
if(ret_val == TRANS_CANCEL) {
restoreTransObjects(&Trans);
}
else {
BIF_undo_push("Transform");
}
/* free data, reset vars */
postTrans(&Trans);
/* mess from old transform, just for now (ton) */
{
char cmode='g';
if(mode==TFM_RESIZE) cmode= 's';
else if(mode==TFM_ROTATION) cmode= 'r';
/* aftertrans does displists, ipos and action channels */
/* 7 = keyflags, meaning do loc/rot/scale ipos. Not sure if I like the old method to detect what changed (ton) */
special_aftertrans_update(cmode, 0, (short)(ret_val == TRANS_CANCEL), 7);
if(G.obedit==NULL && G.obpose==NULL)
clear_trans_object_base_flags();
}
/* send events out for redraws */
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSOBJECT, 0);
scrarea_queue_headredraw(curarea);
}
/* ************************** WRAP *************************** */
/* warp is done fully in view space */
@@ -2294,26 +2422,27 @@ static void applyTranslation(TransInfo *t, float vec[3]) {
}
}
/* uses t->vec to store actual translation in */
int Translation(TransInfo *t, short mval[2])
{
float vec[3], tvec[3];
float tvec[3];
char str[200];
window_to_3d(vec, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
window_to_3d(t->vec, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
if (t->con.mode & CON_APPLY) {
float pvec[3] = {0.0f, 0.0f, 0.0f};
t->con.applyVec(t, NULL, vec, tvec, pvec);
VECCOPY(vec, tvec);
t->con.applyVec(t, NULL, t->vec, tvec, pvec);
VECCOPY(t->vec, tvec);
headerTranslation(t, pvec, str);
}
else {
snapGrid(t, vec);
applyNumInput(&t->num, vec);
headerTranslation(t, vec, str);
snapGrid(t, t->vec);
applyNumInput(&t->num, t->vec);
headerTranslation(t, t->vec, str);
}
applyTranslation(t, vec);
applyTranslation(t, t->vec);
recalcData(t);

View File

@@ -125,6 +125,9 @@ typedef struct TransInfo {
NumInput num; /* numerical input */
float val; /* init value for some transformations */
float fac; /* factor for distance based transform */
float vec[3]; /* translation, to show for widget */
float mat[3][3]; /* rot/rescale, to show for widget */
} TransInfo;

View File

@@ -580,6 +580,7 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]) {
void BIF_setSingleAxisConstraint(float vec[3]) {
TransInfo *t = BIF_GetTransInfo();
float space[3][3], v[3];
VECCOPY(space[0], vec);
v[0] = vec[2];
@@ -600,6 +601,26 @@ void BIF_setSingleAxisConstraint(float vec[3]) {
t->redraw = 1;
}
void BIF_setDualAxisConstraint(float vec1[3], float vec2[3]) {
TransInfo *t = BIF_GetTransInfo();
float space[3][3];
VECCOPY(space[0], vec1);
VECCOPY(space[1], vec2);
Crossf(space[2], space[0], space[1]);
Mat3CpyMat3(t->con.mtx, space);
t->con.mode = (CON_AXIS0|CON_AXIS1|CON_APPLY);
getConstraintMatrix(t);
t->con.drawExtra = NULL;
t->con.applyVec = applyAxisConstraintVec;
t->con.applySize = applyAxisConstraintSize;
t->con.applyRot = applyAxisConstraintRot;
t->redraw = 1;
}
void BIF_drawConstraint(void)
{
TransInfo *t = BIF_GetTransInfo();

View File

@@ -370,6 +370,12 @@ void initTrans (TransInfo *t)
t->num.val[0] =
t->num.val[1] =
t->num.val[2] = 0.0f;
t->vec[0] =
t->vec[1] =
t->vec[2] = 0.0f;
Mat3One(t->mat);
}
/* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */