Asset Shelf: Add region poll mechanism for initialization #121315

Manually merged
Hans Goudey merged 1 commits from HooglyBoogly/blender:asset-shelf-on-region-poll into main 2024-05-02 16:33:58 +02:00
10 changed files with 76 additions and 25 deletions
Showing only changes of commit deddd92c3a - Show all commits

View File

@ -233,6 +233,12 @@ struct ARegionType {
/* return context data */
bContextDataCallback context;
/**
* Called on every frame in which the region's poll succeeds, regardless of visibility, before
* drawing, visibility evaluation and initialization. Allows the region to override visibility.
*/
void (*on_poll_success)(const bContext *C, ARegion *region);
/**
* Called whenever the user changes the region's size. Not called when the size is changed
* through other means, like to adjust for a scaled down window.
@ -516,6 +522,7 @@ enum AssetShelfTypeFlag {
/** Do not trigger asset dragging on drag events. Drag events can be overridden with custom
* keymap items then. */
ASSET_SHELF_TYPE_FLAG_NO_ASSET_DRAG = (1 << 0),
ASSET_SHELF_TYPE_FLAG_DEFAULT_VISIBLE = (1 << 1),
ASSET_SHELF_TYPE_FLAG_MAX
};

View File

@ -47,6 +47,7 @@ void region_on_user_resize(const ARegion *region);
void region_listen(const wmRegionListenerParams *params);
void region_layout(const bContext *C, ARegion *region);
void region_draw(const bContext *C, ARegion *region);
void region_on_poll_success(const bContext *C, ARegion *region);
void region_blend_read_data(BlendDataReader *reader, ARegion *region);
void region_blend_write(BlendWriter *writer, ARegion *region);
int region_prefsizey();

View File

