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

« back to all changes in this revision

Viewing changes to source/blender/editors/space_node/node_group.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:
 
1
/*
 
2
 * ***** BEGIN GPL LICENSE BLOCK *****
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License
 
6
 * as published by the Free Software Foundation; either version 2
 
7
 * of the License, or (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software Foundation,
 
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 *
 
18
 * The Original Code is Copyright (C) 2005 Blender Foundation.
 
19
 * All rights reserved.
 
20
 *
 
21
 * The Original Code is: all of this file.
 
22
 *
 
23
 * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Nathan Letwory
 
24
 *
 
25
 * ***** END GPL LICENSE BLOCK *****
 
26
 */
 
27
 
 
28
/** \file blender/editors/space_node/node_group.c
 
29
 *  \ingroup spnode
 
30
 */
 
31
 
 
32
#include <stdlib.h>
 
33
 
 
34
#include "MEM_guardedalloc.h"
 
35
 
 
36
#include "DNA_node_types.h"
 
37
#include "DNA_object_types.h"
 
38
#include "DNA_anim_types.h"
 
39
 
 
40
#include "BLI_listbase.h"
 
41
#include "BLI_string.h"
 
42
#include "BLI_rect.h"
 
43
#include "BLI_math.h"
 
44
 
 
45
#include "BKE_action.h"
 
46
#include "BKE_animsys.h"
 
47
#include "BKE_context.h"
 
48
#include "BKE_global.h"
 
49
#include "BKE_library.h"
 
50
#include "BKE_main.h"
 
51
#include "BKE_report.h"
 
52
 
 
53
#include "ED_node.h"  /* own include */
 
54
#include "ED_screen.h"
 
55
#include "ED_render.h"
 
56
 
 
57
#include "RNA_access.h"
 
58
#include "RNA_define.h"
 
59
#include "RNA_enum_types.h"
 
60
 
 
61
#include "WM_api.h"
 
62
#include "WM_types.h"
 
63
 
 
64
#include "UI_resources.h"
 
65
 
 
66
#include "node_intern.h"  /* own include */
 
67
#include "NOD_socket.h"
 
68
 
 
69
static EnumPropertyItem socket_in_out_items[] = {
 
70
        { SOCK_IN, "SOCK_IN", 0, "Input", "" },
 
71
        { SOCK_OUT, "SOCK_OUT", 0, "Output", "" },
 
72
        { 0, NULL, 0, NULL, NULL },
 
73
};
 
74
 
 
75
/* ***************** Edit Group operator ************* */
 
76
 
 
77
void snode_make_group_editable(SpaceNode *snode, bNode *gnode)
 
78
{
 
79
        bNode *node;
 
80
 
 
81
        /* make sure nothing has group editing on */
 
82
        for (node = snode->nodetree->nodes.first; node; node = node->next) {
 
83
                nodeGroupEditClear(node);
 
84
 
 
85
                /* while we're here, clear texture active */
 
86
                if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
 
87
                        /* this is not 100% sure to be reliable, see comment on the flag */
 
88
                        node->flag &= ~NODE_ACTIVE_TEXTURE;
 
89
                }
 
90
        }
 
91
 
 
92
        if (gnode == NULL) {
 
93
                /* with NULL argument we do a toggle */
 
94
                if (snode->edittree == snode->nodetree)
 
95
                        gnode = nodeGetActive(snode->nodetree);
 
96
        }
 
97
 
 
98
        if (gnode) {
 
99
                snode->edittree = nodeGroupEditSet(gnode, 1);
 
100
 
 
101
                /* deselect all other nodes, so we can also do grabbing of entire subtree */
 
102
                for (node = snode->nodetree->nodes.first; node; node = node->next) {
 
103
                        node_deselect(node);
 
104
 
 
105
                        if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
 
106
                                /* this is not 100% sure to be reliable, see comment on the flag */
 
107
                                node->flag &= ~NODE_ACTIVE_TEXTURE;
 
108
                        }
 
109
                }
 
110
                node_select(gnode);
 
111
        }
 
112
        else
 
113
                snode->edittree = snode->nodetree;
 
114
}
 
115
 
 
116
static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op))
 
117
{
 
118
        SpaceNode *snode = CTX_wm_space_node(C);
 
119
 
 
120
        ED_preview_kill_jobs(C);
 
121
 
 
122
        if (snode->nodetree == snode->edittree) {
 
123
                bNode *gnode = nodeGetActive(snode->edittree);
 
124
                snode_make_group_editable(snode, gnode);
 
125
        }
 
126
        else
 
127
                snode_make_group_editable(snode, NULL);
 
128
 
 
129
        WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
 
130
 
 
131
        return OPERATOR_FINISHED;
 
132
}
 
133
 
 
134
static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
 
135
{
 
136
        SpaceNode *snode = CTX_wm_space_node(C);
 
137
        bNode *gnode;
 
138
 
 
139
        /* XXX callback? */
 
140
        if (snode->nodetree == snode->edittree) {
 
141
                gnode = nodeGetActive(snode->edittree);
 
142
                if (gnode && gnode->id && GS(gnode->id->name) == ID_NT && gnode->id->lib) {
 
143
                        uiPupMenuOkee(C, op->type->idname, "Make group local?");
 
144
                        return OPERATOR_CANCELLED;
 
145
                }
 
146
        }
 
147
 
 
148
        return node_group_edit_exec(C, op);
 
149
}
 
150
 
 
151
void NODE_OT_group_edit(wmOperatorType *ot)
 
152
{
 
153
        /* identifiers */
 
154
        ot->name = "Edit Group";
 
155
        ot->description = "Edit node group";
 
156
        ot->idname = "NODE_OT_group_edit";
 
157
 
 
158
        /* api callbacks */
 
159
        ot->invoke = node_group_edit_invoke;
 
160
        ot->exec = node_group_edit_exec;
 
161
        ot->poll = ED_operator_node_active;
 
162
 
 
163
        /* flags */
 
164
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
165
}
 
