Fix #34040: Moving Normal Node with enabled Cycles Material Preview crashes
[blender.git] / source / blender / editors / space_node / node_add.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_add.c
29  *  \ingroup spnode
30  */
31
32 #include <errno.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_node_types.h"
37
38 #include "BLI_listbase.h"
39 #include "BLI_math.h"
40
41 #include "BLF_translation.h"
42
43 #include "BKE_context.h"
44 #include "BKE_image.h"
45 #include "BKE_library.h"
46 #include "BKE_main.h"
47 #include "BKE_node.h"
48 #include "BKE_report.h"
49
50 #include "ED_node.h"  /* own include */
51 #include "ED_screen.h"
52 #include "ED_render.h"
53
54 #include "RNA_access.h"
55 #include "RNA_define.h"
56 #include "RNA_enum_types.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 #include "UI_view2d.h"
62
63 #include "node_intern.h"  /* own include */
64
65 /* can be called from menus too, but they should do own undopush and redraws */
66 bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene,
67                      bNodeTemplate *ntemp, float locx, float locy)
68 {
69         bNode *node = NULL, *gnode;
70
71         node_deselect_all(snode);
72
73         node = nodeAddNode(snode->edittree, ntemp);
74
75         /* generics */
76         if (node) {
77                 node_select(node);
78
79                 /* node location is mapped */
80                 locx /= UI_DPI_FAC;
81                 locy /= UI_DPI_FAC;
82                 
83                 gnode = node_tree_get_editgroup(snode->nodetree);
84                 // arbitrary y offset of 60 so its visible
85                 if (gnode) {
86                         node_from_view(gnode, locx, locy + 60.0f, &node->locx, &node->locy);
87                 }
88                 else {
89                         node->locx = locx;
90                         node->locy = locy + 60.0f;
91                 }
92
93                 ntreeUpdateTree(snode->edittree);
94                 ED_node_set_active(bmain, snode->edittree, node);
95
96                 if (snode->nodetree->type == NTREE_COMPOSIT) {
97                         if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
98                                 node->id = &scene->id;
99                         }
100                         else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
101                                 node->id = (ID *)scene->clip;
102                         }
103
104                         ntreeCompositForceHidden(snode->edittree, scene);
105                 }
106
107                 if (node->id)
108                         id_us_plus(node->id);
109
110
111                 if (snode->flag & SNODE_USE_HIDDEN_PREVIEW)
112                         node->flag &= ~NODE_PREVIEW;
113
114                 snode_update(snode, node);
115         }
116
117         if (snode->nodetree->type == NTREE_TEXTURE) {
118                 ntreeTexCheckCyclics(snode->edittree);
119         }
120
121         return node;
122 }
123
124 /* ********************** Add reroute operator ***************** */
125 static int add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int tot, float result[2])
126 {
127         float coord_array[NODE_LINK_RESOL + 1][2];
128         int i, b;
129
130         if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
131
132                 for (i = 0; i < tot - 1; i++)
133                         for (b = 0; b < NODE_LINK_RESOL; b++)
134                                 if (isect_line_line_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) {
135                                         result[0] = (mcoords[i][0] + mcoords[i + 1][0]) / 2.0f;
136                                         result[1] = (mcoords[i][1] + mcoords[i + 1][1]) / 2.0f;
137                                         return 1;
138                                 }
139         }
140         return 0;
141 }
142
143 typedef struct bNodeSocketLink {
144         struct bNodeSocketLink *next, *prev;
145         
146         struct bNodeSocket *sock;
147         struct bNodeLink *link;
148         float point[2];
149 } bNodeSocketLink;
150
151 static bNodeSocketLink *add_reroute_insert_socket_link(ListBase *lb, bNodeSocket *sock, bNodeLink *link, float point[2])
152 {
153         bNodeSocketLink *socklink, *prev;
154         
155         socklink = MEM_callocN(sizeof(bNodeSocketLink), "socket link");
156         socklink->sock = sock;
157         socklink->link = link;
158         copy_v2_v2(socklink->point, point);
159         
160         for (prev = lb->last; prev; prev = prev->prev) {
161                 if (prev->sock == sock)
162                         break;
163         }
164         BLI_insertlinkafter(lb, prev, socklink);
165         return socklink;
166 }
167
168 static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLink *socklink, int in_out)
169 {
170         SpaceNode *snode = CTX_wm_space_node(C);
171         bNodeTree *ntree = snode->edittree;
172         bNode *reroute_node = NULL;
173         bNodeSocket *cursock = socklink->sock;
174         float insert_point[2];
175         int num_links;
176         
177         zero_v2(insert_point);
178         num_links = 0;
179         
180         while (socklink && socklink->sock == cursock) {
181                 if (!(socklink->link->flag & NODE_LINK_TEST)) {
182                         socklink->link->flag |= NODE_LINK_TEST;
183                         
184                         /* create the reroute node for this cursock */
185                         if (!reroute_node) {
186                                 bNodeTemplate ntemp;
187                                 ntemp.type = NODE_REROUTE;
188                                 reroute_node = nodeAddNode(ntree, &ntemp);
189                                 
190                                 /* add a single link to/from the reroute node to replace multiple links */
191                                 if (in_out == SOCK_OUT) {
192                                         nodeAddLink(ntree, socklink->link->fromnode, socklink->link->fromsock, reroute_node, reroute_node->inputs.first);
193                                 }
194                                 else {
195                                         nodeAddLink(ntree, reroute_node, reroute_node->outputs.first, socklink->link->tonode, socklink->link->tosock);
196                                 }
197                         }
198                         
199                         /* insert the reroute node into the link */
200                         if (in_out == SOCK_OUT) {
201                                 socklink->link->fromnode = reroute_node;
202                                 socklink->link->fromsock = reroute_node->outputs.first;
203                         }
204                         else {
205                                 socklink->link->tonode = reroute_node;
206                                 socklink->link->tosock = reroute_node->inputs.first;
207                         }
208                         
209                         add_v2_v2(insert_point, socklink->point);
210                         num_links++;
211                 }
212                 socklink = socklink->next;
213         }
214         
215         if (num_links > 0) {
216                 bNode *gnode = node_tree_get_editgroup(snode->nodetree);
217                 
218                 /* average cut point from shared links */
219                 mul_v2_fl(insert_point, 1.0f / num_links);
220                 
221                 if (gnode) {
222                         node_from_view(gnode, insert_point[0], insert_point[1], &reroute_node->locx, &reroute_node->locy);
223                 }
224                 else {
225                         reroute_node->locx = insert_point[0];
226                         reroute_node->locy = insert_point[1];
227                 }
228         }
229         
230         return socklink;
231 }
232
233 static int add_reroute_exec(bContext *C, wmOperator *op)
234 {
235         SpaceNode *snode = CTX_wm_space_node(C);
236         ARegion *ar = CTX_wm_region(C);
237         bNodeTree *ntree = snode->edittree;
238         float mcoords[256][2];
239         int i = 0;
240         
241         /* Get the cut path */
242         RNA_BEGIN(op->ptr, itemptr, "path")
243         {
244                 float loc[2];
245
246                 RNA_float_get_array(&itemptr, "loc", loc);
247                 UI_view2d_region_to_view(&ar->v2d, (short)loc[0], (short)loc[1],
248                                          &mcoords[i][0], &mcoords[i][1]);
249                 i++;
250                 if (i >= 256) break;
251         }
252         RNA_END;
253
254         if (i > 1) {
255                 ListBase output_links, input_links;
256                 bNodeLink *link;
257                 bNodeSocketLink *socklink;
258                 float insert_point[2];
259                 
260                 /* always first */
261                 ED_preview_kill_jobs(C);
262                 
263                 node_deselect_all(snode);
264                 
265                 /* Find cut links and sort them by sockets */
266                 output_links.first = output_links.last = NULL;
267                 input_links.first = input_links.last = NULL;
268                 for (link = ntree->links.first; link; link = link->next) {
269                         if (add_reroute_intersect_check(link, mcoords, i, insert_point)) {
270                                 add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point);
271                                 add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point);
272                                 
273                                 /* Clear flag */
274                                 link->flag &= ~NODE_LINK_TEST;
275                         }
276                 }
277                 
278                 /* Create reroute nodes for intersected links.
279                  * Only one reroute if links share the same input/output socket.
280                  */
281                 socklink = output_links.first;
282                 while (socklink) {
283                         socklink = add_reroute_do_socket_section(C, socklink, SOCK_OUT);
284                 }
285                 socklink = input_links.first;
286                 while (socklink) {
287                         socklink = add_reroute_do_socket_section(C, socklink, SOCK_IN);
288                 }
289                 
290                 BLI_freelistN(&output_links);
291                 BLI_freelistN(&input_links);
292                 
293                 /* always last */
294                 ntreeUpdateTree(ntree);
295                 snode_notify(C, snode);
296                 snode_dag_update(C, snode);
297                 
298                 return OPERATOR_FINISHED;
299         }
300         
301         return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
302 }
303
304 void NODE_OT_add_reroute(wmOperatorType *ot)
305 {
306         PropertyRNA *prop;
307
308         ot->name = "Add Reroute";
309         ot->idname = "NODE_OT_add_reroute";
310
311         ot->invoke = WM_gesture_lines_invoke;
312         ot->modal = WM_gesture_lines_modal;
313         ot->exec = add_reroute_exec;
314         ot->cancel = WM_gesture_lines_cancel;
315
316         ot->poll = ED_operator_node_active;
317
318         /* flags */
319         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
320
321         prop = RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
322         RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
323         /* internal */
324         RNA_def_int(ot->srna, "cursor", BC_CROSSCURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
325 }
326
327
328 /* ****************** Add File Node Operator  ******************* */
329
330 static int node_add_file_exec(bContext *C, wmOperator *op)
331 {
332         Main *bmain = CTX_data_main(C);
333         Scene *scene = CTX_data_scene(C);
334         SpaceNode *snode = CTX_wm_space_node(C);
335         bNode *node;
336         Image *ima = NULL;
337         bNodeTemplate ntemp;
338
339         /* check input variables */
340         if (RNA_struct_property_is_set(op->ptr, "filepath")) {
341                 char path[FILE_MAX];
342                 RNA_string_get(op->ptr, "filepath", path);
343
344                 errno = 0;
345
346                 ima = BKE_image_load_exists(path);
347
348                 if (!ima) {
349                         BKE_reportf(op->reports, RPT_ERROR, "Cannot read image '%s': %s",
350                                     path, errno ? strerror(errno) : TIP_("unsupported format"));
351                         return OPERATOR_CANCELLED;
352                 }
353         }
354         else if (RNA_struct_property_is_set(op->ptr, "name")) {
355                 char name[MAX_ID_NAME - 2];
356                 RNA_string_get(op->ptr, "name", name);
357                 ima = (Image *)BKE_libblock_find_name(ID_IM, name);
358
359                 if (!ima) {
360                         BKE_reportf(op->reports, RPT_ERROR, "Image '%s' not found", name);
361                         return OPERATOR_CANCELLED;
362                 }
363         }
364
365         node_deselect_all(snode);
366
367         switch (snode->nodetree->type) {
368                 case NTREE_SHADER:
369                         ntemp.type = SH_NODE_TEX_IMAGE;
370                         break;
371                 case NTREE_TEXTURE:
372                         ntemp.type = TEX_NODE_IMAGE;
373                         break;
374                 case NTREE_COMPOSIT:
375                         ntemp.type = CMP_NODE_IMAGE;
376                         break;
377                 default:
378                         return OPERATOR_CANCELLED;
379         }
380
381         ED_preview_kill_jobs(C);
382
383         node = node_add_node(snode, bmain, scene, &ntemp, snode->cursor[0], snode->cursor[1]);
384
385         if (!node) {
386                 BKE_report(op->reports, RPT_WARNING, "Could not add an image node");
387                 return OPERATOR_CANCELLED;
388         }
389
390         node->id = (ID *)ima;
391         id_us_plus(node->id);
392
393         BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
394         WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
395
396         snode_notify(C, snode);
397         snode_dag_update(C, snode);
398
399         return OPERATOR_FINISHED;
400 }
401
402 static int node_add_file_invoke(bContext *C, wmOperator *op, wmEvent *event)
403 {
404         ARegion *ar = CTX_wm_region(C);
405         SpaceNode *snode = CTX_wm_space_node(C);
406
407         /* convert mouse coordinates to v2d space */
408         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
409                                  &snode->cursor[0], &snode->cursor[1]);
410
411         if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name"))
412                 return node_add_file_exec(C, op);
413         else
414                 return WM_operator_filesel(C, op, event);
415 }
416
417 void NODE_OT_add_file(wmOperatorType *ot)
418 {
419         /* identifiers */
420         ot->name = "Add File Node";
421         ot->description = "Add a file node to the current node editor";
422         ot->idname = "NODE_OT_add_file";
423
424         /* callbacks */
425         ot->exec = node_add_file_exec;
426         ot->invoke = node_add_file_invoke;
427         ot->poll = ED_operator_node_active;
428
429         /* flags */
430         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
431
432         WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE, FILE_SPECIAL, FILE_OPENFILE,
433                                        WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);  //XXX TODO, relative_path
434         RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Datablock name to assign");
435 }
436
437
438 /********************** New node tree operator *********************/
439
440 static int new_node_tree_exec(bContext *C, wmOperator *op)
441 {
442         SpaceNode *snode;
443         bNodeTree *ntree;
444         Main *bmain;
445         PointerRNA ptr, idptr;
446         PropertyRNA *prop;
447         int treetype;
448         char treename[MAX_ID_NAME - 2] = "NodeTree";
449
450         /* retrieve state */
451         snode = CTX_wm_space_node(C);
452         bmain = CTX_data_main(C);
453
454         if (RNA_struct_property_is_set(op->ptr, "type"))
455                 treetype = RNA_enum_get(op->ptr, "type");
456         else
457                 treetype = snode->treetype;
458
459         if (RNA_struct_property_is_set(op->ptr, "name"))
460                 RNA_string_get(op->ptr, "name", treename);
461
462         ntree = ntreeAddTree(bmain, treename, treetype, 0);
463         if (!ntree)
464                 return OPERATOR_CANCELLED;
465
466         /* hook into UI */
467         uiIDContextProperty(C, &ptr, &prop);
468
469         if (prop) {
470                 RNA_id_pointer_create(&ntree->id, &idptr);
471                 RNA_property_pointer_set(&ptr, prop, idptr);
472                 /* RNA_property_pointer_set increases the user count,
473                  * fixed here as the editor is the initial user.
474                  */
475                 ntree->id.us++;
476                 RNA_property_update(C, &ptr, prop);
477         }
478         else if (snode) {
479                 Scene *scene = CTX_data_scene(C);
480                 snode->nodetree = ntree;
481
482                 ED_node_tree_update(snode, scene);
483         }
484
485         return OPERATOR_FINISHED;
486 }
487
488 void NODE_OT_new_node_tree(wmOperatorType *ot)
489 {
490         /* identifiers */
491         ot->name = "New Node Tree";
492         ot->idname = "NODE_OT_new_node_tree";
493         ot->description = "Create a new node tree";
494
495         /* api callbacks */
496         ot->exec = new_node_tree_exec;
497         ot->poll = ED_operator_node_active;
498
499         /* flags */
500         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
501
502         RNA_def_enum(ot->srna, "type", nodetree_type_items, NTREE_COMPOSIT, "Tree Type", "");
503         RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME - 2, "Name", "");
504 }