Blender V4.3
graph/node.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#include <type_traits>
8
9#include "graph/node_type.h"
10
11#include "util/array.h"
12#include "util/map.h"
13#include "util/param.h"
14
16
17class MD5Hash;
18struct Node;
19struct NodeType;
20struct Transform;
21
22/* NOTE: in the following macros we use "type const &" instead of "const type &"
23 * to avoid issues when pasting a pointer type. */
24#define NODE_SOCKET_API_BASE_METHODS(type_, name, string_name) \
25 const SocketType *get_##name##_socket() const \
26 { \
27 /* Explicitly cast to base class to use `Node::type` even if the derived class defines \
28 * `type`. */ \
29 const Node *self_node = this; \
30 static const SocketType *socket = self_node->type->find_input(ustring(string_name)); \
31 return socket; \
32 } \
33 bool name##_is_modified() const \
34 { \
35 const SocketType *socket = get_##name##_socket(); \
36 return socket_is_modified(*socket); \
37 } \
38 void tag_##name##_modified() \
39 { \
40 const SocketType *socket = get_##name##_socket(); \
41 socket_modified |= socket->modified_flag_bit; \
42 } \
43 type_ const &get_##name() const \
44 { \
45 const SocketType *socket = get_##name##_socket(); \
46 return get_socket_value<type_>(this, *socket); \
47 }
49#define NODE_SOCKET_API_BASE(type_, name, string_name) \
50 protected: \
51 type_ name; \
52\
53 public: \
54 NODE_SOCKET_API_BASE_METHODS(type_, name, string_name)
56#define NODE_SOCKET_API(type_, name) \
57 NODE_SOCKET_API_BASE(type_, name, #name) \
58 void set_##name(type_ value) \
59 { \
60 const SocketType *socket = get_##name##_socket(); \
61 this->set(*socket, value); \
62 }
64#define NODE_SOCKET_API_ARRAY(type_, name) \
65 NODE_SOCKET_API_BASE(type_, name, #name) \
66 void set_##name(type_ &value) \
67 { \
68 const SocketType *socket = get_##name##_socket(); \
69 this->set(*socket, value); \
70 } \
71 type_ &get_##name() \
72 { \
73 const SocketType *socket = get_##name##_socket(); \
74 return get_socket_value<type_>(this, *socket); \
75 }
77#define NODE_SOCKET_API_STRUCT_MEMBER(type_, name, member) \
78 NODE_SOCKET_API_BASE_METHODS(type_, name##_##member, #name "." #member) \
79 void set_##name##_##member(type_ value) \
80 { \
81 const SocketType *socket = get_##name##_##member##_socket(); \
82 this->set(*socket, value); \
83 }
84
85/* Node */
87struct NodeOwner {
88 virtual ~NodeOwner();
89};
91struct Node {
92 explicit Node(const NodeType *type, ustring name = ustring());
93 virtual ~Node() = 0;
94
95 /* set values */
96 void set(const SocketType &input, bool value);
97 void set(const SocketType &input, int value);
98 void set(const SocketType &input, uint value);
99 void set(const SocketType &input, uint64_t value);
100 void set(const SocketType &input, float value);
101 void set(const SocketType &input, float2 value);
102 void set(const SocketType &input, float3 value);
103 void set(const SocketType &input, const char *value);
104 void set(const SocketType &input, ustring value);
105 void set(const SocketType &input, const Transform &value);
106 void set(const SocketType &input, Node *value);
107
108 /* Implicitly cast enums and enum classes to integer, which matches an internal way of how
109 * enumerator values are stored and accessed in a generic API. */
110 template<class ValueType, std::enable_if_t<std::is_enum_v<ValueType>, bool> = true>
111 void set(const SocketType &input, const ValueType &value)
112 {
113 static_assert(sizeof(ValueType) <= sizeof(int), "Enumerator type should fit int");
114 set(input, static_cast<int>(value));
115 }
116
117 /* set array values. the memory from the input array will taken over
118 * by the node and the input array will be empty after return */
119 void set(const SocketType &input, array<bool> &value);
120 void set(const SocketType &input, array<int> &value);
121 void set(const SocketType &input, array<float> &value);
122 void set(const SocketType &input, array<float2> &value);
123 void set(const SocketType &input, array<float3> &value);
124 void set(const SocketType &input, array<ustring> &value);
125 void set(const SocketType &input, array<Transform> &value);
126 void set(const SocketType &input, array<Node *> &value);
127
128 /* get values */
129 bool get_bool(const SocketType &input) const;
130 int get_int(const SocketType &input) const;
131 uint get_uint(const SocketType &input) const;
132 uint64_t get_uint64(const SocketType &input) const;
133 float get_float(const SocketType &input) const;
134 float2 get_float2(const SocketType &input) const;
135 float3 get_float3(const SocketType &input) const;
136 ustring get_string(const SocketType &input) const;
137 Transform get_transform(const SocketType &input) const;
138 Node *get_node(const SocketType &input) const;
139
140 /* get array values */
141 const array<bool> &get_bool_array(const SocketType &input) const;
142 const array<int> &get_int_array(const SocketType &input) const;
143 const array<float> &get_float_array(const SocketType &input) const;
144 const array<float2> &get_float2_array(const SocketType &input) const;
145 const array<float3> &get_float3_array(const SocketType &input) const;
146 const array<ustring> &get_string_array(const SocketType &input) const;
147 const array<Transform> &get_transform_array(const SocketType &input) const;
148 const array<Node *> &get_node_array(const SocketType &input) const;
149
150 /* generic values operations */
151 bool has_default_value(const SocketType &input) const;
152 void set_default_value(const SocketType &input);
153 bool equals_value(const Node &other, const SocketType &input) const;
154 void copy_value(const SocketType &input, const Node &other, const SocketType &other_input);
155 void set_value(const SocketType &input, const Node &other, const SocketType &other_input);
156
157 /* equals */
158 bool equals(const Node &other) const;
159
160 /* compute hash of node and its socket values */
161 void hash(MD5Hash &md5);
162
163 /* Get total size of this node. */
164 size_t get_total_size_in_bytes() const;
165
166 /* Type testing, taking into account base classes. */
167 bool is_a(const NodeType *type);
168
169 bool socket_is_modified(const SocketType &input) const;
170
171 bool is_modified() const;
172
173 void tag_modified();
174 void clear_modified();
175
176 void print_modified_sockets() const;
178 ustring name;
179 const NodeType *type;
180
181 const NodeOwner *get_owner() const;
182 void set_owner(const NodeOwner *owner_);
184 int reference_count() const
185 {
186 return ref_count;
187 }
189 void reference()
190 {
191 ref_count += 1;
192 }
194 void dereference()
195 {
196 ref_count -= 1;
197 }
198
199 /* Set the reference count to zero. This should only be called when we know for sure that the
200 * Node is not used by anyone else. For now, this is only the case when "deleting" shaders, as
201 * they are never actually deleted. */
203 {
204 ref_count = 0;
205 }
206
207 protected:
209 int ref_count{0};
211 template<typename T> static T &get_socket_value(const Node *node, const SocketType &socket)
212 {
213 return (T &)*(((char *)node) + socket.struct_offset);
214 }
217
218 template<typename T> void set_if_different(const SocketType &input, T value);
219
220 /* Explicit overload for Node sockets so we can handle reference counting. The old Node is
221 * dereferenced, and the new one is referenced. */
222 void set_if_different(const SocketType &input, Node *value);
223
224 template<typename T> void set_if_different(const SocketType &input, array<T> &value);
225
226 /* Explicit overload for Node sockets so we can handle reference counting. The old Nodes are
227 * dereferenced, and the new ones are referenced. */
228 void set_if_different(const SocketType &input, array<Node *> &value);
229
230 /* Call this function in derived classes' destructors to ensure that used Nodes are dereferenced
231 * properly. */
233};
234
unsigned int uint
Definition md5.h:21
#define CCL_NAMESPACE_END
uint64_t SocketModifiedFlags
Definition node_type.h:19
#define hash
Definition noise.c:154
unsigned __int64 uint64_t
Definition stdint.h:90
virtual ~NodeOwner()
bool has_default_value(const SocketType &input) const
const array< float3 > & get_float3_array(const SocketType &input) const
bool equals(const Node &other) const
const array< float > & get_float_array(const SocketType &input) const
const array< int > & get_int_array(const SocketType &input) const
void dereference()
Definition graph/node.h:193
const NodeOwner * owner
Definition graph/node.h:207
float get_float(const SocketType &input) const
Transform get_transform(const SocketType &input) const
void set(const SocketType &input, bool value)
uint64_t get_uint64(const SocketType &input) const
const NodeType * type
Definition graph/node.h:178
void set_value(const SocketType &input, const Node &other, const SocketType &other_input)
void dereference_all_used_nodes()
float3 get_float3(const SocketType &input) const
int ref_count
Definition graph/node.h:208
void set_default_value(const SocketType &input)
static T & get_socket_value(const Node *node, const SocketType &socket)
Definition graph/node.h:210
const array< bool > & get_bool_array(const SocketType &input) const
void copy_value(const SocketType &input, const Node &other, const SocketType &other_input)
const array< Node * > & get_node_array(const SocketType &input) const
ustring name
Definition graph/node.h:177
size_t get_total_size_in_bytes() const
SocketModifiedFlags socket_modified
Definition graph/node.h:215
bool get_bool(const SocketType &input) const
int reference_count() const
Definition graph/node.h:183
float2 get_float2(const SocketType &input) const
void clear_modified()
void reference()
Definition graph/node.h:188
const array< ustring > & get_string_array(const SocketType &input) const
const array< float2 > & get_float2_array(const SocketType &input) const
bool socket_is_modified(const SocketType &input) const
ustring get_string(const SocketType &input) const
bool is_a(const NodeType *type)
void set_if_different(const SocketType &input, T value)
Node * get_node(const SocketType &input) const
virtual ~Node()=0
const NodeOwner * get_owner() const
void tag_modified()
bool is_modified() const
uint get_uint(const SocketType &input) const
Node(const NodeType *type, ustring name=ustring())
int get_int(const SocketType &input) const
const array< Transform > & get_transform_array(const SocketType &input) const
void clear_reference_count()
Definition graph/node.h:201
bool equals_value(const Node &other, const SocketType &input) const
void print_modified_sockets() const
void set_owner(const NodeOwner *owner_)
int struct_offset
Definition node_type.h:81