Cleanup: Move Outliner runtime hash into internal runtime struct, out of DNA

This way Outliner internal data stays internal, non-Outliner code will not be
able to access and mess with this. Further it allows us to use the real type
(rather than `void *`), change the type to a C++ container if needed and
slightly reduces the size for every Outliner stored in files.

Slightly changed how we set the `SO_TREESTORE_REBUILD` for this, but it should
effectively behave the same way as before.
This commit is contained in:
Julian Eisel 2020-12-04 19:43:33 +01:00
parent f5eaf67e34
commit 3daf28388b
Notes: blender-bot 2023-02-14 11:00:17 +01:00
Referenced by issue #83420, Closing Preferences Panel crashes Blender
7 changed files with 32 additions and 38 deletions

View File

@ -1561,7 +1561,6 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
/* we only saved what was used */
space_outliner->storeflag |= SO_TREESTORE_CLEANUP; /* at first draw */
}
space_outliner->treehash = NULL;
space_outliner->tree.first = space_outliner->tree.last = NULL;
space_outliner->runtime = NULL;
}
@ -1825,10 +1824,8 @@ void BKE_screen_area_blend_read_lib(BlendLibReader *reader, ID *parent_id, ScrAr
while ((tselem = BLI_mempool_iterstep(&iter))) {
BLO_read_id_address(reader, NULL, &tselem->id);
}
if (space_outliner->treehash) {
/* rebuild hash table, because it depends on ids too */
space_outliner->storeflag |= SO_TREESTORE_REBUILD;
}
/* rebuild hash table, because it depends on ids too */
space_outliner->storeflag |= SO_TREESTORE_REBUILD;
}
break;
}

View File

