From 0d7bd0f9b63db4c7891137d18ae6a40e652e190f Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Wed, 19 Oct 2011 17:08:35 +0000 Subject: Adds an update flag to the bNode struct (similar to bNodeTree->update). This prevents access to non-existent typeinfo during type initialization, when node types have been removed and such nodes are deleted from older files. All blenkernel functions now only set the node->update flag instead of directly calling the update function. All operators, etc. calling blenkernel functions to modify nodes should make a ntreeUpdate call afterward (they already did that anyway). Editor/RNA/renderer/etc. high-level functions still can do immediate updates by using nodeUpdate and nodeUpdateID (replacing NodeTagChanged/NodeTagIDChanged respectively). These old functions were previously used only for setting compositor node needexec flags and clearing cached data, but have become generic update functions that require type-specific functionality (i.e. a valid typeinfo struct). --- source/blender/blenkernel/BKE_node.h | 7 ++- source/blender/blenkernel/intern/depsgraph.c | 2 +- source/blender/blenkernel/intern/image.c | 2 +- source/blender/blenkernel/intern/node.c | 52 +++++++++++++--------- source/blender/editors/render/render_internal.c | 4 +- source/blender/editors/space_node/node_draw.c | 4 +- source/blender/editors/space_node/node_edit.c | 22 ++++----- source/blender/editors/space_node/space_node.c | 4 +- source/blender/makesdna/DNA_node_types.h | 11 ++++- source/blender/makesrna/intern/rna_nodetree.c | 4 +- .../blender/nodes/composite/node_composite_tree.c | 27 ++++++----- source/blender/nodes/intern/node_common.c | 6 ++- source/blender/nodes/shader/node_shader_tree.c | 7 ++- source/blender/nodes/texture/node_texture_tree.c | 2 +- source/blender/render/intern/source/pipeline.c | 2 +- 15 files changed, 92 insertions(+), 64 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 1de3c295f4d..b75a8cb29ec 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -346,9 +346,8 @@ struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype); int nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id); void nodeClearActiveID(struct bNodeTree *ntree, short idtype); -void NodeTagChanged(struct bNodeTree *ntree, struct bNode *node); -int NodeTagIDChanged(struct bNodeTree *ntree, struct ID *id); -void ntreeClearTags(struct bNodeTree *ntree); +void nodeUpdate(struct bNodeTree *ntree, struct bNode *node); +int nodeUpdateID(struct bNodeTree *ntree, struct ID *id); void nodeFreePreview(struct bNode *node); @@ -601,7 +600,7 @@ void ntreeCompositTagRender(struct Scene *sce); int ntreeCompositTagAnimated(struct bNodeTree *ntree); void ntreeCompositTagGenerators(struct bNodeTree *ntree); void ntreeCompositForceHidden(struct bNodeTree *ntree, struct Scene *scene); - +void ntreeCompositClearTags(struct bNodeTree *ntree); /* ************** TEXTURE NODES *************** */ diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 80a40c0a3a3..8d0c20ecc52 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1962,7 +1962,7 @@ static void dag_tag_renderlayers(Scene *sce, unsigned int lay) if(node->id==(ID *)sce) { SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); if(srl && (srl->lay & lay_changed)) - NodeTagChanged(sce->nodetree, node); + nodeUpdate(sce->nodetree, node); } } } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index cf8f96c143a..1de581034a4 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1514,7 +1514,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) Scene *scene; for(scene= G.main->scene.first; scene; scene= scene->id.next) { if(scene->nodetree) { - NodeTagIDChanged(scene->nodetree, &ima->id); + nodeUpdateID(scene->nodetree, &ima->id); } } } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index f0be3c99f13..a46b358798a 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -184,7 +184,7 @@ bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char else if (in_out==SOCK_OUT) BLI_addtail(&node->outputs, sock); - ntree->update |= NTREE_UPDATE_NODES; + node->update |= NODE_UPDATE; return sock; } @@ -197,7 +197,7 @@ bNodeSocket *nodeInsertSocket(bNodeTree *ntree, bNode *node, int in_out, bNodeSo else if (in_out==SOCK_OUT) BLI_insertlinkbefore(&node->outputs, next_sock, sock); - ntree->update |= NTREE_UPDATE_NODES; + node->update |= NODE_UPDATE; return sock; } @@ -221,7 +221,7 @@ void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock) MEM_freeN(sock->default_value); MEM_freeN(sock); - ntree->update |= NTREE_UPDATE_NODES; + node->update |= NODE_UPDATE; } void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node) @@ -246,7 +246,7 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node) BLI_freelistN(&node->outputs); - ntree->update |= NTREE_UPDATE_NODES; + node->update |= NODE_UPDATE; } /* finds a node based on its name */ @@ -823,7 +823,7 @@ void nodeUnlinkNode(bNodeTree *ntree, bNode *node) if(link->fromnode==node) { lb= &node->outputs; if (link->tonode) - NodeTagChanged(ntree, link->tonode); + link->tonode->update |= NODE_UPDATE; } else if(link->tonode==node) lb= &node->inputs; @@ -1495,18 +1495,19 @@ void ntreeUpdateTree(bNodeTree *ntree) /* update individual nodes */ for (n=0; n < totnodes; ++n) { node = deplist[n]; - if (ntreetype->update_node) - ntreetype->update_node(ntree, node); - else if (node->typeinfo->updatefunc) - node->typeinfo->updatefunc(ntree, node); + + /* node tree update tags override individual node update flags */ + if ((node->update & NODE_UPDATE) || (ntree->update & NTREE_UPDATE)) { + if (ntreetype->update_node) + ntreetype->update_node(ntree, node); + else if (node->typeinfo->updatefunc) + node->typeinfo->updatefunc(ntree, node); + } + /* clear update flag */ + node->update = 0; } MEM_freeN(deplist); - - /* ensures only a single output node is enabled, texnode allows multiple though */ - if(ntree->type!=NTREE_TEXTURE) - ntreeSetOutput(ntree); - } /* general tree updates */ @@ -1518,6 +1519,9 @@ void ntreeUpdateTree(bNodeTree *ntree) if (ntreetype->update) ntreetype->update(ntree); else { + /* Trees can be associated with a specific node type (i.e. group nodes), + * in that case a tree update function may be defined by that node type. + */ bNodeType *ntype= node_get_type(ntree, ntree->nodetype); if (ntype && ntype->updatetreefunc) ntype->updatetreefunc(ntree); @@ -1530,24 +1534,24 @@ void ntreeUpdateTree(bNodeTree *ntree) ntree->update = 0; } -void NodeTagChanged(bNodeTree *ntree, bNode *node) +void nodeUpdate(bNodeTree *ntree, bNode *node) { - bNodeTreeType *ntreetype = ntreeGetType(ntree->type); + bNodeTreeType *ntreetype= ntreeGetType(ntree->type); - /* extra null pointer checks here because this is called when unlinking - unknown nodes on file load, so typeinfo pointers may not be set */ - if (ntreetype && ntreetype->update_node) + if (ntreetype->update_node) ntreetype->update_node(ntree, node); - else if (node->typeinfo && node->typeinfo->updatefunc) + else if (node->typeinfo->updatefunc) node->typeinfo->updatefunc(ntree, node); + /* clear update flag */ + node->update = 0; } -int NodeTagIDChanged(bNodeTree *ntree, ID *id) +int nodeUpdateID(bNodeTree *ntree, ID *id) { bNodeTreeType *ntreetype; bNode *node; int change = FALSE; - + if(ELEM(NULL, id, ntree)) return change; @@ -1558,6 +1562,8 @@ int NodeTagIDChanged(bNodeTree *ntree, ID *id) if(node->id==id) { change = TRUE; ntreetype->update_node(ntree, node); + /* clear update flag */ + node->update = 0; } } } @@ -1567,6 +1573,8 @@ int NodeTagIDChanged(bNodeTree *ntree, ID *id) change = TRUE; if (node->typeinfo->updatefunc) node->typeinfo->updatefunc(ntree, node); + /* clear update flag */ + node->update = 0; } } } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 0b350e3afd0..d80f3fef125 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -398,13 +398,13 @@ static void render_endjob(void *rjv) ED_update_for_newframe(G.main, rj->scene, rj->win->screen, 1); /* XXX above function sets all tags in nodes */ - ntreeClearTags(rj->scene->nodetree); + ntreeCompositClearTags(rj->scene->nodetree); /* potentially set by caller */ rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE; if(rj->srl) { - NodeTagIDChanged(rj->scene->nodetree, &rj->scene->id); + nodeUpdateID(rj->scene->nodetree, &rj->scene->id); WM_main_add_notifier(NC_NODE|NA_EDITED, rj->scene); } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index e713ed5a678..baa47d4147e 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -102,12 +102,12 @@ void ED_node_changed_update(ID *id, bNode *node) WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, id); } else if(treetype==NTREE_COMPOSIT) { - NodeTagChanged(edittree, node); + nodeUpdate(edittree, node); /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */ node= node_tree_get_editgroup(nodetree); if(node) - NodeTagIDChanged(nodetree, node->id); + nodeUpdateID(nodetree, node->id); WM_main_add_notifier(NC_SCENE|ND_NODES, id); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index baa755ef841..85942901c00 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -496,17 +496,17 @@ void snode_set_context(SpaceNode *snode, Scene *scene) node_tree_from_ID(snode->id, &snode->nodetree, &snode->edittree, NULL); } -static void snode_tag_changed(SpaceNode *snode, bNode *node) +static void snode_update(SpaceNode *snode, bNode *node) { bNode *gnode; if (node) - NodeTagChanged(snode->edittree, node); + nodeUpdate(snode->edittree, node); /* if inside group, tag entire group */ gnode= node_tree_get_editgroup(snode->nodetree); if(gnode) - NodeTagIDChanged(snode->nodetree, gnode->id); + nodeUpdateID(snode->nodetree, gnode->id); } static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup) @@ -1775,7 +1775,7 @@ static void node_link_viewer(SpaceNode *snode, bNode *tonode) link->fromsock= sock; } ntreeUpdateTree(snode->edittree); - snode_tag_changed(snode, node); + snode_update(snode, node); } } } @@ -2127,7 +2127,7 @@ void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace) continue; } - snode_tag_changed(snode, node_to); + snode_update(snode, node_to); ++numlinks; break; } @@ -2175,7 +2175,7 @@ bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene, bNodeTemplate if(node->id) id_us_plus(node->id); - snode_tag_changed(snode, node); + snode_update(snode, node); } if(snode->nodetree->type==NTREE_TEXTURE) { @@ -2412,7 +2412,7 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event) case MIDDLEMOUSE: if(link->tosock && link->fromsock) { /* send changed events for original tonode and new */ - snode_tag_changed(snode, link->tonode); + snode_update(snode, link->tonode); /* we might need to remove a link */ if(in_out==SOCK_OUT) @@ -2495,7 +2495,7 @@ static int node_link_init(SpaceNode *snode, bNodeLinkDrag *nldrag) if(link) { /* send changed event to original tonode */ if(link->tonode) - snode_tag_changed(snode, link->tonode); + snode_update(snode, link->tonode); nldrag->node= link->fromnode; nldrag->sock= link->fromsock; @@ -2663,7 +2663,7 @@ static int cut_links_exec(bContext *C, wmOperator *op) next= link->next; if(cut_links_intersect(link, mcoords, i)) { - snode_tag_changed(snode, link->tonode); + snode_update(snode, link->tonode); nodeRemLink(snode->edittree, link); } } @@ -2794,7 +2794,7 @@ void ED_node_link_insert(ScrArea *sa) nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs, sockto->type), node, sockto); ntreeUpdateTree(snode->edittree); /* needed for pointers */ - snode_tag_changed(snode, select); + snode_update(snode, select); ED_node_changed_update(snode->id, select); } } @@ -3198,7 +3198,7 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op)) /* Be able to mute in-/output nodes as well. - DingTo if(node->inputs.first && node->outputs.first) { */ node->flag ^= NODE_MUTED; - snode_tag_changed(snode, node); + snode_update(snode, node); } } diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 9c4581a43da..1047e906a10 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -244,10 +244,10 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) if(type==NTREE_COMPOSIT) { Scene *scene= wmn->window->screen->scene; - /* note that NodeTagIDChanged is already called by BKE_image_signal() on all + /* note that nodeUpdateID is already called by BKE_image_signal() on all * scenes so really this is just to know if the images is used in the compo else * painting on images could become very slow when the compositor is open. */ - if(NodeTagIDChanged(scene->nodetree, wmn->reference)) + if(nodeUpdateID(scene->nodetree, wmn->reference)) ED_area_tag_refresh(sa); } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 4cfd0b56b70..f03cc200a56 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -154,7 +154,9 @@ typedef struct bNode { float locx, locy; /* root offset for drawing */ float width, height; /* node custom width and height */ float miniwidth; /* node width if hidden */ - int pad; + + int update; /* update flags */ + char label[32]; /* custom user-defined label */ short custom1, custom2; /* to be abused for buttons */ float custom3, custom4; @@ -192,6 +194,13 @@ typedef struct bNode { /* automatic flag for nodes included in transforms */ #define NODE_TRANSFORM (1<<13) +/* node->update */ +/* XXX NODE_UPDATE is a generic update flag. More fine-grained updates + * might be used in the future, but currently all work the same way. + */ +#define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */ +#define NODE_UPDATE_ID 1 /* associated id data block has changed */ + typedef struct bNodeLink { struct bNodeLink *next, *prev; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 061a21056d0..7d20378d55e 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -568,7 +568,7 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *UNUSED(C), Repor } else { ntreeUpdateTree(ntree); /* update group node socket links*/ - NodeTagChanged(ntree, node); + nodeUpdate(ntree, node); WM_main_add_notifier(NC_NODE|NA_EDITED, ntree); if (group) @@ -651,7 +651,7 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports, b ret= nodeAddLink(ntree, fromnode, in, tonode, out); if(ret) { - NodeTagChanged(ntree, tonode); + nodeUpdate(ntree, tonode); ntreeUpdateTree(ntree); diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 5c58070be9d..6f4939ecbdd 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -183,6 +183,11 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree) } } +static void update(bNodeTree *ntree) +{ + ntreeSetOutput(ntree); +} + bNodeTreeType ntreeType_Composite = { /* type */ NTREE_COMPOSIT, /* idname */ "NTCompositing Nodetree", @@ -195,7 +200,7 @@ bNodeTreeType ntreeType_Composite = { /* localize */ localize, /* local_sync */ local_sync, /* local_merge */ local_merge, - /* update */ NULL, + /* update */ update, /* update_node */ update_node }; @@ -716,9 +721,9 @@ void ntreeCompositTagRender(Scene *curscene) for(node= sce->nodetree->nodes.first; node; node= node->next) { if(node->id==(ID *)curscene || node->type==CMP_NODE_COMPOSITE) - NodeTagChanged(sce->nodetree, node); + nodeUpdate(sce->nodetree, node); else if(node->type==CMP_NODE_TEXTURE) /* uses scene sizex/sizey */ - NodeTagChanged(sce->nodetree, node); + nodeUpdate(sce->nodetree, node); } } } @@ -745,7 +750,7 @@ static int node_animation_properties(bNodeTree *ntree, bNode *node) for (index=0; indextype==CMP_NODE_IMAGE) { Image *ima= (Image *)node->id; if(ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { - NodeTagChanged(ntree, node); + nodeUpdate(ntree, node); tagged= 1; } } else if(node->type==CMP_NODE_TIME) { - NodeTagChanged(ntree, node); + nodeUpdate(ntree, node); tagged= 1; } /* here was tag render layer, but this is called after a render, so re-composites fail */ else if(node->type==NODE_GROUP) { if( ntreeCompositTagAnimated((bNodeTree *)node->id) ) { - NodeTagChanged(ntree, node); + nodeUpdate(ntree, node); } } } @@ -818,12 +823,12 @@ void ntreeCompositTagGenerators(bNodeTree *ntree) for(node= ntree->nodes.first; node; node= node->next) { if( ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_IMAGE)) - NodeTagChanged(ntree, node); + nodeUpdate(ntree, node); } } /* XXX after render animation system gets a refresh, this call allows composite to end clean */ -void ntreeClearTags(bNodeTree *ntree) +void ntreeCompositClearTags(bNodeTree *ntree) { bNode *node; @@ -832,6 +837,6 @@ void ntreeClearTags(bNodeTree *ntree) for(node= ntree->nodes.first; node; node= node->next) { node->need_exec= 0; if(node->type==NODE_GROUP) - ntreeClearTags((bNodeTree *)node->id); + ntreeCompositClearTags((bNodeTree *)node->id); } } diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 56f80840112..4dbf4b96b74 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -239,9 +239,11 @@ bNode *node_group_make_from_selected(bNodeTree *ntree) } } + /* update of the group tree */ ngroup->update |= NTREE_UPDATE; ntreeUpdateTree(ngroup); - ntree->update |= NTREE_UPDATE_NODES|NTREE_UPDATE_LINKS; + /* update of the tree containing the group instance node */ + ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS; ntreeUpdateTree(ntree); return gnode; @@ -559,7 +561,7 @@ int node_group_ungroup(bNodeTree *ntree, bNode *gnode) /* free the group tree (takes care of user count) */ free_libblock(&G.main->nodetree, wgroup); - ntree->update |= NTREE_UPDATE_NODES|NTREE_UPDATE_LINKS; + ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS; ntreeUpdateTree(ntree); return 1; diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 28f0f983454..9f3e7ce3c73 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -85,6 +85,11 @@ static void local_sync(bNodeTree *localtree, bNodeTree *ntree) } } +static void update(bNodeTree *ntree) +{ + ntreeSetOutput(ntree); +} + bNodeTreeType ntreeType_Shader = { /* type */ NTREE_SHADER, /* id_name */ "NTShader Nodetree", @@ -97,7 +102,7 @@ bNodeTreeType ntreeType_Shader = { /* localize */ NULL, /* local_sync */ local_sync, /* local_merge */ NULL, - /* update */ NULL, + /* update */ update, /* update_node */ NULL }; diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 603aa7ceb77..2b016177820 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -108,7 +108,7 @@ int ntreeTexTagAnimated(bNodeTree *ntree) for(node= ntree->nodes.first; node; node= node->next) { if(node->type==TEX_NODE_CURVE_TIME) { - NodeTagChanged(ntree, node); + nodeUpdate(ntree, node); return 1; } else if(node->type==NODE_GROUP) { diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7835ae6dcd3..19dc0538dba 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2261,7 +2261,7 @@ static void ntree_render_scenes(Render *re) restore_scene= (scene != re->scene); node->id->flag &= ~LIB_DOIT; - NodeTagChanged(re->scene->nodetree, node); + nodeUpdate(re->scene->nodetree, node); } } } -- cgit v1.2.3