Fix for crashes due to links without fromnode pointers. This can happen with "unfinished" links created during the modal linking operator or when creating links from group tree inputs.

In addition don't store unfinished links in the nodetree->links list any more. This makes code a bit safer because all links in that list can be considered valid now. The temporary bNodeLinkDrag structs used by the modal linking operator are now also stored in a list in SpaceNode, so these links can be drawn too (this separation also allows different display of temporary links, e.g. currently they are drawn on top of all nodes).
This commit is contained in:
Lukas Toenne 2011-03-13 22:07:55 +00:00
parent 1e4010cad6
commit 24f72abf67
5 changed files with 59 additions and 20 deletions

View File

@ -2465,7 +2465,7 @@ static int node_only_value(bNode *node)
if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
int retval= 1;
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->link)
if(sock->link && sock->link->fromnode)
retval &= node_only_value(sock->link->fromnode);
}
return retval;
@ -2623,7 +2623,7 @@ static void freeExecutableNode(bNodeTree *ntree)
for(node= ntree->nodes.first; node; node= node->next) {
if((node->exec & NODE_FINISHED)==0) {
for(sock= node->inputs.first; sock; sock= sock->next)
if(sock->link)
if(sock->link && sock->link->fromnode)
sock->link->fromnode->exec &= ~NODE_FREEBUFS;
}
}

View File

@ -991,6 +991,7 @@ static void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode,
{
bNode *node;
bNodeLink *link;
bNodeLinkDrag *nldrag;
int a;
if(ntree==NULL) return; /* groups... */
@ -1025,6 +1026,14 @@ static void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode,
node_draw_basis(C, ar, snode, ntree, node);
}
}
/* temporary links */
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
for(nldrag= snode->linkdrag.first; nldrag; nldrag= nldrag->next)
node_draw_link(&ar->v2d, snode, nldrag->link);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
static void group_verify_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)

View File

@ -2028,15 +2028,6 @@ void NODE_OT_duplicate(wmOperatorType *ot)
/* *************************** add link op ******************** */
/* temp data to pass on to modal */
typedef struct NodeLinkDrag
{
bNode *node;
bNodeSocket *sock;
bNodeLink *link;
int in_out;
} NodeLinkDrag;
static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeLink *link)
{
bNodeLink *tlink;
@ -2077,7 +2068,7 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
{
SpaceNode *snode= CTX_wm_space_node(C);
ARegion *ar= CTX_wm_region(C);
NodeLinkDrag *nldrag= op->customdata;
bNodeLinkDrag *nldrag= op->customdata;
bNode *tnode, *node;
bNodeSocket *tsock= NULL, *sock;
bNodeLink *link;
@ -2100,11 +2091,15 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
if( link->tosock!= tsock && (!tnode || (tnode!=node && link->tonode!=tnode)) ) {
link->tonode= tnode;
link->tosock= tsock;
if (link->prev==NULL && link->next==NULL)
BLI_addtail(&snode->edittree->links, link);
ntreeSolveOrder(snode->edittree); /* for interactive red line warning */
}
}
}
else {
BLI_remlink(&snode->edittree->links, link);
link->prev = link->next = NULL;
link->tonode= NULL;
link->tosock= NULL;
}
@ -2116,12 +2111,16 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
if( link->fromsock!= tsock && (!tnode || (tnode!=node && link->fromnode!=tnode)) ) {
link->fromnode= tnode;
link->fromsock= tsock;
if (link->prev==NULL && link->next==NULL)
BLI_addtail(&snode->edittree->links, link);
ntreeSolveOrder(snode->edittree); /* for interactive red line warning */
}
}
}
}
else {
BLI_remlink(&snode->edittree->links, link);
link->prev = link->next = NULL;
link->fromnode= NULL;
link->fromsock= NULL;
}
@ -2148,10 +2147,14 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
if (link->tonode && link->tosock) {
link->fromsock = nodeGroupExposeSocket(snode->edittree, link->tosock, SOCK_IN);
link->fromnode = NULL;
if (link->prev==NULL && link->next==NULL)
BLI_addtail(&snode->edittree->links, link);
}
else if (link->fromnode && link->fromsock) {
link->tosock = nodeGroupExposeSocket(snode->edittree, link->fromsock, SOCK_OUT);
link->tonode = NULL;
if (link->prev==NULL && link->next==NULL)
BLI_addtail(&snode->edittree->links, link);
}
}
else
@ -2161,8 +2164,8 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
node_tree_verify_groups(snode->nodetree);
snode_notify(C, snode);
MEM_freeN(op->customdata);
op->customdata= NULL;
BLI_remlink(&snode->linkdrag, nldrag);
MEM_freeN(nldrag);
return OPERATOR_FINISHED;
}
@ -2171,7 +2174,7 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
}
/* return 1 when socket clicked */
static int node_link_init(SpaceNode *snode, NodeLinkDrag *nldrag)
static int node_link_init(SpaceNode *snode, bNodeLinkDrag *nldrag)
{
bNodeLink *link;
@ -2223,7 +2226,8 @@ static int node_link_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
SpaceNode *snode= CTX_wm_space_node(C);
ARegion *ar= CTX_wm_region(C);
NodeLinkDrag *nldrag= MEM_callocN(sizeof(NodeLinkDrag), "drag link op customdata");
bNodeLinkDrag *nldrag= MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
UI_view2d_region_to_view(&ar->v2d, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin,
&snode->mx, &snode->my);
@ -2236,10 +2240,21 @@ static int node_link_invoke(bContext *C, wmOperator *op, wmEvent *event)
op->customdata= nldrag;
/* we make a temporal link */
if(nldrag->in_out==SOCK_OUT)
nldrag->link= nodeAddLink(snode->edittree, nldrag->node, nldrag->sock, NULL, NULL);
else
nldrag->link= nodeAddLink(snode->edittree, NULL, NULL, nldrag->node, nldrag->sock);
if(nldrag->in_out==SOCK_OUT) {
nldrag->link= MEM_callocN(sizeof(bNodeLink), "link");
nldrag->link->fromnode= nldrag->node;
nldrag->link->fromsock= nldrag->sock;
nldrag->link->tonode= NULL;
nldrag->link->tosock= NULL;
}
else {
nldrag->link= MEM_callocN(sizeof(bNodeLink), "link");
nldrag->link->fromnode= NULL;
nldrag->link->fromsock= NULL;
nldrag->link->tonode= nldrag->node;
nldrag->link->tosock= nldrag->sock;
}
BLI_addtail(&snode->linkdrag, nldrag);
/* add modal handler */
WM_event_add_modal_handler(C, op);

View File

@ -40,6 +40,20 @@ struct ARegionType;
struct View2D;
struct bContext;
struct wmWindowManager;
struct bNode;
struct bNodeSocket;
struct bNodeLink;
/* temp data to pass on to modal */
typedef struct bNodeLinkDrag
{
struct bNodeLinkDrag *next, *prev;
struct bNode *node;
struct bNodeSocket *sock;
struct bNodeLink *link;
int in_out;
} bNodeLinkDrag;
/* space_node.c */
ARegion *node_has_buttons_region(ScrArea *sa);

View File

@ -406,6 +406,7 @@ typedef struct SpaceNode {
int treetype; /* treetype: as same nodetree->type */
short texfrom; /* texfrom object, world or brush */
short recalc; /* currently on 0/1, for auto compo */
ListBase linkdrag; /* temporary data for modal linking operator */
struct bGPdata *gpd; /* grease-pencil data */
} SpaceNode;