Need some fun once a while:
authorTon Roosendaal <ton@blender.org>
Fri, 22 Jul 2011 15:28:50 +0000 (15:28 +0000)
committerTon Roosendaal <ton@blender.org>
Fri, 22 Jul 2011 15:28:50 +0000 (15:28 +0000)
On dragging a non-connected node on a noodle, it will insert it.
Functionality tweaks are possible, but it already feels non-intrusive.

Rules:
- Insertion only when a single noodle is intersecting with node.
- Default connects first matching socket type.
- If no socket match, it connects the first.

source/blender/editors/include/ED_node.h
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/transform/transform_conversions.c
source/blender/makesdna/DNA_node_types.h

index 829ad3217a9d4f5285c41359e43a37940c47617e..dfa457c22ded58ab36c921c9fa6f95c143927a07 100644 (file)
@@ -39,6 +39,7 @@ struct Tex;
 struct bContext;
 struct bNode;
 struct ID;
+struct ScrArea;
 
 /* drawnode.c */
 void ED_init_node_butfuncs(void);
@@ -51,6 +52,8 @@ void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct
 void ED_node_shader_default(struct Material *ma);
 void ED_node_composit_default(struct Scene *sce);
 void ED_node_texture_default(struct Tex *tex);
+void ED_node_link_intersect_test(struct ScrArea *sa, int test);
+void ED_node_link_insert(struct ScrArea *sa);
 
 /* node ops.c */
 void ED_operatormacros_node(void);
index 1bf2c3d89bdd8bd2338ce2cb1dd6bc4606acc231..50e657bbb61d031d70d0305e7d5b51dbaefe3020 100644 (file)
@@ -1869,10 +1869,17 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
                else {
                        /* check cyclic */
                        if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
-                               if(link->fromnode->flag & SELECT)
-                                       th_col1= TH_EDGE_SELECT;
-                               if(link->tonode->flag & SELECT)
-                                       th_col2= TH_EDGE_SELECT;
+                               /* special indicated link, on drop-node */
+                               if(link->flag & NODE_LINKFLAG_HILITE) {
+                                       th_col1= th_col2= TH_ACTIVE;
+                               }
+                               else {
+                                       /* regular link */
+                                       if(link->fromnode->flag & SELECT)
+                                               th_col1= TH_EDGE_SELECT;
+                                       if(link->tonode->flag & SELECT)
+                                               th_col2= TH_EDGE_SELECT;
+                               }
                                do_shaded= 1;
                                do_triple= 1;
                        }                               
index abc7b273ec991bc248be1a4f2c87ebe3686fa907..b5648b67d86504feab5f244af698544c4a887bb2 100644 (file)
@@ -2492,6 +2492,127 @@ void NODE_OT_links_cut(wmOperatorType *ot)
        RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
 }
 
