forked from bartvdbraak/blender
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:
parent
382050501d
commit
ea90544d65
@ -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) {
|
||||
/* 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user