Assets: add global `bke::AssetLibraryService` class
Add `blender::bke::AssetLibraryService` class that acts like a blendfile-scoped singleton. It's allocated upon the first call to `BKE_asset_library_load` and destroyed in the LOAD-PRE handler. The `AssetLibraryService` ensures that edits to asset catalogs are not lost when the asset browser editor closes (or even reloads). Instead, the `AssetLibrary` pointers it owns are kept around as long as the blend file is open. Reviewed By: Severin Maniphest Tasks: T92151 Differential Revision: https://developer.blender.org/D12885
This commit is contained in:
parent
1f51037676
commit
f9113c4be8
|
@ -29,9 +29,14 @@ extern "C" {
|
||||||
/** Forward declaration, defined in intern/asset_library.hh */
|
/** Forward declaration, defined in intern/asset_library.hh */
|
||||||
typedef struct AssetLibrary AssetLibrary;
|
typedef struct AssetLibrary AssetLibrary;
|
||||||
|
|
||||||
/** TODO(@sybren): properly have a think/discussion about the API for this. */
|
/**
|
||||||
|
* Return the #AssetLibrary rooted at the given directory path.
|
||||||
|
*
|
||||||
|
* Will return the same pointer for repeated calls, until another blend file is loaded.
|
||||||
|
*
|
||||||
|
* To get the in-memory-only "current file" asset library, pass an empty path.
|
||||||
|
*/
|
||||||
struct AssetLibrary *BKE_asset_library_load(const char *library_path);
|
struct AssetLibrary *BKE_asset_library_load(const char *library_path);
|
||||||
void BKE_asset_library_free(struct AssetLibrary *asset_library);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to find an appropriate location for an asset library root from a file or directory path.
|
* Try to find an appropriate location for an asset library root from a file or directory path.
|
||||||
|
|
|
@ -33,9 +33,15 @@
|
||||||
|
|
||||||
namespace blender::bke {
|
namespace blender::bke {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AssetLibrary provides access to an asset library's data.
|
||||||
|
* For now this is only for catalogs, later this can be expanded to indexes/caches/more.
|
||||||
|
*/
|
||||||
struct AssetLibrary {
|
struct AssetLibrary {
|
||||||
std::unique_ptr<AssetCatalogService> catalog_service;
|
std::unique_ptr<AssetCatalogService> catalog_service;
|
||||||
|
|
||||||
|
~AssetLibrary();
|
||||||
|
|
||||||
void load(StringRefNull library_root_directory);
|
void load(StringRefNull library_root_directory);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,7 +58,7 @@ struct AssetLibrary {
|
||||||
void on_save_post(struct Main *, struct PointerRNA **pointers, const int num_pointers);
|
void on_save_post(struct Main *, struct PointerRNA **pointers, const int num_pointers);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bCallbackFuncStore on_save_callback_store_;
|
bCallbackFuncStore on_save_callback_store_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::bke
|
} // namespace blender::bke
|
||||||
|
|
|
@ -90,6 +90,7 @@ set(SRC
|
||||||
intern/asset_catalog.cc
|
intern/asset_catalog.cc
|
||||||
intern/asset_catalog_path.cc
|
intern/asset_catalog_path.cc
|
||||||
intern/asset_library.cc
|
intern/asset_library.cc
|
||||||
|
intern/asset_library_service.cc
|
||||||
intern/attribute.c
|
intern/attribute.c
|
||||||
intern/attribute_access.cc
|
intern/attribute_access.cc
|
||||||
intern/attribute_math.cc
|
intern/attribute_math.cc
|
||||||
|
@ -472,6 +473,7 @@ set(SRC
|
||||||
intern/CCGSubSurf_inline.h
|
intern/CCGSubSurf_inline.h
|
||||||
intern/CCGSubSurf_intern.h
|
intern/CCGSubSurf_intern.h
|
||||||
intern/attribute_access_intern.hh
|
intern/attribute_access_intern.hh
|
||||||
|
intern/asset_library_service.hh
|
||||||
intern/data_transfer_intern.h
|
intern/data_transfer_intern.h
|
||||||
intern/lib_intern.h
|
intern/lib_intern.h
|
||||||
intern/multires_inline.h
|
intern/multires_inline.h
|
||||||
|
@ -801,6 +803,7 @@ if(WITH_GTESTS)
|
||||||
intern/armature_test.cc
|
intern/armature_test.cc
|
||||||
intern/asset_catalog_test.cc
|
intern/asset_catalog_test.cc
|
||||||
intern/asset_catalog_path_test.cc
|
intern/asset_catalog_path_test.cc
|
||||||
|
intern/asset_library_service_test.cc
|
||||||
intern/asset_library_test.cc
|
intern/asset_library_test.cc
|
||||||
intern/asset_test.cc
|
intern/asset_test.cc
|
||||||
intern/cryptomatte_test.cc
|
intern/cryptomatte_test.cc
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "asset_library_service.hh"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,19 +41,17 @@
|
||||||
*/
|
*/
|
||||||
struct AssetLibrary *BKE_asset_library_load(const char *library_path)
|
struct AssetLibrary *BKE_asset_library_load(const char *library_path)
|
||||||
{
|
{
|
||||||
blender::bke::AssetLibrary *lib = new blender::bke::AssetLibrary();
|
blender::bke::AssetLibraryService *service = blender::bke::AssetLibraryService::get();
|
||||||
lib->on_save_handler_register();
|
blender::bke::AssetLibrary *lib;
|
||||||
lib->load(library_path);
|
if (library_path == nullptr || library_path[0] == '\0') {
|
||||||
|
lib = service->get_asset_library_current_file();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lib = service->get_asset_library_on_disk(library_path);
|
||||||
|
}
|
||||||
return reinterpret_cast<struct AssetLibrary *>(lib);
|
return reinterpret_cast<struct AssetLibrary *>(lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_asset_library_free(struct AssetLibrary *asset_library)
|
|
||||||
{
|
|
||||||
blender::bke::AssetLibrary *lib = reinterpret_cast<blender::bke::AssetLibrary *>(asset_library);
|
|
||||||
lib->on_save_handler_unregister();
|
|
||||||
delete lib;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BKE_asset_library_find_suitable_root_path_from_path(const char *input_path,
|
bool BKE_asset_library_find_suitable_root_path_from_path(const char *input_path,
|
||||||
char *r_library_path)
|
char *r_library_path)
|
||||||
{
|
{
|
||||||
|
@ -102,6 +102,13 @@ void BKE_asset_library_refresh_catalog_simplename(struct AssetLibrary *asset_lib
|
||||||
|
|
||||||
namespace blender::bke {
|
namespace blender::bke {
|
||||||
|
|
||||||
|
AssetLibrary::~AssetLibrary()
|
||||||
|
{
|
||||||
|
if (on_save_callback_store_.func) {
|
||||||
|
on_save_handler_unregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AssetLibrary::load(StringRefNull library_root_directory)
|
void AssetLibrary::load(StringRefNull library_root_directory)
|
||||||
{
|
{
|
||||||
auto catalog_service = std::make_unique<AssetCatalogService>(library_root_directory);
|
auto catalog_service = std::make_unique<AssetCatalogService>(library_root_directory);
|
||||||
|
@ -134,6 +141,8 @@ void AssetLibrary::on_save_handler_register()
|
||||||
void AssetLibrary::on_save_handler_unregister()
|
void AssetLibrary::on_save_handler_unregister()
|
||||||
{
|
{
|
||||||
BKE_callback_remove(&on_save_callback_store_, BKE_CB_EVT_SAVE_POST);
|
BKE_callback_remove(&on_save_callback_store_, BKE_CB_EVT_SAVE_POST);
|
||||||
|
on_save_callback_store_.func = nullptr;
|
||||||
|
on_save_callback_store_.arg = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetLibrary::on_save_post(struct Main *main,
|
void AssetLibrary::on_save_post(struct Main *main,
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup bke
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asset_library_service.hh"
|
||||||
|
|
||||||
|
#include "BKE_asset_library.hh"
|
||||||
|
#include "BKE_blender.h"
|
||||||
|
#include "BKE_callbacks.h"
|
||||||
|
|
||||||
|
#include "BLI_string_ref.hh"
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "CLG_log.h"
|
||||||
|
|
||||||
|
static CLG_LogRef LOG = {"bke.asset_service"};
|
||||||
|
|
||||||
|
namespace blender::bke {
|
||||||
|
|
||||||
|
std::unique_ptr<AssetLibraryService> AssetLibraryService::instance_;
|
||||||
|
bool AssetLibraryService::atexit_handler_registered_ = false;
|
||||||
|
|
||||||
|
AssetLibraryService *AssetLibraryService::get()
|
||||||
|
{
|
||||||
|
if (!instance_) {
|
||||||
|
allocate_service_instance();
|
||||||
|
}
|
||||||
|
return instance_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetLibraryService::destroy()
|
||||||
|
{
|
||||||
|
if (!instance_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
instance_->app_handler_unregister();
|
||||||
|
instance_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetLibrary *AssetLibraryService::get_asset_library_on_disk(StringRefNull top_level_directory)
|
||||||
|
{
|
||||||
|
BLI_assert_msg(!top_level_directory.is_empty(),
|
||||||
|
"top level directory must be given for on-disk asset library");
|
||||||
|
|
||||||
|
AssetLibraryPtr *lib_uptr_ptr = on_disk_libraries_.lookup_ptr(top_level_directory);
|
||||||
|
if (lib_uptr_ptr != nullptr) {
|
||||||
|
CLOG_INFO(&LOG, 2, "get \"%s\" (cached)", top_level_directory.c_str());
|
||||||
|
return lib_uptr_ptr->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetLibraryPtr lib_uptr = std::make_unique<AssetLibrary>();
|
||||||
|
AssetLibrary *lib = lib_uptr.get();
|
||||||
|
|
||||||
|
lib->on_save_handler_register();
|
||||||
|
lib->load(top_level_directory);
|
||||||
|
|
||||||
|
on_disk_libraries_.add_new(top_level_directory, std::move(lib_uptr));
|
||||||
|
CLOG_INFO(&LOG, 2, "get \"%s\" (loaded)", top_level_directory.c_str());
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetLibrary *AssetLibraryService::get_asset_library_current_file()
|
||||||
|
{
|
||||||
|
if (current_file_library_) {
|
||||||
|
CLOG_INFO(&LOG, 2, "get current file lib (cached)");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CLOG_INFO(&LOG, 2, "get current file lib (loaded)");
|
||||||
|
current_file_library_ = std::make_unique<AssetLibrary>();
|
||||||
|
current_file_library_->on_save_handler_register();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetLibrary *lib = current_file_library_.get();
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetLibraryService::allocate_service_instance()
|
||||||
|
{
|
||||||
|
instance_ = std::make_unique<AssetLibraryService>();
|
||||||
|
instance_->app_handler_register();
|
||||||
|
|
||||||
|
if (!atexit_handler_registered_) {
|
||||||
|
/* Ensure the instance gets freed before Blender's memory leak detector runs. */
|
||||||
|
BKE_blender_atexit_register([](void * /*user_data*/) { AssetLibraryService::destroy(); },
|
||||||
|
nullptr);
|
||||||
|
atexit_handler_registered_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_blendfile_load(struct Main * /*bMain*/,
|
||||||
|
struct PointerRNA ** /*pointers*/,
|
||||||
|
const int /*num_pointers*/,
|
||||||
|
void * /*arg*/)
|
||||||
|
{
|
||||||
|
AssetLibraryService::destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the AssetLibraryService instance is destroyed before a new blend file is loaded.
|
||||||
|
* This makes memory management simple, and ensures a fresh start for every blend file. */
|
||||||
|
void AssetLibraryService::app_handler_register()
|
||||||
|
{
|
||||||
|
/* The callback system doesn't own `on_load_callback_store_`. */
|
||||||
|
on_load_callback_store_.alloc = false;
|
||||||
|
|
||||||
|
on_load_callback_store_.func = &on_blendfile_load;
|
||||||
|
on_load_callback_store_.arg = this;
|
||||||
|
|
||||||
|
BKE_callback_add(&on_load_callback_store_, BKE_CB_EVT_LOAD_PRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetLibraryService::app_handler_unregister()
|
||||||
|
{
|
||||||
|
BKE_callback_remove(&on_load_callback_store_, BKE_CB_EVT_LOAD_PRE);
|
||||||
|
on_load_callback_store_.func = nullptr;
|
||||||
|
on_load_callback_store_.arg = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::bke
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup bke
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
# error This is a C++-only header file.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "BKE_asset_library.hh"
|
||||||
|
|
||||||
|
#include "BLI_map.hh"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace blender::bke {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global singleton-ish that provides access to individual #AssetLibrary instances.
|
||||||
|
*
|
||||||
|
* Whenever a blend file is loaded, the existing instance of AssetLibraryService is destructed, and
|
||||||
|
* a new one is created -- hence the "singleton-ish". This ensures only information about relevant
|
||||||
|
* asset libraries is loaded.
|
||||||
|
*
|
||||||
|
* \note How Asset libraries are identified may change in the future.
|
||||||
|
* For now they are assumed to be:
|
||||||
|
* - on disk (identified by the absolute directory), or
|
||||||
|
* - the "current file" library (which is in memory but could have catalogs
|
||||||
|
* loaded from a file on disk).
|
||||||
|
*/
|
||||||
|
class AssetLibraryService {
|
||||||
|
public:
|
||||||
|
using AssetLibraryPtr = std::unique_ptr<AssetLibrary>;
|
||||||
|
|
||||||
|
AssetLibraryService() = default;
|
||||||
|
~AssetLibraryService() = default;
|
||||||
|
|
||||||
|
/** Return the AssetLibraryService singleton, allocating it if necessary. */
|
||||||
|
static AssetLibraryService *get();
|
||||||
|
|
||||||
|
/** Destroy the AssetLibraryService singleton. It will be reallocated by #get() if necessary. */
|
||||||
|
static void destroy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the given asset library. Opens it (i.e. creates a new AssetLibrary instance) if necessary.
|
||||||
|
*/
|
||||||
|
AssetLibrary *get_asset_library_on_disk(StringRefNull top_level_directory);
|
||||||
|
|
||||||
|
/** Get the "Current File" asset library. */
|
||||||
|
AssetLibrary *get_asset_library_current_file();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static std::unique_ptr<AssetLibraryService> instance_;
|
||||||
|
|
||||||
|
/* Mapping absolute path of the library's top-level directory to the AssetLibrary instance. */
|
||||||
|
Map<std::string, AssetLibraryPtr> on_disk_libraries_;
|
||||||
|
AssetLibraryPtr current_file_library_;
|
||||||
|
|
||||||
|
/* Handlers for managing the life cycle of the AssetLibraryService instance. */
|
||||||
|
bCallbackFuncStore on_load_callback_store_;
|
||||||
|
static bool atexit_handler_registered_;
|
||||||
|
|
||||||
|
/** Allocate a new instance of the service and assign it to `instance_`. */
|
||||||
|
static void allocate_service_instance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the AssetLibraryService instance is destroyed before a new blend file is loaded.
|
||||||
|
* This makes memory management simple, and ensures a fresh start for every blend file. */
|
||||||
|
void app_handler_register();
|
||||||
|
void app_handler_unregister();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blender::bke
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2020 Blender Foundation
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asset_library_service.hh"
|
||||||
|
|
||||||
|
#include "CLG_log.h"
|
||||||
|
|
||||||
|
#include "testing/testing.h"
|
||||||
|
|
||||||
|
namespace blender::bke::tests {
|
||||||
|
|
||||||
|
class AssetLibraryServiceTest : public testing::Test {
|
||||||
|
public:
|
||||||
|
CatalogFilePath asset_library_root_;
|
||||||
|
|
||||||
|
static void SetUpTestSuite()
|
||||||
|
{
|
||||||
|
CLG_init();
|
||||||
|
}
|
||||||
|
static void TearDownTestSuite()
|
||||||
|
{
|
||||||
|
CLG_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp() override
|
||||||
|
{
|
||||||
|
const std::string test_files_dir = blender::tests::flags_test_asset_dir();
|
||||||
|
if (test_files_dir.empty()) {
|
||||||
|
FAIL();
|
||||||
|
}
|
||||||
|
asset_library_root_ = test_files_dir + "/" + "asset_library";
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override
|
||||||
|
{
|
||||||
|
AssetLibraryService::destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(AssetLibraryServiceTest, get_destroy)
|
||||||
|
{
|
||||||
|
AssetLibraryService *const service = AssetLibraryService::get();
|
||||||
|
EXPECT_EQ(service, AssetLibraryService::get())
|
||||||
|
<< "Calling twice without destroying in between should return the same instance.";
|
||||||
|
|
||||||
|
AssetLibraryService::destroy();
|
||||||
|
EXPECT_NE(service, AssetLibraryService::get())
|
||||||
|
<< "Calling twice with destroying in between should return a new instance.";
|
||||||
|
|
||||||
|
/* This should not crash. */
|
||||||
|
AssetLibraryService::destroy();
|
||||||
|
AssetLibraryService::destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(AssetLibraryServiceTest, library_pointers)
|
||||||
|
{
|
||||||
|
AssetLibraryService *service = AssetLibraryService::get();
|
||||||
|
AssetLibrary *const lib = service->get_asset_library_on_disk(asset_library_root_);
|
||||||
|
AssetLibrary *const curfile_lib = service->get_asset_library_current_file();
|
||||||
|
|
||||||
|
EXPECT_EQ(lib, service->get_asset_library_on_disk(asset_library_root_))
|
||||||
|
<< "Calling twice without destroying in between should return the same instance.";
|
||||||
|
EXPECT_EQ(curfile_lib, service->get_asset_library_current_file())
|
||||||
|
<< "Calling twice without destroying in between should return the same instance.";
|
||||||
|
|
||||||
|
AssetLibraryService::destroy();
|
||||||
|
service = AssetLibraryService::get();
|
||||||
|
EXPECT_NE(lib, service->get_asset_library_on_disk(asset_library_root_))
|
||||||
|
<< "Calling twice with destroying in between should return a new instance.";
|
||||||
|
EXPECT_NE(curfile_lib, service->get_asset_library_current_file())
|
||||||
|
<< "Calling twice with destroying in between should return a new instance.";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(AssetLibraryServiceTest, catalogs_loaded)
|
||||||
|
{
|
||||||
|
AssetLibraryService *const service = AssetLibraryService::get();
|
||||||
|
AssetLibrary *const lib = service->get_asset_library_on_disk(asset_library_root_);
|
||||||
|
AssetCatalogService *const cat_service = lib->catalog_service.get();
|
||||||
|
|
||||||
|
const bUUID UUID_POSES_ELLIE("df60e1f6-2259-475b-93d9-69a1b4a8db78");
|
||||||
|
EXPECT_NE(nullptr, cat_service->find_catalog(UUID_POSES_ELLIE))
|
||||||
|
<< "Catalogs should be loaded after getting an asset library from disk.";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::bke::tests
|
|
@ -21,11 +21,32 @@
|
||||||
#include "BKE_asset_catalog.hh"
|
#include "BKE_asset_catalog.hh"
|
||||||
#include "BKE_asset_library.hh"
|
#include "BKE_asset_library.hh"
|
||||||
|
|
||||||
|
#include "asset_library_service.hh"
|
||||||
|
|
||||||
|
#include "CLG_log.h"
|
||||||
|
|
||||||
#include "testing/testing.h"
|
#include "testing/testing.h"
|
||||||
|
|
||||||
namespace blender::bke::tests {
|
namespace blender::bke::tests {
|
||||||
|
|
||||||
TEST(AssetLibraryTest, load_and_free_c_functions)
|
class AssetLibraryServiceTest : public testing::Test {
|
||||||
|
public:
|
||||||
|
static void SetUpTestSuite()
|
||||||
|
{
|
||||||
|
CLG_init();
|
||||||
|
}
|
||||||
|
static void TearDownTestSuite()
|
||||||
|
{
|
||||||
|
CLG_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override
|
||||||
|
{
|
||||||
|
AssetLibraryService::destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(AssetLibraryServiceTest, bke_asset_library_load)
|
||||||
{
|
{
|
||||||
const std::string test_files_dir = blender::tests::flags_test_asset_dir();
|
const std::string test_files_dir = blender::tests::flags_test_asset_dir();
|
||||||
if (test_files_dir.empty()) {
|
if (test_files_dir.empty()) {
|
||||||
|
@ -50,11 +71,9 @@ TEST(AssetLibraryTest, load_and_free_c_functions)
|
||||||
AssetCatalog *poses_ellie = service->find_catalog(uuid_poses_ellie);
|
AssetCatalog *poses_ellie = service->find_catalog(uuid_poses_ellie);
|
||||||
ASSERT_NE(nullptr, poses_ellie) << "unable to find POSES_ELLIE catalog";
|
ASSERT_NE(nullptr, poses_ellie) << "unable to find POSES_ELLIE catalog";
|
||||||
EXPECT_EQ("character/Ellie/poselib", poses_ellie->path.str());
|
EXPECT_EQ("character/Ellie/poselib", poses_ellie->path.str());
|
||||||
|
|
||||||
BKE_asset_library_free(library_c_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AssetLibraryTest, load_nonexistent_directory)
|
TEST_F(AssetLibraryServiceTest, load_nonexistent_directory)
|
||||||
{
|
{
|
||||||
const std::string test_files_dir = blender::tests::flags_test_asset_dir();
|
const std::string test_files_dir = blender::tests::flags_test_asset_dir();
|
||||||
if (test_files_dir.empty()) {
|
if (test_files_dir.empty()) {
|
||||||
|
@ -75,8 +94,6 @@ TEST(AssetLibraryTest, load_nonexistent_directory)
|
||||||
|
|
||||||
/* Check that the catalog service doesn't have any catalogs. */
|
/* Check that the catalog service doesn't have any catalogs. */
|
||||||
EXPECT_TRUE(service->is_empty());
|
EXPECT_TRUE(service->is_empty());
|
||||||
|
|
||||||
BKE_asset_library_free(library_c_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::bke::tests
|
} // namespace blender::bke::tests
|
||||||
|
|
|
@ -391,7 +391,7 @@ typedef struct FileList {
|
||||||
eFileSelectType type;
|
eFileSelectType type;
|
||||||
/* The library this list was created for. Stored here so we know when to re-read. */
|
/* The library this list was created for. Stored here so we know when to re-read. */
|
||||||
AssetLibraryReference *asset_library_ref;
|
AssetLibraryReference *asset_library_ref;
|
||||||
struct AssetLibrary *asset_library;
|
struct AssetLibrary *asset_library; /* Non-owning pointer. */
|
||||||
|
|
||||||
short flags;
|
short flags;
|
||||||
|
|
||||||
|
@ -1847,9 +1847,7 @@ void filelist_clear_ex(struct FileList *filelist,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_asset_library && (filelist->asset_library != NULL)) {
|
if (do_asset_library && (filelist->asset_library != NULL)) {
|
||||||
/* There is no way to refresh the catalogs stored by the AssetLibrary struct, so instead of
|
/* The AssetLibraryService owns the AssetLibrary pointer, so no need for us to free it. */
|
||||||
* "clearing" it, the entire struct is freed. It will be reallocated when needed. */
|
|
||||||
BKE_asset_library_free(filelist->asset_library);
|
|
||||||
filelist->asset_library = NULL;
|
filelist->asset_library = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue