Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <julian@blender.org>2021-09-29 18:01:13 +0300
committerJulian Eisel <julian@blender.org>2021-09-29 18:15:23 +0300
commit9d9f205dc4a9ddae3d654c64894eaca8443cacc0 (patch)
treeb41b40fe69987849bb02415ddcd63d465df10501 /source/blender/editors/space_file
parentdf9120b365380cc1d64006e0d37a650eaaff9776 (diff)
Asset Browser: Initial Asset Catalog UI
The Asset Browser now displays a tree with asset catalogs in the left sidebar. This replaces the asset categories. It uses the new UI tree-view API (https://wiki.blender.org/wiki/Source/Interface/Views#Tree-View). Buttons are displayed for adding and removing of catalogs. Parent items can be collapsed, but the collapsed/uncollapsed state is not stored in files yet. Note that edits to catalogs (e.g. new or removed catalogs) are only written to the asset library's catalog definition files when saving a .blend. In the "Current File" asset library, we try to show asset catalogs from a parent asset library, or if that fails, from the directory the file is stored in. See adaf4f56e1ed. There are plenty of TODOs and smaller glitches to be fixed still. Plus a UI polishing pass should be done. Important missing UI features: * Dragging assets into catalogs (WIP, close to being ready). * Renaming catalogs * Proper handling of catalogs in the "Current File" asset library (currently not working well). The "Current File" asset library is especially limited still. Since this is the only place where you can assign assets to a catalog, this makes the catalogs very cumbersome in general. To assign an asset to a catalog, one has to manually copy the Catalog ID (a random hash like number) to the asset metadata through a temporary UI in the Asset Browser Sidebar. These limitations should be addressed over the next few days, they are high priority. Differential Revision: https://developer.blender.org/D12670
Diffstat (limited to 'source/blender/editors/space_file')
-rw-r--r--source/blender/editors/space_file/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_file/asset_catalog_tree_view.cc230
-rw-r--r--source/blender/editors/space_file/file_intern.h10
-rw-r--r--source/blender/editors/space_file/file_panels.c32
-rw-r--r--source/blender/editors/space_file/filelist.c52
-rw-r--r--source/blender/editors/space_file/filelist.h7
-rw-r--r--source/blender/editors/space_file/filesel.c14
-rw-r--r--source/blender/editors/space_file/space_file.c9
8 files changed, 349 insertions, 6 deletions
diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt
index b60f9df82f6..4b508f16c1e 100644
--- a/source/blender/editors/space_file/CMakeLists.txt
+++ b/source/blender/editors/space_file/CMakeLists.txt
@@ -34,6 +34,7 @@ set(INC
)
set(SRC
+ asset_catalog_tree_view.cc
file_draw.c
file_ops.c
file_panels.c
diff --git a/source/blender/editors/space_file/asset_catalog_tree_view.cc b/source/blender/editors/space_file/asset_catalog_tree_view.cc
new file mode 100644
index 00000000000..7eea9af925b
--- /dev/null
+++ b/source/blender/editors/space_file/asset_catalog_tree_view.cc
@@ -0,0 +1,230 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup spfile
+ */
+
+#include "ED_fileselect.h"
+
+#include "DNA_space_types.h"
+
+#include "BKE_asset_catalog.hh"
+#include "BKE_asset_library.hh"
+
+#include "BLI_string_ref.hh"
+
+#include "BLT_translation.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_interface.hh"
+#include "UI_resources.h"
+#include "UI_tree_view.hh"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "file_intern.h"
+
+using namespace blender;
+using namespace blender::bke;
+
+namespace blender::ed::asset_browser {
+
+class AssetCatalogTreeView : public ui::AbstractTreeView {
+ /** The asset catalog tree this tree-view represents. */
+ bke::AssetCatalogTree *catalog_tree_;
+ FileAssetSelectParams *params_;
+
+ friend class AssetCatalogTreeViewItem;
+
+ public:
+ AssetCatalogTreeView(::AssetLibrary *library, FileAssetSelectParams *params);
+
+ void build_tree() override;
+
+ private:
+ ui::BasicTreeViewItem &build_catalog_items_recursive(ui::TreeViewItemContainer &view_parent_item,
+ AssetCatalogTreeItem &catalog);
+
+ void add_all_item();
+ void add_unassigned_item();
+ bool is_active_catalog(CatalogID catalog_id) const;
+};
+/* ---------------------------------------------------------------------- */
+
+class AssetCatalogTreeViewItem : public ui::BasicTreeViewItem {
+ /** The catalog tree item this tree view item represents. */
+ AssetCatalogTreeItem &catalog_item_;
+
+ public:
+ AssetCatalogTreeViewItem(AssetCatalogTreeItem *catalog_item)
+ : BasicTreeViewItem(catalog_item->get_name()), catalog_item_(*catalog_item)
+ {
+ }
+
+ void on_activate() override
+ {
+ const AssetCatalogTreeView &tree_view = static_cast<const AssetCatalogTreeView &>(
+ get_tree_view());
+ tree_view.params_->asset_catalog_visibility = FILE_SHOW_ASSETS_FROM_CATALOG;
+ tree_view.params_->catalog_id = catalog_item_.get_catalog_id();
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
+ }
+
+ void build_row(uiLayout &row) override
+ {
+ ui::BasicTreeViewItem::build_row(row);
+
+ if (!is_active()) {
+ return;
+ }
+
+ PointerRNA *props;
+ const CatalogID catalog_id = catalog_item_.get_catalog_id();
+
+ props = UI_but_extra_operator_icon_add(
+ button(), "ASSET_OT_catalog_new", WM_OP_INVOKE_DEFAULT, ICON_ADD);
+ RNA_string_set(props, "parent_path", catalog_item_.catalog_path().c_str());
+
+ /* Tree items without a catalog ID represent components of catalog paths that are not
+ * associated with an actual catalog. They exist merely by the presence of a child catalog, and
+ * thus cannot be deleted themselves. */
+ if (!BLI_uuid_is_nil(catalog_id)) {
+ char catalog_id_str_buffer[UUID_STRING_LEN] = "";
+ BLI_uuid_format(catalog_id_str_buffer, catalog_id);
+
+ props = UI_but_extra_operator_icon_add(
+ button(), "ASSET_OT_catalog_delete", WM_OP_INVOKE_DEFAULT, ICON_X);
+ RNA_string_set(props, "catalog_id", catalog_id_str_buffer);
+ }
+ }
+};
+
+/** Only reason this isn't just `BasicTreeViewItem` is to add a '+' icon for adding a root level
+ * catalog. */
+class AssetCatalogTreeViewAllItem : public ui::BasicTreeViewItem {
+ using BasicTreeViewItem::BasicTreeViewItem;
+
+ void build_row(uiLayout &row) override
+ {
+ ui::BasicTreeViewItem::build_row(row);
+
+ if (!is_active()) {
+ return;
+ }
+
+ PointerRNA *props;
+ props = UI_but_extra_operator_icon_add(
+ button(), "ASSET_OT_catalog_new", WM_OP_INVOKE_DEFAULT, ICON_ADD);
+ /* No parent path to use the root level. */
+ RNA_string_set(props, "parent_path", nullptr);
+ }
+};
+
+AssetCatalogTreeView::AssetCatalogTreeView(::AssetLibrary *library, FileAssetSelectParams *params)
+ : catalog_tree_(BKE_asset_library_get_catalog_tree(library)), params_(params)
+{
+}
+
+void AssetCatalogTreeView::build_tree()
+{
+ add_all_item();
+
+ if (catalog_tree_) {
+ catalog_tree_->foreach_root_item([this](AssetCatalogTreeItem &item) {
+ ui::BasicTreeViewItem &child_view_item = build_catalog_items_recursive(*this, item);
+
+ /* Open root-level items by default. */
+ child_view_item.set_collapsed(false);
+ });
+ }
+
+ add_unassigned_item();
+}
+
+ui::BasicTreeViewItem &AssetCatalogTreeView::build_catalog_items_recursive(
+ ui::TreeViewItemContainer &view_parent_item, AssetCatalogTreeItem &catalog)
+{
+ ui::BasicTreeViewItem &view_item = view_parent_item.add_tree_item<AssetCatalogTreeViewItem>(
+ &catalog);
+ if (is_active_catalog(catalog.get_catalog_id())) {
+ view_item.set_active();
+ }
+
+ catalog.foreach_child([&view_item, this](AssetCatalogTreeItem &child) {
+ build_catalog_items_recursive(view_item, child);
+ });
+ return view_item;
+}
+
+void AssetCatalogTreeView::add_all_item()
+{
+ FileAssetSelectParams *params = params_;
+
+ ui::AbstractTreeViewItem &item = add_tree_item<AssetCatalogTreeViewAllItem>(
+ IFACE_("All"), ICON_HOME, [params](ui::BasicTreeViewItem & /*item*/) {
+ params->asset_catalog_visibility = FILE_SHOW_ASSETS_ALL_CATALOGS;
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
+ });
+ if (params->asset_catalog_visibility == FILE_SHOW_ASSETS_ALL_CATALOGS) {
+ item.set_active();
+ }
+}
+
+void AssetCatalogTreeView::add_unassigned_item()
+{
+ FileAssetSelectParams *params = params_;
+
+ ui::AbstractTreeViewItem &item = add_tree_item<ui::BasicTreeViewItem>(
+ IFACE_("Unassigned"), ICON_FILE_HIDDEN, [params](ui::BasicTreeViewItem & /*item*/) {
+ params->asset_catalog_visibility = FILE_SHOW_ASSETS_WITHOUT_CATALOG;
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
+ });
+ if (params->asset_catalog_visibility == FILE_SHOW_ASSETS_WITHOUT_CATALOG) {
+ item.set_active();
+ }
+}
+
+bool AssetCatalogTreeView::is_active_catalog(CatalogID catalog_id) const
+{
+ return (params_->asset_catalog_visibility == FILE_SHOW_ASSETS_FROM_CATALOG) &&
+ (params_->catalog_id == catalog_id);
+}
+
+} // namespace blender::ed::asset_browser
+
+/* ---------------------------------------------------------------------- */
+
+void file_create_asset_catalog_tree_view_in_layout(::AssetLibrary *asset_library,
+ uiLayout *layout,
+ FileAssetSelectParams *params)
+{
+ uiBlock *block = uiLayoutGetBlock(layout);
+
+ ui::AbstractTreeView *tree_view = UI_block_add_view(
+ *block,
+ "asset catalog tree view",
+ std::make_unique<ed::asset_browser::AssetCatalogTreeView>(asset_library, params));
+
+ 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 65e0ad94c72..d39aefff691 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -31,8 +31,11 @@ extern "C" {
struct ARegion;
struct ARegionType;
+struct AssetLibrary;
struct FileSelectParams;
+struct FileAssetSelectParams;
struct SpaceFile;
+struct uiLayout;
struct View2D;
/* file_draw.c */
@@ -151,12 +154,19 @@ void file_on_reload_callback_register(struct SpaceFile *sfile,
/* file_panels.c */
void file_tool_props_region_panels_register(struct ARegionType *art);
void file_execute_region_panels_register(struct ARegionType *art);
+void file_tools_region_panels_register(struct ARegionType *art);
/* file_utils.c */
void file_tile_boundbox(const ARegion *region, FileLayout *layout, const int file, rcti *r_bounds);
void file_path_to_ui_path(const char *path, char *r_pathi, int max_size);
+/* asset_catalog_tree_view.cc */
+
+void file_create_asset_catalog_tree_view_in_layout(struct AssetLibrary *asset_library,
+ struct uiLayout *layout,
+ struct FileAssetSelectParams *params);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index 7032d55b331..95aad202f1a 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -47,6 +47,7 @@
#include "WM_types.h"
#include "file_intern.h"
+#include "filelist.h"
#include "fsmenu.h"
#include <string.h>
@@ -57,6 +58,12 @@ static bool file_panel_operator_poll(const bContext *C, PanelType *UNUSED(pt))
return (sfile && sfile->op);
}
+static bool file_panel_asset_browsing_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ return sfile && sfile->files && ED_fileselect_is_asset_browser(sfile);
+}
+
static void file_panel_operator_header(const bContext *C, Panel *panel)
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -222,3 +229,28 @@ void file_execute_region_panels_register(ARegionType *art)
pt->draw = file_panel_execution_buttons_draw;
BLI_addtail(&art->paneltypes, pt);
}
+
+static void file_panel_asset_catalog_buttons_draw(const bContext *C, Panel *panel)
+{
+ SpaceFile *sfile = CTX_wm_space_file(C);
+ /* May be null if the library wasn't loaded yet. */
+ struct AssetLibrary *asset_library = filelist_asset_library(sfile->files);
+ 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);
+}
+
+void file_tools_region_panels_register(ARegionType *art)
+{
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype file asset catalog buttons");
+ strcpy(pt->idname, "FILE_PT_asset_catalog_buttons");
+ strcpy(pt->label, N_("Asset Catalogs"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->flag = PANEL_TYPE_NO_HEADER;
+ pt->poll = file_panel_asset_browsing_poll;
+ pt->draw = file_panel_asset_catalog_buttons_draw;
+ BLI_addtail(&art->paneltypes, pt);
+}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 60fe5364aba..91178b85823 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -50,6 +50,7 @@
#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_uuid.h"
#ifdef WIN32
# include "BLI_winstuff.h"
@@ -369,6 +370,9 @@ typedef struct FileListFilter {
char filter_glob[FILE_MAXFILE];
char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
short flags;
+
+ eFileSel_Params_AssetCatalogVisibility asset_catalog_visibility;
+ bUUID asset_catalog_id;
} FileListFilter;
/* FileListFilter.flags */
@@ -806,6 +810,22 @@ static bool is_filtered_hidden(const char *filename,
return true;
}
+ /* TODO Make catalog activation work properly with the "Current File" asset library. Currently
+ * this will only work for external asset data. */
+ if (file->imported_asset_data) {
+ switch (filter->asset_catalog_visibility) {
+ case FILE_SHOW_ASSETS_WITHOUT_CATALOG:
+ return !BLI_uuid_is_nil(file->imported_asset_data->catalog_id);
+ case FILE_SHOW_ASSETS_FROM_CATALOG:
+ /* TODO show all assets that are in child catalogs of the selected catalog. */
+ return BLI_uuid_is_nil(filter->asset_catalog_id) ||
+ !BLI_uuid_equal(filter->asset_catalog_id, file->imported_asset_data->catalog_id);
+ case FILE_SHOW_ASSETS_ALL_CATALOGS:
+ /* All asset files should be visible. */
+ break;
+ }
+ }
+
return false;
}
@@ -1038,6 +1058,33 @@ void filelist_setfilter_options(FileList *filelist,
}
/**
+ * \param catalog_id: The catalog that should be filtered by if \a catalog_visibility is
+ * #FILE_SHOW_ASSETS_FROM_CATALOG. May be NULL otherwise.
+ */
+void filelist_set_asset_catalog_filter_options(
+ FileList *filelist,
+ eFileSel_Params_AssetCatalogVisibility catalog_visibility,
+ const bUUID *catalog_id)
+{
+ bool update = false;
+
+ if (filelist->filter_data.asset_catalog_visibility != catalog_visibility) {
+ filelist->filter_data.asset_catalog_visibility = catalog_visibility;
+ update = true;
+ }
+
+ if (filelist->filter_data.asset_catalog_visibility == FILE_SHOW_ASSETS_FROM_CATALOG &&
+ catalog_id && !BLI_uuid_equal(filelist->filter_data.asset_catalog_id, *catalog_id)) {
+ filelist->filter_data.asset_catalog_id = *catalog_id;
+ update = true;
+ }
+
+ if (update) {
+ filelist_filter_clear(filelist);
+ }
+}
+
+/**
* Checks two libraries for equality.
* \return True if the libraries match.
*/
@@ -1809,6 +1856,11 @@ void filelist_free(struct FileList *filelist)
filelist->flags &= ~(FL_NEED_SORTING | FL_NEED_FILTERING);
}
+AssetLibrary *filelist_asset_library(FileList *filelist)
+{
+ return filelist->asset_library;
+}
+
void filelist_freelib(struct FileList *filelist)
{
if (filelist->libfiledata) {
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index b51ceee4aa0..d1f37b5b365 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -31,6 +31,7 @@ struct AssetLibraryReference;
struct BlendHandle;
struct FileList;
struct FileSelection;
+struct bUUID;
struct wmWindowManager;
struct FileDirEntry;
@@ -71,6 +72,10 @@ void filelist_setfilter_options(struct FileList *filelist,
const bool filter_assets_only,
const char *filter_glob,
const char *filter_search);
+void filelist_set_asset_catalog_filter_options(
+ struct FileList *filelist,
+ eFileSel_Params_AssetCatalogVisibility catalog_visibility,
+ const struct bUUID *catalog_id);
void filelist_filter(struct FileList *filelist);
void filelist_setlibrary(struct FileList *filelist,
const struct AssetLibraryReference *asset_library_ref);
@@ -144,6 +149,8 @@ void filelist_entry_parent_select_set(struct FileList *filelist,
void filelist_setrecursion(struct FileList *filelist, const int recursion_level);
+struct AssetLibrary *filelist_asset_library(struct FileList *filelist);
+
struct BlendHandle *filelist_lib(struct FileList *filelist);
bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group);
void filelist_freelib(struct FileList *filelist);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 2ca08a3105c..83b33fe8aa9 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -126,13 +126,10 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile)
FileSelectParams *base_params = &asset_params->base_params;
base_params->file[0] = '\0';
base_params->filter_glob[0] = '\0';
- /* TODO: this way of using filters to form categories is notably slower than specifying a
- * "group" to read. That's because all types are read and filtering is applied afterwards. Would
- * be nice if we could lazy-read individual groups. */
base_params->flag |= U_default.file_space_data.flag | FILE_ASSETS_ONLY | FILE_FILTER;
base_params->flag &= ~FILE_DIRSEL_ONLY;
base_params->filter |= FILE_TYPE_BLENDERLIB;
- base_params->filter_id = FILTER_ID_OB | FILTER_ID_GR;
+ base_params->filter_id = FILTER_ID_ALL;
base_params->display = FILE_IMGDISPLAY;
base_params->sort = FILE_SORT_ALPHA;
/* Asset libraries include all sub-directories, so enable maximal recursion. */
@@ -462,6 +459,15 @@ bool ED_fileselect_is_asset_browser(const SpaceFile *sfile)
return (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS);
}
+struct AssetLibrary *ED_fileselect_active_asset_library_get(const SpaceFile *sfile)
+{
+ if (!ED_fileselect_is_asset_browser(sfile) || !sfile->files) {
+ return NULL;
+ }
+
+ return filelist_asset_library(sfile->files);
+}
+
struct ID *ED_fileselect_active_asset_get(const SpaceFile *sfile)
{
if (!ED_fileselect_is_asset_browser(sfile)) {
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index ac23767f933..a563f24e24e 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -335,9 +335,9 @@ static void file_refresh(const bContext *C, ScrArea *area)
params->highlight_file = -1; /* added this so it opens nicer (ton) */
}
- if (!U.experimental.use_extended_asset_browser && ED_fileselect_is_asset_browser(sfile)) {
+ if (ED_fileselect_is_asset_browser(sfile)) {
/* Only poses supported as non-experimental right now. */
- params->filter_id = FILTER_ID_AC;
+ params->filter_id = U.experimental.use_extended_asset_browser ? FILTER_ID_ALL : FILTER_ID_AC;
}
filelist_settype(sfile->files, params->type);
@@ -355,6 +355,10 @@ static void file_refresh(const bContext *C, ScrArea *area)
(params->flag & FILE_ASSETS_ONLY) != 0,
params->filter_glob,
params->filter_search);
+ if (asset_params) {
+ filelist_set_asset_catalog_filter_options(
+ sfile->files, asset_params->asset_catalog_visibility, &asset_params->catalog_id);
+ }
/* Update the active indices of bookmarks & co. */
sfile->systemnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM, params->dir);
@@ -1050,6 +1054,7 @@ void ED_spacetype_file(void)
art->init = file_tools_region_init;
art->draw = file_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
+ file_tools_region_panels_register(art);
/* regions: tool properties */
art = MEM_callocN(sizeof(ARegionType), "spacetype file operator region");