@ -2834,10 +2834,8 @@ static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map,
tselem->id = NULL;
}
}
if (space_outliner->treehash) {
/* rebuild hash table, because it depends on ids too */
space_outliner->storeflag |= SO_TREESTORE_REBUILD;
}
/* rebuild hash table, because it depends on ids too */
space_outliner->storeflag |= SO_TREESTORE_REBUILD;
}
}
else if (sl->spacetype == SPACE_NODE) {

View File

@ -47,10 +47,13 @@ struct wmKeyConfig;
struct wmOperatorType;
typedef struct SpaceOutliner_Runtime {
/**
* Internal C++ object to create and manage the tree for a specific display type (View Layers,
* Scenes, Blender File, etc.). */
/** Internal C++ object to create and manage the tree for a specific display type (View Layers,
* Scenes, Blender File, etc.). */
struct TreeDisplay *tree_display;
/** Pointers to treestore elements, grouped by (id, type, nr)
* in hashtable for faster searching */
struct GHash *treehash;
} SpaceOutliner_Runtime;
typedef enum TreeElementInsertType {

View File

@ -132,9 +132,9 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner)
if (BLI_mempool_len(ts) == unused) {
BLI_mempool_destroy(ts);
space_outliner->treestore = NULL;
if (space_outliner->treehash) {
BKE_outliner_treehash_free(space_outliner->treehash);
space_outliner->treehash = NULL;
if (space_outliner->runtime->treehash) {
BKE_outliner_treehash_free(space_outliner->runtime->treehash);
space_outliner->runtime->treehash = NULL;
}
}
else {
@ -150,16 +150,16 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner)
}
BLI_mempool_destroy(ts);
space_outliner->treestore = new_ts;
if (space_outliner->treehash) {
if (space_outliner->runtime->treehash) {
/* update hash table to fix broken pointers */
BKE_outliner_treehash_rebuild_from_treestore(space_outliner->treehash,
BKE_outliner_treehash_rebuild_from_treestore(space_outliner->runtime->treehash,
space_outliner->treestore);
}
}
}
}
else if (space_outliner->treehash) {
BKE_outliner_treehash_clear_used(space_outliner->treehash);
else if (space_outliner->runtime->treehash) {
BKE_outliner_treehash_clear_used(space_outliner->runtime->treehash);
}
}
}
@ -174,14 +174,14 @@ static void check_persistent(
space_outliner->treestore = BLI_mempool_create(
sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
}
if (space_outliner->treehash == NULL) {
space_outliner->treehash = BKE_outliner_treehash_create_from_treestore(
if (space_outliner->runtime->treehash == NULL) {
space_outliner->runtime->treehash = BKE_outliner_treehash_create_from_treestore(
space_outliner->treestore);
}
/* find any unused tree element in treestore and mark it as used
* (note that there may be multiple unused elements in case of linked objects) */
tselem = BKE_outliner_treehash_lookup_unused(space_outliner->treehash, type, nr, id);
tselem = BKE_outliner_treehash_lookup_unused(space_outliner->runtime->treehash, type, nr, id);
if (tselem) {
te->store_elem = tselem;
tselem->used = 1;
@ -196,7 +196,7 @@ static void check_persistent(
tselem->used = 0;
tselem->flag = TSE_CLOSED;
te->store_elem = tselem;
BKE_outliner_treehash_add_element(space_outliner->treehash, tselem);
BKE_outliner_treehash_add_element(space_outliner->runtime->treehash, tselem);
}
/* ********************************************************* */
@ -2197,12 +2197,12 @@ void outliner_build_tree(Main *mainvar,
space_outliner->search_flags &= ~SO_SEARCH_RECURSIVE;
}
if (space_outliner->treehash && (space_outliner->storeflag & SO_TREESTORE_REBUILD) &&
if (space_outliner->runtime->treehash && (space_outliner->storeflag & SO_TREESTORE_REBUILD) &&
space_outliner->treestore) {
space_outliner->storeflag &= ~SO_TREESTORE_REBUILD;
BKE_outliner_treehash_rebuild_from_treestore(space_outliner->treehash,
BKE_outliner_treehash_rebuild_from_treestore(space_outliner->runtime->treehash,
space_outliner->treestore);
}
space_outliner->storeflag &= ~SO_TREESTORE_REBUILD;
if (region->do_draw & RGN_DRAW_NO_REBUILD) {
return;

View File

@ -212,7 +212,8 @@ TreeElement *outliner_find_tse(SpaceOutliner *space_outliner, const TreeStoreEle
}
/* check if 'tse' is in treestore */
tselem = BKE_outliner_treehash_lookup_any(space_outliner->treehash, tse->type, tse->nr, tse->id);
tselem = BKE_outliner_treehash_lookup_any(
space_outliner->runtime->treehash, tse->type, tse->nr, tse->id);
if (tselem) {
return outliner_find_tree_element(&space_outliner->tree, tselem);
}

View File

@ -349,12 +349,12 @@ static void outliner_free(SpaceLink *sl)
if (space_outliner->treestore) {
BLI_mempool_destroy(space_outliner->treestore);
}
if (space_outliner->treehash) {
BKE_outliner_treehash_free(space_outliner->treehash);
}
if (space_outliner->runtime) {
outliner_tree_display_destroy(&space_outliner->runtime->tree_display);
if (space_outliner->runtime->treehash) {
BKE_outliner_treehash_free(space_outliner->runtime->treehash);
}
MEM_freeN(space_outliner->runtime);
}
}
@ -377,13 +377,13 @@ static SpaceLink *outliner_duplicate(SpaceLink *sl)
BLI_listbase_clear(&space_outliner_new->tree);
space_outliner_new->treestore = NULL;
space_outliner_new->treehash = NULL;
space_outliner_new->sync_select_dirty = WM_OUTLINER_SYNC_SELECT_FROM_ALL;
if (space_outliner->runtime) {
space_outliner_new->runtime = MEM_dupallocN(space_outliner->runtime);
space_outliner_new->runtime->tree_display = NULL;
space_outliner_new->runtime->treehash = NULL;
}
return (SpaceLink *)space_outliner_new;
@ -414,7 +414,7 @@ static void outliner_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_i
changed = true;
}
}
if (space_outliner->treehash && changed) {
if (space_outliner->runtime->treehash && changed) {
/* rebuild hash table, because it depends on ids too */
/* postpone a full rebuild because this can be called many times on-free */
space_outliner->storeflag |= SO_TREESTORE_REBUILD;

View File

@ -1,4 +1,4 @@
/*
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@ -279,11 +279,6 @@ typedef struct SpaceOutliner {
char show_restrict_flags;
short filter_id_type;
/**
* Pointers to treestore elements, grouped by (id, type, nr)
* in hashtable for faster searching */
void *treehash;
SpaceOutliner_Runtime *runtime;
} SpaceOutliner;