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.
This commit is contained in:
Julian Eisel
2024-02-05 18:15:45 +01:00
parent b351638008
commit bdfb1f6a04
11 changed files with 187 additions and 51 deletions

View File

@@ -65,8 +65,6 @@ class AssetLibrary {
*/
std::unique_ptr<AssetStorage> asset_storage_;
std::function<void(AssetLibrary &self)> on_refresh_;
std::optional<eAssetImportMethod> 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<AssetLibraryReference> all_valid_asset_library_refs();

View File

@@ -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

View File

@@ -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,

View File

@@ -0,0 +1,40 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup asset_system
*/
#include <memory>
#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>(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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<AssetLibrary> *lib_uptr_ptr = on_disk_libraries_.lookup_ptr(
std::unique_ptr<OnDiskAssetLibrary> *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<AssetLibrary>(
std::unique_ptr lib_uptr = std::make_unique<OnDiskAssetLibrary>(
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<AssetLibrary>(ASSET_LIBRARY_LOCAL);
current_file_library_->on_blend_save_handler_register();
current_file_library_ = std::make_unique<RuntimeAssetLibrary>();
}
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>(
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<AssetLibrary>(ASSET_LIBRARY_ALL);
all_library_ = std::make_unique<AllAssetLibrary>();
/* 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<AssetLibrary> &library : on_disk_libraries_.values()) {
for (const std::unique_ptr<OnDiskAssetLibrary> &library : on_disk_libraries_.values()) {
if (library->name_ == name) {
return library.get();
}

View File

@@ -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<eAssetLibraryType, std::string>;
/* Mapping of a (type, root path) pair to the AssetLibrary instance. */
Map<OnDiskLibraryIdentifier, std::unique_ptr<AssetLibrary>> on_disk_libraries_;
Map<OnDiskLibraryIdentifier, std::unique_ptr<OnDiskAssetLibrary>> 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<AssetLibrary> current_file_library_;
std::unique_ptr<RuntimeAssetLibrary> current_file_library_;
/** The "all" asset library, merging all other libraries into one. */
std::unique_ptr<AssetLibrary> all_library_;
std::unique_ptr<AllAssetLibrary> all_library_;
/* Handlers for managing the life cycle of the AssetLibraryService instance. */
bCallbackFuncStore on_load_callback_store_;