From da64da2f203d570106cf8e23d518fa74f4ade98a Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Wed, 25 Dec 2024 01:49:45 -0800 Subject: [PATCH] toolbar ui bits are now faded when not connected to the master server --- .efrocachemap | 78 +++++++++---------- CHANGELOG.md | 2 +- .../ba_data/python/babase/_accountv2.py | 12 ++- src/assets/ba_data/python/babase/_appmode.py | 16 ++-- .../ba_data/python/babase/_emptyappmode.py | 2 +- .../ba_data/python/baclassic/_appmode.py | 50 ++++++++++-- src/assets/ba_data/python/baenv.py | 2 +- src/assets/ba_data/python/baplus/_cloud.py | 16 +++- .../python/methods/python_methods_classic.cc | 52 ++++++++++--- .../classic/support/classic_app_mode.cc | 17 ++++ .../classic/support/classic_app_mode.h | 2 + src/ballistica/shared/ballistica.cc | 2 +- src/ballistica/ui_v1/widget/root_widget.cc | 52 +++++++++++-- src/ballistica/ui_v1/widget/root_widget.h | 3 + 14 files changed, 230 insertions(+), 76 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index f42643224..348fee98f 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,8 +421,8 @@ "build/assets/ba_data/audio/zoeOw.ogg": "b2d705c31c9dcc1efdc71394764c3beb", "build/assets/ba_data/audio/zoePickup01.ogg": "e9366dc2d2b8ab8b0c4e2c14c02d0789", "build/assets/ba_data/audio/zoeScream01.ogg": "903e0e45ee9b3373e9d9ce20c814374e", - "build/assets/ba_data/data/langdata.json": "7cdc9f897e458e98cd0131a13b87db24", - "build/assets/ba_data/data/languages/arabic.json": "8f89f09ad168c251765efebde4c9069c", + "build/assets/ba_data/data/langdata.json": "3775cd8b6f05c2205b7653302308acf9", + "build/assets/ba_data/data/languages/arabic.json": "3c22e7b6d7b09a812a2e28b35c9e9241", "build/assets/ba_data/data/languages/belarussian.json": "0b60a9d4496d1213c2d0b647d346ce30", "build/assets/ba_data/data/languages/chinese.json": "fc45d2838b834889c06920ae7c2102fa", "build/assets/ba_data/data/languages/chinesetraditional.json": "904b35b656c53f9830e406565edd5120", @@ -445,7 +445,7 @@ "build/assets/ba_data/data/languages/malay.json": "0212e18e54efa202c17505376e5b82fb", "build/assets/ba_data/data/languages/persian.json": "2584895475fe62b3fe49a5ea5e69b4b1", "build/assets/ba_data/data/languages/piratespeak.json": "7c7e3b72b87c1bcd5b04c9f64d912f0c", - "build/assets/ba_data/data/languages/polish.json": "d0822d5d3bdd72ddb04dc3c43a0b1395", + "build/assets/ba_data/data/languages/polish.json": "941eb816c7db9e04d6a3b8f28a64e2e8", "build/assets/ba_data/data/languages/portuguese.json": "b4463a05d65515f6812e1177c60ac666", "build/assets/ba_data/data/languages/romanian.json": "5ae206fe0b71c4015b02b86da8931c8f", "build/assets/ba_data/data/languages/russian.json": "fc64ed6b6356ea11385ee5c20748425a", @@ -4103,42 +4103,42 @@ "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": "e22300fab655f96dae4021fa82cf5130", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "a585418907ebcd55788fc7522293055d", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "58e5c912b710cb61600f3ad82efd17e1", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "867fc8d0171facc2791323b4a2fc46fc", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "d2f9014578a6d5eca3c345b7c9470812", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "56d41454f04299cfa455aba882028cc1", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "21a9ef40c5cd663a29dc8c24c2ff0f95", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "29e757036b87bef6ce6d68203bda9efb", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "66dde4c6865cfc5b8de8369b92c4a103", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "55f347328de6f3e2c8f2dc9749b57436", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "0d1dbc0d04f264ceddb3ad6803105bd9", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "12e891f298f604be7592b7c7ed5b8479", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "30cb8ee5ebd69d98a3bd625774d19bf0", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "e788895a7c94af2cb7817c02e061c429", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "92a3afc186b9031c7ff91ce2a6800ce7", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "7e947dea1b10297b441ffc829943f437", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "c8c1f174ed35992eb71bf1ff22787f4e", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "67e1e5286f3fe64c9935e0e22d3fe443", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "c8c1f174ed35992eb71bf1ff22787f4e", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "67e1e5286f3fe64c9935e0e22d3fe443", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "c6f45e134e680f696df6d5f605fb8308", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "cfb87dbb40bfd0cdf4be9da5086265f8", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "c6f45e134e680f696df6d5f605fb8308", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "cfb87dbb40bfd0cdf4be9da5086265f8", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "b39713b9f3a9102fefff1f6d62a9fd82", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "1c2d42d75e8f975514b2e30f5602516d", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "b39713b9f3a9102fefff1f6d62a9fd82", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "1c2d42d75e8f975514b2e30f5602516d", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "20ffab975711f6865ea4627a1e5ed377", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "06124d291e394169ff2a50bef10f832d", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "8d9d7fe4ab396118ef3ef2721372c9cf", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "18890dfa2a926a787d46f00a974eae95", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "d597aae4c2924f031d5514386ec84a63", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "04ab6918264677f49f3add66cdc722e8", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "2a4f8529288c1e8e584f8196085b840b", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "02da45dd942ae7703304750f2f6c05c1", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ac42dc5ce0ef7b272822b1afc8c2b78a", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "03a9776bc8d9e2c97928122f2e84374c", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "0654c93a83cb6f40d93e580cd68132c5", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "3b8b885ed5173a3e620f5fb10e4890a9", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "346ee4371820081c5be964fff81ab149", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "87678c0bd2dd856b40379ac9308b88df", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "c6945a8d662afb73a086b01c0bff7e58", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "cfc42ab32e3b86324bcb05df1c0f7c52", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "fbf39427b4e8528bcc4671a2c37a38ec", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "31ee0ec327cff5a85c3ef934e9d93810", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "41cb4f905a9a1eac5ddb9fd7a9b0bdfc", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "e3bc4c63c4e22c56a2ee87e3fd1a3947", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "ad6cdcf56eedccf1c7f94916107260c6", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d7ee1be677872b0c9e1c052589204a97", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "32550cf8d6e8895679f36d68df23b02e", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "266828aaa13614821cee4d66fd9c118b", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "5e7b339b80b97f0bb240078bc9969930", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "cc2ceb7f849be8d5a043e4d2f79a68cf", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "5e7b339b80b97f0bb240078bc9969930", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "cc2ceb7f849be8d5a043e4d2f79a68cf", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "b096576e67b3f0678e74eb1218bd1a4c", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "7fad4b9512b409db539bbe24e668eac7", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "b096576e67b3f0678e74eb1218bd1a4c", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "7fad4b9512b409db539bbe24e668eac7", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "3d5abe0bb45af74117b671b2bd1d7a61", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "f36cdc85dfa38f29410642a0886472e6", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "3d5abe0bb45af74117b671b2bd1d7a61", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "f36cdc85dfa38f29410642a0886472e6", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "80c0900ee2aa69e9865e2cbfaf4ad090", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "0450ca377feacf4e09584560ec4e167e", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "a6a6c697ea7d35fabefe6b9cfd42392f", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "4d7addbfac45de5d9dc764a8c53ba83c", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "b589bcd1262ba6ab78d0afcc1c04708d", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "5668e35fa03836ed849ab3571d76b83c", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "c87aad6e6204db414bdbed97c39e6b39", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "493d0273b8b000ec0ff1bf27c18de7a9", "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 374111e63..7780c6432 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.37 (build 22143, api 9, 2024-12-22) +### 1.7.37 (build 22145, api 9, 2024-12-25) - 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/babase/_accountv2.py b/src/assets/ba_data/python/babase/_accountv2.py index 0d96a380b..b04bec64f 100644 --- a/src/assets/ba_data/python/babase/_accountv2.py +++ b/src/assets/ba_data/python/babase/_accountv2.py @@ -35,6 +35,16 @@ def __init__(self) -> None: from babase._login import LoginAdapterGPGS, LoginAdapterGameCenter + # Register to be informed when connectivity changes. + plus = _babase.app.plus + self._connectivity_changed_cb = ( + None + if plus is None + else plus.cloud.on_connectivity_changed_callbacks.register( + self._on_cloud_connectivity_changed + ) + ) + # Whether or not everything related to an initial sign in (or # lack thereof) has completed. This includes things like # workspace syncing. Completion of this is what flips the app @@ -265,7 +275,7 @@ def on_implicit_login_state_changed( # We may want to auto-sign-in based on this new state. self._update_auto_sign_in() - def on_cloud_connectivity_changed(self, connected: bool) -> None: + def _on_cloud_connectivity_changed(self, connected: bool) -> None: """Should be called with cloud connectivity changes.""" del connected # Unused. assert _babase.in_logic_thread() diff --git a/src/assets/ba_data/python/babase/_appmode.py b/src/assets/ba_data/python/babase/_appmode.py index 17d4adca8..6de1d2b0f 100644 --- a/src/assets/ba_data/python/babase/_appmode.py +++ b/src/assets/ba_data/python/babase/_appmode.py @@ -27,20 +27,22 @@ def can_handle_intent(cls, intent: AppIntent) -> bool: """Return whether this mode can handle the provided intent. For this to return True, the AppMode must claim to support the - provided intent (via its _supports_intent() method) AND the + provided intent (via its _can_handle_intent() method) AND the AppExperience associated with the AppMode must be supported by the current app and runtime environment. """ - # TODO: check AppExperience. - return cls._supports_intent(intent) + # TODO: check AppExperience against current environment. + return cls._can_handle_intent(intent) @classmethod - def _supports_intent(cls, intent: AppIntent) -> bool: + def _can_handle_intent(cls, intent: AppIntent) -> bool: """Return whether our mode can handle the provided intent. - AppModes should override this to define what they can handle. - Note that AppExperience does not have to be considered here; that - is handled automatically by the can_handle_intent() call.""" + AppModes should override this to communicate what they can + handle. Note that AppExperience does not have to be considered + here; that is handled automatically by the can_handle_intent() + call. + """ raise NotImplementedError('AppMode subclasses must override this.') def handle_intent(self, intent: AppIntent) -> None: diff --git a/src/assets/ba_data/python/babase/_emptyappmode.py b/src/assets/ba_data/python/babase/_emptyappmode.py index 01372b54b..f1a7b8f65 100644 --- a/src/assets/ba_data/python/babase/_emptyappmode.py +++ b/src/assets/ba_data/python/babase/_emptyappmode.py @@ -26,7 +26,7 @@ def get_app_experience(cls) -> AppExperience: @override @classmethod - def _supports_intent(cls, intent: AppIntent) -> bool: + def _can_handle_intent(cls, intent: AppIntent) -> bool: # We support default and exec intents currently. return isinstance(intent, AppIntentExec | AppIntentDefault) diff --git a/src/assets/ba_data/python/baclassic/_appmode.py b/src/assets/ba_data/python/baclassic/_appmode.py index 2e5ad16b3..8a1f9ecda 100644 --- a/src/assets/ba_data/python/baclassic/_appmode.py +++ b/src/assets/ba_data/python/baclassic/_appmode.py @@ -30,9 +30,15 @@ def __init__(self) -> None: self._on_primary_account_changed_callback: ( CallbackRegistration | None ) = None + self._on_connectivity_changed_callback: CallbackRegistration | None = ( + None + ) self._test_sub: babase.CloudSubscription | None = None self._account_data_sub: babase.CloudSubscription | None = None + self._have_account_values = False + self._have_connectivity = False + @override @classmethod def get_app_experience(cls) -> AppExperience: @@ -40,7 +46,7 @@ def get_app_experience(cls) -> AppExperience: @override @classmethod - def _supports_intent(cls, intent: babase.AppIntent) -> bool: + def _can_handle_intent(cls, intent: babase.AppIntent) -> bool: # We support default and exec intents currently. return isinstance( intent, babase.AppIntentExec | babase.AppIntentDefault @@ -118,14 +124,22 @@ def on_activate(self) -> None: self._root_ui_chest_slot_pressed, 3 ) + # We want to be informed when connectivity changes. + self._on_connectivity_changed_callback = ( + plus.cloud.on_connectivity_changed_callbacks.register( + self._update_for_connectivity_change + ) + ) # We want to be informed when primary account changes. self._on_primary_account_changed_callback = ( plus.accounts.on_primary_account_changed_callbacks.register( - self.update_for_primary_account + self._update_for_primary_account ) ) # Establish subscriptions/etc. for any current primary account. - self.update_for_primary_account(plus.accounts.primary) + self._update_for_primary_account(plus.accounts.primary) + self._have_connectivity = plus.cloud.is_connected() + self._update_for_connectivity_change(self._have_connectivity) @override def on_deactivate(self) -> None: @@ -136,7 +150,7 @@ def on_deactivate(self) -> None: self._on_primary_account_changed_callback = None # Remove anything following any current account. - self.update_for_primary_account(None) + self._update_for_primary_account(None) # Save where we were in the UI so we return there next time. if classic is not None: @@ -152,7 +166,7 @@ def on_app_active_changed(self) -> None: if not babase.app.active: babase.invoke_main_menu() - def update_for_primary_account( + def _update_for_primary_account( self, account: babase.AccountV2Handle | None ) -> None: """Update subscriptions/etc. for a new primary account state.""" @@ -180,7 +194,7 @@ def update_for_primary_account( if account is None: self._account_data_sub = None - _baclassic.set_root_ui_values( + _baclassic.set_root_ui_account_values( tickets_text='-', tokens_text='-', league_rank_text='-', @@ -195,7 +209,6 @@ def update_for_primary_account( chest_2_appearance='', chest_3_appearance='', ) - else: with account: self._account_data_sub = ( @@ -204,6 +217,23 @@ def update_for_primary_account( ) ) + def _update_for_connectivity_change(self, connected: bool) -> None: + """Update when the app's connectivity state changes.""" + self._have_connectivity = connected + self._update_have_live_values() + + def _update_have_live_values(self) -> None: + + # We want to show ui elements faded out unless we have a live + # connection to the master-server AND have received a set of UI + # values from them. If we just plug in connectivity here we get + # UI stuff un-fading a moment or two before values appear (since + # the subscriptions have not sent us any values yet) which looks + # odd. + _baclassic.set_root_ui_have_live_values( + self._have_connectivity and self._have_account_values + ) + def _on_sub_test_update(self, val: int | None) -> None: print(f'GOT SUB TEST UPDATE: {val}') @@ -221,7 +251,7 @@ def _on_classic_account_data_change( chest2 = val.chests.get('2') chest3 = val.chests.get('3') - _baclassic.set_root_ui_values( + _baclassic.set_root_ui_account_values( tickets_text=str(val.tickets), tokens_text=str(val.tokens), league_rank_text=( @@ -249,6 +279,10 @@ def _on_classic_account_data_change( ), ) + # Note that we have values and updated faded state accordingly. + self._have_account_values = True + self._update_have_live_values() + def _root_ui_menu_press(self) -> None: from babase import push_back_press diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 343467181..65fdfab23 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 = 22143 +TARGET_BALLISTICA_BUILD = 22145 TARGET_BALLISTICA_VERSION = '1.7.37' diff --git a/src/assets/ba_data/python/baplus/_cloud.py b/src/assets/ba_data/python/baplus/_cloud.py index d2ab5c205..fdfcdf56a 100644 --- a/src/assets/ba_data/python/baplus/_cloud.py +++ b/src/assets/ba_data/python/baplus/_cloud.py @@ -7,6 +7,7 @@ import logging from typing import TYPE_CHECKING, overload +from efro.call import CallbackSet import babase if TYPE_CHECKING: @@ -24,6 +25,12 @@ class CloudSubsystem(babase.AppSubsystem): """Manages communication with cloud components.""" + def __init__(self) -> None: + super().__init__() + self.on_connectivity_changed_callbacks: CallbackSet[ + Callable[[bool], None] + ] = CallbackSet() + @property def connected(self) -> bool: """Property equivalent of CloudSubsystem.is_connected().""" @@ -44,9 +51,12 @@ def on_connectivity_changed(self, connected: bool) -> None: plus = babase.app.plus assert plus is not None - # Inform things that use this. - # (TODO: should generalize this into some sort of registration system) - plus.accounts.on_cloud_connectivity_changed(connected) + # Fire any registered callbacks for this. + for call in self.on_connectivity_changed_callbacks.getcalls(): + try: + call(connected) + except Exception: + logging.exception('Error in connectivity-changed callback.') @overload def send_message_cb( diff --git a/src/ballistica/classic/python/methods/python_methods_classic.cc b/src/ballistica/classic/python/methods/python_methods_classic.cc index 7d87408f2..cfcf45fa1 100644 --- a/src/ballistica/classic/python/methods/python_methods_classic.cc +++ b/src/ballistica/classic/python/methods/python_methods_classic.cc @@ -3,6 +3,7 @@ #include "ballistica/classic/python/methods/python_methods_classic.h" #include +#include #include #include @@ -289,10 +290,10 @@ static PyMethodDef PyClassicAppModeDeactivateDef = { "(internal)\n", }; -// -------------------------- set_root_ui_values ------------------------------- +// ---------------------- set_root_ui_account_values --------------------------- -static auto PySetRootUIValues(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PySetRootUIAccountValues(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* tickets_text; @@ -353,12 +354,12 @@ static auto PySetRootUIValues(PyObject* self, PyObject* args, PyObject* keywds) BA_PYTHON_CATCH; } -static PyMethodDef PySetRootUIValuesDef = { - "set_root_ui_values", // name - (PyCFunction)PySetRootUIValues, // method - METH_VARARGS | METH_KEYWORDS, // flags +static PyMethodDef PySetRootUIAccountValuesDef = { + "set_root_ui_account_values", // name + (PyCFunction)PySetRootUIAccountValues, // method + METH_VARARGS | METH_KEYWORDS, // flags - "set_root_ui_values(*,\n" + "set_root_ui_account_values(*,\n" " tickets_text: str,\n" " tokens_text: str,\n" " league_rank_text: str,\n" @@ -377,6 +378,38 @@ static PyMethodDef PySetRootUIValuesDef = { "(internal)", }; +// --------------------- set_root_ui_have_live_values -------------------------- + +static auto PySetRootUIHaveLiveValues(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { + BA_PYTHON_TRY; + + int have_live_values{}; + + static const char* kwlist[] = {"have_live_values", nullptr}; + if (!PyArg_ParseTupleAndKeywords( + args, keywds, "p", const_cast(kwlist), &have_live_values)) { + return nullptr; + } + BA_PRECONDITION(g_base->InLogicThread()); + + auto* appmode = ClassicAppMode::GetActiveOrThrow(); + appmode->SetRootUIHaveLiveValues(have_live_values); + + Py_RETURN_NONE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PySetRootUIHaveLiveValuesDef = { + "set_root_ui_have_live_values", // name + (PyCFunction)PySetRootUIHaveLiveValues, // method + METH_VARARGS | METH_KEYWORDS, // flags + + "set_root_ui_have_live_values(have_live_values: bool) -> None\n" + "\n" + "(internal)", +}; + // ----------------------------------------------------------------------------- auto PythonMethodsClassic::GetMethods() -> std::vector { @@ -387,7 +420,8 @@ auto PythonMethodsClassic::GetMethods() -> std::vector { PyClassicAppModeHandleAppIntentDefaultDef, PyClassicAppModeActivateDef, PyClassicAppModeDeactivateDef, - PySetRootUIValuesDef, + PySetRootUIAccountValuesDef, + PySetRootUIHaveLiveValuesDef, }; } diff --git a/src/ballistica/classic/support/classic_app_mode.cc b/src/ballistica/classic/support/classic_app_mode.cc index 5d9be9d55..eb261a576 100644 --- a/src/ballistica/classic/support/classic_app_mode.cc +++ b/src/ballistica/classic/support/classic_app_mode.cc @@ -161,6 +161,7 @@ void ClassicAppMode::Reset_() { root_widget->SetChests( root_ui_chest_0_appearance_, root_ui_chest_1_appearance_, root_ui_chest_2_appearance_, root_ui_chest_3_appearance_); + root_widget->SetHaveLiveValues(root_ui_have_live_values_); } } @@ -1699,6 +1700,22 @@ void ClassicAppMode::SetRootUIGoldPass(bool enabled) { } } +void ClassicAppMode::SetRootUIHaveLiveValues(bool have_live_values) { + if (have_live_values == root_ui_have_live_values_) { + return; + } + + // Store the value. + root_ui_have_live_values_ = have_live_values; + + // Apply it to any existing UI. + if (uiv1_) { + if (auto* root_widget = uiv1_->root_widget()) { + root_widget->SetHaveLiveValues(root_ui_have_live_values_); + } + } +} + void ClassicAppMode::SetRootUIChests(const std::string& chest_0_appearance, const std::string& chest_1_appearance, const std::string& chest_2_appearance, diff --git a/src/ballistica/classic/support/classic_app_mode.h b/src/ballistica/classic/support/classic_app_mode.h index 805c5a236..edfaafe08 100644 --- a/src/ballistica/classic/support/classic_app_mode.h +++ b/src/ballistica/classic/support/classic_app_mode.h @@ -228,6 +228,7 @@ class ClassicAppMode : public base::AppMode { const std::string& chest_1_appearance, const std::string& chest_2_appearance, const std::string& chest_3_appearance); + void SetRootUIHaveLiveValues(bool val); private: ClassicAppMode(); @@ -271,6 +272,7 @@ class ClassicAppMode : public base::AppMode { bool kick_voting_enabled_{true}; bool replay_paused_{}; bool root_ui_gold_pass_{}; + bool root_ui_have_live_values_{}; ui_v1::UIV1FeatureSet* uiv1_{}; cJSON* game_roster_{}; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 005b1097d..872cf7f8c 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 = 22143; +const int kEngineBuildNumber = 22145; 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 95e66c56b..99092eae8 100644 --- a/src/ballistica/ui_v1/widget/root_widget.cc +++ b/src/ballistica/ui_v1/widget/root_widget.cc @@ -3,6 +3,7 @@ #include "ballistica/ui_v1/widget/root_widget.h" #include +#include #include #include @@ -336,6 +337,13 @@ void RootWidget::AddMeter_(MeterType_ type, float h_align, float r, float g, switch (type) { case MeterType_::kTrophy: trophy_icon_ = img; + break; + case MeterType_::kTickets: + tickets_meter_icon_ = img; + break; + case MeterType_::kTokens: + tokens_meter_icon_ = img; + break; default: break; } @@ -1448,6 +1456,43 @@ void RootWidget::SetXPText(const std::string& val) { xp_text_->widget->SetText(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 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); + + 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); + + assert(inbox_button_); + inbox_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(trophy_icon_); + trophy_icon_->widget->set_opacity(oval2); + + for (auto* button : + {chest_0_button_, chest_1_button_, chest_2_button_, chest_3_button_}) { + assert(button); + button->widget->set_opacity(have_live_values ? 1.0f : 0.5f); + } + assert(chest_backing_); + chest_backing_->widget->set_opacity(have_live_values ? 1.0f : 0.5f); +} + void RootWidget::SetChests(const std::string& chest_0_appearance, const std::string& chest_1_appearance, const std::string& chest_2_appearance, @@ -1470,9 +1515,8 @@ void RootWidget::SetChests(const std::string& chest_0_appearance, assert(b); if (appearance == "") { b->widget->set_color(0.473f, 0.44f, 0.583f); - b->widget->set_opacity(have_chests ? 1.0f : 0.5f); b->width = b->height = 80.0f; - b->y = have_chests ? 44.0f : 0.0f; + b->y = have_chests ? 44.0f : -2.0f; { base::Assets::AssetListLock lock; b->widget->SetTexture( @@ -1481,7 +1525,6 @@ void RootWidget::SetChests(const std::string& chest_0_appearance, } else { have_chests = true; b->widget->set_color(1.0f, 1.0f, 1.0f); - b->widget->set_opacity(1.0f); b->width = b->height = 110.0f; b->y = 44.0f; { @@ -1491,8 +1534,7 @@ void RootWidget::SetChests(const std::string& chest_0_appearance, } } assert(chest_backing_); - chest_backing_->y = have_chests ? 41.0f : -10.0f; - chest_backing_->widget->set_opacity(have_chests ? 1.0f : 0.5f); + chest_backing_->y = have_chests ? 41.0f : -15.0f; child_widgets_dirty_ = true; } diff --git a/src/ballistica/ui_v1/widget/root_widget.h b/src/ballistica/ui_v1/widget/root_widget.h index ec3ad660d..20e9dae63 100644 --- a/src/ballistica/ui_v1/widget/root_widget.h +++ b/src/ballistica/ui_v1/widget/root_widget.h @@ -51,6 +51,7 @@ class RootWidget : public ContainerWidget { const std::string& chest_1_appearance, const std::string& chest_2_appearance, const std::string& chest_3_appearance); + void SetHaveLiveValues(bool have_live_values); auto bottom_left_height() const { return bottom_left_height_; } @@ -102,6 +103,8 @@ class RootWidget : public ContainerWidget { Button_* chest_3_button_{}; Button_* chest_backing_{}; Image_* trophy_icon_{}; + Image_* tickets_meter_icon_{}; + Image_* tokens_meter_icon_{}; Image_* inbox_count_backing_{}; Text_* squad_size_text_{}; Text_* account_name_text_{};