Cleanup: quiet undeclared variable warnings
[blender.git] / source / blender / nodes / composite / node_composite_tree.c
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) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup nodes
22  */
23
24
25 #include <stdio.h>
26
27 #include "DNA_color_types.h"
28 #include "DNA_scene_types.h"
29 #include "DNA_node_types.h"
30
31 #include "BLT_translation.h"
32
33 #include "BKE_context.h"
34 #include "BKE_global.h"
35 #include "BKE_main.h"
36 #include "BKE_node.h"
37 #include "BKE_tracking.h"
38
39 #include "node_common.h"
40 #include "node_util.h"
41
42 #include "RNA_access.h"
43
44 #include "NOD_composite.h"
45 #include "node_composite_util.h"
46
47 #ifdef WITH_COMPOSITOR
48 #  include "COM_compositor.h"
49 #endif
50
51 static void composite_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
52 {
53         Scene *scene = CTX_data_scene(C);
54
55         *r_from = NULL;
56         *r_id = &scene->id;
57         *r_ntree = scene->nodetree;
58 }
59
60 static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
61 {
62         func(calldata, NODE_CLASS_INPUT, N_("Input"));
63         func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
64         func(calldata, NODE_CLASS_OP_COLOR, N_("Color"));
65         func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector"));
66         func(calldata, NODE_CLASS_OP_FILTER, N_("Filter"));
67         func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
68         func(calldata, NODE_CLASS_MATTE, N_("Matte"));
69         func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
70         func(calldata, NODE_CLASS_GROUP, N_("Group"));
71         func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
72         func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
73 }
74
75 static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node)
76 {
77         bNodeSocket *sock;
78
79         for (sock = node->outputs.first; sock; sock = sock->next) {
80                 if (sock->cache) {
81                         sock->cache = NULL;
82                 }
83         }
84 }
85
86 static void free_cache(bNodeTree *ntree)
87 {
88         bNode *node;
89         for (node = ntree->nodes.first; node; node = node->next)
90                 free_node_cache(ntree, node);
91 }
92
93 /* local tree then owns all compbufs */
94 static void localize(bNodeTree *UNUSED(localtree), bNodeTree *ntree)
95 {
96         bNode *node;
97         bNodeSocket *sock;
98
99         for (node = ntree->nodes.first; node; node = node->next) {
100                 /* ensure new user input gets handled ok */
101                 node->need_exec = 0;
102                 node->new_node->original = node;
103
104                 /* move over the compbufs */
105                 /* right after ntreeCopyTree() oldsock pointers are valid */
106
107                 if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
108                         if (node->id) {
109                                 if (node->flag & NODE_DO_OUTPUT)
110                                         node->new_node->id = (ID *)node->id;
111                                 else
112                                         node->new_node->id = NULL;
113                         }
114                 }
115
116                 for (sock = node->outputs.first; sock; sock = sock->next) {
117                         sock->new_sock->cache = sock->cache;
118                         sock->cache = NULL;
119                         sock->new_sock->new_sock = sock;
120                 }
121         }
122 }
123
124 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
125 {
126         BKE_node_preview_sync_tree(ntree, localtree);
127 }
128
129 static void local_merge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
130 {
131         bNode *lnode;
132         bNodeSocket *lsock;
133
134         /* move over the compbufs and previews */
135         BKE_node_preview_merge_tree(ntree, localtree, true);
136
137         for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) {
138                 if (ntreeNodeExists(ntree, lnode->new_node)) {
139                         if (ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
140                                 if (lnode->id && (lnode->flag & NODE_DO_OUTPUT)) {
141                                         /* image_merge does sanity check for pointers */
142                                         BKE_image_merge(bmain, (Image *)lnode->new_node->id, (Image *)lnode->id);
143                                 }
144                         }
145                         else if (lnode->type == CMP_NODE_MOVIEDISTORTION) {
146                                 /* special case for distortion node: distortion context is allocating in exec function
147                                  * and to achieve much better performance on further calls this context should be
148                                  * copied back to original node */
149                                 if (lnode->storage) {
150                                         if (lnode->new_node->storage)
151                                                 BKE_tracking_distortion_free(lnode->new_node->storage);
152
153                                         lnode->new_node->storage = BKE_tracking_distortion_copy(lnode->storage);
154                                 }
155                         }
156
157                         for (lsock = lnode->outputs.first; lsock; lsock = lsock->next) {
158                                 if (ntreeOutputExists(lnode->new_node, lsock->new_sock)) {
159                                         lsock->new_sock->cache = lsock->cache;
160                                         lsock->cache = NULL;
161                                         lsock->new_sock = NULL;
162                                 }
163                         }
164                 }
165         }
166 }
167
168 static void update(bNodeTree *ntree)
169 {
170         ntreeSetOutput(ntree);
171
172         ntree_update_reroute_nodes(ntree);
173
174         if (ntree->update & NTREE_UPDATE_NODES) {
175                 /* clean up preview cache, in case nodes have been removed */
176                 BKE_node_preview_remove_unused(ntree);
177         }
178 }
179
180 static void composite_node_add_init(bNodeTree *UNUSED(bnodetree), bNode *bnode)
181 {
182         /* Composite node will only show previews for input classes
183          * by default, other will be hidden
184          * but can be made visible with the show_preview option */
185         if (bnode->typeinfo->nclass != NODE_CLASS_INPUT) {
186                 bnode->flag &= ~NODE_PREVIEW;
187         }
188 }
189
190 bNodeTreeType *ntreeType_Composite;
191
192 void register_node_tree_type_cmp(void)
193 {
194         bNodeTreeType *tt = ntreeType_Composite = MEM_callocN(sizeof(bNodeTreeType), "compositor node tree type");
195
196         tt->type = NTREE_COMPOSIT;
197         strcpy(tt->idname, "CompositorNodeTree");
198         strcpy(tt->ui_name, N_("Compositing"));
199         tt->ui_icon = 0;    /* defined in drawnode.c */
200         strcpy(tt->ui_description, N_("Compositing nodes"));
201
202         tt->free_cache = free_cache;
203         tt->free_node_cache = free_node_cache;
204         tt->foreach_nodeclass = foreach_nodeclass;
205         tt->localize = localize;
206         tt->local_sync = local_sync;
207         tt->local_merge = local_merge;
208         tt->update = update;
209         tt->get_from_context = composite_get_from_context;
210         tt->node_add_init = composite_node_add_init;
211
212         tt->ext.srna = &RNA_CompositorNodeTree;
213
214         ntreeTypeAdd(tt);
215 }
216
217 extern void *COM_linker_hack;  /* Quiet warning. */
218 void *COM_linker_hack = NULL;
219
220 void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int rendering, int do_preview,
221                            const ColorManagedViewSettings *view_settings,
222                            const ColorManagedDisplaySettings *display_settings,
223                            const char *view_name)
224 {
225 #ifdef WITH_COMPOSITOR
226         COM_execute(rd, scene, ntree, rendering, view_settings, display_settings, view_name);
227 #else
228         UNUSED_VARS(scene, ntree, rd, rendering, view_settings, display_settings, view_name);
229 #endif
230
231         UNUSED_VARS(do_preview);
232 }
233
234 /* *********************************************** */
235
236 /* Update the outputs of the render layer nodes.
237  * Since the outputs depend on the render engine, this part is a bit complex:
238  * - ntreeCompositUpdateRLayers is called and loops over all render layer nodes
239  * - Each render layer node calls the update function of the render engine that's used for its scene
240  * - The render engine calls RE_engine_register_pass for each pass
241  * - RE_engine_register_pass calls ntreeCompositRegisterPass,
242  *   which calls node_cmp_rlayers_register_pass for every render layer node
243  */
244 void ntreeCompositUpdateRLayers(bNodeTree *ntree)
245 {
246         bNode *node;
247
248         if (ntree == NULL) return;
249
250         for (node = ntree->nodes.first; node; node = node->next) {
251                 if (node->type == CMP_NODE_R_LAYERS)
252                         node_cmp_rlayers_outputs(ntree, node);
253         }
254
255 }
256
257 void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, ViewLayer *view_layer, const char *name, int type)
258 {
259         bNode *node;
260
261         if (ntree == NULL) return;
262
263         for (node = ntree->nodes.first; node; node = node->next) {
264                 if (node->type == CMP_NODE_R_LAYERS)
265                         node_cmp_rlayers_register_pass(ntree, node, scene, view_layer, name, type);
266         }
267
268 }
269
270 /* called from render pipeline, to tag render input and output */
271 /* need to do all scenes, to prevent errors when you re-render 1 scene */
272 void ntreeCompositTagRender(Scene *curscene)
273 {
274         Scene *sce;
275
276         /* XXX Think using G_MAIN here is valid, since you want to update current file's scene nodes,
277          * not the ones in temp main generated for rendering?
278          * This is still rather weak though, ideally render struct would store own main AND original G_MAIN... */
279         for (sce = G_MAIN->scene.first; sce; sce = sce->id.next) {
280                 if (sce->nodetree) {
281                         bNode *node;
282
283                         for (node = sce->nodetree->nodes.first; node; node = node->next) {
284                                 if (node->id == (ID *)curscene || node->type == CMP_NODE_COMPOSITE)
285                                         nodeUpdate(sce->nodetree, node);
286                                 else if (node->type == CMP_NODE_TEXTURE) /* uses scene sizex/sizey */
287                                         nodeUpdate(sce->nodetree, node);
288                         }
289                 }
290         }
291 }
292
293 static int node_animation_properties(bNodeTree *ntree, bNode *node)
294 {
295         bNodeSocket *sock;
296         const ListBase *lb;
297         Link *link;
298         PointerRNA ptr;
299         PropertyRNA *prop;
300
301         /* check to see if any of the node's properties have fcurves */
302         RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
303         lb = RNA_struct_type_properties(ptr.type);
304
305         for (link = lb->first; link; link = link->next) {
306                 prop = (PropertyRNA *)link;
307
308                 if (RNA_property_animated(&ptr, prop)) {
309                         nodeUpdate(ntree, node);
310                         return 1;
311                 }
312         }
313
314         /* now check node sockets */
315         for (sock = node->inputs.first; sock; sock = sock->next) {
316                 RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
317                 prop = RNA_struct_find_property(&ptr, "default_value");
318
319                 if (RNA_property_animated(&ptr, prop)) {
320                         nodeUpdate(ntree, node);
321                         return 1;
322                 }
323         }
324
325         return 0;
326 }
327
328 /* tags nodes that have animation capabilities */
329 int ntreeCompositTagAnimated(bNodeTree *ntree)
330 {
331         bNode *node;
332         int tagged = 0;
333
334         if (ntree == NULL) return 0;
335
336         for (node = ntree->nodes.first; node; node = node->next) {
337
338                 tagged = node_animation_properties(ntree, node);
339
340                 /* otherwise always tag these node types */
341                 if (node->type == CMP_NODE_IMAGE) {
342                         Image *ima = (Image *)node->id;
343                         if (ima && BKE_image_is_animated(ima)) {
344                                 nodeUpdate(ntree, node);
345                                 tagged = 1;
346                         }
347                 }
348                 else if (node->type == CMP_NODE_TIME) {
349                         nodeUpdate(ntree, node);
350                         tagged = 1;
351                 }
352                 /* here was tag render layer, but this is called after a render, so re-composites fail */
353                 else if (node->type == NODE_GROUP) {
354                         if (ntreeCompositTagAnimated((bNodeTree *)node->id)) {
355                                 nodeUpdate(ntree, node);
356                         }
357                 }
358                 else if (ELEM(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_TRANSFORM)) {
359                         nodeUpdate(ntree, node);
360                         tagged = 1;
361                 }
362                 else if (node->type == CMP_NODE_MASK) {
363                         nodeUpdate(ntree, node);
364                         tagged = 1;
365                 }
366         }
367
368         return tagged;
369 }
370
371
372 /* called from image window preview */
373 void ntreeCompositTagGenerators(bNodeTree *ntree)
374 {
375         bNode *node;
376
377         if (ntree == NULL) return;
378
379         for (node = ntree->nodes.first; node; node = node->next) {
380                 if (ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_IMAGE))
381                         nodeUpdate(ntree, node);
382         }
383 }
384
385 /* XXX after render animation system gets a refresh, this call allows composite to end clean */
386 void ntreeCompositClearTags(bNodeTree *ntree)
387 {
388         bNode *node;
389
390         if (ntree == NULL) return;
391
392         for (node = ntree->nodes.first; node; node = node->next) {
393                 node->need_exec = 0;
394                 if (node->type == NODE_GROUP)
395                         ntreeCompositClearTags((bNodeTree *)node->id);
396         }
397 }