Asset Shelf: Add callback to get active asset

Add a function for asset shelves, `get_active_asset` in RNA, that
can be used to sync the active item of an asset shelf with an asset
reference elsewhere in Blender. In the brush asset system this is
used to retrieve the asset reference from the active `Paint` struct.

Pull Request: https://projects.blender.org/blender/blender/pulls/121405
This commit is contained in:
Julian Eisel
2024-05-03 15:27:35 -04:00
committed by Hans Goudey
parent eccc24e4a6
commit a700c90ec3
6 changed files with 70 additions and 6 deletions

View File

@@ -555,6 +555,8 @@ struct AssetShelfType {
const blender::asset_system::AssetRepresentation *asset, const blender::asset_system::AssetRepresentation *asset,
uiLayout *layout); uiLayout *layout);
const AssetWeakReference *(*get_active_asset)(const AssetShelfType *shelf_type);
/* RNA integration */ /* RNA integration */
ExtensionRNA rna_ext; ExtensionRNA rna_ext;
}; };

View File

@@ -251,6 +251,9 @@ static void asset_shelf_region_listen(const wmRegionListenerParams *params)
ED_region_tag_redraw(region); ED_region_tag_redraw(region);
} }
break; break;
case NC_ASSET:
ED_region_tag_redraw(region);
break;
} }
} }
@@ -612,7 +615,7 @@ int context(const bContext *C, const char *member, bContextDataResult *result)
/* XXX hack. Get the asset from the active item, but needs to be the file... */ /* XXX hack. Get the asset from the active item, but needs to be the file... */
if (CTX_data_equals(member, "active_file")) { if (CTX_data_equals(member, "active_file")) {
const ARegion *region = CTX_wm_region(C); const ARegion *region = CTX_wm_region(C);
const uiBut *but = UI_region_views_find_active_item_but(region); const uiBut *but = UI_region_views_find_mouse_over_but(CTX_wm_window(C), region);
if (!but) { if (!but) {
return CTX_RESULT_NO_DATA; return CTX_RESULT_NO_DATA;
} }

View File

@@ -39,6 +39,7 @@ namespace blender::ed::asset::shelf {
class AssetView : public ui::AbstractGridView { class AssetView : public ui::AbstractGridView {
const AssetLibraryReference library_ref_; const AssetLibraryReference library_ref_;
const AssetShelf &shelf_; const AssetShelf &shelf_;
std::optional<AssetWeakReference> active_asset_;
/** Copy of the filter string from #AssetShelfSettings, with extra '*' added to the beginning and /** Copy of the filter string from #AssetShelfSettings, with extra '*' added to the beginning and
* end of the string, for `fnmatch()` to work. */ * end of the string, for `fnmatch()` to work. */
char search_string[sizeof(AssetShelfSettings::search_string) + 2] = ""; char search_string[sizeof(AssetShelfSettings::search_string) + 2] = "";
@@ -69,6 +70,7 @@ class AssetViewItem : public ui::PreviewGridItem {
void disable_asset_drag(); void disable_asset_drag();
void build_grid_tile(uiLayout &layout) const override; void build_grid_tile(uiLayout &layout) const override;
void build_context_menu(bContext &C, uiLayout &column) const override; void build_context_menu(bContext &C, uiLayout &column) const override;
std::optional<bool> should_be_active() const override;
bool is_filtered_visible() const override; bool is_filtered_visible() const override;
std::unique_ptr<ui::AbstractViewItemDragController> create_drag_controller() const override; std::unique_ptr<ui::AbstractViewItemDragController> create_drag_controller() const override;
@@ -91,6 +93,14 @@ AssetView::AssetView(const AssetLibraryReference &library_ref, const AssetShelf
BLI_strncpy_ensure_pad( BLI_strncpy_ensure_pad(
search_string, shelf.settings.search_string, '*', sizeof(search_string)); search_string, shelf.settings.search_string, '*', sizeof(search_string));
} }
if (shelf.type->get_active_asset) {
if (const AssetWeakReference *weak_ref = shelf.type->get_active_asset(shelf.type)) {
active_asset_ = *weak_ref;
}
else {
active_asset_.reset();
}
}
} }
void AssetView::build_items() void AssetView::build_items()
@@ -216,6 +226,19 @@ void AssetViewItem::build_context_menu(bContext &C, uiLayout &column) const
} }
} }
std::optional<bool> AssetViewItem::should_be_active() const
{
const AssetView &asset_view = dynamic_cast<const AssetView &>(this->get_view());
if (!asset_view.active_asset_) {
return false;
}
const asset_system::AssetRepresentation *asset = handle_get_representation(&asset_);
AssetWeakReference weak_ref = asset->make_weak_reference();
const bool matches = *asset_view.active_asset_ == weak_ref;
return matches;
}
bool AssetViewItem::is_filtered_visible() const bool AssetViewItem::is_filtered_visible() const
{ {
const AssetView &asset_view = dynamic_cast<const AssetView &>(this->get_view()); const AssetView &asset_view = dynamic_cast<const AssetView &>(this->get_view());

View File

@@ -3394,4 +3394,4 @@ blender::ui::AbstractView *UI_region_view_find_at(const ARegion *region, const i
blender::ui::AbstractViewItem *UI_region_views_find_item_at(const ARegion &region, blender::ui::AbstractViewItem *UI_region_views_find_item_at(const ARegion &region,
const int xy[2]); const int xy[2]);
blender::ui::AbstractViewItem *UI_region_views_find_active_item(const ARegion *region); blender::ui::AbstractViewItem *UI_region_views_find_active_item(const ARegion *region);
uiBut *UI_region_views_find_active_item_but(const ARegion *region); uiBut *UI_region_views_find_mouse_over_but(const wmWindow *win, const ARegion *region);

View File

@@ -201,9 +201,9 @@ ui::AbstractViewItem *UI_region_views_find_active_item(const ARegion *region)
return item_but->view_item; return item_but->view_item;
} }
uiBut *UI_region_views_find_active_item_but(const ARegion *region) uiBut *UI_region_views_find_mouse_over_but(const wmWindow *win, const ARegion *region)
{ {
return ui_view_item_find_active(region); return ui_view_item_find_mouse_over(region, win->eventstate->xy);
} }
namespace blender::ui { namespace blender::ui {

View File

@@ -1145,6 +1145,28 @@ static bool asset_shelf_poll(const bContext *C, const AssetShelfType *shelf_type
return is_visible; return is_visible;
} }
static const AssetWeakReference *asset_shelf_get_active_asset(const AssetShelfType *shelf_type)
{
extern FunctionRNA rna_AssetShelf_get_active_asset_func;
PointerRNA ptr = RNA_pointer_create(nullptr, shelf_type->rna_ext.srna, nullptr); /* dummy */
FunctionRNA *func = &rna_AssetShelf_get_active_asset_func;
ParameterList list;
RNA_parameter_list_create(&list, &ptr, func);
shelf_type->rna_ext.call(nullptr, &ptr, func, &list);
void *ret;
RNA_parameter_get_lookup(&list, "asset_reference", &ret);
/* Get the value before freeing. */
AssetWeakReference *active_asset = *(AssetWeakReference **)ret;
RNA_parameter_list_free(&list);
return active_asset;
}
static void asset_shelf_draw_context_menu(const bContext *C, static void asset_shelf_draw_context_menu(const bContext *C,
const AssetShelfType *shelf_type, const AssetShelfType *shelf_type,
const AssetRepresentationHandle *asset, const AssetRepresentationHandle *asset,
@@ -1214,7 +1236,7 @@ static StructRNA *rna_AssetShelf_register(Main *bmain,
dummy_shelf.type = shelf_type.get(); dummy_shelf.type = shelf_type.get();
PointerRNA dummy_shelf_ptr = RNA_pointer_create(nullptr, &RNA_AssetShelf, &dummy_shelf); PointerRNA dummy_shelf_ptr = RNA_pointer_create(nullptr, &RNA_AssetShelf, &dummy_shelf);
bool have_function[3]; bool have_function[4];
/* validate the python class */ /* validate the python class */
if (validate(&dummy_shelf_ptr, data, have_function) != 0) { if (validate(&dummy_shelf_ptr, data, have_function) != 0) {
@@ -1267,7 +1289,8 @@ static StructRNA *rna_AssetShelf_register(Main *bmain,
shelf_type->poll = have_function[0] ? asset_shelf_poll : nullptr; shelf_type->poll = have_function[0] ? asset_shelf_poll : nullptr;
shelf_type->asset_poll = have_function[1] ? asset_shelf_asset_poll : nullptr; shelf_type->asset_poll = have_function[1] ? asset_shelf_asset_poll : nullptr;
shelf_type->draw_context_menu = have_function[2] ? asset_shelf_draw_context_menu : nullptr; shelf_type->get_active_asset = have_function[2] ? asset_shelf_get_active_asset : nullptr;
shelf_type->draw_context_menu = have_function[3] ? asset_shelf_draw_context_menu : nullptr;
StructRNA *srna = shelf_type->rna_ext.srna; StructRNA *srna = shelf_type->rna_ext.srna;
@@ -2366,6 +2389,19 @@ static void rna_def_asset_shelf(BlenderRNA *brna)
parm = RNA_def_pointer(func, "asset", "AssetRepresentation", "", ""); parm = RNA_def_pointer(func, "asset", "AssetRepresentation", "", "");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED); RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
func = RNA_def_function(srna, "get_active_asset", nullptr);
RNA_def_function_ui_description(
func,
"Return a reference to the asset that should be highlighted as active in the asset shelf");
RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
/* return type */
parm = RNA_def_pointer(func,
"asset_reference",
"AssetWeakReference",
"",
"The weak reference to the asset to be hightlighted as active, or None");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "draw_context_menu", nullptr); func = RNA_def_function(srna, "draw_context_menu", nullptr);
RNA_def_function_ui_description( RNA_def_function_ui_description(
func, "Draw UI elements into the context menu UI layout displayed on right click"); func, "Draw UI elements into the context menu UI layout displayed on right click");