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.
This commit is contained in:
Ton Roosendaal 2011-07-22 15:28:50 +00:00
parent 382050501d
commit ea90544d65
5 changed files with 156 additions and 6 deletions

@ -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);

@ -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;
}

@ -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.");
}

@ -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;

@ -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 {