[Bf-blender-cvs] [0cf37baad6b] temp-asset-browser-catalogs: Initial tree structure to load catalogs into

Julian Eisel noreply at git.blender.org
Wed Sep 1 19:41:26 CEST 2021


Commit: 0cf37baad6bf3553126f13c6aec885920fefdb7d
Author: Julian Eisel
Date:   Wed Sep 1 19:36:51 2021 +0200
Branches: temp-asset-browser-catalogs
https://developer.blender.org/rB0cf37baad6bf3553126f13c6aec885920fefdb7d

Initial tree structure to load catalogs into

See T90608 and the basic design in T90066.

This tree structure will be needed for adding the UI. It's unclear how
much of the catalog backend will change still. Some design questions
were raised that need further discussion.

===================================================================

M	source/blender/blenkernel/BKE_asset_catalog.hh
M	source/blender/blenkernel/intern/asset_catalog.cc
M	source/blender/blenkernel/intern/asset_library.cc

===================================================================

diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh
index b4eee4cfc38..ca30b92f6cb 100644
--- a/source/blender/blenkernel/BKE_asset_catalog.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog.hh
@@ -25,10 +25,11 @@
 #endif
 
 #include "BLI_filesystem.hh"
+#include "BLI_function_ref.hh"
 #include "BLI_map.hh"
 #include "BLI_set.hh"
 #include "BLI_string_ref.hh"
-#include "BLI_vector_set.hh"
+#include "BLI_vector.hh"
 
 #include <filesystem>
 #include <memory>
