fix for crash when moving frames about in the node space, was possible to move a...
[blender.git] / source / blender / editors / space_node / node_edit.c
index 90c61788a51c0df6e407b86b50ccafb5523b2c6b..0af04856522fd447b6f75566248592c4232f7bd6 100644 (file)
 #include "BKE_material.h"
 #include "BKE_paint.h"
 #include "BKE_scene.h"
-#include "BKE_screen.h"
 #include "BKE_texture.h"
 
 #include "RE_pipeline.h"
 
-#include "IMB_imbuf_types.h"
 
 #include "ED_node.h"  /* own include */
-#include "ED_image.h"
 #include "ED_screen.h"
-#include "ED_space_api.h"
 #include "ED_render.h"
 
 #include "RNA_access.h"
@@ -71,9 +67,6 @@
 
 #include "UI_view2d.h"
 
-#include "IMB_imbuf.h"
-
-
 #include "GPU_material.h"
 
 #include "node_intern.h"  /* own include */
@@ -170,26 +163,31 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog
 
 }
 
-void snode_composite_job(const bContext *C, ScrArea *sa)
+/**
+ * \param sa_owner is the owner of the job,
+ * we don't use it for anything else currently so could also be a void pointer,
+ * but for now keep it an 'Scene' for consistency.
+ *
+ * \note only call from spaces `refresh` callbacks, not direct! - use with care.
+ */
+void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene *scene_owner)
 {
-       SpaceNode *snode = sa->spacedata.first;
        wmJob *steve;
        CompoJob *cj;
 
-       steve = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Compositing", WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS);
+       steve = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene_owner, "Compositing", WM_JOB_EXCL_RENDER | WM_JOB_PROGRESS);
        cj = MEM_callocN(sizeof(CompoJob), "compo job");
-       
+
        /* customdata for preview thread */
        cj->scene = CTX_data_scene(C);
-       cj->ntree = snode->nodetree;
-       
+       cj->ntree = nodetree;
+
        /* setup job */
        WM_jobs_customdata(steve, cj, compo_freejob);
        WM_jobs_timer(steve, 0.1, NC_SCENE, NC_SCENE | ND_COMPO_RESULT);
        WM_jobs_callbacks(steve, compo_startjob, compo_initjob, compo_updatejob, NULL);
-       
+
        WM_jobs_start(CTX_wm_manager(C), steve);
-       
 }
 
 /* ***************************************** */
@@ -764,7 +762,7 @@ static void edit_node_properties_get(wmOperator *op, bNodeTree *ntree, bNode **r
 /* ************************** Node generic ************** */
 
 /* is rct in visible part of node? */
-static bNode *visible_node(SpaceNode *snode, rctf *rct)
+static bNode *visible_node(SpaceNode *snode, const rctf *rct)
 {
        bNode *node;
        
@@ -1911,7 +1909,9 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
 {
        SpaceNode *snode = CTX_wm_space_node(C);
        bNodeTree *ntree = snode->edittree;
-       bNode *node, *newnode;
+       bNode *gnode = node_tree_get_editgroup(snode->nodetree);
+       float gnode_x = 0.0f, gnode_y = 0.0f;
+       bNode *node, *new_node;
        bNodeLink *link, *newlink;
 
        ED_preview_kill_jobs(C);
@@ -1919,10 +1919,37 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
        /* clear current clipboard */
        nodeClipboardClear();
 
+       /* get group node offset */
+       if (gnode)
+               nodeToView(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y);
+       
+       for (node = ntree->nodes.first; node; node = node->next) {
+               if (node->flag & SELECT) {
+                       new_node = nodeCopyNode(NULL, node);
+                       nodeClipboardAddNode(new_node);
+               }
+       }
+
        for (node = ntree->nodes.first; node; node = node->next) {
                if (node->flag & SELECT) {
-                       newnode = nodeCopyNode(NULL, node);
-                       nodeClipboardAddNode(newnode);
+                       bNode *new_node = node->new_node;
+                       
+                       /* ensure valid pointers */
+                       if (new_node->parent) {
+                               /* parent pointer must be redirected to new node or detached if parent is not copied */
+                               if (new_node->parent->flag & NODE_SELECT) {
+                                       new_node->parent = new_node->parent->new_node;
+                               }
+                               else {
+                                       nodeDetachNode(new_node);
+                               }
+                       }
+
+                       /* transform to basic view space. child node location is relative to parent */
+                       if (!new_node->parent) {        
+                               new_node->locx += gnode_x;
+                               new_node->locy += gnode_y;
+                       }
                }
        }
 
@@ -1945,16 +1972,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
                }
        }
 
-       /* reparent copied nodes */
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if ((node->flag & SELECT) && node->parent) {
-                       if (node->parent->flag & SELECT)
-                               node->parent = node->parent->new_node;
-                       else
-                               node->parent = NULL;
-               }
-       }
-
        return OPERATOR_FINISHED;
 }
 
