Blender V4.3
COM_NodeGraph.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <cstring>
6
7#include "DNA_node_types.h"
8
9#include "BKE_node.hh"
10#include "BKE_node_runtime.hh"
11
12#include "COM_Converter.h"
13#include "COM_Debug.h"
14#include "COM_SocketProxyNode.h"
15
16#include "COM_NodeGraph.h" /* own include */
17
18namespace blender::compositor {
19
20/*******************
21 **** NodeGraph ****
22 *******************/
23
25{
26 while (nodes_.size()) {
27 delete nodes_.pop_last();
28 }
29}
30
35
36bNodeSocket *NodeGraph::find_b_node_input(bNode *b_node, const char *identifier)
37{
38 for (bNodeSocket *b_sock = (bNodeSocket *)b_node->inputs.first; b_sock; b_sock = b_sock->next) {
39 if (STREQ(b_sock->identifier, identifier)) {
40 return b_sock;
41 }
42 }
43 return nullptr;
44}
45
46bNodeSocket *NodeGraph::find_b_node_output(bNode *b_node, const char *identifier)
47{
48 for (bNodeSocket *b_sock = (bNodeSocket *)b_node->outputs.first; b_sock; b_sock = b_sock->next) {
49 if (STREQ(b_sock->identifier, identifier)) {
50 return b_sock;
51 }
52 }
53 return nullptr;
54}
55
57 bNodeTree *b_ntree,
59 bool is_active_group)
60{
61 node->set_bnodetree(b_ntree);
62 node->set_instance_key(key);
63 node->set_is_in_active_group(is_active_group);
64
65 nodes_.append(node);
66
68}
69
70void NodeGraph::add_link(NodeOutput *from_socket, NodeInput *to_socket)
71{
72 links_.append(Link(from_socket, to_socket));
73
74 /* register with the input */
75 to_socket->set_link(from_socket);
76}
77
79 int nodes_start,
81 bNodeInstanceKey parent_key)
82{
83 const bNodeTree *basetree = context.get_bnodetree();
84
85 /* Update viewers in the active edit-tree as well the base tree (for backdrop). */
86 bool is_active_group = (parent_key.value == basetree->active_viewer_key.value);
87
88 /* add all nodes of the tree to the node list */
89 for (bNode *node = (bNode *)tree->nodes.first; node; node = node->next) {
90 bNodeInstanceKey key = bke::node_instance_key(parent_key, tree, node);
91 add_bNode(context, tree, node, key, is_active_group);
92 }
93
94 NodeRange node_range(nodes_.begin() + nodes_start, nodes_.end());
95 /* Add all node-links of the tree to the link list. */
96 for (bNodeLink *nodelink = (bNodeLink *)tree->links.first; nodelink; nodelink = nodelink->next) {
97 add_bNodeLink(node_range, nodelink);
98 }
99}
100
102 bNodeTree *b_ntree,
103 bNode *b_node,
105 bool is_active_group)
106{
107 /* replace muted nodes by proxies for internal links */
108 if (b_node->flag & NODE_MUTED) {
109 add_proxies_mute(b_ntree, b_node, key, is_active_group);
110 return;
111 }
112
113 /* special node types */
114 if (ELEM(b_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
115 add_proxies_group(context, b_node, key);
116 }
117 else if (b_node->type == NODE_REROUTE) {
118 add_proxies_reroute(b_ntree, b_node, key, is_active_group);
119 }
120 else {
121 /* regular nodes, handled in Converter */
122 Node *node = COM_convert_bnode(b_node);
123 if (node) {
124 add_node(node, b_ntree, key, is_active_group);
125 }
126 }
127}
128
130{
131 for (Vector<Node *>::iterator it = node_range.first; it != node_range.second; ++it) {
132 Node *node = *it;
133 for (NodeOutput *output : node->get_output_sockets()) {
134 if (output->get_bnode_socket() == b_socket) {
135 return output;
136 }
137 }
138 }
139 return nullptr;
140}
141
142void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink)
143{
145 if (!(b_nodelink->flag & NODE_LINK_VALID)) {
146 return;
147 }
148 if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL) ||
149 (b_nodelink->flag & NODE_LINK_MUTED))
150 {
151 return;
152 }
153
154 /* NOTE: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies)
155 * The output then gets linked to each one of them.
156 */
157
158 NodeOutput *output = find_output(node_range, b_nodelink->fromsock);
159 if (!output) {
160 return;
161 }
162
163 for (Vector<Node *>::iterator it = node_range.first; it != node_range.second; ++it) {
164 Node *node = *it;
165 for (NodeInput *input : node->get_input_sockets()) {
166 if (input->get_bnode_socket() == b_nodelink->tosock && !input->is_linked()) {
167 add_link(output, input);
168 }
169 }
170 }
171}
172
173/* **** Special proxy node type conversions **** */
174
176 bNode *b_node,
178 bool is_active_group)
179{
180 for (const bNodeLink &b_link : b_node->internal_links()) {
181 SocketProxyNode *proxy = new SocketProxyNode(b_node, b_link.fromsock, b_link.tosock, false);
182 add_node(proxy, b_ntree, key, is_active_group);
183 }
184}
185
187 bNode *b_node,
189 bool is_active_group)
190{
191 for (bNodeSocket *output = (bNodeSocket *)b_node->outputs.first; output; output = output->next) {
192 bNodeSocket *input;
193
194 /* look for first input with matching datatype for each output */
195 for (input = (bNodeSocket *)b_node->inputs.first; input; input = input->next) {
196 if (input->type == output->type) {
197 break;
198 }
199 }
200
201 if (input) {
202 SocketProxyNode *proxy = new SocketProxyNode(b_node, input, output, true);
203 add_node(proxy, b_ntree, key, is_active_group);
204 }
205 }
206}
207
209{
210 bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
211 BLI_assert(b_group_tree); /* should have been checked in advance */
212
213 /* not important for proxies */
215 bool is_active_group = false;
216
217 for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->outputs.first; b_sock_io;
218 b_sock_io = b_sock_io->next)
219 {
220 bNodeSocket *b_sock_group = find_b_node_input(b_node, b_sock_io->identifier);
221 if (b_sock_group) {
222 SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_group, b_sock_io, true);
223 add_node(proxy, b_group_tree, key, is_active_group);
224 }
225 }
226}
227
229 bNode *b_node,
230 bNode *b_node_io)
231{
232 bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
233 BLI_assert(b_group_tree); /* should have been checked in advance */
234
235 /* not important for proxies */
237 bool is_active_group = false;
238
239 for (bNodeSocket *b_sock_io = (bNodeSocket *)b_node_io->inputs.first; b_sock_io;
240 b_sock_io = b_sock_io->next)
241 {
242 bNodeSocket *b_sock_group = find_b_node_output(b_node, b_sock_io->identifier);
243 if (b_sock_group) {
244 SocketProxyNode *proxy = new SocketProxyNode(b_node_io, b_sock_io, b_sock_group, true);
245 add_node(proxy, b_group_tree, key, is_active_group);
246 }
247 }
248}
249
251 bNode *b_node,
253{
254 bNodeTree *b_group_tree = (bNodeTree *)b_node->id;
255
256 /* missing node group datablock can happen with library linking */
257 if (!b_group_tree) {
258 /* This error case its handled in convert_to_operations()
259 * so we don't get un-converted sockets. */
260 return;
261 }
262
263 /* use node list size before adding proxies, so they can be connected in add_bNodeTree */
264 int nodes_start = nodes_.size();
265
266 /* create proxy nodes for group input/output nodes */
267 for (bNode *b_node_io = (bNode *)b_group_tree->nodes.first; b_node_io;
268 b_node_io = b_node_io->next)
269 {
270 if (b_node_io->type == NODE_GROUP_INPUT) {
271 add_proxies_group_inputs(b_node, b_node_io);
272 }
273
274 if (b_node_io->type == NODE_GROUP_OUTPUT && (b_node_io->flag & NODE_DO_OUTPUT)) {
275 add_proxies_group_outputs(context, b_node, b_node_io);
276 }
277 }
278
279 add_bNodeTree(context, nodes_start, b_group_tree, key);
280}
281
283 bNode *b_node,
285 bool is_active_group)
286{
287 SocketProxyNode *proxy = new SocketProxyNode(
288 b_node, (bNodeSocket *)b_node->inputs.first, (bNodeSocket *)b_node->outputs.first, false);
289 add_node(proxy, b_ntree, key, is_active_group);
290}
291
292} // namespace blender::compositor
#define NODE_REROUTE
Definition BKE_node.hh:804
#define NODE_CUSTOM_GROUP
Definition BKE_node.hh:807
#define NODE_GROUP_OUTPUT
Definition BKE_node.hh:806
#define NODE_GROUP
Definition BKE_node.hh:800
#define NODE_GROUP_INPUT
Definition BKE_node.hh:805
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
#define STREQ(a, b)
struct Link Link
@ NODE_DO_OUTPUT
@ NODE_MUTED
@ NODE_LINK_MUTED
@ NODE_LINK_VALID
@ SOCK_UNAVAIL
#define output
Overall context of the compositor.
static void node_added(const Node *node)
Definition COM_Debug.h:65
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
void from_bNodeTree(const CompositorContext &context, bNodeTree *tree)
void add_proxies_group_inputs(bNode *b_node, bNode *b_node_io)
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)
void add_proxies_group_outputs(const CompositorContext &context, bNode *b_node, bNode *b_node_io)
void add_link(NodeOutput *from_socket, NodeInput *to_socket)
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_node(Node *node, bNodeTree *b_ntree, bNodeInstanceKey key, bool is_active_group)
NodeInput are sockets that can receive data/input.
Definition COM_Node.h:191
void set_link(NodeOutput *link)
Definition COM_Node.cc:131
NodeOutput are sockets that can send data/input.
Definition COM_Node.h:239
OperationNode * node
KDTree_3d * tree
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE
Definition node.cc:4020
bNodeInstanceKey node_instance_key(bNodeInstanceKey parent_key, const bNodeTree *ntree, const bNode *node)
Definition node.cc:4041
Node * COM_convert_bnode(bNode *b_node)
Wraps a bNode in its Node instance.
void * first
unsigned int value
ListBase nodes
bNodeInstanceKey active_viewer_key
ListBase inputs
struct ID * id
struct bNode * next
ListBase outputs
int32_t identifier
int16_t type