Node Editor: Add overlay to automatically label reroute nodes #113368

Merged
Jacques Lucke merged 45 commits from lone_noel/blender:node-editor-reroute-label-propagation into main 2024-06-05 10:02:51 +02:00
5 changed files with 147 additions and 20 deletions

View File

@ -865,6 +865,7 @@ class NODE_PT_overlay(Panel):
col = layout.column()
col.prop(overlay, "show_wire_color", text="Wire Colors")
col.prop(overlay, "show_reroute_auto_labels", text="Reroute Auto Labels")
col.separator()

View File

@ -4049,6 +4049,19 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 53)) {
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype == SPACE_NODE) {
SpaceNode *snode = reinterpret_cast<SpaceNode *>(sl);
snode->overlay.flag |= SN_OVERLAY_SHOW_REROUTE_AUTO_LABELS;
}
}
}
}
}
/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.

View File

@ -131,6 +131,11 @@ struct TreeDrawContext {
blender::Map<bNodeInstanceKey, blender::timeit::Nanoseconds>
*compositor_per_node_execution_time = nullptr;
/**
* Label for reroute nodes that is derived from upstream reroute nodes.
*/
blender::Map<const bNode *, blender::StringRefNull> reroute_auto_labels;
};
float ED_node_grid_size()
@ -2060,6 +2065,15 @@ void node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4],
GPU_blend(state);
}
/** Some elements of the node UI are hidden, when they get too small. */
#define NODE_TREE_SCALE_SMALL 0.2f
/** The node tree scales both with the view and with the UI. */
static float node_tree_view_scale(const SpaceNode &snode)
{
return (1.0f / snode.runtime->aspect) * UI_SCALE_FAC;
}
static void node_draw_preview_background(rctf *rect)
{
GPUVertFormat *format = immVertexFormat();
@ -3625,11 +3639,8 @@ static void node_draw_basis(const bContext &C,
UI_draw_roundbox_4fv(&rect, false, BASIS_RAD + outline_width, color_outline);
}
float scale;
UI_view2d_scale_get(&v2d, &scale, nullptr);
/* Skip slow socket drawing if zoom is small. */
if (scale > 0.2f) {
if (node_tree_view_scale(snode) > NODE_TREE_SCALE_SMALL) {
node_draw_sockets(v2d, C, ntree, node, block, true, false);
}
@ -4151,8 +4162,108 @@ static void frame_node_draw(const bContext &C,
UI_block_draw(&C, &block);
}
static void reroute_node_draw(
const bContext &C, ARegion &region, bNodeTree &ntree, const bNode &node, uiBlock &block)
/**
* Returns the reroute node linked to the input of the given reroute, if there is one.
*/
static const bNode *reroute_node_get_linked_reroute(const bNode &reroute)
{
BLI_assert(reroute.is_reroute());
lone_noel marked this conversation as resolved Outdated

What does 128 used below refer to here?

What does `128 used below` refer to here?

This comment has been there since labels for reroutes were implemented (12 years ago :) ) and has just been kept around since.
Looks like it just used to be a hint for an early declared variable so I removed it.

This comment has been there since labels for reroutes were implemented (12 years ago :) ) and has just been kept around since. Looks like it just used to be a hint for an early declared variable so I removed it.
const bNodeSocket *input_socket = reroute.input_sockets().first();
if (input_socket->directly_linked_links().is_empty()) {
return nullptr;
}
const bNodeLink *input_link = input_socket->directly_linked_links().first();
const bNode *from_node = input_link->fromnode;
return from_node->is_reroute() ? from_node : nullptr;
}
/**
* The auto label overlay displays a label on reroute nodes based on the user-defined label of a
* linked reroute upstream.
*/
static StringRefNull reroute_node_get_auto_label(TreeDrawContext &tree_draw_ctx,
const bNode &src_reroute)
{
BLI_assert(src_reroute.is_reroute());
if (src_reroute.label[0] != '\0') {
return StringRefNull(src_reroute.label);
}
Map<const bNode *, StringRefNull> &reroute_auto_labels = tree_draw_ctx.reroute_auto_labels;
StringRefNull label;
Vector<const bNode *> reroute_path;
/* Traverse reroute path backwards until label, non-reroute node or link-cycle is found. */
for (const bNode *reroute = &src_reroute; reroute;
reroute = reroute_node_get_linked_reroute(*reroute))
{
reroute_path.append(reroute);
if (const StringRefNull *label_ptr = reroute_auto_labels.lookup_ptr(reroute)) {
label = *label_ptr;
break;
}
if (reroute->label[0] != '\0') {
label = reroute->label;
break;
}
/* This makes sure that the loop eventually ends even if there are link-cycles. */
reroute_auto_labels.add(reroute, "");
}
/* Remember the label for each node on the path to avoid recomputing it. */
for (const bNode *reroute : reroute_path) {
reroute_auto_labels.add_overwrite(reroute, label);
}
return label;
}
static void reroute_node_draw_label(TreeDrawContext &tree_draw_ctx,
const SpaceNode &snode,
const bNode &node,
uiBlock &block)
{
const bool has_label = node.label[0] != '\0';
const bool use_auto_label = !has_label && (snode.overlay.flag & SN_OVERLAY_SHOW_OVERLAYS) &&
(snode.overlay.flag & SN_OVERLAY_SHOW_REROUTE_AUTO_LABELS);
if (!has_label && !use_auto_label) {
return;
}
/* Don't show the automatic label, when being zoomed out. */
if (!has_label && node_tree_view_scale(snode) < NODE_TREE_SCALE_SMALL) {
return;
}
char showname[128];
STRNCPY(showname,
has_label ? node.label : reroute_node_get_auto_label(tree_draw_ctx, node).c_str());
const short width = 512;
const int x = BLI_rctf_cent_x(&node.runtime->totr) - (width / 2);
const int y = node.runtime->totr.ymax;
uiBut *label_but = uiDefBut(
&block, UI_BTYPE_LABEL, 0, showname, x, y, width, short(NODE_DY), nullptr, 0, 0, nullptr);
UI_but_drawflag_disable(label_but, UI_BUT_TEXT_LEFT);
if (use_auto_label && !(node.flag & NODE_SELECT)) {
UI_but_flag_enable(label_but, UI_BUT_INACTIVE);
}
}
static void reroute_node_draw(const bContext &C,
TreeDrawContext &tree_draw_ctx,
ARegion &region,
const SpaceNode &snode,
bNodeTree &ntree,
const bNode &node,
uiBlock &block)
{
/* Skip if out of view. */
const rctf &rct = node.runtime->totr;
@ -4163,19 +4274,7 @@ static void reroute_node_draw(
return;
}
if (node.label[0] != '\0') {
/* Draw title (node label). */
char showname[128]; /* 128 used below */
STRNCPY(showname, node.label);
const short width = 512;
const int x = BLI_rctf_cent_x(&node.runtime->totr) - (width / 2);
const int y = node.runtime->totr.ymax;
uiBut *label_but = uiDefBut(
&block, UI_BTYPE_LABEL, 0, showname, x, y, width, short(NODE_DY), nullptr, 0, 0, nullptr);
UI_but_drawflag_disable(label_but, UI_BUT_TEXT_LEFT);
}
reroute_node_draw_label(tree_draw_ctx, snode, node, block);
/* Only draw input socket as they all are placed on the same position highlight
* if node itself is selected, since we don't display the node body separately. */
@ -4198,7 +4297,7 @@ static void node_draw(const bContext &C,
frame_node_draw(C, tree_draw_ctx, region, snode, ntree, node, block);
}
else if (node.is_reroute()) {
reroute_node_draw(C, region, ntree, node, block);
reroute_node_draw(C, tree_draw_ctx, region, snode, ntree, node, block);
}
else {
const View2D &v2d = region.v2d;

View File

@ -1555,6 +1555,11 @@ typedef enum eSpaceNodeOverlay_Flag {
SN_OVERLAY_SHOW_PATH = (1 << 4),
SN_OVERLAY_SHOW_NAMED_ATTRIBUTES = (1 << 5),
SN_OVERLAY_SHOW_PREVIEWS = (1 << 6),
/**
lone_noel marked this conversation as resolved Outdated

Add comment.

Add comment.
* Display an automatic label on reroute nodes based on the user-defined labels
* of connected reroute nodes.
*/
SN_OVERLAY_SHOW_REROUTE_AUTO_LABELS = (1 << 7),
} eSpaceNodeOverlay_Flag;
typedef enum eSpaceNodeOverlay_preview_shape {

View File

@ -7580,6 +7580,15 @@ static void rna_def_space_node_overlay(BlenderRNA *brna)
prop, "Show Wire Colors", "Color node links based on their connected sockets");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, nullptr);
prop = RNA_def_property(srna, "show_reroute_auto_labels", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, "overlay.flag", SN_OVERLAY_SHOW_REROUTE_AUTO_LABELS);
RNA_def_property_boolean_default(prop, false);
RNA_def_property_ui_text(prop,
"Show Reroute Auto Labels",
"Label reroute nodes based on the label of connected reroute nodes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, nullptr);
prop = RNA_def_property(srna, "show_timing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "overlay.flag", SN_OVERLAY_SHOW_TIMINGS);
RNA_def_property_boolean_default(prop, false);