Attempt to sanitize node tree deletion
Make it explicit when freeing node tree which is owned by other ID or when freeing node tree which is outside of a bmain.
This commit is contained in:
@@ -332,6 +332,8 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char
|
||||
|
||||
/* copy/free funcs, need to manage ID users */
|
||||
void ntreeFreeTree(struct bNodeTree *ntree);
|
||||
/* Free tree which is owned byt another datablock. */
|
||||
void ntreeFreeNestedTree(struct bNodeTree *ntree);
|
||||
void BKE_node_tree_copy_data(struct Main *bmain, struct bNodeTree *ntree_dst, const struct bNodeTree *ntree_src, const int flag);
|
||||
struct bNodeTree *ntreeCopyTree_ex(const struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user);
|
||||
struct bNodeTree *ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntree);
|
||||
@@ -343,6 +345,7 @@ void ntreeUserDecrefID(struct bNodeTree *ntree);
|
||||
struct bNodeTree *ntreeFromID(const struct ID *id);
|
||||
|
||||
void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist, const bool lib_local);
|
||||
void ntreeFreeLocalTree(struct bNodeTree *ntree);
|
||||
struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type);
|
||||
bool ntreeHasType(const struct bNodeTree *ntree, int type);
|
||||
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);
|
||||
|
||||
@@ -177,7 +177,7 @@ void BKE_lamp_free(Lamp *la)
|
||||
|
||||
/* is no lib link block, but lamp extension */
|
||||
if (la->nodetree) {
|
||||
ntreeFreeTree(la->nodetree);
|
||||
ntreeFreeNestedTree(la->nodetree);
|
||||
MEM_freeN(la->nodetree);
|
||||
la->nodetree = NULL;
|
||||
}
|
||||
|
||||
@@ -679,19 +679,13 @@ void BKE_libblock_relink_to_newid(ID *id)
|
||||
|
||||
void BKE_libblock_free_data(ID *id, const bool do_id_user)
|
||||
{
|
||||
/* NOTE: We set pointers to NULL so subsequent call of this function doesn't
|
||||
* cause double-free.
|
||||
* This is mainly to prevent crazy behavior of ntreeFreeTree() which does
|
||||
* call BKE_libblock_free_data() for nodetrees outside of bmain. */
|
||||
if (id->properties) {
|
||||
IDP_FreeProperty_ex(id->properties, do_id_user);
|
||||
MEM_freeN(id->properties);
|
||||
id->properties = NULL;
|
||||
}
|
||||
|
||||
if (id->override_static) {
|
||||
BKE_override_static_free(&id->override_static);
|
||||
id->override_static = NULL;
|
||||
}
|
||||
|
||||
/* XXX TODO remove animdata handling from each type's freeing func, and do it here, like for copy! */
|
||||
|
||||
@@ -139,7 +139,7 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle)
|
||||
|
||||
/* is no lib link block, but linestyle extension */
|
||||
if (linestyle->nodetree) {
|
||||
ntreeFreeTree(linestyle->nodetree);
|
||||
ntreeFreeNestedTree(linestyle->nodetree);
|
||||
MEM_freeN(linestyle->nodetree);
|
||||
linestyle->nodetree = NULL;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ void BKE_material_free(Material *ma)
|
||||
|
||||
/* is no lib link block, but material extension */
|
||||
if (ma->nodetree) {
|
||||
ntreeFreeTree(ma->nodetree);
|
||||
ntreeFreeNestedTree(ma->nodetree);
|
||||
MEM_freeN(ma->nodetree);
|
||||
ma->nodetree = NULL;
|
||||
}
|
||||
@@ -1373,7 +1373,7 @@ void clear_matcopybuf(void)
|
||||
void free_matcopybuf(void)
|
||||
{
|
||||
if (matcopybuf.nodetree) {
|
||||
ntreeFreeTree(matcopybuf.nodetree);
|
||||
ntreeFreeLocalTree(matcopybuf.nodetree);
|
||||
MEM_freeN(matcopybuf.nodetree);
|
||||
matcopybuf.nodetree = NULL;
|
||||
}
|
||||
@@ -1406,7 +1406,7 @@ void paste_matcopybuf(Main *bmain, Material *ma)
|
||||
GPU_material_free(&ma->gpumaterial);
|
||||
|
||||
if (ma->nodetree) {
|
||||
ntreeFreeTree(ma->nodetree);
|
||||
ntreeFreeNestedTree(ma->nodetree);
|
||||
MEM_freeN(ma->nodetree);
|
||||
}
|
||||
|
||||
|
||||
@@ -1870,8 +1870,24 @@ void ntreeFreeTree(bNodeTree *ntree)
|
||||
if (ntree->duplilock)
|
||||
BLI_mutex_free(ntree->duplilock);
|
||||
|
||||
/* if ntree is not part of library, free the libblock data explicitly */
|
||||
if (ntree->id.tag & LIB_TAG_NO_MAIN) {
|
||||
if (ntree->id.tag & LIB_TAG_LOCALIZED) {
|
||||
BKE_libblock_free_data(&ntree->id, true);
|
||||
}
|
||||
}
|
||||
|
||||
void ntreeFreeNestedTree(bNodeTree *ntree)
|
||||
{
|
||||
ntreeFreeTree(ntree);
|
||||
BKE_libblock_free_data(&ntree->id, true);
|
||||
}
|
||||
|
||||
void ntreeFreeLocalTree(bNodeTree *ntree)
|
||||
{
|
||||
if (ntree->id.tag & LIB_TAG_LOCALIZED) {
|
||||
ntreeFreeTree(ntree);
|
||||
}
|
||||
else {
|
||||
ntreeFreeTree(ntree);
|
||||
BKE_libblock_free_data(&ntree->id, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,7 +470,7 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
|
||||
|
||||
/* is no lib link block, but scene extension */
|
||||
if (sce->nodetree) {
|
||||
ntreeFreeTree(sce->nodetree);
|
||||
ntreeFreeNestedTree(sce->nodetree);
|
||||
MEM_freeN(sce->nodetree);
|
||||
sce->nodetree = NULL;
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ void BKE_texture_free(Tex *tex)
|
||||
|
||||
/* is no lib link block, but texture extension */
|
||||
if (tex->nodetree) {
|
||||
ntreeFreeTree(tex->nodetree);
|
||||
ntreeFreeNestedTree(tex->nodetree);
|
||||
MEM_freeN(tex->nodetree);
|
||||
tex->nodetree = NULL;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ void BKE_world_free(World *wrld)
|
||||
|
||||
/* is no lib link block, but world extension */
|
||||
if (wrld->nodetree) {
|
||||
ntreeFreeTree(wrld->nodetree);
|
||||
ntreeFreeNestedTree(wrld->nodetree);
|
||||
MEM_freeN(wrld->nodetree);
|
||||
wrld->nodetree = NULL;
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
||||
|
||||
/* Don't enable compositing nodes. */
|
||||
if (scene->nodetree) {
|
||||
ntreeFreeTree(scene->nodetree);
|
||||
ntreeFreeNestedTree(scene->nodetree);
|
||||
MEM_freeN(scene->nodetree);
|
||||
scene->nodetree = NULL;
|
||||
scene->use_nodes = false;
|
||||
|
||||
@@ -714,7 +714,7 @@ GPUMaterial *GPU_material_from_nodetree(
|
||||
|
||||
/* Only free after GPU_pass_shader_get where GPUUniformBuffer
|
||||
* read data from the local tree. */
|
||||
ntreeFreeTree(localtree);
|
||||
ntreeFreeLocalTree(localtree);
|
||||
MEM_freeN(localtree);
|
||||
|
||||
/* note that even if building the shader fails in some way, we still keep
|
||||
|
||||
Reference in New Issue
Block a user