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