window navigation improvements

This commit is contained in:
Eric 2024-09-24 16:05:55 -07:00
parent f6973bac7c
commit 4dc322f956
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
7 changed files with 194 additions and 121 deletions

56
.efrocachemap generated
View File

@ -4096,26 +4096,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "21a16533b62c491d0581609132c22dd5",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "fd60f24823b5fd2951acf06ad92d124b",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "87bba2b52609ee3ae31c2b1255218d93",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "bb123af5ef4bdede5248e4d0e086d623",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "78e44932b961f079ddf15fae69fed639",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "49210bd0982bf5eda8dd1074b0b26152",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "85fcee6b23abbf1c5a8e64fd95567b6e",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "6c881b22460cb58f93249bc9f7a95724",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "625390166d0eac624f14fc1688c638e7",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "66cfb48fb1975ca32a750754d16055eb",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b459b77672b95838742903e0afd1d9ae",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "f17dd55c15904f515e53fc676658194f",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "b1a493c944b9e60a80482e0097699695",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "018ca530ee4e8eaf78c2ea50059f2da4",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "83ef6001e1ef561a33207c396a7dc8b0",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "a00d2cff684ae4df75e52159ead85824",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "775c7f67370eff8d333eda82a626531f",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "1fa9c1e758e790c263b45315b016fe11",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "8b9e532091efbf224cb410ebf66cfbcf",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "7fbbd61ecdcbb4a8e162b6045d2dcf53",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "4c5719f4c7ab007be49e25f7d1c2ebc3",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "f94530fb06665cc65da84a0998a8c34f",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "4565fe7bf5497a1e6f26791d370cbf36",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "861bb4628d6e98833f34cd7fe188ccb4",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "ef45f0ea1f16016366069670869a105b",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "ecb70cb07e1f2a971faa6932278e623e",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "80cad1c9c9d7e95bba8fca46a7ad71cb",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "a62d9dcfec465b4e8e9e7b516ce20d6c",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "53ea2045ee7324176fc41f2c92e34c83",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "a48f988081b53a8cef28978e2779ad53",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "ca6f9f14f49e9578c79d4e192bae2a23",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "b3189be75ff31435fbd0deebf4d05d86",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "37457582e66d96fd63583e64d3392521",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "1505da6f4c3b5a5b5987c485271f567f",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "540e2954f30c48148e1c4824f484ba42",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "bd41f4930a3c1b0dfe1eb992bd1bd2c4",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "d226791f74aa398fd07909ba69eb2a19",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "59f65a8cbcdf13fcb30aec30d053fa85",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "cefcdb5c49a4a3f848119a9159d832f7",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "ea787281130d9e3565dd49b7776fb3f0",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "ad908b297b41c2fdf13582e34c434245",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "086a2ce72497e44079ad6b747fc5439f",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "ad908b297b41c2fdf13582e34c434245",
@ -4132,14 +4132,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "d7a1d4deb51b0792d083737477e6833b",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "4c11b81a574aa9af593f54db4d998e61",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "d7a1d4deb51b0792d083737477e6833b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "564675e2f00a311387a6e621f3b67332",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "93395e2263f9ed10160dd8e80811be77",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "24445c70a851b691690803c87af33c81",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "cf286af8eb7762893ee935e08975eb60",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "33b5f0f70ad2d8775dee1fd810f319e5",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "74a2c3fa9e709ca034a106d56c3b3e36",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "8d97d249be1218c6277dc1de54e5c6b8",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "892e10ddcf3b8f1dd83e5d0303594273",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "d52d476f324fd3c0c1f99add058aa405",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "059bd84629b72597c692b3a6b6cf6aa9",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "8428089ffce127d5eedf8d9cbafa2ffa",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0d267d44801387189b44896d4b6027b3",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "114f954bc27541998dce635b25e3ec01",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "eb84b5585f44e853604fa059ac57f388",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "579d3f0ad1d0f79522408d6197413a88",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "85b61a46caa9ada867f0c643ff28b6cd",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d",

View File

