~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to source/blender/nodes/intern/node_common.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 
33
33
#include <string.h>
34
34
 
35
 
#include "DNA_action_types.h"
36
 
#include "DNA_anim_types.h"
37
35
#include "DNA_node_types.h"
38
36
 
39
37
#include "BLI_listbase.h"
42
40
 
43
41
#include "BLF_translation.h"
44
42
 
45
 
#include "BKE_action.h"
46
 
#include "BKE_animsys.h"
47
43
#include "BKE_global.h"
48
44
#include "BKE_library.h"
49
45
#include "BKE_main.h"
50
46
#include "BLI_math.h"
51
47
#include "BKE_node.h"
52
 
#include "BKE_utildefines.h"
53
48
 
54
49
#include "RNA_access.h"
55
50
#include "RNA_types.h"
57
52
#include "MEM_guardedalloc.h"
58
53
 
59
54
#include "node_common.h"
 
55
#include "node_util.h"
60
56
#include "node_exec.h"
61
57
#include "NOD_socket.h"
62
58
 
96
92
        sock->new_sock = NULL;
97
93
        
98
94
        /* group sockets are dynamically added */
99
 
        sock->flag |= SOCK_DYNAMIC;
 
95
        sock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED;
100
96
        
101
97
        sock->own_index = gsock->own_index;
102
98
        sock->groupsock = gsock;
111
107
        return sock;
112
108
}
113
109
 
114
 
bNode *node_group_make_from_selected(bNodeTree *ntree)
115
 
{
116
 
        bNodeLink *link, *linkn;
117
 
        bNode *node, *gnode, *nextn;
118
 
        bNodeTree *ngroup;
119
 
        bNodeSocket *gsock;
120
 
        ListBase anim_basepaths = {NULL, NULL};
121
 
        float min[2], max[2];
122
 
        int totnode=0;
123
 
        bNodeTemplate ntemp;
124
 
        
125
 
        INIT_MINMAX2(min, max);
126
 
        
127
 
        /* is there something to group? also do some clearing */
128
 
        for (node= ntree->nodes.first; node; node= node->next) {
129
 
                if (node->flag & NODE_SELECT) {
130
 
                        /* no groups in groups */
131
 
                        if (node->type==NODE_GROUP)
132
 
                                return NULL;
133
 
                        DO_MINMAX2( (&node->locx), min, max);
134
 
                        totnode++;
135
 
                }
136
 
                node->done= 0;
137
 
        }
138
 
        if (totnode==0) return NULL;
139
 
        
140
 
        /* check if all connections are OK, no unselected node has both
141
 
         * inputs and outputs to a selection */
142
 
        for (link= ntree->links.first; link; link= link->next) {
143
 
                if (link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT)
144
 
                        link->tonode->done |= 1;
145
 
                if (link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT)
146
 
                        link->fromnode->done |= 2;
147
 
        }       
148
 
        
149
 
        for (node= ntree->nodes.first; node; node= node->next) {
150
 
                if ((node->flag & NODE_SELECT)==0)
151
 
                        if (node->done==3)
152
 
                                break;
153
 
        }
154
 
        if (node) 
155
 
                return NULL;
156
 
        
157
 
        /* OK! new nodetree */
158
 
        ngroup= ntreeAddTree("NodeGroup", ntree->type, NODE_GROUP);
159
 
        
160
 
        /* move nodes over */
161
 
        for (node= ntree->nodes.first; node; node= nextn) {
162
 
                nextn= node->next;
163
 
                if (node->flag & NODE_SELECT) {
164
 
                        /* keep track of this node's RNA "base" path (the part of the pat identifying the node) 
165
 
                         * if the old nodetree has animation data which potentially covers this node
166
 
                         */
167
 
                        if (ntree->adt) {
168
 
                                PointerRNA ptr;
169
 
                                char *path;
170
 
                                
171
 
                                RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
172
 
                                path = RNA_path_from_ID_to_struct(&ptr);
173
 
                                
174
 
                                if (path)
175
 
                                        BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
176
 
                        }
177
 
                        
178
 
                        /* change node-collection membership */
179
 
                        BLI_remlink(&ntree->nodes, node);
180
 
                        BLI_addtail(&ngroup->nodes, node);
181
 
                        
182
 
                        node->locx-= 0.5f*(min[0]+max[0]);
183
 
                        node->locy-= 0.5f*(min[1]+max[1]);
184
 
                }
185
 
        }
186
 
 
187
 
        /* move animation data over */
188
 
        if (ntree->adt) {
189
 
                LinkData *ld, *ldn=NULL;
190
 
                
191
 
                BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);
192
 
                
193
 
                /* paths + their wrappers need to be freed */
194
 
                for (ld = anim_basepaths.first; ld; ld = ldn) {
195
 
                        ldn = ld->next;
196
 
                        
197
 
                        MEM_freeN(ld->data);
198
 
                        BLI_freelinkN(&anim_basepaths, ld);
199
 
                }
200
 
        }
