UI: Nodes: Remove some snapping options

Compositor: UI: remove snapping to nodes.

Snapping nodes to other nodes behaves in a very unpredictable way, which makes most snapping options useless.

The patch removes the following:
- Snapping options `Node X`, `Node Y` and `Node XY`
- Menu `Snap Node Element`
- Menu `Snap Target`

New behavior:
- Activating `Snap` always acts as 'Snap to Grid'

Part of https://projects.blender.org/blender/blender/issues/128612

Pull Request: https://projects.blender.org/blender/blender/pulls/127667
This commit is contained in:
Habib Gahbiche
2024-11-24 14:30:22 +01:00
committed by Habib Gahbiche
parent f181262634
commit 35ea495bb6
13 changed files with 18 additions and 300 deletions

View File

@@ -2263,9 +2263,7 @@ def km_node_editor(params):
{"type": params.select_mouse, "value": 'CLICK_DRAG', "alt": True},
{"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True},
{"properties": [("data_path", "tool_settings.use_snap_node")]}),
("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("data_path", "tool_settings.snap_node_element")]}),
{"properties": [("data_path", 'tool_settings.use_snap_node')]}),
("wm.context_toggle", {"type": 'Z', "value": 'PRESS', "alt": True, "shift": True},
{"properties": [("data_path", "space_data.overlay.show_overlays")]}),
*_template_items_context_menu("NODE_MT_context_menu", params.context_menu_event),

View File

@@ -209,9 +209,6 @@ class NODE_HT_header(Header):
# Snap
row = layout.row(align=True)
row.prop(tool_settings, "use_snap_node", text="")
row.prop(tool_settings, "snap_node_element", icon_only=True)
if tool_settings.snap_node_element != 'GRID':
row.prop(tool_settings, "snap_target", text="")
# Overlay toggle & popover
row = layout.row(align=True)

View File

@@ -5533,6 +5533,7 @@ void blo_do_versions_280(FileData *fd, Library * /*lib*/, Main *bmain)
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 281, 15)) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
constexpr char SCE_SNAP_TO_NODE_X = (1 << 1);
if (scene->toolsettings->snap_node_mode == SCE_SNAP_TO_NODE_X) {
scene->toolsettings->snap_node_mode = SCE_SNAP_TO_GRID;
}

View File

@@ -1259,6 +1259,18 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain)
version_legacy_actions_to_layered(bmain);
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 404, 7)) {
constexpr char SCE_SNAP_TO_NODE_X = (1 << 0);
constexpr char SCE_SNAP_TO_NODE_Y = (1 << 1);
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
if (scene->toolsettings->snap_node_mode & SCE_SNAP_TO_NODE_X ||
scene->toolsettings->snap_node_mode & SCE_SNAP_TO_NODE_Y)
{
scene->toolsettings->snap_node_mode = SCE_SNAP_TO_GRID;
}
}
}
/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
@@ -3769,12 +3781,12 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
auto versioning_snap_to = [](short snap_to_old, int type) {
eSnapMode snap_to_new = SCE_SNAP_TO_NONE;
if (snap_to_old & (1 << 0)) {
snap_to_new |= type == IS_NODE ? SCE_SNAP_TO_NODE_X :
snap_to_new |= type == IS_NODE ? SCE_SNAP_TO_NONE :
type == IS_ANIM ? SCE_SNAP_TO_FRAME :
SCE_SNAP_TO_VERTEX;
}
if (snap_to_old & (1 << 1)) {
snap_to_new |= type == IS_NODE ? SCE_SNAP_TO_NODE_Y :
snap_to_new |= type == IS_NODE ? SCE_SNAP_TO_NONE :
type == IS_ANIM ? SCE_SNAP_TO_SECOND :
SCE_SNAP_TO_EDGE;
}

View File

@@ -24,14 +24,6 @@ struct bNodeType;
struct bNodeSocketType;
} // namespace blender::bke
enum NodeBorder {
NODE_TOP = 1,
NODE_BOTTOM = 2,
NODE_LEFT = 4,
NODE_RIGHT = 8,
};
ENUM_OPERATORS(NodeBorder, NODE_RIGHT)
#define NODE_GRID_STEP_SIZE (20.0f * UI_SCALE_FAC) /* Based on the grid nodes snap to. */
#define NODE_EDGE_PAN_INSIDE_PAD 2
#define NODE_EDGE_PAN_OUTSIDE_PAD 0 /* Disable clamping for node panning, use whole screen. */
@@ -71,8 +63,6 @@ void ED_init_custom_node_socket_type(blender::bke::bNodeSocketType *stype);
void ED_init_standard_node_socket_type(blender::bke::bNodeSocketType *stype);
void ED_init_node_socket_type_virtual(blender::bke::bNodeSocketType *stype);
void ED_node_sample_set(const float col[4]);
void ED_node_draw_snap(
View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned int pos);
void ED_node_type_draw_color(const char *idname, float *r_color);
/* `node_draw.cc` */

