Blender  V2.93
node_shader_tree.c
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  * The Original Code is Copyright (C) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <string.h>
25 
26 #include "DNA_light_types.h"
27 #include "DNA_linestyle_types.h"
28 #include "DNA_material_types.h"
29 #include "DNA_node_types.h"
30 #include "DNA_scene_types.h"
31 #include "DNA_space_types.h"
32 #include "DNA_workspace_types.h"
33 #include "DNA_world_types.h"
34 
35 #include "BLI_alloca.h"
36 #include "BLI_linklist.h"
37 #include "BLI_listbase.h"
38 #include "BLI_threads.h"
39 #include "BLI_utildefines.h"
40 
41 #include "BLT_translation.h"
42 
43 #include "BKE_context.h"
44 #include "BKE_lib_id.h"
45 #include "BKE_linestyle.h"
46 #include "BKE_node.h"
47 #include "BKE_scene.h"
48 
49 #include "RNA_access.h"
50 
51 #include "GPU_material.h"
52 
53 #include "RE_texture.h"
54 
55 #include "NOD_common.h"
56 
57 #include "node_common.h"
58 #include "node_exec.h"
59 #include "node_shader_util.h"
60 #include "node_util.h"
61 
62 typedef struct nTreeTags {
63  float ssr_id, sss_id;
65 
66 static void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tags);
67 
68 static bool shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
69 {
71  const char *engine_id = scene->r.engine;
72 
73  /* Allow empty engine string too,
74  * this is from older versions that didn't have registerable engines yet. */
75  return (engine_id[0] == '\0' || STREQ(engine_id, RE_engine_id_CYCLES) ||
77 }
78 
79 static void shader_get_from_context(const bContext *C,
80  bNodeTreeType *UNUSED(treetype),
81  bNodeTree **r_ntree,
82  ID **r_id,
83  ID **r_from)
84 {
85  SpaceNode *snode = CTX_wm_space_node(C);
87  ViewLayer *view_layer = CTX_data_view_layer(C);
88  Object *ob = OBACT(view_layer);
89 
90  if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
91  if (ob) {
92  *r_from = &ob->id;
93  if (ob->type == OB_LAMP) {
94  *r_id = ob->data;
95  *r_ntree = ((Light *)ob->data)->nodetree;
96  }
97  else {
99  if (ma) {
100  *r_id = &ma->id;
101  *r_ntree = ma->nodetree;
102  }
103  }
104  }
105  }
106 #ifdef WITH_FREESTYLE
107  else if (snode->shaderfrom == SNODE_SHADER_LINESTYLE) {
109  if (linestyle) {
110  *r_from = NULL;
111  *r_id = &linestyle->id;
112  *r_ntree = linestyle->nodetree;
113  }
114  }
115 #endif
116  else { /* SNODE_SHADER_WORLD */
117  if (scene->world) {
118  *r_from = NULL;
119  *r_id = &scene->world->id;
120  *r_ntree = scene->world->nodetree;
121  }
122  }
123 }
124 
125 static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
126 {
127  func(calldata, NODE_CLASS_INPUT, N_("Input"));
128  func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
129  func(calldata, NODE_CLASS_SHADER, N_("Shader"));
130  func(calldata, NODE_CLASS_TEXTURE, N_("Texture"));
131  func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
132  func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
133  func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
134  func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
135  func(calldata, NODE_CLASS_GROUP, N_("Group"));
136  func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
137  func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
138 }
139 
140 static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
141 {
142  bNode *node, *node_next;
143 
144  /* replace muted nodes and reroute nodes by internal links */
145  for (node = localtree->nodes.first; node; node = node_next) {
146  node_next = node->next;
147 
148  if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
149  nodeInternalRelink(localtree, node);
150  ntreeFreeLocalNode(localtree, node);
151  }
152  }
153 }
154 
155 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
156 {
157  BKE_node_preview_sync_tree(ntree, localtree);
158 }
159 
160 static void local_merge(Main *UNUSED(bmain), bNodeTree *localtree, bNodeTree *ntree)
161 {
162  BKE_node_preview_merge_tree(ntree, localtree, true);
163 }
164 
165 static void update(bNodeTree *ntree)
166 {
168 
170 
172  /* clean up preview cache, in case nodes have been removed */
174  }
175 }
176 
178 {
179  /* Can't connect shader into other socket types, other way around is fine
180  * since it will be interpreted as emission. */
181  if (link->fromsock->type == SOCK_SHADER) {
182  return (link->tosock->type == SOCK_SHADER);
183  }
184  return true;
185 }
186 
188 
190 {
192  "shader node tree type");
193 
194  tt->type = NTREE_SHADER;
195  strcpy(tt->idname, "ShaderNodeTree");
196  strcpy(tt->ui_name, N_("Shader Editor"));
197  tt->ui_icon = 0; /* defined in drawnode.c */
198  strcpy(tt->ui_description, N_("Shader nodes"));
199 
201  tt->localize = localize;
202  tt->local_sync = local_sync;
203  tt->local_merge = local_merge;
204  tt->update = update;
205  tt->poll = shader_tree_poll;
208 
210 
211  ntreeTypeAdd(tt);
212 }
213 
214 /* GPU material from shader nodes */
215 
216 /* Find an output node of the shader tree.
217  *
218  * NOTE: it will only return output which is NOT in the group, which isn't how
219  * render engines works but it's how the GPU shader compilation works. This we
220  * can change in the future and make it a generic function, but for now it stays
221  * private here.
222  */
224 {
225  /* Make sure we only have single node tagged as output. */
227 
228  /* Find output node that matches type and target. If there are
229  * multiple, we prefer exact target match and active nodes. */
230  bNode *output_node = NULL;
231 
234  continue;
235  }
236 
237  if (node->custom1 == SHD_OUTPUT_ALL) {
238  if (output_node == NULL) {
239  output_node = node;
240  }
241  else if (output_node->custom1 == SHD_OUTPUT_ALL) {
242  if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) {
243  output_node = node;
244  }
245  }
246  }
247  else if (node->custom1 == target) {
248  if (output_node == NULL) {
249  output_node = node;
250  }
251  else if (output_node->custom1 == SHD_OUTPUT_ALL) {
252  output_node = node;
253  }
254  else if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) {
255  output_node = node;
256  }
257  }
258  }
259 
260  return output_node;
261 }
262 
263 /* Find socket with a specified identifier. */
264 static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets, const char *identifier)
265 {
266  for (bNodeSocket *sock = sockets->first; sock != NULL; sock = sock->next) {
267  if (STREQ(sock->identifier, identifier)) {
268  return sock;
269  }
270  }
271  return NULL;
272 }
273 
274 /* Find input socket with a specified identifier. */
275 static bNodeSocket *ntree_shader_node_find_input(bNode *node, const char *identifier)
276 {
277  return ntree_shader_node_find_socket(&node->inputs, identifier);
278 }
279 
280 /* Find output socket with a specified identifier. */
281 static bNodeSocket *ntree_shader_node_find_output(bNode *node, const char *identifier)
282 {
283  return ntree_shader_node_find_socket(&node->outputs, identifier);
284 }
285 
286 /* Return true on success. */
288  bNode *node,
289  bNodeSocket *socket)
290 {
291  bNode *value_node;
292  bNodeSocket *value_socket;
293  bNodeSocketValueVector *src_vector;
294  bNodeSocketValueRGBA *src_rgba, *dst_rgba;
295  bNodeSocketValueFloat *src_float, *dst_float;
296  bNodeSocketValueInt *src_int;
297 
298  switch (socket->type) {
299  case SOCK_VECTOR:
300  value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_RGB);
301  value_socket = ntree_shader_node_find_output(value_node, "Color");
302  BLI_assert(value_socket != NULL);
303  src_vector = socket->default_value;
304  dst_rgba = value_socket->default_value;
305  copy_v3_v3(dst_rgba->value, src_vector->value);
306  dst_rgba->value[3] = 1.0f; /* should never be read */
307  break;
308  case SOCK_RGBA:
309  value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_RGB);
310  value_socket = ntree_shader_node_find_output(value_node, "Color");
311  BLI_assert(value_socket != NULL);
312  src_rgba = socket->default_value;
313  dst_rgba = value_socket->default_value;
314  copy_v4_v4(dst_rgba->value, src_rgba->value);
315  break;
316  case SOCK_INT:
317  /* HACK: Support as float. */
318  value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_VALUE);
319  value_socket = ntree_shader_node_find_output(value_node, "Value");
320  BLI_assert(value_socket != NULL);
321  src_int = socket->default_value;
322  dst_float = value_socket->default_value;
323  dst_float->value = (float)(src_int->value);
324  break;
325  case SOCK_FLOAT:
326  value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_VALUE);
327  value_socket = ntree_shader_node_find_output(value_node, "Value");
328  BLI_assert(value_socket != NULL);
329  src_float = socket->default_value;
330  dst_float = value_socket->default_value;
331  dst_float->value = src_float->value;
332  break;
333  default:
334  return false;
335  }
336  nodeAddLink(localtree, value_node, value_socket, node, socket);
337  return true;
338 }
339 
341 {
342  bNodeTree *group_ntree = (bNodeTree *)group_node->id;
343  bNode *node;
344  bool removed_link = false;
345 
346  for (node = group_ntree->nodes.first; node; node = node->next) {
347  const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != NULL);
348 
349  LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
350  if (!is_group && (sock->flag & SOCK_HIDE_VALUE) == 0) {
351  continue;
352  }
353  /* If socket is linked to a group input node and sockets id match. */
354  if (sock && sock->link && sock->link->fromnode->type == NODE_GROUP_INPUT) {
355  if (STREQ(isock->identifier, sock->link->fromsock->identifier)) {
356  if (is_group) {
357  /* Recursively unlink sockets within the nested group. */
359  }
360  else {
361  nodeRemLink(group_ntree, sock->link);
362  removed_link = true;
363  }
364  }
365  }
366  }
367  }
368 
369  if (removed_link) {
370  ntreeUpdateTree(G.main, group_ntree);
371  }
372 }
373 
374 /* Node groups once expanded looses their input sockets values.
375  * To fix this, link value/rgba nodes into the sockets and copy the group sockets values. */
377 {
378  bool link_added = false;
379 
380  LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
381  const bool is_group = ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && (node->id != NULL);
382  const bool is_group_output = node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT);
383 
384  if (is_group) {
385  /* Do it recursively. */
387  }
388 
389  if (is_group || is_group_output) {
390  LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
391  if (socket->link != NULL && !(socket->link->flag & NODE_LINK_MUTED)) {
392  bNodeLink *link = socket->link;
393  /* Fix the case where the socket is actually converting the data. (see T71374)
394  * We only do the case of lossy conversion to float.*/
395  if ((socket->type == SOCK_FLOAT) && (link->fromsock->type != link->tosock->type)) {
396  if (link->fromsock->type == SOCK_RGBA) {
397  bNode *tmp = nodeAddStaticNode(NULL, localtree, SH_NODE_RGBTOBW);
398  nodeAddLink(localtree, link->fromnode, link->fromsock, tmp, tmp->inputs.first);
399  nodeAddLink(localtree, tmp, tmp->outputs.first, node, socket);
400  }
401  else if (link->fromsock->type == SOCK_VECTOR) {
402  bNode *tmp = nodeAddStaticNode(NULL, localtree, SH_NODE_VECTOR_MATH);
404  bNodeSocket *dot_input1 = tmp->inputs.first;
405  bNodeSocket *dot_input2 = dot_input1->next;
406  bNodeSocketValueVector *input2_socket_value = dot_input2->default_value;
407  copy_v3_fl(input2_socket_value->value, 1.0f / 3.0f);
408  nodeAddLink(localtree, link->fromnode, link->fromsock, tmp, dot_input1);
409  nodeAddLink(localtree, tmp, tmp->outputs.last, node, socket);
410  }
411  }
412  continue;
413  }
414 
415  if (is_group) {
416  /* Detect the case where an input is plugged into a hidden value socket.
417  * In this case we should just remove the link to trigger the socket default override. */
419  }
420 
421  if (ntree_shader_expand_socket_default(localtree, node, socket)) {
422  link_added = true;
423  }
424  }
425  }
426  }
427 
428  if (link_added) {
429  ntreeUpdateTree(G.main, localtree);
430  }
431 }
432 
433 static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
434 {
435  bNodeLink *link, *linkn, *tlink;
436  bNode *node, *nextnode;
437  bNodeTree *ngroup;
438  LinkNode *group_interface_nodes = NULL;
439 
440  ngroup = (bNodeTree *)gnode->id;
441 
442  /* Add the nodes into the ntree */
443  for (node = ngroup->nodes.first; node; node = nextnode) {
444  nextnode = node->next;
445  /* Remove interface nodes.
446  * This also removes remaining links to and from interface nodes.
447  * We must delay removal since sockets will reference this node. see: T52092 */
449  BLI_linklist_prepend(&group_interface_nodes, node);
450  }
451  /* migrate node */
452  BLI_remlink(&ngroup->nodes, node);
454  /* ensure unique node name in the node tree */
455  /* This is very slow and it has no use for GPU nodetree. (see T70609) */
456  // nodeUniqueName(ntree, node);
457  }
458 
459  /* Save first and last link to iterate over flattened group links. */
460  bNodeLink *glinks_first = ntree->links.last;
461 
462  /* Add internal links to the ntree */
463  for (link = ngroup->links.first; link; link = linkn) {
464  linkn = link->next;
465  BLI_remlink(&ngroup->links, link);
466  BLI_addtail(&ntree->links, link);
467  }
468 
469  bNodeLink *glinks_last = ntree->links.last;
470 
471  /* restore external links to and from the gnode */
472  if (glinks_first != NULL) {
473  /* input links */
474  for (link = glinks_first->next; link != glinks_last->next; link = link->next) {
475  if (link->fromnode->type == NODE_GROUP_INPUT) {
476  const char *identifier = link->fromsock->identifier;
477  /* find external links to this input */
478  for (tlink = ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) {
479  if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
480  nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
481  }
482  }
483  }
484  }
485  /* Also iterate over the new links to cover passthrough links. */
486  glinks_last = ntree->links.last;
487  /* output links */
488  for (tlink = ntree->links.first; tlink != glinks_first->next; tlink = tlink->next) {
489  if (tlink->fromnode == gnode) {
490  const char *identifier = tlink->fromsock->identifier;
491  /* find internal links to this output */
492  for (link = glinks_first->next; link != glinks_last->next; link = link->next) {
493  /* only use active output node */
494  if (link->tonode->type == NODE_GROUP_OUTPUT && (link->tonode->flag & NODE_DO_OUTPUT)) {
495  if (STREQ(link->tosock->identifier, identifier)) {
496  nodeAddLink(ntree, link->fromnode, link->fromsock, tlink->tonode, tlink->tosock);
497  }
498  }
499  }
500  }
501  }
502  }
503 
504  while (group_interface_nodes) {
505  node = BLI_linklist_pop(&group_interface_nodes);
507  }
508 
510 }
511 
512 /* Flatten group to only have a simple single tree */
513 static void ntree_shader_groups_flatten(bNodeTree *localtree)
514 {
515  /* This is effectively recursive as the flattened groups will add
516  * nodes at the end of the list, which will also get evaluated. */
517  for (bNode *node = localtree->nodes.first, *node_next; node; node = node_next) {
518  if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id != NULL) {
519  flatten_group_do(localtree, node);
520  /* Continue even on new flattened nodes. */
521  node_next = node->next;
522  /* delete the group instance and its localtree. */
523  bNodeTree *ngroup = (bNodeTree *)node->id;
524  ntreeFreeLocalNode(localtree, node);
525  ntreeFreeTree(ngroup);
526  BLI_assert(!ngroup->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
527  MEM_freeN(ngroup);
528  }
529  else {
530  node_next = node->next;
531  }
532  }
533 
534  ntreeUpdateTree(G.main, localtree);
535 }
536 
537 /* Check whether shader has a displacement.
538  *
539  * Will also return a node and its socket which is connected to a displacement
540  * output. Additionally, link which is attached to the displacement output is
541  * also returned.
542  */
544  bNode *output_node,
545  bNode **r_node,
546  bNodeSocket **r_socket,
547  bNodeLink **r_link)
548 {
549  if (output_node == NULL) {
550  /* We can't have displacement without output node, apparently. */
551  return false;
552  }
553  /* Make sure sockets links pointers are correct. */
554  ntreeUpdateTree(G.main, ntree);
555  bNodeSocket *displacement = ntree_shader_node_find_input(output_node, "Displacement");
556 
557  if (displacement == NULL) {
558  /* Non-cycles node is used as an output. */
559  return false;
560  }
561 
562  if ((displacement->link != NULL) && !(displacement->link->flag & NODE_LINK_MUTED)) {
563  *r_node = displacement->link->fromnode;
564  *r_socket = displacement->link->fromsock;
565  *r_link = displacement->link;
566  return true;
567  }
568  return false;
569 }
570 
572  bNode *node,
573  bNode *node_from,
574  bNodeSocket *socket_from)
575 {
576  /* TODO(sergey): Can we do something smarter here than just a name-based
577  * matching?
578  */
579  LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
580  if (STREQ(sock->identifier, "Normal") && sock->link == NULL) {
581  /* It's a normal input and nothing is connected to it. */
582  nodeAddLink(ntree, node_from, socket_from, node, sock);
583  }
584  else if (sock->link) {
585  bNodeLink *link = sock->link;
587  STREQ(link->fromsock->identifier, "Normal")) {
588  /* Linked to a geometry node normal output. */
589  nodeAddLink(ntree, node_from, socket_from, node, sock);
590  }
591  }
592  }
593 }
594 
595 /* Use specified node and socket as an input for unconnected normal sockets. */
597  bNode *node_from,
598  bNodeSocket *socket_from)
599 {
600  for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) {
601  if (node == node_from) {
602  /* Don't connect node itself! */
603  continue;
604  }
605  if (node->tmp_flag == -2) {
606  /* This node is used inside the displacement tree. Skip to avoid cycles. */
607  continue;
608  }
609  ntree_shader_relink_node_normal(ntree, node, node_from, socket_from);
610  }
611 }
612 
613 static void ntree_shader_bypass_bump_link(bNodeTree *ntree, bNode *bump_node, bNodeLink *bump_link)
614 {
615  /* Bypass bump nodes. This replicates cycles "implicit" behavior. */
616  bNodeSocket *bump_normal_input = ntree_shader_node_find_input(bump_node, "Normal");
617  bNode *fromnode;
618  bNodeSocket *fromsock;
619  /* Default to builtin normals if there is no link. */
620  if (bump_normal_input->link) {
621  fromsock = bump_normal_input->link->fromsock;
622  fromnode = bump_normal_input->link->fromnode;
623  }
624  else {
626  fromsock = ntree_shader_node_find_output(fromnode, "Normal");
627  }
628  /* Bypass the bump node by creating a link between the previous and next node. */
629  nodeAddLink(ntree, fromnode, fromsock, bump_link->tonode, bump_link->tosock);
630  nodeRemLink(ntree, bump_link);
631 }
632 
634 {
635  /* Bypass bump links inside copied nodes */
637  bNode *node = link->fromnode;
638  /* If node is a copy. */
639  if (node->tmp_flag == -2 && node->type == SH_NODE_BUMP) {
641  }
642  }
643  ntreeUpdateTree(G.main, ntree);
644 }
645 
646 static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
647 {
648  int *node_count = (int *)userdata;
649  if (fromnode->tmp_flag == -1) {
650  fromnode->tmp_flag = *node_count;
651  (*node_count)++;
652  }
653  if (tonode->tmp_flag == -1) {
654  tonode->tmp_flag = *node_count;
655  (*node_count)++;
656  }
657  return true;
658 }
659 
660 /* Create a copy of a branch starting from a given node.
661  * callback is executed once for every copied node.
662  * Returns input node copy. */
664  bNode *start_node,
665  void (*callback)(bNode *node, int user_data),
666  int user_data)
667 {
668  /* Init tmp flag. */
670  node->tmp_flag = -1;
671  }
672  /* Count and tag all nodes inside the displacement branch of the tree. */
673  start_node->tmp_flag = 0;
674  int node_count = 1;
675  nodeChainIterBackwards(ntree, start_node, ntree_branch_count_and_tag_nodes, &node_count, 1);
676  /* Make a full copy of the branch */
677  bNode **nodes_copy = MEM_mallocN(sizeof(bNode *) * node_count, __func__);
679  if (node->tmp_flag >= 0) {
680  int id = node->tmp_flag;
681  nodes_copy[id] = BKE_node_copy_ex(
683  nodes_copy[id]->tmp_flag = -2; /* Copy */
684  /* Make sure to clear all sockets links as they are invalid. */
685  LISTBASE_FOREACH (bNodeSocket *, sock, &nodes_copy[id]->inputs) {
686  sock->link = NULL;
687  }
688  LISTBASE_FOREACH (bNodeSocket *, sock, &nodes_copy[id]->outputs) {
689  sock->link = NULL;
690  }
691  }
692  }
693  /* Recreate links between copied nodes. */
694  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
695  if (link->fromnode->tmp_flag >= 0 && link->tonode->tmp_flag >= 0) {
696  bNode *fromnode = nodes_copy[link->fromnode->tmp_flag];
697  bNode *tonode = nodes_copy[link->tonode->tmp_flag];
698  bNodeSocket *fromsock = ntree_shader_node_find_output(fromnode, link->fromsock->identifier);
699  bNodeSocket *tosock = ntree_shader_node_find_input(tonode, link->tosock->identifier);
700  nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
701  }
702  }
703  /* Per node callback. */
704  if (callback) {
705  for (int i = 0; i < node_count; i++) {
706  callback(nodes_copy[i], user_data);
707  }
708  }
709  bNode *start_node_copy = nodes_copy[start_node->tmp_flag];
710  MEM_freeN(nodes_copy);
711  return start_node_copy;
712 }
713 
715  bNode *displacement_node,
716  bNodeSocket *displacement_socket,
717  bNodeLink *displacement_link)
718 {
719  /* Replace displacement socket/node/link. */
720  bNode *tonode = displacement_link->tonode;
721  bNodeSocket *tosock = displacement_link->tosock;
722  displacement_node = ntree_shader_copy_branch(ntree, displacement_node, NULL, 0);
723  displacement_socket = ntree_shader_node_find_output(displacement_node,
724  displacement_socket->identifier);
725  nodeRemLink(ntree, displacement_link);
726  nodeAddLink(ntree, displacement_node, displacement_socket, tonode, tosock);
727 
728  ntreeUpdateTree(G.main, ntree);
729 }
730 
731 /* Re-link displacement output to unconnected normal sockets via bump node.
732  * This way material with have proper displacement in the viewport.
733  */
735 {
736  bNode *displacement_node;
737  bNodeSocket *displacement_socket;
738  bNodeLink *displacement_link;
740  ntree, output_node, &displacement_node, &displacement_socket, &displacement_link)) {
741  /* There is no displacement output connected, nothing to re-link. */
742  return;
743  }
744 
745  /* Copy the whole displacement branch to avoid cyclic dependency
746  * and issue when bypassing bump nodes. */
748  ntree, displacement_node, displacement_socket, displacement_link);
749  /* Bypass bump nodes inside the copied branch to mimic cycles behavior. */
751 
752  /* Displacement Node may have changed because of branch copy and bump bypass. */
754  ntree, output_node, &displacement_node, &displacement_socket, &displacement_link);
755 
756  /* We have to disconnect displacement output socket, otherwise we'll have
757  * cycles in the Cycles material :)
758  */
759  nodeRemLink(ntree, displacement_link);
760 
761  /* Convert displacement vector to bump height. */
764  bNodeSocket *normal_socket = ntree_shader_node_find_output(geo_node, "Normal");
765  bNodeSocket *dot_input1 = dot_node->inputs.first;
766  bNodeSocket *dot_input2 = dot_input1->next;
768 
769  nodeAddLink(ntree, displacement_node, displacement_socket, dot_node, dot_input1);
770  nodeAddLink(ntree, geo_node, normal_socket, dot_node, dot_input2);
771  displacement_node = dot_node;
772  displacement_socket = ntree_shader_node_find_output(dot_node, "Value");
773 
774  /* We can't connect displacement to normal directly, use bump node for that
775  * and hope that it gives good enough approximation.
776  */
778  bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height");
779  bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal");
780  BLI_assert(bump_input_socket != NULL);
781  BLI_assert(bump_output_socket != NULL);
782  /* Connect bump node to where displacement output was originally
783  * connected to.
784  */
785  nodeAddLink(ntree, displacement_node, displacement_socket, bump_node, bump_input_socket);
786 
787  /* Tag as part of the new displacmeent tree. */
788  dot_node->tmp_flag = -2;
789  geo_node->tmp_flag = -2;
790  bump_node->tmp_flag = -2;
791 
792  ntreeUpdateTree(G.main, ntree);
793 
794  /* Connect all free-standing Normal inputs and relink geometry/coordinate nodes. */
795  ntree_shader_link_builtin_normal(ntree, bump_node, bump_output_socket);
796  /* We modified the tree, it needs to be updated now. */
797  ntreeUpdateTree(G.main, ntree);
798 }
799 
801 {
802  if (dx) {
803  node->branch_tag = 1;
804  }
805  else {
806  node->branch_tag = 2;
807  }
808 }
809 
810 static bool ntree_shader_bump_branches(bNode *fromnode, bNode *UNUSED(tonode), void *userdata)
811 {
812  bNodeTree *ntree = (bNodeTree *)userdata;
813 
814  if (fromnode->type == SH_NODE_BUMP) {
815  bNodeSocket *height_dx_sock, *height_dy_sock, *bump_socket, *bump_dx_socket, *bump_dy_socket;
816  bNode *bump = fromnode;
817  bump_socket = ntree_shader_node_find_input(bump, "Height");
818  bump_dx_socket = ntree_shader_node_find_input(bump, "Height_dx");
819  bump_dy_socket = ntree_shader_node_find_input(bump, "Height_dy");
820  if (bump_dx_socket->link) {
821  /* Avoid reconnecting the same bump twice. */
822  }
823  else if (bump_socket && bump_socket->link) {
824  bNodeLink *link = bump_socket->link;
825  bNode *height = link->fromnode;
828  height_dx_sock = ntree_shader_node_find_output(height_dx, link->fromsock->identifier);
829  height_dy_sock = ntree_shader_node_find_output(height_dy, link->fromsock->identifier);
830  nodeAddLink(ntree, height_dx, height_dx_sock, bump, bump_dx_socket);
831  nodeAddLink(ntree, height_dy, height_dy_sock, bump, bump_dy_socket);
832  /* We could end iter here, but other bump node could be plugged into other input sockets. */
833  }
834  }
835  return true;
836 }
837 
838 static bool ntree_tag_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata)
839 {
840  switch (fromnode->type) {
843  case SH_NODE_BSDF_GLOSSY:
844  case SH_NODE_BSDF_GLASS:
845  fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id;
846  ((nTreeTags *)userdata)->ssr_id += 1;
847  break;
849  fromnode->sss_id = ((nTreeTags *)userdata)->sss_id;
850  ((nTreeTags *)userdata)->sss_id += 1;
851  break;
853  fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id;
854  fromnode->sss_id = ((nTreeTags *)userdata)->sss_id;
855  ((nTreeTags *)userdata)->sss_id += 1;
856  ((nTreeTags *)userdata)->ssr_id += 1;
857  break;
858  default:
859  /* We could return false here but since we
860  * allow the use of Closure as RGBA, we can have
861  * Bsdf nodes linked to other Bsdf nodes. */
862  break;
863  }
864 
865  return true;
866 }
867 
868 /* EEVEE: Scan the ntree to set the Screen Space Reflection
869  * layer id of every specular node AND the Subsurface Scattering id of every SSS node.
870  */
872 {
873  if (output_node == NULL) {
874  return;
875  }
876  /* Make sure sockets links pointers are correct. */
877  ntreeUpdateTree(G.main, ntree);
878 
879  nodeChainIterBackwards(ntree, output_node, ntree_tag_bsdf_cb, tags, 0);
880 }
881 
882 /* This one needs to work on a local tree. */
884  GPUMaterial *mat,
885  bool *has_surface_output,
886  bool *has_volume_output)
887 {
889 
891 
893 
894  ntree_shader_groups_flatten(localtree);
895 
896  if (output == NULL) {
897  /* Search again, now including flattened nodes. */
899  }
900 
901  /* Perform all needed modifications on the tree in order to support
902  * displacement/bump mapping.
903  */
905 
906  /* Duplicate bump height branches for manual derivatives.
907  */
908  nodeChainIterBackwards(localtree, output, ntree_shader_bump_branches, localtree, 0);
909  LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
910  if (node->type == SH_NODE_OUTPUT_AOV) {
911  nodeChainIterBackwards(localtree, node, ntree_shader_bump_branches, localtree, 0);
912  nTreeTags tags = {
913  .ssr_id = 1.0,
914  .sss_id = 1.0,
915  };
916  ntree_shader_tag_nodes(localtree, node, &tags);
917  }
918  }
919 
920  /* TODO(fclem): consider moving this to the gpu shader tree evaluation. */
921  nTreeTags tags = {
922  .ssr_id = 1.0,
923  .sss_id = 1.0,
924  };
925  ntree_shader_tag_nodes(localtree, output, &tags);
926 
927  exec = ntreeShaderBeginExecTree(localtree);
929  LISTBASE_FOREACH (bNode *, node, &localtree->nodes) {
930  if (node->type == SH_NODE_OUTPUT_AOV) {
931  ntreeExecGPUNodes(exec, mat, node);
932  }
933  }
935 
936  /* EEVEE: Find which material domain was used (volume, surface ...). */
937  *has_surface_output = false;
938  *has_volume_output = false;
939 
940  if (output != NULL) {
941  bNodeSocket *surface_sock = ntree_shader_node_find_input(output, "Surface");
942  bNodeSocket *volume_sock = ntree_shader_node_find_input(output, "Volume");
943 
944  if (surface_sock != NULL) {
945  *has_surface_output = (nodeCountSocketLinks(localtree, surface_sock) > 0);
946  }
947 
948  if (volume_sock != NULL) {
949  *has_volume_output = (nodeCountSocketLinks(localtree, volume_sock) > 0);
950  }
951  }
952 }
953 
955  bNodeTree *ntree,
956  bNodeInstanceKey parent_key)
957 {
959  bNode *node;
960 
961  /* ensures only a single output node is enabled */
963 
964  /* common base initialization */
965  exec = ntree_exec_begin(context, ntree, parent_key);
966 
967  /* allocate the thread stack listbase array */
968  exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array");
969 
970  for (node = exec->nodetree->nodes.first; node; node = node->next) {
971  node->need_exec = 1;
972  }
973 
974  return exec;
975 }
976 
978 {
981 
982  /* XXX hack: prevent exec data from being generated twice.
983  * this should be handled by the renderer!
984  */
985  if (ntree->execdata) {
986  return ntree->execdata;
987  }
988 
989  context.previews = ntree->previews;
990 
992 
993  /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
994  * which only store the ntree pointer. Should be fixed at some point!
995  */
996  ntree->execdata = exec;
997 
998  return exec;
999 }
1000 
1002 {
1003  bNodeThreadStack *nts;
1004  int a;
1005 
1006  if (exec->threadstack) {
1007  for (a = 0; a < BLENDER_MAX_THREADS; a++) {
1008  for (nts = exec->threadstack[a].first; nts; nts = nts->next) {
1009  if (nts->stack) {
1010  MEM_freeN(nts->stack);
1011  }
1012  }
1013  BLI_freelistN(&exec->threadstack[a]);
1014  }
1015 
1016  MEM_freeN(exec->threadstack);
1017  exec->threadstack = NULL;
1018  }
1019 
1021 }
1022 
1024 {
1025  if (exec) {
1026  /* exec may get freed, so assign ntree */
1027  bNodeTree *ntree = exec->nodetree;
1029 
1030  /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
1031  ntree->execdata = NULL;
1032  }
1033 }
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct SpaceNode * CTX_wm_space_node(const bContext *C)
Definition: context.c:854
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
@ LIB_ID_CREATE_NO_USER_REFCOUNT
Definition: BKE_lib_id.h:92
@ LIB_ID_CREATE_NO_MAIN
Definition: BKE_lib_id.h:88
Blender kernel freestyle line style functionality.
FreestyleLineStyle * BKE_linestyle_active_from_view_layer(struct ViewLayer *view_layer)
Definition: linestyle.c:818
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:697
void ntreeTypeAdd(struct bNodeTreeType *nt)
Definition: node.cc:1219
#define NODE_CLASS_OUTPUT
Definition: BKE_node.h:335
#define NODE_REROUTE
Definition: BKE_node.h:873
#define SH_NODE_OUTPUT_WORLD
Definition: BKE_node.h:996
#define NODE_CLASS_INTERFACE
Definition: BKE_node.h:357
void BKE_node_preview_sync_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree)
Definition: node.cc:2749
void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node)
Definition: node.cc:2364
const bNodeInstanceKey NODE_INSTANCE_KEY_BASE
Definition: node.cc:3908
#define NODE_CUSTOM_GROUP
Definition: BKE_node.h:876
#define SH_NODE_BSDF_PRINCIPLED
Definition: BKE_node.h:1058
void ntreeFreeLocalNode(struct bNodeTree *ntree, struct bNode *node)
Definition: node.cc:2925
void BKE_node_preview_remove_unused(struct bNodeTree *ntree)
Definition: node.cc:2690
#define SH_NODE_SUBSURFACE_SCATTERING
Definition: BKE_node.h:1042
void(* bNodeClassCallback)(void *calldata, int nclass, const char *name)
Definition: BKE_node.h:378
#define SH_NODE_VALUE
Definition: BKE_node.h:973
void ntreeFreeTree(struct bNodeTree *ntree)
Definition: node.cc:3015
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link)
Definition: node.cc:2231
#define NODE_CLASS_CONVERTOR
Definition: BKE_node.h:341
struct bNode * BKE_node_copy_ex(struct bNodeTree *ntree, const struct bNode *node_src, const int flag, const bool unique_name)
void ntreeUpdateTree(struct Main *main, struct bNodeTree *ntree)
Definition: node.cc:4262
void BKE_node_preview_merge_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree, bool remove_old)
Definition: node.cc:2770
void ntreeSetOutput(struct bNodeTree *ntree)
Definition: node.cc:3050
struct bNodeLink * nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock)
Definition: node.cc:2189
#define SH_NODE_BSDF_ANISOTROPIC
Definition: BKE_node.h:1002
#define NODE_CLASS_OP_VECTOR
Definition: BKE_node.h:337
#define SH_NODE_EEVEE_SPECULAR
Definition: BKE_node.h:1060
#define NODE_CLASS_LAYOUT
Definition: BKE_node.h:361
#define NODE_CLASS_OP_COLOR
Definition: BKE_node.h:336
#define SH_NODE_BSDF_GLASS
Definition: BKE_node.h:1005
#define NODE_CLASS_INPUT
Definition: BKE_node.h:334
void nodeChainIterBackwards(const bNodeTree *ntree, const bNode *node_start, bool(*callback)(bNode *, bNode *, void *), void *userdata, int recursion_lvl)
Definition: node.cc:1944
struct bNode * nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type)
Definition: node.cc:2004
#define NODE_CLASS_GROUP
Definition: BKE_node.h:339
int nodeCountSocketLinks(const struct bNodeTree *ntree, const struct bNodeSocket *sock)
#define NODE_GROUP_INPUT
Definition: BKE_node.h:874
#define NODE_CLASS_TEXTURE
Definition: BKE_node.h:346
#define NODE_CLASS_SHADER
Definition: BKE_node.h:358
#define SH_NODE_OUTPUT_AOV
Definition: BKE_node.h:1072
#define NODE_CLASS_SCRIPT
Definition: BKE_node.h:356
bool BKE_scene_use_shading_nodes_custom(struct Scene *scene)
Definition: scene.c:2919
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:188
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
#define BLENDER_MAX_THREADS
Definition: BLI_threads.h:35
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
#define N_(msgid)
@ NODE_VECTOR_MATH_DOT_PRODUCT
@ SHD_OUTPUT_ALL
@ SHD_OUTPUT_EEVEE
#define NODE_DO_OUTPUT
#define NODE_MUTED
@ SOCK_HIDE_VALUE
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_SHADER
@ SOCK_FLOAT
@ SOCK_RGBA
#define NTREE_SHADER
@ NTREE_UPDATE_LINKS
@ NTREE_UPDATE_NODES
#define NODE_LINK_MUTED
@ OB_LAMP
#define OBACT(_view_layer)
@ SNODE_SHADER_LINESTYLE
@ SNODE_SHADER_OBJECT
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise Wave Voronoi Brick SH_NODE_TEX_COORD
Group RGB to Bright Vector Camera Vector Combine Material SH_NODE_OUTPUT_LIGHT
NODE_GROUP_OUTPUT
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume SH_NODE_BUMP
Group SH_NODE_RGB
NODE_GROUP
Group SH_NODE_RGBTOBW
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse SH_NODE_BSDF_GLOSSY
Group RGB to Bright Vector Camera SH_NODE_VECTOR_MATH
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled SH_NODE_NEW_GEOMETRY
Group RGB to Bright Vector Camera Vector Combine SH_NODE_OUTPUT_MATERIAL
StructRNA RNA_ShaderNodeTree
#define C
Definition: RandGen.cpp:39
#define output
OperationNode * node
Scene scene
FreestyleLineStyle linestyle
void * user_data
DEGForeachIDComponentCallback callback
bNodeTree * ntree
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned a[3]
Definition: RandGen.cpp:92
void ntree_update_reroute_nodes(bNodeTree *ntree)
Definition: node_common.c:357
static bNodeSocketTemplate outputs[]
static bNodeSocketTemplate inputs[]
bNodeTreeExec * ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
Definition: node_exec.cc:156
void ntree_exec_end(bNodeTreeExec *exec)
Definition: node_exec.cc:259
static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
bNodeTreeExec * ntreeShaderBeginExecTree(bNodeTree *ntree)
static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
static bool ntree_shader_expand_socket_default(bNodeTree *localtree, bNode *node, bNodeSocket *socket)
static void ntree_shader_bypass_bump_link(bNodeTree *ntree, bNode *bump_node, bNodeLink *bump_link)
static bool ntree_tag_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata)
static bNodeSocket * ntree_shader_node_find_output(bNode *node, const char *identifier)
static void ntree_shader_groups_expand_inputs(bNodeTree *localtree)
bNodeTreeExec * ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
static void ntree_shader_groups_flatten(bNodeTree *localtree)
static void node_tag_branch_as_derivative(bNode *node, int dx)
static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
static void ntree_shader_link_builtin_normal(bNodeTree *ntree, bNode *node_from, bNodeSocket *socket_from)
static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
static bNode * ntree_shader_copy_branch(bNodeTree *ntree, bNode *start_node, void(*callback)(bNode *node, int user_data), int user_data)
static void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tags)
void ntreeGPUMaterialNodes(bNodeTree *localtree, GPUMaterial *mat, bool *has_surface_output, bool *has_volume_output)
static void update(bNodeTree *ntree)
static bNodeSocket * ntree_shader_node_find_socket(ListBase *sockets, const char *identifier)
static bool ntree_shader_bump_branches(bNode *fromnode, bNode *UNUSED(tonode), void *userdata)
static bool ntree_shader_has_displacement(bNodeTree *ntree, bNode *output_node, bNode **r_node, bNodeSocket **r_socket, bNodeLink **r_link)
static void ntree_shader_relink_node_normal(bNodeTree *ntree, bNode *node, bNode *node_from, bNodeSocket *socket_from)
static void ntree_shader_unlink_hidden_value_sockets(bNode *group_node, bNodeSocket *isock)
bNodeTreeType * ntreeType_Shader
static bool shader_validate_link(bNodeTree *UNUSED(ntree), bNodeLink *link)
static void ntree_shader_bypass_tagged_bump_nodes(bNodeTree *ntree)
static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_node)
static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
struct nTreeTags nTreeTags
static bool shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
void register_node_tree_type_sh(void)
void ntreeShaderEndExecTree(bNodeTreeExec *exec)
static void ntree_shader_copy_branch_displacement(bNodeTree *ntree, bNode *displacement_node, bNodeSocket *displacement_socket, bNodeLink *displacement_link)
bNode * ntreeShaderOutputNode(bNodeTree *ntree, int target)
void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
static bNodeSocket * ntree_shader_node_find_input(bNode *node, const char *identifier)
static void local_merge(Main *UNUSED(bmain), bNodeTree *localtree, bNodeTree *ntree)
void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node)
static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
const char * RE_engine_id_CYCLES
Definition: scene.c:1744
struct SELECTID_Context context
Definition: select_engine.c:47
StructRNA * srna
Definition: RNA_types.h:681
struct bNodeTree * nodetree
Definition: DNA_ID.h:273
void * py_instance
Definition: DNA_ID.h:340
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
struct bNodeTree * nodetree
void * data
char engine[32]
struct RenderData r
struct World * world
struct bNodeTree * nodetree
struct bNodeLink * link
struct bNodeSocket * next
void * default_value
char identifier[64]
struct bNodeThreadStack * next
Definition: node_exec.h:69
struct bNodeStack * stack
Definition: node_exec.h:70
bool(* poll)(const struct bContext *C, struct bNodeTreeType *ntreetype)
Definition: BKE_node.h:393
char idname[64]
Definition: BKE_node.h:381
void(* update)(struct bNodeTree *ntree)
Definition: BKE_node.h:407
void(* local_merge)(struct Main *bmain, struct bNodeTree *localtree, struct bNodeTree *ntree)
Definition: BKE_node.h:404
void(* get_from_context)(const struct bContext *C, struct bNodeTreeType *ntreetype, struct bNodeTree **r_ntree, struct ID **r_id, struct ID **r_from)
Definition: BKE_node.h:395
bool(* validate_link)(struct bNodeTree *ntree, struct bNodeLink *link)
Definition: BKE_node.h:409
char ui_name[64]
Definition: BKE_node.h:383
void(* localize)(struct bNodeTree *localtree, struct bNodeTree *ntree)
Definition: BKE_node.h:402
char ui_description[256]
Definition: BKE_node.h:384
void(* foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func)
Definition: BKE_node.h:391
void(* local_sync)(struct bNodeTree *localtree, struct bNodeTree *ntree)
Definition: BKE_node.h:403
ExtensionRNA rna_ext
Definition: BKE_node.h:414
struct bNodeInstanceHash * previews
ListBase nodes
ListBase links
struct bNodeTreeExec * execdata
short custom1
ListBase inputs
struct ID * id
short tmp_flag
short type
float ssr_id
float sss_id
ListBase outputs
#define G(x, y, z)