201
 
        
202
 
        /* node groups don't use internal cached data */
203
 
        ntreeFreeCache(ngroup);
204
 
        
205
 
        /* make group node */
206
 
        ntemp.type = NODE_GROUP;
207
 
        ntemp.ngroup = ngroup;
208
 
        gnode= nodeAddNode(ntree, &ntemp);
209
 
        gnode->locx= 0.5f*(min[0]+max[0]);
210
 
        gnode->locy= 0.5f*(min[1]+max[1]);
211
 
        
212
 
        /* relink external sockets */
213
 
        for (link= ntree->links.first; link; link= linkn) {
214
 
                linkn= link->next;
215
 
                
216
 
                if (link->fromnode && link->tonode && (link->fromnode->flag & link->tonode->flag & NODE_SELECT)) {
217
 
                        BLI_remlink(&ntree->links, link);
218
 
                        BLI_addtail(&ngroup->links, link);
219
 
                }
220
 
                else if (link->tonode && (link->tonode->flag & NODE_SELECT)) {
221
 
                        gsock = node_group_expose_socket(ngroup, link->tosock, SOCK_IN);
222
 
                        link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock);
223
 
                        link->tosock = node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
224
 
                        link->tonode = gnode;
225
 
                }
226
 
                else if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
227
 
                        /* search for existing group node socket */
228
 
                        for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next)
229
 
                                if (gsock->link && gsock->link->fromsock==link->fromsock)
230
 
                                        break;
231
 
                        if (!gsock) {
232
 
                                gsock = node_group_expose_socket(ngroup, link->fromsock, SOCK_OUT);
233
 
                                gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock);
234
 
                                link->fromsock = node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
235
 
                        }
236
 
                        else
237
 
                                link->fromsock = node_group_find_output(gnode, gsock);
238
 
                        link->fromnode = gnode;
239
 
                }
240
 
        }
241
 
 
242
 
        /* update of the group tree */
243
 
        ngroup->update |= NTREE_UPDATE;
244
 
        ntreeUpdateTree(ngroup);
245
 
        /* update of the tree containing the group instance node */
246
 
        ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
247
 
        ntreeUpdateTree(ntree);
248
 
 
249
 
        return gnode;
250
 
}
251
 
 
252
 
/* returns 1 if its OK */
253
 
int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
254
 
