From 9a9e2e19a9da7bf4edede19cb810cb7e91a01524 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 5 Feb 2025 18:40:04 +0100 Subject: [PATCH] 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 --- .../blender/asset_system/AS_asset_library.hh | 1 + .../asset_system/intern/asset_library.cc | 12 ++++ .../intern/asset_library_service.cc | 6 ++ .../intern/asset_library_service.hh | 5 ++ .../editors/asset/intern/asset_list.cc | 65 ++++++++++++++----- 5 files changed, 73 insertions(+), 16 deletions(-) diff --git a/source/blender/asset_system/AS_asset_library.hh b/source/blender/asset_system/AS_asset_library.hh index 0b1901c0a45..b2e0b66f068 100644 --- a/source/blender/asset_system/AS_asset_library.hh +++ b/source/blender/asset_system/AS_asset_library.hh @@ -197,6 +197,7 @@ class AssetLibrary { Vector 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 diff --git a/source/blender/asset_system/intern/asset_library.cc b/source/blender/asset_system/intern/asset_library.cc index c21b4ac76fb..19c7460c6fc 100644 --- a/source/blender/asset_system/intern/asset_library.cc +++ b/source/blender/asset_system/intern/asset_library.cc @@ -254,6 +254,10 @@ void asset_library_on_save_post(Main *bmain, { AssetLibrary *asset_lib = static_cast(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(); diff --git a/source/blender/asset_system/intern/asset_library_service.cc b/source/blender/asset_system/intern/asset_library_service.cc index b4c879b0240..d4f97a75b03 100644 --- a/source/blender/asset_system/intern/asset_library_service.cc +++ b/source/blender/asset_system/intern/asset_library_service.cc @@ -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. */ diff --git a/source/blender/asset_system/intern/asset_library_service.hh b/source/blender/asset_system/intern/asset_library_service.hh index 74b349dd7ec..04026fcbbb8 100644 --- a/source/blender/asset_system/intern/asset_library_service.hh +++ b/source/blender/asset_system/intern/asset_library_service.hh @@ -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); diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc index 21d56854855..380787ac12c 100644 --- a/source/blender/editors/asset/intern/asset_list.cc +++ b/source/blender/editors/asset/intern/asset_list.cc @@ -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; +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 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(main->wm.first); + const AssetLibraryReference current_file_library = + asset_system::current_file_library_reference(); + clear(¤t_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(); } /** \} */