Blender  V2.93
node_tree_ref.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #include "NOD_node_tree_ref.hh"
18 
19 #include "BLI_dot_export.hh"
20 
21 namespace blender::nodes {
22 
23 NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree)
24 {
25  Map<bNode *, NodeRef *> node_mapping;
26 
27  LISTBASE_FOREACH (bNode *, bnode, &btree->nodes) {
28  NodeRef &node = *allocator_.construct<NodeRef>().release();
29 
30  node.tree_ = this;
31  node.bnode_ = bnode;
32  node.id_ = nodes_by_id_.append_and_get_index(&node);
33  RNA_pointer_create(&btree->id, &RNA_Node, bnode, &node.rna_);
34 
35  LISTBASE_FOREACH (bNodeSocket *, bsocket, &bnode->inputs) {
36  InputSocketRef &socket = *allocator_.construct<InputSocketRef>().release();
37  socket.node_ = &node;
38  socket.index_ = node.inputs_.append_and_get_index(&socket);
39  socket.is_input_ = true;
40  socket.bsocket_ = bsocket;
41  socket.id_ = sockets_by_id_.append_and_get_index(&socket);
42  RNA_pointer_create(&btree->id, &RNA_NodeSocket, bsocket, &socket.rna_);
43  }
44 
45  LISTBASE_FOREACH (bNodeSocket *, bsocket, &bnode->outputs) {
46  OutputSocketRef &socket = *allocator_.construct<OutputSocketRef>().release();
47  socket.node_ = &node;
48  socket.index_ = node.outputs_.append_and_get_index(&socket);
49  socket.is_input_ = false;
50  socket.bsocket_ = bsocket;
51  socket.id_ = sockets_by_id_.append_and_get_index(&socket);
52  RNA_pointer_create(&btree->id, &RNA_NodeSocket, bsocket, &socket.rna_);
53  }
54 
55  LISTBASE_FOREACH (bNodeLink *, blink, &bnode->internal_links) {
56  InternalLinkRef &internal_link = *allocator_.construct<InternalLinkRef>().release();
57  internal_link.blink_ = blink;
58  for (InputSocketRef *socket_ref : node.inputs_) {
59  if (socket_ref->bsocket_ == blink->fromsock) {
60  internal_link.from_ = socket_ref;
61  break;
62  }
63  }
64  for (OutputSocketRef *socket_ref : node.outputs_) {
65  if (socket_ref->bsocket_ == blink->tosock) {
66  internal_link.to_ = socket_ref;
67  break;
68  }
69  }
70  node.internal_links_.append(&internal_link);
71  }
72 
73  input_sockets_.extend(node.inputs_.as_span());
74  output_sockets_.extend(node.outputs_.as_span());
75 
76  node_mapping.add_new(bnode, &node);
77  }
78 
79  LISTBASE_FOREACH (bNodeLink *, blink, &btree->links) {
80  OutputSocketRef &from_socket = this->find_output_socket(
81  node_mapping, blink->fromnode, blink->fromsock);
82  InputSocketRef &to_socket = this->find_input_socket(
83  node_mapping, blink->tonode, blink->tosock);
84 
85  LinkRef &link = *allocator_.construct<LinkRef>().release();
86  link.from_ = &from_socket;
87  link.to_ = &to_socket;
88  link.blink_ = blink;
89 
90  links_.append(&link);
91 
92  from_socket.directly_linked_links_.append(&link);
93  to_socket.directly_linked_links_.append(&link);
94  }
95 
96  for (InputSocketRef *input_socket : input_sockets_) {
97  if (input_socket->is_multi_input_socket()) {
98  std::sort(input_socket->directly_linked_links_.begin(),
99  input_socket->directly_linked_links_.end(),
100  [&](const LinkRef *a, const LinkRef *b) -> bool {
101  int index_a = a->blink()->multi_input_socket_index;
102  int index_b = b->blink()->multi_input_socket_index;
103  return index_a > index_b;
104  });
105  }
106  }
107 
108  this->create_linked_socket_caches();
109 
110  for (NodeRef *node : nodes_by_id_) {
111  const bNodeType *nodetype = node->bnode_->typeinfo;
112  nodes_by_type_.add(nodetype, node);
113  }
114 }
115 
117 {
118  /* The destructor has to be called manually, because these types are allocated in a linear
119  * allocator. */
120  for (NodeRef *node : nodes_by_id_) {
121  node->~NodeRef();
122  }
123  for (InputSocketRef *socket : input_sockets_) {
124  socket->~InputSocketRef();
125  }
126  for (OutputSocketRef *socket : output_sockets_) {
127  socket->~OutputSocketRef();
128  }
129  for (LinkRef *link : links_) {
130  link->~LinkRef();
131  }
132 }
133 
134 InputSocketRef &NodeTreeRef::find_input_socket(Map<bNode *, NodeRef *> &node_mapping,
135  bNode *bnode,
136  bNodeSocket *bsocket)
137 {
138  NodeRef *node = node_mapping.lookup(bnode);
139  for (InputSocketRef *socket : node->inputs_) {
140  if (socket->bsocket_ == bsocket) {
141  return *socket;
142  }
143  }
145  return *node->inputs_[0];
146 }
147 
148 OutputSocketRef &NodeTreeRef::find_output_socket(Map<bNode *, NodeRef *> &node_mapping,
149  bNode *bnode,
150  bNodeSocket *bsocket)
151 {
152  NodeRef *node = node_mapping.lookup(bnode);
153  for (OutputSocketRef *socket : node->outputs_) {
154  if (socket->bsocket_ == bsocket) {
155  return *socket;
156  }
157  }
159  return *node->outputs_[0];
160 }
161 
162 void NodeTreeRef::create_linked_socket_caches()
163 {
164  for (InputSocketRef *socket : input_sockets_) {
165  /* Find directly linked socket based on incident links. */
166  Vector<const SocketRef *> directly_linked_sockets;
167  for (LinkRef *link : socket->directly_linked_links_) {
168  directly_linked_sockets.append(link->from_);
169  }
170  socket->directly_linked_sockets_ = allocator_.construct_array_copy(
171  directly_linked_sockets.as_span());
172 
173  /* Find logically linked sockets. */
174  Vector<const SocketRef *> logically_linked_sockets;
175  Vector<const SocketRef *> logically_linked_skipped_sockets;
176  Vector<const InputSocketRef *> handled_sockets;
177  socket->foreach_logical_origin(
178  [&](const OutputSocketRef &origin) { logically_linked_sockets.append(&origin); },
179  [&](const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); },
180  false,
181  handled_sockets);
182  if (logically_linked_sockets == directly_linked_sockets) {
183  socket->logically_linked_sockets_ = socket->directly_linked_sockets_;
184  }
185  else {
186  socket->logically_linked_sockets_ = allocator_.construct_array_copy(
187  logically_linked_sockets.as_span());
188  }
189  socket->logically_linked_skipped_sockets_ = allocator_.construct_array_copy(
190  logically_linked_skipped_sockets.as_span());
191  }
192 
193  for (OutputSocketRef *socket : output_sockets_) {
194  /* Find directly linked socket based on incident links. */
195  Vector<const SocketRef *> directly_linked_sockets;
196  for (LinkRef *link : socket->directly_linked_links_) {
197  directly_linked_sockets.append(link->to_);
198  }
199  socket->directly_linked_sockets_ = allocator_.construct_array_copy(
200  directly_linked_sockets.as_span());
201 
202  /* Find logically linked sockets. */
203  Vector<const SocketRef *> logically_linked_sockets;
204  Vector<const SocketRef *> logically_linked_skipped_sockets;
205  Vector<const OutputSocketRef *> handled_sockets;
206  socket->foreach_logical_target(
207  [&](const InputSocketRef &target) { logically_linked_sockets.append(&target); },
208  [&](const SocketRef &socket) { logically_linked_skipped_sockets.append(&socket); },
209  handled_sockets);
210  if (logically_linked_sockets == directly_linked_sockets) {
211  socket->logically_linked_sockets_ = socket->directly_linked_sockets_;
212  }
213  else {
214  socket->logically_linked_sockets_ = allocator_.construct_array_copy(
215  logically_linked_sockets.as_span());
216  }
217  socket->logically_linked_skipped_sockets_ = allocator_.construct_array_copy(
218  logically_linked_skipped_sockets.as_span());
219  }
220 }
221 
222 void InputSocketRef::foreach_logical_origin(FunctionRef<void(const OutputSocketRef &)> origin_fn,
223  FunctionRef<void(const SocketRef &)> skipped_fn,
224  bool only_follow_first_input_link,
225  Vector<const InputSocketRef *> &handled_sockets) const
226 {
227  /* Protect against loops. */
228  if (handled_sockets.contains(this)) {
229  return;
230  }
231  handled_sockets.append(this);
232 
233  Span<const LinkRef *> links_to_check = this->directly_linked_links();
234  if (only_follow_first_input_link) {
235  links_to_check = links_to_check.take_front(1);
236  }
237  for (const LinkRef *link : links_to_check) {
238  if (link->is_muted()) {
239  continue;
240  }
241  const OutputSocketRef &origin = link->from();
242  const NodeRef &origin_node = origin.node();
243  if (origin_node.is_reroute_node()) {
244  const InputSocketRef &reroute_input = origin_node.input(0);
245  const OutputSocketRef &reroute_output = origin_node.output(0);
246  skipped_fn.call_safe(reroute_input);
247  skipped_fn.call_safe(reroute_output);
248  reroute_input.foreach_logical_origin(origin_fn, skipped_fn, false, handled_sockets);
249  }
250  else if (origin_node.is_muted()) {
251  for (const InternalLinkRef *internal_link : origin_node.internal_links()) {
252  if (&internal_link->to() == &origin) {
253  const InputSocketRef &mute_input = internal_link->from();
254  skipped_fn.call_safe(origin);
255  skipped_fn.call_safe(mute_input);
256  mute_input.foreach_logical_origin(origin_fn, skipped_fn, true, handled_sockets);
257  break;
258  }
259  }
260  }
261  else {
262  origin_fn(origin);
263  }
264  }
265 }
266 
267 void OutputSocketRef::foreach_logical_target(
268  FunctionRef<void(const InputSocketRef &)> target_fn,
269  FunctionRef<void(const SocketRef &)> skipped_fn,
270  Vector<const OutputSocketRef *> &handled_sockets) const
271 {
272  /* Protect against loops. */
273  if (handled_sockets.contains(this)) {
274  return;
275  }
276  handled_sockets.append(this);
277 
278  for (const LinkRef *link : this->directly_linked_links()) {
279  if (link->is_muted()) {
280  continue;
281  }
282  const InputSocketRef &target = link->to();
283  const NodeRef &target_node = target.node();
284  if (target_node.is_reroute_node()) {
285  const OutputSocketRef &reroute_output = target_node.output(0);
286  skipped_fn.call_safe(target);
287  skipped_fn.call_safe(reroute_output);
288  reroute_output.foreach_logical_target(target_fn, skipped_fn, handled_sockets);
289  }
290  else if (target_node.is_muted()) {
291  skipped_fn.call_safe(target);
292  for (const InternalLinkRef *internal_link : target_node.internal_links()) {
293  if (&internal_link->from() == &target) {
294  const OutputSocketRef &mute_output = internal_link->to();
295  skipped_fn.call_safe(target);
296  skipped_fn.call_safe(mute_output);
297  mute_output.foreach_logical_target(target_fn, skipped_fn, handled_sockets);
298  }
299  }
300  }
301  else {
302  target_fn(target);
303  }
304  }
305 }
306 
309  MutableSpan<bool> is_in_stack)
310 {
311  const int node_id = node.id();
312  if (is_in_stack[node_id]) {
313  return true;
314  }
315  if (visited[node_id]) {
316  return false;
317  }
318 
319  visited[node_id] = true;
320  is_in_stack[node_id] = true;
321 
322  for (const OutputSocketRef *from_socket : node.outputs()) {
323  for (const InputSocketRef *to_socket : from_socket->directly_linked_sockets()) {
324  const NodeRef &to_node = to_socket->node();
325  if (has_link_cycles_recursive(to_node, visited, is_in_stack)) {
326  return true;
327  }
328  }
329  }
330 
331  is_in_stack[node_id] = false;
332  return false;
333 }
334 
336 {
337  const int node_amount = nodes_by_id_.size();
338  Array<bool> visited(node_amount, false);
339  Array<bool> is_in_stack(node_amount, false);
340 
341  for (const NodeRef *node : nodes_by_id_) {
342  if (has_link_cycles_recursive(*node, visited, is_in_stack)) {
343  return true;
344  }
345  }
346  return false;
347 }
348 
350 {
351  for (const NodeRef *node : nodes_by_id_) {
352  if (node->is_undefined()) {
353  return true;
354  }
355  }
356  for (const SocketRef *socket : sockets_by_id_) {
357  if (socket->is_undefined()) {
358  return true;
359  }
360  }
361  return false;
362 }
363 
364 std::string NodeTreeRef::to_dot() const
365 {
366  dot::DirectedGraph digraph;
367  digraph.set_rankdir(dot::Attr_rankdir::LeftToRight);
368 
370 
371  for (const NodeRef *node : nodes_by_id_) {
372  dot::Node &dot_node = digraph.new_node("");
373  dot_node.set_background_color("white");
374 
375  Vector<std::string> input_names;
376  Vector<std::string> output_names;
377  for (const InputSocketRef *socket : node->inputs()) {
378  input_names.append(socket->name());
379  }
380  for (const OutputSocketRef *socket : node->outputs()) {
381  output_names.append(socket->name());
382  }
383 
384  dot_nodes.add_new(node,
385  dot::NodeWithSocketsRef(dot_node, node->name(), input_names, output_names));
386  }
387 
388  for (const OutputSocketRef *from_socket : output_sockets_) {
389  for (const InputSocketRef *to_socket : from_socket->directly_linked_sockets()) {
390  dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(&from_socket->node());
391  dot::NodeWithSocketsRef &to_dot_node = dot_nodes.lookup(&to_socket->node());
392 
393  digraph.new_edge(from_dot_node.output(from_socket->index()),
394  to_dot_node.input(to_socket->index()));
395  }
396  }
397 
398  return digraph.to_dot_string();
399 }
400 
402 {
403  return *node_tree_refs.lookup_or_add_cb(&btree,
404  [&]() { return std::make_unique<NodeTreeRef>(&btree); });
405 }
406 
407 } // namespace blender::nodes
#define BLI_assert_unreachable()
Definition: BLI_assert.h:96
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
StructRNA RNA_Node
StructRNA RNA_NodeSocket
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
MutableSpan< T > construct_array_copy(Span< T > src)
destruct_ptr< T > construct(Args &&... args)
const Value & lookup(const Key &key) const
Definition: BLI_map.hh:499
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition: BLI_map.hh:575
void add_new(const Key &key, const Value &value)
Definition: BLI_map.hh:234
void append(const T &value)
Definition: BLI_vector.hh:438
DirectedEdge & new_edge(NodePort from, NodePort to)
Definition: dot_export.cc:51
std::string to_dot_string() const
Definition: dot_export.cc:135
Node & new_node(StringRef label)
Definition: dot_export.cc:26
void set_rankdir(Attr_rankdir rankdir)
NodePort output(int index) const
NodePort input(int index) const
void set_background_color(StringRef name)
Span< const OutputSocketRef * > directly_linked_sockets() const
bool has_undefined_nodes_or_sockets() const
NodeTreeRef(bNodeTree *btree)
std::string to_dot() const
Vector< LinkRef * > directly_linked_links_
Span< const LinkRef * > directly_linked_links() const
OperationNode * node
Set< ComponentNode * > visited
static unsigned a[3]
Definition: RandGen.cpp:92
static bool has_link_cycles_recursive(const NodeRef &node, MutableSpan< bool > visited, MutableSpan< bool > is_in_stack)
const NodeTreeRef & get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree)
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
ListBase nodes
ListBase links
Defines a node type.
Definition: BKE_node.h:221