diff options
Diffstat (limited to 'source/blender/nodes/NOD_derived_node_tree.hh')
-rw-r--r-- | source/blender/nodes/NOD_derived_node_tree.hh | 511 |
1 files changed, 511 insertions, 0 deletions
diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh new file mode 100644 index 00000000000..b39c9fd1a23 --- /dev/null +++ b/source/blender/nodes/NOD_derived_node_tree.hh @@ -0,0 +1,511 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __NOD_DERIVED_NODE_TREE_HH__ +#define __NOD_DERIVED_NODE_TREE_HH__ + +/** \file + * \ingroup nodes + * + * DerivedNodeTree provides a flattened view on a bNodeTree, i.e. node groups are inlined. It + * builds on top of NodeTreeRef and supports similar queries efficiently. + * + * Every inlined node remembers its path to the parent ("call stack"). + * + * Unlinked group node inputs are handled separately from other sockets. + * + * There is a dot graph exporter for debugging purposes. + */ + +#include "NOD_node_tree_ref.hh" + +namespace blender::nodes { + +class DSocket; +class DInputSocket; +class DOutputSocket; +class DNode; +class DParentNode; +class DGroupInput; +class DerivedNodeTree; + +class DSocket : NonCopyable, NonMovable { + protected: + DNode *node_; + const SocketRef *socket_ref_; + int id_; + + friend DerivedNodeTree; + + public: + const DNode &node() const; + + int id() const; + int index() const; + + bool is_input() const; + bool is_output() const; + + const DSocket &as_base() const; + const DInputSocket &as_input() const; + const DOutputSocket &as_output() const; + + PointerRNA *rna() const; + StringRefNull idname() const; + StringRefNull name() const; + + const SocketRef &socket_ref() const; + bNodeSocket *bsocket() const; + + bool is_available() const; +}; + +class DInputSocket : public DSocket { + private: + Vector<DOutputSocket *> linked_sockets_; + Vector<DGroupInput *> linked_group_inputs_; + + friend DerivedNodeTree; + + public: + const InputSocketRef &socket_ref() const; + + Span<const DOutputSocket *> linked_sockets() const; + Span<const DGroupInput *> linked_group_inputs() const; + + bool is_linked() const; +}; + +class DOutputSocket : public DSocket { + private: + Vector<DInputSocket *> linked_sockets_; + + friend DerivedNodeTree; + + public: + const OutputSocketRef &socket_ref() const; + Span<const DInputSocket *> linked_sockets() const; +}; + +class DGroupInput : NonCopyable, NonMovable { + private: + const InputSocketRef *socket_ref_; + DParentNode *parent_; + Vector<DInputSocket *> linked_sockets_; + int id_; + + friend DerivedNodeTree; + + public: + const InputSocketRef &socket_ref() const; + bNodeSocket *bsocket() const; + const DParentNode *parent() const; + Span<const DInputSocket *> linked_sockets() const; + int id() const; + StringRefNull name() const; +}; + +class DNode : NonCopyable, NonMovable { + private: + const NodeRef *node_ref_; + DParentNode *parent_; + + Span<DInputSocket *> inputs_; + Span<DOutputSocket *> outputs_; + + int id_; + + friend DerivedNodeTree; + + public: + const NodeRef &node_ref() const; + const DParentNode *parent() const; + + Span<const DInputSocket *> inputs() const; + Span<const DOutputSocket *> outputs() const; + + const DInputSocket &input(int index) const; + const DOutputSocket &output(int index) const; + + const DInputSocket &input(int index, StringRef expected_name) const; + const DOutputSocket &output(int index, StringRef expected_name) const; + + int id() const; + + PointerRNA *rna() const; + StringRefNull idname() const; + StringRefNull name() const; + + private: + void destruct_with_sockets(); +}; + +class DParentNode : NonCopyable, NonMovable { + private: + const NodeRef *node_ref_; + DParentNode *parent_; + int id_; + + friend DerivedNodeTree; + + public: + const DParentNode *parent() const; + const NodeRef &node_ref() const; + int id() const; +}; + +using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>; + +class DerivedNodeTree : NonCopyable, NonMovable { + private: + LinearAllocator<> allocator_; + bNodeTree *btree_; + Vector<DNode *> nodes_by_id_; + Vector<DGroupInput *> group_inputs_; + Vector<DParentNode *> parent_nodes_; + + Vector<DSocket *> sockets_by_id_; + Vector<DInputSocket *> input_sockets_; + Vector<DOutputSocket *> output_sockets_; + + MultiValueMap<const bNodeType *, DNode *> nodes_by_type_; + + public: + DerivedNodeTree(bNodeTree *btree, NodeTreeRefMap &node_tree_refs); + ~DerivedNodeTree(); + + Span<const DNode *> nodes() const; + Span<const DNode *> nodes_by_type(StringRefNull idname) const; + Span<const DNode *> nodes_by_type(const bNodeType *nodetype) const; + + Span<const DSocket *> sockets() const; + Span<const DInputSocket *> input_sockets() const; + Span<const DOutputSocket *> output_sockets() const; + + Span<const DGroupInput *> group_inputs() const; + + std::string to_dot() const; + + private: + /* Utility functions used during construction. */ + void insert_nodes_and_links_in_id_order(const NodeTreeRef &tree_ref, + DParentNode *parent, + Vector<DNode *> &all_nodes); + DNode &create_node(const NodeRef &node_ref, + DParentNode *parent, + MutableSpan<DSocket *> r_sockets_map); + void expand_groups(Vector<DNode *> &all_nodes, + Vector<DGroupInput *> &all_group_inputs, + Vector<DParentNode *> &all_parent_nodes, + NodeTreeRefMap &node_tree_refs); + void expand_group_node(DNode &group_node, + Vector<DNode *> &all_nodes, + Vector<DGroupInput *> &all_group_inputs, + Vector<DParentNode *> &all_parent_nodes, + NodeTreeRefMap &node_tree_refs); + void create_group_inputs_for_unlinked_inputs(DNode &node, + Vector<DGroupInput *> &all_group_inputs); + void relink_group_inputs(const NodeTreeRef &group_ref, + Span<DNode *> nodes_by_id, + DNode &group_node); + void relink_group_outputs(const NodeTreeRef &group_ref, + Span<DNode *> nodes_by_id, + DNode &group_node); + void remove_expanded_group_interfaces(Vector<DNode *> &all_nodes); + void remove_unused_group_inputs(Vector<DGroupInput *> &all_group_inputs); + void store_in_this_and_init_ids(Vector<DNode *> &&all_nodes, + Vector<DGroupInput *> &&all_group_inputs, + Vector<DParentNode *> &&all_parent_nodes); +}; + +/* -------------------------------------------------------------------- + * DSocket inline methods. + */ + +inline const DNode &DSocket::node() const +{ + return *node_; +} + +inline int DSocket::id() const +{ + return id_; +} + +inline int DSocket::index() const +{ + return socket_ref_->index(); +} + +inline bool DSocket::is_input() const +{ + return socket_ref_->is_input(); +} + +inline bool DSocket::is_output() const +{ + return socket_ref_->is_output(); +} + +inline const DSocket &DSocket::as_base() const +{ + return *this; +} + +inline const DInputSocket &DSocket::as_input() const +{ + return *(DInputSocket *)this; +} + +inline const DOutputSocket &DSocket::as_output() const +{ + return *(DOutputSocket *)this; +} + +inline PointerRNA *DSocket::rna() const +{ + return socket_ref_->rna(); +} + +inline StringRefNull DSocket::idname() const +{ + return socket_ref_->idname(); +} + +inline StringRefNull DSocket::name() const +{ + return socket_ref_->name(); +} + +inline const SocketRef &DSocket::socket_ref() const +{ + return *socket_ref_; +} + +inline bNodeSocket *DSocket::bsocket() const +{ + return socket_ref_->bsocket(); +} + +inline bool DSocket::is_available() const +{ + return (socket_ref_->bsocket()->flag & SOCK_UNAVAIL) == 0; +} + +/* -------------------------------------------------------------------- + * DInputSocket inline methods. + */ + +inline const InputSocketRef &DInputSocket::socket_ref() const +{ + return socket_ref_->as_input(); +} + +inline Span<const DOutputSocket *> DInputSocket::linked_sockets() const +{ + return linked_sockets_; +} + +inline Span<const DGroupInput *> DInputSocket::linked_group_inputs() const +{ + return linked_group_inputs_; +} + +inline bool DInputSocket::is_linked() const +{ + return linked_sockets_.size() > 0 || linked_group_inputs_.size() > 0; +} + +/* -------------------------------------------------------------------- + * DOutputSocket inline methods. + */ + +inline const OutputSocketRef &DOutputSocket::socket_ref() const +{ + return socket_ref_->as_output(); +} + +inline Span<const DInputSocket *> DOutputSocket::linked_sockets() const +{ + return linked_sockets_; +} + +/* -------------------------------------------------------------------- + * DGroupInput inline methods. + */ + +inline const InputSocketRef &DGroupInput::socket_ref() const +{ + return *socket_ref_; +} + +inline bNodeSocket *DGroupInput::bsocket() const +{ + return socket_ref_->bsocket(); +} + +inline const DParentNode *DGroupInput::parent() const +{ + return parent_; +} + +inline Span<const DInputSocket *> DGroupInput::linked_sockets() const +{ + return linked_sockets_; +} + +inline int DGroupInput::id() const +{ + return id_; +} + +inline StringRefNull DGroupInput::name() const +{ + return socket_ref_->name(); +} + +/* -------------------------------------------------------------------- + * DNode inline methods. + */ + +inline const NodeRef &DNode::node_ref() const +{ + return *node_ref_; +} + +inline const DParentNode *DNode::parent() const +{ + return parent_; +} + +inline Span<const DInputSocket *> DNode::inputs() const +{ + return inputs_; +} + +inline Span<const DOutputSocket *> DNode::outputs() const +{ + return outputs_; +} + +inline const DInputSocket &DNode::input(int index) const +{ + return *inputs_[index]; +} + +inline const DOutputSocket &DNode::output(int index) const +{ + return *outputs_[index]; +} + +inline const DInputSocket &DNode::input(int index, StringRef expected_name) const +{ + const DInputSocket &socket = *inputs_[index]; + BLI_assert(socket.name() == expected_name); + UNUSED_VARS_NDEBUG(expected_name); + return socket; +} + +inline const DOutputSocket &DNode::output(int index, StringRef expected_name) const +{ + const DOutputSocket &socket = *outputs_[index]; + BLI_assert(socket.name() == expected_name); + UNUSED_VARS_NDEBUG(expected_name); + return socket; +} + +inline int DNode::id() const +{ + return id_; +} + +inline PointerRNA *DNode::rna() const +{ + return node_ref_->rna(); +} + +inline StringRefNull DNode::idname() const +{ + return node_ref_->idname(); +} + +inline StringRefNull DNode::name() const +{ + return node_ref_->name(); +} + +/* -------------------------------------------------------------------- + * DParentNode inline methods. + */ + +inline const DParentNode *DParentNode::parent() const +{ + return parent_; +} + +inline const NodeRef &DParentNode::node_ref() const +{ + return *node_ref_; +} + +inline int DParentNode::id() const +{ + return id_; +} + +/* -------------------------------------------------------------------- + * DerivedNodeTree inline methods. + */ + +inline Span<const DNode *> DerivedNodeTree::nodes() const +{ + return nodes_by_id_; +} + +inline Span<const DNode *> DerivedNodeTree::nodes_by_type(StringRefNull idname) const +{ + const bNodeType *nodetype = nodeTypeFind(idname.c_str()); + return this->nodes_by_type(nodetype); +} + +inline Span<const DNode *> DerivedNodeTree::nodes_by_type(const bNodeType *nodetype) const +{ + return nodes_by_type_.lookup(nodetype); +} + +inline Span<const DSocket *> DerivedNodeTree::sockets() const +{ + return sockets_by_id_; +} + +inline Span<const DInputSocket *> DerivedNodeTree::input_sockets() const +{ + return input_sockets_; +} + +inline Span<const DOutputSocket *> DerivedNodeTree::output_sockets() const +{ + return output_sockets_; +} + +inline Span<const DGroupInput *> DerivedNodeTree::group_inputs() const +{ + return group_inputs_; +} + +} // namespace blender::nodes + +#endif /* __NOD_DERIVED_NODE_TREE_HH__ */ |