Fix #130007: Invalid current file asset catalogs after saving file

Second part to fix #130007, after 50f7666785.

When saving a new file with the current file asset library loaded, the
library wasn't converted properly to an on-disk library. While the
library was loaded again as on-disk library, the previous runtime
version of it wasn't cleared, so catalog definitions could be duplicated
across available libraries.

Make sure the runtime only library is destructed properly, and the UI
refreshed.

There seem to be more issues with converting the runtime current file library to
a on-disk current file library, but these can be addressed after the crashes and
hangs are fixed, see report.

Pull Request: https://projects.blender.org/blender/blender/pulls/133341
This commit is contained in:
Julian Eisel
2025-02-05 18:40:04 +01:00
committed by Julian Eisel
parent 4e873487dc
commit 9a9e2e19a9
5 changed files with 73 additions and 16 deletions

View File

@@ -197,6 +197,7 @@ class AssetLibrary {
Vector<AssetLibraryReference> all_valid_asset_library_refs();
AssetLibraryReference all_library_reference();
AssetLibraryReference current_file_library_reference();
void all_library_reload_catalogs_if_dirty();
} // namespace blender::asset_system

View File

@@ -254,6 +254,10 @@ void asset_library_on_save_post(Main *bmain,
{
AssetLibrary *asset_lib = static_cast<AssetLibrary *>(arg);
asset_lib->on_blend_save_post(bmain, pointers, num_pointers);
if (asset_lib->library_type() == ASSET_LIBRARY_LOCAL) {
AssetLibraryService::destroy_runtime_current_file_library();
}
}
} // namespace
@@ -357,6 +361,14 @@ AssetLibraryReference all_library_reference()
return all_library_ref;
}
AssetLibraryReference current_file_library_reference()
{
AssetLibraryReference library_ref{};
library_ref.custom_library_index = -1;
library_ref.type = ASSET_LIBRARY_LOCAL;
return library_ref;
}
void all_library_reload_catalogs_if_dirty()
{
AssetLibraryService *service = AssetLibraryService::get();

View File

@@ -205,6 +205,12 @@ void AssetLibraryService::reload_all_library_catalogs_if_dirty()
}
}
void AssetLibraryService::destroy_runtime_current_file_library()
{
AssetLibraryService &library_service = *AssetLibraryService::get();
library_service.current_file_library_ = nullptr;
}
AssetLibrary *AssetLibraryService::get_asset_library_all(const Main *bmain)
{
/* (Re-)load all other asset libraries. */

View File

@@ -79,6 +79,11 @@ class AssetLibraryService {
const AssetLibraryReference &library_reference);
static bUserAssetLibrary *find_custom_preferences_asset_library_from_asset_weak_ref(
const AssetWeakReference &asset_reference);
/**
* Call when the .blend file is saved or unloaded to destroy the runtime library. It's not
* represented as a on disk library.
*/
static void destroy_runtime_current_file_library();
AssetLibrary *get_asset_library(const Main *bmain,
const AssetLibraryReference &library_reference);

View File

@@ -19,6 +19,7 @@
#include "AS_asset_representation.hh"
#include "BKE_context.hh"
#include "BKE_main.hh"
#include "BKE_screen.hh"
#include "BLI_map.hh"
@@ -93,7 +94,7 @@ class AssetList : NonCopyable {
void setup();
void fetch(const bContext &C);
void clear(const bContext *C);
void clear(wmWindowManager *wm);
AssetHandle asset_get_by_index(int index) const;
@@ -211,12 +212,12 @@ void AssetList::iterate(AssetListIterFn fn) const
}
}
void AssetList::clear(const bContext *C)
void AssetList::clear(wmWindowManager *wm)
{
/* Based on #ED_fileselect_clear() */
FileList *files = filelist_;
filelist_readjob_stop(files, CTX_wm_manager(C));
filelist_readjob_stop(files, wm);
filelist_freelib(files);
filelist_clear(files);
filelist_tag_force_reset(files);
@@ -283,35 +284,51 @@ void AssetList::remap_id(ID * /*id_old*/, ID * /*id_new*/) const
/** \name Runtime asset list cache
* \{ */
static void clear(const AssetLibraryReference *library_reference, wmWindowManager *wm);
static void on_save_post(Main *main, PointerRNA **pointers, int num_pointers, void *arg);
/**
* A global asset list map, each entry being a list for a specific asset library.
*/
using AssetListMap = Map<AssetLibraryReference, AssetList>;
struct GlobalStorage {
AssetListMap list_map;
bCallbackFuncStore on_save_callback_store{};
GlobalStorage()
{
on_save_callback_store.alloc = false;
on_save_callback_store.func = on_save_post;
BKE_callback_add(&on_save_callback_store, BKE_CB_EVT_SAVE_POST);
}
};
/**
* Wrapper for Construct on First Use idiom, to avoid the Static Initialization Fiasco.
*/
static AssetListMap &global_storage()
static AssetListMap &libraries_map()
{
static AssetListMap global_storage;
return global_storage;
static GlobalStorage global_storage;
return global_storage.list_map;
}
static AssetList *lookup_list(const AssetLibraryReference &library_ref)
{
return global_storage().lookup_ptr(library_ref);
return libraries_map().lookup_ptr(library_ref);
}
void storage_tag_main_data_dirty()
{
for (AssetList &list : global_storage().values()) {
for (AssetList &list : libraries_map().values()) {
list.tag_main_data_dirty();
}
}
void storage_id_remap(ID *id_old, ID *id_new)
{
for (AssetList &list : global_storage().values()) {
for (AssetList &list : libraries_map().values()) {
list.remap_id(id_old, id_new);
}
}
@@ -336,7 +353,7 @@ using is_new_t = bool;
static std::tuple<AssetList &, is_new_t> ensure_list_storage(
const AssetLibraryReference &library_reference, eFileSelectType filesel_type)
{
AssetListMap &storage = global_storage();
AssetListMap &storage = libraries_map();
if (AssetList *list = storage.lookup_ptr(library_reference)) {
return {*list, false};
@@ -361,6 +378,17 @@ void asset_reading_region_listen_fn(const wmRegionListenerParams *params)
}
}
static void on_save_post(Main *main,
PointerRNA ** /*pointers*/,
int /*num_pointers*/,
void * /*arg*/)
{
wmWindowManager *wm = static_cast<wmWindowManager *>(main->wm.first);
const AssetLibraryReference current_file_library =
asset_system::current_file_library_reference();
clear(&current_file_library, wm);
}
/* -------------------------------------------------------------------- */
/** \name C-API
* \{ */
@@ -391,14 +419,13 @@ bool is_loaded(const AssetLibraryReference *library_reference)
return list->is_loaded();
}
void clear(const AssetLibraryReference *library_reference, const bContext *C)
void clear(const AssetLibraryReference *library_reference, wmWindowManager *wm)
{
AssetList *list = lookup_list(*library_reference);
if (list) {
list->clear(C);
list->clear(wm);
}
wmWindowManager *wm = CTX_wm_manager(C);
LISTBASE_FOREACH (const wmWindow *, win, &wm->windows) {
const bScreen *screen = WM_window_get_active_screen(win);
LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) {
@@ -418,14 +445,20 @@ void clear(const AssetLibraryReference *library_reference, const bContext *C)
/* Always clear the all library when clearing a nested one. */
if (library_reference->type != ASSET_LIBRARY_ALL) {
clear_all_library(C);
const AssetLibraryReference all_lib_ref = asset_system::all_library_reference();
clear(&all_lib_ref, wm);
}
}
void clear(const AssetLibraryReference *library_reference, const bContext *C)
{
clear(library_reference, CTX_wm_manager(C));
}
void clear_all_library(const bContext *C)
{
const AssetLibraryReference all_lib_ref = asset_system::all_library_reference();
clear(&all_lib_ref, C);
clear(&all_lib_ref, CTX_wm_manager(C));
}
bool storage_has_list_for_library(const AssetLibraryReference *library_reference)
@@ -489,7 +522,7 @@ int size(const AssetLibraryReference *library_reference)
void storage_exit()
{
global_storage().clear();
libraries_map().clear();
}
/** \} */