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