@ -131,12 +131,15 @@ static void activate_shelf(RegionAssetShelf &shelf_regiondata, AssetShelf &shelf
*
* The returned shelf is guaranteed to have its #AssetShelf.type pointer set.
*
* \param on_create: Function called when a new asset shelf is created (case 3).
*
* \return A non-owning pointer to the now active shelf. Might be null if no shelf is valid in
* current context (all polls failed).
*/
static AssetShelf *update_active_shelf(const bContext &C,
const SpaceType &space_type,
RegionAssetShelf &shelf_regiondata)
RegionAssetShelf &shelf_regiondata,
FunctionRef<void(AssetShelf &new_shelf)> on_create)
{
/* Note: Don't access #AssetShelf.type directly, use #type_ensure(). */
@ -170,6 +173,9 @@ static AssetShelf *update_active_shelf(const bContext &C,
BLI_addhead(&shelf_regiondata.shelves, new_shelf);
/* Moves ownership to the regiondata. */
activate_shelf(shelf_regiondata, *new_shelf);
if (on_create) {
on_create(*new_shelf);
}
return new_shelf;
}
}
@ -260,13 +266,13 @@ void region_listen(const wmRegionListenerParams *params)
void region_init(wmWindowManager *wm, ARegion *region)
{
if (!region->regiondata) {
region->regiondata = MEM_cnew<RegionAssetShelf>("RegionAssetShelf");
}
RegionAssetShelf &shelf_regiondata = *RegionAssetShelf::get_from_asset_shelf_region(*region);
/* Region-data should've been created by a previously called #region_before_redraw(). */
RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
BLI_assert_msg(
shelf_regiondata,
"Region-data should've been created by a previously called `region_before_redraw()`.");
/* Active shelf is only set on draw, so this may be null! */
AssetShelf *active_shelf = shelf_regiondata.active_shelf;
AssetShelf *active_shelf = shelf_regiondata->active_shelf;
UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_PANELS_UI, region->winx, region->winy);
@ -410,17 +416,12 @@ int region_prefsizey()
void region_layout(const bContext *C, ARegion *region)
{
const SpaceLink *space = CTX_wm_space_data(C);
SpaceType *space_type = BKE_spacetype_from_id(space->spacetype);
RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(*region);
if (!shelf_regiondata) {
/* Region-data should've been created by a previously called #region_init(). */
BLI_assert_unreachable();
return;
}
BLI_assert_msg(
shelf_regiondata,
"Region-data should've been created by a previously called `region_before_redraw()`.");
AssetShelf *active_shelf = update_active_shelf(*C, *space_type, *shelf_regiondata);
const AssetShelf *active_shelf = shelf_regiondata->active_shelf;
if (!active_shelf) {
return;
}
@ -472,6 +473,28 @@ void region_draw(const bContext *C, ARegion *region)
UI_view2d_scrollers_draw(&region->v2d, nullptr);
}
void region_on_poll_success(const bContext *C, ARegion *region)
{
RegionAssetShelf *shelf_regiondata = RegionAssetShelf::ensure_from_asset_shelf_region(*region);
if (!shelf_regiondata) {
BLI_assert_unreachable();
return;
}
ScrArea *area = CTX_wm_area(C);
update_active_shelf(
*C, *area->type, *shelf_regiondata, /*on_create=*/[&](AssetShelf &new_shelf) {
/* Update region visibility (`'DEFAULT_VISIBLE'` option). */
const int old_flag = region->flag;
SET_FLAG_FROM_TEST(region->flag,
(new_shelf.type->flag & ASSET_SHELF_TYPE_FLAG_DEFAULT_VISIBLE) == 0,
RGN_FLAG_HIDDEN);
if (old_flag != region->flag) {
ED_region_visibility_change_update(const_cast<bContext *>(C), area, region);
}
});
}
void header_region_listen(const wmRegionListenerParams *params)
{
asset_shelf_region_listen(params);
@ -486,15 +509,6 @@ void header_region_init(wmWindowManager * /*wm*/, ARegion *region)
void header_region(const bContext *C, ARegion *region)
{
const SpaceLink *space = CTX_wm_space_data(C);
SpaceType *space_type = BKE_spacetype_from_id(space->spacetype);
const ARegion *main_shelf_region = BKE_area_find_region_type(CTX_wm_area(C),
RGN_TYPE_ASSET_SHELF);
RegionAssetShelf *shelf_regiondata = RegionAssetShelf::get_from_asset_shelf_region(
*main_shelf_region);
update_active_shelf(*C, *space_type, *shelf_regiondata);
ED_region_header_with_button_sections(C, region, uiButtonSectionsAlign::Bottom);
}

View File

@ -25,6 +25,19 @@ RegionAssetShelf *RegionAssetShelf::get_from_asset_shelf_region(const ARegion &r
return static_cast<RegionAssetShelf *>(region.regiondata);
}
RegionAssetShelf *RegionAssetShelf::ensure_from_asset_shelf_region(ARegion &region)
{
if (region.regiontype != RGN_TYPE_ASSET_SHELF) {
/* Should only be called on main asset shelf region. */
BLI_assert_unreachable();
return nullptr;
}
if (!region.regiondata) {
region.regiondata = MEM_cnew<RegionAssetShelf>("RegionAssetShelf");
}
return static_cast<RegionAssetShelf *>(region.regiondata);
}
namespace blender::ed::asset::shelf {
RegionAssetShelf *regiondata_duplicate(const RegionAssetShelf *shelf_regiondata)

View File

@ -2021,6 +2021,9 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar
area_azone_init(win, screen, area);
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->flag & RGN_FLAG_POLL_FAILED) {
continue;
}
region_evaulate_visibility(region);
/* region size may have changed, init does necessary adjustments */

View File

@ -755,6 +755,9 @@ static void screen_regions_poll(bContext *C, const wmWindow *win, bScreen *scree
if (region_poll(C, screen, area, region) == false) {
region->flag |= RGN_FLAG_POLL_FAILED;
}
else if (region->type && region->type->on_poll_success) {
region->type->on_poll_success(C, region);
}
if (old_region_flag != region->flag) {
any_changed = true;

View File

@ -1200,6 +1200,7 @@ void ED_spacetype_image()
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_ASSET_SHELF | ED_KEYMAP_FRAMES;
art->duplicate = asset::shelf::region_duplicate;
art->free = asset::shelf::region_free;
art->on_poll_success = asset::shelf::region_on_poll_success;
art->listener = asset::shelf::region_listen;
art->poll = asset::shelf::regions_poll;
art->snap_size = asset::shelf::region_snap;

View File

@ -2209,6 +2209,7 @@ void ED_spacetype_view3d()
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_ASSET_SHELF | ED_KEYMAP_FRAMES;
art->duplicate = asset::shelf::region_duplicate;
art->free = asset::shelf::region_free;
art->on_poll_success = asset::shelf::region_on_poll_success;
art->listener = asset::shelf::region_listen;
art->poll = asset::shelf::regions_poll;
art->snap_size = asset::shelf::region_snap;

View File

@ -855,6 +855,8 @@ typedef struct RegionAssetShelf {
AssetShelf *active_shelf; /* Non-owning. */
#ifdef __cplusplus
static RegionAssetShelf *get_from_asset_shelf_region(const ARegion &region);
/** Creates the asset shelf region data if necessary, and returns it. */
static RegionAssetShelf *ensure_from_asset_shelf_region(ARegion &region);
#endif
} RegionAssetShelf;

View File

@ -2261,6 +2261,12 @@ static void rna_def_asset_shelf(BlenderRNA *brna)
"No Asset Dragging",
"Disable the default asset dragging on drag events. Useful for implementing custom "
"dragging via custom key-map items"},
{ASSET_SHELF_TYPE_FLAG_DEFAULT_VISIBLE,
"DEFAULT_VISIBLE",
0,
"Visible by Default",
"Unhide the asset shelf when it's available for the first time, otherwise it will be "
"hidden"},
{0, nullptr, 0, nullptr, nullptr},
};