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:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user