[Bf-blender-cvs] [c6db534b996] temp-asset-browser-catalogs-ui: Ensure unique catalog name when adding

Julian Eisel noreply at git.blender.org
Tue Sep 21 00:18:01 CEST 2021


Commit: c6db534b996993b5f75f2b3bb7b9846f41ca7f50
Author: Julian Eisel
Date:   Tue Sep 21 00:16:30 2021 +0200
Branches: temp-asset-browser-catalogs-ui
https://developer.blender.org/rBc6db534b996993b5f75f2b3bb7b9846f41ca7f50

Ensure unique catalog name when adding

Without this, adding multiple catalogs would always add them with the
same name. The first duplicate name would cause an assert to fail.

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

M	source/blender/blenkernel/BKE_asset_catalog.hh
M	source/blender/blenkernel/intern/asset_catalog.cc
M	source/blender/editors/asset/ED_asset_catalog.hh
M	source/blender/editors/asset/intern/asset_catalog.cc

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

diff --git a/source/blender/blenkernel/BKE_asset_catalog.hh b/source/blender/blenkernel/BKE_asset_catalog.hh
index 77195b010d8..d283de9af2f 100644
--- a/source/blender/blenkernel/BKE_asset_catalog.hh
+++ b/source/blender/blenkernel/BKE_asset_catalog.hh
@@ -64,6 +64,10 @@ class AssetCatalogService {
   /** Return catalog with the given ID. Return nullptr if not found. */
   AssetCatalog *find_catalog(const CatalogID &catalog_id);
 
+  /** Return first catalog with the given path. Return nullptr if not found. Not the most efficient
+   * function, better don't use it in performance sensitive areas. */
+  AssetCatalog *find_catalog_from_path(const CatalogPath &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 CatalogPath &catalog_path);
diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc
index 22da9b25235..53bfaf05206 100644
--- a/source/blender/blenkernel/intern/asset_catalog.cc
+++ b/source/blender/blenkernel/intern/asset_catalog.cc
@@ -52,6 +52,17 @@ AssetCatalog *AssetCatalogService::find_catalog(const CatalogID &catalog_id)
   return catalog_uptr_ptr->get();
 }
 
+AssetCatalog *AssetCatalogService::find_catalog_from_path(const CatalogPath &path) const
+{
+  for (auto &catalog : catalogs_.values()) {
+    if (catalog->path == path) {
+      return catalog.get();
+    }
+  }
+
+  return nullptr;
+}
+
 AssetCatalog *AssetCatalogService::create_catalog(const CatalogPath &catalog_path)
 {
   std::unique_ptr<AssetCatalog> catalog = AssetCatalog::from_path(catalog_path);
@@ -59,6 +70,8 @@ AssetCatalog *AssetCatalogService::create_catalog(const CatalogPath &catalog_pat
   /* So we can std::move(catalog) and still use the non-owning pointer: */
   AssetCatalog *const catalog_ptr = catalog.get();
 
+  BLI_assert_msg(find_catalog_from_path(catalog_path) == nullptr,
+                 "duplicate catalog path not supported");
   /* TODO(@sybren): move the `AssetCatalog::from_path()` function to another place, that can reuse
    * catalogs when a catalog with the given path is already known, and avoid duplicate catalog IDs.
    */
diff --git a/source/blender/editors/asset/ED_asset_catalog.hh b/source/blender/editors/asset/ED_asset_catalog.hh
index c08fa9ad093..7ed12c76214 100644
--- a/source/blender/editors/asset/ED_asset_catalog.hh
+++ b/source/blender/editors/asset/ED_asset_catalog.hh
@@ -28,5 +28,5 @@ struct AssetLibrary;
 }  // namespace blender::bke
 
 blender::bke::AssetCatalog *ED_asset_catalog_add(blender::bke::AssetLibrary *library,
-                                                 blender::StringRef name,
+                                                 blender::StringRefNull name,
                                                  blender::StringRef parent_path = nullptr);
diff --git a/source/blender/editors/asset/intern/asset_catalog.cc b/source/blender/editors/asset/intern/asset_catalog.cc
index bc03d3c5263..b1a38e67e97 100644
--- a/source/blender/editors/asset/intern/asset_catalog.cc
+++ b/source/blender/editors/asset/intern/asset_catalog.cc
@@ -21,17 +21,63 @@
 #include "BKE_asset_catalog.hh"
 #include "BKE_asset_library.hh"
 
+#include "BLI_string_utils.h"
+
 #include "ED_asset_catalog.hh"
 
 using namespace blender;
 using namespace blender::bke;
 
+struct CatalogUniqueNameFnData {
+  const AssetCatalogService &catalog_service;
+  StringRef parent_path;
+};
+
+static std::string to_full_path(StringRef parent_path, StringRef name)
+{
+  return parent_path.is_empty() ?
+             std::string(name) :
+             std::string(parent_path) + AssetCatalogService::PATH_SEPARATOR + name;
+}
+
+static bool catalog_name_is_not_unique_fn(void *arg, const char *name)
+{
+  CatalogUniqueNameFnData &fn_data = *static_cast<CatalogUniqueNameFnData *>(arg);
+  std::string fullpath = to_full_path(fn_data.parent_path, name);
+  if (fn_data.catalog_service.find_catalog_from_path(fullpath)) {
+    return true;
+  }
+  return false;
+}
+
+static std::string catalog_name_ensure_unique(AssetCatalogService &catalog_service,
+                                              StringRefNull name,
+                                              StringRef parent_path)
+{
+  CatalogUniqueNameFnData fn_data = {catalog_service, parent_path};
+
+  char unique_name[NAME_MAX] = "";
+  BLI_uniquename_cb(catalog_name_is_not_unique_fn,
+                    &fn_data,
+                    name.c_str(),
+                    '.',
+                    unique_name,
+                    sizeof(unique_name));
+
+  return unique_name;
+}
+
 AssetCatalog *ED_asset_catalog_add(blender::bke::AssetLibrary *library,
-                                   StringRef name,
+                                   StringRefNull name,
                                    StringRef parent_path)
 {
-  std::string fullpath = parent_path.is_empty() ?
-                             std::string(name) :
-                             std::string(parent_path) + AssetCatalogService::PATH_SEPARATOR + name;
+  if (!library || !library->catalog_service) {
+    return nullptr;
+  }
+
+  std::string unique_name = catalog_name_ensure_unique(
+      *library->catalog_service, name, parent_path);
+  std::string fullpath = to_full_path(parent_path, unique_name);
+
   return library->catalog_service->create_catalog(fullpath);
 }



More information about the Bf-blender-cvs mailing list