166
 
 
167
/* ***************** Add Group Socket operator ************* */
 
168
 
 
169
static int node_group_socket_add_exec(bContext *C, wmOperator *op)
 
170
{
 
171
        SpaceNode *snode = CTX_wm_space_node(C);
 
172
        int in_out = -1;
 
173
        char name[MAX_NAME] = "";
 
174
        int type = SOCK_FLOAT;
 
175
        bNodeTree *ngroup = snode->edittree;
 
176
        /* bNodeSocket *sock; */ /* UNUSED */
 
177
 
 
178
        ED_preview_kill_jobs(C);
 
179
 
 
180
        if (RNA_struct_property_is_set(op->ptr, "name"))
 
181
                RNA_string_get(op->ptr, "name", name);
 
182
 
 
183
        if (RNA_struct_property_is_set(op->ptr, "type"))
 
184
                type = RNA_enum_get(op->ptr, "type");
 
185
 
 
186
        if (RNA_struct_property_is_set(op->ptr, "in_out"))
 
187
                in_out = RNA_enum_get(op->ptr, "in_out");
 
188
        else
 
189
                return OPERATOR_CANCELLED;
 
190
 
 
191
        /* using placeholder subtype first */
 
192
        /* sock = */ /* UNUSED */ node_group_add_socket(ngroup, name, type, in_out);
 
193
 
 
194
        ntreeUpdateTree(ngroup);
 
195
 
 
196
        snode_notify(C, snode);
 
197
 
 
198
        return OPERATOR_FINISHED;
 
199
}
 
200
 
 
201
void NODE_OT_group_socket_add(wmOperatorType *ot)
 
