WIP: Rewrite asset browser as separate editor #107576

Draft
Julian Eisel wants to merge 95 commits from asset-browser-frontend-split into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
12 changed files with 242 additions and 51 deletions
Showing only changes of commit 29fdd43605 - Show all commits

View File

@ -207,9 +207,7 @@ void AssetList::fetch(const bContext &C)
void AssetList::setCatalogFilterSettings(const AssetCatalogFilterSettings &settings)
{
filelist_set_asset_catalog_filter_options(
filelist_,
(AssetCatalogFilterMode)settings.filter_mode,
&settings.active_catalog_id);
filelist_, (AssetCatalogFilterMode)settings.filter_mode, &settings.active_catalog_id);
}
bool AssetList::needsRefetch() const
@ -285,7 +283,11 @@ bool AssetList::listen(const wmNotifier &notifier) const
break;
}
case NC_ASSET:
if (ELEM(notifier.data, ND_ASSET_LIST, ND_ASSET_LIST_READING, ND_ASSET_LIST_PREVIEW)) {
if (ELEM(notifier.data, ND_ASSET_LIST)) {
filelist_tag_needs_filtering(filelist_);
return true;
}
if (ELEM(notifier.data, ND_ASSET_LIST_READING, ND_ASSET_LIST_PREVIEW)) {
return true;
}
if (ELEM(notifier.action, NA_ADDED, NA_REMOVED, NA_EDITED)) {

View File

@ -3215,6 +3215,10 @@ uiTreeViewItemHandle *UI_block_tree_view_find_item_at(const struct ARegion *regi
const int xy[2]) ATTR_NONNULL(1, 2);
uiTreeViewItemHandle *UI_block_tree_view_find_active_item(const struct ARegion *region);
/**
* Listen to \a notifier, returning true if the region should redraw.
*/
bool UI_tree_view_listen_should_redraw(const uiTreeViewHandle *view, const wmNotifier *notifier);
/**
* Listen to \a notifier, returning true if the region should redraw.
*/

View File

@ -42,6 +42,7 @@ struct uiButTreeRow;
struct uiLayout;
struct wmDrag;
struct wmEvent;
struct wmNotifier;
namespace blender::ui {
@ -142,6 +143,9 @@ class AbstractTreeView : public TreeViewItemContainer {
void foreach_item(ItemIterFn iter_fn, IterOptions options = IterOptions::None) const;
/** Listen to a notifier, returning true if a redraw is needed. */
virtual bool listen(const wmNotifier &) const;
/** Only one item can be renamed at a time. */
bool is_renaming() const;

View File

@ -101,12 +101,19 @@ void ui_block_free_views(uiBlock *block)
void UI_block_views_listen(const uiBlock *block, const wmRegionListenerParams *listener_params)
{
ARegion *region = listener_params->region;
LISTBASE_FOREACH (ViewLink *, view_link, &block->views) {
/* TODO only grid views, should this be supported by all views? */
if (AbstractGridView *grid_view = get_view_from_link<AbstractGridView>(*view_link)) {
if (UI_grid_view_listen_should_redraw(reinterpret_cast<uiGridViewHandle *>(grid_view),
listener_params->notifier)) {
ED_region_tag_redraw(listener_params->region);
ED_region_tag_redraw(region);
}
}
else if (AbstractTreeView *tree_view = get_view_from_link<AbstractTreeView>(*view_link)) {
if (UI_tree_view_listen_should_redraw(reinterpret_cast<uiTreeViewHandle *>(tree_view),
listener_params->notifier)) {
ED_region_tag_redraw(region);
}
}
}

View File

@ -82,6 +82,12 @@ void AbstractTreeView::foreach_item(ItemIterFn iter_fn, IterOptions options) con
foreach_item_recursive(iter_fn, options);
}
bool AbstractTreeView::listen(const wmNotifier &) const
{
/* Nothing by default. */
return false;
}
bool AbstractTreeView::is_renaming() const
{
return rename_buffer_ != nullptr;
@ -819,6 +825,13 @@ class TreeViewItemAPIWrapper {
using namespace blender::ui;
bool UI_tree_view_listen_should_redraw(const uiTreeViewHandle *view_handle,
const wmNotifier *notifier)
{
const AbstractTreeView &view = *reinterpret_cast<const AbstractTreeView *>(view_handle);
return view.listen(*notifier);
}
bool UI_tree_view_item_is_active(const uiTreeViewItemHandle *item_handle)
{
const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_handle);

View File

@ -26,13 +26,17 @@ struct ARegion;
struct ARegionType;
struct AssetLibrary;
struct bContext;
struct SpaceAssets;
struct PointerRNA;
struct PropertyRNA;
struct uiLayout;
struct wmMsgBus;
void asset_browser_main_region_draw(const bContext *C, ARegion *region);
void asset_browser_navigation_region_panels_register(ARegionType *art);
void asset_brower_create_catalog_tree_view_in_layout(::AssetLibrary *asset_library,
uiLayout *layout,
SpaceAssets *assets_space);
void asset_view_create_catalog_tree_view_in_layout(::AssetLibrary *asset_library,
uiLayout *layout,
PointerRNA *catalog_filter_owner_ptr,
PropertyRNA *catalog_filter_prop,
wmMsgBus *msg_bus);

View File

@ -74,7 +74,10 @@ static void assets_panel_asset_catalog_buttons_draw(const bContext *C, Panel *pa
uiItemS(col);
AssetLibrary *library = ED_assetlist_library_get(&assets_space->asset_library_ref);
asset_brower_create_catalog_tree_view_in_layout(library, col, assets_space);
PropertyRNA *catalog_filter_prop = RNA_struct_find_property(&assets_space_ptr, "catalog_filter");
asset_view_create_catalog_tree_view_in_layout(
library, col, &assets_space_ptr, catalog_filter_prop, CTX_wm_message_bus(C));
}
void asset_browser_navigation_region_panels_register(ARegionType *art)

View File

@ -42,6 +42,7 @@
#include "UI_tree_view.hh"
#include "WM_api.h"
#include "WM_message.h"
#include "WM_types.h"
#include "asset_browser_intern.hh"
@ -54,19 +55,29 @@ namespace blender::ed::asset_browser {
class AssetCatalogTreeViewAllItem;
class AssetCatalogTreeView : public ui::AbstractTreeView {
/** The asset library this catalog tree comes from. May be null when drawing the catalog tree
* before the library was read. */
::AssetLibrary *asset_library_;
/** The asset catalog tree this tree-view represents. */
bke::AssetCatalogTree *catalog_tree_;
AssetCatalogFilterSettings &catalog_filter_;
PointerRNA catalog_filter_owner_;
PropertyRNA &catalog_filter_prop_;
/** Used to notify the parts of the UI that display the filtered assets. */
wmMsgBus *msg_bus_;
friend class AssetCatalogTreeViewItem;
friend class AssetCatalogDropController;
friend class AssetCatalogTreeViewAllItem;
public:
AssetCatalogTreeView(::AssetLibrary *library, AssetCatalogFilterSettings *catalog_filter);
AssetCatalogTreeView(::AssetLibrary *library,
const PointerRNA &catalog_filter_owner,
PropertyRNA &catalog_filter_prop,
wmMsgBus *msg_bus);
void build_tree() override;
bool listen(const wmNotifier &notifier) const override;
void activate_catalog_by_id(CatalogID catalog_id);
@ -77,6 +88,11 @@ class AssetCatalogTreeView : public ui::AbstractTreeView {
AssetCatalogTreeViewAllItem &add_all_item();
void add_unassigned_item();
bool is_active_catalog(CatalogID catalog_id) const;
AssetCatalogFilterSettings &catalog_filter_settings() const;
void notify_catalog_filter_change();
void notify_catalog_tree_change();
void notify_catalog_assignments_change();
};
/* ---------------------------------------------------------------------- */
@ -129,7 +145,7 @@ class AssetCatalogDropController : public ui::AbstractTreeViewItemDropController
static AssetCatalog *get_drag_catalog(const wmDrag &drag, const ::AssetLibrary &asset_library);
static bool has_droppable_asset(const wmDrag &drag, const char **r_disabled_hint);
static bool drop_assets_into_catalog(struct bContext *C,
const AssetCatalogTreeView &tree_view,
AssetCatalogTreeView &tree_view,
const wmDrag &drag,
CatalogID catalog_id,
StringRefNull simple_name = "");
@ -181,14 +197,15 @@ class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
/* ---------------------------------------------------------------------- */
AssetCatalogTreeView::AssetCatalogTreeView(::AssetLibrary *library,
AssetCatalogFilterSettings *catalog_filter)
const PointerRNA &catalog_filter_owner,
PropertyRNA &catalog_filter_prop,
wmMsgBus *msg_bus)
: asset_library_(library),
catalog_tree_(BKE_asset_library_get_catalog_tree(library)),
catalog_filter_(*catalog_filter)
catalog_filter_owner_(catalog_filter_owner),
catalog_filter_prop_(catalog_filter_prop),
msg_bus_(msg_bus)
{
if (!catalog_filter) {
throw "Catalog filter should never be null";
}
}
void AssetCatalogTreeView::build_tree()
@ -224,12 +241,11 @@ AssetCatalogTreeViewAllItem &AssetCatalogTreeView::add_all_item()
{
AssetCatalogTreeViewAllItem &item = add_tree_item<AssetCatalogTreeViewAllItem>(IFACE_("All"));
item.set_on_activate_fn([this](ui::BasicTreeViewItem & /*item*/) {
catalog_filter_.filter_mode = ASSET_CATALOG_SHOW_ALL_ASSETS;
/* TODO */
// WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
catalog_filter_settings().filter_mode = ASSET_CATALOG_SHOW_ALL_ASSETS;
notify_catalog_filter_change();
});
item.set_is_active_fn(
[this]() { return catalog_filter_.filter_mode == ASSET_CATALOG_SHOW_ALL_ASSETS; });
[this]() { return catalog_filter_settings().filter_mode == ASSET_CATALOG_SHOW_ALL_ASSETS; });
return item;
}
@ -239,26 +255,64 @@ void AssetCatalogTreeView::add_unassigned_item()
IFACE_("Unassigned"), ICON_FILE_HIDDEN);
item.set_on_activate_fn([this](ui::BasicTreeViewItem & /*item*/) {
catalog_filter_.filter_mode = ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG;
/* TODO */
// WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
catalog_filter_settings().filter_mode = ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG;
notify_catalog_filter_change();
});
item.set_is_active_fn([this]() {
return catalog_filter_settings().filter_mode == ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG;
});
item.set_is_active_fn(
[this]() { return catalog_filter_.filter_mode == ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG; });
}
void AssetCatalogTreeView::activate_catalog_by_id(CatalogID catalog_id)
{
catalog_filter_.filter_mode = ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG;
catalog_filter_.active_catalog_id = catalog_id;
/* TODO */
// WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
AssetCatalogFilterSettings &catalog_filter = catalog_filter_settings();
catalog_filter.filter_mode = ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG;
catalog_filter.active_catalog_id = catalog_id;
notify_catalog_filter_change();
}
bool AssetCatalogTreeView::is_active_catalog(CatalogID catalog_id) const
{
return (catalog_filter_.filter_mode == ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG) &&
(catalog_filter_.active_catalog_id == catalog_id);
const AssetCatalogFilterSettings &catalog_filter = catalog_filter_settings();
return (catalog_filter.filter_mode == ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG) &&
(catalog_filter.active_catalog_id == catalog_id);
}
AssetCatalogFilterSettings &AssetCatalogTreeView::catalog_filter_settings() const
{
/* Copy so we can pass a non-const pointer to this to RNA functions. */
PointerRNA catalog_filter_owner = catalog_filter_owner_;
PointerRNA catalog_filter_ptr = RNA_property_pointer_get(&catalog_filter_owner,
&catalog_filter_prop_);
BLI_assert(catalog_filter_ptr.type == &RNA_AssetCatalogFilterSettings);
return *reinterpret_cast<AssetCatalogFilterSettings *>(catalog_filter_ptr.data);
}
bool AssetCatalogTreeView::listen(const wmNotifier &notifier) const
{
switch (notifier.category) {
case NC_ASSET:
if (ELEM(notifier.data, ND_ASSET_CATALOGS, ND_ASSET_LIST_READING)) {
return true;
}
}
return false;
}
void AssetCatalogTreeView::notify_catalog_filter_change()
{
WM_msg_publish_rna(msg_bus_, &catalog_filter_owner_, &catalog_filter_prop_);
}
void AssetCatalogTreeView::notify_catalog_tree_change()
{
WM_main_add_notifier(NC_ASSET | ND_ASSET_CATALOGS, nullptr);
}
void AssetCatalogTreeView::notify_catalog_assignments_change()
{
WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, nullptr);
}
/* ---------------------------------------------------------------------- */
@ -445,16 +499,16 @@ bool AssetCatalogDropController::drop_asset_catalog_into_catalog(
ED_asset_catalog_move(tree_view.asset_library_, catalog_drag->drag_catalog_id, drop_catalog_id);
tree_view.activate_catalog_by_id(catalog_drag->drag_catalog_id);
WM_main_add_notifier(NC_ASSET | ND_ASSET_CATALOGS, nullptr);
tree_view.notify_catalog_tree_change();
return true;
}
bool AssetCatalogDropController::drop_assets_into_catalog(
struct bContext *C,
const AssetCatalogTreeView &UNUSED(tree_view),
const wmDrag &drag,
CatalogID catalog_id,
StringRefNull simple_name)
bool AssetCatalogDropController::drop_assets_into_catalog(struct bContext *C,
AssetCatalogTreeView &tree_view,
const wmDrag &drag,
CatalogID catalog_id,
StringRefNull simple_name)
{
BLI_assert(drag.type == WM_DRAG_ASSET_LIST);
const ListBase *asset_drags = WM_drag_asset_list_get(&drag);
@ -478,10 +532,10 @@ bool AssetCatalogDropController::drop_assets_into_catalog(
// filelist_tag_needs_filtering(tree_view.space_file_.files);
// file_select_deselect_all(&tree_view.space_file_, FILE_SEL_SELECTED |
// FILE_SEL_HIGHLIGHTED);
// WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, nullptr);
}
if (did_update) {
tree_view.notify_catalog_assignments_change();
ED_undo_push(C, "Assign Asset Catalog");
}
return true;
@ -661,9 +715,11 @@ bool AssetCatalogTreeViewUnassignedItem::DropController::on_drop(struct bContext
/* ---------------------------------------------------------------------- */
void asset_brower_create_catalog_tree_view_in_layout(::AssetLibrary *asset_library,
uiLayout *layout,
SpaceAssets *assets_space)
void asset_view_create_catalog_tree_view_in_layout(::AssetLibrary *asset_library,
uiLayout *layout,
PointerRNA *catalog_filter_owner_ptr,
PropertyRNA *catalog_filter_prop,
wmMsgBus *msg_bus)
{
uiBlock *block = uiLayoutGetBlock(layout);
@ -672,8 +728,8 @@ void asset_brower_create_catalog_tree_view_in_layout(::AssetLibrary *asset_libra
ui::AbstractTreeView *tree_view = UI_block_add_view(
*block,
"asset catalog tree view",
std::make_unique<ed::asset_browser::AssetCatalogTreeView>(asset_library,
&assets_space->catalog_filter));
std::make_unique<ed::asset_browser::AssetCatalogTreeView>(
asset_library, *catalog_filter_owner_ptr, *catalog_filter_prop, msg_bus));
ui::TreeViewBuilder builder(*block);
builder.build_tree_view(*tree_view);

View File

@ -33,10 +33,14 @@
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "WM_message.h"
#include "asset_browser_intern.hh"
#include "asset_view.hh"
@ -116,6 +120,29 @@ static void asset_browser_main_region_listener(const wmRegionListenerParams *UNU
{
}
/* FIXME: See comment above #WM_msg_publish_rna_prop(). */
extern "C" {
static void asset_browser_main_region_message_subscribe(
const wmRegionMessageSubscribeParams *params)
{
struct wmMsgBus *mbus = params->message_bus;
bScreen *screen = params->screen;
SpaceAssets *assets_space = reinterpret_cast<SpaceAssets *>(params->area->spacedata.first);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
msg_sub_value_region_tag_redraw.owner = params->region;
msg_sub_value_region_tag_redraw.user_data = params->region;
msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
WM_msg_subscribe_rna_prop(mbus,
&screen->id,
assets_space,
SpaceAssets,
catalog_filter,
&msg_sub_value_region_tag_redraw);
}
}
/* ---------------------------------------------------------------------- */
/* Header Region */
@ -171,6 +198,7 @@ void ED_spacetype_assets(void)
art->init = asset_browser_main_region_init;
art->draw = asset_browser_main_region_draw;
art->listener = asset_browser_main_region_listener;
art->message_subscribe = asset_browser_main_region_message_subscribe;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
BLI_addhead(&st->regiontypes, art);

View File

@ -71,6 +71,7 @@ extern StructRNA RNA_ArrayGpencilModifier;
extern StructRNA RNA_ArrayModifier;
extern StructRNA RNA_Attribute;
extern StructRNA RNA_AttributeGroup;
extern StructRNA RNA_AssetCatalogFilterSettings;
extern StructRNA RNA_AssetHandle;
extern StructRNA RNA_AssetLibraryReference;
extern StructRNA RNA_AssetMetaData;

View File

@ -3277,6 +3277,17 @@ static void rna_SpaceAssets_asset_library_set(PointerRNA *ptr, int value)
asset_space->asset_library_ref = ED_asset_library_reference_from_enum_value(value);
}
static void rna_AssetCatalogFilterSettings_active_catalog_id_get(PointerRNA *ptr, char *value)
{
const AssetCatalogFilterSettings *settings = ptr->data;
BLI_uuid_format(value, settings->active_catalog_id);
}
static int rna_AssetCatalogFilterSettings_active_catalog_id_length(PointerRNA *UNUSED(ptr))
{
return UUID_STRING_LEN - 1;
}
#else
static const EnumPropertyItem dt_uv_items[] = {
@ -7987,21 +7998,77 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
}
static void rna_def_asset_catalog_filter_settings(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem asset_catalog_filter_mode[] = {
{ASSET_CATALOG_SHOW_ALL_ASSETS,
"SHOW_ALL_ASSETS",
ICON_NONE,
"All Assets",
"Show all assets, regardless of catalogs"},
{ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG,
"SHOW_ASSETS_FROM_CATALOG",
ICON_NONE,
"From Catalog",
"Show assets assigned to a specific catalog"},
{ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG,
"SHOW_ASSETS_WITHOUT_CATALOG",
ICON_NONE,
"Assets Without Catalog",
"Show any asset that doesn't have a recognized asset catalog assigned to it"},
{0, NULL, 0, NULL, NULL},
};
srna = RNA_def_struct(brna, "AssetCatalogFilterSettings", NULL);
RNA_def_struct_ui_text(
srna,
"Asset Catalog Filter Settings",
"Options to determine how catalogs should affect which assets are visible");
prop = RNA_def_property(srna, "filter_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, asset_catalog_filter_mode);
RNA_def_property_ui_text(prop,
"Asset Catalog Filter Mode",
"Determine how filtering based on asset catalogs should be done");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL);
prop = RNA_def_property(srna, "active_catalog_id", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop,
"rna_AssetCatalogFilterSettings_active_catalog_id_get",
"rna_AssetCatalogFilterSettings_active_catalog_id_length",
NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Catalog UUID", "The UUID of the catalog to show assets from");
}
static void rna_def_space_assets(BlenderRNA *brna)
{
PropertyRNA *prop;
StructRNA *srna;
rna_def_asset_catalog_filter_settings(brna);
srna = RNA_def_struct(brna, "SpaceAssets", "Space");
RNA_def_struct_ui_text(srna, "Space Asset Browser", "Asset browser space data");
// rna_def_space_generic_show_region_toggles(
// srna, (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_CHANNELS) | (1 << RGN_TYPE_FOOTER));
// rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_NAV_BAR));
prop = rna_def_asset_library_reference_common(
srna, "rna_SpaceAssets_asset_library_get", "rna_SpaceAssets_asset_library_set");
RNA_def_property_ui_text(prop, "Asset Library", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL);
prop = RNA_def_property(srna, "catalog_filter", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "AssetCatalogFilterSettings");
RNA_def_property_ui_text(prop,
"Asset Catalog Filter",
"Parameters to set up rules for filtering assets based on the catalogs "
"they are assigned to");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL);
}
void RNA_def_space(BlenderRNA *brna)

View File

@ -461,9 +461,11 @@ typedef struct wmNotifier {
#define ND_SPACE_SPREADSHEET (22 << 16)
/* NC_ASSET */
/* Denote that something in the contents of an AssetList may have changed. Triggers re-filtering of
* items. */
#define ND_ASSET_LIST (1 << 16)
/* Denotes that the AssetList is done reading some previews. NOT that the preview generation of
* assets is done. */
#define ND_ASSET_LIST (1 << 16)
#define ND_ASSET_LIST_PREVIEW (2 << 16)
#define ND_ASSET_LIST_READING (3 << 16)
/* Catalog data changed, requiring a redraw of catalog UIs. Note that this doesn't denote a