Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c114
1 files changed, 113 insertions, 1 deletions
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 26973d619d9..311bf43f3e8 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -36,6 +36,7 @@
#include "BLI_listbase.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
#include "BLT_translation.h"
@@ -202,6 +203,113 @@ 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 bNode *ntree_group_output_node(bNodeTree *ntree);
+
+static bNode *ntree_shader_relink_output_from_group(bNodeTree *ntree,
+ bNode *group_node,
+ 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))
+ {
+ nodeFreeNode(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)){
+ 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.
*
* NOTE: it will only return output which is NOT in the group, which isn't how
@@ -694,9 +802,13 @@ void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tag
/* This one needs to work on a local tree. */
void ntreeGPUMaterialNodes(bNodeTree *localtree, GPUMaterial *mat, bool *has_surface_output, bool *has_volume_output)
{
- bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE);
bNodeTreeExec *exec;
+ /* Extract output nodes from inside nodegroups. */
+ ntree_shader_output_node_from_group(localtree, SHD_OUTPUT_EEVEE);
+
+ bNode *output = ntreeShaderOutputNode(localtree, SHD_OUTPUT_EEVEE);
+
ntree_shader_groups_expand_inputs(localtree);
/* Perform all needed modifications on the tree in order to support