202
{
 
203
        /* identifiers */
 
204
        ot->name = "Add Group Socket";
 
205
        ot->description = "Add node group socket";
 
206
        ot->idname = "NODE_OT_group_socket_add";
 
207
 
 
208
        /* api callbacks */
 
209
        ot->exec = node_group_socket_add_exec;
 
210
        ot->poll = ED_operator_node_active;
 
211
 
 
212
        /* flags */
 
213
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
214
 
 
215
        RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
 
216
        RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Group socket name");
 
217
        RNA_def_enum(ot->srna, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of the group socket");
 
218
}
 
219
 
 
220
/* ***************** Remove Group Socket operator ************* */
 
221
 
 
222
static int node_group_socket_remove_exec(bContext *C, wmOperator *op)
 
223
{
 
224
        SpaceNode *snode = CTX_wm_space_node(C);
 
225
        int index = -1;
 
226
        int in_out = -1;
 
227
        bNodeTree *ngroup = snode->edittree;
 
228
        bNodeSocket *sock;
 
229
 
 
230
        ED_preview_kill_jobs(C);
 
231
 
 
232
        if (RNA_struct_property_is_set(op->ptr, "index"))
 
233
                index = RNA_int_get(op->ptr, "index");
 
234
        else
 
235
                return OPERATOR_CANCELLED;
 
236
 
 
237
        if (RNA_struct_property_is_set(op->ptr, "in_out"))
 
238
                in_out = RNA_enum_get(op->ptr, "in_out");
 
239
        else
 
240
                return OPERATOR_CANCELLED;
 
241
 
 
242
        sock = (bNodeSocket *)BLI_findlink(in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs, index);
 
243
        if (sock) {
 
244
                node_group_remove_socket(ngroup, sock, in_out);
 
245
                ntreeUpdateTree(ngroup);
 
246
 
 
247
                snode_notify(C, snode);
 
248
        }
 
249
 
 
250
        return OPERATOR_FINISHED;
 
251
}
 
252
 
 
253
void NODE_OT_group_socket_remove(wmOperatorType *ot)
 
254
{
 
255
        /* identifiers */
 
256
        ot->name = "Remove Group Socket";
 
257
        ot->description = "Remove a node group socket";
 
258
        ot->idname = "NODE_OT_group_socket_remove";
 
259
 
 
260
        /* api callbacks */
 
261
        ot->exec = node_group_socket_remove_exec;
 
262
        ot->poll = ED_operator_node_active;
 
263
 
 
264
        /* flags */
 
265
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
266
 
 
267
        RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
 
268
        RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
 
269
}
 
270
 
 
271
/* ***************** Move Group Socket Up operator ************* */
 
272
 
 
273
static int node_group_socket_move_up_exec(bContext *C, wmOperator *op)
 
274
{
 
275
        SpaceNode *snode = CTX_wm_space_node(C);
 
276
        int index = -1;
 
277
        int in_out = -1;
 
278
        bNodeTree *ngroup = snode->edittree;
 
279
        bNodeSocket *sock, *prev;
 
280
 
 
281
        ED_preview_kill_jobs(C);
 
282
 
 
283
        if (RNA_struct_property_is_set(op->ptr, "index"))
 
284
                index = RNA_int_get(op->ptr, "index");
 
285
        else
 
286
                return OPERATOR_CANCELLED;
 
287
 
 
288
        if (RNA_struct_property_is_set(op->ptr, "in_out"))
 
289
                in_out = RNA_enum_get(op->ptr, "in_out");
 
290
        else
 
291
                return OPERATOR_CANCELLED;
 
292
 
 
293
        /* swap */
 
294
        if (in_out == SOCK_IN) {
 
295
                sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
 
296
                prev = sock->prev;
 
297
                /* can't move up the first socket */
 
298
                if (!prev)
 
299
                        return OPERATOR_CANCELLED;
 
300
                BLI_remlink(&ngroup->inputs, sock);
 
301
                BLI_insertlinkbefore(&ngroup->inputs, prev, sock);
 
302
 
 
303
                ngroup->update |= NTREE_UPDATE_GROUP_IN;
 
304
        }
 
305
        else if (in_out == SOCK_OUT) {
 
306
                sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
 
307
                prev = sock->prev;
 
308
                /* can't move up the first socket */
 
309
                if (!prev)
 
310
                        return OPERATOR_CANCELLED;
 
311
                BLI_remlink(&ngroup->outputs, sock);
 
312
                BLI_insertlinkbefore(&ngroup->outputs, prev, sock);
 
313
 
 
314
                ngroup->update |= NTREE_UPDATE_GROUP_OUT;
 
315
        }
 
316
        ntreeUpdateTree(ngroup);
 
317
 
 
318
        snode_notify(C, snode);
 
319
 
 
320
        return OPERATOR_FINISHED;
 
321
}
 
322
 
 
323
void NODE_OT_group_socket_move_up(wmOperatorType *ot)
 
324
{
 
325
        /* identifiers */
 
326
        ot->name = "Move Group Socket Up";
 
327
        ot->description = "Move up node group socket";
 
328
        ot->idname = "NODE_OT_group_socket_move_up";
 
329
 
 
330
        /* api callbacks */
 
331
        ot->exec = node_group_socket_move_up_exec;
 
332
        ot->poll = ED_operator_node_active;
 
333
 
 
334
        /* flags */
 
335
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
336
 
 
337
        RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
 
338
        RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
 
339
}
 
340
 
 
341
/* ***************** Move Group Socket Up operator ************* */
 
342
 
 
343
static int node_group_socket_move_down_exec(bContext *C, wmOperator *op)
 
344
{
 
345
        SpaceNode *snode = CTX_wm_space_node(C);
 
346
        int index = -1;
 
347
        int in_out = -1;
 
348
        bNodeTree *ngroup = snode->edittree;
 
349
        bNodeSocket *sock, *next;
 
350
 
 
351
        ED_preview_kill_jobs(C);
 
352
 
 
353
        if (RNA_struct_property_is_set(op->ptr, "index"))
 
354
                index = RNA_int_get(op->ptr, "index");
 
355
        else
 
356
                return OPERATOR_CANCELLED;
 
357
 
 
358
        if (RNA_struct_property_is_set(op->ptr, "in_out"))
 
359
                in_out = RNA_enum_get(op->ptr, "in_out");
 
360
        else
 
361
                return OPERATOR_CANCELLED;
 
362
 
 
363
        /* swap */
 
364
        if (in_out == SOCK_IN) {
 
365
                sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
 
366
                next = sock->next;
 
367
                /* can't move down the last socket */
 
368
                if (!next)
 
369
                        return OPERATOR_CANCELLED;
 
370
                BLI_remlink(&ngroup->inputs, sock);
 
371
                BLI_insertlinkafter(&ngroup->inputs, next, sock);
 
372
 
 
373
                ngroup->update |= NTREE_UPDATE_GROUP_IN;
 
374
        }
 
375
        else if (in_out == SOCK_OUT) {
 
376
                sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
 
377
                next = sock->next;
 
378
                /* can't move down the last socket */
 
379
                if (!next)
 
380
                        return OPERATOR_CANCELLED;
 
381
                BLI_remlink(&ngroup->outputs, sock);
 
382
                BLI_insertlinkafter(&ngroup->outputs, next, sock);
 
383
 
 
384
                ngroup->update |= NTREE_UPDATE_GROUP_OUT;
 
385
        }
 
386
        ntreeUpdateTree(ngroup);
 
387
 
 
388
        snode_notify(C, snode);
 
389
 
 
390
        return OPERATOR_FINISHED;
 
391
}
 
392
 
 
393
void NODE_OT_group_socket_move_down(wmOperatorType *ot)
 
394
{
 
395
        /* identifiers */
 
396
        ot->name = "Move Group Socket Down";
 
397
        ot->description = "Move down node group socket";
 
398
        ot->idname = "NODE_OT_group_socket_move_down";
 
399
 
 
400
        /* api callbacks */
 
401
        ot->exec = node_group_socket_move_down_exec;
 
402
        ot->poll = ED_operator_node_active;
 
403
 
 
404
        /* flags */
 
405
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
406
 
 
407
        RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
 
408
        RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
 
409
}
 
410
 
 
411
/* ******************** Ungroup operator ********************** */
 
412
 
 
413
/* returns 1 if its OK */
 
414
static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
 
415
{
 
416
        bNodeLink *link, *linkn;
 
417
        bNode *node, *nextn;
 
418
        bNodeTree *ngroup, *wgroup;
 
419
        ListBase anim_basepaths = {NULL, NULL};
 
420
 
 
421
        ngroup = (bNodeTree *)gnode->id;
 
422
        if (ngroup == NULL) return 0;
 
423
 
 
424
        /* clear new pointers, set in copytree */
 
425
        for (node = ntree->nodes.first; node; node = node->next)
 
426
                node->new_node = NULL;
 
427
 
 
428
        /* wgroup is a temporary copy of the NodeTree we're merging in
 
429
         * - all of wgroup's nodes are transferred across to their new home
 
430
         * - ngroup (i.e. the source NodeTree) is left unscathed
 
431
         * - temp copy. don't change ID usercount
 
432
         */
 
433
        wgroup = ntreeCopyTree_ex(ngroup, FALSE);
 
434
 
 
435
        /* add the nodes into the ntree */
 
436
        for (node = wgroup->nodes.first; node; node = nextn) {
 
437
                nextn = node->next;
 
438
 
 
439
                /* keep track of this node's RNA "base" path (the part of the path identifying the node)
 
440
                 * if the old nodetree has animation data which potentially covers this node
 
441
                 */
 
442
                if (wgroup->adt) {
 
443
                        PointerRNA ptr;
 
444
                        char *path;
 
445
 
 
446
                        RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
 
447
                        path = RNA_path_from_ID_to_struct(&ptr);
 
448
 
 
449
                        if (path)
 
450
                                BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
 
451
                }
 
452
 
 
453
                /* migrate node */
 
454
                BLI_remlink(&wgroup->nodes, node);
 
455
                BLI_addtail(&ntree->nodes, node);
 
456
 
 
457
                /* ensure unique node name in the nodee tree */
 
458
                nodeUniqueName(ntree, node);
 
459
 
 
460
                if (!node->parent) {
 
461
                        node->locx += gnode->locx;
 
462
                        node->locy += gnode->locy;
 
463
                }
 
464
 
 
465
                node->flag |= NODE_SELECT;
 
466
        }
 
467
 
 
468
        /* restore external links to and from the gnode */
 
469
        for (link = ntree->links.first; link; link = link->next) {
 
470
                if (link->fromnode == gnode) {
 
471
                        if (link->fromsock->groupsock) {
 
472
                                bNodeSocket *gsock = link->fromsock->groupsock;
 
473
                                if (gsock->link) {
 
474
                                        if (gsock->link->fromnode) {
 
475
                                                /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
 
476
                                                link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
 
477
                                                link->fromsock = gsock->link->fromsock->new_sock;
 
478
                                        }
 
479
                                        else {
 
480
                                                /* group output directly maps to group input */
 
481
                                                bNodeSocket *insock = node_group_find_input(gnode, gsock->link->fromsock);
 
482
                                                if (insock->link) {
 
483
                                                        link->fromnode = insock->link->fromnode;
 
484
                                                        link->fromsock = insock->link->fromsock;
 
485
                                                }
 
486
                                        }
 
487
                                }
 
488
                                else {
 
489
                                        /* copy the default input value from the group socket default to the external socket */
 
490
                                        node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, gsock->type, gsock->default_value);
 
491
                                }
 
492
                        }
 
493
                }
 
494
        }
 
495
        /* remove internal output links, these are not used anymore */
 
496
        for (link = wgroup->links.first; link; link = linkn) {
 
497
                linkn = link->next;
 
498
                if (!link->tonode)
 
499
                        nodeRemLink(wgroup, link);
 
500
        }
 
501
        /* restore links from internal nodes */
 
502
        for (link = wgroup->links.first; link; link = linkn) {
 
503
                linkn = link->next;
 
504
                /* indicates link to group input */
 
505
                if (!link->fromnode) {
 
506
                        /* NB: can't use find_group_node_input here,
 
507
                         * because gnode sockets still point to the old tree!
 
508
                         */
 
509
                        bNodeSocket *insock;
 
510
                        for (insock = gnode->inputs.first; insock; insock = insock->next)
 
511
                                if (insock->groupsock->new_sock == link->fromsock)
 
512
                                        break;
 
513
                        if (insock->link) {
 
514
                                link->fromnode = insock->link->fromnode;
 
515
                                link->fromsock = insock->link->fromsock;
 
516
                        }
 
517
                        else {
 
518
                                /* copy the default input value from the group node socket default to the internal socket */
 
519
                                node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, insock->type, insock->default_value);
 
520
                                nodeRemLink(wgroup, link);
 
521
                        }
 
522
                }
 
523
        }
 
