Fix: show invalid links when separate group input nodes have different linked menu items

Previously, these invalid links would not show as invalid even though they don't work.

Pull Request: https://projects.blender.org/blender/blender/pulls/118610
This commit is contained in:
Jacques Lucke 2024-02-22 14:40:21 +01:00
parent 7b472b83a3
commit e2d809fa91
3 changed files with 58 additions and 0 deletions

@ -479,6 +479,11 @@ inline const bNode *bNodeTree::group_output_node() const
return this->runtime->group_output_node; return this->runtime->group_output_node;
} }
inline blender::Span<bNode *> bNodeTree::group_input_nodes()
{
return this->nodes_by_type("NodeGroupInput");
}
inline blender::Span<const bNode *> bNodeTree::group_input_nodes() const inline blender::Span<const bNode *> bNodeTree::group_input_nodes() const
{ {
return this->nodes_by_type("NodeGroupInput"); return this->nodes_by_type("NodeGroupInput");

@ -905,6 +905,58 @@ class NodeTreeMainUpdater {
} }
} }
/* Find conflicts between on corresponding menu sockets on different group input nodes. */
const Span<bNode *> 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<bNodeSocketValueMenu>();
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<bNodeSocketValueMenu>();
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<bNodeSocketValueMenu>();
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. */ /* Build list of new enum items for the node tree interface. */
Vector<bNodeSocketValueMenu> interface_enum_items(ntree.interface_inputs().size(), {0}); Vector<bNodeSocketValueMenu> interface_enum_items(ntree.interface_inputs().size(), {0});
for (const bNode *group_input_node : ntree.group_input_nodes()) { for (const bNode *group_input_node : ntree.group_input_nodes()) {

@ -787,6 +787,7 @@ typedef struct bNodeTree {
bNode *group_output_node(); bNode *group_output_node();
const bNode *group_output_node() const; const bNode *group_output_node() const;
/** Get all input nodes of the node group. */ /** Get all input nodes of the node group. */
blender::Span<bNode *> group_input_nodes();
blender::Span<const bNode *> group_input_nodes() const; blender::Span<const bNode *> group_input_nodes() const;
/** Zones in the node tree. Currently there are only simulation zones in geometry nodes. */ /** Zones in the node tree. Currently there are only simulation zones in geometry nodes. */