{
255
 
        bNodeLink *link, *linkn;
256
 
        bNode *node, *nextn;
257
 
        bNodeTree *ngroup, *wgroup;
258
 
        ListBase anim_basepaths = {NULL, NULL};
259
 
        
260
 
        ngroup= (bNodeTree *)gnode->id;
261
 
        if (ngroup==NULL) return 0;
262
 
        
263
 
        /* clear new pointers, set in copytree */
264
 
        for (node= ntree->nodes.first; node; node= node->next)
265
 
                node->new_node= NULL;
266
 
        
267
 
        /* wgroup is a temporary copy of the NodeTree we're merging in
268
 
         *      - all of wgroup's nodes are transferred across to their new home
269
 
         *      - ngroup (i.e. the source NodeTree) is left unscathed
270
 
         */
271
 
        wgroup= ntreeCopyTree(ngroup);
272
 
        
273
 
        /* add the nodes into the ntree */
274
 
        for (node= wgroup->nodes.first; node; node= nextn) {
275
 
                nextn= node->next;
276
 
                
277
 
                /* keep track of this node's RNA "base" path (the part of the pat identifying the node) 
278
 
                 * if the old nodetree has animation data which potentially covers this node
279
 
                 */
280
 
                if (wgroup->adt) {
281
 
                        PointerRNA ptr;
282
 
                        char *path;
283
 
                        
284
 
                        RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
285
 
                        path = RNA_path_from_ID_to_struct(&ptr);
286
 
                        
287
 
                        if (path)
288
 
                                BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
289
 
                }
290
 
                
291
 
                /* migrate node */
292
 
                BLI_remlink(&wgroup->nodes, node);
293
 
                BLI_addtail(&ntree->nodes, node);
294
 
                
295
 
                node->locx+= gnode->locx;
296
 
                node->locy+= gnode->locy;
297
 
                
298
 
                node->flag |= NODE_SELECT;
299
 
        }
300
 
        
301
 
        /* restore external links to and from the gnode */
302
 
        for (link= ntree->links.first; link; link= link->next) {
303
 
                if (link->fromnode==gnode) {
304
 
                        if (link->fromsock->groupsock) {
305
 
                                bNodeSocket *gsock= link->fromsock->groupsock;
306
 
                                if (gsock->link) {
307
 
                                        if (gsock->link->fromnode) {
308
 
                                                /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
309
 
                                                link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
310
 
                                                link->fromsock = gsock->link->fromsock->new_sock;
311
 
                                        }
312
 
                                        else {
313
 
                                                /* group output directly maps to group input */
314
 
                                                bNodeSocket *insock= node_group_find_input(gnode, gsock->link->fromsock);
315
 
                                                if (insock->link) {
316
 
                                                        link->fromnode = insock->link->fromnode;
317
 
                                                        link->fromsock = insock->link->fromsock;
318
 
                                                }
319
 
                                        }
320
 
                                }
321
 
                                else {
322
 
                                        /* copy the default input value from the group socket default to the external socket */
323
 
                                        node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, gsock->type, gsock->default_value);
324
 
                                }
325
 
                        }
326
 
                }
327
 
        }
328
 
        /* remove internal output links, these are not used anymore */
329
 
        for (link=wgroup->links.first; link; link= linkn) {
330
 
                linkn = link->next;
331
 
                if (!link->tonode)
332
 
                        nodeRemLink(wgroup, link);
333
 
        }
334
 
        /* restore links from internal nodes */
335
 
        for (link= wgroup->links.first; link; link= link->next) {
336
 
                /* indicates link to group input */
337
 
                if (!link->fromnode) {
338
 
                        /* NB: can't use find_group_node_input here,
339
 
                         * because gnode sockets still point to the old tree!
340
 
                         */
341
 
                        bNodeSocket *insock;
342
 
                        for (insock= gnode->inputs.first; insock; insock= insock->next)
343
 
                                if (insock->groupsock->new_sock == link->fromsock)
344
 
                                        break;
345
 
                        if (insock->link) {
346
 
                                link->fromnode = insock->link->fromnode;
347
 
                                link->fromsock = insock->link->fromsock;
348
 
                        }
349
 
                        else {
350
 
                                /* copy the default input value from the group node socket default to the internal socket */
351
 
                                node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, insock->type, insock->default_value);
352
 
                                nodeRemLink(wgroup, link);
353
 
                        }
354
 
                }
355
 
        }
356
 
        
357
 
        /* add internal links to the ntree */
358
 
        for (link= wgroup->links.first; link; link= linkn) {
359
 
                linkn= link->next;
360
 
                BLI_remlink(&wgroup->links, link);
361
 
                BLI_addtail(&ntree->links, link);
362
 
        }
363
 
        
364
 
        /* and copy across the animation,
365
 
         * note that the animation data's action can be NULL here */
366
 
        if (wgroup->adt) {
367
 
                LinkData *ld, *ldn=NULL;
368
 
                bAction *waction;
369
 
                
370
 
                /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
371
 
                waction = wgroup->adt->action = copy_action(wgroup->adt->action);
372
 
                
373
 
                /* now perform the moving */
374
 
                BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
375
 
                
376
 
                /* paths + their wrappers need to be freed */
377
 
                for (ld = anim_basepaths.first; ld; ld = ldn) {
378
 
                        ldn = ld->next;
379
 
                        
380
 
                        MEM_freeN(ld->data);
381
 
                        BLI_freelinkN(&anim_basepaths, ld);
382
 
                }
383
 
                
384
 
                /* free temp action too */
385
 
                if (waction) {
386
 
                        free_libblock(&G.main->action, waction);
387
 
                }
388
 
        }
389
 
        
390
 
        /* delete the group instance. this also removes old input links! */
