Cleanup: use `rna_enum_` prefix for RNA enums
[blender.git] / source / blender / editors / space_node / node_edit.c
index f9b5b09778710dcfd7b5334db9195965b256d692..e4861a713b7b954e0c6247f7c44a2a64270ae8b1 100644 (file)
@@ -31,7 +31,6 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "DNA_action_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_material_types.h"
 #include "DNA_node_types.h"
@@ -73,8 +72,6 @@
 #include "IMB_imbuf_types.h"
 
 #include "node_intern.h"  /* own include */
-#include "NOD_common.h"
-#include "NOD_socket.h"
 #include "NOD_composite.h"
 #include "NOD_shader.h"
 #include "NOD_texture.h"
@@ -96,7 +93,6 @@ typedef struct CompoJob {
        const short *stop;
        short *do_update;
        float *progress;
-       short need_sync;
        int recalc_flags;
 } CompoJob;
 
@@ -165,13 +161,12 @@ static int compo_breakjob(void *cjv)
                );
 }
 
-/* called by compo, wmJob sends notifier, old compositor system only */
-static void compo_statsdrawjob(void *cjv, char *UNUSED(str))
+/* called by compo, wmJob sends notifier */
+static void compo_statsdrawjob(void *cjv, const char *UNUSED(str))
 {
        CompoJob *cj = cjv;
        
        *(cj->do_update) = true;
-       cj->need_sync = true;
 }
 
 /* called by compo, wmJob sends notifier */
@@ -205,17 +200,8 @@ static void compo_initjob(void *cjv)
 }
 
 /* called before redraw notifiers, it moves finished previews over */
-static void compo_updatejob(void *cjv)
+static void compo_updatejob(void *UNUSED(cjv))
 {
-       CompoJob *cj = cjv;
-
-       if (cj->need_sync) {
-               /* was used by old compositor system only */
-               ntreeLocalSync(cj->localtree, cj->ntree);
-
-               cj->need_sync = false;
-       }
-
        WM_main_add_notifier(NC_SCENE | ND_COMPO_RESULT, NULL);
 }
 
@@ -226,13 +212,13 @@ static void compo_progressjob(void *cjv, float progress)
        *(cj->progress) = progress;
 }
 
-
 /* only this runs inside thread */
 static void compo_startjob(void *cjv, short *stop, short *do_update, float *progress)
 {
        CompoJob *cj = cjv;
        bNodeTree *ntree = cj->localtree;
        Scene *scene = cj->scene;
+       SceneRenderView *srv;
 
        if (scene->use_nodes == false)
                return;
@@ -252,7 +238,16 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog
 
        // XXX BIF_store_spare();
        /* 1 is do_previews */
-       ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings);
+
+       if ((cj->scene->r.scemode & R_MULTIVIEW) == 0) {
+               ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, "");
+       }
+       else {
+               for (srv = scene->r.views.first; srv; srv = srv->next) {
+                       if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) continue;
+                       ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, &scene->view_settings, &scene->display_settings, srv->name);
+               }
+       }
 
        ntree->test_break = NULL;
        ntree->stats_draw = NULL;
@@ -342,14 +337,22 @@ void snode_dag_update(bContext *C, SpaceNode *snode)
 
 void snode_notify(bContext *C, SpaceNode *snode)
 {
+       ID *id = snode->id;
+
        WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
 
-       if (ED_node_is_shader(snode))
-               WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id);
+       if (ED_node_is_shader(snode)) {
+               if (GS(id->name) == ID_MA)
+                       WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
+               else if (GS(id->name) == ID_LA)
+                       WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
+               else if (GS(id->name) == ID_WO)
+                       WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
+       }
        else if (ED_node_is_compositor(snode))
-               WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id);
+               WM_event_add_notifier(C, NC_SCENE | ND_NODES, id);
        else if (ED_node_is_texture(snode))
-               WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id);
+               WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, id);
 }
 
 void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
@@ -561,7 +564,7 @@ void snode_set_context(const bContext *C)
                return;
        }
        
