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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/NOD_derived_node_tree.hh172
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh2
-rw-r--r--source/blender/nodes/NOD_multi_function.hh18
-rw-r--r--source/blender/nodes/NOD_node_tree_ref.hh760
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.cc18
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_normal.cc7
-rw-r--r--source/blender/nodes/function/node_function_util.hh2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_align_euler_to_vector.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_boolean_math.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_combine_color.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_compare.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_float_to_int.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_input_bool.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_input_color.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_input_int.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_input_string.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_input_vector.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_rotate_euler.cc2
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.hh2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_points.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc2
-rw-r--r--source/blender/nodes/intern/derived_node_tree.cc139
-rw-r--r--source/blender/nodes/intern/geometry_nodes_eval_log.cc8
-rw-r--r--source/blender/nodes/intern/node_geometry_exec.cc34
-rw-r--r--source/blender/nodes/intern/node_multi_function.cc8
-rw-r--r--source/blender/nodes/intern/node_tree_ref.cc679
-rw-r--r--source/blender/nodes/shader/CMakeLists.txt1
-rw-r--r--source/blender/nodes/shader/node_shader_util.hh2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_color_ramp.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_curves.cc6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mix.cc443
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mix_rgb.cc6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_magic.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_wave.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_white_noise.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc2
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 &params)
}
}
-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 &params)
+{
+ 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 &params) {
+ 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 &params) {
+ 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 &params) {
+ 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 &params) {
+ 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 &params) {
+ 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;