View File

@@ -2548,30 +2548,3 @@ void node_draw_link_dragged(const bContext &C,
}
} // namespace blender::ed::space_node
void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder border, uint pos)
{
immBegin(GPU_PRIM_LINES, 4);
if (border & (NODE_LEFT | NODE_RIGHT)) {
immVertex2f(pos, cent[0], v2d->cur.ymin);
immVertex2f(pos, cent[0], v2d->cur.ymax);
}
else {
immVertex2f(pos, cent[0], cent[1] - size);
immVertex2f(pos, cent[0], cent[1] + size);
}
if (border & (NODE_TOP | NODE_BOTTOM)) {
immVertex2f(pos, v2d->cur.xmin, cent[1]);
immVertex2f(pos, v2d->cur.xmax, cent[1]);
}
else {
immVertex2f(pos, cent[0] - size, cent[1]);
immVertex2f(pos, cent[0] + size, cent[1]);
}
immEnd();
}
/** \} */

View File

@@ -534,7 +534,6 @@ struct TransSnap {
/** To this point (in global-space). */
float snap_target[3];
float snapNormal[3];
char snapNodeBorder;
ListBase points;
TransSnapPoint *selectedPoint;
double last;

View File

@@ -350,16 +350,7 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3])
float point[3];
getSnapPoint(t, point);
if (t->spacetype == SPACE_NODE) {
char border = t->tsnap.snapNodeBorder;
if (border & (NODE_LEFT | NODE_RIGHT)) {
vec[0] = point[0] - t->tsnap.snap_source[0];
}
if (border & (NODE_BOTTOM | NODE_TOP)) {
vec[1] = point[1] - t->tsnap.snap_source[1];
}
}
else if (t->spacetype == SPACE_SEQ) {
if (t->spacetype == SPACE_SEQ) {
if (t->region->regiontype == RGN_TYPE_PREVIEW) {
transform_snap_sequencer_image_apply_translate(t, vec);
}

View File

@@ -52,7 +52,6 @@ static void setSnappingCallback(TransInfo *t);
static void snap_target_view3d_fn(TransInfo *t, float *vec);
static void snap_target_uv_fn(TransInfo *t, float *vec);
static void snap_target_node_fn(TransInfo *t, float *vec);
static void snap_target_sequencer_fn(TransInfo *t, float *vec);
static void snap_target_nla_fn(TransInfo *t, float *vec);
@@ -70,9 +69,6 @@ static eSnapMode snapObjectsTransform(
/** \name Implementations
* \{ */
static bool snapNodeTest(View2D *v2d, bNode *node, eSnapTargetOP snap_target_select);
static NodeBorder snapNodeBorder(eSnapMode snap_node_mode);
#if 0
int BIF_snappingSupported(Object *obedit)
{
@@ -312,40 +308,6 @@ void drawSnapping(TransInfo *t)
GPU_matrix_pop_projection();
}
else if (t->spacetype == SPACE_NODE) {
ARegion *region = t->region;
float size;
size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
GPU_blend(GPU_BLEND_ALPHA);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
LISTBASE_FOREACH (TransSnapPoint *, p, &t->tsnap.points) {
if (p == t->tsnap.selectedPoint) {
immUniformColor4ubv(selectedCol);
}
else {
immUniformColor4ubv(col);
}
ED_node_draw_snap(&region->v2d, p->co, size, NodeBorder(0), pos);
}
if (t->tsnap.status & SNAP_TARGET_FOUND) {
immUniformColor4ubv(activeCol);
ED_node_draw_snap(
&region->v2d, t->tsnap.snap_target, size, NodeBorder(t->tsnap.snapNodeBorder), pos);
}
immUnbindProgram();
GPU_blend(GPU_BLEND_NONE);
}
else if (t->spacetype == SPACE_SEQ) {
const ARegion *region = t->region;
GPU_blend(GPU_BLEND_ALPHA);
@@ -618,8 +580,6 @@ void resetSnapping(TransInfo *t)
t->tsnap.snapNormal[0] = 0;
t->tsnap.snapNormal[1] = 0;
t->tsnap.snapNormal[2] = 0;
t->tsnap.snapNodeBorder = 0;
}
bool usingSnappingNormal(const TransInfo *t)
@@ -1065,7 +1025,7 @@ static void setSnappingCallback(TransInfo *t)
}
}
else if (t->spacetype == SPACE_NODE) {
t->tsnap.snap_target_fn = snap_target_node_fn;
/* Pass. */
}
else if (t->spacetype == SPACE_SEQ) {
t->tsnap.snap_target_fn = snap_target_sequencer_fn;
@@ -1334,26 +1294,6 @@ static void snap_target_uv_fn(TransInfo *t, float * /*vec*/)
SET_FLAG_FROM_TEST(t->tsnap.status, found, SNAP_TARGET_FOUND);
}
static void snap_target_node_fn(TransInfo *t, float * /*vec*/)
{
BLI_assert(t->spacetype == SPACE_NODE);
if (t->tsnap.mode & (SCE_SNAP_TO_NODE_X | SCE_SNAP_TO_NODE_Y)) {
float loc[2];
float dist_px = SNAP_MIN_DISTANCE; /* Use a user defined value here. */
char node_border;
if (snapNodesTransform(t, t->mval, loc, &dist_px, &node_border)) {
copy_v2_v2(t->tsnap.snap_target, loc);
t->tsnap.snapNodeBorder = node_border;
t->tsnap.status |= SNAP_TARGET_FOUND;
}
else {
t->tsnap.status &= ~SNAP_TARGET_FOUND;
}
}
}
static void snap_target_sequencer_fn(TransInfo *t, float * /*vec*/)
{
BLI_assert(t->spacetype == SPACE_SEQ);
@@ -1414,29 +1354,6 @@ void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3])
}
mul_v3_fl(r_median, 1.0 / i_accum);
// TargetSnapOffset(t, nullptr);
}
static void TargetSnapOffset(TransInfo *t, TransData *td)
{
if (t->spacetype == SPACE_NODE && td != nullptr) {
bNode *node = static_cast<bNode *>(td->extra);
char border = t->tsnap.snapNodeBorder;
if (border & NODE_LEFT) {
t->tsnap.snap_source[0] -= 0.0f;
}
if (border & NODE_RIGHT) {
t->tsnap.snap_source[0] += BLI_rctf_size_x(&node->runtime->totr);
}
if (border & NODE_BOTTOM) {
t->tsnap.snap_source[1] -= BLI_rctf_size_y(&node->runtime->totr);
}
if (border & NODE_TOP) {
t->tsnap.snap_source[1] += 0.0f;
}
}
}
static void snap_source_center_fn(TransInfo *t)
@@ -1444,7 +1361,6 @@ static void snap_source_center_fn(TransInfo *t)
/* Only need to calculate once. */
if ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0) {
copy_v3_v3(t->tsnap.snap_source, t->center_global);
TargetSnapOffset(t, nullptr);
t->tsnap.status |= SNAP_SOURCE_FOUND;
t->tsnap.source_type = SCE_SNAP_TO_NONE;
@@ -1456,7 +1372,6 @@ static void snap_source_active_fn(TransInfo *t)
/* Only need to calculate once. */
if ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0) {
if (calculateCenterActive(t, true, t->tsnap.snap_source)) {
TargetSnapOffset(t, nullptr);
t->tsnap.status |= SNAP_SOURCE_FOUND;
t->tsnap.source_type = SCE_SNAP_TO_NONE;
}
@@ -1583,9 +1498,6 @@ static void snap_source_closest_fn(TransInfo *t)
}
}
}
TargetSnapOffset(t, closest);
t->tsnap.source_type = SCE_SNAP_TO_NONE;
}
t->tsnap.status |= SNAP_SOURCE_FOUND;
@@ -1719,129 +1631,6 @@ bool peelObjectsTransform(TransInfo *t,
/** \} */
/* -------------------------------------------------------------------- */
/** \name snap Nodes
* \{ */
static bool snapNodeTest(View2D *v2d, bNode *node, eSnapTargetOP snap_target_select)
{
/* Node is use for snapping only if a) snap mode matches and b) node is inside the view. */
return (((snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED) && !(node->flag & NODE_SELECT)) ||
(snap_target_select == SCE_SNAP_TARGET_ALL && !(node->flag & NODE_ACTIVE))) &&
(node->runtime->totr.xmin < v2d->cur.xmax && node->runtime->totr.xmax > v2d->cur.xmin &&
node->runtime->totr.ymin < v2d->cur.ymax && node->runtime->totr.ymax > v2d->cur.ymin);
}
static NodeBorder snapNodeBorder(eSnapMode snap_node_mode)
{
NodeBorder flag = NodeBorder(0);
if (snap_node_mode & SCE_SNAP_TO_NODE_X) {
flag |= NODE_LEFT | NODE_RIGHT;
}
if (snap_node_mode & SCE_SNAP_TO_NODE_Y) {
flag |= NODE_TOP | NODE_BOTTOM;
}
return flag;
}
static bool snapNode(ToolSettings *ts,
SpaceNode * /*snode*/,
ARegion *region,
bNode *node,
const float2 &mval,
float r_loc[2],
float *r_dist_px,
char *r_node_border)
{
View2D *v2d = &region->v2d;
NodeBorder border = snapNodeBorder(eSnapMode(ts->snap_node_mode));
bool retval = false;
rcti totr;
int new_dist;
UI_view2d_view_to_region_rcti(v2d, &node->runtime->totr, &totr);
if (border & NODE_LEFT) {
new_dist = abs(totr.xmin - mval[0]);
if (new_dist < *r_dist_px) {
UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]);
*r_dist_px = new_dist;
*r_node_border = NODE_LEFT;
retval = true;
}
}
if (border & NODE_RIGHT) {
new_dist = abs(totr.xmax - mval[0]);
if (new_dist < *r_dist_px) {
UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]);
*r_dist_px = new_dist;
*r_node_border = NODE_RIGHT;
retval = true;
}
}
if (border & NODE_BOTTOM) {
new_dist = abs(totr.ymin - mval[1]);
if (new_dist < *r_dist_px) {
UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]);
*r_dist_px = new_dist;
*r_node_border = NODE_BOTTOM;
retval = true;
}
}
if (border & NODE_TOP) {
new_dist = abs(totr.ymax - mval[1]);
if (new_dist < *r_dist_px) {
UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]);
*r_dist_px = new_dist;
*r_node_border = NODE_TOP;
retval = true;
}
}
return retval;
}
static bool snapNodes(ToolSettings *ts,
SpaceNode *snode,
ARegion *region,
const float2 &mval,
eSnapTargetOP snap_target_select,
float r_loc[2],
float *r_dist_px,
char *r_node_border)
{
bNodeTree *ntree = snode->edittree;
bool retval = false;
*r_node_border = 0;
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (snapNodeTest(&region->v2d, node, snap_target_select)) {
retval |= snapNode(ts, snode, region, node, mval, r_loc, r_dist_px, r_node_border);
}
}
return retval;
}
bool snapNodesTransform(
TransInfo *t, const float2 &mval, float r_loc[2], float *r_dist_px, char *r_node_border)
{
return snapNodes(t->settings,
static_cast<SpaceNode *>(t->area->spacedata.first),
t->region,
mval,
t->tsnap.target_operation,
r_loc,
r_dist_px,
r_node_border);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name snap Grid
* \{ */

View File

@@ -22,13 +22,6 @@ bool peelObjectsTransform(TransInfo *t,
float r_no[3],
float *r_thickness);
bool snapNodesTransform(TransInfo *t,
const blender::float2 &mval,
/* Return args. */
float r_loc[2],
float *r_dist_px,
char *r_node_border);
bool transformModeUseSnap(const TransInfo *t);
void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3]);

