[Bf-blender-cvs] [ea335357c51] node-add-asset-menu: Proper catalog building

Hans Goudey noreply at git.blender.org
Thu Oct 6 00:39:25 CEST 2022


Commit: ea335357c5129b245fd8fd88eda1a4bfe9cf3a35
Author: Hans Goudey
Date:   Wed Oct 5 17:39:16 2022 -0500
Branches: node-add-asset-menu
https://developer.blender.org/rBea335357c5129b245fd8fd88eda1a4bfe9cf3a35

Proper catalog building

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

M	source/blender/blenkernel/BKE_asset_catalog.hh
M	source/blender/blenkernel/BKE_screen.h
M	source/blender/blenkernel/intern/asset_catalog.cc
M	source/blender/editors/space_node/add_menu_assets.cc

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

diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh
index 2e933ed3094..0ca2b27b5a0 100644
--- a/source/blender/blenkernel/BKE_asset_catalog.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog.hh
@@ -127,6 +127,8 @@ class AssetCatalogService {
   AssetCatalogFilter create_catalog_filter(const AssetCatalogPath &path) const;
   AssetCatalogFilter create_catalog_filter(CatalogID catalog_id) const;
 
+  Set<CatalogID> catalogs_for_path(const AssetCatalogPath &path) 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);
@@ -309,7 +311,7 @@ class AssetCatalogTreeItem {
 
   /** Iterate over children calling \a callback for each of them, but do not recurse into their
    * children. */
-  void foreach_child(const ItemIterFn callback);
+  void foreach_child(ItemIterFn callback);
 
  protected:
   /** Child tree items, ordered by their names. */
@@ -352,6 +354,10 @@ class AssetCatalogTree {
    * children. */
   void foreach_root_item(ItemIterFn callback);
 
+  bool is_empty() const;
+
+  AssetCatalogTreeItem *find_item(const AssetCatalogPath &path);
+
  protected:
   /** Child tree items, ordered by their names. */
   ChildMap root_items_;
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 9d670b98af9..9a7d2bde810 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -393,7 +393,6 @@ typedef struct MenuType {
 typedef struct Menu {
   struct MenuType *type;   /* runtime */
   struct uiLayout *layout; /* runtime for drawing */
-  // PointerRNA custom_data;
 } Menu;
 
 /* Space-types. */
diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc
index 9feb62840d6..c69deac059e 100644
--- a/source/blender/blenkernel/intern/asset_catalog.cc
+++ b/source/blender/blenkernel/intern/asset_catalog.cc
@@ -169,6 +169,17 @@ AssetCatalogFilter AssetCatalogService::create_catalog_filter(const AssetCatalog
   return AssetCatalogFilter(std::move(matching_catalog_ids), std::move(known_catalog_ids));
 }
 
+Set<CatalogID> AssetCatalogService::catalogs_for_path(const AssetCatalogPath &path) const
+{
+  Set<CatalogID> catalog_ids;
+  for (const auto &catalog_uptr : catalog_collection_->catalogs_.values()) {
+    if (catalog_uptr->path == path) {
+      catalog_ids.add(catalog_uptr->catalog_id);
+    }
+  }
+  return catalog_ids;
+}
+
 AssetCatalogFilter AssetCatalogService::create_catalog_filter(const CatalogID catalog_id) const
 {
   const AssetCatalog *catalog = this->find_catalog(catalog_id);
@@ -800,6 +811,26 @@ void AssetCatalogTree::foreach_root_item(const ItemIterFn callback)
   }
 }
 
+bool AssetCatalogTree::is_empty() const
+{
+  return root_items_.empty();
+}
+
+AssetCatalogTreeItem *AssetCatalogTree::find_item(const AssetCatalogPath &path)
+{
+  AssetCatalogTreeItem *result = nullptr;
+  this->foreach_item([&](AssetCatalogTreeItem &item) {
+    if (result) {
+      /* TODO: Add a way to stop iteration. */
+      return;
+    }
+    if (item.catalog_path() == path) {
+      result = &item;
+    }
+  });
+  return result;
+}
+
 /* ---------------------------------------------------------------------- */
 
 /* ---------------------------------------------------------------------- */
diff --git a/source/blender/editors/space_node/add_menu_assets.cc b/source/blender/editors/space_node/add_menu_assets.cc
index 3dbad2a1e45..7540842d644 100644
--- a/source/blender/editors/space_node/add_menu_assets.cc
+++ b/source/blender/editors/space_node/add_menu_assets.cc
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later */
 
+#include "BLI_multi_value_map.hh"
+
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
 
@@ -23,73 +25,86 @@ static bool node_add_menu_poll(const bContext *C, MenuType * /*mt*/)
   return CTX_wm_space_node(C);
 }
 
-struct AssetItem {
-  AssetHandle handle;
+struct LibraryAsset {
   const AssetLibraryReference &library_ref;
+  AssetHandle handle;
+};
+
+struct LibraryCatalog {
+  bke::AssetLibrary *library;
+  const bke::AssetCatalog *catalog;
+};
+
+struct AssetItemTree {
+  bke::AssetCatalogTree catalogs;
+  MultiValueMap<bke::AssetCatalogPath, LibraryAsset> assets_per_path;
 };
 
-static void gather_items_for_asset_library(const bContext &C,
-                                           const bNodeTree &node_tree,
-                                           const AssetLibraryReference &library_ref,
-                                           bke::AssetLibrary &library,
-                                           const bke::AssetCatalogPath &path,
-                                           Vector<AssetItem> &assets)
+static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree &node_tree)
 {
-  const Set<bke::CatalogID> catalog_ids = library.catalog_service->catalogs_for_path(path);
-  AssetFilterSettings type_filter{};
-  type_filter.id_types = FILTER_ID_NT;
-
-  /* Iterate over all the assets in the current catalog. */
-  ED_assetlist_storage_fetch(&library_ref, &C);
-  ED_assetlist_ensure_previews_job(&library_ref, &C);
-  ED_assetlist_iterate(library_ref, [&](AssetHandle asset) {
-    if (!ED_asset_filter_matches_asset(&type_filter, &asset)) {
-      return true;
-    }
-    const AssetMetaData *meta_data = ED_asset_handle_get_metadata(&asset);
-    if (!catalog_ids.contains(meta_data->catalog_id)) {
-      return true;
-    }
-    const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&asset);
-    const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&asset_data, "type");
-    if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
-      return true;
+  const Main &bmain = *CTX_data_main(&C);
+  const Vector<AssetLibraryReference> all_libraries = bke::all_asset_library_refs();
+
+  /* Merge catalogs from all libraries to deduplicate menu items. Also store the catalog and
+   * library for each asset ID in order to use them later when retrieving assets and removing
+   * empty catalogs.  */
+  Map<bke::CatalogID, LibraryCatalog> id_to_catalog_map;
+  bke::AssetCatalogTree catalogs_from_all_libraries;
+  for (const AssetLibraryReference &ref : all_libraries) {
+    if (bke::AssetLibrary *library = BKE_asset_library_load(&bmain, ref)) {
+      if (bke::AssetCatalogTree *tree = library->catalog_service->get_catalog_tree()) {
+        tree->foreach_item([&](bke::AssetCatalogTreeItem &item) {
+          const bke::CatalogID &id = item.get_catalog_id();
+          bke::AssetCatalog *catalog = library->catalog_service->find_catalog(id);
+          catalogs_from_all_libraries.insert_item(*catalog);
+          id_to_catalog_map.add(item.get_catalog_id(), LibraryCatalog{library, catalog});
+        });
+      }
     }
-    assets.append({asset, library_ref});
-    return true;
-  });
-}
+  }
 
