Fix #145103: incorrect socket usage for built-in menu sockets

The socket usage of built-in menu sockets did not take into account if any of the
outputs of the node were actually used.

Pull Request: https://projects.blender.org/blender/blender/pulls/145162
This commit is contained in:
Jacques Lucke
2025-08-28 14:28:14 +02:00
parent fff8834213
commit 20b2ec5cdf
3 changed files with 40 additions and 0 deletions

View File

@@ -89,6 +89,13 @@ class InputSocketUsageParams {
*/
InferenceValue get_input(StringRef identifier) const;
/**
* Returns true if any output is known to be used or false if no output is used. std::nullopt is
* returned if it's not known yet if any output is used. In this case, the caller should return
* early, it will be checked again once new information about output usages becomes available.
*/
std::optional<bool> any_output_is_used() const;
/**
* Utility for the case when the socket depends on a specific menu input to have a certain value.
*/

View File

@@ -823,6 +823,17 @@ BaseSocketDeclarationBuilder &BaseSocketDeclarationBuilder::usage_by_single_menu
this->usage_inference([menu_value](const socket_usage_inference::InputSocketUsageParams &params)
-> std::optional<bool> {
const bNodeSocket &socket = find_single_menu_input(params.node);
if (const std::optional<bool> any_output_used = params.any_output_is_used()) {
if (!*any_output_used) {
/* If no output is used, none if the inputs is used either. */
return false;
}
}
else {
/* It's not known if any output is used yet. This function will be called again once new
* information about output usages is available. */
return std::nullopt;
}
return params.menu_input_may_be(socket.identifier, menu_value);
});
return *this;

View File

@@ -1553,6 +1553,28 @@ InferenceValue InputSocketUsageParams::get_input(const StringRef identifier) con
return inferencer_.get_socket_value(input_socket);
}
std::optional<bool> InputSocketUsageParams::any_output_is_used() const
{
const bNodeSocket *first_missing = nullptr;
for (const bNodeSocket *output_socket : this->node.output_sockets()) {
if (const std::optional<bool> is_used = inferencer_.all_socket_usages_.lookup_try(
{compute_context_, output_socket}))
{
if (*is_used) {
return true;
}
}
else {
first_missing = output_socket;
}
}
if (first_missing) {
inferencer_.push_usage_task({compute_context_, first_missing});
return std::nullopt;
}
return false;
}
bool InputSocketUsageParams::menu_input_may_be(const StringRef identifier,
const int enum_value) const
{