diff --git a/.efrocachemap b/.efrocachemap index cb49f047f..b13b239e9 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4103,22 +4103,22 @@ "build/assets/windows/Win32/ucrtbased.dll": "bfd1180c269d3950b76f35a63655e9e1", "build/assets/windows/Win32/vc_redist.x86.exe": "15a5f1f876503885adbdf5b3989b3718", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "831d5f904fef843b966d8e7660c8c310", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "2cbfc93f4523729dee68b1db2cf09c10", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "64a2a607a99a8a89df83e95441bc9361", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "a0fac95c32f3b78e268ce11634728436", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "f706f7873d2b6954b08fe481b1e13704", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "9f9becc6d5ce6960210c65fc1004c8d6", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "fceb974dfa1ed9e6eed0b28658d80d6e", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "ed386560c3fc4de94119b47eda30e723", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "780ab5c3146085919b070198aa752f0b", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "c14f0240b1fd17be3f52823e37e2c2af", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b630856a0a5153a2766772d4c6d6657f", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "ebdc492db21008db802180853df82f25", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "7220f0036f22a8107110b1c02ebbdc6e", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "167a2273b849e53d77b0f03814c7c5b0", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "628ac9a71589d60aa1db1cede931f4a2", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "d1091a830960c56677c1a1141a543ce8", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "aaaf15a8a3968a5f9c99d242f5384857", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "9864117215a88d0434d153e3840323fc", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "6bfaafce85f68dbd631a6bf5d71be6c7", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "1b3a9671e0ec25d4d4f4312939e45f2a", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "85facaa825957bfdb3971220033b77c8", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "3ac89f516eca7a337b351aad780e5fec", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "6b7fa3e1615f004d7db2624174406baf", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "3277dcd7907ae9cdb9d71a6ab55203eb", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "b88dc886212e085e2c3f2c60497b6e9e", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "0ca8ee17ea6c20b955f09e06586dd03e", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d2e0005fbeb6cfb7029d2587befbd703", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "4badd0d286f63a16886876c161c562be", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "1a7c38b236a5fe16c685c15527f658bd", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "2f4f2de5d326cceed8bef59f7d53eaa9", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9e555dd5536b24e2f369261022e6301b", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "0875d9be5d271563bee284cbe052aa87", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "33a0ae6f1ea5a0b0c60055ce01478488", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "aad882eaf2230b89973e2cf4f13c9759", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "33a0ae6f1ea5a0b0c60055ce01478488", @@ -4131,14 +4131,14 @@ "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "ae4e3f563892f6b9311c4b7284f28c11", "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "01dab862a43d9e7c4ee4e49212442d42", "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "ae4e3f563892f6b9311c4b7284f28c11", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "e6486a7303980b5cdb1b3c66039d6943", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "99daefc8faf688a6d981c814047ea7c9", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "c3c45e8b50ebf18228b420740230ae4e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "86cca50b63553ed472aa26f24e377676", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "f626c31a39d7da50d5b7fd9651c88b19", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "d8befd638527cc591c18dd805999fc1b", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "577626c543f72d9d9cdd08bb2278718f", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "e190ceb6cd33b3281eaf52c40e5b2c13", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "4db5845cd1089bf9591c52f4feca4455", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "38ab6b8b4bfceae47d27c218556d770f", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "8764576e60e3fcd114bdd910736fc972", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "95f6af857196b71243ab71fd6ddc0da5", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "baa253ffc6a9d7be71b64c75b8e17498", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "473ac21b2510149bd46849f21d5f3420", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1cf5b56cfa597ad908caa117247a031f", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "f51e076eede86d41e3853673dcfa5ea6", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad", "src/ballistica/base/mgen/pyembed/binding_base.inc": "06042d31df0ff9af96b99477162e2a91", diff --git a/CHANGELOG.md b/CHANGELOG.md index 27d00c68f..694920f96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.37 (build 22146, api 9, 2024-12-25) +### 1.7.37 (build 22147, api 9, 2024-12-28) - 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/.asset_manifest_public.json b/src/assets/.asset_manifest_public.json index ba8a9e434..84ab582ba 100644 --- a/src/assets/.asset_manifest_public.json +++ b/src/assets/.asset_manifest_public.json @@ -420,11 +420,13 @@ "ba_data/python/bauiv1lib/account/__pycache__/__init__.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/account/__pycache__/link.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/account/__pycache__/settings.cpython-312.opt-1.pyc", + "ba_data/python/bauiv1lib/account/__pycache__/signin.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/account/__pycache__/unlink.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/account/__pycache__/v2proxy.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/account/__pycache__/viewer.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/account/link.py", "ba_data/python/bauiv1lib/account/settings.py", + "ba_data/python/bauiv1lib/account/signin.py", "ba_data/python/bauiv1lib/account/unlink.py", "ba_data/python/bauiv1lib/account/v2proxy.py", "ba_data/python/bauiv1lib/account/viewer.py", @@ -476,9 +478,7 @@ "ba_data/python/bauiv1lib/kiosk.py", "ba_data/python/bauiv1lib/league/__init__.py", "ba_data/python/bauiv1lib/league/__pycache__/__init__.cpython-312.opt-1.pyc", - "ba_data/python/bauiv1lib/league/__pycache__/rankbutton.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/league/__pycache__/rankwindow.cpython-312.opt-1.pyc", - "ba_data/python/bauiv1lib/league/rankbutton.py", "ba_data/python/bauiv1lib/league/rankwindow.py", "ba_data/python/bauiv1lib/mainmenu.py", "ba_data/python/bauiv1lib/party.py", @@ -570,10 +570,8 @@ "ba_data/python/bauiv1lib/store/__init__.py", "ba_data/python/bauiv1lib/store/__pycache__/__init__.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/store/__pycache__/browser.cpython-312.opt-1.pyc", - "ba_data/python/bauiv1lib/store/__pycache__/button.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/store/__pycache__/item.cpython-312.opt-1.pyc", "ba_data/python/bauiv1lib/store/browser.py", - "ba_data/python/bauiv1lib/store/button.py", "ba_data/python/bauiv1lib/store/item.py", "ba_data/python/bauiv1lib/tabs.py", "ba_data/python/bauiv1lib/teamnamescolors.py", diff --git a/src/assets/Makefile b/src/assets/Makefile index a2fd0782d..414ce46a4 100644 --- a/src/assets/Makefile +++ b/src/assets/Makefile @@ -341,6 +341,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/__init__.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/link.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/settings.py \ + $(BUILD_DIR)/ba_data/python/bauiv1lib/account/signin.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/unlink.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/v2proxy.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/viewer.py \ @@ -378,7 +379,6 @@ SCRIPT_TARGETS_PY_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/keyboard/englishkeyboard.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/kiosk.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/league/__init__.py \ - $(BUILD_DIR)/ba_data/python/bauiv1lib/league/rankbutton.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/league/rankwindow.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/mainmenu.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/party.py \ @@ -432,7 +432,6 @@ SCRIPT_TARGETS_PY_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/soundtrack/macmusicapp.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/store/__init__.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/store/browser.py \ - $(BUILD_DIR)/ba_data/python/bauiv1lib/store/button.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/store/item.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/tabs.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/teamnamescolors.py \ @@ -622,6 +621,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/__pycache__/__init__.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/__pycache__/link.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/__pycache__/settings.cpython-312.opt-1.pyc \ + $(BUILD_DIR)/ba_data/python/bauiv1lib/account/__pycache__/signin.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/__pycache__/unlink.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/__pycache__/v2proxy.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/account/__pycache__/viewer.cpython-312.opt-1.pyc \ @@ -659,7 +659,6 @@ SCRIPT_TARGETS_PYC_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/keyboard/__pycache__/englishkeyboard.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/kiosk.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/league/__pycache__/__init__.cpython-312.opt-1.pyc \ - $(BUILD_DIR)/ba_data/python/bauiv1lib/league/__pycache__/rankbutton.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/league/__pycache__/rankwindow.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/mainmenu.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/party.cpython-312.opt-1.pyc \ @@ -713,7 +712,6 @@ SCRIPT_TARGETS_PYC_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/soundtrack/__pycache__/macmusicapp.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/store/__pycache__/__init__.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/store/__pycache__/browser.cpython-312.opt-1.pyc \ - $(BUILD_DIR)/ba_data/python/bauiv1lib/store/__pycache__/button.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/store/__pycache__/item.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/tabs.cpython-312.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/teamnamescolors.cpython-312.opt-1.pyc \ diff --git a/src/assets/ba_data/python/babase/__init__.py b/src/assets/ba_data/python/babase/__init__.py index 9ab5baf50..5aed67c30 100644 --- a/src/assets/ba_data/python/babase/__init__.py +++ b/src/assets/ba_data/python/babase/__init__.py @@ -175,7 +175,7 @@ get_type_name, ) from babase._language import Lstr, LanguageSubsystem -from babase._logging import balog, lifecyclelog +from babase._logging import balog, applog, lifecyclelog from babase._login import LoginAdapter, LoginInfo from babase._mgen.enums import ( @@ -214,6 +214,7 @@ 'AppIntentExec', 'AppMode', 'app_instance_uuid', + 'applog', 'appname', 'appnameupper', 'AppModeSelector', diff --git a/src/assets/ba_data/python/babase/_app.py b/src/assets/ba_data/python/babase/_app.py index 5fd5d0480..cd5d57441 100644 --- a/src/assets/ba_data/python/babase/_app.py +++ b/src/assets/ba_data/python/babase/_app.py @@ -25,7 +25,7 @@ from babase._stringedit import StringEditSubsystem from babase._devconsole import DevConsoleSubsystem from babase._appconfig import AppConfig -from babase._logging import lifecyclelog +from babase._logging import lifecyclelog, applog if TYPE_CHECKING: import asyncio @@ -909,6 +909,7 @@ def _update_state(self) -> None: # Entering shutdown state: if self.state is not self.State.SHUTTING_DOWN: self.state = self.State.SHUTTING_DOWN + applog.info('Shutting down...') lifecyclelog.info('app-state is now %s', self.state.name) self._on_shutting_down() diff --git a/src/assets/ba_data/python/babase/_logging.py b/src/assets/ba_data/python/babase/_logging.py index 946b7cbf4..42d063dce 100644 --- a/src/assets/ba_data/python/babase/_logging.py +++ b/src/assets/ba_data/python/babase/_logging.py @@ -8,4 +8,5 @@ # Our standard set of loggers. balog = logging.getLogger('ba') +applog = logging.getLogger('ba.app') lifecyclelog = logging.getLogger('ba.lifecycle') diff --git a/src/assets/ba_data/python/baclassic/_appmode.py b/src/assets/ba_data/python/baclassic/_appmode.py index 49f03e095..e04890a90 100644 --- a/src/assets/ba_data/python/baclassic/_appmode.py +++ b/src/assets/ba_data/python/baclassic/_appmode.py @@ -11,6 +11,8 @@ from bacommon.app import AppExperience import babase import bauiv1 +from bauiv1lib.connectivity import wait_for_connectivity +from bauiv1lib.account.signin import show_sign_in_prompt import _baclassic @@ -429,17 +431,26 @@ def _auxiliary_window_nav( def _root_ui_achievements_press(self) -> None: from bauiv1lib.achievements import AchievementsWindow - self._auxiliary_window_nav( - win_type=AchievementsWindow, - win_create_call=lambda: AchievementsWindow( - origin_widget=bauiv1.get_special_widget('achievements_button') - ), + if not self._ensure_signed_in_v1(): + return + + wait_for_connectivity( + on_connected=lambda: self._auxiliary_window_nav( + win_type=AchievementsWindow, + win_create_call=lambda: AchievementsWindow( + origin_widget=bauiv1.get_special_widget( + 'achievements_button' + ) + ), + ) ) def _root_ui_inbox_press(self) -> None: - from bauiv1lib.connectivity import wait_for_connectivity from bauiv1lib.inbox import InboxWindow + if not self._ensure_signed_in(): + return + wait_for_connectivity( on_connected=lambda: self._auxiliary_window_nav( win_type=InboxWindow, @@ -452,11 +463,16 @@ def _root_ui_inbox_press(self) -> None: def _root_ui_store_press(self) -> None: from bauiv1lib.store.browser import StoreBrowserWindow - self._auxiliary_window_nav( - win_type=StoreBrowserWindow, - win_create_call=lambda: StoreBrowserWindow( - origin_widget=bauiv1.get_special_widget('store_button') - ), + if not self._ensure_signed_in_v1(): + return + + wait_for_connectivity( + on_connected=lambda: self._auxiliary_window_nav( + win_type=StoreBrowserWindow, + win_create_call=lambda: StoreBrowserWindow( + origin_widget=bauiv1.get_special_widget('store_button') + ), + ) ) def _root_ui_tickets_meter_press(self) -> None: @@ -474,13 +490,9 @@ def _root_ui_tokens_meter_press(self) -> None: ) def _root_ui_trophy_meter_press(self) -> None: - from bauiv1lib.account import show_sign_in_prompt from bauiv1lib.league.rankwindow import LeagueRankWindow - plus = bauiv1.app.plus - assert plus is not None - if plus.get_v1_account_state() != 'signed_in': - show_sign_in_prompt() + if not self._ensure_signed_in_v1(): return self._auxiliary_window_nav( @@ -500,6 +512,9 @@ def _root_ui_level_meter_press(self) -> None: def _root_ui_inventory_press(self) -> None: from bauiv1lib.inventory import InventoryWindow + if not self._ensure_signed_in_v1(): + return + self._auxiliary_window_nav( win_type=InventoryWindow, win_create_call=lambda: InventoryWindow( @@ -507,9 +522,36 @@ def _root_ui_inventory_press(self) -> None: ), ) + def _ensure_signed_in(self) -> bool: + """Make sure we're signed in (requiring modern v2 accounts).""" + plus = bauiv1.app.plus + if plus is None: + bauiv1.screenmessage('This requires plus.', color=(1, 0, 0)) + bauiv1.getsound('error').play() + return False + if plus.accounts.primary is None: + show_sign_in_prompt() + return False + return True + + def _ensure_signed_in_v1(self) -> bool: + """Make sure we're signed in (allowing legacy v1-only accounts).""" + plus = bauiv1.app.plus + if plus is None: + bauiv1.screenmessage('This requires plus.', color=(1, 0, 0)) + bauiv1.getsound('error').play() + return False + if plus.get_v1_account_state() != 'signed_in': + show_sign_in_prompt() + return False + return True + def _root_ui_get_tokens_press(self) -> None: from bauiv1lib.gettokens import GetTokensWindow + if not self._ensure_signed_in(): + return + self._auxiliary_window_nav( win_type=GetTokensWindow, win_create_call=lambda: GetTokensWindow( @@ -524,7 +566,6 @@ def _root_ui_chest_slot_pressed(self, index: int) -> None: ChestWindow2, ChestWindow3, ) - from bauiv1lib.connectivity import wait_for_connectivity widgetid: Literal[ 'chest_0_button', diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index b16055e9c..60905f76e 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -53,7 +53,7 @@ # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 22146 +TARGET_BALLISTICA_BUILD = 22147 TARGET_BALLISTICA_VERSION = '1.7.37' diff --git a/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py b/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py index 981100455..74cd78bbf 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py @@ -19,9 +19,6 @@ if TYPE_CHECKING: from typing import Any, Sequence - from bauiv1lib.store.button import StoreButton - from bauiv1lib.league.rankbutton import LeagueRankButton - class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): """Score screen showing the results of a cooperative game.""" @@ -105,10 +102,7 @@ def __init__(self, settings: dict): # Ui bits. self._corner_button_offs: tuple[float, float] | None = None - self._league_rank_button: LeagueRankButton | None = None - self._store_button_instance: StoreButton | None = None self._restart_button: bui.Widget | None = None - self._update_corner_button_positions_timer: bui.AppTimer | None = None self._next_level_error: bs.Actor | None = None # Score/gameplay bits. @@ -207,11 +201,6 @@ def on_transition_in(self) -> None: ) def _ui_menu(self) -> None: - # from bauiv1lib import specialoffer - - # if specialoffer.show_offer(): - # return - bui.containerwidget(edit=self._root_ui, transition='out_left') with self.context: bs.timer(0.1, bs.Call(bs.WeakCall(self.session.end))) @@ -219,11 +208,6 @@ def _ui_menu(self) -> None: def _ui_restart(self) -> None: from bauiv1lib.tournamententry import TournamentEntryWindow - # from bauiv1lib import specialoffer - - # if specialoffer.show_offer(): - # return - # If we're in a tournament and it looks like there's no time left, # disallow. if self.session.tournament_id is not None: @@ -270,10 +254,6 @@ def _ui_restart(self) -> None: self.end({'outcome': 'restart'}) def _ui_next(self) -> None: - # from bauiv1lib.specialoffer import show_offer - - # if show_offer(): - # return # If we didn't just complete this level but are choosing to play the # next one, set it as current (this won't happen otherwise). @@ -333,6 +313,12 @@ def _ui_error(self) -> None: ) def _should_show_worlds_best_button(self) -> bool: + + # Old high score lists webpage for tourneys seems broken + # (looking at meteor shower at least). + if self.session.tournament_id is not None: + return False + # Link is too complicated to display with no browser. return bui.is_browser_likely_available() @@ -349,8 +335,8 @@ def request_ui(self) -> None: def show_ui(self) -> None: """Show the UI for restarting, playing the next Level, etc.""" # pylint: disable=too-many-locals - from bauiv1lib.store.button import StoreButton - from bauiv1lib.league.rankbutton import LeagueRankButton + # pylint: disable=too-many-statements + # pylint: disable=too-many-branches assert bui.app.classic is not None @@ -420,38 +406,83 @@ def show_ui(self) -> None: if not show_next_button: h_offs += 70 - menu_button = bui.buttonwidget( - parent=rootc, - autoselect=True, - position=(h_offs - 130 - 60, v_offs), - size=(110, 85), - label='', - on_activate_call=bui.WeakCall(self._ui_menu), - ) - bui.imagewidget( - parent=rootc, - draw_controller=menu_button, - position=(h_offs - 130 - 60 + 22, v_offs + 14), - size=(60, 60), - texture=self._menu_icon_texture, - opacity=0.8, - ) - self._restart_button = restart_button = bui.buttonwidget( - parent=rootc, - autoselect=True, - position=(h_offs - 60, v_offs), - size=(110, 85), - label='', - on_activate_call=bui.WeakCall(self._ui_restart), - ) - bui.imagewidget( - parent=rootc, - draw_controller=restart_button, - position=(h_offs - 60 + 19, v_offs + 7), - size=(70, 70), - texture=self._replay_icon_texture, - opacity=0.8, - ) + # Due to virtual-bounds changes, have to squish buttons a bit to + # avoid overlapping with tips at bottom. Could look nicer to + # rework things in the middle to get more space, but would + # rather not touch this old code more than necessary. + small_buttons = True + + if small_buttons: + menu_button = bui.buttonwidget( + parent=rootc, + autoselect=True, + position=(h_offs - 130 - 45, v_offs + 40), + size=(100, 50), + label='', + button_type='square', + on_activate_call=bui.WeakCall(self._ui_menu), + ) + bui.imagewidget( + parent=rootc, + draw_controller=menu_button, + position=(h_offs - 130 - 60 + 43, v_offs + 43), + size=(45, 45), + texture=self._menu_icon_texture, + opacity=0.8, + ) + else: + menu_button = bui.buttonwidget( + parent=rootc, + autoselect=True, + position=(h_offs - 130 - 60, v_offs), + size=(110, 85), + label='', + on_activate_call=bui.WeakCall(self._ui_menu), + ) + bui.imagewidget( + parent=rootc, + draw_controller=menu_button, + position=(h_offs - 130 - 60 + 22, v_offs + 14), + size=(60, 60), + texture=self._menu_icon_texture, + opacity=0.8, + ) + + if small_buttons: + self._restart_button = restart_button = bui.buttonwidget( + parent=rootc, + autoselect=True, + position=(h_offs - 60, v_offs + 40), + size=(100, 50), + label='', + button_type='square', + on_activate_call=bui.WeakCall(self._ui_restart), + ) + bui.imagewidget( + parent=rootc, + draw_controller=restart_button, + position=(h_offs - 60 + 25, v_offs + 42), + size=(47, 47), + texture=self._replay_icon_texture, + opacity=0.8, + ) + else: + self._restart_button = restart_button = bui.buttonwidget( + parent=rootc, + autoselect=True, + position=(h_offs - 60, v_offs), + size=(110, 85), + label='', + on_activate_call=bui.WeakCall(self._ui_restart), + ) + bui.imagewidget( + parent=rootc, + draw_controller=restart_button, + position=(h_offs - 60 + 19, v_offs + 7), + size=(70, 70), + texture=self._replay_icon_texture, + opacity=0.8, + ) next_button: bui.Widget | None = None @@ -468,24 +499,46 @@ def show_ui(self) -> None: button_sound = False image_opacity = 0.2 color = (0.3, 0.3, 0.3) - next_button = bui.buttonwidget( - parent=rootc, - autoselect=True, - position=(h_offs + 130 - 60, v_offs), - size=(110, 85), - label='', - on_activate_call=call, - color=color, - enable_sound=button_sound, - ) - bui.imagewidget( - parent=rootc, - draw_controller=next_button, - position=(h_offs + 130 - 60 + 12, v_offs + 5), - size=(80, 80), - texture=self._next_level_icon_texture, - opacity=image_opacity, - ) + + if small_buttons: + next_button = bui.buttonwidget( + parent=rootc, + autoselect=True, + position=(h_offs + 130 - 75, v_offs + 40), + size=(100, 50), + label='', + button_type='square', + on_activate_call=call, + color=color, + enable_sound=button_sound, + ) + bui.imagewidget( + parent=rootc, + draw_controller=next_button, + position=(h_offs + 130 - 60 + 12, v_offs + 40), + size=(50, 50), + texture=self._next_level_icon_texture, + opacity=image_opacity, + ) + else: + next_button = bui.buttonwidget( + parent=rootc, + autoselect=True, + position=(h_offs + 130 - 60, v_offs), + size=(110, 85), + label='', + on_activate_call=call, + color=color, + enable_sound=button_sound, + ) + bui.imagewidget( + parent=rootc, + draw_controller=next_button, + position=(h_offs + 130 - 60 + 12, v_offs + 5), + size=(80, 80), + texture=self._next_level_icon_texture, + opacity=image_opacity, + ) x_offs_extra = 0 if show_next_button else -100 self._corner_button_offs = ( @@ -493,33 +546,6 @@ def show_ui(self) -> None: v_offs + 519.0, ) - if env.demo or env.arcade: - self._league_rank_button = None - self._store_button_instance = None - else: - self._league_rank_button = LeagueRankButton( - parent=rootc, - position=(h_offs + 300 + x_offs_extra, v_offs + 519), - size=(100, 60), - scale=0.9, - color=(0.4, 0.4, 0.9), - textcolor=(0.9, 0.9, 2.0), - transition_delay=0.0, - smooth_update_delay=5.0, - ) - self._store_button_instance = StoreButton( - parent=rootc, - position=(h_offs + 400 + x_offs_extra, v_offs + 519), - show_tickets=True, - sale_scale=0.85, - size=(100, 60), - scale=0.9, - button_type='square', - color=(0.35, 0.25, 0.45), - textcolor=(0.9, 0.7, 1.0), - transition_delay=0.0, - ) - bui.containerwidget( edit=rootc, selected_child=( @@ -530,25 +556,12 @@ def show_ui(self) -> None: on_cancel_call=menu_button.activate, ) - self._update_corner_button_positions() - self._update_corner_button_positions_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update_corner_button_positions), repeat=True - ) - - def _update_corner_button_positions(self) -> None: - assert self._corner_button_offs is not None - pos_x = self._corner_button_offs[0] - pos_y = self._corner_button_offs[1] - if self._league_rank_button is not None: - self._league_rank_button.set_position((pos_x, pos_y)) - if self._store_button_instance is not None: - self._store_button_instance.set_position((pos_x + 100, pos_y)) - def _player_press(self) -> None: # (Only for headless builds). - # If this activity is a good 'end point', ask server-mode just once if - # it wants to do anything special like switch sessions or kill the app. + # If this activity is a good 'end point', ask server-mode just + # once if it wants to do anything special like switch sessions + # or kill the app. if ( self._allow_server_transition and bs.app.classic is not None @@ -715,7 +728,7 @@ def on_begin(self) -> None: color=(0.5, 1, 0.5, 1), h_align='center', scale=0.4, - position=(0, 255), + position=(0, 260), jitter=1.0, ).autoretain() Text( diff --git a/src/assets/ba_data/python/bauiv1/_appsubsystem.py b/src/assets/ba_data/python/bauiv1/_appsubsystem.py index 4ee010164..5e0aae087 100644 --- a/src/assets/ba_data/python/bauiv1/_appsubsystem.py +++ b/src/assets/ba_data/python/bauiv1/_appsubsystem.py @@ -162,40 +162,6 @@ def on_app_loading(self) -> None: # checks. self.upkeeptimer = babase.AppTimer(2.6543, ui_upkeep, repeat=True) - def auto_set_back_window(self, from_window: MainWindow) -> None: - """Sets the main menu window automatically from a parent WindowState.""" - - main_window = self._main_window() - - # This should never get called for top-level main-windows. - assert ( - main_window is None or main_window.main_window_is_top_level is False - ) - - back_state = ( - None if main_window is None else main_window.main_window_back_state - ) - if back_state is None: - raise RuntimeError( - f'Main window {main_window} provides no back-state;' - f' cannot use auto-back.' - ) - - # Valid states should have values here. - assert back_state.is_top_level is not None - assert back_state.is_auxiliary is not None - assert back_state.window_type is not None - - backwin = back_state.create_window(transition='in_left') - - self.set_main_window( - backwin, - from_window=from_window, - is_back=True, - back_state=back_state, - suppress_warning=True, - ) - def get_main_window(self) -> bauiv1.MainWindow | None: """Return main window, if any.""" return self._main_window() @@ -211,11 +177,14 @@ def set_main_window( back_state: MainWindowState | None = None, suppress_warning: bool = False, ) -> None: - """Set the current 'main' window, replacing any existing. + """Set the current 'main' window. 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. + should be used whenever possible to implement navigation. + + The caller is responsible for cleaning up any previous main + window. """ # pylint: disable=too-many-locals # pylint: disable=too-many-branches diff --git a/src/assets/ba_data/python/bauiv1/_uitypes.py b/src/assets/ba_data/python/bauiv1/_uitypes.py index 8f974395a..e8e8e6c0c 100644 --- a/src/assets/ba_data/python/bauiv1/_uitypes.py +++ b/src/assets/ba_data/python/bauiv1/_uitypes.py @@ -46,7 +46,14 @@ def get_root_widget(self) -> bauiv1.Widget: class MainWindow(Window): - """A special window that can be used as a main window.""" + """A special type of window that can be set as 'main'. + + The UI system has at most one main window at any given time. + MainWindows support high level functionality such as saving and + restoring states, allowing them to be automatically recreated when + navigating back from other locations or when something like ui-scale + changes. + """ def __init__( self, @@ -146,11 +153,33 @@ def main_window_back(self) -> None: if not self.main_window_has_control(): return + uiv1 = babase.app.ui_v1 + + # Get the 'back' window coming in. if not self.main_window_is_top_level: - # Get the 'back' window coming in. - babase.app.ui_v1.auto_set_back_window(self) + back_state = self.main_window_back_state + if back_state is None: + raise RuntimeError( + f'Main window {self} provides no back-state.' + ) + + # Valid states should have values here. + assert back_state.is_top_level is not None + assert back_state.is_auxiliary is not None + assert back_state.window_type is not None + backwin = back_state.create_window(transition='in_left') + + uiv1.set_main_window( + backwin, + from_window=self, + is_back=True, + back_state=back_state, + suppress_warning=True, + ) + + # Transition ourself out. self.main_window_close() def main_window_replace( @@ -203,7 +232,7 @@ def get_main_window_state(self) -> MainWindowState: class MainWindowState: - """Persistent state for a specific main-window and its ancestors. + """Persistent state for a specific MainWindow. This allows MainWindows to be automatically recreated for back-button purposes, when switching app-modes, etc. diff --git a/src/assets/ba_data/python/bauiv1lib/account/__init__.py b/src/assets/ba_data/python/bauiv1lib/account/__init__.py index d34e9ef52..1d25ed06b 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/__init__.py +++ b/src/assets/ba_data/python/bauiv1lib/account/__init__.py @@ -1,21 +1,3 @@ # Released under the MIT License. See LICENSE for details. # """UI functionality related to accounts.""" - -from __future__ import annotations - -import bauiv1 as bui - - -def show_sign_in_prompt() -> None: - """Bring up a prompt telling the user they must sign in.""" - from bauiv1lib.confirm import ConfirmWindow - from bauiv1lib.account.settings import AccountSettingsWindow - - ConfirmWindow( - bui.Lstr(resource='notSignedInErrorText'), - lambda: AccountSettingsWindow(modal=True, close_once_signed_in=True), - ok_text=bui.Lstr(resource='accountSettingsWindow.signInText'), - width=460, - height=130, - ) diff --git a/src/assets/ba_data/python/bauiv1lib/account/link.py b/src/assets/ba_data/python/bauiv1lib/account/link.py index 58828ad8c..d19ed0647 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/link.py +++ b/src/assets/ba_data/python/bauiv1lib/account/link.py @@ -105,13 +105,13 @@ def __init__(self, origin_widget: bui.Widget | None = None): ) def _generate_press(self) -> None: - from bauiv1lib import account + from bauiv1lib.account.signin import show_sign_in_prompt plus = bui.app.plus assert plus is not None if plus.get_v1_account_state() != 'signed_in': - account.show_sign_in_prompt() + show_sign_in_prompt() return bui.screenmessage( bui.Lstr(resource='gatherWindow.requestingAPromoCodeText'), diff --git a/src/assets/ba_data/python/bauiv1lib/account/settings.py b/src/assets/ba_data/python/bauiv1lib/account/settings.py index da5820478..74777902d 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/settings.py +++ b/src/assets/ba_data/python/bauiv1lib/account/settings.py @@ -28,7 +28,6 @@ class AccountSettingsWindow(bui.MainWindow): def __init__( self, transition: str | None = 'in_right', - modal: bool = False, origin_widget: bui.Widget | None = None, close_once_signed_in: bool = False, ): @@ -49,7 +48,6 @@ def __init__( self._explicitly_signed_out_of_gpgs = False self._r = 'accountSettingsWindow' - self._modal = modal self._needs_refresh = False self._v1_signed_in = plus.get_v1_account_state() == 'signed_in' self._v1_account_state_num = plus.get_v1_account_state_num() @@ -129,22 +127,17 @@ def __init__( scale=0.8, text_scale=1.2, autoselect=True, - label=bui.Lstr( - resource='cancelText' if self._modal else 'backText' - ), - button_type='regular' if self._modal else 'back', - on_activate_call=( - self._modal_close if self._modal else self.main_window_back - ), + label=bui.Lstr(resource='backText'), + button_type='back', + on_activate_call=self.main_window_back, ) bui.containerwidget(edit=self._root_widget, cancel_button=btn) - if not self._modal: - bui.buttonwidget( - edit=btn, - button_type='backSmall', - size=(60, 56), - label=bui.charstr(bui.SpecialChar.BACK), - ) + bui.buttonwidget( + edit=btn, + button_type='backSmall', + size=(60, 56), + label=bui.charstr(bui.SpecialChar.BACK), + ) titleyoffs = -9 if uiscale is bui.UIScale.SMALL else 0 titlescale = 0.7 if uiscale is bui.UIScale.SMALL else 1.0 @@ -176,18 +169,6 @@ def __init__( self._refresh() self._restore_state() - def _modal_close(self) -> None: - assert 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 - - bui.containerwidget( - edit=self._root_widget, - transition=('out_right'), - ) - @override def get_main_window_state(self) -> bui.MainWindowState: # Support recreating our window for back/refresh purposes. diff --git a/src/assets/ba_data/python/bauiv1lib/account/signin.py b/src/assets/ba_data/python/bauiv1lib/account/signin.py new file mode 100644 index 000000000..0b2272329 --- /dev/null +++ b/src/assets/ba_data/python/bauiv1lib/account/signin.py @@ -0,0 +1,51 @@ +# Released under the MIT License. See LICENSE for details. +# +"""UI functionality related to accounts.""" + +from __future__ import annotations + +import bauiv1 as bui + + +def show_sign_in_prompt() -> None: + """Bring up a prompt telling the user they must sign in.""" + from bauiv1lib.confirm import ConfirmWindow + + ConfirmWindow( + bui.Lstr(resource='notSignedInErrorText'), + _show_account_settings, + ok_text=bui.Lstr(resource='accountSettingsWindow.signInText'), + width=460, + height=130, + ) + + +def _show_account_settings() -> None: + from bauiv1lib.account.settings import AccountSettingsWindow + + # NOTE TO USERS: The code below is not the proper way to do things; + # whenever possible one should use a MainWindow's + # main_window_replace() or main_window_back() methods. We just need + # to do things a bit more manually in this case. + + prev_main_window = bui.app.ui_v1.get_main_window() + + # Special-case: If it seems we're already in the account window, do + # nothing. + if isinstance(prev_main_window, AccountSettingsWindow): + return + + # Set our new main window. + bui.app.ui_v1.set_main_window( + AccountSettingsWindow( + close_once_signed_in=True, + origin_widget=bui.get_special_widget('account_button'), + ), + from_window=False, + is_auxiliary=True, + suppress_warning=True, + ) + + # Transition out any previous main window. + if prev_main_window is not None: + prev_main_window.main_window_close() diff --git a/src/assets/ba_data/python/bauiv1lib/account/v2proxy.py b/src/assets/ba_data/python/bauiv1lib/account/v2proxy.py index d91f1f048..f84b3b355 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/v2proxy.py +++ b/src/assets/ba_data/python/bauiv1lib/account/v2proxy.py @@ -34,9 +34,9 @@ def __init__(self, origin_widget: bui.Widget): origin_widget.get_screen_space_center() ), scale=( - 1.25 + 1.16 if uiscale is bui.UIScale.SMALL - else 1.05 if uiscale is bui.UIScale.MEDIUM else 0.9 + else 1.0 if uiscale is bui.UIScale.MEDIUM else 0.9 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/characterpicker.py b/src/assets/ba_data/python/bauiv1lib/characterpicker.py index cd8286b4b..835f3f05c 100644 --- a/src/assets/ba_data/python/bauiv1lib/characterpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/characterpicker.py @@ -193,7 +193,7 @@ def __init__( bui.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30) def _on_store_press(self) -> None: - from bauiv1lib.account import show_sign_in_prompt + from bauiv1lib.account.signin import show_sign_in_prompt plus = bui.app.plus assert plus is not None diff --git a/src/assets/ba_data/python/bauiv1lib/coop/browser.py b/src/assets/ba_data/python/bauiv1lib/coop/browser.py index 77702a4ce..0a50d1c0b 100644 --- a/src/assets/ba_data/python/bauiv1lib/coop/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/coop/browser.py @@ -1032,7 +1032,7 @@ def run_game(self, game: str) -> None: # pylint: disable=cyclic-import from bauiv1lib.confirm import ConfirmWindow from bauiv1lib.purchase import PurchaseWindow - from bauiv1lib.account import show_sign_in_prompt + from bauiv1lib.account.signin import show_sign_in_prompt plus = bui.app.plus assert plus is not None @@ -1106,7 +1106,7 @@ def run_game(self, game: str) -> None: def run_tournament(self, tournament_button: TournamentButton) -> None: """Run the provided tournament game.""" - from bauiv1lib.account import show_sign_in_prompt + from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.tournamententry import TournamentEntryWindow plus = bui.app.plus diff --git a/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py b/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py index 7b1bdac61..b67763774 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py @@ -200,7 +200,7 @@ def on_activate( return scroll_widget def _invite_to_try_press(self) -> None: - from bauiv1lib.account import show_sign_in_prompt + from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.appinvite import handle_app_invites_press plus = bui.app.plus diff --git a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py index 5111405d1..eb6804caa 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py @@ -1375,7 +1375,7 @@ def _do_status_check(self) -> None: ) def _on_start_advertizing_press(self) -> None: - from bauiv1lib.account import show_sign_in_prompt + from bauiv1lib.account.signin import show_sign_in_prompt plus = bui.app.plus assert plus is not None diff --git a/src/assets/ba_data/python/bauiv1lib/iconpicker.py b/src/assets/ba_data/python/bauiv1lib/iconpicker.py index 4f186b413..0a9bd4bcf 100644 --- a/src/assets/ba_data/python/bauiv1lib/iconpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/iconpicker.py @@ -171,7 +171,7 @@ def __init__( bui.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30) def _on_store_press(self) -> None: - from bauiv1lib.account import show_sign_in_prompt + from bauiv1lib.account.signin import show_sign_in_prompt plus = bui.app.plus assert plus is not None diff --git a/src/assets/ba_data/python/bauiv1lib/league/rankbutton.py b/src/assets/ba_data/python/bauiv1lib/league/rankbutton.py deleted file mode 100644 index da58d53fa..000000000 --- a/src/assets/ba_data/python/bauiv1lib/league/rankbutton.py +++ /dev/null @@ -1,424 +0,0 @@ -# Released under the MIT License. See LICENSE for details. -# -"""Provides a button showing league rank.""" - -from __future__ import annotations - -import logging -from typing import TYPE_CHECKING - -import bauiv1 as bui - -if TYPE_CHECKING: - from typing import Any, Callable - - -class LeagueRankButton: - """Button showing league rank.""" - - def __init__( - self, - parent: bui.Widget, - position: tuple[float, float], - size: tuple[float, float], - scale: float, - *, - on_activate_call: Callable[[], Any] | None = None, - transition_delay: float | None = None, - color: tuple[float, float, float] | None = None, - textcolor: tuple[float, float, float] | None = None, - smooth_update_delay: float | None = None, - ): - if on_activate_call is None: - on_activate_call = bui.WeakCall(self._default_on_activate_call) - self._on_activate_call = on_activate_call - if smooth_update_delay is None: - smooth_update_delay = 1.0 - self._smooth_update_delay = smooth_update_delay - self._size = size - self._scale = scale - if color is None: - color = (0.5, 0.6, 0.5) - if textcolor is None: - textcolor = (1, 1, 1) - self._color = color - self._textcolor = textcolor - self._header_color = (0.8, 0.8, 2.0) - self._parent = parent - self._position: tuple[float, float] = (0.0, 0.0) - - self._button = bui.buttonwidget( - parent=parent, - size=size, - label='', - button_type='square', - scale=scale, - autoselect=True, - on_activate_call=self._on_activate, - transition_delay=transition_delay, - color=color, - ) - - self._title_text = bui.textwidget( - parent=parent, - size=(0, 0), - draw_controller=self._button, - h_align='center', - v_align='center', - maxwidth=size[0] * scale * 0.85, - text=bui.Lstr( - resource='league.leagueRankText', - fallback_resource='coopSelectWindow.powerRankingText', - ), - color=self._header_color, - flatness=1.0, - shadow=1.0, - scale=scale * 0.5, - transition_delay=transition_delay, - ) - - self._value_text = bui.textwidget( - parent=parent, - size=(0, 0), - h_align='center', - v_align='center', - maxwidth=size[0] * scale * 0.85, - text='-', - draw_controller=self._button, - big=True, - scale=scale, - transition_delay=transition_delay, - color=textcolor, - ) - - plus = bui.app.plus - assert plus is not None - - self._smooth_percent: float | None = None - self._percent: int | None = None - self._smooth_rank: float | None = None - self._rank: int | None = None - self._ticking_sound: bui.Sound | None = None - self._smooth_increase_speed = 1.0 - self._league: str | None = None - self._improvement_text: str | None = None - - self._smooth_update_timer: bui.AppTimer | None = None - - # Take note of our account state; we'll refresh later if this changes. - self._account_state_num = plus.get_v1_account_state_num() - self._last_power_ranking_query_time: float | None = None - self._doing_power_ranking_query = False - self.set_position(position) - self._bg_flash = False - self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True - ) - self._update() - - # If we've got cached power-ranking data already, apply it. - assert bui.app.classic is not None - data = bui.app.classic.accounts.get_cached_league_rank_data() - if data is not None: - self._update_for_league_rank_data(data) - - def _on_activate(self) -> None: - bui.increment_analytics_count('League rank button press') - self._on_activate_call() - - def __del__(self) -> None: - if self._ticking_sound is not None: - self._ticking_sound.stop() - self._ticking_sound = None - - def _start_smooth_update(self) -> None: - self._smooth_update_timer = bui.AppTimer( - 0.05, bui.WeakCall(self._smooth_update), repeat=True - ) - - def _smooth_update(self) -> None: - # pylint: disable=too-many-branches - # pylint: disable=too-many-statements - try: - if not self._button: - return - if self._ticking_sound is None: - self._ticking_sound = bui.getsound('scoreIncrease') - self._ticking_sound.play() - self._bg_flash = not self._bg_flash - color_used = ( - (self._color[0] * 2, self._color[1] * 2, self._color[2] * 2) - if self._bg_flash - else self._color - ) - textcolor_used = (1, 1, 1) if self._bg_flash else self._textcolor - header_color_used = ( - (1, 1, 1) if self._bg_flash else self._header_color - ) - - if self._rank is not None: - assert self._smooth_rank is not None - self._smooth_rank -= 1.0 * self._smooth_increase_speed - finished = int(self._smooth_rank) <= self._rank - elif self._smooth_percent is not None: - self._smooth_percent += 1.0 * self._smooth_increase_speed - assert self._percent is not None - finished = int(self._smooth_percent) >= self._percent - else: - finished = True - if finished: - if self._rank is not None: - self._smooth_rank = float(self._rank) - elif self._percent is not None: - self._smooth_percent = float(self._percent) - color_used = self._color - textcolor_used = self._textcolor - self._smooth_update_timer = None - if self._ticking_sound is not None: - self._ticking_sound.stop() - self._ticking_sound = None - bui.getsound('cashRegister2').play() - assert self._improvement_text is not None - diff_text = bui.textwidget( - parent=self._parent, - size=(0, 0), - h_align='center', - v_align='center', - text='+' + self._improvement_text + '!', - position=( - self._position[0] + self._size[0] * 0.5 * self._scale, - self._position[1] + self._size[1] * -0.2 * self._scale, - ), - color=(0, 1, 0), - flatness=1.0, - shadow=0.0, - scale=self._scale * 0.7, - ) - - def safe_delete(widget: bui.Widget) -> None: - if widget: - widget.delete() - - bui.apptimer(2.0, bui.Call(safe_delete, diff_text)) - status_text: str | bui.Lstr - if self._rank is not None: - assert self._smooth_rank is not None - status_text = bui.Lstr( - resource='numberText', - subs=[('${NUMBER}', str(int(self._smooth_rank)))], - ) - elif self._smooth_percent is not None: - status_text = str(int(self._smooth_percent)) + '%' - else: - status_text = '-' - bui.textwidget( - edit=self._value_text, text=status_text, color=textcolor_used - ) - bui.textwidget(edit=self._title_text, color=header_color_used) - bui.buttonwidget(edit=self._button, color=color_used) - - except Exception: - logging.exception('Error doing smooth update.') - self._smooth_update_timer = None - - def _update_for_league_rank_data(self, data: dict[str, Any] | None) -> None: - # pylint: disable=too-many-branches - # pylint: disable=too-many-statements - - plus = bui.app.plus - assert plus is not None - - # If our button has died, ignore. - if not self._button: - return - - status_text: str | bui.Lstr - - in_top = data is not None and data['rank'] is not None - do_percent = False - if data is None or plus.get_v1_account_state() != 'signed_in': - self._percent = self._rank = None - status_text = '-' - elif in_top: - self._percent = None - self._rank = data['rank'] - prev_league = self._league - self._league = data['l'] - - # If this is the first set, league has changed, or rank has gotten - # worse, snap the smooth value immediately. - assert self._rank is not None - if ( - self._smooth_rank is None - or prev_league != self._league - or self._rank > int(self._smooth_rank) - ): - self._smooth_rank = float(self._rank) - status_text = bui.Lstr( - resource='numberText', - subs=[('${NUMBER}', str(int(self._smooth_rank)))], - ) - else: - try: - if not data['scores'] or data['scores'][-1][1] <= 0: - self._percent = self._rank = None - status_text = '-' - else: - assert bui.app.classic is not None - our_points = ( - bui.app.classic.accounts.get_league_rank_points(data) - ) - progress = float(our_points) / data['scores'][-1][1] - self._percent = int(progress * 100.0) - self._rank = None - do_percent = True - prev_league = self._league - self._league = data['l'] - - # If this is the first set, league has changed, or percent - # has decreased, snap the smooth value immediately. - if ( - self._smooth_percent is None - or prev_league != self._league - or self._percent < int(self._smooth_percent) - ): - self._smooth_percent = float(self._percent) - status_text = str(int(self._smooth_percent)) + '%' - - except Exception: - logging.exception('Error updating power ranking.') - self._percent = self._rank = None - status_text = '-' - - # If we're doing a smooth update, set a timer. - if ( - self._rank is not None - and self._smooth_rank is not None - and int(self._smooth_rank) != self._rank - ): - self._improvement_text = str( - -(int(self._rank) - int(self._smooth_rank)) - ) - diff = abs(self._rank - self._smooth_rank) - if diff > 100: - self._smooth_increase_speed = diff / 80.0 - elif diff > 50: - self._smooth_increase_speed = diff / 70.0 - elif diff > 25: - self._smooth_increase_speed = diff / 55.0 - else: - self._smooth_increase_speed = diff / 40.0 - self._smooth_increase_speed = max(0.4, self._smooth_increase_speed) - bui.apptimer( - self._smooth_update_delay, - bui.WeakCall(self._start_smooth_update), - ) - - if ( - self._percent is not None - and self._smooth_percent is not None - and int(self._smooth_percent) != self._percent - ): - self._improvement_text = str( - (int(self._percent) - int(self._smooth_percent)) - ) - self._smooth_increase_speed = 0.3 - bui.apptimer( - self._smooth_update_delay, - bui.WeakCall(self._start_smooth_update), - ) - - if do_percent: - bui.textwidget( - edit=self._title_text, - text=bui.Lstr(resource='coopSelectWindow.toRankedText'), - ) - else: - try: - assert data is not None - txt = bui.Lstr( - resource='league.leagueFullText', - subs=[ - ( - '${NAME}', - bui.Lstr(translate=('leagueNames', data['l']['n'])), - ), - ], - ) - t_color = data['l']['c'] - except Exception: - txt = bui.Lstr( - resource='league.leagueRankText', - fallback_resource='coopSelectWindow.powerRankingText', - ) - assert bui.app.classic is not None - t_color = bui.app.ui_v1.title_color - bui.textwidget(edit=self._title_text, text=txt, color=t_color) - bui.textwidget(edit=self._value_text, text=status_text) - - def _on_power_ranking_query_response( - self, data: dict[str, Any] | None - ) -> None: - self._doing_power_ranking_query = False - assert bui.app.classic is not None - bui.app.classic.accounts.cache_league_rank_data(data) - self._update_for_league_rank_data(data) - - def _update(self) -> None: - cur_time = bui.apptime() - - plus = bui.app.plus - assert plus is not None - - # If our account state has changed, refresh our UI. - account_state_num = plus.get_v1_account_state_num() - if account_state_num != self._account_state_num: - self._account_state_num = account_state_num - - # And power ranking too... - if not self._doing_power_ranking_query: - self._last_power_ranking_query_time = None - - # Send off a new power-ranking query if its been - # long enough or whatnot. - if not self._doing_power_ranking_query and ( - self._last_power_ranking_query_time is None - or cur_time - self._last_power_ranking_query_time > 30.0 - ): - self._last_power_ranking_query_time = cur_time - self._doing_power_ranking_query = True - plus.power_ranking_query( - callback=bui.WeakCall(self._on_power_ranking_query_response) - ) - - def _default_on_activate_call(self) -> None: - # pylint: disable=cyclic-import - # from bauiv1lib.league.rankwindow import LeagueRankWindow - - raise RuntimeError() - # LeagueRankWindow(modal=True, origin_widget=self._button) - - def set_position(self, position: tuple[float, float]) -> None: - """Set the button's position.""" - self._position = position - if not self._button: - return - bui.buttonwidget(edit=self._button, position=self._position) - bui.textwidget( - edit=self._title_text, - position=( - self._position[0] + self._size[0] * 0.5 * self._scale, - self._position[1] + self._size[1] * 0.82 * self._scale, - ), - ) - bui.textwidget( - edit=self._value_text, - position=( - self._position[0] + self._size[0] * 0.5 * self._scale, - self._position[1] + self._size[1] * 0.36 * self._scale, - ), - ) - - def get_button(self) -> bui.Widget: - """Return the underlying button bui.Widget>""" - return self._button diff --git a/src/assets/ba_data/python/bauiv1lib/mainmenu.py b/src/assets/ba_data/python/bauiv1lib/mainmenu.py index 3da6fc627..8495903ac 100644 --- a/src/assets/ba_data/python/bauiv1lib/mainmenu.py +++ b/src/assets/ba_data/python/bauiv1lib/mainmenu.py @@ -83,7 +83,6 @@ def _preload_modules() -> None: # pylint: disable=cyclic-import import bauiv1lib.getremote as _unused import bauiv1lib.confirm as _unused2 - import bauiv1lib.store.button as _unused3 import bauiv1lib.account.settings as _unused5 import bauiv1lib.store.browser as _unused6 import bauiv1lib.credits as _unused7 @@ -153,30 +152,31 @@ def _refresh(self) -> None: uiscale = app.ui_v1.uiscale # Temp note about UI changes. - bui.textwidget( - parent=self._root_widget, - position=( - (-400, 400) - if uiscale is bui.UIScale.LARGE - else ( - (-270, 320) - if uiscale is bui.UIScale.MEDIUM - else (-280, 280) - ) - ), - size=(0, 0), - scale=0.4, - flatness=1.0, - text=( - 'WARNING: This build contains a revamped UI\n' - 'which is still a work-in-progress. A number\n' - 'of features are not currently functional or\n' - 'contain bugs. To go back to the stable legacy UI,\n' - 'grab version 1.7.36 from ballistica.net' - ), - h_align='left', - v_align='top', - ) + if bool(False): + bui.textwidget( + parent=self._root_widget, + position=( + (-400, 400) + if uiscale is bui.UIScale.LARGE + else ( + (-270, 320) + if uiscale is bui.UIScale.MEDIUM + else (-280, 280) + ) + ), + size=(0, 0), + scale=0.4, + flatness=1.0, + text=( + 'WARNING: This build contains a revamped UI\n' + 'which is still a work-in-progress. A number\n' + 'of features are not currently functional or\n' + 'contain bugs. To go back to the stable legacy UI,\n' + 'grab version 1.7.36 from ballistica.net' + ), + h_align='left', + v_align='top', + ) self._have_quit_button = app.classic.platform in ( 'windows', diff --git a/src/assets/ba_data/python/bauiv1lib/partyqueue.py b/src/assets/ba_data/python/bauiv1lib/partyqueue.py index 3b8263319..3c4d10be7 100644 --- a/src/assets/ba_data/python/bauiv1lib/partyqueue.py +++ b/src/assets/ba_data/python/bauiv1lib/partyqueue.py @@ -566,7 +566,7 @@ def on_update_response(self, response: dict[str, Any] | None) -> None: def on_boost_press(self) -> None: """Boost was pressed.""" - from bauiv1lib import account + from bauiv1lib.account.signin import show_sign_in_prompt # from bauiv1lib import gettickets @@ -574,7 +574,7 @@ def on_boost_press(self) -> None: assert plus is not None if plus.get_v1_account_state() != 'signed_in': - account.show_sign_in_prompt() + show_sign_in_prompt() return if plus.get_v1_account_ticket_count() < self._boost_tickets: diff --git a/src/assets/ba_data/python/bauiv1lib/play.py b/src/assets/ba_data/python/bauiv1lib/play.py index b94e7840b..27b05a407 100644 --- a/src/assets/ba_data/python/bauiv1lib/play.py +++ b/src/assets/ba_data/python/bauiv1lib/play.py @@ -572,7 +572,7 @@ def _preload_modules() -> None: def _coop(self) -> None: # pylint: disable=cyclic-import - from bauiv1lib.account import show_sign_in_prompt + from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.coop.browser import CoopBrowserWindow # no-op if we're not currently in control. diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py b/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py index 7e064d1f4..bcffd6e31 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py @@ -255,7 +255,7 @@ def _doit() -> None: ) def _on_get_more_games_press(self) -> None: - from bauiv1lib.account import show_sign_in_prompt + from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.store.browser import StoreBrowserWindow # No-op if we're not in control. @@ -271,17 +271,12 @@ def _on_get_more_games_press(self) -> None: 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 _add(self) -> None: bui.lock_all_input() # Make sure no more commands happen. bui.apptimer(0.1, bui.unlock_all_input) diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py b/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py index 603cd97a9..ca8cdc9e5 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py @@ -283,7 +283,7 @@ def _refresh(self, select_get_more_maps_button: bool = False) -> None: ) def _on_store_press(self) -> None: - from bauiv1lib import account + from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.store.browser import StoreBrowserWindow # No-op if we're not in control. @@ -294,7 +294,7 @@ def _on_store_press(self) -> None: assert plus is not None if plus.get_v1_account_state() != 'signed_in': - account.show_sign_in_prompt() + show_sign_in_prompt() return self._selected_get_more_maps = True diff --git a/src/assets/ba_data/python/bauiv1lib/playoptions.py b/src/assets/ba_data/python/bauiv1lib/playoptions.py index 2d206135b..fc23723ea 100644 --- a/src/assets/ba_data/python/bauiv1lib/playoptions.py +++ b/src/assets/ba_data/python/bauiv1lib/playoptions.py @@ -432,7 +432,7 @@ def _cb_callback_2(val: bool) -> None: self._update() def _custom_colors_names_press(self) -> None: - from bauiv1lib.account import show_sign_in_prompt + from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.teamnamescolors import TeamNamesColorsWindow from bauiv1lib.purchase import PurchaseWindow diff --git a/src/assets/ba_data/python/bauiv1lib/profile/edit.py b/src/assets/ba_data/python/bauiv1lib/profile/edit.py index 447bbb72e..27af50332 100644 --- a/src/assets/ba_data/python/bauiv1lib/profile/edit.py +++ b/src/assets/ba_data/python/bauiv1lib/profile/edit.py @@ -550,7 +550,7 @@ def assign_random_name(self) -> None: def upgrade_profile(self) -> None: """Attempt to upgrade the profile to global.""" - from bauiv1lib import account + from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.profile import upgrade as pupgrade new_name = self.getname().strip() @@ -566,7 +566,7 @@ def upgrade_profile(self) -> None: assert plus is not None if plus.get_v1_account_state() != 'signed_in': - account.show_sign_in_prompt() + show_sign_in_prompt() return pupgrade.ProfileUpgradeWindow(self) diff --git a/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py b/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py index 9ca597c17..c9d4efdf7 100644 --- a/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py +++ b/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py @@ -53,24 +53,52 @@ def __init__( iconscale=1.2, ) + yoffs = self._height - 150 + if resource_type == 'tickets': - rdesc = 'Will describe tickets.' + rdesc = ( + 'Use tickets to unlock characters, maps,\n' + 'minigames, and more in the store.\n' + '\n' + 'Earn tickets by completing achievements or\n' + 'by opening chests won in the game.' + ) + texname = 'tickets' elif resource_type == 'tokens': - rdesc = 'Will describe tokens.' + rdesc = ( + 'Tokens can be used to speed up chest unlocks\n' + 'and skip other waits.\n' + '\n' + 'You can buy packs of tokens or buy a Gold Pass\n' + 'to get infinite tokens forever.\n' + ) + texname = 'coin' elif resource_type == 'trophies': - rdesc = 'Will show trophies & league rankings.' + rdesc = 'TODO: Will show trophies & league rankings.' + texname = 'crossOut' elif resource_type == 'xp': - rdesc = 'Will describe xp/levels.' + rdesc = 'TODO: Will describe xp/levels.' + texname = 'crossOut' else: assert_never(resource_type) + imgsize = 100.0 + bui.imagewidget( + parent=self.root_widget, + position=(self._width * 0.5 - imgsize * 0.5, yoffs + 5.0), + size=(imgsize, imgsize), + texture=bui.gettexture(texname), + ) + bui.textwidget( parent=self.root_widget, h_align='center', - v_align='center', + v_align='top', size=(0, 0), - position=(self._width * 0.5, self._height * 0.5), - text=(f'UNDER CONSTRUCTION.\n({rdesc})'), + maxwidth=self._width * 0.8, + position=(self._width * 0.5, yoffs - 5.0), + text=rdesc, + scale=0.8, ) def _on_cancel_press(self) -> None: diff --git a/src/assets/ba_data/python/bauiv1lib/settings/advanced.py b/src/assets/ba_data/python/bauiv1lib/settings/advanced.py index 343d4a8dc..096545cd5 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/advanced.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/advanced.py @@ -787,13 +787,13 @@ def _on_net_test_press(self) -> None: def _on_friend_promo_code_press(self) -> None: from bauiv1lib import appinvite - from bauiv1lib import account + from bauiv1lib.account.signin import show_sign_in_prompt plus = bui.app.plus assert plus is not None if plus.get_v1_account_state() != 'signed_in': - account.show_sign_in_prompt() + show_sign_in_prompt() return appinvite.handle_app_invites_press() diff --git a/src/assets/ba_data/python/bauiv1lib/store/browser.py b/src/assets/ba_data/python/bauiv1lib/store/browser.py index 27a2f3d70..094268758 100644 --- a/src/assets/ba_data/python/bauiv1lib/store/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/store/browser.py @@ -281,12 +281,12 @@ def __init__( self._restore_state() def _restore_purchases(self) -> None: - from bauiv1lib import account + from bauiv1lib.account.signin import show_sign_in_prompt plus = bui.app.plus assert plus is not None if plus.accounts.primary is None: - account.show_sign_in_prompt() + show_sign_in_prompt() else: plus.restore_purchases() @@ -490,7 +490,7 @@ def _do_purchase_check( def buy(self, item: str) -> None: """Attempt to purchase the provided item.""" - from bauiv1lib import account + from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.confirm import ConfirmWindow assert bui.app.classic is not None @@ -509,7 +509,7 @@ def buy(self, item: str) -> None: bui.getsound('error').play() else: if plus.get_v1_account_state() != 'signed_in': - account.show_sign_in_prompt() + show_sign_in_prompt() else: self._last_buy_time = curtime diff --git a/src/assets/ba_data/python/bauiv1lib/store/button.py b/src/assets/ba_data/python/bauiv1lib/store/button.py deleted file mode 100644 index 7d061c90c..000000000 --- a/src/assets/ba_data/python/bauiv1lib/store/button.py +++ /dev/null @@ -1,329 +0,0 @@ -# Released under the MIT License. See LICENSE for details. -# -"""UI functionality for a button leading to the store.""" -from __future__ import annotations - -import logging -from typing import TYPE_CHECKING - -from efro.util import utc_now - -import bauiv1 as bui - -if TYPE_CHECKING: - from typing import Any, Sequence, Callable - - -class StoreButton: - """A button leading to the store.""" - - def __init__( - self, - parent: bui.Widget, - position: Sequence[float], - size: Sequence[float], - scale: float, - *, - on_activate_call: Callable[[], Any] | None = None, - transition_delay: float | None = None, - color: Sequence[float] | None = None, - textcolor: Sequence[float] | None = None, - show_tickets: bool = False, - button_type: str | None = None, - sale_scale: float = 1.0, - ): - self._position = position - self._size = size - self._scale = scale - - if on_activate_call is None: - on_activate_call = bui.WeakCall(self._default_on_activate_call) - self._on_activate_call = on_activate_call - - self._button = bui.buttonwidget( - parent=parent, - size=size, - label='' if show_tickets else bui.Lstr(resource='storeText'), - scale=scale, - autoselect=True, - on_activate_call=self._on_activate, - transition_delay=transition_delay, - color=color, - button_type=button_type, - ) - - self._title_text: bui.Widget | None - self._ticket_text: bui.Widget | None - - if show_tickets: - self._title_text = bui.textwidget( - parent=parent, - position=( - position[0] + size[0] * 0.5 * scale, - position[1] + size[1] * 0.65 * scale, - ), - size=(0, 0), - h_align='center', - v_align='center', - maxwidth=size[0] * scale * 0.65, - text=bui.Lstr(resource='storeText'), - draw_controller=self._button, - scale=scale, - transition_delay=transition_delay, - color=textcolor, - ) - self._ticket_text = bui.textwidget( - parent=parent, - size=(0, 0), - h_align='center', - v_align='center', - maxwidth=size[0] * scale * 0.85, - text='', - color=(0.2, 1.0, 0.2), - flatness=1.0, - shadow=0.0, - scale=scale * 0.6, - transition_delay=transition_delay, - ) - else: - self._title_text = None - self._ticket_text = None - - self._circle_rad = 12 * scale - self._circle_center = (0.0, 0.0) - self._sale_circle_center = (0.0, 0.0) - - self._available_purchase_backing = bui.imagewidget( - parent=parent, - color=(1, 0, 0), - draw_controller=self._button, - size=(2.2 * self._circle_rad, 2.2 * self._circle_rad), - texture=bui.gettexture('circleShadow'), - transition_delay=transition_delay, - ) - self._available_purchase_text = bui.textwidget( - parent=parent, - size=(0, 0), - h_align='center', - v_align='center', - text='', - draw_controller=self._button, - color=(1, 1, 1), - flatness=1.0, - shadow=1.0, - scale=0.6 * scale, - maxwidth=self._circle_rad * 1.4, - transition_delay=transition_delay, - ) - - self._sale_circle_rad = 18 * scale * sale_scale - self._sale_backing = bui.imagewidget( - parent=parent, - color=(0.5, 0, 1.0), - draw_controller=self._button, - size=(2 * self._sale_circle_rad, 2 * self._sale_circle_rad), - texture=bui.gettexture('circleZigZag'), - transition_delay=transition_delay, - ) - self._sale_title_text = bui.textwidget( - parent=parent, - size=(0, 0), - h_align='center', - v_align='center', - draw_controller=self._button, - color=(0, 1, 0), - flatness=1.0, - shadow=0.0, - scale=0.5 * scale * sale_scale, - maxwidth=self._sale_circle_rad * 1.5, - transition_delay=transition_delay, - ) - self._sale_time_text = bui.textwidget( - parent=parent, - size=(0, 0), - h_align='center', - v_align='center', - draw_controller=self._button, - color=(0, 1, 0), - flatness=1.0, - shadow=0.0, - scale=0.4 * scale * sale_scale, - maxwidth=self._sale_circle_rad * 1.5, - transition_delay=transition_delay, - ) - - self.set_position(position) - self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True - ) - self._update() - - def _on_activate(self) -> None: - bui.increment_analytics_count('Store button press') - self._on_activate_call() - - def set_position(self, position: Sequence[float]) -> None: - """Set the button position.""" - self._position = position - self._circle_center = ( - position[0] + 0.1 * self._size[0] * self._scale, - position[1] + self._size[1] * self._scale * 0.8, - ) - self._sale_circle_center = ( - position[0] + 0.07 * self._size[0] * self._scale, - position[1] + self._size[1] * self._scale * 0.8, - ) - - if not self._button: - return - bui.buttonwidget(edit=self._button, position=self._position) - if self._title_text is not None: - bui.textwidget( - edit=self._title_text, - position=( - self._position[0] + self._size[0] * 0.5 * self._scale, - self._position[1] + self._size[1] * 0.65 * self._scale, - ), - ) - if self._ticket_text is not None: - bui.textwidget( - edit=self._ticket_text, - position=( - position[0] + self._size[0] * 0.5 * self._scale, - position[1] + self._size[1] * 0.28 * self._scale, - ), - size=(0, 0), - ) - bui.imagewidget( - edit=self._available_purchase_backing, - position=( - self._circle_center[0] - self._circle_rad * 1.02, - self._circle_center[1] - self._circle_rad * 1.13, - ), - ) - bui.textwidget( - edit=self._available_purchase_text, position=self._circle_center - ) - - bui.imagewidget( - edit=self._sale_backing, - position=( - self._sale_circle_center[0] - self._sale_circle_rad, - self._sale_circle_center[1] - self._sale_circle_rad, - ), - ) - bui.textwidget( - edit=self._sale_title_text, - position=( - self._sale_circle_center[0], - self._sale_circle_center[1] + self._sale_circle_rad * 0.3, - ), - ) - bui.textwidget( - edit=self._sale_time_text, - position=( - self._sale_circle_center[0], - self._sale_circle_center[1] - self._sale_circle_rad * 0.3, - ), - ) - - 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 - - plus = bui.app.plus - assert plus is not None - if plus.get_v1_account_state() != 'signed_in': - show_sign_in_prompt() - return - - raise RuntimeError('no longer wired up') - - # StoreBrowserWindow(modal=True, origin_widget=self._button) - - def get_button(self) -> bui.Widget: - """Return the underlying button widget.""" - return self._button - - def _update(self) -> None: - # pylint: disable=too-many-branches - # pylint: disable=cyclic-import - from babase import SpecialChar - - plus = bui.app.plus - assert plus is not None - assert bui.app.classic is not None - store = bui.app.classic.store - - if not self._button: - return # Our instance may outlive our UI objects. - - if self._ticket_text is not None: - if plus.get_v1_account_state() == 'signed_in': - sval = bui.charstr(SpecialChar.TICKET) + str( - plus.get_v1_account_ticket_count() - ) - else: - sval = '-' - bui.textwidget(edit=self._ticket_text, text=sval) - available_purchases = store.get_available_purchase_count() - - # Old pro sale stuff.. - sale_time = store.get_available_sale_time('extras') - - # ..also look for new style sales. - if sale_time is None: - import datetime - - sales_raw = plus.get_v1_account_misc_read_val('sales', {}) - sale_times = [] - try: - # Look at the current set of sales; filter any with time - # remaining that we don't own. - for sale_item, sale_info in list(sales_raw.items()): - if not plus.get_v1_account_product_purchased(sale_item): - to_end = ( - datetime.datetime.fromtimestamp( - sale_info['e'], datetime.UTC - ) - - utc_now() - ).total_seconds() - if to_end > 0: - sale_times.append(to_end) - except Exception: - logging.exception('Error parsing sales.') - if sale_times: - sale_time = int(min(sale_times) * 1000) - - if sale_time is not None: - bui.textwidget( - edit=self._sale_title_text, - text=bui.Lstr(resource='store.saleText'), - ) - bui.textwidget( - edit=self._sale_time_text, - text=bui.timestring(sale_time / 1000.0, centi=False), - ) - bui.imagewidget(edit=self._sale_backing, opacity=1.0) - bui.imagewidget(edit=self._available_purchase_backing, opacity=1.0) - bui.textwidget(edit=self._available_purchase_text, text='') - bui.imagewidget(edit=self._available_purchase_backing, opacity=0.0) - else: - bui.imagewidget(edit=self._sale_backing, opacity=0.0) - bui.textwidget(edit=self._sale_time_text, text='') - bui.textwidget(edit=self._sale_title_text, text='') - if available_purchases > 0: - bui.textwidget( - edit=self._available_purchase_text, - text=str(available_purchases), - ) - bui.imagewidget( - edit=self._available_purchase_backing, opacity=1.0 - ) - else: - bui.textwidget(edit=self._available_purchase_text, text='') - bui.imagewidget( - edit=self._available_purchase_backing, opacity=0.0 - ) diff --git a/src/ballistica/base/base.cc b/src/ballistica/base/base.cc index 34fff06f2..99b62cf18 100644 --- a/src/ballistica/base/base.cc +++ b/src/ballistica/base/base.cc @@ -206,7 +206,7 @@ void BaseFeatureSet::StartApp() { called_start_app_ = true; assert(!app_started_); // Shouldn't be possible. - LogVersionInfo_(); + LogStartupMessage_(); g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "start-app begin (main thread)"); @@ -420,7 +420,7 @@ void BaseFeatureSet::OnAppShutdownComplete() { } } -void BaseFeatureSet::LogVersionInfo_() { +void BaseFeatureSet::LogStartupMessage_() { char buffer[256]; if (g_buildconfig.headless_build()) { snprintf(buffer, sizeof(buffer), diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index 9ce9d9d57..8bc37bb71 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -828,7 +828,7 @@ class BaseFeatureSet : public FeatureSetNativeComponent, private: BaseFeatureSet(); - void LogVersionInfo_(); + void LogStartupMessage_(); void PrintContextNonLogicThread_(); void PrintContextForCallableLabel_(const char* label); void PrintContextUnavailable_(); diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 954891e37..0a2e9e024 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 = 22146; +const int kEngineBuildNumber = 22147; 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 99092eae8..ff3c1b4d1 100644 --- a/src/ballistica/ui_v1/widget/root_widget.cc +++ b/src/ballistica/ui_v1/widget/root_widget.cc @@ -3,7 +3,6 @@ #include "ballistica/ui_v1/widget/root_widget.h" #include -#include #include #include @@ -1457,30 +1456,51 @@ void RootWidget::SetXPText(const std::string& val) { } void RootWidget::SetHaveLiveValues(bool have_live_values) { - auto cval{have_live_values ? 1.0f : 0.4f}; - auto oval{have_live_values ? 1.0f : 0.2f}; + // auto cval{have_live_values ? 1.0f : 0.4f}; + auto oval{have_live_values ? 1.0f : 0.4f}; auto oval2{have_live_values ? 1.0f : 0.4f}; assert(tickets_meter_text_); assert(tickets_meter_icon_); tickets_meter_text_->widget->set_color(1.0f, 1.0f, 1.0f, oval); - tickets_meter_icon_->widget->set_color(cval, cval, cval); + // tickets_meter_icon_->widget->set_color(cval, cval, cval); + tickets_meter_icon_->widget->set_opacity(oval2); assert(tokens_meter_text_); assert(tokens_meter_icon_); tokens_meter_text_->widget->set_color(1.0f, 1.0f, 1.0f, oval); - tokens_meter_icon_->widget->set_color(cval, cval, cval); + // tokens_meter_icon_->widget->set_color(cval, cval, cval); + tokens_meter_icon_->widget->set_opacity(oval2); assert(inbox_button_); inbox_button_->widget->set_opacity(oval2); + assert(achievements_button_); + achievements_button_->widget->set_opacity(oval2); + assert(achievement_percent_text_); + achievement_percent_text_->widget->set_color(1.0f, 1.0f, 1.0f, oval); + + assert(store_button_); + store_button_->widget->set_opacity(oval2); + + assert(inventory_button_); + inventory_button_->widget->set_opacity(oval2); + + assert(get_tokens_button_); + get_tokens_button_->widget->set_opacity(oval2); + assert(league_rank_text_); league_rank_text_->widget->set_color(1.0f, 1.0f, 1.0f, oval); - // Note: We are currently driving trophy icon color based on league and - // opacity here based on connectivity. This keeps logic simple but is a - // bit different than other icons where we only drive color and keep - // opacity at 1.0. + assert(tickets_meter_button_); + tickets_meter_button_->widget->set_opacity(oval2); + + assert(tokens_meter_button_); + tokens_meter_button_->widget->set_opacity(oval2); + + assert(trophy_meter_button_); + trophy_meter_button_->widget->set_opacity(oval2); + assert(trophy_icon_); trophy_icon_->widget->set_opacity(oval2);