Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_asset_catalog.hh5
-rw-r--r--source/blender/blenkernel/BKE_asset_catalog_path.hh5
-rw-r--r--source/blender/blenkernel/intern/asset_catalog.cc41
-rw-r--r--source/blender/blenkernel/intern/asset_catalog_path.cc12
-rw-r--r--source/blender/blenkernel/intern/asset_catalog_path_test.cc17
-rw-r--r--source/blender/blenkernel/intern/asset_catalog_test.cc43
6 files changed, 122 insertions, 1 deletions
diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh
index 9d179011b25..a0bc1267826 100644
--- a/source/blender/blenkernel/BKE_asset_catalog.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog.hh
@@ -150,6 +150,11 @@ class AssetCatalogService {
std::unique_ptr<AssetCatalogTree> read_into_tree();
void rebuild_tree();
+
+ /**
+ * For every catalog, ensure that its parent path also has a known catalog.
+ */
+ void create_missing_catalogs();
};
/**
diff --git a/source/blender/blenkernel/BKE_asset_catalog_path.hh b/source/blender/blenkernel/BKE_asset_catalog_path.hh
index 1e53df553a9..b150f805ed5 100644
--- a/source/blender/blenkernel/BKE_asset_catalog_path.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog_path.hh
@@ -112,6 +112,11 @@ class AssetCatalogPath {
bool is_contained_in(const AssetCatalogPath &other_path) const;
/**
+ * \return the parent path, or an empty path if there is no parent.
+ */
+ AssetCatalogPath parent() const;
+
+ /**
* Change the initial part of the path from `from_path` to `to_path`.
* If this path does not start with `from_path`, return an empty path as result.
*
diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc
index bb213877e05..a948c0f96ff 100644
--- a/source/blender/blenkernel/intern/asset_catalog.cc
+++ b/source/blender/blenkernel/intern/asset_catalog.cc
@@ -188,7 +188,7 @@ void AssetCatalogService::load_from_disk(const CatalogFilePath &file_or_director
/* TODO: Should there be a sanitize step? E.g. to remove catalogs with identical paths? */
- catalog_tree_ = read_into_tree();
+ rebuild_tree();
}
void AssetCatalogService::load_directory_recursive(const CatalogFilePath &directory_path)
@@ -356,9 +356,48 @@ std::unique_ptr<AssetCatalogTree> AssetCatalogService::read_into_tree()
void AssetCatalogService::rebuild_tree()
{
+ create_missing_catalogs();
this->catalog_tree_ = read_into_tree();
}
+void AssetCatalogService::create_missing_catalogs()
+{
+ /* Construct an ordered set of paths to check, so that parents are ordered before children. */
+ std::set<AssetCatalogPath> paths_to_check;
+ for (auto &catalog : catalogs_.values()) {
+ paths_to_check.insert(catalog->path);
+ }
+
+ std::set<AssetCatalogPath> seen_paths;
+ /* The empty parent should never be created, so always be considered "seen". */
+ seen_paths.insert(AssetCatalogPath(""));
+
+ /* Find and create missing direct parents (so ignoring parents-of-parents). */
+ while (!paths_to_check.empty()) {
+ /* Pop the first path of the queue. */
+ const AssetCatalogPath path = *paths_to_check.begin();
+ paths_to_check.erase(paths_to_check.begin());
+
+ if (seen_paths.find(path) != seen_paths.end()) {
+ /* This path has been seen already, so it can be ignored. */
+ continue;
+ }
+ seen_paths.insert(path);
+
+ const AssetCatalogPath parent_path = path.parent();
+ if (seen_paths.find(parent_path) != seen_paths.end()) {
+ /* The parent exists, continue to the next path. */
+ continue;
+ }
+
+ /* The parent doesn't exist, so create it and queue it up for checking its parent. */
+ create_catalog(parent_path);
+ paths_to_check.insert(parent_path);
+ }
+
+ /* TODO(Sybren): bind the newly created catalogs to a CDF, if we know about it. */
+}
+
/* ---------------------------------------------------------------------- */
AssetCatalogTreeItem::AssetCatalogTreeItem(StringRef name,
diff --git a/source/blender/blenkernel/intern/asset_catalog_path.cc b/source/blender/blenkernel/intern/asset_catalog_path.cc
index d8af7be4a02..cc6aceef8e7 100644
--- a/source/blender/blenkernel/intern/asset_catalog_path.cc
+++ b/source/blender/blenkernel/intern/asset_catalog_path.cc
@@ -172,6 +172,18 @@ bool AssetCatalogPath::is_contained_in(const AssetCatalogPath &other_path) const
return prefix_ok && next_char == SEPARATOR;
}
+AssetCatalogPath AssetCatalogPath::parent() const
+{
+ if (!*this) {
+ return AssetCatalogPath("");
+ }
+ std::string::size_type last_sep_index = this->path_.rfind(SEPARATOR);
+ if (last_sep_index == std::string::npos) {
+ return AssetCatalogPath("");
+ }
+ return AssetCatalogPath(this->path_.substr(0, last_sep_index));
+}
+
void AssetCatalogPath::iterate_components(ComponentIteratorFn callback) const
{
const char *next_slash_ptr;
diff --git a/source/blender/blenkernel/intern/asset_catalog_path_test.cc b/source/blender/blenkernel/intern/asset_catalog_path_test.cc
index 55919abbb8f..af15cbf405a 100644
--- a/source/blender/blenkernel/intern/asset_catalog_path_test.cc
+++ b/source/blender/blenkernel/intern/asset_catalog_path_test.cc
@@ -231,4 +231,21 @@ TEST(AssetCatalogPathTest, rebase)
EXPECT_EQ(empty.rebase("", ""), "");
}
+TEST(AssetCatalogPathTest, parent)
+{
+ const AssetCatalogPath ascii_path("path/with/missing/parents");
+ EXPECT_EQ(ascii_path.parent(), "path/with/missing");
+
+ const AssetCatalogPath path("путь/в/Пермь/долог/и/далек");
+ EXPECT_EQ(path.parent(), "путь/в/Пермь/долог/и");
+ EXPECT_EQ(path.parent().parent(), "путь/в/Пермь/долог");
+ EXPECT_EQ(path.parent().parent().parent(), "путь/в/Пермь");
+
+ const AssetCatalogPath one_level("one");
+ EXPECT_EQ(one_level.parent(), "");
+
+ const AssetCatalogPath empty("");
+ EXPECT_EQ(empty.parent(), "");
+}
+
} // namespace blender::bke::tests
diff --git a/source/blender/blenkernel/intern/asset_catalog_test.cc b/source/blender/blenkernel/intern/asset_catalog_test.cc
index d7c3e50cbdf..836b681c950 100644
--- a/source/blender/blenkernel/intern/asset_catalog_test.cc
+++ b/source/blender/blenkernel/intern/asset_catalog_test.cc
@@ -57,6 +57,11 @@ class TestableAssetCatalogService : public AssetCatalogService {
{
return catalog_definition_file_.get();
}
+
+ void create_missing_catalogs()
+ {
+ AssetCatalogService::create_missing_catalogs();
+ }
};
class AssetCatalogTest : public testing::Test {
@@ -846,4 +851,42 @@ TEST_F(AssetCatalogTest, order_by_path)
}
}
+TEST_F(AssetCatalogTest, create_missing_catalogs)
+{
+ TestableAssetCatalogService new_service;
+ new_service.create_catalog("path/with/missing/parents");
+
+ EXPECT_EQ(nullptr, new_service.find_catalog_by_path("path/with/missing"))
+ << "Missing parents should not be immediately created.";
+ EXPECT_EQ(nullptr, new_service.find_catalog_by_path("")) << "Empty path should never be valid";
+
+ new_service.create_missing_catalogs();
+
+ EXPECT_NE(nullptr, new_service.find_catalog_by_path("path/with/missing"));
+ EXPECT_NE(nullptr, new_service.find_catalog_by_path("path/with"));
+ EXPECT_NE(nullptr, new_service.find_catalog_by_path("path"));
+ EXPECT_EQ(nullptr, new_service.find_catalog_by_path(""))
+ << "Empty path should never be valid, even when after missing catalogs";
+}
+
+TEST_F(AssetCatalogTest, create_missing_catalogs_after_loading)
+{
+ TestableAssetCatalogService loaded_service(asset_library_root_);
+ loaded_service.load_from_disk();
+
+ const AssetCatalog *cat_char = loaded_service.find_catalog_by_path("character");
+ const AssetCatalog *cat_ellie = loaded_service.find_catalog_by_path("character/Ellie");
+ const AssetCatalog *cat_ruzena = loaded_service.find_catalog_by_path("character/Ružena");
+ ASSERT_NE(nullptr, cat_char) << "Missing parents should be created immediately after loading.";
+ ASSERT_NE(nullptr, cat_ellie) << "Missing parents should be created immediately after loading.";
+ ASSERT_NE(nullptr, cat_ruzena) << "Missing parents should be created immediately after loading.";
+
+ AssetCatalogDefinitionFile *cdf = loaded_service.get_catalog_definition_file();
+ ASSERT_NE(nullptr, cdf);
+ EXPECT_TRUE(cdf->contains(cat_char->catalog_id)) << "Missing parents should be saved to a CDF.";
+ EXPECT_TRUE(cdf->contains(cat_ellie->catalog_id)) << "Missing parents should be saved to a CDF.";
+ EXPECT_TRUE(cdf->contains(cat_ruzena->catalog_id))
+ << "Missing parents should be saved to a CDF.";
+}
+
} // namespace blender::bke::tests