-static void gather_child_catalogs(bke::AssetLibrary &library,
-                                  const bke::AssetCatalogPath &catalog_path,
-                                  Vector<bke::AssetCatalogPath> &child_catalogs)
-{
-  bke::AssetCatalogTree *tree = library.catalog_service->get_catalog_tree();
-  if (!tree) {
-    return;
+  /* Find assets for every catalog path. */
+  MultiValueMap<bke::AssetCatalogPath, LibraryAsset> assets_per_path;
+  for (const AssetLibraryReference &library : all_libraries) {
+    AssetFilterSettings type_filter{};
+    type_filter.id_types = FILTER_ID_NT;
+
+    ED_assetlist_storage_fetch(&library, &C);
+    ED_assetlist_ensure_previews_job(&library, &C);
+    ED_assetlist_iterate(library, [&](AssetHandle asset) {
+      if (!ED_asset_filter_matches_asset(&type_filter, &asset)) {
+        return true;
+      }
+      const AssetMetaData &meta_data = *ED_asset_handle_get_metadata(&asset);
+      const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
+      if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
+        return true;
+      }
+      if (BLI_uuid_is_nil(meta_data.catalog_id)) {
+        return true;
+      }
+      const LibraryCatalog &library_catalog = id_to_catalog_map.lookup(meta_data.catalog_id);
+      assets_per_path.add(library_catalog.catalog->path, LibraryAsset{library, asset});
+      return true;
+    });
   }
-  tree->foreach_item([&](bke::AssetCatalogTreeItem &catalog_item) {
-    if (catalog_item.catalog_path().parent() == catalog_path) {
-      child_catalogs.append(catalog_item.catalog_path());
+
+  /* Build the final tree without any of the catalogs that don't have proper node group assets. */
+  bke::AssetCatalogTree catalogs_with_node_assets;
+  catalogs_from_all_libraries.foreach_item([&](bke::AssetCatalogTreeItem &item) {
+    if (!assets_per_path.lookup(item.catalog_path()).is_empty()) {
+      const bke::CatalogID &id = item.get_catalog_id();
+      const LibraryCatalog &library_catalog = id_to_catalog_map.lookup(id);
+      bke::AssetCatalog *catalog = library_catalog.library->catalog_service->find_catalog(id);
+      catalogs_with_node_assets.insert_item(*catalog);
     }
   });
-}
 
-static void gather_root_catalogs(const bke::AssetLibrary &library,
-                                 Vector<bke::AssetCatalogPath> &root_catalogs)
-{
-  bke::AssetCatalogTree *tree = library.catalog_service->get_catalog_tree();
-  if (!tree) {
-    return;
-  }
-  tree->foreach_root_item([&](bke::AssetCatalogTreeItem &catalog_item) {
-    root_catalogs.append(catalog_item.catalog_path());
-  });
+  return {std::move(catalogs_with_node_assets), std::move(assets_per_path)};
 }
 
 static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
 {
-  const Main &bmain = *CTX_data_main(C);
   bScreen &screen = *CTX_wm_screen(C);
   const SpaceNode &snode = *CTX_wm_space_node(C);
   const bNodeTree *edit_tree = snode.edittree;
@@ -104,72 +119,65 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
   const bke::AssetCatalogPath &menu_path = *static_cast<const bke::AssetCatalogPath *>(
       menu_path_ptr.data);
 
-  Vector<AssetItem> asse

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list