diff options
author | Jacques Lucke <jacques@blender.org> | 2021-03-17 18:43:06 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-03-17 18:43:54 +0300 |
commit | 0ff3f96a1b0193d69dae5ca69e7c93d6cdf34558 (patch) | |
tree | 5086e9545f68db59881e383f5f76ffd3ac058610 /source | |
parent | e9eb08fea16ab033bec52e9b7355f6b52245e152 (diff) |
Nodes: make derived link data more obvious in NodeTreeRef
`NodeTreeRef` is a thin wrapper on top of `bNodeTree`. By default it
should not hide anything from the underlying `bNodeTree` (before this
it was hiding muted links).
For convenience some "derived" data is cached on sockets. For example
all the connected sockets when reroutes and muted links are ignored.
A nice side benefit of this refactor is that `NodeTreeRef` requires
less memory than before.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/nodes/NOD_node_tree_ref.hh | 33 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_tree_ref.cc | 100 |
2 files changed, 100 insertions, 33 deletions
diff --git a/source/blender/nodes/NOD_node_tree_ref.hh b/source/blender/nodes/NOD_node_tree_ref.hh index ec0444852c8..6b8eb21bf9a 100644 --- a/source/blender/nodes/NOD_node_tree_ref.hh +++ b/source/blender/nodes/NOD_node_tree_ref.hh @@ -45,6 +45,7 @@ */ #include "BLI_array.hh" +#include "BLI_function_ref.hh" #include "BLI_linear_allocator.hh" #include "BLI_map.hh" #include "BLI_multi_value_map.hh" @@ -77,9 +78,10 @@ class SocketRef : NonCopyable, NonMovable { int id_; int index_; PointerRNA rna_; - Vector<SocketRef *> linked_sockets_; - Vector<SocketRef *> directly_linked_sockets_; Vector<LinkRef *> directly_linked_links_; + /* This is derived data that is cached for easy and fast access. */ + MutableSpan<SocketRef *> directly_linked_sockets_; + MutableSpan<SocketRef *> linked_sockets_without_reroutes_and_muted_links_; friend NodeTreeRef; @@ -182,6 +184,8 @@ class LinkRef : NonCopyable, NonMovable { const InputSocketRef &to() const; bNodeLink *blink() const; + + bool is_muted() const; }; class InternalLinkRef : NonCopyable, NonMovable { @@ -238,7 +242,12 @@ class NodeTreeRef : NonCopyable, NonMovable { OutputSocketRef &find_output_socket(Map<bNode *, NodeRef *> &node_mapping, bNode *bnode, bNodeSocket *bsocket); - void find_origins_skipping_reroutes(InputSocketRef &socket, Vector<SocketRef *> &r_origins); + + void create_linked_socket_caches(); + void foreach_origin_skipping_reroutes_and_muted_links( + InputSocketRef &socket, FunctionRef<void(OutputSocketRef &)> callback); + void foreach_target_skipping_reroutes_and_muted_links( + OutputSocketRef &socket, FunctionRef<void(InputSocketRef &)> callback); }; using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>; @@ -260,7 +269,7 @@ using nodes::SocketRef; inline Span<const SocketRef *> SocketRef::linked_sockets() const { - return linked_sockets_; + return linked_sockets_without_reroutes_and_muted_links_; } inline Span<const SocketRef *> SocketRef::directly_linked_sockets() const @@ -275,7 +284,7 @@ inline Span<const LinkRef *> SocketRef::directly_linked_links() const inline bool SocketRef::is_linked() const { - return linked_sockets_.size() > 0; + return linked_sockets_without_reroutes_and_muted_links_.size() > 0; } inline const NodeRef &SocketRef::node() const @@ -376,12 +385,13 @@ inline bool SocketRef::is_available() const inline Span<const OutputSocketRef *> InputSocketRef::linked_sockets() const { - return linked_sockets_.as_span().cast<const OutputSocketRef *>(); + return linked_sockets_without_reroutes_and_muted_links_.as_span() + .cast<const OutputSocketRef *>(); } inline Span<const OutputSocketRef *> InputSocketRef::directly_linked_sockets() const { - return directly_linked_sockets_.as_span().cast<const OutputSocketRef *>(); + return directly_linked_sockets_.cast<const OutputSocketRef *>(); } inline bool InputSocketRef::is_multi_input_socket() const @@ -395,12 +405,12 @@ inline bool InputSocketRef::is_multi_input_socket() const inline Span<const InputSocketRef *> OutputSocketRef::linked_sockets() const { - return linked_sockets_.as_span().cast<const InputSocketRef *>(); + return linked_sockets_without_reroutes_and_muted_links_.as_span().cast<const InputSocketRef *>(); } inline Span<const InputSocketRef *> OutputSocketRef::directly_linked_sockets() const { - return directly_linked_sockets_.as_span().cast<const InputSocketRef *>(); + return directly_linked_sockets_.cast<const InputSocketRef *>(); } /* -------------------------------------------------------------------- @@ -516,6 +526,11 @@ inline bNodeLink *LinkRef::blink() const return blink_; } +inline bool LinkRef::is_muted() const +{ + return blink_->flag & NODE_LINK_MUTED; +} + /* -------------------------------------------------------------------- * InternalLinkRef inline methods. */ diff --git a/source/blender/nodes/intern/node_tree_ref.cc b/source/blender/nodes/intern/node_tree_ref.cc index 8d979ffac9c..4b326929dbb 100644 --- a/source/blender/nodes/intern/node_tree_ref.cc +++ b/source/blender/nodes/intern/node_tree_ref.cc @@ -77,9 +77,6 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree) } LISTBASE_FOREACH (bNodeLink *, blink, &btree->links) { - if (blink->flag & NODE_LINK_MUTED) { - continue; - } OutputSocketRef &from_socket = this->find_output_socket( node_mapping, blink->fromnode, blink->fromsock); InputSocketRef &to_socket = this->find_input_socket( @@ -92,7 +89,6 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree) links_.append(&link); - from_socket.directly_linked_sockets_.append(&to_socket); from_socket.directly_linked_links_.append(&link); to_socket.directly_linked_links_.append(&link); } @@ -109,20 +105,7 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree) } } - for (InputSocketRef *input_socket : input_sockets_) { - for (const LinkRef *link : input_socket->directly_linked_links()) { - input_socket->directly_linked_sockets_.append(link->from_); - } - } - - for (InputSocketRef *socket : input_sockets_) { - if (!socket->node_->is_reroute_node()) { - this->find_origins_skipping_reroutes(*socket, socket->linked_sockets_); - for (SocketRef *origin : socket->linked_sockets_) { - origin->linked_sockets_.append(socket); - } - } - } + this->create_linked_socket_caches(); for (NodeRef *node : nodes_by_id_) { const bNodeType *nodetype = node->bnode_->typeinfo; @@ -176,15 +159,84 @@ OutputSocketRef &NodeTreeRef::find_output_socket(Map<bNode *, NodeRef *> &node_m return *node->outputs_[0]; } -void NodeTreeRef::find_origins_skipping_reroutes(InputSocketRef &socket, - Vector<SocketRef *> &r_origins) +void NodeTreeRef::create_linked_socket_caches() { - for (SocketRef *direct_origin : socket.directly_linked_sockets_) { - if (direct_origin->node_->is_reroute_node()) { - this->find_origins_skipping_reroutes(*direct_origin->node_->inputs_[0], r_origins); + for (InputSocketRef *socket : input_sockets_) { + /* Find directly linked socket based on incident links. */ + Vector<SocketRef *> directly_linked_sockets; + for (LinkRef *link : socket->directly_linked_links_) { + directly_linked_sockets.append(link->from_); + } + socket->directly_linked_sockets_ = allocator_.construct_array_copy( + directly_linked_sockets.as_span()); + + /* Find linked sockets when skipping reroutes. */ + Vector<SocketRef *> linked_sockets; + this->foreach_origin_skipping_reroutes_and_muted_links( + *socket, [&](OutputSocketRef &origin) { linked_sockets.append(&origin); }); + if (linked_sockets == directly_linked_sockets) { + socket->linked_sockets_without_reroutes_and_muted_links_ = socket->directly_linked_sockets_; + } + else { + socket->linked_sockets_without_reroutes_and_muted_links_ = allocator_.construct_array_copy( + linked_sockets.as_span()); + } + } + + for (OutputSocketRef *socket : output_sockets_) { + /* Find directly linked socket based on incident links. */ + Vector<SocketRef *> directly_linked_sockets; + for (LinkRef *link : socket->directly_linked_links_) { + directly_linked_sockets.append(link->to_); + } + socket->directly_linked_sockets_ = allocator_.construct_array_copy( + directly_linked_sockets.as_span()); + + /* Find linked sockets when skipping reroutes. */ + Vector<SocketRef *> linked_sockets; + this->foreach_target_skipping_reroutes_and_muted_links( + *socket, [&](InputSocketRef &target) { linked_sockets.append(&target); }); + if (linked_sockets == directly_linked_sockets) { + socket->linked_sockets_without_reroutes_and_muted_links_ = socket->directly_linked_sockets_; + } + else { + socket->linked_sockets_without_reroutes_and_muted_links_ = allocator_.construct_array_copy( + linked_sockets.as_span()); + } + } +} + +void NodeTreeRef::foreach_origin_skipping_reroutes_and_muted_links( + InputSocketRef &socket, FunctionRef<void(OutputSocketRef &)> callback) +{ + for (LinkRef *link : socket.directly_linked_links_) { + if (link->is_muted()) { + continue; + } + OutputSocketRef *origin = link->from_; + if (origin->node_->is_reroute_node()) { + this->foreach_origin_skipping_reroutes_and_muted_links(*origin->node_->inputs_[0], callback); + } + else { + callback(*(OutputSocketRef *)origin); + } + } +} + +void NodeTreeRef::foreach_target_skipping_reroutes_and_muted_links( + OutputSocketRef &socket, FunctionRef<void(InputSocketRef &)> callback) +{ + for (LinkRef *link : socket.directly_linked_links_) { + if (link->is_muted()) { + continue; + } + InputSocketRef *target = link->to_; + if (target->node_->is_reroute_node()) { + this->foreach_target_skipping_reroutes_and_muted_links(*target->node_->outputs_[0], + callback); } else { - r_origins.append(direct_origin); + callback(*(InputSocketRef *)target); } } } |