Asset Shelf: Add region poll mechanism for initialization

Allows running some action when the context changes to make the
asset shelf region visible. Also add an option for when whether the
shelf should be visible by default when the poll succeeds.

Pull Request: https://projects.blender.org/blender/blender/pulls/121315
This commit is contained in:
Julian Eisel
2024-05-02 10:27:55 -04:00
committed by Hans Goudey
parent 471378c666
commit d4fc167db1
10 changed files with 76 additions and 25 deletions

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},
};