Blender  V2.93
node_composite_outputFile.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2006 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BLI_string_utils.h"
25 #include "BLI_utildefines.h"
26 #include <string.h>
27 
28 #include "BKE_context.h"
29 
30 #include "RNA_access.h"
31 
32 #include "node_composite_util.h"
33 
35 
36 /* **************** OUTPUT FILE ******************** */
37 
38 /* find unique path */
39 static bool unique_path_unique_check(void *arg, const char *name)
40 {
41  struct {
42  ListBase *lb;
43  bNodeSocket *sock;
44  } *data = arg;
45  bNodeSocket *sock;
46  for (sock = data->lb->first; sock; sock = sock->next) {
47  if (sock != data->sock) {
48  NodeImageMultiFileSocket *sockdata = sock->storage;
49  if (STREQ(sockdata->path, name)) {
50  return true;
51  }
52  }
53  }
54  return false;
55 }
57  bNodeSocket *sock,
58  const char defname[],
59  char delim)
60 {
61  NodeImageMultiFileSocket *sockdata;
62  struct {
63  ListBase *lb;
64  bNodeSocket *sock;
65  } data;
66  data.lb = list;
67  data.sock = sock;
68 
69  /* See if we are given an empty string */
70  if (ELEM(NULL, sock, defname)) {
71  return;
72  }
73 
74  sockdata = sock->storage;
76  unique_path_unique_check, &data, defname, delim, sockdata->path, sizeof(sockdata->path));
77 }
78 
79 /* find unique EXR layer */
80 static bool unique_layer_unique_check(void *arg, const char *name)
81 {
82  struct {
83  ListBase *lb;
84  bNodeSocket *sock;
85  } *data = arg;
86  bNodeSocket *sock;
87  for (sock = data->lb->first; sock; sock = sock->next) {
88  if (sock != data->sock) {
89  NodeImageMultiFileSocket *sockdata = sock->storage;
90  if (STREQ(sockdata->layer, name)) {
91  return true;
92  }
93  }
94  }
95  return false;
96 }
98  bNodeSocket *sock,
99  const char defname[],
100  char delim)
101 {
102  NodeImageMultiFileSocket *sockdata;
103  struct {
104  ListBase *lb;
105  bNodeSocket *sock;
106  } data;
107  data.lb = list;
108  data.sock = sock;
109 
110  /* See if we are given an empty string */
111  if (ELEM(NULL, sock, defname)) {
112  return;
113  }
114 
115  sockdata = sock->storage;
117  unique_layer_unique_check, &data, defname, delim, sockdata->layer, sizeof(sockdata->layer));
118 }
119 
121  bNode *node,
122  const char *name,
123  ImageFormatData *im_format)
124 {
125  NodeImageMultiFile *nimf = node->storage;
127 
128  /* create format data for the input socket */
130  "socket image format");
131  sock->storage = sockdata;
132 
133  BLI_strncpy_utf8(sockdata->path, name, sizeof(sockdata->path));
134  ntreeCompositOutputFileUniquePath(&node->inputs, sock, name, '_');
135  BLI_strncpy_utf8(sockdata->layer, name, sizeof(sockdata->layer));
136  ntreeCompositOutputFileUniqueLayer(&node->inputs, sock, name, '_');
137 
138  if (im_format) {
139  sockdata->format = *im_format;
140  if (BKE_imtype_is_movie(sockdata->format.imtype)) {
141  sockdata->format.imtype = R_IMF_IMTYPE_OPENEXR;
142  }
143  }
144  else {
145  BKE_imformat_defaults(&sockdata->format);
146  }
147  /* use node data format by default */
148  sockdata->use_node_format = true;
149  sockdata->save_as_render = true;
150 
151  nimf->active_input = BLI_findindex(&node->inputs, sock);
152 
153  return sock;
154 }
155 
157 {
158  NodeImageMultiFile *nimf = node->storage;
159  bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input);
160  int totinputs = BLI_listbase_count(&node->inputs);
161 
162  if (!sock) {
163  return 0;
164  }
165 
166  if (nimf->active_input == totinputs - 1) {
167  --nimf->active_input;
168  }
169 
170  /* free format data */
171  MEM_freeN(sock->storage);
172 
173  nodeRemoveSocket(ntree, node, sock);
174  return 1;
175 }
176 
177 void ntreeCompositOutputFileSetPath(bNode *node, bNodeSocket *sock, const char *name)
178 {
179  NodeImageMultiFileSocket *sockdata = sock->storage;
180  BLI_strncpy_utf8(sockdata->path, name, sizeof(sockdata->path));
181  ntreeCompositOutputFileUniquePath(&node->inputs, sock, name, '_');
182 }
183 
184 void ntreeCompositOutputFileSetLayer(bNode *node, bNodeSocket *sock, const char *name)
185 {
186  NodeImageMultiFileSocket *sockdata = sock->storage;
187  BLI_strncpy_utf8(sockdata->layer, name, sizeof(sockdata->layer));
188  ntreeCompositOutputFileUniqueLayer(&node->inputs, sock, name, '_');
189 }
190 
191 /* XXX uses initfunc_api callback, regular initfunc does not support context yet */
192 static void init_output_file(const bContext *C, PointerRNA *ptr)
193 {
196  bNode *node = ptr->data;
197  NodeImageMultiFile *nimf = MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
199  node->storage = nimf;
200 
201  if (scene) {
202  RenderData *rd = &scene->r;
203 
204  BLI_strncpy(nimf->base_path, rd->pic, sizeof(nimf->base_path));
205  nimf->format = rd->im_format;
206  if (BKE_imtype_is_movie(nimf->format.imtype)) {
207  nimf->format.imtype = R_IMF_IMTYPE_OPENEXR;
208  }
209 
210  format = &nimf->format;
211  }
212  else {
213  BKE_imformat_defaults(&nimf->format);
214  }
215 
216  /* add one socket by default */
218 }
219 
221 {
222  bNodeSocket *sock;
223 
224  /* free storage data in sockets */
225  for (sock = node->inputs.first; sock; sock = sock->next) {
226  MEM_freeN(sock->storage);
227  }
228 
229  MEM_freeN(node->storage);
230 }
231 
232 static void copy_output_file(bNodeTree *UNUSED(dest_ntree),
233  bNode *dest_node,
234  const bNode *src_node)
235 {
236  bNodeSocket *src_sock, *dest_sock;
237 
238  dest_node->storage = MEM_dupallocN(src_node->storage);
239 
240  /* duplicate storage data in sockets */
241  for (src_sock = src_node->inputs.first, dest_sock = dest_node->inputs.first;
242  src_sock && dest_sock;
243  src_sock = src_sock->next, dest_sock = dest_sock->next) {
244  dest_sock->storage = MEM_dupallocN(src_sock->storage);
245  }
246 }
247 
249 {
250  bNodeSocket *sock, *sock_next;
251  PointerRNA ptr;
252 
253  /* XXX fix for T36706: remove invalid sockets added with bpy API.
254  * This is not ideal, but prevents crashes from missing storage.
255  * FileOutput node needs a redesign to support this properly.
256  */
257  for (sock = node->inputs.first; sock; sock = sock_next) {
258  sock_next = sock->next;
259  if (sock->storage == NULL) {
260  nodeRemoveSocket(ntree, node, sock);
261  }
262  }
263  for (sock = node->outputs.first; sock; sock = sock_next) {
264  sock_next = sock->next;
265  nodeRemoveSocket(ntree, node, sock);
266  }
267 
269 
270  /* automatically update the socket type based on linked input */
271  for (sock = node->inputs.first; sock; sock = sock->next) {
272  if (sock->link) {
274  RNA_enum_set(&ptr, "type", sock->link->fromsock->type);
275  }
276  }
277 }
278 
280 {
281  static bNodeType ntype;
282 
286  node_type_storage(&ntype, "NodeImageMultiFile", free_output_file, copy_output_file);
288 
289  nodeRegisterType(&ntype);
290 }
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
void BKE_imformat_defaults(struct ImageFormatData *im_format)
Definition: image.c:1785
bool BKE_imtype_is_movie(const char imtype)
Definition: image.c:1443
#define NODE_CLASS_OUTPUT
Definition: BKE_node.h:335
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
Definition: node.cc:4527
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4623
struct bNodeSocket * nodeAddStaticSocket(struct bNodeTree *ntree, struct bNode *node, eNodeSocketInOut in_out, int type, int subtype, const char *identifier, const char *name)
Definition: node.cc:1716
#define CMP_NODE_OUTPUT_FILE
Definition: BKE_node.h:1154
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
Definition: node.cc:4599
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock)
Definition: node.cc:1775
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1298
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string_utf8.c:258
bool BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_len)
Definition: string_utils.c:294
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
@ SOCK_IN
#define NODE_PREVIEW
@ SOCK_RGBA
#define R_IMF_IMTYPE_OPENEXR
StructRNA RNA_NodeSocket
@ PROP_NONE
Definition: RNA_types.h:113
#define C
Definition: RandGen.cpp:39
OperationNode * node
Scene scene
bNodeTree * ntree
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void ntreeCompositOutputFileUniqueLayer(ListBase *list, bNodeSocket *sock, const char defname[], char delim)
void ntreeCompositOutputFileSetPath(bNode *node, bNodeSocket *sock, const char *name)
static void free_output_file(bNode *node)
static void update_output_file(bNodeTree *ntree, bNode *node)
void register_node_type_cmp_output_file(void)
bNodeSocket * ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, const char *name, ImageFormatData *im_format)
static void init_output_file(const bContext *C, PointerRNA *ptr)
int ntreeCompositOutputFileRemoveActiveSocket(bNodeTree *ntree, bNode *node)
static bool unique_path_unique_check(void *arg, const char *name)
void ntreeCompositOutputFileSetLayer(bNode *node, bNodeSocket *sock, const char *name)
static bool unique_layer_unique_check(void *arg, const char *name)
static void copy_output_file(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
void ntreeCompositOutputFileUniquePath(ListBase *list, bNodeSocket *sock, const char defname[], char delim)
void cmp_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
void cmp_node_update_default(bNodeTree *UNUSED(ntree), bNode *node)
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
Definition: DNA_ID.h:273
void * first
Definition: DNA_listBase.h:47
void * data
Definition: RNA_types.h:52
struct ID * owner_id
Definition: RNA_types.h:50
struct ImageFormatData im_format
char pic[1024]
struct RenderData r
void * storage
struct bNodeLink * link
struct bNodeSocket * next
Defines a node type.
Definition: BKE_node.h:221
void(* initfunc_api)(const struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:288
ListBase inputs
void * storage
PointerRNA * ptr
Definition: wm_files.c:3157