diff options
author | Martin Poirier <theeth@yahoo.com> | 2008-01-14 01:20:18 +0300 |
---|---|---|
committer | Martin Poirier <theeth@yahoo.com> | 2008-01-14 01:20:18 +0300 |
commit | e4e66c9aa429dde5b38985f54af9e1336c4b6fa0 (patch) | |
tree | 3feb5f5fd38e56eeb6c875b3d9f88cdf37f560ef /source | |
parent | d660e293650d88e00009ad315fb00ade71239621 (diff) |
=== Transform Snap ===
Snapping for object mode
Changes:
- Transform snap now working in object mode and not just mesh edit mode
- Shift-Tab can be used to toggle snap on/off inside transform too (no more Esc,toggle,restart)
- Object mode snap: Closest uses the bounding box corners of all selected objects, Median uses object center and Center uses transform center (same as edit mode).
- Object mode snap: all visible meshes can be used to get the snapping point (unlike edit mode snap which is limited to selected mesh: this might be adjusted to make edit mode snap use all visible too).
To Do:
- Add "Active" snap target method: use active object (or mesh element) as snap target
- Add snapping capabilities to Scale
- (Maybe) Add "Near pointer" snap target method: use selected element that is closest to mouse pointer as snap target. Active could probably accomplish that already in a less confusing manner, so I might skip this.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/include/BIF_transform.h | 2 | ||||
-rw-r--r-- | source/blender/include/transform.h | 2 | ||||
-rw-r--r-- | source/blender/src/header_view3d.c | 4 | ||||
-rw-r--r-- | source/blender/src/space.c | 4 | ||||
-rw-r--r-- | source/blender/src/transform_conversions.c | 2 | ||||
-rw-r--r-- | source/blender/src/transform_snap.c | 102 |
6 files changed, 91 insertions, 25 deletions
diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index 98af3b84770..c8e2a4832ab 100644 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -90,6 +90,8 @@ void BIF_setDualAxisConstraint(float vec1[3], float vec2[3], char *text); void BIF_setLocalAxisConstraint(char axis, char *text); void BIF_setLocalLockConstraint(char axis, char *text); +int BIF_snappingSupported(void); + struct TransformOrientation; void BIF_clearTransformOrientation(void); diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index ae8997a28ee..e9e82612721 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -122,7 +122,7 @@ typedef struct TransDataExtension { float iquat[4]; /* Initial rotation quaternion */ float *size; /* Size of the data to transform (Faculative) */ float isize[3]; /* Initial size */ - float obmat[3][3]; /* Object matrix */ + float obmat[4][4]; /* Object matrix */ } TransDataExtension; typedef struct TransData2D { diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index dbfbaf9d30b..8102e60c7fb 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -1818,7 +1818,7 @@ static uiBlock *view3d_transformmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center Cursor", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, ""); } - if (G.obedit != NULL && G.obedit->type==OB_MESH) + if (BIF_snappingSupported()) { uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -5476,7 +5476,7 @@ void view3d_buttons(void) } /* Snap */ - if(G.obedit && (G.obedit->type == OB_MESH)) { // Only Mesh for now + if (BIF_snappingSupported()) { uiBlockBeginAlign(block); if (G.scene->snap_flag & SCE_SNAP) { diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 775148582a8..9f3754f32da 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1570,8 +1570,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) /* Shift-Tabe handling (other cases are in toets) */ if (G.qual == LR_SHIFTKEY) { - /* Snap toggle (only edit mesh right now) */ - if (G.obedit && G.obedit->type==OB_MESH) + /* Snap toggle only when supported */ + if (BIF_snappingSupported()) { G.scene->snap_flag ^= SCE_SNAP; allqueue(REDRAWHEADERS, 0); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 77d9938f778..3f69316e373 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -2861,6 +2861,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) VECCOPY(td->ext->dsize, ob->dsize); VECCOPY(td->center, ob->obmat[3]); + + Mat4CpyMat4(td->ext->obmat, ob->obmat); /* is there a need to set the global<->data space conversion matrices? */ if (ob->parent || constinv) { diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 355c150657e..3aeb90bee32 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -90,10 +90,22 @@ 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 findNearestVertFromObjects(int *dist, float *loc, int selected); /****************** IMPLEMENTATIONS *********************/ +int BIF_snappingSupported(void) +{ + int status = 0; + + if (G.obedit == NULL || G.obedit->type==OB_MESH) /* only support object or mesh */ + { + status = 1; + } + + return status; +} + void drawSnapping(TransInfo *t) { if ((t->tsnap.status & (SNAP_ON|POINT_INIT|TARGET_INIT)) == (SNAP_ON|POINT_INIT|TARGET_INIT) && @@ -168,7 +180,13 @@ int handleSnapping(TransInfo *t, int event) { int status = 0; - // Put keyhandling code here + if (BIF_snappingSupported() && event == TABKEY && (G.qual & LR_SHIFTKEY) == LR_SHIFTKEY) + { + /* toggle snap and reinit */ + G.scene->snap_flag ^= SCE_SNAP; + initSnapping(t); + status = 1; + } return status; } @@ -211,10 +229,19 @@ void initSnapping(TransInfo *t) if (t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) { // Only 3D view or UV setSnappingCallback(t); + /* Edit mode */ if (t->tsnap.applySnap != NULL && // A snapping function actually exist + (G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on (G.obedit != NULL && G.obedit->type==OB_MESH) && // Temporary limited to edit mode meshes + ((t->flag & T_PROP_EDIT) == 0) ) // No PET, obviously + { + t->tsnap.status |= SNAP_ON; + t->tsnap.modePoint = SNAP_GEO; + } + /* Object mode */ + else if (t->tsnap.applySnap != NULL && // A snapping function actually exist (G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on - (t->flag & T_PROP_EDIT) == 0) // No PET, obviously + (G.obedit == NULL) ) // Object Mode { t->tsnap.status |= SNAP_ON; t->tsnap.modePoint = SNAP_GEO; @@ -364,7 +391,28 @@ void CalcSnapGrid(TransInfo *t, float *vec) void CalcSnapGeometry(TransInfo *t, float *vec) { - if (G.obedit != NULL && G.obedit->type==OB_MESH) + if (G.obedit == NULL) + { + if (t->spacetype == SPACE_VIEW3D) + { + float vec[3]; + int found = 0; + int dist = 40; // Use a user defined value here + + found = findNearestVertFromObjects(&dist, vec, 0); + if (found == 1) + { + VECCOPY(t->tsnap.snapPoint, vec); + + t->tsnap.status |= POINT_INIT; + } + else + { + t->tsnap.status &= ~POINT_INIT; + } + } + } + else if (G.obedit != NULL && G.obedit->type==OB_MESH) { /*if (G.scene->selectmode & B_SEL_VERT)*/ @@ -378,7 +426,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); + found = findNearestVertFromObjects(&dist, vec, SELECT); if (found == 1) { VECCOPY(t->tsnap.snapPoint, vec); @@ -479,7 +527,7 @@ void TargetSnapMedian(TransInfo *t) for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) { - VecAddf(t->tsnap.snapTarget, t->tsnap.snapTarget, td->iloc); + VecAddf(t->tsnap.snapTarget, t->tsnap.snapTarget, td->center); } VecMulf(t->tsnap.snapTarget, 1.0 / t->total); @@ -500,28 +548,42 @@ void TargetSnapClosest(TransInfo *t) { TransData *closest = NULL, *td = NULL; - // Base case, only one selected item - if (t->total == 1) + /* Object mode */ + if (t->flag & T_OBJECT) { - VECCOPY(t->tsnap.snapTarget, t->data[0].iloc); - - if(t->flag & (T_EDIT|T_POSE)) { - Object *ob= G.obedit?G.obedit:t->poseobj; - Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); + int i; + for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) + { + struct BoundBox *bb = object_get_boundbox(td->ob); + int j; + + for (j = 0; j < 8; j++) { + float loc[3]; + float dist; + + VECCOPY(loc, bb->vec[j]); + Mat4MulVecfl(td->ext->obmat, loc); + + dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); + + if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) + { + VECCOPY(t->tsnap.snapTarget, loc); + closest = td; + t->tsnap.dist = dist; + } + } } - - t->tsnap.dist = t->tsnap.distance(t, t->tsnap.snapTarget, t->tsnap.snapPoint); } - // More than one selected item else - { + { int i; for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) { float loc[3]; float dist; - VECCOPY(loc, td->iloc); + VECCOPY(loc, td->center); if(t->flag & (T_EDIT|T_POSE)) { Object *ob= G.obedit?G.obedit:t->poseobj; @@ -544,7 +606,7 @@ void TargetSnapClosest(TransInfo *t) } /*================================================================*/ -int findNearestVertFromObjects(int *dist, float *loc) { +int findNearestVertFromObjects(int *dist, float *loc, int selected) { Base *base; int retval = 0; short mval[2]; @@ -553,7 +615,7 @@ int findNearestVertFromObjects(int *dist, float *loc) { base= FIRSTBASE; for ( base = FIRSTBASE; base != NULL; base = base->next ) { - if ( TESTBASE(base) && base != BASACT ) { + if ( base != BASACT && BASE_SELECTABLE(base) && (base->flag & SELECT) == selected ) { Object *ob = base->object; if (ob->type == OB_MESH) { |