diff options
Diffstat (limited to 'source/blender/nodes')
-rw-r--r-- | source/blender/nodes/CMakeLists.txt | 4 | ||||
-rw-r--r-- | source/blender/nodes/NOD_composite.h | 4 | ||||
-rw-r--r-- | source/blender/nodes/composite/node_composite_tree.c | 35 | ||||
-rw-r--r-- | source/blender/nodes/composite/nodes/node_composite_image.c | 544 |
4 files changed, 269 insertions, 318 deletions
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 3596a2aa12d..c5a3c70100b 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -289,8 +289,4 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() -if(WITH_CYCLES AND WITH_CYCLES_DEBUG) - add_definitions(-DWITH_CYCLES_DEBUG) -endif() - blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 0215db1dd55..a5c2e604f46 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -139,6 +139,8 @@ void register_node_type_cmp_trackpos(void); void register_node_type_cmp_planetrackdeform(void); void register_node_type_cmp_cornerpin(void); -void node_cmp_rlayers_force_hidden_passes(struct bNode *node); +void node_cmp_rlayers_outputs(struct bNodeTree *ntree, struct bNode *node); +void node_cmp_rlayers_register_pass(struct bNodeTree *ntree, struct bNode *node, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type); +const char *node_cmp_rlayers_sock_to_pass(int sock_index); #endif diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index cb565bd5491..36778a18f77 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -240,8 +240,15 @@ void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int r /* *********************************************** */ -/* based on rules, force sockets hidden always */ -void ntreeCompositForceHidden(bNodeTree *ntree) +/* Update the outputs of the render layer nodes. + * Since the outputs depend on the render engine, this part is a bit complex: + * - ntreeCompositUpdateRLayers is called and loops over all render layer nodes + * - Each render layer node calls the update function of the render engine that's used for its scene + * - The render engine calls RE_engine_register_pass for each pass + * - RE_engine_register_pass calls ntreeCompositRegisterPass, + * which calls node_cmp_rlayers_register_pass for every render layer node + */ +void ntreeCompositUpdateRLayers(bNodeTree *ntree) { bNode *node; @@ -249,16 +256,20 @@ void ntreeCompositForceHidden(bNodeTree *ntree) for (node = ntree->nodes.first; node; node = node->next) { if (node->type == CMP_NODE_R_LAYERS) - node_cmp_rlayers_force_hidden_passes(node); - - /* XXX this stuff is called all the time, don't want that. - * Updates should only happen when actually necessary. - */ -#if 0 - else if (node->type == CMP_NODE_IMAGE) { - nodeUpdate(ntree, node); - } -#endif + node_cmp_rlayers_outputs(ntree, node); + } + +} + +void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, SceneRenderLayer *srl, const char *name, int type) +{ + bNode *node; + + if (ntree == NULL) return; + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_R_LAYERS) + node_cmp_rlayers_register_pass(ntree, node, scene, srl, name, type); } } diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 4f02c106569..510e24554f0 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -32,192 +32,104 @@ #include "node_composite_util.h" #include "BLI_utildefines.h" +#include "BLI_linklist.h" #include "DNA_scene_types.h" +#include "RE_engine.h" + #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" -#ifdef WITH_CYCLES_DEBUG -# include "RE_pipeline.h" -#endif - /* **************** IMAGE (and RenderResult, multilayer image) ******************** */ static bNodeSocketTemplate cmp_node_rlayers_out[] = { - { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Z"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, N_("UV"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, N_("Speed"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Specular"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Shadow"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("AO"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Reflect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Refract"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("IndexOB"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("IndexMA"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Mist"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Emit"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Environment"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Glossy Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Glossy Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Glossy Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Transmission Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Transmission Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Transmission Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Subsurface Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Subsurface Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Subsurface Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, -#ifdef WITH_CYCLES_DEBUG - { SOCK_RGBA, 0, N_("Debug"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, -#endif + { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_Z), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_(RE_PASSNAME_NORMAL), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_(RE_PASSNAME_UV), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_(RE_PASSNAME_VECTOR), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_RGBA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SPEC), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SHADOW), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_AO), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_REFLECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_REFRACT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXOB), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXMA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_MIST), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_EMIT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_ENVIRONMENT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int pass, int rres_index) +static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node, + const char *name, const char *passname, + int rres_index, int type, int is_rlayers, + LinkNodePair *available_sockets, int *prev_index) { bNodeSocket *sock; - NodeImageLayer *sockdata; - - sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT); - /* extra socket info */ - sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); - sock->storage = sockdata; - - sockdata->pass_flag = pass; - - return sock; -} - -static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag) -{ - if (passflag & SCE_PASS_COMBINED) { - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE); - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA); - } - - if (passflag & SCE_PASS_Z) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z); - if (passflag & SCE_PASS_NORMAL) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL); - if (passflag & SCE_PASS_VECTOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC); - if (passflag & SCE_PASS_UV) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV); - if (passflag & SCE_PASS_RGBA) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA); - if (passflag & SCE_PASS_DIFFUSE) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF); - if (passflag & SCE_PASS_SPEC) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC); - if (passflag & SCE_PASS_SHADOW) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW); - if (passflag & SCE_PASS_AO) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO); - if (passflag & SCE_PASS_REFLECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT); - if (passflag & SCE_PASS_REFRACT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT); - if (passflag & SCE_PASS_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT); - if (passflag & SCE_PASS_INDEXOB) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB); - if (passflag & SCE_PASS_INDEXMA) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA); - if (passflag & SCE_PASS_MIST) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST); - if (passflag & SCE_PASS_EMIT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT); - if (passflag & SCE_PASS_ENVIRONMENT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV); - - if (passflag & SCE_PASS_DIFFUSE_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT); - if (passflag & SCE_PASS_DIFFUSE_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT); - if (passflag & SCE_PASS_DIFFUSE_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR); - - if (passflag & SCE_PASS_GLOSSY_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT); - if (passflag & SCE_PASS_GLOSSY_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT); - if (passflag & SCE_PASS_GLOSSY_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR); - - if (passflag & SCE_PASS_TRANSM_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT); - if (passflag & SCE_PASS_TRANSM_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT); - if (passflag & SCE_PASS_TRANSM_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR); - - if (passflag & SCE_PASS_SUBSURFACE_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_DIRECT, RRES_OUT_SUBSURFACE_DIRECT); - if (passflag & SCE_PASS_SUBSURFACE_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_INDIRECT, RRES_OUT_SUBSURFACE_INDIRECT); - if (passflag & SCE_PASS_SUBSURFACE_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_COLOR, RRES_OUT_SUBSURFACE_COLOR); - -#ifdef WITH_CYCLES_DEBUG - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DEBUG, RRES_OUT_DEBUG); -#endif -} - -static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl) -{ - bNodeSocket *sock; - NodeImageLayer *sockdata; - RenderPass *rpass; - int index; - int passflag = 0; - for (rpass = rl->passes.first, index = 0; rpass; rpass = rpass->next, ++index) { - int type; - if (rpass->channels == 1) - type = SOCK_FLOAT; - else - type = SOCK_RGBA; - - /* we only need one socket per type */ - if (passflag & rpass->passtype) - continue; - - passflag |= rpass->passtype; - - sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->internal_name, rpass->internal_name); + int sock_index = BLI_findstringindex(&node->outputs, name, offsetof(bNodeSocket, name)); + + if (sock_index < 0) { + /* The first 31 sockets always are the legacy hardcoded sockets. + * Any dynamically allocated sockets follow afterwards, and are sorted in the order in which they were stored in the RenderResult. + * Therefore, we remember the index of the last matched socket. New sockets are placed behind the previously traversed one, but always after the first 31. */ + int after_index = *prev_index; + if (is_rlayers && after_index < 30) + after_index = 30; + + if (rres_index >= 0) { + sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT); + } + else { + sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, name, name); + } /* extra socket info */ - sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); + NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); sock->storage = sockdata; - - sockdata->pass_index = index; - sockdata->pass_flag = rpass->passtype; - - if (rpass->passtype == SCE_PASS_COMBINED) { - sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_FLOAT, PROP_NONE, "Alpha", "Alpha"); - sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); - sock->storage = sockdata; - sockdata->pass_index = index; - sockdata->pass_flag = rpass->passtype; + + BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name)); + + sock_index = BLI_listbase_count(&node->outputs)-1; + if (sock_index != after_index+1) { + bNodeSocket *after_sock = BLI_findlink(&node->outputs, after_index); + BLI_remlink(&node->outputs, sock); + BLI_insertlinkafter(&node->outputs, after_sock, sock); } } + else { + sock = BLI_findlink(&node->outputs, sock_index); + } + + BLI_linklist_append(available_sockets, sock); + *prev_index = sock_index; } -static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) +static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets) { Image *ima = (Image *)node->id; + ImBuf *ibuf; + int prev_index = -1; if (ima) { ImageUser *iuser = node->storage; ImageUser load_iuser = {NULL}; - ImBuf *ibuf; int offset = BKE_image_sequence_guess_offset(ima); /* It is possible that image user in this node is not @@ -238,104 +150,150 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) RenderLayer *rl = BLI_findlink(&ima->rr->layers, iuser->layer); if (rl) { - if (ima->type != IMA_TYPE_MULTILAYER) - cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag); - else - cmp_node_image_add_multilayer_outputs(ntree, node, rl); + RenderPass *rpass; + for (rpass = rl->passes.first; rpass; rpass = rpass->next) { + int type; + if (rpass->channels == 1) + type = SOCK_FLOAT; + else + type = SOCK_RGBA; + + /* Special handling for the Combined pass to ensure compatibility. */ + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { + cmp_node_image_add_pass_output(ntree, node, "Image", rpass->name, -1, type, false, available_sockets, &prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", rpass->name, -1, SOCK_FLOAT, false, available_sockets, &prev_index); + } + else { + cmp_node_image_add_pass_output(ntree, node, rpass->name, rpass->name, -1, type, false, available_sockets, &prev_index); + } + } + BKE_image_release_ibuf(ima, ibuf, NULL); + return; } - else - cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA); } - else - cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA | RRES_OUT_Z); - + } + + cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, false, available_sockets, &prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, false, available_sockets, &prev_index); + + if (ima) { + if (!ima->rr) { + cmp_node_image_add_pass_output(ntree, node, RE_PASSNAME_Z, RE_PASSNAME_Z, RRES_OUT_Z, SOCK_FLOAT, false, available_sockets, &prev_index); + } BKE_image_release_ibuf(ima, ibuf, NULL); } - else - cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA); } -static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist) -{ - bNodeSocket *sock; - - for (sock = oldsocklist->first; sock; sock = sock->next) - if (STREQ(sock->name, newsock->name)) - return sock; - return NULL; -} +typedef struct RLayerUpdateData { + LinkNodePair *available_sockets; + int prev_index; +} RLayerUpdateData; -static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex) +void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, SceneRenderLayer *srl, const char *name, int type) { - bNodeSocket *sock; - - /* first try to find matching socket name */ - for (sock = node->outputs.first; sock; sock = sock->next) - if (STREQ(sock->name, oldsock->name)) - return sock; - - /* no matching name, simply link to same index */ - return BLI_findlink(&node->outputs, oldindex); + RLayerUpdateData *data = node->storage; + + if (scene == NULL || srl == NULL || data == NULL || node->id != scene) { + return; + } + + SceneRenderLayer *node_srl = BLI_findlink(&scene->r.layers, node->custom1); + if (node_srl != srl) { + return; + } + + /* Special handling for the Combined pass to ensure compatibility. */ + if (STREQ(name, RE_PASSNAME_COMBINED)) { + cmp_node_image_add_pass_output(ntree, node, "Image", name, -1, type, true, data->available_sockets, &data->prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", name, -1, SOCK_FLOAT, true, data->available_sockets, &data->prev_index); + } + else { + cmp_node_image_add_pass_output(ntree, node, name, name, -1, type, true, data->available_sockets, &data->prev_index); + } } -static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock)) +static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets) { - /* pass */ + Scene *scene = (Scene *)node->id; + + if (scene) { + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + if(engine_type && engine_type->update_render_passes) { + SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, node->custom1); + if(srl) { + RLayerUpdateData *data = MEM_mallocN(sizeof(RLayerUpdateData), "render layer update data"); + data->available_sockets = available_sockets; + data->prev_index = -1; + node->storage = data; + + RenderEngine *engine = RE_engine_create(engine_type); + engine_type->update_render_passes(engine, scene, srl); + RE_engine_free(engine); + + MEM_freeN(data); + node->storage = NULL; + + return; + } + } + } + + int prev_index = -1; + cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, true, available_sockets, &prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, true, available_sockets, &prev_index); } /* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */ -static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node) +static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rlayer) { - bNodeSocket *newsock, *oldsock, *oldsock_next; - ListBase oldsocklist; - int oldindex; - bNodeLink *link; - - /* store current nodes in oldsocklist, then clear socket list */ - oldsocklist = node->outputs; - BLI_listbase_clear(&node->outputs); + bNodeSocket *sock, *sock_next; + LinkNodePair available_sockets = {NULL, NULL}; + int sock_index; /* XXX make callback */ - cmp_node_image_create_outputs(ntree, node); - - for (newsock = node->outputs.first; newsock; newsock = newsock->next) { - /* XXX make callback */ - oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist); - if (oldsock) { - /* XXX make callback */ - cmp_node_image_sync_output(node, newsock, oldsock); + if (rlayer) + cmp_node_rlayer_create_outputs(ntree, node, &available_sockets); + else + cmp_node_image_create_outputs(ntree, node, &available_sockets); + + /* Get rid of sockets whose passes are not available in the image. + * If sockets that are not available would be deleted, the connections to them would be lost + * when e.g. opening a file (since there's no render at all yet). + * Therefore, sockets with connected links will just be set as unavailable. + * + * Another important detail comes from compatibility with the older socket model, where there + * was a fixed socket per pass type that was just hidden or not. Therefore, older versions expect + * the first 31 passes to belong to a specific pass type. + * So, we keep those 31 always allocated before the others as well, even if they have no links attached. */ + sock_index = 0; + for (sock = node->outputs.first; sock; sock = sock_next, sock_index++) { + sock_next = sock->next; + if (BLI_linklist_index(available_sockets.list, sock) >= 0) { + sock->flag &= ~(SOCK_UNAVAIL | SOCK_HIDDEN); } - } - - /* move links to new socket */ - for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) { - newsock = cmp_node_image_output_relink(node, oldsock, oldindex); - - if (newsock) { + else { + bNodeLink *link; for (link = ntree->links.first; link; link = link->next) { - if (link->fromsock == oldsock) - link->fromsock = newsock; + if (link->fromsock == sock) break; + } + if (!link && sock_index > 30) { + MEM_freeN(sock->storage); + nodeRemoveSocket(ntree, node, sock); + } + else { + sock->flag |= SOCK_UNAVAIL; } } } - - /* delete old sockets - * XXX oldsock is not actually in the node->outputs list any more, - * but the nodeRemoveSocket function works anyway. In future this - * should become part of the core code, so can take care of this behavior. - */ - for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) { - oldsock_next = oldsock->next; - MEM_freeN(oldsock->storage); - nodeRemoveSocket(ntree, node, oldsock); - } + + BLI_linklist_free(available_sockets.list, NULL); } static void cmp_node_image_update(bNodeTree *ntree, bNode *node) { /* avoid unnecessary updates, only changes to the image/image user data are of interest */ if (node->update & NODE_UPDATE_ID) - cmp_node_image_verify_outputs(ntree, node); + cmp_node_image_verify_outputs(ntree, node, false); } static void node_composit_init_image(bNodeTree *ntree, bNode *node) @@ -348,7 +306,7 @@ static void node_composit_init_image(bNodeTree *ntree, bNode *node) iuser->ok = 1; /* setup initial outputs */ - cmp_node_image_verify_outputs(ntree, node); + cmp_node_image_verify_outputs(ntree, node, false); } static void node_composit_free_image(bNode *node) @@ -388,87 +346,45 @@ void register_node_type_cmp_image(void) /* **************** RENDER RESULT ******************** */ -static void set_output_visible(bNode *node, int passflag, int index, int pass) +void node_cmp_rlayers_outputs(bNodeTree *ntree, bNode *node) { - bNodeSocket *sock = BLI_findlink(&node->outputs, index); - bool pass_enabled = ((passflag & pass) != 0); -#ifdef WITH_CYCLES_DEBUG - pass_enabled |= (pass == SCE_PASS_DEBUG); -#endif - /* clear the SOCK_HIDDEN flag as well, in case a socket was hidden before */ - if (pass_enabled) - sock->flag &= ~(SOCK_HIDDEN | SOCK_UNAVAIL); - else - sock->flag |= SOCK_UNAVAIL; + cmp_node_image_verify_outputs(ntree, node, true); } -/* clumsy checking... should do dynamic outputs once */ -void node_cmp_rlayers_force_hidden_passes(bNode *node) +const char* node_cmp_rlayers_sock_to_pass(int sock_index) { - Scene *scene = (Scene *)node->id; - SceneRenderLayer *srl; - int passflag; - bNodeSocket *sock; - - /* must always have valid scene pointer */ - if (!scene) - return; - - srl = BLI_findlink(&scene->r.layers, node->custom1); - if (!srl) - return; - - passflag = srl->passflag; - - for (sock = node->outputs.first; sock; sock = sock->next) - sock->flag &= ~SOCK_UNAVAIL; - - set_output_visible(node, passflag, RRES_OUT_IMAGE, SCE_PASS_COMBINED); - set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED); - - set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z); - set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL); - set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR); - set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV); - set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA); - set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE); - set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC); - set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW); - set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO); - set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT); - set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT); - set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB); - set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA); - set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST); - set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT); - set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT); - set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT); - set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR); - set_output_visible(node, passflag, RRES_OUT_TRANSM_DIRECT, SCE_PASS_TRANSM_DIRECT); - set_output_visible(node, passflag, RRES_OUT_TRANSM_INDIRECT, SCE_PASS_TRANSM_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_TRANSM_COLOR, SCE_PASS_TRANSM_COLOR); - set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_DIRECT, SCE_PASS_SUBSURFACE_DIRECT); - set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_INDIRECT, SCE_PASS_SUBSURFACE_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_COLOR, SCE_PASS_SUBSURFACE_COLOR); - -#ifdef WITH_CYCLES_DEBUG - set_output_visible(node, passflag, RRES_OUT_DEBUG, SCE_PASS_DEBUG); -#endif + const char* sock_to_passname[] = { + RE_PASSNAME_COMBINED, RE_PASSNAME_COMBINED, + RE_PASSNAME_Z, RE_PASSNAME_NORMAL, RE_PASSNAME_UV, RE_PASSNAME_VECTOR, RE_PASSNAME_RGBA, + RE_PASSNAME_DIFFUSE, RE_PASSNAME_SPEC, RE_PASSNAME_SHADOW, RE_PASSNAME_AO, + RE_PASSNAME_REFLECT, RE_PASSNAME_REFRACT, RE_PASSNAME_INDIRECT, + RE_PASSNAME_INDEXOB, RE_PASSNAME_INDEXMA, RE_PASSNAME_MIST, RE_PASSNAME_EMIT, RE_PASSNAME_ENVIRONMENT, + RE_PASSNAME_DIFFUSE_DIRECT, RE_PASSNAME_DIFFUSE_INDIRECT, RE_PASSNAME_DIFFUSE_COLOR, + RE_PASSNAME_GLOSSY_DIRECT, RE_PASSNAME_GLOSSY_INDIRECT, RE_PASSNAME_GLOSSY_COLOR, + RE_PASSNAME_TRANSM_DIRECT, RE_PASSNAME_TRANSM_INDIRECT, RE_PASSNAME_TRANSM_COLOR, + RE_PASSNAME_SUBSURFACE_DIRECT, RE_PASSNAME_SUBSURFACE_INDIRECT, RE_PASSNAME_SUBSURFACE_COLOR + }; + if (sock_index > 30) { + return NULL; + } + return sock_to_passname[sock_index]; } static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr) { Scene *scene = CTX_data_scene(C); bNode *node = ptr->data; - + int sock_index = 0; + node->id = &scene->id; - - node_cmp_rlayers_force_hidden_passes(node); + + for (bNodeSocket *sock = node->outputs.first; sock; sock = sock->next, sock_index++) + { + NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); + sock->storage = sockdata; + + BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(sock_index), sizeof(sockdata->pass_name)); + } } static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree) @@ -489,6 +405,29 @@ static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree return false; } +static void node_composit_free_rlayers(bNode *node) +{ + bNodeSocket *sock; + + /* free extra socket info */ + for (sock = node->outputs.first; sock; sock = sock->next) + MEM_freeN(sock->storage); +} + +static void node_composit_copy_rlayers(bNodeTree *UNUSED(dest_ntree), bNode *UNUSED(dest_node), bNode *src_node) +{ + bNodeSocket *sock; + + /* copy extra socket info */ + for (sock = src_node->outputs.first; sock; sock = sock->next) + sock->new_sock->storage = MEM_dupallocN(sock->storage); +} + +static void cmp_node_rlayers_update(bNodeTree *ntree, bNode *node) +{ + cmp_node_image_verify_outputs(ntree, node, true); +} + void register_node_type_cmp_rlayers(void) { static bNodeType ntype; @@ -497,6 +436,9 @@ void register_node_type_cmp_rlayers(void) node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out); ntype.initfunc_api = node_composit_init_rlayers; ntype.poll = node_composit_poll_rlayers; + node_type_storage(&ntype, NULL, node_composit_free_rlayers, node_composit_copy_rlayers); + node_type_update(&ntype, cmp_node_rlayers_update, NULL); + node_type_init(&ntype, node_cmp_rlayers_outputs); nodeRegisterType(&ntype); } |