From 450b3664e1592a2b17491b6b229d8e6808ac8ee4 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Thu, 24 Jan 2008 20:11:54 +0000 Subject: [PATCH] === Mirror Tool === Making the mirror tool axis selection interactive instead of using a popmenu. Mirror is now just a constant -1 scaling transform, which enables you to choose the mirror axis through hotkeys (x,y,z) and with MMB. It also means it's easier to select the correct axis if you're not sure which is which and gives access to all the orientation supported in transform (including custom user orientations). Mesh and Object header menus still have the individual axis as options but have an added "Interactive Mirror" which just enters transform and lets user pick the axis there. Ctrl-M enters "Interactive Mirror" too. In a nutshell, this changes adds more possible mirroring axis and unifies the mirror axis selection process with transform constraint axis selection. --- source/blender/include/BIF_transform.h | 2 +- source/blender/include/transform.h | 3 + source/blender/src/editobject.c | 12 +- source/blender/src/header_view3d.c | 81 +++++++++--- source/blender/src/transform.c | 169 ++++++++++++------------- 5 files changed, 147 insertions(+), 120 deletions(-) diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index c8e2a4832ab..a0f991f2631 100644 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -68,10 +68,10 @@ #define CTX_NO_PET 4 #define CTX_TWEAK 8 #define CTX_NO_MIRROR 16 +#define CTX_AUTOCONFIRM 32 void initTransform(int mode, int context); void Transform(void); -void Mirror(short mode); /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 30b9bbf3f51..48e840a7128 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -363,6 +363,9 @@ int TimeScale(TransInfo *t, short mval[2]); void initBakeTime(TransInfo *t); int BakeTime(TransInfo *t, short mval[2]); +void initMirror(TransInfo *t); +int Mirror(TransInfo *t, short mval[2]); + /*********************** transform_conversions.c ********** */ struct ListBase; void flushTransIpoData(TransInfo *t); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 90b0e8c048e..2e96ea464fa 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -5574,17 +5574,9 @@ void mirrormenu(void) if(G.f & G_PARTICLEEDIT) { PE_mirror_x(0); } - else if (G.obedit==0) { - mode=pupmenu("Mirror Axis %t|X Local%x4|Y Local%x5|Z Local%x6|"); - - if (mode==-1) return; /* return */ - Mirror(mode); /* separating functionality from interface | call*/ - } else { - mode=pupmenu("Mirror Axis %t|X Global%x1|Y Global%x2|Z Global%x3|%l|X Local%x4|Y Local%x5|Z Local%x6|%l|X View%x7|Y View%x8|Z View%x9|"); - - if (mode==-1) return; /* return */ - Mirror(mode); /* separating functionality from interface | call*/ + initTransform(TFM_MIRROR, CTX_NO_PET); + Transform(); } } diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index f7cf9dd22cd..4cbad8a9758 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -1881,10 +1881,24 @@ static uiBlock *view3d_transformmenu(void *arg_unused) void do_view3d_object_mirrormenu(void *arg, int event) { switch(event) { + case 0: + initTransform(TFM_MIRROR, CTX_NO_PET); + Transform(); + break; case 1: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('X', " on X axis"); + Transform(); + break; case 2: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('Y', " on Y axis"); + Transform(); + break; case 3: - Mirror(event + 3); /* + 3 because the first three modes are global*/ + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('Z', " on Z axis"); + Transform(); break; } allqueue(REDRAWVIEW3D, 0); @@ -1898,9 +1912,11 @@ static uiBlock *view3d_object_mirrormenu(void *arg_unused) block= uiNewBlock(&curarea->uiblocks, "view3d_object_mirrormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); uiBlockSetButmFunc(block, do_view3d_object_mirrormenu, NULL); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Interactive Mirror|Ctrl M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); @@ -2853,17 +2869,44 @@ static uiBlock *view3d_edit_mesh_normalsmenu(void *arg_unused) void do_view3d_edit_mirrormenu(void *arg, int event) { + float mat[3][3]; + + Mat3One(mat); + switch(event) { + case 0: + initTransform(TFM_MIRROR, CTX_NO_PET); + Transform(); + break; case 1: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setSingleAxisConstraint(mat[0], " on global X axis"); + Transform(); + break; case 2: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setSingleAxisConstraint(mat[1], " on global Y axis"); + Transform(); + break; case 3: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setSingleAxisConstraint(mat[2], "on global Z axis"); + Transform(); + break; case 4: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('X', " on local X axis"); + Transform(); + break; case 5: + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('Y', " on local Y axis"); + Transform(); + break; case 6: - case 7: - case 8: - case 9: - Mirror(event); + initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM); + BIF_setLocalAxisConstraint('Z', " on local Z axis"); + Transform(); break; } allqueue(REDRAWVIEW3D, 0); @@ -2877,21 +2920,19 @@ static uiBlock *view3d_edit_mirrormenu(void *arg_unused) block= uiNewBlock(&curarea->uiblocks, "view3d_edit_mirrormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); uiBlockSetButmFunc(block, do_view3d_edit_mirrormenu, NULL); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|Ctrl M, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|Ctrl M, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|Ctrl M, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Interactive Mirror|Ctrl M", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|Ctrl M, X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|Ctrl M, Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|Ctrl M, Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X View|Ctrl M, 7", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y View|Ctrl M, 8", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z View|Ctrl M, 9", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, X X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, Y Y", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, Z Z", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index bbb5e514942..498b546ba57 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -888,6 +888,8 @@ static char *transform_to_undostr(TransInfo *t) return "Time Slide"; case TFM_BAKE_TIME: return "Key Time"; + case TFM_MIRROR: + return "Mirror"; } return "Transform"; } @@ -1323,6 +1325,9 @@ void initTransform(int mode, int context) { case TFM_BAKE_TIME: initBakeTime(&Trans); break; + case TFM_MIRROR: + initMirror(&Trans); + break; } } @@ -1359,6 +1364,13 @@ void Transform() } Trans.redraw = 0; } + + /* If auto confirm is on, break after one pass */ + if (Trans.context & CTX_AUTOCONFIRM) + { + Trans.state = TRANS_CONFIRM; + break; + } /* essential for idling subloop */ if( qtest()==0) PIL_sleep_ms(2); @@ -4033,105 +4045,84 @@ int BakeTime(TransInfo *t, short mval[2]) return 1; } - /* ************************** MIRROR *************************** */ -void Mirror(short mode) +void initMirror(TransInfo *t) +{ + t->flag |= T_NULL_ONE; + if (!G.obedit) { + t->flag |= T_NO_ZERO; + } + + t->transform = Mirror; + t->fac = 0.1f; +} + +int Mirror(TransInfo *t, short mval[2]) { TransData *td; - float mati[3][3], matview[3][3], mat[3][3]; - float size[3]; + float size[3], mat[3][3]; int i; + char str[200]; - Trans.context = CTX_NO_PET; + /* + * OPTIMISATION: + * This still recalcs transformation on mouse move + * while it should only recalc on constraint change + * */ - initTrans(&Trans); // internal data, mouse, vectors - - Mat3One(mati); - Mat3CpyMat4(matview, Trans.viewinv); // t->viewinv was set in initTrans - Mat3Ortho(matview); - - createTransData(&Trans); // make TransData structs from selection - - calculatePropRatio(&Trans); - calculateCenter(&Trans); - - initResize(&Trans); - - if (Trans.total == 0) { - postTrans(&Trans); - return; - } - - size[0] = size[1] = size[2] = 1.0f; - td = Trans.data; - - switch (mode) { - case 1: - size[0] = -1.0f; - setConstraint(&Trans, mati, (CON_AXIS0), ""); - break; - case 2: - size[1] = -1.0f; - setConstraint(&Trans, mati, (CON_AXIS1), ""); - break; - case 3: - size[2] = -1.0f; - setConstraint(&Trans, mati, (CON_AXIS2), ""); - break; - case 4: - size[0] = -1.0f; - setLocalConstraint(&Trans, (CON_AXIS0), ""); - break; - case 5: - size[1] = -1.0f; - setLocalConstraint(&Trans, (CON_AXIS1), ""); - break; - case 6: - size[2] = -1.0f; - setLocalConstraint(&Trans, (CON_AXIS2), ""); - break; - case 7: - size[0] = -1.0f; - setConstraint(&Trans, matview, (CON_AXIS0), ""); - break; - case 8: - size[1] = -1.0f; - setConstraint(&Trans, matview, (CON_AXIS1), ""); - break; - case 9: - size[2] = -1.0f; - setConstraint(&Trans, matview, (CON_AXIS2), ""); - break; - default: - return; - } - - SizeToMat3(size, mat); - - if (Trans.con.applySize) { - Trans.con.applySize(&Trans, NULL, mat); - } - - for(i = 0 ; i < Trans.total; i++, td++) { - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; + /* if an axis has been selected */ + if (t->con.mode & CON_APPLY) { + if (t->con.applySize) { + t->con.applySize(t, NULL, mat); + } - ElementResize(&Trans, td, mat); + sprintf(str, "Mirror%s", t->con.text); + + size[0] = size[1] = size[2] = -1; + + SizeToMat3(size, mat); + + for(i = 0, td=t->data; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + ElementResize(t, td, mat); + } + + recalcData(t); + + headerprint(str); + + viewRedrawForce(t); + } + else + { + size[0] = size[1] = size[2] = 1; + + SizeToMat3(size, mat); + + for(i = 0, td=t->data; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + ElementResize(t, td, mat); + } + + recalcData(t); + + headerprint("Select a mirror axis (X, Y, Z)"); + + viewRedrawForce(t); } - recalcData(&Trans); - - BIF_undo_push("Mirror"); - - /* free data, reset vars */ - postTrans(&Trans); - - /* send events out for redraws */ - viewRedrawPost(&Trans); + return 1; } /* ************************** ANIM EDITORS - TRANSFORM TOOLS *************************** */