diff options
author | Julian Eisel <julian@blender.org> | 2021-10-04 00:58:20 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2021-10-04 00:58:20 +0300 |
commit | c4dca6522812670ab9782e4f90553c5054109f3d (patch) | |
tree | 24dc1e2c0eb55985e8e6543b131989da1ca4125e /source/blender/editors/space_file | |
parent | 3b1a2430391a6c1e0ea2744cfce2cf0749c72c85 (diff) |
Asset Browser: Support dragging assets into catalogs
With this it is possible to select any number of assets in the Asset
Browser and drag them into catalogs. The assets will be moved to that
catalog then. However, this will only work in the "Current File" asset
library, since that is the only library that allows changing assets,
which is what's done here.
While dragging assets over the tree row, a tooltip is shown explaining
what's going to happen.
In preparation to this, the new UI tree-view API was already extended
with custom drop support, see 4ee2d9df428d.
----
Changes here to the `wmDrag` code were needed to support dragging multiple
assets. Some of it is considered temporary because a) a proper #AssetHandle
design should replace some ugly parts of this patch and b) the multi-item
support in `wmDrag` isn't that great yet. The entire API will have to be
written anyway (see D4071).
Maniphest Tasks: T91573
Differential Revision: https://developer.blender.org/D12713
Reviewed by: Sybren Stüvel
Diffstat (limited to 'source/blender/editors/space_file')
-rw-r--r-- | source/blender/editors/space_file/asset_catalog_tree_view.cc | 83 | ||||
-rw-r--r-- | source/blender/editors/space_file/file_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/space_file/file_panels.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_file/filelist.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_file/filelist.h | 1 | ||||
-rw-r--r-- | source/blender/editors/space_file/space_file.c | 19 |
6 files changed, 102 insertions, 7 deletions
diff --git a/source/blender/editors/space_file/asset_catalog_tree_view.cc b/source/blender/editors/space_file/asset_catalog_tree_view.cc index 7eea9af925b..92e4e668885 100644 --- a/source/blender/editors/space_file/asset_catalog_tree_view.cc +++ b/source/blender/editors/space_file/asset_catalog_tree_view.cc @@ -25,6 +25,7 @@ #include "DNA_space_types.h" +#include "BKE_asset.h" #include "BKE_asset_catalog.hh" #include "BKE_asset_library.hh" @@ -43,6 +44,7 @@ #include "WM_types.h" #include "file_intern.h" +#include "filelist.h" using namespace blender; using namespace blender::bke; @@ -53,11 +55,14 @@ class AssetCatalogTreeView : public ui::AbstractTreeView { /** The asset catalog tree this tree-view represents. */ bke::AssetCatalogTree *catalog_tree_; FileAssetSelectParams *params_; + SpaceFile &space_file_; friend class AssetCatalogTreeViewItem; public: - AssetCatalogTreeView(::AssetLibrary *library, FileAssetSelectParams *params); + AssetCatalogTreeView(::AssetLibrary *library, + FileAssetSelectParams *params, + SpaceFile &space_file); void build_tree() override; @@ -117,6 +122,70 @@ class AssetCatalogTreeViewItem : public ui::BasicTreeViewItem { RNA_string_set(props, "catalog_id", catalog_id_str_buffer); } } + + bool has_droppable_item(const wmDrag &drag) const + { + const ListBase *asset_drags = WM_drag_asset_list_get(&drag); + + /* There needs to be at least one asset from the current file. */ + LISTBASE_FOREACH (const wmDragAssetListItem *, asset_item, asset_drags) { + if (!asset_item->is_external) { + return true; + } + } + return false; + } + + bool can_drop(const wmDrag &drag) const override + { + if (drag.type != WM_DRAG_ASSET_LIST) { + return false; + } + return has_droppable_item(drag); + } + + std::string drop_tooltip(const bContext & /*C*/, + const wmDrag &drag, + const wmEvent & /*event*/) const override + { + const ListBase *asset_drags = WM_drag_asset_list_get(&drag); + const bool is_multiple_assets = !BLI_listbase_is_single(asset_drags); + + /* Don't try to be smart by dynamically adding the 's' for the plural. Just makes translation + * harder, so use full literals. */ + std::string basic_tip = is_multiple_assets ? TIP_("Move assets to catalog") : + TIP_("Move asset to catalog"); + + return basic_tip + ": " + catalog_item_.get_name() + " (" + + catalog_item_.catalog_path().str() + ")"; + } + + bool on_drop(const wmDrag &drag) override + { + const ListBase *asset_drags = WM_drag_asset_list_get(&drag); + if (!asset_drags) { + return false; + } + + const AssetCatalogTreeView &tree_view = static_cast<const AssetCatalogTreeView &>( + get_tree_view()); + + LISTBASE_FOREACH (wmDragAssetListItem *, asset_item, asset_drags) { + if (asset_item->is_external) { + /* Only internal assets can be modified! */ + continue; + } + BKE_asset_metadata_catalog_id_set(asset_item->asset_data.local_id->asset_data, + catalog_item_.get_catalog_id(), + catalog_item_.get_simple_name().c_str()); + + /* Trigger re-run of filtering to update visible assets. */ + filelist_tag_needs_filtering(tree_view.space_file_.files); + file_select_deselect_all(&tree_view.space_file_, FILE_SEL_SELECTED | FILE_SEL_HIGHLIGHTED); + } + + return true; + } }; /** Only reason this isn't just `BasicTreeViewItem` is to add a '+' icon for adding a root level @@ -140,8 +209,12 @@ class AssetCatalogTreeViewAllItem : public ui::BasicTreeViewItem { } }; -AssetCatalogTreeView::AssetCatalogTreeView(::AssetLibrary *library, FileAssetSelectParams *params) - : catalog_tree_(BKE_asset_library_get_catalog_tree(library)), params_(params) +AssetCatalogTreeView::AssetCatalogTreeView(::AssetLibrary *library, + FileAssetSelectParams *params, + SpaceFile &space_file) + : catalog_tree_(BKE_asset_library_get_catalog_tree(library)), + params_(params), + space_file_(space_file) { } @@ -216,6 +289,7 @@ bool AssetCatalogTreeView::is_active_catalog(CatalogID catalog_id) const void file_create_asset_catalog_tree_view_in_layout(::AssetLibrary *asset_library, uiLayout *layout, + SpaceFile *space_file, FileAssetSelectParams *params) { uiBlock *block = uiLayoutGetBlock(layout); @@ -223,7 +297,8 @@ void file_create_asset_catalog_tree_view_in_layout(::AssetLibrary *asset_library ui::AbstractTreeView *tree_view = UI_block_add_view( *block, "asset catalog tree view", - std::make_unique<ed::asset_browser::AssetCatalogTreeView>(asset_library, params)); + std::make_unique<ed::asset_browser::AssetCatalogTreeView>( + asset_library, params, *space_file)); ui::TreeViewBuilder builder(*block); builder.build_tree_view(*tree_view); diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index d39aefff691..c8609f48adb 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -165,6 +165,7 @@ void file_path_to_ui_path(const char *path, char *r_pathi, int max_size); void file_create_asset_catalog_tree_view_in_layout(struct AssetLibrary *asset_library, struct uiLayout *layout, + struct SpaceFile *space_file, struct FileAssetSelectParams *params); #ifdef __cplusplus diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index 95aad202f1a..b530f1d0aa7 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -238,7 +238,7 @@ static void file_panel_asset_catalog_buttons_draw(const bContext *C, Panel *pane FileAssetSelectParams *params = ED_fileselect_get_asset_params(sfile); BLI_assert(params != NULL); - file_create_asset_catalog_tree_view_in_layout(asset_library, panel->layout, params); + file_create_asset_catalog_tree_view_in_layout(asset_library, panel->layout, sfile, params); } void file_tools_region_panels_register(ARegionType *art) diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 0cb587c3b19..b58a04d6d4f 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -490,7 +490,6 @@ static void filelist_readjob_main_assets(struct FileListReadJob *job_params, static int groupname_to_code(const char *group); static uint64_t groupname_to_filter_id(const char *group); -static void filelist_tag_needs_filtering(FileList *filelist); static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size); /* ********** Sort helpers ********** */ @@ -970,7 +969,7 @@ static bool is_filtered_main_assets(FileListInternEntry *file, is_filtered_asset(file, filter); } -static void filelist_tag_needs_filtering(FileList *filelist) +void filelist_tag_needs_filtering(FileList *filelist) { filelist->flags |= FL_NEED_FILTERING; } diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index d1f37b5b365..c2c1211b81c 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -76,6 +76,7 @@ void filelist_set_asset_catalog_filter_options( struct FileList *filelist, eFileSel_Params_AssetCatalogVisibility catalog_visibility, const struct bUUID *catalog_id); +void filelist_tag_needs_filtering(struct FileList *filelist); void filelist_filter(struct FileList *filelist); void filelist_setlibrary(struct FileList *filelist, const struct AssetLibraryReference *asset_library_ref); diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index a563f24e24e..c8bca22c166 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -894,6 +894,7 @@ const char *file_context_dir[] = { "active_file", "selected_files", "asset_library_ref", + "selected_asset_files", "id", NULL, }; @@ -951,6 +952,24 @@ static int /*eContextResult*/ file_context(const bContext *C, result, &screen->id, &RNA_AssetLibraryReference, &asset_params->asset_library_ref); return CTX_RESULT_OK; } + /** TODO temporary AssetHandle design: For now this returns the file entry. Would be better if it + * was `"selected_assets"` and returned the assets (e.g. as `AssetHandle`) directly. See comment + * for #AssetHandle for more info. */ + if (CTX_data_equals(member, "selected_asset_files")) { + const int num_files_filtered = filelist_files_ensure(sfile->files); + + for (int file_index = 0; file_index < num_files_filtered; file_index++) { + if (filelist_entry_is_selected(sfile->files, file_index)) { + FileDirEntry *entry = filelist_file(sfile->files, file_index); + if (entry->asset_data) { + CTX_data_list_add(result, &screen->id, &RNA_FileSelectEntry, entry); + } + } + } + + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return CTX_RESULT_OK; + } if (CTX_data_equals(member, "id")) { const FileDirEntry *file = filelist_file(sfile->files, params->active_file); if (file == NULL) { |