524
 
 
525
        /* add internal links to the ntree */
 
526
        for (link = wgroup->links.first; link; link = linkn) {
 
527
                linkn = link->next;
 
528
                BLI_remlink(&wgroup->links, link);
 
529
                BLI_addtail(&ntree->links, link);
 
530
        }
 
531
 
 
532
        /* and copy across the animation,
 
533
         * note that the animation data's action can be NULL here */
 
534
        if (wgroup->adt) {
 
535
                LinkData *ld, *ldn = NULL;
 
536
                bAction *waction;
 
537
 
 
538
                /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
 
539
                waction = wgroup->adt->action = BKE_action_copy(wgroup->adt->action);
 
540
 
 
541
                /* now perform the moving */
 
542
                BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
 
543
 
 
544
                /* paths + their wrappers need to be freed */
 
545
                for (ld = anim_basepaths.first; ld; ld = ldn) {
 
546
                        ldn = ld->next;
 
547
 
 
548
                        MEM_freeN(ld->data);
 
549
                        BLI_freelinkN(&anim_basepaths, ld);
 
550
                }
 
551
 
 
552
                /* free temp action too */
 
553
                if (waction) {
 
554
                        BKE_libblock_free(&G.main->action, waction);
 
555
                }
 
556
        }
 
557
 
 
558
        /* delete the group instance. this also removes old input links! */
 
559
        nodeFreeNode(ntree, gnode);
 
560
 
 
561
        /* free the group tree (takes care of user count) */
 
562
        BKE_libblock_free(&G.main->nodetree, wgroup);
 
563
 
 
564
        ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
 
565
 
 
566
        return 1;
 
567
}
 
568
 
 
569
static int node_group_ungroup_exec(bContext *C, wmOperator *op)
 
570
{
 
571
        SpaceNode *snode = CTX_wm_space_node(C);
 
572
        bNode *gnode;
 
573
 
 
574
        ED_preview_kill_jobs(C);
 
575
 
 
576
        /* are we inside of a group? */
 
577
        gnode = node_tree_get_editgroup(snode->nodetree);
 
578
        if (gnode)
 
579
                snode_make_group_editable(snode, NULL);
 
580
 
 
581
        gnode = nodeGetActive(snode->edittree);
 
582
        if (gnode == NULL)
 
583
                return OPERATOR_CANCELLED;
 
584
 
 
585
        if (gnode->type != NODE_GROUP) {
 
586
                BKE_report(op->reports, RPT_WARNING, "Not a group");
 
587
                return OPERATOR_CANCELLED;
 
588
        }
 
589
        else if (node_group_ungroup(snode->nodetree, gnode)) {
 
590
                ntreeUpdateTree(snode->nodetree);
 
591
        }
 
592
        else {
 
593
                BKE_report(op->reports, RPT_WARNING, "Cannot ungroup");
 
594
                return OPERATOR_CANCELLED;
 
595
        }
 
596
 
 
597
        snode_notify(C, snode);
 
598
        snode_dag_update(C, snode);
 
599
 
 
600
        return OPERATOR_FINISHED;
 
601
}
 
