Orange; update commit on WIP project for Noodle editing. :)

- Grabbing works (Gkey) or tweak (LMB) or use RMB click-drag for grab
- Shift+d works
- Akey: select all
- Drawing links works too now!
This commit is contained in:
Ton Roosendaal
2005-12-18 23:08:22 +00:00
parent 87d9ca4b99
commit be0b59ea6d
9 changed files with 505 additions and 53 deletions

View File

@@ -35,11 +35,18 @@
struct bNodeTree;
struct bNode;
struct bNodeLink;
struct bNodeSocket;
struct ListBase;
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
void nodeFreeTree(struct bNodeTree *ntree);
struct bNode *nodeAddNode(struct bNodeTree *ntree, char *name);
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
void nodeFreeTree(struct bNodeTree *ntree);
struct bNode *nodeAddNode(struct bNodeTree *ntree, char *name);
struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to);
#endif

View File

@@ -44,11 +44,40 @@
bNode *nodeAddNode(struct bNodeTree *ntree, char *name)
{
bNode *node= MEM_callocN(sizeof(bNode), "new node");
BLI_addtail(&ntree->nodes, node);
BLI_strncpy(node->name, name, NODE_MAXSTR);
return node;
}
bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
{
bNode *nnode= MEM_callocN(sizeof(bNode), "dupli node");
*nnode= *node;
BLI_addtail(&ntree->nodes, nnode);
duplicatelist(&nnode->inputs, &node->inputs);
duplicatelist(&nnode->outputs, &node->outputs);
if(nnode->id)
nnode->id->us++;
return nnode;
}
bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
{
bNodeLink *link= MEM_callocN(sizeof(bNodeLink), "link");
BLI_addtail(&ntree->links, link);
link->fromnode= fromnode;
link->fromsock= fromsock;
link->tonode= tonode;
link->tosock= tosock;
return link;
}
/* ************** Free stuff ********** */
@@ -64,6 +93,9 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
if(ntree)
node_unlink_node(ntree, node);
if(node->id)
node->id->us--;
BLI_freelistN(&node->inputs);
BLI_freelistN(&node->outputs);
@@ -85,3 +117,18 @@ void nodeFreeTree(bNodeTree *ntree)
MEM_freeN(ntree);
}
/* ************ find stuff *************** */
bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to)
{
bNodeLink *link;
for(link= ntree->links.first; link; link= link->next) {
if(link->fromsock==from && link->tosock==to)
return link;
if(link->fromsock==to && link->tosock==from) /* hrms? */
return link;
}
return NULL;
}

View File

@@ -30,7 +30,10 @@
#ifndef BSE_NODE_H
#define BSE_NODE_H
struct SpaceNode;
void node_deselectall(struct SpaceNode *snode, int swap);
void node_transform_ext(int mode, int unused);
#endif

View File

