diff --git a/source/blender/blenkernel/BKE_screen.hh b/source/blender/blenkernel/BKE_screen.hh index 0200155d580..a178947a6c9 100644 --- a/source/blender/blenkernel/BKE_screen.hh +++ b/source/blender/blenkernel/BKE_screen.hh @@ -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 }; diff --git a/source/blender/editors/asset/ED_asset_shelf.hh b/source/blender/editors/asset/ED_asset_shelf.hh index cb08ad95d7b..10115c8011f 100644 --- a/source/blender/editors/asset/ED_asset_shelf.hh +++ b/source/blender/editors/asset/ED_asset_shelf.hh @@ -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(); diff --git a/source/blender/editors/asset/intern/asset_shelf.cc b/source/blender/editors/asset/intern/asset_shelf.cc index 86db72d3517..33f48a347ae 100644 --- a/source/blender/editors/asset/intern/asset_shelf.cc +++ b/source/blender/editors/asset/intern/asset_shelf.cc @@ -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 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 &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(®ion->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(®ion->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(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); } diff --git a/source/blender/editors/asset/intern/asset_shelf_regiondata.cc b/source/blender/editors/asset/intern/asset_shelf_regiondata.cc index 5cf411e73cd..e2c3b418a49 100644 --- a/source/blender/editors/asset/intern/asset_shelf_regiondata.cc +++ b/source/blender/editors/asset/intern/asset_shelf_regiondata.cc @@ -25,6 +25,19 @@ RegionAssetShelf *RegionAssetShelf::get_from_asset_shelf_region(const ARegion &r return static_cast(region.regiondata); } +RegionAssetShelf *RegionAssetShelf::ensure_from_asset_shelf_region(ARegion ®ion) +{ + 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"); + } + return static_cast(region.regiondata); +} + namespace blender::ed::asset::shelf { RegionAssetShelf *regiondata_duplicate(const RegionAssetShelf *shelf_regiondata) diff --git a/source/blender/editors/screen/area.cc b/source/blender/editors/screen/area.cc index d2992ee0fb4..09f4c2fb1d7 100644 --- a/source/blender/editors/screen/area.cc +++ b/source/blender/editors/screen/area.cc @@ -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 */ diff --git a/source/blender/editors/screen/screen_edit.cc b/source/blender/editors/screen/screen_edit.cc index 4c1b8af99df..90fb94cf634 100644 --- a/source/blender/editors/screen/screen_edit.cc +++ b/source/blender/editors/screen/screen_edit.cc @@ -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; diff --git a/source/blender/editors/space_image/space_image.cc b/source/blender/editors/space_image/space_image.cc index ecfaa592898..42aa7433a51 100644 --- a/source/blender/editors/space_image/space_image.cc +++ b/source/blender/editors/space_image/space_image.cc @@ -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; diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index c3a09b737d6..570b18fd7ee 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -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; diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 972f1a59b2d..32d32c7e7f4 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -855,6 +855,8 @@ typedef struct RegionAssetShelf { AssetShelf *active_shelf; /* Non-owning. */ #ifdef __cplusplus static RegionAssetShelf *get_from_asset_shelf_region(const ARegion ®ion); + /** Creates the asset shelf region data if necessary, and returns it. */ + static RegionAssetShelf *ensure_from_asset_shelf_region(ARegion ®ion); #endif } RegionAssetShelf; diff --git a/source/blender/makesrna/intern/rna_ui.cc b/source/blender/makesrna/intern/rna_ui.cc index b10048ec2aa..0f35e8cb3ac 100644 --- a/source/blender/makesrna/intern/rna_ui.cc +++ b/source/blender/makesrna/intern/rna_ui.cc @@ -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}, };