602
 
 
603
void NODE_OT_group_ungroup(wmOperatorType *ot)
 
604
{
 
605
        /* identifiers */
 
606
        ot->name = "Ungroup";
 
607
        ot->description = "Ungroup selected nodes";
 
608
        ot->idname = "NODE_OT_group_ungroup";
 
609
 
 
610
        /* api callbacks */
 
611
        ot->exec = node_group_ungroup_exec;
 
612
        ot->poll = ED_operator_node_active;
 
613
 
 
614
        /* flags */
 
615
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
616
}
 
617
 
 
618
/* ******************** Separate operator ********************** */
 
619
 
 
620
/* returns 1 if its OK */
 
621
static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make_copy)
 
622
{
 
623
        bNodeLink *link, *link_next;
 
624
        bNode *node, *node_next, *newnode;
 
625
        bNodeTree *ngroup;
 
626
        ListBase anim_basepaths = {NULL, NULL};
 
627
 
 
628
        ngroup = (bNodeTree *)gnode->id;
 
629
        if (ngroup == NULL) return 0;
 
630
 
 
631
        /* deselect all nodes in the target tree */
 
632
        for (node = ntree->nodes.first; node; node = node->next)
 
633
                node_deselect(node);
 
634
 
 
635
        /* clear new pointers, set in nodeCopyNode */
 
636
        for (node = ngroup->nodes.first; node; node = node->next)
 
637
                node->new_node = NULL;
 
638
 
 
639
        /* add selected nodes into the ntree */
 
640
        for (node = ngroup->nodes.first; node; node = node_next) {
 
641
                node_next = node->next;
 
642
                if (node->flag & NODE_SELECT) {
 
643
                        
 
644
                        if (make_copy) {
 
645
                                /* make a copy */
 
646
                                newnode = nodeCopyNode(ngroup, node);
 
647
                        }
 
648
                        else {
 
649
                                /* use the existing node */
 
650
                                newnode = node;
 
651
                        }
 
652
                        
 
653
                        /* keep track of this node's RNA "base" path (the part of the path identifying the node)
 
654
                         * if the old nodetree has animation data which potentially covers this node
 
655
                         */
 
656
                        if (ngroup->adt) {
 
657
                                PointerRNA ptr;
 
658
                                char *path;
 
659
                                
 
660
                                RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
 
661
                                path = RNA_path_from_ID_to_struct(&ptr);
 
662
                                
 
663
                                if (path)
 
664
                                        BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
 
665
                        }
 
666
                        
 
667
                        /* ensure valid parent pointers, detach if parent stays inside the group */
 
668
                        if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
 
669
                                nodeDetachNode(newnode);
 
670
                        
 
671
                        /* migrate node */
 
672
                        BLI_remlink(&ngroup->nodes, newnode);
 
673
                        BLI_addtail(&ntree->nodes, newnode);
 
674
                        
 
675
                        /* ensure unique node name in the node tree */
 
676
                        nodeUniqueName(ntree, newnode);
 
677
                        
 
678
                        if (!newnode->parent) {
 
679
                                newnode->locx += gnode->locx;
 
680
                                newnode->locy += gnode->locy;
 
681
                        }
 
682
                }
 
683
                else {
 
684
                        /* ensure valid parent pointers, detach if child stays inside the group */
 
685
                        if (node->parent && (node->parent->flag & NODE_SELECT))
 
686
                                nodeDetachNode(node);
 
687
                }
 
688
        }
 
689
 
 
690
        /* add internal links to the ntree */
 
691
        for (link = ngroup->links.first; link; link = link_next) {
 
692
                int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
 
693
                int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
 
694
                link_next = link->next;
 
695
 
 
696
                if (make_copy) {
 
697
                        /* make a copy of internal links */
 
698
                        if (fromselect && toselect)
 
699
                                nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock, link->tonode->new_node, link->tosock->new_sock);
 
700
                }
 
701
                else {
 
702
                        /* move valid links over, delete broken links */
 
703
                        if (fromselect && toselect) {
 
704
                                BLI_remlink(&ngroup->links, link);
 
705
                                BLI_addtail(&ntree->links, link);
 
706
                        }
 
707
                        else if (fromselect || toselect) {
 
708
                                nodeRemLink(ngroup, link);
 
709
                        }
 
710
                }
 
711
        }
 
712
 
 
713
        /* and copy across the animation,
 
714
         * note that the animation data's action can be NULL here */
 
715
        if (ngroup->adt) {
 
716
                LinkData *ld, *ldn = NULL;
 
717
 
 
718
                /* now perform the moving */
 
719
                BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths);
 
720
 
 
721
                /* paths + their wrappers need to be freed */
 
722
                for (ld = anim_basepaths.first; ld; ld = ldn) {
 
723
                        ldn = ld->next;
 
724
 
 
725
                        MEM_freeN(ld->data);
 
726
                        BLI_freelinkN(&anim_basepaths, ld);
 
727
                }
 
728
        }
 
729
 
 
730
        ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
 
731
        if (!make_copy)
 
732
                ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
 
733
 
 
734
        return 1;
 
735
}
 
736
 
 
737
typedef enum eNodeGroupSeparateType {
 
738
        NODE_GS_COPY,
 
739
        NODE_GS_MOVE
 
740
} eNodeGroupSeparateType;
 
741
 
 
742
/* Operator Property */
 
743
EnumPropertyItem node_group_separate_types[] = {
 
744
        {NODE_GS_COPY, "COPY", 0, "Copy", "Copy to parent node tree, keep group intact"},
 
745
        {NODE_GS_MOVE, "MOVE", 0, "Move", "Move to parent node tree, remove from group"},
 
746
        {0, NULL, 0, NULL, NULL}
 
747
};
 
748
 
 
749
static int node_group_separate_exec(bContext *C, wmOperator *op)
 
