1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2005 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup spnode
22 */
23
24 #include <stdlib.h>
25
26 #include "MEM_guardedalloc.h"
27
28 #include "DNA_anim_types.h"
29 #include "DNA_node_types.h"
30
31 #include "BLI_linklist.h"
32 #include "BLI_listbase.h"
33 #include "BLI_math.h"
34
35 #include "BLT_translation.h"
36
37 #include "BKE_action.h"
38 #include "BKE_animsys.h"
39 #include "BKE_context.h"
40 #include "BKE_lib_id.h"
41 #include "BKE_main.h"
42 #include "BKE_report.h"
43
44 #include "DEG_depsgraph_build.h"
45
46 #include "ED_node.h" /* own include */
47 #include "ED_render.h"
48 #include "ED_screen.h"
49
50 #include "RNA_access.h"
51 #include "RNA_define.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "UI_resources.h"
57
58 #include "NOD_common.h"
59 #include "NOD_socket.h"
60 #include "node_intern.h" /* own include */
61
node_group_operator_active(bContext * C)62 static bool node_group_operator_active(bContext *C)
63 {
64 if (ED_operator_node_active(C)) {
65 SpaceNode *snode = CTX_wm_space_node(C);
66
67 /* Group operators only defined for standard node tree types.
68 * Disabled otherwise to allow pynodes define their own operators
69 * with same keymap.
70 */
71 if (STREQ(snode->tree_idname, "ShaderNodeTree") ||
72 STREQ(snode->tree_idname, "CompositorNodeTree") ||
73 STREQ(snode->tree_idname, "TextureNodeTree") ||
74 STREQ(snode->tree_idname, "SimulationNodeTree")) {
75 return true;
76 }
77 }
78 return false;
79 }
80
node_group_operator_editable(bContext * C)81 static bool node_group_operator_editable(bContext *C)
82 {
83 if (ED_operator_node_editable(C)) {
84 SpaceNode *snode = CTX_wm_space_node(C);
85
86 /* Group operators only defined for standard node tree types.
87 * Disabled otherwise to allow pynodes define their own operators
88 * with same keymap.
89 */
90 if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode) ||
91 ED_node_is_simulation(snode)) {
92 return true;
93 }
94 }
95 return false;
96 }
97
group_ntree_idname(bContext * C)98 static const char *group_ntree_idname(bContext *C)
99 {
100 SpaceNode *snode = CTX_wm_space_node(C);
101 return snode->tree_idname;
102 }
103
group_node_idname(bContext * C)104 static const char *group_node_idname(bContext *C)
105 {
106 SpaceNode *snode = CTX_wm_space_node(C);
107
108 if (ED_node_is_shader(snode)) {
109 return "ShaderNodeGroup";
110 }
111 if (ED_node_is_compositor(snode)) {
112 return "CompositorNodeGroup";
113 }
114 if (ED_node_is_texture(snode)) {
115 return "TextureNodeGroup";
116 }
117 if (ED_node_is_simulation(snode)) {
118 return "SimulationNodeGroup";
119 }
120
121 return "";
122 }
123
node_group_get_active(bContext * C,const char * node_idname)124 static bNode *node_group_get_active(bContext *C, const char *node_idname)
125 {
126 SpaceNode *snode = CTX_wm_space_node(C);
127 bNode *node = nodeGetActive(snode->edittree);
128
129 if (node && STREQ(node->idname, node_idname)) {
130 return node;
131 }
132 return NULL;
133 }
134
135 /* ***************** Edit Group operator ************* */
136
node_group_edit_exec(bContext * C,wmOperator * op)137 static int node_group_edit_exec(bContext *C, wmOperator *op)
138 {
139 SpaceNode *snode = CTX_wm_space_node(C);
140 const char *node_idname = group_node_idname(C);
141 const bool exit = RNA_boolean_get(op->ptr, "exit");
142
143 ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
144
145 bNode *gnode = node_group_get_active(C, node_idname);
146
147 if (gnode && !exit) {
148 bNodeTree *ngroup = (bNodeTree *)gnode->id;
149
150 if (ngroup) {
151 ED_node_tree_push(snode, ngroup, gnode);
152 }
153 }
154 else {
155 ED_node_tree_pop(snode);
156 }
157
158 WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
159
160 return OPERATOR_FINISHED;
161 }
162
NODE_OT_group_edit(wmOperatorType * ot)163 void NODE_OT_group_edit(wmOperatorType *ot)
164 {
165 /* identifiers */
166 ot->name = "Edit Group";
167 ot->description = "Edit node group";
168 ot->idname = "NODE_OT_group_edit";
169
170 /* api callbacks */
171 ot->exec = node_group_edit_exec;
172 ot->poll = node_group_operator_active;
173
174 /* flags */
175 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
176
177 RNA_def_boolean(ot->srna, "exit", false, "Exit", "");
178 }
179
180 /* ******************** Ungroup operator ********************** */
181
182 /* The given paths will be owned by the returned instance. Both pointers are allowed to point to
183 * the same string. */
animation_basepath_change_new(const char * src_basepath,const char * dst_basepath)184 static AnimationBasePathChange *animation_basepath_change_new(const char *src_basepath,
185 const char *dst_basepath)
186 {
187 AnimationBasePathChange *basepath_change = MEM_callocN(sizeof(*basepath_change), AT);
188 basepath_change->src_basepath = src_basepath;
189 basepath_change->dst_basepath = dst_basepath;
190 return basepath_change;
191 }
192
animation_basepath_change_free(AnimationBasePathChange * basepath_change)193 static void animation_basepath_change_free(AnimationBasePathChange *basepath_change)
194 {
195 if (basepath_change->src_basepath != basepath_change->dst_basepath) {
196 MEM_freeN((void *)basepath_change->src_basepath);
197 }
198 MEM_freeN((void *)basepath_change->dst_basepath);
199 MEM_freeN(basepath_change);
200 }
201
202 /* returns 1 if its OK */
node_group_ungroup(Main * bmain,bNodeTree * ntree,bNode * gnode)203 static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
204 {
205 /* clear new pointers, set in copytree */
206 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
207 node->new_node = NULL;
208 }
209
210 ListBase anim_basepaths = {NULL, NULL};
211 LinkNode *nodes_delayed_free = NULL;
212 bNodeTree *ngroup = (bNodeTree *)gnode->id;
213
214 /* wgroup is a temporary copy of the NodeTree we're merging in
215 * - all of wgroup's nodes are copied across to their new home
216 * - ngroup (i.e. the source NodeTree) is left unscathed
217 * - temp copy. do change ID usercount for the copies
218 */
219 bNodeTree *wgroup = ntreeCopyTree_ex_new_pointers(ngroup, bmain, true);
220
221 /* Add the nodes into the ntree */
222 LISTBASE_FOREACH_MUTABLE (bNode *, node, &wgroup->nodes) {
223 /* Remove interface nodes.
224 * This also removes remaining links to and from interface nodes.
225 */
226 if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
227 /* We must delay removal since sockets will reference this node. see: T52092 */
228 BLI_linklist_prepend(&nodes_delayed_free, node);
229 }
230
231 /* keep track of this node's RNA "base" path (the part of the path identifying the node)
232 * if the old nodetree has animation data which potentially covers this node
233 */
234 const char *old_animation_basepath = NULL;
235 if (wgroup->adt) {
236 PointerRNA ptr;
237 RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
238 old_animation_basepath = RNA_path_from_ID_to_struct(&ptr);
239 }
240
241 /* migrate node */
242 BLI_remlink(&wgroup->nodes, node);
243 BLI_addtail(&ntree->nodes, node);
244
245 /* ensure unique node name in the node tree */
246 nodeUniqueName(ntree, node);
247
248 if (wgroup->adt) {
249 PointerRNA ptr;
250 RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
251 const char *new_animation_basepath = RNA_path_from_ID_to_struct(&ptr);
252 BLI_addtail(&anim_basepaths,
253 animation_basepath_change_new(old_animation_basepath, new_animation_basepath));
254 }
255
256 if (!node->parent) {
257 node->locx += gnode->locx;
258 node->locy += gnode->locy;
259 }
260
261 node->flag |= NODE_SELECT;
262 }
263
264 bNodeLink *glinks_first = ntree->links.last;
265
266 /* Add internal links to the ntree */
267 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &wgroup->links) {
268 BLI_remlink(&wgroup->links, link);
269 BLI_addtail(&ntree->links, link);
270 }
271
272 bNodeLink *glinks_last = ntree->links.last;
273
274 /* and copy across the animation,
275 * note that the animation data's action can be NULL here */
276 if (wgroup->adt) {
277 bAction *waction;
278
279 /* firstly, wgroup needs to temporary dummy action
280 * that can be destroyed, as it shares copies */
281 waction = wgroup->adt->action = (bAction *)BKE_id_copy(bmain, &wgroup->adt->action->id);
282
283 /* now perform the moving */
284 BKE_animdata_transfer_by_basepath(bmain, &wgroup->id, &ntree->id, &anim_basepaths);
285
286 /* paths + their wrappers need to be freed */
287 LISTBASE_FOREACH_MUTABLE (AnimationBasePathChange *, basepath_change, &anim_basepaths) {
288 animation_basepath_change_free(basepath_change);
289 }
290
291 /* free temp action too */
292 if (waction) {
293 BKE_id_free(bmain, waction);
294 wgroup->adt->action = NULL;
295 }
296 }
297
298 /* free the group tree (takes care of user count) */
299 BKE_id_free(bmain, wgroup);
300
301 /* restore external links to and from the gnode */
302
303 /* input links */
304 if (glinks_first != NULL) {
305 for (bNodeLink *link = glinks_first->next; link != glinks_last->next; link = link->next) {
306 if (link->fromnode->type == NODE_GROUP_INPUT) {
307 const char *identifier = link->fromsock->identifier;
308 int num_external_links = 0;
309
310 /* find external links to this input */
311 for (bNodeLink *tlink = ntree->links.first; tlink != glinks_first->next;
312 tlink = tlink->next) {
313 if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
314 nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
315 num_external_links++;
316 }
317 }
318
319 /* if group output is not externally linked,
320 * convert the constant input value to ensure somewhat consistent behavior */
321 if (num_external_links == 0) {
322 /* TODO */
323 #if 0
324 bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
325 BLI_assert(sock);
326
327 nodeSocketCopy(
328 ntree, link->tosock->new_sock, link->tonode->new_node, ntree, sock, gnode);
329 #endif
330 }
331 }
332 }
333
334 /* Also iterate over new links to cover passthrough links. */
335 glinks_last = ntree->links.last;
336
337 /* output links */
338 for (bNodeLink *link = ntree->links.first; link != glinks_first->next; link = link->next) {
339 if (link->fromnode == gnode) {
340 const char *identifier = link->fromsock->identifier;
341 int num_internal_links = 0;
342
343 /* find internal links to this output */
344 for (bNodeLink *tlink = glinks_first->next; tlink != glinks_last->next;
345 tlink = tlink->next) {
346 /* only use active output node */
347 if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
348 if (STREQ(tlink->tosock->identifier, identifier)) {
349 nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode, link->tosock);
350 num_internal_links++;
351 }
352 }
353 }
354
355 /* if group output is not internally linked,
356 * convert the constant output value to ensure somewhat consistent behavior */
357 if (num_internal_links == 0) {
358 /* TODO */
359 #if 0
360 bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
361 BLI_assert(sock);
362
363 nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode);
364 #endif
365 }
366 }
367 }
368 }
369
370 while (nodes_delayed_free) {
371 bNode *node = BLI_linklist_pop(&nodes_delayed_free);
372 nodeRemoveNode(bmain, ntree, node, false);
373 }
374
375 /* delete the group instance and dereference group tree */
376 nodeRemoveNode(bmain, ntree, gnode, true);
377
378 ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
379
380 return 1;
381 }
382
node_group_ungroup_exec(bContext * C,wmOperator * op)383 static int node_group_ungroup_exec(bContext *C, wmOperator *op)
384 {
385 Main *bmain = CTX_data_main(C);
386 SpaceNode *snode = CTX_wm_space_node(C);
387 const char *node_idname = group_node_idname(C);
388
389 ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
390
391 bNode *gnode = node_group_get_active(C, node_idname);
392 if (!gnode) {
393 return OPERATOR_CANCELLED;
394 }
395
396 if (gnode->id && node_group_ungroup(bmain, snode->edittree, gnode)) {
397 ntreeUpdateTree(bmain, snode->nodetree);
398 }
399 else {
400 BKE_report(op->reports, RPT_WARNING, "Cannot ungroup");
401 return OPERATOR_CANCELLED;
402 }
403
404 snode_notify(C, snode);
405 snode_dag_update(C, snode);
406
407 return OPERATOR_FINISHED;
408 }
409
NODE_OT_group_ungroup(wmOperatorType * ot)410 void NODE_OT_group_ungroup(wmOperatorType *ot)
411 {
412 /* identifiers */
413 ot->name = "Ungroup";
414 ot->description = "Ungroup selected nodes";
415 ot->idname = "NODE_OT_group_ungroup";
416
417 /* api callbacks */
418 ot->exec = node_group_ungroup_exec;
419 ot->poll = node_group_operator_editable;
420
421 /* flags */
422 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
423 }
424
425 /* ******************** Separate operator ********************** */
426
427 /* returns 1 if its OK */
node_group_separate_selected(Main * bmain,bNodeTree * ntree,bNodeTree * ngroup,float offx,float offy,int make_copy)428 static int node_group_separate_selected(
429 Main *bmain, bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy)
430 {
431 /* deselect all nodes in the target tree */
432 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
433 nodeSetSelected(node, false);
434 }
435
436 /* clear new pointers, set in BKE_node_copy_ex(). */
437 LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) {
438 node->new_node = NULL;
439 }
440
441 ListBase anim_basepaths = {NULL, NULL};
442
443 /* add selected nodes into the ntree */
444 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ngroup->nodes) {
445 if (!(node->flag & NODE_SELECT)) {
446 continue;
447 }
448
449 /* ignore interface nodes */
450 if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
451 nodeSetSelected(node, false);
452 continue;
453 }
454
455 bNode *newnode;
456 if (make_copy) {
457 /* make a copy */
458 newnode = BKE_node_copy_store_new_pointers(ngroup, node, LIB_ID_COPY_DEFAULT);
459 }
460 else {
461 /* use the existing node */
462 newnode = node;
463 }
464
465 /* keep track of this node's RNA "base" path (the part of the path identifying the node)
466 * if the old nodetree has animation data which potentially covers this node
467 */
468 if (ngroup->adt) {
469 PointerRNA ptr;
470 char *path;
471
472 RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
473 path = RNA_path_from_ID_to_struct(&ptr);
474
475 if (path) {
476 BLI_addtail(&anim_basepaths, animation_basepath_change_new(path, path));
477 }
478 }
479
480 /* ensure valid parent pointers, detach if parent stays inside the group */
481 if (newnode->parent && !(newnode->parent->flag & NODE_SELECT)) {
482 nodeDetachNode(newnode);
483 }
484
485 /* migrate node */
486 BLI_remlink(&ngroup->nodes, newnode);
487 BLI_addtail(&ntree->nodes, newnode);
488
489 /* ensure unique node name in the node tree */
490 nodeUniqueName(ntree, newnode);
491
492 if (!newnode->parent) {
493 newnode->locx += offx;
494 newnode->locy += offy;
495 }
496 }
497
498 /* add internal links to the ntree */
499 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ngroup->links) {
500 const bool fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
501 const bool toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
502
503 if (make_copy) {
504 /* make a copy of internal links */
505 if (fromselect && toselect) {
506 nodeAddLink(ntree,
507 link->fromnode->new_node,
508 link->fromsock->new_sock,
509 link->tonode->new_node,
510 link->tosock->new_sock);
511 }
512 }
513 else {
514 /* move valid links over, delete broken links */
515 if (fromselect && toselect) {
516 BLI_remlink(&ngroup->links, link);
517 BLI_addtail(&ntree->links, link);
518 }
519 else if (fromselect || toselect) {
520 nodeRemLink(ngroup, link);
521 }
522 }
523 }
524
525 /* and copy across the animation,
526 * note that the animation data's action can be NULL here */
527 if (ngroup->adt) {
528 /* now perform the moving */
529 BKE_animdata_transfer_by_basepath(bmain, &ngroup->id, &ntree->id, &anim_basepaths);
530
531 /* paths + their wrappers need to be freed */
532 LISTBASE_FOREACH_MUTABLE (AnimationBasePathChange *, basepath_change, &anim_basepaths) {
533 animation_basepath_change_free(basepath_change);
534 }
535 }
536
537 ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
538 if (!make_copy) {
539 ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
540 }
541
542 return 1;
543 }
544
545 typedef enum eNodeGroupSeparateType {
546 NODE_GS_COPY,
547 NODE_GS_MOVE,
548 } eNodeGroupSeparateType;
549
550 /* Operator Property */
551 static const EnumPropertyItem node_group_separate_types[] = {
552 {NODE_GS_COPY, "COPY", 0, "Copy", "Copy to parent node tree, keep group intact"},
553 {NODE_GS_MOVE, "MOVE", 0, "Move", "Move to parent node tree, remove from group"},
554 {0, NULL, 0, NULL, NULL},
555 };
556
node_group_separate_exec(bContext * C,wmOperator * op)557 static int node_group_separate_exec(bContext *C, wmOperator *op)
558 {
559 Main *bmain = CTX_data_main(C);
560 SpaceNode *snode = CTX_wm_space_node(C);
561 int type = RNA_enum_get(op->ptr, "type");
562
563 ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
564
565 /* are we inside of a group? */
566 bNodeTree *ngroup = snode->edittree;
567 bNodeTree *nparent = ED_node_tree_get(snode, 1);
568 if (!nparent) {
569 BKE_report(op->reports, RPT_WARNING, "Not inside node group");
570 return OPERATOR_CANCELLED;
571 }
572 /* get node tree offset */
573 float offx, offy;
574 space_node_group_offset(snode, &offx, &offy);
575
576 switch (type) {
577 case NODE_GS_COPY:
578 if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, true)) {
579 BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
580 return OPERATOR_CANCELLED;
581 }
582 break;
583 case NODE_GS_MOVE:
584 if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, false)) {
585 BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
586 return OPERATOR_CANCELLED;
587 }
588 break;
589 }
590
591 /* switch to parent tree */
592 ED_node_tree_pop(snode);
593
594 ntreeUpdateTree(CTX_data_main(C), snode->nodetree);
595
596 snode_notify(C, snode);
597 snode_dag_update(C, snode);
598
599 return OPERATOR_FINISHED;
600 }
601
node_group_separate_invoke(bContext * C,wmOperator * UNUSED (op),const wmEvent * UNUSED (event))602 static int node_group_separate_invoke(bContext *C,
603 wmOperator *UNUSED(op),
604 const wmEvent *UNUSED(event))
605 {
606 uiPopupMenu *pup = UI_popup_menu_begin(
607 C, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
608 uiLayout *layout = UI_popup_menu_layout(pup);
609
610 uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
611 uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
612 uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
613
614 UI_popup_menu_end(C, pup);
615
616 return OPERATOR_INTERFACE;
617 }
618
NODE_OT_group_separate(wmOperatorType * ot)619 void NODE_OT_group_separate(wmOperatorType *ot)
620 {
621 /* identifiers */
622 ot->name = "Separate";
623 ot->description = "Separate selected nodes from the node group";
624 ot->idname = "NODE_OT_group_separate";
625
626 /* api callbacks */
627 ot->invoke = node_group_separate_invoke;
628 ot->exec = node_group_separate_exec;
629 ot->poll = node_group_operator_editable;
630
631 /* flags */
632 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
633
634 RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
635 }
636
637 /* ****************** Make Group operator ******************* */
638
node_group_make_use_node(bNode * node,bNode * gnode)639 static bool node_group_make_use_node(bNode *node, bNode *gnode)
640 {
641 return (node != gnode && !ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT) &&
642 (node->flag & NODE_SELECT));
643 }
644
node_group_make_test_selected(bNodeTree * ntree,bNode * gnode,const char * ntree_idname,struct ReportList * reports)645 static bool node_group_make_test_selected(bNodeTree *ntree,
646 bNode *gnode,
647 const char *ntree_idname,
648 struct ReportList *reports)
649 {
650 int ok = true;
651
652 /* make a local pseudo node tree to pass to the node poll functions */
653 bNodeTree *ngroup = ntreeAddTree(NULL, "Pseudo Node Group", ntree_idname);
654
655 /* check poll functions for selected nodes */
656 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
657 if (node_group_make_use_node(node, gnode)) {
658 if (node->typeinfo->poll_instance && !node->typeinfo->poll_instance(node, ngroup)) {
659 BKE_reportf(reports, RPT_WARNING, "Can not add node '%s' in a group", node->name);
660 ok = false;
661 break;
662 }
663 }
664
665 node->done = 0;
666 }
667
668 /* free local pseudo node tree again */
669 ntreeFreeTree(ngroup);
670 MEM_freeN(ngroup);
671 if (!ok) {
672 return false;
673 }
674
675 /* check if all connections are OK, no unselected node has both
676 * inputs and outputs to a selection */
677 LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
678 if (node_group_make_use_node(link->fromnode, gnode)) {
679 link->tonode->done |= 1;
680 }
681 if (node_group_make_use_node(link->tonode, gnode)) {
682 link->fromnode->done |= 2;
683 }
684 }
685 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
686 if (!(node->flag & NODE_SELECT) && node != gnode && node->done == 3) {
687 return false;
688 }
689 }
690 return true;
691 }
692
node_get_selected_minmax(bNodeTree * ntree,bNode * gnode,float * min,float * max,bool use_size)693 static int node_get_selected_minmax(
694 bNodeTree *ntree, bNode *gnode, float *min, float *max, bool use_size)
695 {
696 int totselect = 0;
697
698 INIT_MINMAX2(min, max);
699 LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
700 if (node_group_make_use_node(node, gnode)) {
701 float loc[2];
702 nodeToView(node, node->offsetx, node->offsety, &loc[0], &loc[1]);
703 minmax_v2v2_v2(min, max, loc);
704 if (use_size) {
705 loc[0] += node->width;
706 loc[1] -= node->height;
707 minmax_v2v2_v2(min, max, loc);
708 }
709 totselect++;
710 }
711 }
712
713 /* sane min/max if no selected nodes */
714 if (totselect == 0) {
715 min[0] = min[1] = max[0] = max[1] = 0.0f;
716 }
717
718 return totselect;
719 }
720
node_group_make_insert_selected(const bContext * C,bNodeTree * ntree,bNode * gnode)721 static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, bNode *gnode)
722 {
723 Main *bmain = CTX_data_main(C);
724 bNodeTree *ngroup = (bNodeTree *)gnode->id;
725 bool expose_visible = false;
726
727 /* XXX rough guess, not nice but we don't have access to UI constants here ... */
728 static const float offsetx = 200;
729 static const float offsety = 0.0f;
730
731 /* deselect all nodes in the target tree */
732 LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) {
733 nodeSetSelected(node, false);
734 }
735
736 float center[2], min[2], max[2];
737 const int totselect = node_get_selected_minmax(ntree, gnode, min, max, false);
738 add_v2_v2v2(center, min, max);
739 mul_v2_fl(center, 0.5f);
740
741 float real_min[2], real_max[2];
742 node_get_selected_minmax(ntree, gnode, real_min, real_max, true);
743
744 /* auto-add interface for "solo" nodes */
745 if (totselect == 1) {
746 expose_visible = true;
747 }
748
749 ListBase anim_basepaths = {NULL, NULL};
750
751 /* move nodes over */
752 LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
753 if (node_group_make_use_node(node, gnode)) {
754 /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
755 * if the old nodetree has animation data which potentially covers this node
756 */
757 if (ntree->adt) {
758 PointerRNA ptr;
759 char *path;
760
761 RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
762 path = RNA_path_from_ID_to_struct(&ptr);
763
764 if (path) {
765 BLI_addtail(&anim_basepaths, animation_basepath_change_new(path, path));
766 }
767 }
768
769 /* ensure valid parent pointers, detach if parent stays outside the group */
770 if (node->parent && !(node->parent->flag & NODE_SELECT)) {
771 nodeDetachNode(node);
772 }
773
774 /* change node-collection membership */
775 BLI_remlink(&ntree->nodes, node);
776 BLI_addtail(&ngroup->nodes, node);
777
778 /* ensure unique node name in the ngroup */
779 nodeUniqueName(ngroup, node);
780 }
781 }
782
783 /* move animation data over */
784 if (ntree->adt) {
785 BKE_animdata_transfer_by_basepath(bmain, &ntree->id, &ngroup->id, &anim_basepaths);
786
787 /* paths + their wrappers need to be freed */
788 LISTBASE_FOREACH_MUTABLE (AnimationBasePathChange *, basepath_change, &anim_basepaths) {
789 animation_basepath_change_free(basepath_change);
790 }
791 }
792
793 /* node groups don't use internal cached data */
794 ntreeFreeCache(ngroup);
795
796 /* create input node */
797 bNode *input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT);
798 input_node->locx = real_min[0] - center[0] - offsetx;
799 input_node->locy = -offsety;
800
801 /* create output node */
802 bNode *output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT);
803 output_node->locx = real_max[0] - center[0] + offsetx * 0.25f;
804 output_node->locy = -offsety;
805
806 /* relink external sockets */
807 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
808 int fromselect = node_group_make_use_node(link->fromnode, gnode);
809 int toselect = node_group_make_use_node(link->tonode, gnode);
810
811 if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) {
812 /* remove all links to/from the gnode.
813 * this can remove link information, but there's no general way to preserve it.
814 */
815 nodeRemLink(ntree, link);
816 }
817 else if (toselect && !fromselect) {
818 bNodeSocket *link_sock;
819 bNode *link_node;
820 node_socket_skip_reroutes(&ntree->links, link->tonode, link->tosock, &link_node, &link_sock);
821 bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link_node, link_sock);
822
823 /* update the group node and interface node sockets,
824 * so the new interface socket can be linked.
825 */
826 node_group_update(ntree, gnode);
827 node_group_input_update(ngroup, input_node);
828
829 /* create new internal link */
830 bNodeSocket *input_sock = node_group_input_find_socket(input_node, iosock->identifier);
831 nodeAddLink(ngroup, input_node, input_sock, link->tonode, link->tosock);
832
833 /* redirect external link */
834 link->tonode = gnode;
835 link->tosock = node_group_find_input_socket(gnode, iosock->identifier);
836 }
837 else if (fromselect && !toselect) {
838 /* First check whether the source of this link is already connected to an output.
839 * If yes, reuse that output instead of duplicating it. */
840 bool connected = false;
841 LISTBASE_FOREACH (bNodeLink *, olink, &ngroup->links) {
842 if (olink->fromsock == link->fromsock && olink->tonode == output_node) {
843 bNodeSocket *output_sock = node_group_find_output_socket(gnode,
844 olink->tosock->identifier);
845 link->fromnode = gnode;
846 link->fromsock = output_sock;
847 connected = true;
848 }
849 }
850
851 if (!connected) {
852 bNodeSocket *link_sock;
853 bNode *link_node;
854 node_socket_skip_reroutes(
855 &ntree->links, link->fromnode, link->fromsock, &link_node, &link_sock);
856 bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link_node, link_sock);
857
858 /* update the group node and interface node sockets,
859 * so the new interface socket can be linked.
860 */
861 node_group_update(ntree, gnode);
862 node_group_output_update(ngroup, output_node);
863
864 /* create new internal link */
865 bNodeSocket *output_sock = node_group_output_find_socket(output_node, iosock->identifier);
866 nodeAddLink(ngroup, link->fromnode, link->fromsock, output_node, output_sock);
867
868 /* redirect external link */
869 link->fromnode = gnode;
870 link->fromsock = node_group_find_output_socket(gnode, iosock->identifier);
871 }
872 }
873 }
874
875 /* move internal links */
876 LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
877 int fromselect = node_group_make_use_node(link->fromnode, gnode);
878 int toselect = node_group_make_use_node(link->tonode, gnode);
879
880 if (fromselect && toselect) {
881 BLI_remlink(&ntree->links, link);
882 BLI_addtail(&ngroup->links, link);
883 }
884 }
885
886 /* move nodes in the group to the center */
887 LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) {
888 if (node_group_make_use_node(node, gnode) && !node->parent) {
889 node->locx -= center[0];
890 node->locy -= center[1];
891 }
892 }
893
894 /* expose all unlinked sockets too but only the visible ones*/
895 if (expose_visible) {
896 LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) {
897 if (node_group_make_use_node(node, gnode)) {
898 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
899 bool skip = false;
900 LISTBASE_FOREACH (bNodeLink *, link, &ngroup->links) {
901 if (link->tosock == sock) {
902 skip = true;
903 break;
904 }
905 }
906 if (sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) {
907 skip = true;
908 }
909 if (skip) {
910 continue;
911 }
912
913 bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
914
915 node_group_input_update(ngroup, input_node);
916
917 /* create new internal link */
918 bNodeSocket *input_sock = node_group_input_find_socket(input_node, iosock->identifier);
919 nodeAddLink(ngroup, input_node, input_sock, node, sock);
920 }
921
922 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
923 bool skip = false;
924 LISTBASE_FOREACH (bNodeLink *, link, &ngroup->links) {
925 if (link->fromsock == sock) {
926 skip = true;
927 }
928 }
929 if (sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) {
930 skip = true;
931 }
932 if (skip) {
933 continue;
934 }
935
936 bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
937
938 node_group_output_update(ngroup, output_node);
939
940 /* create new internal link */
941 bNodeSocket *output_sock = node_group_output_find_socket(output_node,
942 iosock->identifier);
943 nodeAddLink(ngroup, node, sock, output_node, output_sock);
944 }
945 }
946 }
947 }
948
949 /* update of the group tree */
950 ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS;
951 /* update of the tree containing the group instance node */
952 ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
953 }
954
node_group_make_from_selected(const bContext * C,bNodeTree * ntree,const char * ntype,const char * ntreetype)955 static bNode *node_group_make_from_selected(const bContext *C,
956 bNodeTree *ntree,
957 const char *ntype,
958 const char *ntreetype)
959 {
960 Main *bmain = CTX_data_main(C);
961
962 float min[2], max[2];
963 const int totselect = node_get_selected_minmax(ntree, NULL, min, max, false);
964 /* don't make empty group */
965 if (totselect == 0) {
966 return NULL;
967 }
968
969 /* new nodetree */
970 bNodeTree *ngroup = ntreeAddTree(bmain, "NodeGroup", ntreetype);
971
972 /* make group node */
973 bNode *gnode = nodeAddNode(C, ntree, ntype);
974 gnode->id = (ID *)ngroup;
975
976 gnode->locx = 0.5f * (min[0] + max[0]);
977 gnode->locy = 0.5f * (min[1] + max[1]);
978
979 node_group_make_insert_selected(C, ntree, gnode);
980
981 /* update of the tree containing the group instance node */
982 ntree->update |= NTREE_UPDATE_NODES;
983
984 return gnode;
985 }
986
node_group_make_exec(bContext * C,wmOperator * op)987 static int node_group_make_exec(bContext *C, wmOperator *op)
988 {
989 SpaceNode *snode = CTX_wm_space_node(C);
990 bNodeTree *ntree = snode->edittree;
991 const char *ntree_idname = group_ntree_idname(C);
992 const char *node_idname = group_node_idname(C);
993 Main *bmain = CTX_data_main(C);
994
995 ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
996
997 if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports)) {
998 return OPERATOR_CANCELLED;
999 }
1000
1001 bNode *gnode = node_group_make_from_selected(C, ntree, node_idname, ntree_idname);
1002
1003 if (gnode) {
1004 bNodeTree *ngroup = (bNodeTree *)gnode->id;
1005
1006 nodeSetActive(ntree, gnode);
1007 if (ngroup) {
1008 ED_node_tree_push(snode, ngroup, gnode);
1009 ntreeUpdateTree(bmain, ngroup);
1010 }
1011 }
1012
1013 ntreeUpdateTree(bmain, ntree);
1014
1015 snode_notify(C, snode);
1016 snode_dag_update(C, snode);
1017
1018 /* We broke relations in node tree, need to rebuild them in the grahes. */
1019 DEG_relations_tag_update(bmain);
1020
1021 return OPERATOR_FINISHED;
1022 }
1023
NODE_OT_group_make(wmOperatorType * ot)1024 void NODE_OT_group_make(wmOperatorType *ot)
1025 {
1026 /* identifiers */
1027 ot->name = "Make Group";
1028 ot->description = "Make group from selected nodes";
1029 ot->idname = "NODE_OT_group_make";
1030
1031 /* api callbacks */
1032 ot->exec = node_group_make_exec;
1033 ot->poll = node_group_operator_editable;
1034
1035 /* flags */
1036 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1037 }
1038
1039 /* ****************** Group Insert operator ******************* */
1040
node_group_insert_exec(bContext * C,wmOperator * op)1041 static int node_group_insert_exec(bContext *C, wmOperator *op)
1042 {
1043 SpaceNode *snode = CTX_wm_space_node(C);
1044 bNodeTree *ntree = snode->edittree;
1045 const char *node_idname = group_node_idname(C);
1046 Main *bmain = CTX_data_main(C);
1047
1048 ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
1049
1050 bNode *gnode = node_group_get_active(C, node_idname);
1051
1052 if (!gnode || !gnode->id) {
1053 return OPERATOR_CANCELLED;
1054 }
1055
1056 bNodeTree *ngroup = (bNodeTree *)gnode->id;
1057 if (!node_group_make_test_selected(ntree, gnode, ngroup->idname, op->reports)) {
1058 return OPERATOR_CANCELLED;
1059 }
1060
1061 node_group_make_insert_selected(C, ntree, gnode);
1062
1063 nodeSetActive(ntree, gnode);
1064 ED_node_tree_push(snode, ngroup, gnode);
1065 ntreeUpdateTree(bmain, ngroup);
1066
1067 ntreeUpdateTree(bmain, ntree);
1068
1069 snode_notify(C, snode);
1070 snode_dag_update(C, snode);
1071
1072 return OPERATOR_FINISHED;
1073 }
1074
NODE_OT_group_insert(wmOperatorType * ot)1075 void NODE_OT_group_insert(wmOperatorType *ot)
1076 {
1077 /* identifiers */
1078 ot->name = "Group Insert";
1079 ot->description = "Insert selected nodes into a node group";
1080 ot->idname = "NODE_OT_group_insert";
1081
1082 /* api callbacks */
1083 ot->exec = node_group_insert_exec;
1084 ot->poll = node_group_operator_editable;
1085
1086 /* flags */
1087 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1088 }
1089