diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 7db8b8164e9..3cc0a30717c 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -353,11 +353,15 @@ static bool is_node_panels_supported(const bNode &node) } /* Draw UI for options, buttons, and previews. */ -static bool node_update_basis_buttons( - const bContext &C, bNodeTree &ntree, bNode &node, uiBlock &block, int &dy) +static bool node_update_basis_buttons(const bContext &C, + bNodeTree &ntree, + bNode &node, + nodes::PanelDrawButtonsFunction draw_buttons, + uiBlock &block, + int &dy) { /* Buttons rect? */ - const bool node_options = node.typeinfo->draw_buttons && (node.flag & NODE_OPTIONS); + const bool node_options = draw_buttons && (node.flag & NODE_OPTIONS); if (!node_options) { return false; } @@ -388,7 +392,7 @@ static bool node_update_basis_buttons( uiLayoutSetContextPointer(layout, "node", &nodeptr); - node.typeinfo->draw_buttons(layout, (bContext *)&C, &nodeptr); + draw_buttons(layout, (bContext *)&C, &nodeptr); UI_block_align_end(&block); int buty; @@ -686,7 +690,8 @@ static void node_update_basis_from_declaration( /* Draw buttons before the first panel. */ if (!buttons_drawn) { buttons_drawn = true; - need_spacer_after_item = node_update_basis_buttons(C, ntree, node, block, locy); + need_spacer_after_item = node_update_basis_buttons( + C, ntree, node, node.typeinfo->draw_buttons, block, locy); } if (!is_parent_collapsed) { @@ -710,6 +715,7 @@ static void node_update_basis_from_declaration( item.runtime->max_content_y = item.runtime->min_content_y = round(locy); if (!is_collapsed) { locy -= NODE_ITEM_SPACING_Y; /* Space at top of panel contents. */ + node_update_basis_buttons(C, ntree, node, item.panel_decl->draw_buttons, block, locy); } } else if (item.is_valid_socket()) { @@ -718,7 +724,8 @@ static void node_update_basis_from_declaration( /* Draw buttons before the first input, unless it's inline with an output. */ if (!item.socket_decl->inline_with_next && !buttons_drawn) { buttons_drawn = true; - need_spacer_after_item = node_update_basis_buttons(C, ntree, node, block, locy); + need_spacer_after_item = node_update_basis_buttons( + C, ntree, node, node.typeinfo->draw_buttons, block, locy); } if (is_parent_collapsed) { @@ -782,7 +789,8 @@ static void node_update_basis_from_declaration( /* Draw buttons at the bottom if no inputs exist. */ if (!buttons_drawn) { - need_spacer_after_item = node_update_basis_buttons(C, ntree, node, block, locy); + need_spacer_after_item = node_update_basis_buttons( + C, ntree, node, node.typeinfo->draw_buttons, block, locy); } if (need_spacer_after_item) { @@ -821,7 +829,7 @@ static void node_update_basis_from_socket_lists( locy -= NODE_DY / 4; } - node_update_basis_buttons(C, ntree, node, block, locy); + node_update_basis_buttons(C, ntree, node, node.typeinfo->draw_buttons, block, locy); /* Input sockets. */ for (bNodeSocket *socket : node.input_sockets()) { diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc index e015f2365ca..0ed01316118 100644 --- a/source/blender/editors/space_node/node_templates.cc +++ b/source/blender/editors/space_node/node_templates.cc @@ -781,7 +781,8 @@ static void ui_node_draw_panel(uiLayout &layout, bContext &C, bNodeTree &ntree, const nodes::PanelDeclaration &panel_decl, - bNodePanelState &panel_state) + bNodePanelState &panel_state, + PointerRNA nodeptr) { uiLayout *row = uiLayoutRow(&layout, true); uiLayoutSetPropDecorate(row, false); @@ -808,6 +809,12 @@ static void ui_node_draw_panel(uiLayout &layout, UI_but_drawflag_enable(but, UI_BUT_TEXT_LEFT | UI_BUT_NO_TOOLTIP); UI_but_func_set(but, node_panel_toggle_button_cb, &panel_state, &ntree); UI_block_emboss_set(block, UI_EMBOSS); + + /* Panel buttons. */ + if (!panel_state.is_collapsed() && panel_decl.draw_buttons) { + uiLayoutSetPropSep(&layout, true); + panel_decl.draw_buttons(&layout, &C, &nodeptr); + } } static void ui_node_draw_node( @@ -853,7 +860,7 @@ static void ui_node_draw_node( { panel_collapsed = panel_state->is_collapsed(); panel_label = panel_decl->name.c_str(); - ui_node_draw_panel(layout, C, ntree, *panel_decl, *panel_state); + ui_node_draw_panel(layout, C, ntree, *panel_decl, *panel_state, nodeptr); ++panel_state; } } diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh index 195fdc7a1f0..34018d184af 100644 --- a/source/blender/nodes/NOD_node_declaration.hh +++ b/source/blender/nodes/NOD_node_declaration.hh @@ -16,7 +16,10 @@ #include "DNA_node_types.h" +struct bContext; struct bNode; +struct PointerRNA; +struct uiLayout; namespace blender::nodes { @@ -569,6 +572,8 @@ class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder { using SocketDeclarationPtr = std::unique_ptr; +typedef void (*PanelDrawButtonsFunction)(uiLayout *, bContext *, PointerRNA *); + /** * Describes a panel containing sockets or other panels. */ @@ -580,6 +585,7 @@ class PanelDeclaration : public ItemDeclaration { std::string translation_context; bool default_collapsed = false; int num_child_decls = 0; + PanelDrawButtonsFunction draw_buttons = nullptr; private: friend NodeDeclarationBuilder; @@ -619,6 +625,12 @@ class PanelDeclarationBuilder { return *this; } + Self &draw_buttons(PanelDrawButtonsFunction func) + { + decl_->draw_buttons = func; + return *this; + } + template typename DeclType::Builder &add_input(StringRef name, StringRef identifier = ""); template diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index 4cd09c181d7..46c20b8016d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -54,7 +54,12 @@ static void node_declare(NodeDeclarationBuilder &b) #define SOCK_WEIGHT_ID 7 /* Panel for Subsurface scattering settings. */ - PanelDeclarationBuilder &sss = b.add_panel("Subsurface").default_closed(true); + PanelDeclarationBuilder &sss = + b.add_panel("Subsurface") + .default_closed(true) + .draw_buttons([](uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) { + uiItemR(layout, ptr, "subsurface_method", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + }); sss.add_input("Subsurface") .default_value(0.0f) .min(0.0f) @@ -93,7 +98,12 @@ static void node_declare(NodeDeclarationBuilder &b) #define SOCK_SUBSURFACE_ANISOTROPY_ID 12 /* Panel for Specular settings. */ - PanelDeclarationBuilder &spec = b.add_panel("Specular").default_closed(true); + PanelDeclarationBuilder &spec = + b.add_panel("Specular") + .default_closed(true) + .draw_buttons([](uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) { + uiItemR(layout, ptr, "distribution", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); + }); spec.add_input("Specular") .default_value(0.5f) .min(0.0f) @@ -179,12 +189,6 @@ static void node_declare(NodeDeclarationBuilder &b) #define SOCK_EMISSION_STRENGTH_ID 27 } -static void node_shader_buts_principled(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) -{ - uiItemR(layout, ptr, "distribution", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); - uiItemR(layout, ptr, "subsurface_method", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); -} - static void node_shader_init_principled(bNodeTree * /*ntree*/, bNode *node) { node->custom1 = SHD_GLOSSY_MULTI_GGX; @@ -314,7 +318,6 @@ void register_node_type_sh_bsdf_principled() sh_node_type_base(&ntype, SH_NODE_BSDF_PRINCIPLED, "Principled BSDF", NODE_CLASS_SHADER); ntype.declare = file_ns::node_declare; ntype.add_ui_poll = object_shader_nodes_poll; - ntype.draw_buttons = file_ns::node_shader_buts_principled; blender::bke::node_type_size_preset(&ntype, blender::bke::eNodeSizePreset::LARGE); ntype.initfunc = file_ns::node_shader_init_principled; ntype.gpu_fn = file_ns::node_shader_gpu_bsdf_principled;