diff options
Diffstat (limited to 'source/blender/editors/transform/transform_snap.c')
-rw-r--r-- | source/blender/editors/transform/transform_snap.c | 278 |
1 files changed, 250 insertions, 28 deletions
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 90b67951614..c49e1715f34 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -42,6 +42,7 @@ #include "DNA_object_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" // Temporary, for snapping to other unselected meshes +#include "DNA_node_types.h" #include "DNA_space_types.h" #include "DNA_screen_types.h" #include "DNA_view3d_types.h" @@ -74,6 +75,7 @@ #include "ED_armature.h" #include "ED_image.h" #include "ED_mesh.h" +#include "ED_node.h" #include "ED_uvedit.h" #include "ED_view3d.h" @@ -113,6 +115,9 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]); /****************** IMPLEMENTATIONS *********************/ +static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode); +static NodeBorder snapNodeBorder(int snap_node_mode); + #if 0 int BIF_snappingSupported(Object *obedit) { @@ -140,19 +145,22 @@ int activeSnap(TransInfo *t) void drawSnapping(const struct bContext *C, TransInfo *t) { - if (validSnap(t) && activeSnap(t)) { - - unsigned char col[4], selectedCol[4], activeCol[4]; - UI_GetThemeColor3ubv(TH_TRANSFORM, col); - col[3] = 128; - - UI_GetThemeColor3ubv(TH_SELECT, selectedCol); - selectedCol[3] = 128; - - UI_GetThemeColor3ubv(TH_ACTIVE, activeCol); - activeCol[3] = 192; - - if (t->spacetype == SPACE_VIEW3D) { + unsigned char col[4], selectedCol[4], activeCol[4]; + + if (!activeSnap(t)) + return; + + UI_GetThemeColor3ubv(TH_TRANSFORM, col); + col[3] = 128; + + UI_GetThemeColor3ubv(TH_SELECT, selectedCol); + selectedCol[3] = 128; + + UI_GetThemeColor3ubv(TH_ACTIVE, activeCol); + activeCol[3] = 192; + + if (t->spacetype == SPACE_VIEW3D) { + if (validSnap(t)) { TransSnapPoint *p; View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -160,11 +168,11 @@ void drawSnapping(const struct bContext *C, TransInfo *t) float size; glDisable(GL_DEPTH_TEST); - + size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); - + invert_m4_m4(imat, rv3d->viewmat); - + for (p = t->tsnap.points.first; p; p = p->next) { if (p == t->tsnap.selectedPoint) { glColor4ubv(selectedCol); @@ -172,20 +180,20 @@ void drawSnapping(const struct bContext *C, TransInfo *t) else { glColor4ubv(col); } - + drawcircball(GL_LINE_LOOP, p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat); } - + if (t->tsnap.status & POINT_INIT) { glColor4ubv(activeCol); - + drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat); } /* draw normal if needed */ if (usingSnappingNormal(t) && validSnappingNormal(t)) { glColor4ubv(activeCol); - + glBegin(GL_LINES); glVertex3f(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]); glVertex3f(t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0], @@ -197,7 +205,9 @@ void drawSnapping(const struct bContext *C, TransInfo *t) if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } - else if (t->spacetype == SPACE_IMAGE) { + } + else if (t->spacetype == SPACE_IMAGE) { + if (validSnap(t)) { /* This will not draw, and Im nor sure why - campbell */ #if 0 float xuser_asp, yuser_asp; @@ -228,7 +238,36 @@ void drawSnapping(const struct bContext *C, TransInfo *t) glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f); setlinestyle(0); #endif + } + } + else if (t->spacetype == SPACE_NODE) { + if (validSnap(t)) { + ARegion *ar = CTX_wm_region(C); + TransSnapPoint *p; + float size; + + size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); + + glEnable(GL_BLEND); + for (p = t->tsnap.points.first; p; p = p->next) { + if (p == t->tsnap.selectedPoint) { + glColor4ubv(selectedCol); + } + else { + glColor4ubv(col); + } + + drawnodesnap(&ar->v2d, p->co, size, 0); + } + + if (t->tsnap.status & POINT_INIT) { + glColor4ubv(activeCol); + + drawnodesnap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder); + } + + glDisable(GL_BLEND); } } } @@ -349,6 +388,8 @@ void resetSnapping(TransInfo *t) t->tsnap.snapNormal[0] = 0; t->tsnap.snapNormal[1] = 0; t->tsnap.snapNormal[2] = 0; + + t->tsnap.snapNodeBorder = 0; } int usingSnappingNormal(TransInfo *t) @@ -373,12 +414,20 @@ static void initSnappingMode(TransInfo *t) Object *obedit = t->obedit; Scene *scene = t->scene; - /* force project off when not supported */ - if (ts->snap_mode != SCE_SNAP_MODE_FACE) { + if (t->spacetype == SPACE_NODE) { + /* force project off when not supported */ t->tsnap.project = 0; + + t->tsnap.mode = ts->snap_node_mode; + } + else { + /* force project off when not supported */ + if (ts->snap_mode != SCE_SNAP_MODE_FACE) { + t->tsnap.project = 0; + } + + t->tsnap.mode = ts->snap_mode; } - - t->tsnap.mode = ts->snap_mode; if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && /* Only 3D view or UV */ (t->flag & T_CAMERA) == 0) /* Not with camera selected in camera view */ @@ -414,6 +463,19 @@ static void initSnappingMode(TransInfo *t) t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; } } + else if (t->spacetype == SPACE_NODE) + { + setSnappingCallback(t); + + if (t->tsnap.applySnap != NULL) + { + t->tsnap.modeSelect = SNAP_NOT_SELECTED; + } + else { + /* Grid if snap is not possible */ + t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; + } + } else { /* Always grid outside of 3D view */ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; @@ -459,7 +521,7 @@ void initSnapping(TransInfo *t, wmOperator *op) } /* use scene defaults only when transform is modal */ else if (t->flag & T_MODAL) { - if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) { + if (ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) { if (ts->snap_flag & SCE_SNAP) { t->modifiers |= MOD_SNAP; } @@ -624,7 +686,17 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3]) { float point[3]; getSnapPoint(t, point); - sub_v3_v3v3(vec, point, t->tsnap.snapTarget); + + if (t->spacetype == SPACE_NODE) { + char border = t->tsnap.snapNodeBorder; + if (border & (NODE_LEFT | NODE_RIGHT)) + vec[0] = point[0] - t->tsnap.snapTarget[0]; + if (border & (NODE_BOTTOM | NODE_TOP)) + vec[1] = point[1] - t->tsnap.snapTarget[1]; + } + else { + sub_v3_v3v3(vec, point, t->tsnap.snapTarget); + } } static void ApplySnapRotation(TransInfo *t, float *value) @@ -879,20 +951,57 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) t->tsnap.status &= ~POINT_INIT; } } + else if (t->spacetype == SPACE_NODE) { + float loc[2]; + int dist = SNAP_MIN_DISTANCE; // Use a user defined value here + char node_border; + + if (snapNodesTransform(t, t->mval, &dist, loc, &node_border, t->tsnap.modeSelect)) { + copy_v2_v2(t->tsnap.snapPoint, loc); + t->tsnap.snapNodeBorder = node_border; + + t->tsnap.status |= POINT_INIT; + } + else { + t->tsnap.status &= ~POINT_INIT; + } + } } /********************** TARGET **************************/ +static void TargetSnapOffset(TransInfo *t, TransData *td) +{ + if (t->spacetype == SPACE_NODE && td != NULL) { + bNode *node = td->extra; + char border = t->tsnap.snapNodeBorder; + float width = node->totr.xmax - node->totr.xmin; + float height = node->totr.ymax - node->totr.ymin; + + if (border & NODE_LEFT) + t->tsnap.snapTarget[0] -= 0.5f * width; + if (border & NODE_RIGHT) + t->tsnap.snapTarget[0] += 0.5f * width; + if (border & NODE_BOTTOM) + t->tsnap.snapTarget[1] -= 0.5f * height; + if (border & NODE_TOP) + t->tsnap.snapTarget[1] += 0.5f * height; + } +} + static void TargetSnapCenter(TransInfo *t) { /* Only need to calculate once */ if ((t->tsnap.status & TARGET_INIT) == 0) { copy_v3_v3(t->tsnap.snapTarget, t->center); + if (t->flag & (T_EDIT | T_POSE)) { Object *ob = t->obedit ? t->obedit : t->poseobj; mul_m4_v3(ob->obmat, t->tsnap.snapTarget); } + TargetSnapOffset(t, NULL); + t->tsnap.status |= TARGET_INIT; } } @@ -914,12 +1023,14 @@ static void TargetSnapActive(TransInfo *t) if (active_td) { copy_v3_v3(t->tsnap.snapTarget, active_td->center); - + if (t->flag & (T_EDIT | T_POSE)) { Object *ob = t->obedit ? t->obedit : t->poseobj; mul_m4_v3(ob->obmat, t->tsnap.snapTarget); } + TargetSnapOffset(t, active_td); + t->tsnap.status |= TARGET_INIT; } /* No active, default to median */ @@ -953,6 +1064,8 @@ static void TargetSnapMedian(TransInfo *t) mul_m4_v3(ob->obmat, t->tsnap.snapTarget); } + TargetSnapOffset(t, NULL); + t->tsnap.status |= TARGET_INIT; } } @@ -1029,6 +1142,8 @@ static void TargetSnapClosest(TransInfo *t) } } + TargetSnapOffset(t, closest); + t->tsnap.status |= TARGET_INIT; } } @@ -1876,6 +1991,113 @@ int peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], return peelObjects(CTX_data_scene(C), v3d, CTX_wm_region(C), CTX_data_edit_object(C), depth_peels, mval, mode); } +/******************** NODES ***********************************/ + +static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode) +{ + /* node is use for snapping only if a) snap mode matches and b) node is inside the view */ + return ((mode == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) || + (mode == SNAP_ALL && !(node->flag & NODE_ACTIVE))) && + (node->totr.xmin < v2d->cur.xmax && node->totr.xmax > v2d->cur.xmin && + node->totr.ymin < v2d->cur.ymax && node->totr.ymax > v2d->cur.ymin); +} + +static NodeBorder snapNodeBorder(int snap_node_mode) +{ + switch (snap_node_mode) { + case SCE_SNAP_MODE_NODE_X: + return NODE_LEFT | NODE_RIGHT; + case SCE_SNAP_MODE_NODE_Y: + return NODE_TOP | NODE_BOTTOM; + case SCE_SNAP_MODE_NODE_XY: + return NODE_LEFT | NODE_RIGHT | NODE_TOP | NODE_BOTTOM; + } + return 0; +} + +static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2], + float r_loc[2], int *r_dist, char *r_node_border) +{ + View2D *v2d = &ar->v2d; + NodeBorder border = snapNodeBorder(ts->snap_node_mode); + int retval = 0; + rcti totr; + int new_dist; + + UI_view2d_to_region_no_clip(v2d, node->totr.xmin, node->totr.ymin, &totr.xmin, &totr.ymin); + UI_view2d_to_region_no_clip(v2d, node->totr.xmax, node->totr.ymax, &totr.xmax, &totr.ymax); + + if (border & NODE_LEFT) { + new_dist = abs(totr.xmin - mval[0]); + if (new_dist < *r_dist) { + UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]); + *r_dist = new_dist; + *r_node_border = NODE_LEFT; + retval = 1; + } + } + + if (border & NODE_RIGHT) { + new_dist = abs(totr.xmax - mval[0]); + if (new_dist < *r_dist) { + UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]); + *r_dist = new_dist; + *r_node_border = NODE_RIGHT; + retval = 1; + } + } + + if (border & NODE_BOTTOM) { + new_dist = abs(totr.ymin - mval[1]); + if (new_dist < *r_dist) { + UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]); + *r_dist = new_dist; + *r_node_border = NODE_BOTTOM; + retval = 1; + } + } + + if (border & NODE_TOP) { + new_dist = abs(totr.ymax - mval[1]); + if (new_dist < *r_dist) { + UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]); + *r_dist = new_dist; + *r_node_border = NODE_TOP; + retval = 1; + } + } + + return retval; +} + +static int snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2], + int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) +{ + bNodeTree *ntree = snode->edittree; + bNode *node; + int retval = 0; + + *r_node_border = 0; + + for (node = ntree->nodes.first; node; node = node->next) { + if (snapNodeTest(&ar->v2d, node, mode)) + retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist, r_node_border); + } + + return retval; +} + +int snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) +{ + return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist, r_loc, r_node_border, mode); +} + +int snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) +{ + Scene *scene = CTX_data_scene(C); + return snapNodes(scene->toolsettings, CTX_wm_space_node(C), CTX_wm_region(C), mval, r_dist, r_loc, r_node_border, mode); +} + /*================================================================*/ static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action); |