750
{
 
751
        SpaceNode *snode = CTX_wm_space_node(C);
 
752
        bNode *gnode;
 
753
        int type = RNA_enum_get(op->ptr, "type");
 
754
 
 
755
        ED_preview_kill_jobs(C);
 
756
 
 
757
        /* are we inside of a group? */
 
758
        gnode = node_tree_get_editgroup(snode->nodetree);
 
759
        if (!gnode) {
 
760
                BKE_report(op->reports, RPT_WARNING, "Not inside node group");
 
761
                return OPERATOR_CANCELLED;
 
762
        }
 
763
 
 
764
        switch (type) {
 
765
                case NODE_GS_COPY:
 
766
                        if (!node_group_separate_selected(snode->nodetree, gnode, 1)) {
 
767
                                BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
 
768
                                return OPERATOR_CANCELLED;
 
769
                        }
 
770
                        break;
 
771
                case NODE_GS_MOVE:
 
772
                        if (!node_group_separate_selected(snode->nodetree, gnode, 0)) {
 
773
                                BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
 
774
                                return OPERATOR_CANCELLED;
 
775
                        }
 
776
                        break;
 
777
        }
 
778
 
 
779
        /* switch to parent tree */
 
780
        snode_make_group_editable(snode, NULL);
 
781
 
 
782
        ntreeUpdateTree(snode->nodetree);
 
783
 
 
784
        snode_notify(C, snode);
 
785
        snode_dag_update(C, snode);
 
786
 
 
787
        return OPERATOR_FINISHED;
 
788
}
 
789
 
 
790
static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
 
791
{
 
792
        uiPopupMenu *pup = uiPupMenuBegin(C, "Separate", ICON_NONE);
 
793
        uiLayout *layout = uiPupMenuLayout(pup);
 
794
 
 
795
        uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
 
796
        uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
 
797
        uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
 
798
 
 
799
        uiPupMenuEnd(C, pup);
 
800
 
 
801
        return OPERATOR_CANCELLED;
 
802
}
 
803
 
 
804
void NODE_OT_group_separate(wmOperatorType *ot)
 
805
{
 
806
        /* identifiers */
 
807
        ot->name = "Separate";
 
808
        ot->description = "Separate selected nodes from the node group";
 
809
        ot->idname = "NODE_OT_group_separate";
 
810
 
 
811
        /* api callbacks */
 
812
        ot->invoke = node_group_separate_invoke;
 
813
        ot->exec = node_group_separate_exec;
 
814
        ot->poll = ED_operator_node_active;
 
815
 
 
816
        /* flags */
 
817
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
818
 
 
819
        RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
 
820
}
 
821
 
 
822
/* ****************** Make Group operator ******************* */
 
823
 
 
824
static int node_group_make_test(bNodeTree *ntree, bNode *gnode)
 
825
{
 
826
        bNode *node;
 
827
        bNodeLink *link;
 
828
        int totnode = 0;
 
829
 
 
830
        /* is there something to group? also do some clearing */
 
831
        for (node = ntree->nodes.first; node; node = node->next) {
 
832
                if (node == gnode)
 
833
                        continue;
 
834
 
 
835
                if (node->flag & NODE_SELECT) {
 
836
                        /* no groups in groups */
 
837
                        if (node->type == NODE_GROUP)
 
838
                                return 0;
 
839
                        totnode++;
 
840
                }
 
841
 
 
842
                node->done = 0;
 
843
        }
 
844
        if (totnode == 0) return 0;
 
845
 
 
846
        /* check if all connections are OK, no unselected node has both
 
847
         * inputs and outputs to a selection */
 
848
        for (link = ntree->links.first; link; link = link->next) {
 
849
                if (link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT && link->fromnode != gnode)
 
850
                        link->tonode->done |= 1;
 
851
                if (link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT && link->tonode != gnode)
 
852
                        link->fromnode->done |= 2;
 
853
        }
 
854
 
 
855
        for (node = ntree->nodes.first; node; node = node->next) {
 
856
                if (node == gnode)
 
857
                        continue;
 
858
                if ((node->flag & NODE_SELECT) == 0)
 
859
                        if (node->done == 3)
 
860
                                break;
 
861
        }
 
862
        if (node)
 
863
                return 0;
 
864
 
 
865
        return 1;
 
866
}
 
867
 
 
868
 
 
869
static void node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max)
 
870
{
 
871
        bNode *node;
 
872
        float loc[2];
 
873
        INIT_MINMAX2(min, max);
 
874
        for (node = ntree->nodes.first; node; node = node->next) {
 
875
                if (node == gnode)
 
876
                        continue;
 
877
                if (node->flag & NODE_SELECT) {
 
878
                        nodeToView(node, 0.0f, 0.0f, &loc[0], &loc[1]);
 
879
                        minmax_v2v2_v2(min, max, loc);
 
880
                }
 
881
        }
 
882
}
 
883
 
 
884
static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
 
