Node Editor: Introduce color overlay and dashed wires theme setting

This patch includes code from D9891 and D12754, so credit goes to Juanfran and Dalai.
I updated the patches to work with `master` and with the new overlay toggle.

The reason to include both changes as part of one patch is that the dimmed dashed lines work much better together with colored wires.

Theme setting for dash opacity:
{F11370574, size=full}

{F11286177, size=full, autoplay, loop}

{F11149912, size=full}

For adding the overlay I used `SpaceImageOverlay` as reference, although I'm not familiar with this code so there might be mistakes.

Reviewed By: #user_interface, HooglyBoogly

Differential Revision: https://developer.blender.org/D12886
This commit is contained in:
Pablo Vazquez 2021-10-21 21:00:17 +02:00 committed by Pablo Vazquez
parent 1d96a48267
commit 9b1b4b9e32
16 changed files with 212 additions and 20 deletions

View File

@ -828,6 +828,7 @@ const bTheme U_theme_default = {
.facedot_size = 4,
.noodle_curving = 4,
.grid_levels = 2,
.dash_alpha = 0.5f,
.syntaxl = RGBA(0x565656ff),
.syntaxs = RGBA(0x975b5bff),
.syntaxb = RGBA(0xccb83dff),

View File

@ -956,6 +956,7 @@
distor_node="#749797"
noodle_curving="4"
grid_levels="2"
dash_alpha="0.5"
input_node="#cb3d4a"
output_node="#cb3d4a"
filter_node="#6c696f"

View File

@ -2064,6 +2064,8 @@ def km_node_editor(params):
{"properties": [("data_path", 'tool_settings.use_snap')]}),
("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("data_path", 'tool_settings.snap_node_element')]}),
("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

@ -49,6 +49,7 @@ class NODE_HT_header(Header):
scene = context.scene
snode = context.space_data
overlay = snode.overlay
snode_id = snode.id
id_from = snode.id_from
tool_settings = context.tool_settings
@ -205,6 +206,13 @@ class NODE_HT_header(Header):
if tool_settings.snap_node_element != 'GRID':
row.prop(tool_settings, "snap_target", text="")
# Overlay toggle & popover
row = layout.row(align=True)
row.prop(overlay, "show_overlays", icon='OVERLAY', text="")
sub = row.row(align=True)
sub.active = overlay.show_overlays
sub.popover(panel="NODE_PT_overlay", text="")
class NODE_MT_editor_menus(Menu):
bl_idname = "NODE_MT_editor_menus"
@ -680,6 +688,29 @@ class NODE_PT_quality(bpy.types.Panel):
col.prop(snode, "use_auto_render")
class NODE_PT_overlay(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'HEADER'
bl_label = "Overlays"
bl_ui_units_x = 7
def draw(self, context):
layout = self.layout
layout.label(text="Node Editor Overlays")
snode = context.space_data
overlay = snode.overlay
layout.active = overlay.show_overlays
col = layout.column()
col.prop(overlay, "show_wire_color", text="Wire Colors")
col.separator()
col.prop(snode, "show_annotation", text="Annotations")
class NODE_UL_interface_sockets(bpy.types.UIList):
def draw_item(self, context, layout, _data, item, icon, _active_data, _active_propname, _index):
socket = item
@ -848,6 +879,7 @@ classes = (
NODE_PT_backdrop,
NODE_PT_quality,
NODE_PT_annotation,
NODE_PT_overlay,
NODE_UL_interface_sockets,
NODE_PT_node_tree_interface_inputs,
NODE_PT_node_tree_interface_outputs,

View File

@ -1988,6 +1988,23 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 300, 37)) {
/* Node Editor: toggle overlays on. */
if (!DNA_struct_find(fd->filesdna, "SpaceNodeOverlay")) {
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
if (space->spacetype == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *)space;
snode->overlay.flag |= SN_OVERLAY_SHOW_OVERLAYS;
snode->overlay.flag |= SN_OVERLAY_SHOW_WIRE_COLORS;
}
}
}
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -310,6 +310,10 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
btheme->tui.panel_roundness = 0.4f;
}
if (!USER_VERSION_ATLEAST(300, 37)) {
btheme->space_node.dash_alpha = 0.5f;
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -240,6 +240,7 @@ typedef enum ThemeColorID {
TH_NODE_CURVING,
TH_NODE_GRID_LEVELS,
TH_NODE_DASH_ALPHA,
TH_MARKER_OUTLINE,
TH_MARKER,

View File

@ -657,6 +657,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_NODE_GRID_LEVELS:
cp = &ts->grid_levels;
break;
case TH_NODE_DASH_ALPHA:
cp = &ts->dash_alpha;
break;
case TH_SEQ_MOVIE:
cp = ts->movie;

View File

@ -3944,15 +3944,17 @@ static struct {
GPUBatch *batch_single; /* for single line */
GPUVertBuf *inst_vbo;
uint p0_id, p1_id, p2_id, p3_id;
uint colid_id, muted_id;
uint colid_id, muted_id, start_color_id, end_color_id;
uint dim_factor_id;
uint thickness_id;
uint dash_factor_id;
uint dash_alpha_id;
GPUVertBufRaw p0_step, p1_step, p2_step, p3_step;
GPUVertBufRaw colid_step, muted_step;
GPUVertBufRaw colid_step, muted_step, start_color_step, end_color_step;
GPUVertBufRaw dim_factor_step;
GPUVertBufRaw thickness_step;
GPUVertBufRaw dash_factor_step;
GPUVertBufRaw dash_alpha_step;
uint count;
bool enabled;
} g_batch_link;
@ -3973,6 +3975,12 @@ static void nodelink_batch_reset()
g_batch_link.inst_vbo, g_batch_link.thickness_id, &g_batch_link.thickness_step);
GPU_vertbuf_attr_get_raw_data(
g_batch_link.inst_vbo, g_batch_link.dash_factor_id, &g_batch_link.dash_factor_step);
GPU_vertbuf_attr_get_raw_data(
g_batch_link.inst_vbo, g_batch_link.dash_alpha_id, &g_batch_link.dash_alpha_step);
GPU_vertbuf_attr_get_raw_data(
g_batch_link.inst_vbo, g_batch_link.start_color_id, &g_batch_link.start_color_step);
GPU_vertbuf_attr_get_raw_data(
g_batch_link.inst_vbo, g_batch_link.end_color_id, &g_batch_link.end_color_step);
g_batch_link.count = 0;
}
@ -4088,6 +4096,10 @@ static void nodelink_batch_init()
&format_inst, "P3", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
g_batch_link.colid_id = GPU_vertformat_attr_add(
&format_inst, "colid_doarrow", GPU_COMP_U8, 4, GPU_FETCH_INT);
g_batch_link.start_color_id = GPU_vertformat_attr_add(
&format_inst, "start_color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
g_batch_link.end_color_id = GPU_vertformat_attr_add(
&format_inst, "end_color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
g_batch_link.muted_id = GPU_vertformat_attr_add(
&format_inst, "domuted", GPU_COMP_U8, 2, GPU_FETCH_INT);
g_batch_link.dim_factor_id = GPU_vertformat_attr_add(
@ -4096,6 +4108,8 @@ static void nodelink_batch_init()
&format_inst, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
g_batch_link.dash_factor_id = GPU_vertformat_attr_add(
&format_inst, "dash_factor", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
g_batch_link.dash_alpha_id = GPU_vertformat_attr_add(
&format_inst, "dash_alpha", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
g_batch_link.inst_vbo = GPU_vertbuf_create_with_format_ex(&format_inst, GPU_USAGE_STREAM);
/* Alloc max count but only draw the range we need. */
GPU_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE);
@ -4170,11 +4184,14 @@ static void nodelink_batch_add_link(const SpaceNode *snode,
int th_col1,
int th_col2,
int th_col3,
const float start_color[4],
const float end_color[4],
bool drawarrow,
bool drawmuted,
float dim_factor,
float thickness,
float dash_factor)
float dash_factor,
float dash_alpha)
{
/* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
@ -4191,11 +4208,14 @@ static void nodelink_batch_add_link(const SpaceNode *snode,
colid[1] = nodelink_get_color_id(th_col2);
colid[2] = nodelink_get_color_id(th_col3);
colid[3] = drawarrow;
copy_v4_v4((float *)GPU_vertbuf_raw_step(&g_batch_link.start_color_step), start_color);
copy_v4_v4((float *)GPU_vertbuf_raw_step(&g_batch_link.end_color_step), end_color);
char *muted = (char *)GPU_vertbuf_raw_step(&g_batch_link.muted_step);
muted[0] = drawmuted;
*(float *)GPU_vertbuf_raw_step(&g_batch_link.dim_factor_step) = dim_factor;
*(float *)GPU_vertbuf_raw_step(&g_batch_link.thickness_step) = thickness;
*(float *)GPU_vertbuf_raw_step(&g_batch_link.dash_factor_step) = dash_factor;
*(float *)GPU_vertbuf_raw_step(&g_batch_link.dash_alpha_step) = dash_alpha;
if (g_batch_link.count == NODELINK_GROUP_SIZE) {
nodelink_batch_draw(snode);
@ -4213,6 +4233,10 @@ void node_draw_link_bezier(const View2D *v2d,
const float dim_factor = node_link_dim_factor(v2d, link);
float thickness = 1.5f;
float dash_factor = 1.0f;
bTheme *btheme = UI_GetTheme();
const float dash_alpha = btheme->space_node.dash_alpha;
if (snode->edittree->type == NTREE_GEOMETRY) {
if (link->fromsock && link->fromsock->display_shape == SOCK_DISPLAY_SHAPE_DIAMOND) {
/* Make field links a bit thinner. */
@ -4231,6 +4255,32 @@ void node_draw_link_bezier(const View2D *v2d,
if (g_batch_link.batch == nullptr) {
nodelink_batch_init();
}
/* Draw single link. */
float colors[3][4] = {{0.0f}};
if (th_col3 != -1) {
UI_GetThemeColor4fv(th_col3, colors[0]);
}
if (snode->overlay.flag & SN_OVERLAY_SHOW_OVERLAYS &&
snode->overlay.flag & SN_OVERLAY_SHOW_WIRE_COLORS) {
if (link->fromsock) {
copy_v4_v4(colors[1], std_node_socket_colors[link->fromsock->typeinfo->type]);
}
else {
copy_v4_v4(colors[1], std_node_socket_colors[link->tosock->typeinfo->type]);
}
if (link->tosock) {
copy_v4_v4(colors[2], std_node_socket_colors[link->tosock->typeinfo->type]);
}
else {
copy_v4_v4(colors[2], std_node_socket_colors[link->fromsock->typeinfo->type]);
}
}
else {
UI_GetThemeColor4fv(th_col1, colors[1]);
UI_GetThemeColor4fv(th_col2, colors[2]);
}
if (g_batch_link.enabled && !highlighted) {
/* Add link to batch. */
@ -4242,21 +4292,16 @@ void node_draw_link_bezier(const View2D *v2d,
th_col1,
th_col2,
th_col3,
colors[1],
colors[2],
drawarrow,
drawmuted,
dim_factor,
thickness,
dash_factor);
dash_factor,
dash_alpha);
}
else {
/* Draw single link. */
float colors[3][4] = {{0.0f}};
if (th_col3 != -1) {
UI_GetThemeColor4fv(th_col3, colors[0]);
}
UI_GetThemeColor4fv(th_col1, colors[1]);
UI_GetThemeColor4fv(th_col2, colors[2]);
if (highlighted) {
float link_preselection_highlight_color[4];
UI_GetThemeColor4fv(TH_SELECT, link_preselection_highlight_color);
@ -4274,6 +4319,7 @@ void node_draw_link_bezier(const View2D *v2d,
GPU_batch_uniform_1f(batch, "dim_factor", dim_factor);
GPU_batch_uniform_1f(batch, "thickness", thickness);
GPU_batch_uniform_1f(batch, "dash_factor", dash_factor);
GPU_batch_uniform_1f(batch, "dash_alpha", dash_alpha);
GPU_batch_draw(batch);
}
}

View File

@ -2299,7 +2299,7 @@ void node_draw_space(const bContext *C, ARegion *region)
GPU_line_smooth(false);
GPU_blend(GPU_BLEND_NONE);
if (snode->flag & SNODE_SHOW_GPENCIL) {
if (snode->overlay.flag & SN_OVERLAY_SHOW_OVERLAYS && snode->flag & SNODE_SHOW_GPENCIL) {
/* Draw grease-pencil annotations. */
ED_annotation_draw_view2d(C, true);
}
@ -2318,7 +2318,7 @@ void node_draw_space(const bContext *C, ARegion *region)
UI_view2d_view_restore(C);
if (snode->treepath.last) {
if (snode->flag & SNODE_SHOW_GPENCIL) {
if (snode->overlay.flag & SN_OVERLAY_SHOW_OVERLAYS && snode->flag & SNODE_SHOW_GPENCIL) {
/* Draw grease-pencil (screen strokes, and also paint-buffer). */
ED_annotation_draw_view2d(C, false);
}

View File

@ -4,12 +4,14 @@ in vec4 finalColor;
in float lineU;
flat in float lineLength;
flat in float dashFactor;
flat in float dashAlpha;
flat in int isMainLine;
out vec4 fragColor;
#define DASH_WIDTH 20.0
#define DASH_WIDTH 10.0
#define ANTIALIAS 1.0
#define MINIMUM_ALPHA 0.5
void main()
{
@ -29,7 +31,7 @@ void main()
float slope = 1.0 / (2.0 * t);
float unclamped_alpha = 1.0 - slope * (normalized_distance_triangle - dashFactor + t);
float alpha = max(0.0, min(unclamped_alpha, 1.0));
float alpha = max(dashAlpha, min(unclamped_alpha, 1.0));
fragColor.a *= alpha;
}

View File

@ -17,15 +17,18 @@ in vec2 P1;
in vec2 P2;
in vec2 P3;
in ivec4 colid_doarrow;
in vec4 start_color;
in vec4 end_color;
in ivec2 domuted;
in float dim_factor;
in float thickness;
in float dash_factor;
in float dash_alpha;
uniform vec4 colors[6];
# define colStart colors[colid_doarrow[0]]
# define colEnd colors[colid_doarrow[1]]
# define colStart (colid_doarrow[0] < 3 ? start_color : colors[colid_doarrow[0]])
# define colEnd (colid_doarrow[1] < 3 ? end_color : colors[colid_doarrow[1]])
# define colShadow colors[colid_doarrow[2]]
# define doArrow (colid_doarrow[3] != 0)
# define doMuted (domuted[0] != 0)
@ -61,13 +64,20 @@ out vec4 finalColor;
out float lineU;
flat out float lineLength;
flat out float dashFactor;
flat out float dashAlpha;
flat out int isMainLine;
/* Define where along the noodle the gradient will starts and ends.
* Use 0.25 instead of 0.35-0.65, because of a visual shift issue. */
const float start_gradient_threshold = 0.25;
const float end_gradient_threshold = 0.55;
void main(void)
{
/* Parameters for the dashed line. */
isMainLine = expand.y != 1.0 ? 0 : 1;
dashFactor = dash_factor;
dashAlpha = dash_alpha;
/* Approximate line length, no need for real bezier length calculation. */
lineLength = distance(P0, P3);
/* TODO: Incorrect U, this leads to non-uniform dash distribution. */
@ -109,7 +119,16 @@ void main(void)
}
else {
/* Second pass */
finalColor = mix(colStart, colEnd, uv.x);
if (uv.x < start_gradient_threshold) {
finalColor = colStart;
}
else if (uv.x > end_gradient_threshold) {
finalColor = colEnd;
}
else {
/* Add 0.1 to avoid a visual shift issue. */
finalColor = mix(colStart, colEnd, uv.x + 0.1);
}
expand_dist *= 0.5;
if (doMuted) {
finalColor[3] = 0.65;

View File

@ -1509,6 +1509,15 @@ typedef struct bNodeTreePath {
char display_name[64];
} bNodeTreePath;
typedef struct SpaceNodeOverlay {
int flag;
} SpaceNodeOverlay;
typedef enum eSpaceNodeOverlay_Flag {
SN_OVERLAY_SHOW_OVERLAYS = (1 << 1),
SN_OVERLAY_SHOW_WIRE_COLORS = (1 << 2),
} eSpaceNodeOverlay_Flag;
typedef struct SpaceNode {
SpaceLink *next, *prev;
/** Storage of regions for inactive spaces. */
@ -1562,6 +1571,9 @@ typedef struct SpaceNode {
/** Grease-pencil data. */
struct bGPdata *gpd;
SpaceNodeOverlay overlay;
char _pad2[4];
SpaceNode_Runtime *runtime;
} SpaceNode;

View File

@ -206,7 +206,6 @@ typedef struct ThemeUI {
/** Intensity of the border icons. >0 will render an border around themed
* icons. */
float icon_border_intensity;
float panel_roundness;
char _pad2[4];
@ -323,6 +322,8 @@ typedef struct ThemeSpace {
unsigned char vertex_size, outline_width, obcenter_dia, facedot_size;
unsigned char noodle_curving;
unsigned char grid_levels;
char _pad5[3];
float dash_alpha;
/* syntax for textwindow and nodes */
unsigned char syntaxl[4], syntaxs[4]; /* in nodespace used for backdrop matte */
@ -345,6 +346,7 @@ typedef struct ThemeSpace {
unsigned char active_strip[4], selected_strip[4];
/** For dopesheet - scale factor for size of keyframes (i.e. height of channels). */
char _pad7[1];
float keyframe_scale_fac;
unsigned char editmesh_active[4];

View File

@ -2348,6 +2348,15 @@ static char *rna_SpaceSequencerTimelineOverlay_path(PointerRNA *UNUSED(ptr))
}
/* Space Node Editor */
static PointerRNA rna_SpaceNode_overlay_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_SpaceNodeOverlay, ptr->data);
}
static char *rna_SpaceNodeOverlay_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("overlay");
}
static void rna_SpaceNodeEditor_node_tree_set(PointerRNA *ptr,
const PointerRNA value,
@ -7004,6 +7013,32 @@ static void rna_def_space_node_path_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
}
static void rna_def_space_node_overlay(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "SpaceNodeOverlay", NULL);
RNA_def_struct_sdna(srna, "SpaceNode");
RNA_def_struct_nested(brna, srna, "SpaceNodeEditor");
RNA_def_struct_path_func(srna, "rna_SpaceNodeOverlay_path");
RNA_def_struct_ui_text(
srna, "Overlay Settings", "Settings for display of overlays in the Node Editor");
prop = RNA_def_property(srna, "show_overlays", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", SN_OVERLAY_SHOW_OVERLAYS);
RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop, "Show Overlays", "Display overlays like colored or dashed wires");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
prop = RNA_def_property(srna, "show_wire_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", SN_OVERLAY_SHOW_WIRE_COLORS);
RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(
prop, "Show Wire Colors", "Color node links based on their connected sockets");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
}
static void rna_def_space_node(BlenderRNA *brna)
{
StructRNA *srna;
@ -7187,6 +7222,15 @@ static void rna_def_space_node(BlenderRNA *brna)
prop, "Auto-offset Direction", "Direction to offset nodes on insertion");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
/* Overlays */
prop = RNA_def_property(srna, "overlay", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "SpaceNodeOverlay");
RNA_def_property_pointer_funcs(prop, "rna_SpaceNode_overlay_get", NULL, NULL, NULL);
RNA_def_property_ui_text(
prop, "Overlay Settings", "Settings for display of overlays in the Node Editor");
rna_def_space_node_overlay(brna);
RNA_api_space_node(srna);
}

View File

@ -2917,6 +2917,12 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
prop, "Grid Levels", "Amount of grid lines displayed in the background");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
prop = RNA_def_property(srna, "dash_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_ui_text(prop, "Dashed Lines Opacity", "Opacity for the dashed lines in wires");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
prop = RNA_def_property(srna, "input_node", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "syntaxn");
RNA_def_property_array(prop, 3);