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:
authorSybren A. Stüvel <sybren@blender.org>2021-10-01 16:21:44 +0300
committerSybren A. Stüvel <sybren@blender.org>2021-10-01 16:22:05 +0300
commit56ce51d1f75a5966977847aeafd25a60a9f44260 (patch)
tree343deb17cf7226d7cd220def37e24fee0edad513
parent1c7ce7e0b45b6613b22cee1515187f5a251932e7 (diff)
Asset Catalogs: add catalog filter for the asset browser
Given an "active catalog" (i.e. the one selected in the UI), construct an `AssetCatalogFilter` instance. This filter can determine whether an asset should be shown or not. It returns `true` when The asset's catalog ID is: - the active catalog, - an alias of the active catalog (so different UUID that maps to the same path), - a sub-catalog of the active catalog. Not yet hooked up to the UI.
-rw-r--r--source/blender/blenkernel/BKE_asset_catalog.hh26
-rw-r--r--source/blender/blenkernel/intern/asset_catalog.cc37
-rw-r--r--source/blender/blenkernel/intern/asset_catalog_test.cc56
3 files changed, 119 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh
index 052cf8e9d1e..65082f06f3a 100644
--- a/source/blender/blenkernel/BKE_asset_catalog.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog.hh
@@ -26,6 +26,7 @@
#include "BLI_function_ref.hh"
#include "BLI_map.hh"
+#include "BLI_set.hh"
#include "BLI_string_ref.hh"
#include "BLI_uuid.h"
#include "BLI_vector.hh"
@@ -48,6 +49,7 @@ using CatalogFilePath = std::string;
class AssetCatalog;
class AssetCatalogDefinitionFile;
class AssetCatalogTree;
+class AssetCatalogFilter;
/* Manages the asset catalogs of a single asset library (i.e. of catalogs defined in a single
* directory hierarchy). */
@@ -100,6 +102,14 @@ class AssetCatalogService {
* efficient call as it's just a linear search over the catalogs. */
AssetCatalog *find_catalog_by_path(const AssetCatalogPath &path) const;
+ /**
+ * Create a filter object that can be used to determine whether an asset belongs to the given
+ * catalog, or any of the catalogs in the sub-tree rooted at the given catalog.
+ *
+ * \see #AssetCatalogFilter
+ */
+ AssetCatalogFilter create_catalog_filter(CatalogID active_catalog_id) const;
+
/** Create a catalog with some sensible auto-generated catalog ID.
* The catalog will be saved to the default catalog file.*/
AssetCatalog *create_catalog(const AssetCatalogPath &catalog_path);
@@ -331,4 +341,20 @@ struct AssetCatalogPathCmp {
* Being a set, duplicates are removed. The catalog's simple name is ignored in this. */
using AssetCatalogOrderedSet = std::set<const AssetCatalog *, AssetCatalogPathCmp>;
+/**
+ * Filter that can determine whether an asset should be visible or not, based on its catalog ID.
+ *
+ * \see AssetCatalogService::create_filter()
+ */
+class AssetCatalogFilter {
+ public:
+ bool contains(CatalogID asset_catalog_id) const;
+
+ protected:
+ friend AssetCatalogService;
+ const Set<CatalogID> matching_catalog_ids;
+
+ explicit AssetCatalogFilter(Set<CatalogID> &&matching_catalog_ids);
+};
+
} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc
index 34bd1fd49db..4973de20fb3 100644
--- a/source/blender/blenkernel/intern/asset_catalog.cc
+++ b/source/blender/blenkernel/intern/asset_catalog.cc
@@ -85,6 +85,33 @@ AssetCatalog *AssetCatalogService::find_catalog_by_path(const AssetCatalogPath &
return nullptr;
}
+AssetCatalogFilter AssetCatalogService::create_catalog_filter(
+ const CatalogID active_catalog_id) const
+{
+ Set<CatalogID> matching_catalog_ids;
+ matching_catalog_ids.add(active_catalog_id);
+
+ const AssetCatalog *active_catalog = find_catalog(active_catalog_id);
+ if (!active_catalog) {
+ /* If the UUID is unknown (i.e. not mapped to an actual Catalog), it is impossible to determine
+ * its children. The filter can still work on the given UUID. */
+ return AssetCatalogFilter(std::move(matching_catalog_ids));
+ }
+
+ /* This cannot just iterate over tree items to get all the required data, because tree items only
+ * represent single UUIDs. It could be used to get the main UUIDs of the children, though, and
+ * then only do an exact match on the path (instead of the more complex `is_contained_in()`
+ * call). Without an extra indexed-by-path acceleration structure, this is still going to require
+ * a linear search, though. */
+ for (const auto &catalog_uptr : this->catalogs_.values()) {
+ if (catalog_uptr->path.is_contained_in(active_catalog->path)) {
+ matching_catalog_ids.add(catalog_uptr->catalog_id);
+ }
+ }
+
+ return AssetCatalogFilter(std::move(matching_catalog_ids));
+}
+
void AssetCatalogService::delete_catalog(CatalogID catalog_id)
{
std::unique_ptr<AssetCatalog> *catalog_uptr_ptr = this->catalogs_.lookup_ptr(catalog_id);
@@ -754,4 +781,14 @@ std::string AssetCatalog::sensible_simple_name_for_path(const AssetCatalogPath &
return "..." + name.substr(name.length() - 60);
}
+AssetCatalogFilter::AssetCatalogFilter(Set<CatalogID> &&matching_catalog_ids)
+ : matching_catalog_ids(std::move(matching_catalog_ids))
+{
+}
+
+bool AssetCatalogFilter::contains(const CatalogID asset_catalog_id) const
+{
+ return matching_catalog_ids.contains(asset_catalog_id);
+}
+
} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/asset_catalog_test.cc b/source/blender/blenkernel/intern/asset_catalog_test.cc
index f3e1f7984a4..e8d40771b89 100644
--- a/source/blender/blenkernel/intern/asset_catalog_test.cc
+++ b/source/blender/blenkernel/intern/asset_catalog_test.cc
@@ -906,4 +906,60 @@ TEST_F(AssetCatalogTest, create_missing_catalogs_after_loading)
EXPECT_EQ(1, loaded_service.count_catalogs_with_path("character/Ružena"));
}
+TEST_F(AssetCatalogTest, create_catalog_filter)
+{
+ AssetCatalogService service(asset_library_root_);
+ service.load_from_disk();
+
+ /* Alias for the same catalog as the main one. */
+ AssetCatalog *alias_ruzena = service.create_catalog("character/Ružena/poselib");
+ /* Alias for a sub-catalog. */
+ AssetCatalog *alias_ruzena_hand = service.create_catalog("character/Ružena/poselib/hand");
+
+ AssetCatalogFilter filter = service.create_catalog_filter(UUID_POSES_RUZENA);
+
+ /* Positive test for loaded-from-disk catalogs. */
+ EXPECT_TRUE(filter.contains(UUID_POSES_RUZENA))
+ << "Main catalog should be included in the filter.";
+ EXPECT_TRUE(filter.contains(UUID_POSES_RUZENA_HAND))
+ << "Sub-catalog should be included in the filter.";
+ EXPECT_TRUE(filter.contains(UUID_POSES_RUZENA_FACE))
+ << "Sub-catalog should be included in the filter.";
+
+ /* Positive test for newly-created catalogs. */
+ EXPECT_TRUE(filter.contains(alias_ruzena->catalog_id))
+ << "Alias of main catalog should be included in the filter.";
+ EXPECT_TRUE(filter.contains(alias_ruzena_hand->catalog_id))
+ << "Alias of sub-catalog should be included in the filter.";
+
+ /* Negative test for unrelated catalogs. */
+ EXPECT_FALSE(filter.contains(BLI_uuid_nil())) << "Nil catalog should not be included.";
+ EXPECT_FALSE(filter.contains(UUID_ID_WITHOUT_PATH));
+ EXPECT_FALSE(filter.contains(UUID_POSES_ELLIE));
+ EXPECT_FALSE(filter.contains(UUID_POSES_ELLIE_WHITESPACE));
+ EXPECT_FALSE(filter.contains(UUID_POSES_ELLIE_TRAILING_SLASH));
+ EXPECT_FALSE(filter.contains(UUID_WITHOUT_SIMPLENAME));
+}
+
+TEST_F(AssetCatalogTest, create_catalog_filter_for_unknown_uuid)
+{
+ AssetCatalogService service;
+ const bUUID unknown_uuid = BLI_uuid_generate_random();
+
+ AssetCatalogFilter filter = service.create_catalog_filter(unknown_uuid);
+ EXPECT_TRUE(filter.contains(unknown_uuid));
+
+ EXPECT_FALSE(filter.contains(BLI_uuid_nil())) << "Nil catalog should not be included.";
+ EXPECT_FALSE(filter.contains(UUID_POSES_ELLIE));
+}
+
+TEST_F(AssetCatalogTest, create_catalog_filter_for_unassigned_assets)
+{
+ AssetCatalogService service;
+
+ AssetCatalogFilter filter = service.create_catalog_filter(BLI_uuid_nil());
+ EXPECT_TRUE(filter.contains(BLI_uuid_nil()));
+ EXPECT_FALSE(filter.contains(UUID_POSES_ELLIE));
+}
+
} // namespace blender::bke::tests