diff options
author | Martin Poirier <theeth@yahoo.com> | 2008-01-21 01:43:48 +0300 |
---|---|---|
committer | Martin Poirier <theeth@yahoo.com> | 2008-01-21 01:43:48 +0300 |
commit | 3d7271f059d5cb5c6f2c7adfaec8d35858485da1 (patch) | |
tree | d2018f243ef4bb2dd2f651e574c60d02489a7072 /source/blender | |
parent | 32c4bbbcc5d7a8048ec252eda49a408783f03bea (diff) |
=== Transform Snap ===
Snapping Mode: Active
With this mode, the active element (at this time, object or vertice) is used as snapping target. If there is no active element in the selection, it reverts back to median mode.
Edit Mode snapping, other meshes no longer have to be selected to act as snapping point.
Fix a potential bug with snapping point from other meshes.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/include/transform.h | 22 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 1 | ||||
-rw-r--r-- | source/blender/src/header_view3d.c | 20 | ||||
-rw-r--r-- | source/blender/src/transform_conversions.c | 24 | ||||
-rw-r--r-- | source/blender/src/transform_snap.c | 61 |
5 files changed, 107 insertions, 21 deletions
diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index e9e82612721..30b9bbf3f51 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -265,18 +265,19 @@ typedef struct TransInfo { /* transdata->flag */ #define TD_SELECTED 1 -#define TD_NOACTION 2 -#define TD_USEQUAT 4 -#define TD_NOTCONNECTED 8 -#define TD_SINGLESIZE 16 /* used for scaling of MetaElem->rad */ +#define TD_ACTIVE (1 << 1) +#define TD_NOACTION (1 << 2) +#define TD_USEQUAT (1 << 3) +#define TD_NOTCONNECTED (1 << 4) +#define TD_SINGLESIZE (1 << 5) /* used for scaling of MetaElem->rad */ #ifdef WITH_VERSE - #define TD_VERSE_OBJECT 32 - #define TD_VERSE_VERT 64 + #define TD_VERSE_OBJECT (1 << 6) + #define TD_VERSE_VERT (1 << 7) #endif -#define TD_TIMEONLY 128 -#define TD_NOCENTER 256 -#define TD_NO_EXT 512 /* ext abused for particle key timing */ -#define TD_SKIP 1024 /* don't transform this data */ +#define TD_TIMEONLY (1 << 8) +#define TD_NOCENTER (1 << 9) +#define TD_NO_EXT (1 << 10) /* ext abused for particle key timing */ +#define TD_SKIP (1 << 11) /* don't transform this data */ /* transsnap->status */ #define SNAP_ON 1 @@ -291,6 +292,7 @@ typedef struct TransInfo { #define SNAP_CLOSEST 0 #define SNAP_CENTER 1 #define SNAP_MEDIAN 2 +#define SNAP_ACTIVE 3 void checkFirstTime(void); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 200e904bc88..b342bc5afe8 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -663,6 +663,7 @@ typedef struct Scene { #define SCE_SNAP_TARGET_CLOSEST 0 #define SCE_SNAP_TARGET_CENTER 1 #define SCE_SNAP_TARGET_MEDIAN 2 +#define SCE_SNAP_TARGET_ACTIVE 3 /* sce->selectmode */ #define SCE_SELECT_VERTEX 1 /* for mesh */ diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index b476bb6c944..1c39d286989 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -1768,6 +1768,9 @@ static void do_view3d_transformmenu(void *arg, int event) case 19: G.scene->snap_target = SCE_SNAP_TARGET_MEDIAN; break; + case 20: + G.scene->snap_target = SCE_SNAP_TARGET_ACTIVE; + break; } allqueue(REDRAWVIEW3D, 0); } @@ -1839,19 +1842,28 @@ static uiBlock *view3d_transformmenu(void *arg_unused) switch(G.scene->snap_target) { case SCE_SNAP_TARGET_CLOSEST: - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); break; case SCE_SNAP_TARGET_CENTER: uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); break; case SCE_SNAP_TARGET_MEDIAN: uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); + break; + case SCE_SNAP_TARGET_ACTIVE: + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Closest", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Center", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Snap Median", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Active", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); break; } } @@ -5484,7 +5496,7 @@ void view3d_buttons(void) if (G.scene->snap_flag & SCE_SNAP) { uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,0,XIC,YIC, &G.scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab)"); xco+= XIC; - uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,0,70,YIC, &G.scene->snap_target, 0, 0, 0, 0, "Snap Target Mode"); + uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,0,70,YIC, &G.scene->snap_target, 0, 0, 0, 0, "Snap Target Mode"); xco+= 70; } else { uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,0,XIC,YIC, &G.scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)"); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 3f69316e373..de3e9988f8d 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -1952,6 +1952,7 @@ static void createTransEditVerts(TransInfo *t) EditMesh *em = G.editMesh; EditVert *eve; EditVert **nears = NULL; + EditVert *eve_act = NULL; float *vectors = NULL, *mappedcos = NULL, *quats= NULL; float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; int count=0, countsel=0, a, totleft; @@ -2002,6 +2003,15 @@ static void createTransEditVerts(TransInfo *t) /* note: in prop mode we need at least 1 selected */ if (countsel==0) return; + /* check active */ + if (G.editMesh->selected.last) { + EditSelection *ese = G.editMesh->selected.last; + if ( ese->type == EDITVERT ) { + eve_act = (EditVert *)ese->data; + } + } + + if(propmode) { t->total = count; @@ -2057,8 +2067,13 @@ static void createTransEditVerts(TransInfo *t) if(eve->h==0) { if(propmode || eve->f1) { VertsToTransData(tob, eve); - + + /* selected */ if(eve->f1) tob->flag |= TD_SELECTED; + + /* active */ + if(eve == eve_act) tob->flag |= TD_ACTIVE; + if(propmode) { if (eve->f2) { float vec[3]; @@ -2883,6 +2898,13 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) Mat3One(td->smtx); Mat3One(td->mtx); } + + /* set active flag */ + if (BASACT && BASACT->object == ob) + { + td->flag |= TD_ACTIVE; + } + #ifdef WITH_VERSE if(ob->vnode) { td->verse = (void*)ob; diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 3279e6e6f09..c0f634a3f67 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -85,12 +85,15 @@ void CalcSnapGeometry(TransInfo *t, float *vec); void TargetSnapMedian(TransInfo *t); void TargetSnapCenter(TransInfo *t); void TargetSnapClosest(TransInfo *t); +void TargetSnapActive(TransInfo *t); float RotationBetween(TransInfo *t, float p1[3], float p2[3]); float TranslationBetween(TransInfo *t, float p1[3], float p2[3]); -// Trickery -int findNearestVertFromObjects(int *dist, float *loc, int selected); +/* Modes */ +#define NOT_SELECTED 0 +#define NOT_ACTIVE 1 +int findNearestVertFromObjects(int *dist, float *loc, int mode); /****************** IMPLEMENTATIONS *********************/ @@ -277,6 +280,11 @@ void setSnappingCallback(TransInfo *t) t->tsnap.modeTarget = SNAP_MEDIAN; t->tsnap.targetSnap = TargetSnapMedian; break; + case SCE_SNAP_TARGET_ACTIVE: + t->tsnap.modeTarget = SNAP_ACTIVE; + t->tsnap.targetSnap = TargetSnapActive; + break; + } switch (t->mode) @@ -391,6 +399,7 @@ void CalcSnapGrid(TransInfo *t, float *vec) void CalcSnapGeometry(TransInfo *t, float *vec) { + /* Object mode */ if (G.obedit == NULL) { if (t->spacetype == SPACE_VIEW3D) @@ -399,7 +408,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec) int found = 0; int dist = 40; // Use a user defined value here - found = findNearestVertFromObjects(&dist, vec, 0); + found = findNearestVertFromObjects(&dist, vec, NOT_SELECTED); if (found == 1) { VECCOPY(t->tsnap.snapPoint, vec); @@ -412,6 +421,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec) } } } + /* Mesh edit mode */ else if (G.obedit != NULL && G.obedit->type==OB_MESH) { /*if (G.scene->selectmode & B_SEL_VERT)*/ @@ -426,7 +436,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec) // use findnearestverts in vert mode, others in other modes nearest = findnearestvert(&dist, SELECT, 1); - found = findNearestVertFromObjects(&dist, vec, SELECT); + found = findNearestVertFromObjects(&dist, vec, NOT_ACTIVE); if (found == 1) { VECCOPY(t->tsnap.snapPoint, vec); @@ -513,6 +523,45 @@ void TargetSnapCenter(TransInfo *t) } } +void TargetSnapActive(TransInfo *t) +{ + // Only need to calculate once + if ((t->tsnap.status & TARGET_INIT) == 0) + { + TransData *td = NULL; + TransData *active_td = NULL; + int i; + + for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) + { + if (td->flag & TD_ACTIVE) + { + active_td = td; + break; + } + } + + if (active_td) + { + VECCOPY(t->tsnap.snapTarget, active_td->center); + + if(t->flag & (T_EDIT|T_POSE)) { + Object *ob= G.obedit?G.obedit:t->poseobj; + Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); + } + + t->tsnap.status |= TARGET_INIT; + } + /* No active, default to median */ + else + { + t->tsnap.modeTarget = SNAP_MEDIAN; + t->tsnap.targetSnap = TargetSnapMedian; + TargetSnapMedian(t); + } + } +} + void TargetSnapMedian(TransInfo *t) { // Only need to calculate once @@ -628,7 +677,7 @@ void TargetSnapClosest(TransInfo *t) } /*================================================================*/ -int findNearestVertFromObjects(int *dist, float *loc, int selected) { +int findNearestVertFromObjects(int *dist, float *loc, int mode) { Base *base; int retval = 0; short mval[2]; @@ -637,7 +686,7 @@ int findNearestVertFromObjects(int *dist, float *loc, int selected) { base= FIRSTBASE; for ( base = FIRSTBASE; base != NULL; base = base->next ) { - if ( base != BASACT && BASE_SELECTABLE(base) && (base->flag & SELECT) == selected ) { + if ( BASE_SELECTABLE(base) && ((mode == NOT_SELECTED && (base->flag & SELECT) == 0) || (mode == NOT_ACTIVE && base != BASACT)) ) { Object *ob = base->object; if (ob->type == OB_MESH) { |