Merging r39998 through r40043 from trunk into soc-2011-tomato
[blender-staging.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 /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
204  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
205  */
206 struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree, int use_tree_data)
207 {
208         bNodeTreeExec *exec;
209         bNode *node;
210         bNodeSocket *sock;
211         
212         if (use_tree_data) {
213                 /* XXX hack: prevent exec data from being generated twice.
214                  * this should be handled by the renderer!
215                  */
216                 if (ntree->execdata)
217                         return ntree->execdata;
218         }
219         
220         /* ensures only a single output node is enabled */
221         ntreeSetOutput(ntree);
222         
223         exec = ntree_exec_begin(ntree);
224         
225         for(node= exec->nodetree->nodes.first; node; node= node->next) {
226                 /* initialize needed for groups */
227                 node->exec= 0;  
228                 
229                 for(sock= node->outputs.first; sock; sock= sock->next) {
230                         bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
231                         if(ns && sock->cache) {
232                                 ns->data= sock->cache;
233                                 sock->cache= NULL;
234                         }
235                 }
236                 /* cannot initialize them while using in threads */
237                 if(ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) {
238                         curvemapping_initialize(node->storage);
239                         if(node->type==CMP_NODE_CURVE_RGB)
240                                 curvemapping_premultiply(node->storage, 0);
241                 }
242         }
243         
244         if (use_tree_data) {
245                 /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
246                  * which only store the ntree pointer. Should be fixed at some point!
247                  */
248                 ntree->execdata = exec;
249         }
250         
251         return exec;
252 }
253
254 /* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
255  * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
256  */
257 void ntreeCompositEndExecTree(bNodeTreeExec *exec, int use_tree_data)
258 {
259         if(exec) {
260                 bNodeTree *ntree= exec->nodetree;
261                 bNode *node;
262                 bNodeStack *ns;
263                 
264                 for(node= exec->nodetree->nodes.first; node; node= node->next) {
265                         bNodeSocket *sock;
266                         
267                         for(sock= node->outputs.first; sock; sock= sock->next) {
268                                 ns = node_get_socket_stack(exec->stack, sock);
269                                 if(ns && ns->data) {
270                                         sock->cache= ns->data;
271                                         ns->data= NULL;
272                                 }
273                         }
274                         if(node->type==CMP_NODE_CURVE_RGB)
275                                 curvemapping_premultiply(node->storage, 1);
276                         
277                         node->need_exec= 0;
278                 }
279         
280                 ntree_exec_end(exec);
281                 
282                 if (use_tree_data) {
283                         /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
284                         ntree->execdata = NULL;
285                 }
286         }
287 }
288
289 /* ***************************** threaded version for execute composite nodes ************* */
290 /* these are nodes without input, only giving values */
291 /* or nodes with only value inputs */
292 static int node_only_value(bNode *node)
293 {
294         bNodeSocket *sock;
295         
296         if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB))
297                 return 1;
298         
299         /* doing this for all node types goes wrong. memory free errors */
300         if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
301                 int retval= 1;
302                 for(sock= node->inputs.first; sock; sock= sock->next) {
303                         if(sock->link)
304                                 retval &= node_only_value(sock->link->fromnode);
305                 }
306                 return retval;
307         }
308         return 0;
309 }
310
311 /* not changing info, for thread callback */
312 typedef struct ThreadData {
313         bNodeStack *stack;
314         RenderData *rd;
315 } ThreadData;
316
317 static void *exec_composite_node(void *nodeexec_v)
318 {
319         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
320         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
321         bNodeExec *nodeexec= nodeexec_v;
322         bNode *node= nodeexec->node;
323         ThreadData *thd= (ThreadData *)node->threaddata;
324         
325         node_get_stack(node, thd->stack, nsin, nsout);
326         
327         if((node->flag & NODE_MUTED) && (!node_only_value(node))) {
328                 /* viewers we execute, for feedback to user */
329                 if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
330                         node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
331                 else
332                         node_compo_pass_on(node, nsin, nsout);
333         }
334         else if(node->typeinfo->execfunc)
335                 node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
336         else if (node->typeinfo->newexecfunc)
337                 node->typeinfo->newexecfunc(thd->rd, 0, node, nodeexec->data, nsin, nsout);
338         
339         node->exec |= NODE_READY;
340         return 0;
341 }
342
343 /* return total of executable nodes, for timecursor */
344 static int setExecutableNodes(bNodeTreeExec *exec, ThreadData *thd)
345 {
346         bNodeTree *ntree = exec->nodetree;
347         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
348         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
349         bNodeExec *nodeexec;
350         bNode *node;
351         bNodeSocket *sock;
352         int n, totnode= 0, group_edit= 0;
353         
354         /* if we are in group edit, viewer nodes get skipped when group has viewer */
355         for(node= ntree->nodes.first; node; node= node->next)
356                 if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
357                         if(ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER))
358                                 group_edit= 1;
359         
360         /* NB: using the exec data list here to have valid dependency sort */
361         for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
362                 int a;
363                 node = nodeexec->node;
364                 
365                 node_get_stack(node, exec->stack, nsin, nsout);
366                 
367                 /* test the outputs */
368                 /* skip value-only nodes (should be in type!) */
369                 if(!node_only_value(node)) {
370                         for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
371                                 if(nsout[a]->data==NULL && nsout[a]->hasoutput) {
372                                         node->need_exec= 1;
373                                         break;
374                                 }
375                         }
376                 }
377                 
378                 /* test the inputs */
379                 for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
380                         /* skip viewer nodes in bg render or group edit */
381                         if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit))
382                                 node->need_exec= 0;
383                         /* is sock in use? */
384                         else if(sock->link) {
385                                 bNodeLink *link= sock->link;
386                                 
387                                 /* this is the test for a cyclic case */
388                                 if(link->fromnode==NULL || link->tonode==NULL);
389                                 else if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
390                                         if(link->fromnode->need_exec) {
391                                                 node->need_exec= 1;
392                                                 break;
393                                         }
394                                 }
395                                 else {
396                                         node->need_exec= 0;
397                                         printf("Node %s skipped, cyclic dependency\n", node->name);
398                                 }
399                         }
400                 }
401                 
402                 if(node->need_exec) {
403                         
404                         /* free output buffers */
405                         for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
406                                 if(nsout[a]->data) {
407                                         free_compbuf(nsout[a]->data);
408                                         nsout[a]->data= NULL;
409                                 }
410                         }
411                         totnode++;
412                         /* printf("node needs exec %s\n", node->name); */
413                         
414                         /* tag for getExecutableNode() */
415                         node->exec= 0;
416                 }
417                 else {
418                         /* tag for getExecutableNode() */
419                         node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED;
420                         
421                 }
422         }
423         
424         /* last step: set the stack values for only-value nodes */
425         /* just does all now, compared to a full buffer exec this is nothing */
426         if(totnode) {
427                 for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
428                         node = nodeexec->node;
429                         if(node->need_exec==0 && node_only_value(node)) {
430                                 if(node->typeinfo->execfunc) {
431                                         node_get_stack(node, exec->stack, nsin, nsout);
432                                         node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
433                                 }
434                         }
435                 }
436         }
437         
438         return totnode;
439 }
440
441 /* while executing tree, free buffers from nodes that are not needed anymore */
442 static void freeExecutableNode(bNodeTreeExec *exec)
443 {
444         /* node outputs can be freed when:
445         - not a render result or image node
446         - when node outputs go to nodes all being set NODE_FINISHED
447         */
448         bNodeTree *ntree = exec->nodetree;
449         bNodeExec *nodeexec;
450         bNode *node;
451         bNodeSocket *sock;
452         int n;
453         
454         /* set exec flag for finished nodes that might need freed */
455         for(node= ntree->nodes.first; node; node= node->next) {
456                 if(node->type!=CMP_NODE_R_LAYERS)
457                         if(node->exec & NODE_FINISHED)
458                                 node->exec |= NODE_FREEBUFS;
459         }
460         /* clear this flag for input links that are not done yet.
461          * Using the exec data for valid dependency sort.
462          */
463         for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
464                 node = nodeexec->node;
465                 if((node->exec & NODE_FINISHED)==0) {
466                         for(sock= node->inputs.first; sock; sock= sock->next)
467                                 if(sock->link)
468                                         sock->link->fromnode->exec &= ~NODE_FREEBUFS;
469                 }
470         }
471         /* now we can free buffers */
472         for(node= ntree->nodes.first; node; node= node->next) {
473                 if(node->exec & NODE_FREEBUFS) {
474                         for(sock= node->outputs.first; sock; sock= sock->next) {
475                                 bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
476                                 if(ns && ns->data) {
477                                         free_compbuf(ns->data);
478                                         ns->data= NULL;
479                                         // printf("freed buf node %s \n", node->name);
480                                 }
481                         }
482                 }
483         }
484 }
485
486 static bNodeExec *getExecutableNode(bNodeTreeExec *exec)
487 {
488         bNodeExec *nodeexec;
489         bNodeSocket *sock;
490         int n;
491         
492         for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
493                 if(nodeexec->node->exec==0) {
494                         /* input sockets should be ready */
495                         for(sock= nodeexec->node->inputs.first; sock; sock= sock->next) {
496                                 if(sock->link && sock->link->fromnode)
497                                         if((sock->link->fromnode->exec & NODE_READY)==0)
498                                                 break;
499                         }
500                         if(sock==NULL)
501                                 return nodeexec;
502                 }
503         }
504         return NULL;
505 }
506
507 /* check if texture nodes need exec or end */
508 static  void ntree_composite_texnode(bNodeTree *ntree, int init)
509 {
510         bNode *node;
511         
512         for(node= ntree->nodes.first; node; node= node->next) {
513                 if(node->type==CMP_NODE_TEXTURE && node->id) {
514                         Tex *tex= (Tex *)node->id;
515                         if(tex->nodetree && tex->use_nodes) {
516                                 /* has internal flag to detect it only does it once */
517                                 if(init) {
518                                         if (!tex->nodetree->execdata)
519                                                 tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree, 1); 
520                                 }
521                                 else
522                                         ntreeTexEndExecTree(tex->nodetree->execdata, 1);
523                                         tex->nodetree->execdata = NULL;
524                         }
525                 }
526         }
527
528 }
529
530 /* optimized tree execute test for compositing */
531 void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
532 {
533         bNodeExec *nodeexec;
534         bNode *node;
535         ListBase threads;
536         ThreadData thdata;
537         int totnode, curnode, rendering= 1, n;
538         bNodeTreeExec *exec= ntree->execdata;
539         
540         if(ntree==NULL) return;
541         
542         if(do_preview)
543                 ntreeInitPreview(ntree, 0, 0);
544         
545         if (!ntree->execdata) {
546                 /* XXX this is the top-level tree, so we use the ntree->execdata pointer. */
547                 exec = ntreeCompositBeginExecTree(ntree, 1);
548         }
549         ntree_composite_texnode(ntree, 1);
550         
551         /* prevent unlucky accidents */
552         if(G.background)
553                 rd->scemode &= ~R_COMP_CROP;
554         
555         /* setup callerdata for thread callback */
556         thdata.rd= rd;
557         thdata.stack= exec->stack;
558         
559         /* fixed seed, for example noise texture */
560         BLI_srandom(rd->cfra);
561
562         /* sets need_exec tags in nodes */
563         curnode = totnode= setExecutableNodes(exec, &thdata);
564
565         BLI_init_threads(&threads, exec_composite_node, rd->threads);
566         
567         while(rendering) {
568                 
569                 if(BLI_available_threads(&threads)) {
570                         nodeexec= getExecutableNode(exec);
571                         if(nodeexec) {
572                                 node = nodeexec->node;
573                                 if(ntree->progress && totnode)
574                                         ntree->progress(ntree->prh, (1.0 - curnode/(float)totnode));
575                                 if(ntree->stats_draw) {
576                                         char str[64];
577                                         sprintf(str, "Compositing %d %s", curnode, node->name);
578                                         ntree->stats_draw(ntree->sdh, str);
579                                 }
580                                 curnode--;
581                                 
582                                 node->threaddata = &thdata;
583                                 node->exec= NODE_PROCESSING;
584                                 BLI_insert_thread(&threads, nodeexec);
585                         }
586                         else
587                                 PIL_sleep_ms(50);
588                 }
589                 else
590                         PIL_sleep_ms(50);
591                 
592                 rendering= 0;
593                 /* test for ESC */
594                 if(ntree->test_break && ntree->test_break(ntree->tbh)) {
595                         for(node= ntree->nodes.first; node; node= node->next)
596                                 node->exec |= NODE_READY;
597                 }
598                 
599                 /* check for ready ones, and if we need to continue */
600                 for(n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
601                         node = nodeexec->node;
602                         if(node->exec & NODE_READY) {
603                                 if((node->exec & NODE_FINISHED)==0) {
604                                         BLI_remove_thread(&threads, nodeexec); /* this waits for running thread to finish btw */
605                                         node->exec |= NODE_FINISHED;
606                                         
607                                         /* freeing unused buffers */
608                                         if(rd->scemode & R_COMP_FREE)
609                                                 freeExecutableNode(exec);
610                                 }
611                         }
612                         else rendering= 1;
613                 }
614         }
615         
616         BLI_end_threads(&threads);
617         
618         /* XXX top-level tree uses the ntree->execdata pointer */
619         ntreeCompositEndExecTree(exec, 1);
620 }
621
622 /* *********************************************** */
623
624 /* clumsy checking... should do dynamic outputs once */
625 static void force_hidden_passes(bNode *node, int passflag)
626 {
627         bNodeSocket *sock;
628         
629         for(sock= node->outputs.first; sock; sock= sock->next)
630                 sock->flag &= ~SOCK_UNAVAIL;
631         
632         sock= BLI_findlink(&node->outputs, RRES_OUT_Z);
633         if(!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL;
634         sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL);
635         if(!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL;
636         sock= BLI_findlink(&node->outputs, RRES_OUT_VEC);
637         if(!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL;
638         sock= BLI_findlink(&node->outputs, RRES_OUT_UV);
639         if(!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL;
640         sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA);
641         if(!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL;
642         sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF);
643         if(!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL;
644         sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC);
645         if(!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL;
646         sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW);
647         if(!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL;
648         sock= BLI_findlink(&node->outputs, RRES_OUT_AO);
649         if(!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL;
650         sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT);
651         if(!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL;
652         sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT);
653         if(!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL;
654         sock= BLI_findlink(&node->outputs, RRES_OUT_INDIRECT);
655         if(!(passflag & SCE_PASS_INDIRECT)) sock->flag |= SOCK_UNAVAIL;
656         sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB);
657         if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL;
658         sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMA);
659         if(!(passflag & SCE_PASS_INDEXMA)) sock->flag |= SOCK_UNAVAIL;
660         sock= BLI_findlink(&node->outputs, RRES_OUT_MIST);
661         if(!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL;
662         sock= BLI_findlink(&node->outputs, RRES_OUT_EMIT);
663         if(!(passflag & SCE_PASS_EMIT)) sock->flag |= SOCK_UNAVAIL;
664         sock= BLI_findlink(&node->outputs, RRES_OUT_ENV);
665         if(!(passflag & SCE_PASS_ENVIRONMENT)) sock->flag |= SOCK_UNAVAIL;
666         
667 }
668
669 /* based on rules, force sockets hidden always */
670 void ntreeCompositForceHidden(bNodeTree *ntree, Scene *curscene)
671 {
672         bNode *node;
673         
674         if(ntree==NULL) return;
675         
676         for(node= ntree->nodes.first; node; node= node->next) {
677                 if( node->type==CMP_NODE_R_LAYERS) {
678                         Scene *sce= node->id?(Scene *)node->id:curscene;
679                         SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
680                         if(srl)
681                                 force_hidden_passes(node, srl->passflag);
682                 }
683                 else if( node->type==CMP_NODE_IMAGE) {
684                         Image *ima= (Image *)node->id;
685                         if(ima) {
686                                 if(ima->rr) {
687                                         ImageUser *iuser= node->storage;
688                                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
689                                         if(rl)
690                                                 force_hidden_passes(node, rl->passflag);
691                                         else
692                                                 force_hidden_passes(node, 0);
693                                 }
694                                 else if(ima->type!=IMA_TYPE_MULTILAYER) {       /* if ->rr not yet read we keep inputs */
695                                         force_hidden_passes(node, RRES_OUT_Z);
696                                 }
697                                 else
698                                         force_hidden_passes(node, 0);
699                         }
700                         else
701                                 force_hidden_passes(node, 0);
702                 }
703         }
704
705 }
706
707 /* called from render pipeline, to tag render input and output */
708 /* need to do all scenes, to prevent errors when you re-render 1 scene */
709 void ntreeCompositTagRender(Scene *curscene)
710 {
711         Scene *sce;
712         
713         for(sce= G.main->scene.first; sce; sce= sce->id.next) {
714                 if(sce->nodetree) {
715                         bNode *node;
716                         
717                         for(node= sce->nodetree->nodes.first; node; node= node->next) {
718                                 if(node->id==(ID *)curscene || node->type==CMP_NODE_COMPOSITE)
719                                         NodeTagChanged(sce->nodetree, node);
720                                 else if(node->type==CMP_NODE_TEXTURE) /* uses scene sizex/sizey */
721                                         NodeTagChanged(sce->nodetree, node);
722                         }
723                 }
724         }
725 }
726
727 static int node_animation_properties(bNodeTree *ntree, bNode *node)
728 {
729         bNodeSocket *sock;
730         const ListBase *lb;
731         Link *link;
732         PointerRNA ptr;
733         PropertyRNA *prop;
734         
735         /* check to see if any of the node's properties have fcurves */
736         RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
737         lb = RNA_struct_type_properties(ptr.type);
738         
739         for (link=lb->first; link; link=link->next) {
740                 int driven, len=1, index;
741                 prop = (PropertyRNA *)link;
742                 
743                 if (RNA_property_array_check(prop))
744                         len = RNA_property_array_length(&ptr, prop);
745                 
746                 for (index=0; index<len; index++) {
747                         if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
748                                 NodeTagChanged(ntree, node);
749                                 return 1;
750                         }
751                 }
752         }
753         
754         /* now check node sockets */
755         for (sock = node->inputs.first; sock; sock=sock->next) {
756                 int driven, len=1, index;
757                 
758                 RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
759                 prop = RNA_struct_find_property(&ptr, "default_value");
760                 if (prop) {
761                         if (RNA_property_array_check(prop))
762                                 len = RNA_property_array_length(&ptr, prop);
763                         
764                         for (index=0; index<len; index++) {
765                                 if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
766                                         NodeTagChanged(ntree, node);
767                                         return 1;
768                                 }
769                         }
770                 }
771         }
772
773         return 0;
774 }
775
776 /* tags nodes that have animation capabilities */
777 int ntreeCompositTagAnimated(bNodeTree *ntree)
778 {
779         bNode *node;
780         int tagged= 0;
781         
782         if(ntree==NULL) return 0;
783         
784         for(node= ntree->nodes.first; node; node= node->next) {
785                 
786                 tagged = node_animation_properties(ntree, node);
787                 
788                 /* otherwise always tag these node types */
789                 if(node->type==CMP_NODE_IMAGE) {
790                         Image *ima= (Image *)node->id;
791                         if(ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
792                                 NodeTagChanged(ntree, node);
793                                 tagged= 1;
794                         }
795                 }
796                 else if(node->type==CMP_NODE_TIME) {
797                         NodeTagChanged(ntree, node);
798                         tagged= 1;
799                 }
800                 /* here was tag render layer, but this is called after a render, so re-composites fail */
801                 else if(node->type==NODE_GROUP) {
802                         if( ntreeCompositTagAnimated((bNodeTree *)node->id) ) {
803                                 NodeTagChanged(ntree, node);
804                         }
805                 }
806                 else if(ELEM(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_TRANSFORM)) {
807                         NodeTagChanged(ntree, node);
808                         tagged= 1;
809                 }
810         }
811         
812         return tagged;
813 }
814
815
816 /* called from image window preview */
817 void ntreeCompositTagGenerators(bNodeTree *ntree)
818 {
819         bNode *node;
820         
821         if(ntree==NULL) return;
822         
823         for(node= ntree->nodes.first; node; node= node->next) {
824                 if( ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_IMAGE))
825                         NodeTagChanged(ntree, node);
826         }
827 }
828
829 /* XXX after render animation system gets a refresh, this call allows composite to end clean */
830 void ntreeClearTags(bNodeTree *ntree)
831 {
832         bNode *node;
833         
834         if(ntree==NULL) return;
835         
836         for(node= ntree->nodes.first; node; node= node->next) {
837                 node->need_exec= 0;
838                 if(node->type==NODE_GROUP)
839                         ntreeClearTags((bNodeTree *)node->id);
840         }
841 }