diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index fed1cc49c4c..831fd359782 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -135,9 +135,10 @@ class NODE_MT_node(bpy.types.Menu): layout.operator("transform.resize") layout.separator() - + layout.operator("node.duplicate_move") layout.operator("node.delete") + layout.operator("node.delete_reconnect") layout.separator() layout.operator("node.link_make") diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 5f8ab0dded5..cd1fa5c16a7 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -461,6 +461,7 @@ static void node_update_group(const bContext *C, bNodeTree *UNUSED(ntree), bNode } /* note: in cmp_util.c is similar code, for node_compo_pass_on() */ +/* note: in node_edit.c is similar code, for untangle node */ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) { bNodeSocket *valsock= NULL, *colsock= NULL, *vecsock= NULL; diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index a6a60035aa7..e760c9021c2 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -2906,6 +2906,117 @@ void NODE_OT_delete(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/* ****************** Delete with reconnect ******************* */ + +/* note: in cmp_util.c is similar code, for node_compo_pass_on() */ +/* used for disabling node (similar code in node_draw.c for disable line) */ +static void node_delete_reconnect(bNodeTree* tree, bNode* node) { + bNodeLink *link, *next; + bNodeSocket *valsocket= NULL, *colsocket= NULL, *vecsocket= NULL; + bNodeSocket *deliveringvalsocket= NULL, *deliveringcolsocket= NULL, *deliveringvecsocket= NULL; + bNode *deliveringvalnode= NULL, *deliveringcolnode= NULL, *deliveringvecnode= NULL; + bNodeSocket *sock; + + /* test the inputs */ + for(sock= node->inputs.first; sock; sock= sock->next) { + int type = sock->type; + if(type==SOCK_VALUE && valsocket==NULL) valsocket = sock; + if(type==SOCK_VECTOR && vecsocket==NULL) vecsocket = sock; + if(type==SOCK_RGBA && colsocket==NULL) colsocket = sock; + } + // we now have the input sockets for the 'data types' + // now find the output sockets (and nodes) in the tree that delivers data to these input sockets + for(link= tree->links.first; link; link=link->next) { + if (valsocket != NULL) { + if (link->tosock == valsocket) { + deliveringvalnode = link->fromnode; + deliveringvalsocket = link->fromsock; + } + } + if (vecsocket != NULL) { + if (link->tosock == vecsocket) { + deliveringvecnode = link->fromnode; + deliveringvecsocket = link->fromsock; + } + } + if (colsocket != NULL) { + if (link->tosock == colsocket) { + deliveringcolnode = link->fromnode; + deliveringcolsocket = link->fromsock; + } + } + } + // we now have the sockets+nodes that fill the inputsockets be aware for group nodes these can be NULL + // now make the links for all outputlinks of the node to be reconnected + for(link= tree->links.first; link; link=next) { + next= link->next; + if (link->fromnode == node) { + sock = link->fromsock; + switch(sock->type) { + case SOCK_VALUE: + if (deliveringvalsocket) { + link->fromnode = deliveringvalnode; + link->fromsock = deliveringvalsocket; + } + break; + case SOCK_VECTOR: + if (deliveringvecsocket) { + link->fromnode = deliveringvecnode; + link->fromsock = deliveringvecsocket; + } + break; + case SOCK_RGBA: + if (deliveringcolsocket) { + link->fromnode = deliveringcolnode; + link->fromsock = deliveringcolsocket; + } + break; + } + } + } + if(node->id) + node->id->us--; + nodeFreeNode(tree, node); + +} + +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); + + for(node= snode->edittree->nodes.first; node; node= next) { + next= node->next; + if(node->flag & SELECT) { + node_delete_reconnect(snode->edittree, node); + } + } + + node_tree_verify_groups(snode->nodetree); + + snode_notify(C, snode); + snode_dag_update(C, snode); + + return OPERATOR_FINISHED; +} + +void NODE_OT_delete_reconnect(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Delete with reconnect"; + ot->description = "Delete nodes; will reconnect nodes as if deletion was muted"; + ot->idname= "NODE_OT_delete_reconnect"; + + /* api callbacks */ + ot->exec= node_delete_reconnect_exec; + ot->poll= ED_operator_node_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ****************** Show Cyclic Dependencies Operator ******************* */ static int node_show_cycles_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index a1c0f5535fe..9122235f33c 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -114,6 +114,7 @@ int node_render_changed_exec(bContext *, wmOperator *); void NODE_OT_duplicate(struct wmOperatorType *ot); void NODE_OT_delete(struct wmOperatorType *ot); +void NODE_OT_delete_reconnect(struct wmOperatorType *ot); void NODE_OT_resize(struct wmOperatorType *ot); void NODE_OT_link(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 11e7949791d..4d181a34894 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -70,12 +70,13 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_duplicate); WM_operatortype_append(NODE_OT_delete); + WM_operatortype_append(NODE_OT_delete_reconnect); WM_operatortype_append(NODE_OT_resize); WM_operatortype_append(NODE_OT_link); WM_operatortype_append(NODE_OT_link_make); WM_operatortype_append(NODE_OT_links_cut); - + WM_operatortype_append(NODE_OT_group_make); WM_operatortype_append(NODE_OT_group_ungroup); WM_operatortype_append(NODE_OT_group_edit); @@ -108,8 +109,7 @@ void ED_operatormacros_node(void) ot= WM_operatortype_append_macro("NODE_OT_select_link_viewer", "Link Viewer", OPTYPE_UNDO); WM_operatortype_macro_define(ot, "NODE_OT_select"); WM_operatortype_macro_define(ot, "NODE_OT_link_viewer"); - -} + } void node_keymap(struct wmKeyConfig *keyconf) { @@ -167,6 +167,7 @@ void node_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "NODE_OT_select_border", BKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_delete", DELKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NODE_OT_delete_reconnect", XKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_select_all", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_select_linked_to", LKEY, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/nodes/intern/CMP_util.c b/source/blender/nodes/intern/CMP_util.c index b73a46c7d7d..a763f34a644 100644 --- a/source/blender/nodes/intern/CMP_util.c +++ b/source/blender/nodes/intern/CMP_util.c @@ -132,7 +132,7 @@ void compbuf_set_node(CompBuf *cbuf, bNode *node) if (cbuf) cbuf->node = node; } -/* used for disabling node (similar code in drawnode.c for disable line) */ +/* used for disabling node (similar code in node_draw.c for disable line and node_edit for untangling nodes) */ void node_compo_pass_on(bNode *node, bNodeStack **nsin, bNodeStack **nsout) { CompBuf *valbuf= NULL, *colbuf= NULL, *vecbuf= NULL;