391
 
        nodeFreeNode(ntree, gnode);
392
 
 
393
 
        /* free the group tree (takes care of user count) */
394
 
        free_libblock(&G.main->nodetree, wgroup);
395
 
        
396
 
        ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
397
 
        ntreeUpdateTree(ntree);
398
 
        
399
 
        return 1;
400
 
}
401
 
 
402
110
bNodeSocket *node_group_add_socket(bNodeTree *ngroup, const char *name, int type, int in_out)
403
111
{
404
112
        bNodeSocketType *stype = ntreeGetSocketType(type);
407
115
        BLI_strncpy(gsock->name, name, sizeof(gsock->name));
408
116
        gsock->type = type;
409
117
        /* group sockets are dynamically added */
410
 
        gsock->flag |= SOCK_DYNAMIC;
 
118
        gsock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED;
411
119
 
412
120
        gsock->next = gsock->prev = NULL;
413
121
        gsock->new_sock = NULL;
489
197
/* groups display their internal tree name as label */
490
198
const char *node_group_label(bNode *node)
491
199
{
492
 
        return (node->id)? node->id->name+2: IFACE_("Missing Datablock");
 
200
        return (node->id)? node->id->name + 2: IFACE_("Missing Datablock");
493
201
}
494
202
 
495
203
int node_group_valid(bNodeTree *ntree, bNodeTemplate *ntemp)
515
223
{
516
224
        bNodeTemplate ntemp;
517
225
        ntemp.type = NODE_GROUP;
518
 
        ntemp.ngroup = (bNodeTree*)node->id;
 
226
        ntemp.ngroup = (bNodeTree *)node->id;
519
227
        return ntemp;
520
228
}
521
229
 
522
230
void node_group_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
523
231
{
524
 
        node->id = (ID*)ntemp->ngroup;
 
232
        node->id = (ID *)ntemp->ngroup;
525
233
        
526
234
        /* NB: group socket input/output roles are inverted internally!
527
235
         * Group "inputs" work as outputs in links and vice versa.
551
259
                sock->groupsock = gsock;
552
260
                
553
261
                BLI_strncpy(sock->name, gsock->name, sizeof(sock->name));
554
 
                if(gsock->type != sock->type)
 
262
                if (gsock->type != sock->type)
555
263
                        nodeSocketSetType(sock, gsock->type);
556
264
                
557
265
                /* XXX hack: group socket input/output roles are inverted internally,
597
305
{
598
306
        /* check inputs and outputs, and remove or insert them */
599
307
        if (node->id==id) {
600
 
                bNodeTree *ngroup= (bNodeTree*)node->id;
 
308
                bNodeTree *ngroup= (bNodeTree *)node->id;
601
309
                group_verify_socket_list(ntree, node, &node->inputs, SOCK_IN, &ngroup->inputs);
602
310
                group_verify_socket_list(ntree, node, &node->outputs, SOCK_OUT, &ngroup->outputs);
603
311
        }
606
314
struct bNodeTree *node_group_edit_get(bNode *node)
607
315
{
608
316
        if (node->flag & NODE_GROUP_EDIT)
609
 
                return (bNodeTree*)node->id;
 
317
                return (bNodeTree *)node->id;
610
318
        else
611
319
                return NULL;
612
320
}
614
322
struct bNodeTree *node_group_edit_set(bNode *node, int edit)
615
323
{
616
324
        if (edit) {
617
 
                bNodeTree *ngroup= (bNodeTree*)node->id;
 
325
                bNodeTree *ngroup= (bNodeTree *)node->id;
618
326
                if (ngroup) {
619
327
                        if (ngroup->id.lib)
620
328
                                ntreeMakeLocal(ngroup);
631
339
 
632
340
void node_group_edit_clear(bNode *node)
633
341
{
634
 
        bNodeTree *ngroup= (bNodeTree*)node->id;
 
342
        bNodeTree *ngroup= (bNodeTree *)node->id;
635
343
        bNode *inode;
636
344
        
637
345
        node->flag &= ~NODE_GROUP_EDIT;
641
349
                        nodeGroupEditClear(inode);
642
350
}
643
351
 
644
 
void node_group_link(bNodeTree *ntree, bNodeSocket *sock, int in_out)
 
352
static void UNUSED_FUNCTION(node_group_link)(bNodeTree *ntree, bNodeSocket *sock, int in_out)
645
353
{
646
354
        node_group_expose_socket(ntree, sock, in_out);
647
355
}
648
356
 
649
 
/**** For Loop ****/
650
 
 
651
 
/* Essentially a group node with slightly different behavior.
652
 
 * The internal tree is executed several times, with each output being re-used
653
 
 * as an input in the next iteration. For this purpose, input and output socket
654
 
 * lists are kept identical!
655
 
 */
656
 
 
657
 
bNodeTemplate node_forloop_template(bNode *node)
658
 
{
659
 
        bNodeTemplate ntemp;
660
 
        ntemp.type = NODE_FORLOOP;
661
 
        ntemp.ngroup = (bNodeTree*)node->id;
662
 
        return ntemp;
663
 
}
664
 
 
665
 
void node_forloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
666
 
{
667
 
        bNodeSocket *sock;
668
 
        
669
 
        node->id = (ID*)ntemp->ngroup;
670
 
        
671
 
        sock = nodeAddSocket(ntree, node, SOCK_IN, "Iterations", SOCK_FLOAT);
672
 
        node_socket_set_default_value_float(sock->default_value, PROP_UNSIGNED, 1, 0, 10000);
673
 
        
674
 
        /* NB: group socket input/output roles are inverted internally!
675
 
         * Group "inputs" work as outputs in links and vice versa.
676
 
         */
677
 
        if (ntemp->ngroup) {
678
 
                bNodeSocket *gsock;
679
 
                for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next)
680
 
                        node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock);
681
 
                for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next)
682
 
                        node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock);
683
 
        }
684
 
}
685
 
 
686
 
void node_forloop_init_tree(bNodeTree *ntree)
687
 
{
688
 
        bNodeSocket *sock;
689
 
        sock = node_group_add_socket(ntree, "Iteration", SOCK_FLOAT, SOCK_IN);
690
 
        sock->flag |= SOCK_INTERNAL;
691
 
}
692
 
 
693
 
static void loop_sync(bNodeTree *ntree, int sync_in_out)
694
 
{
695
 
        bNodeSocket *sock, *sync, *nsync, *mirror;
696
 
        ListBase *sync_lb;
697
 
        
698
 
        if (sync_in_out==SOCK_IN) {
699
 
                sock = ntree->outputs.first;
700
 
                
701
 
                sync = ntree->inputs.first;
702
 
                sync_lb = &ntree->inputs;
703
 
        }
704
 
        else {
705
 
                sock = ntree->inputs.first;
706
 
                
707
 
                sync = ntree->outputs.first;
708
 
                sync_lb = &ntree->outputs;
709
 
        }
710
 
        
711
 
        /* NB: the sock->storage pointer is used here directly to store the own_index int
712
 
         * out the mirrored socket counterpart!
713
 
         */
714
 
        
715
 
        while (sock) {
716
 
                /* skip static and internal sockets on the sync side (preserves socket order!) */
717
 
                while (sync && ((sync->flag & SOCK_INTERNAL) || !(sync->flag & SOCK_DYNAMIC)))
718
 
                        sync = sync->next;
719
 
                
720
 
                if (sync && !(sync->flag & SOCK_INTERNAL) && (sync->flag & SOCK_DYNAMIC)) {
721
 
                        if (sock->storage==NULL) {
722
 
                                /* if mirror index is 0, the sockets is newly added and a new mirror must be created. */
723
 
                                mirror = node_group_expose_socket(ntree, sock, sync_in_out);
724
 
                                /* store the mirror index */
725
 
                                sock->storage = SET_INT_IN_POINTER(mirror->own_index);
726
 
                                mirror->storage = SET_INT_IN_POINTER(sock->own_index);
727
 
                                /* move mirror to the right place */
728
 
                                BLI_remlink(sync_lb, mirror);
729
 
                                if (sync)
730
 
                                        BLI_insertlinkbefore(sync_lb, sync, mirror);
731
 
                                else
732
 
                                        BLI_addtail(sync_lb, mirror);
733
 
                        }
734
 
                        else {
735
 
                                /* look up the mirror socket */
736
 
                                for (mirror=sync; mirror; mirror=mirror->next)
737
 
                                        if (mirror->own_index == GET_INT_FROM_POINTER(sock->storage))
738
 
                                                break;
739
 
                                /* make sure the name is the same (only for identification by user, no deeper meaning) */
740
 
                                BLI_strncpy(mirror->name, sock->name, sizeof(mirror->name));
741
 
                                /* fix the socket order if necessary */
742
 
                                if (mirror != sync) {
743
 
                                        BLI_remlink(sync_lb, mirror);
744
 
                                        BLI_insertlinkbefore(sync_lb, sync, mirror);
745
 
                                }
746
 
                                else
747
 
                                        sync = sync->next;
748
 
                        }
749
 
                }
750
 
                
751
 
                sock = sock->next;
752
 
        }
753
 
        
754
 
        /* remaining sockets in sync_lb are leftovers from deleted sockets, remove them */
755
 
        while (sync) {
756
 
                nsync = sync->next;
757
 
                if (!(sync->flag & SOCK_INTERNAL) && (sync->flag & SOCK_DYNAMIC))
758
 
                        node_group_remove_socket(ntree, sync, sync_in_out);
759
 
                sync = nsync;
760
 
        }
761
 
}
762
 
 
763
 
void node_loop_update_tree(bNodeTree *ngroup)
764
 
{
765
 
        /* make sure inputs & outputs are identical */
766
 
        if (ngroup->update & NTREE_UPDATE_GROUP_IN)
767
 
                loop_sync(ngroup, SOCK_OUT);
768
 
        if (ngroup->update & NTREE_UPDATE_GROUP_OUT)
769
 
                loop_sync(ngroup, SOCK_IN);
770
 
}
771
 
 
772
 
void node_whileloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
773
 
{
774
 
        bNodeSocket *sock;
775
 
        
776
 
        node->id = (ID*)ntemp->ngroup;
777
 
        
778
 
        sock = nodeAddSocket(ntree, node, SOCK_IN, "Condition", SOCK_FLOAT);
779
 
        node_socket_set_default_value_float(sock->default_value, PROP_NONE, 1, 0, 1);
780
 
        
781
 
        /* max iterations */
782
 
        node->custom1 = 10000;
783
 
        
784
 
        /* NB: group socket input/output roles are inverted internally!
785
 
         * Group "inputs" work as outputs in links and vice versa.
786
 
         */
787
 
        if (ntemp->ngroup) {
788
 
                bNodeSocket *gsock;
789
 
                for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next)
790
 
                        node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock);
791
 
                for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next)
