A number of changes to node RNA and the file output node, to simplify socket types and make node code more robust for future nodes with extra socket data.

* Removed the struct_type identifier from sockets completely. Any specialization of socket types can be done by using separate collections in RNA and customized socket draw callbacks in node type. Sockets themselves are pure data inputs/outputs now. Possibly the sock->storage data could also be removed, but this will change anyway with id properties in custom nodes.

* Replaced the direct socket button draw calls by extra callbacks in node types. This allows nodes to draw sockets in specialized ways without referring to the additional struct_type identifier. Default is simply drawing the socket default_value button, only file output node overrides this atm.

* File output node slots now use a separate file sub-path in their storage data, instead of using the socket name. That way the path is an actual PROP_FILEPATH property and it works better with the UI list template (name property is local to the data struct).

* Node draw contexts for options on the node itself and detail buttons in the sidebar now have an extra context pointer "node" (uiLayoutSetContextPointer). This can be used to bind operator buttons to a specific node, instead of having to rely on the active/selected node(s) or making weak links via node name. Compare to modifiers and logic bricks, they use the same feature.

* Added another operator for reordering custom input slots in the file output node.
This commit is contained in:
Lukas Toenne
2012-05-02 07:18:51 +00:00
parent 7f8643806d
commit 01b3deb680
11 changed files with 308 additions and 203 deletions

View File

