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