@@ -38,10 +39,12 @@ namespace blender::bke {
 
 using CatalogID = std::string;
 using CatalogPath = std::string;
+using CatalogPathComponent = std::string;
 using CatalogFilePath = filesystem::path;
 
 class AssetCatalog;
 class AssetCatalogDefinitionFile;
+class AssetCatalogTree;
 
 /* Manages the asset catalogs of a single asset library (i.e. of catalogs defined in a single
  * directory hierarchy). */
@@ -75,6 +78,7 @@ class AssetCatalogService {
   /* These pointers are owned by this AssetCatalogService. */
   Map<CatalogID, std::unique_ptr<AssetCatalog>> catalogs_;
   std::unique_ptr<AssetCatalogDefinitionFile> catalog_definition_file_;
+  std::unique_ptr<AssetCatalogTree> catalog_tree_;
   CatalogFilePath asset_library_root_;
 
   void load_directory_recursive(const CatalogFilePath &directory_path);
@@ -96,6 +100,50 @@ class AssetCatalogService {
    * TODO(@sybren): this might move to the #AssetLibrary class instead, and just assumed to exist
    * in this class. */
   bool ensure_asset_library_root();
+
+  std::unique_ptr<AssetCatalogTree> read_into_tree();
+  void print_tree();
+};
+
+class AssetCatalogTreeItem {
+  friend class AssetCatalogService;
+
+ public:
+  /* Would be nice to avoid needing a vector of pointers. But child items want to keep a pointer to
+   * the parent, which would get invalidated once the vector grows and reallocates. */
+  using ChildVec = std::vector<std::unique_ptr<AssetCatalogTreeItem>>;
+  using ItemIterFn = FunctionRef<void(const AssetCatalogTreeItem &)>;
+
+  AssetCatalogTreeItem(StringRef name, const AssetCatalogTreeItem *parent = nullptr);
+
+  StringRef get_name() const;
+  int count_parents() const;
+
+  static void foreach_item_recursive(const ChildVec &children_, const ItemIterFn callback);
+
+ protected:
+  ChildVec children_;
+  /** The user visible name of this component. */
+  CatalogPathComponent name_;
+
+  /** Pointer back to the parent item. Used to reconstruct the hierarchy from an item (e.g. to
+   * build a path). */
+  const AssetCatalogTreeItem *parent_ = nullptr;
+};
+
+/**
+ * A representation of the catalog paths as tree structure. Each component of the catalog tree is
+ * represented by a #AssetCatalogTreeItem.
+ * There is no single root tree element, the #AssetCatalogTree instance itself represents the root.
+ */
+class AssetCatalogTree {
+  friend class AssetCatalogService;
+
+ public:
+  void foreach_item(const AssetCatalogTreeItem::ItemIterFn callback) const;
+
+ protected:
+  AssetCatalogTreeItem::ChildVec children_;
 };
 
 /** Keeps track of which catalogs are defined in a certain file on disk.
diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc
index f9574908ed4..3eb0d7b48fb 100644
--- a/source/blender/blenkernel/intern/asset_catalog.cc
+++ b/source/blender/blenkernel/intern/asset_catalog.cc
@@ -139,6 +139,11 @@ void AssetCatalogService::load_from_disk(const CatalogFilePath &file_or_director
       // TODO(@sybren): throw an appropriate exception.
       return;
   }
+
+  /* TODO: Should there be a sanitize step? E.g. to remove catalogs with identical paths? */
+
+  catalog_tree_ = read_into_tree();
+  print_tree();
 }
 
 void AssetCatalogService::load_directory_recursive(const CatalogFilePath &directory_path)
@@ -228,6 +233,90 @@ std::unique_ptr<AssetCatalog> AssetCatalogService::parse_catalog_line(
   return std::make_unique<AssetCatalog>(catalog_id, catalog_path);
 }
 
+std::unique_ptr<AssetCatalogTree> AssetCatalogService::read_into_tree()
+{
+  auto tree = std::make_unique<AssetCatalogTree>();
+
+  /* Go through the catalogs, insert each path component into the tree where needed. */
+  for (auto &catalog : catalogs_.values()) {
+    fs::path catalog_path = catalog->path;
+
+    const AssetCatalogTreeItem *parent = nullptr;
+    AssetCatalogTreeItem::ChildVec *insert_to_vec = &tree->children_;
+
+    BLI_assert_msg(catalog_path.is_relative() && !catalog_path.has_root_path(),
+                   "Malformed catalog path: Path should be a relative path, with no root-name or "
+                   "root-directory as defined by std::filesystem::path.");
+    for (const fs::path &component : catalog_path) {
+      std::string component_name = component.string();
+
+      auto matching_item = std::find_if(
+          insert_to_vec->begin(), insert_to_vec->end(), [&component_name](auto &iter_item) {
+            return component_name.c_str() == iter_item->get_name();
+          });
+      if (matching_item != insert_to_vec->end()) {
+        /* The component already exists in the tree. Walk further into the path. */
+        parent = matching_item->get();
+        insert_to_vec = &(*matching_item)->children_;
+        continue;
+      }
+
+      /* Create a new component and walk further into the path. */
+      AssetCatalogTreeItem &new_item = *insert_to_vec->emplace_back(
+          new AssetCatalogTreeItem(component_name, parent));
+      parent = &new_item;
+      insert_to_vec = &new_item.children_;
+    }
+  }
+
+  return tree;
+}
+
+/* TODO just for testing. */
+void AssetCatalogService::print_tree()
+{
+  std::cout << "==== Printing Catalog Tree: ====" << std::endl;
+  catalog_tree_->foreach_item([](const AssetCatalogTreeItem &item) {
+    for (int i = 0; i < item.count_parents(); i++) {
+      std::cout << "  ";
+    }
+    std::cout << item.get_name() << std::endl;
+  });
+}
+
+AssetCatalogTreeItem::AssetCatalogTreeItem(StringRef name, const AssetCatalogTreeItem *parent)
+    : name_(name), parent_(parent)
+{
+}
+
+StringRef AssetCatalogTreeItem::get_name() const
+{
+  return name_;
+}
+
+int AssetCatalogTreeItem::count_parents() const
+{
+  int i = 0;
+  for (const AssetCatalogTreeItem *parent = parent_; parent; parent = parent->parent_) {
+    i++;
+  }
+  return i;
+}
+
+void AssetCatalogTree::foreach_item(const AssetCatalogTreeItem::ItemIterFn callback) const
+{
+  AssetCatalogTreeItem::foreach_item_recursive(children_, callback);
+}
+
+void AssetCatalogTreeItem::foreach_item_recursive(const AssetCatalogTreeItem::ChildVec &children,
+                                                  const ItemIterFn callback)
+{
+  for (const std::unique_ptr<AssetCatalogTreeItem> &item : children) {
+    callback(*item);
+    foreach_item_recursive(item->children_, callback);
+  }
+}
+
 AssetCatalogDefinitionFile *AssetCatalogService::get_catalog_definition_file()
 {
   return catalog_definition_file_.get();
diff --git a/source/blender/blenkernel/intern/asset_library.cc b/source/blender/blenkernel/intern/asset_library.cc
index bb5ffa7c6bd..8923c9766bd 100644
--- a/source/blender/blenkernel/intern/asset_library.cc
+++ b/source/blender/blenkernel/intern/asset_library.cc
@@ -24,6 +24,10 @@
 
 #include <memory>
 
+/**
+ * Loading an asset library at this point only means loading the catalogs. Later on this should
+ * invoke reading of asset representations too.
+ */
 struct AssetLibrary *BKE_asset_library_load(const char *library_path)
 {
   blender::bke::AssetLibrary *lib = new blender::bke::AssetLibrary();



More information about the Bf-blender-cvs mailing list