Blender V5.0
AS_asset_catalog.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include <memory>
12#include <mutex>
13#include <set>
14#include <string>
15
16#include "BLI_function_ref.hh"
17#include "BLI_map.hh"
18#include "BLI_set.hh"
19#include "BLI_uuid.h"
20#include "BLI_vector.hh"
21
23
25
26class AssetCatalog;
31
33using CatalogPathComponent = std::string;
34/* Would be nice to be able to use `std::filesystem::path` for this, but it's currently not
35 * available on the minimum macOS target version. */
36using CatalogFilePath = std::string;
38
39/* Manages the asset catalogs of a single asset library (i.e. of catalogs defined in a single
40 * directory hierarchy). */
42 std::unique_ptr<AssetCatalogCollection> catalog_collection_;
43
47 std::unique_ptr<AssetCatalogTree> catalog_tree_;
48 std::recursive_mutex catalog_tree_mutex_;
49
52
53 CatalogFilePath asset_library_root_;
54 bool is_read_only_ = false;
55
56 friend class AssetLibraryService;
57 friend class AssetLibrary;
58
59 public:
61
62 struct read_only_tag {};
63
64 explicit AssetCatalogService(const CatalogFilePath &asset_library_root = {});
65 explicit AssetCatalogService(read_only_tag);
66
74 void tag_has_unsaved_changes(AssetCatalog *edited_catalog = nullptr);
75 bool has_unsaved_changes() const;
76
82 bool is_read_only() const;
83
85 void load_from_disk();
87 void load_from_disk(const CatalogFilePath &file_or_directory_path);
88
96 void add_from_existing(const AssetCatalogService &other_service,
97 FunctionRef<void(const AssetCatalog &existing,
98 const AssetCatalog &to_be_ignored)> on_duplicate_items);
99
117 bool write_to_disk(const CatalogFilePath &blend_file_path);
118
127
136 void reload_catalogs();
137
139 AssetCatalog *find_catalog(CatalogID catalog_id) const;
140
148
152 bool is_catalog_known(CatalogID catalog_id) const;
153
160 AssetCatalogFilter create_catalog_filter(CatalogID active_catalog_id) const;
161
171 AssetCatalog *create_catalog(const AssetCatalogPath &catalog_path);
172
177
182 void prune_catalogs_by_id(CatalogID catalog_id);
183
187 void update_catalog_path(CatalogID catalog_id, const AssetCatalogPath &new_catalog_path);
188
193
195 bool is_empty() const;
196
200 void undo_push();
205 void undo();
206 bool is_undo_possbile() const;
210 void redo();
211 bool is_redo_possbile() const;
212
213 protected:
214 void load_directory_recursive(const CatalogFilePath &directory_path);
215 void load_single_file(const CatalogFilePath &catalog_definition_file_path);
216
218 bool write_to_disk_ex(const CatalogFilePath &blend_file_path);
221
229 void purge_catalogs_not_listed(const Set<CatalogID> &catalogs_to_keep);
230
244 void delete_catalog_by_id_soft(CatalogID catalog_id);
245
249 void delete_catalog_by_id_hard(CatalogID catalog_id);
250
251 std::unique_ptr<AssetCatalogDefinitionFile> parse_catalog_file(
252 const CatalogFilePath &catalog_definition_file_path);
253
257 std::unique_ptr<AssetCatalogDefinitionFile> construct_cdf_in_memory(
258 const CatalogFilePath &file_path) const;
259
267 const CatalogFilePath &blend_file_path);
268
269 std::unique_ptr<AssetCatalogTree> read_into_tree() const;
276
281
286
287 /* For access by subclasses, as those will not be marked as friend by #AssetCatalogCollection. */
289 const OwningAssetCatalogMap &get_catalogs() const;
291};
292
302 public:
312 std::string simple_name;
313
314 struct Flags {
315 /* Treat this catalog as deleted. Keeping deleted catalogs around is necessary to support
316 * merging of on-disk changes with in-memory changes. */
317 bool is_deleted = false;
318
319 /* Sort this catalog first when there are multiple catalogs with the same catalog path. This
320 * ensures that in a situation where missing catalogs were auto-created, and then
321 * load-and-merged with a file that also has these catalogs, the first one in that file is
322 * always sorted first, regardless of the sort order of its UUID. */
323 bool is_first_loaded = false;
324
325 /* Merging on-disk changes into memory will not overwrite this catalog.
326 * For example, when a catalog was renamed (i.e. changed path) in this Blender session,
327 * reloading the catalog definition file should not overwrite that change.
328 *
329 * Note that this flag is ignored when is_deleted=true; deleted catalogs that are still in
330 * memory are considered "unsaved" by definition. */
333
334 AssetCatalog() = delete;
336
343 static std::unique_ptr<AssetCatalog> from_path(const AssetCatalogPath &path);
344
346 void simple_name_refresh();
347
348 protected:
350 static std::string sensible_simple_name_for_path(const AssetCatalogPath &path);
351};
352
355 bool operator()(const AssetCatalog *lhs, const AssetCatalog *rhs) const
356 {
357 if (lhs->path != rhs->path) {
358 return lhs->path < rhs->path;
359 }
360
361 if (lhs->flags.is_first_loaded != rhs->flags.is_first_loaded) {
362 return lhs->flags.is_first_loaded;
363 }
364
365 return lhs->catalog_id < rhs->catalog_id;
366 }
367};
368
372using AssetCatalogOrderedSet = std::set<const AssetCatalog *, AssetCatalogLessThan>;
373using MutableAssetCatalogOrderedSet = std::set<AssetCatalog *, AssetCatalogLessThan>;
374
381 const Set<CatalogID> matching_catalog_ids_;
382 const Set<CatalogID> known_catalog_ids_;
383
384 friend AssetCatalogService;
385
386 public:
387 bool contains(CatalogID asset_catalog_id) const;
388
389 /* So that all unknown catalogs can be shown under "Unassigned". */
390 bool is_known(CatalogID asset_catalog_id) const;
391
392 protected:
393 explicit AssetCatalogFilter(Set<CatalogID> &&matching_catalog_ids,
394 Set<CatalogID> &&known_catalog_ids);
395};
396
397} // namespace blender::asset_system
AssetCatalogFilter(Set< CatalogID > &&matching_catalog_ids, Set< CatalogID > &&known_catalog_ids)
void load_single_file(const CatalogFilePath &catalog_definition_file_path)
AssetCatalogFilter create_catalog_filter(CatalogID active_catalog_id) const
AssetCatalog * find_catalog_by_path(const AssetCatalogPath &path) const
AssetCatalog * find_catalog(CatalogID catalog_id) const
bool write_to_disk(const CatalogFilePath &blend_file_path)
std::unique_ptr< AssetCatalogTree > read_into_tree() const
void purge_catalogs_not_listed(const Set< CatalogID > &catalogs_to_keep)
std::unique_ptr< AssetCatalogDefinitionFile > parse_catalog_file(const CatalogFilePath &catalog_definition_file_path)
std::unique_ptr< AssetCatalogDefinitionFile > construct_cdf_in_memory(const CatalogFilePath &file_path) const
AssetCatalogService(const CatalogFilePath &asset_library_root={})
AssetCatalog * create_catalog(const AssetCatalogPath &catalog_path)
void update_catalog_path(CatalogID catalog_id, const AssetCatalogPath &new_catalog_path)
void add_from_existing(const AssetCatalogService &other_service, FunctionRef< void(const AssetCatalog &existing, const AssetCatalog &to_be_ignored)> on_duplicate_items)
static CatalogFilePath find_suitable_cdf_path_for_writing(const CatalogFilePath &blend_file_path)
bool write_to_disk_ex(const CatalogFilePath &blend_file_path)
void load_directory_recursive(const CatalogFilePath &directory_path)
bool is_catalog_known_with_unsaved_changes(CatalogID catalog_id) const
void tag_has_unsaved_changes(AssetCatalog *edited_catalog=nullptr)
static const CatalogFilePath DEFAULT_CATALOG_FILENAME
const AssetCatalogDefinitionFile * get_catalog_definition_file() const
static std::unique_ptr< AssetCatalog > from_path(const AssetCatalogPath &path)
static std::string sensible_simple_name_for_path(const AssetCatalogPath &path)
struct blender::asset_system::AssetCatalog::Flags flags
std::set< AssetCatalog *, AssetCatalogLessThan > MutableAssetCatalogOrderedSet
Map< CatalogID, std::unique_ptr< AssetCatalog > > OwningAssetCatalogMap
std::set< const AssetCatalog *, AssetCatalogLessThan > AssetCatalogOrderedSet
bool operator()(const AssetCatalog *lhs, const AssetCatalog *rhs) const