36 friend InputSocketUsageParams;
73 bool ignore_top_level_node_muting_ =
false;
81 const bool ignore_top_level_node_muting)
82 : compute_context_cache_(compute_context_cache),
83 value_inferencer_(value_inferencer),
85 ignore_top_level_node_muting_(ignore_top_level_node_muting)
87 root_tree_.ensure_topology_cache();
88 root_tree_.ensure_interface_cache();
93 for (
const bNode *node : root_tree_.all_nodes()) {
94 if (node->is_group_input()) {
99 for (
const bNodeSocket *socket : node->output_sockets()) {
100 all_socket_usages_.add_new({
nullptr, socket},
true);
107 for (
const bNode *node : root_tree_.group_input_nodes()) {
108 const bNodeSocket &socket = node->output_socket(input_i);
109 if (!socket.is_directly_linked()) {
122 const std::optional<bool> is_used = all_socket_usages_.lookup_try(socket);
123 if (is_used.has_value()) {
126 if (socket->is_output() && !socket->is_directly_linked()) {
130 if (socket->owner_tree().has_available_link_cycle()) {
135 usage_tasks_.push(socket);
137 while (!usage_tasks_.is_empty()) {
139 this->usage_task(socket);
140 if (&socket == &usage_tasks_.peek()) {
146 return all_socket_usages_.lookup(socket);
151 return value_inferencer_.get_socket_value(socket);
156 const bNode *group_output_node = root_tree_.group_output_node();
157 if (!group_output_node) {
160 const SocketInContext socket{
nullptr, &group_output_node->input_socket(output_i)};
166 const std::optional<bool>
is_disabled = all_socket_disable_states_.lookup_try(socket);
170 if (socket->owner_tree().has_available_link_cycle()) {
173 BLI_assert(disabled_output_tasks_.is_empty());
174 disabled_output_tasks_.push(socket);
176 while (!disabled_output_tasks_.is_empty()) {
178 this->disabled_output_task(socket);
179 if (&socket == &disabled_output_tasks_.peek()) {
181 disabled_output_tasks_.pop();
184 return all_socket_disable_states_.lookup(socket);
190 if (all_socket_usages_.
contains(socket)) {
193 const bNode &node = socket->owner_node();
194 if (!socket->is_available()) {
195 all_socket_usages_.
add_new(socket,
false);
198 if (node.is_undefined() && !node.is_custom_group()) {
199 all_socket_usages_.
add_new(socket,
false);
202 if (socket->is_input()) {
203 this->usage_task__input(socket);
206 this->usage_task__output(socket);
210 void usage_task__input(
const SocketInContext &socket)
212 const NodeInContext node = socket.owner_node();
214 if (node->is_muted()) {
215 const bool is_top_level = socket.context ==
nullptr;
216 if (!this->ignore_top_level_node_muting_ || !is_top_level) {
217 this->usage_task__input__muted_node(socket);
222 switch (node->type_legacy) {
225 this->usage_task__input__group_node(socket);
229 this->usage_task__input__group_output_node(socket);
233 this->usage_task__input__generic_switch(
238 this->usage_task__input__generic_switch(
243 if (socket->index() == 0) {
244 this->usage_task__input__fallback(socket);
247 this->usage_task__input__generic_switch(
253 this->usage_task__input__generic_switch(
258 this->usage_task__input__generic_switch(
263 this->usage_task__input__simulation_input_node(socket);
267 this->usage_task__input__repeat_input_node(socket);
271 this->usage_task__input__foreach_element_input_node(socket);
275 this->usage_task__input__foreach_element_output_node(socket);
279 this->usage_task__input__capture_attribute_node(socket);
289 this->usage_task__input__output_node(socket);
293 if (node->is_type(
"NodeEnableOutput")) {
294 this->usage_task__input__enable_output(socket);
297 this->usage_task__input__fallback(socket);
303 void usage_task__input__output_node(
const SocketInContext &socket)
305 all_socket_usages_.add_new(socket,
true);
312 void usage_task__input__generic_switch(
313 const SocketInContext &socket,
314 const FunctionRef<
bool(
const SocketInContext &socket,
const InferenceValue &condition)>
317 const NodeInContext node = socket.owner_node();
318 BLI_assert(node->input_sockets().size() >= 1);
319 BLI_assert(node->output_sockets().size() >= 1);
321 if (socket->type ==
SOCK_CUSTOM &&
STREQ(socket->idname,
"NodeSocketVirtual")) {
322 all_socket_usages_.add_new(socket,
false);
325 const SocketInContext output_socket{socket.context,
326 get_first_available_bsocket(node->output_sockets())};
327 const std::optional<bool> output_is_used = all_socket_usages_.lookup_try(output_socket);
328 if (!output_is_used.has_value()) {
329 this->push_usage_task(output_socket);
332 if (!*output_is_used) {
333 all_socket_usages_.add_new(socket,
false);
336 const SocketInContext condition_socket{socket.context,
337 get_first_available_bsocket(node->input_sockets())};
338 if (socket == condition_socket) {
339 all_socket_usages_.add_new(socket,
true);
342 const InferenceValue condition_value = this->
get_socket_value(condition_socket);
343 if (condition_value.is_unknown()) {
345 all_socket_usages_.add_new(socket,
true);
348 const bool is_used = is_selected_socket(socket, condition_value);
349 all_socket_usages_.add_new(socket, is_used);
352 void usage_task__input__group_node(
const SocketInContext &socket)
354 const NodeInContext node = socket.owner_node();
357 all_socket_usages_.add_new(socket,
false);
360 group->ensure_topology_cache();
361 if (group->has_available_link_cycle()) {
362 all_socket_usages_.add_new(socket,
false);
368 const ComputeContext &group_context = compute_context_cache_.for_group_node(
369 socket.context, node->identifier, &node->owner_tree());
370 Vector<const bNodeSocket *> dependent_sockets;
371 for (
const bNode *group_input_node : group->group_input_nodes()) {
372 const bNodeSocket &group_input_socket = group_input_node->output_socket(socket->index());
373 if (group_input_socket.is_directly_linked()) {
376 dependent_sockets.
append(&group_input_socket);
379 this->usage_task__with_dependent_sockets(socket, dependent_sockets, {}, &group_context);
382 void usage_task__input__group_output_node(
const SocketInContext &socket)
384 const int output_i = socket->index();
385 if (socket.context ==
nullptr) {
387 all_socket_usages_.add_new(socket,
true);
391 const bke::GroupNodeComputeContext &group_context =
392 *
static_cast<const bke::GroupNodeComputeContext *
>(socket.context);
393 const bNodeSocket &group_node_output = group_context.node()->output_socket(output_i);
394 this->usage_task__with_dependent_sockets(
395 socket, {&group_node_output}, {}, group_context.parent());
398 void usage_task__output(
const SocketInContext &socket)
401 Vector<const bNodeSocket *> dependent_sockets;
402 for (
const bNodeLink *link : socket->directly_linked_links()) {
403 if (link->is_used()) {
404 dependent_sockets.
append(link->tosock);
407 this->usage_task__with_dependent_sockets(socket, dependent_sockets, {}, socket.context);
410 void usage_task__input__simulation_input_node(
const SocketInContext &socket)
412 const NodeInContext node = socket.owner_node();
418 if (!sim_output_node) {
419 all_socket_usages_.add_new(socket,
false);
423 Vector<const bNodeSocket *, 16> dependent_sockets;
424 dependent_sockets.
extend(node->output_sockets());
425 dependent_sockets.
extend(sim_output_node->output_sockets());
426 this->usage_task__with_dependent_sockets(socket, dependent_sockets, {}, socket.context);
429 void usage_task__input__repeat_input_node(
const SocketInContext &socket)
431 const NodeInContext node = socket.owner_node();
437 if (!repeat_output_node) {
438 all_socket_usages_.add_new(socket,
false);
443 Vector<const bNodeSocket *, 16> dependent_sockets;
444 dependent_sockets.
extend(node->output_sockets());
445 dependent_sockets.
extend(repeat_output_node->output_sockets());
446 this->usage_task__with_dependent_sockets(socket, dependent_sockets, {}, socket.context);
449 void usage_task__input__foreach_element_output_node(
const SocketInContext &socket)
451 const NodeInContext node = socket.owner_node();
452 this->usage_task__with_dependent_sockets(
453 socket, {node->output_by_identifier(socket->identifier)}, {}, socket.context);
456 void usage_task__input__capture_attribute_node(
const SocketInContext &socket)
458 const NodeInContext node = socket.owner_node();
459 this->usage_task__with_dependent_sockets(
460 socket, {&node->output_socket(socket->index())}, {}, socket.context);
463 void usage_task__input__enable_output(
const SocketInContext &socket)
465 const NodeInContext node = socket.owner_node();
466 const SocketInContext enable_socket = node.input_socket(0);
467 const SocketInContext output_socket = node.output_socket(0);
468 if (socket == enable_socket) {
469 this->usage_task__with_dependent_sockets(socket, {&*output_socket}, {}, socket.context);
472 this->usage_task__with_dependent_sockets(
473 socket, {&*output_socket}, {&*enable_socket}, socket.context);
477 void usage_task__input__fallback(
const SocketInContext &socket)
479 const SocketDeclaration *socket_decl = socket->runtime->declaration;
481 all_socket_usages_.add_new(socket,
true);
485 this->usage_task__with_dependent_sockets(
486 socket, socket->owner_node().output_sockets(), {}, socket.context);
489 InputSocketUsageParams
params{
490 *
owner_, socket.context, socket->owner_tree(), socket->owner_node(), *socket};
492 if (!is_used.has_value()) {
496 all_socket_usages_.add_new(socket, *is_used);
499 void usage_task__input__foreach_element_input_node(
const SocketInContext &socket)
501 const NodeInContext node = socket.owner_node();
507 if (!foreach_output_node) {
508 all_socket_usages_.add_new(socket,
false);
511 Vector<const bNodeSocket *, 16> dependent_sockets;
512 if (StringRef(socket->identifier).startswith(
"Input_")) {
513 dependent_sockets.
append(node->output_by_identifier(socket->identifier));
517 dependent_sockets.
extend(node->output_sockets());
518 dependent_sockets.
extend(foreach_output_node->output_sockets());
520 this->usage_task__with_dependent_sockets(socket, dependent_sockets, {}, socket.context);
523 void usage_task__input__muted_node(
const SocketInContext &socket)
525 const NodeInContext node = socket.owner_node();
526 Vector<const bNodeSocket *> dependent_sockets;
527 for (
const bNodeLink &internal_link : node->internal_links()) {
528 if (internal_link.fromsock != socket.socket) {
531 dependent_sockets.
append(internal_link.tosock);
533 this->usage_task__with_dependent_sockets(socket, dependent_sockets, {}, socket.context);
540 void usage_task__with_dependent_sockets(
const SocketInContext &socket,
541 const Span<const bNodeSocket *> dependent_outputs,
542 const Span<const bNodeSocket *> condition_inputs,
543 const ComputeContext *dependent_socket_context)
546 SocketInContext next_unknown_socket;
547 bool any_output_used =
false;
548 for (
const bNodeSocket *dependent_socket_ptr : dependent_outputs) {
549 const SocketInContext dependent_socket{dependent_socket_context, dependent_socket_ptr};
550 const std::optional<bool> is_used = all_socket_usages_.lookup_try(dependent_socket);
551 if (!is_used.has_value()) {
552 if (dependent_socket_ptr->is_output() && !dependent_socket_ptr->is_directly_linked()) {
555 if (!next_unknown_socket) {
556 next_unknown_socket = dependent_socket;
560 if (is_used.value_or(
false)) {
561 any_output_used =
true;
565 if (next_unknown_socket) {
569 this->push_usage_task(next_unknown_socket);
572 if (!any_output_used) {
573 all_socket_usages_.add_new(socket,
false);
576 bool all_condition_inputs_true =
true;
577 for (
const bNodeSocket *condition_input_ptr : condition_inputs) {
578 const SocketInContext condition_input{dependent_socket_context, condition_input_ptr};
579 const InferenceValue condition_value = this->
get_socket_value(condition_input);
580 if (!condition_value.is_primitive_value()) {
585 if (!condition_value.get_primitive<
bool>()) {
586 all_condition_inputs_true =
false;
590 all_socket_usages_.add_new(socket, all_condition_inputs_true);
593 void push_usage_task(
const SocketInContext &socket)
595 usage_tasks_.push(socket);
598 void disabled_output_task(
const SocketInContext &socket)
600 if (all_socket_disable_states_.contains(socket)) {
603 const bNode &node = socket->owner_node();
604 if (!socket->is_available()) {
605 all_socket_disable_states_.add_new(socket,
true);
608 if (node.is_undefined() && !node.is_custom_group()) {
609 all_socket_disable_states_.add_new(socket,
true);
612 if (socket->is_input()) {
613 this->disabled_output_task__input(socket);
616 this->disabled_output_task__output(socket);
620 void disabled_output_task__input(
const SocketInContext &socket)
622 const Span<const bNodeLink *> links = socket->directly_linked_links();
623 const bNodeLink *single_link = links.
size() == 1 && links[0]->is_used() ? links[0] :
nullptr;
624 if (links.
size() != 1 || !links[0]->is_used()) {
626 all_socket_disable_states_.add_new(socket,
false);
629 const SocketInContext origin_socket{socket.context, single_link->
fromsock};
630 this->disabled_output_task__with_origin_socket(socket, origin_socket);
633 void disabled_output_task__output(
const SocketInContext &socket)
635 const NodeInContext node = socket.owner_node();
636 if (node->is_muted()) {
637 const bool is_top_level = socket.context ==
nullptr;
638 if (!this->ignore_top_level_node_muting_ || !is_top_level) {
639 this->disabled_output_task__output__muted_node(socket);
644 switch (node->type_legacy) {
647 this->disabled_output_task__output__group_node(socket);
651 this->disabled_output_task__with_origin_socket(socket, node.input_socket(0));
655 if (node->is_type(
"NodeEnableOutput")) {
656 this->disabled_output_task__output__enable_output_node(socket);
661 all_socket_disable_states_.add_new(socket,
false);
667 void disabled_output_task__output__muted_node(
const SocketInContext &socket)
669 const NodeInContext node = socket.owner_node();
670 for (
const bNodeLink &internal_link : node->internal_links()) {
671 if (internal_link.tosock != socket.socket) {
674 this->disabled_output_task__with_origin_socket(socket,
675 {socket.context, internal_link.fromsock});
678 all_socket_disable_states_.add_new(socket,
false);
681 void disabled_output_task__output__group_node(
const SocketInContext &socket)
683 const NodeInContext node = socket.owner_node();
686 all_socket_disable_states_.add_new(socket,
false);
689 group->ensure_topology_cache();
690 if (group->has_available_link_cycle()) {
691 all_socket_disable_states_.add_new(socket,
false);
694 const bNode *group_output_node = group->group_output_node();
695 if (!group_output_node) {
696 all_socket_disable_states_.add_new(socket,
false);
699 const ComputeContext &group_context = compute_context_cache_.for_group_node(
700 socket.context, node->identifier, &node->owner_tree());
701 const SocketInContext origin_socket{&group_context,
702 &group_output_node->input_socket(socket->index())};
703 this->disabled_output_task__with_origin_socket(socket, origin_socket);
706 void disabled_output_task__output__enable_output_node(
const SocketInContext &socket)
708 const NodeInContext node = socket.owner_node();
709 const SocketInContext enable_socket = node.input_socket(0);
711 const std::optional<bool> is_enabled_opt = enable_value.get_if_primitive<
bool>();
712 const bool is_enabled = is_enabled_opt.value_or(
true);
713 all_socket_disable_states_.add_new(socket, !is_enabled);
716 void disabled_output_task__with_origin_socket(
const SocketInContext &socket,
717 const SocketInContext &origin_socket)
719 const std::optional<bool>
is_disabled = all_socket_disable_states_.lookup_try(origin_socket);
721 all_socket_disable_states_.add_new(socket, *
is_disabled);
724 this->push_disabled_output_task(origin_socket);
727 void push_disabled_output_task(
const SocketInContext &socket)
729 disabled_output_tasks_.push(socket);
732 static const bNodeSocket *get_first_available_bsocket(
const Span<const bNodeSocket *> sockets)
735 if (socket->is_available()) {