@@ -85,14 +85,13 @@ typedef struct {
void *xl, *large, *medium, *small;
} uiFont;
typedef struct uiLinkLine uiLinkLine;
struct uiLinkLine { /* only for draw/edit */
uiLinkLine *next, *prev;
typedef struct uiLinkLine { /* only for draw/edit */
struct uiLinkLine *next, *prev;
short flag, pad;
uiBut *from, *to;
};
} uiLinkLine;
typedef struct {
void **poin; /* pointer to original pointer */

View File

@@ -69,7 +69,8 @@ typedef struct bNode {
typedef struct bNodeLink {
struct bNodeLink *next, *prev;
bNode *from, *to;
bNode *fromnode, *tonode;
bNodeSocket *fromsock, *tosock;
} bNodeLink;

View File

@@ -84,6 +84,73 @@ static void get_nodetree(SpaceNode *snode)
}
static void node_draw_link(SpaceNode *snode, bNodeLink *link)
{
float vec[4][3];
float dist, spline_step, mx=0.0f, my=0.0f;
int curve_res;
if(link->fromnode==NULL && link->tonode==NULL)
return;
/* this is dragging link */
if(link->fromnode==NULL || link->tonode==NULL) {
short mval[2];
getmouseco_areawin(mval);
areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
}
BIF_ThemeColor(TH_WIRE);
vec[0][2]= vec[1][2]= vec[2][2]= vec[3][2]= 0.0; /* only 2d spline, set the Z to 0*/
/* in v0 and v3 we put begin/end points */
if(link->fromnode) {
vec[0][0]= link->fromsock->locx;
vec[0][1]= link->fromsock->locy;
}
else {
vec[0][0]= mx;
vec[0][1]= my;
}
if(link->tonode) {
vec[3][0]= link->tosock->locx;
vec[3][1]= link->tosock->locy;
}
else {
vec[3][0]= mx;
vec[3][1]= my;
}
dist= 0.5*VecLenf(vec[0], vec[3]);
/* check direction later, for top sockets */
vec[1][0]= vec[0][0]+dist;
vec[1][1]= vec[0][1];
vec[2][0]= vec[3][0]-dist;
vec[2][1]= vec[3][1];
if( MIN4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > G.v2d->cur.xmax); /* clipped */
else if ( MAX4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < G.v2d->cur.xmin); /* clipped */
else {
curve_res = 24;
/* we can reuse the dist variable here to increment the GL curve eval amount*/
dist = 1.0f/curve_res;
spline_step = 0.0f;
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
glBegin(GL_LINE_STRIP);
while (spline_step < 1.000001f) {
glEvalCoord1f(spline_step);
spline_step += dist;
}
glEnd();
}
}
void drawnodespace(ScrArea *sa, void *spacedata)
{
SpaceNode *snode= sa->spacedata.first;
@@ -101,6 +168,7 @@ void drawnodespace(ScrArea *sa, void *spacedata)
/* only set once */
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable(GL_MAP1_VERTEX_3);
/* aspect+font, set each time */
snode->aspect= (snode->v2d.cur.xmax - snode->v2d.cur.xmin)/((float)sa->winx);
@@ -113,9 +181,25 @@ void drawnodespace(ScrArea *sa, void *spacedata)
get_nodetree(snode);
if(snode->nodetree) {
bNode *node;
for(node= snode->nodetree->nodes.first; node; node= node->next) {
node->drawfunc(snode, node);
}
bNodeLink *link;
/* node lines */
glEnable(GL_BLEND);
glEnable( GL_LINE_SMOOTH );
for(link= snode->nodetree->links.first; link; link= link->next)
node_draw_link(snode, link);
glDisable(GL_BLEND);
glDisable( GL_LINE_SMOOTH );
/* not selected */
for(node= snode->nodetree->nodes.first; node; node= node->next)
if(!(node->flag & SELECT))
node->drawfunc(snode, node);
/* selected */
for(node= snode->nodetree->nodes.first; node; node= node->next)
if(node->flag & SELECT)
node->drawfunc(snode, node);
}
/* restore viewport */

View File

@@ -51,6 +51,7 @@
#include "BKE_material.h"
#include "BKE_utildefines.h"
#include "BIF_editview.h"
#include "BIF_gl.h"
#include "BIF_interface.h"
#include "BIF_language.h"
@@ -62,19 +63,26 @@
#include "BSE_drawipo.h"
#include "BSE_headerbuttons.h"
#include "BSE_node.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BDR_editobject.h"
#include "blendef.h"
#include "interface.h" /* urm... for rasterpos_safe, roundbox */
#include "PIL_time.h"
#include "mydevice.h"
/* ***************************** */
/* **************** NODE draw callbacks ************* */
#define NODE_DY 20
#define NODE_SOCK 5
#define SOCK_IN 1
#define SOCK_OUT 2
static void nodeshadow(rctf *rct, int select)
{
@@ -165,7 +173,7 @@ static int node_basis_draw(SpaceNode *snode, bNode *node)
BIF_DrawString(snode->curfont, node->name, trans);
for(sock= node->inputs.first; sock; sock= sock->next) {
socket_circle_draw(sock->locx, sock->locy, 5.0f);
socket_circle_draw(sock->locx, sock->locy, NODE_SOCK);
BIF_ThemeColor(TH_TEXT);
ui_rasterpos_safe(sock->locx+8.0f, sock->locy-5.0f, snode->aspect);
@@ -173,7 +181,7 @@ static int node_basis_draw(SpaceNode *snode, bNode *node)
}
for(sock= node->outputs.first; sock; sock= sock->next) {
socket_circle_draw(sock->locx, sock->locy, 5.0f);
socket_circle_draw(sock->locx, sock->locy, NODE_SOCK);
BIF_ThemeColor(TH_TEXT);
slen= snode->aspect*BIF_GetStringWidth(snode->curfont, sock->name, trans);
@@ -184,29 +192,7 @@ static int node_basis_draw(SpaceNode *snode, bNode *node)
return 0;
}
static void node_deselectall(SpaceNode *snode, int swap)
{
bNode *node;
if(swap) {
for(node= snode->nodetree->nodes.first; node; node= node->next)
if(node->flag & SELECT)
break;
if(node==NULL) {
for(node= snode->nodetree->nodes.first; node; node= node->next)
node->flag |= SELECT;
allqueue(REDRAWNODE, 0);
return;
}
/* else pass on to deselect */
}
for(node= snode->nodetree->nodes.first; node; node= node->next)
node->flag &= ~SELECT;
allqueue(REDRAWNODE, 0);
}
/* ************************** Node generic ************** */
/* based on settings in tree and node,
- it fills it with appropriate callbacks
@@ -250,6 +236,172 @@ void node_update(bNodeTree *ntree, bNode *node)
node->tot.ymax= node->locy + dy;
}
/* ********************* transform ****************** */
/* releases on event, only intern (for extern see below) */
static void transform_nodes(SpaceNode *snode, char *undostr)
{
bNode *node;
float mxstart, mystart, mx, my, *oldlocs, *ol;
int cont=1, tot=0, cancel=0, firsttime=1;
short mval[2], mvalo[2];
char str[64];
/* count total */
for(node= snode->nodetree->nodes.first; node; node= node->next)
if(node->flag & SELECT) tot++;
if(tot==0) return;
/* store oldlocs */
ol= oldlocs= MEM_mallocN(sizeof(float)*2*tot, "oldlocs transform");
for(node= snode->nodetree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
ol[0]= node->locx; ol[1]= node->locy;
ol+= 2;
}
}
getmouseco_areawin(mvalo);
areamouseco_to_ipoco(G.v2d, mvalo, &mxstart, &mystart);
while(cont) {
getmouseco_areawin(mval);
if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || firsttime) {
firsttime= 0;
areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
mvalo[0]= mval[0];
mvalo[1]= mval[1];
for(ol= oldlocs, node= snode->nodetree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
node->locx= ol[0] + mx-mxstart;
node->locy= ol[1] + my-mystart;
node_update(snode->nodetree, node);
ol+= 2;
}
}
sprintf(str, "X: %.1f Y: %.1f", mx-mxstart, my-mystart);
headerprint(str);
force_draw(0);
}
else
PIL_sleep_ms(10);
while (qtest()) {
short val;
unsigned short event= extern_qread(&val);
switch (event) {
case LEFTMOUSE:
case SPACEKEY:
case RETKEY:
cont=0;
break;
case ESCKEY:
case RIGHTMOUSE:
if(val) {
cancel=1;
cont=0;
}
break;
default:
if(val) arrows_move_cursor(event);
break;
}
}
}
if(cancel) {
for(ol= oldlocs, node= snode->nodetree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
node->locx= ol[0];
node->locy= ol[1];
ol+= 2;
node_update(snode->nodetree, node);
}
}
}
else
BIF_undo_push(undostr);
allqueue(REDRAWNODE, 1);
MEM_freeN(oldlocs);
}
/* external call, also for callback */
void node_transform_ext(int mode, int unused)
{
transform_nodes(curarea->spacedata.first, "Translate node");
}
/* ********************** select ******************** */
/* no undo here! */
void node_deselectall(SpaceNode *snode, int swap)
{
bNode *node;
if(swap) {
for(node= snode->nodetree->nodes.first; node; node= node->next)
if(node->flag & SELECT)
break;
if(node==NULL) {
for(node= snode->nodetree->nodes.first; node; node= node->next)
node->flag |= SELECT;
allqueue(REDRAWNODE, 0);
return;
}
/* else pass on to deselect */
}
for(node= snode->nodetree->nodes.first; node; node= node->next)
node->flag &= ~SELECT;
allqueue(REDRAWNODE, 0);
}
static void node_mouse_select(SpaceNode *snode)
{
bNode *node;
float mx, my;
short mval[2];
getmouseco_areawin(mval);
areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
if((G.qual & LR_SHIFTKEY)==0)
node_deselectall(snode, 0);
for(node= snode->nodetree->nodes.first; node; node= node->next) {
if(BLI_in_rctf(&node->tot, mx, my)) {
if(G.qual & LR_SHIFTKEY) {
if(node->flag & SELECT)
node->flag &= ~SELECT;
else
node->flag |= SELECT;
}
else
node->flag |= SELECT;
break;
}
}
/* not so nice (no event), but function below delays redraw otherwise */
force_draw(0);
std_rmouse_transform(node_transform_ext); /* does undo push for select */
}
/* ****************** Add *********************** */
/* editor context */
static void node_add_menu(SpaceNode *snode)
{
@@ -283,30 +435,178 @@ static void node_add_menu(SpaceNode *snode)
node_update(snode->nodetree, node);
/* fake links */
// if(snode->nodetree->nodes.first!=snode->nodetree->nodes.last) {
// bNode *first= snode->nodetree->nodes.first;
//
// nodeAddLink(snode->nodetree, first, first->outputs.first, node, node->inputs.first);
// }
allqueue(REDRAWNODE, 0);
}
BIF_undo_push("Add Node");
}
static void node_select(SpaceNode *snode)
void node_adduplicate(SpaceNode *snode)
{
bNode *node, *nnode;
/* backwards, we add to list end */
for(node= snode->nodetree->nodes.last; node; node= node->prev) {
if(node->flag & SELECT) {
nnode= nodeCopyNode(snode->nodetree, node);
node->flag &= ~SELECT;
nnode->flag |= SELECT;
}
}
transform_nodes(snode, "Duplicate");
}
/* checks mouse position, and returns found node/socket */
/* type is SOCK_IN and/or SOCK_OUT */
static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int type)
{
bNode *node;
float mx, my;
bNodeSocket *sock;
rctf rect;
short mval[2];
getmouseco_areawin(mval);
areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
areamouseco_to_ipoco(G.v2d, mval, &rect.xmin, &rect.ymin);
if((G.qual & LR_SHIFTKEY)==0)
node_deselectall(snode, 0);
rect.xmin -= NODE_SOCK+3;
rect.ymin -= NODE_SOCK+3;
rect.xmax = rect.xmin + 2*NODE_SOCK+6;
rect.ymax = rect.ymin + 2*NODE_SOCK+6;
/* check if we click in a socket */
for(node= snode->nodetree->nodes.first; node; node= node->next) {
if(BLI_in_rctf(&node->tot, mx, my)) {
node->flag |= SELECT;
if(type & SOCK_IN) {
for(sock= node->inputs.first; sock; sock= sock->next) {
if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
*nodep= node;
*sockp= sock;
return 1;
}
}
}
if(type & SOCK_OUT) {
for(sock= node->outputs.first; sock; sock= sock->next) {
if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
*nodep= node;
*sockp= sock;
return 1;
}
}
}
}
allqueue(REDRAWNODE, 0);
return 0;
}
/* loop that adds a link node, called by function below though */
static int node_draw_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock, int type)
{
bNode *tnode;
bNodeSocket *tsock;
bNodeLink *link= NULL;
short mval[2], mvalo[2];
/* we make a temporal link */
if(type==SOCK_OUT)
link= nodeAddLink(snode->nodetree, node, sock, NULL, NULL);
else
link= nodeAddLink(snode->nodetree, NULL, NULL, node, sock);
getmouseco_areawin(mvalo);
while (get_mbut() & L_MOUSE) {
getmouseco_areawin(mval);
if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
mvalo[0]= mval[0];
mvalo[1]= mval[1];
if(type==SOCK_OUT) {
if(find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
if(nodeFindLink(snode->nodetree, sock, tsock)==NULL) {
if(tnode!=node) {
link->tonode= tnode;
link->tosock= tsock;
}
}
}
else {
link->tonode= NULL;
link->tosock= NULL;
}
}
else {
if(find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
if(nodeFindLink(snode->nodetree, sock, tsock)==NULL) {
if(tnode!=node) {
link->fromnode= tnode;
link->fromsock= tsock;
}
}
}
else {
link->fromnode= NULL;
link->fromsock= NULL;
}
}
force_draw(0);
}
else BIF_wait_for_statechange();
}
if(link->tonode==NULL || link->fromnode==NULL) {
BLI_remlink(&snode->nodetree->links, link);
MEM_freeN(link);
}
allqueue(REDRAWNODE, 0);
return 1;
}
static int node_draw_link(SpaceNode *snode)
{
bNode *node;
bNodeSocket *sock;
/* we're going to draw an output */
if(find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
return node_draw_link_drag(snode, node, sock, SOCK_OUT);
}
if(find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
bNodeLink *link;
/* find if we break a link */
for(link= snode->nodetree->links.first; link; link= link->next) {
if(link->tosock==sock)
break;
}
if(link) {
node= link->fromnode;
sock= link->fromsock;
BLI_remlink(&snode->nodetree->links, link);
MEM_freeN(link);
return node_draw_link_drag(snode, node, sock, SOCK_OUT);
}
else {
/* link from input to output */
return node_draw_link_drag(snode, node, sock, SOCK_IN);
}
}
return 0;
}
/* ******************** main event loop ****************** */
void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
{
@@ -323,11 +623,12 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
switch(event) {
case LEFTMOUSE:
node_select(snode);
if(node_draw_link(snode)==0)
node_mouse_select(snode);
break;
case RIGHTMOUSE:
node_select(snode);
node_mouse_select(snode);
break;
case MIDDLEMOUSE:
@@ -356,14 +657,19 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
case AKEY:
if(G.qual==LR_SHIFTKEY)
node_add_menu(snode);
else if(G.qual==0)
else if(G.qual==0) {
node_deselectall(snode, 1);
BIF_undo_push("Deselect all nodes");
}
break;
case DKEY:
if(G.qual==LR_SHIFTKEY)
node_adduplicate(snode);
break;
case CKEY:
break;
case GKEY:
transform_nodes(snode, "Translate Node");
break;
case DELKEY:
case XKEY:

View File

@@ -3537,9 +3537,14 @@ void std_rmouse_transform(void (*xf_func)(int, int))
short timer=0;
short mousebut;
/* check for left mouse select/right mouse select user pref */
if (U.flag & USER_LMOUSESELECT) mousebut = L_MOUSE;
else mousebut = R_MOUSE;
/* check for left mouse select/right mouse select */
if(curarea->spacetype==SPACE_NODE)
mousebut = L_MOUSE|R_MOUSE;
else if (U.flag & USER_LMOUSESELECT)
mousebut = L_MOUSE;
else
mousebut = R_MOUSE;
getmouseco_areawin(mval);
xo= mval[0];

View File

@@ -5248,7 +5248,7 @@ SpaceType *spacenode_get_type(void)
if (!st) {
st= spacetype_new("Node");
spacetype_set_winfuncs(st, drawnodespace, NULL, winqreadnodespace);
spacetype_set_winfuncs(st, drawnodespace, changeview2dspace, winqreadnodespace);
}
return st;