885
{
 
886
        bNodeTree *ngroup = (bNodeTree *)gnode->id;
 
887
        bNodeLink *link, *linkn;
 
888
        bNode *node, *nextn;
 
889
        bNodeSocket *gsock, *sock;
 
890
        ListBase anim_basepaths = {NULL, NULL};
 
891
        float min[2], max[2];
 
892
 
 
893
        /* deselect all nodes in the target tree */
 
894
        for (node = ngroup->nodes.first; node; node = node->next)
 
895
                node_deselect(node);
 
896
 
 
897
        node_get_selected_minmax(ntree, gnode, min, max);
 
898
 
 
899
        /* move nodes over */
 
900
        for (node = ntree->nodes.first; node; node = nextn) {
 
901
                nextn = node->next;
 
902
                if (node == gnode)
 
903
                        continue;
 
904
                if (node->flag & NODE_SELECT) {
 
905
                        /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
 
906
                         * if the old nodetree has animation data which potentially covers this node
 
907
                         */
 
908
                        if (ntree->adt) {
 
909
                                PointerRNA ptr;
 
910
                                char *path;
 
911
 
 
912
                                RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
 
913
                                path = RNA_path_from_ID_to_struct(&ptr);
 
914
 
 
915
                                if (path)
 
916
                                        BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
 
917
                        }
 
918
 
 
919
                        /* ensure valid parent pointers, detach if parent stays outside the group */
 
920
                        if (node->parent && !(node->parent->flag & NODE_SELECT))
 
921
                                nodeDetachNode(node);
 
922
 
 
923
                        /* change node-collection membership */
 
924
                        BLI_remlink(&ntree->nodes, node);
 
925
                        BLI_addtail(&ngroup->nodes, node);
 
926
 
 
927
                        /* ensure unique node name in the ngroup */
 
928
                        nodeUniqueName(ngroup, node);
 
929
 
 
930
                        if (!node->parent) {
 
931
                                node->locx -= 0.5f * (min[0] + max[0]);
 
932
                                node->locy -= 0.5f * (min[1] + max[1]);
 
933
                        }
 
934
                }
 
935
                else {
 
936
                        /* if the parent is to be inserted but not the child, detach properly */
 
937
                        if (node->parent && (node->parent->flag & NODE_SELECT))
 
938
                                nodeDetachNode(node);
 
939
                }
 
940
        }
 
941
 
 
942
        /* move animation data over */
 
943
        if (ntree->adt) {
 
944
                LinkData *ld, *ldn = NULL;
 
945
 
 
946
                BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);
 
947
 
 
948
                /* paths + their wrappers need to be freed */
 
949
                for (ld = anim_basepaths.first; ld; ld = ldn) {
 
950
                        ldn = ld->next;
 
951
 
 
952
                        MEM_freeN(ld->data);
 
953
                        BLI_freelinkN(&anim_basepaths, ld);
 
954
                }
 
955
        }
 
956
 
 
957
        /* node groups don't use internal cached data */
 
958
        ntreeFreeCache(ngroup);
 
959
 
 
960
        /* relink external sockets */
 
961
        for (link = ntree->links.first; link; link = linkn) {
 
962
                int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT) && link->fromnode != gnode);
 
963
                int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT) && link->tonode != gnode);
 
964
                linkn = link->next;
 
965
 
 
966
                if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) {
 
967
                        /* remove all links to/from the gnode.
 
968
                         * this can remove link information, but there's no general way to preserve it.
 
969
                         */
 
970
                        nodeRemLink(ntree, link);
 
971
                }
 
972
                else if (fromselect && toselect) {
 
973
                        BLI_remlink(&ntree->links, link);
 
974
                        BLI_addtail(&ngroup->links, link);
 
975
                }
 
976
                else if (toselect) {
 
977
                        gsock = node_group_expose_socket(ngroup, link->tosock, SOCK_IN);
 
978
                        link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock);
 
979
                        link->tosock = node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
 
980
                        link->tonode = gnode;
 
981
                }
 
982
                else if (fromselect) {
 
983
                        /* search for existing group node socket */
 
984
                        for (gsock = ngroup->outputs.first; gsock; gsock = gsock->next)
 
985
                                if (gsock->link && gsock->link->fromsock == link->fromsock)
 
986
                                        break;
 
987
                        if (!gsock) {
 
988
                                gsock = node_group_expose_socket(ngroup, link->fromsock, SOCK_OUT);
 
989
                                gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock);
 
990
                                link->fromsock = node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
 
991
                        }
 
992
                        else
 
993
                                link->fromsock = node_group_find_output(gnode, gsock);
 
994
                        link->fromnode = gnode;
 
995
                }
 
996
        }
 
997
 
 
998
        /* auto-add interface for "solo" nodes */
 
999
        node = ((bNodeTree *)gnode->id)->nodes.first;
 
1000
        if (node && !node->next) {
 
1001
                for (sock = node->inputs.first; sock; sock = sock->next) {
 
1002
                        int skip = FALSE;
 
1003
                        
 
1004
                        for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
 
1005
                                if (link->tosock == sock)
 
1006
                                        skip = TRUE;
 
1007
 
 
1008
                        if (skip == TRUE)
 
1009
                                continue;
 
1010
 
 
1011
                        gsock = node_group_expose_socket(ngroup, sock, SOCK_IN);
 
1012
                        node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
 
1013
                        nodeAddLink(ngroup, NULL, gsock, node, sock);
 
1014
                }
 
1015
 
 
1016
                for (sock = node->outputs.first; sock; sock = sock->next) {
 
1017
                        int skip = FALSE;
 
1018
                        
 
1019
                        for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
 
1020
                                if (link->fromsock == sock)
 
1021
                                        skip = TRUE;
 
1022
 
 
1023
                        if (skip == TRUE)
 
1024
                                continue;
 
1025
 
 
1026
                        gsock = node_group_expose_socket(ngroup, sock, SOCK_OUT);
 
1027
                        node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
 
1028
                        nodeAddLink(ngroup, NULL, gsock, node, sock);
 
1029
                }
 
1030
        }
 
1031
 
 
1032
        /* update of the group tree */
 
1033
        ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS;
 
1034
        /* update of the tree containing the group instance node */
 
1035
        ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
 
1036
 
 
1037
        return 1;
 
1038
}
 
1039
 
 
1040
static bNode *node_group_make_from_selected(bNodeTree *ntree)
 
1041
{
 
1042
        bNode *gnode;
 
1043
        bNodeTree *ngroup;
 
1044
        float min[2], max[2];
 
1045
        bNodeTemplate ntemp;
 
1046
 
 
1047
        node_get_selected_minmax(ntree, NULL, min, max);
 
1048
 
 
1049
        /* new nodetree */
 
1050
        ngroup = ntreeAddTree(G.main, "NodeGroup", ntree->type, NODE_GROUP);
 
1051
 
 
1052
        /* make group node */
 
1053
        ntemp.type = NODE_GROUP;
 
1054
        ntemp.ngroup = ngroup;
 
1055
        gnode = nodeAddNode(ntree, &ntemp);
 
1056
        gnode->locx = 0.5f * (min[0] + max[0]);
 
1057
        gnode->locy = 0.5f * (min[1] + max[1]);
 
1058
 
 
1059
        node_group_make_insert_selected(ntree, gnode);
 
1060
 
 
1061
        /* update of the tree containing the group instance node */
 
1062
        ntree->update |= NTREE_UPDATE_NODES;
 
1063
 
 
1064
        return gnode;
 
1065
}
 
