diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/nodes/shader/node_shader_tree.c | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/nodes/shader/node_shader_tree.c')
-rw-r--r-- | source/blender/nodes/shader/node_shader_tree.c | 1383 |
1 files changed, 677 insertions, 706 deletions
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 9f01d2ab254..816c56713d0 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -21,7 +21,6 @@ * \ingroup nodes */ - #include <string.h> #include "DNA_light_types.h" @@ -58,141 +57,144 @@ #include "node_util.h" #include "node_shader_util.h" - typedef struct nTreeTags { - float ssr_id, sss_id; + float ssr_id, sss_id; } nTreeTags; static void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tags); static bool shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype)) { - Scene *scene = CTX_data_scene(C); - const char *engine_id = scene->r.engine; + Scene *scene = CTX_data_scene(C); + const char *engine_id = scene->r.engine; - /* allow empty engine string too, this is from older versions that didn't have registerable engines yet */ - return (engine_id[0] == '\0' || - STREQ(engine_id, RE_engine_id_CYCLES) || - !BKE_scene_use_shading_nodes_custom(scene)); + /* allow empty engine string too, this is from older versions that didn't have registerable engines yet */ + return (engine_id[0] == '\0' || STREQ(engine_id, RE_engine_id_CYCLES) || + !BKE_scene_use_shading_nodes_custom(scene)); } -static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from) +static void shader_get_from_context(const bContext *C, + bNodeTreeType *UNUSED(treetype), + bNodeTree **r_ntree, + ID **r_id, + ID **r_from) { - SpaceNode *snode = CTX_wm_space_node(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - - if (snode->shaderfrom == SNODE_SHADER_OBJECT) { - if (ob) { - *r_from = &ob->id; - if (ob->type == OB_LAMP) { - *r_id = ob->data; - *r_ntree = ((Light *)ob->data)->nodetree; - } - else { - Material *ma = give_current_material(ob, ob->actcol); - if (ma) { - *r_id = &ma->id; - *r_ntree = ma->nodetree; - } - } - } - } + SpaceNode *snode = CTX_wm_space_node(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + + if (snode->shaderfrom == SNODE_SHADER_OBJECT) { + if (ob) { + *r_from = &ob->id; + if (ob->type == OB_LAMP) { + *r_id = ob->data; + *r_ntree = ((Light *)ob->data)->nodetree; + } + else { + Material *ma = give_current_material(ob, ob->actcol); + if (ma) { + *r_id = &ma->id; + *r_ntree = ma->nodetree; + } + } + } + } #ifdef WITH_FREESTYLE - else if (snode->shaderfrom == SNODE_SHADER_LINESTYLE) { - FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer); - if (linestyle) { - *r_from = NULL; - *r_id = &linestyle->id; - *r_ntree = linestyle->nodetree; - } - } + else if (snode->shaderfrom == SNODE_SHADER_LINESTYLE) { + FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer); + if (linestyle) { + *r_from = NULL; + *r_id = &linestyle->id; + *r_ntree = linestyle->nodetree; + } + } #endif - else { /* SNODE_SHADER_WORLD */ - if (scene->world) { - *r_from = NULL; - *r_id = &scene->world->id; - *r_ntree = scene->world->nodetree; - } - } + else { /* SNODE_SHADER_WORLD */ + if (scene->world) { + *r_from = NULL; + *r_id = &scene->world->id; + *r_ntree = scene->world->nodetree; + } + } } static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func) { - func(calldata, NODE_CLASS_INPUT, N_("Input")); - func(calldata, NODE_CLASS_OUTPUT, N_("Output")); - func(calldata, NODE_CLASS_SHADER, N_("Shader")); - func(calldata, NODE_CLASS_TEXTURE, N_("Texture")); - func(calldata, NODE_CLASS_OP_COLOR, N_("Color")); - func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector")); - func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor")); - func(calldata, NODE_CLASS_SCRIPT, N_("Script")); - func(calldata, NODE_CLASS_GROUP, N_("Group")); - func(calldata, NODE_CLASS_INTERFACE, N_("Interface")); - func(calldata, NODE_CLASS_LAYOUT, N_("Layout")); + func(calldata, NODE_CLASS_INPUT, N_("Input")); + func(calldata, NODE_CLASS_OUTPUT, N_("Output")); + func(calldata, NODE_CLASS_SHADER, N_("Shader")); + func(calldata, NODE_CLASS_TEXTURE, N_("Texture")); + func(calldata, NODE_CLASS_OP_COLOR, N_("Color")); + func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector")); + func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor")); + func(calldata, NODE_CLASS_SCRIPT, N_("Script")); + func(calldata, NODE_CLASS_GROUP, N_("Group")); + func(calldata, NODE_CLASS_INTERFACE, N_("Interface")); + func(calldata, NODE_CLASS_LAYOUT, N_("Layout")); } static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) { - bNode *node, *node_next; + bNode *node, *node_next; - /* replace muted nodes and reroute nodes by internal links */ - for (node = localtree->nodes.first; node; node = node_next) { - node_next = node->next; + /* replace muted nodes and reroute nodes by internal links */ + for (node = localtree->nodes.first; node; node = node_next) { + node_next = node->next; - if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { - nodeInternalRelink(localtree, node); - ntreeFreeLocalNode(localtree, node); - } - } + if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { + nodeInternalRelink(localtree, node); + ntreeFreeLocalNode(localtree, node); + } + } } static void local_sync(bNodeTree *localtree, bNodeTree *ntree) { - BKE_node_preview_sync_tree(ntree, localtree); + BKE_node_preview_sync_tree(ntree, localtree); } static void local_merge(Main *UNUSED(bmain), bNodeTree *localtree, bNodeTree *ntree) { - BKE_node_preview_merge_tree(ntree, localtree, true); + BKE_node_preview_merge_tree(ntree, localtree, true); } static void update(bNodeTree *ntree) { - ntreeSetOutput(ntree); + ntreeSetOutput(ntree); - ntree_update_reroute_nodes(ntree); + ntree_update_reroute_nodes(ntree); - if (ntree->update & NTREE_UPDATE_NODES) { - /* clean up preview cache, in case nodes have been removed */ - BKE_node_preview_remove_unused(ntree); - } + if (ntree->update & NTREE_UPDATE_NODES) { + /* clean up preview cache, in case nodes have been removed */ + BKE_node_preview_remove_unused(ntree); + } } bNodeTreeType *ntreeType_Shader; void register_node_tree_type_sh(void) { - bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type"); - - tt->type = NTREE_SHADER; - strcpy(tt->idname, "ShaderNodeTree"); - strcpy(tt->ui_name, N_("Shader Editor")); - tt->ui_icon = 0; /* defined in drawnode.c */ - strcpy(tt->ui_description, N_("Shader nodes")); - - tt->foreach_nodeclass = foreach_nodeclass; - tt->localize = localize; - tt->local_sync = local_sync; - tt->local_merge = local_merge; - tt->update = update; - tt->poll = shader_tree_poll; - tt->get_from_context = shader_get_from_context; - - tt->ext.srna = &RNA_ShaderNodeTree; - - ntreeTypeAdd(tt); + bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), + "shader node tree type"); + + tt->type = NTREE_SHADER; + strcpy(tt->idname, "ShaderNodeTree"); + strcpy(tt->ui_name, N_("Shader Editor")); + tt->ui_icon = 0; /* defined in drawnode.c */ + strcpy(tt->ui_description, N_("Shader nodes")); + + tt->foreach_nodeclass = foreach_nodeclass; + tt->localize = localize; + tt->local_sync = local_sync; + tt->local_merge = local_merge; + tt->update = update; + tt->poll = shader_tree_poll; + tt->get_from_context = shader_get_from_context; + + tt->ext.srna = &RNA_ShaderNodeTree; + + ntreeTypeAdd(tt); } /* GPU material from shader nodes */ @@ -203,8 +205,7 @@ static void ntree_shader_link_builtin_normal(bNodeTree *ntree, bNode *displacement_node, bNodeSocket *displacement_socket); -static bNodeSocket *ntree_shader_node_find_input(bNode *node, - const char *identifier); +static bNodeSocket *ntree_shader_node_find_input(bNode *node, const char *identifier); static bNode *ntree_group_output_node(bNodeTree *ntree); @@ -213,101 +214,98 @@ static bNode *ntree_shader_relink_output_from_group(bNodeTree *ntree, bNode *sh_output_node, int target) { - int i; - bNodeTree *group_ntree = (bNodeTree *)group_node->id; - - int sock_len = BLI_listbase_count(&sh_output_node->inputs); - bNodeSocket **group_surface_sockets = BLI_array_alloca(group_surface_sockets, sock_len); - - /* Create output sockets to plug output connection to. */ - i = 0; - for (bNodeSocket *sock = sh_output_node->inputs.first; sock; sock = sock->next, ++i) { - group_surface_sockets[i] = - ntreeAddSocketInterface(group_ntree, - SOCK_OUT, - sock->typeinfo->idname, - sock->name); - } - - bNode *group_output_node = ntree_group_output_node(group_ntree); - - /* If no group output node is present, we need to create one. */ - if (group_output_node == NULL) { - group_output_node = nodeAddStaticNode(NULL, group_ntree, NODE_GROUP_OUTPUT); - } - - /* Need to update tree so all node instances nodes gets proper sockets. */ - node_group_verify(ntree, group_node, &group_ntree->id); - node_group_output_verify(group_ntree, group_output_node, &group_ntree->id); - ntreeUpdateTree(G.main, group_ntree); - - /* Remove other shader output nodes so that only the new one can be selected as active. */ - for (bNode *node = ntree->nodes.first; node; node = node->next) { - if (ELEM(node->type, SH_NODE_OUTPUT_MATERIAL, - SH_NODE_OUTPUT_WORLD, - SH_NODE_OUTPUT_LIGHT)) - { - ntreeFreeLocalNode(ntree, node); - } - } - - /* Create new shader output node outside the group. */ - bNode *new_output_node = nodeAddStaticNode(NULL, ntree, sh_output_node->type); - new_output_node->custom1 = target; - - i = 0; - for (bNodeSocket *sock = sh_output_node->inputs.first; sock; sock = sock->next, ++i) { - if (sock->link != NULL) { - /* Link the shader output node incoming link to the group output sockets */ - bNodeSocket *group_output_node_surface_input_sock = nodeFindSocket(group_output_node, - SOCK_IN, - group_surface_sockets[i]->identifier); - nodeAddLink(group_ntree, - sock->link->fromnode, sock->link->fromsock, - group_output_node, group_output_node_surface_input_sock); - - /* Link the group output sockets to the new shader output node. */ - bNodeSocket *group_node_surface_output = nodeFindSocket(group_node, - SOCK_OUT, - group_surface_sockets[i]->identifier); - bNodeSocket *output_node_surface_input = ntree_shader_node_find_input(new_output_node, sock->name); - - nodeAddLink(ntree, - group_node, group_node_surface_output, - new_output_node, output_node_surface_input); - } - } - - ntreeUpdateTree(G.main, group_ntree); - ntreeUpdateTree(G.main, ntree); - - return new_output_node; + int i; + bNodeTree *group_ntree = (bNodeTree *)group_node->id; + + int sock_len = BLI_listbase_count(&sh_output_node->inputs); + bNodeSocket **group_surface_sockets = BLI_array_alloca(group_surface_sockets, sock_len); + + /* Create output sockets to plug output connection to. */ + i = 0; + for (bNodeSocket *sock = sh_output_node->inputs.first; sock; sock = sock->next, ++i) { + group_surface_sockets[i] = ntreeAddSocketInterface( + group_ntree, SOCK_OUT, sock->typeinfo->idname, sock->name); + } + + bNode *group_output_node = ntree_group_output_node(group_ntree); + + /* If no group output node is present, we need to create one. */ + if (group_output_node == NULL) { + group_output_node = nodeAddStaticNode(NULL, group_ntree, NODE_GROUP_OUTPUT); + } + + /* Need to update tree so all node instances nodes gets proper sockets. */ + node_group_verify(ntree, group_node, &group_ntree->id); + node_group_output_verify(group_ntree, group_output_node, &group_ntree->id); + ntreeUpdateTree(G.main, group_ntree); + + /* Remove other shader output nodes so that only the new one can be selected as active. */ + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (ELEM(node->type, SH_NODE_OUTPUT_MATERIAL, SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LIGHT)) { + ntreeFreeLocalNode(ntree, node); + } + } + + /* Create new shader output node outside the group. */ + bNode *new_output_node = nodeAddStaticNode(NULL, ntree, sh_output_node->type); + new_output_node->custom1 = target; + + i = 0; + for (bNodeSocket *sock = sh_output_node->inputs.first; sock; sock = sock->next, ++i) { + if (sock->link != NULL) { + /* Link the shader output node incoming link to the group output sockets */ + bNodeSocket *group_output_node_surface_input_sock = nodeFindSocket( + group_output_node, SOCK_IN, group_surface_sockets[i]->identifier); + nodeAddLink(group_ntree, + sock->link->fromnode, + sock->link->fromsock, + group_output_node, + group_output_node_surface_input_sock); + + /* Link the group output sockets to the new shader output node. */ + bNodeSocket *group_node_surface_output = nodeFindSocket( + group_node, SOCK_OUT, group_surface_sockets[i]->identifier); + bNodeSocket *output_node_surface_input = ntree_shader_node_find_input(new_output_node, + sock->name); + + nodeAddLink(ntree, + group_node, + group_node_surface_output, + new_output_node, + output_node_surface_input); + } + } + + ntreeUpdateTree(G.main, group_ntree); + ntreeUpdateTree(G.main, ntree); + + return new_output_node; } static bNode *ntree_shader_output_node_from_group(bNodeTree *ntree, int target) { - bNode *output_node = NULL; - - /* Search if node groups do not contain valid output nodes (recursively). */ - for (bNode *node = ntree->nodes.first; node; node = node->next) { - if (!ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) { - continue; - } - if (node->id != NULL) { - output_node = ntree_shader_output_node_from_group((bNodeTree *)node->id, target); - - if (output_node == NULL) { - output_node = ntreeShaderOutputNode((bNodeTree *)node->id, target); - } - - if (output_node != NULL) { - /* Output is inside this group node. Create relink to make the output outside the group. */ - output_node = ntree_shader_relink_output_from_group(ntree, node, output_node, target); - break; - } - } - } - return output_node; + bNode *output_node = NULL; + + /* Search if node groups do not contain valid output nodes (recursively). */ + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (!ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) { + continue; + } + if (node->id != NULL) { + output_node = ntree_shader_output_node_from_group((bNodeTree *)node->id, target); + + if (output_node == NULL) { + output_node = ntreeShaderOutputNode((bNodeTree *)node->id, target); + } + + if (output_node != NULL) { + /* Output is inside this group node. Create relink to make the output outside the group. */ + output_node = ntree_shader_relink_output_from_group(ntree, node, output_node, target); + break; + } + } + } + return output_node; } /* Find an output node of the shader tree. @@ -319,49 +317,42 @@ static bNode *ntree_shader_output_node_from_group(bNodeTree *ntree, int target) */ bNode *ntreeShaderOutputNode(bNodeTree *ntree, int target) { - /* Make sure we only have single node tagged as output. */ - ntreeSetOutput(ntree); - - /* Find output node that matches type and target. If there are - * multiple, we prefer exact target match and active nodes. */ - bNode *output_node = NULL; - - for (bNode *node = ntree->nodes.first; node; node = node->next) { - if (!ELEM(node->type, SH_NODE_OUTPUT_MATERIAL, - SH_NODE_OUTPUT_WORLD, - SH_NODE_OUTPUT_LIGHT)) - { - continue; - } - - if (node->custom1 == SHD_OUTPUT_ALL) { - if (output_node == NULL) { - output_node = node; - } - else if (output_node->custom1 == SHD_OUTPUT_ALL) { - if ((node->flag & NODE_DO_OUTPUT) && - !(output_node->flag & NODE_DO_OUTPUT)) - { - output_node = node; - } - } - } - else if (node->custom1 == target) { - if (output_node == NULL) { - output_node = node; - } - else if (output_node->custom1 == SHD_OUTPUT_ALL) { - output_node = node; - } - else if ((node->flag & NODE_DO_OUTPUT) && - !(output_node->flag & NODE_DO_OUTPUT)) - { - output_node = node; - } - } - } - - return output_node; + /* Make sure we only have single node tagged as output. */ + ntreeSetOutput(ntree); + + /* Find output node that matches type and target. If there are + * multiple, we prefer exact target match and active nodes. */ + bNode *output_node = NULL; + + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (!ELEM(node->type, SH_NODE_OUTPUT_MATERIAL, SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LIGHT)) { + continue; + } + + if (node->custom1 == SHD_OUTPUT_ALL) { + if (output_node == NULL) { + output_node = node; + } + else if (output_node->custom1 == SHD_OUTPUT_ALL) { + if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) { + output_node = node; + } + } + } + else if (node->custom1 == target) { + if (output_node == NULL) { + output_node = node; + } + else if (output_node->custom1 == SHD_OUTPUT_ALL) { + output_node = node; + } + else if ((node->flag & NODE_DO_OUTPUT) && !(output_node->flag & NODE_DO_OUTPUT)) { + output_node = node; + } + } + } + + return output_node; } /* Find the active output node of a group nodetree. @@ -370,154 +361,147 @@ bNode *ntreeShaderOutputNode(bNodeTree *ntree, int target) */ static bNode *ntree_group_output_node(bNodeTree *ntree) { - /* Make sure we only have single node tagged as output. */ - ntreeSetOutput(ntree); - - /* Find output node that matches type and target. If there are - * multiple, we prefer exact target match and active nodes. */ - bNode *output_node = NULL; - - for (bNode *node = ntree->nodes.first; node; node = node->next) { - if ((node->type == NODE_GROUP_OUTPUT) && - (node->flag & NODE_DO_OUTPUT)) - { - output_node = node; - } - } - - return output_node; + /* Make sure we only have single node tagged as output. */ + ntreeSetOutput(ntree); + + /* Find output node that matches type and target. If there are + * multiple, we prefer exact target match and active nodes. */ + bNode *output_node = NULL; + + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if ((node->type == NODE_GROUP_OUTPUT) && (node->flag & NODE_DO_OUTPUT)) { + output_node = node; + } + } + + return output_node; } /* Find socket with a specified identifier. */ -static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets, - const char *identifier) +static bNodeSocket *ntree_shader_node_find_socket(ListBase *sockets, const char *identifier) { - for (bNodeSocket *sock = sockets->first; sock != NULL; sock = sock->next) { - if (STREQ(sock->identifier, identifier)) { - return sock; - } - } - return NULL; + for (bNodeSocket *sock = sockets->first; sock != NULL; sock = sock->next) { + if (STREQ(sock->identifier, identifier)) { + return sock; + } + } + return NULL; } /* Find input socket with a specified identifier. */ -static bNodeSocket *ntree_shader_node_find_input(bNode *node, - const char *identifier) +static bNodeSocket *ntree_shader_node_find_input(bNode *node, const char *identifier) { - return ntree_shader_node_find_socket(&node->inputs, identifier); + return ntree_shader_node_find_socket(&node->inputs, identifier); } /* Find output socket with a specified identifier. */ -static bNodeSocket *ntree_shader_node_find_output(bNode *node, - const char *identifier) +static bNodeSocket *ntree_shader_node_find_output(bNode *node, const char *identifier) { - return ntree_shader_node_find_socket(&node->outputs, identifier); + return ntree_shader_node_find_socket(&node->outputs, identifier); } static void ntree_shader_unlink_hidden_value_sockets(bNode *group_node, bNodeSocket *isock) { - bNodeTree *group_ntree = (bNodeTree *)group_node->id; - bNode *node; - bool removed_link = false; - - for (node = group_ntree->nodes.first; node; node = node->next) { - for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) { - if ((sock->flag & SOCK_HIDE_VALUE) == 0) - continue; - /* If socket is linked to a group input node and sockets id match. */ - if (sock && sock->link && sock->link->fromnode->type == NODE_GROUP_INPUT) { - if (STREQ(isock->identifier, sock->link->fromsock->identifier)) { - nodeRemLink(group_ntree, sock->link); - removed_link = true; - } - } - } - } - - if (removed_link) { - ntreeUpdateTree(G.main, group_ntree); - } + bNodeTree *group_ntree = (bNodeTree *)group_node->id; + bNode *node; + bool removed_link = false; + + for (node = group_ntree->nodes.first; node; node = node->next) { + for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) { + if ((sock->flag & SOCK_HIDE_VALUE) == 0) + continue; + /* If socket is linked to a group input node and sockets id match. */ + if (sock && sock->link && sock->link->fromnode->type == NODE_GROUP_INPUT) { + if (STREQ(isock->identifier, sock->link->fromsock->identifier)) { + nodeRemLink(group_ntree, sock->link); + removed_link = true; + } + } + } + } + + if (removed_link) { + ntreeUpdateTree(G.main, group_ntree); + } } /* Node groups once expanded looses their input sockets values. * To fix this, link value/rgba nodes into the sockets and copy the group sockets values. */ static void ntree_shader_groups_expand_inputs(bNodeTree *localtree) { - bNode *value_node, *group_node; - bNodeSocket *value_socket; - bNodeSocketValueVector *src_vector; - bNodeSocketValueRGBA *src_rgba, *dst_rgba; - bNodeSocketValueFloat *src_float, *dst_float; - bNodeSocketValueInt *src_int; - bool link_added = false; - - for (group_node = localtree->nodes.first; group_node; group_node = group_node->next) { - - if (!(ELEM(group_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) || group_node->id == NULL) - continue; - - /* Do it recursively. */ - ntree_shader_groups_expand_inputs((bNodeTree *)group_node->id); - - bNodeSocket *group_socket = group_node->inputs.first; - for (; group_socket; group_socket = group_socket->next) { - if (group_socket->link != NULL) - continue; - - /* Detect the case where an input is plugged into a hidden value socket. - * In this case we should just remove the link to trigger the socket default override. */ - ntree_shader_unlink_hidden_value_sockets(group_node, group_socket); - - switch (group_socket->type) { - case SOCK_VECTOR: - value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_RGB); - value_socket = ntree_shader_node_find_output(value_node, "Color"); - BLI_assert(value_socket != NULL); - src_vector = group_socket->default_value; - dst_rgba = value_socket->default_value; - copy_v3_v3(dst_rgba->value, src_vector->value); - dst_rgba->value[3] = 1.0f; /* should never be read */ - break; - case SOCK_RGBA: - value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_RGB); - value_socket = ntree_shader_node_find_output(value_node, "Color"); - BLI_assert(value_socket != NULL); - src_rgba = group_socket->default_value; - dst_rgba = value_socket->default_value; - copy_v4_v4(dst_rgba->value, src_rgba->value); - break; - case SOCK_INT: - /* HACK: Support as float. */ - value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_VALUE); - value_socket = ntree_shader_node_find_output(value_node, "Value"); - BLI_assert(value_socket != NULL); - src_int = group_socket->default_value; - dst_float = value_socket->default_value; - dst_float->value = (float)(src_int->value); - break; - case SOCK_FLOAT: - value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_VALUE); - value_socket = ntree_shader_node_find_output(value_node, "Value"); - BLI_assert(value_socket != NULL); - src_float = group_socket->default_value; - dst_float = value_socket->default_value; - dst_float->value = src_float->value; - break; - default: - continue; - } - - nodeAddLink(localtree, - value_node, value_socket, - group_node, group_socket); - - link_added = true; - } - } - - if (link_added) { - ntreeUpdateTree(G.main, localtree); - } + bNode *value_node, *group_node; + bNodeSocket *value_socket; + bNodeSocketValueVector *src_vector; + bNodeSocketValueRGBA *src_rgba, *dst_rgba; + bNodeSocketValueFloat *src_float, *dst_float; + bNodeSocketValueInt *src_int; + bool link_added = false; + + for (group_node = localtree->nodes.first; group_node; group_node = group_node->next) { + + if (!(ELEM(group_node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) || group_node->id == NULL) + continue; + + /* Do it recursively. */ + ntree_shader_groups_expand_inputs((bNodeTree *)group_node->id); + + bNodeSocket *group_socket = group_node->inputs.first; + for (; group_socket; group_socket = group_socket->next) { + if (group_socket->link != NULL) + continue; + + /* Detect the case where an input is plugged into a hidden value socket. + * In this case we should just remove the link to trigger the socket default override. */ + ntree_shader_unlink_hidden_value_sockets(group_node, group_socket); + + switch (group_socket->type) { + case SOCK_VECTOR: + value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_RGB); + value_socket = ntree_shader_node_find_output(value_node, "Color"); + BLI_assert(value_socket != NULL); + src_vector = group_socket->default_value; + dst_rgba = value_socket->default_value; + copy_v3_v3(dst_rgba->value, src_vector->value); + dst_rgba->value[3] = 1.0f; /* should never be read */ + break; + case SOCK_RGBA: + value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_RGB); + value_socket = ntree_shader_node_find_output(value_node, "Color"); + BLI_assert(value_socket != NULL); + src_rgba = group_socket->default_value; + dst_rgba = value_socket->default_value; + copy_v4_v4(dst_rgba->value, src_rgba->value); + break; + case SOCK_INT: + /* HACK: Support as float. */ + value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_VALUE); + value_socket = ntree_shader_node_find_output(value_node, "Value"); + BLI_assert(value_socket != NULL); + src_int = group_socket->default_value; + dst_float = value_socket->default_value; + dst_float->value = (float)(src_int->value); + break; + case SOCK_FLOAT: + value_node = nodeAddStaticNode(NULL, localtree, SH_NODE_VALUE); + value_socket = ntree_shader_node_find_output(value_node, "Value"); + BLI_assert(value_socket != NULL); + src_float = group_socket->default_value; + dst_float = value_socket->default_value; + dst_float->value = src_float->value; + break; + default: + continue; + } + + nodeAddLink(localtree, value_node, value_socket, group_node, group_socket); + + link_added = true; + } + } + + if (link_added) { + ntreeUpdateTree(G.main, localtree); + } } /* Check whether shader has a displacement. @@ -532,25 +516,24 @@ static bool ntree_shader_has_displacement(bNodeTree *ntree, bNodeSocket **r_socket, bNodeLink **r_link) { - if (output_node == NULL) { - /* We can't have displacement without output node, apparently. */ - return false; - } - /* Make sure sockets links pointers are correct. */ - ntreeUpdateTree(G.main, ntree); - bNodeSocket *displacement = ntree_shader_node_find_input(output_node, - "Displacement"); - - if (displacement == NULL) { - /* Non-cycles node is used as an output. */ - return false; - } - if (displacement->link != NULL) { - *r_node = displacement->link->fromnode; - *r_socket = displacement->link->fromsock; - *r_link = displacement->link; - } - return displacement->link != NULL; + if (output_node == NULL) { + /* We can't have displacement without output node, apparently. */ + return false; + } + /* Make sure sockets links pointers are correct. */ + ntreeUpdateTree(G.main, ntree); + bNodeSocket *displacement = ntree_shader_node_find_input(output_node, "Displacement"); + + if (displacement == NULL) { + /* Non-cycles node is used as an output. */ + return false; + } + if (displacement->link != NULL) { + *r_node = displacement->link->fromnode; + *r_socket = displacement->link->fromsock; + *r_link = displacement->link; + } + return displacement->link != NULL; } static bool ntree_shader_relink_node_normal(bNodeTree *ntree, @@ -558,108 +541,100 @@ static bool ntree_shader_relink_node_normal(bNodeTree *ntree, bNode *node_from, bNodeSocket *socket_from) { - bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal"); - /* TODO(sergey): Can we do something smarter here than just a name-based - * matching? - */ - if (sock == NULL) { - /* There's no Normal input, nothing to link. */ - return false; - } - if (sock->link != NULL) { - /* Something is linked to the normal input already. can't - * use other input for that. - */ - return false; - } - /* Create connection between specified node and the normal input. */ - nodeAddLink(ntree, node_from, socket_from, node, sock); - return true; + bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal"); + /* TODO(sergey): Can we do something smarter here than just a name-based + * matching? + */ + if (sock == NULL) { + /* There's no Normal input, nothing to link. */ + return false; + } + if (sock->link != NULL) { + /* Something is linked to the normal input already. can't + * use other input for that. + */ + return false; + } + /* Create connection between specified node and the normal input. */ + nodeAddLink(ntree, node_from, socket_from, node, sock); + return true; } -static void ntree_shader_link_builtin_group_normal( - bNodeTree *ntree, - bNode *group_node, - bNode *node_from, - bNodeSocket *socket_from, - bNode *displacement_node, - bNodeSocket *displacement_socket) +static void ntree_shader_link_builtin_group_normal(bNodeTree *ntree, + bNode *group_node, + bNode *node_from, + bNodeSocket *socket_from, + bNode *displacement_node, + bNodeSocket *displacement_socket) { - bNodeTree *group_ntree = (bNodeTree *)group_node->id; - /* Create input socket to plug displacement connection to. */ - bNodeSocket *group_normal_socket = - ntreeAddSocketInterface(group_ntree, - SOCK_IN, - "NodeSocketVector", - "Normal"); - /* Need to update tree so all node instances nodes gets proper sockets. */ - bNode *group_input_node = ntreeFindType(group_ntree, NODE_GROUP_INPUT); - node_group_verify(ntree, group_node, &group_ntree->id); - if (group_input_node) - node_group_input_verify(group_ntree, group_input_node, &group_ntree->id); - ntreeUpdateTree(G.main, group_ntree); - /* Assumes sockets are always added at the end. */ - bNodeSocket *group_node_normal_socket = group_node->inputs.last; - if (displacement_node == group_node) { - /* If displacement is coming from this node group we need to perform - * some internal re-linking in order to avoid cycles. - */ - bNode *group_output_node = ntreeFindType(group_ntree, NODE_GROUP_OUTPUT); - if (group_output_node == NULL) { - return; - } - bNodeSocket *group_output_node_displacement_socket = - nodeFindSocket(group_output_node, - SOCK_IN, - displacement_socket->identifier); - bNodeLink *group_displacement_link = group_output_node_displacement_socket->link; - if (group_displacement_link == NULL) { - /* Displacement output is not connected to anything, can just stop - * right away. - */ - return; - } - /* This code is similar to ntree_shader_relink_displacement() */ - bNode *group_displacement_node = group_displacement_link->fromnode; - bNodeSocket *group_displacement_socket = group_displacement_link->fromsock; - /* Create and link bump node. - * Can't re-use bump node from parent tree because it'll cause cycle. - */ - bNode *bump_node = nodeAddStaticNode(NULL, group_ntree, SH_NODE_BUMP); - bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height"); - bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal"); - BLI_assert(bump_input_socket != NULL); - BLI_assert(bump_output_socket != NULL); - nodeAddLink(group_ntree, - group_displacement_node, group_displacement_socket, - bump_node, bump_input_socket); - /* Relink normals inside of the instanced tree. */ - ntree_shader_link_builtin_normal(group_ntree, - bump_node, - bump_output_socket, - group_displacement_node, - group_displacement_socket); - ntreeUpdateTree(G.main, group_ntree); - } - else if (group_input_node) { - /* Connect group node normal input. */ - nodeAddLink(ntree, - node_from, socket_from, - group_node, group_node_normal_socket); - BLI_assert(group_input_node != NULL); - bNodeSocket *group_input_node_normal_socket = - nodeFindSocket(group_input_node, - SOCK_OUT, - group_normal_socket->identifier); - BLI_assert(group_input_node_normal_socket != NULL); - /* Relink normals inside of the instanced tree. */ - ntree_shader_link_builtin_normal(group_ntree, - group_input_node, - group_input_node_normal_socket, - displacement_node, - displacement_socket); - ntreeUpdateTree(G.main, group_ntree); - } + bNodeTree *group_ntree = (bNodeTree *)group_node->id; + /* Create input socket to plug displacement connection to. */ + bNodeSocket *group_normal_socket = ntreeAddSocketInterface( + group_ntree, SOCK_IN, "NodeSocketVector", "Normal"); + /* Need to update tree so all node instances nodes gets proper sockets. */ + bNode *group_input_node = ntreeFindType(group_ntree, NODE_GROUP_INPUT); + node_group_verify(ntree, group_node, &group_ntree->id); + if (group_input_node) + node_group_input_verify(group_ntree, group_input_node, &group_ntree->id); + ntreeUpdateTree(G.main, group_ntree); + /* Assumes sockets are always added at the end. */ + bNodeSocket *group_node_normal_socket = group_node->inputs.last; + if (displacement_node == group_node) { + /* If displacement is coming from this node group we need to perform + * some internal re-linking in order to avoid cycles. + */ + bNode *group_output_node = ntreeFindType(group_ntree, NODE_GROUP_OUTPUT); + if (group_output_node == NULL) { + return; + } + bNodeSocket *group_output_node_displacement_socket = nodeFindSocket( + group_output_node, SOCK_IN, displacement_socket->identifier); + bNodeLink *group_displacement_link = group_output_node_displacement_socket->link; + if (group_displacement_link == NULL) { + /* Displacement output is not connected to anything, can just stop + * right away. + */ + return; + } + /* This code is similar to ntree_shader_relink_displacement() */ + bNode *group_displacement_node = group_displacement_link->fromnode; + bNodeSocket *group_displacement_socket = group_displacement_link->fromsock; + /* Create and link bump node. + * Can't re-use bump node from parent tree because it'll cause cycle. + */ + bNode *bump_node = nodeAddStaticNode(NULL, group_ntree, SH_NODE_BUMP); + bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height"); + bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal"); + BLI_assert(bump_input_socket != NULL); + BLI_assert(bump_output_socket != NULL); + nodeAddLink(group_ntree, + group_displacement_node, + group_displacement_socket, + bump_node, + bump_input_socket); + /* Relink normals inside of the instanced tree. */ + ntree_shader_link_builtin_normal(group_ntree, + bump_node, + bump_output_socket, + group_displacement_node, + group_displacement_socket); + ntreeUpdateTree(G.main, group_ntree); + } + else if (group_input_node) { + /* Connect group node normal input. */ + nodeAddLink(ntree, node_from, socket_from, group_node, group_node_normal_socket); + BLI_assert(group_input_node != NULL); + bNodeSocket *group_input_node_normal_socket = nodeFindSocket( + group_input_node, SOCK_OUT, group_normal_socket->identifier); + BLI_assert(group_input_node_normal_socket != NULL); + /* Relink normals inside of the instanced tree. */ + ntree_shader_link_builtin_normal(group_ntree, + group_input_node, + group_input_node_normal_socket, + displacement_node, + displacement_socket); + ntreeUpdateTree(G.main, group_ntree); + } } /* Use specified node and socket as an input for unconnected normal sockets. */ @@ -669,27 +644,23 @@ static void ntree_shader_link_builtin_normal(bNodeTree *ntree, bNode *displacement_node, bNodeSocket *displacement_socket) { - for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) { - if (node == node_from) { - /* Don't connect node itself! */ - continue; - } - if ((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id) { - /* Special re-linking for group nodes. */ - ntree_shader_link_builtin_group_normal(ntree, - node, - node_from, - socket_from, - displacement_node, - displacement_socket); - continue; - } - if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) { - /* Group inputs and outputs needs nothing special. */ - continue; - } - ntree_shader_relink_node_normal(ntree, node, node_from, socket_from); - } + for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) { + if (node == node_from) { + /* Don't connect node itself! */ + continue; + } + if ((ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) && node->id) { + /* Special re-linking for group nodes. */ + ntree_shader_link_builtin_group_normal( + ntree, node, node_from, socket_from, displacement_node, displacement_socket); + continue; + } + if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) { + /* Group inputs and outputs needs nothing special. */ + continue; + } + ntree_shader_relink_node_normal(ntree, node, node_from, socket_from); + } } /* Re-link displacement output to unconnected normal sockets via bump node. @@ -697,107 +668,101 @@ static void ntree_shader_link_builtin_normal(bNodeTree *ntree, */ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_node) { - bNode *displacement_node; - bNodeSocket *displacement_socket; - bNodeLink *displacement_link; - if (!ntree_shader_has_displacement(ntree, - output_node, - &displacement_node, - &displacement_socket, - &displacement_link)) - { - /* There is no displacement output connected, nothing to re-link. */ - return; - } - /* We have to disconnect displacement output socket, otherwise we'll have - * cycles in the Cycles material :) - */ - nodeRemLink(ntree, displacement_link); - - /* Convert displacement vector to bump height. */ - bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECT_MATH); - bNode *geo_node = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY); - dot_node->custom1 = 3; /* dot product */ - - nodeAddLink(ntree, - displacement_node, displacement_socket, - dot_node, dot_node->inputs.first); - nodeAddLink(ntree, - geo_node, ntree_shader_node_find_output(geo_node, "Normal"), - dot_node, dot_node->inputs.last); - displacement_node = dot_node; - displacement_socket = ntree_shader_node_find_output(dot_node, "Value"); - - /* We can't connect displacement to normal directly, use bump node for that - * and hope that it gives good enough approximation. - */ - bNode *bump_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BUMP); - bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height"); - bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal"); - BLI_assert(bump_input_socket != NULL); - BLI_assert(bump_output_socket != NULL); - /* Connect bump node to where displacement output was originally - * connected to. - */ - nodeAddLink(ntree, - displacement_node, displacement_socket, - bump_node, bump_input_socket); - /* Connect all free-standing Normal inputs. */ - ntree_shader_link_builtin_normal(ntree, - bump_node, - bump_output_socket, - displacement_node, - displacement_socket); - /* TODO(sergey): Reconnect Geometry Info->Normal sockets to the new - * bump node. - */ - /* We modified the tree, it needs to be updated now. */ - ntreeUpdateTree(G.main, ntree); + bNode *displacement_node; + bNodeSocket *displacement_socket; + bNodeLink *displacement_link; + if (!ntree_shader_has_displacement( + ntree, output_node, &displacement_node, &displacement_socket, &displacement_link)) { + /* There is no displacement output connected, nothing to re-link. */ + return; + } + /* We have to disconnect displacement output socket, otherwise we'll have + * cycles in the Cycles material :) + */ + nodeRemLink(ntree, displacement_link); + + /* Convert displacement vector to bump height. */ + bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECT_MATH); + bNode *geo_node = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY); + dot_node->custom1 = 3; /* dot product */ + + nodeAddLink(ntree, displacement_node, displacement_socket, dot_node, dot_node->inputs.first); + nodeAddLink(ntree, + geo_node, + ntree_shader_node_find_output(geo_node, "Normal"), + dot_node, + dot_node->inputs.last); + displacement_node = dot_node; + displacement_socket = ntree_shader_node_find_output(dot_node, "Value"); + + /* We can't connect displacement to normal directly, use bump node for that + * and hope that it gives good enough approximation. + */ + bNode *bump_node = nodeAddStaticNode(NULL, ntree, SH_NODE_BUMP); + bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height"); + bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal"); + BLI_assert(bump_input_socket != NULL); + BLI_assert(bump_output_socket != NULL); + /* Connect bump node to where displacement output was originally + * connected to. + */ + nodeAddLink(ntree, displacement_node, displacement_socket, bump_node, bump_input_socket); + /* Connect all free-standing Normal inputs. */ + ntree_shader_link_builtin_normal( + ntree, bump_node, bump_output_socket, displacement_node, displacement_socket); + /* TODO(sergey): Reconnect Geometry Info->Normal sockets to the new + * bump node. + */ + /* We modified the tree, it needs to be updated now. */ + ntreeUpdateTree(G.main, ntree); } -static bool ntree_tag_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed)) +static bool ntree_tag_bsdf_cb(bNode *fromnode, + bNode *UNUSED(tonode), + void *userdata, + const bool UNUSED(reversed)) { - /* Don't evaluate nodes more than once. */ - if (fromnode->tmp_flag) { - return true; - } - fromnode->tmp_flag = 1; - - switch (fromnode->type) { - case NODE_GROUP: - case NODE_CUSTOM_GROUP: - /* Recursive */ - if (fromnode->id != NULL) { - bNodeTree *ntree = (bNodeTree *)fromnode->id; - bNode *group_output = ntree_group_output_node(ntree); - ntree_shader_tag_nodes(ntree, group_output, (nTreeTags *)userdata); - } - break; - case SH_NODE_BSDF_ANISOTROPIC: - case SH_NODE_EEVEE_SPECULAR: - case SH_NODE_BSDF_GLOSSY: - case SH_NODE_BSDF_GLASS: - fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id; - ((nTreeTags *)userdata)->ssr_id += 1; - break; - case SH_NODE_SUBSURFACE_SCATTERING: - fromnode->sss_id = ((nTreeTags *)userdata)->sss_id; - ((nTreeTags *)userdata)->sss_id += 1; - break; - case SH_NODE_BSDF_PRINCIPLED: - fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id; - fromnode->sss_id = ((nTreeTags *)userdata)->sss_id; - ((nTreeTags *)userdata)->sss_id += 1; - ((nTreeTags *)userdata)->ssr_id += 1; - break; - default: - /* We could return false here but since we - * allow the use of Closure as RGBA, we can have - * Bsdf nodes linked to other Bsdf nodes. */ - break; - } - - return true; + /* Don't evaluate nodes more than once. */ + if (fromnode->tmp_flag) { + return true; + } + fromnode->tmp_flag = 1; + + switch (fromnode->type) { + case NODE_GROUP: + case NODE_CUSTOM_GROUP: + /* Recursive */ + if (fromnode->id != NULL) { + bNodeTree *ntree = (bNodeTree *)fromnode->id; + bNode *group_output = ntree_group_output_node(ntree); + ntree_shader_tag_nodes(ntree, group_output, (nTreeTags *)userdata); + } + break; + case SH_NODE_BSDF_ANISOTROPIC: + case SH_NODE_EEVEE_SPECULAR: + case SH_NODE_BSDF_GLOSSY: + case SH_NODE_BSDF_GLASS: + fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id; + ((nTreeTags *)userdata)->ssr_id += 1; + break; + case SH_NODE_SUBSURFACE_SCATTERING: + fromnode->sss_id = ((nTreeTags *)userdata)->sss_id; + ((nTreeTags *)userdata)->sss_id += 1; + break; + case SH_NODE_BSDF_PRINCIPLED: + fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id; + fromnode->sss_id = ((nTreeTags *)userdata)->sss_id; + ((nTreeTags *)userdata)->sss_id += 1; + ((nTreeTags *)userdata)->ssr_id += 1; + break; + default: + /* We could return false here but since we + * allow the use of Closure as RGBA, we can have + * Bsdf nodes linked to other Bsdf nodes. */ + break; + } + + return true; } /* EEVEE: Scan the ntree to set the Screen Space Reflection @@ -805,162 +770,168 @@ static bool ntree_tag_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *user */ void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tags) { - if (output_node == NULL) { - return; - } - /* Make sure sockets links pointers are correct. */ - ntreeUpdateTree(G.main, ntree); - - /* Reset visit flag. */ - for (bNode *node = ntree->nodes.first; node; node = node->next) { - node->tmp_flag = 0; - } - - nodeChainIter(ntree, output_node, ntree_tag_bsdf_cb, tags, true); + if (output_node == NULL) { + return; + } + /* Make sure sockets links pointers are correct. */ + ntreeUpdateTree(G.main, ntree); + + /* Reset visit flag. */ + for (bNode *node = ntree->nodes.first; node; node = node->next) { + node->tmp_flag = 0; + } + + nodeChainIter(ntree, output_node, ntree_tag_bsdf_cb, tags, true); } /* This one needs to work on a local tree. */ -void ntreeGPUMaterialNodes(bNodeTree *localtree, GPUMaterial *mat, bool *has_surface_output, bool *has_volume_output) +void ntreeGPUMaterialNodes(bNodeTree *localtree, + GPUMaterial *mat, + bool *has_surface_output, + bool *has_volume_output) { - bNodeTreeExec *exec; + bNodeTreeExec *exec; - /* Extract output nodes from inside nodegroups. */ - ntree_shader_output_node_from_group(localtree, SHD_OUTPUT_EEVEE); + /* Extract output nodes from inside nodegroups. */ + ntree_shader_output_node_from_group(localtree, SHD_OUTPUT_EEVEE); - bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE); + bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE); - ntree_shader_groups_expand_inputs(localtree); + ntree_shader_groups_expand_inputs(localtree); - /* Perform all needed modifications on the tree in order to support - * displacement/bump mapping. - */ - ntree_shader_relink_displacement(localtree, output); + /* Perform all needed modifications on the tree in order to support + * displacement/bump mapping. + */ + ntree_shader_relink_displacement(localtree, output); - /* TODO(fclem): consider moving this to the gpu shader tree evaluation. */ - nTreeTags tags = { - .ssr_id = 1.0, - .sss_id = 1.0, - }; - ntree_shader_tag_nodes(localtree, output, &tags); + /* TODO(fclem): consider moving this to the gpu shader tree evaluation. */ + nTreeTags tags = { + .ssr_id = 1.0, + .sss_id = 1.0, + }; + ntree_shader_tag_nodes(localtree, output, &tags); - exec = ntreeShaderBeginExecTree(localtree); - ntreeExecGPUNodes(exec, mat, output); - ntreeShaderEndExecTree(exec); + exec = ntreeShaderBeginExecTree(localtree); + ntreeExecGPUNodes(exec, mat, output); + ntreeShaderEndExecTree(exec); - /* EEVEE: Find which material domain was used (volume, surface ...). */ - *has_surface_output = false; - *has_volume_output = false; + /* EEVEE: Find which material domain was used (volume, surface ...). */ + *has_surface_output = false; + *has_volume_output = false; - if (output != NULL) { - bNodeSocket *surface_sock = ntree_shader_node_find_input(output, "Surface"); - bNodeSocket *volume_sock = ntree_shader_node_find_input(output, "Volume"); + if (output != NULL) { + bNodeSocket *surface_sock = ntree_shader_node_find_input(output, "Surface"); + bNodeSocket *volume_sock = ntree_shader_node_find_input(output, "Volume"); - if (surface_sock != NULL) { - *has_surface_output = (nodeCountSocketLinks(localtree, surface_sock) > 0); - } + if (surface_sock != NULL) { + *has_surface_output = (nodeCountSocketLinks(localtree, surface_sock) > 0); + } - if (volume_sock != NULL) { - *has_volume_output = (nodeCountSocketLinks(localtree, volume_sock) > 0); - } - } + if (volume_sock != NULL) { + *has_volume_output = (nodeCountSocketLinks(localtree, volume_sock) > 0); + } + } } -bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key) +bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, + bNodeTree *ntree, + bNodeInstanceKey parent_key) { - bNodeTreeExec *exec; - bNode *node; + bNodeTreeExec *exec; + bNode *node; - /* ensures only a single output node is enabled */ - ntreeSetOutput(ntree); + /* ensures only a single output node is enabled */ + ntreeSetOutput(ntree); - /* common base initialization */ - exec = ntree_exec_begin(context, ntree, parent_key); + /* common base initialization */ + exec = ntree_exec_begin(context, ntree, parent_key); - /* allocate the thread stack listbase array */ - exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); + /* allocate the thread stack listbase array */ + exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); - for (node = exec->nodetree->nodes.first; node; node = node->next) - node->need_exec = 1; + for (node = exec->nodetree->nodes.first; node; node = node->next) + node->need_exec = 1; - return exec; + return exec; } bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree) { - bNodeExecContext context; - bNodeTreeExec *exec; + bNodeExecContext context; + bNodeTreeExec *exec; - /* XXX hack: prevent exec data from being generated twice. - * this should be handled by the renderer! - */ - if (ntree->execdata) - return ntree->execdata; + /* XXX hack: prevent exec data from being generated twice. + * this should be handled by the renderer! + */ + if (ntree->execdata) + return ntree->execdata; - context.previews = ntree->previews; + context.previews = ntree->previews; - exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE); + exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE); - /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, - * which only store the ntree pointer. Should be fixed at some point! - */ - ntree->execdata = exec; + /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, + * which only store the ntree pointer. Should be fixed at some point! + */ + ntree->execdata = exec; - return exec; + return exec; } void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec) { - bNodeThreadStack *nts; - int a; - - if (exec->threadstack) { - for (a = 0; a < BLENDER_MAX_THREADS; a++) { - for (nts = exec->threadstack[a].first; nts; nts = nts->next) - if (nts->stack) MEM_freeN(nts->stack); - BLI_freelistN(&exec->threadstack[a]); - } - - MEM_freeN(exec->threadstack); - exec->threadstack = NULL; - } - - ntree_exec_end(exec); + bNodeThreadStack *nts; + int a; + + if (exec->threadstack) { + for (a = 0; a < BLENDER_MAX_THREADS; a++) { + for (nts = exec->threadstack[a].first; nts; nts = nts->next) + if (nts->stack) + MEM_freeN(nts->stack); + BLI_freelistN(&exec->threadstack[a]); + } + + MEM_freeN(exec->threadstack); + exec->threadstack = NULL; + } + + ntree_exec_end(exec); } void ntreeShaderEndExecTree(bNodeTreeExec *exec) { - if (exec) { - /* exec may get freed, so assign ntree */ - bNodeTree *ntree = exec->nodetree; - ntreeShaderEndExecTree_internal(exec); - - /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ - ntree->execdata = NULL; - } + if (exec) { + /* exec may get freed, so assign ntree */ + bNodeTree *ntree = exec->nodetree; + ntreeShaderEndExecTree_internal(exec); + + /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ + ntree->execdata = NULL; + } } /* TODO: left over from Blender Internal, could reuse for new texture nodes. */ bool ntreeShaderExecTree(bNodeTree *ntree, int thread) { - ShaderCallData scd; - bNodeThreadStack *nts = NULL; - bNodeTreeExec *exec = ntree->execdata; - int compat; - - /* ensure execdata is only initialized once */ - if (!exec) { - BLI_thread_lock(LOCK_NODES); - if (!ntree->execdata) - ntree->execdata = ntreeShaderBeginExecTree(ntree); - BLI_thread_unlock(LOCK_NODES); - - exec = ntree->execdata; - } - - nts = ntreeGetThreadStack(exec, thread); - compat = ntreeExecThreadNodes(exec, nts, &scd, thread); - ntreeReleaseThreadStack(nts); - - /* if compat is zero, it has been using non-compatible nodes */ - return compat; + ShaderCallData scd; + bNodeThreadStack *nts = NULL; + bNodeTreeExec *exec = ntree->execdata; + int compat; + + /* ensure execdata is only initialized once */ + if (!exec) { + BLI_thread_lock(LOCK_NODES); + if (!ntree->execdata) + ntree->execdata = ntreeShaderBeginExecTree(ntree); + BLI_thread_unlock(LOCK_NODES); + + exec = ntree->execdata; + } + + nts = ntreeGetThreadStack(exec, thread); + compat = ntreeExecThreadNodes(exec, nts, &scd, thread); + ntreeReleaseThreadStack(nts); + + /* if compat is zero, it has been using non-compatible nodes */ + return compat; } |