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:
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h8
-rw-r--r--source/blender/blenkernel/intern/node.c14
-rw-r--r--source/blender/blenloader/intern/readfile.c86
-rw-r--r--source/blender/blenloader/intern/writefile.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c213
-rw-r--r--source/blender/editors/space_node/node_edit.c42
-rw-r--r--source/blender/editors/space_node/node_intern.h4
-rw-r--r--source/blender/editors/space_node/node_ops.c4
-rw-r--r--source/blender/makesdna/DNA_node_types.h9
-rw-r--r--source/blender/makesrna/RNA_access.h2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c89
-rw-r--r--source/blender/makesrna/intern/rna_nodetree_types.h1
-rw-r--r--source/blender/nodes/CMakeLists.txt4
-rw-r--r--source/blender/nodes/NOD_composite.h1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c314
16 files changed, 465 insertions, 330 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 1c661b3804f..392642b5305 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 262
-#define BLENDER_SUBVERSION 0
+#define BLENDER_SUBVERSION 1
#define BLENDER_MINVERSION 250
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 753161d0788..cb161b26ee5 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -364,6 +364,7 @@ int nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
void nodeFreePreview(struct bNode *node);
int nodeSocketIsHidden(struct bNodeSocket *sock);
+void nodeSocketSetType(struct bNodeSocket *sock, int type);
/* ************** NODE TYPE ACCESS *************** */
@@ -636,7 +637,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
#define CMP_NODE_TRANSFORM 264
#define CMP_NODE_MOVIEDISTORTION 265
#define CMP_NODE_DOUBLEEDGEMASK 266
-#define CMP_NODE_OUTPUT_MULTI_FILE 267
+#define CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED 267 /* DEPRECATED multi file node has been merged into regular CMP_NODE_OUTPUT_FILE */
#define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302
@@ -676,8 +677,9 @@ void ntreeCompositTagGenerators(struct bNodeTree *ntree);
void ntreeCompositForceHidden(struct bNodeTree *ntree, struct Scene *scene);
void ntreeCompositClearTags(struct bNodeTree *ntree);
-void ntreeCompositOutputMultiFileAddSocket(struct bNodeTree *ntree, struct bNode *node, struct ImageFormatData *im_format);
-int ntreeCompositOutputMultiFileRemoveActiveSocket(struct bNodeTree *ntree, struct bNode *node);
+struct bNodeSocket *ntreeCompositOutputFileAddSocket(struct bNodeTree *ntree, struct bNode *node,
+ const char *name, struct ImageFormatData *im_format);
+int ntreeCompositOutputFileRemoveActiveSocket(struct bNodeTree *ntree, struct bNode *node);
/* ************** TEXTURE NODES *************** */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index c394a5354f1..99edd4bac8c 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1369,6 +1369,19 @@ int nodeSocketIsHidden(bNodeSocket *sock)
return ((sock->flag & (SOCK_HIDDEN | SOCK_AUTO_HIDDEN | SOCK_UNAVAIL)) != 0);
}
+void nodeSocketSetType(bNodeSocket *sock, int type)
+{
+ int old_type = sock->type;
+ void *old_default_value = sock->default_value;
+
+ sock->type = type;
+
+ sock->default_value = node_socket_make_default_value(sock->type);
+ node_socket_init_default_value(type, sock->default_value);
+ node_socket_convert_default_value(sock->type, sock->default_value, old_type, old_default_value);
+ node_socket_free_default_value(old_type, old_default_value);
+}
+
/* ************** dependency stuff *********** */
/* node is guaranteed to be not checked before */
@@ -1839,7 +1852,6 @@ static void registerCompositNodes(bNodeTreeType *ttype)
register_node_type_cmp_viewer(ttype);
register_node_type_cmp_splitviewer(ttype);
register_node_type_cmp_output_file(ttype);
- register_node_type_cmp_output_multi_file(ttype);
register_node_type_cmp_view_levels(ttype);
register_node_type_cmp_curve_rgb(ttype);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 180ccaddb0a..8abdc974488 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -7685,6 +7685,77 @@ static void do_versions_nodetree_socket_auto_hidden_flags_2_62(bNodeTree *ntree)
}
}
+static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNodeTree *ntree)
+{
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node=ntree->nodes.first; node; node=node->next) {
+ if (node->type==CMP_NODE_OUTPUT_FILE) {
+ /* previous CMP_NODE_OUTPUT_FILE nodes get converted to multi-file outputs */
+ NodeImageFile *old_data = node->storage;
+ NodeImageMultiFile *nimf= MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
+ bNodeSocket *old_image = BLI_findlink(&node->inputs, 0);
+ bNodeSocket *old_z = BLI_findlink(&node->inputs, 1);
+ bNodeSocket *sock;
+
+ node->storage= nimf;
+
+ BLI_strncpy(nimf->base_path, old_data->name, sizeof(nimf->base_path));
+ nimf->format = old_data->im_format;
+
+ /* if z buffer is saved, change the image type to multilayer exr.
+ * XXX this is slightly messy, Z buffer was ignored before for anything but EXR and IRIS ...
+ * i'm just assuming here that IRIZ means IRIS with z buffer ...
+ */
+ if (ELEM(old_data->im_format.imtype, R_IMF_IMTYPE_IRIZ, R_IMF_IMTYPE_OPENEXR)) {
+ nimf->format.imtype = R_IMF_IMTYPE_MULTILAYER;
+ sock = ntreeCompositOutputFileAddSocket(ntree, node, old_image->name, &nimf->format);
+ if (old_image->link) {
+ old_image->link->tosock = sock;
+ sock->link = old_image->link;
+ }
+ sock = ntreeCompositOutputFileAddSocket(ntree, node, old_z->name, &nimf->format);
+ if (old_z->link) {
+ old_z->link->tosock = sock;
+ sock->link = old_z->link;
+ }
+ }
+ else {
+ /* saves directly to base path, which is the old image output path */
+ sock = ntreeCompositOutputFileAddSocket(ntree, node, "", &nimf->format);
+ if (old_image->link) {
+ old_image->link->tosock = sock;
+ sock->link = old_image->link;
+ }
+ }
+
+ nodeRemoveSocket(ntree, node, old_image);
+ nodeRemoveSocket(ntree, node, old_z);
+ MEM_freeN(old_data);
+ }
+ else if (node->type==CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED) {
+ NodeImageMultiFile *nimf = node->storage;
+
+ /* CMP_NODE_OUTPUT_MULTI_FILE has been redeclared as CMP_NODE_OUTPUT_FILE */
+ node->type = CMP_NODE_OUTPUT_FILE;
+
+ /* initialize the node-wide image format from render data, if available */
+ if (sce)
+ nimf->format = sce->r.im_format;
+
+ /* transfer render format toggle to node format toggle */
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ NodeImageMultiFileSocket *simf = sock->storage;
+ simf->use_node_format = simf->use_render_format;
+ }
+
+ /* we do have preview now */
+ node->flag |= NODE_PREVIEW;
+ }
+ }
+}
+
static void do_versions(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
@@ -13164,6 +13235,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
+ if (main->versionfile < 262 || (main->versionfile == 262 && main->subversionfile < 1))
+ {
+ /* update use flags for node sockets (was only temporary before) */
+ Scene *sce;
+ bNodeTree *ntree;
+
+ for (sce=main->scene.first; sce; sce=sce->id.next)
+ if (sce->nodetree)
+ do_versions_nodetree_multi_file_output_format_2_62_1(sce, sce->nodetree);
+
+ /* XXX can't associate with scene for group nodes, image format will stay uninitialized */
+ for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
+ do_versions_nodetree_multi_file_output_format_2_62_1(NULL, ntree);
+ }
+
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index d5ed3096c79..b063a1656ab 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -727,7 +727,7 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
- if (node->type==CMP_NODE_OUTPUT_MULTI_FILE) {
+ if (node->type==CMP_NODE_OUTPUT_FILE) {
/* inputs have own storage data */
for (sock=node->inputs.first; sock; sock=sock->next)
writestruct(wd, DATA, "NodeImageMultiFileSocket", 1, sock->storage);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index a58e03be237..bc22e668b5a 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -102,24 +102,71 @@ static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block,
uiDefBut(block, LABEL, 0, sock->name, x, y, width, NODE_DY, NULL, 0, 0, 0, 0, "");
}
+/* draw function for file output node sockets.
+ * XXX a bit ugly use atm, called from datatype button functions,
+ * since all node types and callbacks only use data type without struct_type.
+ */
+static void node_socket_button_output_file(const bContext *C, uiBlock *block,
+ bNodeTree *ntree, bNode *node, bNodeSocket *sock,
+ const char *UNUSED(name), int x, int y, int width)
+{
+ uiLayout *layout, *row;
+ PointerRNA nodeptr, sockptr, imfptr;
+ int imtype;
+ int rx, ry;
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &sockptr);
+
+ layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y+NODE_DY, width, 20, UI_GetStyle());
+ row = uiLayoutRow(layout, 0);
+
+ uiItemL(row, sock->name, 0);
+
+ imfptr = RNA_pointer_get(&nodeptr, "format");
+ imtype = RNA_enum_get(&imfptr, "file_format");
+ /* in multilayer format all socket format details are ignored */
+ if (imtype != R_IMF_IMTYPE_MULTILAYER) {
+ PropertyRNA *imtype_prop;
+ const char *imtype_name;
+
+ if (!RNA_boolean_get(&sockptr, "use_node_format"))
+ imfptr = RNA_pointer_get(&sockptr, "format");
+
+ imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
+ RNA_property_enum_name((bContext*)C, &imfptr, imtype_prop, RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
+ uiBlockSetEmboss(block, UI_EMBOSSP);
+ uiItemL(row, imtype_name, 0);
+ uiBlockSetEmboss(block, UI_EMBOSSN);
+ }
+
+ uiBlockLayoutResolve(block, &rx, &ry);
+}
static void node_socket_button_default(const bContext *C, uiBlock *block,
bNodeTree *ntree, bNode *node, bNodeSocket *sock,
const char *name, int x, int y, int width)
{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
- else {
- PointerRNA ptr;
- uiBut *bt;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- bt = uiDefButR(block, NUM, B_NODE_EXEC, name,
- x, y+1, width, NODE_DY-2,
- &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
+ switch (sock->struct_type) {
+ case SOCK_STRUCT_NONE: {
+ if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
+ node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
+ else {
+ PointerRNA ptr;
+ uiBut *bt;
+
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
+
+ bt = uiDefButR(block, NUM, B_NODE_EXEC, name,
+ x, y+1, width, NODE_DY-2,
+ &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
+ if (node)
+ uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
+ }
+ break;
+ }
+ case SOCK_STRUCT_OUTPUT_FILE:
+ node_socket_button_output_file(C, block, ntree, node, sock, name, x, y, width);
+ break;
}
}
@@ -149,25 +196,33 @@ static void node_socket_button_components(const bContext *C, uiBlock *block,
bNodeTree *ntree, bNode *node, bNodeSocket *sock,
const char *name, int x, int y, int width)
{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
- else {
- PointerRNA ptr;
- SocketComponentMenuArgs *args;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- args= MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs");
-
- args->ptr = ptr;
- args->x = x;
- args->y = y;
- args->width = width;
- args->cb = node_sync_cb;
- args->arg1 = CTX_wm_space_node(C);
- args->arg2 = node;
-
- uiDefBlockButN(block, socket_component_menu, args, name, x, y+1, width, NODE_DY-2, "");
+ switch (sock->struct_type) {
+ case SOCK_STRUCT_NONE: {
+ if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
+ node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
+ else {
+ PointerRNA ptr;
+ SocketComponentMenuArgs *args;
+
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
+
+ args= MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs");
+
+ args->ptr = ptr;
+ args->x = x;
+ args->y = y;
+ args->width = width;
+ args->cb = node_sync_cb;
+ args->arg1 = CTX_wm_space_node(C);
+ args->arg2 = node;
+
+ uiDefBlockButN(block, socket_component_menu, args, name, x, y+1, width, NODE_DY-2, "");
+ }
+ break;
+ }
+ case SOCK_STRUCT_OUTPUT_FILE:
+ node_socket_button_output_file(C, block, ntree, node, sock, name, x, y, width);
+ break;
}
}
@@ -200,29 +255,10 @@ static void node_socket_button_color(const bContext *C, uiBlock *block,
}
break;
}
- case SOCK_STRUCT_OUTPUT_MULTI_FILE: {
- uiLayout *layout, *row;
- PointerRNA ptr, imfptr;
- PropertyRNA *imtype_prop;
- const char *imtype_name;
- int rx, ry;
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
- imfptr = RNA_pointer_get(&ptr, "format");
-
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y+NODE_DY, width, 20, UI_GetStyle());
- row = uiLayoutRow(layout, 0);
-
- uiItemL(row, sock->name, 0);
- imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
- RNA_property_enum_name((bContext*)C, &imfptr, imtype_prop, RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
- uiBlockSetEmboss(block, UI_EMBOSSP);
- uiItemL(row, imtype_name, 0);
- uiBlockSetEmboss(block, UI_EMBOSSN);
-
- uiBlockLayoutResolve(block, &rx, &ry);
+ case SOCK_STRUCT_OUTPUT_FILE:
+ node_socket_button_output_file(C, block, ntree, node, sock, name, x, y, width);
break;
}
- }
}
/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
@@ -1699,56 +1735,54 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po
static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNode *node= ptr->data;
- NodeImageFile *nif= node->storage;
- PointerRNA imfptr;
-
- uiLayout *row;
-
- uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE);
-
- RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &nif->im_format, &imfptr);
- uiTemplateImageSettings(layout, &imfptr);
-
- row= uiLayoutRow(layout, 1);
- uiItemR(row, ptr, "frame_start", 0, "Start", ICON_NONE);
- uiItemR(row, ptr, "frame_end", 0, "End", ICON_NONE);
-}
-
-static void node_composit_buts_multi_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
-{
- uiItemL(layout, "Base Path:", 0);
+ PointerRNA imfptr = RNA_pointer_get(ptr, "format");
+ int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
+
+ if (multilayer)
+ uiItemL(layout, "Path:", 0);
+ else
+ uiItemL(layout, "Base Path:", 0);
uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE);
}
-static void node_composit_buts_multi_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
+static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
+ PointerRNA imfptr = RNA_pointer_get(ptr, "format");
PointerRNA active_input_ptr = RNA_pointer_get(ptr, "active_input");
+ int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
- node_composit_buts_multi_file_output(layout, C, ptr);
+ node_composit_buts_file_output(layout, C, ptr);
+ uiTemplateImageSettings(layout, &imfptr);
+
+ uiItemS(layout);
- uiItemO(layout, "Add Input", ICON_ZOOMIN, "NODE_OT_output_multi_file_add_socket");
+ uiItemO(layout, "Add Input", ICON_ZOOMIN, "NODE_OT_output_file_add_socket");
uiTemplateList(layout, C, ptr, "inputs", ptr, "active_input_index", NULL, 0, 0, 0);
if (active_input_ptr.data) {
- PointerRNA imfptr = RNA_pointer_get(&active_input_ptr, "format");
uiLayout *row, *col;
col = uiLayoutColumn(layout, 1);
- uiItemL(col, "File Path:", 0);
+ if (multilayer)
+ uiItemL(col, "Layer Name:", 0);
+ else
+ uiItemL(col, "File Path:", 0);
row = uiLayoutRow(col, 0);
uiItemR(row, &active_input_ptr, "name", 0, "", 0);
- uiItemFullO(row, "NODE_OT_output_multi_file_remove_active_socket", "", ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
-
- uiItemS(layout);
+ uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
- col = uiLayoutColumn(layout, 1);
- uiItemL(col, "Format:", 0);
- uiItemR(col, &active_input_ptr, "use_render_format", 0, NULL, 0);
-
- col= uiLayoutColumn(layout, 0);
- uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_render_format")==0);
- uiTemplateImageSettings(col, &imfptr);
+ /* in multilayer format all socket format details are ignored */
+ if (!multilayer) {
+ imfptr = RNA_pointer_get(&active_input_ptr, "format");
+
+ col = uiLayoutColumn(layout, 1);
+ uiItemL(col, "Format:", 0);
+ uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, 0);
+
+ col= uiLayoutColumn(layout, 0);
+ uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format")==0);
+ uiTemplateImageSettings(col, &imfptr);
+ }
}
}
@@ -1986,10 +2020,7 @@ static void node_composit_set_butfunc(bNodeType *ntype)
break;
case CMP_NODE_OUTPUT_FILE:
ntype->uifunc= node_composit_buts_file_output;
- break;
- case CMP_NODE_OUTPUT_MULTI_FILE:
- ntype->uifunc= node_composit_buts_multi_file_output;
- ntype->uifuncbut= node_composit_buts_multi_file_output_details;
+ ntype->uifuncbut= node_composit_buts_file_output_details;
break;
case CMP_NODE_DIFF_MATTE:
ntype->uifunc=node_composit_buts_diff_matte;
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index c89e91724fb..a6d18b58cca 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -2254,6 +2254,8 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeL
}
else
nodeRemLink(snode->edittree, tlink);
+
+ snode->edittree->update |= NTREE_UPDATE_LINKS;
}
}
}
@@ -3515,49 +3517,47 @@ void NODE_OT_new_node_tree(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME-2, "Name", "");
}
-/* ****************** Multi File Output Add Socket ******************* */
+/* ****************** File Output Add Socket ******************* */
-static int node_output_multi_file_add_socket_exec(bContext *C, wmOperator *UNUSED(op))
+static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
SpaceNode *snode= CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
bNode *node = nodeGetActive(ntree);
+ char file_path[MAX_NAME];
if (!node)
return OPERATOR_CANCELLED;
- ntreeCompositOutputMultiFileAddSocket(ntree, node, &scene->r.im_format);
+ RNA_string_get(op->ptr, "file_path", file_path);
+ ntreeCompositOutputFileAddSocket(ntree, node, file_path, &scene->r.im_format);
snode_notify(C, snode);
return OPERATOR_FINISHED;
}
-static int node_output_multi_file_add_socket_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
-{
- return node_output_multi_file_add_socket_exec(C, op);
-}
-
-void NODE_OT_output_multi_file_add_socket(wmOperatorType *ot)
+void NODE_OT_output_file_add_socket(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Add Multi File Node Socket";
- ot->description= "Add a new input to a multi file output node";
- ot->idname= "NODE_OT_output_multi_file_add_socket";
+ ot->name= "Add File Node Socket";
+ ot->description= "Add a new input to a file output node";
+ ot->idname= "NODE_OT_output_file_add_socket";
/* callbacks */
- ot->exec= node_output_multi_file_add_socket_exec;
- ot->invoke= node_output_multi_file_add_socket_invoke;
+ ot->exec= node_output_file_add_socket_exec;
ot->poll= composite_node_active;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_string(ot->srna, "file_path", "Image", MAX_NAME, "File Path", "Sub-path of the output file");
}
/* ****************** Multi File Output Remove Socket ******************* */
-static int node_output_multi_file_remove_active_socket_exec(bContext *C, wmOperator *UNUSED(op))
+static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode= CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
@@ -3566,7 +3566,7 @@ static int node_output_multi_file_remove_active_socket_exec(bContext *C, wmOpera
if (!node)
return OPERATOR_CANCELLED;
- if (!ntreeCompositOutputMultiFileRemoveActiveSocket(ntree, node))
+ if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node))
return OPERATOR_CANCELLED;
snode_notify(C, snode);
@@ -3574,15 +3574,15 @@ static int node_output_multi_file_remove_active_socket_exec(bContext *C, wmOpera
return OPERATOR_FINISHED;
}
-void NODE_OT_output_multi_file_remove_active_socket(wmOperatorType *ot)
+void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Remove Multi File Node Socket";
- ot->description= "Remove active input from a multi file output node";
- ot->idname= "NODE_OT_output_multi_file_remove_active_socket";
+ ot->name= "Remove File Node Socket";
+ ot->description= "Remove active input from a file output node";
+ ot->idname= "NODE_OT_output_file_remove_active_socket";
/* callbacks */
- ot->exec= node_output_multi_file_remove_active_socket_exec;
+ ot->exec= node_output_file_remove_active_socket_exec;
ot->poll= composite_node_active;
/* flags */
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index f6d52aa9474..2524454d9c0 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -157,8 +157,8 @@ void NODE_OT_add_file(struct wmOperatorType *ot);
void NODE_OT_new_node_tree(struct wmOperatorType *ot);
-void NODE_OT_output_multi_file_add_socket(struct wmOperatorType *ot);
-void NODE_OT_output_multi_file_remove_active_socket(struct wmOperatorType *ot);
+void NODE_OT_output_file_add_socket(struct wmOperatorType *ot);
+void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot);
extern const char *node_context_dir[];
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 608c6b51f70..d358556d36a 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -101,8 +101,8 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_new_node_tree);
- WM_operatortype_append(NODE_OT_output_multi_file_add_socket);
- WM_operatortype_append(NODE_OT_output_multi_file_remove_active_socket);
+ WM_operatortype_append(NODE_OT_output_file_add_socket);
+ WM_operatortype_append(NODE_OT_output_file_remove_active_socket);
}
void ED_operatormacros_node(void)
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 93891a9edfa..ed9eaff4b92 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -114,7 +114,7 @@ typedef struct bNodeSocket {
/* sock->struct_type */
#define SOCK_STRUCT_NONE 0 /* default, type is defined by sock->type only */
-#define SOCK_STRUCT_OUTPUT_MULTI_FILE 1 /* multi file output node socket */
+#define SOCK_STRUCT_OUTPUT_FILE 1 /* file output node socket */
/* socket side (input/output) */
#define SOCK_IN 1
@@ -352,7 +352,7 @@ typedef struct NodeHueSat {
float hue, sat, val;
} NodeHueSat;
-typedef struct NodeImageFile {
+typedef DNA_DEPRECATED struct NodeImageFile {
char name[1024]; /* 1024 = FILE_MAX */
struct ImageFormatData im_format;
int sfra, efra;
@@ -362,10 +362,11 @@ typedef struct NodeImageMultiFile {
char base_path[1024]; /* 1024 = FILE_MAX */
int active_input; /* selected input in details view list */
int pad;
+ ImageFormatData format;
} NodeImageMultiFile;
typedef struct NodeImageMultiFileSocket {
- short use_render_format; /* use global render settings instead of own format */
- short pad1;
+ short use_render_format DNA_DEPRECATED;
+ short use_node_format; /* use overall node image format */
int pad2;
ImageFormatData format;
} NodeImageMultiFileSocket;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 67d27af8b41..596e348e3f6 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -347,7 +347,7 @@ extern StructRNA RNA_NlaTrack;
extern StructRNA RNA_Node;
extern StructRNA RNA_NodeForLoop;
extern StructRNA RNA_NodeGroup;
-extern StructRNA RNA_NodeImageMultiFileSocket;
+extern StructRNA RNA_NodeImageFileSocket;
extern StructRNA RNA_NodeLink;
extern StructRNA RNA_NodeSocket;
extern StructRNA RNA_NodeSocketPanel;
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index a6a8d9f9a35..01131709f3b 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -245,32 +245,28 @@ static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
return &RNA_NodeSocket##stypename##idname; \
}
- if (sock->struct_type == SOCK_STRUCT_NONE) {
+ switch (sock->struct_type) {
+ case SOCK_STRUCT_NONE:
switch (sock->type) {
case SOCK_FLOAT:
NODE_DEFINE_SUBTYPES_FLOAT
- break;
+ break;
case SOCK_INT:
NODE_DEFINE_SUBTYPES_INT
- break;
+ break;
case SOCK_BOOLEAN:
return &RNA_NodeSocketBoolean;
- break;
case SOCK_VECTOR:
NODE_DEFINE_SUBTYPES_VECTOR
- break;
+ break;
case SOCK_RGBA:
return &RNA_NodeSocketRGBA;
- break;
case SOCK_SHADER:
return &RNA_NodeSocketShader;
}
- }
- else {
- switch (sock->struct_type) {
- case SOCK_STRUCT_OUTPUT_MULTI_FILE:
- return &RNA_NodeImageMultiFileSocket;
- }
+ break;
+ case SOCK_STRUCT_OUTPUT_FILE:
+ return &RNA_NodeImageFileSocket;
}
#undef SUBTYPE
@@ -332,24 +328,6 @@ static void rna_Matte_t2_set(PointerRNA *ptr, float value)
chroma->t2 = value;
}
-static void rna_Image_start_frame_set(PointerRNA *ptr, int value)
-{
- bNode *node= (bNode*)ptr->data;
- NodeImageFile *image = node->storage;
-
- CLAMP(value, MINFRAME, image->efra);
- image->sfra= value;
-}
-
-static void rna_Image_end_frame_set(PointerRNA *ptr, int value)
-{
- bNode *node= (bNode*)ptr->data;
- NodeImageFile *image = node->storage;
-
- CLAMP(value, image->sfra, MAXFRAME);
- image->efra= value;
-}
-
static void rna_Node_scene_set(PointerRNA *ptr, PointerRNA value)
{
bNode *node= (bNode*)ptr->data;
@@ -1770,61 +1748,29 @@ static void def_cmp_render_layers(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
}
-static void def_cmp_output_file(StructRNA *srna)
-{
- PropertyRNA *prop;
-
- RNA_def_struct_sdna_from(srna, "NodeImageFile", "storage");
-
- prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
- RNA_def_property_string_sdna(prop, NULL, "name");
- RNA_def_property_ui_text(prop, "File Path", "Output path for the image, same functionality as render output");
- RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
-
- prop= RNA_def_property(srna, "image_settings", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "im_format");
- RNA_def_property_struct_type(prop, "ImageFormatSettings");
- RNA_def_property_ui_text(prop, "Image Format", "");
-
- prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "sfra");
- RNA_def_property_int_funcs(prop, NULL, "rna_Image_start_frame_set", NULL);
- RNA_def_property_range(prop, MINFRAMEF, MAXFRAMEF);
- RNA_def_property_ui_text(prop, "Start Frame", "");
- RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
-
- prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "efra");
- RNA_def_property_int_funcs(prop, NULL, "rna_Image_end_frame_set", NULL);
- RNA_def_property_range(prop, MINFRAMEF, MAXFRAMEF);
- RNA_def_property_ui_text(prop, "End Frame", "");
- RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
-}
-
-static void rna_def_cmp_output_multi_file_socket(BlenderRNA *brna)
+static void rna_def_cmp_output_file_socket(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- srna = RNA_def_struct(brna, "NodeImageMultiFileSocket", "NodeSocketRGBA");
+ srna = RNA_def_struct(brna, "NodeImageFileSocket", "NodeSocketRGBA");
RNA_def_struct_sdna(srna, "bNodeSocket");
RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
- RNA_def_struct_ui_text(srna, "Node Image Multi File Socket", "Socket data of multi file output node");
+ RNA_def_struct_ui_text(srna, "Node Image File Socket", "Socket data of file output node");
RNA_def_struct_ui_icon(srna, ICON_PLUG);
RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
RNA_def_struct_sdna_from(srna, "NodeImageMultiFileSocket", "storage");
- prop = RNA_def_property(srna, "use_render_format", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "use_render_format", 1);
- RNA_def_property_ui_text(prop, "Use Render Format", "");
+ prop = RNA_def_property(srna, "use_node_format", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "use_node_format", 1);
+ RNA_def_property_ui_text(prop, "Use Node Format", "");
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_NodeSocket_update");
prop = RNA_def_property(srna, "format", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ImageFormatSettings");
}
-static void def_cmp_output_multi_file(StructRNA *srna)
+static void def_cmp_output_file(StructRNA *srna)
{
PropertyRNA *prop;
@@ -1845,6 +1791,9 @@ static void def_cmp_output_multi_file(StructRNA *srna)
RNA_def_property_int_sdna(prop, NULL, "active_input");
RNA_def_property_ui_text(prop, "Active Input Index", "Active input index in details view list");
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "format", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ImageFormatSettings");
}
static void def_cmp_dilate_erode(StructRNA *srna)
@@ -3477,7 +3426,7 @@ void RNA_def_nodetree(BlenderRNA *brna)
define_specific_node(brna, NODE_FRAME, def_frame);
/* special socket types */
- rna_def_cmp_output_multi_file_socket(brna);
+ rna_def_cmp_output_file_socket(brna);
}
/* clean up macro definition */
diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h
index b336f864012..745a956d831 100644
--- a/source/blender/makesrna/intern/rna_nodetree_types.h
+++ b/source/blender/makesrna/intern/rna_nodetree_types.h
@@ -113,7 +113,6 @@ DefNode( CompositorNode, CMP_NODE_IMAGE, def_cmp_image, "IMAGE
DefNode( CompositorNode, CMP_NODE_R_LAYERS, def_cmp_render_layers, "R_LAYERS", RLayers, "Render Layers", "" )
DefNode( CompositorNode, CMP_NODE_COMPOSITE, 0, "COMPOSITE", Composite, "Composite", "" )
DefNode( CompositorNode, CMP_NODE_OUTPUT_FILE, def_cmp_output_file, "OUTPUT_FILE", OutputFile, "Output File", "" )
-DefNode( CompositorNode, CMP_NODE_OUTPUT_MULTI_FILE, def_cmp_output_multi_file, "OUTPUT_MULTI_FILE", OutputMultiFile, "Output Multi File", "" )
DefNode( CompositorNode, CMP_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" )
DefNode( CompositorNode, CMP_NODE_TRANSLATE, 0, "TRANSLATE", Translate, "Translate", "" )
DefNode( CompositorNode, CMP_NODE_ZCOMBINE, def_cmp_zcombine, "ZCOMBINE", Zcombine, "Z Combine", "" )
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index b458ae3a77d..aabf13f3bb2 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -222,4 +222,8 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
+if(WITH_IMAGE_OPENEXR)
+ add_definitions(-DWITH_OPENEXR)
+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 e2bbaea8c7f..284b89bc095 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -55,7 +55,6 @@ void register_node_type_cmp_composite(struct bNodeTreeType *ttype);
void register_node_type_cmp_viewer(struct bNodeTreeType *ttype);
void register_node_type_cmp_splitviewer(struct bNodeTreeType *ttype);
void register_node_type_cmp_output_file(struct bNodeTreeType *ttype);
-void register_node_type_cmp_output_multi_file(struct bNodeTreeType *ttype);
void register_node_type_cmp_view_levels(struct bNodeTreeType *ttype);
void register_node_type_cmp_curve_rgb(struct bNodeTreeType *ttype);
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index 66075f1bba4..90aa03997c1 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -37,107 +37,22 @@
#include "node_composite_util.h"
-/* **************** OUTPUT FILE ******************** */
-static bNodeSocketTemplate cmp_node_output_file_in[]= {
- { SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f},
- { SOCK_FLOAT, 1, "Z", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
- { -1, 0, "" }
-};
-
-static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
-{
- /* image assigned to output */
- /* stack order input sockets: col, alpha */
-
- if(in[0]->data) {
- RenderData *rd= data;
- NodeImageFile *nif= node->storage;
- if(nif->sfra!=nif->efra && (rd->cfra<nif->sfra || rd->cfra>nif->efra)) {
- return; /* BAIL OUT RETURN */
- }
- else if (!G.rendering) {
- /* only output files when rendering a sequence -
- * otherwise, it overwrites the output files just
- * scrubbing through the timeline when the compositor updates */
- return;
- } else {
- Main *bmain= G.main; /* TODO, have this passed along */
- CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
- ImBuf *ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
- char string[FILE_MAX];
-
- ibuf->rect_float= cbuf->rect;
- ibuf->dither= rd->dither_intensity;
-
- if (rd->color_mgt_flag & R_COLOR_MANAGEMENT)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
-
- if(in[1]->data) {
- CompBuf *zbuf= in[1]->data;
- if(zbuf->type==CB_VAL && zbuf->x==cbuf->x && zbuf->y==cbuf->y) {
- nif->im_format.flag |= R_IMF_FLAG_ZBUF;
- ibuf->zbuf_float= zbuf->rect;
- }
- }
-
- BKE_makepicstring(string, nif->name, bmain->name, rd->cfra, nif->im_format.imtype, (rd->scemode & R_EXTENSION), TRUE);
-
- if(0 == BKE_write_ibuf(ibuf, string, &nif->im_format))
- printf("Cannot save Node File Output to %s\n", string);
- else
- printf("Saved: %s\n", string);
-
- IMB_freeImBuf(ibuf);
-
- generate_preview(data, node, cbuf);
-
- if(in[0]->data != cbuf)
- free_compbuf(cbuf);
- }
- }
-}
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
-static void node_composit_init_output_file(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *ntemp)
-{
- RenderData *rd = &ntemp->scene->r;
- NodeImageFile *nif= MEM_callocN(sizeof(NodeImageFile), "node image file");
- node->storage= nif;
+#include "intern/openexr/openexr_multi.h"
- BLI_strncpy(nif->name, rd->pic, sizeof(nif->name));
- nif->im_format= rd->im_format;
- if (BKE_imtype_is_movie(nif->im_format.imtype)) {
- nif->im_format.imtype= R_IMF_IMTYPE_OPENEXR;
- }
- nif->sfra= rd->sfra;
- nif->efra= rd->efra;
-}
-
-void register_node_type_cmp_output_file(bNodeTreeType *ttype)
-{
- static bNodeType ntype;
-
- node_type_base(ttype, &ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
- node_type_socket_templates(&ntype, cmp_node_output_file_in, NULL);
- node_type_size(&ntype, 140, 80, 300);
- node_type_init(&ntype, node_composit_init_output_file);
- node_type_storage(&ntype, "NodeImageFile", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, node_composit_exec_output_file);
-
- nodeRegisterType(ttype, &ntype);
-}
-
-
-/* =============================================================================== */
+/* **************** OUTPUT FILE ******************** */
-void ntreeCompositOutputMultiFileAddSocket(bNodeTree *ntree, bNode *node, ImageFormatData *im_format)
+bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, const char *name, ImageFormatData *im_format)
{
- bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, "", SOCK_RGBA);
+ bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_RGBA);
/* create format data for the input socket */
NodeImageMultiFileSocket *sockdata = MEM_callocN(sizeof(NodeImageMultiFileSocket), "socket image format");
sock->storage = sockdata;
- sock->struct_type = SOCK_STRUCT_OUTPUT_MULTI_FILE;
+ sock->struct_type = SOCK_STRUCT_OUTPUT_FILE;
if(im_format) {
sockdata->format= *im_format;
@@ -145,11 +60,13 @@ void ntreeCompositOutputMultiFileAddSocket(bNodeTree *ntree, bNode *node, ImageF
sockdata->format.imtype= R_IMF_IMTYPE_OPENEXR;
}
}
- /* use render data format by default */
- sockdata->use_render_format = 1;
+ /* use node data format by default */
+ sockdata->use_node_format = 1;
+
+ return sock;
}
-int ntreeCompositOutputMultiFileRemoveActiveSocket(bNodeTree *ntree, bNode *node)
+int ntreeCompositOutputFileRemoveActiveSocket(bNodeTree *ntree, bNode *node)
{
NodeImageMultiFile *nimf = node->storage;
bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input);
@@ -164,19 +81,20 @@ int ntreeCompositOutputMultiFileRemoveActiveSocket(bNodeTree *ntree, bNode *node
return 1;
}
-static void init_output_multi_file(bNodeTree *ntree, bNode* node, bNodeTemplate *ntemp)
+static void init_output_file(bNodeTree *ntree, bNode* node, bNodeTemplate *ntemp)
{
RenderData *rd = &ntemp->scene->r;
NodeImageMultiFile *nimf= MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
node->storage= nimf;
BLI_strncpy(nimf->base_path, rd->pic, sizeof(nimf->base_path));
+ nimf->format = rd->im_format;
/* add one socket by default */
- ntreeCompositOutputMultiFileAddSocket(ntree, node, &rd->im_format);
+ ntreeCompositOutputFileAddSocket(ntree, node, "Image", &rd->im_format);
}
-void free_output_multi_file(bNode *node)
+static void free_output_file(bNode *node)
{
bNodeSocket *sock;
@@ -188,7 +106,7 @@ void free_output_multi_file(bNode *node)
MEM_freeN(node->storage);
}
-void copy_output_multi_file(struct bNode *node, struct bNode *target)
+static void copy_output_file(struct bNode *node, struct bNode *target)
{
bNodeSocket *sock, *newsock;
@@ -200,52 +118,73 @@ void copy_output_multi_file(struct bNode *node, struct bNode *target)
}
}
-static void exec_output_multi_file(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
+static void update_output_file(bNodeTree *UNUSED(ntree), bNode *node)
{
- RenderData *rd= data;
+ bNodeSocket *sock;
+
+ /* automatically update the socket type based on linked input */
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ if (sock->link) {
+ int linktype = sock->link->fromsock->type;
+ if (linktype != sock->type)
+ nodeSocketSetType(sock, linktype);
+ }
+ }
+}
+
+/* write input data into individual files */
+static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack **in)
+{
+ Main *bmain= G.main; /* TODO, have this passed along */
NodeImageMultiFile *nimf= node->storage;
bNodeSocket *sock;
int i;
+ int has_preview = 0;
for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
- if (!in[i]->data)
- continue;
-
- if (!G.rendering) {
- /* only output files when rendering a sequence -
- * otherwise, it overwrites the output files just
- * scrubbing through the timeline when the compositor updates */
- return;
- } else {
- Main *bmain= G.main; /* TODO, have this passed along */
+ if (in[i]->data) {
NodeImageMultiFileSocket *sockdata = sock->storage;
- CompBuf *cbuf= typecheck_compbuf(in[i]->data, CB_RGBA);
- ImBuf *ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
- ImageFormatData *format = (sockdata->use_render_format ? &rd->im_format : &sockdata->format);
+ ImageFormatData *format = (sockdata->use_node_format ? &nimf->format : &sockdata->format);
char path[FILE_MAX];
- char string[FILE_MAX];
+ char filename[FILE_MAX];
+ CompBuf *cbuf;
+ ImBuf *ibuf;
- ibuf->rect_float= cbuf->rect;
- ibuf->dither= rd->dither_intensity;
+ switch (format->planes) {
+ case R_IMF_PLANES_BW:
+ cbuf = typecheck_compbuf(in[i]->data, CB_VAL);
+ break;
+ case R_IMF_PLANES_RGB:
+ cbuf = typecheck_compbuf(in[i]->data, CB_VEC3);
+ break;
+ case R_IMF_PLANES_RGBA:
+ cbuf = typecheck_compbuf(in[i]->data, CB_RGBA);
+ break;
+ }
+
+ ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, format->planes, 0);
+ ibuf->rect_float = cbuf->rect;
+ ibuf->dither = rd->dither_intensity;
if (rd->color_mgt_flag & R_COLOR_MANAGEMENT)
ibuf->profile = IB_PROFILE_LINEAR_RGB;
/* get full path */
BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sock->name);
+ BKE_makepicstring(filename, path, bmain->name, rd->cfra, format->imtype, (rd->scemode & R_EXTENSION), TRUE);
- BKE_makepicstring(string, path, bmain->name, rd->cfra, format->imtype, (rd->scemode & R_EXTENSION), TRUE);
-
- if(0 == BKE_write_ibuf(ibuf, string, format))
- printf("Cannot save Node File Output to %s\n", string);
+ if(0 == BKE_write_ibuf(ibuf, filename, format))
+ printf("Cannot save Node File Output to %s\n", filename);
else
- printf("Saved: %s\n", string);
+ printf("Saved: %s\n", filename);
- IMB_freeImBuf(ibuf);
+ IMB_freeImBuf(ibuf);
- #if 0 /* XXX not used yet */
- generate_preview(data, node, cbuf);
- #endif
+ /* simply pick the first valid input for preview */
+ if (!has_preview) {
+ generate_preview(rd, node, cbuf);
+ has_preview = 1;
+ }
if(in[i]->data != cbuf)
free_compbuf(cbuf);
@@ -253,16 +192,129 @@ static void exec_output_multi_file(void *data, bNode *node, bNodeStack **in, bNo
}
}
-void register_node_type_cmp_output_multi_file(bNodeTreeType *ttype)
+/* write input data into layers */
+static void exec_output_file_multilayer(RenderData *rd, bNode *node, bNodeStack **in)
+{
+ Main *bmain= G.main; /* TODO, have this passed along */
+ NodeImageMultiFile *nimf= node->storage;
+ void *exrhandle= IMB_exr_get_handle();
+ char filename[FILE_MAX];
+ bNodeSocket *sock;
+ int i;
+ /* Must have consistent pixel size for exr file, simply take the first valid input size. */
+ int rectx = -1;
+ int recty = -1;
+ int has_preview = 0;
+
+ BKE_makepicstring(filename, nimf->base_path, bmain->name, rd->cfra, R_IMF_IMTYPE_MULTILAYER, (rd->scemode & R_EXTENSION), TRUE);
+ BLI_make_existing_file(filename);
+
+ for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
+ if (in[i]->data) {
+ CompBuf *cbuf = in[i]->data;
+ char layname[EXR_LAY_MAXNAME];
+ char channelname[EXR_PASS_MAXNAME];
+ char *channelname_ext;
+
+ if (cbuf->rect_procedural) {
+ printf("Error writing multilayer EXR: Procedural buffer not supported\n");
+ continue;
+ }
+ if (rectx < 0) {
+ rectx = cbuf->x;
+ recty = cbuf->y;
+ }
+ else if (cbuf->x != rectx || cbuf->y != recty) {
+ printf("Error: Multilayer EXR output node %s expects same resolution for all input buffers. Layer %s skipped.\n", node->name, sock->name);
+ continue;
+ }
+
+ BLI_strncpy(layname, sock->name, sizeof(layname));
+ BLI_strncpy(channelname, sock->name, sizeof(channelname)-2);
+ channelname_ext = channelname + strlen(channelname);
+
+ /* create channels */
+ switch (cbuf->type) {
+ case CB_VAL:
+ strcpy(channelname_ext, ".V");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 1, rectx, cbuf->rect);
+ break;
+ case CB_VEC2:
+ strcpy(channelname_ext, ".X");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 2, 2*rectx, cbuf->rect);
+ strcpy(channelname_ext, ".Y");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 2, 2*rectx, cbuf->rect+1);
+ break;
+ case CB_VEC3:
+ strcpy(channelname_ext, ".X");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 3, 3*rectx, cbuf->rect);
+ strcpy(channelname_ext, ".Y");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 3, 3*rectx, cbuf->rect+1);
+ strcpy(channelname_ext, ".Z");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 3, 3*rectx, cbuf->rect+2);
+ break;
+ case CB_RGBA:
+ strcpy(channelname_ext, ".R");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 4, 4*rectx, cbuf->rect);
+ strcpy(channelname_ext, ".G");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 4, 4*rectx, cbuf->rect+1);
+ strcpy(channelname_ext, ".B");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 4, 4*rectx, cbuf->rect+2);
+ strcpy(channelname_ext, ".A");
+ IMB_exr_add_channel(exrhandle, layname, channelname, 4, 4*rectx, cbuf->rect+3);
+ break;
+ }
+
+ /* simply pick the first valid input for preview */
+ if (!has_preview) {
+ generate_preview(rd, node, cbuf);
+ has_preview = 1;
+ }
+ }
+ }
+
+ /* when the filename has no permissions, this can fail */
+ if(IMB_exr_begin_write(exrhandle, filename, rectx, recty, nimf->format.compress)) {
+ IMB_exr_write_channels(exrhandle);
+ }
+ else {
+ /* TODO, get the error from openexr's exception */
+ /* XXX nice way to do report? */
+ printf("Error Writing Render Result, see console\n");
+ }
+
+ IMB_exr_close(exrhandle);
+}
+
+static void exec_output_file(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
+{
+ RenderData *rd= data;
+ NodeImageMultiFile *nimf= node->storage;
+
+ if (!G.rendering) {
+ /* only output files when rendering a sequence -
+ * otherwise, it overwrites the output files just
+ * scrubbing through the timeline when the compositor updates */
+ return;
+ }
+
+ if (nimf->format.imtype==R_IMF_IMTYPE_MULTILAYER)
+ exec_output_file_multilayer(rd, node, in);
+ else
+ exec_output_file_singlelayer(rd, node, in);
+}
+
+void register_node_type_cmp_output_file(bNodeTreeType *ttype)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_OUTPUT_MULTI_FILE, "Multi File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS);
+ node_type_base(ttype, &ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_socket_templates(&ntype, NULL, NULL);
node_type_size(&ntype, 140, 80, 300);
- node_type_init(&ntype, init_output_multi_file);
- node_type_storage(&ntype, "NodeImageMultiFile", free_output_multi_file, copy_output_multi_file);
- node_type_exec(&ntype, exec_output_multi_file);
+ node_type_init(&ntype, init_output_file);
+ node_type_storage(&ntype, "NodeImageMultiFile", free_output_file, copy_output_file);
+ node_type_update(&ntype, update_output_file, NULL);
+ node_type_exec(&ntype, exec_output_file);
nodeRegisterType(ttype, &ntype);
}