Add delete with reconnect feature.
authorJeroen Bakker <j.bakker@atmind.nl>
Tue, 12 Jul 2011 18:59:54 +0000 (18:59 +0000)
committerJeroen Bakker <j.bakker@atmind.nl>
Tue, 12 Jul 2011 18:59:54 +0000 (18:59 +0000)
this will reconnect nodes as if the deleted node is muted.
Operation is added to the space_node node menu and to the keymap as CTRL-X

to test this just add some nodes to the space_node
select one or multiple nodes and press CTRL-X

It should reconnect the nodes as they were muted

limitations:
1. it performs a delete and reconnect per node. It does not evaluate all selected nodes as one whole
2. mute only supports Value, Vector and Color data types, so does this feature
3. not usable for nodes where input and output does not match (like colorToBW)

Where reconnect could not be preformed the links will be removed from the model.

Undo works with this delete with reconnect.

release/scripts/startup/bl_ui/space_node.py
source/blender/editors/space_node/node_draw.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_intern.h
source/blender/editors/space_node/node_ops.c
source/blender/nodes/intern/CMP_util.c

index fed1cc49c4cd13680880e86aa34df292a2664076..831fd3597823d0de843c5bd61e86db33641cae4f 100644 (file)
@@ -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")
index 5f8ab0dded5524bda5b3ab282deee19363268f16..cd1fa5c16a7a731277791c5f8dd5bcae958eee4a 100644 (file)
@@ -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;
index a6a60035aa78255b8fe1c059b65d823d708cbc84..e760c9021c25835787da5764e6d86cabbb79337d 100644 (file)
@@ -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))
index a1c0f5535fe46a22d0be64f98884b3e917762ac7..9122235f33c14e241193505d722256c9f64b041f 100644 (file)
@@ -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);
index 11e7949791dd6f58ba3040c6f50250cc5093a238..4d181a3489489e75d3795e7609882755adffc037 100644 (file)
@@ -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);
index b73a46c7d7db4c2a4f5f0a71c25a4141243f3e43..a763f34a644c75bae368bef242e671aeb298cf92 100644 (file)
@@ -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;