Orange; more render & compo stuff!
[blender-staging.git] / source / blender / blenkernel / intern / node.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2005 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "DNA_ID.h"
34 #include "DNA_node_types.h"
35 #include "DNA_material_types.h"
36 #include "DNA_scene_types.h"
37
38 #include "BKE_blender.h"
39 #include "BKE_colortools.h"
40 #include "BKE_global.h"
41 #include "BKE_library.h"
42 #include "BKE_main.h"
43 #include "BKE_node.h"
44 #include "BKE_texture.h"
45 #include "BKE_utildefines.h"
46
47 #include "BLI_arithb.h"
48 #include "BLI_blenlib.h"
49
50 #include "MEM_guardedalloc.h"
51 #include "IMB_imbuf.h"
52
53 /* not very important, but the stack solver likes to know a maximum */
54 #define MAX_SOCKET      64
55
56 #pragma mark /* ************** Type stuff **********  */
57
58 static bNodeType *node_get_type(bNodeTree *ntree, int type, bNodeTree *ngroup)
59 {
60         if(type==NODE_GROUP) {
61                 if(ngroup && GS(ngroup->id.name)==ID_NT) {
62                         return ngroup->owntype;
63                 }
64                 return NULL;
65         }
66         else {
67                 bNodeType **typedefs= ntree->alltypes;
68                 
69                 while( *typedefs && (*typedefs)->type!=type)
70                         typedefs++;
71                 
72                 return *typedefs;
73         }
74 }
75
76 void ntreeInitTypes(bNodeTree *ntree)
77 {
78         bNode *node, *next;
79         
80         if(ntree->type==NTREE_SHADER)
81                 ntree->alltypes= node_all_shaders;
82         else if(ntree->type==NTREE_COMPOSIT)
83                 ntree->alltypes= node_all_composit;
84         else {
85                 ntree->alltypes= NULL;
86                 printf("Error: no type definitions for nodes\n");
87         }
88         
89         for(node= ntree->nodes.first; node; node= next) {
90                 next= node->next;
91                 node->typeinfo= node_get_type(ntree, node->type, (bNodeTree *)node->id);
92                 if(node->typeinfo==NULL) {
93                         printf("Error: Node type %s doesn't exist anymore, removed\n", node->name);
94                         nodeFreeNode(ntree, node);
95                 }
96         }
97                         
98         ntree->init |= NTREE_TYPE_INIT;
99 }
100
101 /* only used internal... we depend on type definitions! */
102 static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype)
103 {
104         bNodeSocket *sock= MEM_callocN(sizeof(bNodeSocket), "sock");
105         
106         BLI_strncpy(sock->name, stype->name, NODE_MAXSTR);
107         if(stype->limit==0) sock->limit= 0xFFF;
108         else sock->limit= stype->limit;
109         sock->type= stype->type;
110         
111         sock->to_index= stype->own_index;
112         sock->tosock= stype->internsock;
113         
114         sock->ns.vec[0]= stype->val1;
115         sock->ns.vec[1]= stype->val2;
116         sock->ns.vec[2]= stype->val3;
117         sock->ns.vec[3]= stype->val4;
118                                 
119         if(lb)
120                 BLI_addtail(lb, sock);
121         
122         return sock;
123 }
124
125 static void node_rem_socket(bNodeTree *ntree, ListBase *lb, bNodeSocket *sock)
126 {
127         bNodeLink *link, *next;
128         
129         for(link= ntree->links.first; link; link= next) {
130                 next= link->next;
131                 if(link->fromsock==sock || link->tosock==sock) {
132                         nodeRemLink(ntree, link);
133                 }
134         }
135         
136         BLI_remlink(lb, sock);
137         MEM_freeN(sock);
138 }
139
140 static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype)
141 {
142         bNodeSocket *sock;
143         
144         for(sock= lb->first; sock; sock= sock->next) {
145                 /* both indices are zero for non-groups, otherwise it's a unique index */
146                 if(sock->to_index==stype->own_index)
147                         if(strncmp(sock->name, stype->name, NODE_MAXSTR)==0)
148                                 break;
149         }
150         if(sock) {
151                 sock->type= stype->type;                /* in future, read this from tydefs! */
152                 if(stype->limit==0) sock->limit= 0xFFF;
153                 else sock->limit= stype->limit;
154                 sock->tosock= stype->internsock;
155                 
156                 BLI_remlink(lb, sock);
157                 
158                 return sock;
159         }
160         else {
161                 return node_add_socket_type(NULL, stype);
162         }
163 }
164
165 static void verify_socket_list(bNodeTree *ntree, ListBase *lb, bNodeSocketType *stype_first)
166 {
167         bNodeSocketType *stype;
168         
169         /* no inputs anymore? */
170         if(stype_first==NULL) {
171                 while(lb->first)
172                         node_rem_socket(ntree, lb, lb->first);
173         }
174         else {
175                 /* step by step compare */
176                 stype= stype_first;
177                 while(stype->type != -1) {
178                         stype->sock= verify_socket(lb, stype);
179                         stype++;
180                 }
181                 /* leftovers are removed */
182                 while(lb->first)
183                         node_rem_socket(ntree, lb, lb->first);
184                 /* and we put back the verified sockets */
185                 stype= stype_first;
186                 while(stype->type != -1) {
187                         BLI_addtail(lb, stype->sock);
188                         stype++;
189                 }
190         }
191 }
192
193 void nodeVerifyType(bNodeTree *ntree, bNode *node)
194 {
195         bNodeType *ntype= node->typeinfo;
196         
197         if(ntype) {
198                 /* might add some other verify stuff here */
199                 
200                 verify_socket_list(ntree, &node->inputs, ntype->inputs);
201                 verify_socket_list(ntree, &node->outputs, ntype->outputs);
202         }
203 }
204
205 void ntreeVerifyTypes(bNodeTree *ntree)
206 {
207         bNode *node;
208         
209         if((ntree->init & NTREE_TYPE_INIT)==0)
210                 ntreeInitTypes(ntree);
211         
212         /* check inputs and outputs, and remove or insert them */
213         for(node= ntree->nodes.first; node; node= node->next)
214                 nodeVerifyType(ntree, node);
215         
216 }
217
218 #pragma mark /* ************** Group stuff ********** */
219
220 bNodeType node_group_typeinfo= {
221         /* type code   */       NODE_GROUP,
222         /* name        */       "Group",
223         /* width+range */       120, 60, 200,
224         /* class+opts  */       NODE_CLASS_GROUP, NODE_OPTIONS,
225         /* input sock  */       NULL,
226         /* output sock */       NULL,
227         /* storage     */       "",
228         /* execfunc    */       NULL,
229         
230 };
231
232 /* tag internal sockets */
233 static void group_tag_internal_sockets(bNodeTree *ngroup)
234 {
235         bNode *node;
236         bNodeSocket *sock;
237         bNodeLink *link;
238         
239         /* clear intern tag, but check already for hidden sockets */
240         for(node= ngroup->nodes.first; node; node= node->next) {
241                 for(sock= node->inputs.first; sock; sock= sock->next)
242                         sock->intern= sock->flag & SOCK_HIDDEN;
243                 for(sock= node->outputs.first; sock; sock= sock->next)
244                         sock->intern= sock->flag & SOCK_HIDDEN;
245         }
246         /* set tag */
247         for(link= ngroup->links.first; link; link= link->next) {
248                 link->fromsock->intern= 1;
249                 link->tosock->intern= 1;
250         }
251         
252         /* remove link pointer to external links (only happens on create group) */
253         for(node= ngroup->nodes.first; node; node= node->next) {
254                 for(sock= node->inputs.first; sock; sock= sock->next)
255                         if(sock->intern==0)
256                                 sock->link= NULL;
257         }
258
259         /* set all intern sockets to own_index zero, makes sure that later use won't mixup */
260         for(node= ngroup->nodes.first; node; node= node->next) {
261                 for(sock= node->inputs.first; sock; sock= sock->next)
262                         if(sock->intern)
263                                 sock->own_index= 0;
264                 for(sock= node->outputs.first; sock; sock= sock->next)
265                         if(sock->intern)
266                                 sock->own_index= 0;
267         }
268 }
269
270 /* after editing group, new sockets are zero */
271 /* this routine ensures unique identifiers for zero sockets that are exposed */
272 static void group_verify_own_indices(bNodeTree *ngroup)
273 {
274         bNode *node;
275         bNodeSocket *sock;
276         
277         for(node= ngroup->nodes.first; node; node= node->next) {
278                 for(sock= node->inputs.first; sock; sock= sock->next)
279                         if(sock->own_index==0 && sock->intern==0)
280                                 sock->own_index= ++(ngroup->cur_index);
281                 for(sock= node->outputs.first; sock; sock= sock->next)
282                         if(sock->own_index==0 && sock->intern==0)
283                                 sock->own_index= ++(ngroup->cur_index);
284         }
285         printf("internal index %d\n", ngroup->cur_index);
286 }
287
288
289 /* nodetrees can be used as groups, so we need typeinfo structs generated */
290 void ntreeMakeOwnType(bNodeTree *ngroup)
291 {
292         bNode *node;
293         bNodeSocket *sock;
294         int totin= 0, totout=0, a;
295
296         /* tags socket when internal linked */
297         group_tag_internal_sockets(ngroup);
298         
299         /* ensure all sockets have own unique id */
300         group_verify_own_indices(ngroup);
301         
302         /* counting stats */
303         for(node= ngroup->nodes.first; node; node= node->next) {
304                 if(node->type==NODE_GROUP)
305                         break;
306                 for(sock= node->inputs.first; sock; sock= sock->next)
307                         if(sock->intern==0) 
308                                 totin++;
309                 for(sock= node->outputs.first; sock; sock= sock->next)
310                         if(sock->intern==0) 
311                                 totout++;
312         }
313         /* debug: nodetrees in nodetrees not handled yet */
314         if(node) {
315                 printf("group in group, not supported yet\n");
316                 return;
317         }
318         
319         /* free own type struct */
320         if(ngroup->owntype) {
321                 if(ngroup->owntype->inputs)
322                         MEM_freeN(ngroup->owntype->inputs);
323                 if(ngroup->owntype->outputs)
324                         MEM_freeN(ngroup->owntype->outputs);
325                 MEM_freeN(ngroup->owntype);
326         }
327         
328         /* make own type struct */
329         ngroup->owntype= MEM_mallocN(sizeof(bNodeType), "group type");
330         *ngroup->owntype= node_group_typeinfo;
331         
332         /* input type arrays */
333         if(totin) {
334                 bNodeSocketType *stype;
335                 bNodeSocketType *inputs= MEM_mallocN(sizeof(bNodeSocketType)*(totin+1), "bNodeSocketType");
336                 a= 0;
337                 
338                 for(node= ngroup->nodes.first; node; node= node->next) {
339                         /* nodes are presumed fully verified, stype and socket list are in sync */
340                         stype= node->typeinfo->inputs;
341                         for(sock= node->inputs.first; sock; sock= sock->next, stype++) {
342                                 if(sock->intern==0) {
343                                         /* debug only print */
344                                         if(stype==NULL || stype->type==-1) printf("group verification error %s\n", ngroup->id.name);
345                                         
346                                         inputs[a]= *stype;
347                                         inputs[a].own_index= sock->own_index;
348                                         inputs[a].internsock= sock;     
349                                         a++;
350                                 }
351                         }
352                 }
353                 inputs[a].type= -1;     /* terminator code */
354                 ngroup->owntype->inputs= inputs;
355         }       
356         
357         /* output type arrays */
358         if(totout) {
359                 bNodeSocketType *stype;
360                 bNodeSocketType *outputs= MEM_mallocN(sizeof(bNodeSocketType)*(totout+1), "bNodeSocketType");
361                 a= 0;
362                 
363                 for(node= ngroup->nodes.first; node; node= node->next) {
364                         /* nodes are presumed fully verified, stype and socket list are in sync */
365                         stype= node->typeinfo->outputs;
366                         for(sock= node->outputs.first; sock; sock= sock->next, stype++) {
367                                 if(sock->intern==0) {
368                                         /* debug only print */
369                                         if(stype==NULL || stype->type==-1) printf("group verification error %s\n", ngroup->id.name);
370                                         
371                                         outputs[a]= *stype;
372                                         outputs[a].own_index= sock->own_index;
373                                         outputs[a].internsock= sock;    
374                                         a++;
375                                 }
376                         }
377                 }
378                 outputs[a].type= -1;    /* terminator code */
379                 ngroup->owntype->outputs= outputs;
380         }
381         
382         /* voila, the nodetree has the full definition for generating group-node instances! */
383 }
384
385
386 static bNodeSocket *groupnode_find_tosock(bNode *gnode, int index)
387 {
388         bNodeSocket *sock;
389         
390         for(sock= gnode->inputs.first; sock; sock= sock->next)
391                 if(sock->to_index==index)
392                         return sock;
393         return NULL;
394 }
395
396 static bNodeSocket *groupnode_find_fromsock(bNode *gnode, int index)
397 {
398         bNodeSocket *sock;
399         
400         for(sock= gnode->outputs.first; sock; sock= sock->next)
401                 if(sock->to_index==index)
402                         return sock;
403         return NULL;
404 }
405
406 bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
407 {
408         bNodeLink *link, *linkn;
409         bNode *node, *gnode, *nextn;
410         bNodeTree *ngroup;
411         float min[2], max[2];
412         int totnode=0;
413         
414         INIT_MINMAX2(min, max);
415         
416         /* is there something to group? also do some clearing */
417         for(node= ntree->nodes.first; node; node= node->next) {
418                 if(node->flag & NODE_SELECT) {
419                         /* no groups in groups */
420                         if(node->type==NODE_GROUP)
421                                 return NULL;
422                         DO_MINMAX2( (&node->locx), min, max);
423                         totnode++;
424                 }
425                 node->done= 0;
426         }
427         if(totnode==0) return NULL;
428         
429         /* check if all connections are OK, no unselected node has both
430                 inputs and outputs to a selection */
431         for(link= ntree->links.first; link; link= link->next) {
432                 if(link->fromnode->flag & NODE_SELECT)
433                         link->tonode->done |= 1;
434                 if(link->tonode->flag & NODE_SELECT)
435                         link->fromnode->done |= 2;
436         }       
437         
438         for(node= ntree->nodes.first; node; node= node->next) {
439                 if((node->flag & NODE_SELECT)==0)
440                         if(node->done==3)
441                                 break;
442         }
443         if(node) 
444                 return NULL;
445         
446         /* OK! new nodetree */
447         ngroup= alloc_libblock(&G.main->nodetree, ID_NT, "NodeGroup");
448         ngroup->type= ntree->type;
449         ngroup->alltypes= ntree->alltypes;
450         
451         /* move nodes over */
452         for(node= ntree->nodes.first; node; node= nextn) {
453                 nextn= node->next;
454                 if(node->flag & NODE_SELECT) {
455                         BLI_remlink(&ntree->nodes, node);
456                         BLI_addtail(&ngroup->nodes, node);
457                         node->locx-= 0.5f*(min[0]+max[0]);
458                         node->locy-= 0.5f*(min[1]+max[1]);
459                 }
460         }
461
462         /* move links over */
463         for(link= ntree->links.first; link; link= linkn) {
464                 linkn= link->next;
465                 if(link->fromnode->flag & link->tonode->flag & NODE_SELECT) {
466                         BLI_remlink(&ntree->links, link);
467                         BLI_addtail(&ngroup->links, link);
468                 }
469         }
470         
471         /* now we can make own group typeinfo */
472         ntreeMakeOwnType(ngroup);
473         
474         /* make group node */
475         gnode= nodeAddNodeType(ntree, NODE_GROUP, ngroup);
476         gnode->locx= 0.5f*(min[0]+max[0]);
477         gnode->locy= 0.5f*(min[1]+max[1]);
478         
479         /* relink external sockets */
480         for(link= ntree->links.first; link; link= link->next) {
481                 if(link->tonode->flag & NODE_SELECT) {
482                         link->tonode= gnode;
483                         link->tosock= groupnode_find_tosock(gnode, link->tosock->own_index);
484                         if(link->tosock==NULL) printf("Bad!\n");
485                 }
486                 else if(link->fromnode->flag & NODE_SELECT) {
487                         link->fromnode= gnode;
488                         link->fromsock= groupnode_find_fromsock(gnode, link->fromsock->own_index);
489                         if(link->fromsock==NULL) printf("Bad!\n");
490                 }
491         }
492         
493         return gnode;
494 }
495
496 /* note: ungroup: group_indices zero! */
497
498 /* here's a nasty little one, need to check users... */
499 /* should become callbackable... */
500 void nodeVerifyGroup(bNodeTree *ngroup)
501 {
502         
503         /* group changed, so we rebuild the type definition */
504         ntreeMakeOwnType(ngroup);
505         
506         if(ngroup->type==NTREE_SHADER) {
507                 Material *ma;
508                 for(ma= G.main->mat.first; ma; ma= ma->id.next) {
509                         if(ma->nodetree) {
510                                 bNode *node;
511                                 
512                                 /* find if group is in tree */
513                                 for(node= ma->nodetree->nodes.first; node; node= node->next)
514                                         if(node->id == (ID *)ngroup)
515                                                 break;
516                                 
517                                 if(node) {
518                                         /* set all type pointers OK */
519                                         ntreeInitTypes(ma->nodetree);
520                                         
521                                         for(node= ma->nodetree->nodes.first; node; node= node->next)
522                                                 if(node->id == (ID *)ngroup)
523                                                         nodeVerifyType(ma->nodetree, node);
524                                 }
525                         }
526                 }
527         }
528         else if(ngroup->type==NTREE_COMPOSIT) {
529                 Scene *sce;
530                 for(sce= G.main->scene.first; sce; sce= sce->id.next) {
531                         if(sce->nodetree) {
532                                 bNode *node;
533                                 
534                                 /* find if group is in tree */
535                                 for(node= sce->nodetree->nodes.first; node; node= node->next)
536                                         if(node->id == (ID *)ngroup)
537                                                 break;
538                                 
539                                 if(node) {
540                                         /* set all type pointers OK */
541                                         ntreeInitTypes(sce->nodetree);
542                                         
543                                         for(node= sce->nodetree->nodes.first; node; node= node->next)
544                                                 if(node->id == (ID *)ngroup)
545                                                         nodeVerifyType(sce->nodetree, node);
546                                 }
547                         }
548                 }
549         }
550 }
551
552 /* also to check all users of groups. Now only used in editor for hide/unhide */
553 /* should become callbackable? */
554 void nodeGroupSocketUseFlags(bNodeTree *ngroup)
555 {
556         bNode *node;
557         bNodeSocket *sock;
558
559         /* clear flags */
560         for(node= ngroup->nodes.first; node; node= node->next) {
561                 for(sock= node->inputs.first; sock; sock= sock->next)
562                         sock->flag &= ~SOCK_IN_USE;
563                 for(sock= node->outputs.first; sock; sock= sock->next)
564                         sock->flag &= ~SOCK_IN_USE;
565         }
566         
567         /* tag all thats in use */
568         if(ngroup->type==NTREE_SHADER) {
569                 Material *ma;
570                 for(ma= G.main->mat.first; ma; ma= ma->id.next) {
571                         if(ma->nodetree) {
572                                 for(node= ma->nodetree->nodes.first; node; node= node->next) {
573                                         if(node->id==(ID *)ngroup) {
574                                                 for(sock= node->inputs.first; sock; sock= sock->next)
575                                                         if(sock->link)
576                                                                 if(sock->tosock) 
577                                                                         sock->tosock->flag |= SOCK_IN_USE;
578                                                 for(sock= node->outputs.first; sock; sock= sock->next)
579                                                         if(nodeCountSocketLinks(ma->nodetree, sock))
580                                                                 if(sock->tosock) 
581                                                                         sock->tosock->flag |= SOCK_IN_USE;
582                                         }
583                                 }
584                         }
585                 }
586         }
587         else if(ngroup->type==NTREE_COMPOSIT) {
588                 Scene *sce;
589                 for(sce= G.main->scene.first; sce; sce= sce->id.next) {
590                         if(sce->nodetree) {
591                                 for(node= sce->nodetree->nodes.first; node; node= node->next) {
592                                         if(node->id==(ID *)ngroup) {
593                                                 for(sock= node->inputs.first; sock; sock= sock->next)
594                                                         if(sock->link)
595                                                                 if(sock->tosock) 
596                                                                         sock->tosock->flag |= SOCK_IN_USE;
597                                                 for(sock= node->outputs.first; sock; sock= sock->next)
598                                                         if(nodeCountSocketLinks(sce->nodetree, sock))
599                                                                 if(sock->tosock) 
600                                                                         sock->tosock->flag |= SOCK_IN_USE;
601                                         }
602                                 }
603                         }
604                 }
605         }
606 }
607
608 static void find_node_with_socket(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex)
609 {
610         bNode *node;
611         bNodeSocket *tsock;
612         int index;
613         
614         for(node= ntree->nodes.first; node; node= node->next) {
615                 for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++)
616                         if(tsock==sock)
617                                 break;
618                 if(tsock)
619                         break;
620                 for(index=0, tsock= node->outputs.first; tsock; tsock= tsock->next, index++)
621                         if(tsock==sock)
622                                 break;
623                 if(tsock)
624                         break;
625         }
626         if(node) {
627                 *nodep= node;
628                 *sockindex= index;
629         }
630         else {
631                 *nodep= NULL;
632         }
633 }
634
635 /* returns 1 if its OK */
636 int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
637 {
638         bNodeLink *link, *linkn;
639         bNode *node, *nextn;
640         bNodeTree *ngroup, *wgroup;
641         int index;
642         
643         ngroup= (bNodeTree *)gnode->id;
644         if(ngroup==NULL) return 0;
645         
646         /* clear new pointers, set in copytree */
647         for(node= ntree->nodes.first; node; node= node->next)
648                 node->new= NULL;
649
650         wgroup= ntreeCopyTree(ngroup, 0);
651         
652         /* add the nodes into the ntree */
653         for(node= wgroup->nodes.first; node; node= nextn) {
654                 nextn= node->next;
655                 BLI_remlink(&wgroup->nodes, node);
656                 BLI_addtail(&ntree->nodes, node);
657                 node->locx+= gnode->locx;
658                 node->locy+= gnode->locy;
659                 node->flag |= NODE_SELECT;
660         }
661         /* and the internal links */
662         for(link= wgroup->links.first; link; link= linkn) {
663                 linkn= link->next;
664                 BLI_remlink(&wgroup->links, link);
665                 BLI_addtail(&ntree->links, link);
666         }
667
668         /* restore links to and from the gnode */
669         for(link= ntree->links.first; link; link= link->next) {
670                 if(link->tonode==gnode) {
671                         /* link->tosock->tosock is on the node we look for */
672                         find_node_with_socket(ngroup, link->tosock->tosock, &nextn, &index);
673                         if(nextn==NULL) printf("wrong stuff!\n");
674                         else if(nextn->new==NULL) printf("wrong stuff too!\n");
675                         else {
676                                 link->tonode= nextn->new;
677                                 link->tosock= BLI_findlink(&link->tonode->inputs, index);
678                         }
679                 }
680                 else if(link->fromnode==gnode) {
681                         /* link->fromsock->tosock is on the node we look for */
682                         find_node_with_socket(ngroup, link->fromsock->tosock, &nextn, &index);
683                         if(nextn==NULL) printf("1 wrong stuff!\n");
684                         else if(nextn->new==NULL) printf("1 wrong stuff too!\n");
685                         else {
686                                 link->fromnode= nextn->new;
687                                 link->fromsock= BLI_findlink(&link->fromnode->outputs, index);
688                         }
689                 }
690         }
691         
692         /* remove the gnode & work tree */
693         ntreeFreeTree(wgroup);
694         MEM_freeN(wgroup);
695         
696         nodeFreeNode(ntree, gnode);
697         
698         return 1;
699 }
700
701 #pragma mark /* ************** Add stuff ********** */
702
703 bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup)
704 {
705         bNode *node;
706         bNodeType *ntype= node_get_type(ntree, type, ngroup);
707         bNodeSocketType *stype;
708         
709         node= MEM_callocN(sizeof(bNode), "new node");
710         BLI_addtail(&ntree->nodes, node);
711         node->typeinfo= ntype;
712         
713         BLI_strncpy(node->name, ntype->name, NODE_MAXSTR);
714         node->type= ntype->type;
715         node->flag= NODE_SELECT|ntype->flag;
716         node->width= ntype->width;
717         node->miniwidth= 15.0f;         /* small value only, allows print of first chars */
718         
719         if(type==NODE_GROUP)
720                 node->id= (ID *)ngroup;
721         
722         if(ntype->inputs) {
723                 stype= ntype->inputs;
724                 while(stype->type != -1) {
725                         node_add_socket_type(&node->inputs, stype);
726                         stype++;
727                 }
728         }
729         if(ntype->outputs) {
730                 stype= ntype->outputs;
731                 while(stype->type != -1) {
732                         node_add_socket_type(&node->outputs, stype);
733                         stype++;
734                 }
735         }
736         
737         /* need init handler later? */
738         if(ntree->type==NTREE_SHADER) {
739                 if(type==SH_NODE_MATERIAL)
740                         node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC;
741                 else if(type==SH_NODE_VALTORGB)
742                         node->storage= add_colorband(1);
743                 else if(type==SH_NODE_MAPPING)
744                         node->storage= add_mapping();
745                 else if(type==SH_NODE_CURVE_VEC)
746                         node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
747                 else if(type==SH_NODE_CURVE_RGB)
748                         node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
749         }
750         else if(ntree->type==NTREE_COMPOSIT) {
751                 if(type==CMP_NODE_VALTORGB)
752                         node->storage= add_colorband(1);
753                 else if(type==CMP_NODE_CURVE_VEC)
754                         node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
755                 else if(type==CMP_NODE_CURVE_RGB)
756                         node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
757                 else if(type==CMP_NODE_MAP_VALUE)
758                         node->storage= add_mapping();
759         }
760         
761         return node;
762 }
763
764 /* keep socket listorder identical, for copying links */
765 /* ntree is the target tree */
766 bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
767 {
768         bNode *nnode= MEM_callocN(sizeof(bNode), "dupli node");
769         bNodeSocket *sock;
770
771         *nnode= *node;
772         BLI_addtail(&ntree->nodes, nnode);
773         
774         duplicatelist(&nnode->inputs, &node->inputs);
775         for(sock= nnode->inputs.first; sock; sock= sock->next)
776                 sock->own_index= 0;
777         
778         duplicatelist(&nnode->outputs, &node->outputs);
779         for(sock= nnode->outputs.first; sock; sock= sock->next)
780                 sock->own_index= 0;
781         
782         if(nnode->id)
783                 nnode->id->us++;
784         
785         if(nnode->storage) {
786                 /* another candidate for handlerizing! */
787                 if(ntree->type==NTREE_SHADER) {
788                         if(node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB)
789                                 nnode->storage= curvemapping_copy(node->storage);
790                         else 
791                                 nnode->storage= MEM_dupallocN(nnode->storage);
792                 }
793                 else if(ntree->type==NTREE_COMPOSIT) {
794                         if(node->type==CMP_NODE_CURVE_VEC || node->type==CMP_NODE_CURVE_RGB)
795                                 nnode->storage= curvemapping_copy(node->storage);
796                         else 
797                                 nnode->storage= MEM_dupallocN(nnode->storage);
798                 }
799                 else 
800                         nnode->storage= MEM_dupallocN(nnode->storage);
801         }
802         
803         node->new= nnode;
804         nnode->new= NULL;
805         nnode->preview= NULL;
806         
807         return nnode;
808 }
809
810 bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
811 {
812         bNodeLink *link= MEM_callocN(sizeof(bNodeLink), "link");
813         
814         BLI_addtail(&ntree->links, link);
815         link->fromnode= fromnode;
816         link->fromsock= fromsock;
817         link->tonode= tonode;
818         link->tosock= tosock;
819         
820         return link;
821 }
822
823 void nodeRemLink(bNodeTree *ntree, bNodeLink *link)
824 {
825         BLI_remlink(&ntree->links, link);
826         if(link->tosock)
827                 link->tosock->link= NULL;
828         MEM_freeN(link);
829 }
830
831
832 bNodeTree *ntreeAddTree(int type)
833 {
834         bNodeTree *ntree= MEM_callocN(sizeof(bNodeTree), "new node tree");
835         ntree->type= type;
836         
837         ntreeInitTypes(ntree);
838         return ntree;
839 }
840
841 #pragma mark /* ************** Free stuff ********** */
842
843 /* goes over entire tree */
844 static void node_unlink_node(bNodeTree *ntree, bNode *node)
845 {
846         bNodeLink *link, *next;
847         bNodeSocket *sock;
848         ListBase *lb;
849         
850         for(link= ntree->links.first; link; link= next) {
851                 next= link->next;
852                 
853                 if(link->fromnode==node)
854                         lb= &node->outputs;
855                 else if(link->tonode==node)
856                         lb= &node->inputs;
857                 else
858                         lb= NULL;
859
860                 if(lb) {
861                         for(sock= lb->first; sock; sock= sock->next) {
862                                 if(link->fromsock==sock || link->tosock==sock)
863                                         break;
864                         }
865                         if(sock) {
866                                 nodeRemLink(ntree, link);
867                         }
868                 }
869         }
870 }
871
872 void nodeFreeNode(bNodeTree *ntree, bNode *node)
873 {
874         node_unlink_node(ntree, node);
875         BLI_remlink(&ntree->nodes, node);
876
877         if(node->id)
878                 node->id->us--;
879         
880         BLI_freelistN(&node->inputs);
881         BLI_freelistN(&node->outputs);
882         
883         if(node->preview) {
884                 if(node->preview->rect)
885                         MEM_freeN(node->preview->rect);
886                 MEM_freeN(node->preview);
887         }
888         if(node->storage) {
889                 /* could be handlerized at some point, now only 1 exception still */
890                 if(ntree->type==NTREE_SHADER) {
891                         if(node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB)
892                                 curvemapping_free(node->storage);
893                         else 
894                                 MEM_freeN(node->storage);
895                 }
896                 else if(ntree->type==NTREE_COMPOSIT) {
897                         if(node->type==CMP_NODE_CURVE_VEC || node->type==CMP_NODE_CURVE_RGB)
898                                 curvemapping_free(node->storage);
899                         else 
900                                 MEM_freeN(node->storage);
901                 }
902                 else 
903                         MEM_freeN(node->storage);
904         }
905         MEM_freeN(node);
906 }
907
908 /* do not free ntree itself here, free_libblock calls this function too */
909 void ntreeFreeTree(bNodeTree *ntree)
910 {
911         bNode *node, *next;
912         
913         if(ntree==NULL) return;
914         
915         BLI_freelistN(&ntree->links);   /* do first, then unlink_node goes fast */
916         
917         for(node= ntree->nodes.first; node; node= next) {
918                 next= node->next;
919                 nodeFreeNode(ntree, node);
920         }
921         
922         if(ntree->owntype) {
923                 if(ntree->owntype->inputs)
924                         MEM_freeN(ntree->owntype->inputs);
925                 if(ntree->owntype->outputs)
926                         MEM_freeN(ntree->owntype->outputs);
927                 MEM_freeN(ntree->owntype);
928         }
929 }
930
931 bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select)
932 {
933         bNodeTree *newtree;
934         bNode *node, *nnode, *last;
935         bNodeLink *link, *nlink;
936         bNodeSocket *sock;
937         int a;
938         
939         if(ntree==NULL) return NULL;
940         
941         if(internal_select==0) {
942                 newtree= MEM_dupallocN(ntree);
943                 newtree->nodes.first= newtree->nodes.last= NULL;
944                 newtree->links.first= newtree->links.last= NULL;
945         }
946         else
947                 newtree= ntree;
948         
949         last= ntree->nodes.last;
950         for(node= ntree->nodes.first; node; node= node->next) {
951                 
952                 node->new= NULL;
953                 if(internal_select==0 || (node->flag & NODE_SELECT)) {
954                         nnode= nodeCopyNode(newtree, node);     /* sets node->new */
955                         if(internal_select) {
956                                 node->flag &= ~NODE_SELECT;
957                                 nnode->flag |= NODE_SELECT;
958                         }
959                         node->flag &= ~NODE_ACTIVE;
960                 }
961                 if(node==last) break;
962         }
963         
964         /* check for copying links */
965         for(link= ntree->links.first; link; link= link->next) {
966                 if(link->fromnode->new && link->tonode->new) {
967                         nlink= nodeAddLink(newtree, link->fromnode->new, NULL, link->tonode->new, NULL);
968                         /* sockets were copied in order */
969                         for(a=0, sock= link->fromnode->outputs.first; sock; sock= sock->next, a++) {
970                                 if(sock==link->fromsock)
971                                         break;
972                         }
973                         nlink->fromsock= BLI_findlink(&link->fromnode->new->outputs, a);
974                         
975                         for(a=0, sock= link->tonode->inputs.first; sock; sock= sock->next, a++) {
976                                 if(sock==link->tosock)
977                                         break;
978                         }
979                         nlink->tosock= BLI_findlink(&link->tonode->new->inputs, a);
980                 }
981         }
982         
983         /* own type definition for group usage */
984         if(internal_select==0) {
985                 if(ntree->owntype) {
986                         newtree->owntype= MEM_dupallocN(ntree->owntype);
987                         if(ntree->owntype->inputs)
988                                 newtree->owntype->inputs= MEM_dupallocN(ntree->owntype->inputs);
989                         if(ntree->owntype->outputs)
990                                 newtree->owntype->outputs= MEM_dupallocN(ntree->owntype->outputs);
991                 }
992         }       
993         return newtree;
994 }
995
996 #pragma mark /* ************ find stuff *************** */
997
998 bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to)
999 {
1000         bNodeLink *link;
1001         
1002         for(link= ntree->links.first; link; link= link->next) {
1003                 if(link->fromsock==from && link->tosock==to)
1004                         return link;
1005                 if(link->fromsock==to && link->tosock==from)    /* hrms? */
1006                         return link;
1007         }
1008         return NULL;
1009 }
1010
1011 int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
1012 {
1013         bNodeLink *link;
1014         int tot= 0;
1015         
1016         for(link= ntree->links.first; link; link= link->next) {
1017                 if(link->fromsock==sock || link->tosock==sock)
1018                         tot++;
1019         }
1020         return tot;
1021 }
1022
1023 bNode *nodeGetActive(bNodeTree *ntree)
1024 {
1025         bNode *node;
1026         
1027         if(ntree==NULL) return NULL;
1028         
1029         for(node= ntree->nodes.first; node; node= node->next)
1030                 if(node->flag & NODE_ACTIVE)
1031                         break;
1032         return node;
1033 }
1034
1035 /* two active flags, ID nodes have special flag for buttons display */
1036 bNode *nodeGetActiveID(bNodeTree *ntree, short idtype)
1037 {
1038         bNode *node;
1039         
1040         if(ntree==NULL) return NULL;
1041         
1042         for(node= ntree->nodes.first; node; node= node->next)
1043                 if(node->id && GS(node->id->name)==idtype)
1044                         if(node->flag & NODE_ACTIVE_ID)
1045                                 break;
1046         return node;
1047 }
1048
1049 /* two active flags, ID nodes have special flag for buttons display */
1050 void nodeClearActiveID(bNodeTree *ntree, short idtype)
1051 {
1052         bNode *node;
1053         
1054         if(ntree==NULL) return;
1055         
1056         for(node= ntree->nodes.first; node; node= node->next)
1057                 if(node->id && GS(node->id->name)==idtype)
1058                         node->flag &= ~NODE_ACTIVE_ID;
1059 }
1060
1061 /* two active flags, ID nodes have special flag for buttons display */
1062 void nodeSetActive(bNodeTree *ntree, bNode *node)
1063 {
1064         bNode *tnode;
1065         
1066         /* make sure only one node is active, and only one per ID type */
1067         for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) {
1068                 tnode->flag &= ~NODE_ACTIVE;
1069                 
1070                 if(node->id && tnode->id) {
1071                         if(GS(node->id->name) == GS(tnode->id->name))
1072                                 tnode->flag &= ~NODE_ACTIVE_ID;
1073                 }
1074         }
1075         
1076         node->flag |= NODE_ACTIVE;
1077         if(node->id)
1078                 node->flag |= NODE_ACTIVE_ID;
1079 }
1080
1081 /* use flags are not persistant yet, groups might need different tagging, so we do it each time
1082    when we need to get this info */
1083 void ntreeSocketUseFlags(bNodeTree *ntree)
1084 {
1085         bNode *node;
1086         bNodeSocket *sock;
1087         bNodeLink *link;
1088         
1089         /* clear flags */
1090         for(node= ntree->nodes.first; node; node= node->next) {
1091                 for(sock= node->inputs.first; sock; sock= sock->next)
1092                         sock->flag &= ~SOCK_IN_USE;
1093                 for(sock= node->outputs.first; sock; sock= sock->next)
1094                         sock->flag &= ~SOCK_IN_USE;
1095         }
1096         
1097         /* tag all thats in use */
1098         for(link= ntree->links.first; link; link= link->next) {
1099                 link->fromsock->flag |= SOCK_IN_USE;
1100                 link->tosock->flag |= SOCK_IN_USE;
1101         }
1102 }
1103
1104 #pragma mark /* ************** dependency stuff *********** */
1105
1106 /* node is guaranteed to be not checked before */
1107 static int node_recurs_check(bNode *node, bNode ***nsort, int level)
1108 {
1109         bNode *fromnode;
1110         bNodeSocket *sock;
1111         int has_inputlinks= 0;
1112         
1113         node->done= 1;
1114         level++;
1115         
1116         for(sock= node->inputs.first; sock; sock= sock->next) {
1117                 if(sock->link) {
1118                         has_inputlinks= 1;
1119                         fromnode= sock->link->fromnode;
1120                         if(fromnode->done==0) {
1121                                 fromnode->level= node_recurs_check(fromnode, nsort, level);
1122                         }
1123                 }
1124         }
1125 //      printf("node sort %s level %d\n", node->name, level);
1126         **nsort= node;
1127         (*nsort)++;
1128         
1129         if(has_inputlinks)
1130                 return level;
1131         else 
1132                 return 0xFFF;
1133 }
1134
1135 void ntreeSolveOrder(bNodeTree *ntree)
1136 {
1137         bNode *node, **nodesort, **nsort;
1138         bNodeSocket *sock;
1139         bNodeLink *link;
1140         int a, totnode=0;
1141         
1142         /* the solve-order is called on each tree change, so we should be sure no exec can be running */
1143         ntreeEndExecTree(ntree);
1144
1145         /* set links pointers the input sockets, to find dependencies */
1146         /* first clear data */
1147         for(node= ntree->nodes.first; node; node= node->next) {
1148                 node->done= 0;
1149                 totnode++;
1150                 for(sock= node->inputs.first; sock; sock= sock->next)
1151                         sock->link= NULL;
1152         }
1153         if(totnode==0)
1154                 return;
1155         
1156         for(link= ntree->links.first; link; link= link->next) {
1157                 link->tosock->link= link;
1158         }
1159         
1160         nsort= nodesort= MEM_callocN(totnode*sizeof(void *), "sorted node array");
1161         
1162         /* recursive check */
1163         for(node= ntree->nodes.first; node; node= node->next) {
1164                 if(node->done==0) {
1165                         node->level= node_recurs_check(node, &nsort, 0);
1166                 }
1167         }
1168         
1169         /* re-insert nodes in order, first a paranoia check */
1170         for(a=0; a<totnode; a++) {
1171                 if(nodesort[a]==NULL)
1172                         break;
1173         }
1174         if(a<totnode)
1175                 printf("sort error in node tree");
1176         else {
1177                 ntree->nodes.first= ntree->nodes.last= NULL;
1178                 for(a=0; a<totnode; a++)
1179                         BLI_addtail(&ntree->nodes, nodesort[a]);
1180         }
1181         
1182         MEM_freeN(nodesort);
1183         
1184         /* find the active outputs, might become tree type dependant handler */
1185         for(node= ntree->nodes.first; node; node= node->next) {
1186                 if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
1187                         bNode *tnode;
1188                         int output= 0;
1189                         /* there is more types having output class, each one is checked */
1190                         for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) {
1191                                 if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) {
1192                                         if(tnode->type==node->type) {
1193                                                 if(tnode->flag & NODE_DO_OUTPUT) {
1194                                                         if(output>1)
1195                                                                 tnode->flag &= ~NODE_DO_OUTPUT;
1196                                                         output++;
1197                                                 }
1198                                         }
1199                                 }
1200                         }
1201                         if(output==0)
1202                                 node->flag |= NODE_DO_OUTPUT;
1203                 }
1204         }
1205         
1206         /* here we could recursively set which nodes have to be done,
1207                 might be different for editor or for "real" use... */
1208 }
1209
1210 #pragma mark /* *************** preview *********** */
1211
1212 /* if node->preview, then we assume the rect to exist */
1213
1214 static void nodeInitPreview(bNode *node, int xsize, int ysize)
1215 {
1216         
1217         if(node->preview==NULL) {
1218                 node->preview= MEM_callocN(sizeof(bNodePreview), "node preview");
1219                 printf("added preview %s\n", node->name);
1220         }
1221         
1222         /* node previews can get added with variable size this way */
1223         if(xsize==0 || ysize==0)
1224                 return;
1225         
1226         /* sanity checks & initialize */
1227         if(node->preview && node->preview->rect) {
1228                 if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) {
1229                         MEM_freeN(node->preview->rect);
1230                         node->preview->rect= NULL;
1231                 }
1232         }
1233         
1234         if(node->preview->rect==NULL) {
1235                 node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect");
1236                 node->preview->xsize= xsize;
1237                 node->preview->ysize= ysize;
1238         }
1239 }
1240
1241 void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize)
1242 {
1243         bNode *node;
1244         
1245         if(ntree==NULL)
1246                 return;
1247         
1248         for(node= ntree->nodes.first; node; node= node->next) {
1249                 if(node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */
1250                         nodeInitPreview(node, xsize, ysize);
1251                 if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
1252                         ntreeInitPreview((bNodeTree *)node->id, xsize, ysize);
1253         }               
1254 }
1255
1256 void nodeAddToPreview(bNode *node, float *col, int x, int y)
1257 {
1258         bNodePreview *preview= node->preview;
1259         if(preview) {
1260                 if(x>=0 && y>=0) {
1261                         if(x<preview->xsize && y<preview->ysize) {
1262                                 float *tar= preview->rect+ 4*((preview->xsize*y) + x);
1263                                 QUATCOPY(tar, col);
1264                         }
1265                         else printf("prv out bound x y %d %d\n", x, y);
1266                 }
1267                 else printf("prv out bound x y %d %d\n", x, y);
1268         }
1269 }
1270
1271
1272
1273 #pragma mark /* ******************* executing ************* */
1274
1275 /* see notes at ntreeBeginExecTree */
1276 static void group_node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out, bNodeStack **gin, bNodeStack **gout)
1277 {
1278         bNodeSocket *sock;
1279         
1280         /* build pointer stack */
1281         for(sock= node->inputs.first; sock; sock= sock->next) {
1282                 if(sock->intern) {
1283                         /* yep, intern can have link or is hidden socket */
1284                         if(sock->link)
1285                                 *(in++)= stack + sock->link->fromsock->stack_index;
1286                         else
1287                                 *(in++)= &sock->ns;
1288                 }
1289                 else
1290                         *(in++)= gin[sock->stack_index_ext];
1291         }
1292         
1293         for(sock= node->outputs.first; sock; sock= sock->next) {
1294                 if(sock->intern)
1295                         *(out++)= stack + sock->stack_index;
1296                 else
1297                         *(out++)= gout[sock->stack_index_ext];
1298         }
1299 }
1300
1301 static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNodeStack **in, bNodeStack **out)
1302 {
1303         bNode *node;
1304         bNodeTree *ntree= (bNodeTree *)gnode->id;
1305         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
1306         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
1307         
1308         if(ntree==NULL) return;
1309         
1310         stack+= gnode->stack_index;
1311                 
1312         for(node= ntree->nodes.first; node; node= node->next) {
1313                 if(node->typeinfo->execfunc) {
1314                         group_node_get_stack(node, stack, nsin, nsout, in, out);
1315                         node->typeinfo->execfunc(data, node, nsin, nsout);
1316                 }
1317         }
1318 }
1319
1320 /* recursively called for groups */
1321 /* we set all trees on own local indices, but put a total counter
1322    in the groups, so each instance of a group has own stack */
1323 static int ntree_begin_exec_tree(bNodeTree *ntree)
1324 {
1325         bNode *node;
1326         bNodeSocket *sock;
1327         int index= 0, index_in= 0, index_out= 0;
1328         
1329         if((ntree->init & NTREE_TYPE_INIT)==0)
1330                 ntreeInitTypes(ntree);
1331         
1332         /* create indices for stack, check preview */
1333         for(node= ntree->nodes.first; node; node= node->next) {
1334                 
1335                 for(sock= node->inputs.first; sock; sock= sock->next) {
1336                         if(sock->intern==0)
1337                                 sock->stack_index_ext= index_in++;
1338                 }
1339                 
1340                 for(sock= node->outputs.first; sock; sock= sock->next) {
1341                         sock->stack_index= index++;
1342                         if(sock->intern==0)
1343                                 sock->stack_index_ext= index_out++;
1344                 }
1345                 
1346                 if(node->type==NODE_GROUP) {
1347                         if(node->id) {
1348                                 
1349                                 node->stack_index= index;
1350                                 index+= ntree_begin_exec_tree((bNodeTree *)node->id);
1351
1352                                 /* copy internal data from internal nodes to own input sockets */
1353                                 for(sock= node->inputs.first; sock; sock= sock->next) {
1354                                         if(sock->tosock) {
1355                                                 sock->ns= sock->tosock->ns;
1356                                         }
1357                                 }
1358                         }
1359                 }
1360         }
1361         
1362         return index;
1363 }
1364
1365 /* stack indices make sure all nodes only write in allocated data, for making it thread safe */
1366 /* only root tree gets the stack, to enable instances to have own stack entries */
1367 /* only two threads now! */
1368 /* per tree (and per group) unique indices are created */
1369 /* the index_ext we need to be able to map from groups to the group-node own stack */
1370
1371 void ntreeBeginExecTree(bNodeTree *ntree)
1372 {
1373         
1374         /* goes recursive over all groups */
1375         ntree->stacksize= ntree_begin_exec_tree(ntree);
1376         
1377         if(ntree->stacksize) {
1378                 bNode *node;
1379                 bNodeStack *ns;
1380                 int a;
1381                 
1382                 /* allocate stack */
1383                 ns=ntree->stack= MEM_callocN(ntree->stacksize*sizeof(bNodeStack), "node stack");
1384                 
1385                 /* tag inputs, the get_stack() gives own socket stackdata if not in use */
1386                 for(a=0; a<ntree->stacksize; a++, ns++) ns->hasinput= 1;
1387                 
1388                 /* tag outputs, so we know when we can skip operations */
1389                 for(node= ntree->nodes.first; node; node= node->next) {
1390                         bNodeSocket *sock;
1391                         for(sock= node->inputs.first; sock; sock= sock->next) {
1392                                 if(sock->link) {
1393                                         ns= ntree->stack + sock->link->fromsock->stack_index;
1394                                         ns->hasoutput= 1;
1395                                 }
1396                         }
1397                 }
1398                 
1399                 ntree->stack1= MEM_dupallocN(ntree->stack);
1400         }
1401         
1402         ntree->init |= NTREE_EXEC_INIT;
1403 }
1404
1405 void ntreeEndExecTree(bNodeTree *ntree)
1406 {
1407         
1408         if(ntree->init & NTREE_EXEC_INIT) {
1409                 
1410                 if(ntree->stack) {
1411                         
1412                         /* another callback candidate! */
1413                         if(ntree->type==NTREE_COMPOSIT) {
1414                                 bNodeStack *ns;
1415                                 int a;
1416                                 
1417                                 for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++)
1418                                         if(ns->data)
1419                                                 free_compbuf(ns->data);
1420                                 for(ns= ntree->stack1, a=0; a<ntree->stacksize; a++, ns++)
1421                                         if(ns->data)
1422                                                 free_compbuf(ns->data);
1423                         }
1424                         MEM_freeN(ntree->stack);
1425                         ntree->stack= NULL;
1426                         MEM_freeN(ntree->stack1);
1427                         ntree->stack1= NULL;
1428                 }
1429
1430                 ntree->init &= ~NTREE_EXEC_INIT;
1431         }
1432 }
1433
1434 static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
1435 {
1436         bNodeSocket *sock;
1437         
1438         /* build pointer stack */
1439         for(sock= node->inputs.first; sock; sock= sock->next) {
1440                 if(sock->link)
1441                         *(in++)= stack + sock->link->fromsock->stack_index;
1442                 else
1443                         *(in++)= &sock->ns;
1444         }
1445         
1446         for(sock= node->outputs.first; sock; sock= sock->next) {
1447                 *(out++)= stack + sock->stack_index;
1448         }
1449 }
1450
1451 /* nodes are presorted, so exec is in order of list */
1452 void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
1453 {
1454         bNode *node;
1455         bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
1456         bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
1457         bNodeStack *stack;
1458         
1459         /* only when initialized */
1460         if((ntree->init & NTREE_EXEC_INIT)==0)
1461                 ntreeBeginExecTree(ntree);
1462                 
1463         if(thread)
1464                 stack= ntree->stack1;
1465         else
1466                 stack= ntree->stack;
1467         
1468         for(node= ntree->nodes.first; node; node= node->next) {
1469                 if(node->typeinfo->execfunc) {
1470                         node_get_stack(node, stack, nsin, nsout);
1471                         node->typeinfo->execfunc(callerdata, node, nsin, nsout);
1472                 }
1473                 else if(node->type==NODE_GROUP && node->id) {
1474                         node_get_stack(node, stack, nsin, nsout);
1475                         node_group_execute(stack, callerdata, node, nsin, nsout); 
1476                 }
1477         }
1478 }
1479