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.
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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 {
|
||||
r_origins.append(direct_origin);
|
||||
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 {
|
||||
callback(*(InputSocketRef *)target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user