38 asset_library_root_(asset_library_root)
44 const_cast<bool &
>(is_read_only_) =
true;
55 catalog_collection_->has_unsaved_changes_ =
true;
61 catalog_collection_->has_unsaved_changes_ =
false;
66 if (catalog_collection_->catalog_definition_file_) {
67 for (
CatalogID catalog_id : catalog_collection_->deleted_catalogs_.keys()) {
68 catalog_collection_->catalog_definition_file_->forget(catalog_id);
71 catalog_collection_->deleted_catalogs_.clear();
74 for (
auto &catalog_uptr : catalog_collection_->catalogs_.values()) {
75 catalog_uptr->flags.has_unsaved_changes =
false;
82 return catalog_collection_->has_unsaved_changes_;
92 for (
auto &catalog : catalog_collection_->catalogs_.values()) {
93 catalog->flags.has_unsaved_changes =
true;
95 catalog_collection_->has_unsaved_changes_ =
true;
101 return catalog_collection_->catalogs_.is_empty();
106 return catalog_collection_->catalogs_;
110 return catalog_collection_->deleted_catalogs_;
115 return catalog_collection_->catalog_definition_file_.get();
120 const std::unique_ptr<AssetCatalog> *catalog_uptr_ptr =
121 catalog_collection_->catalogs_.lookup_ptr(catalog_id);
122 if (catalog_uptr_ptr ==
nullptr) {
125 return catalog_uptr_ptr->get();
135 for (
const auto &catalog : catalog_collection_->catalogs_.values()) {
136 if (catalog->path == path) {
137 ordered_catalogs.insert(catalog.get());
141 if (ordered_catalogs.empty()) {
145 MutableAssetCatalogOrderedSet::iterator best_choice_it = ordered_catalogs.begin();
146 return *best_choice_it;
152 return catalog_collection_->catalogs_.contains(catalog_id);
160 matching_catalog_ids.
add(active_catalog_id);
169 for (
const auto &catalog_uptr : catalog_collection_->catalogs_.values()) {
171 matching_catalog_ids.
add(catalog_uptr->catalog_id);
173 known_catalog_ids.
add(catalog_uptr->catalog_id);
176 return AssetCatalogFilter(std::move(matching_catalog_ids), std::move(known_catalog_ids));
181 std::unique_ptr<AssetCatalog> *catalog_uptr_ptr = catalog_collection_->catalogs_.lookup_ptr(
183 if (catalog_uptr_ptr ==
nullptr) {
194 catalog_collection_->deleted_catalogs_.add(catalog_id, std::move(*catalog_uptr_ptr));
197 catalog_collection_->catalogs_.remove(catalog_id);
202 catalog_collection_->catalogs_.remove(catalog_id);
203 catalog_collection_->deleted_catalogs_.remove(catalog_id);
206 catalog_collection_->catalog_definition_file_->forget(catalog_id);
213 for (
const auto &catalog_uptr : catalog_collection_->catalogs_.values()) {
221 for (
const CatalogID cat_id : catalogs_to_delete) {
232 BLI_assert_msg(catalog,
"trying to prune asset catalogs by the path of a non-existent catalog");
245 for (
auto &catalog_uptr : catalog_collection_->catalogs_.values()) {
252 cat->
path = new_path;
268 catalog->flags.has_unsaved_changes =
true;
276 BLI_assert_msg(!catalog_collection_->catalogs_.contains(catalog->catalog_id),
277 "duplicate catalog ID not supported");
278 catalog_collection_->catalogs_.add_new(catalog->catalog_id, std::move(catalog));
280 if (catalog_collection_->catalog_definition_file_) {
283 catalog_collection_->catalog_definition_file_->add_new(catalog_ptr);
297 asset_library_root.
data(),
310 if (
BLI_stat(file_or_directory_path.data(), &status) == -1) {
312 CLOG_WARN(&
LOG,
"path not found: %s", file_or_directory_path.data());
319 else if (
S_ISDIR(status.st_mode)) {
336 catalog_collection_->add_catalogs_from_existing(*other_service.catalog_collection_,
348 CLOG_INFO(&
LOG, 2,
"path not found: %s", file_path.data());
360 catalog_definition_file_path);
363 "Only loading of a single catalog definition file is supported.");
364 catalog_collection_->catalog_definition_file_ = std::move(cdf);
370 auto cdf = std::make_unique<AssetCatalogDefinitionFile>(catalog_definition_file_path);
375 auto catalog_parsed_callback = [
this, catalog_definition_file_path, &seen_paths](
376 std::unique_ptr<AssetCatalog> catalog) {
377 if (catalog_collection_->catalogs_.contains(catalog->catalog_id)) {
379 std::cerr << catalog_definition_file_path <<
": multiple definitions of catalog "
380 << catalog->catalog_id <<
" in multiple files, ignoring this one." << std::endl;
385 catalog->flags.is_first_loaded = seen_paths.
add(catalog->path);
388 catalog_collection_->catalogs_.add_new(catalog->catalog_id, std::move(catalog));
392 cdf->parse_catalog_file(cdf->file_path, catalog_parsed_callback);
409 auto catalog_parsed_callback = [
this, &cats_in_file](std::unique_ptr<AssetCatalog> catalog) {
410 const CatalogID catalog_id = catalog->catalog_id;
411 cats_in_file.
add(catalog_id);
421 catalog_collection_->catalogs_.add_overwrite(catalog_id, std::move(catalog));
434 for (
CatalogID cat_id : this->catalog_collection_->catalogs_.keys()) {
435 if (catalogs_to_keep.
contains(cat_id)) {
442 cats_to_remove.
add(cat_id);
445 for (
CatalogID cat_id : cats_to_remove) {
452 if (catalog_collection_->deleted_catalogs_.contains(catalog_id)) {
457 const std::unique_ptr<AssetCatalog> *catalog_uptr_ptr =
458 catalog_collection_->catalogs_.lookup_ptr(catalog_id);
459 if (!catalog_uptr_ptr) {
486 if (catalog_collection_->catalog_definition_file_) {
488 return catalog_collection_->catalog_definition_file_->write_to_disk();
491 if (catalog_collection_->catalogs_.is_empty() &&
492 catalog_collection_->deleted_catalogs_.is_empty())
502 return catalog_collection_->catalog_definition_file_->write_to_disk();
509 if (!catalog_collection_->catalog_definition_file_) {
516 catalog_collection_->catalog_definition_file_.reset();
527 "A non-empty .blend file path is required to be able to determine where the "
528 "catalog definition file should be put");
533 if (!suitable_root_path.empty()) {
536 sizeof(asset_lib_cdf_path),
537 suitable_root_path.c_str(),
539 return asset_lib_cdf_path;
547 return cdf_path_next_to_blend;
553 auto cdf = std::make_unique<AssetCatalogDefinitionFile>(file_path);
555 for (
auto &catalog : catalog_collection_->catalogs_.values()) {
556 cdf->add_new(catalog.get());
564 auto tree = std::make_unique<AssetCatalogTree>();
567 for (
auto &catalog : catalog_collection_->catalogs_.values()) {
568 tree->insert_item(*catalog);
576 std::lock_guard
lock{catalog_tree_mutex_};
577 this->catalog_tree_ =
nullptr;
582 std::lock_guard
lock{catalog_tree_mutex_};
583 if (!catalog_tree_) {
590 return *catalog_tree_;
596 std::set<AssetCatalogPath> paths_to_check;
597 for (
auto &catalog : catalog_collection_->catalogs_.values()) {
598 paths_to_check.insert(catalog->path);
601 std::set<AssetCatalogPath> seen_paths;
606 while (!paths_to_check.empty()) {
609 paths_to_check.erase(paths_to_check.begin());
611 if (seen_paths.find(path) != seen_paths.end()) {
615 seen_paths.insert(path);
618 if (seen_paths.find(parent_path) != seen_paths.end()) {
627 paths_to_check.insert(parent_path);
635 return !undo_snapshots_.is_empty();
640 return !redo_snapshots_.is_empty();
647 redo_snapshots_.append(std::move(catalog_collection_));
648 catalog_collection_ = undo_snapshots_.pop_last();
659 undo_snapshots_.append(std::move(catalog_collection_));
660 catalog_collection_ = redo_snapshots_.pop_last();
669 std::unique_ptr<AssetCatalogCollection> snapshot = catalog_collection_->deep_copy();
670 undo_snapshots_.append(std::move(snapshot));
671 redo_snapshots_.clear();
678 const std::string &simple_name)
679 : catalog_id(catalog_id), path(path), simple_name(simple_name)
688 auto catalog = std::make_unique<AssetCatalog>(cat_id, clean_path,
simple_name);
707 return "..." + name.substr(name.length() - 60);
714 : matching_catalog_ids_(std::move(matching_catalog_ids)),
715 known_catalog_ids_(std::move(known_catalog_ids))
721 return matching_catalog_ids_.contains(asset_catalog_id);
729 return known_catalog_ids_.contains(asset_catalog_id);
std::string AS_asset_library_find_suitable_root_path_from_path(blender::StringRefNull input_path)
#define BLI_assert_msg(a, msg)
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_is_file(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define BLI_path_join(...)
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
bool BLI_uuid_is_nil(bUUID uuid)
bUUID BLI_uuid_generate_random(void)
Compatibility-like things for windows.
#define CLOG_WARN(clg_ref,...)
#define CLOG_INFO(clg_ref, level,...)
bool contains(const Key &key) const
constexpr const char * data() const
void parse_catalog_file(const CatalogFilePath &catalog_definition_file_path, AssetCatalogParsedFn catalog_loaded_callback)
const CatalogFilePath file_path
bool contains(CatalogID asset_catalog_id) const
bool is_known(CatalogID asset_catalog_id) const
AssetCatalogFilter(Set< CatalogID > &&matching_catalog_ids, Set< CatalogID > &&known_catalog_ids)
AssetCatalogPath parent() const
const std::string & str() const
AssetCatalogPath cleanup() const
AssetCatalogPath rebase(const AssetCatalogPath &from_path, const AssetCatalogPath &to_path) const
bool is_contained_in(const AssetCatalogPath &other_path) const
static const char SEPARATOR
bool is_undo_possbile() const
void prepare_to_merge_on_write()
void delete_catalog_by_id_soft(CatalogID catalog_id)
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
void delete_catalog_by_id_hard(CatalogID catalog_id)
void prune_catalogs_by_path(const AssetCatalogPath &path)
bool write_to_disk(const CatalogFilePath &blend_file_path)
bool has_unsaved_changes() const
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
void create_missing_catalogs()
AssetCatalogService(const CatalogFilePath &asset_library_root={})
void tag_all_catalogs_as_unsaved_changes()
AssetCatalog * create_catalog(const AssetCatalogPath &catalog_path)
void update_catalog_path(CatalogID catalog_id, const AssetCatalogPath &new_catalog_path)
bool is_read_only() const
void prune_catalogs_by_id(CatalogID catalog_id)
void invalidate_catalog_tree()
void add_from_existing(const AssetCatalogService &other_service, FunctionRef< void(const AssetCatalog &existing, const AssetCatalog &to_be_ignored)> on_duplicate_items)
void untag_has_unsaved_changes()
bool is_redo_possbile() const
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
const OwningAssetCatalogMap & get_deleted_catalogs() const
static const CatalogFilePath DEFAULT_CATALOG_FILENAME
bool is_catalog_known(CatalogID catalog_id) const
void tag_has_unsaved_changes(AssetCatalog *edited_catalog)
const AssetCatalogDefinitionFile * get_catalog_definition_file() const
const AssetCatalogTree & catalog_tree()
const OwningAssetCatalogMap & get_catalogs() const
const CatalogID catalog_id
static std::unique_ptr< AssetCatalog > from_path(const AssetCatalogPath &path)
void simple_name_refresh()
static std::string sensible_simple_name_for_path(const AssetCatalogPath &path)
struct blender::asset_system::AssetCatalog::Flags flags
void tag_all_library_catalogs_dirty()
static AssetLibraryService * get()
std::set< AssetCatalog *, AssetCatalogLessThan > MutableAssetCatalogOrderedSet
static std::string asset_definition_default_file_path_from_dir(StringRef asset_library_root)
std::string CatalogFilePath
Universally Unique Identifier according to RFC4122.