diff options
-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) { |