[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