@ -1,4 +1,4 @@
### 1.7.37 (build 22010, api 9, 2024-09-24)
### 1.7.37 (build 22011, api 9, 2024-09-24)
- Bumping api version to 9. As you'll see below, there's some UI changes that
will require a bit of work for any UI mods to adapt to. If your mods don't
touch UI stuff at all you can simply bump your api version and call it a day.
@ -101,6 +101,11 @@
- There is now a `ba*.app.classic.save_ui_state()` method that should be called
right before jumping into a game/replay/etc. This will save a state that will
automatically be restored the next time the main menu activity is entered.
- (build 22010) Added the concept of 'auxiliary' windows and used them to make
various window navigation more intuitive. Example: previously, if you were on
the co-op screen and pressed the trophy toolbar icon to see your league rank
and then pressed back, you would be taken back to the top level main menu. Now
it will take you back to the co-op screen.
### 1.7.36 (build 21944, api 8, 2024-07-26)
- Wired up Tokens, BombSquad's new purchasable currency. The first thing these

View File

@ -15,14 +15,16 @@ from babase import (
AppIntentDefault,
invoke_main_menu,
screenmessage,
in_main_menu,
# in_main_menu,
)
import _baclassic
if TYPE_CHECKING:
from typing import Callable
from babase import AppIntent
from bauiv1 import UIV1AppSubsystem, MainWindow
from bauiv1 import UIV1AppSubsystem, MainWindow, MainWindowState
class ClassicAppMode(AppMode):
@ -124,38 +126,6 @@ class ClassicAppMode(AppMode):
if not app.active:
invoke_main_menu()
def _jump_to_main_window(self, window: MainWindow) -> None:
"""Jump to a window with the main menu as its parent."""
from bauiv1lib.mainmenu import MainMenuWindow
from bauiv1lib.ingamemenu import InGameMenuWindow
ui = app.ui_v1
old_window = ui.get_main_window()
if isinstance(old_window, (MainMenuWindow, InGameMenuWindow)):
# If we're currently in the top level menu window, just push
# our mainwindow on to the end.
old_window.main_window_replace(window)
else:
# Blow away the window stack and build a fresh one.
ui.clear_main_window()
back_state = (
MainMenuWindow.do_get_main_window_state()
if in_main_menu()
else InGameMenuWindow.do_get_main_window_state()
)
# set_main_window() needs this to be set.
back_state.is_top_level = True
ui.set_main_window(
window,
from_window=False, # Disable from-check.
back_state=back_state,
suppress_warning=True,
)
def _root_ui_menu_press(self) -> None:
from babase import push_back_press
@ -173,18 +143,11 @@ class ClassicAppMode(AppMode):
import bauiv1
from bauiv1lib.account.settings import AccountSettingsWindow
ui = app.ui_v1
# If the window is already showing, back out of it.
current_main_window = ui.get_main_window()
if isinstance(current_main_window, AccountSettingsWindow):
current_main_window.main_window_back()
return
self._jump_to_main_window(
AccountSettingsWindow(
self._auxiliary_window_nav(
win_type=AccountSettingsWindow,
win_create_call=lambda: AccountSettingsWindow(
origin_widget=bauiv1.get_special_widget('account_button')
)
),
)
def _root_ui_squad_press(self) -> None:
@ -201,18 +164,100 @@ class ClassicAppMode(AppMode):
import bauiv1
from bauiv1lib.settings.allsettings import AllSettingsWindow
self._auxiliary_window_nav(
win_type=AllSettingsWindow,
win_create_call=lambda: AllSettingsWindow(
origin_widget=bauiv1.get_special_widget('settings_button')
),
)
def _auxiliary_window_nav(
self,
win_type: type[MainWindow],
win_create_call: Callable[[], MainWindow],
) -> None:
"""Navigate to or away from a particular type of Auxiliary window."""
# pylint: disable=unidiomatic-typecheck
ui = app.ui_v1
# If the window is already showing, back out of it.
current_main_window = ui.get_main_window()
if isinstance(current_main_window, AllSettingsWindow):
# Scan our ancestors for auxiliary states matching our type as
# well as auxiliary states in general.
aux_matching_state: MainWindowState | None = None
aux_state: MainWindowState | None = None
if current_main_window is None:
raise RuntimeError(
'Not currently handling no-top-level-window case.'
)
state = current_main_window.main_window_back_state
while state is not None:
assert state.window_type is not None
if state.is_auxiliary:
if state.window_type is win_type:
aux_matching_state = state
else:
aux_state = state
state = state.parent
# If there's an ancestor auxiliary window-state matching our
# type, back out past it (example: poking settings, navigating
# down a level or two, and then poking settings again should
# back out of settings).
if aux_matching_state is not None:
current_main_window.main_window_back_state = (
aux_matching_state.parent
)
current_main_window.main_window_back()
return
self._jump_to_main_window(
AllSettingsWindow(
origin_widget=bauiv1.get_special_widget('settings_button')
# If there's an ancestory auxiliary state *not* matching our
# type, crop the state and swap in our new auxiliary UI
# (example: poking settings, then poking account, then poking
# back should end up where things were before the settings
# poke).
if aux_state is not None:
# Blow away the window stack and build a fresh one.
ui.clear_main_window()
ui.set_main_window(
win_create_call(),
from_window=False, # Disable from-check.
back_state=aux_state.parent,
suppress_warning=True,
is_auxiliary=True,
)
return
# Ok, no auxiliary states found. Now if current window is auxiliary
# and the type matches, simply do a back.
if (
current_main_window.main_window_is_auxiliary
and type(current_main_window) is win_type
):
current_main_window.main_window_back()
return
# If current window is auxiliary but type doesn't match,
# swap it out for our new auxiliary UI.
if current_main_window.main_window_is_auxiliary:
ui.clear_main_window()
ui.set_main_window(
win_create_call(),
from_window=False, # Disable from-check.
back_state=current_main_window.main_window_back_state,
suppress_warning=True,
is_auxiliary=True,
)
return
# Ok, no existing auxiliary stuff was found period. Just
# navigate forward to this UI.
current_main_window.main_window_replace(
win_create_call(), is_auxiliary=True
)
def _root_ui_achievements_press(self) -> None:
@ -235,18 +280,11 @@ class ClassicAppMode(AppMode):
import bauiv1
from bauiv1lib.store.browser import StoreBrowserWindow
ui = app.ui_v1
# If the window is already showing, back out of it.
current_main_window = ui.get_main_window()
if isinstance(current_main_window, StoreBrowserWindow):
current_main_window.main_window_back()
return
self._jump_to_main_window(
StoreBrowserWindow(
self._auxiliary_window_nav(
win_type=StoreBrowserWindow,
win_create_call=lambda: StoreBrowserWindow(
origin_widget=bauiv1.get_special_widget('store_button')
)
),
)
def _root_ui_tickets_meter_press(self) -> None:
@ -270,25 +308,17 @@ class ClassicAppMode(AppMode):
from bauiv1lib.account import show_sign_in_prompt
from bauiv1lib.league.rankwindow import LeagueRankWindow
ui = app.ui_v1
# If the window is already showing, back out of it.
current_main_window = ui.get_main_window()
if isinstance(current_main_window, LeagueRankWindow):
current_main_window.main_window_back()
return
plus = bauiv1.app.plus
assert plus is not None
if plus.get_v1_account_state() != 'signed_in':
show_sign_in_prompt()
return
self._jump_to_main_window(
LeagueRankWindow(
self._auxiliary_window_nav(
win_type=LeagueRankWindow,
win_create_call=lambda: LeagueRankWindow(
origin_widget=bauiv1.get_special_widget('trophy_meter')
)
),
)
def _root_ui_level_meter_press(self) -> None:
@ -303,19 +333,25 @@ class ClassicAppMode(AppMode):
import bauiv1
from bauiv1lib.inventory import InventoryWindow
ui = app.ui_v1
# If the window is already showing, back out of it.
current_main_window = ui.get_main_window()
if isinstance(current_main_window, InventoryWindow):
current_main_window.main_window_back()
return
self._jump_to_main_window(
InventoryWindow(
self._auxiliary_window_nav(
win_type=InventoryWindow,
win_create_call=lambda: InventoryWindow(
origin_widget=bauiv1.get_special_widget('inventory_button')
)
),
)
# ui = app.ui_v1
# # If the window is already showing, back out of it.
# current_main_window = ui.get_main_window()
# if isinstance(current_main_window, InventoryWindow):
# current_main_window.main_window_back()
# return
# self._jump_to_auxiliary_window(
# InventoryWindow(
# origin_widget=bauiv1.get_special_widget('inventory_button')
# )
# )
def _root_ui_get_tokens_press(self) -> None:
import bauiv1

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 22010
TARGET_BALLISTICA_BUILD = 22011
TARGET_BALLISTICA_VERSION = '1.7.37'

View File

@ -181,8 +181,10 @@ class UIV1AppSubsystem(babase.AppSubsystem):
f' cannot use auto-back.'
)
# Valid states should have a value here.
# Valid states should have values here.
assert back_state.is_top_level is not None
assert back_state.is_auxiliary is not None
assert back_state.window_type is not None
backwin = back_state.create_window(transition='in_left')
@ -205,6 +207,7 @@ class UIV1AppSubsystem(babase.AppSubsystem):
from_window: bauiv1.MainWindow | None | bool = True,
is_back: bool = False,
is_top_level: bool = False,
is_auxiliary: bool = False,
back_state: MainWindowState | None = None,
suppress_warning: bool = False,
) -> None:
@ -214,6 +217,7 @@ class UIV1AppSubsystem(babase.AppSubsystem):
MainWindow methods main_window_replace() and main_window_back()
should be used when possible for navigation.
"""
# pylint: disable=too-many-locals
# pylint: disable=too-many-branches
# pylint: disable=too-many-statements
from bauiv1._uitypes import MainWindow
@ -254,9 +258,13 @@ class UIV1AppSubsystem(babase.AppSubsystem):
# If they passed a back-state, make sure it is fully filled out.
if back_state is not None:
if back_state.is_top_level is None:
if (
back_state.is_top_level is None
or back_state.is_auxiliary is None
or back_state.window_type is None
):
raise RuntimeError(
'back_state.is_top_level has not been set.'
'Provided back_state is incomplete.'
' Make sure to only pass fully-filled-out MainWindowStates.'
)
# If a top-level main-window is being set, complain if there already
@ -309,18 +317,24 @@ class UIV1AppSubsystem(babase.AppSubsystem):
logging.exception('Error checking from_window')
if is_back:
# is_top_level should never be True here (only applies forward).
# These values should only be passed for forward navigation.
assert not is_top_level
# Always should have back_state in this case.
assert not is_auxiliary
# Make sure back state is complete.
assert back_state is not None
assert back_state.is_top_level is not None
assert back_state.is_auxiliary is not None
assert back_state.window_type is type(window)
window.main_window_back_state = back_state.parent
window.main_window_is_top_level = back_state.is_top_level
window.main_window_is_auxiliary = back_state.is_auxiliary
else:
# Store if the window is top-level so we won't complain later if
# we go back from it and there's nowhere to go to.
window.main_window_is_top_level = is_top_level
window.main_window_is_auxiliary = is_auxiliary
# When navigating forward, generate a back-window-state from
# the outgoing window.
if is_top_level:
@ -386,6 +400,8 @@ class UIV1AppSubsystem(babase.AppSubsystem):
# Store some common window stuff on its state.
winstate.parent = window.main_window_back_state
winstate.is_top_level = window.main_window_is_top_level
winstate.is_auxiliary = window.main_window_is_auxiliary
winstate.window_type = type(window)
return winstate
@ -397,12 +413,15 @@ class UIV1AppSubsystem(babase.AppSubsystem):
# Valid states should have a value here.
assert state.is_top_level is not None
assert state.is_auxiliary is not None
assert state.window_type is not None
win = state.create_window(transition=None)
self.set_main_window(
win,
from_window=False, # disable check
is_top_level=state.is_top_level,
is_auxiliary=state.is_auxiliary,
back_state=state.parent,
suppress_warning=True,
)

View File

@ -65,6 +65,13 @@ class MainWindow(Window):
self.main_window_is_top_level: bool = False
# Windows can be flagged as auxiliary when not related to the
# main UI task at hand. UI code may choose to handle auxiliary
# windows in special ways, such as by implicitly replacing
# existing auxiliary windows with new ones instead of keeping
# old ones as back targets.
self.main_window_is_auxiliary: bool = False
self._main_window_transition = transition
self._main_window_origin_widget = origin_widget
super().__init__(root_widget, cleanupcheck)
@ -147,7 +154,10 @@ class MainWindow(Window):
self.main_window_close()
def main_window_replace(
self, new_window: MainWindow, back_state: MainWindowState | None = None
self,
new_window: MainWindow,
back_state: MainWindowState | None = None,
is_auxiliary: bool = False,
) -> None:
"""Replace ourself with a new MainWindow."""
@ -177,6 +187,7 @@ class MainWindow(Window):
new_window,
from_window=self,
back_state=back_state,
is_auxiliary=is_auxiliary,
suppress_warning=True,
)
@ -203,6 +214,8 @@ class MainWindowState:
# The window that back/cancel navigation should take us to.
self.parent: MainWindowState | None = None
self.is_top_level: bool | None = None
self.is_auxiliary: bool | None = None
self.window_type: type[MainWindow] | None = None
def create_window(
self,

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 22010;
const int kEngineBuildNumber = 22011;
const char* kEngineVersion = "1.7.37";
const int kEngineApiVersion = 9;