=== 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.
This commit is contained in:
Martin Poirier 2008-01-20 22:43:48 +00:00
parent 32c4bbbcc5
commit 3d7271f059
5 changed files with 107 additions and 21 deletions

@ -265,18 +265,19 @@ typedef struct TransInfo {
/* transdata->flag */ /* transdata->flag */
#define TD_SELECTED 1 #define TD_SELECTED 1
#define TD_NOACTION 2 #define TD_ACTIVE (1 << 1)
#define TD_USEQUAT 4 #define TD_NOACTION (1 << 2)
#define TD_NOTCONNECTED 8 #define TD_USEQUAT (1 << 3)
#define TD_SINGLESIZE 16 /* used for scaling of MetaElem->rad */ #define TD_NOTCONNECTED (1 << 4)
#define TD_SINGLESIZE (1 << 5) /* used for scaling of MetaElem->rad */
#ifdef WITH_VERSE #ifdef WITH_VERSE
#define TD_VERSE_OBJECT 32 #define TD_VERSE_OBJECT (1 << 6)
#define TD_VERSE_VERT 64 #define TD_VERSE_VERT (1 << 7)
#endif #endif
#define TD_TIMEONLY 128 #define TD_TIMEONLY (1 << 8)
#define TD_NOCENTER 256 #define TD_NOCENTER (1 << 9)
#define TD_NO_EXT 512 /* ext abused for particle key timing */ #define TD_NO_EXT (1 << 10) /* ext abused for particle key timing */
#define TD_SKIP 1024 /* don't transform this data */ #define TD_SKIP (1 << 11) /* don't transform this data */
/* transsnap->status */ /* transsnap->status */
#define SNAP_ON 1 #define SNAP_ON 1
@ -291,6 +292,7 @@ typedef struct TransInfo {
#define SNAP_CLOSEST 0 #define SNAP_CLOSEST 0
#define SNAP_CENTER 1 #define SNAP_CENTER 1
#define SNAP_MEDIAN 2 #define SNAP_MEDIAN 2
#define SNAP_ACTIVE 3
void checkFirstTime(void); void checkFirstTime(void);

@ -663,6 +663,7 @@ typedef struct Scene {
#define SCE_SNAP_TARGET_CLOSEST 0 #define SCE_SNAP_TARGET_CLOSEST 0
#define SCE_SNAP_TARGET_CENTER 1 #define SCE_SNAP_TARGET_CENTER 1
#define SCE_SNAP_TARGET_MEDIAN 2 #define SCE_SNAP_TARGET_MEDIAN 2
#define SCE_SNAP_TARGET_ACTIVE 3
/* sce->selectmode */ /* sce->selectmode */
#define SCE_SELECT_VERTEX 1 /* for mesh */ #define SCE_SELECT_VERTEX 1 /* for mesh */

@ -1768,6 +1768,9 @@ static void do_view3d_transformmenu(void *arg, int event)
case 19: case 19:
G.scene->snap_target = SCE_SNAP_TARGET_MEDIAN; G.scene->snap_target = SCE_SNAP_TARGET_MEDIAN;
break; break;
case 20:
G.scene->snap_target = SCE_SNAP_TARGET_ACTIVE;
break;
} }
allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWVIEW3D, 0);
} }
@ -1839,19 +1842,28 @@ static uiBlock *view3d_transformmenu(void *arg_unused)
switch(G.scene->snap_target) switch(G.scene->snap_target)
{ {
case SCE_SNAP_TARGET_CLOSEST: 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 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 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; break;
case SCE_SNAP_TARGET_CENTER: 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_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 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; break;
case SCE_SNAP_TARGET_MEDIAN: 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 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 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; break;
} }
} }
@ -5484,7 +5496,7 @@ void view3d_buttons(void)
if (G.scene->snap_flag & SCE_SNAP) { 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)"); 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; 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; xco+= 70;
} else { } 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)"); 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)");

