diff options
author | Julian Eisel <julian@blender.org> | 2021-09-27 18:45:02 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2021-09-27 18:49:31 +0300 |
commit | 824733ea47d13030c18faa618c1dc31a08dfa43d (patch) | |
tree | 4d2c9ee4da79e51d5f02bfd9091c9d5bcee71753 /source/blender/blenkernel/intern/asset_catalog.cc | |
parent | 5bea5e25d52fe26b53928781ec0b1f5d4ddf5ad0 (diff) |
Assets: Additions/fixes to the catalog system in preparation for the UI
* Fixes missing update of the catalog tree when adding catalogs.
* Adds iterators for the catalogs, needed for UI code.
* Store catalog ID in the catalog tree items, needed for UI code.
* Other smaller API additions for the UI.
* Improve comments and smaller cleanups.
New functions are covered with unit tests.
Differential Revision: https://developer.blender.org/D12618
Reviewed by: Sybren Stüvel
Diffstat (limited to 'source/blender/blenkernel/intern/asset_catalog.cc')
-rw-r--r-- | source/blender/blenkernel/intern/asset_catalog.cc | 147 |
1 files changed, 113 insertions, 34 deletions
diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc index 4f1de09e148..b65ae12e5a7 100644 --- a/source/blender/blenkernel/intern/asset_catalog.cc +++ b/source/blender/blenkernel/intern/asset_catalog.cc @@ -64,6 +64,17 @@ AssetCatalog *AssetCatalogService::find_catalog(CatalogID catalog_id) return catalog_uptr_ptr->get(); } +AssetCatalog *AssetCatalogService::find_catalog_by_path(const CatalogPath &path) const +{ + for (auto &catalog : catalogs_.values()) { + if (catalog->path == path) { + return catalog.get(); + } + } + + return nullptr; +} + void AssetCatalogService::delete_catalog(CatalogID catalog_id) { std::unique_ptr<AssetCatalog> *catalog_uptr_ptr = this->catalogs_.lookup_ptr(catalog_id); @@ -104,6 +115,12 @@ AssetCatalog *AssetCatalogService::create_catalog(const CatalogPath &catalog_pat catalog_definition_file_->add_new(catalog_ptr); } + /* The tree may not exist; this happens when no catalog definition file has been loaded yet. When + * the tree is created any in-memory catalogs will be added, so it doesn't need to happen now. */ + if (catalog_tree_) { + catalog_tree_->insert_item(*catalog_ptr); + } + return catalog_ptr; } @@ -268,34 +285,7 @@ std::unique_ptr<AssetCatalogTree> AssetCatalogService::read_into_tree() /* Go through the catalogs, insert each path component into the tree where needed. */ for (auto &catalog : catalogs_.values()) { - const AssetCatalogTreeItem *parent = nullptr; - AssetCatalogTreeItem::ChildMap *insert_to_map = &tree->children_; - - BLI_assert_msg(!ELEM(catalog->path[0], '/', '\\'), - "Malformed catalog path; should not start with a separator"); - - const char *next_slash_ptr; - /* Looks more complicated than it is, this just iterates over path components. E.g. - * "just/some/path" iterates over "just", then "some" then "path". */ - for (const char *name_begin = catalog->path.data(); name_begin && name_begin[0]; - /* Jump to one after the next slash if there is any. */ - name_begin = next_slash_ptr ? next_slash_ptr + 1 : nullptr) { - next_slash_ptr = BLI_path_slash_find(name_begin); - - /* Note that this won't be null terminated. */ - StringRef component_name = next_slash_ptr ? - StringRef(name_begin, next_slash_ptr - name_begin) : - /* Last component in the path. */ - name_begin; - - /* Insert new tree element - if no matching one is there yet! */ - auto [item, was_inserted] = insert_to_map->emplace( - component_name, AssetCatalogTreeItem(component_name, parent)); - - /* Walk further into the path (no matter if a new item was created or not). */ - parent = &item->second; - insert_to_map = &item->second.children_; - } + tree->insert_item(*catalog); } return tree; @@ -306,9 +296,18 @@ void AssetCatalogService::rebuild_tree() this->catalog_tree_ = read_into_tree(); } -AssetCatalogTreeItem::AssetCatalogTreeItem(StringRef name, const AssetCatalogTreeItem *parent) - : name_(name), parent_(parent) +/* ---------------------------------------------------------------------- */ + +AssetCatalogTreeItem::AssetCatalogTreeItem(StringRef name, + CatalogID catalog_id, + const AssetCatalogTreeItem *parent) + : name_(name), catalog_id_(catalog_id), parent_(parent) +{ +} + +CatalogID AssetCatalogTreeItem::get_catalog_id() const { + return catalog_id_; } StringRef AssetCatalogTreeItem::get_name() const @@ -334,20 +333,100 @@ int AssetCatalogTreeItem::count_parents() const return i; } -void AssetCatalogTree::foreach_item(const AssetCatalogTreeItem::ItemIterFn callback) const +bool AssetCatalogTreeItem::has_children() const +{ + return !children_.empty(); +} + +/* ---------------------------------------------------------------------- */ + +/** + * Iterate over path components, calling \a callback for each component. E.g. "just/some/path" + * iterates over "just", then "some" then "path". + */ +static void iterate_over_catalog_path_components( + const CatalogPath &path, + FunctionRef<void(StringRef component_name, bool is_last_component)> callback) +{ + const char *next_slash_ptr; + + for (const char *path_component = path.data(); path_component && path_component[0]; + /* Jump to one after the next slash if there is any. */ + path_component = next_slash_ptr ? next_slash_ptr + 1 : nullptr) { + next_slash_ptr = BLI_path_slash_find(path_component); + + const bool is_last_component = next_slash_ptr == nullptr; + /* Note that this won't be null terminated. */ + const StringRef component_name = is_last_component ? + path_component : + StringRef(path_component, + next_slash_ptr - path_component); + + callback(component_name, is_last_component); + } +} + +void AssetCatalogTree::insert_item(const AssetCatalog &catalog) +{ + const AssetCatalogTreeItem *parent = nullptr; + /* The children for the currently iterated component, where the following component should be + * added to (if not there yet). */ + AssetCatalogTreeItem::ChildMap *current_item_children = &root_items_; + + BLI_assert_msg(!ELEM(catalog.path[0], '/', '\\'), + "Malformed catalog path; should not start with a separator"); + + const CatalogID nil_id{}; + + iterate_over_catalog_path_components( + catalog.path, [&](StringRef component_name, const bool is_last_component) { + /* Insert new tree element - if no matching one is there yet! */ + auto [key_and_item, was_inserted] = current_item_children->emplace( + component_name, + AssetCatalogTreeItem( + component_name, is_last_component ? catalog.catalog_id : nil_id, parent)); + AssetCatalogTreeItem &item = key_and_item->second; + + /* If full path of this catalog already exists as parent path of a previously read catalog, + * we can ensure this tree item's UUID is set here. */ + if (is_last_component && BLI_uuid_is_nil(item.catalog_id_)) { + item.catalog_id_ = catalog.catalog_id; + } + + /* Walk further into the path (no matter if a new item was created or not). */ + parent = &item; + current_item_children = &item.children_; + }); +} + +void AssetCatalogTree::foreach_item(AssetCatalogTreeItem::ItemIterFn callback) { - AssetCatalogTreeItem::foreach_item_recursive(children_, callback); + AssetCatalogTreeItem::foreach_item_recursive(root_items_, callback); } -void AssetCatalogTreeItem::foreach_item_recursive(const AssetCatalogTreeItem::ChildMap &children, +void AssetCatalogTreeItem::foreach_item_recursive(AssetCatalogTreeItem::ChildMap &children, const ItemIterFn callback) { - for (const auto &[key, item] : children) { + for (auto &[key, item] : children) { callback(item); foreach_item_recursive(item.children_, callback); } } +void AssetCatalogTree::foreach_root_item(const ItemIterFn callback) +{ + for (auto &[key, item] : root_items_) { + callback(item); + } +} + +void AssetCatalogTreeItem::foreach_child(const ItemIterFn callback) +{ + for (auto &[key, item] : children_) { + callback(item); + } +} + AssetCatalogTree *AssetCatalogService::get_catalog_tree() { return catalog_tree_.get(); |