Extended modes for snapping in the node editor.

The transform operators in nodes will now use the unselected nodes to generate snapping points. Unlike object snapping, node snapping works for the x/y axes separately and snaps node borders to same borders of unselected nodes. The sensitive area for node borders extends over the whole view2D range, to enable simple alignment of nodes in both x and y direction.

For snap points in the node editor an additional enum value is stored to indicate the type of node border (left/right/top/bottom). This works as a constraint on possible node alignments: only same border types align with each other.
This commit is contained in:
Lukas Toenne 2012-06-29 14:34:46 +00:00
parent 344ca17247
commit 83093d6770
13 changed files with 334 additions and 35 deletions

View File

@ -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()

View File

@ -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);

View File

@ -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

View File

@ -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();
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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[];

View File

@ -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);