@ -1952,6 +1952,7 @@ static void createTransEditVerts(TransInfo *t)
EditMesh *em = G.editMesh; EditMesh *em = G.editMesh;
EditVert *eve; EditVert *eve;
EditVert **nears = NULL; EditVert **nears = NULL;
EditVert *eve_act = NULL;
float *vectors = NULL, *mappedcos = NULL, *quats= NULL; float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
int count=0, countsel=0, a, totleft; 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 */ /* note: in prop mode we need at least 1 selected */
if (countsel==0) return; 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) { if(propmode) {
t->total = count; t->total = count;
@ -2057,8 +2067,13 @@ static void createTransEditVerts(TransInfo *t)
if(eve->h==0) { if(eve->h==0) {
if(propmode || eve->f1) { if(propmode || eve->f1) {
VertsToTransData(tob, eve); VertsToTransData(tob, eve);
/* selected */
if(eve->f1) tob->flag |= TD_SELECTED; if(eve->f1) tob->flag |= TD_SELECTED;
/* active */
if(eve == eve_act) tob->flag |= TD_ACTIVE;
if(propmode) { if(propmode) {
if (eve->f2) { if (eve->f2) {
float vec[3]; float vec[3];
@ -2883,6 +2898,13 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
Mat3One(td->smtx); Mat3One(td->smtx);
Mat3One(td->mtx); Mat3One(td->mtx);
} }
/* set active flag */
if (BASACT && BASACT->object == ob)
{
td->flag |= TD_ACTIVE;
}
#ifdef WITH_VERSE #ifdef WITH_VERSE
if(ob->vnode) { if(ob->vnode) {
td->verse = (void*)ob; td->verse = (void*)ob;

@ -85,12 +85,15 @@ void CalcSnapGeometry(TransInfo *t, float *vec);
void TargetSnapMedian(TransInfo *t); void TargetSnapMedian(TransInfo *t);
void TargetSnapCenter(TransInfo *t); void TargetSnapCenter(TransInfo *t);
void TargetSnapClosest(TransInfo *t); void TargetSnapClosest(TransInfo *t);
void TargetSnapActive(TransInfo *t);
float RotationBetween(TransInfo *t, float p1[3], float p2[3]); float RotationBetween(TransInfo *t, float p1[3], float p2[3]);
float TranslationBetween(TransInfo *t, float p1[3], float p2[3]); float TranslationBetween(TransInfo *t, float p1[3], float p2[3]);
// Trickery /* Modes */
int findNearestVertFromObjects(int *dist, float *loc, int selected); #define NOT_SELECTED 0
#define NOT_ACTIVE 1
int findNearestVertFromObjects(int *dist, float *loc, int mode);
/****************** IMPLEMENTATIONS *********************/ /****************** IMPLEMENTATIONS *********************/
@ -277,6 +280,11 @@ void setSnappingCallback(TransInfo *t)
t->tsnap.modeTarget = SNAP_MEDIAN; t->tsnap.modeTarget = SNAP_MEDIAN;
t->tsnap.targetSnap = TargetSnapMedian; t->tsnap.targetSnap = TargetSnapMedian;
break; break;
case SCE_SNAP_TARGET_ACTIVE:
t->tsnap.modeTarget = SNAP_ACTIVE;
t->tsnap.targetSnap = TargetSnapActive;
break;
} }
switch (t->mode) switch (t->mode)
@ -391,6 +399,7 @@ void CalcSnapGrid(TransInfo *t, float *vec)
void CalcSnapGeometry(TransInfo *t, float *vec) void CalcSnapGeometry(TransInfo *t, float *vec)
{ {
/* Object mode */
if (G.obedit == NULL) if (G.obedit == NULL)
{ {
if (t->spacetype == SPACE_VIEW3D) if (t->spacetype == SPACE_VIEW3D)
@ -399,7 +408,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
int found = 0; int found = 0;
int dist = 40; // Use a user defined value here int dist = 40; // Use a user defined value here
found = findNearestVertFromObjects(&dist, vec, 0); found = findNearestVertFromObjects(&dist, vec, NOT_SELECTED);
if (found == 1) if (found == 1)
{ {
VECCOPY(t->tsnap.snapPoint, vec); 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) else if (G.obedit != NULL && G.obedit->type==OB_MESH)
{ {
/*if (G.scene->selectmode & B_SEL_VERT)*/ /*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 // use findnearestverts in vert mode, others in other modes
nearest = findnearestvert(&dist, SELECT, 1); nearest = findnearestvert(&dist, SELECT, 1);
found = findNearestVertFromObjects(&dist, vec, SELECT); found = findNearestVertFromObjects(&dist, vec, NOT_ACTIVE);
if (found == 1) if (found == 1)
{ {
VECCOPY(t->tsnap.snapPoint, vec); 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) void TargetSnapMedian(TransInfo *t)
{ {
// Only need to calculate once // 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; Base *base;
int retval = 0; int retval = 0;
short mval[2]; short mval[2];
@ -637,7 +686,7 @@ int findNearestVertFromObjects(int *dist, float *loc, int selected) {
base= FIRSTBASE; base= FIRSTBASE;
for ( base = FIRSTBASE; base != NULL; base = base->next ) { 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; Object *ob = base->object;
if (ob->type == OB_MESH) { if (ob->type == OB_MESH) {