@@ -145,6 +145,9 @@ typedef struct bNodeType {
void (*uifunc)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
/// Additional parameters in the side panel.
void (*uifuncbut)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
/// Draw a node socket. Default draws the input value button.
NodeSocketButtonFunction drawinputfunc;
NodeSocketButtonFunction drawoutputfunc;
/// Optional custom label function for the node header.
const char *(*labelfunc)(struct bNode *);
/// Optional custom resize handle polling.

View File

@@ -7786,6 +7786,23 @@ static void do_versions_mesh_mloopcol_swap_2_62_1(Mesh *me)
}
}
static void do_versions_nodetree_multi_file_output_path_2_64_0(bNodeTree *ntree)
{
bNode *node;
for (node=ntree->nodes.first; node; node=node->next) {
if (node->type==CMP_NODE_OUTPUT_FILE) {
bNodeSocket *sock;
for (sock=node->inputs.first; sock; sock=sock->next) {
NodeImageMultiFileSocket *input = sock->storage;
/* input file path is stored in dedicated struct now instead socket name */
BLI_strncpy(input->path, sock->name, sizeof(input->path));
sock->name[0] = '\0'; /* unused */
}
}
}
}
static void do_versions(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
@@ -13282,11 +13299,24 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 263) {
{
/* Default for old files is to save particle rotations to pointcache */
ParticleSettings *part;
for (part = main->particle.first; part; part = part->id.next)
part->flag |= PART_ROTATIONS;
}
{
/* file output node paths are now stored in the file info struct instead socket name */
Scene *sce;
bNodeTree *ntree;
for (sce = main->scene.first; sce; sce=sce->id.next)
if (sce->nodetree)
do_versions_nodetree_multi_file_output_path_2_64_0(sce->nodetree);
for (ntree = main->nodetree.first; ntree; ntree=ntree->id.next)
do_versions_nodetree_multi_file_output_path_2_64_0(ntree);
}
}
if (main->versionfile <= 263 && main->subversionfile == 0) {
Scene *scene;

View File

@@ -98,52 +98,10 @@ 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)
{
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 {
@@ -158,12 +116,6 @@ static void node_socket_button_default(const bContext *C, uiBlock *block,
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;
}
}
typedef struct SocketComponentMenuArgs {
@@ -192,8 +144,6 @@ 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)
{
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 {
@@ -214,24 +164,12 @@ static void node_socket_button_components(const bContext *C, uiBlock *block,
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;
}
}
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)
{
/* 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.
*/
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 {
@@ -249,12 +187,35 @@ static void node_socket_button_color(const bContext *C, uiBlock *block,
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_FILE:
node_socket_button_output_file(C, block, ntree, node, sock, name, x, y, width);
break;
/* standard draw function, display the default input value */
static void node_draw_input_default(const bContext *C, uiBlock *block,
bNodeTree *ntree, bNode *node, bNodeSocket *sock,
const char *name, int x, int y, int width)
{
bNodeSocketType *stype = ntreeGetSocketType(sock->type);
if (stype->buttonfunc)
stype->buttonfunc(C, block, ntree, node, sock, name, x, y, width);
else
node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
}
static void node_draw_output_default(const bContext *C, uiBlock *block,
bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock,
const char *name, int UNUSED(x), int UNUSED(y), int UNUSED(width))
{
SpaceNode *snode = CTX_wm_space_node(C);
float slen;
int ofs = 0;
UI_ThemeColor(TH_TEXT);
slen= snode->aspect*UI_GetStringWidth(name);
while (slen > node->width) {
ofs++;
slen= snode->aspect*UI_GetStringWidth(name+ofs);
}
uiDefBut(block, LABEL, 0, name+ofs, (short)(sock->locx-15.0f-slen), (short)(sock->locy-9.0f),
(short)(node->width-NODE_DY), NODE_DY, NULL, 0, 0, 0, 0, "");
}
/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
@@ -1743,6 +1704,43 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po
uiItemR(layout, ptr, "use_smooth_mask", 0, NULL, ICON_NONE);
}
/* draw function for file output node sockets, displays only sub-path and format, no value button */
static void node_draw_input_file_output(const bContext *C, uiBlock *block,
bNodeTree *ntree, bNode *node, bNodeSocket *sock,
const char *UNUSED(name), int x, int y, int width)
{
NodeImageMultiFileSocket *input = sock->storage;
uiLayout *layout, *row;
PointerRNA nodeptr, inputptr, imfptr;
int imtype;
int rx, ry;
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
RNA_pointer_create(&ntree->id, &RNA_NodeImageFileSocket, input, &inputptr);
layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y+NODE_DY, width, 20, UI_GetStyle());
row = uiLayoutRow(layout, 0);
uiItemL(row, input->path, 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(&inputptr, "use_node_format"))
imfptr = RNA_pointer_get(&inputptr, "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_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
PointerRNA imfptr = RNA_pointer_get(ptr, "format");
@@ -1757,7 +1755,9 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C)
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");
PointerRNA active_input_ptr, op_ptr;
uiLayout *col, *row;
int active_index;
int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
node_composit_buts_file_output(layout, C, ptr);
@@ -1767,7 +1767,16 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
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);
uiTemplateList(layout, C, ptr, "file_inputs", ptr, "active_input_index", NULL, 0, 0, 0);
active_index = RNA_int_get(ptr, "active_input_index");
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_inputs"), active_index, &active_input_ptr);
row = uiLayoutRow(layout, 1);
op_ptr = uiItemFullO(row, "NODE_OT_output_file_move_active_socket", "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&op_ptr, "direction", 1);
op_ptr = uiItemFullO(row, "NODE_OT_output_file_move_active_socket", "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&op_ptr, "direction", 2);
if (active_input_ptr.data) {
uiLayout *row, *col;
@@ -1778,7 +1787,7 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
else
uiItemL(col, "File Path:", 0);
row = uiLayoutRow(col, 0);
uiItemR(row, &active_input_ptr, "name", 0, "", 0);
uiItemR(row, &active_input_ptr, "path", 0, "", 0);
uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
/* in multilayer format all socket format details are ignored */
@@ -2033,6 +2042,7 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_OUTPUT_FILE:
ntype->uifunc= node_composit_buts_file_output;
ntype->uifuncbut= node_composit_buts_file_output_details;
ntype->drawinputfunc = node_draw_input_file_output;
break;
case CMP_NODE_DIFF_MATTE:
ntype->uifunc=node_composit_buts_diff_matte;
@@ -2292,6 +2302,8 @@ void ED_init_node_butfuncs(void)
ntype->drawupdatefunc = node_update_default;
ntype->uifunc = NULL;
ntype->uifuncbut = NULL;
ntype->drawinputfunc = node_draw_input_default;
ntype->drawoutputfunc = node_draw_output_default;
ntype->resize_area_func = node_resize_area_default;
node_common_set_butfunc(ntype);

View File

@@ -89,7 +89,7 @@ static void active_node_panel(const bContext *C, Panel *pa)
SpaceNode *snode= CTX_wm_space_node(C);
bNodeTree *ntree= (snode) ? snode->edittree : NULL;
bNode *node = (ntree) ? nodeGetActive(ntree) : NULL; // xxx... for editing group nodes
uiLayout *layout= pa->layout;
uiLayout *layout;
PointerRNA ptr;
/* verify pointers, and create RNA pointer for the node */
@@ -100,6 +100,10 @@ static void active_node_panel(const bContext *C, Panel *pa)
//else
RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
/* XXX nicer way to make sub-layout? */
layout = uiLayoutColumn(pa->layout, 0);
uiLayoutSetContextPointer(layout, "node", &ptr);
/* draw this node's name, etc. */
uiItemR(layout, &ptr, "label", 0, NULL, ICON_NODE);
uiItemS(layout);

View File

@@ -303,6 +303,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
layout= uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
locx+NODE_DYS, dy, node->butr.xmax, NODE_DY, UI_GetStyle());
uiLayoutSetContextPointer(layout, "node", &ptr);
node->typeinfo->uifunc(layout, (bContext *)C, &ptr);
@@ -711,41 +712,24 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
/* socket inputs, buttons */
for (sock= node->inputs.first; sock; sock= sock->next) {
bNodeSocketType *stype= ntreeGetSocketType(sock->type);
if (nodeSocketIsHidden(sock))
continue;
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE);
if (stype->buttonfunc)
stype->buttonfunc(C, node->block, ntree, node, sock, IFACE_(sock->name), sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY);
node->typeinfo->drawinputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY);
}
/* socket outputs */
for (sock= node->outputs.first; sock; sock= sock->next) {
PointerRNA sockptr;
RNA_pointer_create((ID*)ntree, &RNA_NodeSocket, sock, &sockptr);
if (nodeSocketIsHidden(sock))
continue;
node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE);
{
const char *name = IFACE_(sock->name);
float slen;
int ofs = 0;
UI_ThemeColor(TH_TEXT);
slen= snode->aspect*UI_GetStringWidth(name);
while (slen > node->width) {
ofs++;
slen= snode->aspect*UI_GetStringWidth(name+ofs);
}
uiDefBut(node->block, LABEL, 0, name+ofs, (short)(sock->locx-15.0f-slen), (short)(sock->locy-9.0f),
(short)(node->width-NODE_DY), NODE_DY, NULL, 0, 0, 0, 0, "");
}
node->typeinfo->drawoutputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
sock->locx-node->width+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY);
}
/* preview */

