Blender  V2.93
COM_NodeGraph.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  * Copyright 2013, Blender Foundation.
17  */
18 
19 #include <cstring>
20 
21 #include "BLI_listbase.h"
22 #include "BLI_utildefines.h"
23 
24 #include "DNA_node_types.h"
25 
26 #include "BKE_node.h"
27 
28 #include "COM_CompositorContext.h"
29 #include "COM_Converter.h"
30 #include "COM_Debug.h"
31 #include "COM_Node.h"
32 #include "COM_SocketProxyNode.h"
33 
34 #include "COM_NodeGraph.h" /* own include */
35 
36 namespace blender::compositor {
37 
38 /*******************
39  **** NodeGraph ****
40  *******************/
41 
43 {
44  while (m_nodes.size()) {
45  delete m_nodes.pop_last();
46  }
47 }
48 
50 {
52 }
53 
54 bNodeSocket *NodeGraph::find_b_node_input(bNode *b_node, const char *identifier)
55 {
56  for (bNodeSocket *b_sock = (bNodeSocket *)b_node->inputs.first; b_sock; b_sock = b_sock->next) {
57  if (STREQ(b_sock->identifier, identifier)) {
58  return b_sock;
59  }
60  }
61  return nullptr;
62 }
63 
64 bNodeSocket *NodeGraph::find_b_node_output(bNode *b_node, const char *identifier)
65 {
66  for (bNodeSocket *b_sock = (bNodeSocket *)b_node->outputs.first; b_sock; b_sock = b_sock->next) {
67  if (STREQ(b_sock->identifier, identifier)) {
68  return b_sock;
69  }
70  }
71  return nullptr;
72 }
73 
75  bNodeTree *b_ntree,
76  bNodeInstanceKey key,
77  bool is_active_group)
78 {
79  node->setbNodeTree(b_ntree);
80  node->setInstanceKey(key);
81  node->setIsInActiveGroup(is_active_group);
82 
83  m_nodes.append(node);
84 
86 }
87 
88 void NodeGraph::add_link(NodeOutput *fromSocket, NodeInput *toSocket)
89 {
90  m_links.append(Link(fromSocket, toSocket));
91 
92  /* register with the input */
93  toSocket->setLink(fromSocket);
94 }
95 
97  int nodes_start,
98  bNodeTree *tree,
99  bNodeInstanceKey parent_key)
100 {
101  const bNodeTree *basetree = context.getbNodeTree();
102 
103  /* Update viewers in the active edit-tree as well the base tree (for backdrop). */
104  bool is_active_group = (parent_key.value == basetree->active_viewer_key.value);
105 
106  /* add all nodes of the tree to the node list */
107  for (bNode *node = (bNode *)tree->nodes.first; node; node = node->next) {
108  bNodeInstanceKey key = BKE_node_instance_key(parent_key, tree, node);
109  add_bNode(context, tree, node, key, is_active_group);
110  }
111 
112  NodeRange node_range(m_nodes.begin() + nodes_start, m_nodes.end());
113  /* Add all node-links of the tree to the link list. */
114  for (bNodeLink *nodelink = (bNodeLink *)tree->links.first; nodelink; nodelink = nodelink->next) {
115  add_bNodeLink(node_range, nodelink);
116  }
117 }
118 
120  bNodeTree *b_ntree,
121  bNode *b_node,
122  bNodeInstanceKey key,
123  bool is_active_group)
124 {
125  /* replace muted nodes by proxies for internal links */
126  if (b_node->flag & NODE_MUTED) {
127  add_proxies_mute(b_ntree, b_node, key, is_active_group);
128  return;
129  }
130 
131  /* replace slow nodes with proxies for fast execution */
132  if (context.isFastCalculation() && !COM_bnode_is_fast_node(*b_node)) {
133  add_proxies_skip(b_ntree, b_node, key, is_active_group);
134  return;
135  }
136 
137  /* special node types */
138  if (ELEM(b_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
139  add_proxies_group(context, b_node, key);
140  }
141  else if (b_node->type == NODE_REROUTE) {
142  add_proxies_reroute(b_ntree, b_node, key, is_active_group);
143  }
144  else {
145  /* regular nodes, handled in Converter */
146  Node *node = COM_convert_bnode(b_node);
147  if (node) {
148  add_node(node, b_ntree, key, is_active_group);
149  }
150  }
151 }
152 
154 {
155  for (Vector<Node *>::iterator it = node_range.first; it != node_range.second; ++it) {
156  Node *node = *it;
157  for (NodeOutput *output : node->getOutputSockets()) {
158  if (output->getbNodeSocket() == b_socket) {
159  return output;
160  }
161  }
162  }
163  return nullptr;
164 }
165 
166 void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink)
167 {
169  if (!(b_nodelink->flag & NODE_LINK_VALID)) {
170  return;
171  }
172  if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL) ||
173  (b_nodelink->flag & NODE_LINK_MUTED)) {
174  return;
175  }
176 
177  /* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)
178  * The output then gets linked to each one of them.
179  */
180 
181  NodeOutput *output = find_output(node_range, b_nodelink->fromsock);
182  if (!output) {
183  return;
184  }
185 
186  for (Vector<Node *>::iterator it = node_range.first; it != node_range.second; ++it) {
187  Node *node = *it;
188  for (NodeInput *input : node->getInputSockets()) {
189  if (input->getbNodeSocket() == b_nodelink->tosock && !input->isLinked()) {
190  add_link(output, input);
191  }
192  }
193  }
194 }
195 
196 /* **** Special proxy node type conversions **** */
197 
199  bNode *b_node,
200  bNodeInstanceKey key,
201  bool is_active_group)
202 {
203  for (bNodeLink *b_link = (bNodeLink *)b_node->internal_links.first; b_link;
204  b_link = b_link->next) {
205  SocketProxyNode *proxy = new SocketProxyNode(b_node, b_link->fromsock, b_link->tosock, false);
206  add_node(proxy, b_ntree, key, is_active_group);
207  }
208 }
209 
211  bNode *b_node,
212  bNodeInstanceKey key,
213  bool is_active_group)
214 {
215  for (bNodeSocket *output = (bNodeSocket *)b_node->outputs.first; output; output = output->next) {
216  bNodeSocket *input;
217 
218  /* look for first input with matching datatype for each output */
219  for (input = (bNodeSocket *)b_node->inputs.first; input; input = input->next) {
220  if (input->type == output->type) {
221  break;
222  }
223  }
224 
225  if (input) {
226  SocketProxyNode *proxy = new SocketProxyNode(b_node, input, output, true);
227  add_node(proxy, b_ntree, key, is_active_group);
228  }
229  }
230 }
231 
233 {
234  bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
235  BLI_assert(b_group_tree); /* should have been checked in advance */
236 
237  /* not important for proxies */
239  bool is_active_group = false;
240 
241  for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->outputs.first; b_sock_io;
242  b_sock_io = b_sock_io->next) {
243  bNodeSocket *b_sock_group = find_b_node_input(b_node, b_sock_io->identifier);
244  if (b_sock_group) {
245  SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_group, b_sock_io, true);
246  add_node(proxy, b_group_tree, key, is_active_group);
247  }
248  }
249 }
250 
251 void NodeGraph::add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer)
252 {
253  bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
254  BLI_assert(b_group_tree); /* should have been checked in advance */
255 
256  /* not important for proxies */
258  bool is_active_group = false;
259 
260  for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->inputs.first; b_sock_io;
261  b_sock_io = b_sock_io->next) {
262  bNodeSocket *b_sock_group = find_b_node_output(b_node, b_sock_io->identifier);
263  if (b_sock_group) {
264  if (use_buffer) {
265  SocketBufferNode *buffer = new SocketBufferNode(b_node_io, b_sock_io, b_sock_group);
266  add_node(buffer, b_group_tree, key, is_active_group);
267  }
268  else {
269  SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_io, b_sock_group, true);
270  add_node(proxy, b_group_tree, key, is_active_group);
271  }
272  }
273  }
274 }
275 
277  bNode *b_node,
278  bNodeInstanceKey key)
279 {
280  bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
281 
282  /* missing node group datablock can happen with library linking */
283  if (!b_group_tree) {
284  /* This error case its handled in convertToOperations()
285  * so we don't get un-converted sockets. */
286  return;
287  }
288 
289  /* use node list size before adding proxies, so they can be connected in add_bNodeTree */
290  int nodes_start = m_nodes.size();
291 
292  /* create proxy nodes for group input/output nodes */
293  for (bNode *b_node_io = (bNode *)b_group_tree->nodes.first; b_node_io;
294  b_node_io = b_node_io->next) {
295  if (b_node_io->type == NODE_GROUP_INPUT) {
296  add_proxies_group_inputs(b_node, b_node_io);
297  }
298 
299  if (b_node_io->type == NODE_GROUP_OUTPUT && (b_node_io->flag & NODE_DO_OUTPUT)) {
300  add_proxies_group_outputs(b_node, b_node_io, context.isGroupnodeBufferEnabled());
301  }
302  }
303 
304  add_bNodeTree(context, nodes_start, b_group_tree, key);
305 }
306 
308  bNode *b_node,
309  bNodeInstanceKey key,
310  bool is_active_group)
311 {
312  SocketProxyNode *proxy = new SocketProxyNode(
313  b_node, (bNodeSocket *)b_node->inputs.first, (bNodeSocket *)b_node->outputs.first, false);
314  add_node(proxy, b_ntree, key, is_active_group);
315 }
316 
317 } // namespace blender::compositor
#define NODE_REROUTE
Definition: BKE_node.h:873
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE
Definition: node.cc:3908
#define NODE_CUSTOM_GROUP
Definition: BKE_node.h:876
#define NODE_GROUP_INPUT
Definition: BKE_node.h:874
bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, const struct bNodeTree *ntree, const struct bNode *node)
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define ELEM(...)
#define STREQ(a, b)
struct Link Link
#define NODE_LINK_VALID
#define NODE_DO_OUTPUT
#define NODE_MUTED
@ SOCK_UNAVAIL
#define NODE_LINK_MUTED
NODE_GROUP_OUTPUT
NODE_GROUP
#define output
Overall context of the compositor.
static void node_added(const Node *node)
Definition: COM_Debug.cc:478
static bNodeSocket * find_b_node_input(bNode *b_node, const char *identifier)
void add_bNodeTree(const CompositorContext &context, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key)
void add_bNode(const CompositorContext &context, bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
std::pair< Vector< Node * >::iterator, Vector< Node * >::iterator > NodeRange
Definition: COM_NodeGraph.h:73
void from_bNodeTree(const CompositorContext &context, bNodeTree *tree)
void add_proxies_group_inputs(bNode *b_node, bNode *b_node_io)
void add_link(NodeOutput *fromSocket, NodeInput *toSocket)
void add_proxies_reroute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
void add_proxies_skip(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
NodeOutput * find_output(const NodeRange &node_range, bNodeSocket *b_socket)
void add_proxies_mute(bNodeTree *b_ntree, bNode *b_node, bNodeInstanceKey key, bool is_active_group)
static bNodeSocket * find_b_node_output(bNode *b_node, const char *identifier)
void add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink)
void add_proxies_group(const CompositorContext &context, bNode *b_node, bNodeInstanceKey key)
void add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer)
void add_node(Node *node, bNodeTree *b_ntree, bNodeInstanceKey key, bool is_active_group)
NodeInput are sockets that can receive data/input.
Definition: COM_Node.h:210
void setLink(NodeOutput *link)
Definition: COM_Node.cc:154
NodeOutput are sockets that can send data/input.
Definition: COM_Node.h:258
OperationNode * node
void * tree
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
Node * COM_convert_bnode(bNode *b_node)
Wraps a bNode in its Node instance.
bool COM_bnode_is_fast_node(const bNode &b_node)
True if the node is considered 'fast'.
void * first
Definition: DNA_listBase.h:47
Definition: node.h:98
unsigned int value
struct bNodeSocket * next
ListBase nodes
bNodeInstanceKey active_viewer_key
ListBase inputs
struct ID * id
ListBase internal_links
short type
ListBase outputs