792
 
                        node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock);
793
 
        }
794
 
}
795
 
 
796
 
void node_whileloop_init_tree(bNodeTree *ntree)
797
 
{
798
 
        bNodeSocket *sock;
799
 
        sock = node_group_add_socket(ntree, "Condition", SOCK_FLOAT, SOCK_OUT);
800
 
        sock->flag |= SOCK_INTERNAL;
801
 
}
802
 
 
803
 
bNodeTemplate node_whileloop_template(bNode *node)
804
 
{
805
 
        bNodeTemplate ntemp;
806
 
        ntemp.type = NODE_WHILELOOP;
807
 
        ntemp.ngroup = (bNodeTree*)node->id;
808
 
        return ntemp;
809
 
}
810
 
 
811
357
/**** FRAME ****/
812
358
 
 
359
static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
 
360
{
 
361
        NodeFrame *data = (NodeFrame *)MEM_callocN(sizeof(NodeFrame), "frame node storage");
 
362
        node->storage = data;
 
363
        
 
364
        data->flag |= NODE_FRAME_SHRINK;
 
365
        
 
366
        data->label_size = 20;
 
367
}
 
368
 
813
369
void register_node_type_frame(bNodeTreeType *ttype)
814
370
{
815
371
        /* frame type is used for all tree types, needs dynamic allocation */
816
372
        bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
817
373
 
818
 
        node_type_base(ttype, ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND);
 
374
        node_type_base(ttype, ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND|NODE_OPTIONS);
 
375
        node_type_init(ntype, node_frame_init);
 
376
        node_type_storage(ntype, "NodeFrame", node_free_standard_storage, node_copy_standard_storage);
819
377
        node_type_size(ntype, 150, 100, 0);
820
378
        node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
821
379
        
822
380
        ntype->needs_free = 1;
823
381
        nodeRegisterType(ttype, ntype);
824
382
}
 