View File

@@ -3591,12 +3591,16 @@ 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);
PointerRNA ptr;
bNodeTree *ntree;
bNode *node;
char file_path[MAX_NAME];
if (!node)
ptr = CTX_data_pointer_get(C, "node");
if (!ptr.data)
return OPERATOR_CANCELLED;
node = ptr.data;
ntree = ptr.id.data;
RNA_string_get(op->ptr, "file_path", file_path);
ntreeCompositOutputFileAddSocket(ntree, node, file_path, &scene->r.im_format);
@@ -3628,11 +3632,14 @@ void NODE_OT_output_file_add_socket(wmOperatorType *ot)
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;
bNode *node = nodeGetActive(ntree);
PointerRNA ptr = CTX_data_pointer_get(C, "node");
bNodeTree *ntree;
bNode *node;
if (!node)
if (!ptr.data)
return OPERATOR_CANCELLED;
node = ptr.data;
ntree = ptr.id.data;
if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node))
return OPERATOR_CANCELLED;
@@ -3656,3 +3663,68 @@ void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
/* ****************** Multi File Output Move Socket ******************* */
static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode= CTX_wm_space_node(C);
PointerRNA ptr = CTX_data_pointer_get(C, "node");
bNode *node;
NodeImageMultiFile *nimf;
bNodeSocket *sock;
int direction;
if (!ptr.data)
return OPERATOR_CANCELLED;
node = ptr.data;
nimf = node->storage;
sock = BLI_findlink(&node->inputs, nimf->active_input);
if (!sock)
return OPERATOR_CANCELLED;
direction = RNA_enum_get(op->ptr, "direction");
if (direction==1) {
bNodeSocket *before = sock->prev;
if (!before)
return OPERATOR_CANCELLED;
BLI_remlink(&node->inputs, sock);
BLI_insertlinkbefore(&node->inputs, before, sock);
--nimf->active_input;
}
else {
bNodeSocket *after = sock->next;
if (!after)
return OPERATOR_CANCELLED;
BLI_remlink(&node->inputs, sock);
BLI_insertlinkafter(&node->inputs, after, sock);
++nimf->active_input;
}
snode_notify(C, snode);
return OPERATOR_FINISHED;
}
void NODE_OT_output_file_move_active_socket(wmOperatorType *ot)
{
static EnumPropertyItem direction_items[] = {
{1, "UP", 0, "Up", ""},
{2, "DOWN", 0, "Down", ""}};
/* identifiers */
ot->name = "Move File Node Socket";
ot->description = "Move the active input of a file output node up or down the list";
ot->idname = "NODE_OT_output_file_move_active_socket";
/* callbacks */
ot->exec = node_output_file_move_active_socket_exec;
ot->poll = composite_node_active;
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_enum(ot->srna, "direction", direction_items, 2, "Direction", "");
}

