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_node.h8
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/blenloader/intern/writefile.c6
-rw-r--r--source/blender/editors/space_node/drawnode.c160
-rw-r--r--source/blender/editors/space_node/node_draw.c10
-rw-r--r--source/blender/editors/space_node/node_edit.c74
-rw-r--r--source/blender/editors/space_node/node_header.c18
-rw-r--r--source/blender/editors/space_node/node_intern.h3
-rw-r--r--source/blender/editors/space_node/node_ops.c3
-rw-r--r--source/blender/makesdna/DNA_node_types.h18
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c107
-rw-r--r--source/blender/makesrna/intern/rna_nodetree_types.h1
-rw-r--r--source/blender/nodes/NOD_composite.h1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c182
15 files changed, 514 insertions, 79 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index ae2f9305894..fe914a8c5ba 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -112,8 +112,9 @@ typedef struct bNodeSocketType {
typedef struct bNodeTemplate {
int type;
- /* group tree */
- struct bNodeTree *ngroup;
+ struct Main *main;
+ struct Scene *scene;
+ struct bNodeTree *ngroup; /* group tree */
} bNodeTemplate;
/** Defines a node type.
@@ -653,6 +654,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_GLARE 301
#define CMP_NODE_TONEMAP 302
@@ -692,6 +694,8 @@ 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);
/* ************** TEXTURE NODES *************** */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index b72abcd79f4..cf2cbaed8f1 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1804,6 +1804,7 @@ 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/writefile.c b/source/blender/blenloader/intern/writefile.c
index a6a61286fb1..8ea5427b1ed 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -725,6 +725,12 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
else
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
+
+ if (node->type==CMP_NODE_OUTPUT_MULTI_FILE) {
+ /* inputs have own storage data */
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ writestruct(wd, DATA, "NodeImageMultiFileSocket", 1, sock->storage);
+ }
}
for(link= ntree->links.first; link; link= link->next)
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 143173da5bc..63eead6780f 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -107,16 +107,20 @@ 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)
{
- 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);
+ 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);
+ }
}
typedef struct SocketComponentMenuArgs {
@@ -145,42 +149,80 @@ 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)
{
- 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, "");
+ 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, "");
+ }
}
static void node_socket_button_color(const bContext *C, uiBlock *block,
bNodeTree *ntree, bNode *node, bNodeSocket *sock,
const char *name, int x, int y, int width)
{
- PointerRNA ptr;
- uiBut *bt;
- int labelw= width - 40;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- bt=uiDefButR(block, COL, B_NODE_EXEC, "",
- x, y+2, (labelw>0 ? 40 : 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);
+ /* XXX would be nicer to have draw function based on sock->struct_type as well,
+ * but currently socket types are completely identified by data type only.
+ */
- if (name[0]!='\0' && labelw>0)
- uiDefBut(block, LABEL, 0, name, x + 40, y+2, labelw, NODE_DY-2, NULL, 0, 0, 0, 0, "");
+ 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;
+ int labelw= width - 40;
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
+
+ bt=uiDefButR(block, COL, B_NODE_EXEC, "",
+ x, y+2, (labelw>0 ? 40 : 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);
+
+ if (name[0]!='\0' && labelw>0)
+ uiDefBut(block, LABEL, 0, name, x + 40, y+2, labelw, NODE_DY-2, NULL, 0, 0, 0, 0, "");
+ }
+ 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);
+ break;
+ }
+ }
}
/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
@@ -1673,6 +1715,42 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C)
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);
+ uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE);
+}
+static void node_composit_buts_multi_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+ PointerRNA active_input_ptr = RNA_pointer_get(ptr, "active_input");
+
+ node_composit_buts_multi_file_output(layout, C, ptr);
+
+ uiItemO(layout, "Add Input", ICON_ZOOMIN, "NODE_OT_output_multi_file_add_socket");
+
+ uiTemplateList(layout, C, ptr, "inputs", ptr, "active_input_index", NULL, 0, 0, 0);
+
+ if (active_input_ptr.data) {
+ uiLayout *row, *col;
+
+ uiItemS(layout);
+
+ col = uiLayoutColumn(layout, 1);
+ 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);
+ uiItemL(layout, "Format:", 0);
+ uiItemR(layout, &active_input_ptr, "use_render_format", 0, NULL, 0);
+ if (!RNA_boolean_get(&active_input_ptr, "use_render_format")) {
+ PointerRNA imfptr = RNA_pointer_get(&active_input_ptr, "format");
+ uiTemplateImageSettings(layout, &imfptr);
+ }
+ }
+}
+
static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "space", 0, "", ICON_NONE);
@@ -1908,6 +1986,10 @@ static void node_composit_set_butfunc(bNodeType *ntype)
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;
+ break;
case CMP_NODE_DIFF_MATTE:
ntype->uifunc=node_composit_buts_diff_matte;
break;
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index a82ea9e9046..0913c3fb9eb 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -718,14 +718,8 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE);
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE)) {
- uiDefBut(node->block, LABEL, 0, sock->name, sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY, NODE_DY,
- NULL, 0, 0, 0, 0, "");
- }
- else {
- if (stype->buttonfunc)
- stype->buttonfunc(C, node->block, ntree, node, sock, sock->name, sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY);
- }
+ if (stype->buttonfunc)
+ stype->buttonfunc(C, node->block, ntree, node, sock, sock->name, sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY);
}
/* socket outputs */
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 906b5d01e32..d92bdc42958 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -3587,3 +3587,77 @@ void NODE_OT_new_node_tree(wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", nodetree_type_items, NTREE_COMPOSIT, "Tree Type", "");
RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME-2, "Name", "");
}
+
+/* ****************** Multi File Output Add Socket ******************* */
+
+static int node_output_multi_file_add_socket_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene= CTX_data_scene(C);
+ SpaceNode *snode= CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *node = nodeGetActive(ntree);
+
+ if (!node)
+ return OPERATOR_CANCELLED;
+
+ ntreeCompositOutputMultiFileAddSocket(ntree, node, &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)
+{
+ /* 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";
+
+ /* callbacks */
+ ot->exec= node_output_multi_file_add_socket_exec;
+ ot->invoke= node_output_multi_file_add_socket_invoke;
+ ot->poll= composite_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ****************** Multi File Output Remove Socket ******************* */
+
+static int node_output_multi_file_remove_active_socket_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode= CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNode *node = nodeGetActive(ntree);
+
+ if (!node)
+ return OPERATOR_CANCELLED;
+
+ if (!ntreeCompositOutputMultiFileRemoveActiveSocket(ntree, node))
+ return OPERATOR_CANCELLED;
+
+ snode_notify(C, snode);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_output_multi_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";
+
+ /* callbacks */
+ ot->exec= node_output_multi_file_remove_active_socket_exec;
+ ot->poll= composite_node_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index 6dd5eeba832..df83afc143e 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -110,14 +110,22 @@ static void do_node_add(bContext *C, bNodeTemplate *ntemp)
static void do_node_add_static(bContext *C, void *UNUSED(arg), int event)
{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
bNodeTemplate ntemp;
+
ntemp.type = event;
+ ntemp.main = bmain;
+ ntemp.scene = scene;
+
do_node_add(C, &ntemp);
}
static void do_node_add_group(bContext *C, void *UNUSED(arg), int event)
{
SpaceNode *snode= CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
bNodeTemplate ntemp;
if (event>=0) {
@@ -143,14 +151,24 @@ static void do_node_add_group(bContext *C, void *UNUSED(arg), int event)
if (!ntemp.ngroup)
return;
+ ntemp.main = bmain;
+ ntemp.scene = scene;
+
do_node_add(C, &ntemp);
}
#if 0 /* disabled */
static void do_node_add_dynamic(bContext *C, void *UNUSED(arg), int event)
{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
bNodeTemplate ntemp;
+
ntemp.type = NODE_DYNAMIC;
+
+ ntemp.main = bmain;
+ ntemp.scene = scene;
+
do_node_add(C, &ntemp);
}
#endif
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 48501079e60..4bfb62023b5 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -159,6 +159,9 @@ 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);
+
extern const char *node_context_dir[];
// XXXXXX
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 508021540b5..493f4747387 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -99,6 +99,9 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_add_file);
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);
}
void ED_operatormacros_node(void)
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 361aca4a572..05a469916a6 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -77,7 +77,7 @@ typedef struct bNodeSocket {
short type, flag;
short limit; /* max. number of links */
- short pad1;
+ short struct_type; /* optional identifier for RNA struct subtype */
float locx, locy;
@@ -112,6 +112,10 @@ typedef struct bNodeSocket {
#define SOCK_INT 6
#define NUM_SOCKET_TYPES 7 /* must be last! */
+/* 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 */
+
/* socket side (input/output) */
#define SOCK_IN 1
#define SOCK_OUT 2
@@ -354,6 +358,18 @@ typedef struct NodeImageFile {
int sfra, efra;
} NodeImageFile;
+typedef struct NodeImageMultiFile {
+ char base_path[1024]; /* 1024 = FILE_MAX */
+ int active_input; /* selected input in details view list */
+ int pad;
+} NodeImageMultiFile;
+typedef struct NodeImageMultiFileSocket {
+ short use_render_format; /* use global render settings instead of own format */
+ short pad1;
+ int pad2;
+ ImageFormatData format;
+} NodeImageMultiFileSocket;
+
typedef struct NodeChroma {
float t1,t2,t3;
float fsize,fstrength,falpha;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 1aecbc223b5..67d27af8b41 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -347,6 +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_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 989202f785c..42668c6080c 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -35,6 +35,8 @@
#include "rna_internal.h"
#include "rna_internal_types.h"
+#include "BLI_listbase.h"
+
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
@@ -243,24 +245,32 @@ static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
return &RNA_NodeSocket##stypename##idname; \
}
- switch (sock->type) {
- case SOCK_FLOAT:
- NODE_DEFINE_SUBTYPES_FLOAT
- break;
- case SOCK_INT:
- NODE_DEFINE_SUBTYPES_INT
- break;
- case SOCK_BOOLEAN:
- return &RNA_NodeSocketBoolean;
- break;
- case SOCK_VECTOR:
- NODE_DEFINE_SUBTYPES_VECTOR
- break;
- case SOCK_RGBA:
- return &RNA_NodeSocketRGBA;
- break;
- case SOCK_SHADER:
- return &RNA_NodeSocketShader;
+ if (sock->struct_type == SOCK_STRUCT_NONE) {
+ switch (sock->type) {
+ case SOCK_FLOAT:
+ NODE_DEFINE_SUBTYPES_FLOAT
+ break;
+ case SOCK_INT:
+ NODE_DEFINE_SUBTYPES_INT
+ break;
+ case SOCK_BOOLEAN:
+ return &RNA_NodeSocketBoolean;
+ break;
+ case SOCK_VECTOR:
+ NODE_DEFINE_SUBTYPES_VECTOR
+ 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;
+ }
}
#undef SUBTYPE
@@ -824,6 +834,16 @@ static void rna_Mapping_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_Node_update(bmain, scene, ptr);
}
+static PointerRNA rna_CompositNodeOutputMultiFile_active_input_get(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ NodeImageMultiFile *nimf = node->storage;
+ bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input);
+ PointerRNA sock_ptr;
+ RNA_pointer_create((ID*)ptr->id.data, &RNA_NodeSocket, sock, &sock_ptr);
+ return sock_ptr;
+}
+
#else
static EnumPropertyItem prop_image_layer_items[] = {
@@ -1782,6 +1802,51 @@ static void def_cmp_output_file(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
}
+static void rna_def_cmp_output_multi_file_socket(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "NodeImageMultiFileSocket", "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_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", "");
+ 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)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeImageMultiFile", "storage");
+
+ prop = RNA_def_property(srna, "base_path", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_string_sdna(prop, NULL, "base_path");
+ RNA_def_property_ui_text(prop, "Base Path", "Base output path for the image");
+ RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "active_input", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, "rna_CompositNodeOutputMultiFile_active_input_get", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "NodeSocket");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Active Input", "Active input in details view list");
+
+ prop = RNA_def_property(srna, "active_input_index", PROP_INT, PROP_NONE);
+ 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");
+}
+
static void def_cmp_dilate_erode(StructRNA *srna)
{
PropertyRNA *prop;
@@ -3144,6 +3209,9 @@ static void rna_def_node_socket_subtype(BlenderRNA *brna, int type, int subtype,
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_NodeSocket_update");
break;
}
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
}
static void rna_def_node(BlenderRNA *brna)
@@ -3407,6 +3475,9 @@ void RNA_def_nodetree(BlenderRNA *brna)
define_specific_node(brna, NODE_FORLOOP, def_forloop);
define_specific_node(brna, NODE_WHILELOOP, def_whileloop);
define_specific_node(brna, NODE_FRAME, def_frame);
+
+ /* special socket types */
+ rna_def_cmp_output_multi_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 745a956d831..b336f864012 100644
--- a/source/blender/makesrna/intern/rna_nodetree_types.h
+++ b/source/blender/makesrna/intern/rna_nodetree_types.h
@@ -113,6 +113,7 @@ 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/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 284b89bc095..e2bbaea8c7f 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -55,6 +55,7 @@ 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 50a196deb07..02df603f494 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -30,6 +30,11 @@
*/
+#include <string.h>
+#include "BLI_path_util.h"
+
+#include "BKE_utildefines.h"
+
#include "node_composite_util.h"
/* **************** OUTPUT FILE ******************** */
@@ -59,7 +64,7 @@ static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack *
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[256];
+ char string[FILE_MAX];
ibuf->rect_float= cbuf->rect;
ibuf->dither= rd->dither_intensity;
@@ -92,21 +97,26 @@ static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack *
}
}
-static void node_composit_init_output_file(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_mute_output_file(void *UNUSED(data), int UNUSED(thread),
+ struct bNode *UNUSED(node), void *UNUSED(nodedata),
+ struct bNodeStack **UNUSED(in), struct bNodeStack **UNUSED(out))
+{
+ /* nothing to do here */
+}
+
+static void node_composit_init_output_file(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *ntemp)
{
- Scene *scene= (Scene *)node->id;
+ RenderData *rd = &ntemp->scene->r;
NodeImageFile *nif= MEM_callocN(sizeof(NodeImageFile), "node image file");
node->storage= nif;
- if(scene) {
- BLI_strncpy(nif->name, scene->r.pic, sizeof(nif->name));
- nif->im_format= scene->r.im_format;
- if (BKE_imtype_is_movie(nif->im_format.imtype)) {
- nif->im_format.imtype= R_IMF_IMTYPE_OPENEXR;
- }
- nif->sfra= scene->r.sfra;
- nif->efra= scene->r.efra;
+ 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)
@@ -119,6 +129,156 @@ void register_node_type_cmp_output_file(bNodeTreeType *ttype)
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);
+ node_type_mute(&ntype, node_composit_mute_output_file, NULL);
+
+ nodeRegisterType(ttype, &ntype);
+}
+
+
+/* =============================================================================== */
+
+
+void ntreeCompositOutputMultiFileAddSocket(bNodeTree *ntree, bNode *node, ImageFormatData *im_format)
+{
+ bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, "", 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;
+
+ if(im_format) {
+ sockdata->format= *im_format;
+ if (BKE_imtype_is_movie(sockdata->format.imtype)) {
+ sockdata->format.imtype= R_IMF_IMTYPE_OPENEXR;
+ }
+ }
+ /* use render data format by default */
+ sockdata->use_render_format = 1;
+}
+
+int ntreeCompositOutputMultiFileRemoveActiveSocket(bNodeTree *ntree, bNode *node)
+{
+ NodeImageMultiFile *nimf = node->storage;
+ bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input);
+
+ if (!sock)
+ return 0;
+
+ /* free format data */
+ MEM_freeN(sock->storage);
+
+ nodeRemoveSocket(ntree, node, sock);
+ return 1;
+}
+
+static void init_output_multi_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));
+
+ /* add one socket by default */
+ ntreeCompositOutputMultiFileAddSocket(ntree, node, &rd->im_format);
+}
+
+void free_output_multi_file(bNode *node)
+{
+ bNodeSocket *sock;
+
+ /* free storage data in sockets */
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ MEM_freeN(sock->storage);
+ }
+
+ MEM_freeN(node->storage);
+}
+
+void copy_output_multi_file(struct bNode *node, struct bNode *target)
+{
+ bNodeSocket *sock, *newsock;
+
+ target->storage = MEM_dupallocN(node->storage);
+
+ /* duplicate storage data in sockets */
+ for (sock=node->inputs.first, newsock=target->inputs.first; sock && newsock; sock=sock->next, newsock=newsock->next) {
+ newsock->storage = MEM_dupallocN(sock->storage);
+ }
+}
+
+static void exec_output_multi_file(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
+{
+ RenderData *rd= data;
+ NodeImageMultiFile *nimf= node->storage;
+ bNodeSocket *sock;
+ int i;
+
+ 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 */
+ 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);
+ char path[FILE_MAX];
+ 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;
+
+ /* get full path */
+ BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sock->name);
+
+ 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);
+ else
+ printf("Saved: %s\n", string);
+
+ IMB_freeImBuf(ibuf);
+
+ #if 0 /* XXX not used yet */
+ generate_preview(data, node, cbuf);
+ #endif
+
+ if(in[i]->data != cbuf)
+ free_compbuf(cbuf);
+ }
+ }
+}
+
+static void mute_output_multi_file(void *UNUSED(data), int UNUSED(thread),
+ struct bNode *UNUSED(node), void *UNUSED(nodedata),
+ struct bNodeStack **UNUSED(in), struct bNodeStack **UNUSED(out))
+{
+ /* nothing to do here */
+}
+
+void register_node_type_cmp_output_multi_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_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_mute(&ntype, mute_output_multi_file, NULL);
nodeRegisterType(ttype, &ntype);
}