Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc111
-rw-r--r--source/blender/nodes/NOD_derived_node_tree.hh15
-rw-r--r--source/blender/nodes/intern/derived_node_tree.cc95
3 files changed, 137 insertions, 84 deletions
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index a312872f5d9..70d2bd9c7f5 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -568,15 +568,15 @@ class GeometryNodesEvaluator {
}
/* Count the number of potential users for this socket. */
socket.foreach_target_socket(
- [&, this](const DInputSocket target_socket) {
+ [&, this](const DInputSocket target_socket,
+ const DOutputSocket::TargetSocketPathInfo &UNUSED(path_info)) {
const DNode target_node = target_socket.node();
if (!this->node_states_.contains_as(target_node)) {
/* The target node is not computed because it is not computed to the output. */
return;
}
output_state.potential_users += 1;
- },
- {});
+ });
if (output_state.potential_users == 0) {
/* If it does not have any potential users, it is unused. It might become required again in
* `schedule_initial_nodes`. */
@@ -1257,43 +1257,61 @@ class GeometryNodesEvaluator {
{
BLI_assert(value_to_forward.get() != nullptr);
- Vector<DSocket> sockets_to_log_to;
- sockets_to_log_to.append(from_socket);
-
- Vector<DInputSocket> to_sockets;
- auto handle_target_socket_fn = [&, this](const DInputSocket to_socket) {
- if (this->should_forward_to_socket(to_socket)) {
- to_sockets.append(to_socket);
- }
- };
- auto handle_skipped_socket_fn = [&](const DSocket socket) {
- sockets_to_log_to.append(socket);
- };
- from_socket.foreach_target_socket(handle_target_socket_fn, handle_skipped_socket_fn);
-
LinearAllocator<> &allocator = local_allocators_.local();
- const CPPType &from_type = *value_to_forward.type();
- Vector<DInputSocket> to_sockets_same_type;
- for (const DInputSocket &to_socket : to_sockets) {
- const CPPType &to_type = *get_socket_cpp_type(to_socket);
- if (from_type == to_type) {
- /* All target sockets that do not need a conversion will be handled afterwards. */
- to_sockets_same_type.append(to_socket);
- /* Multi input socket values are logged once all values are available. */
- if (!to_socket->is_multi_input_socket()) {
- sockets_to_log_to.append(to_socket);
- }
- continue;
- }
- this->forward_to_socket_with_different_type(
- allocator, value_to_forward, from_socket, to_socket, to_type);
- }
-
- this->log_socket_value(sockets_to_log_to, value_to_forward);
+ Vector<DSocket> log_original_value_sockets;
+ Vector<DInputSocket> forward_original_value_sockets;
+ log_original_value_sockets.append(from_socket);
+ from_socket.foreach_target_socket(
+ [&](const DInputSocket to_socket, const DOutputSocket::TargetSocketPathInfo &path_info) {
+ if (!this->should_forward_to_socket(to_socket)) {
+ return;
+ }
+ BLI_assert(to_socket == path_info.sockets.last());
+ GMutablePointer current_value = value_to_forward;
+ for (const DSocket &next_socket : path_info.sockets) {
+ const DNode next_node = next_socket.node();
+ const bool is_last_socket = to_socket == next_socket;
+ const bool do_conversion_if_necessary = is_last_socket ||
+ next_node->is_group_output_node() ||
+ (next_node->is_group_node() &&
+ !next_node->is_muted());
+ if (do_conversion_if_necessary) {
+ const CPPType &next_type = *get_socket_cpp_type(next_socket);
+ if (*current_value.type() != next_type) {
+ void *buffer = allocator.allocate(next_type.size(), next_type.alignment());
+ this->convert_value(*current_value.type(), next_type, current_value.get(), buffer);
+ if (current_value.get() != value_to_forward.get()) {
+ current_value.destruct();
+ }
+ current_value = {next_type, buffer};
+ }
+ }
+ if (current_value.get() == value_to_forward.get()) {
+ /* Log the original value at the current socket. */
+ log_original_value_sockets.append(next_socket);
+ }
+ else {
+ /* Multi-input sockets are logged when all values are available. */
+ if (!(next_socket->is_input() && next_socket->as_input().is_multi_input_socket())) {
+ /* Log the converted value at the socket. */
+ this->log_socket_value({next_socket}, current_value);
+ }
+ }
+ }
+ if (current_value.get() == value_to_forward.get()) {
+ /* The value has not been converted, so forward the original value. */
+ forward_original_value_sockets.append(to_socket);
+ }
+ else {
+ /* The value has been converted. */
+ this->add_value_to_input_socket(to_socket, from_socket, current_value);
+ }
+ });
+ this->log_socket_value(log_original_value_sockets, value_to_forward);
this->forward_to_sockets_with_same_type(
- allocator, to_sockets_same_type, value_to_forward, from_socket);
+ allocator, forward_original_value_sockets, value_to_forward, from_socket);
}
bool should_forward_to_socket(const DInputSocket socket)
@@ -1312,27 +1330,6 @@ class GeometryNodesEvaluator {
return target_input_state.usage != ValueUsage::Unused;
}
- void forward_to_socket_with_different_type(LinearAllocator<> &allocator,
- const GPointer value_to_forward,
- const DOutputSocket from_socket,
- const DInputSocket to_socket,
- const CPPType &to_type)
- {
- const CPPType &from_type = *value_to_forward.type();
-
- /* Allocate a buffer for the converted value. */
- void *buffer = allocator.allocate(to_type.size(), to_type.alignment());
- GMutablePointer value{to_type, buffer};
-
- this->convert_value(from_type, to_type, value_to_forward.get(), buffer);
-
- /* Multi input socket values are logged once all values are available. */
- if (!to_socket->is_multi_input_socket()) {
- this->log_socket_value({to_socket}, value);
- }
- this->add_value_to_input_socket(to_socket, from_socket, value);
- }
-
void forward_to_sockets_with_same_type(LinearAllocator<> &allocator,
Span<DInputSocket> to_sockets,
GMutablePointer value_to_forward,
diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh
index e903e3c9255..895f7ef6d5b 100644
--- a/source/blender/nodes/NOD_derived_node_tree.hh
+++ b/source/blender/nodes/NOD_derived_node_tree.hh
@@ -158,8 +158,19 @@ class DOutputSocket : public DSocket {
DInputSocket get_corresponding_group_node_input() const;
DInputSocket get_active_corresponding_group_output_socket() const;
- void foreach_target_socket(FunctionRef<void(DInputSocket)> target_fn,
- FunctionRef<void(DSocket)> skipped_fn) const;
+ struct TargetSocketPathInfo {
+ /** All sockets on the path from the current to the final target sockets, excluding `this`. */
+ Vector<DSocket, 16> sockets;
+ };
+
+ using ForeachTargetSocketFn =
+ FunctionRef<void(DInputSocket, const TargetSocketPathInfo &path_info)>;
+
+ void foreach_target_socket(ForeachTargetSocketFn target_fn) const;
+
+ private:
+ void foreach_target_socket(ForeachTargetSocketFn target_fn,
+ TargetSocketPathInfo &path_info) const;
};
class DerivedNodeTree {
diff --git a/source/blender/nodes/intern/derived_node_tree.cc b/source/blender/nodes/intern/derived_node_tree.cc
index f7279cf7524..fb12157f147 100644
--- a/source/blender/nodes/intern/derived_node_tree.cc
+++ b/source/blender/nodes/intern/derived_node_tree.cc
@@ -231,45 +231,90 @@ void DInputSocket::foreach_origin_socket(FunctionRef<void(DSocket)> origin_fn) c
/* Calls `target_fn` for every "real" target socket. "Real" means that reroutes, muted nodes
* and node groups are handled by this function. Target sockets are on the nodes that use the value
- * from this socket. The `skipped_fn` function is called for sockets that have been skipped during
- * the search for target sockets (e.g. reroutes). */
-void DOutputSocket::foreach_target_socket(FunctionRef<void(DInputSocket)> target_fn,
- FunctionRef<void(DSocket)> skipped_fn) const
+ * from this socket. */
+void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn) const
{
- for (const SocketRef *skipped_socket : socket_ref_->logically_linked_skipped_sockets()) {
- skipped_fn.call_safe({context_, skipped_socket});
- }
- for (const InputSocketRef *linked_socket : socket_ref_->as_output().logically_linked_sockets()) {
- const NodeRef &linked_node = linked_socket->node();
- DInputSocket linked_dsocket{context_, linked_socket};
+ TargetSocketPathInfo path_info;
+ this->foreach_target_socket(target_fn, path_info);
+}
- if (linked_node.is_group_output_node()) {
+void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn,
+ TargetSocketPathInfo &path_info) const
+{
+ for (const LinkRef *link : socket_ref_->as_output().directly_linked_links()) {
+ if (link->is_muted()) {
+ continue;
+ }
+ const DInputSocket &linked_socket{context_, &link->to()};
+ if (!linked_socket->is_available()) {
+ continue;
+ }
+ const DNode linked_node = linked_socket.node();
+ if (linked_node->is_reroute_node()) {
+ const DInputSocket reroute_input = linked_socket;
+ const DOutputSocket reroute_output = linked_node.output(0);
+ path_info.sockets.append(reroute_input);
+ path_info.sockets.append(reroute_output);
+ reroute_output.foreach_target_socket(target_fn, path_info);
+ path_info.sockets.pop_last();
+ path_info.sockets.pop_last();
+ }
+ else if (linked_node->is_muted()) {
+ for (const InternalLinkRef *internal_link : linked_node->internal_links()) {
+ if (&internal_link->from() != linked_socket.socket_ref()) {
+ continue;
+ }
+ /* The internal link only forwards the first incoming link. */
+ if (linked_socket->is_multi_input_socket()) {
+ if (linked_socket->directly_linked_links()[0] == link) {
+ continue;
+ }
+ }
+ const DInputSocket mute_input = linked_socket;
+ const DOutputSocket mute_output{context_, &internal_link->to()};
+ path_info.sockets.append(mute_input);
+ path_info.sockets.append(mute_output);
+ mute_output.foreach_target_socket(target_fn, path_info);
+ path_info.sockets.pop_last();
+ path_info.sockets.pop_last();
+ break;
+ }
+ }
+ else if (linked_node->is_group_output_node()) {
if (context_->is_root()) {
/* This is a group output in the root node group. */
- target_fn(linked_dsocket);
+ path_info.sockets.append(linked_socket);
+ target_fn(linked_socket, path_info);
+ path_info.sockets.pop_last();
}
else {
/* Follow the links going out of the group node in the parent node group. */
- DOutputSocket socket_in_parent_group =
- linked_dsocket.get_corresponding_group_node_output();
- skipped_fn.call_safe(linked_dsocket);
- skipped_fn.call_safe(socket_in_parent_group);
- socket_in_parent_group.foreach_target_socket(target_fn, skipped_fn);
+ const DOutputSocket socket_in_parent_group =
+ linked_socket.get_corresponding_group_node_output();
+ path_info.sockets.append(linked_socket);
+ path_info.sockets.append(socket_in_parent_group);
+ socket_in_parent_group.foreach_target_socket(target_fn, path_info);
+ path_info.sockets.pop_last();
+ path_info.sockets.pop_last();
}
}
- else if (linked_node.is_group_node()) {
+ else if (linked_node->is_group_node()) {
/* Follow the links within the nested node group. */
- Vector<DOutputSocket> sockets_in_group =
- linked_dsocket.get_corresponding_group_input_sockets();
- skipped_fn.call_safe(linked_dsocket);
- for (DOutputSocket socket_in_group : sockets_in_group) {
- skipped_fn.call_safe(socket_in_group);
- socket_in_group.foreach_target_socket(target_fn, skipped_fn);
+ path_info.sockets.append(linked_socket);
+ const Vector<DOutputSocket> sockets_in_group =
+ linked_socket.get_corresponding_group_input_sockets();
+ for (const DOutputSocket &socket_in_group : sockets_in_group) {
+ path_info.sockets.append(socket_in_group);
+ socket_in_group.foreach_target_socket(target_fn, path_info);
+ path_info.sockets.pop_last();
}
+ path_info.sockets.pop_last();
}
else {
/* The normal case: just use the linked input socket as target. */
- target_fn(linked_dsocket);
+ path_info.sockets.append(linked_socket);
+ target_fn(linked_socket, path_info);
+ path_info.sockets.pop_last();
}
}
}