View File

@@ -166,6 +166,7 @@ void NODE_OT_new_node_tree(struct wmOperatorType *ot);
void NODE_OT_output_file_add_socket(struct wmOperatorType *ot);
void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot);
void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
extern const char *node_context_dir[];

View File

@@ -103,6 +103,7 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_output_file_add_socket);
WM_operatortype_append(NODE_OT_output_file_remove_active_socket);
WM_operatortype_append(NODE_OT_output_file_move_active_socket);
}
void ED_operatormacros_node(void)

View File

@@ -77,7 +77,7 @@ typedef struct bNodeSocket {
short type, flag;
short limit; /* max. number of links */
short struct_type; /* optional identifier for RNA struct subtype */
short pad1;
float locx, locy;
@@ -87,7 +87,7 @@ typedef struct bNodeSocket {
short stack_index; /* local stack index */
/* XXX deprecated, kept for forward compatibility */
short stack_type DNA_DEPRECATED;
int pad3;
int pad2;
void *cache; /* cached data from execution */
/* internal data to retrieve relations and groups */
@@ -112,10 +112,6 @@ 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_FILE 1 /* file output node socket */
/* socket side (input/output) */
#define SOCK_IN 1
#define SOCK_OUT 2
@@ -371,6 +367,7 @@ typedef struct NodeImageMultiFileSocket {
short use_render_format DNA_DEPRECATED;
short use_node_format; /* use overall node image format */
int pad2;
char path[1024]; /* 1024 = FILE_MAX */
ImageFormatData format;
} NodeImageMultiFileSocket;

View File

@@ -245,8 +245,6 @@ static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
return &RNA_NodeSocket##stypename##idname; \
}
switch (sock->struct_type) {
case SOCK_STRUCT_NONE:
switch (sock->type) {
case SOCK_FLOAT:
NODE_DEFINE_SUBTYPES_FLOAT
@@ -264,10 +262,6 @@ static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
case SOCK_SHADER:
return &RNA_NodeSocketShader;
}
break;
case SOCK_STRUCT_OUTPUT_FILE:
return &RNA_NodeImageFileSocket;
}
#undef SUBTYPE
}
@@ -858,14 +852,18 @@ 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)
static void rna_NodeOutputFile_file_inputs_begin(CollectionPropertyIterator *iter, 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;
rna_iterator_listbase_begin(iter, &node->inputs, NULL);
}
static PointerRNA rna_NodeOutputFile_file_inputs_get(CollectionPropertyIterator *iter)
{
PointerRNA ptr;
bNodeSocket *sock = rna_iterator_listbase_get(iter);
RNA_pointer_create(iter->ptr.id.data, &RNA_NodeImageFileSocket, sock->storage, &ptr);
return ptr;
}
#else
@@ -1827,22 +1825,23 @@ static void rna_def_cmp_output_file_socket(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "NodeImageFileSocket", "NodeSocketRGBA");
RNA_def_struct_sdna(srna, "bNodeSocket");
RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
srna = RNA_def_struct(brna, "NodeImageFileSocket", NULL);
RNA_def_struct_sdna(srna, "NodeImageMultiFileSocket");
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_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");
RNA_def_property_update(prop, NC_NODE|NA_EDITED, NULL);
prop = RNA_def_property(srna, "format", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ImageFormatSettings");
prop = RNA_def_property(srna, "path", PROP_STRING, PROP_FILEPATH);
RNA_def_property_string_sdna(prop, NULL, "path");
RNA_def_property_ui_text(prop, "Path", "Subpath used for this input");
RNA_def_struct_name_property(srna, prop);
RNA_def_property_update(prop, NC_NODE|NA_EDITED, NULL);
}
static void def_cmp_output_file(StructRNA *srna)
{
@@ -1855,12 +1854,6 @@ static void def_cmp_output_file(StructRNA *srna)
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");
@@ -1868,6 +1861,12 @@ static void def_cmp_output_file(StructRNA *srna)
prop = RNA_def_property(srna, "format", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ImageFormatSettings");
prop = RNA_def_property(srna, "file_inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_funcs(prop, "rna_NodeOutputFile_file_inputs_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end",
"rna_NodeOutputFile_file_inputs_get", NULL, NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "NodeImageFileSocket");
RNA_def_property_ui_text(prop, "File Inputs", "");
}
static void def_cmp_dilate_erode(StructRNA *srna)

View File

@@ -48,12 +48,13 @@
bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, const char *name, ImageFormatData *im_format)
{
NodeImageMultiFile *nimf = node->storage;
bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, name, SOCK_RGBA);
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_FILE;
BLI_strncpy(sockdata->path, name, sizeof(sockdata->path));
if (im_format) {
sockdata->format= *im_format;
@@ -188,7 +189,7 @@ static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack
ibuf->profile = IB_PROFILE_LINEAR_RGB;
/* get full path */
BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sock->name);
BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sockdata->path);
BKE_makepicstring(filename, path, bmain->name, rd->cfra, format->imtype, (rd->scemode & R_EXTENSION), TRUE);
if (0 == BKE_write_ibuf(ibuf, filename, format))
@@ -229,6 +230,7 @@ static void exec_output_file_multilayer(RenderData *rd, bNode *node, bNodeStack
for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
if (in[i]->data) {
NodeImageMultiFileSocket *sockdata = sock->storage;
CompBuf *cbuf = in[i]->data;
char layname[EXR_LAY_MAXNAME];
char channelname[EXR_PASS_MAXNAME];
@@ -247,8 +249,8 @@ static void exec_output_file_multilayer(RenderData *rd, bNode *node, bNodeStack
continue;
}
BLI_strncpy(layname, sock->name, sizeof(layname));
BLI_strncpy(channelname, sock->name, sizeof(channelname)-2);
BLI_strncpy(layname, sockdata->path, sizeof(layname));
BLI_strncpy(channelname, sockdata->path, sizeof(channelname)-2);
channelname_ext = channelname + strlen(channelname);
/* create channels */