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 /*******************
37  **** NodeGraph ****
38  *******************/
39 
NodeGraph()40 NodeGraph::NodeGraph()
41 {
42 }
43 
~NodeGraph()44 NodeGraph::~NodeGraph()
45 {
46   for (int index = 0; index < this->m_nodes.size(); index++) {
47     Node *node = this->m_nodes[index];
48     delete node;
49   }
50 }
51 
from_bNodeTree(const CompositorContext & context,bNodeTree * tree)52 void NodeGraph::from_bNodeTree(const CompositorContext &context, bNodeTree *tree)
53 {
54   add_bNodeTree(context, 0, tree, NODE_INSTANCE_KEY_BASE);
55 }
56 
find_b_node_input(bNode * b_node,const char * identifier)57 bNodeSocket *NodeGraph::find_b_node_input(bNode *b_node, const char *identifier)
58 {
59   for (bNodeSocket *b_sock = (bNodeSocket *)b_node->inputs.first; b_sock; b_sock = b_sock->next) {
60     if (STREQ(b_sock->identifier, identifier)) {
61       return b_sock;
62     }
63   }
64   return NULL;
65 }
66 
find_b_node_output(bNode * b_node,const char * identifier)67 bNodeSocket *NodeGraph::find_b_node_output(bNode *b_node, const char *identifier)
68 {
69   for (bNodeSocket *b_sock = (bNodeSocket *)b_node->outputs.first; b_sock; b_sock = b_sock->next) {
70     if (STREQ(b_sock->identifier, identifier)) {
71       return b_sock;
72     }
73   }
74   return NULL;
75 }
76 
add_node(Node * node,bNodeTree * b_ntree,bNodeInstanceKey key,bool is_active_group)77 void NodeGraph::add_node(Node *node,
78                          bNodeTree *b_ntree,
79                          bNodeInstanceKey key,
80                          bool is_active_group)
81 {
82   node->setbNodeTree(b_ntree);
83   node->setInstanceKey(key);
84   node->setIsInActiveGroup(is_active_group);
85 
86   m_nodes.push_back(node);
87 
88   DebugInfo::node_added(node);
89 }
90 
add_link(NodeOutput * fromSocket,NodeInput * toSocket)91 void NodeGraph::add_link(NodeOutput *fromSocket, NodeInput *toSocket)
92 {
93   m_links.push_back(Link(fromSocket, toSocket));
94 
95   /* register with the input */
96   toSocket->setLink(fromSocket);
97 }
98 
add_bNodeTree(const CompositorContext & context,int nodes_start,bNodeTree * tree,bNodeInstanceKey parent_key)99 void NodeGraph::add_bNodeTree(const CompositorContext &context,
100                               int nodes_start,
101                               bNodeTree *tree,
102                               bNodeInstanceKey parent_key)
103 {
104   const bNodeTree *basetree = context.getbNodeTree();
105 
106   /* update viewers in the active edittree as well the base tree (for backdrop) */
107   bool is_active_group = (parent_key.value == basetree->active_viewer_key.value);
108 
109   /* add all nodes of the tree to the node list */
110   for (bNode *node = (bNode *)tree->nodes.first; node; node = node->next) {
111     bNodeInstanceKey key = BKE_node_instance_key(parent_key, tree, node);
112     add_bNode(context, tree, node, key, is_active_group);
113   }
114 
115   NodeRange node_range(m_nodes.begin() + nodes_start, m_nodes.end());
116   /* add all nodelinks of the tree to the link list */
117   for (bNodeLink *nodelink = (bNodeLink *)tree->links.first; nodelink; nodelink = nodelink->next) {
118     add_bNodeLink(node_range, nodelink);
119   }
120 }
121 
add_bNode(const CompositorContext & context,bNodeTree * b_ntree,bNode * b_node,bNodeInstanceKey key,bool is_active_group)122 void NodeGraph::add_bNode(const CompositorContext &context,
123                           bNodeTree *b_ntree,
124                           bNode *b_node,
125                           bNodeInstanceKey key,
126                           bool is_active_group)
127 {
128   /* replace muted nodes by proxies for internal links */
129   if (b_node->flag & NODE_MUTED) {
130     add_proxies_mute(b_ntree, b_node, key, is_active_group);
131     return;
132   }
133 
134   /* replace slow nodes with proxies for fast execution */
135   if (context.isFastCalculation() && !Converter::is_fast_node(b_node)) {
136     add_proxies_skip(b_ntree, b_node, key, is_active_group);
137     return;
138   }
139 
140   /* special node types */
141   if (ELEM(b_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
142     add_proxies_group(context, b_node, key);
143   }
144   else if (b_node->type == NODE_REROUTE) {
145     add_proxies_reroute(b_ntree, b_node, key, is_active_group);
146   }
147   else {
148     /* regular nodes, handled in Converter */
149     Node *node = Converter::convert(b_node);
150     if (node) {
151       add_node(node, b_ntree, key, is_active_group);
152     }
153   }
154 }
155 
find_inputs(const NodeRange & node_range,bNodeSocket * b_socket)156 NodeGraph::NodeInputs NodeGraph::find_inputs(const NodeRange &node_range, bNodeSocket *b_socket)
157 {
158   NodeInputs result;
159   for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
160     Node *node = *it;
161     for (int index = 0; index < node->getNumberOfInputSockets(); index++) {
162       NodeInput *input = node->getInputSocket(index);
163       if (input->getbNodeSocket() == b_socket) {
164         result.push_back(input);
165       }
166     }
167   }
168   return result;
169 }
170 
find_output(const NodeRange & node_range,bNodeSocket * b_socket)171 NodeOutput *NodeGraph::find_output(const NodeRange &node_range, bNodeSocket *b_socket)
172 {
173   for (NodeGraph::NodeIterator it = node_range.first; it != node_range.second; ++it) {
174     Node *node = *it;
175     for (int index = 0; index < node->getNumberOfOutputSockets(); index++) {
176       NodeOutput *output = node->getOutputSocket(index);
177       if (output->getbNodeSocket() == b_socket) {
178         return output;
179       }
180     }
181   }
182   return NULL;
183 }
184 
add_bNodeLink(const NodeRange & node_range,bNodeLink * b_nodelink)185 void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink)
186 {
187   /** \note Ignore invalid links. */
188   if (!(b_nodelink->flag & NODE_LINK_VALID)) {
189     return;
190   }
191   if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL)) {
192     return;
193   }
194 
195   /* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)
196    * The output then gets linked to each one of them.
197    */
198 
199   NodeOutput *output = find_output(node_range, b_nodelink->fromsock);
200   if (!output) {
201     return;
202   }
203 
204   NodeInputs inputs = find_inputs(node_range, b_nodelink->tosock);
205   for (NodeInputs::const_iterator it = inputs.begin(); it != inputs.end(); ++it) {
206     NodeInput *input = *it;
207     if (input->isLinked()) {
208       continue;
209     }
210     add_link(output, input);
211   }
212 }
213 
214 /* **** Special proxy node type conversions **** */
215 
add_proxies_mute(bNodeTree * b_ntree,bNode * b_node,bNodeInstanceKey key,bool is_active_group)216 void NodeGraph::add_proxies_mute(bNodeTree *b_ntree,
217                                  bNode *b_node,
218                                  bNodeInstanceKey key,
219                                  bool is_active_group)
220 {
221   for (bNodeLink *b_link = (bNodeLink *)b_node->internal_links.first; b_link;
222        b_link = b_link->next) {
223     SocketProxyNode *proxy = new SocketProxyNode(b_node, b_link->fromsock, b_link->tosock, false);
224     add_node(proxy, b_ntree, key, is_active_group);
225   }
226 }
227 
add_proxies_skip(bNodeTree * b_ntree,bNode * b_node,bNodeInstanceKey key,bool is_active_group)228 void NodeGraph::add_proxies_skip(bNodeTree *b_ntree,
229                                  bNode *b_node,
230                                  bNodeInstanceKey key,
231                                  bool is_active_group)
232 {
233   for (bNodeSocket *output = (bNodeSocket *)b_node->outputs.first; output; output = output->next) {
234     bNodeSocket *input;
235 
236     /* look for first input with matching datatype for each output */
237     for (input = (bNodeSocket *)b_node->inputs.first; input; input = input->next) {
238       if (input->type == output->type) {
239         break;
240       }
241     }
242 
243     if (input) {
244       SocketProxyNode *proxy = new SocketProxyNode(b_node, input, output, true);
245       add_node(proxy, b_ntree, key, is_active_group);
246     }
247   }
248 }
249 
add_proxies_group_inputs(bNode * b_node,bNode * b_node_io)250 void NodeGraph::add_proxies_group_inputs(bNode *b_node, bNode *b_node_io)
251 {
252   bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
253   BLI_assert(b_group_tree); /* should have been checked in advance */
254 
255   /* not important for proxies */
256   bNodeInstanceKey key = NODE_INSTANCE_KEY_BASE;
257   bool is_active_group = false;
258 
259   for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->outputs.first; b_sock_io;
260        b_sock_io = b_sock_io->next) {
261     bNodeSocket *b_sock_group = find_b_node_input(b_node, b_sock_io->identifier);
262     if (b_sock_group) {
263       SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_group, b_sock_io, true);
264       add_node(proxy, b_group_tree, key, is_active_group);
265     }
266   }
267 }
268 
add_proxies_group_outputs(bNode * b_node,bNode * b_node_io,bool use_buffer)269 void NodeGraph::add_proxies_group_outputs(bNode *b_node, bNode *b_node_io, bool use_buffer)
270 {
271   bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
272   BLI_assert(b_group_tree); /* should have been checked in advance */
273 
274   /* not important for proxies */
275   bNodeInstanceKey key = NODE_INSTANCE_KEY_BASE;
276   bool is_active_group = false;
277 
278   for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->inputs.first; b_sock_io;
279        b_sock_io = b_sock_io->next) {
280     bNodeSocket *b_sock_group = find_b_node_output(b_node, b_sock_io->identifier);
281     if (b_sock_group) {
282       if (use_buffer) {
283         SocketBufferNode *buffer = new SocketBufferNode(b_node_io, b_sock_io, b_sock_group);
284         add_node(buffer, b_group_tree, key, is_active_group);
285       }
286       else {
287         SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_io, b_sock_group, true);
288         add_node(proxy, b_group_tree, key, is_active_group);
289       }
290     }
291   }
292 }
293 
add_proxies_group(const CompositorContext & context,bNode * b_node,bNodeInstanceKey key)294 void NodeGraph::add_proxies_group(const CompositorContext &context,
295                                   bNode *b_node,
296                                   bNodeInstanceKey key)
297 {
298   bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
299 
300   /* missing node group datablock can happen with library linking */
301   if (!b_group_tree) {
302     /* This error case its handled in convertToOperations()
303      * so we don't get un-converted sockets. */
304     return;
305   }
306 
307   /* use node list size before adding proxies, so they can be connected in add_bNodeTree */
308   int nodes_start = m_nodes.size();
309 
310   /* create proxy nodes for group input/output nodes */
311   for (bNode *b_node_io = (bNode *)b_group_tree->nodes.first; b_node_io;
312        b_node_io = b_node_io->next) {
313     if (b_node_io->type == NODE_GROUP_INPUT) {
314       add_proxies_group_inputs(b_node, b_node_io);
315     }
316 
317     if (b_node_io->type == NODE_GROUP_OUTPUT && (b_node_io->flag & NODE_DO_OUTPUT)) {
318       add_proxies_group_outputs(b_node, b_node_io, context.isGroupnodeBufferEnabled());
319     }
320   }
321 
322   add_bNodeTree(context, nodes_start, b_group_tree, key);
323 }
324 
add_proxies_reroute(bNodeTree * b_ntree,bNode * b_node,bNodeInstanceKey key,bool is_active_group)325 void NodeGraph::add_proxies_reroute(bNodeTree *b_ntree,
326                                     bNode *b_node,
327                                     bNodeInstanceKey key,
328                                     bool is_active_group)
329 {
330   SocketProxyNode *proxy = new SocketProxyNode(
331       b_node, (bNodeSocket *)b_node->inputs.first, (bNodeSocket *)b_node->outputs.first, false);
332   add_node(proxy, b_ntree, key, is_active_group);
333 }
334