From ffcc63a7d0ef6e0651412588ec5e8867e7e0e023 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Aug 2012 08:54:18 +0000 Subject: node tree functions for copy/free now support optional ID user count management, this is not used yet, so no functional changes. --- source/blender/blenkernel/BKE_node.h | 24 ++++++---- source/blender/blenkernel/intern/lamp.c | 4 +- source/blender/blenkernel/intern/library.c | 4 +- source/blender/blenkernel/intern/material.c | 12 ++--- source/blender/blenkernel/intern/node.c | 65 +++++++++++++++++++++++--- source/blender/blenkernel/intern/scene.c | 6 +-- source/blender/blenkernel/intern/texture.c | 4 +- source/blender/blenkernel/intern/world.c | 4 +- source/blender/editors/space_node/node_group.c | 2 +- 9 files changed, 92 insertions(+), 33 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index c45afbe77a9..2a0679e3977 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -301,21 +301,29 @@ struct bNodeType *ntreeGetNodeType(struct bNodeTree *ntree); struct bNodeSocketType *ntreeGetSocketType(int type); struct bNodeTree *ntreeAddTree(const char *name, int type, int nodetype); -void ntreeInitTypes(struct bNodeTree *ntree); +void ntreeInitTypes(struct bNodeTree *ntree); -void ntreeFreeTree(struct bNodeTree *ntree); +/* copy/free funcs, need to manage ID users */ +void ntreeFreeTree_ex(struct bNodeTree *ntree, const short do_id_user); +void ntreeFreeTree(struct bNodeTree *ntree); +struct bNodeTree *ntreeCopyTree_ex(struct bNodeTree *ntree, const short do_id_user); struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree); -void ntreeSwitchID(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to); -void ntreeMakeLocal(struct bNodeTree *ntree); -int ntreeHasType(struct bNodeTree *ntree, int type); +void ntreeSwitchID_ex(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to, const short do_id_user); +void ntreeSwitchID(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to); +/* node->id user count */ +void ntreeUserIncrefID(struct bNodeTree *ntree); +void ntreeUserDecrefID(struct bNodeTree *ntree); -void ntreeUpdateTree(struct bNodeTree *ntree); + +void ntreeMakeLocal(struct bNodeTree *ntree); +int ntreeHasType(struct bNodeTree *ntree, int type); +void ntreeUpdateTree(struct bNodeTree *ntree); /* XXX Currently each tree update call does call to ntreeVerifyNodes too. * Some day this should be replaced by a decent depsgraph automatism! */ -void ntreeVerifyNodes(struct Main *main, struct ID *id); +void ntreeVerifyNodes(struct Main *main, struct ID *id); -void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes); +void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes); /* XXX old trees handle output flags automatically based on special output node types and last active selection. * new tree types have a per-output socket flag to indicate the final output to use explicitly. diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 4782d09a7c8..6a802236ec4 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -120,7 +120,7 @@ Lamp *BKE_lamp_copy(Lamp *la) lan->curfalloff = curvemapping_copy(la->curfalloff); if (la->nodetree) - lan->nodetree = ntreeCopyTree(la->nodetree); + lan->nodetree = ntreeCopyTree_ex(la->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ if (la->preview) lan->preview = BKE_previewimg_copy(la->preview); @@ -223,7 +223,7 @@ void BKE_lamp_free(Lamp *la) /* is no lib link block, but lamp extension */ if (la->nodetree) { - ntreeFreeTree(la->nodetree); + ntreeFreeTree_ex(la->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ MEM_freeN(la->nodetree); } diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index e073cfdf76d..f1d1d128c16 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -348,7 +348,7 @@ int id_copy(ID *id, ID **newid, int test) if (!test) *newid = (ID *)BKE_action_copy((bAction *)id); return 1; case ID_NT: - if (!test) *newid = (ID *)ntreeCopyTree((bNodeTree *)id); + if (!test) *newid = (ID *)ntreeCopyTree_ex((bNodeTree *)id, FALSE); /* TODO: do_id_user arg needs checking */ return 1; case ID_BR: if (!test) *newid = (ID *)BKE_brush_copy((Brush *)id); @@ -881,7 +881,7 @@ void BKE_libblock_free(ListBase *lb, void *idv) BKE_action_free((bAction *)id); break; case ID_NT: - ntreeFreeTree((bNodeTree *)id); + ntreeFreeTree_ex((bNodeTree *)id, FALSE); /* TODO: do_id_user arg needs checking */ break; case ID_BR: BKE_brush_free((Brush *)id); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index e5f392e4bce..a1288b8af08 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -101,7 +101,7 @@ void BKE_material_free(Material *ma) /* is no lib link block, but material extension */ if (ma->nodetree) { - ntreeFreeTree(ma->nodetree); + ntreeFreeTree_ex(ma->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ MEM_freeN(ma->nodetree); } @@ -235,7 +235,7 @@ Material *BKE_material_copy(Material *ma) if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview); if (ma->nodetree) { - man->nodetree = ntreeCopyTree(ma->nodetree); /* 0 == full new tree */ + man->nodetree = ntreeCopyTree_ex(ma->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ } man->gpumaterial.first = man->gpumaterial.last = NULL; @@ -1511,7 +1511,7 @@ void free_matcopybuf(void) matcopybuf.ramp_spec = NULL; if (matcopybuf.nodetree) { - ntreeFreeTree(matcopybuf.nodetree); + ntreeFreeTree_ex(matcopybuf.nodetree, FALSE); /* TODO: do_id_user arg needs checking */ MEM_freeN(matcopybuf.nodetree); matcopybuf.nodetree = NULL; } @@ -1537,7 +1537,7 @@ void copy_matcopybuf(Material *ma) matcopybuf.mtex[a] = MEM_dupallocN(mtex); } } - matcopybuf.nodetree = ntreeCopyTree(ma->nodetree); + matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ matcopybuf.preview = NULL; matcopybuf.gpumaterial.first = matcopybuf.gpumaterial.last = NULL; matcopied = 1; @@ -1561,7 +1561,7 @@ void paste_matcopybuf(Material *ma) } if (ma->nodetree) { - ntreeFreeTree(ma->nodetree); + ntreeFreeTree_ex(ma->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ MEM_freeN(ma->nodetree); } @@ -1582,7 +1582,7 @@ void paste_matcopybuf(Material *ma) } } - ma->nodetree = ntreeCopyTree(matcopybuf.nodetree); + ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, FALSE); /* TODO: do_id_user arg needs checking */ } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 62e80645a35..56ae912756e 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -671,7 +671,7 @@ bNodeTree *ntreeAddTree(const char *name, int type, int nodetype) * copying for internal use (threads for eg), where you wont want it to modify the * scene data. */ -static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_extern) +static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern) { bNodeTree *newtree; bNode *node /*, *nnode */ /* UNUSED */, *last; @@ -702,6 +702,11 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e last = ntree->nodes.last; for (node = ntree->nodes.first; node; node = node->next) { + /* ntreeUserDecrefID inline */ + if (do_id_user) { + id_us_min(node->id); + } + if (do_make_extern) { id_lib_extern(node->id); } @@ -751,22 +756,56 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e return newtree; } +bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user) +{ + return ntreeCopyTree_internal(ntree, do_id_user, TRUE); +} bNodeTree *ntreeCopyTree(bNodeTree *ntree) { - return ntreeCopyTree_internal(ntree, TRUE); + return ntreeCopyTree_ex(ntree, TRUE); } /* use when duplicating scenes */ -void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to) +void ntreeSwitchID_ex(bNodeTree *ntree, ID *id_from, ID *id_to, const short do_id_user) { bNode *node; + + if (id_from == id_to) { + /* should never happen but may as well skip if it does */ + return; + } + /* for scene duplication only */ for (node = ntree->nodes.first; node; node = node->next) { if (node->id == id_from) { + if (do_id_user) { + id_us_min(id_from); + id_us_plus(id_to); + } + node->id = id_to; } } } +void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to) +{ + ntreeSwitchID_ex(ntree, id_from, id_to, TRUE); +} + +void ntreeUserIncrefID(bNodeTree *ntree) +{ + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + id_us_plus(node->id); + } +} +void ntreeUserDecrefID(bNodeTree *ntree) +{ + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + id_us_min(node->id); + } +} /* *************** preview *********** */ /* if node->preview, then we assume the rect to exist */ @@ -913,6 +952,7 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent) } } +/** \note caller needs to manage node->id user */ void nodeFreeNode(bNodeTree *ntree, bNode *node) { bNodeSocket *sock, *nextsock; @@ -956,7 +996,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) } /* do not free ntree itself here, BKE_libblock_free calls this function too */ -void ntreeFreeTree(bNodeTree *ntree) +void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) { bNode *node, *next; bNodeSocket *sock; @@ -990,6 +1030,12 @@ void ntreeFreeTree(bNodeTree *ntree) for (node = ntree->nodes.first; node; node = next) { next = node->next; + + /* ntreeUserIncrefID inline */ + if (do_id_user) { + id_us_min(node->id); + } + nodeFreeNode(ntree, node); } @@ -1000,6 +1046,11 @@ void ntreeFreeTree(bNodeTree *ntree) node_socket_free_default_value(sock->type, sock->default_value); BLI_freelistN(&ntree->outputs); } +/* same as ntreeFreeTree_ex but always manage users */ +void ntreeFreeTree(bNodeTree *ntree) +{ + ntreeFreeTree_ex(ntree, TRUE); +} void ntreeFreeCache(bNodeTree *ntree) { @@ -1137,7 +1188,7 @@ void ntreeMakeLocal(bNodeTree *ntree) } else if (cd.local && cd.lib) { /* this is the mixed case, we copy the tree and assign it to local users */ - bNodeTree *newtree = ntreeCopyTree(ntree); + bNodeTree *newtree = ntreeCopyTree_ex(ntree, FALSE); /* TODO: do_id_user arg needs checking */ newtree->id.us = 0; @@ -1188,7 +1239,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) } /* node copy func */ - ltree = ntreeCopyTree_internal(ntree, FALSE); + ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE); if (adt) { AnimData *ladt = BKE_animdata_from_id(<ree->id); @@ -1248,7 +1299,7 @@ void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) if (ntreetype->local_merge) ntreetype->local_merge(localtree, ntree); - ntreeFreeTree(localtree); + ntreeFreeTree_ex(localtree, FALSE); /* TODO: do_id_user arg needs checking */ MEM_freeN(localtree); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d476e90498c..4fd08c8f6f8 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -153,8 +153,8 @@ Scene *BKE_scene_copy(Scene *sce, int type) BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets)); if (sce->nodetree) { - scen->nodetree = ntreeCopyTree(sce->nodetree); /* copies actions */ - ntreeSwitchID(scen->nodetree, &sce->id, &scen->id); + scen->nodetree = ntreeCopyTree_ex(sce->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ /* copies actions */ + ntreeSwitchID_ex(scen->nodetree, &sce->id, &scen->id, FALSE); } obase = sce->base.first; @@ -321,7 +321,7 @@ void BKE_scene_free(Scene *sce) } if (sce->nodetree) { - ntreeFreeTree(sce->nodetree); + ntreeFreeTree_ex(sce->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ MEM_freeN(sce->nodetree); } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 2f54fe6cebd..66b096b14f1 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -430,7 +430,7 @@ void BKE_texture_free(Tex *tex) tex->id.icon_id = 0; if (tex->nodetree) { - ntreeFreeTree(tex->nodetree); + ntreeFreeTree_ex(tex->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ MEM_freeN(tex->nodetree); } } @@ -697,7 +697,7 @@ Tex *BKE_texture_copy(Tex *tex) if (tex->nodetree->execdata) { ntreeTexEndExecTree(tex->nodetree->execdata, 1); } - texn->nodetree = ntreeCopyTree(tex->nodetree); + texn->nodetree = ntreeCopyTree_ex(tex->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ } return texn; diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index dd71e43182e..418d7da6b85 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -67,7 +67,7 @@ void BKE_world_free(World *wrld) /* is no lib link block, but world extension */ if (wrld->nodetree) { - ntreeFreeTree(wrld->nodetree); + ntreeFreeTree_ex(wrld->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ MEM_freeN(wrld->nodetree); } @@ -129,7 +129,7 @@ World *BKE_world_copy(World *wrld) } if (wrld->nodetree) { - wrldn->nodetree = ntreeCopyTree(wrld->nodetree); + wrldn->nodetree = ntreeCopyTree_ex(wrld->nodetree, FALSE); /* TODO: do_id_user arg needs checking */ } if (wrld->preview) diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index efd2378bf31..4e3529738e6 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -424,7 +424,7 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) * - all of wgroup's nodes are transferred across to their new home * - ngroup (i.e. the source NodeTree) is left unscathed */ - wgroup = ntreeCopyTree(ngroup); + wgroup = ntreeCopyTree_ex(ngroup, FALSE); /* TODO: do_id_user arg needs checking */ /* add the nodes into the ntree */ for (node = wgroup->nodes.first; node; node = nextn) { -- cgit v1.2.3