From bdfb1f6a043f2ddf735896a046ac0c0b714952dd Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 5 Feb 2024 18:15:45 +0100 Subject: [PATCH] Assets: Use inheritance for asset library class Initial changes to make the asset library class polymorphic, plus using that to cleanup some basic loading logic. I'm confident that this will help us improve the asset library management code quite a bit, currently it's quite confusing. Plus it will be extendable this way in future, so new kinds of asset libraries (e.g. Blender project asset libraries or arbitrary online asset libraries) can be added much easier. --- .../blender/asset_system/AS_asset_library.hh | 11 ++--- source/blender/asset_system/CMakeLists.txt | 6 +++ .../asset_system/intern/asset_library.cc | 7 +-- .../asset_system/intern/asset_library_all.cc | 40 +++++++++++++++ .../asset_system/intern/asset_library_all.hh | 24 +++++++++ .../intern/asset_library_on_disk.cc | 26 ++++++++++ .../intern/asset_library_on_disk.hh | 24 +++++++++ .../intern/asset_library_runtime.cc | 18 +++++++ .../intern/asset_library_runtime.hh | 23 +++++++++ .../intern/asset_library_service.cc | 49 +++++-------------- .../intern/asset_library_service.hh | 10 ++-- 11 files changed, 187 insertions(+), 51 deletions(-) create mode 100644 source/blender/asset_system/intern/asset_library_all.cc create mode 100644 source/blender/asset_system/intern/asset_library_all.hh create mode 100644 source/blender/asset_system/intern/asset_library_on_disk.cc create mode 100644 source/blender/asset_system/intern/asset_library_on_disk.hh create mode 100644 source/blender/asset_system/intern/asset_library_runtime.cc create mode 100644 source/blender/asset_system/intern/asset_library_runtime.hh diff --git a/source/blender/asset_system/AS_asset_library.hh b/source/blender/asset_system/AS_asset_library.hh index 513fe29d94b..1f06f3853bd 100644 --- a/source/blender/asset_system/AS_asset_library.hh +++ b/source/blender/asset_system/AS_asset_library.hh @@ -65,8 +65,6 @@ class AssetLibrary { */ std::unique_ptr asset_storage_; - std::function on_refresh_; - std::optional import_method_; /** Assets owned by this library may be imported with a different method than set in * #import_method_ above, it's just a default. */ @@ -95,7 +93,7 @@ class AssetLibrary { * \param root_path: If this is an asset library on disk, the top-level directory path. */ AssetLibrary(eAssetLibraryType library_type, StringRef name = "", StringRef root_path = ""); - ~AssetLibrary(); + virtual ~AssetLibrary(); /** * Execute \a fn for every asset library that is loaded. The asset library is passed to the @@ -109,9 +107,6 @@ class AssetLibrary { void load_catalogs(); - /** Load catalogs that have changed on disk. */ - void refresh(); - /** * Create a representation of an asset to be considered part of this library. Once the * representation is not needed anymore, it must be freed using #remove_asset(), or there will be @@ -171,6 +166,10 @@ class AssetLibrary { eAssetLibraryType library_type() const; StringRefNull name() const; StringRefNull root_path() const; + + protected: + /** Load catalogs that have changed on disk. */ + virtual void refresh_catalogs(); }; Vector all_valid_asset_library_refs(); diff --git a/source/blender/asset_system/CMakeLists.txt b/source/blender/asset_system/CMakeLists.txt index d580493c6ed..b6451319aab 100644 --- a/source/blender/asset_system/CMakeLists.txt +++ b/source/blender/asset_system/CMakeLists.txt @@ -18,6 +18,9 @@ set(SRC intern/asset_essentials_library.cc intern/asset_identifier.cc intern/asset_library.cc + intern/asset_library_all.cc + intern/asset_library_on_disk.cc + intern/asset_library_runtime.cc intern/asset_library_service.cc intern/asset_representation.cc intern/asset_storage.cc @@ -30,6 +33,9 @@ set(SRC AS_asset_library.hh AS_asset_representation.hh AS_essentials_library.hh + intern/asset_library_all.hh + intern/asset_library_on_disk.hh + intern/asset_library_runtime.hh intern/asset_library_service.hh intern/asset_storage.hh intern/utils.hh diff --git a/source/blender/asset_system/intern/asset_library.cc b/source/blender/asset_system/intern/asset_library.cc index 5eb1cbee74e..f48c72562f7 100644 --- a/source/blender/asset_system/intern/asset_library.cc +++ b/source/blender/asset_system/intern/asset_library.cc @@ -216,12 +216,7 @@ void AssetLibrary::load_catalogs() this->catalog_service = std::move(catalog_service); } -void AssetLibrary::refresh() -{ - if (on_refresh_) { - on_refresh_(*this); - } -} +void AssetLibrary::refresh_catalogs() {} AssetRepresentation &AssetLibrary::add_external_asset(StringRef relative_asset_path, StringRef name, diff --git a/source/blender/asset_system/intern/asset_library_all.cc b/source/blender/asset_system/intern/asset_library_all.cc new file mode 100644 index 00000000000..42f5f350b98 --- /dev/null +++ b/source/blender/asset_system/intern/asset_library_all.cc @@ -0,0 +1,40 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + */ + +#include + +#include "AS_asset_catalog_tree.hh" + +#include "asset_library_all.hh" + +namespace blender::asset_system { + +AllAssetLibrary::AllAssetLibrary() : AssetLibrary(ASSET_LIBRARY_ALL) {} + +void AllAssetLibrary::rebuild(const bool reload_catalogs) +{ + /* Start with empty catalog storage. */ + catalog_service = std::make_unique(AssetCatalogService::read_only_tag()); + + AssetLibrary::foreach_loaded( + [&](AssetLibrary &nested) { + if (reload_catalogs) { + nested.catalog_service->reload_catalogs(); + } + catalog_service->add_from_existing(*nested.catalog_service); + }, + false); + catalog_service->rebuild_tree(); +} + +void AllAssetLibrary::refresh_catalogs() +{ + rebuild(/*reload_catalogs=*/true); +} + +} // namespace blender::asset_system diff --git a/source/blender/asset_system/intern/asset_library_all.hh b/source/blender/asset_system/intern/asset_library_all.hh new file mode 100644 index 00000000000..6e28dcfd013 --- /dev/null +++ b/source/blender/asset_system/intern/asset_library_all.hh @@ -0,0 +1,24 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + */ + +#pragma once + +#include "AS_asset_library.hh" + +namespace blender::asset_system { + +class AllAssetLibrary : public AssetLibrary { + public: + AllAssetLibrary(); + + void refresh_catalogs() override; + + void rebuild(const bool reload_catalogs); +}; + +} // namespace blender::asset_system diff --git a/source/blender/asset_system/intern/asset_library_on_disk.cc b/source/blender/asset_system/intern/asset_library_on_disk.cc new file mode 100644 index 00000000000..7028a517de9 --- /dev/null +++ b/source/blender/asset_system/intern/asset_library_on_disk.cc @@ -0,0 +1,26 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + */ + +#include "asset_library_on_disk.hh" + +namespace blender::asset_system { + +OnDiskAssetLibrary::OnDiskAssetLibrary(eAssetLibraryType library_type, + StringRef name, + StringRef root_path) + : AssetLibrary(library_type, name, root_path) +{ + on_blend_save_handler_register(); +} + +void OnDiskAssetLibrary::refresh_catalogs() +{ + catalog_service->reload_catalogs(); +} + +} // namespace blender::asset_system diff --git a/source/blender/asset_system/intern/asset_library_on_disk.hh b/source/blender/asset_system/intern/asset_library_on_disk.hh new file mode 100644 index 00000000000..8f4cad375d9 --- /dev/null +++ b/source/blender/asset_system/intern/asset_library_on_disk.hh @@ -0,0 +1,24 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + */ + +#pragma once + +#include "AS_asset_library.hh" + +namespace blender::asset_system { + +class OnDiskAssetLibrary : public AssetLibrary { + public: + OnDiskAssetLibrary(eAssetLibraryType library_type, + StringRef name = "", + StringRef root_path = ""); + + void refresh_catalogs() override; +}; + +} // namespace blender::asset_system diff --git a/source/blender/asset_system/intern/asset_library_runtime.cc b/source/blender/asset_system/intern/asset_library_runtime.cc new file mode 100644 index 00000000000..486786e79e7 --- /dev/null +++ b/source/blender/asset_system/intern/asset_library_runtime.cc @@ -0,0 +1,18 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + */ + +#include "asset_library_runtime.hh" + +namespace blender::asset_system { + +RuntimeAssetLibrary::RuntimeAssetLibrary() : AssetLibrary(ASSET_LIBRARY_LOCAL) +{ + on_blend_save_handler_register(); +} + +} // namespace blender::asset_system diff --git a/source/blender/asset_system/intern/asset_library_runtime.hh b/source/blender/asset_system/intern/asset_library_runtime.hh new file mode 100644 index 00000000000..385f4e09b67 --- /dev/null +++ b/source/blender/asset_system/intern/asset_library_runtime.hh @@ -0,0 +1,23 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + * + * An asset library that is purely stored in-memory. Used for the "Current File" asset library + * while the file has not been saved on disk yet. + */ + +#pragma once + +#include "AS_asset_library.hh" + +namespace blender::asset_system { + +class RuntimeAssetLibrary : public AssetLibrary { + public: + RuntimeAssetLibrary(); +}; + +} // namespace blender::asset_system diff --git a/source/blender/asset_system/intern/asset_library_service.cc b/source/blender/asset_system/intern/asset_library_service.cc index fdeaf294cfe..b7def6dec97 100644 --- a/source/blender/asset_system/intern/asset_library_service.cc +++ b/source/blender/asset_system/intern/asset_library_service.cc @@ -17,9 +17,11 @@ #include "CLG_log.h" -#include "AS_asset_catalog_tree.hh" #include "AS_asset_library.hh" #include "AS_essentials_library.hh" +#include "asset_library_all.hh" +#include "asset_library_on_disk.hh" +#include "asset_library_runtime.hh" #include "asset_library_service.hh" #include "utils.hh" @@ -121,23 +123,20 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk(eAssetLibraryType l std::string normalized_root_path = utils::normalize_directory_path(root_path); - std::unique_ptr *lib_uptr_ptr = on_disk_libraries_.lookup_ptr( + std::unique_ptr *lib_uptr_ptr = on_disk_libraries_.lookup_ptr( {library_type, normalized_root_path}); if (lib_uptr_ptr != nullptr) { CLOG_INFO(&LOG, 2, "get \"%s\" (cached)", normalized_root_path.c_str()); AssetLibrary *lib = lib_uptr_ptr->get(); - lib->refresh(); + lib->refresh_catalogs(); return lib; } - std::unique_ptr lib_uptr = std::make_unique( + std::unique_ptr lib_uptr = std::make_unique( library_type, name, normalized_root_path); AssetLibrary *lib = lib_uptr.get(); - lib->on_blend_save_handler_register(); lib->load_catalogs(); - /* Reload catalogs on refresh. */ - lib->on_refresh_ = [](AssetLibrary &self) { self.catalog_service->reload_catalogs(); }; on_disk_libraries_.add_new({library_type, normalized_root_path}, std::move(lib_uptr)); CLOG_INFO(&LOG, 2, "get \"%s\" (loaded)", normalized_root_path.c_str()); @@ -166,39 +165,21 @@ AssetLibrary *AssetLibraryService::get_asset_library_current_file() { if (current_file_library_) { CLOG_INFO(&LOG, 2, "get current file lib (cached)"); - current_file_library_->refresh(); + current_file_library_->refresh_catalogs(); } else { CLOG_INFO(&LOG, 2, "get current file lib (loaded)"); - current_file_library_ = std::make_unique(ASSET_LIBRARY_LOCAL); - current_file_library_->on_blend_save_handler_register(); + current_file_library_ = std::make_unique(); } AssetLibrary *lib = current_file_library_.get(); return lib; } -static void rebuild_all_library_ex(AssetLibrary &all_library, const bool reload_catalogs) -{ - /* Start with empty catalog storage. */ - all_library.catalog_service = std::make_unique( - AssetCatalogService::read_only_tag()); - - AssetLibrary::foreach_loaded( - [&](AssetLibrary &nested) { - if (reload_catalogs) { - nested.catalog_service->reload_catalogs(); - } - all_library.catalog_service->add_from_existing(*nested.catalog_service); - }, - false); - all_library.catalog_service->rebuild_tree(); -} - void AssetLibraryService::rebuild_all_library() { if (all_library_) { - rebuild_all_library_ex(*all_library_, false); + all_library_->rebuild(false); } } @@ -217,19 +198,15 @@ AssetLibrary *AssetLibraryService::get_asset_library_all(const Main *bmain) if (all_library_) { CLOG_INFO(&LOG, 2, "get all lib (cached)"); - all_library_->refresh(); + all_library_->refresh_catalogs(); return all_library_.get(); } CLOG_INFO(&LOG, 2, "get all lib (loaded)"); - all_library_ = std::make_unique(ASSET_LIBRARY_ALL); + all_library_ = std::make_unique(); /* Don't reload catalogs on this initial read, they've just been loaded above. */ - rebuild_all_library_ex(*all_library_, /*reload_catlogs=*/false); - - all_library_->on_refresh_ = [](AssetLibrary &all_library) { - rebuild_all_library_ex(all_library, /*reload_catalogs=*/true); - }; + all_library_->rebuild(/*reload_catalogs=*/false); return all_library_.get(); } @@ -247,7 +224,7 @@ bUserAssetLibrary *AssetLibraryService::find_custom_preferences_asset_library_fr AssetLibrary *AssetLibraryService::find_loaded_on_disk_asset_library_from_name( StringRef name) const { - for (const std::unique_ptr &library : on_disk_libraries_.values()) { + for (const std::unique_ptr &library : on_disk_libraries_.values()) { if (library->name_ == name) { return library.get(); } diff --git a/source/blender/asset_system/intern/asset_library_service.hh b/source/blender/asset_system/intern/asset_library_service.hh index 8b27f532cea..9644549a731 100644 --- a/source/blender/asset_system/intern/asset_library_service.hh +++ b/source/blender/asset_system/intern/asset_library_service.hh @@ -23,6 +23,10 @@ struct bUserAssetLibrary; namespace blender::asset_system { +class AllAssetLibrary; +class OnDiskAssetLibrary; +class RuntimeAssetLibrary; + /** * Global singleton-ish that provides access to individual #AssetLibrary instances. * @@ -44,13 +48,13 @@ class AssetLibraryService { * library may point to the same path as a custom library. */ using OnDiskLibraryIdentifier = std::pair; /* Mapping of a (type, root path) pair to the AssetLibrary instance. */ - Map> on_disk_libraries_; + Map> on_disk_libraries_; /** Library without a known path, i.e. the "Current File" library if the file isn't saved yet. If * the file was saved, a valid path for the library can be determined and #on_disk_libraries_ * above should be used. */ - std::unique_ptr current_file_library_; + std::unique_ptr current_file_library_; /** The "all" asset library, merging all other libraries into one. */ - std::unique_ptr all_library_; + std::unique_ptr all_library_; /* Handlers for managing the life cycle of the AssetLibraryService instance. */ bCallbackFuncStore on_load_callback_store_;