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,
uiLayout *layout);
const AssetWeakReference *(*get_active_asset)(const AssetShelfType *shelf_type);
/* RNA integration */
ExtensionRNA rna_ext;
};

View File

@@ -251,6 +251,9 @@ static void asset_shelf_region_listen(const wmRegionListenerParams *params)
ED_region_tag_redraw(region);
}
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... */
if (CTX_data_equals(member, "active_file")) {
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) {
return CTX_RESULT_NO_DATA;
}

View File

@@ -39,6 +39,7 @@ namespace blender::ed::asset::shelf {
class AssetView : public ui::AbstractGridView {
const AssetLibraryReference library_ref_;
const AssetShelf &shelf_;
std::optional<AssetWeakReference> active_asset_;
/** Copy of the filter string from #AssetShelfSettings, with extra '*' added to the beginning and
* end of the string, for `fnmatch()` to work. */
char search_string[sizeof(AssetShelfSettings::search_string) + 2] = "";
@@ -69,6 +70,7 @@ class AssetViewItem : public ui::PreviewGridItem {
void disable_asset_drag();
void build_grid_tile(uiLayout &layout) 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;
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(
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()
@@ -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
{
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,
const int xy[2]);
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;
}
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 {

View File

@@ -1145,6 +1145,28 @@ static bool asset_shelf_poll(const bContext *C, const AssetShelfType *shelf_type
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,
const AssetShelfType *shelf_type,
const AssetRepresentationHandle *asset,
@@ -1214,7 +1236,7 @@ static StructRNA *rna_AssetShelf_register(Main *bmain,
dummy_shelf.type = shelf_type.get();
PointerRNA dummy_shelf_ptr = RNA_pointer_create(nullptr, &RNA_AssetShelf, &dummy_shelf);
bool have_function[3];
bool have_function[4];
/* validate the python class */
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->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;
@@ -2366,6 +2389,19 @@ static void rna_def_asset_shelf(BlenderRNA *brna)
parm = RNA_def_pointer(func, "asset", "AssetRepresentation", "", "");
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);
RNA_def_function_ui_description(
func, "Draw UI elements into the context menu UI layout displayed on right click");