svn merge -r39930:39947 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / nodes / composite / node_composite_tree.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s):
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/nodes/composite/node_composite_tree.c
31  *  \ingroup nodes
32  */
33
34
35 #include <stdio.h>
36
37 #include "DNA_anim_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_node_types.h"
40
41 #include "BLI_listbase.h"
42 #include "BLI_threads.h"
43
44 #include "BKE_animsys.h"
45 #include "BKE_colortools.h"
46 #include "BKE_fcurve.h"
47 #include "BKE_global.h"
48 #include "BKE_main.h"
49 #include "BKE_node.h"
50 #include "BKE_utildefines.h"
51
52 #include "node_exec.h"
53 #include "node_util.h"
54
55 #include "PIL_time.h"
56
57 #include "RNA_access.h"
58
59 #include "NOD_composite.h"
60 #include "node_composite_util.h"
61
62 static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
63 {
64         Scene *sce;
65         for(sce= main->scene.first; sce; sce= sce->id.next) {
66                 if(sce->nodetree) {
67                         func(calldata, &sce->id, sce->nodetree);
68                 }
69         }
70 }
71
72 static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node)
73 {
74         bNodeSocket *sock;
75         
76         for(sock= node->outputs.first; sock; sock= sock->next) {
77                 if(sock->cache) {
78                         free_compbuf(sock->cache);
79                         sock->cache= NULL;
80                 }
81         }
82 }
83
84 static void free_cache(bNodeTree *ntree)
85 {
86         bNode *node;
87         for(node= ntree->nodes.first; node; node= node->next)
88                 free_node_cache(ntree, node);
89 }
90
91 static void update_node(bNodeTree *ntree, bNode *node)
92 {
93         bNodeSocket *sock;
94
95         for(sock= node->outputs.first; sock; sock= sock->next) {
96                 if(sock->cache) {
97                         //free_compbuf(sock->cache);
98                         //sock->cache= NULL;
99                 }
100         }
101         node->need_exec= 1;
102         
103         /* individual node update call */
104         if (node->typeinfo->updatefunc)
105                 node->typeinfo->updatefunc(ntree, node);
106 }
107
108 /* local tree then owns all compbufs */
109 static void localize(bNodeTree *UNUSED(localtree), bNodeTree *ntree)
110 {
111         bNode *node;
112         bNodeSocket *sock;
113         
114         for(node= ntree->nodes.first; node; node= node->next) {
115                 /* ensure new user input gets handled ok */
116                 node->need_exec= 0;
117                 
118                 /* move over the compbufs */
119                 /* right after ntreeCopyTree() oldsock pointers are valid */
120                 
121                 if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
122                         if(node->id) {
123                                 if(node->flag & NODE_DO_OUTPUT)
124                                         node->new_node->id= (ID *)copy_image((Image *)node->id);
125                                 else
126                                         node->new_node->id= NULL;
127                         }
128                 }
129                 
130                 for(sock= node->outputs.first; sock; sock= sock->next) {
131                         sock->new_sock->cache= sock->cache;
132                         compbuf_set_node(sock->new_sock->cache, node->new_node);
133                         
134                         sock->cache= NULL;
135                         sock->new_sock->new_sock= sock;
136                 }
137         }
138 }
139
140 static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
141 {
142         bNode *lnode;
143         
144         /* move over the compbufs and previews */
145         for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
146                 if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
147                         if(ntreeNodeExists(ntree, lnode->new_node)) {
148                                 
149                                 if(lnode->preview && lnode->preview->rect) {
150                                         nodeFreePreview(lnode->new_node);
151                                         lnode->new_node->preview= lnode->preview;
152                                         lnode->preview= NULL;
153                                 }
154                         }
155                 }
156         }
157 }
158
159 static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
160 {
161         bNode *lnode;
162         bNodeSocket *lsock;
163         
164         /* move over the compbufs and previews */
165         for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
166                 if(ntreeNodeExists(ntree, lnode->new_node)) {
167                         if(ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
168                                 if(lnode->id && (lnode->flag & NODE_DO_OUTPUT)) {
169                                         /* image_merge does sanity check for pointers */
170                                         BKE_image_merge((Image *)lnode->new_node->id, (Image *)lnode->id);
171                                 }
172                         }
173                         
174                         for(lsock= lnode->outputs.first; lsock; lsock= lsock->next) {
175                                 if(ntreeOutputExists(lnode->new_node, lsock->new_sock)) {
176                                         lsock->new_sock->cache= lsock->cache;
177                                         compbuf_set_node(lsock->new_sock->cache, lnode->new_node);
178                                         lsock->cache= NULL;
179                                         lsock->new_sock= NULL;
180                                 }
181                         }
182                 }
183         }
184 }
185
186 bNodeTreeType ntreeType_Composite = {
187         /* type */                              NTREE_COMPOSIT,
188         /* idname */                    "NTCompositing Nodetree",
189         
190         /* node_types */                { NULL, NULL },
191         
192         /* free_cache */                free_cache,
193         /* free_node_cache */   free_node_cache,
194         /* foreach_nodetree */  foreach_nodetree,
195         /* localize */                  localize,
196         /* local_sync */                local_sync,
197         /* local_merge */               local_merge,
198         /* update */                    NULL,
199         /* update_node */               update_node
200 };
201
202
203 struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree)
204 {
205         bNodeTreeExec *exec;
206         bNode *node;
207         bNodeSocket *sock;
208         
209         /* XXX hack: prevent exec data from being generated twice.
210          * this should be handled by the renderer!
211          */
212         if (ntree->execdata)
213                 return ntree->execdata;
214         
215         /* ensures only a single output node is enabled */
216         ntreeSetOutput(ntree);
217         
218         exec = ntree_exec_begin(ntree);
219         
220         for(node= exec->nodetree->nodes.first; node; node= node->next) {
221                 /* initialize needed for groups */
222                 node->exec= 0;  
223                 
224                 for(sock= node->outputs.first; sock; sock= sock->next) {
225                         bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
226                         if(ns && sock->cache) {
227                                 ns->data= sock->cache;
228                                 sock->cache= NULL;
229                         }
230                 }
231                 /* cannot initialize them while using in threads */
232                 if(ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) {
233                         curvemapping_initialize(node->storage);
234                         if(node->type==CMP_NODE_CURVE_RGB)
235                                 curvemapping_premultiply(node->storage, 0);
236                 }
237         }
238         
239         /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
240                  * which only store the ntree pointer. Should be fixed at some point!
241                  */
242         ntree->execdata = exec;
243         
244         return exec;
245 }
246
247 void ntreeCompositEndExecTree(bNodeTreeExec *exec)
248 {
249         if(exec) {
250                 bNodeTree *ntree= exec->nodetree;
251                 bNode *node;
252                 bNodeStack *ns;
253                 
254                 for(node= exec->nodetree->nodes.first; node; node= node->next) {
255                         bNodeSocket *sock;
256                         
257                         for(sock= node->outputs.first; sock; sock= sock->next) {
258                                 ns = node_get_socket_stack(exec->stack, sock);
259                                 if(ns && ns->data) {
260                                         sock->cache= ns->data;
261                                         ns->data= NULL;
262                                 }
263                         }
264                         if(node->type==CMP_NODE_CURVE_RGB)
265                                 curvemapping_premultiply(node->storage, 1);
266                         
267                         node->need_exec= 0;
268                 }
269         
270                 ntree_exec_end(exec);
271                 
272                 /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
273                 ntree->execdata = NULL;
274         }
275 }
276
277 /* ***************************** threaded version for execute composite nodes ************* */
278 /* these are nodes without input, only giving values */
279 /* or nodes with only value inputs */
280 static int node_only_value(bNode *node)
281 {
282         bNodeSocket *sock;
283         
284         if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB))
285                 return 1;
286         
287         /* doing this for all node types goes wrong. memory free errors */
288         if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
289                 int retval= 1;
290                 for(sock= node->inputs.first; sock; sock= sock->next) {
291                         if(sock->link)
292                                 retval &= node_only_value(sock->link->fromnode);
293                 }
294                 return retval;
295         }
296         return 0;
297 }
298
299 /* not changing info, for thread callback */
300 typedef struct ThreadData {
301         bNodeStack *stack;
302         RenderData *rd;
303 } ThreadData;
304
305 static void *exec_composite_node(void *nodeexec_v)
306 {
307         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
308         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
309         bNodeExec *nodeexec= nodeexec_v;
310         bNode *node= nodeexec->node;
311         ThreadData *thd= (ThreadData *)node->threaddata;
312         
313         node_get_stack(node, thd->stack, nsin, nsout);
314         
315         if((node->flag & NODE_MUTED) && (!node_only_value(node))) {
316                 /* viewers we execute, for feedback to user */
317                 if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
318                         node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
319                 else
320                         node_compo_pass_on(node, nsin, nsout);
321         }
322         else if(node->typeinfo->execfunc)
323                 node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
324         else if (node->typeinfo->newexecfunc)
325                 node->typeinfo->newexecfunc(thd->rd, 0, node, nodeexec->data, nsin, nsout);
326         
327         node->exec |= NODE_READY;
328         return 0;
329 }
330
331 /* return total of executable nodes, for timecursor */
332 static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd)
333 {
334         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
335         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
336         bNode *node;
337         bNodeSocket *sock;
338         int totnode= 0, group_edit= 0;
339         
340         /* note; do not add a dependency sort here, the stack was created already */
341         
342         /* if we are in group edit, viewer nodes get skipped when group has viewer */
343         for(node= ntree->nodes.first; node; node= node->next)
344                 if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
345                         if(ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER))
346                                 group_edit= 1;
347         
348         for(node= ntree->nodes.first; node; node= node->next) {
349                 int a;
350                 
351                 node_get_stack(node, thd->stack, nsin, nsout);
352                 
353                 /* test the outputs */
354                 /* skip value-only nodes (should be in type!) */
355                 if(!node_only_value(node)) {
356                         for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
357                                 if(nsout[a]->data==NULL && nsout[a]->hasoutput) {
358                                         node->need_exec= 1;
359                                         break;
360                                 }
361                         }
362                 }
363                 
364                 /* test the inputs */
365                 for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
366                         /* skip viewer nodes in bg render or group edit */
367                         if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit))
368                                 node->need_exec= 0;
369                         /* is sock in use? */
370                         else if(sock->link) {
371                                 bNodeLink *link= sock->link;
372                                 
373                                 /* this is the test for a cyclic case */
374                                 if(link->fromnode==NULL || link->tonode==NULL);
375                                 else if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
376                                         if(link->fromnode->need_exec) {
377                                                 node->need_exec= 1;
378                                                 break;
379                                         }
380                                 }
381                                 else {
382                                         node->need_exec= 0;
383                                         printf("Node %s skipped, cyclic dependency\n", node->name);
384                                 }
385                         }
386                 }
387                 
388                 if(node->need_exec) {
389                         
390                         /* free output buffers */
391                         for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
392                                 if(nsout[a]->data) {
393                                         free_compbuf(nsout[a]->data);
394                                         nsout[a]->data= NULL;
395                                 }
396                         }
397                         totnode++;
398                         /* printf("node needs exec %s\n", node->name); */
399                         
400                         /* tag for getExecutableNode() */
401                         node->exec= 0;
402                 }
403                 else {
404                         /* tag for getExecutableNode() */
405                         node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED;
406                         
407                 }
408         }
409         
410         /* last step: set the stack values for only-value nodes */
411         /* just does all now, compared to a full buffer exec this is nothing */
412         if(totnode) {
413                 for(node= ntree->nodes.first; node; node= node->next) {
414                         if(node->need_exec==0 && node_only_value(node)) {
415                                 if(node->typeinfo->execfunc) {
416                                         node_get_stack(node, thd->stack, nsin, nsout);
417                                         node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
418                                 }
419                         }
420                 }
421         }
422         
423         return totnode;
424 }
425
426 /* while executing tree, free buffers from nodes that are not needed anymore */
427 static void freeExecutableNode(bNodeTree *ntree, bNodeTreeExec *exec)
428 {
429         /* node outputs can be freed when:
430         - not a render result or image node
431         - when node outputs go to nodes all being set NODE_FINISHED
432         */
433         bNode *node;
434         bNodeSocket *sock;
435         
436         /* set exec flag for finished nodes that might need freed */
437         for(node= ntree->nodes.first; node; node= node->next) {
438                 if(node->type!=CMP_NODE_R_LAYERS)
439                         if(node->exec & NODE_FINISHED)
440                                 node->exec |= NODE_FREEBUFS;
441         }
442         /* clear this flag for input links that are not done yet */
443         for(node= ntree->nodes.first; node; node= node->next) {
444                 if((node->exec & NODE_FINISHED)==0) {
445                         for(sock= node->inputs.first; sock; sock= sock->next)
446                                 if(sock->link)
447                                         sock->link->fromnode->exec &= ~NODE_FREEBUFS;
448                 }
449         }
450         /* now we can free buffers */
451         for(node= ntree->nodes.first; node; node= node->next) {
452                 if(node->exec & NODE_FREEBUFS) {
453                         for(sock= node->outputs.first; sock; sock= sock->next) {
454                                 bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
455                                 if(ns && ns->data) {
456                                         free_compbuf(ns->data);
457                                         ns->data= NULL;
458                                         // printf("freed buf node %s \n", node->name);
459                                 }
460                         }
461                 }
462         }
463 }
464
465 static bNodeExec *getExecutableNode(bNodeTreeExec *exec)
466 {
467         bNodeExec *nodeexec;
468         bNodeSocket *sock;
469         int n;
470         
471         for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
472                 if(nodeexec->node->exec==0) {
473                         /* input sockets should be ready */
474                         for(sock= nodeexec->node->inputs.first; sock; sock= sock->next) {
475                                 if(sock->link && sock->link->fromnode)
476                                         if((sock->link->fromnode->exec & NODE_READY)==0)
477                                                 break;
478                         }
479                         if(sock==NULL)
480                                 return nodeexec;
481                 }
482         }
483         return NULL;
484 }
485
486 /* check if texture nodes need exec or end */
487 static  void ntree_composite_texnode(bNodeTree *ntree, int init)
488 {
489         bNode *node;
490         
491         for(node= ntree->nodes.first; node; node= node->next) {
492                 if(node->type==CMP_NODE_TEXTURE && node->id) {
493                         Tex *tex= (Tex *)node->id;
494                         if(tex->nodetree && tex->use_nodes) {
495                                 /* has internal flag to detect it only does it once */
496                                 if(init) {
497                                         if (!tex->nodetree->execdata)
498                                                 tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree); 
499                                 }
500                                 else
501                                         ntreeTexEndExecTree(tex->nodetree->execdata);
502                                         tex->nodetree->execdata = NULL;
503                         }
504                 }
505         }
506
507 }
508
509 /* optimized tree execute test for compositing */
510 void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
511 {
512         bNodeExec *nodeexec;
513         bNode *node;
514         ListBase threads;
515         ThreadData thdata;
516         int totnode, curnode, rendering= 1, n;
517         bNodeTreeExec *exec= NULL;
518         
519         if(ntree==NULL) return;
520         
521         if(do_preview)
522                 ntreeInitPreview(ntree, 0, 0);
523         
524         if (!ntree->execdata)
525                 exec = ntreeCompositBeginExecTree(ntree);
526         ntree_composite_texnode(ntree, 1);
527         
528         /* prevent unlucky accidents */
529         if(G.background)
530                 rd->scemode &= ~R_COMP_CROP;
531         
532         /* setup callerdata for thread callback */
533         thdata.rd= rd;
534         thdata.stack= exec->stack;
535         
536         /* fixed seed, for example noise texture */
537         BLI_srandom(rd->cfra);
538
539         /* sets need_exec tags in nodes */
540         curnode = totnode= setExecutableNodes(ntree, &thdata);
541
542         BLI_init_threads(&threads, exec_composite_node, rd->threads);
543         
544         while(rendering) {
545                 
546                 if(BLI_available_threads(&threads)) {
547                         nodeexec= getExecutableNode(exec);
548                         if(nodeexec) {
549                                 node = nodeexec->node;
550                                 if(ntree->progress && totnode)
551                                         ntree->progress(ntree->prh, (1.0 - curnode/(float)totnode));
552                                 if(ntree->stats_draw) {
553                                         char str[64];
554                                         sprintf(str, "Compositing %d %s", curnode, node->name);
555                                         ntree->stats_draw(ntree->sdh, str);
556                                 }
557                                 curnode--;
558                                 
559                                 node->threaddata = &thdata;
560                                 node->exec= NODE_PROCESSING;
561                                 BLI_insert_thread(&threads, nodeexec);
562                         }
563                         else
564                                 PIL_sleep_ms(50);
565                 }
566                 else
567                         PIL_sleep_ms(50);
568                 
569                 rendering= 0;
570                 /* test for ESC */
571                 if(ntree->test_break && ntree->test_break(ntree->tbh)) {
572                         for(node= ntree->nodes.first; node; node= node->next)
573                                 node->exec |= NODE_READY;
574                 }
575                 
576                 /* check for ready ones, and if we need to continue */
577                 for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
578                         node = nodeexec->node;
579                         if(node->exec & NODE_READY) {
580                                 if((node->exec & NODE_FINISHED)==0) {
581                                         BLI_remove_thread(&threads, nodeexec); /* this waits for running thread to finish btw */
582                                         node->exec |= NODE_FINISHED;
583                                         
584                                         /* freeing unused buffers */
585                                         if(rd->scemode & R_COMP_FREE)
586                                                 freeExecutableNode(ntree, exec);
587                                 }
588                         }
589                         else rendering= 1;
590                 }
591         }
592         
593         BLI_end_threads(&threads);
594         
595         ntreeCompositEndExecTree(exec);
596 }
597
598 /* *********************************************** */
599
600 /* clumsy checking... should do dynamic outputs once */
601 static void force_hidden_passes(bNode *node, int passflag)
602 {
603         bNodeSocket *sock;
604         
605         for(sock= node->outputs.first; sock; sock= sock->next)
606                 sock->flag &= ~SOCK_UNAVAIL;
607         
608         sock= BLI_findlink(&node->outputs, RRES_OUT_Z);
609         if(!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL;
610         sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL);
611         if(!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL;
612         sock= BLI_findlink(&node->outputs, RRES_OUT_VEC);
613         if(!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL;
614         sock= BLI_findlink(&node->outputs, RRES_OUT_UV);
615         if(!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL;
616         sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA);
617         if(!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL;
618         sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF);
619         if(!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL;
620         sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC);
621         if(!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL;
622         sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW);
623         if(!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL;
624         sock= BLI_findlink(&node->outputs, RRES_OUT_AO);
625         if(!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL;
626         sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT);
627         if(!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL;
628         sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT);
629         if(!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL;
630         sock= BLI_findlink(&node->outputs, RRES_OUT_INDIRECT);
631         if(!(passflag & SCE_PASS_INDIRECT)) sock->flag |= SOCK_UNAVAIL;
632         sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB);
633         if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL;
634         sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMA);
635         if(!(passflag & SCE_PASS_INDEXMA)) sock->flag |= SOCK_UNAVAIL;
636         sock= BLI_findlink(&node->outputs, RRES_OUT_MIST);
637         if(!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL;
638         sock= BLI_findlink(&node->outputs, RRES_OUT_EMIT);
639         if(!(passflag & SCE_PASS_EMIT)) sock->flag |= SOCK_UNAVAIL;
640         sock= BLI_findlink(&node->outputs, RRES_OUT_ENV);
641         if(!(passflag & SCE_PASS_ENVIRONMENT)) sock->flag |= SOCK_UNAVAIL;
642         
643 }
644
645 /* based on rules, force sockets hidden always */
646 void ntreeCompositForceHidden(bNodeTree *ntree, Scene *curscene)
647 {
648         bNode *node;
649         
650         if(ntree==NULL) return;
651         
652         for(node= ntree->nodes.first; node; node= node->next) {
653                 if( node->type==CMP_NODE_R_LAYERS) {
654                         Scene *sce= node->id?(Scene *)node->id:curscene;
655                         SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
656                         if(srl)
657                                 force_hidden_passes(node, srl->passflag);
658                 }
659                 else if( node->type==CMP_NODE_IMAGE) {
660                         Image *ima= (Image *)node->id;
661                         if(ima) {
662                                 if(ima->rr) {
663                                         ImageUser *iuser= node->storage;
664                                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
665                                         if(rl)
666                                                 force_hidden_passes(node, rl->passflag);
667                                         else
668                                                 force_hidden_passes(node, 0);
669                                 }
670                                 else if(ima->type!=IMA_TYPE_MULTILAYER) {       /* if ->rr not yet read we keep inputs */
671                                         force_hidden_passes(node, RRES_OUT_Z);
672                                 }
673                                 else
674                                         force_hidden_passes(node, 0);
675                         }
676                         else
677                                 force_hidden_passes(node, 0);
678                 }
679         }
680
681 }
682
683 /* called from render pipeline, to tag render input and output */
684 /* need to do all scenes, to prevent errors when you re-render 1 scene */
685 void ntreeCompositTagRender(Scene *curscene)
686 {
687         Scene *sce;
688         
689         for(sce= G.main->scene.first; sce; sce= sce->id.next) {
690                 if(sce->nodetree) {
691                         bNode *node;
692                         
693                         for(node= sce->nodetree->nodes.first; node; node= node->next) {
694                                 if(node->id==(ID *)curscene || node->type==CMP_NODE_COMPOSITE)
695                                         NodeTagChanged(sce->nodetree, node);
696                                 else if(node->type==CMP_NODE_TEXTURE) /* uses scene sizex/sizey */
697                                         NodeTagChanged(sce->nodetree, node);
698                         }
699                 }
700         }
701 }
702
703 static int node_animation_properties(bNodeTree *ntree, bNode *node)
704 {
705         bNodeSocket *sock;
706         const ListBase *lb;
707         Link *link;
708         PointerRNA ptr;
709         PropertyRNA *prop;
710         
711         /* check to see if any of the node's properties have fcurves */
712         RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
713         lb = RNA_struct_type_properties(ptr.type);
714         
715         for (link=lb->first; link; link=link->next) {
716                 int driven, len=1, index;
717                 prop = (PropertyRNA *)link;
718                 
719                 if (RNA_property_array_check(prop))
720                         len = RNA_property_array_length(&ptr, prop);
721                 
722                 for (index=0; index<len; index++) {
723                         if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
724                                 NodeTagChanged(ntree, node);
725                                 return 1;
726                         }
727                 }
728         }
729         
730         /* now check node sockets */
731         for (sock = node->inputs.first; sock; sock=sock->next) {
732                 int driven, len=1, index;
733                 
734                 RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
735                 prop = RNA_struct_find_property(&ptr, "default_value");
736                 if (prop) {
737                         if (RNA_property_array_check(prop))
738                                 len = RNA_property_array_length(&ptr, prop);
739                         
740                         for (index=0; index<len; index++) {
741                                 if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
742                                         NodeTagChanged(ntree, node);
743                                         return 1;
744                                 }
745                         }
746                 }
747         }
748
749         return 0;
750 }
751
752 /* tags nodes that have animation capabilities */
753 int ntreeCompositTagAnimated(bNodeTree *ntree)
754 {
755         bNode *node;
756         int tagged= 0;
757         
758         if(ntree==NULL) return 0;
759         
760         for(node= ntree->nodes.first; node; node= node->next) {
761                 
762                 tagged = node_animation_properties(ntree, node);
763                 
764                 /* otherwise always tag these node types */
765                 if(node->type==CMP_NODE_IMAGE) {
766                         Image *ima= (Image *)node->id;
767                         if(ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
768                                 NodeTagChanged(ntree, node);
769                                 tagged= 1;
770                         }
771                 }
772                 else if(node->type==CMP_NODE_TIME) {
773                         NodeTagChanged(ntree, node);
774                         tagged= 1;
775                 }
776                 /* here was tag render layer, but this is called after a render, so re-composites fail */
777                 else if(node->type==NODE_GROUP) {
778                         if( ntreeCompositTagAnimated((bNodeTree *)node->id) ) {
779                                 NodeTagChanged(ntree, node);
780                         }
781                 }
782         }
783         
784         return tagged;
785 }
786
787
788 /* called from image window preview */
789 void ntreeCompositTagGenerators(bNodeTree *ntree)
790 {
791         bNode *node;
792         
793         if(ntree==NULL) return;
794         
795         for(node= ntree->nodes.first; node; node= node->next) {
796                 if( ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_IMAGE))
797                         NodeTagChanged(ntree, node);
798         }
799 }
800
801 /* XXX after render animation system gets a refresh, this call allows composite to end clean */
802 void ntreeClearTags(bNodeTree *ntree)
803 {
804         bNode *node;
805         
806         if(ntree==NULL) return;
807         
808         for(node= ntree->nodes.first; node; node= node->next) {
809                 node->need_exec= 0;
810                 if(node->type==NODE_GROUP)
811                         ntreeClearTags((bNodeTree *)node->id);
812         }
813 }