diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_node.py | 3 | ||||
-rw-r--r-- | source/blender/editors/include/ED_node.h | 10 | ||||
-rw-r--r-- | source/blender/editors/include/ED_transform.h | 2 | ||||
-rw-r--r-- | source/blender/editors/space_node/drawnode.c | 25 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.c | 5 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 6 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 1 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_constraints.c | 2 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 9 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_snap.c | 276 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 12 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_enum_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 17 |
13 files changed, 334 insertions, 35 deletions
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index d7f25a597ed..bb29e415c19 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -90,6 +90,9 @@ class NODE_HT_header(Header): # Snap row = layout.row(align=True) row.prop(toolsettings, "use_snap", text="") + row.prop(toolsettings, "snap_node_element", text="", icon_only=True) + if toolsettings.snap_node_element != 'INCREMENT': + row.prop(toolsettings, "snap_target", text="") layout.template_running_jobs() diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 0979e3ec92b..6f86d01fb98 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -41,10 +41,20 @@ struct bNodeTree; struct bNode; struct bNodeTree; struct ScrArea; +struct View2D; + +typedef enum { + NODE_TOP = 1, + NODE_BOTTOM = 2, + NODE_LEFT = 4, + NODE_RIGHT = 8 +} NodeBorder; /* drawnode.c */ void ED_init_node_butfuncs(void); +void drawnodesnap(struct View2D *v2d, const float cent[2], float size, NodeBorder border); + /* node_draw.c */ void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene); void ED_node_changed_update(struct ID *id, struct bNode *node); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 608df8dd9b3..d7e9fc323a6 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -180,6 +180,8 @@ int peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, cons int peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, const float mval[2], SnapMode mode); int snapObjectsTransform(struct TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode); int snapObjectsContext(struct bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode); +int snapNodesTransform(struct TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode); +int snapNodesContext(struct bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode); #endif diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index cc58c4174b3..d644747413b 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3351,3 +3351,28 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); // node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); } + +void drawnodesnap(View2D *v2d, const float cent[2], float size, NodeBorder border) +{ + glBegin(GL_LINES); + + if (border & (NODE_LEFT | NODE_RIGHT)) { + glVertex2f(cent[0], v2d->cur.ymin); + glVertex2f(cent[0], v2d->cur.ymax); + } + else { + glVertex2f(cent[0], cent[1] - size); + glVertex2f(cent[0], cent[1] + size); + } + + if (border & (NODE_TOP | NODE_BOTTOM)) { + glVertex2f(v2d->cur.xmin, cent[1]); + glVertex2f(v2d->cur.xmax, cent[1]); + } + else { + glVertex2f(cent[0] - size, cent[1]); + glVertex2f(cent[0] + size, cent[1]); + } + + glEnd(); +} diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index f9aa0dfd582..17d7530d2a7 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -65,6 +65,7 @@ #include "ED_node.h" #include "ED_gpencil.h" +#include "ED_space_api.h" #include "UI_interface.h" #include "UI_interface_icons.h" @@ -1087,6 +1088,8 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d) //uiFreeBlocksWin(&sa->uiblocks, sa->win); + ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); + /* only set once */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_MAP1_VERTEX_3); @@ -1139,6 +1142,8 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d) glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); + ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); + /* draw grease-pencil ('canvas' strokes) */ if (snode->nodetree) draw_gpencil_view2d(C, 1); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a00376974a5..1d70c6d68f2 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1655,6 +1655,12 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int unit_m3(t->spacemtx); t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); } + else if (t->spacetype == SPACE_NODE) { + unit_m3(t->spacemtx); + /*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);*/ + t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + /*t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);*/ + } else unit_m3(t->spacemtx); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index fdc09c1bed0..3ab5bf7bbfb 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -86,6 +86,7 @@ typedef struct TransSnap { float snapTarget[3]; /* to this point */ float snapNormal[3]; float snapTangent[3]; + char snapNodeBorder; ListBase points; TransSnapPoint *selectedPoint; float dist; // Distance from snapPoint to snapTarget diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index f4c025f71be..8ca29864dff 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -640,7 +640,7 @@ void drawConstraint(TransInfo *t) { TransCon *tc = &(t->con); - if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) + if (!ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) return; if (!(tc->mode & CON_APPLY)) return; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f3a846daf29..af0b33d58ae 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5516,8 +5516,11 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node) } td->loc = td2d->loc; - copy_v3_v3(td->center, td->loc); copy_v3_v3(td->iloc, td->loc); + /* use node center instead of origin (top-left corner) */ + td->center[0] = node->locx + 0.5f * (node->totr.xmax - node->totr.xmin); + td->center[1] = node->locy - 0.5f * (node->totr.ymax - node->totr.ymin); /* node height is used negative */ + td->center[2] = 0.0f; memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; @@ -5529,6 +5532,8 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node) unit_m3(td->mtx); unit_m3(td->smtx); + + td->extra = node; } static void createTransNodeData(bContext *C, TransInfo *t) @@ -6324,7 +6329,7 @@ void createTransData(bContext *C, TransInfo *t) #endif } else if (t->spacetype == SPACE_NODE) { - t->flag |= T_2D_EDIT | T_POINTS; + t->flag |= T_POINTS | T_2D_EDIT; createTransNodeData(C, t); if (t->data && (t->flag & T_PROP_EDIT)) { sort_trans_data(t); // makes selected become first in array diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index d485b886ea7..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; @@ -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); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 6a8022c07a5..02a7d0da325 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -899,7 +899,7 @@ typedef struct ToolSettings { /* Subdivide Settings */ short cornertype; - short pad3; + short pad1; /*Triangle to Quad conversion threshold*/ float jointrilimit; /* Editmode Tools */ @@ -995,12 +995,13 @@ typedef struct ToolSettings { char edge_mode_live_unwrap; /* Transform */ - char snap_mode; + char snap_mode, snap_node_mode; + char pad3; short snap_flag, snap_target; short proportional, prop_mode; char proportional_objects; /* proportional edit, object mode */ char proportional_mask; /* proportional edit, object mode */ - char pad[4]; + char pad4[2]; char auto_normalize; /*auto normalizing mode in wpaint*/ char multipaint; /* paint multiple bones in wpaint */ @@ -1012,7 +1013,7 @@ typedef struct ToolSettings { int uv_relax_method; /* XXX: these sculpt_paint_* fields are deprecated, use the * unified_paint_settings field instead! */ - short sculpt_paint_settings DNA_DEPRECATED; short pad1; + short sculpt_paint_settings DNA_DEPRECATED; short pad5; int sculpt_paint_unified_size DNA_DEPRECATED; float sculpt_paint_unified_unprojected_radius DNA_DEPRECATED; float sculpt_paint_unified_alpha DNA_DEPRECATED; @@ -1370,6 +1371,9 @@ typedef struct Scene { #define SCE_SNAP_MODE_EDGE 2 #define SCE_SNAP_MODE_FACE 3 #define SCE_SNAP_MODE_VOLUME 4 +#define SCE_SNAP_MODE_NODE_X 5 +#define SCE_SNAP_MODE_NODE_Y 6 +#define SCE_SNAP_MODE_NODE_XY 7 /* toolsettings->selectmode */ #define SCE_SELECT_VERTEX 1 /* for mesh */ diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index a8d176db767..a0614a9d82a 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -45,6 +45,7 @@ extern EnumPropertyItem proportional_falloff_curve_only_items[]; extern EnumPropertyItem proportional_editing_items[]; extern EnumPropertyItem snap_target_items[]; extern EnumPropertyItem snap_element_items[]; +extern EnumPropertyItem snap_node_element_items[]; extern EnumPropertyItem mesh_select_mode_items[]; extern EnumPropertyItem space_type_items[]; extern EnumPropertyItem region_type_items[]; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 7a2f0736e98..4c0d6eb30d2 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -136,6 +136,14 @@ EnumPropertyItem snap_element_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem snap_node_element_items[] = { + {SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments of grid"}, + {SCE_SNAP_MODE_NODE_X, "NODE_X", ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"}, + {SCE_SNAP_MODE_NODE_Y, "NODE_Y", ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"}, + {SCE_SNAP_MODE_NODE_XY, "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"}, + {0, NULL, 0, NULL, NULL} +}; + /* workaround for duplice enums, * have each enum line as a defne then conditionally set it or not @@ -1626,6 +1634,13 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, snap_element_items); RNA_def_property_ui_text(prop, "Snap Element", "Type of element to snap to"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + /* node editor uses own set of snap modes */ + prop = RNA_def_property(srna, "snap_node_element", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "snap_node_mode"); + RNA_def_property_enum_items(prop, snap_node_element_items); + RNA_def_property_ui_text(prop, "Snap Node Element", "Type of element to snap to"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ prop = RNA_def_property(srna, "snap_target", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "snap_target"); @@ -1651,7 +1666,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Project to Self", "Snap onto itself (editmode)"); RNA_def_property_ui_icon(prop, ICON_ORTHO, 0); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - + /* Grease Pencil */ prop = RNA_def_property(srna, "use_grease_pencil_sessions", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gpencil_flags", GP_TOOL_FLAG_PAINTSESSIONS_ON); |