@@ -1979,6 +1996,8 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *UNUSED(op))
 {
        SpaceNode *snode = CTX_wm_space_node(C);
        bNodeTree *ntree = snode->edittree;
+       bNode *gnode = node_tree_get_editgroup(snode->nodetree);
+       float gnode_x = 0.0f, gnode_y = 0.0f;
        bNode *node;
        bNodeLink *link;
        int num_nodes;
@@ -1989,27 +2008,41 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *UNUSED(op))
        /* deselect old nodes */
        node_deselect_all(snode);
 
+       /* get group node offset */
+       if (gnode)
+               nodeToView(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y);
+
        /* calculate "barycenter" for placing on mouse cursor */
        num_nodes = 0;
        centerx = centery = 0.0f;
        for (node = nodeClipboardGetNodes()->first; node; node = node->next) {
                ++num_nodes;
-               centerx += node->locx + 0.5f * node->width;
-               centery += node->locy - 0.5f * node->height;
+               centerx += 0.5f * (node->totr.xmin + node->totr.xmax);
+               centery += 0.5f * (node->totr.ymin + node->totr.ymax);
        }
        centerx /= num_nodes;
        centery /= num_nodes;
 
        /* copy nodes from clipboard */
        for (node = nodeClipboardGetNodes()->first; node; node = node->next) {
-               bNode *newnode = nodeCopyNode(ntree, node);
+               bNode *new_node = nodeCopyNode(ntree, node);
 
                /* pasted nodes are selected */
-               node_select(newnode);
-
-               /* place nodes around the mouse cursor */
-               newnode->locx += snode->mx - centerx;
-               newnode->locy += snode->my - centery;
+               node_select(new_node);
+       }
+       
+       /* reparent copied nodes */
+       for (node = nodeClipboardGetNodes()->first; node; node = node->next) {
+               bNode *new_node = node->new_node;
+               if (new_node->parent)
+                       new_node->parent = new_node->parent->new_node;
+               
+               
+               /* place nodes around the mouse cursor. child nodes locations are relative to parent */
+               if (!new_node->parent) {
+                       new_node->locx += snode->mx - centerx - gnode_x;
+                       new_node->locy += snode->my - centery - gnode_y;
+               }
        }
 
        for (link = nodeClipboardGetLinks()->first; link; link = link->next) {
@@ -2017,12 +2050,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *UNUSED(op))
                            link->tonode->new_node, link->tosock->new_sock);
        }
 
-       /* reparent copied nodes */
-       for (node = nodeClipboardGetNodes()->first; node; node = node->next) {
-               if (node->new_node->parent)
-                       node->new_node->parent = node->new_node->parent->new_node;
-       }
-
        ntreeUpdateTree(snode->edittree);
 
        snode_notify(C, snode);
@@ -2055,5 +2082,5 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot)
        ot->poll = ED_operator_node_active;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }