diff options
Diffstat (limited to 'source/blender/nodes')
46 files changed, 687 insertions, 1686 deletions
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index ae31fd7ff5f..ff8bd27f8d7 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -49,7 +49,6 @@ set(SRC intern/node_multi_function.cc intern/node_socket.cc intern/node_socket_declarations.cc - intern/node_tree_ref.cc intern/node_util.c intern/socket_search_link.cc @@ -63,7 +62,6 @@ set(SRC NOD_math_functions.hh NOD_multi_function.hh NOD_node_declaration.hh - NOD_node_tree_ref.hh NOD_shader.h NOD_socket.h NOD_socket_declarations.hh diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh index b0799d90dcd..b3775e729da 100644 --- a/source/blender/nodes/NOD_derived_node_tree.hh +++ b/source/blender/nodes/NOD_derived_node_tree.hh @@ -5,16 +5,17 @@ /** \file * \ingroup nodes * - * DerivedNodeTree builds on top of NodeTreeRef and makes working with (nested) node groups more - * convenient and safe. It does so by pairing nodes and sockets with a context. The context - * contains information about the current "instance" of the node or socket. A node might be - * "instanced" multiple times when it is in a node group that is used multiple times. + * DerivedNodeTree makes working with (nested) node groups more convenient and safe. It does so by + * pairing nodes and sockets with a context. The context contains information about the current + * "instance" of the node or socket. A node might be "instanced" multiple times when it is in a + * node group that is used multiple times. */ #include "BLI_function_ref.hh" +#include "BLI_linear_allocator.hh" #include "BLI_vector_set.hh" -#include "NOD_node_tree_ref.hh" +#include "BKE_node_runtime.hh" namespace blender::nodes { @@ -40,20 +41,20 @@ class DTreeContext { DTreeContext *parent_context_; /* Null when this context is for the root node group. Otherwise it points to the group node in * the parent node group that contains this context. */ - const NodeRef *parent_node_; + const bNode *parent_node_; /* The current node tree. */ - const NodeTreeRef *tree_; + const bNodeTree *btree_; /* All the children contexts of this context. */ - Map<const NodeRef *, DTreeContext *> children_; + Map<const bNode *, DTreeContext *> children_; DerivedNodeTree *derived_tree_; friend DerivedNodeTree; public: - const NodeTreeRef &tree() const; + const bNodeTree &btree() const; const DTreeContext *parent_context() const; - const NodeRef *parent_node() const; - const DTreeContext *child_context(const NodeRef &node) const; + const bNode *parent_node() const; + const DTreeContext *child_context(const bNode &node) const; const DerivedNodeTree &derived_tree() const; bool is_root() const; }; @@ -65,15 +66,16 @@ class DTreeContext { class DNode { private: const DTreeContext *context_ = nullptr; - const NodeRef *node_ref_ = nullptr; + const bNode *bnode_ = nullptr; public: DNode() = default; - DNode(const DTreeContext *context, const NodeRef *node); + DNode(const DTreeContext *context, const bNode *node); const DTreeContext *context() const; - const NodeRef *node_ref() const; - const NodeRef *operator->() const; + const bNode *bnode() const; + const bNode *operator->() const; + const bNode &operator*() const; friend bool operator==(const DNode &a, const DNode &b); friend bool operator!=(const DNode &a, const DNode &b); @@ -98,17 +100,18 @@ class DNode { class DSocket { protected: const DTreeContext *context_ = nullptr; - const SocketRef *socket_ref_ = nullptr; + const bNodeSocket *bsocket_ = nullptr; public: DSocket() = default; - DSocket(const DTreeContext *context, const SocketRef *socket); + DSocket(const DTreeContext *context, const bNodeSocket *socket); DSocket(const DInputSocket &input_socket); DSocket(const DOutputSocket &output_socket); const DTreeContext *context() const; - const SocketRef *socket_ref() const; - const SocketRef *operator->() const; + const bNodeSocket *bsocket() const; + const bNodeSocket *operator->() const; + const bNodeSocket &operator*() const; friend bool operator==(const DSocket &a, const DSocket &b); friend bool operator!=(const DSocket &a, const DSocket &b); @@ -123,12 +126,9 @@ class DSocket { class DInputSocket : public DSocket { public: DInputSocket() = default; - DInputSocket(const DTreeContext *context, const InputSocketRef *socket); + DInputSocket(const DTreeContext *context, const bNodeSocket *socket); explicit DInputSocket(const DSocket &base_socket); - const InputSocketRef *socket_ref() const; - const InputSocketRef *operator->() const; - DOutputSocket get_corresponding_group_node_output() const; Vector<DOutputSocket, 4> get_corresponding_group_input_sockets() const; @@ -144,12 +144,9 @@ class DInputSocket : public DSocket { class DOutputSocket : public DSocket { public: DOutputSocket() = default; - DOutputSocket(const DTreeContext *context, const OutputSocketRef *socket); + DOutputSocket(const DTreeContext *context, const bNodeSocket *socket); explicit DOutputSocket(const DSocket &base_socket); - const OutputSocketRef *socket_ref() const; - const OutputSocketRef *operator->() const; - DInputSocket get_corresponding_group_node_input() const; DInputSocket get_active_corresponding_group_output_socket() const; @@ -177,7 +174,7 @@ class DerivedNodeTree { private: LinearAllocator<> allocator_; DTreeContext *root_context_; - VectorSet<const NodeTreeRef *> used_node_tree_refs_; + VectorSet<const bNodeTree *> used_btrees_; public: /** @@ -186,11 +183,11 @@ class DerivedNodeTree { * has to make sure that the node tree refs added to #node_tree_refs live at least as long as the * derived node tree. */ - DerivedNodeTree(bNodeTree &btree, NodeTreeRefMap &node_tree_refs); + DerivedNodeTree(const bNodeTree &btree); ~DerivedNodeTree(); const DTreeContext &root_context() const; - Span<const NodeTreeRef *> used_node_tree_refs() const; + Span<const bNodeTree *> used_btrees() const; /** * \return True when there is a link cycle. Unavailable sockets are ignored. @@ -205,9 +202,8 @@ class DerivedNodeTree { private: DTreeContext &construct_context_recursively(DTreeContext *parent_context, - const NodeRef *parent_node, - bNodeTree &btree, - NodeTreeRefMap &node_tree_refs); + const bNode *parent_node, + const bNodeTree &btree); void destruct_context_recursively(DTreeContext *context); void foreach_node_in_context_recursive(const DTreeContext &context, @@ -215,7 +211,6 @@ class DerivedNodeTree { }; namespace derived_node_tree_types { -using namespace node_tree_ref_types; using nodes::DerivedNodeTree; using nodes::DInputSocket; using nodes::DNode; @@ -228,9 +223,9 @@ using nodes::DTreeContext; /** \name #DTreeContext Inline Methods * \{ */ -inline const NodeTreeRef &DTreeContext::tree() const +inline const bNodeTree &DTreeContext::btree() const { - return *tree_; + return *btree_; } inline const DTreeContext *DTreeContext::parent_context() const @@ -238,12 +233,12 @@ inline const DTreeContext *DTreeContext::parent_context() const return parent_context_; } -inline const NodeRef *DTreeContext::parent_node() const +inline const bNode *DTreeContext::parent_node() const { return parent_node_; } -inline const DTreeContext *DTreeContext::child_context(const NodeRef &node) const +inline const DTreeContext *DTreeContext::child_context(const bNode &node) const { return children_.lookup_default(&node, nullptr); } @@ -264,10 +259,10 @@ inline bool DTreeContext::is_root() const /** \name #DNode Inline Methods * \{ */ -inline DNode::DNode(const DTreeContext *context, const NodeRef *node_ref) - : context_(context), node_ref_(node_ref) +inline DNode::DNode(const DTreeContext *context, const bNode *bnode) + : context_(context), bnode_(bnode) { - BLI_assert(node_ref == nullptr || &node_ref->tree() == &context->tree()); + BLI_assert(bnode == nullptr || bnode->runtime->owner_tree == &context->btree()); } inline const DTreeContext *DNode::context() const @@ -275,14 +270,14 @@ inline const DTreeContext *DNode::context() const return context_; } -inline const NodeRef *DNode::node_ref() const +inline const bNode *DNode::bnode() const { - return node_ref_; + return bnode_; } inline bool operator==(const DNode &a, const DNode &b) { - return a.context_ == b.context_ && a.node_ref_ == b.node_ref_; + return a.context_ == b.context_ && a.bnode_ == b.bnode_; } inline bool operator!=(const DNode &a, const DNode &b) @@ -292,37 +287,43 @@ inline bool operator!=(const DNode &a, const DNode &b) inline DNode::operator bool() const { - return node_ref_ != nullptr; + return bnode_ != nullptr; +} + +inline const bNode *DNode::operator->() const +{ + return bnode_; } -inline const NodeRef *DNode::operator->() const +inline const bNode &DNode::operator*() const { - return node_ref_; + BLI_assert(bnode_ != nullptr); + return *bnode_; } inline uint64_t DNode::hash() const { - return get_default_hash_2(context_, node_ref_); + return get_default_hash_2(context_, bnode_); } inline DInputSocket DNode::input(int index) const { - return {context_, &node_ref_->input(index)}; + return {context_, &bnode_->input_socket(index)}; } inline DOutputSocket DNode::output(int index) const { - return {context_, &node_ref_->output(index)}; + return {context_, &bnode_->output_socket(index)}; } inline DInputSocket DNode::input_by_identifier(StringRef identifier) const { - return {context_, &node_ref_->input_by_identifier(identifier)}; + return {context_, &bnode_->input_by_identifier(identifier)}; } inline DOutputSocket DNode::output_by_identifier(StringRef identifier) const { - return {context_, &node_ref_->output_by_identifier(identifier)}; + return {context_, &bnode_->output_by_identifier(identifier)}; } /** \} */ @@ -331,19 +332,20 @@ inline DOutputSocket DNode::output_by_identifier(StringRef identifier) const /** \name #DSocket Inline Methods * \{ */ -inline DSocket::DSocket(const DTreeContext *context, const SocketRef *socket_ref) - : context_(context), socket_ref_(socket_ref) +inline DSocket::DSocket(const DTreeContext *context, const bNodeSocket *bsocket) + : context_(context), bsocket_(bsocket) { - BLI_assert(socket_ref == nullptr || &socket_ref->tree() == &context->tree()); + BLI_assert(bsocket == nullptr || + bsocket->runtime->owner_node->runtime->owner_tree == &context->btree()); } inline DSocket::DSocket(const DInputSocket &input_socket) - : DSocket(input_socket.context_, input_socket.socket_ref_) + : DSocket(input_socket.context_, input_socket.bsocket_) { } inline DSocket::DSocket(const DOutputSocket &output_socket) - : DSocket(output_socket.context_, output_socket.socket_ref_) + : DSocket(output_socket.context_, output_socket.bsocket_) { } @@ -352,14 +354,14 @@ inline const DTreeContext *DSocket::context() const return context_; } -inline const SocketRef *DSocket::socket_ref() const +inline const bNodeSocket *DSocket::bsocket() const { - return socket_ref_; + return bsocket_; } inline bool operator==(const DSocket &a, const DSocket &b) { - return a.context_ == b.context_ && a.socket_ref_ == b.socket_ref_; + return a.context_ == b.context_ && a.bsocket_ == b.bsocket_; } inline bool operator!=(const DSocket &a, const DSocket &b) @@ -369,23 +371,29 @@ inline bool operator!=(const DSocket &a, const DSocket &b) inline DSocket::operator bool() const { - return socket_ref_ != nullptr; + return bsocket_ != nullptr; } -inline const SocketRef *DSocket::operator->() const +inline const bNodeSocket *DSocket::operator->() const { - return socket_ref_; + return bsocket_; +} + +inline const bNodeSocket &DSocket::operator*() const +{ + BLI_assert(bsocket_ != nullptr); + return *bsocket_; } inline uint64_t DSocket::hash() const { - return get_default_hash_2(context_, socket_ref_); + return get_default_hash_2(context_, bsocket_); } inline DNode DSocket::node() const { - BLI_assert(socket_ref_ != nullptr); - return {context_, &socket_ref_->node()}; + BLI_assert(bsocket_ != nullptr); + return {context_, bsocket_->runtime->owner_node}; } /** \} */ @@ -394,8 +402,8 @@ inline DNode DSocket::node() const /** \name #DInputSocket Inline Methods * \{ */ -inline DInputSocket::DInputSocket(const DTreeContext *context, const InputSocketRef *socket_ref) - : DSocket(context, socket_ref) +inline DInputSocket::DInputSocket(const DTreeContext *context, const bNodeSocket *bsocket) + : DSocket(context, bsocket) { } @@ -404,24 +412,14 @@ inline DInputSocket::DInputSocket(const DSocket &base_socket) : DSocket(base_soc BLI_assert(base_socket->is_input()); } -inline const InputSocketRef *DInputSocket::socket_ref() const -{ - return (const InputSocketRef *)socket_ref_; -} - -inline const InputSocketRef *DInputSocket::operator->() const -{ - return (const InputSocketRef *)socket_ref_; -} - /** \} */ /* -------------------------------------------------------------------- */ /** \name #DOutputSocket Inline Methods * \{ */ -inline DOutputSocket::DOutputSocket(const DTreeContext *context, const OutputSocketRef *socket_ref) - : DSocket(context, socket_ref) +inline DOutputSocket::DOutputSocket(const DTreeContext *context, const bNodeSocket *bsocket) + : DSocket(context, bsocket) { } @@ -430,16 +428,6 @@ inline DOutputSocket::DOutputSocket(const DSocket &base_socket) : DSocket(base_s BLI_assert(base_socket->is_output()); } -inline const OutputSocketRef *DOutputSocket::socket_ref() const -{ - return (const OutputSocketRef *)socket_ref_; -} - -inline const OutputSocketRef *DOutputSocket::operator->() const -{ - return (const OutputSocketRef *)socket_ref_; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -451,9 +439,9 @@ inline const DTreeContext &DerivedNodeTree::root_context() const return *root_context_; } -inline Span<const NodeTreeRef *> DerivedNodeTree::used_node_tree_refs() const +inline Span<const bNodeTree *> DerivedNodeTree::used_btrees() const { - return used_node_tree_refs_; + return used_btrees_; } /** \} */ diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index a7f5fbf1926..b5ffd3a317c 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -283,7 +283,7 @@ class GeoNodeExecParams { */ const bNode &node() const { - return *provider_->dnode->bnode(); + return *provider_->dnode; } const Object *self_object() const diff --git a/source/blender/nodes/NOD_multi_function.hh b/source/blender/nodes/NOD_multi_function.hh index b6d51578b1c..21a94d9192b 100644 --- a/source/blender/nodes/NOD_multi_function.hh +++ b/source/blender/nodes/NOD_multi_function.hh @@ -19,15 +19,15 @@ class NodeMultiFunctions; */ class NodeMultiFunctionBuilder : NonCopyable, NonMovable { private: - bNode &node_; - bNodeTree &tree_; + const bNode &node_; + const bNodeTree &tree_; std::shared_ptr<MultiFunction> owned_built_fn_; const MultiFunction *built_fn_ = nullptr; friend NodeMultiFunctions; public: - NodeMultiFunctionBuilder(bNode &node, bNodeTree &tree); + NodeMultiFunctionBuilder(const bNode &node, const bNodeTree &tree); /** * Assign a multi-function for the current node. The input and output parameters of the function @@ -42,8 +42,8 @@ class NodeMultiFunctionBuilder : NonCopyable, NonMovable { */ template<typename T, typename... Args> void construct_and_set_matching_fn(Args &&...args); - bNode &node(); - bNodeTree &tree(); + const bNode &node(); + const bNodeTree &tree(); }; /** @@ -69,17 +69,17 @@ class NodeMultiFunctions { /** \name #NodeMultiFunctionBuilder Inline Methods * \{ */ -inline NodeMultiFunctionBuilder::NodeMultiFunctionBuilder(bNode &node, bNodeTree &tree) +inline NodeMultiFunctionBuilder::NodeMultiFunctionBuilder(const bNode &node, const bNodeTree &tree) : node_(node), tree_(tree) { } -inline bNode &NodeMultiFunctionBuilder::node() +inline const bNode &NodeMultiFunctionBuilder::node() { return node_; } -inline bNodeTree &NodeMultiFunctionBuilder::tree() +inline const bNodeTree &NodeMultiFunctionBuilder::tree() { return tree_; } @@ -110,7 +110,7 @@ inline void NodeMultiFunctionBuilder::construct_and_set_matching_fn(Args &&...ar inline const NodeMultiFunctions::Item &NodeMultiFunctions::try_get(const DNode &node) const { static Item empty_item; - const Item *item = map_.lookup_ptr(node->bnode()); + const Item *item = map_.lookup_ptr(node.bnode()); if (item == nullptr) { return empty_item; } diff --git a/source/blender/nodes/NOD_node_tree_ref.hh b/source/blender/nodes/NOD_node_tree_ref.hh deleted file mode 100644 index 257aa5f4110..00000000000 --- a/source/blender/nodes/NOD_node_tree_ref.hh +++ /dev/null @@ -1,760 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup nodes - * - * NodeTreeRef makes querying information about a bNodeTree more efficient. It is an immutable data - * structure. It should not be used after anymore, after the underlying node tree changed. - * - * The following queries are supported efficiently: - * - socket -> index of socket - * - socket -> directly linked sockets - * - socket -> directly linked links - * - socket -> linked sockets when skipping reroutes - * - socket -> node - * - socket/node -> rna pointer - * - node -> inputs/outputs - * - node -> tree - * - tree -> all nodes - * - tree -> all (input/output) sockets - * - idname -> nodes - * - * Every socket has an id. The id-space is shared between input and output sockets. - * When storing data per socket, it is often better to use the id as index into an array, instead - * of a hash table. - * - * Every node has an id as well. The same rule regarding hash tables applies. - * - * There is an utility to export this data structure as graph in dot format. - */ - -#include "BLI_array.hh" -#include "BLI_function_ref.hh" -#include "BLI_linear_allocator.hh" -#include "BLI_map.hh" -#include "BLI_multi_value_map.hh" -#include "BLI_string_ref.hh" -#include "BLI_timeit.hh" -#include "BLI_utility_mixins.hh" -#include "BLI_vector.hh" - -#include "BKE_node.h" -#include "BKE_node_runtime.hh" - -#include "DNA_node_types.h" - -#include "RNA_access.h" - -namespace blender::nodes { - -class SocketRef; -class InputSocketRef; -class OutputSocketRef; -class NodeRef; -class NodeTreeRef; -class LinkRef; -class InternalLinkRef; - -using SocketIndexByIdentifierMap = Map<std::string, int>; - -class SocketRef : NonCopyable, NonMovable { - protected: - NodeRef *node_; - bNodeSocket *bsocket_; - bool is_input_; - int id_; - int index_; - Vector<LinkRef *> directly_linked_links_; - - /* These sockets are linked directly, i.e. with a single link in between. */ - MutableSpan<const SocketRef *> directly_linked_sockets_; - /* These sockets are linked when reroutes, muted links and muted nodes have been taken into - * account. */ - MutableSpan<const SocketRef *> logically_linked_sockets_; - /* These are the sockets that have been skipped when searching for logically linked sockets. - * That includes for example the input and output socket of an intermediate reroute node. */ - MutableSpan<const SocketRef *> logically_linked_skipped_sockets_; - - friend NodeTreeRef; - - public: - Span<const SocketRef *> logically_linked_sockets() const; - Span<const SocketRef *> logically_linked_skipped_sockets() const; - Span<const SocketRef *> directly_linked_sockets() const; - Span<const LinkRef *> directly_linked_links() const; - - bool is_directly_linked() const; - bool is_logically_linked() const; - - const NodeRef &node() const; - const NodeTreeRef &tree() const; - - int id() const; - int index() const; - - bool is_input() const; - bool is_output() const; - - const SocketRef &as_base() const; - const InputSocketRef &as_input() const; - const OutputSocketRef &as_output() const; - - PointerRNA rna() const; - - StringRefNull idname() const; - StringRefNull name() const; - StringRefNull identifier() const; - bNodeSocketType *typeinfo() const; - - bNodeSocket *bsocket() const; - bNode *bnode() const; - bNodeTree *btree() const; - - bool is_available() const; - bool is_undefined() const; - - void *default_value() const; - template<typename T> T *default_value() const; -}; - -class InputSocketRef final : public SocketRef { - public: - friend NodeTreeRef; - - Span<const OutputSocketRef *> logically_linked_sockets() const; - Span<const OutputSocketRef *> directly_linked_sockets() const; - - bool is_multi_input_socket() const; - - private: - void foreach_logical_origin(FunctionRef<void(const OutputSocketRef &)> origin_fn, - FunctionRef<void(const SocketRef &)> skipped_fn, - bool only_follow_first_input_link, - Vector<const InputSocketRef *> &seen_sockets_stack) const; -}; - -class OutputSocketRef final : public SocketRef { - public: - friend NodeTreeRef; - - Span<const InputSocketRef *> logically_linked_sockets() const; - Span<const InputSocketRef *> directly_linked_sockets() const; - - private: - void foreach_logical_target(FunctionRef<void(const InputSocketRef &)> target_fn, - FunctionRef<void(const SocketRef &)> skipped_fn, - Vector<const OutputSocketRef *> &seen_sockets_stack) const; -}; - -class NodeRef : NonCopyable, NonMovable { - private: - NodeTreeRef *tree_; - bNode *bnode_; - int id_; - Vector<InputSocketRef *> inputs_; - Vector<OutputSocketRef *> outputs_; - Vector<InternalLinkRef *> internal_links_; - SocketIndexByIdentifierMap *input_index_by_identifier_; - SocketIndexByIdentifierMap *output_index_by_identifier_; - - friend NodeTreeRef; - - public: - const NodeTreeRef &tree() const; - - Span<const InputSocketRef *> inputs() const; - Span<const OutputSocketRef *> outputs() const; - Span<const InternalLinkRef *> internal_links() const; - Span<const SocketRef *> sockets(eNodeSocketInOut in_out) const; - - const InputSocketRef &input(int index) const; - const OutputSocketRef &output(int index) const; - - const InputSocketRef &input_by_identifier(StringRef identifier) const; - const OutputSocketRef &output_by_identifier(StringRef identifier) const; - - bool any_input_is_directly_linked() const; - bool any_output_is_directly_linked() const; - bool any_socket_is_directly_linked(eNodeSocketInOut in_out) const; - - bNode *bnode() const; - bNodeTree *btree() const; - - PointerRNA rna() const; - StringRefNull idname() const; - StringRefNull name() const; - StringRefNull label() const; - StringRefNull label_or_name() const; - bNodeType *typeinfo() const; - const NodeDeclaration *declaration() const; - - int id() const; - - bool is_reroute_node() const; - bool is_group_node() const; - bool is_group_input_node() const; - bool is_group_output_node() const; - bool is_muted() const; - bool is_frame() const; - bool is_undefined() const; - - void *storage() const; - template<typename T> T *storage() const; -}; - -class LinkRef : NonCopyable, NonMovable { - private: - OutputSocketRef *from_; - InputSocketRef *to_; - bNodeLink *blink_; - - friend NodeTreeRef; - - public: - const OutputSocketRef &from() const; - const InputSocketRef &to() const; - - bNodeLink *blink() const; - - bool is_muted() const; -}; - -class InternalLinkRef : NonCopyable, NonMovable { - private: - InputSocketRef *from_; - OutputSocketRef *to_; - bNodeLink *blink_; - - friend NodeTreeRef; - - public: - const InputSocketRef &from() const; - const OutputSocketRef &to() const; - - bNodeLink *blink() const; -}; - -class NodeTreeRef : NonCopyable, NonMovable { - private: - LinearAllocator<> allocator_; - bNodeTree *btree_; - Vector<NodeRef *> nodes_by_id_; - Vector<SocketRef *> sockets_by_id_; - Vector<InputSocketRef *> input_sockets_; - Vector<OutputSocketRef *> output_sockets_; - Vector<LinkRef *> links_; - MultiValueMap<const bNodeType *, NodeRef *> nodes_by_type_; - Vector<std::unique_ptr<SocketIndexByIdentifierMap>> owned_identifier_maps_; - const NodeRef *group_output_node_ = nullptr; - - public: - NodeTreeRef(bNodeTree *btree); - ~NodeTreeRef(); - - Span<const NodeRef *> nodes() const; - Span<const NodeRef *> nodes_by_type(StringRefNull idname) const; - Span<const NodeRef *> nodes_by_type(const bNodeType *nodetype) const; - - Span<const SocketRef *> sockets() const; - Span<const InputSocketRef *> input_sockets() const; - Span<const OutputSocketRef *> output_sockets() const; - - Span<const LinkRef *> links() const; - - const NodeRef *find_node(const bNode &bnode) const; - - /** - * This is the active group output node if there are multiple. - */ - const NodeRef *group_output_node() const; - - /** - * \return True when there is a link cycle. Unavailable sockets are ignored. - */ - bool has_link_cycles() const; - bool has_undefined_nodes_or_sockets() const; - - enum class ToposortDirection { - LeftToRight, - RightToLeft, - }; - - struct ToposortResult { - Vector<const NodeRef *> sorted_nodes; - /** - * There can't be a correct topological sort of the nodes when there is a cycle. The nodes will - * still be sorted to some degree. The caller has to decide whether it can handle non-perfect - * sorts or not. - */ - bool has_cycle = false; - }; - - /** - * Sort nodes topologically from left to right or right to left. - * In the future the result if this could be cached on #NodeTreeRef. - */ - ToposortResult toposort(ToposortDirection direction) const; - - bNodeTree *btree() const; - StringRefNull name() const; - - std::string to_dot() const; - - private: - /* Utility functions used during construction. */ - InputSocketRef &find_input_socket(Map<bNode *, NodeRef *> &node_mapping, - bNode *bnode, - bNodeSocket *bsocket); - OutputSocketRef &find_output_socket(Map<bNode *, NodeRef *> &node_mapping, - bNode *bnode, - bNodeSocket *bsocket); - - void create_linked_socket_caches(); - void create_socket_identifier_maps(); -}; - -using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>; - -const NodeTreeRef &get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree); - -namespace node_tree_ref_types { -using nodes::InputSocketRef; -using nodes::NodeRef; -using nodes::NodeTreeRef; -using nodes::NodeTreeRefMap; -using nodes::OutputSocketRef; -using nodes::SocketRef; -} // namespace node_tree_ref_types - -/* -------------------------------------------------------------------- */ -/** \name #SocketRef Inline Methods - * \{ */ - -inline Span<const SocketRef *> SocketRef::logically_linked_sockets() const -{ - return logically_linked_sockets_; -} - -inline Span<const SocketRef *> SocketRef::logically_linked_skipped_sockets() const -{ - return logically_linked_skipped_sockets_; -} - -inline Span<const SocketRef *> SocketRef::directly_linked_sockets() const -{ - return directly_linked_sockets_; -} - -inline Span<const LinkRef *> SocketRef::directly_linked_links() const -{ - return directly_linked_links_; -} - -inline bool SocketRef::is_directly_linked() const -{ - return directly_linked_sockets_.size() > 0; -} - -inline bool SocketRef::is_logically_linked() const -{ - return logically_linked_sockets_.size() > 0; -} - -inline const NodeRef &SocketRef::node() const -{ - return *node_; -} - -inline const NodeTreeRef &SocketRef::tree() const -{ - return node_->tree(); -} - -inline int SocketRef::id() const -{ - return id_; -} - -inline int SocketRef::index() const -{ - return index_; -} - -inline bool SocketRef::is_input() const -{ - return is_input_; -} - -inline bool SocketRef::is_output() const -{ - return !is_input_; -} - -inline const SocketRef &SocketRef::as_base() const -{ - return *this; -} - -inline const InputSocketRef &SocketRef::as_input() const -{ - BLI_assert(this->is_input()); - return static_cast<const InputSocketRef &>(*this); -} - -inline const OutputSocketRef &SocketRef::as_output() const -{ - BLI_assert(this->is_output()); - return static_cast<const OutputSocketRef &>(*this); -} - -inline StringRefNull SocketRef::idname() const -{ - return bsocket_->idname; -} - -inline StringRefNull SocketRef::name() const -{ - return bsocket_->name; -} - -inline StringRefNull SocketRef::identifier() const -{ - return bsocket_->identifier; -} - -inline bNodeSocketType *SocketRef::typeinfo() const -{ - return bsocket_->typeinfo; -} - -inline bNodeSocket *SocketRef::bsocket() const -{ - return bsocket_; -} - -inline bNode *SocketRef::bnode() const -{ - return node_->bnode(); -} - -inline bNodeTree *SocketRef::btree() const -{ - return node_->btree(); -} - -inline bool SocketRef::is_available() const -{ - return (bsocket_->flag & SOCK_UNAVAIL) == 0; -} - -inline bool SocketRef::is_undefined() const -{ - return bsocket_->typeinfo == &NodeSocketTypeUndefined; -} - -inline void *SocketRef::default_value() const -{ - return bsocket_->default_value; -} - -template<typename T> inline T *SocketRef::default_value() const -{ - return (T *)bsocket_->default_value; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #InputSocketRef Inline Methods - * \{ */ - -inline Span<const OutputSocketRef *> InputSocketRef::logically_linked_sockets() const -{ - return logically_linked_sockets_.as_span().cast<const OutputSocketRef *>(); -} - -inline Span<const OutputSocketRef *> InputSocketRef::directly_linked_sockets() const -{ - return directly_linked_sockets_.cast<const OutputSocketRef *>(); -} - -inline bool InputSocketRef::is_multi_input_socket() const -{ - return bsocket_->flag & SOCK_MULTI_INPUT; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #OutputSocketRef Inline Methods - * \{ */ - -inline Span<const InputSocketRef *> OutputSocketRef::logically_linked_sockets() const -{ - return logically_linked_sockets_.as_span().cast<const InputSocketRef *>(); -} - -inline Span<const InputSocketRef *> OutputSocketRef::directly_linked_sockets() const -{ - return directly_linked_sockets_.cast<const InputSocketRef *>(); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #NodeRef Inline Methods - * \{ */ - -inline const NodeTreeRef &NodeRef::tree() const -{ - return *tree_; -} - -inline Span<const InputSocketRef *> NodeRef::inputs() const -{ - return inputs_; -} - -inline Span<const OutputSocketRef *> NodeRef::outputs() const -{ - return outputs_; -} - -inline Span<const SocketRef *> NodeRef::sockets(const eNodeSocketInOut in_out) const -{ - return in_out == SOCK_IN ? inputs_.as_span().cast<const SocketRef *>() : - outputs_.as_span().cast<const SocketRef *>(); -} - -inline Span<const InternalLinkRef *> NodeRef::internal_links() const -{ - return internal_links_; -} - -inline const InputSocketRef &NodeRef::input(int index) const -{ - return *inputs_[index]; -} - -inline const OutputSocketRef &NodeRef::output(int index) const -{ - return *outputs_[index]; -} - -inline const InputSocketRef &NodeRef::input_by_identifier(StringRef identifier) const -{ - const int index = input_index_by_identifier_->lookup_as(identifier); - return this->input(index); -} - -inline const OutputSocketRef &NodeRef::output_by_identifier(StringRef identifier) const -{ - const int index = output_index_by_identifier_->lookup_as(identifier); - return this->output(index); -} - -inline bNode *NodeRef::bnode() const -{ - return bnode_; -} - -inline bNodeTree *NodeRef::btree() const -{ - return tree_->btree(); -} - -inline StringRefNull NodeRef::idname() const -{ - return bnode_->idname; -} - -inline StringRefNull NodeRef::name() const -{ - return bnode_->name; -} - -inline StringRefNull NodeRef::label() const -{ - return bnode_->label; -} - -inline StringRefNull NodeRef::label_or_name() const -{ - const StringRefNull label = this->label(); - if (!label.is_empty()) { - return label; - } - return this->name(); -} - -inline bNodeType *NodeRef::typeinfo() const -{ - return bnode_->typeinfo; -} - -/* Returns a pointer because not all nodes have declarations currently. */ -inline const NodeDeclaration *NodeRef::declaration() const -{ - nodeDeclarationEnsure(this->tree().btree(), bnode_); - return bnode_->runtime->declaration; -} - -inline int NodeRef::id() const -{ - return id_; -} - -inline bool NodeRef::is_reroute_node() const -{ - return bnode_->type == NODE_REROUTE; -} - -inline bool NodeRef::is_group_node() const -{ - return bnode_->type == NODE_GROUP || bnode_->type == NODE_CUSTOM_GROUP; -} - -inline bool NodeRef::is_group_input_node() const -{ - return bnode_->type == NODE_GROUP_INPUT; -} - -inline bool NodeRef::is_group_output_node() const -{ - return bnode_->type == NODE_GROUP_OUTPUT; -} - -inline bool NodeRef::is_frame() const -{ - return bnode_->type == NODE_FRAME; -} - -inline bool NodeRef::is_undefined() const -{ - return bnode_->typeinfo == &NodeTypeUndefined; -} - -inline bool NodeRef::is_muted() const -{ - return (bnode_->flag & NODE_MUTED) != 0; -} - -inline void *NodeRef::storage() const -{ - return bnode_->storage; -} - -template<typename T> inline T *NodeRef::storage() const -{ - return (T *)bnode_->storage; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #LinkRef Inline Methods - * \{ */ - -inline const OutputSocketRef &LinkRef::from() const -{ - return *from_; -} - -inline const InputSocketRef &LinkRef::to() const -{ - return *to_; -} - -inline bNodeLink *LinkRef::blink() const -{ - return blink_; -} - -inline bool LinkRef::is_muted() const -{ - return blink_->flag & NODE_LINK_MUTED; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #InternalLinkRef Inline Methods - * \{ */ - -inline const InputSocketRef &InternalLinkRef::from() const -{ - return *from_; -} - -inline const OutputSocketRef &InternalLinkRef::to() const -{ - return *to_; -} - -inline bNodeLink *InternalLinkRef::blink() const -{ - return blink_; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #NodeTreeRef Inline Methods - * \{ */ - -inline Span<const NodeRef *> NodeTreeRef::nodes() const -{ - return nodes_by_id_; -} - -inline Span<const NodeRef *> NodeTreeRef::nodes_by_type(StringRefNull idname) const -{ - const bNodeType *nodetype = nodeTypeFind(idname.c_str()); - return this->nodes_by_type(nodetype); -} - -inline Span<const NodeRef *> NodeTreeRef::nodes_by_type(const bNodeType *nodetype) const -{ - return nodes_by_type_.lookup(nodetype); -} - -inline Span<const SocketRef *> NodeTreeRef::sockets() const -{ - return sockets_by_id_; -} - -inline Span<const InputSocketRef *> NodeTreeRef::input_sockets() const -{ - return input_sockets_; -} - -inline Span<const OutputSocketRef *> NodeTreeRef::output_sockets() const -{ - return output_sockets_; -} - -inline Span<const LinkRef *> NodeTreeRef::links() const -{ - return links_; -} - -inline const NodeRef *NodeTreeRef::group_output_node() const -{ - return group_output_node_; -} - -inline bNodeTree *NodeTreeRef::btree() const -{ - return btree_; -} - -inline StringRefNull NodeTreeRef::name() const -{ - return btree_->id.name + 2; -} - -/** \} */ - -} // namespace blender::nodes diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 1d1310360b8..8fe77bffaad 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -26,6 +26,7 @@ void register_node_type_sh_camera(void); void register_node_type_sh_value(void); void register_node_type_sh_rgb(void); void register_node_type_sh_mix_rgb(void); +void register_node_type_sh_mix(void); void register_node_type_sh_valtorgb(void); void register_node_type_sh_rgbtobw(void); void register_node_type_sh_shadertorgb(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 786ce88152e..e6cdd462c66 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -25,7 +25,7 @@ DefNode(Node, NODE_REROUTE, 0, "REROUT DefNode(ShaderNode, SH_NODE_RGB, 0, "RGB", RGB, "RGB", "A color picker") DefNode(ShaderNode, SH_NODE_VALUE, 0, "VALUE", Value, "Value", "Used to Input numerical values to other nodes in the tree") -DefNode(ShaderNode, SH_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "MixRGB", "Mix two input colors") +DefNode(ShaderNode, SH_NODE_MIX_RGB_LEGACY, def_mix_rgb, "MIX_RGB", MixRGB, "MixRGB", "Mix two input colors") DefNode(ShaderNode, SH_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "Map values to colors with the use of a gradient") DefNode(ShaderNode, SH_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "Convert a color's luminance to a grayscale value") DefNode(ShaderNode, SH_NODE_SHADERTORGB, 0, "SHADERTORGB", ShaderToRGB, "Shader to RGB", "Convert rendering effect (such as light and shadow) to color. Typically used for non-photorealistic rendering, to apply additional effects on the output of BSDFs.\nNote: only supported for Eevee") @@ -122,6 +122,7 @@ DefNode(ShaderNode, SH_NODE_OUTPUT_AOV, def_sh_output_aov, "OUT DefNode(ShaderNode, SH_NODE_CURVE_FLOAT, def_float_curve, "CURVE_FLOAT", FloatCurve, "Float Curve", "Map an input float to a curve and outputs a float value") DefNode(ShaderNode, SH_NODE_COMBINE_COLOR, def_sh_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "Create a color from individual components using multiple models") DefNode(ShaderNode, SH_NODE_SEPARATE_COLOR, def_sh_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "Split a color into its individual components using multiple models") +DefNode(ShaderNode, SH_NODE_MIX, def_sh_mix, "MIX", Mix, "Mix", "Mix values by a factor") DefNode(CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) DefNode(CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_image.cc b/source/blender/nodes/composite/nodes/node_composite_image.cc index d8852e9333f..b6bd263b150 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.cc +++ b/source/blender/nodes/composite/nodes/node_composite_image.cc @@ -457,8 +457,8 @@ class ImageOperation : public NodeOperation { update_image_frame_number(); - for (const OutputSocketRef *output : node()->outputs()) { - compute_output(output->identifier()); + for (const bNodeSocket *output : this->node()->output_sockets()) { + compute_output(output->identifier); } } @@ -488,12 +488,12 @@ class ImageOperation : public NodeOperation { /* Allocate all needed outputs as invalid. This should be called when is_valid returns false. */ void allocate_invalid() { - for (const OutputSocketRef *output : node()->outputs()) { - if (!should_compute_output(output->identifier())) { + for (const bNodeSocket *output : this->node()->output_sockets()) { + if (!should_compute_output(output->identifier)) { continue; } - Result &result = get_result(output->identifier()); + Result &result = get_result(output->identifier); result.allocate_invalid(); } } @@ -594,7 +594,7 @@ class ImageOperation : public NodeOperation { const char *get_pass_name(StringRef identifier) { DOutputSocket output = node().output_by_identifier(identifier); - return static_cast<NodeImageLayer *>(output->bsocket()->storage)->pass_name; + return static_cast<NodeImageLayer *>(output->storage)->pass_name; } /* Get the index of the pass with the given name in the selected render layer's passes list @@ -850,9 +850,9 @@ class RenderLayerOperation : public NodeOperation { alpha_result.unbind_as_image(); /* Other output passes are not supported for now, so allocate them as invalid. */ - for (const OutputSocketRef *output : node()->outputs()) { - if (output->identifier() != "Image" && output->identifier() != "Alpha") { - get_result(output->identifier()).allocate_invalid(); + for (const bNodeSocket *output : this->node()->output_sockets()) { + if (!STREQ(output->identifier, "Image") && !STREQ(output->identifier, "Alpha")) { + get_result(output->identifier).allocate_invalid(); } } } diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.cc b/source/blender/nodes/composite/nodes/node_composite_normal.cc index f61ace01cfd..a1a6303e21b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normal.cc +++ b/source/blender/nodes/composite/nodes/node_composite_normal.cc @@ -51,9 +51,12 @@ class NormalShaderNode : public ShaderNode { } /* The vector value is stored in the default value of the output socket. */ - float *get_vector_value() + const float *get_vector_value() { - return node().output_by_identifier("Normal")->default_value<bNodeSocketValueVector>()->value; + return node() + .output_by_identifier("Normal") + ->default_value_typed<bNodeSocketValueVector>() + ->value; } }; diff --git a/source/blender/nodes/function/node_function_util.hh b/source/blender/nodes/function/node_function_util.hh index fd0b6c31b1d..059b2f9bc17 100644 --- a/source/blender/nodes/function/node_function_util.hh +++ b/source/blender/nodes/function/node_function_util.hh @@ -23,4 +23,6 @@ #include "FN_multi_function_builder.hh" +#include "RNA_access.h" + void fn_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass); diff --git a/source/blender/nodes/function/nodes/node_fn_align_euler_to_vector.cc b/source/blender/nodes/function/nodes/node_fn_align_euler_to_vector.cc index 7d08d57c503..e5c89567d44 100644 --- a/source/blender/nodes/function/nodes/node_fn_align_euler_to_vector.cc +++ b/source/blender/nodes/function/nodes/node_fn_align_euler_to_vector.cc @@ -190,7 +190,7 @@ class MF_AlignEulerToVector : public fn::MultiFunction { static void fn_node_align_euler_to_vector_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); + const bNode &node = builder.node(); builder.construct_and_set_matching_fn<MF_AlignEulerToVector>(node.custom1, node.custom2); } diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc index b6d7e6c9a5f..5fc28509a49 100644 --- a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc +++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc @@ -68,7 +68,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) } } -static const fn::MultiFunction *get_multi_function(bNode &bnode) +static const fn::MultiFunction *get_multi_function(const bNode &bnode) { static auto exec_preset = fn::CustomMF_presets::AllSpanOrSingle(); static fn::CustomMF_SI_SI_SO<bool, bool, bool> and_fn{ diff --git a/source/blender/nodes/function/nodes/node_fn_combine_color.cc b/source/blender/nodes/function/nodes/node_fn_combine_color.cc index c5fd3ce38a1..450cd166e78 100644 --- a/source/blender/nodes/function/nodes/node_fn_combine_color.cc +++ b/source/blender/nodes/function/nodes/node_fn_combine_color.cc @@ -49,7 +49,7 @@ static void fn_node_combine_color_init(bNodeTree *UNUSED(tree), bNode *node) node->storage = data; } -static const fn::MultiFunction *get_multi_function(bNode &bnode) +static const fn::MultiFunction *get_multi_function(const bNode &bnode) { const NodeCombSepColor &storage = node_storage(bnode); diff --git a/source/blender/nodes/function/nodes/node_fn_compare.cc b/source/blender/nodes/function/nodes/node_fn_compare.cc index e3f13dc7d6b..122d1a3c93e 100644 --- a/source/blender/nodes/function/nodes/node_fn_compare.cc +++ b/source/blender/nodes/function/nodes/node_fn_compare.cc @@ -167,7 +167,7 @@ static float component_average(float3 a) return (a.x + a.y + a.z) / 3.0f; } -static const fn::MultiFunction *get_multi_function(bNode &node) +static const fn::MultiFunction *get_multi_function(const bNode &node) { const NodeFunctionCompare *data = (NodeFunctionCompare *)node.storage; diff --git a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc index 9c9d8620a7e..aad2f532d20 100644 --- a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc +++ b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc @@ -39,7 +39,7 @@ static void node_float_to_int_label(const bNodeTree *UNUSED(ntree), BLI_strncpy(label, IFACE_(name), maxlen); } -static const fn::MultiFunction *get_multi_function(bNode &bnode) +static const fn::MultiFunction *get_multi_function(const bNode &bnode) { static auto exec_preset = fn::CustomMF_presets::AllSpanOrSingle(); static fn::CustomMF_SI_SO<float, int> round_fn{ diff --git a/source/blender/nodes/function/nodes/node_fn_input_bool.cc b/source/blender/nodes/function/nodes/node_fn_input_bool.cc index 5ced719627f..717f4d1ac6b 100644 --- a/source/blender/nodes/function/nodes/node_fn_input_bool.cc +++ b/source/blender/nodes/function/nodes/node_fn_input_bool.cc @@ -22,7 +22,7 @@ static void fn_node_input_bool_layout(uiLayout *layout, bContext *UNUSED(C), Poi static void fn_node_input_bool_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); + const bNode &bnode = builder.node(); NodeInputBool *node_storage = static_cast<NodeInputBool *>(bnode.storage); builder.construct_and_set_matching_fn<fn::CustomMF_Constant<bool>>(node_storage->boolean); } diff --git a/source/blender/nodes/function/nodes/node_fn_input_color.cc b/source/blender/nodes/function/nodes/node_fn_input_color.cc index 46787f7575d..cdad1542c66 100644 --- a/source/blender/nodes/function/nodes/node_fn_input_color.cc +++ b/source/blender/nodes/function/nodes/node_fn_input_color.cc @@ -23,7 +23,7 @@ static void fn_node_input_color_layout(uiLayout *layout, bContext *UNUSED(C), Po static void fn_node_input_color_build_multi_function( blender::nodes::NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); + const bNode &bnode = builder.node(); NodeInputColor *node_storage = static_cast<NodeInputColor *>(bnode.storage); blender::ColorGeometry4f color = (ColorGeometry4f)node_storage->color; builder.construct_and_set_matching_fn<blender::fn::CustomMF_Constant<ColorGeometry4f>>(color); diff --git a/source/blender/nodes/function/nodes/node_fn_input_int.cc b/source/blender/nodes/function/nodes/node_fn_input_int.cc index 1e5dcd5ae7a..16506b5f9b8 100644 --- a/source/blender/nodes/function/nodes/node_fn_input_int.cc +++ b/source/blender/nodes/function/nodes/node_fn_input_int.cc @@ -22,7 +22,7 @@ static void fn_node_input_int_layout(uiLayout *layout, bContext *UNUSED(C), Poin static void fn_node_input_int_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); + const bNode &bnode = builder.node(); NodeInputInt *node_storage = static_cast<NodeInputInt *>(bnode.storage); builder.construct_and_set_matching_fn<fn::CustomMF_Constant<int>>(node_storage->integer); } diff --git a/source/blender/nodes/function/nodes/node_fn_input_string.cc b/source/blender/nodes/function/nodes/node_fn_input_string.cc index 124a8572f78..129d19f4f04 100644 --- a/source/blender/nodes/function/nodes/node_fn_input_string.cc +++ b/source/blender/nodes/function/nodes/node_fn_input_string.cc @@ -20,7 +20,7 @@ static void fn_node_input_string_layout(uiLayout *layout, bContext *UNUSED(C), P static void fn_node_input_string_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); + const bNode &bnode = builder.node(); NodeInputString *node_storage = static_cast<NodeInputString *>(bnode.storage); std::string string = std::string((node_storage->string) ? node_storage->string : ""); builder.construct_and_set_matching_fn<fn::CustomMF_Constant<std::string>>(std::move(string)); diff --git a/source/blender/nodes/function/nodes/node_fn_input_vector.cc b/source/blender/nodes/function/nodes/node_fn_input_vector.cc index 898c19e92f0..de894a4038d 100644 --- a/source/blender/nodes/function/nodes/node_fn_input_vector.cc +++ b/source/blender/nodes/function/nodes/node_fn_input_vector.cc @@ -22,7 +22,7 @@ static void fn_node_input_vector_layout(uiLayout *layout, bContext *UNUSED(C), P static void fn_node_input_vector_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); + const bNode &bnode = builder.node(); NodeInputVector *node_storage = static_cast<NodeInputVector *>(bnode.storage); float3 vector(node_storage->vector); builder.construct_and_set_matching_fn<fn::CustomMF_Constant<float3>>(vector); diff --git a/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc b/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc index a4fc1a6bfd1..299c0f7a932 100644 --- a/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc +++ b/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc @@ -52,7 +52,7 @@ static void fn_node_rotate_euler_layout(uiLayout *layout, bContext *UNUSED(C), P uiItemR(layout, ptr, "space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); } -static const fn::MultiFunction *get_multi_function(bNode &bnode) +static const fn::MultiFunction *get_multi_function(const bNode &bnode) { static fn::CustomMF_SI_SI_SO<float3, float3, float3> obj_euler_rot{ "Rotate Euler by Euler/Object", [](const float3 &input, const float3 &rotation) { diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index a4af608a40e..4db4d8bb097 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -20,6 +20,8 @@ #include "NOD_socket_declarations.hh" #include "NOD_socket_declarations_geometry.hh" +#include "RNA_access.h" + #include "node_util.h" void geo_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc index 8c3e97edac0..28d979facac 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc @@ -64,12 +64,12 @@ class EndpointFieldInput final : public bke::CurvesFieldInput { devirtualize_varray2(start_size, end_size, [&](const auto &start_size, const auto &end_size) { threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange curves_range) { for (const int i : curves_range) { - const IndexRange range = curves.points_for_curve(i); + const IndexRange points = curves.points_for_curve(i); const int start = std::max(start_size[i], 0); const int end = std::max(end_size[i], 0); - selection_span.slice(range.take_front(start)).fill(true); - selection_span.slice(range.take_back(end)).fill(true); + selection_span.slice(points.take_front(start)).fill(true); + selection_span.slice(points.take_back(end)).fill(true); } }); }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_points.cc b/source/blender/nodes/geometry/nodes/node_geo_points.cc index dd32e6714f4..e0ba1f1c810 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points.cc @@ -69,10 +69,8 @@ static void node_geo_exec(GeoNodeExecParams params) Field<float3> position_field = params.extract_input<Field<float3>>("Position"); Field<float> radius_field = params.extract_input<Field<float>>("Radius"); - PointCloud *new_point_cloud = BKE_pointcloud_new_nomain(count); - GeometrySet geometry_set = GeometrySet::create_with_pointcloud(new_point_cloud); - PointCloudComponent &points = geometry_set.get_component_for_write<PointCloudComponent>(); - MutableAttributeAccessor attributes = *points.attributes_for_write(); + PointCloud *points = BKE_pointcloud_new_nomain(count); + MutableAttributeAccessor attributes = bke::pointcloud_attributes_for_write(*points); AttributeWriter<float3> output_position = attributes.lookup_or_add_for_write<float3>( "position", ATTR_DOMAIN_POINT); AttributeWriter<float> output_radii = attributes.lookup_or_add_for_write<float>( @@ -86,7 +84,7 @@ static void node_geo_exec(GeoNodeExecParams params) output_position.finish(); output_radii.finish(); - params.set_output("Geometry", std::move(geometry_set)); + params.set_output("Geometry", GeometrySet::create_with_pointcloud(points)); } } // namespace blender::nodes::node_geo_points_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc index 9719833097e..c2d6f57ce8a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc @@ -123,7 +123,7 @@ static void try_capture_field_on_geometry(GeometryComponent &component, } } attributes.remove(name); - if (attributes.add(name, domain, data_type, bke::AttributeInitMove{buffer})) { + if (attributes.add(name, domain, data_type, bke::AttributeInitMoveArray{buffer})) { return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index f1fb9ce5563..60c8a89a6bf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -73,7 +73,7 @@ static void write_vertex_creases(Mesh &mesh, const VArray<float> &crease_varray) } else { crease = static_cast<float *>( - CustomData_add_layer(&mesh.vdata, CD_CREASE, CD_DEFAULT, nullptr, mesh.totvert)); + CustomData_add_layer(&mesh.vdata, CD_CREASE, CD_CONSTRUCT, nullptr, mesh.totvert)); } materialize_and_clamp_creases(crease_varray, {crease, mesh.totvert}); } diff --git a/source/blender/nodes/intern/derived_node_tree.cc b/source/blender/nodes/intern/derived_node_tree.cc index e589da09b16..e8e0f0fa61c 100644 --- a/source/blender/nodes/intern/derived_node_tree.cc +++ b/source/blender/nodes/intern/derived_node_tree.cc @@ -2,38 +2,38 @@ #include "NOD_derived_node_tree.hh" +#include "BKE_node.h" + #include "BLI_dot_export.hh" namespace blender::nodes { -DerivedNodeTree::DerivedNodeTree(bNodeTree &btree, NodeTreeRefMap &node_tree_refs) +DerivedNodeTree::DerivedNodeTree(const bNodeTree &btree) { /* Construct all possible contexts immediately. This is significantly cheaper than inlining all * node groups. If it still becomes a performance issue in the future, contexts could be * constructed lazily when they are needed. */ - root_context_ = &this->construct_context_recursively(nullptr, nullptr, btree, node_tree_refs); + root_context_ = &this->construct_context_recursively(nullptr, nullptr, btree); } DTreeContext &DerivedNodeTree::construct_context_recursively(DTreeContext *parent_context, - const NodeRef *parent_node, - bNodeTree &btree, - NodeTreeRefMap &node_tree_refs) + const bNode *parent_node, + const bNodeTree &btree) { + btree.ensure_topology_cache(); DTreeContext &context = *allocator_.construct<DTreeContext>().release(); context.parent_context_ = parent_context; context.parent_node_ = parent_node; context.derived_tree_ = this; - context.tree_ = &get_tree_ref_from_map(node_tree_refs, btree); - used_node_tree_refs_.add(context.tree_); + context.btree_ = &btree; + used_btrees_.add(context.btree_); - for (const NodeRef *node : context.tree_->nodes()) { - if (node->is_group_node()) { - bNode *bnode = node->bnode(); + for (const bNode *bnode : context.btree_->all_nodes()) { + if (bnode->is_group()) { bNodeTree *child_btree = reinterpret_cast<bNodeTree *>(bnode->id); if (child_btree != nullptr) { - DTreeContext &child = this->construct_context_recursively( - &context, node, *child_btree, node_tree_refs); - context.children_.add_new(node, &child); + DTreeContext &child = this->construct_context_recursively(&context, bnode, *child_btree); + context.children_.add_new(bnode, &child); } } } @@ -57,8 +57,8 @@ void DerivedNodeTree::destruct_context_recursively(DTreeContext *context) bool DerivedNodeTree::has_link_cycles() const { - for (const NodeTreeRef *tree_ref : used_node_tree_refs_) { - if (tree_ref->has_link_cycles()) { + for (const bNodeTree *btree : used_btrees_) { + if (btree->has_link_cycle()) { return true; } } @@ -67,8 +67,8 @@ bool DerivedNodeTree::has_link_cycles() const bool DerivedNodeTree::has_undefined_nodes_or_sockets() const { - for (const NodeTreeRef *tree_ref : used_node_tree_refs_) { - if (tree_ref->has_undefined_nodes_or_sockets()) { + for (const bNodeTree *btree : used_btrees_) { + if (btree->has_undefined_nodes_or_sockets()) { return true; } } @@ -83,8 +83,8 @@ void DerivedNodeTree::foreach_node(FunctionRef<void(DNode)> callback) const void DerivedNodeTree::foreach_node_in_context_recursive(const DTreeContext &context, FunctionRef<void(DNode)> callback) const { - for (const NodeRef *node_ref : context.tree_->nodes()) { - callback(DNode(&context, node_ref)); + for (const bNode *bnode : context.btree_->all_nodes()) { + callback(DNode(&context, bnode)); } for (const DTreeContext *child_context : context.children_.values()) { this->foreach_node_in_context_recursive(*child_context, callback); @@ -94,32 +94,32 @@ void DerivedNodeTree::foreach_node_in_context_recursive(const DTreeContext &cont DOutputSocket DInputSocket::get_corresponding_group_node_output() const { BLI_assert(*this); - BLI_assert(socket_ref_->node().is_group_output_node()); - BLI_assert(socket_ref_->index() < socket_ref_->node().inputs().size() - 1); + BLI_assert(bsocket_->owner_node().is_group_output()); + BLI_assert(bsocket_->index() < bsocket_->owner_node().input_sockets().size() - 1); const DTreeContext *parent_context = context_->parent_context(); - const NodeRef *parent_node = context_->parent_node(); + const bNode *parent_node = context_->parent_node(); BLI_assert(parent_context != nullptr); BLI_assert(parent_node != nullptr); - const int socket_index = socket_ref_->index(); - return {parent_context, &parent_node->output(socket_index)}; + const int socket_index = bsocket_->index(); + return {parent_context, &parent_node->output_socket(socket_index)}; } Vector<DOutputSocket> DInputSocket::get_corresponding_group_input_sockets() const { BLI_assert(*this); - BLI_assert(socket_ref_->node().is_group_node()); + BLI_assert(bsocket_->owner_node().is_group()); - const DTreeContext *child_context = context_->child_context(socket_ref_->node()); + const DTreeContext *child_context = context_->child_context(bsocket_->owner_node()); BLI_assert(child_context != nullptr); - const NodeTreeRef &child_tree = child_context->tree(); - Span<const NodeRef *> group_input_nodes = child_tree.nodes_by_type("NodeGroupInput"); - const int socket_index = socket_ref_->index(); + const bNodeTree &child_tree = child_context->btree(); + Span<const bNode *> group_input_nodes = child_tree.nodes_by_type("NodeGroupInput"); + const int socket_index = bsocket_->index(); Vector<DOutputSocket> sockets; - for (const NodeRef *group_input_node : group_input_nodes) { - sockets.append(DOutputSocket(child_context, &group_input_node->output(socket_index))); + for (const bNode *group_input_node : group_input_nodes) { + sockets.append(DOutputSocket(child_context, &group_input_node->output_socket(socket_index))); } return sockets; } @@ -127,36 +127,36 @@ Vector<DOutputSocket> DInputSocket::get_corresponding_group_input_sockets() cons DInputSocket DOutputSocket::get_corresponding_group_node_input() const { BLI_assert(*this); - BLI_assert(socket_ref_->node().is_group_input_node()); - BLI_assert(socket_ref_->index() < socket_ref_->node().outputs().size() - 1); + BLI_assert(bsocket_->owner_node().is_group_input()); + BLI_assert(bsocket_->index() < bsocket_->owner_node().output_sockets().size() - 1); const DTreeContext *parent_context = context_->parent_context(); - const NodeRef *parent_node = context_->parent_node(); + const bNode *parent_node = context_->parent_node(); BLI_assert(parent_context != nullptr); BLI_assert(parent_node != nullptr); - const int socket_index = socket_ref_->index(); - return {parent_context, &parent_node->input(socket_index)}; + const int socket_index = bsocket_->index(); + return {parent_context, &parent_node->input_socket(socket_index)}; } DInputSocket DOutputSocket::get_active_corresponding_group_output_socket() const { BLI_assert(*this); - BLI_assert(socket_ref_->node().is_group_node()); + BLI_assert(bsocket_->owner_node().is_group()); - const DTreeContext *child_context = context_->child_context(socket_ref_->node()); + const DTreeContext *child_context = context_->child_context(bsocket_->owner_node()); if (child_context == nullptr) { /* Can happen when the group node references a non-existent group (e.g. when the group is * linked but the original file is not found). */ return {}; } - const NodeTreeRef &child_tree = child_context->tree(); - Span<const NodeRef *> group_output_nodes = child_tree.nodes_by_type("NodeGroupOutput"); - const int socket_index = socket_ref_->index(); - for (const NodeRef *group_output_node : group_output_nodes) { - if (group_output_node->bnode()->flag & NODE_DO_OUTPUT || group_output_nodes.size() == 1) { - return {child_context, &group_output_node->input(socket_index)}; + const bNodeTree &child_tree = child_context->btree(); + Span<const bNode *> group_output_nodes = child_tree.nodes_by_type("NodeGroupOutput"); + const int socket_index = bsocket_->index(); + for (const bNode *group_output_node : group_output_nodes) { + if (group_output_node->flag & NODE_DO_OUTPUT || group_output_nodes.size() == 1) { + return {child_context, &group_output_node->input_socket(socket_index)}; } } return {}; @@ -165,11 +165,11 @@ DInputSocket DOutputSocket::get_active_corresponding_group_output_socket() const void DInputSocket::foreach_origin_socket(FunctionRef<void(DSocket)> origin_fn) const { BLI_assert(*this); - for (const OutputSocketRef *linked_socket : socket_ref_->as_input().logically_linked_sockets()) { - const NodeRef &linked_node = linked_socket->node(); + for (const bNodeSocket *linked_socket : bsocket_->logically_linked_sockets()) { + const bNode &linked_node = linked_socket->owner_node(); DOutputSocket linked_dsocket{context_, linked_socket}; - if (linked_node.is_group_input_node()) { + if (linked_node.is_group_input()) { if (context_->is_root()) { /* This is a group input in the root node group. */ origin_fn(linked_dsocket); @@ -187,7 +187,7 @@ void DInputSocket::foreach_origin_socket(FunctionRef<void(DSocket)> origin_fn) c } } } - else if (linked_node.is_group_node()) { + else if (linked_node.is_group()) { DInputSocket socket_in_group = linked_dsocket.get_active_corresponding_group_output_socket(); if (socket_in_group) { if (socket_in_group->is_logically_linked()) { @@ -217,16 +217,16 @@ void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn) const void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn, TargetSocketPathInfo &path_info) const { - for (const LinkRef *link : socket_ref_->as_output().directly_linked_links()) { + for (const bNodeLink *link : bsocket_->directly_linked_links()) { if (link->is_muted()) { continue; } - const DInputSocket &linked_socket{context_, &link->to()}; + const DInputSocket &linked_socket{context_, link->tosock}; if (!linked_socket->is_available()) { continue; } const DNode linked_node = linked_socket.node(); - if (linked_node->is_reroute_node()) { + if (linked_node->is_reroute()) { const DInputSocket reroute_input = linked_socket; const DOutputSocket reroute_output = linked_node.output(0); path_info.sockets.append(reroute_input); @@ -236,18 +236,18 @@ void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn, 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()) { + for (const bNodeLink *internal_link : linked_node->internal_links_span()) { + if (internal_link->fromsock != linked_socket.bsocket()) { continue; } /* The internal link only forwards the first incoming link. */ - if (linked_socket->is_multi_input_socket()) { + if (linked_socket->is_multi_input()) { if (linked_socket->directly_linked_links()[0] != link) { continue; } } const DInputSocket mute_input = linked_socket; - const DOutputSocket mute_output{context_, &internal_link->to()}; + const DOutputSocket mute_output{context_, internal_link->tosock}; path_info.sockets.append(mute_input); path_info.sockets.append(mute_output); mute_output.foreach_target_socket(target_fn, path_info); @@ -255,8 +255,8 @@ void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn, path_info.sockets.pop_last(); } } - else if (linked_node->is_group_output_node()) { - if (linked_node.node_ref() != context_->tree().group_output_node()) { + else if (linked_node->is_group_output()) { + if (linked_node.bnode() != context_->btree().group_output_node()) { continue; } if (context_->is_root()) { @@ -276,7 +276,7 @@ void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn, path_info.sockets.pop_last(); } } - else if (linked_node->is_group_node()) { + else if (linked_node->is_group()) { /* Follow the links within the nested node group. */ path_info.sockets.append(linked_socket); const Vector<DOutputSocket> sockets_in_group = @@ -310,7 +310,8 @@ static dot::Cluster *get_dot_cluster_for_context( } dot::Cluster *parent_cluster = get_dot_cluster_for_context( digraph, parent_context, dot_clusters); - std::string cluster_name = context->tree().name() + " / " + context->parent_node()->name(); + std::string cluster_name = StringRef(context->btree().id.name + 2) + " / " + + context->parent_node()->name; dot::Cluster &cluster = digraph.new_cluster(cluster_name); cluster.set_parent_cluster(parent_cluster); return &cluster; @@ -328,11 +329,11 @@ std::string DerivedNodeTree::to_dot() const this->foreach_node([&](DNode node) { /* Ignore nodes that should not show up in the final output. */ - if (node->is_muted() || node->is_group_node() || node->is_reroute_node() || node->is_frame()) { + if (node->is_muted() || node->is_group() || node->is_reroute() || node->is_frame()) { return; } if (!node.context()->is_root()) { - if (node->is_group_input_node() || node->is_group_output_node()) { + if (node->is_group_input() || node->is_group_output()) { return; } } @@ -345,22 +346,22 @@ std::string DerivedNodeTree::to_dot() const Vector<std::string> input_names; Vector<std::string> output_names; - for (const InputSocketRef *socket : node->inputs()) { + for (const bNodeSocket *socket : node->input_sockets()) { if (socket->is_available()) { - input_names.append(socket->name()); + input_names.append(socket->name); } } - for (const OutputSocketRef *socket : node->outputs()) { + for (const bNodeSocket *socket : node->output_sockets()) { if (socket->is_available()) { - output_names.append(socket->name()); + output_names.append(socket->name); } } dot::NodeWithSocketsRef dot_node_with_sockets = dot::NodeWithSocketsRef( - dot_node, node->name(), input_names, output_names); + dot_node, node->name, input_names, output_names); int input_index = 0; - for (const InputSocketRef *socket : node->inputs()) { + for (const bNodeSocket *socket : node->input_sockets()) { if (socket->is_available()) { dot_input_sockets.add_new(DInputSocket{node.context(), socket}, dot_node_with_sockets.input(input_index)); @@ -368,7 +369,7 @@ std::string DerivedNodeTree::to_dot() const } } int output_index = 0; - for (const OutputSocketRef *socket : node->outputs()) { + for (const bNodeSocket *socket : node->output_sockets()) { if (socket->is_available()) { dot_output_sockets.add_new(DOutputSocket{node.context(), socket}, dot_node_with_sockets.output(output_index)); @@ -392,7 +393,7 @@ std::string DerivedNodeTree::to_dot() const } } dot::Node &dot_node = *dot_floating_inputs.lookup_or_add_cb(from_socket, [&]() { - dot::Node &dot_node = digraph.new_node(from_socket->name()); + dot::Node &dot_node = digraph.new_node(from_socket->name); dot_node.set_background_color("white"); dot_node.set_shape(dot::Attr_shape::Ellipse); dot_node.set_parent_cluster( diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc index 55930dcb1ee..89bfa5834e8 100644 --- a/source/blender/nodes/intern/geometry_nodes_eval_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc @@ -89,17 +89,17 @@ TreeLog &ModifierLog::lookup_or_add_tree_log(LogByTreeContext &log_by_tree_conte destruct_ptr<TreeLog> owned_tree_log = allocator_.construct<TreeLog>(); tree_log = owned_tree_log.get(); log_by_tree_context.add_new(&tree_context, tree_log); - parent_log.child_logs_.add_new(tree_context.parent_node()->name(), std::move(owned_tree_log)); + parent_log.child_logs_.add_new(tree_context.parent_node()->name, std::move(owned_tree_log)); return *tree_log; } NodeLog &ModifierLog::lookup_or_add_node_log(LogByTreeContext &log_by_tree_context, DNode node) { TreeLog &tree_log = this->lookup_or_add_tree_log(log_by_tree_context, *node.context()); - NodeLog &node_log = *tree_log.node_logs_.lookup_or_add_cb(node->name(), [&]() { + NodeLog &node_log = *tree_log.node_logs_.lookup_or_add_cb(node->name, [&]() { destruct_ptr<NodeLog> node_log = allocator_.construct<NodeLog>(); - node_log->input_logs_.resize(node->inputs().size()); - node_log->output_logs_.resize(node->outputs().size()); + node_log->input_logs_.resize(node->input_sockets().size()); + node_log->output_logs_.resize(node->output_sockets().size()); return node_log; }); return node_log; diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index c6ebc22c43c..953dce035c2 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -38,7 +38,7 @@ void GeoNodeExecParams::check_input_geometry_set(StringRef identifier, const GeometrySet &geometry_set) const { const SocketDeclaration &decl = - *provider_->dnode->input_by_identifier(identifier).bsocket()->runtime->declaration; + *provider_->dnode->input_by_identifier(identifier).runtime->declaration; const decl::Geometry *geo_decl = dynamic_cast<const decl::Geometry *>(&decl); if (geo_decl == nullptr) { return; @@ -118,9 +118,9 @@ void GeoNodeExecParams::check_output_geometry_set(const GeometrySet &geometry_se const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name) const { - for (const InputSocketRef *socket : provider_->dnode->inputs()) { - if (socket->is_available() && socket->name() == name) { - return socket->bsocket(); + for (const bNodeSocket *socket : provider_->dnode->runtime->inputs) { + if (socket->is_available() && socket->name == name) { + return socket; } } @@ -140,10 +140,10 @@ void GeoNodeExecParams::set_default_remaining_outputs() void GeoNodeExecParams::check_input_access(StringRef identifier, const CPPType *requested_type) const { - bNodeSocket *found_socket = nullptr; - for (const InputSocketRef *socket : provider_->dnode->inputs()) { - if (socket->identifier() == identifier) { - found_socket = socket->bsocket(); + const bNodeSocket *found_socket = nullptr; + for (const bNodeSocket *socket : provider_->dnode->input_sockets()) { + if (socket->identifier == identifier) { + found_socket = socket; break; } } @@ -151,9 +151,9 @@ void GeoNodeExecParams::check_input_access(StringRef identifier, if (found_socket == nullptr) { std::cout << "Did not find an input socket with the identifier '" << identifier << "'.\n"; std::cout << "Possible identifiers are: "; - for (const InputSocketRef *socket : provider_->dnode->inputs()) { + for (const bNodeSocket *socket : provider_->dnode->input_sockets()) { if (socket->is_available()) { - std::cout << "'" << socket->identifier() << "', "; + std::cout << "'" << socket->identifier << "', "; } } std::cout << "\n"; @@ -182,10 +182,10 @@ void GeoNodeExecParams::check_input_access(StringRef identifier, void GeoNodeExecParams::check_output_access(StringRef identifier, const CPPType &value_type) const { - bNodeSocket *found_socket = nullptr; - for (const OutputSocketRef *socket : provider_->dnode->outputs()) { - if (socket->identifier() == identifier) { - found_socket = socket->bsocket(); + const bNodeSocket *found_socket = nullptr; + for (const bNodeSocket *socket : provider_->dnode->output_sockets()) { + if (socket->identifier == identifier) { + found_socket = socket; break; } } @@ -193,9 +193,9 @@ void GeoNodeExecParams::check_output_access(StringRef identifier, const CPPType if (found_socket == nullptr) { std::cout << "Did not find an output socket with the identifier '" << identifier << "'.\n"; std::cout << "Possible identifiers are: "; - for (const OutputSocketRef *socket : provider_->dnode->outputs()) { - if (socket->is_available()) { - std::cout << "'" << socket->identifier() << "', "; + for (const bNodeSocket *socket : provider_->dnode->output_sockets()) { + if (!(socket->flag & SOCK_UNAVAIL)) { + std::cout << "'" << socket->identifier << "', "; } } std::cout << "\n"; diff --git a/source/blender/nodes/intern/node_multi_function.cc b/source/blender/nodes/intern/node_multi_function.cc index 13bfdfbfac1..1f8397923e9 100644 --- a/source/blender/nodes/intern/node_multi_function.cc +++ b/source/blender/nodes/intern/node_multi_function.cc @@ -2,14 +2,14 @@ #include "NOD_multi_function.hh" +#include "BKE_node.h" + namespace blender::nodes { NodeMultiFunctions::NodeMultiFunctions(const DerivedNodeTree &tree) { - for (const NodeTreeRef *tree_ref : tree.used_node_tree_refs()) { - bNodeTree *btree = tree_ref->btree(); - for (const NodeRef *node : tree_ref->nodes()) { - bNode *bnode = node->bnode(); + for (const bNodeTree *btree : tree.used_btrees()) { + for (const bNode *bnode : btree->all_nodes()) { if (bnode->typeinfo->build_multi_function == nullptr) { continue; } diff --git a/source/blender/nodes/intern/node_tree_ref.cc b/source/blender/nodes/intern/node_tree_ref.cc deleted file mode 100644 index 05e7fe33776..00000000000 --- a/source/blender/nodes/intern/node_tree_ref.cc +++ /dev/null @@ -1,679 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include <mutex> - -#include "NOD_node_tree_ref.hh" - -#include "BLI_dot_export.hh" -#include "BLI_stack.hh" - -#include "RNA_prototypes.h" - -namespace blender::nodes { - -NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree) -{ - Map<bNode *, NodeRef *> node_mapping; - - LISTBASE_FOREACH (bNode *, bnode, &btree->nodes) { - NodeRef &node = *allocator_.construct<NodeRef>().release(); - - node.tree_ = this; - node.bnode_ = bnode; - node.id_ = nodes_by_id_.append_and_get_index(&node); - - LISTBASE_FOREACH (bNodeSocket *, bsocket, &bnode->inputs) { - InputSocketRef &socket = *allocator_.construct<InputSocketRef>().release(); - socket.node_ = &node; - socket.index_ = node.inputs_.append_and_get_index(&socket); - socket.is_input_ = true; - socket.bsocket_ = bsocket; - socket.id_ = sockets_by_id_.append_and_get_index(&socket); - } - - LISTBASE_FOREACH (bNodeSocket *, bsocket, &bnode->outputs) { - OutputSocketRef &socket = *allocator_.construct<OutputSocketRef>().release(); - socket.node_ = &node; - socket.index_ = node.outputs_.append_and_get_index(&socket); - socket.is_input_ = false; - socket.bsocket_ = bsocket; - socket.id_ = sockets_by_id_.append_and_get_index(&socket); - } - - LISTBASE_FOREACH (bNodeLink *, blink, &bnode->internal_links) { - InternalLinkRef &internal_link = *allocator_.construct<InternalLinkRef>().release(); - internal_link.blink_ = blink; - for (InputSocketRef *socket_ref : node.inputs_) { - if (socket_ref->bsocket_ == blink->fromsock) { - internal_link.from_ = socket_ref; - break; - } - } - for (OutputSocketRef *socket_ref : node.outputs_) { - if (socket_ref->bsocket_ == blink->tosock) { - internal_link.to_ = socket_ref; - break; - } - } - BLI_assert(internal_link.from_ != nullptr); - BLI_assert(internal_link.to_ != nullptr); - node.internal_links_.append(&internal_link); - } - - input_sockets_.extend(node.inputs_.as_span()); - output_sockets_.extend(node.outputs_.as_span()); - - node_mapping.add_new(bnode, &node); - } - - LISTBASE_FOREACH (bNodeLink *, blink, &btree->links) { - OutputSocketRef &from_socket = this->find_output_socket( - node_mapping, blink->fromnode, blink->fromsock); - InputSocketRef &to_socket = this->find_input_socket( - node_mapping, blink->tonode, blink->tosock); - - LinkRef &link = *allocator_.construct<LinkRef>().release(); - link.from_ = &from_socket; - link.to_ = &to_socket; - link.blink_ = blink; - - links_.append(&link); - - from_socket.directly_linked_links_.append(&link); - to_socket.directly_linked_links_.append(&link); - } - - for (InputSocketRef *input_socket : input_sockets_) { - if (input_socket->is_multi_input_socket()) { - std::sort(input_socket->directly_linked_links_.begin(), - input_socket->directly_linked_links_.end(), - [&](const LinkRef *a, const LinkRef *b) -> bool { - int index_a = a->blink()->multi_input_socket_index; - int index_b = b->blink()->multi_input_socket_index; - return index_a > index_b; - }); - } - } - - this->create_socket_identifier_maps(); - this->create_linked_socket_caches(); - - for (NodeRef *node : nodes_by_id_) { - const bNodeType *nodetype = node->bnode_->typeinfo; - nodes_by_type_.add(nodetype, node); - } - - const Span<const NodeRef *> group_output_nodes = this->nodes_by_type("NodeGroupOutput"); - if (group_output_nodes.is_empty()) { - group_output_node_ = nullptr; - } - else if (group_output_nodes.size() == 1) { - group_output_node_ = group_output_nodes.first(); - } - else { - for (const NodeRef *group_output : group_output_nodes) { - if (group_output->bnode_->flag & NODE_DO_OUTPUT) { - group_output_node_ = group_output; - break; - } - } - } -} - -NodeTreeRef::~NodeTreeRef() -{ - /* The destructor has to be called manually, because these types are allocated in a linear - * allocator. */ - for (NodeRef *node : nodes_by_id_) { - node->~NodeRef(); - } - for (InputSocketRef *socket : input_sockets_) { - socket->~InputSocketRef(); - } - for (OutputSocketRef *socket : output_sockets_) { - socket->~OutputSocketRef(); - } - for (LinkRef *link : links_) { - link->~LinkRef(); - } -} - -InputSocketRef &NodeTreeRef::find_input_socket(Map<bNode *, NodeRef *> &node_mapping, - bNode *bnode, - bNodeSocket *bsocket) -{ - NodeRef *node = node_mapping.lookup(bnode); - for (InputSocketRef *socket : node->inputs_) { - if (socket->bsocket_ == bsocket) { - return *socket; - } - } - BLI_assert_unreachable(); - return *node->inputs_[0]; -} - -OutputSocketRef &NodeTreeRef::find_output_socket(Map<bNode *, NodeRef *> &node_mapping, - bNode *bnode, - bNodeSocket *bsocket) -{ - NodeRef *node = node_mapping.lookup(bnode); - for (OutputSocketRef *socket : node->outputs_) { - if (socket->bsocket_ == bsocket) { - return *socket; - } - } - BLI_assert_unreachable(); - return *node->outputs_[0]; -} - -void NodeTreeRef::create_linked_socket_caches() -{ - for (InputSocketRef *socket : input_sockets_) { - /* Find directly linked socket based on incident links. */ - Vector<const 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 logically linked sockets. */ - Vector<const SocketRef *> logically_linked_sockets; - Vector<const SocketRef *> logically_linked_skipped_sockets; - Vector<const InputSocketRef *> seen_sockets_stack; - socket->foreach_logical_origin( - [&](const OutputSocketRef &origin) { logically_linked_sockets.append(&origin); }, - [&](const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); }, - false, - seen_sockets_stack); - if (logically_linked_sockets == directly_linked_sockets) { - socket->logically_linked_sockets_ = socket->directly_linked_sockets_; - } - else { - socket->logically_linked_sockets_ = allocator_.construct_array_copy( - logically_linked_sockets.as_span()); - } - socket->logically_linked_skipped_sockets_ = allocator_.construct_array_copy( - logically_linked_skipped_sockets.as_span()); - } - - for (OutputSocketRef *socket : output_sockets_) { - /* Find directly linked socket based on incident links. */ - Vector<const 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 logically linked sockets. */ - Vector<const SocketRef *> logically_linked_sockets; - Vector<const SocketRef *> logically_linked_skipped_sockets; - Vector<const OutputSocketRef *> handled_sockets; - socket->foreach_logical_target( - [&](const InputSocketRef &target) { logically_linked_sockets.append(&target); }, - [&](const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); }, - handled_sockets); - if (logically_linked_sockets == directly_linked_sockets) { - socket->logically_linked_sockets_ = socket->directly_linked_sockets_; - } - else { - socket->logically_linked_sockets_ = allocator_.construct_array_copy( - logically_linked_sockets.as_span()); - } - socket->logically_linked_skipped_sockets_ = allocator_.construct_array_copy( - logically_linked_skipped_sockets.as_span()); - } -} - -void InputSocketRef::foreach_logical_origin( - FunctionRef<void(const OutputSocketRef &)> origin_fn, - FunctionRef<void(const SocketRef &)> skipped_fn, - bool only_follow_first_input_link, - Vector<const InputSocketRef *> &seen_sockets_stack) const -{ - /* Protect against loops. */ - if (seen_sockets_stack.contains(this)) { - return; - } - seen_sockets_stack.append(this); - - Span<const LinkRef *> links_to_check = this->directly_linked_links(); - if (only_follow_first_input_link) { - links_to_check = links_to_check.take_front(1); - } - for (const LinkRef *link : links_to_check) { - if (link->is_muted()) { - continue; - } - const OutputSocketRef &origin = link->from(); - const NodeRef &origin_node = origin.node(); - if (!origin.is_available()) { - /* Non available sockets are ignored. */ - } - else if (origin_node.is_reroute_node()) { - const InputSocketRef &reroute_input = origin_node.input(0); - const OutputSocketRef &reroute_output = origin_node.output(0); - skipped_fn.call_safe(reroute_input); - skipped_fn.call_safe(reroute_output); - reroute_input.foreach_logical_origin(origin_fn, skipped_fn, false, seen_sockets_stack); - } - else if (origin_node.is_muted()) { - for (const InternalLinkRef *internal_link : origin_node.internal_links()) { - if (&internal_link->to() == &origin) { - const InputSocketRef &mute_input = internal_link->from(); - skipped_fn.call_safe(origin); - skipped_fn.call_safe(mute_input); - mute_input.foreach_logical_origin(origin_fn, skipped_fn, true, seen_sockets_stack); - } - } - } - else { - origin_fn(origin); - } - } - - seen_sockets_stack.pop_last(); -} - -void OutputSocketRef::foreach_logical_target( - FunctionRef<void(const InputSocketRef &)> target_fn, - FunctionRef<void(const SocketRef &)> skipped_fn, - Vector<const OutputSocketRef *> &seen_sockets_stack) const -{ - /* Protect against loops. */ - if (seen_sockets_stack.contains(this)) { - return; - } - seen_sockets_stack.append(this); - - for (const LinkRef *link : this->directly_linked_links()) { - if (link->is_muted()) { - continue; - } - const InputSocketRef &target = link->to(); - const NodeRef &target_node = target.node(); - if (!target.is_available()) { - /* Non available sockets are ignored. */ - } - else if (target_node.is_reroute_node()) { - const OutputSocketRef &reroute_output = target_node.output(0); - skipped_fn.call_safe(target); - skipped_fn.call_safe(reroute_output); - reroute_output.foreach_logical_target(target_fn, skipped_fn, seen_sockets_stack); - } - else if (target_node.is_muted()) { - skipped_fn.call_safe(target); - for (const InternalLinkRef *internal_link : target_node.internal_links()) { - if (&internal_link->from() == &target) { - /* The internal link only forwards the first incoming link. */ - if (target.is_multi_input_socket()) { - if (target.directly_linked_links()[0] != link) { - continue; - } - } - const OutputSocketRef &mute_output = internal_link->to(); - skipped_fn.call_safe(target); - skipped_fn.call_safe(mute_output); - mute_output.foreach_logical_target(target_fn, skipped_fn, seen_sockets_stack); - } - } - } - else { - target_fn(target); - } - } - - seen_sockets_stack.pop_last(); -} - -namespace { -struct SocketByIdentifierMap { - SocketIndexByIdentifierMap *map = nullptr; - std::unique_ptr<SocketIndexByIdentifierMap> owned_map; -}; -} // namespace - -static std::unique_ptr<SocketIndexByIdentifierMap> create_identifier_map(const ListBase &sockets) -{ - std::unique_ptr<SocketIndexByIdentifierMap> map = std::make_unique<SocketIndexByIdentifierMap>(); - int index; - LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, &sockets, index) { - map->add_new(socket->identifier, index); - } - return map; -} - -/* This function is not threadsafe. */ -static SocketByIdentifierMap get_or_create_identifier_map( - const bNode &node, const ListBase &sockets, const bNodeSocketTemplate *sockets_template) -{ - SocketByIdentifierMap map; - if (sockets_template == nullptr) { - if (BLI_listbase_is_empty(&sockets)) { - static SocketIndexByIdentifierMap empty_map; - map.map = &empty_map; - } - else if (node.type == NODE_REROUTE) { - if (&node.inputs == &sockets) { - static SocketIndexByIdentifierMap reroute_input_map = [] { - SocketIndexByIdentifierMap map; - map.add_new("Input", 0); - return map; - }(); - map.map = &reroute_input_map; - } - else { - static SocketIndexByIdentifierMap reroute_output_map = [] { - SocketIndexByIdentifierMap map; - map.add_new("Output", 0); - return map; - }(); - map.map = &reroute_output_map; - } - } - else { - /* The node has a dynamic amount of sockets. Therefore we need to create a new map. */ - map.owned_map = create_identifier_map(sockets); - map.map = &*map.owned_map; - } - } - else { - /* Cache only one map for nodes that have the same sockets. */ - static Map<const bNodeSocketTemplate *, std::unique_ptr<SocketIndexByIdentifierMap>> maps; - map.map = &*maps.lookup_or_add_cb(sockets_template, - [&]() { return create_identifier_map(sockets); }); - } - return map; -} - -void NodeTreeRef::create_socket_identifier_maps() -{ - /* `get_or_create_identifier_map` is not threadsafe, therefore we have to hold a lock here. */ - static std::mutex mutex; - std::lock_guard lock{mutex}; - - for (NodeRef *node : nodes_by_id_) { - bNode &bnode = *node->bnode_; - SocketByIdentifierMap inputs_map = get_or_create_identifier_map( - bnode, bnode.inputs, bnode.typeinfo->inputs); - SocketByIdentifierMap outputs_map = get_or_create_identifier_map( - bnode, bnode.outputs, bnode.typeinfo->outputs); - node->input_index_by_identifier_ = inputs_map.map; - node->output_index_by_identifier_ = outputs_map.map; - if (inputs_map.owned_map) { - owned_identifier_maps_.append(std::move(inputs_map.owned_map)); - } - if (outputs_map.owned_map) { - owned_identifier_maps_.append(std::move(outputs_map.owned_map)); - } - } -} - -static bool has_link_cycles_recursive(const NodeRef &node, - MutableSpan<bool> visited, - MutableSpan<bool> is_in_stack) -{ - const int node_id = node.id(); - if (is_in_stack[node_id]) { - return true; - } - if (visited[node_id]) { - return false; - } - - visited[node_id] = true; - is_in_stack[node_id] = true; - - for (const OutputSocketRef *from_socket : node.outputs()) { - if (!from_socket->is_available()) { - continue; - } - for (const InputSocketRef *to_socket : from_socket->directly_linked_sockets()) { - if (!to_socket->is_available()) { - continue; - } - const NodeRef &to_node = to_socket->node(); - if (has_link_cycles_recursive(to_node, visited, is_in_stack)) { - return true; - } - } - } - - is_in_stack[node_id] = false; - return false; -} - -bool NodeTreeRef::has_link_cycles() const -{ - const int node_amount = nodes_by_id_.size(); - Array<bool> visited(node_amount, false); - Array<bool> is_in_stack(node_amount, false); - - for (const NodeRef *node : nodes_by_id_) { - if (has_link_cycles_recursive(*node, visited, is_in_stack)) { - return true; - } - } - return false; -} - -bool NodeTreeRef::has_undefined_nodes_or_sockets() const -{ - for (const NodeRef *node : nodes_by_id_) { - if (node->is_undefined()) { - return true; - } - } - for (const SocketRef *socket : sockets_by_id_) { - if (socket->is_undefined()) { - return true; - } - } - return false; -} - -bool NodeRef::any_input_is_directly_linked() const -{ - for (const SocketRef *socket : inputs_) { - if (!socket->directly_linked_sockets().is_empty()) { - return true; - } - } - return false; -} - -bool NodeRef::any_output_is_directly_linked() const -{ - for (const SocketRef *socket : outputs_) { - if (!socket->directly_linked_sockets().is_empty()) { - return true; - } - } - return false; -} - -bool NodeRef::any_socket_is_directly_linked(eNodeSocketInOut in_out) const -{ - if (in_out == SOCK_IN) { - return this->any_input_is_directly_linked(); - } - return this->any_output_is_directly_linked(); -} - -struct ToposortNodeState { - bool is_done = false; - bool is_in_stack = false; -}; - -static void toposort_from_start_node(const NodeTreeRef::ToposortDirection direction, - const NodeRef &start_node, - MutableSpan<ToposortNodeState> node_states, - NodeTreeRef::ToposortResult &result) -{ - struct Item { - const NodeRef *node; - /* Index of the next socket that is checked in the depth-first search. */ - int socket_index = 0; - /* Link index in the next socket that is checked in the depth-first search. */ - int link_index = 0; - }; - - /* Do a depth-first search to sort nodes topologically. */ - Stack<Item, 64> nodes_to_check; - nodes_to_check.push({&start_node}); - node_states[start_node.id()].is_in_stack = true; - while (!nodes_to_check.is_empty()) { - Item &item = nodes_to_check.peek(); - const NodeRef &node = *item.node; - const Span<const SocketRef *> sockets = node.sockets( - direction == NodeTreeRef::ToposortDirection::LeftToRight ? SOCK_IN : SOCK_OUT); - - while (true) { - if (item.socket_index == sockets.size()) { - /* All sockets have already been visited. */ - break; - } - const SocketRef &socket = *sockets[item.socket_index]; - const Span<const SocketRef *> linked_sockets = socket.directly_linked_sockets(); - if (item.link_index == linked_sockets.size()) { - /* All links connected to this socket have already been visited. */ - item.socket_index++; - item.link_index = 0; - continue; - } - const SocketRef &linked_socket = *linked_sockets[item.link_index]; - const NodeRef &linked_node = linked_socket.node(); - ToposortNodeState &linked_node_state = node_states[linked_node.id()]; - if (linked_node_state.is_done) { - /* The linked node has already been visited. */ - item.link_index++; - continue; - } - if (linked_node_state.is_in_stack) { - result.has_cycle = true; - } - else { - nodes_to_check.push({&linked_node}); - linked_node_state.is_in_stack = true; - } - break; - } - - /* If no other element has been pushed, the current node can be pushed to the sorted list. */ - if (&item == &nodes_to_check.peek()) { - ToposortNodeState &node_state = node_states[node.id()]; - node_state.is_done = true; - node_state.is_in_stack = false; - result.sorted_nodes.append(&node); - nodes_to_check.pop(); - } - } -} - -NodeTreeRef::ToposortResult NodeTreeRef::toposort(const ToposortDirection direction) const -{ - ToposortResult result; - result.sorted_nodes.reserve(nodes_by_id_.size()); - - Array<ToposortNodeState> node_states(nodes_by_id_.size()); - - for (const NodeRef *node : nodes_by_id_) { - if (node_states[node->id()].is_done) { - /* Ignore nodes that are done already. */ - continue; - } - if (node->any_socket_is_directly_linked( - direction == ToposortDirection::LeftToRight ? SOCK_OUT : SOCK_IN)) { - /* Ignore non-start nodes. */ - continue; - } - - toposort_from_start_node(direction, *node, node_states, result); - } - - /* Check if the loop above forgot some nodes because there is a cycle. */ - if (result.sorted_nodes.size() < nodes_by_id_.size()) { - result.has_cycle = true; - for (const NodeRef *node : nodes_by_id_) { - if (node_states[node->id()].is_done) { - /* Ignore nodes that are done already. */ - continue; - } - /* Start toposort at this node which is somewhere in the middle of a loop. */ - toposort_from_start_node(direction, *node, node_states, result); - } - } - - BLI_assert(result.sorted_nodes.size() == nodes_by_id_.size()); - return result; -} - -const NodeRef *NodeTreeRef::find_node(const bNode &bnode) const -{ - for (const NodeRef *node : this->nodes_by_type(bnode.typeinfo)) { - if (node->bnode_ == &bnode) { - return node; - } - } - return nullptr; -} - -std::string NodeTreeRef::to_dot() const -{ - dot::DirectedGraph digraph; - digraph.set_rankdir(dot::Attr_rankdir::LeftToRight); - - Map<const NodeRef *, dot::NodeWithSocketsRef> dot_nodes; - - for (const NodeRef *node : nodes_by_id_) { - dot::Node &dot_node = digraph.new_node(""); - dot_node.set_background_color("white"); - - Vector<std::string> input_names; - Vector<std::string> output_names; - for (const InputSocketRef *socket : node->inputs()) { - input_names.append(socket->name()); - } - for (const OutputSocketRef *socket : node->outputs()) { - output_names.append(socket->name()); - } - - dot_nodes.add_new(node, - dot::NodeWithSocketsRef(dot_node, node->name(), input_names, output_names)); - } - - for (const OutputSocketRef *from_socket : output_sockets_) { - for (const InputSocketRef *to_socket : from_socket->directly_linked_sockets()) { - dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(&from_socket->node()); - dot::NodeWithSocketsRef &to_dot_node = dot_nodes.lookup(&to_socket->node()); - - digraph.new_edge(from_dot_node.output(from_socket->index()), - to_dot_node.input(to_socket->index())); - } - } - - return digraph.to_dot_string(); -} - -const NodeTreeRef &get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree) -{ - return *node_tree_refs.lookup_or_add_cb(&btree, - [&]() { return std::make_unique<NodeTreeRef>(&btree); }); -} - -PointerRNA NodeRef::rna() const -{ - PointerRNA rna; - RNA_pointer_create(&tree_->btree()->id, &RNA_Node, bnode_, &rna); - return rna; -} - -PointerRNA SocketRef::rna() const -{ - PointerRNA rna; - RNA_pointer_create(&this->tree().btree()->id, &RNA_NodeSocket, bsocket_, &rna); - return rna; -} - -} // namespace blender::nodes diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt index 3e90f185168..d135f9a12a4 100644 --- a/source/blender/nodes/shader/CMakeLists.txt +++ b/source/blender/nodes/shader/CMakeLists.txt @@ -68,6 +68,7 @@ set(SRC nodes/node_shader_mapping.cc nodes/node_shader_math.cc nodes/node_shader_mix_rgb.cc + nodes/node_shader_mix.cc nodes/node_shader_mix_shader.cc nodes/node_shader_normal.cc nodes/node_shader_normal_map.cc diff --git a/source/blender/nodes/shader/node_shader_util.hh b/source/blender/nodes/shader/node_shader_util.hh index d5f54d9cac9..38220634695 100644 --- a/source/blender/nodes/shader/node_shader_util.hh +++ b/source/blender/nodes/shader/node_shader_util.hh @@ -59,6 +59,8 @@ #include "RE_pipeline.h" #include "RE_texture.h" +#include "RNA_access.h" + bool sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree, const char **r_disabled_hint); diff --git a/source/blender/nodes/shader/nodes/node_shader_color_ramp.cc b/source/blender/nodes/shader/nodes/node_shader_color_ramp.cc index 3723480ffa3..d73ffd89288 100644 --- a/source/blender/nodes/shader/nodes/node_shader_color_ramp.cc +++ b/source/blender/nodes/shader/nodes/node_shader_color_ramp.cc @@ -125,7 +125,7 @@ class ColorBandFunction : public fn::MultiFunction { static void sh_node_valtorgb_build_multi_function(nodes::NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); + const bNode &bnode = builder.node(); const ColorBand *color_band = (const ColorBand *)bnode.storage; builder.construct_and_set_matching_fn<ColorBandFunction>(*color_band); } diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.cc b/source/blender/nodes/shader/nodes/node_shader_curves.cc index eb47059063d..4725aef5991 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.cc +++ b/source/blender/nodes/shader/nodes/node_shader_curves.cc @@ -95,7 +95,7 @@ class CurveVecFunction : public fn::MultiFunction { static void sh_node_curve_vec_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); + const bNode &bnode = builder.node(); CurveMapping *cumap = (CurveMapping *)bnode.storage; BKE_curvemapping_init(cumap); builder.construct_and_set_matching_fn<CurveVecFunction>(*cumap); @@ -237,7 +237,7 @@ class CurveRGBFunction : public fn::MultiFunction { static void sh_node_curve_rgb_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); + const bNode &bnode = builder.node(); CurveMapping *cumap = (CurveMapping *)bnode.storage; BKE_curvemapping_init(cumap); builder.construct_and_set_matching_fn<CurveRGBFunction>(*cumap); @@ -356,7 +356,7 @@ class CurveFloatFunction : public fn::MultiFunction { static void sh_node_curve_float_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &bnode = builder.node(); + const bNode &bnode = builder.node(); CurveMapping *cumap = (CurveMapping *)bnode.storage; BKE_curvemapping_init(cumap); builder.construct_and_set_matching_fn<CurveFloatFunction>(*cumap); diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc index 73ee6fb3f85..bd83f8dac37 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_math.cc @@ -102,7 +102,7 @@ static int gpu_shader_math(GPUMaterial *mat, return 0; } -static const fn::MultiFunction *get_base_multi_function(bNode &node) +static const fn::MultiFunction *get_base_multi_function(const bNode &node) { const int mode = node.custom1; const fn::MultiFunction *base_fn = nullptr; diff --git a/source/blender/nodes/shader/nodes/node_shader_mix.cc b/source/blender/nodes/shader/nodes/node_shader_mix.cc new file mode 100644 index 00000000000..918d9b747d5 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_mix.cc @@ -0,0 +1,443 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2005 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup shdnodes + */ + +#include <algorithm> + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_shader_util.hh" + +#include "NOD_socket_search_link.hh" +#include "RNA_enum_types.h" + +namespace blender::nodes::node_sh_mix_cc { + +NODE_STORAGE_FUNCS(NodeShaderMix) + +static void sh_node_mix_declare(NodeDeclarationBuilder &b) +{ + b.is_function_node(); + b.add_input<decl::Float>(N_("Factor"), "Factor_Float") + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Vector>(N_("Factor"), "Factor_Vector") + .default_value(float3(0.5f)) + .subtype(PROP_FACTOR); + + b.add_input<decl::Float>(N_("A"), "A_Float") + .min(-10000.0f) + .max(10000.0f) + .is_default_link_socket(); + b.add_input<decl::Float>(N_("B"), "B_Float").min(-10000.0f).max(10000.0f); + + b.add_input<decl::Vector>(N_("A"), "A_Vector").is_default_link_socket(); + b.add_input<decl::Vector>(N_("B"), "B_Vector"); + + b.add_input<decl::Color>(N_("A"), "A_Color") + .default_value({0.5f, 0.5f, 0.5f, 1.0f}) + .is_default_link_socket(); + b.add_input<decl::Color>(N_("B"), "B_Color").default_value({0.5f, 0.5f, 0.5f, 1.0f}); + + b.add_output<decl::Float>(N_("Result"), "Result_Float"); + b.add_output<decl::Vector>(N_("Result"), "Result_Vector"); + b.add_output<decl::Color>(N_("Result"), "Result_Color"); +}; + +static void sh_node_mix_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + const NodeShaderMix &data = node_storage(*static_cast<const bNode *>(ptr->data)); + uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); + if (data.data_type == SOCK_VECTOR) { + uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE); + } + if (data.data_type == SOCK_RGBA) { + uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "clamp_result", 0, nullptr, ICON_NONE); + uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE); + } + else { + uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE); + } +} + +static void sh_node_mix_label(const bNodeTree *UNUSED(ntree), + const bNode *node, + char *label, + int maxlen) +{ + const NodeShaderMix &storage = node_storage(*node); + if (storage.data_type == SOCK_RGBA) { + const char *name; + bool enum_label = RNA_enum_name(rna_enum_ramp_blend_items, storage.blend_type, &name); + if (!enum_label) { + name = "Unknown"; + } + BLI_strncpy(label, IFACE_(name), maxlen); + } +} + +static int sh_node_mix_ui_class(const bNode *node) +{ + const NodeShaderMix &storage = node_storage(*node); + const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.data_type); + + switch (data_type) { + case SOCK_VECTOR: + return NODE_CLASS_OP_VECTOR; + case SOCK_RGBA: + return NODE_CLASS_OP_COLOR; + default: + return NODE_CLASS_CONVERTER; + } +} + +static void sh_node_mix_update(bNodeTree *ntree, bNode *node) +{ + const NodeShaderMix &storage = node_storage(*node); + const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.data_type); + + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { + nodeSetSocketAvailability(ntree, socket, socket->type == data_type); + } + + LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) { + nodeSetSocketAvailability(ntree, socket, socket->type == data_type); + } + + bool use_vector_factor = data_type == SOCK_VECTOR && + storage.factor_mode != NODE_MIX_MODE_UNIFORM; + + bNodeSocket *sock_factor = (bNodeSocket *)BLI_findlink(&node->inputs, 0); + nodeSetSocketAvailability(ntree, sock_factor, !use_vector_factor); + + bNodeSocket *sock_factor_vec = (bNodeSocket *)BLI_findlink(&node->inputs, 1); + nodeSetSocketAvailability(ntree, sock_factor_vec, use_vector_factor); +} + +static void node_mix_gather_link_searches(GatherLinkSearchOpParams ¶ms) +{ + const eNodeSocketDatatype sock_type = static_cast<eNodeSocketDatatype>( + params.other_socket().type); + + if (ELEM(sock_type, SOCK_BOOLEAN, SOCK_FLOAT, SOCK_RGBA, SOCK_VECTOR, SOCK_INT)) { + const eNodeSocketDatatype type = ELEM(sock_type, SOCK_BOOLEAN, SOCK_INT) ? SOCK_FLOAT : + sock_type; + + if (params.in_out() == SOCK_OUT) { + params.add_item(IFACE_("Result"), [type](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("ShaderNodeMix"); + node_storage(node).data_type = type; + params.update_and_connect_available_socket(node, "Result"); + }); + } + else { + if (ELEM(sock_type, SOCK_VECTOR, SOCK_RGBA)) { + params.add_item(IFACE_("Factor (Non-Uniform)"), [type](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("ShaderNodeMix"); + node_storage(node).data_type = SOCK_VECTOR; + node_storage(node).factor_mode = NODE_MIX_MODE_NON_UNIFORM; + params.update_and_connect_available_socket(node, "Factor"); + }); + } + params.add_item(IFACE_("Factor"), [type](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("ShaderNodeMix"); + node_storage(node).data_type = type; + params.update_and_connect_available_socket(node, "Factor"); + }); + params.add_item(IFACE_("A"), [type](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("ShaderNodeMix"); + node_storage(node).data_type = type; + params.update_and_connect_available_socket(node, "A"); + }); + params.add_item(IFACE_("B"), [type](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("ShaderNodeMix"); + node_storage(node).data_type = type; + params.update_and_connect_available_socket(node, "B"); + }); + } + } +} + +static void node_mix_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeShaderMix *data = MEM_cnew<NodeShaderMix>(__func__); + data->data_type = SOCK_FLOAT; + data->factor_mode = NODE_MIX_MODE_UNIFORM; + data->clamp_factor = 1; + data->clamp_result = 0; + data->blend_type = MA_RAMP_BLEND; + node->storage = data; +} + +static const char *gpu_shader_get_name(eNodeSocketDatatype data_type, + const bool non_uniform, + const int blend_type) +{ + switch (data_type) { + case SOCK_FLOAT: + return "node_mix_float"; + case SOCK_VECTOR: + return (non_uniform) ? "node_mix_vector_non_uniform" : "node_mix_vector"; + case SOCK_RGBA: + switch (blend_type) { + case MA_RAMP_BLEND: + return "node_mix_blend"; + case MA_RAMP_ADD: + return "node_mix_add"; + case MA_RAMP_MULT: + return "node_mix_mult"; + case MA_RAMP_SUB: + return "node_mix_sub"; + case MA_RAMP_SCREEN: + return "node_mix_screen"; + case MA_RAMP_DIV: + return "node_mix_div_fallback"; + case MA_RAMP_DIFF: + return "node_mix_diff"; + case MA_RAMP_DARK: + return "node_mix_dark"; + case MA_RAMP_LIGHT: + return "node_mix_light"; + case MA_RAMP_OVERLAY: + return "node_mix_overlay"; + case MA_RAMP_DODGE: + return "node_mix_dodge"; + case MA_RAMP_BURN: + return "node_mix_burn"; + case MA_RAMP_HUE: + return "node_mix_hue"; + case MA_RAMP_SAT: + return "node_mix_sat"; + case MA_RAMP_VAL: + return "node_mix_val"; + case MA_RAMP_COLOR: + return "node_mix_color"; + case MA_RAMP_SOFT: + return "node_mix_soft"; + case MA_RAMP_LINEAR: + return "node_mix_linear"; + default: + BLI_assert_unreachable(); + return nullptr; + } + default: + BLI_assert_unreachable(); + return nullptr; + } +} + +static int gpu_shader_mix(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + const NodeShaderMix &storage = node_storage(*node); + const bool is_non_uniform = storage.factor_mode == NODE_MIX_MODE_NON_UNIFORM; + const bool is_color_mode = storage.data_type == SOCK_RGBA; + const bool is_vector_mode = storage.data_type == SOCK_VECTOR; + const int blend_type = storage.blend_type; + const char *name = gpu_shader_get_name( + (eNodeSocketDatatype)storage.data_type, is_non_uniform, blend_type); + + if (name == nullptr) { + return 0; + } + + if (storage.clamp_factor) { + if (is_non_uniform && is_vector_mode) { + const float min[3] = {0.0f, 0.0f, 0.0f}; + const float max[3] = {1.0f, 1.0f, 1.0f}; + const GPUNodeLink *factor_link = in[1].link ? in[1].link : GPU_uniform(in[1].vec); + GPU_link(mat, + "node_mix_clamp_vector", + factor_link, + GPU_constant(min), + GPU_constant(max), + &in[1].link); + } + else { + const float min = 0.0f; + const float max = 1.0f; + const GPUNodeLink *factor_link = in[0].link ? in[0].link : GPU_uniform(in[0].vec); + GPU_link(mat, + "node_mix_clamp_value", + factor_link, + GPU_constant(&min), + GPU_constant(&max), + &in[0].link); + } + } + + int ret = GPU_stack_link(mat, node, name, in, out); + + if (ret && is_color_mode && storage.clamp_result) { + const float min[3] = {0.0f, 0.0f, 0.0f}; + const float max[3] = {1.0f, 1.0f, 1.0f}; + GPU_link(mat, + "node_mix_clamp_vector", + out[2].link, + GPU_constant(min), + GPU_constant(max), + &out[2].link); + } + return ret; +} + +class MixColorFunction : public fn::MultiFunction { + private: + const bool clamp_factor_; + const bool clamp_result_; + const int blend_type_; + + public: + MixColorFunction(const bool clamp_factor, const bool clamp_result, const int blend_type) + : clamp_factor_(clamp_factor), clamp_result_(clamp_result), blend_type_(blend_type) + { + static fn::MFSignature signature = create_signature(); + this->set_signature(&signature); + } + + static fn::MFSignature create_signature() + { + fn::MFSignatureBuilder signature{"MixColor"}; + signature.single_input<float>("Factor"); + signature.single_input<ColorGeometry4f>("A"); + signature.single_input<ColorGeometry4f>("B"); + signature.single_output<ColorGeometry4f>("Result"); + return signature.build(); + } + + void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override + { + const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor"); + const VArray<ColorGeometry4f> &col1 = params.readonly_single_input<ColorGeometry4f>(1, "A"); + const VArray<ColorGeometry4f> &col2 = params.readonly_single_input<ColorGeometry4f>(2, "B"); + MutableSpan<ColorGeometry4f> results = params.uninitialized_single_output<ColorGeometry4f>( + 3, "Result"); + + if (clamp_factor_) { + for (int64_t i : mask) { + results[i] = col1[i]; + ramp_blend(blend_type_, results[i], std::clamp(fac[i], 0.0f, 1.0f), col2[i]); + } + } + else { + for (int64_t i : mask) { + results[i] = col1[i]; + ramp_blend(blend_type_, results[i], fac[i], col2[i]); + } + } + + if (clamp_result_) { + for (int64_t i : mask) { + clamp_v3(results[i], 0.0f, 1.0f); + } + } + } +}; + +static const fn::MultiFunction *get_multi_function(const bNode &node) +{ + const NodeShaderMix *data = (NodeShaderMix *)node.storage; + bool uniform_factor = data->factor_mode == NODE_MIX_MODE_UNIFORM; + const bool clamp_factor = data->clamp_factor; + switch (data->data_type) { + case SOCK_FLOAT: { + if (clamp_factor) { + static fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{ + "Clamp Mix Float", [](float t, const float a, const float b) { + return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f)); + }}; + return &fn; + } + else { + static fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{ + "Mix Float", [](const float t, const float a, const float b) { + return math::interpolate(a, b, t); + }}; + return &fn; + } + } + case SOCK_VECTOR: { + if (clamp_factor) { + if (uniform_factor) { + static fn::CustomMF_SI_SI_SI_SO<float, float3, float3, float3> fn{ + "Clamp Mix Vector", [](const float t, const float3 a, const float3 b) { + return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f)); + }}; + return &fn; + } + else { + static fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{ + "Clamp Mix Vector Non Uniform", [](float3 t, const float3 a, const float3 b) { + t = math::clamp(t, 0.0f, 1.0f); + return a * (float3(1.0f) - t) + b * t; + }}; + return &fn; + } + } + else { + if (uniform_factor) { + static fn::CustomMF_SI_SI_SI_SO<float, float3, float3, float3> fn{ + "Mix Vector", [](const float t, const float3 a, const float3 b) { + return math::interpolate(a, b, t); + }}; + return &fn; + } + else { + static fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{ + "Mix Vector Non Uniform", [](const float3 t, const float3 a, const float3 b) { + return a * (float3(1.0f) - t) + b * t; + }}; + return &fn; + } + } + } + } + BLI_assert_unreachable(); + return nullptr; +} + +static void sh_node_mix_build_multi_function(NodeMultiFunctionBuilder &builder) +{ + const NodeShaderMix &storage = node_storage(builder.node()); + + if (storage.data_type == SOCK_RGBA) { + builder.construct_and_set_matching_fn<MixColorFunction>( + storage.clamp_factor, storage.clamp_result, storage.blend_type); + } + else { + const fn::MultiFunction *fn = get_multi_function(builder.node()); + builder.set_matching_fn(fn); + } +} + +} // namespace blender::nodes::node_sh_mix_cc + +void register_node_type_sh_mix() +{ + namespace file_ns = blender::nodes::node_sh_mix_cc; + + static bNodeType ntype; + sh_fn_node_type_base(&ntype, SH_NODE_MIX, "Mix", NODE_CLASS_CONVERTER); + ntype.declare = file_ns::sh_node_mix_declare; + ntype.ui_class = file_ns::sh_node_mix_ui_class; + node_type_gpu(&ntype, file_ns::gpu_shader_mix); + node_type_update(&ntype, file_ns::sh_node_mix_update); + node_type_init(&ntype, file_ns::node_mix_init); + node_type_storage( + &ntype, "NodeShaderMix", node_free_standard_storage, node_copy_standard_storage); + ntype.build_multi_function = file_ns::sh_node_mix_build_multi_function; + ntype.draw_buttons = file_ns::sh_node_mix_layout; + ntype.labelfunc = file_ns::sh_node_mix_label; + ntype.gather_link_search_ops = file_ns::node_mix_gather_link_searches; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc index 478a6812c36..46ac8f05803 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc @@ -136,7 +136,7 @@ class MixRGBFunction : public fn::MultiFunction { static void sh_node_mix_rgb_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); + const bNode &node = builder.node(); bool clamp = node.custom2 & SHD_MIXRGB_CLAMP; int mix_type = node.custom1; builder.construct_and_set_matching_fn<MixRGBFunction>(clamp, mix_type); @@ -150,11 +150,11 @@ void register_node_type_sh_mix_rgb() static bNodeType ntype; - sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR); + sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB_LEGACY, "Mix", NODE_CLASS_OP_COLOR); ntype.declare = file_ns::sh_node_mix_rgb_declare; ntype.labelfunc = node_blend_label; node_type_gpu(&ntype, file_ns::gpu_shader_mix_rgb); ntype.build_multi_function = file_ns::sh_node_mix_rgb_build_multi_function; - + ntype.gather_link_search_ops = nullptr; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc b/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc index cad9e1b33f2..a1c51a440d0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.cc @@ -261,7 +261,7 @@ class BrickFunction : public fn::MultiFunction { static void sh_node_brick_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); + const bNode &node = builder.node(); NodeTexBrick *tex = (NodeTexBrick *)node.storage; builder.construct_and_set_matching_fn<BrickFunction>( diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc index 8478cbd406b..37c72ec1f17 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc @@ -139,7 +139,7 @@ class GradientFunction : public fn::MultiFunction { static void sh_node_gradient_tex_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); + const bNode &node = builder.node(); NodeTexGradient *tex = (NodeTexGradient *)node.storage; builder.construct_and_set_matching_fn<GradientFunction>(tex->gradient_type); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc b/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc index 95c4a8b8e46..205d3b89016 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.cc @@ -161,7 +161,7 @@ class MagicFunction : public fn::MultiFunction { static void sh_node_magic_tex_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); + const bNode &node = builder.node(); NodeTexMagic *tex = (NodeTexMagic *)node.storage; builder.construct_and_set_matching_fn<MagicFunction>(tex->depth); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc index c13ce3c3df3..a2241c2327f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc @@ -516,7 +516,7 @@ class MusgraveFunction : public fn::MultiFunction { static void sh_node_musgrave_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); + const bNode &node = builder.node(); NodeTexMusgrave *tex = (NodeTexMusgrave *)node.storage; builder.construct_and_set_matching_fn<MusgraveFunction>(tex->dimensions, tex->musgrave_type); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc index ad24224dc7f..8475101dbaf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.cc @@ -206,7 +206,7 @@ class WaveFunction : public fn::MultiFunction { static void sh_node_wave_tex_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); + const bNode &node = builder.node(); NodeTexWave *tex = (NodeTexWave *)node.storage; builder.construct_and_set_matching_fn<WaveFunction>( tex->wave_type, tex->bands_direction, tex->rings_direction, tex->wave_profile); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc index 6d4c491046b..64075a903ab 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc @@ -176,7 +176,7 @@ class WhiteNoiseFunction : public fn::MultiFunction { static void sh_node_noise_build_multi_function(NodeMultiFunctionBuilder &builder) { - bNode &node = builder.node(); + const bNode &node = builder.node(); builder.construct_and_set_matching_fn<WhiteNoiseFunction>((int)node.custom1); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc index 21f5c44c640..d01e03f9d71 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc @@ -225,7 +225,7 @@ static void node_shader_update_vector_math(bNodeTree *ntree, bNode *node) } } -static const fn::MultiFunction *get_multi_function(bNode &node) +static const fn::MultiFunction *get_multi_function(const bNode &node) { NodeVectorMathOperation operation = NodeVectorMathOperation(node.custom1); diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc index b35f686e331..a036fc52d84 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc @@ -96,7 +96,7 @@ static float3 sh_node_vector_rotate_euler(const float3 &vector, return result + center; } -static const fn::MultiFunction *get_multi_function(bNode &node) +static const fn::MultiFunction *get_multi_function(const bNode &node) { bool invert = node.custom2; const int mode = node.custom1; |