View File

@@ -2426,10 +2426,6 @@ ENUM_OPERATORS(eSnapTargetOP, SCE_SNAP_TARGET_NOT_NONEDITED)
typedef enum eSnapMode {
SCE_SNAP_TO_NONE = 0,
/** #ToolSettings::snap_node_mode */
SCE_SNAP_TO_NODE_X = (1 << 0),
SCE_SNAP_TO_NODE_Y = (1 << 1),
/** #ToolSettings::snap_anim_mode */
SCE_SNAP_TO_FRAME = (1 << 0),
SCE_SNAP_TO_SECOND = (1 << 1),

View File

@@ -27,7 +27,6 @@ DEF_ENUM(rna_enum_proportional_falloff_items)
DEF_ENUM(rna_enum_proportional_falloff_curve_only_items)
DEF_ENUM(rna_enum_snap_source_items)
DEF_ENUM(rna_enum_snap_element_items)
DEF_ENUM(rna_enum_snap_node_element_items)
DEF_ENUM(rna_enum_snap_animation_element_items)
DEF_ENUM(rna_enum_curve_fit_method_items)
DEF_ENUM(rna_enum_mesh_select_mode_items)

View File

@@ -206,18 +206,6 @@ static const EnumPropertyItem *rna_enum_snap_element_individual_items =
&rna_enum_snap_element_items[ARRAY_SIZE(rna_enum_snap_element_items) - 3];
#endif
const EnumPropertyItem rna_enum_snap_node_element_items[] = {
{SCE_SNAP_TO_GRID, "GRID", ICON_SNAP_GRID, "Grid", "Snap to grid"},
{SCE_SNAP_TO_NODE_X, "NODE_X", ICON_NODE_SIDE, "Node X", "Snap to left/right node border"},
{SCE_SNAP_TO_NODE_Y, "NODE_Y", ICON_NODE_TOP, "Node Y", "Snap to top/bottom node border"},
{SCE_SNAP_TO_NODE_X | SCE_SNAP_TO_NODE_Y,
"NODE_XY",
ICON_NODE_CORNER,
"Node X / Y",
"Snap to any node border"},
{0, nullptr, 0, nullptr, nullptr},
};
const EnumPropertyItem rna_enum_snap_animation_element_items[] = {
{SCE_SNAP_TO_FRAME, "FRAME", 0, "Frame", "Snap to frame"},
{SCE_SNAP_TO_SECOND, "SECOND", 0, "Second", "Snap to seconds"},
@@ -3645,14 +3633,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
"Snap to Same Target",
"Snap only to target that source was initially near (\"Face Nearest\" only)");
/* node editor uses its own set of snap modes */
prop = RNA_def_property(srna, "snap_node_element", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, nullptr, "snap_node_mode");
RNA_def_property_flag(prop, PROP_DEG_SYNC_ONLY);
RNA_def_property_enum_items(prop, rna_enum_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, nullptr); /* header redraw */
prop = RNA_def_property(srna, "use_snap_anim", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "snap_flag_anim", SCE_SNAP);
RNA_def_property_flag(prop, PROP_DEG_SYNC_ONLY);