diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh index 08f4ced5ab1..93f3a346249 100644 --- a/source/blender/blenkernel/BKE_node_runtime.hh +++ b/source/blender/blenkernel/BKE_node_runtime.hh @@ -479,6 +479,11 @@ inline const bNode *bNodeTree::group_output_node() const return this->runtime->group_output_node; } +inline blender::Span bNodeTree::group_input_nodes() +{ + return this->nodes_by_type("NodeGroupInput"); +} + inline blender::Span bNodeTree::group_input_nodes() const { return this->nodes_by_type("NodeGroupInput"); diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc index 9eb8b2b9b59..5bae653b9e9 100644 --- a/source/blender/blenkernel/intern/node_tree_update.cc +++ b/source/blender/blenkernel/intern/node_tree_update.cc @@ -905,6 +905,58 @@ class NodeTreeMainUpdater { } } + /* Find conflicts between on corresponding menu sockets on different group input nodes. */ + const Span group_input_nodes = ntree.group_input_nodes(); + for (const int interface_input_i : ntree.interface_inputs().index_range()) { + const bNodeTreeInterfaceSocket &interface_socket = + *ntree.interface_inputs()[interface_input_i]; + if (interface_socket.socket_type != StringRef("NodeSocketMenu")) { + continue; + } + const RuntimeNodeEnumItems *found_enum_items = nullptr; + bool found_conflict = false; + for (bNode *input_node : group_input_nodes) { + const bNodeSocket &socket = input_node->output_socket(interface_input_i); + const auto &socket_value = *socket.default_value_typed(); + if (socket_value.has_conflict()) { + found_conflict = true; + break; + } + if (found_enum_items == nullptr) { + found_enum_items = socket_value.enum_items; + } + else if (socket_value.enum_items != nullptr) { + if (found_enum_items != socket_value.enum_items) { + found_conflict = true; + break; + } + } + } + if (found_conflict) { + /* Make sure that all group input sockets know that there is a socket. */ + for (bNode *input_node : group_input_nodes) { + bNodeSocket &socket = input_node->output_socket(interface_input_i); + auto &socket_value = *socket.default_value_typed(); + if (socket_value.enum_items) { + socket_value.enum_items->remove_user_and_delete_if_last(); + socket_value.enum_items = nullptr; + } + socket_value.runtime_flag |= NodeSocketValueMenuRuntimeFlag::NODE_MENU_ITEMS_CONFLICT; + } + } + else if (found_enum_items != nullptr) { + /* Make sure all corresponding menu sockets have the same menu reference. */ + for (bNode *input_node : group_input_nodes) { + bNodeSocket &socket = input_node->output_socket(interface_input_i); + auto &socket_value = *socket.default_value_typed(); + if (socket_value.enum_items == nullptr) { + found_enum_items->add_user(); + socket_value.enum_items = found_enum_items; + } + } + } + } + /* Build list of new enum items for the node tree interface. */ Vector interface_enum_items(ntree.interface_inputs().size(), {0}); for (const bNode *group_input_node : ntree.group_input_nodes()) { diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 05852be43f1..a5d9a593653 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -787,6 +787,7 @@ typedef struct bNodeTree { bNode *group_output_node(); const bNode *group_output_node() const; /** Get all input nodes of the node group. */ + blender::Span group_input_nodes(); blender::Span group_input_nodes() const; /** Zones in the node tree. Currently there are only simulation zones in geometry nodes. */