2
* ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18
* The Original Code is Copyright (C) 2005 Blender Foundation.
19
* All rights reserved.
21
* The Original Code is: all of this file.
23
* Contributor(s): David Millan Escriva, Juho Vepsäläinen, Nathan Letwory
25
* ***** END GPL LICENSE BLOCK *****
28
/** \file blender/editors/space_node/node_group.c
34
#include "MEM_guardedalloc.h"
36
#include "DNA_node_types.h"
37
#include "DNA_object_types.h"
38
#include "DNA_anim_types.h"
40
#include "BLI_listbase.h"
41
#include "BLI_string.h"
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"
51
#include "BKE_report.h"
53
#include "ED_node.h" /* own include */
54
#include "ED_screen.h"
55
#include "ED_render.h"
57
#include "RNA_access.h"
58
#include "RNA_define.h"
59
#include "RNA_enum_types.h"
64
#include "UI_resources.h"
66
#include "node_intern.h" /* own include */
67
#include "NOD_socket.h"
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 },
75
/* ***************** Edit Group operator ************* */
77
void snode_make_group_editable(SpaceNode *snode, bNode *gnode)
81
/* make sure nothing has group editing on */
82
for (node = snode->nodetree->nodes.first; node; node = node->next) {
83
nodeGroupEditClear(node);
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;
93
/* with NULL argument we do a toggle */
94
if (snode->edittree == snode->nodetree)
95
gnode = nodeGetActive(snode->nodetree);
99
snode->edittree = nodeGroupEditSet(gnode, 1);
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) {
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;
113
snode->edittree = snode->nodetree;
116
static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op))
118
SpaceNode *snode = CTX_wm_space_node(C);
120
ED_preview_kill_jobs(C);
122
if (snode->nodetree == snode->edittree) {
123
bNode *gnode = nodeGetActive(snode->edittree);
124
snode_make_group_editable(snode, gnode);
127
snode_make_group_editable(snode, NULL);
129
WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
131
return OPERATOR_FINISHED;
134
static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
136
SpaceNode *snode = CTX_wm_space_node(C);
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;
148
return node_group_edit_exec(C, op);
151
void NODE_OT_group_edit(wmOperatorType *ot)
154
ot->name = "Edit Group";
155
ot->description = "Edit node group";
156
ot->idname = "NODE_OT_group_edit";
159
ot->invoke = node_group_edit_invoke;
160
ot->exec = node_group_edit_exec;
161
ot->poll = ED_operator_node_active;
164
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
167
/* ***************** Add Group Socket operator ************* */
169
static int node_group_socket_add_exec(bContext *C, wmOperator *op)
171
SpaceNode *snode = CTX_wm_space_node(C);
173
char name[MAX_NAME] = "";
174
int type = SOCK_FLOAT;
175
bNodeTree *ngroup = snode->edittree;
176
/* bNodeSocket *sock; */ /* UNUSED */
178
ED_preview_kill_jobs(C);
180
if (RNA_struct_property_is_set(op->ptr, "name"))
181
RNA_string_get(op->ptr, "name", name);
183
if (RNA_struct_property_is_set(op->ptr, "type"))
184
type = RNA_enum_get(op->ptr, "type");
186
if (RNA_struct_property_is_set(op->ptr, "in_out"))
187
in_out = RNA_enum_get(op->ptr, "in_out");
189
return OPERATOR_CANCELLED;
191
/* using placeholder subtype first */
192
/* sock = */ /* UNUSED */ node_group_add_socket(ngroup, name, type, in_out);
194
ntreeUpdateTree(ngroup);
196
snode_notify(C, snode);
198
return OPERATOR_FINISHED;
201
void NODE_OT_group_socket_add(wmOperatorType *ot)
204
ot->name = "Add Group Socket";
205
ot->description = "Add node group socket";
206
ot->idname = "NODE_OT_group_socket_add";
209
ot->exec = node_group_socket_add_exec;
210
ot->poll = ED_operator_node_active;
213
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
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");
220
/* ***************** Remove Group Socket operator ************* */
222
static int node_group_socket_remove_exec(bContext *C, wmOperator *op)
224
SpaceNode *snode = CTX_wm_space_node(C);
227
bNodeTree *ngroup = snode->edittree;
230
ED_preview_kill_jobs(C);
232
if (RNA_struct_property_is_set(op->ptr, "index"))
233
index = RNA_int_get(op->ptr, "index");
235
return OPERATOR_CANCELLED;
237
if (RNA_struct_property_is_set(op->ptr, "in_out"))
238
in_out = RNA_enum_get(op->ptr, "in_out");
240
return OPERATOR_CANCELLED;
242
sock = (bNodeSocket *)BLI_findlink(in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs, index);
244
node_group_remove_socket(ngroup, sock, in_out);
245
ntreeUpdateTree(ngroup);
247
snode_notify(C, snode);
250
return OPERATOR_FINISHED;
253
void NODE_OT_group_socket_remove(wmOperatorType *ot)
256
ot->name = "Remove Group Socket";
257
ot->description = "Remove a node group socket";
258
ot->idname = "NODE_OT_group_socket_remove";
261
ot->exec = node_group_socket_remove_exec;
262
ot->poll = ED_operator_node_active;
265
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
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");
271
/* ***************** Move Group Socket Up operator ************* */
273
static int node_group_socket_move_up_exec(bContext *C, wmOperator *op)
275
SpaceNode *snode = CTX_wm_space_node(C);
278
bNodeTree *ngroup = snode->edittree;
279
bNodeSocket *sock, *prev;
281
ED_preview_kill_jobs(C);
283
if (RNA_struct_property_is_set(op->ptr, "index"))
284
index = RNA_int_get(op->ptr, "index");
286
return OPERATOR_CANCELLED;
288
if (RNA_struct_property_is_set(op->ptr, "in_out"))
289
in_out = RNA_enum_get(op->ptr, "in_out");
291
return OPERATOR_CANCELLED;
294
if (in_out == SOCK_IN) {
295
sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
297
/* can't move up the first socket */
299
return OPERATOR_CANCELLED;
300
BLI_remlink(&ngroup->inputs, sock);
301
BLI_insertlinkbefore(&ngroup->inputs, prev, sock);
303
ngroup->update |= NTREE_UPDATE_GROUP_IN;
305
else if (in_out == SOCK_OUT) {
306
sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
308
/* can't move up the first socket */
310
return OPERATOR_CANCELLED;
311
BLI_remlink(&ngroup->outputs, sock);
312
BLI_insertlinkbefore(&ngroup->outputs, prev, sock);
314
ngroup->update |= NTREE_UPDATE_GROUP_OUT;
316
ntreeUpdateTree(ngroup);
318
snode_notify(C, snode);
320
return OPERATOR_FINISHED;
323
void NODE_OT_group_socket_move_up(wmOperatorType *ot)
326
ot->name = "Move Group Socket Up";
327
ot->description = "Move up node group socket";
328
ot->idname = "NODE_OT_group_socket_move_up";
331
ot->exec = node_group_socket_move_up_exec;
332
ot->poll = ED_operator_node_active;
335
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
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");
341
/* ***************** Move Group Socket Up operator ************* */
343
static int node_group_socket_move_down_exec(bContext *C, wmOperator *op)
345
SpaceNode *snode = CTX_wm_space_node(C);
348
bNodeTree *ngroup = snode->edittree;
349
bNodeSocket *sock, *next;
351
ED_preview_kill_jobs(C);
353
if (RNA_struct_property_is_set(op->ptr, "index"))
354
index = RNA_int_get(op->ptr, "index");
356
return OPERATOR_CANCELLED;
358
if (RNA_struct_property_is_set(op->ptr, "in_out"))
359
in_out = RNA_enum_get(op->ptr, "in_out");
361
return OPERATOR_CANCELLED;
364
if (in_out == SOCK_IN) {
365
sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
367
/* can't move down the last socket */
369
return OPERATOR_CANCELLED;
370
BLI_remlink(&ngroup->inputs, sock);
371
BLI_insertlinkafter(&ngroup->inputs, next, sock);
373
ngroup->update |= NTREE_UPDATE_GROUP_IN;
375
else if (in_out == SOCK_OUT) {
376
sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
378
/* can't move down the last socket */
380
return OPERATOR_CANCELLED;
381
BLI_remlink(&ngroup->outputs, sock);
382
BLI_insertlinkafter(&ngroup->outputs, next, sock);
384
ngroup->update |= NTREE_UPDATE_GROUP_OUT;
386
ntreeUpdateTree(ngroup);
388
snode_notify(C, snode);
390
return OPERATOR_FINISHED;
393
void NODE_OT_group_socket_move_down(wmOperatorType *ot)
396
ot->name = "Move Group Socket Down";
397
ot->description = "Move down node group socket";
398
ot->idname = "NODE_OT_group_socket_move_down";
401
ot->exec = node_group_socket_move_down_exec;
402
ot->poll = ED_operator_node_active;
405
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
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");
411
/* ******************** Ungroup operator ********************** */
413
/* returns 1 if its OK */
414
static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
416
bNodeLink *link, *linkn;
418
bNodeTree *ngroup, *wgroup;
419
ListBase anim_basepaths = {NULL, NULL};
421
ngroup = (bNodeTree *)gnode->id;
422
if (ngroup == NULL) return 0;
424
/* clear new pointers, set in copytree */
425
for (node = ntree->nodes.first; node; node = node->next)
426
node->new_node = NULL;
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
433
wgroup = ntreeCopyTree_ex(ngroup, FALSE);
435
/* add the nodes into the ntree */
436
for (node = wgroup->nodes.first; node; node = nextn) {
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
446
RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
447
path = RNA_path_from_ID_to_struct(&ptr);
450
BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
454
BLI_remlink(&wgroup->nodes, node);
455
BLI_addtail(&ntree->nodes, node);
457
/* ensure unique node name in the nodee tree */
458
nodeUniqueName(ntree, node);
461
node->locx += gnode->locx;
462
node->locy += gnode->locy;
465
node->flag |= NODE_SELECT;
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;
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;
480
/* group output directly maps to group input */
481
bNodeSocket *insock = node_group_find_input(gnode, gsock->link->fromsock);
483
link->fromnode = insock->link->fromnode;
484
link->fromsock = insock->link->fromsock;
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);
495
/* remove internal output links, these are not used anymore */
496
for (link = wgroup->links.first; link; link = linkn) {
499
nodeRemLink(wgroup, link);
501
/* restore links from internal nodes */
502
for (link = wgroup->links.first; link; link = linkn) {
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!
510
for (insock = gnode->inputs.first; insock; insock = insock->next)
511
if (insock->groupsock->new_sock == link->fromsock)
514
link->fromnode = insock->link->fromnode;
515
link->fromsock = insock->link->fromsock;
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);
525
/* add internal links to the ntree */
526
for (link = wgroup->links.first; link; link = linkn) {
528
BLI_remlink(&wgroup->links, link);
529
BLI_addtail(&ntree->links, link);
532
/* and copy across the animation,
533
* note that the animation data's action can be NULL here */
535
LinkData *ld, *ldn = NULL;
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);
541
/* now perform the moving */
542
BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
544
/* paths + their wrappers need to be freed */
545
for (ld = anim_basepaths.first; ld; ld = ldn) {
549
BLI_freelinkN(&anim_basepaths, ld);
552
/* free temp action too */
554
BKE_libblock_free(&G.main->action, waction);
558
/* delete the group instance. this also removes old input links! */
559
nodeFreeNode(ntree, gnode);
561
/* free the group tree (takes care of user count) */
562
BKE_libblock_free(&G.main->nodetree, wgroup);
564
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
569
static int node_group_ungroup_exec(bContext *C, wmOperator *op)
571
SpaceNode *snode = CTX_wm_space_node(C);
574
ED_preview_kill_jobs(C);
576
/* are we inside of a group? */
577
gnode = node_tree_get_editgroup(snode->nodetree);
579
snode_make_group_editable(snode, NULL);
581
gnode = nodeGetActive(snode->edittree);
583
return OPERATOR_CANCELLED;
585
if (gnode->type != NODE_GROUP) {
586
BKE_report(op->reports, RPT_WARNING, "Not a group");
587
return OPERATOR_CANCELLED;
589
else if (node_group_ungroup(snode->nodetree, gnode)) {
590
ntreeUpdateTree(snode->nodetree);
593
BKE_report(op->reports, RPT_WARNING, "Cannot ungroup");
594
return OPERATOR_CANCELLED;
597
snode_notify(C, snode);
598
snode_dag_update(C, snode);
600
return OPERATOR_FINISHED;
603
void NODE_OT_group_ungroup(wmOperatorType *ot)
606
ot->name = "Ungroup";
607
ot->description = "Ungroup selected nodes";
608
ot->idname = "NODE_OT_group_ungroup";
611
ot->exec = node_group_ungroup_exec;
612
ot->poll = ED_operator_node_active;
615
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
618
/* ******************** Separate operator ********************** */
620
/* returns 1 if its OK */
621
static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make_copy)
623
bNodeLink *link, *link_next;
624
bNode *node, *node_next, *newnode;
626
ListBase anim_basepaths = {NULL, NULL};
628
ngroup = (bNodeTree *)gnode->id;
629
if (ngroup == NULL) return 0;
631
/* deselect all nodes in the target tree */
632
for (node = ntree->nodes.first; node; node = node->next)
635
/* clear new pointers, set in nodeCopyNode */
636
for (node = ngroup->nodes.first; node; node = node->next)
637
node->new_node = NULL;
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) {
646
newnode = nodeCopyNode(ngroup, node);
649
/* use the existing node */
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
660
RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
661
path = RNA_path_from_ID_to_struct(&ptr);
664
BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
667
/* ensure valid parent pointers, detach if parent stays inside the group */
668
if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
669
nodeDetachNode(newnode);
672
BLI_remlink(&ngroup->nodes, newnode);
673
BLI_addtail(&ntree->nodes, newnode);
675
/* ensure unique node name in the node tree */
676
nodeUniqueName(ntree, newnode);
678
if (!newnode->parent) {
679
newnode->locx += gnode->locx;
680
newnode->locy += gnode->locy;
684
/* ensure valid parent pointers, detach if child stays inside the group */
685
if (node->parent && (node->parent->flag & NODE_SELECT))
686
nodeDetachNode(node);
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;
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);
702
/* move valid links over, delete broken links */
703
if (fromselect && toselect) {
704
BLI_remlink(&ngroup->links, link);
705
BLI_addtail(&ntree->links, link);
707
else if (fromselect || toselect) {
708
nodeRemLink(ngroup, link);
713
/* and copy across the animation,
714
* note that the animation data's action can be NULL here */
716
LinkData *ld, *ldn = NULL;
718
/* now perform the moving */
719
BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths);
721
/* paths + their wrappers need to be freed */
722
for (ld = anim_basepaths.first; ld; ld = ldn) {
726
BLI_freelinkN(&anim_basepaths, ld);
730
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
732
ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
737
typedef enum eNodeGroupSeparateType {
740
} eNodeGroupSeparateType;
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}
749
static int node_group_separate_exec(bContext *C, wmOperator *op)
751
SpaceNode *snode = CTX_wm_space_node(C);
753
int type = RNA_enum_get(op->ptr, "type");
755
ED_preview_kill_jobs(C);
757
/* are we inside of a group? */
758
gnode = node_tree_get_editgroup(snode->nodetree);
760
BKE_report(op->reports, RPT_WARNING, "Not inside node group");
761
return OPERATOR_CANCELLED;
766
if (!node_group_separate_selected(snode->nodetree, gnode, 1)) {
767
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
768
return OPERATOR_CANCELLED;
772
if (!node_group_separate_selected(snode->nodetree, gnode, 0)) {
773
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
774
return OPERATOR_CANCELLED;
779
/* switch to parent tree */
780
snode_make_group_editable(snode, NULL);
782
ntreeUpdateTree(snode->nodetree);
784
snode_notify(C, snode);
785
snode_dag_update(C, snode);
787
return OPERATOR_FINISHED;
790
static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
792
uiPopupMenu *pup = uiPupMenuBegin(C, "Separate", ICON_NONE);
793
uiLayout *layout = uiPupMenuLayout(pup);
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);
799
uiPupMenuEnd(C, pup);
801
return OPERATOR_CANCELLED;
804
void NODE_OT_group_separate(wmOperatorType *ot)
807
ot->name = "Separate";
808
ot->description = "Separate selected nodes from the node group";
809
ot->idname = "NODE_OT_group_separate";
812
ot->invoke = node_group_separate_invoke;
813
ot->exec = node_group_separate_exec;
814
ot->poll = ED_operator_node_active;
817
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
819
RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
822
/* ****************** Make Group operator ******************* */
824
static int node_group_make_test(bNodeTree *ntree, bNode *gnode)
830
/* is there something to group? also do some clearing */
831
for (node = ntree->nodes.first; node; node = node->next) {
835
if (node->flag & NODE_SELECT) {
836
/* no groups in groups */
837
if (node->type == NODE_GROUP)
844
if (totnode == 0) return 0;
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;
855
for (node = ntree->nodes.first; node; node = node->next) {
858
if ((node->flag & NODE_SELECT) == 0)
869
static void node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max)
873
INIT_MINMAX2(min, max);
874
for (node = ntree->nodes.first; node; node = node->next) {
877
if (node->flag & NODE_SELECT) {
878
nodeToView(node, 0.0f, 0.0f, &loc[0], &loc[1]);
879
minmax_v2v2_v2(min, max, loc);
884
static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
886
bNodeTree *ngroup = (bNodeTree *)gnode->id;
887
bNodeLink *link, *linkn;
889
bNodeSocket *gsock, *sock;
890
ListBase anim_basepaths = {NULL, NULL};
891
float min[2], max[2];
893
/* deselect all nodes in the target tree */
894
for (node = ngroup->nodes.first; node; node = node->next)
897
node_get_selected_minmax(ntree, gnode, min, max);
899
/* move nodes over */
900
for (node = ntree->nodes.first; node; node = nextn) {
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
912
RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
913
path = RNA_path_from_ID_to_struct(&ptr);
916
BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
919
/* ensure valid parent pointers, detach if parent stays outside the group */
920
if (node->parent && !(node->parent->flag & NODE_SELECT))
921
nodeDetachNode(node);
923
/* change node-collection membership */
924
BLI_remlink(&ntree->nodes, node);
925
BLI_addtail(&ngroup->nodes, node);
927
/* ensure unique node name in the ngroup */
928
nodeUniqueName(ngroup, node);
931
node->locx -= 0.5f * (min[0] + max[0]);
932
node->locy -= 0.5f * (min[1] + max[1]);
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);
942
/* move animation data over */
944
LinkData *ld, *ldn = NULL;
946
BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);
948
/* paths + their wrappers need to be freed */
949
for (ld = anim_basepaths.first; ld; ld = ldn) {
953
BLI_freelinkN(&anim_basepaths, ld);
957
/* node groups don't use internal cached data */
958
ntreeFreeCache(ngroup);
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);
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.
970
nodeRemLink(ntree, link);
972
else if (fromselect && toselect) {
973
BLI_remlink(&ntree->links, link);
974
BLI_addtail(&ngroup->links, link);
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;
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)
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);
993
link->fromsock = node_group_find_output(gnode, gsock);
994
link->fromnode = gnode;
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) {
1004
for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
1005
if (link->tosock == sock)
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);
1016
for (sock = node->outputs.first; sock; sock = sock->next) {
1019
for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
1020
if (link->fromsock == sock)
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);
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;
1040
static bNode *node_group_make_from_selected(bNodeTree *ntree)
1044
float min[2], max[2];
1045
bNodeTemplate ntemp;
1047
node_get_selected_minmax(ntree, NULL, min, max);
1050
ngroup = ntreeAddTree(G.main, "NodeGroup", ntree->type, NODE_GROUP);
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]);
1059
node_group_make_insert_selected(ntree, gnode);
1061
/* update of the tree containing the group instance node */
1062
ntree->update |= NTREE_UPDATE_NODES;
1067
typedef enum eNodeGroupMakeType {
1070
} eNodeGroupMakeType;
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}
1079
static int node_group_make_exec(bContext *C, wmOperator *op)
1081
SpaceNode *snode = CTX_wm_space_node(C);
1083
int type = RNA_enum_get(op->ptr, "type");
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;
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)
1099
BKE_report(op->reports, RPT_WARNING, "Cannot add a Render Layers node in a group");
1100
return OPERATOR_CANCELLED;
1104
ED_preview_kill_jobs(C);
1108
if (node_group_make_test(snode->nodetree, NULL)) {
1109
gnode = node_group_make_from_selected(snode->nodetree);
1112
BKE_report(op->reports, RPT_WARNING, "Cannot make group");
1113
return OPERATOR_CANCELLED;
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;
1122
if (node_group_make_test(snode->nodetree, gnode)) {
1123
node_group_make_insert_selected(snode->nodetree, gnode);
1126
BKE_report(op->reports, RPT_WARNING, "Cannot insert into group");
1127
return OPERATOR_CANCELLED;
1133
nodeSetActive(snode->nodetree, gnode);
1134
snode_make_group_editable(snode, gnode);
1138
ntreeUpdateTree((bNodeTree *)gnode->id);
1139
ntreeUpdateTree(snode->nodetree);
1141
snode_notify(C, snode);
1142
snode_dag_update(C, snode);
1144
return OPERATOR_FINISHED;
1147
static int node_group_make_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
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);
1154
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
1155
uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_NEW);
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);
1162
uiPupMenuEnd(C, pup);
1164
return OPERATOR_CANCELLED;
1167
void NODE_OT_group_make(wmOperatorType *ot)
1171
ot->description = "Make group from selected nodes";
1172
ot->idname = "NODE_OT_group_make";
1175
ot->invoke = node_group_make_invoke;
1176
ot->exec = node_group_make_exec;
1177
ot->poll = ED_operator_node_active;
1180
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1182
RNA_def_enum(ot->srna, "type", node_group_make_types, NODE_GM_NEW, "Type", "");