diff options
Diffstat (limited to 'source/blender/editors/space_node/node_edit.c')
-rw-r--r-- | source/blender/editors/space_node/node_edit.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 4b554185933..fa8fa13a645 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -2215,3 +2215,156 @@ void NODE_OT_node_copy_color(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/* ****************** Copy to clipboard ******************* */ + +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; + bNodeLink *link, *newlink; + + ED_preview_kill_jobs(C); + + /* clear current clipboard */ + nodeClipboardClear(); + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->flag & SELECT) { + newnode = nodeCopyNode(NULL, node); + nodeClipboardAddNode(newnode); + } + } + + /* copy links between selected nodes + * NB: this depends on correct node->new_node and sock->new_sock pointers from above copy! + */ + for (link = ntree->links.first; link; link = link->next) { + /* This creates new links between copied nodes. */ + if (link->tonode && (link->tonode->flag & NODE_SELECT) && + link->fromnode && (link->fromnode->flag & NODE_SELECT)) + { + newlink = MEM_callocN(sizeof(bNodeLink), "bNodeLink"); + newlink->flag = link->flag; + newlink->tonode = link->tonode->new_node; + newlink->tosock = link->tosock->new_sock; + newlink->fromnode = link->fromnode->new_node; + newlink->fromsock = link->fromsock->new_sock; + + nodeClipboardAddLink(newlink); + } + } + + /* 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; +} + +void NODE_OT_clipboard_copy(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Copy to clipboard"; + ot->description = "Copies selected nodes to the clipboard"; + ot->idname = "NODE_OT_clipboard_copy"; + + /* api callbacks */ + ot->exec = node_clipboard_copy_exec; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ****************** Paste from clipboard ******************* */ + +static int node_clipboard_paste_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + bNode *node; + bNodeLink *link; + int num_nodes; + float centerx, centery; + + ED_preview_kill_jobs(C); + + /* deselect old nodes */ + node_deselect_all(snode); + + /* 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 /= num_nodes; + centery /= num_nodes; + + /* copy nodes from clipboard */ + for (node = nodeClipboardGetNodes()->first; node; node = node->next) { + bNode *newnode = 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; + } + + for (link = nodeClipboardGetLinks()->first; link; link = link->next) { + nodeAddLink(ntree, link->fromnode->new_node, link->fromsock->new_sock, + 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); + snode_dag_update(C, snode); + + return OPERATOR_FINISHED; +} + +static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + SpaceNode *snode = CTX_wm_space_node(C); + + /* convert mouse coordinates to v2d space */ + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->mx, &snode->my); + + return node_clipboard_paste_exec(C, op); +} + +void NODE_OT_clipboard_paste(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Paste from clipboard"; + ot->description = "Pastes nodes from the clipboard to the active node tree"; + ot->idname = "NODE_OT_clipboard_paste"; + + /* api callbacks */ + ot->exec = node_clipboard_paste_exec; + ot->invoke = node_clipboard_paste_invoke; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} |