66 if (socket->identifier == identifier) {
141 const char **r_disabled_hint)
172 const char **r_disabled_hint)
177 if (grouptree ==
nullptr) {
181 if (nodetree == grouptree) {
182 if (r_disabled_hint) {
183 *r_disabled_hint =
RPT_(
"Nesting a node group inside of itself is not allowed");
187 if (nodetree->
type != grouptree->
type) {
188 if (r_disabled_hint) {
189 *r_disabled_hint =
RPT_(
"Node group has different type");
194 for (
const bNode *node : grouptree->all_nodes()) {
195 if (node->typeinfo->poll_instance &&
196 !node->typeinfo->poll_instance(node, nodetree, r_disabled_hint))
209 const int item_index = tree_interface.find_item_index(io_socket.
item);
213 return [item_index](
const bNode &node) ->
ID * {
214 if (node.id ==
nullptr) {
217 if (
GS(node.id->name) !=
ID_NT) {
231static std::function<void(
bNode &node,
bNodeSocket &socket,
const char *data_path)>
234 const int item_index =
interface.find_item_index(io_socket.
item);
238 return [item_index](
bNode &node,
bNodeSocket &socket,
const char *data_path) {
239 if (node.
id ==
nullptr) {
262 const std::optional<StructureType> structure_type,
275 datatype = base_typeinfo->
type;
291 .dimensions(value.dimensions)
400 if (structure_type) {
401 decl->structure_type(*structure_type);
417 bool layout_added =
false;
418 auto add_layout_if_needed = [&]() {
421 if (is_root && !layout_added) {
422 b.add_default_layout();
435 add_layout_if_needed();
438 group, io_socket, structure_type_by_socket.
lookup_try(&io_socket), in_out,
b);
442 add_layout_if_needed();
444 auto &panel_b =
b.add_panel(
StringRef(io_panel.name), io_panel.identifier)
445 .description(
StringRef(io_panel.description))
448 panel_b, node, group, structure_type_by_socket, io_panel,
false);
454 add_layout_if_needed();
459 const bNode *node =
b.node_or_null();
460 if (node ==
nullptr) {
477 group->ensure_interface_cache();
481 structure_type_by_socket.
reserve(group->interface_items().size());
485 group->
runtime->structure_type_interface->inputs;
486 for (
const int i :
inputs.index_range()) {
487 structure_type_by_socket.
add(
inputs[
i], input_structure_types[
i]);
492 group->
runtime->structure_type_interface->outputs;
493 for (
const int i :
outputs.index_range()) {
494 structure_type_by_socket.
add(
outputs[
i], output_structure_types[
i].type);
502 group->ensure_interface_cache();
505 *group->
runtime->field_inferencing_interface;
506 for (
const int i :
inputs.index_range()) {
511 for (
const int i : r_declaration.
outputs.index_range()) {
512 r_declaration.
outputs[
i]->output_field_dependency = field_interface.
outputs[
i];
532 data->label_size = 20;
544 "Collect related nodes together in a common area. Useful for organization when the "
545 "re-usability of a node group is not required";
565 const bNode *node =
b.node_or_null();
566 if (node ==
nullptr) {
573 .idname(socket_idname.
c_str())
576 .idname(socket_idname.
c_str())
596 "A single-socket organization tool that supports one input and multiple outputs";
607 int node_i = std::numeric_limits<int>::max();
618 if (this->node_i == other.
node_i) {
621 return this->node_i < other.
node_i;
628 ntree->ensure_topology_cache();
630 const Span<bNode *> all_reroute_nodes = ntree->nodes_by_type(
"NodeReroute");
633 for (
const bNode *reroute : all_reroute_nodes) {
634 reroute_nodes.
add(reroute->index());
644 for (
const bNode *src_reroute : all_reroute_nodes) {
645 const int src_reroute_i = reroute_nodes.
index_of(src_reroute->index());
647 src_reroute->output_sockets().first()->directly_linked_sockets())
649 const bNode &dst_node = dst_socket->owner_node();
650 if (!dst_node.is_reroute()) {
653 const int dst_reroute_i = reroute_nodes.
index_of(dst_node.index());
654 reroutes_groups.
join(src_reroute_i, dst_reroute_i);
659 for (
const int reroute_i : reroute_nodes.
index_range()) {
660 const int root_reroute_i = reroutes_groups.find_root(reroute_i);
661 reroute_groups.
add(root_reroute_i);
674 for (
const bNodeLink *link : ntree->all_links()) {
675 const bNode *src_node = link->fromnode;
676 const bNode *dst_node = link->tonode;
678 if (src_node->is_reroute() == dst_node->is_reroute()) {
682 if (!dst_node->is_reroute()) {
683 const int src_reroute_i = reroute_nodes.
index_of(src_node->index());
684 const int src_reroute_root_i = reroutes_groups.find_root(src_reroute_i);
685 const int src_reroute_group_i = reroute_groups.
index_of(src_reroute_root_i);
688 if (reroute_group_dst_type_priority[src_reroute_group_i] > type_priority) {
692 reroute_group_dst_type_priority[src_reroute_group_i] = type_priority;
697 dst_type_by_reroute_group[src_reroute_group_i] = dst_socket->
typeinfo;
702 const int dst_reroute_i = reroute_nodes.
index_of(dst_node->index());
703 const int dst_reroute_root_i = reroutes_groups.find_root(dst_reroute_i);
704 const int dst_reroute_group_i = reroute_groups.
index_of(dst_reroute_root_i);
709 src_type_by_reroute_group[dst_reroute_group_i] = src_socket->
typeinfo;
713 for (
const int reroute_i : reroute_nodes.
index_range()) {
714 const int reroute_root_i = reroutes_groups.find_root(reroute_i);
715 const int reroute_group_i = reroute_groups.
index_of(reroute_root_i);
718 if (dst_type_by_reroute_group[reroute_group_i] !=
nullptr) {
719 reroute_type = dst_type_by_reroute_group[reroute_group_i];
721 if (src_type_by_reroute_group[reroute_group_i] !=
nullptr) {
722 reroute_type = src_type_by_reroute_group[reroute_group_i];
725 if (reroute_type ==
nullptr) {
729 const int reroute_index = reroute_nodes[reroute_i];
730 bNode &reroute_node = *all_nodes[reroute_index];
741 ntree.ensure_topology_cache();
743 for (
const bNodeSocket *socket : node.output_sockets()) {
744 for (
const bNodeLink *link : socket->directly_linked_links()) {
745 nodes_to_check.
push(link->tonode);
748 while (!nodes_to_check.
is_empty()) {
749 const bNode *next_node = nodes_to_check.
pop();
750 for (
const bNodeSocket *socket : next_node->output_sockets()) {
751 for (
const bNodeLink *link : socket->directly_linked_links()) {
757 nodes_to_check.
push(link->tonode);
774 if (sock->identifier == identifier) {
785 const bNodeTree *node_tree =
b.tree_or_null();
786 if (node_tree ==
nullptr) {
815 const bNodeTree *node_tree =
b.tree_or_null();
816 if (node_tree ==
nullptr) {
894 get_compositor_group_input_extra_info(
params);
904 ntype->
ui_name =
"Group Input";
906 "Expose connected data from inside a node group as inputs to its interface";
923 if (sock->identifier == identifier) {
932 get_compositor_group_output_extra_info(
params);
935 if (group_output_nodes.
size() <= 1) {
943 row.
icon = ICON_ERROR;
944 row.
tooltip =
TIP_(
"There are multiple group output nodes and this one is not active");
945 params.rows.append(std::move(row));
955 ntype->
ui_name =
"Group Output";
956 ntype->
ui_description =
"Output data from inside of a node group";
#define NODE_CLASS_OUTPUT
#define NODE_CLASS_INTERFACE
#define NODE_CLASS_CONVERTER
#define NODE_CLASS_PATTERN
#define NODE_CLASS_GEOMETRY
#define NODE_GROUP_OUTPUT
#define NODE_CLASS_DISTORT
#define NODE_CLASS_OP_VECTOR
#define NODE_CLASS_LAYOUT
#define NODE_CLASS_OP_COLOR
#define NODE_CLASS_OP_FILTER
#define NODE_CLASS_ATTRIBUTE
#define NODE_CLASS_TEXTURE
#define NODE_CLASS_SHADER
#define NODE_CLASS_SCRIPT
#define LISTBASE_FOREACH(type, var, list)
char * STRNCPY(char(&dst)[N], const char *src)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define BLT_I18NCONTEXT_ID_NODETREE
#define CTX_IFACE_(context, msgid)
#define ID_IS_LINKED(_id)
NodeTreeInterfaceItemType
@ NODE_INTERFACE_PANEL_DEFAULT_CLOSED
@ NODE_INTERFACE_SOCKET_OUTPUT
@ NODE_INTERFACE_SOCKET_PANEL_TOGGLE
@ NODE_INTERFACE_SOCKET_INPUT
@ NODE_INTERFACE_SOCKET_OPTIONAL_LABEL
@ NODE_INTERFACE_SOCKET_MENU_EXPANDED
@ NODE_INTERFACE_SOCKET_COMPACT
@ NODE_INTERFACE_SOCKET_HIDE_VALUE
@ NODE_DEFAULT_INPUT_VALUE
Read Guarded memory(de)allocation.
BMesh const char void * data
void join(const size_t x, const size_t y)
int64_t index_of(const Key &key) const
IndexRange index_range() const
std::optional< Value > lookup_try(const Key &key) const
bool add(const Key &key, const Value &value)
constexpr int64_t size() const
void push(const T &value)
constexpr bool startswith(StringRef prefix) const
void copy_utf8_truncated(char *dst, int64_t dst_size) const
constexpr const char * c_str() const
bool skip_updating_sockets
Vector< SocketDeclaration * > inputs
Vector< SocketDeclaration * > outputs
bool use_custom_socket_order
StructureType structure_type
std::function< void(bNode &node, bNodeSocket &socket, const char *data_path)> init_socket_fn
std::string default_value
void * MEM_callocN(size_t len, const char *str)
T & get_item_as(bNodeTreeInterfaceItem &item)
bNodeTreeInterfaceSocket * add_interface_socket_from_node(bNodeTree &ntree, const bNode &from_node, const bNodeSocket &from_sock, StringRef socket_type, StringRef name)
T & get_socket_data_as(bNodeTreeInterfaceSocket &item)
bool node_is_connected_to_output(const bNodeTree &ntree, const bNode &node)
bool node_group_poll(const bNodeTree *nodetree, const bNodeTree *grouptree, const char **r_disabled_hint)
void node_type_size(bNodeType &ntype, int width, int minwidth, int maxwidth)
void node_register_type(bNodeType &ntype)
void node_type_base(bNodeType &ntype, std::string idname, std::optional< int16_t > legacy_type=std::nullopt)
bNodeSocketType * node_socket_type_find(StringRef idname)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
void node_tree_interface_draw(bContext &C, uiLayout &layout, bNodeTree &tree)
EulerXYZBase< float > EulerXYZ
static void group_input_declare(NodeDeclarationBuilder &b)
static std::function< ID *(const bNode &node)> get_default_id_getter(const bNodeTreeInterface &tree_interface, const bNodeTreeInterfaceSocket &io_socket)
static void node_group_output_layout(uiLayout *layout, bContext *C, PointerRNA *ptr)
static bool group_input_insert_link(blender::bke::NodeInsertLinkParams ¶ms)
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
compositor::NodeOperation * get_group_output_compositor_operation(compositor::Context &context, DNode node)
static std::function< void(bNode &node, bNodeSocket &socket, const char *data_path)> get_init_socket_fn(const bNodeTreeInterface &interface, const bNodeTreeInterfaceSocket &io_socket)
void node_group_declare(NodeDeclarationBuilder &b)
static bool group_output_insert_link(blender::bke::NodeInsertLinkParams ¶ms)
static void node_group_input_layout(uiLayout *layout, bContext *C, PointerRNA *ptr)
static void group_output_declare(NodeDeclarationBuilder &b)
compositor::NodeOperation * get_group_input_compositor_operation(compositor::Context &context, DNode node)
static BaseSocketDeclarationBuilder & build_interface_socket_declaration(const bNodeTree &tree, const bNodeTreeInterfaceSocket &io_socket, const std::optional< StructureType > structure_type, const eNodeSocketInOut in_out, DeclarationListBuilder &b)
static void node_group_declare_panel_recursive(DeclarationListBuilder &b, const bNode &node, const bNodeTree &group, const Map< const bNodeTreeInterfaceSocket *, StructureType > &structure_type_by_socket, const bNodeTreeInterfacePanel &io_parent_panel, const bool is_root)
VecBase< float, 4 > float4
VecBase< float, 3 > float3
static void node_group_input_extra_info(blender::nodes::NodeExtraInfoParams ¶ms)
static void node_group_output_extra_info(blender::nodes::NodeExtraInfoParams ¶ms)
static bNodeSocket * find_matching_socket(ListBase &sockets, StringRef identifier)
int node_group_ui_class(const bNode *node)
bNodeSocket * node_group_output_find_socket(bNode *node, const StringRef identifier)
bNodeSocket * node_group_input_find_socket(bNode *node, const StringRef identifier)
void register_node_type_group_output()
void node_group_label(const bNodeTree *, const bNode *node, char *label, int label_maxncpy)
void register_node_type_group_input()
bNodeSocket * node_group_find_input_socket(bNode *groupnode, const blender::StringRef identifier)
void ntree_update_reroute_nodes(bNodeTree *ntree)
static void node_frame_init(bNodeTree *, bNode *node)
bool node_group_poll_instance(const bNode *node, const bNodeTree *nodetree, const char **r_disabled_hint)
static void node_reroute_init(bNodeTree *, bNode *node)
void register_node_type_frame()
bNodeSocket * node_group_find_output_socket(bNode *groupnode, const blender::StringRef identifier)
static void node_reroute_declare(blender::nodes::NodeDeclarationBuilder &b)
std::string node_group_ui_description(const bNode &node)
void register_node_type_reroute()
static blender::bke::bNodeSocketTemplate outputs[]
static blender::bke::bNodeSocketTemplate inputs[]
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
struct AssetMetaData * asset_data
RerouteTargetPriority()=default
RerouteTargetPriority(const bNodeSocket &socket)
bool operator>(const RerouteTargetPriority other)
bNodeSocketTypeHandle * typeinfo
bNodeTreeInterfaceItem item
bNodeTreeInterfacePanel root_panel
bNodeTreeRuntimeHandle * runtime
bNodeTreeInterface tree_interface
bNodeTypeHandle * typeinfo
void(* interface_init_socket)(ID *id, const bNodeTreeInterfaceSocket *interface_socket, bNode *node, bNodeSocket *socket, StringRefNull data_path)
std::string ui_description
NodeGetCompositorOperationFunction get_compositor_operation
void(* initfunc)(bNodeTree *ntree, bNode *node)
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeExtraInfoFunction get_extra_info
const char * enum_name_legacy
bool(* insert_link)(NodeInsertLinkParams ¶ms)
NodeDeclareFunction declare
void(* free_self)(bNodeType *ntype)
Array< InputSocketFieldType > inputs
Array< OutputFieldDependency > outputs