From 9b85768cd002b71ef80fa9f234286155e1fdbea7 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 3 Sep 2024 11:19:18 -0700 Subject: [PATCH 1/5] updated private party playlist selection for MainWindow system --- .efrocachemap | 56 ++++----- CHANGELOG.md | 2 +- config/requirements.txt | 4 +- .../ba_data/python/baclassic/_appsubsystem.py | 4 - src/assets/ba_data/python/baenv.py | 2 +- .../ba_data/python/bauiv1/_appsubsystem.py | 100 +++++----------- src/assets/ba_data/python/bauiv1/_uitypes.py | 63 +++++----- .../python/bauiv1lib/gather/__init__.py | 31 +++-- .../python/bauiv1lib/gather/privatetab.py | 21 +++- .../ba_data/python/bauiv1lib/mainmenu.py | 5 - src/assets/ba_data/python/bauiv1lib/play.py | 113 ++++++++++-------- .../python/bauiv1lib/playlist/browser.py | 45 ++++++- .../ba_data/python/bauiv1lib/playoptions.py | 39 +++--- .../python/bauiv1lib/soundtrack/edit.py | 3 +- .../bauiv1lib/soundtrack/entrytypeselect.py | 5 +- src/ballistica/shared/ballistica.cc | 2 +- 16 files changed, 252 insertions(+), 243 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index b5f38fa3..c57ef2ad 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -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": "d6246c930e7e2d2d9a6aff6788f33b69", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "001c67c4d4d33e20755399e0b2ed1593", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "6f6bfaf19daf6e866f4fecbc889b8854", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ebc7449903d7868c631c504aed10f371", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "91f03e7dbfc0d7eb75568704f681fba5", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0b32b6eb05df0a7e23e55ff2e7235a8f", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "4ed4b63cc506815f759412a295bfe088", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "1890731fb8a2fb43c4cde72af9d7a4e6", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "1a4764a504dcb20591ac3472c48db8d9", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "9bfd6234aac4ffd7d7601a40017a73be", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "941f8fb79d54522ca5df97a735c3babe", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "290a3d9840efc5e88532e13b76b3ae6b", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "621a6684b54b0a9101f808209bcca1ee", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "43c8b0b29e5fb257e4cde0f7fce1c680", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "9a30c6b88ffc11bdf6765780616d8ba1", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "8a8f63850fc296b060a994f4e001d74f", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "2864e9ae1d2d566def85f1cdf6e863fe", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "dc0db7ca99661a896634fc05187a5c75", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "f56bb0fafe0a45cecdcd06a10a6924c9", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e3a58b09fea193d78187f97cf922717d", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6f45d8d041a5c44d44e6da00ddd68983", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "fc5c2514f1773c91159fc8014e5f3e93", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a8679f4c2a071af5f024c04fb2de5685", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "2d32e5d05331df1b4b6923ee241b630b", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "8d9d7a041a1d3e56aec39682821927f6", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0d0405cb2e05629b0a23d6b8eca203ad", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "338528869c6fd8797b96cb875e3820cf", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "4428797051af1f7fde71fb638db52b17", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "c202858e8db64aebb88be04828ddfaa9", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "bd13e0e3edf0aac64609fb764921d7b1", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "f183757c9541262774adb1e0599f2001", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "85791e6585f4858517330e23834fc7b8", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "90b0d97ebaf7756824493b2fcee1e97e", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "955eef9f918e24c37e279db75ec6fca3", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b42ae8f5896f850e72fc4c30b2b8c52b", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "dda8f5a5099d9b695c9ab5a148f5ff10", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "8389b61cf60dd2f4ebad8b0e2c376605", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "cce612fb88788b32b303a956cd6fd6f5", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d54a451817bee9d4f8debd1fecf84ae9", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e41c4795f5b6f7dd0cf61286e62e91ac", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "fa659b5d6119acba6570c92ce4d35ae2", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", @@ -4132,14 +4132,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1659535e95e3047fda529543e265ac97", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "6b6aae30362b1e9aaf3f1a8daae0b0b4", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "25db08ee2b4c79ca631e517b622c741d", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "2ea419644782c4c52d1fa784d0ced86d", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "c40627a46ee127997153df041e47eda5", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "fff81b29e2d86031ec25c4a672a243e7", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "2a87e2f53c658d0be3918476cd8a04ee", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1e91536979b318b9a8325ab0e871ecec", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "c6506399a93ef93e8322425f78e2e6b0", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "ccc8a569891e0e5541706ca21aa91a3e", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "f39ae9be9fe75e16f45ea78f2bd3147a", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "5b1eb9ecc0eaaa22fb0b838479515deb", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "41977e7f7bbd1baa587661e9c0daee85", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "92451c795510652611fdac035839f0eb", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "6b3215ddfb8bb3ff8149b380f829806a", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1980c181a06f7355770d31499b7f9245", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "ce4592ab12f3954f62140365211c8eb4", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "cb299985623bbcc86015cb103a424ae6", "src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d", diff --git a/CHANGELOG.md b/CHANGELOG.md index 514fe060..9f9072a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.37 (build 21977, api 9, 2024-08-30) +### 1.7.37 (build 21978, api 9, 2024-09-03) - 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. diff --git a/config/requirements.txt b/config/requirements.txt index 95c86a2f..42cf3454 100644 --- a/config/requirements.txt +++ b/config/requirements.txt @@ -6,8 +6,8 @@ mypy==1.11.2 pbxproj==4.2.1 pdoc==14.6.1 pur==7.3.2 -pylint==3.2.6 -pylsp-mypy==0.6.8 +pylint==3.2.7 +pylsp-mypy==0.6.9 pytest==8.3.2 python-daemon==3.0.1 python-lsp-black==2.0.0 diff --git a/src/assets/ba_data/python/baclassic/_appsubsystem.py b/src/assets/ba_data/python/baclassic/_appsubsystem.py index 99559170..4fe3637c 100644 --- a/src/assets/ba_data/python/baclassic/_appsubsystem.py +++ b/src/assets/ba_data/python/baclassic/_appsubsystem.py @@ -112,10 +112,6 @@ class ClassicAppSubsystem(babase.AppSubsystem): self.invite_confirm_windows: list[Any] = [] # FIXME: Don't use Any. self.party_window: weakref.ref[PartyWindow] | None = None self.main_menu_resume_callbacks: list = [] - # Switch our overall game selection UI flow between Play and - # Private-party playlist selection modes; should do this in - # a more elegant way once we revamp high level UI stuff a bit. - self.selecting_private_party_playlist: bool = False # Store. self.store_layout: dict[str, list[dict[str, Any]]] | None = None diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index eb72351a..dbd337c6 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21977 +TARGET_BALLISTICA_BUILD = 21978 TARGET_BALLISTICA_VERSION = '1.7.37' diff --git a/src/assets/ba_data/python/bauiv1/_appsubsystem.py b/src/assets/ba_data/python/bauiv1/_appsubsystem.py index c58b44ba..d9fc8d41 100644 --- a/src/assets/ba_data/python/bauiv1/_appsubsystem.py +++ b/src/assets/ba_data/python/bauiv1/_appsubsystem.py @@ -68,7 +68,6 @@ class UIV1AppSubsystem(babase.AppSubsystem): # another MainWindow and we complain if they don't. self._main_window = empty_weakref(MainWindow) self._main_window_widget: bauiv1.Widget | None = None - self.main_window_group_id: str | None = None self.quit_window: bauiv1.Widget | None = None @@ -123,7 +122,6 @@ class UIV1AppSubsystem(babase.AppSubsystem): self.root_ui_calls.clear() self._main_window = empty_weakref(MainWindow) self._main_window_widget = None - self.main_window_group_id = None @property def uiscale(self) -> babase.UIScale: @@ -164,7 +162,7 @@ class UIV1AppSubsystem(babase.AppSubsystem): # FIXME: Can probably kill this if we do immediate UI death checks. self.upkeeptimer = babase.AppTimer(2.6543, ui_upkeep, repeat=True) - def do_main_window_back(self, window: MainWindow) -> None: + def do_main_window_back(self, from_window: MainWindow) -> None: """Sets the main menu window automatically from a parent WindowState.""" main_window = self._main_window() @@ -178,7 +176,7 @@ class UIV1AppSubsystem(babase.AppSubsystem): ) backwin = back_state.create_window(transition='in_left') backwin.main_window_back_state = back_state.parent - self.set_main_window(backwin, from_window=window, is_back=True) + self.set_main_window(backwin, from_window=from_window, is_back=True) def get_main_window(self) -> bauiv1.MainWindow | None: """Return main window, if any.""" @@ -189,30 +187,14 @@ class UIV1AppSubsystem(babase.AppSubsystem): window: bauiv1.MainWindow, from_window: bauiv1.MainWindow | None | bool = True, is_back: bool = False, - group_id: str | None = None, is_top_level: bool = False, back_state: MainWindowState | None = None, ) -> None: """Set the current 'main' window, replacing any existing. - If 'from_window' is passed as a bauiv1.Widget or bauiv1.Window - or None, a warning will be issued if it that value does not - match the current main window. This can help identify flawed - code that can lead to bad UI states. A value of False will - disable the check, which is necessary in some cases when the - current main window is not known. - - When navigating somewhere from a cancel or back-button, pass - is_back=True; this will prevent the new main window from itself - being registered as a new location on the stack that can be - returned to. - - If a 'group_id' string is provided and the window being replaced - has the same group-id, the WindowState stack is left unchanged, - effectively replacing the previous window with the new one in - the stack. This can be useful in cases where tab-bar-like UIs - allow flipping between sibling windows with the back button - always leading to a shared parent. + Generally this should not be called directly; The high level + 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 @@ -222,13 +204,24 @@ class UIV1AppSubsystem(babase.AppSubsystem): from_window_widget: bauiv1.Widget | None # We used to accept Widgets but now want MainWindows. - assert isinstance(window, MainWindow) + if not isinstance(window, MainWindow): + raise RuntimeError( + f'set_main_window() now takes a MainWindow as its "window" arg.' + f' You passed a {type(window)}.', + ) window_weakref = weakref.ref(window) window_widget = window.get_root_widget() if isinstance(from_window, MainWindow): from_window_widget = from_window.get_root_widget() else: + if from_window is not None and not isinstance(from_window, bool): + raise RuntimeError( + f'set_main_window() now takes a MainWindow or bool or None' + f'as its "from_window" arg.' + f' You passed a {type(from_window)}.', + ) + from_window_widget = None existing = self._main_window_widget @@ -317,13 +310,15 @@ class UIV1AppSubsystem(babase.AppSubsystem): else: # When navigating forward, generate a back-window-state from # the outgoing window. - - # Exception is when we were passed a group and it matches - # the existing group; in that case we just keep the existing - # back-state. - if group_id is not None and group_id == self.main_window_group_id: - assert not is_top_level - print(f'GOT GROUP ID MATCH {group_id}; KEEPING BACK STATE.') + if is_top_level: + # Top level windows don't have or expect anywhere to + # go back to. + # + # self._main_window_back_state = None + window.main_window_back_state = None + elif back_state is not None: + window.main_window_back_state = back_state + else: oldwin = self._main_window() if oldwin is None: # We currenty only hold weak refs to windows so @@ -332,48 +327,20 @@ class UIV1AppSubsystem(babase.AppSubsystem): # alive as long as its the main one. Holler if # that seems to not be happening. logging.warning( - 'set_main_window: no existing MainWindow found' - ' (and is_top_level is False); should not happen.' - ' a MainWindow should keep itself alive as long' - ' as it is main.' + 'set_main_window: No old MainWindow found' + ' and is_top_level is False;' + ' this should not happen.' ) window.main_window_back_state = None else: - window.main_window_back_state = ( - oldwin.main_window_back_state - ) - else: - if is_top_level: - # Top level windows don't have or expect anywhere to go - # back to. - # self._main_window_back_state = None - window.main_window_back_state = None - elif back_state is not None: - window.main_window_back_state = back_state - else: - oldwin = self._main_window() - if oldwin is None: - # We currenty only hold weak refs to windows so - # that they are free to die on their own, but we - # expect the main menu window to keep itself - # alive as long as its the main one. Holler if - # that seems to not be happening. - logging.warning( - 'set_main_window: No old MainWindow found' - ' and is_top_level is False;' - ' this should not happen.' - ) - window.main_window_back_state = None - else: - oldwinstate = oldwin.get_main_window_state() + oldwinstate = oldwin.get_main_window_state() - # Store our previous back state on this new one. - oldwinstate.parent = oldwin.main_window_back_state - window.main_window_back_state = oldwinstate + # Store our previous back state on this new one. + oldwinstate.parent = oldwin.main_window_back_state + window.main_window_back_state = oldwinstate self._main_window = window_weakref self._main_window_widget = window_widget - self.main_window_group_id = group_id def has_main_window(self) -> bool: """Return whether a main menu window is present.""" @@ -397,4 +364,3 @@ class UIV1AppSubsystem(babase.AppSubsystem): self._main_window = empty_weakref(MainWindow) self._main_window_widget = None - self.main_window_group_id = None diff --git a/src/assets/ba_data/python/bauiv1/_uitypes.py b/src/assets/ba_data/python/bauiv1/_uitypes.py index 496d32fc..2743bde3 100644 --- a/src/assets/ba_data/python/bauiv1/_uitypes.py +++ b/src/assets/ba_data/python/bauiv1/_uitypes.py @@ -60,7 +60,6 @@ class MainWindow(Window): Automatically handles in and out transitions on the provided widget, so there is no need to set transitions when creating it. """ - # TODO - move to MainWindow # A back-state supplied by the ui system. self.main_window_back_state: MainWindowState | None = None @@ -82,7 +81,7 @@ class MainWindow(Window): scale_origin_stack_offset=scale_origin, ) - def main_window_close(self) -> None: + def main_window_close(self, transition: str | None = None) -> None: """Get window transitioning out if still alive.""" # no-op if our underlying widget is dead or on its way out. @@ -96,16 +95,21 @@ class MainWindow(Window): logging.exception('Error in on_main_window_close() for %s.', self) _bauiv1.containerwidget( - edit=self._root_widget, transition=self._main_window_transition_out + edit=self._root_widget, + transition=( + self._main_window_transition_out + if transition is None + else transition + ), ) def main_window_has_control(self) -> bool: """Is this MainWindow allowed to change the global main window? It is a good idea to make sure this is True before calling - either main_window_back() or main_window_replace(). This - prevents fluke UI breakage such as multiple simultaneous events - causing a MainWindow to spawn multiple replacements for itself. + main_window_replace(). This prevents fluke UI breakage such as + multiple simultaneous events causing a MainWindow to spawn + multiple replacements for itself. """ # We are allowed to change main windows if we are the current one # AND our underlying widget is still alive and not transitioning out. @@ -116,48 +120,39 @@ class MainWindow(Window): ) def main_window_back(self) -> None: - """Move back in the main window stack.""" + """Move back in the main window stack. + + Is a no-op if the main window does not have control; + no need to check main_window_has_control() first. + """ # Users should always check main_window_has_control() before # calling us. Error if it seems they did not. if not self.main_window_has_control(): - raise RuntimeError( - 'main_window_back() should only be called' - ' if main_window_has_control() returns True' - ' (it currently is False).' - ) + return # Get the 'back' window coming in. babase.app.ui_v1.do_main_window_back(self) self.main_window_close() - def main_window_replace( - self, new_window: MainWindow, group_id: str | None = None - ) -> None: + def main_window_replace(self, new_window: MainWindow) -> None: """Replace ourself with a new MainWindow.""" - # Users should always check main_window_has_control() before - # creating new MainWindows and passing them in here. Error if it - # seems they did not. + # Users should always check main_window_has_control() *before* + # creating new MainWindows and passing them in here. Kill the + # passed window and Error if it seems they did not. if not self.main_window_has_control(): + new_window.get_root_widget().delete() raise RuntimeError( - 'main_window_replace() should only be called' - ' if main_window_has_control() returns True' - ' (it currently is False).' + f'main_window_replace() called on a not-in-control window' + f' ({self}); always check main_window_has_control() before' + f' calling main_window_replace().' ) - # If we're navigating within a group, we want it to look like we're - # backing out of the old one and going into the new one. - if ( - group_id is not None - and babase.app.ui_v1.main_window_group_id == group_id - ): - transition = self._main_window_transition_out - else: - # Otherwise just shove the old out the left to give the feel - # that we're adding to the nav stack. - transition = 'out_left' + # Just shove the old out the left to give the feel that we're + # adding to the nav stack. + transition = 'out_left' # Transition ourself out. try: @@ -166,9 +161,7 @@ class MainWindow(Window): logging.exception('Error in on_main_window_close() for %s.', self) _bauiv1.containerwidget(edit=self._root_widget, transition=transition) - babase.app.ui_v1.set_main_window( - new_window, from_window=self, group_id=group_id - ) + babase.app.ui_v1.set_main_window(new_window, from_window=self) def on_main_window_close(self) -> None: """Called before transitioning out a main window. diff --git a/src/assets/ba_data/python/bauiv1lib/gather/__init__.py b/src/assets/ba_data/python/bauiv1lib/gather/__init__.py index e71d2cc3..8d3c18f6 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/__init__.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/__init__.py @@ -7,11 +7,14 @@ from __future__ import annotations import weakref import logging from enum import Enum -from typing import override +from typing import override, TYPE_CHECKING from bauiv1lib.tabs import TabRow import bauiv1 as bui +if TYPE_CHECKING: + from bauiv1lib.play import PlaylistSelectContext + class GatherTab: """Defines a tab for use in the gather UI.""" @@ -264,23 +267,27 @@ class GatherWindow(bui.MainWindow): def on_main_window_close(self) -> None: self._save_state() - def playlist_select(self, origin_widget: bui.Widget) -> None: + def playlist_select( + self, + origin_widget: bui.Widget, + context: PlaylistSelectContext, + ) -> None: """Called by the private-hosting tab to select a playlist.""" from bauiv1lib.play import PlayWindow - classic = bui.app.classic - assert classic is not None - - # no-op if our underlying widget is dead or on its way out. - if not self._root_widget or self._root_widget.transitioning_out: + # Avoid redundant window spawns. + if not self.main_window_has_control(): return - self._save_state() - bui.containerwidget(edit=self._root_widget, transition='out_left') - classic.selecting_private_party_playlist = True - bui.app.ui_v1.set_main_window( - PlayWindow(origin_widget=origin_widget), from_window=self + playwindow = PlayWindow( + origin_widget=origin_widget, playlist_select_context=context ) + self.main_window_replace(playwindow) + + # Grab the newly-set main-window's back-state; that will lead us + # back here once we're done going down our main-window + # rabbit-hole for playlist selection. + context.back_state = playwindow.main_window_back_state def _set_tab(self, tab_id: TabID) -> None: if self._current_tab is tab_id: diff --git a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py index 6bdf4c6b..8681fa12 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py @@ -22,6 +22,7 @@ from bacommon.net import ( PrivatePartyConnectResult, ) from bauiv1lib.gather import GatherTab +from bauiv1lib.play import PlaylistSelectContext from bauiv1lib.gettokens import GetTokensWindow, show_get_tokens_prompt import bascenev1 as bs @@ -49,6 +50,7 @@ class State: """Our core state that persists while the app is running.""" sub_tab: SubTabType = SubTabType.JOIN + playlist_select_context: PlaylistSelectContext | None = None class PrivateGatherTab(GatherTab): @@ -685,12 +687,13 @@ class PrivateGatherTab(GatherTab): # If it appears we're coming back from playlist selection, # re-select our playlist button. - if classic.selecting_private_party_playlist: + if self._state.playlist_select_context is not None: + self._state.playlist_select_context = None bui.containerwidget( edit=self._container, selected_child=self._host_playlist_button, ) - classic.selecting_private_party_playlist = False + else: # We've got a current party; show its info. bui.textwidget( @@ -918,11 +921,17 @@ class PrivateGatherTab(GatherTab): ) def _playlist_press(self) -> None: - if bool(True): - bui.screenmessage('UNDER CONSTRUCTION') - return + # if bool(True): + # bui.screenmessage('UNDER CONSTRUCTION') + # return assert self._host_playlist_button is not None - self.window.playlist_select(origin_widget=self._host_playlist_button) + + self._state.playlist_select_context = PlaylistSelectContext() + + self.window.playlist_select( + origin_widget=self._host_playlist_button, + context=self._state.playlist_select_context, + ) def _host_copy_press(self) -> None: assert self._hostingstate.party_code is not None diff --git a/src/assets/ba_data/python/bauiv1lib/mainmenu.py b/src/assets/ba_data/python/bauiv1lib/mainmenu.py index f4904fbd..555ff8d0 100644 --- a/src/assets/ba_data/python/bauiv1lib/mainmenu.py +++ b/src/assets/ba_data/python/bauiv1lib/mainmenu.py @@ -505,7 +505,6 @@ class MainMenuWindow(bui.MainWindow): self.main_window_replace( CreditsWindow(origin_widget=self._credits_button), - # group_id='mainmenutop', ) def _howtoplay(self) -> None: @@ -607,8 +606,4 @@ class MainMenuWindow(bui.MainWindow): if not self.main_window_has_control(): return - classic = bui.app.classic - if classic is not None: - classic.selecting_private_party_playlist = False - self.main_window_replace(PlayWindow(origin_widget=self._play_button)) diff --git a/src/assets/ba_data/python/bauiv1lib/play.py b/src/assets/ba_data/python/bauiv1lib/play.py index 4bce5070..5548c67c 100644 --- a/src/assets/ba_data/python/bauiv1lib/play.py +++ b/src/assets/ba_data/python/bauiv1lib/play.py @@ -5,11 +5,20 @@ from __future__ import annotations import logging -from typing import override +from typing import override, TYPE_CHECKING import bascenev1 as bs import bauiv1 as bui +if TYPE_CHECKING: + from bauiv1 import MainWindowState + + +class PlaylistSelectContext: + """For using PlayWindow to select a playlist instead of running game.""" + + back_state: MainWindowState | None = None + class PlayWindow(bui.MainWindow): """Window for selecting overall play type.""" @@ -18,6 +27,7 @@ class PlayWindow(bui.MainWindow): self, transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, + playlist_select_context: PlaylistSelectContext | None = None, ): # pylint: disable=too-many-statements # pylint: disable=too-many-locals @@ -29,11 +39,7 @@ class PlayWindow(bui.MainWindow): classic = bui.app.classic assert classic is not None - # We can currently be used either for main window duty or - # modally for selecting playlists. Ideally we should clean - # things up and make playlist selection go through the - # main-window mechanism. - self._is_main_menu = not classic.selecting_private_party_playlist + self._playlist_select_context = playlist_select_context uiscale = bui.app.ui_v1.uiscale width = 1100 if uiscale is bui.UIScale.SMALL else 800 @@ -54,7 +60,11 @@ class PlayWindow(bui.MainWindow): super().__init__( root_widget=bui.containerwidget( size=(width, height), - toolbar_visibility='menu_full', + toolbar_visibility=( + 'menu_full' + if playlist_select_context is None + else 'menu_minimal' + ), scale=( 1.35 if uiscale is bui.UIScale.SMALL @@ -88,7 +98,7 @@ class PlayWindow(bui.MainWindow): text=bui.Lstr( resource=( (f'{self._r}.titleText') - if self._is_main_menu + if self._playlist_select_context is None else 'playlistsText' ) ), @@ -109,13 +119,17 @@ class PlayWindow(bui.MainWindow): if uiscale is bui.UIScale.SMALL: bui.textwidget(edit=txt, text='') - v = height - (110 if self._is_main_menu else 90) + v = height - (110 if self._playlist_select_context is None else 90) v -= 100 clr = (0.6, 0.7, 0.6, 1.0) - v -= 280 if self._is_main_menu else 180 + v -= 280 if self._playlist_select_context is None else 180 v += 30 if uiscale is bui.UIScale.SMALL else 0 - hoffs = x_offs + 80 if self._is_main_menu else x_offs - 100 - scl = 1.13 if self._is_main_menu else 0.68 + hoffs = ( + x_offs + 80 + if self._playlist_select_context is None + else x_offs - 100 + ) + scl = 1.13 if self._playlist_select_context is None else 0.68 self._lineup_tex = bui.gettexture('playerLineup') angry_computer_transparent_mesh = bui.getmesh( @@ -137,8 +151,8 @@ class PlayWindow(bui.MainWindow): self._coop_button: bui.Widget | None = None - # Only show coop button in main-menu variant. - if self._is_main_menu: + # Only show coop button in regular variant. + if self._playlist_select_context is None: self._coop_button = btn = bui.buttonwidget( parent=self._root_widget, position=(hoffs, v + (scl * 15)), @@ -238,16 +252,19 @@ class PlayWindow(bui.MainWindow): color=clr, ) - scl = 0.5 if self._is_main_menu else 0.68 - hoffs += 440 if self._is_main_menu else 216 - v += 180 if self._is_main_menu else -68 + scl = 0.5 if self._playlist_select_context is None else 0.68 + hoffs += 440 if self._playlist_select_context is None else 216 + v += 180 if self._playlist_select_context is None else -68 self._teams_button = btn = bui.buttonwidget( parent=self._root_widget, - position=(hoffs, v + (scl * 15 if self._is_main_menu else 0)), + position=( + hoffs, + v + (scl * 15 if self._playlist_select_context is None else 0), + ), size=( scl * button_width, - scl * (300 if self._is_main_menu else 360), + scl * (300 if self._playlist_select_context is None else 360), ), extra_touch_border_scale=0.1, autoselect=True, @@ -369,14 +386,17 @@ class PlayWindow(bui.MainWindow): color=clr, ) - hoffs += 0 if self._is_main_menu else 300 - v -= 155 if self._is_main_menu else 0 + hoffs += 0 if self._playlist_select_context is None else 300 + v -= 155 if self._playlist_select_context is None else 0 self._free_for_all_button = btn = bui.buttonwidget( parent=self._root_widget, - position=(hoffs, v + (scl * 15 if self._is_main_menu else 0)), + position=( + hoffs, + v + (scl * 15 if self._playlist_select_context is None else 0), + ), size=( scl * button_width, - scl * (300 if self._is_main_menu else 360), + scl * (300 if self._playlist_select_context is None else 360), ), extra_touch_border_scale=0.1, autoselect=True, @@ -493,22 +513,24 @@ class PlayWindow(bui.MainWindow): back_button.delete() bui.containerwidget( edit=self._root_widget, - on_cancel_call=self._back, + on_cancel_call=self.main_window_back, # cancel_button=bui.get_special_widget('back_button'), selected_child=( self._coop_button - if self._is_main_menu + if self._playlist_select_context is None else self._teams_button ), ) else: - bui.buttonwidget(edit=back_button, on_activate_call=self._back) + bui.buttonwidget( + edit=back_button, on_activate_call=self.main_window_back + ) bui.containerwidget( edit=self._root_widget, cancel_button=back_button, selected_child=( self._coop_button - if self._is_main_menu + if self._playlist_select_context is None else self._teams_button ), ) @@ -519,9 +541,15 @@ class PlayWindow(bui.MainWindow): def get_main_window_state(self) -> bui.MainWindowState: # Support recreating our window for back/refresh purposes. cls = type(self) + + # Pull any values out of self here; if we do it in the lambda + # we'll keep our window alive inadvertantly. + playlist_select_context = self._playlist_select_context return bui.BasicMainWindowState( create_call=lambda transition, origin_widget: cls( - transition=transition, origin_widget=origin_widget + transition=transition, + origin_widget=origin_widget, + playlist_select_context=playlist_select_context, ) ) @@ -537,30 +565,6 @@ class PlayWindow(bui.MainWindow): import bauiv1lib.coop.browser as _unused3 import bauiv1lib.playlist.browser as _unused4 - def _back(self) -> None: - # pylint: disable=cyclic-import - - # no-op if we're not currently in control. - if not self.main_window_has_control(): - return - - if self._is_main_menu: - self.main_window_back() - else: - from bauiv1lib.gather import GatherWindow - - assert bui.app.classic is not None - - self._save_state() - bui.app.ui_v1.set_main_window( - GatherWindow(transition='in_left'), - from_window=self, - is_back=True, - ) - bui.containerwidget( - edit=self._root_widget, transition=self._transition_out - ) - def _coop(self) -> None: # pylint: disable=cyclic-import from bauiv1lib.account import show_sign_in_prompt @@ -595,7 +599,9 @@ class PlayWindow(bui.MainWindow): self.main_window_replace( PlaylistBrowserWindow( - origin_widget=self._teams_button, sessiontype=bs.DualTeamSession + origin_widget=self._teams_button, + sessiontype=bs.DualTeamSession, + playlist_select_context=self._playlist_select_context, ) ) @@ -614,6 +620,7 @@ class PlayWindow(bui.MainWindow): PlaylistBrowserWindow( origin_widget=self._free_for_all_button, sessiontype=bs.FreeForAllSession, + playlist_select_context=self._playlist_select_context, ), from_window=self, ) diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/browser.py b/src/assets/ba_data/python/bauiv1lib/playlist/browser.py index ef0fcf57..6913d3a9 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/browser.py @@ -7,11 +7,14 @@ from __future__ import annotations import copy import math import logging -from typing import override +from typing import override, TYPE_CHECKING import bascenev1 as bs import bauiv1 as bui +if TYPE_CHECKING: + from bauiv1lib.play import PlaylistSelectContext + class PlaylistBrowserWindow(bui.MainWindow): """Window for starting teams games.""" @@ -21,6 +24,7 @@ class PlaylistBrowserWindow(bui.MainWindow): sessiontype: type[bs.Session], transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, + playlist_select_context: PlaylistSelectContext | None = None, ): # pylint: disable=cyclic-import from bauiv1lib.playlist import PlaylistTypeVars @@ -39,6 +43,7 @@ class PlaylistBrowserWindow(bui.MainWindow): self._customize_button: bui.Widget | None = None self._sub_width: float | None = None self._sub_height: float | None = None + self._playlist_select_context = playlist_select_context self._ensure_standard_playlists_exist() @@ -63,7 +68,10 @@ class PlaylistBrowserWindow(bui.MainWindow): size=(self._width, self._height + top_extra), toolbar_visibility=( 'menu_minimal' - if uiscale is bui.UIScale.SMALL + if ( + uiscale is bui.UIScale.SMALL + or playlist_select_context is not None + ) else 'menu_full' ), scale=( @@ -160,11 +168,16 @@ class PlaylistBrowserWindow(bui.MainWindow): # then we keep self alive. sessiontype = self._sessiontype + # Pull anything out of self here; if we do it in the lambda + # we'll inadvertanly keep self alive. + playlist_select_context = self._playlist_select_context + return bui.BasicMainWindowState( create_call=lambda transition, origin_widget: cls( transition=transition, origin_widget=origin_widget, sessiontype=sessiontype, + playlist_select_context=playlist_select_context, ) ) @@ -639,9 +652,30 @@ class PlaylistBrowserWindow(bui.MainWindow): def on_play_options_window_run_game(self) -> None: """(internal)""" - if not self._root_widget: + + # No-op if we're not in control. + if not self.main_window_has_control(): + # if not self._root_widget: return - bui.containerwidget(edit=self._root_widget, transition='out_left') + + if self._playlist_select_context is not None: + # Done doing a playlist selection; now back all the way out + # of our selection windows to our stored starting point. + if self._playlist_select_context.back_state is None: + logging.error( + 'No back state found' + ' after playlist select context completion.' + ) + else: + self.main_window_back_state = ( + self._playlist_select_context.back_state + ) + self.main_window_back() + else: + # Launching a regular game session; simply get our window + # transitioning out. + self.main_window_close(transition='out_left') + # bui.containerwidget(edit=self._root_widget, transition='out_left') def _on_playlist_select(self, playlist_name: str) -> None: self._selected_playlist = playlist_name @@ -676,6 +710,7 @@ class PlaylistBrowserWindow(bui.MainWindow): scale_origin=button.get_screen_space_center(), playlist=playlist_name, delegate=self, + playlist_select_context=self._playlist_select_context, ) def _on_customize_press(self) -> None: @@ -690,7 +725,7 @@ class PlaylistBrowserWindow(bui.MainWindow): self._save_state() bui.containerwidget(edit=self._root_widget, transition='out_left') - assert bui.app.classic is not None + # assert bui.app.classic is not None bui.app.ui_v1.set_main_window( PlaylistCustomizeBrowserWindow( origin_widget=self._customize_button, diff --git a/src/assets/ba_data/python/bauiv1lib/playoptions.py b/src/assets/ba_data/python/bauiv1lib/playoptions.py index 2b81de6a..0428db3a 100644 --- a/src/assets/ba_data/python/bauiv1lib/playoptions.py +++ b/src/assets/ba_data/python/bauiv1lib/playoptions.py @@ -15,6 +15,8 @@ from bauiv1lib.popup import PopupWindow if TYPE_CHECKING: from typing import Any + from bauiv1lib.play import PlaylistSelectContext + class PlayOptionsWindow(PopupWindow): """A popup window for configuring play options.""" @@ -25,6 +27,7 @@ class PlayOptionsWindow(PopupWindow): playlist: str, scale_origin: tuple[float, float], delegate: Any = None, + playlist_select_context: PlaylistSelectContext | None = None, ): # FIXME: Tidy this up. # pylint: disable=too-many-branches @@ -39,11 +42,7 @@ class PlayOptionsWindow(PopupWindow): self._pvars = PlaylistTypeVars(sessiontype) self._transitioning_out = False - # We behave differently if we're being used for playlist selection - # vs starting a game directly (should make this more elegant). - classic = bui.app.classic - assert classic is not None - self._selecting_mode = classic.selecting_private_party_playlist + self._playlist_select_context = playlist_select_context self._do_randomize_val = bui.app.config.get( self._pvars.config_name + ' Playlist Randomize', 0 @@ -66,7 +65,8 @@ class PlayOptionsWindow(PopupWindow): mesh_transparent = bui.getmesh('level_select_button_transparent') mask_tex = bui.gettexture('mapPreviewMask') - # Poke into this playlist and see if we can display some of its maps. + # Poke into this playlist and see if we can display some of its + # maps. map_textures = [] map_texture_entries = [] rows = 0 @@ -405,7 +405,11 @@ class PlayOptionsWindow(PopupWindow): on_activate_call=self._on_ok_press, autoselect=True, label=bui.Lstr( - resource='okText' if self._selecting_mode else 'playText' + resource=( + 'okText' + if self._playlist_select_context is not None + else 'playText' + ) ), ) @@ -498,8 +502,8 @@ class PlayOptionsWindow(PopupWindow): # Head back to the gather window in playlist-select mode # or start the game in regular mode. - if self._selecting_mode: - from bauiv1lib.gather import GatherWindow + if self._playlist_select_context is not None: + # from bauiv1lib.gather import GatherWindow if self._sessiontype is bs.FreeForAllSession: typename = 'ffa' @@ -509,14 +513,15 @@ class PlayOptionsWindow(PopupWindow): raise RuntimeError('Only teams and ffa currently supported') cfg['Private Party Host Session Type'] = typename bui.getsound('gunCocking').play() - assert bui.app.classic is not None - # Note: this is a wonky situation where we aren't actually - # the main window but we set it on behalf of the main window - # that popped us up. - bui.app.ui_v1.set_main_window( - GatherWindow(transition='in_right'), - from_window=False, # Disable this test. - ) + + # assert bui.app.classic is not None + # # Note: this is a wonky situation where we aren't actually + # # the main window but we set it on behalf of the main window + # # that popped us up. + # bui.app.ui_v1.set_main_window( + # GatherWindow(transition='in_right'), + # from_window=False, # Disable this test. + # ) self._transition_out(transition='out_left') if self._delegate is not None: self._delegate.on_play_options_window_run_game() diff --git a/src/assets/ba_data/python/bauiv1lib/soundtrack/edit.py b/src/assets/ba_data/python/bauiv1lib/soundtrack/edit.py index 77bcae57..5d7132ad 100644 --- a/src/assets/ba_data/python/bauiv1lib/soundtrack/edit.py +++ b/src/assets/ba_data/python/bauiv1lib/soundtrack/edit.py @@ -393,8 +393,7 @@ class SoundtrackEditWindow(bui.MainWindow): bui.Call(self._restore_editor, state, song_type), entry, selection_target_name, - ), - group_id='soundtrackentryselect', + ) ) # bui.containerwidget(edit=self._root_widget, transition='out_left') # bui.app.ui_v1.set_main_window( diff --git a/src/assets/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py b/src/assets/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py index 4556e00f..31879986 100644 --- a/src/assets/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py +++ b/src/assets/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py @@ -209,8 +209,7 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow): self.main_window_replace( MacMusicAppPlaylistSelectWindow( self._callback, current_playlist_entry, self._current_entry - ), - group_id='soundtrackentryselect', + ) ) # MacMusicAppPlaylistSelectWindow( # self._callback, current_playlist_entry, self._current_entry @@ -241,7 +240,6 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow): ), allow_folders=False, ), - group_id='soundtrackentryselect', ) # bui.app.ui_v1.set_main_window( # FileSelectorWindow( @@ -276,7 +274,6 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow): valid_file_extensions=[], allow_folders=True, ), - group_id='soundtrackentryselect', ) # bui.app.ui_v1.set_main_window( # FileSelectorWindow( diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 9fb9e776..45b5bcd9 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -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 = 21977; +const int kEngineBuildNumber = 21978; const char* kEngineVersion = "1.7.37"; const int kEngineApiVersion = 9; From b550866ed7dbe4ba7e58b14854ace681eaf2e790 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 3 Sep 2024 14:14:00 -0700 Subject: [PATCH 2/5] updated playlist editing for MainWindow system --- .efrocachemap | 56 +++---- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- .../ba_data/python/bascenev1/_gameactivity.py | 64 ++++---- .../python/bauiv1lib/characterpicker.py | 19 ++- .../ba_data/python/bauiv1lib/iconpicker.py | 19 ++- .../python/bauiv1lib/playlist/addgame.py | 37 +++-- .../python/bauiv1lib/playlist/browser.py | 19 +-- .../bauiv1lib/playlist/customizebrowser.py | 114 ++++---------- .../ba_data/python/bauiv1lib/playlist/edit.py | 41 +---- .../bauiv1lib/playlist/editcontroller.py | 143 ++++++++++-------- .../python/bauiv1lib/playlist/editgame.py | 47 ++++-- .../python/bauiv1lib/playlist/mapselect.py | 60 ++++++-- .../ba_data/python/bauiv1lib/store/browser.py | 65 ++++---- .../ba_data/python/bauiv1lib/store/button.py | 8 +- src/ballistica/shared/ballistica.cc | 2 +- 16 files changed, 353 insertions(+), 345 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index c57ef2ad..209822f2 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -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": "6f45d8d041a5c44d44e6da00ddd68983", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "fc5c2514f1773c91159fc8014e5f3e93", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a8679f4c2a071af5f024c04fb2de5685", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "2d32e5d05331df1b4b6923ee241b630b", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "8d9d7a041a1d3e56aec39682821927f6", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0d0405cb2e05629b0a23d6b8eca203ad", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "338528869c6fd8797b96cb875e3820cf", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "4428797051af1f7fde71fb638db52b17", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "c202858e8db64aebb88be04828ddfaa9", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "bd13e0e3edf0aac64609fb764921d7b1", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "f183757c9541262774adb1e0599f2001", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "85791e6585f4858517330e23834fc7b8", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "90b0d97ebaf7756824493b2fcee1e97e", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "955eef9f918e24c37e279db75ec6fca3", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b42ae8f5896f850e72fc4c30b2b8c52b", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "dda8f5a5099d9b695c9ab5a148f5ff10", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "8389b61cf60dd2f4ebad8b0e2c376605", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "cce612fb88788b32b303a956cd6fd6f5", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d54a451817bee9d4f8debd1fecf84ae9", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e41c4795f5b6f7dd0cf61286e62e91ac", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "b4a141253c7e65acf25669015d739dc8", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "66dd516f011240f4bd89d960747f5306", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "7467a00e52c02904d385a9f03cb938c1", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "bff07f7aaba6de3994093450f6b7652e", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "e4264a74c5197c903ced0f9fad9f358f", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0b2b7ffdcba7fce08115d60f46907dd3", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2b6bedf49d78797be81a3a91a40faea4", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "8a83499d274108ac181c8709cfecebcc", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "ac51052669f94969d50c32c3bb5faa39", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "0de05110dc0d73c578f1ee90098d062f", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "29536a3ccaa1373662a9ad61d15ea311", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "56d6bd161d82ff248b1389c83dbc1a9e", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "8cfafd625e0744cc1cd6a825d4192d6b", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "5673525e6591eed323a574dbc4e053cd", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "fef949796918e90da2c867d212923fc5", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "2c5b61d0105dc5c2c0d69fee4de0b3bb", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "27084c4785c00b0b47348a7ea2121df4", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "b474ebbbd3498bfbbf7ade35bf4e3273", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9d364f0f8023699a7f4c14ee4f1f80a2", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e8b7846713d5aca5a9a472652b49bced", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "fa659b5d6119acba6570c92ce4d35ae2", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", @@ -4132,14 +4132,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1659535e95e3047fda529543e265ac97", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "ccc8a569891e0e5541706ca21aa91a3e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "f39ae9be9fe75e16f45ea78f2bd3147a", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "5b1eb9ecc0eaaa22fb0b838479515deb", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "41977e7f7bbd1baa587661e9c0daee85", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "92451c795510652611fdac035839f0eb", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "6b3215ddfb8bb3ff8149b380f829806a", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1980c181a06f7355770d31499b7f9245", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "ce4592ab12f3954f62140365211c8eb4", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "8f7ffb5997d1601d57d71af95584d719", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "cacccdf999c17e285edfb89a830f2286", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "c39508091d106d9fb77fd676a14ae4b1", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "584298e65be570d131f7543744c28b47", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "79a0e0beb67caef006d3ef5d3afa3fae", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "a5520e9b3ba6556412381d179a9e3884", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "5ad1b6928cdb9fb4e0c29f399785f535", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "504cfbf0d946547c3c26bda13afe0833", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "cb299985623bbcc86015cb103a424ae6", "src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d", diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f9072a8..5f1675c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.37 (build 21978, api 9, 2024-09-03) +### 1.7.37 (build 21980, api 9, 2024-09-03) - 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. diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index dbd337c6..504da6c9 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21978 +TARGET_BALLISTICA_BUILD = 21980 TARGET_BALLISTICA_VERSION = '1.7.37' diff --git a/src/assets/ba_data/python/bascenev1/_gameactivity.py b/src/assets/ba_data/python/bascenev1/_gameactivity.py index de6ecc05..d990f818 100644 --- a/src/assets/ba_data/python/bascenev1/_gameactivity.py +++ b/src/assets/ba_data/python/bascenev1/_gameactivity.py @@ -64,43 +64,43 @@ class GameActivity(Activity[PlayerT, TeamT]): # (unless overridden by the map). default_music: bascenev1.MusicType | None = None - @classmethod - def create_settings_ui( - cls, - sessiontype: type[bascenev1.Session], - settings: dict | None, - completion_call: Callable[[dict | None], None], - ) -> None: - """Launch an in-game UI to configure settings for a game type. + # @classmethod + # def create_settings_ui( + # cls, + # sessiontype: type[bascenev1.Session], + # settings: dict | None, + # completion_call: Callable[[dict | None], None], + # ) -> None: + # """Launch an in-game UI to configure settings for a game type. - 'sessiontype' should be the bascenev1.Session class the game will - be used in. + # 'sessiontype' should be the bascenev1.Session class the game will + # be used in. - 'settings' should be an existing settings dict (implies 'edit' - ui mode) or None (implies 'add' ui mode). + # 'settings' should be an existing settings dict (implies 'edit' + # ui mode) or None (implies 'add' ui mode). - 'completion_call' will be called with a filled-out settings dict on - success or None on cancel. + # 'completion_call' will be called with a filled-out settings dict on + # success or None on cancel. - Generally subclasses don't need to override this; if they override - bascenev1.GameActivity.get_available_settings() and - bascenev1.GameActivity.get_supported_maps() they can just rely on - the default implementation here which calls those methods. - """ - # pylint: disable=cyclic-import - from bauiv1lib.playlist.editgame import PlaylistEditGameWindow + # Generally subclasses don't need to override this; if they override + # bascenev1.GameActivity.get_available_settings() and + # bascenev1.GameActivity.get_supported_maps() they can just rely on + # the default implementation here which calls those methods. + # """ + # # pylint: disable=cyclic-import + # from bauiv1lib.playlist.editgame import PlaylistEditGameWindow - assert babase.app.classic is not None - babase.app.ui_v1.clear_main_window() - babase.app.ui_v1.set_main_window( - PlaylistEditGameWindow( - cls, - sessiontype, - settings, - completion_call=completion_call, - ), - from_window=False, # Disable check since we don't know. - ) + # assert babase.app.classic is not None + # babase.app.ui_v1.clear_main_window() + # babase.app.ui_v1.set_main_window( + # PlaylistEditGameWindow( + # cls, + # sessiontype, + # settings, + # completion_call=completion_call, + # ), + # from_window=False, # Disable check since we don't know. + # ) @classmethod def getscoreconfig(cls) -> bascenev1.ScoreConfig: diff --git a/src/assets/ba_data/python/bauiv1lib/characterpicker.py b/src/assets/ba_data/python/bauiv1lib/characterpicker.py index 5e6ad306..b914f9af 100644 --- a/src/assets/ba_data/python/bauiv1lib/characterpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/characterpicker.py @@ -181,7 +181,8 @@ class CharacterPicker(PopupWindow): def _on_store_press(self) -> None: from bauiv1lib.account import show_sign_in_prompt - from bauiv1lib.store.browser import StoreBrowserWindow + + # from bauiv1lib.store.browser import StoreBrowserWindow plus = bui.app.plus assert plus is not None @@ -189,12 +190,16 @@ class CharacterPicker(PopupWindow): if plus.get_v1_account_state() != 'signed_in': show_sign_in_prompt() return - self._transition_out() - StoreBrowserWindow( - modal=True, - show_tab=StoreBrowserWindow.TabID.CHARACTERS, - origin_widget=self._get_more_characters_button, - ) + + bui.screenmessage('UNDER CONSTRUCTION') + return + + # self._transition_out() + # StoreBrowserWindow( + # modal=True, + # show_tab=StoreBrowserWindow.TabID.CHARACTERS, + # origin_widget=self._get_more_characters_button, + # ) def _select_character(self, character: str) -> None: if self._delegate is not None: diff --git a/src/assets/ba_data/python/bauiv1lib/iconpicker.py b/src/assets/ba_data/python/bauiv1lib/iconpicker.py index 968b9c16..20ebdb0c 100644 --- a/src/assets/ba_data/python/bauiv1lib/iconpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/iconpicker.py @@ -159,7 +159,8 @@ class IconPicker(PopupWindow): def _on_store_press(self) -> None: from bauiv1lib.account import show_sign_in_prompt - from bauiv1lib.store.browser import StoreBrowserWindow + + # from bauiv1lib.store.browser import StoreBrowserWindow plus = bui.app.plus assert plus is not None @@ -167,12 +168,16 @@ class IconPicker(PopupWindow): if plus.get_v1_account_state() != 'signed_in': show_sign_in_prompt() return - self._transition_out() - StoreBrowserWindow( - modal=True, - show_tab=StoreBrowserWindow.TabID.ICONS, - origin_widget=self._get_more_icons_button, - ) + # self._transition_out() + + bui.screenmessage('UNDER CONSTRUCTION') + return + + # StoreBrowserWindow( + # modal=True, + # show_tab=StoreBrowserWindow.TabID.ICONS, + # origin_widget=self._get_more_icons_button, + # ) def _select_icon(self, icon: str) -> None: if self._delegate is not None: diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py b/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py index 02ef065a..54b54914 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py @@ -57,12 +57,10 @@ class PlaylistAddGameWindow(bui.MainWindow): self._back_button = bui.buttonwidget( parent=self._root_widget, position=(58 + x_inset, self._height - 53), - size=(165, 70), - scale=0.75, - text_scale=1.2, - label=bui.Lstr(resource='backText'), + size=(60, 48), + label=bui.charstr(bui.SpecialChar.BACK), autoselect=True, - button_type='back', + button_type='backSmall', on_activate_call=self.main_window_back, ) self._select_button = select_button = bui.buttonwidget( @@ -257,27 +255,37 @@ class PlaylistAddGameWindow(bui.MainWindow): from bauiv1lib.account import show_sign_in_prompt from bauiv1lib.store.browser import StoreBrowserWindow + # No-op if we're not in control. + if self.main_window_has_control(): + return + plus = bui.app.plus assert plus is not None if plus.get_v1_account_state() != 'signed_in': show_sign_in_prompt() return - StoreBrowserWindow( - modal=True, - show_tab=StoreBrowserWindow.TabID.MINIGAMES, - on_close_call=self._on_store_close, - origin_widget=self._get_more_games_button, + + self.main_window_replace( + StoreBrowserWindow( + # modal=True, + show_tab=StoreBrowserWindow.TabID.MINIGAMES, + # on_close_call=self._on_store_close, + origin_widget=self._get_more_games_button, + minimal_toolbars=True, + ) ) - def _on_store_close(self) -> None: - self._refresh(select_get_more_games_button=True) + # def _on_store_close(self) -> None: + # self._refresh(select_get_more_games_button=True) def _add(self) -> None: bui.lock_all_input() # Make sure no more commands happen. bui.apptimer(0.1, bui.unlock_all_input) assert self._selected_game_type is not None - self._editcontroller.add_game_type_selected(self._selected_game_type) + self._editcontroller.add_game_type_selected( + self._selected_game_type, from_window=self + ) def _set_selected_game_type(self, gametype: type[bs.GameActivity]) -> None: self._selected_game_type = gametype @@ -290,6 +298,3 @@ class PlaylistAddGameWindow(bui.MainWindow): self._editcontroller.get_session_type() ), ) - - # def _back(self) -> None: - # self._editcontroller.add_game_cancelled() diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/browser.py b/src/assets/ba_data/python/bauiv1lib/playlist/browser.py index 6913d3a9..7523639d 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/browser.py @@ -114,8 +114,6 @@ class PlaylistBrowserWindow(bui.MainWindow): h_align='center', v_align='center', ) - # if uiscale is bui.UIScale.SMALL and bui.app.ui_v1.use_toolbars: - # bui.textwidget(edit=txt, text='') bui.buttonwidget( edit=self._back_button, @@ -152,8 +150,8 @@ class PlaylistBrowserWindow(bui.MainWindow): self._config_name_full = self._pvars.config_name + ' Playlists' self._last_config = None - # Update now and once per second. - # (this should do our initial refresh) + # Update now and once per second (this should do our initial + # refresh). self._update() self._update_timer = bui.AppTimer( 1.0, bui.WeakCall(self._update), repeat=True @@ -675,13 +673,12 @@ class PlaylistBrowserWindow(bui.MainWindow): # Launching a regular game session; simply get our window # transitioning out. self.main_window_close(transition='out_left') - # bui.containerwidget(edit=self._root_widget, transition='out_left') def _on_playlist_select(self, playlist_name: str) -> None: self._selected_playlist = playlist_name def _update(self) -> None: - # make sure config exists + # Make sure config exists. if self._config_name_full not in bui.app.config: bui.app.config[self._config_name_full] = {} @@ -725,7 +722,6 @@ class PlaylistBrowserWindow(bui.MainWindow): self._save_state() bui.containerwidget(edit=self._root_widget, transition='out_left') - # assert bui.app.classic is not None bui.app.ui_v1.set_main_window( PlaylistCustomizeBrowserWindow( origin_widget=self._customize_button, @@ -756,15 +752,6 @@ class PlaylistBrowserWindow(bui.MainWindow): self.main_window_back() - # self._save_state() - # bui.containerwidget( - # edit=self._root_widget, transition=self._transition_out - # ) - # assert bui.app.classic is not None - # bui.app.ui_v1.set_main_window( - # PlayWindow(transition='in_left'), from_window=self, is_back=True - # ) - def _save_state(self) -> None: try: sel = self._root_widget.get_selected_child() diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/customizebrowser.py b/src/assets/ba_data/python/bauiv1lib/playlist/customizebrowser.py index 08658d5f..f9c777fd 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/customizebrowser.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/customizebrowser.py @@ -6,19 +6,19 @@ from __future__ import annotations import copy import time -import logging + +# import logging from typing import TYPE_CHECKING, override -import bascenev1 as bs +# import bascenev1 as bs import bauiv1 as bui if TYPE_CHECKING: from typing import Any -REQUIRE_PRO = False + import bascenev1 as bs -# TEMP -UNDER_CONSTRUCTION = True +REQUIRE_PRO = False class PlaylistCustomizeBrowserWindow(bui.MainWindow): @@ -77,7 +77,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): if uiscale is bui.UIScale.SMALL: self._back_button = None bui.containerwidget( - edit=self._root_widget, on_cancel_call=self._back + edit=self._root_widget, on_cancel_call=self.main_window_back ) else: self._back_button = bui.buttonwidget( @@ -291,8 +291,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): right_widget=bui.get_special_widget('squad_button'), ) - # make sure config exists - self._config_name_full = self._pvars.config_name + ' Playlists' + # Make sure config exists. + self._config_name_full = f'{self._pvars.config_name} Playlists' if self._config_name_full not in bui.app.config: bui.app.config[self._config_name_full] = {} @@ -305,7 +305,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): if self._back_button is not None: bui.buttonwidget( - edit=self._back_button, on_activate_call=self._back + edit=self._back_button, on_activate_call=self.main_window_back ) bui.containerwidget( edit=self._root_widget, cancel_button=self._back_button @@ -336,9 +336,14 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): ) ) - # @override - # def on_main_window_close(self) -> None: - # self._save_state() + @override + def on_main_window_close(self) -> None: + if self._selected_playlist_name is not None: + cfg = bui.app.config + cfg[f'{self._pvars.config_name} Playlist Selection'] = ( + self._selected_playlist_name + ) + cfg.commit() def _update(self) -> None: assert bui.app.classic is not None @@ -348,59 +353,10 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): edit=lock, opacity=0.0 if (have or not REQUIRE_PRO) else 1.0 ) - def _back(self) -> None: - # pylint: disable=cyclic-import - # from bauiv1lib.playlist import browser - - # no-op if our underlying widget is dead or on its way out. - if not self._root_widget or self._root_widget.transitioning_out: - return - - if self._selected_playlist_name is not None: - cfg = bui.app.config - cfg[self._pvars.config_name + ' Playlist Selection'] = ( - self._selected_playlist_name - ) - cfg.commit() - - self.main_window_back() - # bui.containerwidget( - # edit=self._root_widget, transition=self._transition_out - # ) - # assert bui.app.classic is not None - # bui.app.ui_v1.set_main_window( - # browser.PlaylistBrowserWindow( - # transition='in_left', sessiontype=self._sessiontype - # ), - # from_window=self, - # is_back=True, - # ) - def _select(self, name: str, index: int) -> None: self._selected_playlist_name = name self._selected_playlist_index = index - def _run_selected_playlist(self) -> None: - # pylint: disable=cyclic-import - bui.unlock_all_input() - try: - bs.new_host_session(self._sessiontype) - except Exception: - from bascenev1lib import mainmenu - - logging.exception('Error running session %s.', self._sessiontype) - - # Drop back into a main menu session. - bs.new_host_session(mainmenu.MainMenuSession) - - def _choose_playlist(self) -> None: - if self._selected_playlist_name is None: - return - self._save_playlist_selection() - bui.containerwidget(edit=self._root_widget, transition='out_left') - bui.fade_screen(False, endcall=self._run_selected_playlist) - bui.lock_all_input() - def _refresh(self, select_playlist: str | None = None) -> None: from efro.util import asserttype @@ -451,7 +407,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): ) bui.widget(edit=txtw, show_buffer_top=50, show_buffer_bottom=50) - # Hitting up from top widget should jump to 'back' + # Hitting up from top widget should jump to 'back'. if index == 0: bui.widget( edit=txtw, @@ -473,8 +429,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): visible_child=txtw, ) else: - # Select this one if it was previously selected. - # Go by index if there's one. + # Select this one if it was previously selected. Go by + # index if there's one. if old_selection_index is not None: if index == old_selection_index: bui.columnwidget( @@ -493,10 +449,10 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): index += 1 def _save_playlist_selection(self) -> None: - # Store the selected playlist in prefs. - # This serves dual purposes of letting us re-select it next time - # if we want and also lets us pass it to the game (since we reset - # the whole python environment that's not actually easy). + # Store the selected playlist in prefs. This serves dual + # purposes of letting us re-select it next time if we want and + # also lets us pass it to the game (since we reset the whole + # python environment that's not actually easy). cfg = bui.app.config cfg[self._pvars.config_name + ' Playlist Selection'] = ( self._selected_playlist_name @@ -511,8 +467,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): from bauiv1lib.playlist.editcontroller import PlaylistEditController from bauiv1lib.purchase import PurchaseWindow - if UNDER_CONSTRUCTION: - bui.screenmessage('UNDER CONSTRUCTION') + # No-op if we're not in control. + if not self.main_window_has_control(): return assert bui.app.classic is not None @@ -538,18 +494,13 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): self._save_playlist_selection() # Kick off the edit UI. - PlaylistEditController(sessiontype=self._sessiontype) - bui.containerwidget(edit=self._root_widget, transition='out_left') + PlaylistEditController(sessiontype=self._sessiontype, from_window=self) def _edit_playlist(self) -> None: # pylint: disable=cyclic-import from bauiv1lib.playlist.editcontroller import PlaylistEditController from bauiv1lib.purchase import PurchaseWindow - if UNDER_CONSTRUCTION: - bui.screenmessage('UNDER CONSTRUCTION') - return - assert bui.app.classic is not None if REQUIRE_PRO and not bui.app.classic.accounts.have_pro_options(): PurchaseWindow(items=['pro']) @@ -566,8 +517,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): PlaylistEditController( existing_playlist_name=self._selected_playlist_name, sessiontype=self._sessiontype, + from_window=self, ) - bui.containerwidget(edit=self._root_widget, transition='out_left') def _do_delete_playlist(self) -> None: plus = bui.app.plus @@ -732,7 +683,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): bui.getsound('error').play() return - # clamp at our max playlist number + # Clamp at our max playlist number. if len(bui.app.config[self._config_name_full]) > self._max_playlists: bui.screenmessage( bui.Lstr( @@ -747,10 +698,11 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): return copy_text = bui.Lstr(resource='copyOfText').evaluate() - # get just 'Copy' or whatnot - copy_word = copy_text.replace('${NAME}', '').strip() - # find a valid dup name that doesn't exist + # Get just 'Copy' or whatnot. + copy_word = copy_text.replace('${NAME}', '').strip() + + # Find a valid dup name that doesn't exist. test_index = 1 base_name = self._get_playlist_display_name( self._selected_playlist_name diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/edit.py b/src/assets/ba_data/python/bauiv1lib/playlist/edit.py index 43a39cfa..0a1b68f4 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/edit.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/edit.py @@ -290,9 +290,6 @@ class PlaylistEditWindow(bui.MainWindow): self._editcontroller.set_edit_ui_selection(selection) def _cancel(self) -> None: - # from bauiv1lib.playlist.customizebrowser import ( - # PlaylistCustomizeBrowserWindow, - # ) # no-op if our underlying widget is dead or on its way out. if not self._root_widget or self._root_widget.transitioning_out: @@ -301,38 +298,25 @@ class PlaylistEditWindow(bui.MainWindow): bui.getsound('powerdown01').play() self.main_window_back() - # bui.containerwidget(edit=self._root_widget, transition='out_right') - # assert bui.app.classic is not None - # bui.app.ui_v1.set_main_window( - # PlaylistCustomizeBrowserWindow( - # transition='in_left', - # sessiontype=self._editcontroller.get_session_type(), - # select_playlist=( - # self._editcontroller.get_existing_playlist_name() - # ), - # ), - # from_window=self, - # is_back=True, - # ) - def _add(self) -> None: # Store list name then tell the session to perform an add. self._editcontroller.setname( cast(str, bui.textwidget(query=self._text_field)) ) - self._editcontroller.add_game_pressed() + self._editcontroller.add_game_pressed(from_window=self) def _edit(self) -> None: # Store list name then tell the session to perform an add. self._editcontroller.setname( cast(str, bui.textwidget(query=self._text_field)) ) - self._editcontroller.edit_game_pressed() + self._editcontroller.edit_game_pressed(from_window=self) def _save_press(self) -> None: - from bauiv1lib.playlist.customizebrowser import ( - PlaylistCustomizeBrowserWindow, - ) + + # No-op if we're not in control. + if not self.main_window_has_control(): + return # no-op if our underlying widget is dead or on its way out. if not self._root_widget or self._root_widget.transitioning_out: @@ -395,18 +379,9 @@ class PlaylistEditWindow(bui.MainWindow): ) plus.run_v1_account_transactions() - bui.containerwidget(edit=self._root_widget, transition='out_right') bui.getsound('gunCocking').play() - assert bui.app.classic is not None - bui.app.ui_v1.set_main_window( - PlaylistCustomizeBrowserWindow( - transition='in_left', - sessiontype=self._editcontroller.get_session_type(), - select_playlist=new_name, - ), - from_window=self, - is_back=True, - ) + + self.main_window_back() def _save_press_with_sound(self) -> None: bui.getsound('swish').play() diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/editcontroller.py b/src/assets/ba_data/python/bauiv1lib/playlist/editcontroller.py index 2fb584c6..f398e5b0 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/editcontroller.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/editcontroller.py @@ -11,7 +11,7 @@ import bascenev1 as bs import bauiv1 as bui if TYPE_CHECKING: - from typing import Any + from typing import Any, Callable class PlaylistEditController: @@ -20,8 +20,8 @@ class PlaylistEditController: def __init__( self, sessiontype: type[bs.Session], + from_window: bui.MainWindow, existing_playlist_name: str | None = None, - transition: str = 'in_right', playlist: list[dict[str, Any]] | None = None, playlist_name: str | None = None, ): @@ -44,6 +44,9 @@ class PlaylistEditController: self._existing_playlist_name = existing_playlist_name self._config_name_full = self._pvars.config_name + ' Playlists' + self._pre_game_add_state: bui.MainWindowState | None = None + self._pre_game_edit_state: bui.MainWindowState | None = None + # Make sure config exists. if self._config_name_full not in appconfig: appconfig[self._config_name_full] = {} @@ -88,11 +91,12 @@ class PlaylistEditController: # and that's all they can do. self._edit_ui_selection = 'add_button' - assert bui.app.classic is not None - bui.app.ui_v1.set_main_window( - PlaylistEditWindow(editcontroller=self, transition=transition), - from_window=False, # Disable this check. - ) + editwindow = PlaylistEditWindow(editcontroller=self) + from_window.main_window_replace(editwindow) + + # Once we've set our start window, store the back state. We'll + # skip back to there once we're fully done. + self._back_state = editwindow.main_window_back_state def get_config_name(self) -> str: """(internal)""" @@ -142,83 +146,88 @@ class PlaylistEditController: """Sets the selected playlist index.""" self._selected_index = index - def add_game_pressed(self) -> None: + def add_game_pressed(self, from_window: bui.MainWindow) -> None: """(internal)""" from bauiv1lib.playlist.addgame import PlaylistAddGameWindow - assert bui.app.classic is not None - bui.app.ui_v1.clear_main_window() - bui.app.ui_v1.set_main_window( - PlaylistAddGameWindow(editcontroller=self), from_window=None - ) + # assert bui.app.classic is not None - def edit_game_pressed(self) -> None: + # No op if we're not in control. + if not from_window.main_window_has_control(): + return + + addwindow = PlaylistAddGameWindow(editcontroller=self) + from_window.main_window_replace(addwindow) + + # Once we're there, store the back state. We'll use that to jump + # back to our current location once the edit is done. + assert self._pre_game_add_state is None + self._pre_game_add_state = addwindow.main_window_back_state + + def edit_game_pressed(self, from_window: bui.MainWindow) -> None: """Should be called by supplemental UIs when a game is to be edited.""" if not self._playlist: return + self._show_edit_ui( gametype=bui.getclass( self._playlist[self._selected_index]['type'], subclassof=bs.GameActivity, ), settings=self._playlist[self._selected_index], + from_window=from_window, ) - # def add_game_cancelled(self) -> None: - # """(internal)""" - # from bauiv1lib.playlist.edit import PlaylistEditWindow - - # assert bui.app.classic is not None - # bui.app.ui_v1.clear_main_window(transition='out_right') - # bui.app.ui_v1.set_main_window( - # PlaylistEditWindow(editcontroller=self, transition='in_left'), - # from_window=None, - # is_back=True, - # ) - def _show_edit_ui( - self, gametype: type[bs.GameActivity], settings: dict[str, Any] | None + self, + gametype: type[bs.GameActivity], + settings: dict[str, Any] | None, + from_window: bui.MainWindow, ) -> None: + # pylint: disable=cyclic-import + from bauiv1lib.playlist.editgame import PlaylistEditGameWindow + + if not from_window.main_window_has_control(): + return + self._editing_game = settings is not None self._editing_game_type = gametype assert self._sessiontype is not None - gametype.create_settings_ui( - self._sessiontype, copy.deepcopy(settings), self._edit_game_done + + # Jump into an edit window. + editwindow = PlaylistEditGameWindow( + gametype, + self._sessiontype, + copy.deepcopy(settings), + completion_call=self._edit_game_done, + ) + from_window.main_window_replace(editwindow) + + # Once we're there, store the back state. We'll use that to jump + # back to our current location once the edit is done. + assert self._pre_game_edit_state is None + self._pre_game_edit_state = editwindow.main_window_back_state + + def add_game_type_selected( + self, gametype: type[bs.GameActivity], from_window: bui.MainWindow + ) -> None: + """(internal)""" + self._show_edit_ui( + gametype=gametype, settings=None, from_window=from_window ) - def add_game_type_selected(self, gametype: type[bs.GameActivity]) -> None: - """(internal)""" - self._show_edit_ui(gametype=gametype, settings=None) + def _edit_game_done( + self, config: dict[str, Any] | None, from_window: bui.MainWindow + ) -> None: - def _edit_game_done(self, config: dict[str, Any] | None) -> None: - from bauiv1lib.playlist.edit import PlaylistEditWindow - from bauiv1lib.playlist.addgame import PlaylistAddGameWindow + # No-op if provided window isn't in charge. + if not from_window.main_window_has_control(): + return assert bui.app.classic is not None if config is None: - # If we were editing, go back to our list. - if self._editing_game: - bui.getsound('powerdown01').play() - bui.app.ui_v1.clear_main_window() - bui.app.ui_v1.set_main_window( - PlaylistEditWindow( - editcontroller=self, transition='in_left' - ), - from_window=None, - is_back=True, - ) - - # Otherwise we were adding; go back to the add type choice list. - else: - bui.app.ui_v1.clear_main_window() - bui.app.ui_v1.set_main_window( - PlaylistAddGameWindow( - editcontroller=self, transition='in_left' - ), - from_window=None, - is_back=True, - ) + bui.getsound('powerdown01').play() else: # Make sure type is in there. assert self._editing_game_type is not None @@ -235,9 +244,17 @@ class PlaylistEditController: self._selected_index = insert_index bui.getsound('gunCocking').play() - bui.app.ui_v1.clear_main_window() - bui.app.ui_v1.set_main_window( - PlaylistEditWindow(editcontroller=self, transition='in_left'), - from_window=None, - is_back=True, - ) + + # If we're adding, jump to before the add started. + # Otherwise jump to before the edit started. + assert ( + self._pre_game_edit_state is not None + or self._pre_game_add_state is not None + ) + if self._pre_game_add_state is not None: + from_window.main_window_back_state = self._pre_game_add_state + elif self._pre_game_edit_state is not None: + from_window.main_window_back_state = self._pre_game_edit_state + from_window.main_window_back() + self._pre_game_edit_state = None + self._pre_game_add_state = None diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/editgame.py b/src/assets/ba_data/python/bauiv1lib/playlist/editgame.py index 5dfbe182..9192703f 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/editgame.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/editgame.py @@ -24,7 +24,7 @@ class PlaylistEditGameWindow(bui.MainWindow): gametype: type[bs.GameActivity], sessiontype: type[bs.Session], config: dict[str, Any] | None, - completion_call: Callable[[dict[str, Any] | None], Any], + completion_call: Callable[[dict[str, Any] | None, bui.MainWindow], Any], default_selection: str | None = None, transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, @@ -141,15 +141,15 @@ class PlaylistEditGameWindow(bui.MainWindow): btn = bui.buttonwidget( parent=self._root_widget, position=(45 + x_inset, height - 82 + y_extra2), - size=(180, 70) if is_add else (180, 65), + size=(60, 48) if is_add else (180, 65), label=( - bui.Lstr(resource='backText') + bui.charstr(bui.SpecialChar.BACK) if is_add else bui.Lstr(resource='cancelText') ), - button_type='back' if is_add else None, + button_type='backSmall' if is_add else None, autoselect=True, - scale=0.75, + scale=1.0 if is_add else 0.75, text_scale=1.3, on_activate_call=bui.Call(self._cancel), ) @@ -541,24 +541,41 @@ class PlaylistEditGameWindow(bui.MainWindow): # pylint: disable=cyclic-import from bauiv1lib.playlist.mapselect import PlaylistMapSelectWindow - # no-op if our underlying widget is dead or on its way out. - if not self._root_widget or self._root_widget.transitioning_out: + # No-op if we're not in control. + if not self.main_window_has_control(): return + # no-op if our underlying widget is dead or on its way out. + # if not self._root_widget or self._root_widget.transitioning_out: + # return + + self._config = self._getconfig() + # Replace ourself with the map-select UI. - bui.containerwidget(edit=self._root_widget, transition='out_left') - assert bui.app.classic is not None - bui.app.ui_v1.set_main_window( + self.main_window_replace( PlaylistMapSelectWindow( self._gametype, self._sessiontype, - copy.deepcopy(self._getconfig()), + # copy.deepcopy(self._getconfig()), + self._config, self._edit_info, self._completion_call, - ), - from_window=self, + ) ) + # bui.containerwidget(edit=self._root_widget, transition='out_left') + # assert bui.app.classic is not None + # bui.app.ui_v1.set_main_window( + # PlaylistMapSelectWindow( + # self._gametype, + # self._sessiontype, + # copy.deepcopy(self._getconfig()), + # self._edit_info, + # self._completion_call, + # ), + # from_window=self, + # ) + def _choice_inc( self, setting_name: str, @@ -586,7 +603,7 @@ class PlaylistEditGameWindow(bui.MainWindow): ][1] def _cancel(self) -> None: - self._completion_call(None) + self._completion_call(None, self) def _check_value_change( self, setting_name: str, widget: bui.Widget, value: int @@ -607,7 +624,7 @@ class PlaylistEditGameWindow(bui.MainWindow): return {'settings': settings} def _add(self) -> None: - self._completion_call(copy.deepcopy(self._getconfig())) + self._completion_call(self._getconfig(), self) def _inc( self, diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py b/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py index 6b7fc547..6383945d 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py @@ -5,7 +5,7 @@ from __future__ import annotations import math -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, override import bauiv1 as bui @@ -24,9 +24,10 @@ class PlaylistMapSelectWindow(bui.MainWindow): sessiontype: type[bs.Session], config: dict[str, Any], edit_info: dict[str, Any], - completion_call: Callable[[dict[str, Any] | None], Any], + completion_call: Callable[[dict[str, Any] | None, bui.MainWindow], Any], transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, + select_get_more_maps_button: bool = False, ): # pylint: disable=too-many-locals @@ -38,6 +39,7 @@ class PlaylistMapSelectWindow(bui.MainWindow): self._completion_call = completion_call self._edit_info = edit_info self._maps: list[tuple[str, bui.Texture]] = [] + self._selected_get_more_maps = False try: self._previous_map = get_filtered_map_name( config['settings']['map'] @@ -114,7 +116,34 @@ class PlaylistMapSelectWindow(bui.MainWindow): bui.containerwidget(edit=self._scrollwidget, claims_left_right=True) self._subcontainer: bui.Widget | None = None - self._refresh() + self._refresh(select_get_more_maps_button=select_get_more_maps_button) + + @override + def get_main_window_state(self) -> bui.MainWindowState: + # Support recreating our window for back/refresh purposes. + cls = type(self) + + # Pull things out of self here; if we do it in the lambda we'll + # keep ourself alive. + gametype = self._gametype + sessiontype = self._sessiontype + config = self._config + edit_info = self._edit_info + completion_call = self._completion_call + select_get_more_maps = self._selected_get_more_maps + + return bui.BasicMainWindowState( + create_call=lambda transition, origin_widget: cls( + transition=transition, + origin_widget=origin_widget, + gametype=gametype, + sessiontype=sessiontype, + config=config, + edit_info=edit_info, + completion_call=completion_call, + select_get_more_maps_button=select_get_more_maps, + ) + ) def _refresh(self, select_get_more_maps_button: bool = False) -> None: # pylint: disable=too-many-statements @@ -255,21 +284,32 @@ class PlaylistMapSelectWindow(bui.MainWindow): from bauiv1lib import account from bauiv1lib.store.browser import StoreBrowserWindow + # No-op if we're not in control. + if not self.main_window_has_control(): + return + plus = bui.app.plus assert plus is not None if plus.get_v1_account_state() != 'signed_in': account.show_sign_in_prompt() return - StoreBrowserWindow( - modal=True, - show_tab=StoreBrowserWindow.TabID.MAPS, - on_close_call=self._on_store_close, - origin_widget=self._get_more_maps_button, + + self._selected_get_more_maps = True + + self.main_window_replace( + StoreBrowserWindow( + # modal=True, + show_tab=StoreBrowserWindow.TabID.MAPS, + # on_close_call=self._on_store_close, + origin_widget=self._get_more_maps_button, + minimal_toolbars=True, + ) ) - def _on_store_close(self) -> None: - self._refresh(select_get_more_maps_button=True) + # def _on_store_close(self) -> None: + # pass + # self._refresh(select_get_more_maps_button=True) def _select(self, map_name: str) -> None: # from bauiv1lib.playlist.editgame import PlaylistEditGameWindow diff --git a/src/assets/ba_data/python/bauiv1lib/store/browser.py b/src/assets/ba_data/python/bauiv1lib/store/browser.py index f176e7c8..74d4a60d 100644 --- a/src/assets/ba_data/python/bauiv1lib/store/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/store/browser.py @@ -41,11 +41,12 @@ class StoreBrowserWindow(bui.MainWindow): def __init__( self, transition: str | None = 'in_right', - modal: bool = False, + # modal: bool = False, show_tab: StoreBrowserWindow.TabID | None = None, - on_close_call: Callable[[], Any] | None = None, - back_location: str | None = None, + # on_close_call: Callable[[], Any] | None = None, + # back_location: str | None = None, origin_widget: bui.Widget | None = None, + minimal_toolbars: bool = False, ): # pylint: disable=too-many-statements # pylint: disable=too-many-locals @@ -59,19 +60,19 @@ class StoreBrowserWindow(bui.MainWindow): bui.set_analytics_screen('Store Window') # Need to store this ourself for modal mode. - if origin_widget is not None: - self._transition_out = 'out_scale' - else: - self._transition_out = 'out_right' + # if origin_widget is not None: + # self._transition_out = 'out_scale' + # else: + # self._transition_out = 'out_right' self.button_infos: dict[str, dict[str, Any]] | None = None self.update_buttons_timer: bui.AppTimer | None = None self._status_textwidget_update_timer = None - self._back_location = back_location - self._on_close_call = on_close_call + # self._back_location = back_location + # self._on_close_call = on_close_call self._show_tab = show_tab - self._modal = modal + # self._modal = modal self._width = 1670 if uiscale is bui.UIScale.SMALL else 1040 self._x_inset = x_inset = 310 if uiscale is bui.UIScale.SMALL else 0 self._height = ( @@ -91,7 +92,7 @@ class StoreBrowserWindow(bui.MainWindow): size=(self._width, self._height + extra_top), toolbar_visibility=( 'menu_store' - if uiscale is bui.UIScale.SMALL + if (uiscale is bui.UIScale.SMALL or minimal_toolbars) else 'menu_full' ), scale=( @@ -115,15 +116,15 @@ class StoreBrowserWindow(bui.MainWindow): size=(140, 60), scale=1.1, autoselect=True, - label=bui.Lstr(resource='doneText' if self._modal else 'backText'), - button_type=None if self._modal else 'back', - on_activate_call=self._back, + label=bui.Lstr(resource='backText'), + button_type='back', + on_activate_call=self.main_window_back, ) if uiscale is bui.UIScale.SMALL: self._back_button.delete() bui.containerwidget( - edit=self._root_widget, on_cancel_call=self._back + edit=self._root_widget, on_cancel_call=self.main_window_back ) backbuttonspecial = True else: @@ -163,7 +164,7 @@ class StoreBrowserWindow(bui.MainWindow): maxwidth=290, ) - if not self._modal and not backbuttonspecial: + if not backbuttonspecial: bui.buttonwidget( edit=self._back_button, button_type='backSmall', @@ -1251,23 +1252,23 @@ class StoreBrowserWindow(bui.MainWindow): except Exception: logging.exception('Error restoring state for %s.', self) - def _back(self) -> None: + # def _back(self) -> None: - if self._modal: - # no-op if our underlying widget is dead or on its way out. - if not self._root_widget or self._root_widget.transitioning_out: - return - self._save_state() - bui.containerwidget( - edit=self._root_widget, transition=self._transition_out - ) - else: - # no-op if we're not currently in control. - if not self.main_window_has_control(): - return - self.main_window_back() - if self._on_close_call is not None: - self._on_close_call() + # # if self._modal: + # # # no-op if our underlying widget is dead or on its way out. + # # if not self._root_widget or self._root_widget.transitioning_out: + # # return + # # self._save_state() + # # bui.containerwidget( + # # edit=self._root_widget, transition=self._transition_out + # # ) + # # else: + # # no-op if we're not currently in control. + # if not self.main_window_has_control(): + # return + # self.main_window_back() + # # if self._on_close_call is not None: + # # self._on_close_call() def _check_merch_availability_in_bg_thread() -> None: diff --git a/src/assets/ba_data/python/bauiv1lib/store/button.py b/src/assets/ba_data/python/bauiv1lib/store/button.py index f2050352..5571fef1 100644 --- a/src/assets/ba_data/python/bauiv1lib/store/button.py +++ b/src/assets/ba_data/python/bauiv1lib/store/button.py @@ -229,14 +229,18 @@ class StoreButton: def _default_on_activate_call(self) -> None: # pylint: disable=cyclic-import from bauiv1lib.account import show_sign_in_prompt - from bauiv1lib.store.browser import StoreBrowserWindow + + # from bauiv1lib.store.browser import StoreBrowserWindow plus = bui.app.plus assert plus is not None if plus.get_v1_account_state() != 'signed_in': show_sign_in_prompt() return - StoreBrowserWindow(modal=True, origin_widget=self._button) + + raise RuntimeError('no longer wired up') + + # StoreBrowserWindow(modal=True, origin_widget=self._button) def get_button(self) -> bui.Widget: """Return the underlying button widget.""" diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 45b5bcd9..61464f5a 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -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 = 21978; +const int kEngineBuildNumber = 21980; const char* kEngineVersion = "1.7.37"; const int kEngineApiVersion = 9; From 8a35969fc0498a09b1154808679aa5e5a3027742 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 3 Sep 2024 16:08:32 -0700 Subject: [PATCH 3/5] wired up game-controller config for the new MainWindow system --- .efrocachemap | 56 ++--- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- .../ba_data/python/bauiv1/_appsubsystem.py | 4 +- src/assets/ba_data/python/bauiv1/_uitypes.py | 8 +- .../python/bauiv1lib/gather/privatetab.py | 3 - .../python/bauiv1lib/settings/gamepad.py | 78 +++---- .../bauiv1lib/settings/gamepadselect.py | 211 +++++++++--------- src/ballistica/shared/ballistica.cc | 2 +- 9 files changed, 183 insertions(+), 183 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 209822f2..ae335fa3 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -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": "b4a141253c7e65acf25669015d739dc8", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "66dd516f011240f4bd89d960747f5306", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "7467a00e52c02904d385a9f03cb938c1", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "bff07f7aaba6de3994093450f6b7652e", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "e4264a74c5197c903ced0f9fad9f358f", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0b2b7ffdcba7fce08115d60f46907dd3", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2b6bedf49d78797be81a3a91a40faea4", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "8a83499d274108ac181c8709cfecebcc", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "ac51052669f94969d50c32c3bb5faa39", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "0de05110dc0d73c578f1ee90098d062f", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "29536a3ccaa1373662a9ad61d15ea311", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "56d6bd161d82ff248b1389c83dbc1a9e", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "8cfafd625e0744cc1cd6a825d4192d6b", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "5673525e6591eed323a574dbc4e053cd", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "fef949796918e90da2c867d212923fc5", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "2c5b61d0105dc5c2c0d69fee4de0b3bb", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "27084c4785c00b0b47348a7ea2121df4", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "b474ebbbd3498bfbbf7ade35bf4e3273", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9d364f0f8023699a7f4c14ee4f1f80a2", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e8b7846713d5aca5a9a472652b49bced", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "fdb570ca6bdd3b6d99ce8c8d253fb2e3", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "5d4acb829768fdbeabe94131d0483a6a", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "b6627d26b51b581205ce26e493bd190c", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "cbb7d5c3650237e6b442fb2ebda46f1c", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b8b599bf7db21492c4a45e80978b5949", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0d90cea395d9aaaabcd158663225a3dd", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "1564bba0949d9e1aa65f1389cd03c96e", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "2613a1072975508a5123ccd847b6a1c9", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "941b27dafbe60f4a4225ecc2998ce4f6", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "5e95b9923453b0f4b78f9e2a7258c3d5", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "810852a17cf44c522740628fa24f71e8", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "13008f16f21abcfb24262ce2842718dc", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "9af0b5d3b404bd6a00e7405ec28d2f86", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "9316ea6bb849e1f2420fa738ebd51be0", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5c25ed8b51702160adf7f94975333690", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "32cb3de3deccb042d6bc23f9051605db", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "980fabe1caa650ad63e0dfad15aeb681", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "8fa7fd27a3f1cbca84c1e22e899ea82f", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "58b9330de90f5e7dd2f448252a1e5c62", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "ad8711189edb9ac148010d4cb976fedf", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "fa659b5d6119acba6570c92ce4d35ae2", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", @@ -4132,14 +4132,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1659535e95e3047fda529543e265ac97", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "8f7ffb5997d1601d57d71af95584d719", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "cacccdf999c17e285edfb89a830f2286", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "c39508091d106d9fb77fd676a14ae4b1", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "584298e65be570d131f7543744c28b47", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "79a0e0beb67caef006d3ef5d3afa3fae", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "a5520e9b3ba6556412381d179a9e3884", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "5ad1b6928cdb9fb4e0c29f399785f535", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "504cfbf0d946547c3c26bda13afe0833", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "5be7c79fcb8dfefc17234f63094dae1a", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "c61e76677707094a5c476d4bf3b35027", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "1cce083c5562eebc8bab6ecf8154223a", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "2d5421108b9066f34c049fce5f0dec2c", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "149d53a2414c3731e595f5d93dc966cd", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c88b477490ed0e3cf5712cbef3efbe66", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "241bef769bc25143b622da29cd2e7b9d", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "64483ffc9564a7e3f782c26637b0bd4f", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "cb299985623bbcc86015cb103a424ae6", "src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d", diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f1675c1..80fbfb26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.37 (build 21980, api 9, 2024-09-03) +### 1.7.37 (build 21982, api 9, 2024-09-03) - 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. diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 504da6c9..42621884 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21980 +TARGET_BALLISTICA_BUILD = 21982 TARGET_BALLISTICA_VERSION = '1.7.37' diff --git a/src/assets/ba_data/python/bauiv1/_appsubsystem.py b/src/assets/ba_data/python/bauiv1/_appsubsystem.py index d9fc8d41..2e9a5aaa 100644 --- a/src/assets/ba_data/python/bauiv1/_appsubsystem.py +++ b/src/assets/ba_data/python/bauiv1/_appsubsystem.py @@ -346,13 +346,13 @@ class UIV1AppSubsystem(babase.AppSubsystem): """Return whether a main menu window is present.""" return bool(self._main_window_widget) - def clear_main_window(self) -> None: + def clear_main_window(self, transition: str | None = None) -> None: """Clear any existing main window.""" from bauiv1._uitypes import MainWindow main_window = self._main_window() if main_window: - main_window.main_window_close() + main_window.main_window_close(transition=transition) else: # Fallback; if we have a widget but no window, nuke the widget. if self._main_window_widget: diff --git a/src/assets/ba_data/python/bauiv1/_uitypes.py b/src/assets/ba_data/python/bauiv1/_uitypes.py index 2743bde3..69cc8b04 100644 --- a/src/assets/ba_data/python/bauiv1/_uitypes.py +++ b/src/assets/ba_data/python/bauiv1/_uitypes.py @@ -136,7 +136,9 @@ class MainWindow(Window): self.main_window_close() - def main_window_replace(self, new_window: MainWindow) -> None: + def main_window_replace( + self, new_window: MainWindow, back_state: MainWindowState | None = None + ) -> None: """Replace ourself with a new MainWindow.""" # Users should always check main_window_has_control() *before* @@ -161,7 +163,9 @@ class MainWindow(Window): logging.exception('Error in on_main_window_close() for %s.', self) _bauiv1.containerwidget(edit=self._root_widget, transition=transition) - babase.app.ui_v1.set_main_window(new_window, from_window=self) + babase.app.ui_v1.set_main_window( + new_window, from_window=self, back_state=back_state + ) def on_main_window_close(self) -> None: """Called before transitioning out a main window. diff --git a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py index 8681fa12..65854a1a 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py @@ -921,9 +921,6 @@ class PrivateGatherTab(GatherTab): ) def _playlist_press(self) -> None: - # if bool(True): - # bui.screenmessage('UNDER CONSTRUCTION') - # return assert self._host_playlist_button is not None self._state.playlist_select_context = PlaylistSelectContext() diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py index 1a0cba67..6b43edc7 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py @@ -24,20 +24,20 @@ class GamepadSettingsWindow(bui.MainWindow): def __init__( self, - gamepad: bs.InputDevice, - is_main_menu: bool = True, + inputdevice: bs.InputDevice, + modal: bool = False, transition: str = 'in_right', transition_out: str = 'out_right', origin_widget: bui.Widget | None = None, settings: dict | None = None, ): - self._input = gamepad + self._inputdevice = inputdevice # If our input-device went away, just return an empty zombie. - if not self._input: + if not self._inputdevice: return - self._name = self._input.name + self._name = self._inputdevice.name self._r = 'configGamepadWindow' self._transition_out = transition_out @@ -45,7 +45,7 @@ class GamepadSettingsWindow(bui.MainWindow): # We're a secondary gamepad if supplied with settings. self._is_secondary = settings is not None self._ext = '_B' if self._is_secondary else '' - self._is_main_menu = is_main_menu + self._modal = modal self._displayname = self._name self._width = 700 if self._is_secondary else 730 self._height = 440 if self._is_secondary else 450 @@ -63,7 +63,6 @@ class GamepadSettingsWindow(bui.MainWindow): stack_offset=( (-20, -16) if uiscale is bui.UIScale.SMALL else (0, 0) ), - transition=transition, ), transition=transition, origin_widget=origin_widget, @@ -72,6 +71,7 @@ class GamepadSettingsWindow(bui.MainWindow): self._settings: dict[str, int] = {} if not self._is_secondary: self._get_config_mapping() + # Don't ask to config joysticks while we're in here. self._rebuild_ui() @@ -137,7 +137,7 @@ class GamepadSettingsWindow(bui.MainWindow): ]: assert bui.app.classic is not None val = bui.app.classic.get_input_device_mapped_value( - self._input, button, default + self._inputdevice, button, default ) if val != -1: self._settings[button] = val @@ -419,7 +419,7 @@ class GamepadSettingsWindow(bui.MainWindow): def get_input(self) -> bs.InputDevice: """(internal)""" - return self._input + return self._inputdevice def _do_advanced(self) -> None: # pylint: disable=cyclic-import @@ -535,8 +535,8 @@ class GamepadSettingsWindow(bui.MainWindow): def show_secondary_editor(self) -> None: """(internal)""" GamepadSettingsWindow( - self._input, - is_main_menu=False, + self._inputdevice, + modal=True, settings=self._settings, transition='in_scale', transition_out='out_scale', @@ -562,16 +562,16 @@ class GamepadSettingsWindow(bui.MainWindow): assert isinstance(sval2, (int, type(None))) if sval1 is not None and sval2 is not None: return ( - self._input.get_axis_name(sval1) + self._inputdevice.get_axis_name(sval1) + ' / ' - + self._input.get_axis_name(sval2) + + self._inputdevice.get_axis_name(sval2) ) return bui.Lstr(resource=f'{self._r}.unsetText') # If they're looking for triggers. if control in ['triggerRun1' + self._ext, 'triggerRun2' + self._ext]: if control in self._settings: - return self._input.get_axis_name(self._settings[control]) + return self._inputdevice.get_axis_name(self._settings[control]) return bui.Lstr(resource=f'{self._r}.unsetText') # Dead-zone. @@ -592,7 +592,9 @@ class GamepadSettingsWindow(bui.MainWindow): # If *any* dpad buttons are assigned, show only button assignments. if any(b in self._settings for b in dpad_buttons): if control in self._settings: - return self._input.get_button_name(self._settings[control]) + return self._inputdevice.get_button_name( + self._settings[control] + ) return bui.Lstr(resource=f'{self._r}.unsetText') # No dpad buttons - show the dpad number for all 4. @@ -617,7 +619,7 @@ class GamepadSettingsWindow(bui.MainWindow): # Other buttons. if control in self._settings: - return self._input.get_button_name(self._settings[control]) + return self._inputdevice.get_button_name(self._settings[control]) return bui.Lstr(resource=f'{self._r}.unsetText') def _gamepad_event( @@ -694,7 +696,7 @@ class GamepadSettingsWindow(bui.MainWindow): # Now launch the up/down listener. AwaitGamepadInputWindow( - self._input, + self._inputdevice, 'analogStickUD' + ext, self._gamepad_event, bui.Lstr(resource=f'{self._r}.pressUpDownText'), @@ -783,7 +785,7 @@ class GamepadSettingsWindow(bui.MainWindow): edit=btn, on_activate_call=bui.Call( AwaitGamepadInputWindow, - self._input, + self._inputdevice, button, self._gamepad_event, message, @@ -795,16 +797,16 @@ class GamepadSettingsWindow(bui.MainWindow): return btn def _cancel(self) -> None: - # from bauiv1lib.settings.controls import ControlsSettingsWindow # no-op if our underlying widget is dead or on its way out. if not self._root_widget or self._root_widget.transitioning_out: return - bui.containerwidget( - edit=self._root_widget, transition=self._transition_out - ) - if self._is_main_menu: + if self._modal: + bui.containerwidget( + edit=self._root_widget, transition=self._transition_out + ) + else: self.main_window_back() # assert bui.app.classic is not None # bui.app.ui_v1.set_main_window( @@ -899,18 +901,20 @@ class GamepadSettingsWindow(bui.MainWindow): if not self._root_widget or self._root_widget.transitioning_out: return - bui.containerwidget( - edit=self._root_widget, transition=self._transition_out - ) - # If we're a secondary editor we just go away (we were editing our # parent's settings dict). if self._is_secondary: + assert self._modal + bui.containerwidget( + edit=self._root_widget, transition=self._transition_out + ) return assert self._settings is not None - if self._input: - dst = classic.get_input_device_config(self._input, default=True) + if self._inputdevice: + dst = classic.get_input_device_config( + self._inputdevice, default=True + ) dst2: dict[str, Any] = dst[0][dst[1]] dst2.clear() @@ -921,7 +925,7 @@ class GamepadSettingsWindow(bui.MainWindow): # If we're allowed to phone home, send this config so we can # generate more defaults in the future. - inputhash = classic.get_input_device_map_hash(self._input) + inputhash = classic.get_input_device_map_hash(self._inputdevice) classic.master_server_v1_post( 'controllerConfig', { @@ -938,15 +942,13 @@ class GamepadSettingsWindow(bui.MainWindow): else: bui.getsound('error').play() - if self._is_main_menu: - from bauiv1lib.settings.controls import ControlsSettingsWindow - - assert bui.app.classic is not None - bui.app.ui_v1.set_main_window( - ControlsSettingsWindow(transition='in_left'), - from_window=self, - is_back=True, + if self._modal: + bui.containerwidget( + edit=self._root_widget, transition=self._transition_out ) + else: + assert self.main_window_has_control() + self.main_window_back() class AwaitGamepadInputWindow(bui.Window): diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py index 9040c81d..382e353e 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py @@ -4,7 +4,6 @@ from __future__ import annotations -import logging from typing import TYPE_CHECKING, override import bascenev1 as bs @@ -14,107 +13,6 @@ if TYPE_CHECKING: from typing import Any -def gamepad_configure_callback(event: dict[str, Any]) -> None: - """Respond to a gamepad button press during config selection.""" - from bauiv1lib.settings.gamepad import GamepadSettingsWindow - - # Ignore all but button-presses. - if event['type'] not in ['BUTTONDOWN', 'HATMOTION']: - return - bs.release_gamepad_input() - - if bool(True): - bui.screenmessage('UNDER CONSTRUCTION') - return - - assert bui.app.classic is not None - try: - bui.app.ui_v1.clear_main_window() - except Exception: - logging.exception('Error transitioning out main_menu_window.') - bui.getsound('activateBeep').play() - bui.getsound('swish').play() - device = event['input_device'] - assert isinstance(device, bs.InputDevice) - if device.allows_configuring: - bui.app.ui_v1.set_main_window( - GamepadSettingsWindow(device), from_window=None - ) - else: - width = 700 - height = 200 - button_width = 80 - uiscale = bui.app.ui_v1.uiscale - - class _Window(bui.MainWindow): - def __init__(self) -> None: - super().__init__( - root_widget=bui.containerwidget( - scale=( - 1.7 - if uiscale is bui.UIScale.SMALL - else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 - ), - size=(width, height), - ), - transition='in_right', - origin_widget=None, - ) - - win = _Window() - dlg = win.get_root_widget() - - bui.app.ui_v1.set_main_window(win, from_window=None) - - if device.allows_configuring_in_system_settings: - msg = bui.Lstr( - resource='configureDeviceInSystemSettingsText', - subs=[('${DEVICE}', device.name)], - ) - elif device.is_controller_app: - msg = bui.Lstr( - resource='bsRemoteConfigureInAppText', - subs=[('${REMOTE_APP_NAME}', bui.get_remote_app_name())], - ) - else: - msg = bui.Lstr( - resource='cantConfigureDeviceText', - subs=[('${DEVICE}', device.name)], - ) - bui.textwidget( - parent=dlg, - position=(0, height - 80), - size=(width, 25), - text=msg, - scale=0.8, - h_align='center', - v_align='top', - ) - - def _ok() -> None: - from bauiv1lib.settings import controls - - # no-op if our underlying widget is dead or on its way out. - if not dlg or dlg.transitioning_out: - return - - bui.containerwidget(edit=dlg, transition='out_right') - assert bui.app.classic is not None - bui.app.ui_v1.set_main_window( - controls.ControlsSettingsWindow(transition='in_left'), - from_window=win, - is_back=True, - ) - - bui.buttonwidget( - parent=dlg, - position=((width - button_width) / 2, 20), - size=(button_width, 60), - label=bui.Lstr(resource='okText'), - on_activate_call=_ok, - ) - - class GamepadSelectWindow(bui.MainWindow): """Window for selecting a gamepad to configure.""" @@ -155,8 +53,8 @@ class GamepadSelectWindow(bui.MainWindow): on_activate_call=self.main_window_back, ) - # Let's not have anything selected by default; its misleading looking - # for the controller getting configured. + # Let's not have anything selected by default; its misleading + # looking for the controller getting configured. bui.containerwidget( edit=self._root_widget, cancel_button=btn, @@ -207,7 +105,10 @@ class GamepadSelectWindow(bui.MainWindow): v_align='top', ) - bs.capture_gamepad_input(gamepad_configure_callback) + bs.capture_gamepad_input(bui.WeakCall(self.gamepad_configure_callback)) + + def __del__(self) -> None: + bs.release_gamepad_input() @override def get_main_window_state(self) -> bui.MainWindowState: @@ -219,6 +120,102 @@ class GamepadSelectWindow(bui.MainWindow): ) ) - @override - def on_main_window_close(self) -> None: + def gamepad_configure_callback(self, event: dict[str, Any]) -> None: + """Respond to a gamepad button press during config selection.""" + from bauiv1lib.settings.gamepad import GamepadSettingsWindow + + if not self.main_window_has_control(): + return + + # Ignore all but button-presses. + if event['type'] not in ['BUTTONDOWN', 'HATMOTION']: + return bs.release_gamepad_input() + + assert bui.app.classic is not None + + bui.getsound('activateBeep').play() + bui.getsound('swish').play() + device = event['input_device'] + assert isinstance(device, bs.InputDevice) + + # No matter where we redirect to, we want their back + # functionality to skip over us and go to our parent. + assert self.main_window_back_state is not None + back_state = self.main_window_back_state + + if device.allows_configuring: + self.main_window_replace( + GamepadSettingsWindow(device), back_state=back_state + ) + else: + self.main_window_replace( + _NotConfigurableWindow(device), back_state=back_state + ) + + +class _NotConfigurableWindow(bui.MainWindow): + + def __init__(self, device: bs.InputDevice) -> None: + width = 700 + height = 200 + button_width = 80 + uiscale = bui.app.ui_v1.uiscale + super().__init__( + root_widget=bui.containerwidget( + scale=( + 1.7 + if uiscale is bui.UIScale.SMALL + else (1.4 if uiscale is bui.UIScale.MEDIUM else 1.0) + ), + size=(width, height), + ), + transition='in_right', + origin_widget=None, + ) + if device.allows_configuring_in_system_settings: + msg = bui.Lstr( + resource='configureDeviceInSystemSettingsText', + subs=[('${DEVICE}', device.name)], + ) + elif device.is_controller_app: + msg = bui.Lstr( + resource='bsRemoteConfigureInAppText', + subs=[ + ( + '${REMOTE_APP_NAME}', + bui.get_remote_app_name(), + ) + ], + ) + else: + msg = bui.Lstr( + resource='cantConfigureDeviceText', + subs=[('${DEVICE}', device.name)], + ) + bui.textwidget( + parent=self._root_widget, + position=(0, height - 80), + size=(width, 25), + text=msg, + scale=0.8, + h_align='center', + v_align='top', + ) + + btn = bui.buttonwidget( + parent=self._root_widget, + position=((width - button_width) / 2, 20), + size=(button_width, 60), + label=bui.Lstr(resource='okText'), + on_activate_call=self.main_window_back, + ) + bui.containerwidget(edit=self._root_widget, cancel_button=btn) + + # def _ok(self) -> None: + + # # Back would take us to the gamepad-select window. We want to go + # # past that. + # assert self.main_window_back_state is not None + # self.main_window_back_state = self.main_window_back_state.parent + # self.main_window_back() diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 61464f5a..c32fa644 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -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 = 21980; +const int kEngineBuildNumber = 21982; const char* kEngineVersion = "1.7.37"; const int kEngineApiVersion = 9; From 8cd4b2baf2a994f74e050ec4528b6bf77ecf4c83 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 3 Sep 2024 17:26:08 -0700 Subject: [PATCH 4/5] updated touchscreen settings for MainWindow system --- .efrocachemap | 56 ++++----- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- .../python/bauiv1lib/settings/controls.py | 2 +- .../python/bauiv1lib/settings/gamepad.py | 6 +- .../bauiv1lib/settings/gamepadadvanced.py | 2 +- .../python/bauiv1lib/settings/touchscreen.py | 113 ++++++++++-------- .../base/app_adapter/app_adapter_sdl.cc | 11 ++ src/ballistica/shared/ballistica.cc | 2 +- src/ballistica/ui_v1/widget/root_widget.cc | 17 +-- 10 files changed, 121 insertions(+), 92 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index ae335fa3..7ac07183 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -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": "fdb570ca6bdd3b6d99ce8c8d253fb2e3", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "5d4acb829768fdbeabe94131d0483a6a", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "b6627d26b51b581205ce26e493bd190c", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "cbb7d5c3650237e6b442fb2ebda46f1c", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b8b599bf7db21492c4a45e80978b5949", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0d90cea395d9aaaabcd158663225a3dd", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "1564bba0949d9e1aa65f1389cd03c96e", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "2613a1072975508a5123ccd847b6a1c9", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "941b27dafbe60f4a4225ecc2998ce4f6", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "5e95b9923453b0f4b78f9e2a7258c3d5", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "810852a17cf44c522740628fa24f71e8", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "13008f16f21abcfb24262ce2842718dc", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "9af0b5d3b404bd6a00e7405ec28d2f86", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "9316ea6bb849e1f2420fa738ebd51be0", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5c25ed8b51702160adf7f94975333690", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "32cb3de3deccb042d6bc23f9051605db", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "980fabe1caa650ad63e0dfad15aeb681", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "8fa7fd27a3f1cbca84c1e22e899ea82f", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "58b9330de90f5e7dd2f448252a1e5c62", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "ad8711189edb9ac148010d4cb976fedf", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "dd3351f875c7f1ebc7475e1878e3b70b", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "54594112bc57bde0a84827f038327c88", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "4105f2bc300954c2b0f1ca02de22cd8a", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "223df1db2bcad539caea58ed6c74e247", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "da8ba45943d195a5bfa7a030fba42eb7", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "fc4ead0d2002ed11253183855e92a560", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "da7ef6205bada0a9fbca9c2fe6d2c9e6", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "6963b73b5b89bd4099493af0e0629e9b", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "cde4c77485a8d9fd72fc8faded5d756f", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "d7eac32efd5f57d914965cdfbfbbf968", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "dc2f9c4b9bde148c373652c3444a4b75", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "99171bfb206814bed28da7358b1462de", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "76885f2221f179a2bbecff0751080bcd", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "e9d613fb41c03077b1f4b93d75688d80", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "33aa23a5329d7d157a70267f52225c75", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "c1e1e2dc90aefc8270fe1dd63b2d4ba3", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "7e8e8ba464ba64c902638f77c3351bba", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "5b507d73207dc1a57b8061ff840f2f78", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "8228a25a276514280da9bfbea119a65f", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "1a3ac3f388b47c55f75c2da9704dd5b8", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "fa659b5d6119acba6570c92ce4d35ae2", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", @@ -4132,14 +4132,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1659535e95e3047fda529543e265ac97", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "5be7c79fcb8dfefc17234f63094dae1a", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "c61e76677707094a5c476d4bf3b35027", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "1cce083c5562eebc8bab6ecf8154223a", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "2d5421108b9066f34c049fce5f0dec2c", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "149d53a2414c3731e595f5d93dc966cd", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c88b477490ed0e3cf5712cbef3efbe66", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "241bef769bc25143b622da29cd2e7b9d", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "64483ffc9564a7e3f782c26637b0bd4f", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "18baa99704381be8e41a25076ec17383", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "0e7adfb8137919457c7e696e47c98fc9", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "777ca0e814594195eafea61fa4ecda74", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "b77bdd35d833f6edd4f4346d8adb8ac6", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "6b2510a269eb6c28d853e27c38175994", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "f6841f5b2c28d33a27b0c3edbffbe01e", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "b24527db115dbf53f3c5795381e2cd4c", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "f7dde79d60634436528e8d2cf6f952e7", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "cb299985623bbcc86015cb103a424ae6", "src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d", diff --git a/CHANGELOG.md b/CHANGELOG.md index 80fbfb26..7ef47677 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.37 (build 21982, api 9, 2024-09-03) +### 1.7.37 (build 21983, api 9, 2024-09-03) - 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. diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 42621884..92294ff1 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21982 +TARGET_BALLISTICA_BUILD = 21983 TARGET_BALLISTICA_VERSION = '1.7.37' diff --git a/src/assets/ba_data/python/bauiv1lib/settings/controls.py b/src/assets/ba_data/python/bauiv1lib/settings/controls.py index 85620b48..5ee43fa1 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/controls.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/controls.py @@ -105,7 +105,7 @@ class ControlsSettingsWindow(bui.MainWindow): height += spacing assert bui.app.classic is not None - smallscale = 1.7 if show_keyboard else 2.2 + smallscale = 1.7 super().__init__( root_widget=bui.containerwidget( size=(width, height), diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py index 6b43edc7..962eb3ad 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py @@ -56,12 +56,12 @@ class GamepadSettingsWindow(bui.MainWindow): root_widget=bui.containerwidget( size=(self._width, self._height), scale=( - 1.63 + 1.4 if uiscale is bui.UIScale.SMALL - else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 + else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 ), stack_offset=( - (-20, -16) if uiscale is bui.UIScale.SMALL else (0, 0) + (0, -10) if uiscale is bui.UIScale.SMALL else (0, 0) ), ), transition=transition, diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py index 7ac9b807..7db6b2e7 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py @@ -40,7 +40,7 @@ class GamepadAdvancedSettingsWindow(bui.Window): size=(self._width, self._height), scale=1.06 * ( - 1.85 + 1.6 if uiscale is bui.UIScale.SMALL else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 ), diff --git a/src/assets/ba_data/python/bauiv1lib/settings/touchscreen.py b/src/assets/ba_data/python/bauiv1lib/settings/touchscreen.py index ea965829..ad8195a7 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/touchscreen.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/touchscreen.py @@ -13,11 +13,6 @@ class TouchscreenSettingsWindow(bui.MainWindow): """Settings window for touchscreens.""" def __del__(self) -> None: - # Note - this happens in 'back' too; - # we just do it here too in case the window is closed by other means. - - # FIXME: Could switch to a UI destroy callback now that those are a - # thing that exists. bs.set_touchscreen_editing(False) def __init__( @@ -25,9 +20,9 @@ class TouchscreenSettingsWindow(bui.MainWindow): transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, ) -> None: - self._width = 650 + self._width = 780 self._height = 380 - self._spacing = 40 + # self._spacing = 40 self._r = 'configTouchscreenWindow' bs.set_touchscreen_editing(True) @@ -42,25 +37,38 @@ class TouchscreenSettingsWindow(bui.MainWindow): if uiscale is bui.UIScale.SMALL else 1.55 if uiscale is bui.UIScale.MEDIUM else 1.2 ), + toolbar_visibility=( + 'menu_minimal' + if uiscale is bui.UIScale.SMALL + else 'menu_full' + ), + stack_offset=( + (0, -20) if uiscale is bui.UIScale.SMALL else (0, 0) + ), ), transition=transition, origin_widget=origin_widget, ) - btn = bui.buttonwidget( - parent=self._root_widget, - position=(55, self._height - 60), - size=(120, 60), - label=bui.Lstr(resource='backText'), - button_type='back', - scale=0.8, - on_activate_call=self._back, - ) - bui.containerwidget(edit=self._root_widget, cancel_button=btn) + if uiscale is bui.UIScale.SMALL: + bui.containerwidget( + edit=self._root_widget, on_cancel_call=self.main_window_back + ) + else: + btn = bui.buttonwidget( + parent=self._root_widget, + position=(55, self._height - 60), + size=(60, 60), + label=bui.charstr(bui.SpecialChar.BACK), + button_type='backSmall', + scale=0.8, + on_activate_call=self.main_window_back, + ) + bui.containerwidget(edit=self._root_widget, cancel_button=btn) bui.textwidget( parent=self._root_widget, - position=(25, self._height - 50), + position=(25, self._height - 57), size=(self._width, 25), text=bui.Lstr(resource=f'{self._r}.titleText'), color=bui.app.ui_v1.title_color, @@ -69,13 +77,6 @@ class TouchscreenSettingsWindow(bui.MainWindow): v_align='center', ) - bui.buttonwidget( - edit=btn, - button_type='backSmall', - size=(60, 60), - label=bui.charstr(bui.SpecialChar.BACK), - ) - self._scroll_width = self._width - 100 self._scroll_height = self._height - 110 self._sub_width = self._scroll_width - 20 @@ -113,6 +114,7 @@ class TouchscreenSettingsWindow(bui.MainWindow): ) def _build_gui(self) -> None: + # pylint: disable=too-many-locals from bauiv1lib.config import ConfigNumberEdit, ConfigCheckBox from bauiv1lib.radiogroup import make_radio_group @@ -121,13 +123,16 @@ class TouchscreenSettingsWindow(bui.MainWindow): for child in children: child.delete() h = 30 + hoffs = 100 + hoffs2 = 70 + hoffs3 = 320 v = self._sub_height - 85 clr = (0.8, 0.8, 0.8, 1.0) clr2 = (0.8, 0.8, 0.8) bui.textwidget( parent=self._subcontainer, - position=(-10, v + 43), - size=(self._sub_width, 25), + position=(self._sub_width * 0.5, v + 63), + size=(0, 0), text=bui.Lstr(resource=f'{self._r}.swipeInfoText'), flatness=1.0, color=(0, 0.9, 0.1, 0.7), @@ -148,7 +153,7 @@ class TouchscreenSettingsWindow(bui.MainWindow): ) cb1 = bui.checkboxwidget( parent=self._subcontainer, - position=(h + 220, v), + position=(h + hoffs + 220, v), size=(170, 30), text=bui.Lstr(resource=f'{self._r}.joystickText'), maxwidth=100, @@ -157,7 +162,7 @@ class TouchscreenSettingsWindow(bui.MainWindow): ) cb2 = bui.checkboxwidget( parent=self._subcontainer, - position=(h + 357, v), + position=(h + hoffs + 357, v), size=(170, 30), text=bui.Lstr(resource=f'{self._r}.swipeText'), maxwidth=100, @@ -172,7 +177,7 @@ class TouchscreenSettingsWindow(bui.MainWindow): ConfigNumberEdit( parent=self._subcontainer, position=(h, v), - xoffset=65, + xoffset=hoffs2 + 65, configkey='Touch Controls Scale Movement', displayname=bui.Lstr( resource=f'{self._r}.movementControlScaleText' @@ -195,7 +200,7 @@ class TouchscreenSettingsWindow(bui.MainWindow): ) cb1 = bui.checkboxwidget( parent=self._subcontainer, - position=(h + 220, v), + position=(h + hoffs + 220, v), size=(170, 30), text=bui.Lstr(resource=f'{self._r}.buttonsText'), maxwidth=100, @@ -204,7 +209,7 @@ class TouchscreenSettingsWindow(bui.MainWindow): ) cb2 = bui.checkboxwidget( parent=self._subcontainer, - position=(h + 357, v), + position=(h + hoffs + 357, v), size=(170, 30), text=bui.Lstr(resource=f'{self._r}.swipeText'), maxwidth=100, @@ -218,7 +223,7 @@ class TouchscreenSettingsWindow(bui.MainWindow): ConfigNumberEdit( parent=self._subcontainer, position=(h, v), - xoffset=65, + xoffset=hoffs2 + 65, configkey='Touch Controls Scale Actions', displayname=bui.Lstr(resource=f'{self._r}.actionControlScaleText'), changesound=False, @@ -228,13 +233,23 @@ class TouchscreenSettingsWindow(bui.MainWindow): ) v -= 50 + bui.textwidget( + parent=self._subcontainer, + position=(h, v - 2), + size=(0, 30), + text=bui.Lstr(resource=f'{self._r}.swipeControlsHiddenText'), + maxwidth=190, + color=clr, + v_align='center', + ) + ConfigCheckBox( parent=self._subcontainer, - position=(h, v), - size=(400, 30), + position=(h + hoffs3, v), + size=(100, 30), maxwidth=400, configkey='Touch Controls Swipe Hidden', - displayname=bui.Lstr(resource=f'{self._r}.swipeControlsHiddenText'), + displayname='', ) v -= 65 @@ -288,18 +303,18 @@ class TouchscreenSettingsWindow(bui.MainWindow): cfg.apply_and_commit() bui.apptimer(0, self._build_gui) - def _back(self) -> None: - from bauiv1lib.settings import controls + # def _back(self) -> None: + # from bauiv1lib.settings import controls - # no-op if our underlying widget is dead or on its way out. - if not self._root_widget or self._root_widget.transitioning_out: - return + # # no-op if our underlying widget is dead or on its way out. + # if not self._root_widget or self._root_widget.transitioning_out: + # return - bui.containerwidget(edit=self._root_widget, transition='out_right') - assert bui.app.classic is not None - bui.app.ui_v1.set_main_window( - controls.ControlsSettingsWindow(transition='in_left'), - from_window=self, - is_back=True, - ) - bs.set_touchscreen_editing(False) + # bui.containerwidget(edit=self._root_widget, transition='out_right') + # assert bui.app.classic is not None + # bui.app.ui_v1.set_main_window( + # controls.ControlsSettingsWindow(transition='in_left'), + # from_window=self, + # is_back=True, + # ) + # bs.set_touchscreen_editing(False) diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.cc b/src/ballistica/base/app_adapter/app_adapter_sdl.cc index d574f665..b5422f1a 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -585,6 +585,17 @@ void AppAdapterSDL::RemoveSDLInputDevice_(int index) { assert(g_core->InMainThread()); assert(index >= 0); JoystickInput* j = GetSDLJoystickInput_(index); + + // Note: am running into this with a PS5 controller on macOS Sequoia beta. + if (!j) { + Log(LogLevel::kError, + "GetSDLJoystickInput_() returned nullptr on RemoveSDLInputDevice_();" + " joysticks size is " + + std::to_string(sdl_joysticks_.size()) + "; index is " + + std::to_string(index)); + return; + } + assert(j); if (static_cast_check_fit(sdl_joysticks_.size()) > index) { sdl_joysticks_[index] = nullptr; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index c32fa644..5274e203 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -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 = 21982; +const int kEngineBuildNumber = 21983; const char* kEngineVersion = "1.7.37"; const int kEngineApiVersion = 9; diff --git a/src/ballistica/ui_v1/widget/root_widget.cc b/src/ballistica/ui_v1/widget/root_widget.cc index b82ac95f..b1d5324b 100644 --- a/src/ballistica/ui_v1/widget/root_widget.cc +++ b/src/ballistica/ui_v1/widget/root_widget.cc @@ -967,9 +967,12 @@ void RootWidget::Setup() { // AddCover(0.5f, VAlign::kBottom, 0.0f, -180.0f, 600.0f, 550.0f, // 0.35f); - float backingR = 0.44f; - float backingG = 0.41f; - float backingB = 0.56f; + float backingR = 0.4f; + float backingG = 0.38f; + float backingB = 0.53f; + // float backingR = 0.44f; + // float backingG = 0.41f; + // float backingB = 0.56f; float backingCoverR = backingR; float backingCoverG = backingG; float backingCoverB = backingB; @@ -997,8 +1000,8 @@ void RootWidget::Setup() { ButtonDef bd; bd.h_align = 0.5f; bd.v_align = VAlign::kBottom; - bd.width = 550.0f; - bd.height = 110.0f; + bd.width = 500.0f; + bd.height = 100.0f; bd.x = 0.0f; bd.y = 41.0f; bd.img = "uiAtlas2"; @@ -1023,7 +1026,7 @@ void RootWidget::Setup() { ButtonDef b; b.h_align = 0.5f; b.v_align = VAlign::kBottom; - b.width = b.height = 120.0f; + b.width = b.height = 110.0f; b.x = 0.0f; b.y = b.height * 0.4f; b.img = "chestIcon"; @@ -1032,7 +1035,7 @@ void RootWidget::Setup() { (static_cast(Widget::ToolbarVisibility::kMenuFull) | static_cast(Widget::ToolbarVisibility::kMenuFullNoBack) | static_cast(Widget::ToolbarVisibility::kMenuFullRoot)); - float spacing = 130.0f; + float spacing = 120.0f; b.x = -1.5f * spacing; b.call = UIV1Python::ObjID::kRootUIChestSlot1PressCall; b.allow_in_game = false; From 5b6b2455c9941a4b116d64bc8057e7db00f1ae09 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 3 Sep 2024 19:23:22 -0700 Subject: [PATCH 5/5] tidying --- .efrocachemap | 56 ++++++++++---------- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/shared/ballistica.cc | 2 +- src/ballistica/ui_v1/widget/root_widget.cc | 61 ++++++++++++---------- 5 files changed, 63 insertions(+), 60 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 7ac07183..d46eace5 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -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": "dd3351f875c7f1ebc7475e1878e3b70b", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "54594112bc57bde0a84827f038327c88", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "4105f2bc300954c2b0f1ca02de22cd8a", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "223df1db2bcad539caea58ed6c74e247", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "da8ba45943d195a5bfa7a030fba42eb7", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "fc4ead0d2002ed11253183855e92a560", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "da7ef6205bada0a9fbca9c2fe6d2c9e6", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "6963b73b5b89bd4099493af0e0629e9b", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "cde4c77485a8d9fd72fc8faded5d756f", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "d7eac32efd5f57d914965cdfbfbbf968", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "dc2f9c4b9bde148c373652c3444a4b75", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "99171bfb206814bed28da7358b1462de", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "76885f2221f179a2bbecff0751080bcd", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "e9d613fb41c03077b1f4b93d75688d80", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "33aa23a5329d7d157a70267f52225c75", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "c1e1e2dc90aefc8270fe1dd63b2d4ba3", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "7e8e8ba464ba64c902638f77c3351bba", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "5b507d73207dc1a57b8061ff840f2f78", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "8228a25a276514280da9bfbea119a65f", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "1a3ac3f388b47c55f75c2da9704dd5b8", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "a0e1890fc3d156a1d480e7cbba7295bd", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "2ea3ddfd5280b5fa721a82286767208a", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f9860dbec27801cf8b24c3b42e0b62bd", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "a53de05a4a3c3c2e766f488b0b53230d", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "43485a1c27605267ee83d27961b61017", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "65fe6d346dfd844925a07278a73bbb39", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "bc277e964bc08d0bd086f836732901f8", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "738e76cf0dc643a016f16f94503767db", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "949fd54340bc597c19ada580f59c30a9", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "f0f1037044f841e6817e970ba67f3c02", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "3990893e788968fe74e98aa419f28397", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0c5fbd4cd45f944f02d7482e08d4b5d5", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "c39bcf72ef41865429f3df1d3ad586d0", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "37cb193fec5c61443fafa24d3ae96447", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "e454f30500a3ef2c0e4248388338db89", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ddb81916ad653ccb38be9ffc9f98e7f3", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "18766baaa9e1a23e785aceb9f6be0d3a", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "b687f66795a831f0dfd7e15aa7a908b2", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "146168838c8e9cdbd5c016772b68e91a", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "f0ee92768afe3211aeab356539d58876", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "fa659b5d6119acba6570c92ce4d35ae2", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", @@ -4132,14 +4132,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1659535e95e3047fda529543e265ac97", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "18baa99704381be8e41a25076ec17383", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "0e7adfb8137919457c7e696e47c98fc9", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "777ca0e814594195eafea61fa4ecda74", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "b77bdd35d833f6edd4f4346d8adb8ac6", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "6b2510a269eb6c28d853e27c38175994", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "f6841f5b2c28d33a27b0c3edbffbe01e", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "b24527db115dbf53f3c5795381e2cd4c", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "f7dde79d60634436528e8d2cf6f952e7", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "07c51c6015b17d6ad2e32ac6bad9aaee", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "d9dc89c65a1f5ae3a0a4e25636129bb7", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "8afac2e5edb1586137c60ce1d4829d0a", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "c9bfc854e52b6d2270d748ce80f45342", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "ec65affda58721c395d5188810195443", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e16447cfaffecc545ae970aff2f09d16", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1f5ba81d75d56eb680bb7f3aefaae5b6", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "44bc0d1aab93081db335ebd837f44632", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "cb299985623bbcc86015cb103a424ae6", "src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d", diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ef47677..c993e272 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.37 (build 21983, api 9, 2024-09-03) +### 1.7.37 (build 21985, api 9, 2024-09-03) - 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. diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 92294ff1..f2c1fae8 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21983 +TARGET_BALLISTICA_BUILD = 21985 TARGET_BALLISTICA_VERSION = '1.7.37' diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 5274e203..9086c601 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -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 = 21983; +const int kEngineBuildNumber = 21985; const char* kEngineVersion = "1.7.37"; const int kEngineApiVersion = 9; diff --git a/src/ballistica/ui_v1/widget/root_widget.cc b/src/ballistica/ui_v1/widget/root_widget.cc index b1d5324b..ef24309c 100644 --- a/src/ballistica/ui_v1/widget/root_widget.cc +++ b/src/ballistica/ui_v1/widget/root_widget.cc @@ -967,31 +967,31 @@ void RootWidget::Setup() { // AddCover(0.5f, VAlign::kBottom, 0.0f, -180.0f, 600.0f, 550.0f, // 0.35f); - float backingR = 0.4f; - float backingG = 0.38f; - float backingB = 0.53f; + float backing_r = 0.43f; + float backing_g = 0.40f; + float backing_b = 0.53f; // float backingR = 0.44f; // float backingG = 0.41f; // float backingB = 0.56f; - float backingCoverR = backingR; - float backingCoverG = backingG; - float backingCoverB = backingB; + float backing_cover_r = backing_r; + float backing_cover_g = backing_g; + float backing_cover_b = backing_b; float backingA = 1.0f; if (g_base->ui->scale() != UIScale::kSmall) { - backingR *= TOOLBAR_COLOR_R * TOOLBAR_BACK_COLOR_R; - backingG *= TOOLBAR_COLOR_G * TOOLBAR_BACK_COLOR_G; - backingB *= TOOLBAR_COLOR_B * TOOLBAR_BACK_COLOR_B; - backingCoverR *= TOOLBAR_COLOR_R; - backingCoverG *= TOOLBAR_COLOR_G; - backingCoverB *= TOOLBAR_COLOR_B; + backing_r *= TOOLBAR_COLOR_R * TOOLBAR_BACK_COLOR_R; + backing_g *= TOOLBAR_COLOR_G * TOOLBAR_BACK_COLOR_G; + backing_b *= TOOLBAR_COLOR_B * TOOLBAR_BACK_COLOR_B; + backing_cover_r *= TOOLBAR_COLOR_R; + backing_cover_g *= TOOLBAR_COLOR_G; + backing_cover_b *= TOOLBAR_COLOR_B; backingA *= TOOLBAR_OPACITY; } else { - backingR *= 1.1f; - backingG *= 1.1f; - backingB *= 1.1f; - backingCoverR *= 1.1f; - backingCoverG *= 1.1f; - backingCoverB *= 1.1f; + backing_r *= 1.1f; + backing_g *= 1.1f; + backing_b *= 1.1f; + backing_cover_r *= 1.1f; + backing_cover_g *= 1.1f; + backing_cover_b *= 1.1f; backingA *= TOOLBAR_OPACITY_2; } @@ -1007,9 +1007,9 @@ void RootWidget::Setup() { bd.img = "uiAtlas2"; bd.mesh_transparent = "toolbarBackingBottom2"; bd.selectable = false; - bd.color_r = backingR; - bd.color_g = backingG; - bd.color_b = backingB; + bd.color_r = backing_r; + bd.color_g = backing_g; + bd.color_b = backing_b; bd.opacity = backingA; bd.depth_min = 0.2f; @@ -1041,22 +1041,25 @@ void RootWidget::Setup() { b.allow_in_game = false; AddButton_(b); - b.x = -0.5f * spacing; - b.img = "chestOpenIcon"; - b.y = b.height * 0.5f; - b.call = UIV1Python::ObjID::kRootUIChestSlot2PressCall; - AddButton_(b); + // b.x = -0.5f * spacing; + // b.img = "chestOpenIcon"; + // b.y = b.height * 0.5f; + // b.call = UIV1Python::ObjID::kRootUIChestSlot2PressCall; + // AddButton_(b); // test - empty icons b.y = b.height * 0.4f; b.x = 0.5f * spacing; b.img = "chestIconEmpty"; b.width = b.height = 80.0f; - b.color_r = backingCoverR; - b.color_g = backingCoverG; - b.color_b = backingCoverB; + b.color_r = backing_cover_r; + b.color_g = backing_cover_g; + b.color_b = backing_cover_b; b.opacity = 1.0f; b.call = UIV1Python::ObjID::kRootUIChestSlot3PressCall; + b.x = -0.5f * spacing; + AddButton_(b); + b.x = 0.5f * spacing; AddButton_(b); b.x = 1.5f * spacing; b.call = UIV1Python::ObjID::kRootUIChestSlot4PressCall;