-       if (snode->nodetree && strcmp(snode->nodetree->idname, snode->tree_idname) != 0) {
+       if (snode->nodetree && !STREQ(snode->nodetree->idname, snode->tree_idname)) {
                /* current tree does not match selected type, clear tree path */
                ntree = NULL;
                id = NULL;
@@ -640,11 +643,11 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
                /* tree specific activate calls */
                if (ntree->type == NTREE_SHADER) {
                        /* when we select a material, active texture is cleared, for buttons */
-                       if (node->id && ELEM3(GS(node->id->name), ID_MA, ID_LA, ID_WO))
+                       if (node->id && ELEM(GS(node->id->name), ID_MA, ID_LA, ID_WO))
                                nodeClearActiveID(ntree, ID_TE);
                        
-                       if (ELEM4(node->type, SH_NODE_OUTPUT, SH_NODE_OUTPUT_MATERIAL,
-                                 SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LAMP))
+                       if (ELEM(node->type, SH_NODE_OUTPUT, SH_NODE_OUTPUT_MATERIAL,
+                                SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LAMP, SH_NODE_OUTPUT_LINESTYLE))
                        {
                                bNode *tnode;
                                
@@ -662,11 +665,16 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
                        /* if active texture changed, free glsl materials */
                        if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
                                Material *ma;
+                               World *wo;
 
                                for (ma = bmain->mat.first; ma; ma = ma->id.next)
                                        if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree))
-                                               GPU_material_free(ma);
+                                               GPU_material_free(&ma->gpumaterial);
 
+                               for (wo = bmain->world.first; wo; wo = wo->id.next)
+                                       if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree))
+                                               GPU_material_free(&wo->gpumaterial);
+                               
                                WM_main_add_notifier(NC_IMAGE, NULL);
                        }
 
@@ -695,7 +703,12 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
                                for (scene = bmain->scene.first; scene; scene = scene->id.next) {
                                        if (scene->nodetree && scene->use_nodes && ntreeHasTree(scene->nodetree, ntree)) {
                                                if (node->id == NULL || node->id == (ID *)scene) {
+                                                       int num_layers = BLI_listbase_count(&scene->r.layers);
                                                        scene->r.actlay = node->custom1;
+                                                       /* Clamp the value, because it might have come from a different
+                                                        * scene which could have more render layers than new one.
+                                                        */
+                                                       scene->r.actlay = min_ff(scene->r.actlay, num_layers - 1);
                                                }
                                        }
                                }
@@ -727,6 +740,34 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
        }
 }
 
+void ED_node_id_unref(SpaceNode *snode, const ID *id)
+{
+       if (GS(id->name) == ID_SCE) {
+               if (snode->id == id) {
+                       /* nasty DNA logic for SpaceNode:
+                        * ideally should be handled by editor code, but would be bad level call
+                        */
+                       bNodeTreePath *path, *path_next;
+                       for (path = snode->treepath.first; path; path = path_next) {
+                               path_next = path->next;
+                               MEM_freeN(path);
+                       }
+                       BLI_listbase_clear(&snode->treepath);
+
+                       snode->id = NULL;
+                       snode->from = NULL;
+                       snode->nodetree = NULL;
+                       snode->edittree = NULL;
+               }
+       }
+       else if (GS(id->name) == ID_OB) {
+               if (snode->from == id) {
+                       snode->flag &= ~SNODE_PIN;
+                       snode->from = NULL;
+               }
+       }
+}
+
 void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
 {
        /* XXX This does not work due to layout functions relying on node->block,
@@ -750,7 +791,7 @@ static void edit_node_properties(wmOperatorType *ot)
        /* XXX could node be a context pointer? */
        RNA_def_string(ot->srna, "node", NULL, MAX_NAME, "Node", "");
        RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
-       RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Side", "");
+       RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Side", "");
 }
 
 static int edit_node_invoke_properties(bContext *C, wmOperator *op)
