From 9f7bb766b2cba12156fd92f5e79075887ad5c81c Mon Sep 17 00:00:00 2001 From: Leon Schittek Date: Fri, 8 Mar 2024 14:22:04 +0100 Subject: [PATCH 01/11] WIP: Add new node socket shader Add a new shader for node sockets and add a grip area to reroute node. --- source/blender/editors/include/ED_node.hh | 2 - .../blender/editors/include/UI_interface_c.hh | 7 + .../editors/interface/interface_draw.cc | 41 ++ .../editors/interface/interface_intern.hh | 12 + .../editors/interface/interface_widgets.cc | 22 + .../blender/editors/space_node/node_draw.cc | 631 +++++++----------- .../blender/editors/space_node/node_edit.cc | 2 +- .../blender/editors/space_node/node_intern.hh | 1 - .../blender/editors/space_node/node_select.cc | 7 - source/blender/gpu/CMakeLists.txt | 3 + source/blender/gpu/GPU_shader_builtin.h | 4 + .../blender/gpu/intern/gpu_shader_builtin.cc | 4 + .../gpu_shader_2D_node_socket_frag.glsl | 46 ++ .../gpu_shader_2D_node_socket_vert.glsl | 120 ++++ .../infos/gpu_shader_2D_node_socket_info.hh | 49 ++ 15 files changed, 537 insertions(+), 414 deletions(-) create mode 100644 source/blender/gpu/shaders/gpu_shader_2D_node_socket_frag.glsl create mode 100644 source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl create mode 100644 source/blender/gpu/shaders/infos/gpu_shader_2D_node_socket_info.hh diff --git a/source/blender/editors/include/ED_node.hh b/source/blender/editors/include/ED_node.hh index ab6c6058e66..4c92a970784 100644 --- a/source/blender/editors/include/ED_node.hh +++ b/source/blender/editors/include/ED_node.hh @@ -37,8 +37,6 @@ void node_insert_on_link_flags_clear(bNodeTree &node_tree); /** * Draw a single node socket at default size. - * \note this is only called from external code, internally #node_socket_draw_nested() is used for - * optimized drawing of multiple/all sockets of a node. */ void node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale); diff --git a/source/blender/editors/include/UI_interface_c.hh b/source/blender/editors/include/UI_interface_c.hh index 3bdf931048d..614653a34fc 100644 --- a/source/blender/editors/include/UI_interface_c.hh +++ b/source/blender/editors/include/UI_interface_c.hh @@ -491,6 +491,13 @@ void UI_draw_roundbox_4fv_ex(const rctf *rect, const float outline[4], float outline_width, float rad); +void UI_draw_node_socket(const rctf *rect, + const float color_inner[4], + const float color_outline[4], + float outline_thickness, + float dot_thickness, + float border_offset, + int flags); #if 0 /* unused */ int UI_draw_roundbox_corner_get(); diff --git a/source/blender/editors/interface/interface_draw.cc b/source/blender/editors/interface/interface_draw.cc index 864d4e1bde0..79a6455f3f5 100644 --- a/source/blender/editors/interface/interface_draw.cc +++ b/source/blender/editors/interface/interface_draw.cc @@ -228,6 +228,47 @@ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const flo immUnbindProgram(); } +void UI_draw_node_socket(const rctf *rect, + const float color_inner[4], + const float color_outline[4], + const float outline_thickness, + const float dot_thickness, + const float border_offset, + const int flags) +{ + /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. + * If it has been scaled, then it's no longer valid. */ + uiNodeSocketParameters socket_params = {}; + socket_params.rect = *rect; + socket_params.color_inner[0] = color_inner ? color_inner[0] : 0.0f; + socket_params.color_inner[1] = color_inner ? color_inner[1] : 0.0f; + socket_params.color_inner[2] = color_inner ? color_inner[2] : 0.0f; + socket_params.color_inner[3] = color_inner ? color_inner[3] : 0.0f; + socket_params.color_outline[0] = color_outline ? color_outline[0] : + color_inner ? color_inner[0] : + 0.0f; + socket_params.color_outline[1] = color_outline ? color_outline[1] : + color_inner ? color_inner[1] : + 0.0f; + socket_params.color_outline[2] = color_outline ? color_outline[2] : + color_inner ? color_inner[2] : + 0.0f; + socket_params.color_outline[3] = color_outline ? color_outline[3] : + color_inner ? color_inner[3] : + 0.0f; + socket_params.outline_thickness = outline_thickness; + socket_params.dot_thickness = dot_thickness; + socket_params.border_offset = border_offset; + + GPUBatch *batch = ui_batch_node_socket_get(); + GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); + GPU_batch_uniform_4fv_array(batch, "parameters", 4, (const float(*)[4]) & socket_params); + GPU_batch_uniform_1i(batch, "shape_flags", flags); + GPU_blend(GPU_BLEND_ALPHA); + GPU_batch_draw(batch); + GPU_blend(GPU_BLEND_NONE); +} + /* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */ void ui_draw_but_TAB_outline(const rcti *rect, diff --git a/source/blender/editors/interface/interface_intern.hh b/source/blender/editors/interface/interface_intern.hh index 72f9ee05eb7..03c25172e3b 100644 --- a/source/blender/editors/interface/interface_intern.hh +++ b/source/blender/editors/interface/interface_intern.hh @@ -1183,6 +1183,17 @@ struct uiWidgetBaseParameters { float _pad[3]; }; +/* Node Socket shader parameters, must match the shader layout. */ +struct uiNodeSocketParameters { + rctf rect; + float color_inner[4]; + float color_outline[4]; + float outline_thickness; + float dot_thickness; + float border_offset; + float _pad[1]; +}; + enum { ROUNDBOX_TRIA_NONE = 0, ROUNDBOX_TRIA_ARROWS, @@ -1197,6 +1208,7 @@ enum { GPUBatch *ui_batch_roundbox_widget_get(); GPUBatch *ui_batch_roundbox_shadow_get(); +GPUBatch *ui_batch_node_socket_get(); void ui_draw_menu_back(uiStyle *style, uiBlock *block, rcti *rect); void ui_draw_popover_back(ARegion *region, uiStyle *style, uiBlock *block, rcti *rect); diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index 439dc89ab2f..7f9feea1f9c 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -394,6 +394,7 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} static struct { GPUBatch *roundbox_widget; GPUBatch *roundbox_shadow; + GPUBatch *node_socket; /* TODO: remove. */ GPUVertFormat format; @@ -501,6 +502,27 @@ GPUBatch *ui_batch_roundbox_shadow_get() return g_ui_batch_cache.roundbox_shadow; } +GPUBatch *ui_batch_node_socket_get(void) +{ + if (g_ui_batch_cache.node_socket == NULL) { + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format()); + + GPU_vertbuf_data_alloc(vbo, 6); + + GPUIndexBufBuilder ibuf; + GPU_indexbuf_init(&ibuf, GPU_PRIM_TRIS, 2, 4); + /* Quad to draw the node socket in. */ + GPU_indexbuf_add_tri_verts(&ibuf, 0, 1, 2); + GPU_indexbuf_add_tri_verts(&ibuf, 2, 1, 3); + + g_ui_batch_cache.node_socket = GPU_batch_create_ex( + GPU_PRIM_TRIS, vbo, GPU_indexbuf_build(&ibuf), GPU_BATCH_OWNS_INDEX | GPU_BATCH_OWNS_VBO); + gpu_batch_presets_register(g_ui_batch_cache.node_socket); + } + return g_ui_batch_cache.node_socket; +} + + #undef INNER #undef OUTLINE #undef EMBOSS diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 83370531f68..394d27df68e 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -1132,78 +1132,6 @@ static void node_draw_mute_line(const bContext &C, GPU_blend(GPU_BLEND_NONE); } -static void node_socket_draw(const bNodeSocket &sock, - const float color[4], - const float color_outline[4], - const float size, - const float locx, - const float locy, - uint pos_id, - uint col_id, - uint shape_id, - uint size_id, - uint outline_col_id) -{ - int flags; - - /* Set shape flags. */ - switch (sock.display_shape) { - case SOCK_DISPLAY_SHAPE_DIAMOND: - case SOCK_DISPLAY_SHAPE_DIAMOND_DOT: - flags = GPU_KEYFRAME_SHAPE_DIAMOND; - break; - case SOCK_DISPLAY_SHAPE_SQUARE: - case SOCK_DISPLAY_SHAPE_SQUARE_DOT: - flags = GPU_KEYFRAME_SHAPE_SQUARE; - break; - default: - case SOCK_DISPLAY_SHAPE_CIRCLE: - case SOCK_DISPLAY_SHAPE_CIRCLE_DOT: - flags = GPU_KEYFRAME_SHAPE_CIRCLE; - break; - } - - if (ELEM(sock.display_shape, - SOCK_DISPLAY_SHAPE_DIAMOND_DOT, - SOCK_DISPLAY_SHAPE_SQUARE_DOT, - SOCK_DISPLAY_SHAPE_CIRCLE_DOT)) - { - flags |= GPU_KEYFRAME_SHAPE_INNER_DOT; - } - - immAttr4fv(col_id, color); - immAttr1u(shape_id, flags); - immAttr1f(size_id, size); - immAttr4fv(outline_col_id, color_outline); - immVertex2f(pos_id, locx, locy); -} - -static void node_socket_draw_multi_input(const float color[4], - const float color_outline[4], - const float width, - const float height, - const float2 location) -{ - /* The other sockets are drawn with the keyframe shader. There, the outline has a base - * thickness that can be varied but always scales with the size the socket is drawn at. Using - * `UI_SCALE_FAC` has the same effect here. It scales the outline correctly across different - * screen DPI's and UI scales without being affected by the 'line-width'. */ - const float outline_width = NODE_SOCK_OUTLINE_SCALE * UI_SCALE_FAC; - - /* UI_draw_roundbox draws the outline on the outer side, so compensate for the outline width. - */ - const rctf rect = { - location.x - width + outline_width * 0.5f, - location.x + width - outline_width * 0.5f, - location.y - height + outline_width * 0.5f, - location.y + height - outline_width * 0.5f, - }; - - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_4fv_ex( - &rect, color, nullptr, 1.0f, color_outline, outline_width, width - outline_width * 0.5f); -} - static const float virtual_node_socket_outline_color[4] = {0.5, 0.5, 0.5, 1.0}; static void node_socket_outline_color_get(const bool selected, @@ -1693,121 +1621,28 @@ void node_socket_add_tooltip(const bNodeTree &ntree, const bNodeSocket &sock, ui MEM_freeN); } -static void node_socket_draw_nested(const bContext &C, - const bNodeTree &ntree, - PointerRNA &node_ptr, - uiBlock &block, - const bNodeSocket &sock, - const uint pos_id, - const uint col_id, - const uint shape_id, - const uint size_id, - const uint outline_col_id, - const float size, - const bool selected) -{ - const float2 location = sock.runtime->location; - - float color[4]; - float outline_color[4]; - node_socket_color_get(C, ntree, node_ptr, sock, color); - node_socket_outline_color_get(selected, sock.type, outline_color); - - node_socket_draw(sock, - color, - outline_color, - size, - location.x, - location.y, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id); - - if (!node_socket_has_tooltip(ntree, sock)) { - return; - } - - /* Ideally sockets themselves should be buttons, but they aren't currently. So add an invisible - * button on top of them for the tooltip. */ - const eUIEmbossType old_emboss = UI_block_emboss_get(&block); - UI_block_emboss_set(&block, UI_EMBOSS_NONE); - uiBut *but = uiDefIconBut(&block, - UI_BTYPE_BUT, - 0, - ICON_NONE, - location.x - size / 2.0f, - location.y - size / 2.0f, - size, - size, - nullptr, - 0, - 0, - nullptr); - - UI_but_func_tooltip_set( - but, - [](bContext *C, void *argN, const char * /*tip*/) { - const SpaceNode &snode = *CTX_wm_space_node(C); - const bNodeTree &ntree = *snode.edittree; - const int index_in_tree = POINTER_AS_INT(argN); - ntree.ensure_topology_cache(); - return node_socket_get_tooltip(&snode, ntree, *ntree.all_sockets()[index_in_tree]); - }, - POINTER_FROM_INT(sock.index_in_tree()), - nullptr); - /* Disable the button so that clicks on it are ignored the link operator still works. */ - UI_but_flag_enable(but, UI_BUT_DISABLED); - UI_block_emboss_set(&block, old_emboss); -} +#define NODE_SOCKET_OUTLINE U.pixelsize +#define NODE_SOCKET_DOT U.scale_factor void node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale) { - const float size = NODE_SOCKSIZE_DRAW_MULIPLIER * NODE_SOCKSIZE * scale; - rcti draw_rect = *rect; + const float radius = NODE_SOCKSIZE * scale; + const float2 center = {BLI_rcti_cent_x_fl(rect), BLI_rcti_cent_y_fl(rect)}; + const rctf draw_rect = { + center.x - radius, + center.x + radius, + center.y - radius, + center.y + radius, + }; float outline_color[4] = {0}; - node_socket_outline_color_get(sock->flag & SELECT, sock->type, outline_color); - - BLI_rcti_resize(&draw_rect, size, size); - - GPUVertFormat *format = immVertexFormat(); - uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); - uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - uint outline_col_id = GPU_vertformat_attr_add( - format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - - eGPUBlend state = GPU_blend_get(); - GPU_blend(GPU_BLEND_ALPHA); - GPU_program_point_size(true); - - immBindBuiltinProgram(GPU_SHADER_KEYFRAME_SHAPE); - immUniform1f("outline_scale", NODE_SOCK_OUTLINE_SCALE); - immUniform2f("ViewportSize", -1.0f, -1.0f); - - /* Single point. */ - immBegin(GPU_PRIM_POINTS, 1); - node_socket_draw(*sock, - color, - outline_color, - BLI_rcti_size_y(&draw_rect), - BLI_rcti_cent_x(&draw_rect), - BLI_rcti_cent_y(&draw_rect), - pos_id, - col_id, - shape_id, - size_id, - outline_col_id); - immEnd(); - - immUnbindProgram(); - GPU_program_point_size(false); - - /* Restore. */ - GPU_blend(state); + UI_draw_node_socket(&draw_rect, + color, + outline_color, + NODE_SOCKET_OUTLINE * scale, + NODE_SOCKET_DOT * scale, + 0.0f, + sock->display_shape); } static void node_draw_preview_background(rctf *rect) @@ -1915,207 +1750,92 @@ static void node_draw_shadow(const SpaceNode &snode, UI_draw_roundbox_4fv(&rect, false, radius + 0.5f, color); } -static void node_draw_sockets(const View2D &v2d, - const bContext &C, - const bNodeTree &ntree, - const bNode &node, - uiBlock &block, - const bool draw_outputs, - const bool select_all) +static void node_draw_socket_ex(const bContext &C, + const bNodeTree &ntree, + const bNode &node, + PointerRNA &node_ptr, + const bNodeSocket &sock, + const float outline_thickness, + const float border_offset, + const float dot_radius, + const bool selected) +{ + const float half_width = NODE_SOCKSIZE; + + const bool multi_socket = (sock.flag & SOCK_MULTI_INPUT) && !(node.flag & NODE_HIDDEN); + float half_height = multi_socket ? node_socket_calculate_height(sock) : half_width; + + ColorTheme4f socket_color; + ColorTheme4f outline_color; + node_socket_color_get(C, ntree, node_ptr, sock, socket_color); + node_socket_outline_color_get(selected, sock.type, outline_color); + + const float2 socket_location = sock.runtime->location; + + const rctf rect = { + socket_location.x - half_width, + socket_location.x + half_width, + socket_location.y - half_height, + socket_location.y + half_height, + }; + + UI_draw_node_socket(&rect, + socket_color, + outline_color, + outline_thickness, + dot_radius, + border_offset, + sock.display_shape); +} + +/* Some elements of the node tree like labels or node sockets are hardly visible when zoomed + * out and can slow down the drawing quite a bit, when there are a lot of elements. + * This function can be used to check if it's worth to draw those details and return + * early. */ +static bool draw_node_details(const View2D &v2d) +{ + float scale; + UI_view2d_scale_get(&v2d, &scale, nullptr); + return scale > 0.2f * UI_INV_SCALE_FAC; +} + +static void node_draw_sockets_ex(const bContext &C, + bNodeTree &ntree, + const bNode &node, + const float outline_thickness, + const float border_offset, + const float dot_radius, + const bool select_all) { if (node.input_sockets().is_empty() && node.output_sockets().is_empty()) { return; } - bool selected = false; - - GPUVertFormat *format = immVertexFormat(); - uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); - uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - uint outline_col_id = GPU_vertformat_attr_add( - format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - - GPU_blend(GPU_BLEND_ALPHA); - GPU_program_point_size(true); - immBindBuiltinProgram(GPU_SHADER_KEYFRAME_SHAPE); - immUniform1f("outline_scale", NODE_SOCK_OUTLINE_SCALE); - immUniform2f("ViewportSize", -1.0f, -1.0f); - - /* Set handle size. */ - const float socket_draw_size = NODE_SOCKSIZE * NODE_SOCKSIZE_DRAW_MULIPLIER; - float scale; - UI_view2d_scale_get(&v2d, &scale, nullptr); - scale *= socket_draw_size; - - if (!select_all) { - immBeginAtMost(GPU_PRIM_POINTS, node.input_sockets().size() + node.output_sockets().size()); - } - - PointerRNA node_ptr = RNA_pointer_create( - &const_cast(ntree.id), &RNA_Node, &const_cast(node)); - + PointerRNA nodeptr = RNA_pointer_create( + const_cast(&ntree.id), &RNA_Node, const_cast(&node)); /* Socket inputs. */ - int selected_input_len = 0; for (const bNodeSocket *sock : node.input_sockets()) { - /* In "hidden" nodes: draw sockets even when panels are collapsed. */ if (!node.is_socket_icon_drawn(*sock)) { continue; } - if (select_all || (sock->flag & SELECT)) { - if (!(sock->flag & SOCK_MULTI_INPUT)) { - /* Don't add multi-input sockets here since they are drawn in a different batch. */ - selected_input_len++; - } - continue; - } - /* Don't draw multi-input sockets here since they are drawn in a different batch. */ - if (sock->flag & SOCK_MULTI_INPUT) { - continue; - } - - node_socket_draw_nested(C, - ntree, - node_ptr, - block, - *sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_draw_socket_ex( + C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, select_all); } /* Socket outputs. */ - int selected_output_len = 0; - if (draw_outputs) { - for (const bNodeSocket *sock : node.output_sockets()) { - /* In "hidden" nodes: draw sockets even when panels are collapsed. */ - if (!node.is_socket_icon_drawn(*sock)) { - continue; - } - if (select_all || (sock->flag & SELECT)) { - selected_output_len++; - continue; - } - - node_socket_draw_nested(C, - ntree, - node_ptr, - block, - *sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); - } - } - - if (!select_all) { - immEnd(); - } - - /* Go back and draw selected sockets. */ - if (selected_input_len + selected_output_len > 0) { - /* Outline for selected sockets. */ - - selected = true; - - immBegin(GPU_PRIM_POINTS, selected_input_len + selected_output_len); - - if (selected_input_len) { - /* Socket inputs. */ - for (const bNodeSocket *sock : node.input_sockets()) { - if (!node.is_socket_icon_drawn(*sock)) { - continue; - } - /* Don't draw multi-input sockets here since they are drawn in a different batch. */ - if (sock->flag & SOCK_MULTI_INPUT) { - continue; - } - if (select_all || (sock->flag & SELECT)) { - node_socket_draw_nested(C, - ntree, - node_ptr, - block, - *sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); - if (--selected_input_len == 0) { - /* Stop as soon as last one is drawn. */ - break; - } - } - } - } - - if (selected_output_len) { - /* Socket outputs. */ - for (const bNodeSocket *sock : node.output_sockets()) { - if (!node.is_socket_icon_drawn(*sock)) { - continue; - } - if (select_all || (sock->flag & SELECT)) { - node_socket_draw_nested(C, - ntree, - node_ptr, - block, - *sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); - if (--selected_output_len == 0) { - /* Stop as soon as last one is drawn. */ - break; - } - } - } - } - - immEnd(); - } - - immUnbindProgram(); - - GPU_program_point_size(false); - GPU_blend(GPU_BLEND_NONE); - - /* Draw multi-input sockets after the others because they are drawn with `UI_draw_roundbox` - * rather than with `GL_POINT`. */ - for (const bNodeSocket *socket : node.input_sockets()) { - if (!node.is_socket_icon_drawn(*socket)) { - continue; - } - if (!(socket->flag & SOCK_MULTI_INPUT)) { + for (const bNodeSocket *sock : node.output_sockets()) { + if (!node.is_socket_icon_drawn(*sock)) { continue; } + node_draw_socket_ex( + C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, select_all); + } +} - const bool is_node_hidden = (node.flag & NODE_HIDDEN); - const float width = 0.5f * socket_draw_size; - float height = is_node_hidden ? width : node_socket_calculate_height(*socket) - width; - - float color[4]; - float outline_color[4]; - node_socket_color_get(C, ntree, node_ptr, *socket, color); - node_socket_outline_color_get(socket->flag & SELECT, socket->type, outline_color); - - const float2 location = socket->runtime->location; - node_socket_draw_multi_input(color, outline_color, width, height, location); +void node_draw_sockets(const View2D &v2d, const bContext &C, bNodeTree &ntree, const bNode &node) +{ + if (draw_node_details(v2d)) { + node_draw_sockets_ex(C, ntree, node, NODE_SOCKET_OUTLINE, 0.0f, NODE_SOCKET_DOT, false); } } @@ -3310,13 +3030,7 @@ 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) { - node_draw_sockets(v2d, C, ntree, node, block, true, false); - } + node_draw_sockets(v2d, C, ntree, node); if (is_node_panels_supported(node)) { node_draw_panels(ntree, node, block); @@ -3496,7 +3210,7 @@ static void node_draw_hidden(const bContext &C, immUnbindProgram(); GPU_blend(GPU_BLEND_NONE); - node_draw_sockets(v2d, C, ntree, node, block, true, false); + node_draw_sockets(v2d, C, ntree, node); UI_block_end(&C, &block); UI_block_draw(&C, &block); @@ -3641,20 +3355,51 @@ static void frame_node_prepare_for_draw(bNode &node, Span nodes) node.runtime->totr = rect; } -static void reroute_node_prepare_for_draw(bNode &node) +#define NODE_REROUTE_SIZE (3.0f * NODE_SOCKSIZE) +#define NODE_REROUTE_HIDDEN_SIZE 8.0f +static void reroute_node_prepare_for_draw_basis(bNode &node) +{ + /* Get "global" coordinates. */ + const float2 loc = node_to_view(node, float2(0)); + + const float half_width = NODE_REROUTE_SIZE; + const float half_height = NODE_SOCKSIZE; + const float2 x_offset(half_width - half_height, 0); + + /* Reroute nodes have exactly one input and one output. */ + node.input_socket(0).runtime->location = loc - x_offset; + node.output_socket(0).runtime->location = loc + x_offset; + + node.width = half_width * 2; + node.runtime->totr.xmin = (loc.x - half_width); + node.runtime->totr.xmax = (loc.x + half_width); + node.runtime->totr.ymax = (loc.y + half_height); + node.runtime->totr.ymin = (loc.y - half_height); +} +static void reroute_node_prepare_for_draw_hidden(bNode &node) { const float2 loc = node_to_view(node, float2(0)); - /* Reroute node has exactly one input and one output, both in the same place. */ + /* When the node is hidden, the input and output socket are both in the same place. */ node.input_socket(0).runtime->location = loc; node.output_socket(0).runtime->location = loc; - const float size = 8.0f; - node.width = size * 2; - node.runtime->totr.xmin = loc.x - size; - node.runtime->totr.xmax = loc.x + size; - node.runtime->totr.ymax = loc.y + size; - node.runtime->totr.ymin = loc.y - size; + const float radius = NODE_SOCKSIZE; + node.width = radius * 2; + node.runtime->totr.xmin = loc.x - radius; + node.runtime->totr.xmax = loc.x + radius; + node.runtime->totr.ymax = loc.y + radius; + node.runtime->totr.ymin = loc.y - radius; +} + +static void reroute_node_prepare_for_draw(bNode &node) +{ + if (node.flag & NODE_HIDDEN) { + reroute_node_prepare_for_draw_hidden(node); + } + else { + reroute_node_prepare_for_draw_basis(node); + } } static void node_update_nodetree(const bContext &C, @@ -3827,35 +3572,115 @@ static void frame_node_draw(const bContext &C, UI_block_draw(&C, &block); } -static void reroute_node_draw( - const bContext &C, ARegion ®ion, bNodeTree &ntree, const bNode &node, uiBlock &block) +void reroute_node_draw_body(const bContext &C, + const bNodeTree &ntree, + const bNode &node, + const bool selected) +{ + BLI_assert(node.is_reroute()); + + bNodeSocket &sock = *static_cast(node.inputs.first); + + PointerRNA nodeptr = RNA_pointer_create( + const_cast(&ntree.id), &RNA_Node, const_cast(&node)); + + ColorTheme4f socket_color; + ColorTheme4f outline_color; + + node_socket_color_get(C, ntree, nodeptr, sock, socket_color); + node_socket_outline_color_get(selected, sock.type, outline_color); + + UI_draw_node_socket(&node.runtime->totr, + socket_color, + outline_color, + NODE_SOCKET_OUTLINE, + NODE_SOCKET_DOT, + 0.0f, + sock.display_shape); +} + +static void reroute_node_draw_label(const bNode &node, uiBlock &block) +{ + /* 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); +} + +static void reroute_node_draw_basis(const bContext &C, const bNodeTree &ntree, const bNode &node) +{ + rctf *rct = &node.runtime->totr; + const bool selected = (node.flag & NODE_SELECT); + + reroute_node_draw_body(C, ntree, node, selected); + + /* Grip area. */ + const float grip_width = UI_icon_get_width(ICON_GRIP) * UI_SCALE_FAC; + const float grip_height = UI_icon_get_height(ICON_GRIP) * UI_SCALE_FAC; + const float grip_x = BLI_rctf_cent_x(rct) - 0.5f * grip_width; + const float grip_y = BLI_rctf_cent_y(rct) - 0.5f * grip_height; + + /* Make the grip match the socket outline color. */ + const bNodeSocket &sock = *static_cast(node.inputs.first); + ColorTheme4f outline_color; + node_socket_outline_color_get(selected, sock.type, outline_color); + + uchar icon_color[4] = { + (uchar)(outline_color.r * 255), + (uchar)(outline_color.g * 255), + (uchar)(outline_color.b * 255), + (uchar)(outline_color.a * 255), + }; + + UI_icon_draw_ex(grip_x, + grip_y, + ICON_GRIP, + UI_INV_SCALE_FAC, + 1.0f, + 0, + icon_color, + false, + UI_NO_ICON_OVERLAY_TEXT); +} + +static void reroute_node_draw_hidden(const bContext &C, const bNodeTree &ntree, const bNode &node) +{ + /* Only draw the input socket, since all sockets are at the same location. */ + const bool selected = node.flag & NODE_SELECT; + reroute_node_draw_body(C, ntree, node, selected); +} + +static void reroute_node_draw( + const bContext &C, ARegion ®ion, const bNodeTree &ntree, const bNode &node, uiBlock &block) { - /* Skip if out of view. */ const rctf &rct = node.runtime->totr; - if (rct.xmax < region.v2d.cur.xmin || rct.xmin > region.v2d.cur.xmax || - rct.ymax < region.v2d.cur.ymin || node.runtime->totr.ymin > region.v2d.cur.ymax) + const View2D &v2d = region.v2d; + + /* Skip if out of view. */ + if (rct.xmax < v2d.cur.xmin || rct.xmin > v2d.cur.xmax || rct.ymax < v2d.cur.ymin || + node.runtime->totr.ymin > v2d.cur.ymax) { UI_block_end(&C, &block); 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); + if (draw_node_details(v2d)) { + reroute_node_draw_label(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. */ - node_draw_sockets(region.v2d, C, ntree, node, block, false, node.flag & SELECT); + if (node.flag & NODE_HIDDEN) { + reroute_node_draw_hidden(C, ntree, node); + } + else { + reroute_node_draw_basis(C, ntree, node); + } UI_block_end(&C, &block); UI_block_draw(&C, &block); diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 04affd994a1..1abd6877f18 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -107,7 +107,7 @@ struct CompoJob { float node_socket_calculate_height(const bNodeSocket &socket) { - float sock_height = NODE_SOCKSIZE * NODE_SOCKSIZE_DRAW_MULIPLIER; + float sock_height = NODE_SOCKSIZE; if (socket.flag & SOCK_MULTI_INPUT) { sock_height += max_ii(NODE_MULTI_INPUT_LINK_GAP * 0.5f * socket.runtime->total_inputs, NODE_SOCKSIZE); diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index 5c324ffbb61..ddf8eb89e6d 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -144,7 +144,6 @@ ENUM_OPERATORS(NodeResizeDirection, NODE_RESIZE_LEFT); #define NODE_HEIGHT(node) (node.height * UI_SCALE_FAC) #define NODE_MARGIN_X (1.2f * U.widget_unit) #define NODE_SOCKSIZE (0.25f * U.widget_unit) -#define NODE_SOCKSIZE_DRAW_MULIPLIER 2.25f #define NODE_SOCK_OUTLINE_SCALE 1.0f #define NODE_MULTI_INPUT_LINK_GAP (0.25f * U.widget_unit) #define NODE_RESIZE_MARGIN (0.20f * U.widget_unit) diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index 3842e1e1f08..ccfd6805a15 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -150,13 +150,6 @@ static bool node_under_mouse_tweak(const SpaceNode &snode, const float2 &mouse) { for (bNode *node : tree_draw_order_calc_nodes_reversed(*snode.edittree)) { switch (node->type) { - case NODE_REROUTE: { - const float2 location = node_to_view(*node, {node->locx, node->locy}); - if (math::distance_squared(mouse, location) < square_f(24.0f)) { - return true; - } - break; - } case NODE_FRAME: { if (node_frame_select_isect_mouse(snode, *node, mouse)) { return true; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index c6d0f299436..a28aaffc53c 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -426,6 +426,8 @@ set(GLSL_SRC shaders/gpu_shader_2D_widget_base_frag.glsl shaders/gpu_shader_2D_widget_shadow_vert.glsl shaders/gpu_shader_2D_widget_shadow_frag.glsl + shaders/gpu_shader_2D_node_socket_frag.glsl + shaders/gpu_shader_2D_node_socket_vert.glsl shaders/gpu_shader_2D_nodelink_frag.glsl shaders/gpu_shader_2D_nodelink_vert.glsl shaders/gpu_shader_2D_line_dashed_frag.glsl @@ -746,6 +748,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/infos/gpu_shader_2D_image_overlays_stereo_merge_info.hh shaders/infos/gpu_shader_2D_image_rect_color_info.hh shaders/infos/gpu_shader_2D_image_shuffle_color_info.hh + shaders/infos/gpu_shader_2D_node_socket_info.hh shaders/infos/gpu_shader_2D_nodelink_info.hh shaders/infos/gpu_shader_2D_point_uniform_size_uniform_color_aa_info.hh shaders/infos/gpu_shader_2D_point_uniform_size_uniform_color_outline_aa_info.hh diff --git a/source/blender/gpu/GPU_shader_builtin.h b/source/blender/gpu/GPU_shader_builtin.h index 2b3cfbe7e1e..cebb2230080 100644 --- a/source/blender/gpu/GPU_shader_builtin.h +++ b/source/blender/gpu/GPU_shader_builtin.h @@ -62,6 +62,10 @@ typedef enum eGPUBuiltinShader { GPU_SHADER_2D_WIDGET_BASE, GPU_SHADER_2D_WIDGET_BASE_INST, GPU_SHADER_2D_WIDGET_SHADOW, + /** Draw a node socket given it's bounding rectangle. All socket shapes are supported through + * a single shader. */ + GPU_SHADER_2D_NODE_SOCKET, + GPU_SHADER_2D_NODE_SOCKET_INST, /** Draw a node link given an input quadratic Bezier curve. */ GPU_SHADER_2D_NODELINK, GPU_SHADER_2D_NODELINK_INST, diff --git a/source/blender/gpu/intern/gpu_shader_builtin.cc b/source/blender/gpu/intern/gpu_shader_builtin.cc index 442fa484582..52a9f8df5f7 100644 --- a/source/blender/gpu/intern/gpu_shader_builtin.cc +++ b/source/blender/gpu/intern/gpu_shader_builtin.cc @@ -81,6 +81,10 @@ static const char *builtin_shader_create_info_name(eGPUBuiltinShader shader) return "gpu_shader_2D_widget_base_inst"; case GPU_SHADER_2D_WIDGET_SHADOW: return "gpu_shader_2D_widget_shadow"; + case GPU_SHADER_2D_NODE_SOCKET: + return "gpu_shader_2D_node_socket"; + case GPU_SHADER_2D_NODE_SOCKET_INST: + return "gpu_shader_2D_node_socket_inst"; case GPU_SHADER_2D_NODELINK: return "gpu_shader_2D_nodelink"; case GPU_SHADER_2D_NODELINK_INST: diff --git a/source/blender/gpu/shaders/gpu_shader_2D_node_socket_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_frag.glsl new file mode 100644 index 00000000000..b5d9718a8eb --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_frag.glsl @@ -0,0 +1,46 @@ +/* SPDX-FileCopyrightText: 2018-2022 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#define COS45 (0.70710678118) +#define SIN45 (0.70710678118) + +#define AA_WIDTH 1.0f + +float square_sdf(vec2 absCo, float half_width) +{ + vec2 extruded = vec2(max(0.0, absCo.x - half_width), max(0.0, absCo.y - half_width)); + return dot(extruded, extruded); +} + +vec2 rotate_45(vec2 co) +{ + return vec2(COS45 * co.x - SIN45 * co.y, SIN45 * co.x + COS45 * co.y); +} + +void main() +{ + vec2 absUV = abs(uv); + vec2 co = vec2(max(absUV.x - extrusion.x, 0.0), max(absUV.y - extrusion.y, 0.0)); + + co = (is_diamond == 1) ? abs(rotate_45(co)) : co; + float distSquared = square_sdf(co, sdf_shape_radius); + + /* Needed to draw two dots for the wide reroute nodes. */ + vec2 biCenteredUV = abs(absUV - extrusion); + + /* Black mask with a white dot */ + float mask_dot = smoothstep(dotThresholds[1], dotThresholds[0], dot(biCenteredUV, biCenteredUV)); + + bool noOutline = thresholds[2] - thresholds[0] < 0.0001; + + /* Alpha for the socket: White where the socket is, black outside of it. */ + float mask_all = smoothstep(thresholds[3], thresholds[2], distSquared); + + /* Mask for the outline. The inner part of the socket is masked with black. */ + float mask_outline = noOutline ? 0.0 : smoothstep(thresholds[0], thresholds[1], distSquared); + mask_outline += mask_dot; + + fragColor = mix(finalColor, finalOutlineColor, mask_outline); + fragColor.a *= mask_all; +} diff --git a/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl new file mode 100644 index 00000000000..6b0db0297ec --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl @@ -0,0 +1,120 @@ +/* SPDX-FileCopyrightText: 2018-2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/* Values in `eNodeSocketDisplayShape` in DNA_node_types.h. Keep in sync. */ +#define SOCK_DISPLAY_SHAPE_CIRCLE 0 +#define SOCK_DISPLAY_SHAPE_SQUARE 1 +#define SOCK_DISPLAY_SHAPE_DIAMOND 2 +#define SOCK_DISPLAY_SHAPE_CIRCLE_DOT 3 +#define SOCK_DISPLAY_SHAPE_SQUARE_DOT 4 +#define SOCK_DISPLAY_SHAPE_DIAMOND_DOT 5 + +#define rect parameters[widgetID * MAX_PARAM + 0] +#define colorInner parameters[widgetID * MAX_PARAM + 1] +#define colorOutline parameters[widgetID * MAX_PARAM + 2] +#define outlineThickness parameters[widgetID * MAX_PARAM + 3].x +#define dotRadius parameters[widgetID * MAX_PARAM + 3].y +#define borderOffset parameters[widgetID * MAX_PARAM + 3].z + +#define AA_SIZE 0.75 +#define IS_CIRCLE \ + (shape_flags == SOCK_DISPLAY_SHAPE_CIRCLE || shape_flags == SOCK_DISPLAY_SHAPE_CIRCLE_DOT) +#define IS_DIAMOND \ + (shape_flags == SOCK_DISPLAY_SHAPE_DIAMOND || shape_flags == SOCK_DISPLAY_SHAPE_DIAMOND_DOT) +#define IS_SQUARE \ + (shape_flags == SOCK_DISPLAY_SHAPE_SQUARE || shape_flags == SOCK_DISPLAY_SHAPE_SQUARE_DOT) +#define HAS_DOT \ + (shape_flags == SOCK_DISPLAY_SHAPE_CIRCLE_DOT || \ + shape_flags == SOCK_DISPLAY_SHAPE_DIAMOND_DOT || shape_flags == SOCK_DISPLAY_SHAPE_SQUARE_DOT) + +/* Offsetting by a pixel further to avoid losing pixels. */ +vec2 ofs = vec2(borderOffset + 1.0, -borderOffset - 1.0); + +/* Calculate size of the original rectangle before expanding it based on the offset for the outline + */ +vec2 rectSize = rect.yw - rect.xz; +float minSize = min(rectSize.x, rectSize.y); + +/* Set the parameters for the sdf function that is used to draw the socket. */ +#define CIRCLE_RADIUS 0.5 +#define SQUARE_RADIUS 0.5 +#define DIAMOND_RADIUS 0.4 + +vec3 shapeRadii = vec3(CIRCLE_RADIUS, SQUARE_RADIUS, DIAMOND_RADIUS); +vec3 cornerRoundness = vec3(1.0, 0.4, 0.4); + +int shapeIndex = shape_flags % 3; +float shapeRadiusUV = shapeRadii[shapeIndex]; +float cornerRoundingUV = shapeRadiusUV * cornerRoundness[shapeIndex]; + +float pow2(float x) +{ + return x * x; +} + +void main() +{ + vec2 pos; + switch (gl_VertexID) { + default: + case 0: { + pos = rect.xz + ofs.yy; + break; + } + case 1: { + pos = rect.xw + ofs.yx; + break; + } + case 2: { + pos = rect.yz + ofs.xy; + break; + } + case 3: { + pos = rect.yw + ofs.xx; + break; + } + } + + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + + vec2 centeredCoordinates = pos - ((rect.xz + rect.yw) / 2.0); + uv = centeredCoordinates / minSize; + + /* Calculate the necessary "extrusion" to extend the of the middle part to draw multi sockets + * or wide reroute nodes. */ + float aspect = rectSize.x / rectSize.y; + extrusion = (aspect > 1.0) ? vec2((aspect - 1.0) / 2.0, 0.0) : + vec2(0.0, ((1.0 / aspect) - 1.0) / 2.0); + + /* Thresholds for the masks in UV Space. Use squared values, so we can use the squared length in + * the fragment shader. */ + float InnerOutlineUVSquared1 = pow2( + ((borderOffset - 0.5 * outlineThickness - AA_SIZE) / minSize) + cornerRoundingUV); + float InnerOutlineUVSquared2 = pow2(((borderOffset - 0.5 * outlineThickness) / minSize) + + cornerRoundingUV); + float OuterOutlineUVSquared1 = pow2( + ((borderOffset + 0.5 * outlineThickness - AA_SIZE) / minSize) + cornerRoundingUV); + float OuterOutlineUVSquared2 = pow2(((borderOffset + 0.5 * outlineThickness) / minSize) + + cornerRoundingUV); + + thresholds = vec4(InnerOutlineUVSquared1, + InnerOutlineUVSquared2, + OuterOutlineUVSquared1, + OuterOutlineUVSquared2); + + /* Thresholds for the mask of the dot. */ + bool has_dot = HAS_DOT; + float dotRadiusSquared1 = has_dot ? pow2((dotRadius - AA_SIZE) / minSize) : (-1.0f); + float dotRadiusSquared2 = has_dot ? pow2(dotRadius / minSize) : 0.0f; + + dotThresholds = vec2(dotRadiusSquared1, dotRadiusSquared2); + + /* Shape parameters. */ + sdf_shape_radius = shapeRadiusUV - cornerRoundingUV; + is_diamond = IS_DIAMOND ? 1 : 0; + + /* Pass through parameters. */ + finalColor = colorInner; + finalOutlineColor = colorOutline; +} diff --git a/source/blender/gpu/shaders/infos/gpu_shader_2D_node_socket_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_2D_node_socket_info.hh new file mode 100644 index 00000000000..16edef9d31a --- /dev/null +++ b/source/blender/gpu/shaders/infos/gpu_shader_2D_node_socket_info.hh @@ -0,0 +1,49 @@ +/* SPDX-FileCopyrightText: 2022 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup gpu + */ + +#include "gpu_interface_info.hh" +#include "gpu_shader_create_info.hh" + GPU_SHADER_INTERFACE_INFO(gpu_node_socket_iface, "") + .flat(Type::FLOAT, "sdf_shape_radius") + .flat(Type::VEC4, "finalColor") + .flat(Type::VEC4, "finalOutlineColor") + .flat(Type::VEC4, "thresholds") + .flat(Type::VEC2, "dotThresholds") + .flat(Type::VEC2, "extrusion") + .flat(Type::INT, "is_diamond") + .smooth(Type::VEC2, "uv"); + +/* TODO(Leon): Share with C code. */ +/* TODO(Leon): Tweak the instance count to test if there's a noticable sweet spot. */ +#define MAX_SOCKET_PARAM 4 +#define MAX_SOCKET_INSTANCE 18 + +GPU_SHADER_CREATE_INFO(gpu_shader_2D_node_socket_shared) + .define("MAX_PARAM", STRINGIFY(MAX_SOCKET_PARAM)) + .push_constant(Type::MAT4, "ModelViewProjectionMatrix") + .vertex_out(gpu_node_socket_iface) + .fragment_out(0, Type::VEC4, "fragColor") + .vertex_source("gpu_shader_2D_node_socket_vert.glsl") + .fragment_source("gpu_shader_2D_node_socket_frag.glsl"); + +GPU_SHADER_CREATE_INFO(gpu_shader_2D_node_socket) + .do_static_compilation(true) + /* gl_InstanceID is supposed to be 0 if not drawing instances, but this seems + * to be violated in some drivers. For example, macOS 10.15.4 and Intel Iris + * causes #78307 when using gl_InstanceID outside of instance. */ + .define("widgetID", "0") + .push_constant(Type::VEC4, "parameters", MAX_SOCKET_PARAM) + .push_constant(Type::INT, "shape_flags") + .additional_info("gpu_shader_2D_node_socket_shared"); + +GPU_SHADER_CREATE_INFO(gpu_shader_2D_node_socket_inst) + .do_static_compilation(true) + .define("widgetID", "gl_InstanceID") + .push_constant(Type::VEC4, "parameters", (MAX_SOCKET_PARAM * MAX_SOCKET_INSTANCE)) + .push_constant(Type::INT, "shape_flags", MAX_SOCKET_INSTANCE) + .additional_info("gpu_shader_2D_node_socket_shared"); -- 2.30.2 From 3b6e72bc9fd3dec7c9c3dc4995bdc226f8a4fe23 Mon Sep 17 00:00:00 2001 From: Leon Schittek Date: Fri, 8 Mar 2024 18:30:02 +0100 Subject: [PATCH 02/11] Fix socket selection highlight. --- source/blender/editors/space_node/node_draw.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 394d27df68e..1eff46b6d0d 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -1818,8 +1818,9 @@ static void node_draw_sockets_ex(const bContext &C, if (!node.is_socket_icon_drawn(*sock)) { continue; } + const bool selected = (sock->flag & SELECT) || select_all; node_draw_socket_ex( - C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, select_all); + C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, selected); } /* Socket outputs. */ @@ -1827,8 +1828,9 @@ static void node_draw_sockets_ex(const bContext &C, if (!node.is_socket_icon_drawn(*sock)) { continue; } + const bool selected = (sock->flag & SELECT) || select_all; node_draw_socket_ex( - C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, select_all); + C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, selected); } } -- 2.30.2 From 409124ecffefab45cd014800dcee01fdad5c7d65 Mon Sep 17 00:00:00 2001 From: Leon Schittek Date: Fri, 8 Mar 2024 18:39:23 +0100 Subject: [PATCH 03/11] Remove changes to reroute nodes. --- .../blender/editors/space_node/node_draw.cc | 89 ++----------------- 1 file changed, 7 insertions(+), 82 deletions(-) diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 1eff46b6d0d..2e70caf8b31 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -3357,28 +3357,7 @@ static void frame_node_prepare_for_draw(bNode &node, Span nodes) node.runtime->totr = rect; } -#define NODE_REROUTE_SIZE (3.0f * NODE_SOCKSIZE) -#define NODE_REROUTE_HIDDEN_SIZE 8.0f -static void reroute_node_prepare_for_draw_basis(bNode &node) -{ - /* Get "global" coordinates. */ - const float2 loc = node_to_view(node, float2(0)); - - const float half_width = NODE_REROUTE_SIZE; - const float half_height = NODE_SOCKSIZE; - const float2 x_offset(half_width - half_height, 0); - - /* Reroute nodes have exactly one input and one output. */ - node.input_socket(0).runtime->location = loc - x_offset; - node.output_socket(0).runtime->location = loc + x_offset; - - node.width = half_width * 2; - node.runtime->totr.xmin = (loc.x - half_width); - node.runtime->totr.xmax = (loc.x + half_width); - node.runtime->totr.ymax = (loc.y + half_height); - node.runtime->totr.ymin = (loc.y - half_height); -} -static void reroute_node_prepare_for_draw_hidden(bNode &node) +static void reroute_node_prepare_for_draw(bNode &node) { const float2 loc = node_to_view(node, float2(0)); @@ -3394,16 +3373,6 @@ static void reroute_node_prepare_for_draw_hidden(bNode &node) node.runtime->totr.ymin = loc.y - radius; } -static void reroute_node_prepare_for_draw(bNode &node) -{ - if (node.flag & NODE_HIDDEN) { - reroute_node_prepare_for_draw_hidden(node); - } - else { - reroute_node_prepare_for_draw_basis(node); - } -} - static void node_update_nodetree(const bContext &C, TreeDrawContext &tree_draw_ctx, bNodeTree &ntree, @@ -3616,49 +3585,6 @@ static void reroute_node_draw_label(const bNode &node, uiBlock &block) UI_but_drawflag_disable(label_but, UI_BUT_TEXT_LEFT); } -static void reroute_node_draw_basis(const bContext &C, const bNodeTree &ntree, const bNode &node) -{ - rctf *rct = &node.runtime->totr; - const bool selected = (node.flag & NODE_SELECT); - - reroute_node_draw_body(C, ntree, node, selected); - - /* Grip area. */ - const float grip_width = UI_icon_get_width(ICON_GRIP) * UI_SCALE_FAC; - const float grip_height = UI_icon_get_height(ICON_GRIP) * UI_SCALE_FAC; - const float grip_x = BLI_rctf_cent_x(rct) - 0.5f * grip_width; - const float grip_y = BLI_rctf_cent_y(rct) - 0.5f * grip_height; - - /* Make the grip match the socket outline color. */ - const bNodeSocket &sock = *static_cast(node.inputs.first); - ColorTheme4f outline_color; - node_socket_outline_color_get(selected, sock.type, outline_color); - - uchar icon_color[4] = { - (uchar)(outline_color.r * 255), - (uchar)(outline_color.g * 255), - (uchar)(outline_color.b * 255), - (uchar)(outline_color.a * 255), - }; - - UI_icon_draw_ex(grip_x, - grip_y, - ICON_GRIP, - UI_INV_SCALE_FAC, - 1.0f, - 0, - icon_color, - false, - UI_NO_ICON_OVERLAY_TEXT); -} - -static void reroute_node_draw_hidden(const bContext &C, const bNodeTree &ntree, const bNode &node) -{ - /* Only draw the input socket, since all sockets are at the same location. */ - const bool selected = node.flag & NODE_SELECT; - reroute_node_draw_body(C, ntree, node, selected); -} - static void reroute_node_draw( const bContext &C, ARegion ®ion, const bNodeTree &ntree, const bNode &node, uiBlock &block) { @@ -3674,15 +3600,14 @@ static void reroute_node_draw( } if (draw_node_details(v2d)) { - reroute_node_draw_label(node, block); + if (node.label[0] != '\n') { + reroute_node_draw_label(node, block); + } } - if (node.flag & NODE_HIDDEN) { - reroute_node_draw_hidden(C, ntree, node); - } - else { - reroute_node_draw_basis(C, ntree, node); - } + /* Only draw the input socket, since all sockets are at the same location. */ + const bool selected = node.flag & NODE_SELECT; + reroute_node_draw_body(C, ntree, node, selected); UI_block_end(&C, &block); UI_block_draw(&C, &block); -- 2.30.2 From c20529bc955db047e68d20700e2998ac1c489809 Mon Sep 17 00:00:00 2001 From: Leon Schittek Date: Fri, 8 Mar 2024 19:01:25 +0100 Subject: [PATCH 04/11] Cleanup: Remove unnecessary null checks --- .../editors/interface/interface_draw.cc | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/interface/interface_draw.cc b/source/blender/editors/interface/interface_draw.cc index 79a6455f3f5..4299c86f514 100644 --- a/source/blender/editors/interface/interface_draw.cc +++ b/source/blender/editors/interface/interface_draw.cc @@ -238,24 +238,18 @@ void UI_draw_node_socket(const rctf *rect, { /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. * If it has been scaled, then it's no longer valid. */ + BLI_assert((color_inner != nullptr) && (color_outline != nullptr)); + uiNodeSocketParameters socket_params = {}; socket_params.rect = *rect; - socket_params.color_inner[0] = color_inner ? color_inner[0] : 0.0f; - socket_params.color_inner[1] = color_inner ? color_inner[1] : 0.0f; - socket_params.color_inner[2] = color_inner ? color_inner[2] : 0.0f; - socket_params.color_inner[3] = color_inner ? color_inner[3] : 0.0f; - socket_params.color_outline[0] = color_outline ? color_outline[0] : - color_inner ? color_inner[0] : - 0.0f; - socket_params.color_outline[1] = color_outline ? color_outline[1] : - color_inner ? color_inner[1] : - 0.0f; - socket_params.color_outline[2] = color_outline ? color_outline[2] : - color_inner ? color_inner[2] : - 0.0f; - socket_params.color_outline[3] = color_outline ? color_outline[3] : - color_inner ? color_inner[3] : - 0.0f; + socket_params.color_inner[0] = color_inner[0]; + socket_params.color_inner[1] = color_inner[1]; + socket_params.color_inner[2] = color_inner[2]; + socket_params.color_inner[3] = color_inner[3]; + socket_params.color_outline[0] = color_outline[0]; + socket_params.color_outline[1] = color_outline[1]; + socket_params.color_outline[2] = color_outline[2]; + socket_params.color_outline[3] = color_outline[3]; socket_params.outline_thickness = outline_thickness; socket_params.dot_thickness = dot_thickness; socket_params.border_offset = border_offset; -- 2.30.2 From 1f4304e381ab8efaf85f84120486e2a21841ca88 Mon Sep 17 00:00:00 2001 From: Leon Schittek Date: Fri, 15 Mar 2024 14:12:40 +0100 Subject: [PATCH 05/11] Small cleanups. --- .../blender/editors/include/UI_interface_c.hh | 8 +++- .../editors/interface/interface_draw.cc | 8 ++-- .../editors/interface/interface_intern.hh | 4 +- .../blender/editors/space_node/node_draw.cc | 42 +++++++++---------- .../gpu_shader_2D_node_socket_frag.glsl | 5 +-- .../gpu_shader_2D_node_socket_vert.glsl | 28 ++++++------- 6 files changed, 47 insertions(+), 48 deletions(-) diff --git a/source/blender/editors/include/UI_interface_c.hh b/source/blender/editors/include/UI_interface_c.hh index 614653a34fc..5aef1be3294 100644 --- a/source/blender/editors/include/UI_interface_c.hh +++ b/source/blender/editors/include/UI_interface_c.hh @@ -491,12 +491,18 @@ void UI_draw_roundbox_4fv_ex(const rctf *rect, const float outline[4], float outline_width, float rad); +/** + * Draw a node socket shape. + * + * \param outline_offset: Factor to move the outline from being drawn inside the shape (`0.0f`) to + * outside of the shape (`1.0f`). `0.5f` Makes the centers the outline on the shape. + */ void UI_draw_node_socket(const rctf *rect, const float color_inner[4], const float color_outline[4], float outline_thickness, + float outline_offset, float dot_thickness, - float border_offset, int flags); #if 0 /* unused */ diff --git a/source/blender/editors/interface/interface_draw.cc b/source/blender/editors/interface/interface_draw.cc index 4299c86f514..3681e1a1a5e 100644 --- a/source/blender/editors/interface/interface_draw.cc +++ b/source/blender/editors/interface/interface_draw.cc @@ -232,8 +232,8 @@ void UI_draw_node_socket(const rctf *rect, const float color_inner[4], const float color_outline[4], const float outline_thickness, - const float dot_thickness, - const float border_offset, + const float outline_offset, + const float dot_radius, const int flags) { /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. @@ -251,8 +251,8 @@ void UI_draw_node_socket(const rctf *rect, socket_params.color_outline[2] = color_outline[2]; socket_params.color_outline[3] = color_outline[3]; socket_params.outline_thickness = outline_thickness; - socket_params.dot_thickness = dot_thickness; - socket_params.border_offset = border_offset; + socket_params.dot_radius = dot_radius; + socket_params.outline_offset = outline_offset; GPUBatch *batch = ui_batch_node_socket_get(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); diff --git a/source/blender/editors/interface/interface_intern.hh b/source/blender/editors/interface/interface_intern.hh index 03c25172e3b..c7defc272d5 100644 --- a/source/blender/editors/interface/interface_intern.hh +++ b/source/blender/editors/interface/interface_intern.hh @@ -1189,8 +1189,8 @@ struct uiNodeSocketParameters { float color_inner[4]; float color_outline[4]; float outline_thickness; - float dot_thickness; - float border_offset; + float outline_offset; + float dot_radius; float _pad[1]; }; diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index f44ef29a00c..c84c7ce61d1 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -1643,8 +1643,8 @@ void node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], color, outline_color, NODE_SOCKET_OUTLINE * scale, - NODE_SOCKET_DOT * scale, 0.0f, + NODE_SOCKET_DOT * scale, sock->display_shape); } @@ -1759,7 +1759,7 @@ static void node_draw_socket_ex(const bContext &C, PointerRNA &node_ptr, const bNodeSocket &sock, const float outline_thickness, - const float border_offset, + const float outline_offset, const float dot_radius, const bool selected) { @@ -1786,13 +1786,13 @@ static void node_draw_socket_ex(const bContext &C, socket_color, outline_color, outline_thickness, + outline_offset, dot_radius, - border_offset, sock.display_shape); } /* Some elements of the node tree like labels or node sockets are hardly visible when zoomed - * out and can slow down the drawing quite a bit, when there are a lot of elements. + * out and can slow down the drawing quite a bit. * This function can be used to check if it's worth to draw those details and return * early. */ static bool draw_node_details(const View2D &v2d) @@ -1802,48 +1802,44 @@ static bool draw_node_details(const View2D &v2d) return scale > 0.2f * UI_INV_SCALE_FAC; } -static void node_draw_sockets_ex(const bContext &C, - bNodeTree &ntree, - const bNode &node, - const float outline_thickness, - const float border_offset, - const float dot_radius, - const bool select_all) +void node_draw_sockets(const View2D &v2d, const bContext &C, bNodeTree &ntree, const bNode &node) { + if (!draw_node_details(v2d)) { + return; + } + if (node.input_sockets().is_empty() && node.output_sockets().is_empty()) { return; } PointerRNA nodeptr = RNA_pointer_create( const_cast(&ntree.id), &RNA_Node, const_cast(&node)); - /* Socket inputs. */ + + const float outline_thickness = NODE_SOCKET_OUTLINE; + const float border_offset = 0.0f; + const float dot_radius = NODE_SOCKET_DOT; + + /* Input sockets. */ for (const bNodeSocket *sock : node.input_sockets()) { if (!node.is_socket_icon_drawn(*sock)) { continue; } - const bool selected = (sock->flag & SELECT) || select_all; + const bool selected = (sock->flag & SELECT); node_draw_socket_ex( C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, selected); } - /* Socket outputs. */ + /* Output sockets. */ for (const bNodeSocket *sock : node.output_sockets()) { if (!node.is_socket_icon_drawn(*sock)) { continue; } - const bool selected = (sock->flag & SELECT) || select_all; + const bool selected = (sock->flag & SELECT); node_draw_socket_ex( C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, selected); } } -void node_draw_sockets(const View2D &v2d, const bContext &C, bNodeTree &ntree, const bNode &node) -{ - if (draw_node_details(v2d)) { - node_draw_sockets_ex(C, ntree, node, NODE_SOCKET_OUTLINE, 0.0f, NODE_SOCKET_DOT, false); - } -} - static void node_panel_toggle_button_cb(bContext *C, void *panel_state_argv, void *ntree_argv) { Main *bmain = CTX_data_main(C); @@ -3568,8 +3564,8 @@ void reroute_node_draw_body(const bContext &C, socket_color, outline_color, NODE_SOCKET_OUTLINE, - NODE_SOCKET_DOT, 0.0f, + NODE_SOCKET_DOT, sock.display_shape); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_node_socket_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_frag.glsl index b5d9718a8eb..90881499475 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_node_socket_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_frag.glsl @@ -5,8 +5,6 @@ #define COS45 (0.70710678118) #define SIN45 (0.70710678118) -#define AA_WIDTH 1.0f - float square_sdf(vec2 absCo, float half_width) { vec2 extruded = vec2(max(0.0, absCo.x - half_width), max(0.0, absCo.y - half_width)); @@ -32,12 +30,11 @@ void main() /* Black mask with a white dot */ float mask_dot = smoothstep(dotThresholds[1], dotThresholds[0], dot(biCenteredUV, biCenteredUV)); - bool noOutline = thresholds[2] - thresholds[0] < 0.0001; - /* Alpha for the socket: White where the socket is, black outside of it. */ float mask_all = smoothstep(thresholds[3], thresholds[2], distSquared); /* Mask for the outline. The inner part of the socket is masked with black. */ + bool noOutline = thresholds[2] - thresholds[0] < 0.0001; float mask_outline = noOutline ? 0.0 : smoothstep(thresholds[0], thresholds[1], distSquared); mask_outline += mask_dot; diff --git a/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl index 6b0db0297ec..e95243eca6a 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl @@ -14,8 +14,8 @@ #define colorInner parameters[widgetID * MAX_PARAM + 1] #define colorOutline parameters[widgetID * MAX_PARAM + 2] #define outlineThickness parameters[widgetID * MAX_PARAM + 3].x -#define dotRadius parameters[widgetID * MAX_PARAM + 3].y -#define borderOffset parameters[widgetID * MAX_PARAM + 3].z +#define outlineOffset parameters[widgetID * MAX_PARAM + 3].y +#define dotRadius parameters[widgetID * MAX_PARAM + 3].z #define AA_SIZE 0.75 #define IS_CIRCLE \ @@ -29,7 +29,7 @@ shape_flags == SOCK_DISPLAY_SHAPE_DIAMOND_DOT || shape_flags == SOCK_DISPLAY_SHAPE_SQUARE_DOT) /* Offsetting by a pixel further to avoid losing pixels. */ -vec2 ofs = vec2(borderOffset + 1.0, -borderOffset - 1.0); +vec2 ofs = vec2(outlineOffset + 1.0, -outlineOffset - 1.0); /* Calculate size of the original rectangle before expanding it based on the offset for the outline */ @@ -45,8 +45,8 @@ vec3 shapeRadii = vec3(CIRCLE_RADIUS, SQUARE_RADIUS, DIAMOND_RADIUS); vec3 cornerRoundness = vec3(1.0, 0.4, 0.4); int shapeIndex = shape_flags % 3; -float shapeRadiusUV = shapeRadii[shapeIndex]; -float cornerRoundingUV = shapeRadiusUV * cornerRoundness[shapeIndex]; +float shapeRadius = shapeRadii[shapeIndex]; +float cornerRadius = shapeRadius * cornerRoundness[shapeIndex]; float pow2(float x) { @@ -81,8 +81,8 @@ void main() vec2 centeredCoordinates = pos - ((rect.xz + rect.yw) / 2.0); uv = centeredCoordinates / minSize; - /* Calculate the necessary "extrusion" to extend the of the middle part to draw multi sockets - * or wide reroute nodes. */ + /* Calculate the necessary "extrusion" of the coordinates to draw the middle part of + * multi sockets. */ float aspect = rectSize.x / rectSize.y; extrusion = (aspect > 1.0) ? vec2((aspect - 1.0) / 2.0, 0.0) : vec2(0.0, ((1.0 / aspect) - 1.0) / 2.0); @@ -90,13 +90,13 @@ void main() /* Thresholds for the masks in UV Space. Use squared values, so we can use the squared length in * the fragment shader. */ float InnerOutlineUVSquared1 = pow2( - ((borderOffset - 0.5 * outlineThickness - AA_SIZE) / minSize) + cornerRoundingUV); - float InnerOutlineUVSquared2 = pow2(((borderOffset - 0.5 * outlineThickness) / minSize) + - cornerRoundingUV); + ((outlineOffset - 0.5 * outlineThickness - AA_SIZE) / minSize) + cornerRadius); + float InnerOutlineUVSquared2 = pow2(((outlineOffset - 0.5 * outlineThickness) / minSize) + + cornerRadius); float OuterOutlineUVSquared1 = pow2( - ((borderOffset + 0.5 * outlineThickness - AA_SIZE) / minSize) + cornerRoundingUV); - float OuterOutlineUVSquared2 = pow2(((borderOffset + 0.5 * outlineThickness) / minSize) + - cornerRoundingUV); + ((outlineOffset + 0.5 * outlineThickness - AA_SIZE) / minSize) + cornerRadius); + float OuterOutlineUVSquared2 = pow2(((outlineOffset + 0.5 * outlineThickness) / minSize) + + cornerRadius); thresholds = vec4(InnerOutlineUVSquared1, InnerOutlineUVSquared2, @@ -111,7 +111,7 @@ void main() dotThresholds = vec2(dotRadiusSquared1, dotRadiusSquared2); /* Shape parameters. */ - sdf_shape_radius = shapeRadiusUV - cornerRoundingUV; + sdf_shape_radius = shapeRadius - cornerRadius; is_diamond = IS_DIAMOND ? 1 : 0; /* Pass through parameters. */ -- 2.30.2 From 813468aeff63d3273fef9d1777db0116b130dcbb Mon Sep 17 00:00:00 2001 From: Leon Schittek Date: Fri, 29 Mar 2024 13:26:07 +0100 Subject: [PATCH 06/11] WIP: Implement instanced drawing --- .../blender/editors/include/UI_interface_c.hh | 13 -- .../editors/interface/interface_draw.cc | 35 ----- .../editors/interface/interface_intern.hh | 12 -- .../editors/interface/interface_widgets.cc | 21 --- source/blender/editors/space_node/drawnode.cc | 148 ++++++++++++++++++ .../blender/editors/space_node/node_draw.cc | 66 ++++---- .../blender/editors/space_node/node_intern.hh | 12 ++ .../gpu_shader_2D_node_socket_vert.glsl | 13 +- .../infos/gpu_shader_2D_node_socket_info.hh | 30 ++-- 9 files changed, 213 insertions(+), 137 deletions(-) diff --git a/source/blender/editors/include/UI_interface_c.hh b/source/blender/editors/include/UI_interface_c.hh index 33f15fae504..b8d95e0f5f0 100644 --- a/source/blender/editors/include/UI_interface_c.hh +++ b/source/blender/editors/include/UI_interface_c.hh @@ -491,19 +491,6 @@ void UI_draw_roundbox_4fv_ex(const rctf *rect, const float outline[4], float outline_width, float rad); -/** - * Draw a node socket shape. - * - * \param outline_offset: Factor to move the outline from being drawn inside the shape (`0.0f`) to - * outside of the shape (`1.0f`). `0.5f` Makes the centers the outline on the shape. - */ -void UI_draw_node_socket(const rctf *rect, - const float color_inner[4], - const float color_outline[4], - float outline_thickness, - float outline_offset, - float dot_thickness, - int flags); #if 0 /* unused */ int UI_draw_roundbox_corner_get(); diff --git a/source/blender/editors/interface/interface_draw.cc b/source/blender/editors/interface/interface_draw.cc index a517a078eb9..4698759e921 100644 --- a/source/blender/editors/interface/interface_draw.cc +++ b/source/blender/editors/interface/interface_draw.cc @@ -228,41 +228,6 @@ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const flo immUnbindProgram(); } -void UI_draw_node_socket(const rctf *rect, - const float color_inner[4], - const float color_outline[4], - const float outline_thickness, - const float outline_offset, - const float dot_radius, - const int flags) -{ - /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. - * If it has been scaled, then it's no longer valid. */ - BLI_assert((color_inner != nullptr) && (color_outline != nullptr)); - - uiNodeSocketParameters socket_params = {}; - socket_params.rect = *rect; - socket_params.color_inner[0] = color_inner[0]; - socket_params.color_inner[1] = color_inner[1]; - socket_params.color_inner[2] = color_inner[2]; - socket_params.color_inner[3] = color_inner[3]; - socket_params.color_outline[0] = color_outline[0]; - socket_params.color_outline[1] = color_outline[1]; - socket_params.color_outline[2] = color_outline[2]; - socket_params.color_outline[3] = color_outline[3]; - socket_params.outline_thickness = outline_thickness; - socket_params.dot_radius = dot_radius; - socket_params.outline_offset = outline_offset; - - GPUBatch *batch = ui_batch_node_socket_get(); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); - GPU_batch_uniform_4fv_array(batch, "parameters", 4, (const float(*)[4]) & socket_params); - GPU_batch_uniform_1i(batch, "shape_flags", flags); - GPU_blend(GPU_BLEND_ALPHA); - GPU_batch_draw(batch); - GPU_blend(GPU_BLEND_NONE); -} - /* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */ void ui_draw_but_TAB_outline(const rcti *rect, diff --git a/source/blender/editors/interface/interface_intern.hh b/source/blender/editors/interface/interface_intern.hh index 85722bad349..0cbdf539c0e 100644 --- a/source/blender/editors/interface/interface_intern.hh +++ b/source/blender/editors/interface/interface_intern.hh @@ -1185,17 +1185,6 @@ struct uiWidgetBaseParameters { float _pad[3]; }; -/* Node Socket shader parameters, must match the shader layout. */ -struct uiNodeSocketParameters { - rctf rect; - float color_inner[4]; - float color_outline[4]; - float outline_thickness; - float outline_offset; - float dot_radius; - float _pad[1]; -}; - enum { ROUNDBOX_TRIA_NONE = 0, ROUNDBOX_TRIA_ARROWS, @@ -1210,7 +1199,6 @@ enum { blender::gpu::Batch *ui_batch_roundbox_widget_get(); blender::gpu::Batch *ui_batch_roundbox_shadow_get(); -blender::gpu::Batch *ui_batch_node_socket_get(); void ui_draw_menu_back(uiStyle *style, uiBlock *block, rcti *rect); void ui_draw_popover_back(ARegion *region, uiStyle *style, uiBlock *block, rcti *rect); diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index fd372e0d728..1b088f6a160 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -394,7 +394,6 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} static struct { blender::gpu::Batch *roundbox_widget; blender::gpu::Batch *roundbox_shadow; - blender::gpu::Batch *node_socket; /* TODO: remove. */ GPUVertFormat format; @@ -502,26 +501,6 @@ blender::gpu::Batch *ui_batch_roundbox_shadow_get() return g_ui_batch_cache.roundbox_shadow; } -GPUBatch *ui_batch_node_socket_get(void) -{ - if (g_ui_batch_cache.node_socket == NULL) { - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format()); - - GPU_vertbuf_data_alloc(vbo, 6); - - GPUIndexBufBuilder ibuf; - GPU_indexbuf_init(&ibuf, GPU_PRIM_TRIS, 2, 4); - /* Quad to draw the node socket in. */ - GPU_indexbuf_add_tri_verts(&ibuf, 0, 1, 2); - GPU_indexbuf_add_tri_verts(&ibuf, 2, 1, 3); - - g_ui_batch_cache.node_socket = GPU_batch_create_ex( - GPU_PRIM_TRIS, vbo, GPU_indexbuf_build(&ibuf), GPU_BATCH_OWNS_INDEX | GPU_BATCH_OWNS_VBO); - gpu_batch_presets_register(g_ui_batch_cache.node_socket); - } - return g_ui_batch_cache.node_socket; -} - #undef INNER #undef OUTLINE #undef EMBOSS diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index 63b72f39c9a..4379cd7805e 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -1799,6 +1799,152 @@ void node_link_bezier_points_evaluated(const bNodeLink &link, sizeof(float2)); } +/* -------------------------------------------------------------------- */ +/** \name Node Socket Drawing + * \{ */ + +/* Node Socket shader parameters, must match the shader layout. */ +struct NodeSocketShaderParameters { + rctf rect; + float color_inner[4]; + float color_outline[4]; + float outline_thickness; + float outline_offset; + float dot_radius; + float shape; +}; + +/* Keep in sync with shader. */ +#define MAX_SOCKET_PARAMETERS 4 +#define MAX_SOCKET_INSTANCE 32 + +static struct { + blender::gpu::Batch *batch; + NodeSocketShaderParameters params[MAX_SOCKET_INSTANCE]; + int count; + bool enabled; +} g_batch_nodesocket; + +blender::gpu::Batch *nodesocket_batch_init(void) +{ + if (g_batch_nodesocket.batch == NULL) { + GPUVertFormat format = {0}; + blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC); + + GPU_vertbuf_data_alloc(vbo, 6); + + GPUIndexBufBuilder ibuf; + GPU_indexbuf_init(&ibuf, GPU_PRIM_TRIS, 2, 4); + /* Quad to draw the node socket in. */ + GPU_indexbuf_add_tri_verts(&ibuf, 0, 1, 2); + GPU_indexbuf_add_tri_verts(&ibuf, 2, 1, 3); + + g_batch_nodesocket.batch = GPU_batch_create_ex( + GPU_PRIM_TRIS, vbo, GPU_indexbuf_build(&ibuf), GPU_BATCH_OWNS_INDEX | GPU_BATCH_OWNS_VBO); + gpu_batch_presets_register(g_batch_nodesocket.batch); + } + return g_batch_nodesocket.batch; +} + +static void nodesocket_cache_flush() +{ + if (g_batch_nodesocket.count == 0) { + return; + } + + blender::gpu::Batch *batch = nodesocket_batch_init(); + if (g_batch_nodesocket.count == 1) { + /* draw single */ + GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); + GPU_batch_uniform_4fv_array( + batch, "parameters", 4, (const float(*)[4])g_batch_nodesocket.params); + GPU_batch_draw(batch); + } + else { + GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET_INST); + GPU_batch_uniform_4fv_array(batch, + "parameters", + MAX_SOCKET_PARAMETERS * MAX_SOCKET_INSTANCE, + (float(*)[4])g_batch_nodesocket.params); + GPU_batch_draw_instance_range(batch, 0, g_batch_nodesocket.count); + } + g_batch_nodesocket.count = 0; +} + +void nodesocket_batch_start() +{ + BLI_assert(g_batch_nodesocket.enabled == false); + g_batch_nodesocket.enabled = true; +} + +void nodesocket_batch_end() +{ + BLI_assert(g_batch_nodesocket.enabled == true); + g_batch_nodesocket.enabled = false; + + GPU_blend(GPU_BLEND_ALPHA); + nodesocket_cache_flush(); + GPU_blend(GPU_BLEND_NONE); +} + +static void draw_node_socket_batch(NodeSocketShaderParameters *socket_params) +{ + if (g_batch_nodesocket.enabled) { + g_batch_nodesocket.params[g_batch_nodesocket.count] = *socket_params; + g_batch_nodesocket.count++; + + if (g_batch_nodesocket.count >= MAX_SOCKET_INSTANCE) { + nodesocket_cache_flush(); + } + } + else { + /* draw single */ + blender::gpu::Batch *batch = nodesocket_batch_init(); + GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); + GPU_batch_uniform_4fv_array( + batch, "parameters", MAX_SOCKET_PARAMETERS, (float(*)[4])socket_params); + GPU_batch_draw(batch); + } +} + +void node_draw_nodesocket(const rctf *rect, + const float color_inner[4], + const float color_outline[4], + const float outline_thickness, + const float outline_offset, + const float dot_radius, + int shape) +{ + /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. + * If it has been scaled, then it's no longer valid. */ + BLI_assert((color_inner != nullptr) && (color_outline != nullptr)); + + NodeSocketShaderParameters socket_params = {}; + socket_params.rect = *rect; + socket_params.color_inner[0] = color_inner[0]; + socket_params.color_inner[1] = color_inner[1]; + socket_params.color_inner[2] = color_inner[2]; + socket_params.color_inner[3] = color_inner[3]; + socket_params.color_outline[0] = color_outline[0]; + socket_params.color_outline[1] = color_outline[1]; + socket_params.color_outline[2] = color_outline[2]; + socket_params.color_outline[3] = color_outline[3]; + socket_params.outline_thickness = outline_thickness; + socket_params.dot_radius = dot_radius; + socket_params.outline_offset = outline_offset; + socket_params.shape = float(shape) + 0.1f; + + GPU_blend(GPU_BLEND_ALPHA); + draw_node_socket_batch(&socket_params); + GPU_blend(GPU_BLEND_NONE); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Node Link Drawing + * \{ */ + #define NODELINK_GROUP_SIZE 256 #define LINK_RESOL 24 #define LINK_WIDTH 2.5f @@ -2407,3 +2553,5 @@ void ED_node_draw_snap(View2D *v2d, const float cent[2], float size, NodeBorder immEnd(); } + +/** \} */ diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index a1a778bea9e..b0e62006e6b 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -1638,13 +1638,13 @@ void node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], }; float outline_color[4] = {0}; - UI_draw_node_socket(&draw_rect, - color, - outline_color, - NODE_SOCKET_OUTLINE * scale, - 0.0f, - NODE_SOCKET_DOT * scale, - sock->display_shape); + node_draw_nodesocket(&draw_rect, + color, + outline_color, + NODE_SOCKET_OUTLINE * scale, + 0.0f, + NODE_SOCKET_DOT * scale, + sock->display_shape); } static void node_draw_preview_background(rctf *rect) @@ -1752,15 +1752,15 @@ static void node_draw_shadow(const SpaceNode &snode, UI_draw_roundbox_4fv(&rect, false, radius + 0.5f, color); } -static void node_draw_socket_ex(const bContext &C, - const bNodeTree &ntree, - const bNode &node, - PointerRNA &node_ptr, - const bNodeSocket &sock, - const float outline_thickness, - const float outline_offset, - const float dot_radius, - const bool selected) +static void node_draw_socket(const bContext &C, + const bNodeTree &ntree, + const bNode &node, + PointerRNA &node_ptr, + const bNodeSocket &sock, + const float outline_thickness, + const float outline_offset, + const float dot_radius, + const bool selected) { const float half_width = NODE_SOCKSIZE; @@ -1781,13 +1781,13 @@ static void node_draw_socket_ex(const bContext &C, socket_location.y + half_height, }; - UI_draw_node_socket(&rect, - socket_color, - outline_color, - outline_thickness, - outline_offset, - dot_radius, - sock.display_shape); + node_draw_nodesocket(&rect, + socket_color, + outline_color, + outline_thickness, + outline_offset, + dot_radius, + sock.display_shape); } /* Some elements of the node tree like labels or node sockets are hardly visible when zoomed @@ -1818,13 +1818,14 @@ void node_draw_sockets(const View2D &v2d, const bContext &C, bNodeTree &ntree, c const float border_offset = 0.0f; const float dot_radius = NODE_SOCKET_DOT; + nodesocket_batch_start(); /* Input sockets. */ for (const bNodeSocket *sock : node.input_sockets()) { if (!node.is_socket_icon_drawn(*sock)) { continue; } const bool selected = (sock->flag & SELECT); - node_draw_socket_ex( + node_draw_socket( C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, selected); } @@ -1834,9 +1835,10 @@ void node_draw_sockets(const View2D &v2d, const bContext &C, bNodeTree &ntree, c continue; } const bool selected = (sock->flag & SELECT); - node_draw_socket_ex( + node_draw_socket( C, ntree, node, nodeptr, *sock, outline_thickness, border_offset, dot_radius, selected); } + nodesocket_batch_end(); } static void node_panel_toggle_button_cb(bContext *C, void *panel_state_argv, void *ntree_argv) @@ -3572,13 +3574,13 @@ void reroute_node_draw_body(const bContext &C, node_socket_color_get(C, ntree, nodeptr, sock, socket_color); node_socket_outline_color_get(selected, sock.type, outline_color); - UI_draw_node_socket(&node.runtime->totr, - socket_color, - outline_color, - NODE_SOCKET_OUTLINE, - 0.0f, - NODE_SOCKET_DOT, - sock.display_shape); + node_draw_nodesocket(&node.runtime->totr, + socket_color, + outline_color, + NODE_SOCKET_OUTLINE, + 0.0f, + NODE_SOCKET_DOT, + sock.display_shape); } static void reroute_node_draw_label(const bNode &node, uiBlock &block) diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh index ddf8eb89e6d..c332668fef9 100644 --- a/source/blender/editors/space_node/node_intern.hh +++ b/source/blender/editors/space_node/node_intern.hh @@ -244,6 +244,18 @@ NodeResizeDirection node_get_resize_direction(const SpaceNode &snode, int x, int y); +/* node socket batched drawing */ +void UI_node_socket_draw_cache_flush(); +void nodesocket_batch_start(); +void nodesocket_batch_end(); +void node_draw_nodesocket(const rctf *rect, + const float color_inner[4], + const float color_outline[4], + const float outline_thickness, + const float outline_offset, + const float dot_radius, + int shape); + void nodelink_batch_start(SpaceNode &snode); void nodelink_batch_end(SpaceNode &snode); diff --git a/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl index e95243eca6a..d8d333376b5 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_node_socket_vert.glsl @@ -16,17 +16,13 @@ #define outlineThickness parameters[widgetID * MAX_PARAM + 3].x #define outlineOffset parameters[widgetID * MAX_PARAM + 3].y #define dotRadius parameters[widgetID * MAX_PARAM + 3].z +#define shape parameters[widgetID * MAX_PARAM + 3].w #define AA_SIZE 0.75 -#define IS_CIRCLE \ - (shape_flags == SOCK_DISPLAY_SHAPE_CIRCLE || shape_flags == SOCK_DISPLAY_SHAPE_CIRCLE_DOT) #define IS_DIAMOND \ - (shape_flags == SOCK_DISPLAY_SHAPE_DIAMOND || shape_flags == SOCK_DISPLAY_SHAPE_DIAMOND_DOT) -#define IS_SQUARE \ - (shape_flags == SOCK_DISPLAY_SHAPE_SQUARE || shape_flags == SOCK_DISPLAY_SHAPE_SQUARE_DOT) + (shapeFlags == SOCK_DISPLAY_SHAPE_DIAMOND || shapeFlags == SOCK_DISPLAY_SHAPE_DIAMOND_DOT) #define HAS_DOT \ - (shape_flags == SOCK_DISPLAY_SHAPE_CIRCLE_DOT || \ - shape_flags == SOCK_DISPLAY_SHAPE_DIAMOND_DOT || shape_flags == SOCK_DISPLAY_SHAPE_SQUARE_DOT) + (shapeFlags > 2) /* Offsetting by a pixel further to avoid losing pixels. */ vec2 ofs = vec2(outlineOffset + 1.0, -outlineOffset - 1.0); @@ -44,7 +40,8 @@ float minSize = min(rectSize.x, rectSize.y); vec3 shapeRadii = vec3(CIRCLE_RADIUS, SQUARE_RADIUS, DIAMOND_RADIUS); vec3 cornerRoundness = vec3(1.0, 0.4, 0.4); -int shapeIndex = shape_flags % 3; +int shapeFlags = int(shape); +int shapeIndex = shapeFlags % 3; float shapeRadius = shapeRadii[shapeIndex]; float cornerRadius = shapeRadius * cornerRoundness[shapeIndex]; diff --git a/source/blender/gpu/shaders/infos/gpu_shader_2D_node_socket_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_2D_node_socket_info.hh index 16edef9d31a..e9042420a71 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_2D_node_socket_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_2D_node_socket_info.hh @@ -8,23 +8,23 @@ #include "gpu_interface_info.hh" #include "gpu_shader_create_info.hh" - GPU_SHADER_INTERFACE_INFO(gpu_node_socket_iface, "") - .flat(Type::FLOAT, "sdf_shape_radius") - .flat(Type::VEC4, "finalColor") - .flat(Type::VEC4, "finalOutlineColor") - .flat(Type::VEC4, "thresholds") - .flat(Type::VEC2, "dotThresholds") - .flat(Type::VEC2, "extrusion") - .flat(Type::INT, "is_diamond") - .smooth(Type::VEC2, "uv"); +GPU_SHADER_INTERFACE_INFO(gpu_node_socket_iface, "") + .flat(Type::FLOAT, "sdf_shape_radius") + .flat(Type::VEC4, "finalColor") + .flat(Type::VEC4, "finalOutlineColor") + .flat(Type::VEC4, "thresholds") + .flat(Type::VEC2, "dotThresholds") + .flat(Type::VEC2, "extrusion") + .flat(Type::INT, "is_diamond") + .smooth(Type::VEC2, "uv"); /* TODO(Leon): Share with C code. */ /* TODO(Leon): Tweak the instance count to test if there's a noticable sweet spot. */ -#define MAX_SOCKET_PARAM 4 -#define MAX_SOCKET_INSTANCE 18 +#define MAX_SOCKET_PARAMETERS 4 +#define MAX_SOCKET_INSTANCE 32 GPU_SHADER_CREATE_INFO(gpu_shader_2D_node_socket_shared) - .define("MAX_PARAM", STRINGIFY(MAX_SOCKET_PARAM)) + .define("MAX_PARAM", STRINGIFY(MAX_SOCKET_PARAMETERS)) .push_constant(Type::MAT4, "ModelViewProjectionMatrix") .vertex_out(gpu_node_socket_iface) .fragment_out(0, Type::VEC4, "fragColor") @@ -37,13 +37,11 @@ GPU_SHADER_CREATE_INFO(gpu_shader_2D_node_socket) * to be violated in some drivers. For example, macOS 10.15.4 and Intel Iris * causes #78307 when using gl_InstanceID outside of instance. */ .define("widgetID", "0") - .push_constant(Type::VEC4, "parameters", MAX_SOCKET_PARAM) - .push_constant(Type::INT, "shape_flags") + .push_constant(Type::VEC4, "parameters", MAX_SOCKET_PARAMETERS) .additional_info("gpu_shader_2D_node_socket_shared"); GPU_SHADER_CREATE_INFO(gpu_shader_2D_node_socket_inst) .do_static_compilation(true) .define("widgetID", "gl_InstanceID") - .push_constant(Type::VEC4, "parameters", (MAX_SOCKET_PARAM * MAX_SOCKET_INSTANCE)) - .push_constant(Type::INT, "shape_flags", MAX_SOCKET_INSTANCE) + .push_constant(Type::VEC4, "parameters", (MAX_SOCKET_PARAMETERS * MAX_SOCKET_INSTANCE)) .additional_info("gpu_shader_2D_node_socket_shared"); -- 2.30.2 From a8de4862226f5037ec25710e61ae12257c04777a Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 4 Jun 2024 15:06:10 +0200 Subject: [PATCH 07/11] remove unnecessary namespace --- source/blender/editors/space_node/drawnode.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index f956506e9d9..53cad2ebe3f 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -1840,17 +1840,17 @@ struct NodeSocketShaderParameters { #define MAX_SOCKET_INSTANCE 32 static struct { - blender::gpu::Batch *batch; + gpu::Batch *batch; NodeSocketShaderParameters params[MAX_SOCKET_INSTANCE]; int count; bool enabled; } g_batch_nodesocket; -blender::gpu::Batch *nodesocket_batch_init(void) +gpu::Batch *nodesocket_batch_init(void) { if (g_batch_nodesocket.batch == NULL) { GPUVertFormat format = {0}; - blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC); + gpu::VertBuf *vbo = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC); GPU_vertbuf_data_alloc(vbo, 6); @@ -1873,7 +1873,7 @@ static void nodesocket_cache_flush() return; } - blender::gpu::Batch *batch = nodesocket_batch_init(); + gpu::Batch *batch = nodesocket_batch_init(); if (g_batch_nodesocket.count == 1) { /* draw single */ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); @@ -1920,7 +1920,7 @@ static void draw_node_socket_batch(NodeSocketShaderParameters *socket_params) } else { /* draw single */ - blender::gpu::Batch *batch = nodesocket_batch_init(); + gpu::Batch *batch = nodesocket_batch_init(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); GPU_batch_uniform_4fv_array( batch, "parameters", MAX_SOCKET_PARAMETERS, (float(*)[4])socket_params); -- 2.30.2 From fb6c48f384a9fdcb241b8ea66c8bac87dea71706 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 4 Jun 2024 15:08:41 +0200 Subject: [PATCH 08/11] add static --- source/blender/editors/space_node/drawnode.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index 53cad2ebe3f..77253862659 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -1846,7 +1846,7 @@ static struct { bool enabled; } g_batch_nodesocket; -gpu::Batch *nodesocket_batch_init(void) +static gpu::Batch *nodesocket_batch_init(void) { if (g_batch_nodesocket.batch == NULL) { GPUVertFormat format = {0}; -- 2.30.2 From b83636c84f007e3fd808126bb2e32a1b604a6af4 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 4 Jun 2024 15:12:37 +0200 Subject: [PATCH 09/11] use Vector instead of c-array --- source/blender/editors/space_node/drawnode.cc | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index 77253862659..477bc85a0bf 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -1841,8 +1841,7 @@ struct NodeSocketShaderParameters { static struct { gpu::Batch *batch; - NodeSocketShaderParameters params[MAX_SOCKET_INSTANCE]; - int count; + Vector params; bool enabled; } g_batch_nodesocket; @@ -1869,16 +1868,16 @@ static gpu::Batch *nodesocket_batch_init(void) static void nodesocket_cache_flush() { - if (g_batch_nodesocket.count == 0) { + if (g_batch_nodesocket.params.is_empty()) { return; } gpu::Batch *batch = nodesocket_batch_init(); - if (g_batch_nodesocket.count == 1) { + if (g_batch_nodesocket.params.size() == 1) { /* draw single */ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); GPU_batch_uniform_4fv_array( - batch, "parameters", 4, (const float(*)[4])g_batch_nodesocket.params); + batch, "parameters", 4, (const float(*)[4])g_batch_nodesocket.params.data()); GPU_batch_draw(batch); } else { @@ -1886,10 +1885,10 @@ static void nodesocket_cache_flush() GPU_batch_uniform_4fv_array(batch, "parameters", MAX_SOCKET_PARAMETERS * MAX_SOCKET_INSTANCE, - (float(*)[4])g_batch_nodesocket.params); - GPU_batch_draw_instance_range(batch, 0, g_batch_nodesocket.count); + (float(*)[4])g_batch_nodesocket.params.data()); + GPU_batch_draw_instance_range(batch, 0, g_batch_nodesocket.params.size()); } - g_batch_nodesocket.count = 0; + g_batch_nodesocket.params.clear(); } void nodesocket_batch_start() @@ -1911,10 +1910,9 @@ void nodesocket_batch_end() static void draw_node_socket_batch(NodeSocketShaderParameters *socket_params) { if (g_batch_nodesocket.enabled) { - g_batch_nodesocket.params[g_batch_nodesocket.count] = *socket_params; - g_batch_nodesocket.count++; + g_batch_nodesocket.params.append(*socket_params); - if (g_batch_nodesocket.count >= MAX_SOCKET_INSTANCE) { + if (g_batch_nodesocket.params.size() >= MAX_SOCKET_INSTANCE) { nodesocket_cache_flush(); } } -- 2.30.2 From 20fad7898ff7f0f0405d51f4083445954ebf6da3 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 4 Jun 2024 15:13:58 +0200 Subject: [PATCH 10/11] use const and reference --- source/blender/editors/space_node/drawnode.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index 477bc85a0bf..f8c2e893a6e 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -1907,10 +1907,10 @@ void nodesocket_batch_end() GPU_blend(GPU_BLEND_NONE); } -static void draw_node_socket_batch(NodeSocketShaderParameters *socket_params) +static void draw_node_socket_batch(const NodeSocketShaderParameters &socket_params) { if (g_batch_nodesocket.enabled) { - g_batch_nodesocket.params.append(*socket_params); + g_batch_nodesocket.params.append(socket_params); if (g_batch_nodesocket.params.size() >= MAX_SOCKET_INSTANCE) { nodesocket_cache_flush(); @@ -1921,7 +1921,7 @@ static void draw_node_socket_batch(NodeSocketShaderParameters *socket_params) gpu::Batch *batch = nodesocket_batch_init(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); GPU_batch_uniform_4fv_array( - batch, "parameters", MAX_SOCKET_PARAMETERS, (float(*)[4])socket_params); + batch, "parameters", MAX_SOCKET_PARAMETERS, (const float(*)[4])(&socket_params)); GPU_batch_draw(batch); } } @@ -1954,7 +1954,7 @@ void node_draw_nodesocket(const rctf *rect, socket_params.shape = float(shape) + 0.1f; GPU_blend(GPU_BLEND_ALPHA); - draw_node_socket_batch(&socket_params); + draw_node_socket_batch(socket_params); GPU_blend(GPU_BLEND_NONE); } -- 2.30.2 From a561a9c6fac1251bdd870229734c67489a6651dc Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 4 Jun 2024 15:14:17 +0200 Subject: [PATCH 11/11] cleanup comment --- source/blender/editors/space_node/drawnode.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index f8c2e893a6e..a5dd1722f16 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -1917,7 +1917,7 @@ static void draw_node_socket_batch(const NodeSocketShaderParameters &socket_para } } else { - /* draw single */ + /* Draw single instead of batch. */ gpu::Batch *batch = nodesocket_batch_init(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODE_SOCKET); GPU_batch_uniform_4fv_array( -- 2.30.2