383
 
 
384
 
 
385
/* **************** REROUTE ******************** */
 
386
 
 
387
/* simple, only a single input and output here */
 
388
static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node)
 
389
{
 
390
        bNodeLink *link;
 
391
 
 
392
        /* Security check! */
 
393
        if (!ntree)
 
394
                return;
 
395
 
 
396
        link = MEM_callocN(sizeof(bNodeLink), "internal node link");
 
397
        link->fromnode = node;
 
398
        link->fromsock = node->inputs.first;
 
399
        link->tonode = node;
 
400
        link->tosock = node->outputs.first;
 
401
        /* internal link is always valid */
 
402
        link->flag |= NODE_LINK_VALID;
 
403
        BLI_addtail(&node->internal_links, link);
 
404
}
 
405
 
 
406
static void node_reroute_init(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp))
 
407
{
 
408
        /* Note: Cannot use socket templates for this, since it would reset the socket type
 
409
         * on each file read via the template verification procedure.
 
410
         */
 
411
        nodeAddSocket(ntree, node, SOCK_IN, "Input", SOCK_RGBA);
 
412
        nodeAddSocket(ntree, node, SOCK_OUT, "Output", SOCK_RGBA);
 
413
}
 
414
 
 
415
void register_node_type_reroute(bNodeTreeType *ttype)
 
