From ea90544d65a5b2549d5e0b4761de3bf0f2631688 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 22 Jul 2011 15:28:50 +0000 Subject: Need some fun once a while: 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 | 3 + source/blender/editors/space_node/drawnode.c | 15 ++- source/blender/editors/space_node/node_edit.c | 126 ++++++++++++++++++++- .../editors/transform/transform_conversions.c | 14 ++- source/blender/makesdna/DNA_node_types.h | 4 + 5 files changed, 156 insertions(+), 6 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 829ad3217a9..dfa457c22de 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -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); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 1bf2c3d89bd..50e657bbb61 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -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; } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index abc7b273ec9..b5648b67d86 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -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."); } + + diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 16bfc75c979..0a5e290643a 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -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; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 03387c3a63a..efaf30b02f6 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -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 { -- cgit v1.2.3