+/* *********************  automatic node insert on dragging ******************* */
+
+static bNodeSocket *socket_best_match(ListBase *sockets, int type)
+{
+       bNodeSocket *sock;
+       
+       for(sock= sockets->first; sock; sock= sock->next)
+               if(type == sock->type)
+                       return sock;
+       
+       return sockets->first;
+}
+
+/* prevent duplicate testing code below */
+static SpaceNode *ed_node_link_conditions(ScrArea *sa, bNode **select)
+{
+       SpaceNode *snode= sa?sa->spacedata.first:NULL;
+       bNode *node;
+       bNodeLink *link;
+       
+       /* no unlucky accidents */
+       if(sa==NULL || sa->spacetype!=SPACE_NODE) return NULL;
+       
+       *select= NULL;
+       
+       for(node= snode->edittree->nodes.first; node; node= node->next) {
+               if(node->flag & SELECT) {
+                       if(*select)
+                               break;
+                       else
+                               *select= node;
+               }
+       }
+       /* only one selected */
+       if(node || *select==NULL) return NULL;
+       
+       /* correct node */
+       if((*select)->inputs.first==NULL || (*select)->outputs.first==NULL) return NULL;
+       
+       /* test node for links */
+       for(link= snode->edittree->links.first; link; link=link->next) {
+               if(link->tonode == *select || link->fromnode == *select)
+                       return NULL;
+       }
+       
+       return snode;
+}
+
+/* assumes link with NODE_LINKFLAG_HILITE set */
+void ED_node_link_insert(ScrArea *sa)
+{
+       bNode *node, *select;
+       SpaceNode *snode= ed_node_link_conditions(sa, &select);
+       bNodeLink *link;
+       bNodeSocket *sockto;
+       
+       if(snode==NULL) return;
+       
+       /* get the link */
+       for(link= snode->edittree->links.first; link; link=link->next)
+               if(link->flag & NODE_LINKFLAG_HILITE)
+                       break;
+       
+       if(link) {
+               node= link->tonode;
+               sockto= link->tosock;
+               
+               link->tonode= select;
+               link->tosock= socket_best_match(&select->inputs, link->fromsock->type);
+               link->flag &= ~NODE_LINKFLAG_HILITE;
+               
+               nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs, sockto->type), node, sockto);
+               ntreeSolveOrder(snode->edittree);       /* needed for pointers */
+               snode_tag_changed(snode, select);
+               ED_node_changed_update(snode->id, select);
+       }
+}
+
+
+/* test == 0, clear all intersect flags */
+void ED_node_link_intersect_test(ScrArea *sa, int test)
+{
+       bNode *select;
+       SpaceNode *snode= ed_node_link_conditions(sa, &select);
+       bNodeLink *link, *selink=NULL;
+       float mcoords[4][2];
+       
+       if(snode==NULL) return;
+       
+       /* clear flags */
+       for(link= snode->edittree->links.first; link; link=link->next)
+               link->flag &= ~NODE_LINKFLAG_HILITE;
+       
+       if(test==0) return;
+       
+       /* okay, there's 1 node, without links, now intersect */
+       mcoords[0][0]= select->totr.xmin;
+       mcoords[0][1]= select->totr.ymin;
+       mcoords[1][0]= select->totr.xmax;
+       mcoords[1][1]= select->totr.ymin;
+       mcoords[2][0]= select->totr.xmax;
+       mcoords[2][1]= select->totr.ymax;
+       mcoords[3][0]= select->totr.xmin;
+       mcoords[3][1]= select->totr.ymax;
+       
+       /* we only tag a single link for intersect now */
+       /* idea; use header dist when more? */
+       for(link= snode->edittree->links.first; link; link=link->next) {
+               
+               if(cut_links_intersect(link, mcoords, 4)) {
+                       if(selink) 
+                               break;
+                       selink= link;
+               }
+       }
+               
+       if(link==NULL && selink)
+               selink->flag |= NODE_LINKFLAG_HILITE;
+}
+
+
 /* ******************************** */
 // XXX some code needing updating to operators...
 
@@ -2914,7 +3035,8 @@ void NODE_OT_delete(wmOperatorType *ot)
 
 /* 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) {
+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;
@@ -3142,3 +3264,5 @@ void NODE_OT_add_file(wmOperatorType *ot)
        RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Datablock name to assign.");
 }
 
+
+
index 16bfc75c97979cf54b57069acd27261876bf4a92..0a5e290643af3f46806efc46905ca185ebeaade9 100644 (file)
@@ -87,6 +87,7 @@
 #include "ED_object.h"
 #include "ED_markers.h"
 #include "ED_mesh.h"
+#include "ED_node.h"
 #include "ED_types.h"
 #include "ED_uvedit.h"
 #include "ED_curve.h" /* for ED_curve_editnurbs */
@@ -2182,6 +2183,12 @@ void flushTransNodes(TransInfo *t)
                td->loc2d[0]= td->loc[0];
                td->loc2d[1]= td->loc[1];
        }
+       
+       /* handle intersection with noodles */
+       if(t->total==1) {
+               ED_node_link_intersect_test(t->sa, 1);
+       }
+       
 }
 
 /* *** SEQUENCE EDITOR *** */
@@ -4756,7 +4763,12 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
 
        }
        else if (t->spacetype == SPACE_NODE) {
-               /* pass */
+               if(cancelled == 0)
+                       ED_node_link_insert(t->sa);
+               
+               /* clear link line */
+               ED_node_link_intersect_test(t->sa, 0);
+               
        }
        else if (t->spacetype == SPACE_ACTION) {
                SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
index 03387c3a63afa82ea64c49f6800c3c6c83fc6f5a..efaf30b02f617e6287e963f56aa472e5d10c6b5d 100644 (file)
@@ -179,6 +179,10 @@ typedef struct bNodeLink {
        
 } bNodeLink;
 
+
+/* link->flag */
+#define NODE_LINKFLAG_HILITE   1
+
 /* the basis for a Node tree, all links and nodes reside internal here */
 /* only re-usable node trees are in the library though, materials and textures allocate own tree struct */
 typedef struct bNodeTree {