416
{
 
417
        /* frame type is used for all tree types, needs dynamic allocation */
 
418
        bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
 
419
        
 
420
        node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
 
421
        node_type_init(ntype, node_reroute_init);
 
422
        node_type_internal_links(ntype, node_reroute_update_internal_links);
 
423
        
 
424
        ntype->needs_free = 1;
 
425
        nodeRegisterType(ttype, ntype);
 
426
}
 
427
 
 
428
static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
 
429
{
 
430
        bNodeSocket *input = node->inputs.first;
 
431
        bNodeSocket *output = node->outputs.first;
 
432
        int type = SOCK_FLOAT;
 
433
        bNodeLink *link;
 
434
        
 
435
        /* XXX it would be a little bit more efficient to restrict actual updates
 
436
         * to rerout nodes connected to an updated node, but there's no reliable flag
 
437
         * to indicate updated nodes (node->update is not set on linking).
 
438
         */
 
439
        
 
440
        node->done = 1;
 
441
        
 
442
        /* recursive update */
 
443
        for (link = ntree->links.first; link; link = link->next)
 
444
        {
 
445
                bNode *fromnode = link->fromnode;
 
446
                bNode *tonode = link->tonode;
 
447
                if (!tonode || !fromnode)
 
448
                        continue;
 
449
                
 
450
                if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done)
 
451
                        node_reroute_inherit_type_recursive(ntree, fromnode);
 
452
                
 
453
                if (fromnode == node && tonode->type == NODE_REROUTE && !tonode->done)
 
454
                        node_reroute_inherit_type_recursive(ntree, tonode);
 
455
        }
 
456
        
 
457
        /* determine socket type from unambiguous input/output connection if possible */
 
458
        if (input->limit==1 && input->link)
 
459
                type = input->link->fromsock->type;
 
460
        else if (output->limit==1 && output->link)
 
461
                type = output->link->tosock->type;
 
462
        
 
463
        /* arbitrary, could also test output->type, both are the same */
 
464
        if (input->type != type) {
 
465
                /* same type for input/output */
 
466
                nodeSocketSetType(input, type);
 
467
                nodeSocketSetType(output, type);
 
468
        }
 
469
}
 
470
 
 
471
/* Global update function for Reroute node types.
 
472
 * This depends on connected nodes, so must be done as a tree-wide update.
 
473
 */
 
474
void ntree_update_reroute_nodes(bNodeTree *ntree)
 
475
{
 
476
        bNode *node;
 
477
        
 
478
        /* clear tags */
 
479
        for (node = ntree->nodes.first; node; node = node->next)
 
480
                node->done = 0;
 
481
        
 
482
        for (node = ntree->nodes.first; node; node = node->next)
 
483
                if (node->type == NODE_REROUTE && !node->done)
 
484
                        node_reroute_inherit_type_recursive(ntree, node);
 
485
}
 
486
 
 
487
void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree)
 
488
{
 
489
        ID *id = (ID *)calldata;
 
490
        bNode *node;
 
491
 
 
492
        for (node = ntree->nodes.first; node; node = node->next) {
 
493
                if (node->id == id) {
 
494
                        node->id = NULL;
 
495
                }
 
496
        }
 
497
}