Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/composite/nodes/node_composite_image.cc
- This file was moved from source/blender/nodes/composite/nodes/node_composite_image.c.
| Show All 15 Lines | |||||
| * The Original Code is Copyright (C) 2006 Blender Foundation. | * The Original Code is Copyright (C) 2006 Blender Foundation. | ||||
| * All rights reserved. | * All rights reserved. | ||||
| */ | */ | ||||
| /** \file | /** \file | ||||
| * \ingroup cmpnodes | * \ingroup cmpnodes | ||||
| */ | */ | ||||
| #include "node_composite_util.h" | #include "node_composite_util.hh" | ||||
| #include "BLI_linklist.h" | #include "BLI_linklist.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "RE_engine.h" | #include "RE_engine.h" | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | static void cmp_node_image_add_pass_output(bNodeTree *ntree, | ||||
| const char *name, | const char *name, | ||||
| const char *passname, | const char *passname, | ||||
| int rres_index, | int rres_index, | ||||
| eNodeSocketDatatype type, | eNodeSocketDatatype type, | ||||
| int UNUSED(is_rlayers), | int UNUSED(is_rlayers), | ||||
| LinkNodePair *available_sockets, | LinkNodePair *available_sockets, | ||||
| int *prev_index) | int *prev_index) | ||||
| { | { | ||||
| bNodeSocket *sock = BLI_findstring(&node->outputs, name, offsetof(bNodeSocket, name)); | bNodeSocket *sock = (bNodeSocket *)BLI_findstring( | ||||
| &node->outputs, name, offsetof(bNodeSocket, name)); | |||||
| /* Replace if types don't match. */ | /* Replace if types don't match. */ | ||||
| if (sock && sock->type != type) { | if (sock && sock->type != type) { | ||||
| nodeRemoveSocket(ntree, node, sock); | nodeRemoveSocket(ntree, node, sock); | ||||
| sock = NULL; | sock = nullptr; | ||||
| } | } | ||||
| /* Create socket if it doesn't exist yet. */ | /* Create socket if it doesn't exist yet. */ | ||||
| if (sock == NULL) { | if (sock == nullptr) { | ||||
| if (rres_index >= 0) { | if (rres_index >= 0) { | ||||
| sock = node_add_socket_from_template( | sock = node_add_socket_from_template( | ||||
| ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT); | ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT); | ||||
| } | } | ||||
| else { | else { | ||||
| sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, name, name); | sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, name, name); | ||||
| } | } | ||||
| /* extra socket info */ | /* extra socket info */ | ||||
| NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); | NodeImageLayer *sockdata = (NodeImageLayer *)MEM_callocN(sizeof(NodeImageLayer), | ||||
| "node image layer"); | |||||
| sock->storage = sockdata; | sock->storage = sockdata; | ||||
| } | } | ||||
| NodeImageLayer *sockdata = sock->storage; | NodeImageLayer *sockdata = (NodeImageLayer *)sock->storage; | ||||
| if (sockdata) { | if (sockdata) { | ||||
| BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name)); | BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name)); | ||||
| } | } | ||||
| /* Reorder sockets according to order that passes are added. */ | /* Reorder sockets according to order that passes are added. */ | ||||
| const int after_index = (*prev_index)++; | const int after_index = (*prev_index)++; | ||||
| bNodeSocket *after_sock = BLI_findlink(&node->outputs, after_index); | bNodeSocket *after_sock = (bNodeSocket *)BLI_findlink(&node->outputs, after_index); | ||||
| BLI_remlink(&node->outputs, sock); | BLI_remlink(&node->outputs, sock); | ||||
| BLI_insertlinkafter(&node->outputs, after_sock, sock); | BLI_insertlinkafter(&node->outputs, after_sock, sock); | ||||
| BLI_linklist_append(available_sockets, sock); | BLI_linklist_append(available_sockets, sock); | ||||
| } | } | ||||
| static void cmp_node_image_create_outputs(bNodeTree *ntree, | static void cmp_node_image_create_outputs(bNodeTree *ntree, | ||||
| bNode *node, | bNode *node, | ||||
| LinkNodePair *available_sockets) | LinkNodePair *available_sockets) | ||||
| { | { | ||||
| Image *ima = (Image *)node->id; | Image *ima = (Image *)node->id; | ||||
| ImBuf *ibuf; | ImBuf *ibuf; | ||||
| int prev_index = -1; | int prev_index = -1; | ||||
| if (ima) { | if (ima) { | ||||
| ImageUser *iuser = node->storage; | ImageUser *iuser = (ImageUser *)node->storage; | ||||
| ImageUser load_iuser = {NULL}; | ImageUser load_iuser = {nullptr}; | ||||
| int offset = BKE_image_sequence_guess_offset(ima); | int offset = BKE_image_sequence_guess_offset(ima); | ||||
| /* It is possible that image user in this node is not | /* It is possible that image user in this node is not | ||||
| * properly updated yet. In this case loading image will | * properly updated yet. In this case loading image will | ||||
| * fail and sockets detection will go wrong. | * fail and sockets detection will go wrong. | ||||
| * | * | ||||
| * So we manually construct image user to be sure first | * So we manually construct image user to be sure first | ||||
| * image from sequence (that one which is set as filename | * image from sequence (that one which is set as filename | ||||
| * for image datablock) is used for sockets detection | * for image data-block) is used for sockets detection. */ | ||||
| */ | |||||
| load_iuser.ok = 1; | load_iuser.ok = 1; | ||||
| load_iuser.framenr = offset; | load_iuser.framenr = offset; | ||||
| /* make sure ima->type is correct */ | /* make sure ima->type is correct */ | ||||
| ibuf = BKE_image_acquire_ibuf(ima, &load_iuser, NULL); | ibuf = BKE_image_acquire_ibuf(ima, &load_iuser, nullptr); | ||||
| if (ima->rr) { | if (ima->rr) { | ||||
| RenderLayer *rl = BLI_findlink(&ima->rr->layers, iuser->layer); | RenderLayer *rl = (RenderLayer *)BLI_findlink(&ima->rr->layers, iuser->layer); | ||||
| if (rl) { | if (rl) { | ||||
| RenderPass *rpass; | LISTBASE_FOREACH (RenderPass *, rpass, &rl->passes) { | ||||
| for (rpass = rl->passes.first; rpass; rpass = rpass->next) { | eNodeSocketDatatype type; | ||||
| int type; | |||||
| if (rpass->channels == 1) { | if (rpass->channels == 1) { | ||||
| type = SOCK_FLOAT; | type = SOCK_FLOAT; | ||||
| } | } | ||||
| else { | else { | ||||
| type = SOCK_RGBA; | type = SOCK_RGBA; | ||||
| } | } | ||||
| cmp_node_image_add_pass_output(ntree, | cmp_node_image_add_pass_output(ntree, | ||||
| Show All 13 Lines | if (ima->rr) { | ||||
| rpass->name, | rpass->name, | ||||
| -1, | -1, | ||||
| SOCK_FLOAT, | SOCK_FLOAT, | ||||
| false, | false, | ||||
| available_sockets, | available_sockets, | ||||
| &prev_index); | &prev_index); | ||||
| } | } | ||||
| } | } | ||||
| BKE_image_release_ibuf(ima, ibuf, NULL); | BKE_image_release_ibuf(ima, ibuf, nullptr); | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| cmp_node_image_add_pass_output(ntree, | cmp_node_image_add_pass_output(ntree, | ||||
| node, | node, | ||||
| "Image", | "Image", | ||||
| Show All 20 Lines | if (!ima->rr) { | ||||
| RE_PASSNAME_Z, | RE_PASSNAME_Z, | ||||
| RE_PASSNAME_Z, | RE_PASSNAME_Z, | ||||
| -1, | -1, | ||||
| SOCK_FLOAT, | SOCK_FLOAT, | ||||
| false, | false, | ||||
| available_sockets, | available_sockets, | ||||
| &prev_index); | &prev_index); | ||||
| } | } | ||||
| BKE_image_release_ibuf(ima, ibuf, NULL); | BKE_image_release_ibuf(ima, ibuf, nullptr); | ||||
| } | } | ||||
| } | } | ||||
| typedef struct RLayerUpdateData { | struct RLayerUpdateData { | ||||
| LinkNodePair *available_sockets; | LinkNodePair *available_sockets; | ||||
| int prev_index; | int prev_index; | ||||
| } RLayerUpdateData; | }; | ||||
| void node_cmp_rlayers_register_pass(bNodeTree *ntree, | void node_cmp_rlayers_register_pass(bNodeTree *ntree, | ||||
| bNode *node, | bNode *node, | ||||
| Scene *scene, | Scene *scene, | ||||
| ViewLayer *view_layer, | ViewLayer *view_layer, | ||||
| const char *name, | const char *name, | ||||
| eNodeSocketDatatype type) | eNodeSocketDatatype type) | ||||
| { | { | ||||
| RLayerUpdateData *data = node->storage; | RLayerUpdateData *data = (RLayerUpdateData *)node->storage; | ||||
| if (scene == NULL || view_layer == NULL || data == NULL || node->id != (ID *)scene) { | if (scene == nullptr || view_layer == nullptr || data == nullptr || node->id != (ID *)scene) { | ||||
| return; | return; | ||||
| } | } | ||||
| ViewLayer *node_view_layer = BLI_findlink(&scene->view_layers, node->custom1); | ViewLayer *node_view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, node->custom1); | ||||
| if (node_view_layer != view_layer) { | if (node_view_layer != view_layer) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* Special handling for the Combined pass to ensure compatibility. */ | /* Special handling for the Combined pass to ensure compatibility. */ | ||||
| if (STREQ(name, RE_PASSNAME_COMBINED)) { | if (STREQ(name, RE_PASSNAME_COMBINED)) { | ||||
| cmp_node_image_add_pass_output( | cmp_node_image_add_pass_output( | ||||
| ntree, node, "Image", name, -1, type, true, data->available_sockets, &data->prev_index); | ntree, node, "Image", name, -1, type, true, data->available_sockets, &data->prev_index); | ||||
| Show All 23 Lines | |||||
| { | { | ||||
| /* Register the pass in all scenes that have a render layer node for this layer. | /* Register the pass in all scenes that have a render layer node for this layer. | ||||
| * Since multiple scenes can be used in the compositor, the code must loop over all scenes | * Since multiple scenes can be used in the compositor, the code must loop over all scenes | ||||
| * and check whether their nodetree has a node that needs to be updated. */ | * and check whether their nodetree has a node that needs to be updated. */ | ||||
| /* NOTE: using G_MAIN seems valid here, | /* NOTE: using G_MAIN seems valid here, | ||||
| * unless we want to register that for every other temp Main we could generate??? */ | * unless we want to register that for every other temp Main we could generate??? */ | ||||
| ntreeCompositRegisterPass(scene->nodetree, scene, view_layer, name, type); | ntreeCompositRegisterPass(scene->nodetree, scene, view_layer, name, type); | ||||
| for (Scene *sce = G_MAIN->scenes.first; sce; sce = sce->id.next) { | for (Scene *sce = (Scene *)G_MAIN->scenes.first; sce; sce = (Scene *)sce->id.next) { | ||||
| if (sce->nodetree && sce != scene) { | if (sce->nodetree && sce != scene) { | ||||
| ntreeCompositRegisterPass(sce->nodetree, scene, view_layer, name, type); | ntreeCompositRegisterPass(sce->nodetree, scene, view_layer, name, type); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, | static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, | ||||
| bNode *node, | bNode *node, | ||||
| LinkNodePair *available_sockets) | LinkNodePair *available_sockets) | ||||
| { | { | ||||
| Scene *scene = (Scene *)node->id; | Scene *scene = (Scene *)node->id; | ||||
| if (scene) { | if (scene) { | ||||
| RenderEngineType *engine_type = RE_engines_find(scene->r.engine); | RenderEngineType *engine_type = RE_engines_find(scene->r.engine); | ||||
| if (engine_type && engine_type->update_render_passes) { | if (engine_type && engine_type->update_render_passes) { | ||||
| ViewLayer *view_layer = BLI_findlink(&scene->view_layers, node->custom1); | ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, node->custom1); | ||||
| if (view_layer) { | if (view_layer) { | ||||
| RLayerUpdateData *data = MEM_mallocN(sizeof(RLayerUpdateData), "render layer update data"); | RLayerUpdateData *data = (RLayerUpdateData *)MEM_mallocN(sizeof(RLayerUpdateData), | ||||
| "render layer update data"); | |||||
| data->available_sockets = available_sockets; | data->available_sockets = available_sockets; | ||||
| data->prev_index = -1; | data->prev_index = -1; | ||||
| node->storage = data; | node->storage = data; | ||||
| RenderEngine *engine = RE_engine_create(engine_type); | RenderEngine *engine = RE_engine_create(engine_type); | ||||
| RE_engine_update_render_passes( | RE_engine_update_render_passes( | ||||
| engine, scene, view_layer, cmp_node_rlayer_create_outputs_cb, NULL); | engine, scene, view_layer, cmp_node_rlayer_create_outputs_cb, nullptr); | ||||
| RE_engine_free(engine); | RE_engine_free(engine); | ||||
| if ((scene->r.mode & R_EDGE_FRS) && | if ((scene->r.mode & R_EDGE_FRS) && | ||||
| (view_layer->freestyle_config.flags & FREESTYLE_AS_RENDER_PASS)) { | (view_layer->freestyle_config.flags & FREESTYLE_AS_RENDER_PASS)) { | ||||
| ntreeCompositRegisterPass(ntree, scene, view_layer, RE_PASSNAME_FREESTYLE, SOCK_RGBA); | ntreeCompositRegisterPass(ntree, scene, view_layer, RE_PASSNAME_FREESTYLE, SOCK_RGBA); | ||||
| } | } | ||||
| MEM_freeN(data); | MEM_freeN(data); | ||||
| node->storage = NULL; | node->storage = nullptr; | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| int prev_index = -1; | int prev_index = -1; | ||||
| cmp_node_image_add_pass_output(ntree, | cmp_node_image_add_pass_output(ntree, | ||||
| Show All 16 Lines | cmp_node_image_add_pass_output(ntree, | ||||
| &prev_index); | &prev_index); | ||||
| } | } | ||||
| /* XXX make this into a generic socket verification function for dynamic socket replacement | /* XXX make this into a generic socket verification function for dynamic socket replacement | ||||
| * (multilayer, groups, static templates) */ | * (multilayer, groups, static templates) */ | ||||
| static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rlayer) | static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rlayer) | ||||
| { | { | ||||
| bNodeSocket *sock, *sock_next; | bNodeSocket *sock, *sock_next; | ||||
| LinkNodePair available_sockets = {NULL, NULL}; | LinkNodePair available_sockets = {nullptr, nullptr}; | ||||
| int sock_index; | |||||
| /* XXX make callback */ | /* XXX make callback */ | ||||
| if (rlayer) { | if (rlayer) { | ||||
| cmp_node_rlayer_create_outputs(ntree, node, &available_sockets); | cmp_node_rlayer_create_outputs(ntree, node, &available_sockets); | ||||
| } | } | ||||
| else { | else { | ||||
| cmp_node_image_create_outputs(ntree, node, &available_sockets); | cmp_node_image_create_outputs(ntree, node, &available_sockets); | ||||
| } | } | ||||
| /* Get rid of sockets whose passes are not available in the image. | /* 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 | * 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). | * 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. | * Therefore, sockets with connected links will just be set as unavailable. | ||||
| * | * | ||||
| * Another important detail comes from compatibility with the older socket model, where there | * 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 | * 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. | * the first 31 passes to belong to a specific pass type. | ||||
| * So, we keep those 31 always allocated before the others as well, | * So, we keep those 31 always allocated before the others as well, | ||||
| * even if they have no links attached. */ | * even if they have no links attached. */ | ||||
| sock_index = 0; | int sock_index = 0; | ||||
| for (sock = node->outputs.first; sock; sock = sock_next, sock_index++) { | for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock_next, sock_index++) { | ||||
| sock_next = sock->next; | sock_next = sock->next; | ||||
| if (BLI_linklist_index(available_sockets.list, sock) >= 0) { | if (BLI_linklist_index(available_sockets.list, sock) >= 0) { | ||||
| sock->flag &= ~(SOCK_UNAVAIL | SOCK_HIDDEN); | sock->flag &= ~(SOCK_UNAVAIL | SOCK_HIDDEN); | ||||
| } | } | ||||
| else { | else { | ||||
| bNodeLink *link; | bNodeLink *link; | ||||
| for (link = ntree->links.first; link; link = link->next) { | for (link = (bNodeLink *)ntree->links.first; link; link = link->next) { | ||||
| if (link->fromsock == sock) { | if (link->fromsock == sock) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (!link && (!rlayer || sock_index >= NUM_LEGACY_SOCKETS)) { | if (!link && (!rlayer || sock_index >= NUM_LEGACY_SOCKETS)) { | ||||
| MEM_freeN(sock->storage); | MEM_freeN(sock->storage); | ||||
| nodeRemoveSocket(ntree, node, sock); | nodeRemoveSocket(ntree, node, sock); | ||||
| } | } | ||||
| else { | else { | ||||
| sock->flag |= SOCK_UNAVAIL; | sock->flag |= SOCK_UNAVAIL; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BLI_linklist_free(available_sockets.list, NULL); | BLI_linklist_free(available_sockets.list, nullptr); | ||||
| } | } | ||||
| static void cmp_node_image_update(bNodeTree *ntree, bNode *node) | static void cmp_node_image_update(bNodeTree *ntree, bNode *node) | ||||
| { | { | ||||
| /* avoid unnecessary updates, only changes to the image/image user data are of interest */ | /* avoid unnecessary updates, only changes to the image/image user data are of interest */ | ||||
| if (node->update & NODE_UPDATE_ID) { | if (node->update & NODE_UPDATE_ID) { | ||||
| cmp_node_image_verify_outputs(ntree, node, false); | cmp_node_image_verify_outputs(ntree, node, false); | ||||
| } | } | ||||
| cmp_node_update_default(ntree, node); | cmp_node_update_default(ntree, node); | ||||
| } | } | ||||
| static void node_composit_init_image(bNodeTree *ntree, bNode *node) | static void node_composit_init_image(bNodeTree *ntree, bNode *node) | ||||
| { | { | ||||
| ImageUser *iuser = MEM_callocN(sizeof(ImageUser), "node image user"); | ImageUser *iuser = (ImageUser *)MEM_callocN(sizeof(ImageUser), "node image user"); | ||||
| node->storage = iuser; | node->storage = iuser; | ||||
| iuser->frames = 1; | iuser->frames = 1; | ||||
| iuser->sfra = 1; | iuser->sfra = 1; | ||||
| iuser->ok = 1; | iuser->ok = 1; | ||||
| iuser->flag |= IMA_ANIM_ALWAYS; | iuser->flag |= IMA_ANIM_ALWAYS; | ||||
| /* setup initial outputs */ | /* setup initial outputs */ | ||||
| cmp_node_image_verify_outputs(ntree, node, false); | cmp_node_image_verify_outputs(ntree, node, false); | ||||
| } | } | ||||
| static void node_composit_free_image(bNode *node) | static void node_composit_free_image(bNode *node) | ||||
| { | { | ||||
| bNodeSocket *sock; | |||||
| /* free extra socket info */ | /* free extra socket info */ | ||||
| for (sock = node->outputs.first; sock; sock = sock->next) { | LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { | ||||
| MEM_freeN(sock->storage); | MEM_freeN(sock->storage); | ||||
| } | } | ||||
| MEM_freeN(node->storage); | MEM_freeN(node->storage); | ||||
| } | } | ||||
| static void node_composit_copy_image(bNodeTree *UNUSED(dest_ntree), | static void node_composit_copy_image(bNodeTree *UNUSED(dest_ntree), | ||||
| bNode *dest_node, | bNode *dest_node, | ||||
| const bNode *src_node) | const bNode *src_node) | ||||
| { | { | ||||
| dest_node->storage = MEM_dupallocN(src_node->storage); | dest_node->storage = MEM_dupallocN(src_node->storage); | ||||
| const bNodeSocket *src_output_sock = src_node->outputs.first; | const bNodeSocket *src_output_sock = (bNodeSocket *)src_node->outputs.first; | ||||
| bNodeSocket *dest_output_sock = dest_node->outputs.first; | bNodeSocket *dest_output_sock = (bNodeSocket *)dest_node->outputs.first; | ||||
| while (dest_output_sock != NULL) { | while (dest_output_sock != nullptr) { | ||||
| dest_output_sock->storage = MEM_dupallocN(src_output_sock->storage); | dest_output_sock->storage = MEM_dupallocN(src_output_sock->storage); | ||||
| src_output_sock = src_output_sock->next; | src_output_sock = src_output_sock->next; | ||||
| dest_output_sock = dest_output_sock->next; | dest_output_sock = dest_output_sock->next; | ||||
| } | } | ||||
| } | } | ||||
| void register_node_type_cmp_image(void) | void register_node_type_cmp_image(void) | ||||
| Show All 14 Lines | |||||
| void node_cmp_rlayers_outputs(bNodeTree *ntree, bNode *node) | void node_cmp_rlayers_outputs(bNodeTree *ntree, bNode *node) | ||||
| { | { | ||||
| cmp_node_image_verify_outputs(ntree, node, true); | cmp_node_image_verify_outputs(ntree, node, true); | ||||
| } | } | ||||
| const char *node_cmp_rlayers_sock_to_pass(int sock_index) | const char *node_cmp_rlayers_sock_to_pass(int sock_index) | ||||
| { | { | ||||
| if (sock_index >= NUM_LEGACY_SOCKETS) { | if (sock_index >= NUM_LEGACY_SOCKETS) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| const char *name = cmp_node_rlayers_out[sock_index].name; | const char *name = cmp_node_rlayers_out[sock_index].name; | ||||
| /* Exception for alpha, which is derived from Combined. */ | /* Exception for alpha, which is derived from Combined. */ | ||||
| return (STREQ(name, "Alpha")) ? RE_PASSNAME_COMBINED : name; | return (STREQ(name, "Alpha")) ? RE_PASSNAME_COMBINED : name; | ||||
| } | } | ||||
| static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr) | static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| bNode *node = ptr->data; | bNode *node = (bNode *)ptr->data; | ||||
| int sock_index = 0; | int sock_index = 0; | ||||
| node->id = &scene->id; | node->id = &scene->id; | ||||
| id_us_plus(node->id); | id_us_plus(node->id); | ||||
| for (bNodeSocket *sock = node->outputs.first; sock; sock = sock->next, sock_index++) { | for (bNodeSocket *sock = (bNodeSocket *)node->outputs.first; sock; | ||||
| NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); | sock = sock->next, sock_index++) { | ||||
| NodeImageLayer *sockdata = (NodeImageLayer *)MEM_callocN(sizeof(NodeImageLayer), | |||||
| "node image layer"); | |||||
| sock->storage = sockdata; | sock->storage = sockdata; | ||||
| BLI_strncpy(sockdata->pass_name, | BLI_strncpy(sockdata->pass_name, | ||||
| node_cmp_rlayers_sock_to_pass(sock_index), | node_cmp_rlayers_sock_to_pass(sock_index), | ||||
| sizeof(sockdata->pass_name)); | sizeof(sockdata->pass_name)); | ||||
| } | } | ||||
| } | } | ||||
| static bool node_composit_poll_rlayers(bNodeType *UNUSED(ntype), | static bool node_composit_poll_rlayers(bNodeType *UNUSED(ntype), | ||||
| bNodeTree *ntree, | bNodeTree *ntree, | ||||
| const char **r_disabled_hint) | const char **r_disabled_hint) | ||||
| { | { | ||||
| if (!STREQ(ntree->idname, "CompositorNodeTree")) { | if (!STREQ(ntree->idname, "CompositorNodeTree")) { | ||||
| *r_disabled_hint = "Not a compositor node tree"; | *r_disabled_hint = "Not a compositor node tree"; | ||||
| return false; | return false; | ||||
| } | } | ||||
| Scene *scene; | Scene *scene; | ||||
| /* XXX ugly: check if ntree is a local scene node tree. | /* XXX ugly: check if ntree is a local scene node tree. | ||||
| * Render layers node can only be used in local scene->nodetree, | * Render layers node can only be used in local scene->nodetree, | ||||
| * since it directly links to the scene. | * since it directly links to the scene. | ||||
| */ | */ | ||||
| for (scene = G.main->scenes.first; scene; scene = scene->id.next) { | for (scene = (Scene *)G.main->scenes.first; scene; scene = (Scene *)scene->id.next) { | ||||
| if (scene->nodetree == ntree) { | if (scene->nodetree == ntree) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (scene == NULL) { | if (scene == nullptr) { | ||||
| *r_disabled_hint = "The node tree must be the compositing node tree of any scene in the file"; | *r_disabled_hint = "The node tree must be the compositing node tree of any scene in the file"; | ||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| static void node_composit_free_rlayers(bNode *node) | static void node_composit_free_rlayers(bNode *node) | ||||
| { | { | ||||
| bNodeSocket *sock; | |||||
| /* free extra socket info */ | /* free extra socket info */ | ||||
| for (sock = node->outputs.first; sock; sock = sock->next) { | LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { | ||||
| if (sock->storage) { | if (sock->storage) { | ||||
| MEM_freeN(sock->storage); | MEM_freeN(sock->storage); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void node_composit_copy_rlayers(bNodeTree *UNUSED(dest_ntree), | static void node_composit_copy_rlayers(bNodeTree *UNUSED(dest_ntree), | ||||
| bNode *dest_node, | bNode *dest_node, | ||||
| const bNode *src_node) | const bNode *src_node) | ||||
| { | { | ||||
| /* copy extra socket info */ | /* copy extra socket info */ | ||||
| const bNodeSocket *src_output_sock = src_node->outputs.first; | const bNodeSocket *src_output_sock = (bNodeSocket *)src_node->outputs.first; | ||||
| bNodeSocket *dest_output_sock = dest_node->outputs.first; | bNodeSocket *dest_output_sock = (bNodeSocket *)dest_node->outputs.first; | ||||
| while (dest_output_sock != NULL) { | while (dest_output_sock != nullptr) { | ||||
| dest_output_sock->storage = MEM_dupallocN(src_output_sock->storage); | dest_output_sock->storage = MEM_dupallocN(src_output_sock->storage); | ||||
| src_output_sock = src_output_sock->next; | src_output_sock = src_output_sock->next; | ||||
| dest_output_sock = dest_output_sock->next; | dest_output_sock = dest_output_sock->next; | ||||
| } | } | ||||
| } | } | ||||
| static void cmp_node_rlayers_update(bNodeTree *ntree, bNode *node) | static void cmp_node_rlayers_update(bNodeTree *ntree, bNode *node) | ||||
| { | { | ||||
| cmp_node_image_verify_outputs(ntree, node, true); | cmp_node_image_verify_outputs(ntree, node, true); | ||||
| cmp_node_update_default(ntree, node); | cmp_node_update_default(ntree, node); | ||||
| } | } | ||||
| void register_node_type_cmp_rlayers(void) | void register_node_type_cmp_rlayers(void) | ||||
| { | { | ||||
| static bNodeType ntype; | static bNodeType ntype; | ||||
| cmp_node_type_base(&ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW); | cmp_node_type_base(&ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW); | ||||
| node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out); | node_type_socket_templates(&ntype, nullptr, cmp_node_rlayers_out); | ||||
| ntype.initfunc_api = node_composit_init_rlayers; | ntype.initfunc_api = node_composit_init_rlayers; | ||||
| ntype.poll = node_composit_poll_rlayers; | ntype.poll = node_composit_poll_rlayers; | ||||
| node_type_storage(&ntype, NULL, node_composit_free_rlayers, node_composit_copy_rlayers); | node_type_storage(&ntype, nullptr, node_composit_free_rlayers, node_composit_copy_rlayers); | ||||
| node_type_update(&ntype, cmp_node_rlayers_update); | node_type_update(&ntype, cmp_node_rlayers_update); | ||||
| node_type_init(&ntype, node_cmp_rlayers_outputs); | node_type_init(&ntype, node_cmp_rlayers_outputs); | ||||
| node_type_size_preset(&ntype, NODE_SIZE_LARGE); | node_type_size_preset(&ntype, NODE_SIZE_LARGE); | ||||
| nodeRegisterType(&ntype); | nodeRegisterType(&ntype); | ||||
| } | } | ||||