@@ -874,37 +915,38 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
                        dy = (my - nsw->mystart) / UI_DPI_FAC;
                        
                        if (node) {
-                               if (node->flag & NODE_HIDDEN) {
-                                       float widthmin = 0.0f;
-                                       float widthmax = 100.0f;
-                                       if (nsw->directions & NODE_RESIZE_RIGHT) {
-                                               node->miniwidth = nsw->oldminiwidth + dx;
-                                               CLAMP(node->miniwidth, widthmin, widthmax);
-                                       }
-                                       if (nsw->directions & NODE_RESIZE_LEFT) {
-                                               float locmax = nsw->oldlocx + nsw->oldminiwidth;
-                                               
-                                               node->locx = nsw->oldlocx + dx;
-                                               CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
-                                               node->miniwidth = locmax - node->locx;
-                                       }
+                               /* width can use node->width or node->miniwidth (hidden nodes) */
+                               float *pwidth;
+                               float oldwidth, widthmin, widthmax;
+                               /* ignore hidden flag for frame nodes */
+                               bool use_hidden = (node->type != NODE_FRAME);
+                               if (use_hidden && node->flag & NODE_HIDDEN) {
+                                       pwidth = &node->miniwidth;
+                                       oldwidth = nsw->oldminiwidth;
+                                       widthmin = 0.0f;
+                                       widthmax = 100.0f;
                                }
                                else {
-                                       float widthmin = node->typeinfo->minwidth;
-                                       float widthmax = node->typeinfo->maxwidth;
+                                       pwidth = &node->width;
+                                       oldwidth = nsw->oldwidth;
+                                       widthmin = node->typeinfo->minwidth;
+                                       widthmax = node->typeinfo->maxwidth;
+                               }
+                               
+                               {
                                        if (nsw->directions & NODE_RESIZE_RIGHT) {
-                                               node->width = nsw->oldwidth + dx;
-                                               CLAMP(node->width, widthmin, widthmax);
+                                               *pwidth = oldwidth + dx;
+                                               CLAMP(*pwidth, widthmin, widthmax);
                                        }
                                        if (nsw->directions & NODE_RESIZE_LEFT) {
-                                               float locmax = nsw->oldlocx + nsw->oldwidth;
+                                               float locmax = nsw->oldlocx + oldwidth;
                                                
                                                node->locx = nsw->oldlocx + dx;
                                                CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
-                                               node->width = locmax - node->locx;
+                                               *pwidth = locmax - node->locx;
                                        }
                                }
-                       
+                               
                                /* height works the other way round ... */
                                {
                                        float heightmin = UI_DPI_FAC * node->typeinfo->minheight;
@@ -1136,7 +1178,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
        bNodeLink *link, *newlink, *lastlink;
        const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
        
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
        
        lastnode = ntree->nodes.last;
        for (node = ntree->nodes.first; node; node = node->next) {
@@ -1271,7 +1313,7 @@ static int node_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op))
        Scene *curscene = CTX_data_scene(C), *scene;
        bNode *node;
 
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
 
        /* first tag scenes unread */
        for (scene = bmain->scene.first; scene; scene = scene->id.next)
@@ -1470,7 +1512,7 @@ static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
        if ((snode == NULL) || (snode->edittree == NULL))
                return OPERATOR_CANCELLED;
 
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
 
        node_flag_toggle_exec(snode, NODE_PREVIEW);
 
@@ -1534,7 +1576,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
        if ((snode == NULL) || (snode->edittree == NULL))
                return OPERATOR_CANCELLED;
 
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
 
        /* Toggle for all selected nodes */
        hidden = 0;
@@ -1582,7 +1624,7 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceNode *snode = CTX_wm_space_node(C);
        bNode *node;
 
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
 
        for (node = snode->edittree->nodes.first; node; node = node->next) {
                /* Only allow muting of nodes having a mute func! */
@@ -1620,14 +1662,14 @@ static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceNode *snode = CTX_wm_space_node(C);
        bNode *node, *next;
        
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
 
        for (node = snode->edittree->nodes.first; node; node = next) {
                next = node->next;
                if (node->flag & SELECT) {
                        /* check id user here, nodeFreeNode is called for free dbase too */
                        if (node->id)
-                               node->id->us--;
+                               id_us_min(node->id);
                        nodeFreeNode(snode->edittree, node);
                }
        }
@@ -1655,13 +1697,61 @@ void NODE_OT_delete(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/* ****************** Switch View ******************* */
+
+static int node_switch_view_poll(bContext *C)
+{
+       SpaceNode *snode = CTX_wm_space_node(C);
+
+       if (snode && snode->edittree)
+               return true;
+
+       return false;
+}
+
+static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceNode *snode = CTX_wm_space_node(C);
+       bNode *node, *next;
+
+       for (node = snode->edittree->nodes.first; node; node = next) {
+               next = node->next;
+               if (node->flag & SELECT) {
+                       /* call the update function from the Switch View node */
+                       node->update = NODE_UPDATE_OPERATOR;
+               }
+       }
+
+       ntreeUpdateTree(CTX_data_main(C), snode->edittree);
+
+       snode_notify(C, snode);
+       snode_dag_update(C, snode);
+
+       return OPERATOR_FINISHED;
+}
+
+void NODE_OT_switch_view_update(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Update Views";
+       ot->description = "Update views of selected node";
+       ot->idname = "NODE_OT_switch_view_update";
+
+       /* api callbacks */
+       ot->exec = node_switch_view_exec;
+       ot->poll = node_switch_view_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
 /* ****************** Delete with reconnect ******************* */
 static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
 {
        SpaceNode *snode = CTX_wm_space_node(C);
        bNode *node, *next;
 
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
 
        for (node = snode->edittree->nodes.first; node; node = next) {
                next = node->next;
@@ -1670,7 +1760,7 @@ static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
                        
                        /* check id user here, nodeFreeNode is called for free dbase too */
                        if (node->id)
-                               node->id->us--;
+                               id_us_min(node->id);
                        nodeFreeNode(snode->edittree, node);
                }
        }
@@ -1918,7 +2008,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
        bNode *node;
        bNodeLink *link, *newlink;
 
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
 
        /* clear current clipboard */
        BKE_node_clipboard_clear();
@@ -2031,7 +2121,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
        if (!all_nodes_valid)
                return OPERATOR_CANCELLED;
 
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
 
        /* deselect old nodes */
        node_deselect_all(snode);
@@ -2161,7 +2251,7 @@ void NODE_OT_tree_socket_add(wmOperatorType *ot)
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
-       RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Type", "");
+       RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
 }
 
 /********************** Remove interface socket operator *********************/
@@ -2439,7 +2529,7 @@ static int viewer_border_exec(bContext *C, wmOperator *op)
        void *lock;
        ImBuf *ibuf;
 
-       ED_preview_kill_jobs(C);
+       ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
 
        ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
        ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
@@ -2476,14 +2566,6 @@ static int viewer_border_exec(bContext *C, wmOperator *op)
                                btree->flag &= ~NTREE_VIEWER_BORDER;
                        }
                        else {
-                               if (ibuf->rect)
-                                       memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
-
-                               if (ibuf->rect_float)
-                                       memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
-
-                               ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-
                                btree->flag |= NTREE_VIEWER_BORDER;
                        }
 
@@ -2520,3 +2602,30 @@ void NODE_OT_viewer_border(wmOperatorType *ot)
        /* properties */
        WM_operator_properties_gesture_border(ot, true);
 }
+
+static int clear_viewer_border_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceNode *snode = CTX_wm_space_node(C);
+       bNodeTree *btree = snode->nodetree;
+
+       btree->flag &= ~NTREE_VIEWER_BORDER;
+       snode_notify(C, snode);
+       WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+       return OPERATOR_FINISHED;
+}
+
+void NODE_OT_clear_viewer_border(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Clear Viewer Border";
+       ot->description = "Clear the boundaries for viewer operations";
+       ot->idname = "NODE_OT_clear_viewer_border";
+
+       /* api callbacks */
+       ot->exec = clear_viewer_border_exec;
+       ot->poll = composite_node_active;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}