64 if (socket->identifier == identifier) {
87 label, (node->
id) ? node->
id->
name + 2 :
IFACE_(
"Missing Data-Block"), label_maxncpy);
137 const char **r_disabled_hint)
168 const char **r_disabled_hint)
173 if (grouptree ==
nullptr) {
177 if (nodetree == grouptree) {
178 if (r_disabled_hint) {
179 *r_disabled_hint =
RPT_(
"Nesting a node group inside of itself is not allowed");
183 if (nodetree->
type != grouptree->
type) {
184 if (r_disabled_hint) {
185 *r_disabled_hint =
RPT_(
"Node group has different type");
190 for (
const bNode *node : grouptree->all_nodes()) {
191 if (node->typeinfo->poll_instance &&
192 !node->typeinfo->poll_instance(node, nodetree, r_disabled_hint))
205 const int item_index = tree_interface.find_item_index(io_socket.
item);
209 return [item_index](
const bNode &node) ->
ID * {
210 if (node.id ==
nullptr) {
213 if (
GS(node.id->name) !=
ID_NT) {
227static std::function<void(
bNode &node,
bNodeSocket &socket,
const char *data_path)>
230 const int item_index =
interface.find_item_index(io_socket.
item);
234 return [item_index](
bNode &node,
bNodeSocket &socket,
const char *data_path) {
235 if (node.
id ==
nullptr) {
258 const std::optional<StructureType> structure_type,
271 datatype = base_typeinfo->
type;
287 .dimensions(value.dimensions)
294 decl = &
b.add_socket<
decl::Color>(name, identifier, in_out).default_value(value.value);
303 decl = &
b.add_socket<
decl::Bool>(name, identifier, in_out).default_value(value.value);
336 .default_value(value.value)
394 if (structure_type) {
395 decl->structure_type(*structure_type);
411 bool layout_added =
false;
412 auto add_layout_if_needed = [&]() {
415 if (is_root && !layout_added) {
416 b.add_default_layout();
429 add_layout_if_needed();
432 group, io_socket, structure_type_by_socket.
lookup_try(&io_socket), in_out,
b);
436 add_layout_if_needed();
438 auto &panel_b =
b.add_panel(
StringRef(io_panel.name), io_panel.identifier)
439 .description(
StringRef(io_panel.description))
442 panel_b, node, group, structure_type_by_socket, io_panel,
false);
448 add_layout_if_needed();
453 const bNode *node =
b.node_or_null();
454 if (node ==
nullptr) {
471 group->ensure_interface_cache();
475 structure_type_by_socket.
reserve(group->interface_items().size());
479 group->
runtime->structure_type_interface->inputs;
480 for (
const int i :
inputs.index_range()) {
481 structure_type_by_socket.
add(
inputs[
i], input_structure_types[
i]);
486 group->
runtime->structure_type_interface->outputs;
487 for (
const int i :
outputs.index_range()) {
488 structure_type_by_socket.
add(
outputs[
i], output_structure_types[
i].type);
496 group->ensure_interface_cache();
499 *group->
runtime->field_inferencing_interface;
500 for (
const int i :
inputs.index_range()) {
505 for (
const int i : r_declaration.
outputs.index_range()) {
506 r_declaration.
outputs[
i]->output_field_dependency = field_interface.
outputs[
i];
526 data->label_size = 20;
538 "Collect related nodes together in a common area. Useful for organization when the "
539 "re-usability of a node group is not required";
559 const bNode *node =
b.node_or_null();
560 if (node ==
nullptr) {
567 .idname(socket_idname.
c_str())
570 .idname(socket_idname.
c_str())
590 "A single-socket organization tool that supports one input and multiple outputs";
601 int node_i = std::numeric_limits<int>::max();
612 if (this->node_i == other.
node_i) {
615 return this->node_i < other.
node_i;
622 ntree->ensure_topology_cache();
624 const Span<bNode *> all_reroute_nodes = ntree->nodes_by_type(
"NodeReroute");
627 for (
const bNode *reroute : all_reroute_nodes) {
628 reroute_nodes.
add(reroute->index());
638 for (
const bNode *src_reroute : all_reroute_nodes) {
639 const int src_reroute_i = reroute_nodes.
index_of(src_reroute->index());
641 src_reroute->output_sockets().first()->directly_linked_sockets())
643 const bNode &dst_node = dst_socket->owner_node();
644 if (!dst_node.is_reroute()) {
647 const int dst_reroute_i = reroute_nodes.
index_of(dst_node.index());
648 reroutes_groups.
join(src_reroute_i, dst_reroute_i);
653 for (
const int reroute_i : reroute_nodes.
index_range()) {
654 const int root_reroute_i = reroutes_groups.find_root(reroute_i);
655 reroute_groups.
add(root_reroute_i);
668 for (
const bNodeLink *link : ntree->all_links()) {
669 const bNode *src_node = link->fromnode;
670 const bNode *dst_node = link->tonode;
672 if (src_node->is_reroute() == dst_node->is_reroute()) {
676 if (!dst_node->is_reroute()) {
677 const int src_reroute_i = reroute_nodes.
index_of(src_node->index());
678 const int src_reroute_root_i = reroutes_groups.find_root(src_reroute_i);
679 const int src_reroute_group_i = reroute_groups.
index_of(src_reroute_root_i);
682 if (reroute_group_dst_type_priority[src_reroute_group_i] > type_priority) {
686 reroute_group_dst_type_priority[src_reroute_group_i] = type_priority;
691 dst_type_by_reroute_group[src_reroute_group_i] = dst_socket->
typeinfo;
696 const int dst_reroute_i = reroute_nodes.
index_of(dst_node->index());
697 const int dst_reroute_root_i = reroutes_groups.find_root(dst_reroute_i);
698 const int dst_reroute_group_i = reroute_groups.
index_of(dst_reroute_root_i);
703 src_type_by_reroute_group[dst_reroute_group_i] = src_socket->
typeinfo;
707 for (
const int reroute_i : reroute_nodes.
index_range()) {
708 const int reroute_root_i = reroutes_groups.find_root(reroute_i);
709 const int reroute_group_i = reroute_groups.
index_of(reroute_root_i);
712 if (dst_type_by_reroute_group[reroute_group_i] !=
nullptr) {
713 reroute_type = dst_type_by_reroute_group[reroute_group_i];
715 if (src_type_by_reroute_group[reroute_group_i] !=
nullptr) {
716 reroute_type = src_type_by_reroute_group[reroute_group_i];
719 if (reroute_type ==
nullptr) {
723 const int reroute_index = reroute_nodes[reroute_i];
724 bNode &reroute_node = *all_nodes[reroute_index];
733 ntree.ensure_topology_cache();
735 for (
const bNodeSocket *socket : node.output_sockets()) {
736 for (
const bNodeLink *link : socket->directly_linked_links()) {
737 nodes_to_check.
push(link->tonode);
740 while (!nodes_to_check.
is_empty()) {
741 const bNode *next_node = nodes_to_check.
pop();
742 for (
const bNodeSocket *socket : next_node->output_sockets()) {
743 for (
const bNodeLink *link : socket->directly_linked_links()) {
749 nodes_to_check.
push(link->tonode);
766 if (sock->identifier == identifier) {
777 const bNodeTree *node_tree =
b.tree_or_null();
778 if (node_tree ==
nullptr) {
807 const bNodeTree *node_tree =
b.tree_or_null();
808 if (node_tree ==
nullptr) {
881 ntype->
ui_name =
"Group Input";
883 "Expose connected data from inside a node group as inputs to its interface";
897 if (sock->identifier == identifier) {
908 if (group_output_nodes.
size() <= 1) {
916 row.
icon = ICON_ERROR;
917 row.
tooltip =
TIP_(
"There are multiple group output nodes and this one is not active");
918 params.rows.append(std::move(row));
928 ntype->
ui_name =
"Group Output";
929 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
NodeTreeInterfaceItemType
@ NODE_INTERFACE_PANEL_DEFAULT_CLOSED
@ NODE_INTERFACE_SOCKET_OUTPUT
@ NODE_INTERFACE_SOCKET_PANEL_TOGGLE
@ NODE_INTERFACE_SOCKET_INPUT
@ 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
#define ID_IS_LINKED(_id)
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))
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 bool group_input_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &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 void group_output_declare(NodeDeclarationBuilder &b)
compositor::NodeOperation * get_group_input_compositor_operation(compositor::Context &context, DNode node)
static bool group_output_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
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_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)
NodeExtraInfoFunction get_extra_info
const char * enum_name_legacy
bool(* insert_link)(bNodeTree *ntree, bNode *node, bNodeLink *link)
NodeDeclareFunction declare
void(* free_self)(bNodeType *ntype)
Array< InputSocketFieldType > inputs
Array< OutputFieldDependency > outputs