1066
 
 
1067
typedef enum eNodeGroupMakeType {
 
1068
        NODE_GM_NEW,
 
1069
        NODE_GM_INSERT
 
1070
} eNodeGroupMakeType;
 
1071
 
 
1072
/* Operator Property */
 
1073
EnumPropertyItem node_group_make_types[] = {
 
1074
        {NODE_GM_NEW, "NEW", 0, "New", "Create a new node group from selected nodes"},
 
1075
        {NODE_GM_INSERT, "INSERT", 0, "Insert", "Insert into active node group"},
 
1076
        {0, NULL, 0, NULL, NULL}
 
1077
};
 
1078
 
 
1079
static int node_group_make_exec(bContext *C, wmOperator *op)
 
1080
{
 
1081
        SpaceNode *snode = CTX_wm_space_node(C);
 
1082
        bNode *gnode;
 
1083
        int type = RNA_enum_get(op->ptr, "type");
 
1084
 
 
1085
        if (snode->edittree != snode->nodetree) {
 
1086
                BKE_report(op->reports, RPT_WARNING, "Cannot add a new group in a group");
 
1087
                return OPERATOR_CANCELLED;
 
1088
        }
 
1089
 
 
1090
        /* for time being... is too complex to handle */
 
1091
        if (snode->treetype == NTREE_COMPOSIT) {
 
1092
                for (gnode = snode->nodetree->nodes.first; gnode; gnode = gnode->next) {
 
1093
                        if (gnode->flag & SELECT)
 
1094
                                if (gnode->type == CMP_NODE_R_LAYERS)
 
1095
                                        break;
 
1096
                }
 
1097
 
 
1098
                if (gnode) {
 
1099
                        BKE_report(op->reports, RPT_WARNING, "Cannot add a Render Layers node in a group");
 
1100
                        return OPERATOR_CANCELLED;
 
1101
                }
 
1102
        }
 
1103
 
 
1104
        ED_preview_kill_jobs(C);
 
1105
 
 
1106
        switch (type) {
 
1107
                case NODE_GM_NEW:
 
1108
                        if (node_group_make_test(snode->nodetree, NULL)) {
 
1109
                                gnode = node_group_make_from_selected(snode->nodetree);
 
1110
                        }
 
1111
                        else {
 
1112
                                BKE_report(op->reports, RPT_WARNING, "Cannot make group");
 
1113
                                return OPERATOR_CANCELLED;
 
1114
                        }
 
1115
                        break;
 
1116
                case NODE_GM_INSERT:
 
1117
                        gnode = nodeGetActive(snode->nodetree);
 
1118
                        if (!gnode || gnode->type != NODE_GROUP) {
 
1119
                                BKE_report(op->reports, RPT_WARNING, "No active group node");
 
1120
                                return OPERATOR_CANCELLED;
 
1121
                        }
 
1122
                        if (node_group_make_test(snode->nodetree, gnode)) {
 
1123
                                node_group_make_insert_selected(snode->nodetree, gnode);
 
1124
                        }
 
1125
                        else {
 
1126
                                BKE_report(op->reports, RPT_WARNING, "Cannot insert into group");
 
1127
                                return OPERATOR_CANCELLED;
 
1128
                        }
 
1129
                        break;
 
1130
        }
 
1131
 
 
1132
        if (gnode) {
 
1133
                nodeSetActive(snode->nodetree, gnode);
 
1134
                snode_make_group_editable(snode, gnode);
 
1135
        }
 
1136
 
 
1137
        if (gnode)
 
1138
                ntreeUpdateTree((bNodeTree *)gnode->id);
 
1139
        ntreeUpdateTree(snode->nodetree);
 
1140
 
 
1141
        snode_notify(C, snode);
 
1142
        snode_dag_update(C, snode);
 
1143
 
 
1144
        return OPERATOR_FINISHED;
 
1145
}
 
1146
 
 
1147
static int node_group_make_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
 
1148
{
 
1149
        SpaceNode *snode = CTX_wm_space_node(C);
 
1150
        bNode *act = nodeGetActive(snode->edittree);
 
1151
        uiPopupMenu *pup = uiPupMenuBegin(C, "Make Group", ICON_NONE);
 
1152
        uiLayout *layout = uiPupMenuLayout(pup);
 
1153
 
 
1154
        uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
 
1155
        uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_NEW);
 
1156
 
 
1157
        /* if active node is a group, add insert option */
 
1158
        if (act && act->type == NODE_GROUP) {
 
1159
                uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_INSERT);
 
1160
        }
 
1161
 
 
1162
        uiPupMenuEnd(C, pup);
 
1163
 
 
1164
        return OPERATOR_CANCELLED;
 
1165
}
 
1166
 
 
1167
void NODE_OT_group_make(wmOperatorType *ot)
 
1168
{
 
1169
        /* identifiers */
 
1170
        ot->name = "Group";
 
1171
        ot->description = "Make group from selected nodes";
 
1172
        ot->idname = "NODE_OT_group_make";
 
1173
 
 
1174
        /* api callbacks */
 
1175
        ot->invoke = node_group_make_invoke;
 
1176
        ot->exec = node_group_make_exec;
 
1177
        ot->poll = ED_operator_node_active;
 
1178
 
 
1179
        /* flags */
 
1180
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
1181
 
 
1182
        RNA_def_enum(ot->srna, "type", node_group_make_types, NODE_GM_NEW, "Type", "");
 
1183
}