WIP: Brush assets project #106303
|
@ -705,31 +705,7 @@ class NODE_PT_active_node_properties(Panel):
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
node = context.active_node
|
node = context.active_node
|
||||||
# set "node" context pointer for the panel layout
|
layout.template_node_inputs(node)
|
||||||
layout.context_pointer_set("node", node)
|
|
||||||
|
|
||||||
if hasattr(node, "draw_buttons_ext"):
|
|
||||||
node.draw_buttons_ext(context, layout)
|
|
||||||
elif hasattr(node, "draw_buttons"):
|
|
||||||
node.draw_buttons(context, layout)
|
|
||||||
|
|
||||||
# XXX this could be filtered further to exclude socket types
|
|
||||||
# which don't have meaningful input values (e.g. cycles shader)
|
|
||||||
value_inputs = [socket for socket in node.inputs if self.show_socket_input(socket)]
|
|
||||||
if value_inputs:
|
|
||||||
layout.separator()
|
|
||||||
layout.label(text="Inputs:")
|
|
||||||
for socket in value_inputs:
|
|
||||||
row = layout.row()
|
|
||||||
socket.draw(
|
|
||||||
context,
|
|
||||||
row,
|
|
||||||
node,
|
|
||||||
iface_(socket.label if socket.label else socket.name, socket.bl_rna.translation_context),
|
|
||||||
)
|
|
||||||
|
|
||||||
def show_socket_input(self, socket):
|
|
||||||
return hasattr(socket, "draw") and socket.enabled and not socket.is_linked
|
|
||||||
|
|
||||||
|
|
||||||
class NODE_PT_texture_mapping(Panel):
|
class NODE_PT_texture_mapping(Panel):
|
||||||
|
|
|
@ -2714,6 +2714,10 @@ void uiTemplateGreasePencilLayerTree(uiLayout *layout, bContext *C);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void uiTemplateNodeTreeInterface(uiLayout *layout, PointerRNA *ptr);
|
void uiTemplateNodeTreeInterface(uiLayout *layout, PointerRNA *ptr);
|
||||||
|
/**
|
||||||
|
* Draw all node buttons and socket default values with the same panel structure used by the node.
|
||||||
|
*/
|
||||||
|
void uiTemplateNodeInputs(uiLayout *layout, bContext *C, PointerRNA *ptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \return: A RNA pointer for the operator properties.
|
* \return: A RNA pointer for the operator properties.
|
||||||
|
|
|
@ -70,6 +70,7 @@ set(SRC
|
||||||
interface_template_bone_collection_tree.cc
|
interface_template_bone_collection_tree.cc
|
||||||
interface_template_light_linking.cc
|
interface_template_light_linking.cc
|
||||||
interface_template_list.cc
|
interface_template_list.cc
|
||||||
|
interface_template_node_inputs.cc
|
||||||
interface_template_node_tree_interface.cc
|
interface_template_node_tree_interface.cc
|
||||||
interface_template_search_menu.cc
|
interface_template_search_menu.cc
|
||||||
interface_template_search_operator.cc
|
interface_template_search_operator.cc
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup edinterface
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BLI_vector.hh"
|
||||||
|
|
||||||
|
#include "BKE_context.hh"
|
||||||
|
#include "BKE_node.hh"
|
||||||
|
#include "BKE_node_runtime.hh"
|
||||||
|
#include "BKE_screen.hh"
|
||||||
|
|
||||||
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
|
#include "NOD_node_declaration.hh"
|
||||||
|
|
||||||
|
#include "RNA_access.hh"
|
||||||
|
#include "RNA_prototypes.h"
|
||||||
|
|
||||||
|
#include "UI_interface.hh"
|
||||||
|
#include "UI_resources.hh"
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Node Input Buttons Template
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
using blender::nodes::ItemDeclaration;
|
||||||
|
using blender::nodes::NodeDeclaration;
|
||||||
|
using blender::nodes::PanelDeclaration;
|
||||||
|
using blender::nodes::SocketDeclaration;
|
||||||
|
|
||||||
|
using ItemIterator = blender::Vector<blender::nodes::ItemDeclarationPtr>::const_iterator;
|
||||||
|
|
||||||
|
namespace blender::ui::nodes {
|
||||||
|
|
||||||
|
static void draw_node_input(bContext *C,
|
||||||
|
uiLayout *layout,
|
||||||
|
PointerRNA *node_ptr,
|
||||||
|
bNodeSocket &socket)
|
||||||
|
{
|
||||||
|
BLI_assert(socket.typeinfo != nullptr);
|
||||||
|
/* Ignore disabled sockets and linked sockets and sockets without a `draw` callback. */
|
||||||
|
if (!socket.is_available() || (socket.flag & SOCK_IS_LINKED) || socket.typeinfo->draw == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PointerRNA socket_ptr = RNA_pointer_create(node_ptr->owner_id, &RNA_NodeSocket, &socket);
|
||||||
|
const char *text = IFACE_(bke::nodeSocketLabel(&socket));
|
||||||
|
socket.typeinfo->draw(C, layout, &socket_ptr, node_ptr, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_node_input(bContext *C,
|
||||||
|
uiLayout *layout,
|
||||||
|
PointerRNA *node_ptr,
|
||||||
|
StringRefNull identifier)
|
||||||
|
{
|
||||||
|
bNode &node = *static_cast<bNode *>(node_ptr->data);
|
||||||
|
bNodeSocket *socket = node.runtime->inputs_by_identifier.lookup(identifier);
|
||||||
|
draw_node_input(C, layout, node_ptr, *socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consume the item range, draw buttons if layout is not null. */
|
||||||
|
static void handle_node_declaration_items(bContext *C,
|
||||||
|
Panel *root_panel,
|
||||||
|
uiLayout *layout,
|
||||||
|
PointerRNA *node_ptr,
|
||||||
|
ItemIterator &item_iter,
|
||||||
|
const ItemIterator item_end)
|
||||||
|
{
|
||||||
|
while (item_iter != item_end) {
|
||||||
|
const ItemDeclaration *item_decl = item_iter->get();
|
||||||
|
++item_iter;
|
||||||
|
|
||||||
|
if (const SocketDeclaration *socket_decl = dynamic_cast<const SocketDeclaration *>(item_decl))
|
||||||
|
{
|
||||||
|
if (layout && socket_decl->in_out == SOCK_IN) {
|
||||||
|
draw_node_input(C, layout, node_ptr, socket_decl->identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (const PanelDeclaration *panel_decl = dynamic_cast<const PanelDeclaration *>(
|
||||||
|
item_decl))
|
||||||
|
{
|
||||||
|
const ItemIterator panel_item_end = item_iter + panel_decl->num_child_decls;
|
||||||
|
BLI_assert(panel_item_end <= item_end);
|
||||||
|
|
||||||
|
/* Use a root panel property to toggle open/closed state. */
|
||||||
|
const std::string panel_idname = "NodePanel" + std::to_string(panel_decl->identifier);
|
||||||
|
LayoutPanelState *state = BKE_panel_layout_panel_state_ensure(
|
||||||
|
root_panel, panel_idname.c_str(), panel_decl->default_collapsed);
|
||||||
|
PointerRNA state_ptr = RNA_pointer_create(nullptr, &RNA_LayoutPanelState, state);
|
||||||
|
uiLayout *panel_layout = uiLayoutPanel(
|
||||||
|
C, layout, IFACE_(panel_decl->name.c_str()), &state_ptr, "is_open");
|
||||||
|
/* Draw panel buttons at the top of each panel section. */
|
||||||
|
if (panel_layout && panel_decl->draw_buttons) {
|
||||||
|
panel_decl->draw_buttons(panel_layout, C, node_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_node_declaration_items(
|
||||||
|
C, root_panel, panel_layout, node_ptr, item_iter, panel_item_end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::ui::nodes
|
||||||
|
|
||||||
|
void uiTemplateNodeInputs(uiLayout *layout, bContext *C, PointerRNA *ptr)
|
||||||
|
{
|
||||||
|
bNodeTree &tree = *reinterpret_cast<bNodeTree *>(ptr->owner_id);
|
||||||
|
bNode &node = *static_cast<bNode *>(ptr->data);
|
||||||
|
|
||||||
|
tree.ensure_topology_cache();
|
||||||
|
|
||||||
|
BLI_assert(node.typeinfo != nullptr);
|
||||||
|
/* Draw top-level node buttons. */
|
||||||
|
if (node.typeinfo->draw_buttons_ex) {
|
||||||
|
node.typeinfo->draw_buttons_ex(layout, C, ptr);
|
||||||
|
}
|
||||||
|
else if (node.typeinfo->draw_buttons) {
|
||||||
|
node.typeinfo->draw_buttons(layout, C, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.declaration()) {
|
||||||
|
/* Draw socket inputs and panel buttons in the order of declaration panels. */
|
||||||
|
ItemIterator item_iter = node.declaration()->items.begin();
|
||||||
|
const ItemIterator item_end = node.declaration()->items.end();
|
||||||
|
Panel *root_panel = uiLayoutGetRootPanel(layout);
|
||||||
|
blender::ui::nodes::handle_node_declaration_items(
|
||||||
|
C, root_panel, layout, ptr, item_iter, item_end);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Draw socket values using the flat inputs list. */
|
||||||
|
for (bNodeSocket *input : node.runtime->inputs) {
|
||||||
|
blender::ui::nodes::draw_node_input(C, layout, ptr, *input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
|
@ -2205,6 +2205,12 @@ void RNA_api_ui_layout(StructRNA *srna)
|
||||||
"Node Tree Interface",
|
"Node Tree Interface",
|
||||||
"Interface of a node tree to display");
|
"Interface of a node tree to display");
|
||||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||||
|
|
||||||
|
func = RNA_def_function(srna, "template_node_inputs", "uiTemplateNodeInputs");
|
||||||
|
RNA_def_function_ui_description(func, "Show a node settings and input socket values");
|
||||||
|
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||||
|
parm = RNA_def_pointer(func, "node", "Node", "Node", "Display inputs of this node");
|
||||||
|
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue