From 5f46726d203217c8a571e8d7b8d551989d27ec4e Mon Sep 17 00:00:00 2001 From: Vishal Date: Sun, 8 Oct 2023 22:10:39 +0530 Subject: [PATCH 01/25] Update onscreenkeyboard.py --- src/assets/ba_data/python/bauiv1/onscreenkeyboard.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/assets/ba_data/python/bauiv1/onscreenkeyboard.py b/src/assets/ba_data/python/bauiv1/onscreenkeyboard.py index 30a168c3..7dc42b0e 100644 --- a/src/assets/ba_data/python/bauiv1/onscreenkeyboard.py +++ b/src/assets/ba_data/python/bauiv1/onscreenkeyboard.py @@ -51,6 +51,18 @@ class OnScreenKeyboardWindow(Window): else (0, 0), ) ) + self._cancel_button = _bauiv1.buttonwidget( + parent=self._root_widget, + scale=0.5, + position=(30, self._height - 55), + size=(60, 60), + label='', + on_activate_call=self._cancel, + autoselect=True, + color=(0.55, 0.5, 0.6), + icon=_bauiv1.gettexture('crossOut'), + iconscale=1.2, + ) self._done_button = _bauiv1.buttonwidget( parent=self._root_widget, position=(self._width - 200, 44), From 839874604d1d304d4de8628cfbf6c81f697e35cc Mon Sep 17 00:00:00 2001 From: Vishal Date: Fri, 13 Oct 2023 07:21:43 +0530 Subject: [PATCH 02/25] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 968333b3..8eb8e41b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ huge chunks of it and put back still-relevant pieces in a much more cleanly designed way. This should put us in a much better place for supporting various platforms and making graphical improvements going forward. - `ballistica/base/app_adapter/app_adapter_sdl.cc` for an example of the now + `ballistica/base/app_adapter/app_adapter_sdl.cc` is an example of the now nicely implemented system. - The engine now requires OpenGL 3.0 or newer on desktop and OpenGL ES 3.0 or newer on mobile. This means we're cutting off a few percent of old devices on From 32dd54303a1ff9c2781b9356dbfd7c1c0d616f91 Mon Sep 17 00:00:00 2001 From: Vishal Date: Sun, 15 Oct 2023 13:11:39 +0530 Subject: [PATCH 03/25] Update publictab.py --- .../ba_data/python/bauiv1lib/gather/publictab.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py index 0a9ef110..3eb8239e 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py @@ -361,6 +361,7 @@ class PublicGatherTab(GatherTab): self._last_server_list_query_time: float | None = None self._join_list_column: bui.Widget | None = None self._join_status_text: bui.Widget | None = None + self._no_servers_text: bui.Widget | None = None self._host_max_party_size_value: bui.Widget | None = None self._host_max_party_size_minus_button: (bui.Widget | None) = None self._host_max_party_size_plus_button: (bui.Widget | None) = None @@ -658,6 +659,18 @@ class PublicGatherTab(GatherTab): color=(0.6, 0.6, 0.6), position=(c_width * 0.5, c_height * 0.5), ) + self._no_servers_text = bui.textwidget( + parent=self._container, + text='', + size=(0, 0), + scale=0.9, + flatness=1.0, + shadow=0.0, + h_align='center', + v_align='top', + color=(0.6, 0.6, 0.6), + position=(c_width * 0.5, c_height * 0.5), + ) def _build_host_tab( self, region_width: float, region_height: float From a17ac19946d2b6b6b5c84c445869afcacb934c57 Mon Sep 17 00:00:00 2001 From: Vishal Date: Sun, 15 Oct 2023 13:16:46 +0530 Subject: [PATCH 04/25] Update publictab.py --- .../python/bauiv1lib/gather/publictab.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py index 3eb8239e..d1e57760 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py @@ -963,6 +963,10 @@ class PublicGatherTab(GatherTab): self._update_party_rows() def _update_party_rows(self) -> None: + + plus = bui.app.plus + assert plus is not None + columnwidget = self._join_list_column if not columnwidget: return @@ -976,6 +980,10 @@ class PublicGatherTab(GatherTab): edit=self._host_scrollwidget, claims_up_down=(len(self._parties_displayed) > 0), ) + bui.textwidget( + edit=self._no_servers_text, + text='' + ) # Clip if we have more UI rows than parties to show. clipcount = len(self._ui_rows) - len(self._parties_displayed) @@ -985,6 +993,15 @@ class PublicGatherTab(GatherTab): # If we have no parties to show, we're done. if not self._parties_displayed: + text = self._join_status_text + if ( + plus.get_v1_account_state() == 'signed_in' + and cast(str, bui.textwidget(query=text)) == '' + ): + bui.textwidget( + edit=self._no_servers_text, + text='No Servers Found' #bui.Lstr(resource='notSignedInText') + ) return sub_scroll_width = 830 From c4676688e83147f5c66845ea4d1329215944804b Mon Sep 17 00:00:00 2001 From: Vishal Date: Sun, 15 Oct 2023 13:25:58 +0530 Subject: [PATCH 05/25] Adding Language Compatibility --- src/assets/ba_data/python/bauiv1lib/gather/publictab.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py index d1e57760..20ad8e15 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py @@ -1000,7 +1000,7 @@ class PublicGatherTab(GatherTab): ): bui.textwidget( edit=self._no_servers_text, - text='No Servers Found' #bui.Lstr(resource='notSignedInText') + text=bui.Lstr(resource='noServerFoundText') ) return From 0e808871b49ef13dd1970f38445781e82ef2c85c Mon Sep 17 00:00:00 2001 From: Era <100019405+EraOSBeta@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:03:02 +0330 Subject: [PATCH 06/25] Added reject_recently_left_players Co-authored-by: Rikko --- CONTRIBUTORS.md | 4 ++ .../ba_data/python/bascenev1/_session.py | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d8c74cc1..6aacc6ad 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -43,6 +43,10 @@ ### Era0S - Bug Fixer - Modder +- Added a feature ### VinniTR - Fixes + +### Rikko +- Created the original "reject_recently_left_players" plugin diff --git a/src/assets/ba_data/python/bascenev1/_session.py b/src/assets/ba_data/python/bascenev1/_session.py index ffef80cd..60dedad1 100644 --- a/src/assets/ba_data/python/bascenev1/_session.py +++ b/src/assets/ba_data/python/bascenev1/_session.py @@ -3,6 +3,7 @@ """Defines base session class.""" from __future__ import annotations +import math import weakref import logging from typing import TYPE_CHECKING @@ -17,6 +18,8 @@ if TYPE_CHECKING: import bascenev1 +TIMEOUT = 10 + class Session: """Defines a high level series of bascenev1.Activity-es. @@ -203,6 +206,10 @@ class Session: # Instantiate our session globals node which will apply its settings. self._sessionglobalsnode = _bascenev1.newnode('sessionglobals') + self._players_on_wait: dict = {} + self._player_requested_identifiers: dict = {} + self._waitlist_timers: dict = {} + @property def context(self) -> bascenev1.ContextRef: """A context-ref pointing at this activity.""" @@ -253,6 +260,26 @@ class Session: ) return False + identifier = player.get_v1_account_id() + if identifier: + leave_time = self._players_on_wait.get(identifier) + if leave_time: + diff = str(math.ceil(TIMEOUT - babase.apptime() + leave_time)) + _bascenev1.broadcastmessage( + babase.Lstr( + translate=( + 'serverResponses', + 'You can join in ${COUNT} seconds.', + ), + subs=[('${COUNT}', diff)], + ), + color=(1, 1, 0), + clients=[player.inputdevice.client_id], + transient=True, + ) + return False + self._player_requested_identifiers[player.id] = identifier + _bascenev1.getsound('dripity').play() return True @@ -270,6 +297,15 @@ class Session: activity = self._activity_weak() + identifier = self._player_requested_identifiers.get(sessionplayer.id) + if identifier: + self._players_on_wait[identifier] = babase.apptime() + with babase.ContextRef.empty(): + self._waitlist_timers[identifier] = babase.AppTimer( + TIMEOUT, + babase.Call(self._remove_player_from_waitlist, identifier), + ) + if not sessionplayer.in_game: # Ok, the player is still in the lobby; simply remove them. with self.context: @@ -770,3 +806,9 @@ class Session: if pass_to_activity: activity.add_player(sessionplayer) return sessionplayer + + def _remove_player_from_waitlist(self, identifier) -> None: + try: + self._players_on_wait.pop(identifier) + except KeyError: + pass From e0052db619c43a163b64bbf3a44b3b5de0b56107 Mon Sep 17 00:00:00 2001 From: Era <100019405+EraOSBeta@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:27:35 +0330 Subject: [PATCH 07/25] Damn you CI --- src/assets/ba_data/python/bascenev1/_session.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/ba_data/python/bascenev1/_session.py b/src/assets/ba_data/python/bascenev1/_session.py index 60dedad1..481249d9 100644 --- a/src/assets/ba_data/python/bascenev1/_session.py +++ b/src/assets/ba_data/python/bascenev1/_session.py @@ -807,7 +807,7 @@ class Session: activity.add_player(sessionplayer) return sessionplayer - def _remove_player_from_waitlist(self, identifier) -> None: + def _remove_player_from_waitlist(self, identifier: str) -> None: try: self._players_on_wait.pop(identifier) except KeyError: From 2ec08d706e6042d8b307a9bcce493061d53fdabe Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 26 Oct 2023 10:11:20 -0700 Subject: [PATCH 08/25] more apple version work and cleaning up keyboard input --- .efrocachemap | 88 ++--- CHANGELOG.md | 12 +- ballisticakit-cmake/CMakeLists.txt | 2 + .../Generic/BallisticaKitGeneric.vcxproj | 2 + .../BallisticaKitGeneric.vcxproj.filters | 6 + .../Headless/BallisticaKitHeadless.vcxproj | 2 + .../BallisticaKitHeadless.vcxproj.filters | 6 + src/assets/ba_data/python/babase/_app.py | 6 + src/assets/ba_data/python/baenv.py | 2 +- .../base/app_adapter/app_adapter.cc | 3 + src/ballistica/base/app_adapter/app_adapter.h | 10 + .../base/app_adapter/app_adapter_apple.cc | 45 ++- .../base/app_adapter/app_adapter_apple.h | 3 + .../base/app_adapter/app_adapter_sdl.cc | 4 +- src/ballistica/base/assets/assets_server.cc | 2 +- src/ballistica/base/assets/texture_asset.cc | 4 +- src/ballistica/base/audio/audio_server.cc | 2 +- src/ballistica/base/base.h | 1 + src/ballistica/base/graphics/graphics.cc | 6 +- src/ballistica/base/graphics/graphics.h | 29 +- .../base/graphics/graphics_server.cc | 59 +-- .../base/graphics/graphics_server.h | 27 +- .../base/graphics/mesh/text_mesh.cc | 2 +- .../base/graphics/text/font_page_map_data.h | 14 +- .../base/graphics/text/text_graphics.cc | 86 +++-- .../base/graphics/text/text_packer.cc | 78 ++-- .../base/graphics/text/text_packer.h | 16 +- .../base/input/device/joystick_input.cc | 257 ++++--------- .../base/input/device/joystick_input.h | 86 +++-- .../base/input/device/keyboard_input.cc | 350 +++++++++--------- .../base/input/device/keyboard_input.h | 26 +- src/ballistica/base/input/input.cc | 284 +++++++------- src/ballistica/base/logic/logic.cc | 12 +- src/ballistica/base/logic/logic.h | 3 +- .../platform/apple/base_platform_apple.cc | 11 +- .../python/class/python_class_app_timer.cc | 2 +- .../base/python/methods/python_methods_app.cc | 50 ++- .../python/methods/python_methods_graphics.cc | 1 + src/ballistica/base/support/app_timer.h | 16 +- src/ballistica/base/support/repeater.cc | 58 +++ src/ballistica/base/support/repeater.h | 35 ++ src/ballistica/base/ui/dev_console.cc | 105 +++--- src/ballistica/base/ui/dev_console.h | 27 +- src/ballistica/base/ui/ui.cc | 4 +- src/ballistica/base/ui/ui.h | 12 +- .../platform/apple/core_platform_apple.cc | 117 +++--- .../core/platform/apple/core_platform_apple.h | 4 +- .../core/platform/support/min_sdl.h | 2 +- .../python/class/python_class_base_timer.cc | 2 +- .../python/class/python_class_scene_timer.cc | 2 +- .../python/methods/python_methods_scene.cc | 4 +- .../scene_v1/support/host_activity.cc | 10 +- .../scene_v1/support/host_activity.h | 8 +- .../scene_v1/support/host_session.cc | 6 +- .../scene_v1/support/host_session.h | 2 +- .../scene_v1/support/scene_v1_context.cc | 6 +- .../scene_v1/support/scene_v1_context.h | 2 +- src/ballistica/shared/ballistica.cc | 2 +- .../shared/foundation/event_loop.cc | 6 +- src/ballistica/shared/foundation/event_loop.h | 3 +- src/ballistica/shared/generic/timer_list.cc | 3 +- src/ballistica/shared/generic/timer_list.h | 4 +- src/ballistica/ui_v1/widget/button_widget.cc | 4 +- .../ui_v1/widget/h_scroll_widget.cc | 2 +- src/ballistica/ui_v1/widget/scroll_widget.cc | 2 +- src/ballistica/ui_v1/widget/text_widget.cc | 120 +----- 66 files changed, 1112 insertions(+), 1055 deletions(-) create mode 100644 src/ballistica/base/support/repeater.cc create mode 100644 src/ballistica/base/support/repeater.h diff --git a/.efrocachemap b/.efrocachemap index b7a571d2..b24be883 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,50 +4056,50 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ad13d636bcb25150044a7644846b8a09", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "7c5df955611590ef491bf614fbd60179", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "ae38bd212ae64b51482a2ccb9c1cbfd3", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "d0bcee2dd5567719aa35667c5206dffc", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "eb3cd4f86175afcf8ffa2749afa32fa3", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "6b86ba36c3719773008feaa6cdc0d0f8", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "877c9ae4532fef809a3dcbd8ffea343c", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7df313c48c87460f56fa837502965088", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "bc40bb549d26437fb8679c1e9d088272", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "47aa08cb9f5e660023f0f3c0e4ffd65e", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "bbb0a8383d6ce1ca887190ea49223f4f", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "7dd91e3407d49981c1c975d4f01ac205", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "c87883aa2f832e792e945fd9208d712a", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "fea8fd84d8c060f2f82f402902b8c54e", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "0a454a8be47f37231655761d15e3f7e5", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "4c79db3a882eb0b8b225a8df0339b1cc", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "43b9ef321f8e80da29ddb19a760dbd77", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "6f891004f2f07c452dea29bd53f29d30", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "bf7a1ce0e7a2015d538406c6f6df761c", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "cf213dce81901a67c9970b3befdaa320", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "473e7e6c0cf90b9e6ac653552b18f68d", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "4e11b895cbf2e1339cf34bc06c54a4ea", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "473e7e6c0cf90b9e6ac653552b18f68d", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "4e11b895cbf2e1339cf34bc06c54a4ea", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "d9af1a429cff9346e0cad6fcea017e5b", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "ae5f87286947575463c386cfe1c443e4", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "d9af1a429cff9346e0cad6fcea017e5b", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "ae5f87286947575463c386cfe1c443e4", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "110eef3dc285a35a1899510e368c73b1", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "2692dc69f7cb2501f0aaa8675f559987", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "110eef3dc285a35a1899510e368c73b1", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "2692dc69f7cb2501f0aaa8675f559987", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "344954c4f788d7d9b4d7035ebb6131d8", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "abcede4e60fa8877f18e66e086fb7387", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "6149911c660a9864b651cc1a8e50eec1", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "57cef68ab703ba819bd0fbe9e4b1c331", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "a47bab28b86c7cefce891b8e5c8b687a", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "d68ebb1139363d711b044de65e17b204", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "ea1349137f64f3d662b9a95278ca4c02", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c8731ff226716cee3d1e46027ead1cfe", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4ee6b633a99c5bcbea4f5dee5bda186e", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "2c3bd4952b30d88247229ad309f73092", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "c98fdb967f44411171c3d7fde1c74471", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "5514854ae459adab968120a361692cd5", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "83bcfb3af22b61e5c35972d989b3f7f8", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "a63758734d93eb969fe482b56c8d1ed2", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "7e68a605645c70fca06e4f4d5155bb0c", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0598aa59718bb8404c3b007c22123c75", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "9c86d900fc1bc2d6f3bdb4c3e26149da", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "37f5996151f983b45925ad15dce2d0e9", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "b8560855bf772b3e74f2a8f190f54885", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "55c777fa3afd720089223fb949478502", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "81a41ddca9da9060d5d5034a84845674", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "536825d983f4a3bcec018b0295005bdb", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "1733a9610de15f77dd8df3effcca1516", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "f7434d47c371f0baaae676d288847351", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "d16ea39c50f41117697789dafb249200", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "55d18233c5b887af17afcb266a8c5597", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c4df3b76ef890daf48e8181cffd4cd82", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "eb609d02a0897c671e40519faad3365b", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "0c0d303a440e852d0112c3a5aa75ef36", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "bdd6b2c15d6718a6c99ee287d965f022", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "c9ef036408f0832cd068a34365485e0b", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "c9ef036408f0832cd068a34365485e0b", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "5bd8bcd68e03939501d192b7cda55d64", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "a8545c0c985eef9219c351773c5c6127", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "5bd8bcd68e03939501d192b7cda55d64", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "a8545c0c985eef9219c351773c5c6127", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "1e2c088713c47ff47d9aa312ebb0bd1a", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "e6bbe6c564c65cb498edc58daec1e084", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "1e2c088713c47ff47d9aa312ebb0bd1a", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "e6bbe6c564c65cb498edc58daec1e084", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "98df65aba607e74eb5c0c7305903ac29", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "2b57cf28eeadf43d09b1d780a5db1423", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "3314d791a9ab37ea81be824460c63d14", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "2b57cf28eeadf43d09b1d780a5db1423", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "bd63402d48fce829f16d59c6c1f87977", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "de24c4e6f661f6201b933af3343084cc", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "84904f537e435d09c06b4b6c10abea7d", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "22a32d161e85baa6c6459412a368bf82", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "f43972d496e1953fdc30ff094a22a0d1", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c069093fb4773f3feac13236d474ecf1", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4d745c03bbeab02c5f69bed1ae376933", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "c1e1321bb0d5bb74211377e0f5cae45c", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index 46e6c34d..9d37890f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21491, api 8, 2023-10-22) +### 1.7.28 (build 21510, api 8, 2023-10-26) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years @@ -154,6 +154,16 @@ seems pretty awesome these days. It should support most stuff SDL does and with less configuring involved. Please holler if you come across something that doesn't work. +- Mac build is also now using the Game Controller Framework to handle keyboard + events. This should better handle things like modifier keys and also will + allow us to use that exact same code on the iPad/iPhone version. +- OS key repeat events are no longer passed through the engine. This means that + any time we want repeating behavior, such as holding an arrow key to move + through UI elements, we will need to wire it up ourselves. We already do this + for things like game controllers however, so this is more consistent in a way. +- Dev console no longer claims key events unless the Python tab is showing and + there is a hardware keyboard attached. This allows showing dev console tabs + above gameplay without interfering with it. ### 1.7.27 (build 21282, api 8, 2023-08-30) diff --git a/ballisticakit-cmake/CMakeLists.txt b/ballisticakit-cmake/CMakeLists.txt index 297cfe0b..13214011 100644 --- a/ballisticakit-cmake/CMakeLists.txt +++ b/ballisticakit-cmake/CMakeLists.txt @@ -442,6 +442,8 @@ set(BALLISTICA_SOURCES ${BA_SRC_ROOT}/ballistica/base/support/huffman.cc ${BA_SRC_ROOT}/ballistica/base/support/huffman.h ${BA_SRC_ROOT}/ballistica/base/support/plus_soft.h + ${BA_SRC_ROOT}/ballistica/base/support/repeater.cc + ${BA_SRC_ROOT}/ballistica/base/support/repeater.h ${BA_SRC_ROOT}/ballistica/base/support/stdio_console.cc ${BA_SRC_ROOT}/ballistica/base/support/stdio_console.h ${BA_SRC_ROOT}/ballistica/base/support/stress_test.cc diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj index affcd239..68e39f6f 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj @@ -434,6 +434,8 @@ + + diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters index b3e5ebdf..761cf81f 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters @@ -736,6 +736,12 @@ ballistica\base\support + + ballistica\base\support + + + ballistica\base\support + ballistica\base\support diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj index 82d010b3..02f49c4b 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj @@ -429,6 +429,8 @@ + + diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters index b3e5ebdf..761cf81f 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters @@ -736,6 +736,12 @@ ballistica\base\support + + ballistica\base\support + + + ballistica\base\support + ballistica\base\support diff --git a/src/assets/ba_data/python/babase/_app.py b/src/assets/ba_data/python/babase/_app.py index ec0e0d8b..c22aee9f 100644 --- a/src/assets/ba_data/python/babase/_app.py +++ b/src/assets/ba_data/python/babase/_app.py @@ -915,6 +915,12 @@ class App: _babase.lifecyclelog('fade-and-shutdown-graphics begin') _babase.fade_screen(False, time=0.15) await asyncio.sleep(0.15) + + # Now tell the graphics system to go down and wait until + # it has done so. + _babase.graphics_shutdown_begin() + while not _babase.graphics_shutdown_is_complete(): + await asyncio.sleep(0.01) _babase.lifecyclelog('fade-and-shutdown-graphics end') async def _fade_and_shutdown_audio(self) -> None: diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 0d19c817..d2bc7bfe 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21491 +TARGET_BALLISTICA_BUILD = 21510 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/app_adapter/app_adapter.cc b/src/ballistica/base/app_adapter/app_adapter.cc index a7f1cf89..ee84b319 100644 --- a/src/ballistica/base/app_adapter/app_adapter.cc +++ b/src/ballistica/base/app_adapter/app_adapter.cc @@ -315,4 +315,7 @@ auto AppAdapter::GetGraphicsClientContext() -> GraphicsClientContext* { return new GraphicsClientContext(); } +auto AppAdapter::GetKeyRepeatDelay() -> float { return 0.3f; } +auto AppAdapter::GetKeyRepeatInterval() -> float { return 0.08f; } + } // namespace ballistica::base diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index 25fb83de..829c236d 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -189,6 +189,13 @@ class AppAdapter { /// changing (it may be preferable to rely on dialogs for non-english /// languages/etc.). Default implementation returns false. This function /// should be callable from any thread. + /// + /// Note that UI elements wanting to accept direct keyboard input should + /// not call this directly, but instead should call + /// UI::UIHasDirectKeyboardInput, as that takes into account other factors + /// such as which device is currently controlling the UI (Someone + /// navigating the UI with a game controller may still get an on-screen + /// keyboard even if there is a physical keyboard attached). virtual auto HasDirectKeyboardInput() -> bool; /// Called in the graphics context to apply new settings coming in from @@ -197,6 +204,9 @@ class AppAdapter { /// settings coming in. virtual void ApplyGraphicsSettings(const GraphicsSettings* settings); + virtual auto GetKeyRepeatDelay() -> float; + virtual auto GetKeyRepeatInterval() -> float; + protected: AppAdapter(); virtual ~AppAdapter(); diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.cc b/src/ballistica/base/app_adapter/app_adapter_apple.cc index aaefa65e..737b89bf 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -3,16 +3,21 @@ #include "ballistica/base/app_adapter/app_adapter_apple.h" -#include - #include "ballistica/base/graphics/gl/renderer_gl.h" #include "ballistica/base/graphics/graphics.h" #include "ballistica/base/graphics/graphics_server.h" #include "ballistica/base/logic/logic.h" +#include "ballistica/base/platform/apple/from_swift.h" #include "ballistica/base/support/app_config.h" #include "ballistica/shared/ballistica.h" #include "ballistica/shared/foundation/event_loop.h" +// clang-format off +// This needs to be below ballistica headers since it relies on +// some types in them but does not include headers itself. +#include +// clang-format on + namespace ballistica::base { /// RAII-friendly way to mark the thread and calls we're allowed to run graphics @@ -41,7 +46,7 @@ auto AppAdapterApple::ManagesMainThreadEventLoop() const -> bool { void AppAdapterApple::DoPushMainThreadRunnable(Runnable* runnable) { // Kick this along to swift. - BallisticaKit::FromCppPushRawRunnableToMain(runnable); + BallisticaKit::FromCpp::PushRawRunnableToMain(runnable); } void AppAdapterApple::DoApplyAppConfig() { assert(g_base->InLogicThread()); } @@ -122,16 +127,16 @@ auto AppAdapterApple::TryRender() -> bool { // matches what we have (or until we try for too long or fail at drawing). seconds_t start_time = g_core->GetAppTimeSeconds(); for (int i = 0; i < 5; ++i) { - if (((std::abs(resize_target_resolution_.x + bool size_differs = + ((std::abs(resize_target_resolution_.x - g_base->graphics_server->screen_pixel_width()) > 0.01f) || (std::abs(resize_target_resolution_.y - g_base->graphics_server->screen_pixel_height()) - > 0.01f)) - && g_core->GetAppTimeSeconds() - start_time < 0.1 && result) { + > 0.01f)); + if (size_differs && g_core->GetAppTimeSeconds() - start_time < 0.1 + && result) { result = g_base->graphics_server->TryRender(); - } else { - break; } } } @@ -182,13 +187,13 @@ void AppAdapterApple::SetHardwareCursorVisible(bool visible) { assert(g_core->InMainThread()); #if BA_OSTYPE_MACOS - BallisticaKit::CocoaFromCppSetCursorVisible(visible); + BallisticaKit::CocoaFromCpp::SetCursorVisible(visible); #endif } void AppAdapterApple::TerminateApp() { #if BA_OSTYPE_MACOS - BallisticaKit::CocoaFromCppTerminateApp(); + BallisticaKit::CocoaFromCpp::TerminateApp(); #else AppAdapter::TerminateApp(); #endif @@ -205,7 +210,7 @@ auto AppAdapterApple::FullscreenControlAvailable() const -> bool { auto AppAdapterApple::FullscreenControlGet() const -> bool { #if BA_OSTYPE_MACOS - return BallisticaKit::CocoaFromCppGetMainWindowIsFullscreen(); + return BallisticaKit::CocoaFromCpp::GetMainWindowIsFullscreen(); #else return false; #endif @@ -213,7 +218,7 @@ auto AppAdapterApple::FullscreenControlGet() const -> bool { void AppAdapterApple::FullscreenControlSet(bool fullscreen) { #if BA_OSTYPE_MACOS - return BallisticaKit::CocoaFromCppSetMainWindowFullscreen(fullscreen); + return BallisticaKit::CocoaFromCpp::SetMainWindowFullscreen(fullscreen); #endif } @@ -224,6 +229,22 @@ auto AppAdapterApple::FullscreenControlKeyShortcut() const auto AppAdapterApple::HasDirectKeyboardInput() -> bool { return true; }; +auto AppAdapterApple::GetKeyRepeatDelay() -> float { +#if BA_OSTYPE_MACOS + return BallisticaKit::CocoaFromCpp::GetKeyRepeatDelay(); +#else + return AppAdapter::GetKeyRepeatDelay(); +#endif +} + +auto AppAdapterApple::GetKeyRepeatInterval() -> float { +#if BA_OSTYPE_MACOS + return BallisticaKit::CocoaFromCpp::GetKeyRepeatInterval(); +#else + return AppAdapter::GetKeyRepeatDelay(); +#endif +} + } // namespace ballistica::base #endif // BA_XCODE_BUILD diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.h b/src/ballistica/base/app_adapter/app_adapter_apple.h index 9217299b..d1c9823d 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.h +++ b/src/ballistica/base/app_adapter/app_adapter_apple.h @@ -41,6 +41,9 @@ class AppAdapterApple : public AppAdapter { auto HasDirectKeyboardInput() -> bool override; void EnableResizeFriendlyMode(int width, int height); + auto GetKeyRepeatDelay() -> float override; + auto GetKeyRepeatInterval() -> float override; + protected: void DoPushMainThreadRunnable(Runnable* runnable) override; void DoPushGraphicsContextRunnable(Runnable* runnable) override; diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.cc b/src/ballistica/base/app_adapter/app_adapter_sdl.cc index b43f8397..6def0c9f 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -415,7 +415,9 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) { } case SDL_KEYDOWN: { - g_base->input->PushKeyPressEvent(event.key.keysym); + if (!event.key.repeat) { + g_base->input->PushKeyPressEvent(event.key.keysym); + } break; } diff --git a/src/ballistica/base/assets/assets_server.cc b/src/ballistica/base/assets/assets_server.cc index 0fddc71f..102c6027 100644 --- a/src/ballistica/base/assets/assets_server.cc +++ b/src/ballistica/base/assets/assets_server.cc @@ -26,7 +26,7 @@ void AssetsServer::OnAppStartInThread() { // Ask our thread to give us periodic processing time (close to but // not *exactly* one second; try to avoid aliasing with similar updates). process_timer_ = event_loop()->NewTimer( - 987, true, NewLambdaRunnable([this] { Process(); })); + 987, true, NewLambdaRunnable([this] { Process(); }).Get()); } void AssetsServer::PushPendingPreload(Object::Ref* asset_ref_ptr) { diff --git a/src/ballistica/base/assets/texture_asset.cc b/src/ballistica/base/assets/texture_asset.cc index aa757cb4..8198a4d9 100644 --- a/src/ballistica/base/assets/texture_asset.cc +++ b/src/ballistica/base/assets/texture_asset.cc @@ -15,7 +15,7 @@ namespace ballistica::base { -static void rgba8888_unpremultiply_in_place(uint8_t* src, size_t cb) { +static void Rgba8888UnpremultiplyInPlace_(uint8_t* src, size_t cb) { // Compute the actual number of pixel elements in the buffer. size_t cpel = cb / 4; auto* psrc = src; @@ -157,7 +157,7 @@ void TextureAsset::DoPreload() { auto* buffer = static_cast(malloc(buffer_size)); preload_datas_[0].buffers[0] = buffer; memcpy(buffer, pixels, buffer_size); - rgba8888_unpremultiply_in_place(buffer, buffer_size); + Rgba8888UnpremultiplyInPlace_(buffer, buffer_size); preload_datas_[0].widths[0] = width; preload_datas_[0].heights[0] = height; preload_datas_[0].formats[0] = TextureFormat::kRGBA_8888; diff --git a/src/ballistica/base/audio/audio_server.cc b/src/ballistica/base/audio/audio_server.cc index 1e873026..adcdee40 100644 --- a/src/ballistica/base/audio/audio_server.cc +++ b/src/ballistica/base/audio/audio_server.cc @@ -161,7 +161,7 @@ void AudioServer::OnAppStartInThread_() { // Get our thread to give us periodic processing time. process_timer_ = event_loop()->NewTimer(kAudioProcessIntervalNormal, true, - NewLambdaRunnable([this] { Process_(); })); + NewLambdaRunnable([this] { Process_(); }).Get()); #if BA_ENABLE_AUDIO diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index 473e5edf..07ab3f2e 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -99,6 +99,7 @@ class RenderPass; class RenderTarget; class RemoteAppServer; class RemoteControlInput; +class Repeater; class ScoreToBeat; class AppAdapterSDL; class SDLContext; diff --git a/src/ballistica/base/graphics/graphics.cc b/src/ballistica/base/graphics/graphics.cc index cc01e49f..7f405a9d 100644 --- a/src/ballistica/base/graphics/graphics.cc +++ b/src/ballistica/base/graphics/graphics.cc @@ -182,7 +182,7 @@ void Graphics::UpdateInitialGraphicsSettingsSend_() { void Graphics::StepDisplayTime() { assert(g_base->InLogicThread()); } void Graphics::AddCleanFrameCommand(const Object::Ref& c) { - BA_PRECONDITION(g_base->InLogicThread()); + assert(g_base->InLogicThread()); clean_frame_commands_.push_back(c); } @@ -1058,7 +1058,7 @@ void Graphics::ClearFrameDefDeleteList() { } void Graphics::FadeScreen(bool to, millisecs_t time, PyObject* endcall) { - BA_PRECONDITION(g_base->InLogicThread()); + assert(g_base->InLogicThread()); // If there's an ourstanding fade-end command, go ahead and run it. // (otherwise, overlapping fades can cause things to get lost) if (fade_end_call_.Exists()) { @@ -1186,7 +1186,7 @@ void Graphics::DrawDevUI(FrameDef* frame_def) { void Graphics::BuildAndPushFrameDef() { assert(g_base->InLogicThread()); - BA_PRECONDITION_FATAL(g_base->logic->app_bootstrapping_complete()); + assert(g_base->logic->app_bootstrapping_complete()); assert(camera_.Exists()); assert(!g_core->HeadlessMode()); diff --git a/src/ballistica/base/graphics/graphics.h b/src/ballistica/base/graphics/graphics.h index f04ff79c..4c244dd3 100644 --- a/src/ballistica/base/graphics/graphics.h +++ b/src/ballistica/base/graphics/graphics.h @@ -141,8 +141,8 @@ class Graphics { static void DrawRadialMeter(MeshIndexedSimpleFull* m, float amt); - // Ways to add a few simple component types quickly. - // (uses particle rendering for efficient batches). + // Ways to add a few simple component types quickly (uses particle + // rendering for efficient batches). void DrawBlotch(const Vector3f& pos, float size, float r, float g, float b, float a) { DoDrawBlotch(&blotch_indices_, &blotch_verts_, pos, size, r, g, b, a); @@ -240,13 +240,8 @@ class Graphics { float upper_top); void ReleaseFadeEndCommand(); - // auto tv_border() const { - // assert(g_base->InLogicThread()); - // return tv_border_; - // } - - // Nodes that draw flat stuff into the overlay pass should query this z value - // for where to draw in z. + // Nodes that draw flat stuff into the overlay pass should query this z + // value for where to draw in z. auto overlay_node_z_depth() { fetched_overlay_node_z_depth_ = true; return overlay_node_z_depth_; @@ -296,8 +291,8 @@ class Graphics { void AddMeshDataCreate(MeshData* d); void AddMeshDataDestroy(MeshData* d); - // For debugging: ensures that only transparent or opaque components - // are submitted while enabled. + // For debugging: ensures that only transparent or opaque components are + // submitted while enabled. auto drawing_transparent_only() const { return drawing_transparent_only_; } void set_drawing_transparent_only(bool val) { drawing_transparent_only_ = val; @@ -362,8 +357,8 @@ class Graphics { } /// For temporary use in arbitrary threads. This should be removed when - /// possible and replaced with proper safe thread-specific access - /// patterns (so we can support switching renderers/etc.). + /// possible and replaced with proper safe thread-specific access patterns + /// (so we can support switching renderers/etc.). auto placeholder_client_context() const -> const GraphicsClientContext* { // Using this from arbitrary threads is currently ok currently since // context never changes once set. Will need to kill this call once that @@ -478,18 +473,18 @@ class Graphics { float shadow_lower_top_{4.0f}; float shadow_upper_bottom_{30.0f}; float shadow_upper_top_{40.0f}; + seconds_t last_cursor_visibility_event_time_{}; millisecs_t fade_start_{}; millisecs_t fade_time_{}; millisecs_t next_stat_update_time_{}; millisecs_t progress_bar_end_time_{-9999}; millisecs_t last_progress_bar_draw_time_{}; millisecs_t last_progress_bar_start_time_{}; - microsecs_t last_suppress_gyro_time_{}; - seconds_t last_cursor_visibility_event_time_{}; - microsecs_t next_frame_number_filtered_increment_time_{}; - microsecs_t last_create_frame_def_time_microsecs_{}; millisecs_t last_create_frame_def_time_millisecs_{}; millisecs_t last_jitter_update_time_{}; + microsecs_t last_suppress_gyro_time_{}; + microsecs_t next_frame_number_filtered_increment_time_{}; + microsecs_t last_create_frame_def_time_microsecs_{}; Object::Ref screen_mesh_; Object::Ref progress_bar_bottom_mesh_; Object::Ref progress_bar_top_mesh_; diff --git a/src/ballistica/base/graphics/graphics_server.cc b/src/ballistica/base/graphics/graphics_server.cc index 98351f47..949efced 100644 --- a/src/ballistica/base/graphics/graphics_server.cc +++ b/src/ballistica/base/graphics/graphics_server.cc @@ -137,14 +137,10 @@ auto GraphicsServer::TryRender() -> bool { auto GraphicsServer::WaitForRenderFrameDef_() -> FrameDef* { assert(g_base->app_adapter->InGraphicsContext()); - millisecs_t app_time = g_core->GetAppTimeMillisecs(); + millisecs_t start_time = g_core->GetAppTimeMillisecs(); - if (!renderer_) { - return nullptr; - } - - // If the app is paused, never render. - if (g_base->app_adapter->app_suspended()) { + // Don't bother waiting if we can't/shouldn't render anyway. + if (!renderer_ || shutting_down_ || g_base->app_adapter->app_suspended()) { return nullptr; } @@ -173,12 +169,12 @@ auto GraphicsServer::WaitForRenderFrameDef_() -> FrameDef* { // if we've been waiting for too long, give up. On some platforms such // as Android, this frame will still get flipped whether we draw in it // or not, so we *really* want to not skip drawing if we can help it. - millisecs_t t = g_core->GetAppTimeMillisecs() - app_time; + millisecs_t t = g_core->GetAppTimeMillisecs() - start_time; if (t >= 1000) { if (g_buildconfig.debug_build()) { Log(LogLevel::kWarning, - "GraphicsServer: aborting GetRenderFrameDef after " - + std::to_string(t) + "ms."); + "GraphicsServer: timed out at " + std::to_string(t) + + "ms waiting for logic thread to send us a FrameDef."); } break; // Fail. } @@ -336,38 +332,6 @@ void GraphicsServer::LoadRenderer() { texture_quality_ = Graphics::TextureQualityFromRequest( texture_quality_requested_, renderer_->GetAutoTextureQuality()); - // If we don't support high quality graphics, make sure we're no higher than - // medium. - // BA_PRECONDITION(g_base->graphics->has_supports_high_quality_graphics_value()); - // if (!g_base->graphics->supports_high_quality_graphics() - // && graphics_quality_ > GraphicsQuality::kMedium) { - // graphics_quality_ = GraphicsQuality::kMedium; - // } - // graphics_quality_set_ = true; - - // Update texture quality based on request. - // switch (texture_quality_requested_) { - // case TextureQualityRequest::kLow: - // texture_quality_ = TextureQuality::kLow; - // break; - // case TextureQualityRequest::kMedium: - // texture_quality_ = TextureQuality::kMedium; - // break; - // case TextureQualityRequest::kHigh: - // texture_quality_ = TextureQuality::kHigh; - // break; - // case TextureQualityRequest::kAuto: - // texture_quality_ = renderer_->GetAutoTextureQuality(); - // break; - // default: - // Log(LogLevel::kError, - // "Unhandled TextureQualityRequest value: " - // + - // std::to_string(static_cast(texture_quality_requested_))); - // texture_quality_ = TextureQuality::kLow; - // } - // texture_quality_set_ = true; - // Ok we've got our qualities figured out; now load/update the renderer. renderer_->Load(); @@ -657,4 +621,15 @@ auto GraphicsServer::InGraphicsContext_() const -> bool { return g_base->app_adapter->InGraphicsContext(); } +void GraphicsServer::Shutdown() { + BA_PRECONDITION(!shutting_down_); + BA_PRECONDITION(g_base->InGraphicsContext()); + shutting_down_ = true; + + // We don't actually do anything here currently; just take note + // that we're shutting down so we no longer wait for frames to come + // in from the main thread. + shutdown_completed_ = true; +} + } // namespace ballistica::base diff --git a/src/ballistica/base/graphics/graphics_server.h b/src/ballistica/base/graphics/graphics_server.h index ed2cbd5b..dc3df09e 100644 --- a/src/ballistica/base/graphics/graphics_server.h +++ b/src/ballistica/base/graphics/graphics_server.h @@ -231,14 +231,6 @@ class GraphicsServer { return tv_border_; } - // auto graphics_quality_set() const { - // return graphics_quality_ != GraphicsQuality::kUnset; - // } - - // auto texture_quality_set() const { - // return texture_quality_ != TextureQuality::kUnset; - // } - auto SupportsTextureCompressionType(TextureCompressionType t) const -> bool { assert(InGraphicsContext_()); assert(texture_compression_types_set_); @@ -249,10 +241,6 @@ class GraphicsServer { void SetTextureCompressionTypes( const std::list& types); - // auto texture_compression_types_are_set() const { - // return texture_compression_types_set_; - // } - void set_renderer_context_lost(bool lost) { renderer_context_lost_ = lost; } auto renderer_context_lost() const { return renderer_context_lost_; } @@ -289,6 +277,11 @@ class GraphicsServer { return texture_compression_types_; } + /// Start spinning down the graphics server/etc. + void Shutdown(); + + auto shutdown_completed() const { return shutdown_completed_; } + private: /// Pass a freshly allocated GraphicsContext instance, which the graphics /// system will take ownership of. @@ -324,6 +317,10 @@ class GraphicsServer { } } + TextureQualityRequest texture_quality_requested_{}; + TextureQuality texture_quality_{}; + GraphicsQualityRequest graphics_quality_requested_{}; + GraphicsQuality graphics_quality_{}; bool renderer_loaded_ : 1 {}; bool model_view_projection_matrix_dirty_ : 1 {true}; bool model_world_matrix_dirty_ : 1 {true}; @@ -331,11 +328,9 @@ class GraphicsServer { bool renderer_context_lost_ : 1 {}; bool texture_compression_types_set_ : 1 {}; bool cam_orient_matrix_dirty_ : 1 {true}; + bool shutting_down_ : 1 {}; + bool shutdown_completed_ : 1 {}; Snapshot* client_context_{}; - TextureQualityRequest texture_quality_requested_{}; - TextureQuality texture_quality_{}; - GraphicsQualityRequest graphics_quality_requested_{}; - GraphicsQuality graphics_quality_{}; float res_x_{}; float res_y_{}; float res_x_virtual_{}; diff --git a/src/ballistica/base/graphics/mesh/text_mesh.cc b/src/ballistica/base/graphics/mesh/text_mesh.cc index f2c7e378..6b735175 100644 --- a/src/ballistica/base/graphics/mesh/text_mesh.cc +++ b/src/ballistica/base/graphics/mesh/text_mesh.cc @@ -360,7 +360,7 @@ void TextMesh::SetText(const std::string& text_in, HAlign alignment_h, // compile it and add its final spans to our mesh. if (packer) { std::vector spans; - packer->compile(); + packer->Compile(); // DEBUGGING - add a single quad above our first // span showing the entire texture for debugging purposes diff --git a/src/ballistica/base/graphics/text/font_page_map_data.h b/src/ballistica/base/graphics/text/font_page_map_data.h index 10ff01c3..60ea0aa8 100644 --- a/src/ballistica/base/graphics/text/font_page_map_data.h +++ b/src/ballistica/base/graphics/text/font_page_map_data.h @@ -12,25 +12,25 @@ #include "ballistica/base/graphics/text/text_graphics.h" namespace ballistica::base { -// the total number of glyph pages we have +// The total number of glyph pages we have. #define BA_GLYPH_PAGE_COUNT 8 -// the total number of glyphs we have +// The total number of glyphs we have. const int kGlyphCount = 1280; -// the starting glyph index for each page +// The starting glyph index for each page. uint32_t g_glyph_page_start_index_map[8] = {0, 258, 416, 546, 698, 981, 1138, 1276}; -// the number of glyphs on each page +// The number of glyphs on each page. uint32_t g_glyph_page_glyph_counts[8] = {258, 158, 130, 152, 283, 157, 138, 4}; -// our dynamically-loaded glyph structs for each page +// Our dynamically-loaded glyph structs for each page. TextGraphics::Glyph* g_glyph_pages[8] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; -// the page index for each glyph -uint16_t g_glyph_map[kGlyphCount] = { +// The page index for each glyph. +uint8_t g_glyph_map[kGlyphCount] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/ballistica/base/graphics/text/text_graphics.cc b/src/ballistica/base/graphics/text/text_graphics.cc index 5a5cd8de..fae81787 100644 --- a/src/ballistica/base/graphics/text/text_graphics.cc +++ b/src/ballistica/base/graphics/text/text_graphics.cc @@ -116,8 +116,7 @@ TextGraphics::TextGraphics() { } } - // init glyph values for our big font page - // (a 8x8 array) + // Init glyph values for our big font page (a 8x8 array). { float x_offs = 0.009f; float y_offs = 0.0059f; @@ -284,7 +283,7 @@ TextGraphics::TextGraphics() { (1.0f / 8.0f) * static_cast(x + 1) + x_offs + scale_extra; g.tex_max_y = (1.0f / 8.0f) * static_cast(y) + y_offs; - // just scooted letters over.. account for that + // Just scooted letters over; account for that. float foo_x = 0.0183f; float foo_y = 0.000f; g.tex_min_x += foo_x; @@ -292,12 +291,12 @@ TextGraphics::TextGraphics() { g.tex_min_y += foo_y; g.tex_max_y += foo_y; - // clamp based on char width + // Clamp based on char width. float scale = w * 1.32f; g.x_size *= scale; g.tex_max_x = g.tex_min_x + (g.tex_max_x - g.tex_min_x) * scale; - // add bot offset + // Add bot offset. if (bot_offset != 0.0f) { g.tex_min_y = g.tex_max_y + (g.tex_min_y - g.tex_max_y) @@ -305,7 +304,7 @@ TextGraphics::TextGraphics() { g.pen_offset_y -= bot_offset; g.y_size += bot_offset; } - // add left offset + // Add left offset. if (left_offset != 0.0f) { g.tex_min_x = g.tex_max_x + (g.tex_min_x - g.tex_max_x) @@ -313,14 +312,14 @@ TextGraphics::TextGraphics() { g.pen_offset_x -= left_offset; g.x_size += left_offset; } - // add right offset + // Add right offset. if (right_offset != 0.0f) { g.tex_max_x = g.tex_min_x + (g.tex_max_x - g.tex_min_x) * ((g.x_size + right_offset) / g.x_size); g.x_size += right_offset; } - // add top offset + // Add top offset. if (top_offset != 0.0f) { g.tex_max_y = g.tex_min_y + (g.tex_max_y - g.tex_min_y) @@ -844,13 +843,13 @@ void TextGraphics::GetFontPageCharRange(int page, uint32_t* first_char, // Our special pages: switch (page) { case static_cast(FontPage::kOSRendered): { - // we allow the OS to render anything not in one of our glyph textures - // (technically this overlaps the private-use range which we use our own - // textures for, but that's handled as a special-case by - // TextGroup::setText + // We allow the OS to render anything not in one of our glyph textures + // (technically this overlaps the private-use range which we use our + // own textures for, but that's handled as a special-case by + // TextGroup::SetText. (*first_char) = kGlyphCount; - (*last_char) = kTextMaxUnicodeVal; // hmm what's the max unicode value we - // should ever see?.. + // hmm what's the max unicode value we should ever see?.. + (*last_char) = kTextMaxUnicodeVal; break; } case static_cast(FontPage::kExtras1): { @@ -887,52 +886,57 @@ void TextGraphics::GetFontPagesForText(const std::string& text, int last_page = -1; std::vector unicode = Utils::UnicodeFromUTF8(text, "c03853"); for (uint32_t val : unicode) { - int page; + int page{-1}; - // Hack: allow showing euro even if we don't support unicode font rendering. - if (g_buildconfig.enable_os_font_rendering()) { - if (val == 8364) { - val = 0xE000; - } - } + // Hack: allow showing euro even if we don't support unicode font + // rendering. + // if (g_buildconfig.enable_os_font_rendering()) { + // if (val == 8364) { + // val = 0xE000; + // } + // } - // For values in the custom-char range (U+E000–U+F8FF) we point at our own - // custom page(s) + bool covered{}; + + // For values in the custom-char range (U+E000–U+F8FF) we point at our + // own custom page(s) if (val >= 0xE000 && val <= 0xF8FF) { // The 25 chars after this are in our fontExtras sheet. if (val < 0xE000 + 25) { // Special value denoting our custom font page. page = static_cast(FontPage::kExtras1); + covered = true; } else if (val < 0xE000 + 50) { // Special value denoting our custom font page. page = static_cast(FontPage::kExtras2); + covered = true; } else if (val < 0xE000 + 75) { // Special value denoting our custom font page. page = static_cast(FontPage::kExtras3); + covered = true; } else if (val < 0xE000 + 100) { // Special value denoting our custom font page. page = static_cast(FontPage::kExtras4); - } else { - // We dont cover this.. just go with '?' - val = '?'; - page = g_glyph_map[val]; + covered = true; } - } else if (val >= kGlyphCount) { - // Otherwise if its outside of our texture-coverage area. + } else if (val < kGlyphCount) { + page = g_glyph_map[val]; + covered = true; + } + + if (!covered) { if (g_buildconfig.enable_os_font_rendering()) { page = static_cast(FontPage::kOSRendered); } else { val = '?'; page = g_glyph_map[val]; } - } else { - // yay we cover it! - page = g_glyph_map[val]; } - // compare to lastPage to avoid doing a set insert for *everything* since - // most will be the same + + // Compare to last_page to avoid doing a set insert for *everything* + // since most will be the same. if (page != last_page) { - (*font_pages).insert(page); + font_pages->insert(page); last_page = page; } } @@ -1009,12 +1013,8 @@ void TextGraphics::GetOSTextSpanBoundsAndWidth(const std::string& s, Rect* r, // Send this entry to the back of the list since we used it. text_span_bounds_cache_.erase(entry->list_iterator_); - // I guess inspection doesn't realize entry lives on after this?... -#pragma clang diagnostic push -#pragma ide diagnostic ignored "UnusedValue" entry->list_iterator_ = text_span_bounds_cache_.insert(text_span_bounds_cache_.end(), entry); -#pragma clang diagnostic pop return; } auto entry(Object::New()); @@ -1068,7 +1068,9 @@ auto TextGraphics::GetStringWidth(const char* text, bool big) -> float { line_length += GetOSTextSpanWidth(s); os_span.clear(); } - if (line_length > max_line_length) max_line_length = line_length; + if (line_length > max_line_length) { + max_line_length = line_length; + } line_length = 0; t++; } else { @@ -1145,7 +1147,9 @@ void TextGraphics::BreakUpString(const char* text, float width, s_begin = t; } } else { - if (*t == 0) throw Exception(); + if (*t == 0) { + throw Exception(); + } uint32_t val = Utils::GetUTF8Value(t); Utils::AdvanceUTF8(&t); diff --git a/src/ballistica/base/graphics/text/text_packer.cc b/src/ballistica/base/graphics/text/text_packer.cc index 2f9ea250..fffd74b1 100644 --- a/src/ballistica/base/graphics/text/text_packer.cc +++ b/src/ballistica/base/graphics/text/text_packer.cc @@ -24,11 +24,11 @@ void TextPacker::AddSpan(const std::string& text, float x, float y, } // FIXME - we currently run into minor problems because we measure our text -// bounds at one size and then scale that linearly when trying to fit things -// into the texture. However, fonts don't always scale linearly (and even when -// that's an option it can be expensive). +// bounds at one size and then scale that linearly when trying to fit +// things into the texture. However, fonts don't always scale linearly (and +// even when that's an option it can be expensive). -void TextPacker::compile() { +void TextPacker::Compile() { assert(!compiled_); if (spans_.empty()) { compiled_ = true; @@ -57,24 +57,23 @@ void TextPacker::compile() { width *= 2; } - // Alternately, if we're too big, crank our scale down so that our widest span - // fits. + // Alternately, if we're too big, crank our scale down so that our widest + // span fits. if (widest_unscaled_span_width * scale > width * 0.9f) { scale *= ((width * 0.9f) / (widest_unscaled_span_width * scale)); } float start_height = height; int mini_shrink_tries = 0; - // Ok; we've now locked in a width and scale. - // Now we go through and position our spans. - // We may need to do this more than once if our height comes out too big. - // (hopefully this will never be a problem in practice) + // Ok; we've now locked in a width and scale. Now we go through and + // position our spans. We may need to do this more than once if our height + // comes out too big. (hopefully this will never be a problem in practice) while (true) { height = start_height; - // We currently just lay out left-to-right, top-to-bottom. - // This could be somewhat wasteful in particular configurations. - // (leaving half-filled lines, etc) so it might be worth improving later. + // We currently just lay out left-to-right, top-to-bottom. This could be + // somewhat wasteful in particular configurations. (leaving half-filled + // lines, etc) so it might be worth improving later. float widest_fill_right = 0.0f; float fill_right = 0.0f; float fill_bottom = 0.0f; @@ -87,26 +86,27 @@ void TextPacker::compile() { // Start a new line if this would put us past the end. if (fill_right + span_width > width) { if (fill_right > widest_fill_right) { - widest_fill_right = fill_right; // Keep track of how far over we go. + // Keep track of how far over we go. + widest_fill_right = fill_right; } fill_right = 0.0f; fill_bottom += line_height; line_height = 0.0f; } - // Position x such that x + left bound - buffer lines up with our current - // right point. + // Position x such that x + left bound - buffer lines up with our + // current right point. float to_left = (i.bounds.l - span_buffer) * scale; i.tex_x = fill_right - to_left; fill_right += span_width; - // Position y such that y - top bound - buffer lines up with our current - // bottom point. + // Position y such that y - top bound - buffer lines up with our + // current bottom point. float to_top = (-i.bounds.t - span_buffer) * scale; i.tex_y = fill_bottom - to_top; - // If our total height is greater than the current line height, expand the - // line's. + // If our total height is greater than the current line height, expand + // the line's. if (span_height > line_height) { line_height = span_height; } @@ -125,9 +125,9 @@ void TextPacker::compile() { // If it doesn't fit, repeat again with a smaller scale until it does. // Dropping our scale has a disproportional effect on the final height - // (since it opens up more relative horizontal space). - // I'm not sure how to figure out how much to drop by other than - // incrementally dropping values until we fit. + // (since it opens up more relative horizontal space). I'm not sure + // how to figure out how much to drop by other than incrementally + // dropping values until we fit. scale *= 0.75f; } else if (((widest_fill_right < (width * mini_shrink_threshold_h) @@ -135,15 +135,15 @@ void TextPacker::compile() { || fill_bottom + line_height < (height * mini_shrink_threshold_v)) && mini_shrink_tries < 3) { - // If we're here it means we *barely* use more than half of the texture in - // one direction or the other; let's shrink just a tiny bit and we should - // be able to chop our texture size in half + // If we're here it means we *barely* use more than half of the + // texture in one direction or the other; let's shrink just a tiny bit + // and we should be able to chop our texture size in half if (widest_fill_right < width * mini_shrink_threshold_h && width > 16) { float scale_val = 0.99f * (((width * 0.5f) / widest_fill_right)); if (scale_val < 1.0f) { - // FIXME - should think about a fixed multiplier here; - // under the hood the system might be caching glyphs based on scale - // and this would leave us with fewer different scales in the end and + // FIXME - should think about a fixed multiplier here; under the + // hood the system might be caching glyphs based on scale and + // this would leave us with fewer different scales in the end and // thus better caching performance scale *= scale_val; } @@ -151,9 +151,9 @@ void TextPacker::compile() { } else { float scale_val = 0.99f * (height * 0.5f) / (fill_bottom + line_height); if (scale_val < 1.0f) { - // FIXME - should think about a fixed multiplier here; - // under the hood the system might be caching glyphs based on scale - // and this would leave us with fewer different scales in the end and + // FIXME - should think about a fixed multiplier here; under the + // hood the system might be caching glyphs based on scale and + // this would leave us with fewer different scales in the end and // thus better caching performance scale *= scale_val; } @@ -165,8 +165,8 @@ void TextPacker::compile() { } } - // Lastly, now that our texture width and height are completely finalized, we - // can calculate UVs. + // Lastly, now that our texture width and height are completely finalized, + // we can calculate UVs. for (auto&& i : spans_) { // Now store uv coords for this span; they should include the buffer. i.u_min = (i.tex_x + (i.bounds.l - span_buffer) * scale) / width; @@ -182,11 +182,11 @@ void TextPacker::compile() { } // TODO(ericf): now we calculate a hash that's unique to this text - // configuration; we'll use that as a key for the texture we'll generate/use. - // ..this way multiple meshes can share the same generated texture. - // *technically* we could calculate this hash and check for an existing - // texture before we bother laying out our spans, but that might not save us - // much time and would complicate things. + // configuration; we'll use that as a key for the texture we'll + // generate/use. ..this way multiple meshes can share the same generated + // texture. *technically* we could calculate this hash and check for an + // existing texture before we bother laying out our spans, but that might + // not save us much time and would complicate things. hash_ = std::to_string(resolution_scale_); for (auto&& i : spans_) { char buffer[64]; diff --git a/src/ballistica/base/graphics/text/text_packer.h b/src/ballistica/base/graphics/text/text_packer.h index d1889ba8..e2c40310 100644 --- a/src/ballistica/base/graphics/text/text_packer.h +++ b/src/ballistica/base/graphics/text/text_packer.h @@ -21,7 +21,7 @@ class TextPacker : public Object { // outside of here anyway so might as well recycle. void AddSpan(const std::string& text, float x, float y, const Rect& bounds); - auto hash() const -> const std::string& { + const auto& hash() const { assert(compiled_); return hash_; } @@ -51,32 +51,32 @@ class TextPacker : public Object { // Once done adding spans, call this to calculate final span UV values, // texture configuration, and hash. - void compile(); + void Compile(); - auto spans() const -> const std::list& { return spans_; } + const auto& spans() const { return spans_; } - auto texture_width() const -> int { + auto texture_width() const { assert(compiled_); return texture_width_; } - auto texture_height() const -> int { + auto texture_height() const { assert(compiled_); return texture_height_; } - auto text_scale() const -> float { + auto text_scale() const { assert(compiled_); return text_scale_; } private: + bool compiled_{false}; float resolution_scale_; + float text_scale_{}; int texture_width_{}; int texture_height_{}; - float text_scale_{}; std::string hash_; - bool compiled_{false}; std::list spans_; }; diff --git a/src/ballistica/base/input/device/joystick_input.cc b/src/ballistica/base/input/device/joystick_input.cc index 7d6df160..08ad4148 100644 --- a/src/ballistica/base/input/device/joystick_input.cc +++ b/src/ballistica/base/input/device/joystick_input.cc @@ -9,6 +9,7 @@ #include "ballistica/base/input/input.h" #include "ballistica/base/python/base_python.h" #include "ballistica/base/support/classic_soft.h" +#include "ballistica/base/support/repeater.h" #include "ballistica/base/ui/ui.h" #include "ballistica/core/core.h" #include "ballistica/shared/foundation/event_loop.h" @@ -17,10 +18,6 @@ namespace ballistica::base { -const char* kMFiControllerName = "iOS/Mac Controller"; - -const int kJoystickRepeatDelay{500}; - // Joy values below this are candidates for calibration. const float kJoystickCalibrationThreshold{6000.0f}; @@ -78,20 +75,6 @@ JoystickInput::JoystickInput(int sdl_joystick_id, && raw_sdl_joystick_name_.size() <= 22) { raw_sdl_joystick_name_ = "XInput Controller"; } - // #else - // raw_sdl_joystick_name_ = SDL_JoystickName(sdl_joystick_id_); - // #endif // BA_SDL2_BUILD - - // If its an SDL joystick and we're using our custom sdl 1.2 build, ask it. - // #if BA_XCODE_BUILD && BA_OSTYPE_MACOS && !BA_SDL2_BUILD - // raw_sdl_joystick_identifier_ = - // SDL_JoystickIdentifier(sdl_joystick_id_); - // #endif - - // Some special-cases on mac. - if (strstr(raw_sdl_joystick_name_.c_str(), "PLAYSTATION") != nullptr) { - is_mac_ps3_controller_ = true; - } #else // BA_ENABLE_SDL_JOYSTICKS throw Exception(); // Shouldn't happen. @@ -101,8 +84,6 @@ JoystickInput::JoystickInput(int sdl_joystick_id, // Its a manual joystick. sdl_joystick_ = nullptr; - is_mfi_controller_ = (custom_device_name_ == kMFiControllerName); - // Hard code a few remote controls. // The newer way to do this is just set 'UI-Only' on the device config is_remote_control_ = ((custom_device_name_ == "Amazon Remote") @@ -179,6 +160,7 @@ auto JoystickInput::GetButtonName(int index) -> std::string { break; } } + if (g_buildconfig.ostype_android()) { // Special case: if this is a samsung controller, return the dice // button icons. @@ -446,46 +428,6 @@ void JoystickInput::Update() { } } } - - // If a button's being held, potentially pass repeats along. - if (up_held_ || down_held_ || left_held_ || right_held_) { - // Don't ask for the widget unless we have something held. - // (otherwise we prevent other inputs from getting at it) - if (g_base->ui->GetWidgetForInput(this)) { - millisecs_t repeat_delay = kJoystickRepeatDelay; - - millisecs_t t = g_core->GetAppTimeMillisecs(); - auto c = WidgetMessage::Type::kEmptyMessage; - if (t - last_hold_time_ < repeat_delay) { - return; - } - - if (t - last_hold_time_ >= repeat_delay) { - bool pass = false; - if (up_held_) { - pass = true; - c = WidgetMessage::Type::kMoveUp; - } else if (down_held_) { - pass = true; - c = WidgetMessage::Type::kMoveDown; - } else if (left_held_) { - pass = true; - c = WidgetMessage::Type::kMoveLeft; - } else if (right_held_) { - pass = true; - c = WidgetMessage::Type::kMoveRight; - } - if (pass) { - g_base->ui->SendWidgetMessage(WidgetMessage(c)); - } - - // Set another repeat to happen sooner. - last_hold_time_ = - t - - static_cast(static_cast(repeat_delay) * 0.8f); - } - } - } } void JoystickInput::SetStandardExtendedButtons() { @@ -508,6 +450,8 @@ void JoystickInput::ResetHeldStates() { SDL_Event e; dpad_right_held_ = dpad_left_held_ = dpad_up_held_ = dpad_down_held_ = false; + ui_repeater_.Clear(); + run_buttons_held_.clear(); run_trigger1_value_ = run_trigger2_value_ = 0.0f; UpdateRunningState(); @@ -594,28 +538,28 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { || dpad_down_held_)) return; - bool isHoldPositionEvent = false; + bool is_hold_position_event = false; // Keep track of whether hold-position is being held. If so, we don't send - // window events. (some joysticks always give us significant axis values but + // window events (some joysticks always give us significant axis values but // rely on hold position to keep from doing stuff usually). if (e->type == SDL_JOYBUTTONDOWN && e->jbutton.button == hold_position_button_) { need_to_send_held_state_ = true; hold_position_held_ = true; - isHoldPositionEvent = true; + is_hold_position_event = true; } if (e->type == SDL_JOYBUTTONUP && e->jbutton.button == hold_position_button_) { need_to_send_held_state_ = true; hold_position_held_ = false; - isHoldPositionEvent = true; + is_hold_position_event = true; } // Let's ignore events for just a moment after we're created. // (some joysticks seem to spit out erroneous button-pressed events when // first plugged in ). - if (time - creation_time_ < 250 && !isHoldPositionEvent) { + if (time - creation_time_ < 250 && !is_hold_position_event) { return; } @@ -700,7 +644,7 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { } } - // If its the ignore button, ignore it. + // If its an ignored button, ignore it. if ((e->type == SDL_JOYBUTTONDOWN || e->type == SDL_JOYBUTTONUP) && (e->jbutton.button == ignored_button_ || e->jbutton.button == ignored_button2_ @@ -709,49 +653,6 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { return; } - // A little pre-filtering on mac PS3 gamepads. (try to filter out some noise - // we're seeing, etc). - if (g_buildconfig.ostype_macos() && is_mac_ps3_controller_) { - switch (e->type) { - case SDL_JOYAXISMOTION: { - // On my ps3 controller, I seem to be seeing occasional joy-axis-events - // coming in with values of -32768 when nothing is being touched. - // Filtering those out here.. Should look into this more and see if its - // SDL's fault or else forward a bug to apple. - if ((e->jaxis.axis == 0 || e->jaxis.axis == 1) - && e->jaxis.value == -32768 - && (time - ps3_last_joy_press_time_ > 2000) && !ps3_jaxis1_pressed_ - && !ps3_jaxis2_pressed_) { - printf( - "BAJoyStick notice: filtering out errand PS3 axis %d value of " - "%d\n", - static_cast(e->jaxis.axis), - static_cast(e->jaxis.value)); - fflush(stdout); - - // std::cout << "BSJoyStick notice: filtering out errant PS3 axis " << - // int(e->jaxis.axis) << " value of " << e->jaxis.value << std::endl; - return; - } - - if (abs(e->jaxis.value) >= kJoystickDiscreteThreshold) { - ps3_last_joy_press_time_ = time; - } - - // Keep track of whether its pressed for next time. - if (e->jaxis.axis == 0) { - ps3_jaxis1_pressed_ = (abs(e->jaxis.value) > 3000); - } else if (e->jaxis.axis == 1) { - ps3_jaxis2_pressed_ = (abs(e->jaxis.value) > 3000); - } - - break; - } - default: - break; - } - } - // A few high level button press interceptions. if (e->type == SDL_JOYBUTTONDOWN) { if (e->jbutton.button == start_button_ @@ -806,111 +707,116 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { } } - // If we're in a dialog, send dialog events. - // We keep track of special x/y values for dialog usage. + // If we're in the ui, send ui events. + // We keep track of special x/y values for ui usage. // These are formed as combinations of the actual joy value // and the hold-position state. // Think of hold-position as somewhat of a 'magnitude' to the joy event's // direction. They're really one and the same event. (we just need to store // their states ourselves since they don't both come through at once). - bool isAnalogStickJAxisEvent = false; + // FIXME: Ugh need to rip out this old hold-position stuff. + bool is_analog_stick_jaxis_event = false; if (e->type == SDL_JOYAXISMOTION) { if (e->jaxis.axis == analog_lr_) { dialog_jaxis_x_ = e->jaxis.value; - isAnalogStickJAxisEvent = true; + is_analog_stick_jaxis_event = true; } else if (e->jaxis.axis == analog_ud_) { dialog_jaxis_y_ = e->jaxis.value; - isAnalogStickJAxisEvent = true; + is_analog_stick_jaxis_event = true; } } - int dialogJaxisX = dialog_jaxis_x_; + int ui_jaxis_x = dialog_jaxis_x_; if (hold_position_held_) { - dialogJaxisX = 0; // Throttle is off. + ui_jaxis_x = 0; // Throttle is off. } - int dialogJaxisY = dialog_jaxis_y_; + int ui_jaxis_y = dialog_jaxis_y_; if (hold_position_held_) { - dialogJaxisY = 0; // Throttle is off. + ui_jaxis_y = 0; // Throttle is off. } // We might not wanna grab at the UI if we're a axis-motion event // below our 'pressed' threshold.. Otherwise fuzzy analog joystick // readings would cause rampant UI stealing even if no events are being sent. - bool would_go_to_dialog = false; + bool would_go_to_ui = false; auto wm = WidgetMessage::Type::kEmptyMessage; - if (isAnalogStickJAxisEvent || isHoldPositionEvent) { + if (is_analog_stick_jaxis_event || is_hold_position_event) { // Even when we're not sending, clear out some 'held' states. - if (left_held_ && dialogJaxisX >= -kJoystickDiscreteThreshold) { + if (left_held_ && ui_jaxis_x >= -kJoystickDiscreteThreshold) { left_held_ = false; + ui_repeater_.Clear(); } - if (right_held_ && dialogJaxisX <= kJoystickDiscreteThreshold) { + if (right_held_ && ui_jaxis_x <= kJoystickDiscreteThreshold) { right_held_ = false; + ui_repeater_.Clear(); } - if (up_held_ && dialogJaxisY >= -kJoystickDiscreteThreshold) { + if (up_held_ && ui_jaxis_y >= -kJoystickDiscreteThreshold) { up_held_ = false; + ui_repeater_.Clear(); } - if (down_held_ && dialogJaxisY <= kJoystickDiscreteThreshold) { + if (down_held_ && ui_jaxis_y <= kJoystickDiscreteThreshold) { down_held_ = false; + ui_repeater_.Clear(); + } + if ((!right_held_) && ui_jaxis_x > kJoystickDiscreteThreshold) { + would_go_to_ui = true; + } + if ((!left_held_) && ui_jaxis_x < -kJoystickDiscreteThreshold) { + would_go_to_ui = true; + } + if ((!up_held_) && ui_jaxis_y < -kJoystickDiscreteThreshold) { + would_go_to_ui = true; + } + if ((!down_held_) && ui_jaxis_y > kJoystickDiscreteThreshold) { + would_go_to_ui = true; } - if ((!right_held_) && dialogJaxisX > kJoystickDiscreteThreshold) - would_go_to_dialog = true; - if ((!left_held_) && dialogJaxisX < -kJoystickDiscreteThreshold) - would_go_to_dialog = true; - if ((!up_held_) && dialogJaxisY < -kJoystickDiscreteThreshold) - would_go_to_dialog = true; - if ((!down_held_) && dialogJaxisY > kJoystickDiscreteThreshold) - would_go_to_dialog = true; } else if ((e->type == SDL_JOYHATMOTION && e->jhat.hat == hat_) || (e->type == SDL_JOYBUTTONDOWN && e->jbutton.button != hold_position_button_)) { // Other button-downs and hat motions always go. - would_go_to_dialog = true; + would_go_to_ui = true; } // Resets always circumvent dialogs. - if (resetting_) would_go_to_dialog = false; + if (resetting_) { + would_go_to_ui = false; + } - // Anything that would go to a dialog also counts to mark us as - // 'recently-used'. - if (would_go_to_dialog) { + // Anything that would go to ui also counts to mark us as 'recently-used'. + if (would_go_to_ui) { UpdateLastInputTime(); } - if (would_go_to_dialog && g_base->ui->GetWidgetForInput(this)) { - bool pass = false; + if (would_go_to_ui && g_base->ui->GetWidgetForInput(this)) { + bool pass{}; // Special case.. either joy-axis-motion or hold-position events trigger // these. - if (isAnalogStickJAxisEvent || isHoldPositionEvent) { - if (dialogJaxisX > kJoystickDiscreteThreshold) { - // To the right. + if (is_analog_stick_jaxis_event || is_hold_position_event) { + if (ui_jaxis_x > kJoystickDiscreteThreshold) { if (!right_held_ && !up_held_ && !down_held_) { - last_hold_time_ = g_core->GetAppTimeMillisecs(); right_held_ = true; + pass = true; wm = WidgetMessage::Type::kMoveRight; - pass = true; } - } else if (dialogJaxisX < -kJoystickDiscreteThreshold) { + } else if (ui_jaxis_x < -kJoystickDiscreteThreshold) { if (!left_held_ && !up_held_ && !down_held_) { - last_hold_time_ = g_core->GetAppTimeMillisecs(); - wm = WidgetMessage::Type::kMoveLeft; - pass = true; left_held_ = true; + pass = true; + wm = WidgetMessage::Type::kMoveLeft; } } - if (dialogJaxisY > kJoystickDiscreteThreshold) { + if (ui_jaxis_y > kJoystickDiscreteThreshold) { if (!down_held_ && !left_held_ && !right_held_) { - last_hold_time_ = g_core->GetAppTimeMillisecs(); - wm = WidgetMessage::Type::kMoveDown; - pass = true; down_held_ = true; - } - } else if (dialogJaxisY < -kJoystickDiscreteThreshold) { - if (!up_held_ && !left_held_ && !right_held_) { - last_hold_time_ = g_core->GetAppTimeMillisecs(); - wm = WidgetMessage::Type::kMoveUp; pass = true; + wm = WidgetMessage::Type::kMoveDown; + } + } else if (ui_jaxis_y < -kJoystickDiscreteThreshold) { + if (!up_held_ && !left_held_ && !right_held_) { up_held_ = true; + pass = true; + wm = WidgetMessage::Type::kMoveUp; } } } @@ -924,7 +830,6 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { switch (e->jhat.value) { case SDL_HAT_LEFT: { if (!left_held_) { - last_hold_time_ = g_core->GetAppTimeMillisecs(); wm = WidgetMessage::Type::kMoveLeft; pass = true; left_held_ = true; @@ -935,7 +840,6 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { case SDL_HAT_RIGHT: { if (!right_held_) { - last_hold_time_ = g_core->GetAppTimeMillisecs(); wm = WidgetMessage::Type::kMoveRight; pass = true; right_held_ = true; @@ -945,7 +849,6 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { } case SDL_HAT_UP: { if (!up_held_) { - last_hold_time_ = g_core->GetAppTimeMillisecs(); wm = WidgetMessage::Type::kMoveUp; pass = true; up_held_ = true; @@ -955,7 +858,6 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { } case SDL_HAT_DOWN: { if (!down_held_) { - last_hold_time_ = g_core->GetAppTimeMillisecs(); wm = WidgetMessage::Type::kMoveDown; pass = true; down_held_ = true; @@ -968,6 +870,7 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { down_held_ = false; left_held_ = false; right_held_ = false; + ui_repeater_.Clear(); } default: break; @@ -1007,7 +910,20 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) { break; } if (pass) { - g_base->ui->SendWidgetMessage(WidgetMessage(wm)); + switch (wm) { + case WidgetMessage::Type::kMoveUp: + case WidgetMessage::Type::kMoveDown: + case WidgetMessage::Type::kMoveLeft: + case WidgetMessage::Type::kMoveRight: + // For UI movement, set up a repeater so we can hold the button. + ui_repeater_ = Repeater::New( + kUINavigationRepeatDelay, kUINavigationRepeatInterval, + [wm] { g_base->ui->SendWidgetMessage(WidgetMessage(wm)); }); + break; + default: + // Other messages are just one-shots. + g_base->ui->SendWidgetMessage(WidgetMessage(wm)); + } } return; } @@ -1502,22 +1418,7 @@ auto JoystickInput::GetRawDeviceName() -> std::string { auto JoystickInput::GetDeviceExtraDescription() -> std::string { std::string s; - // On mac, PS3 controllers can connect via USB or bluetooth, - // and it can be confusing if one is doing both, - // so lets specify here. - if (GetDeviceName() == "PLAYSTATION(R)3 Controller") { - // For bluetooth we get a serial in the form "04-76-6e-d1-17-90" while - // on USB we get a simple int (the usb location id): "-9340234" - // so lets consider it wireless if its got a dash not at the beginning. - s = " (USB)"; - - auto dname = GetDeviceIdentifier(); - for (const char* tst = dname.c_str(); *tst; tst++) { - if (*tst == '-' && tst != dname) { - s = " (Bluetooth)"; - } - } - } + // (no longer being used). return s; } diff --git a/src/ballistica/base/input/device/joystick_input.h b/src/ballistica/base/input/device/joystick_input.h index e6133154..5748f702 100644 --- a/src/ballistica/base/input/device/joystick_input.h +++ b/src/ballistica/base/input/device/joystick_input.h @@ -16,7 +16,7 @@ namespace ballistica::base { const int kJoystickDiscreteThreshold{15000}; const float kJoystickDiscreteThresholdFloat{0.46f}; const int kJoystickAnalogCalibrationDivisions{20}; -extern const char* kMFiControllerName; +// extern const char* kMFiControllerName; /// A physical game controller. class JoystickInput : public InputDevice { @@ -87,48 +87,48 @@ class JoystickInput : public InputDevice { void UpdateRunningState(); auto GetCalibratedValue(float raw, float neutral) const -> int32_t; - std::string raw_sdl_joystick_name_; - std::string raw_sdl_joystick_identifier_; - float run_value_{}; JoystickInput* child_joy_stick_{}; JoystickInput* parent_joy_stick_{}; millisecs_t last_ui_only_print_time_{}; - bool ui_only_{}; - bool unassigned_buttons_run_{true}; - bool start_button_activates_default_widget_{true}; - bool auto_recalibrate_analog_stick_{}; millisecs_t creation_time_{}; - bool did_initial_reset_{}; // FIXME - should take this out and replace it with a bool // (we never actually access the sdl joystick directly outside of our // constructor) SDL_Joystick* sdl_joystick_{}; - bool is_test_input_{}; - bool is_remote_control_{}; - bool is_remote_app_{}; - bool is_mfi_controller_{}; - bool is_mac_ps3_controller_{}; - - millisecs_t ps3_last_joy_press_time_{-10000}; + bool ui_only_ : 1 {}; + bool unassigned_buttons_run_ : 1 {true}; + bool start_button_activates_default_widget_ : 1 {true}; + bool auto_recalibrate_analog_stick_ : 1 {}; + bool did_initial_reset_ : 1 {}; + bool is_test_input_ : 1 {}; + bool is_remote_control_ : 1 {}; + bool is_remote_app_ : 1 {}; + bool is_mfi_controller_ : 1 {}; // For dialogs. - bool left_held_{}; - bool right_held_{}; - bool up_held_{}; - bool down_held_{}; - bool hold_position_held_{}; - bool need_to_send_held_state_{}; + bool left_held_ : 1 {}; + bool right_held_ : 1 {}; + bool up_held_ : 1 {}; + bool down_held_ : 1 {}; + bool hold_position_held_ : 1 {}; + bool need_to_send_held_state_ : 1 {}; + + bool hat_held_ : 1 {}; + bool dpad_right_held_ : 1 {}; + bool dpad_left_held_ : 1 {}; + bool dpad_up_held_ : 1 {}; + bool dpad_down_held_ : 1 {}; + + bool ignore_completely_ : 1 {}; + bool resetting_ : 1 {}; + bool calibrate_ : 1 {}; + bool can_configure_ : 1 {}; + int hat_{}; int analog_lr_{}; int analog_ud_{1}; - millisecs_t last_hold_time_{}; - bool hat_held_{}; - bool dpad_right_held_{}; - bool dpad_left_held_{}; - bool dpad_up_held_{}; - bool dpad_down_held_{}; // Mappings of ba buttons to SDL buttons. int jump_button_{}; @@ -143,7 +143,6 @@ class JoystickInput : public InputDevice { // Used on rift build; we have one button which we disallow from joining but // the rest we allow. (all devices are treated as one and the same there). int remote_enter_button_{-1}; - bool ignore_completely_{}; int ignored_button_{-1}; int ignored_button2_{-1}; int ignored_button3_{-1}; @@ -153,12 +152,6 @@ class JoystickInput : public InputDevice { int run_trigger1_{-1}; int run_trigger2_{-1}; int vr_reorient_button_{-1}; - float run_trigger1_min_{}; - float run_trigger1_max_{}; - float run_trigger2_min_{}; - float run_trigger2_max_{}; - float run_trigger1_value_{}; - float run_trigger2_value_{}; int left_button_{-1}; int right_button_{-1}; int up_button_{-1}; @@ -167,15 +160,19 @@ class JoystickInput : public InputDevice { int right_button2_{-1}; int up_button2_{-1}; int down_button2_{-1}; - std::set run_buttons_held_; int sdl_joystick_id_{}; - bool ps3_jaxis1_pressed_{}; - bool ps3_jaxis2_pressed_{}; + float run_value_{}; + float run_trigger1_min_{}; + float run_trigger1_max_{}; + float run_trigger2_min_{}; + float run_trigger2_max_{}; + float run_trigger1_value_{}; + float run_trigger2_value_{}; float calibration_threshold_{}; float calibration_break_threshold_{}; float analog_calibration_vals_[kJoystickAnalogCalibrationDivisions]{}; - std::string custom_device_name_; - bool can_configure_{}; + float calibrated_neutral_x_{}; + float calibrated_neutral_y_{}; int32_t dialog_jaxis_x_{}; int32_t dialog_jaxis_y_{}; int32_t jaxis_raw_x_{}; @@ -183,11 +180,12 @@ class JoystickInput : public InputDevice { int32_t jaxis_x_{}; int32_t jaxis_y_{}; millisecs_t calibration_start_time_x_{}; - float calibrated_neutral_x_{}; millisecs_t calibration_start_time_y_{}; - float calibrated_neutral_y_{}; - bool resetting_{}; - bool calibrate_{}; + std::set run_buttons_held_; + std::string custom_device_name_; + std::string raw_sdl_joystick_name_; + std::string raw_sdl_joystick_identifier_; + Object::Ref ui_repeater_; BA_DISALLOW_CLASS_COPIES(JoystickInput); }; diff --git a/src/ballistica/base/input/device/keyboard_input.cc b/src/ballistica/base/input/device/keyboard_input.cc index 4a1908d4..ba9b3cab 100644 --- a/src/ballistica/base/input/device/keyboard_input.cc +++ b/src/ballistica/base/input/device/keyboard_input.cc @@ -2,8 +2,10 @@ #include "ballistica/base/input/device/keyboard_input.h" +#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/platform/base_platform.h" #include "ballistica/base/support/classic_soft.h" +#include "ballistica/base/support/repeater.h" #include "ballistica/base/ui/ui.h" namespace ballistica::base { @@ -42,10 +44,12 @@ KeyboardInput::KeyboardInput(KeyboardInput* parent_keyboard_input_in) { KeyboardInput::~KeyboardInput() = default; -auto KeyboardInput::HandleKey(const SDL_Keysym* keysym, bool repeat, bool down) - -> bool { +auto KeyboardInput::HandleKey(const SDL_Keysym* keysym, bool down) -> bool { // Only allow the *main* keyboard to talk to the UI if (parent_keyboard_input_ == nullptr) { + // Any new event coming in cancels repeats. + ui_repeater_.Clear(); + if (g_base->ui->GetWidgetForInput(this)) { bool pass = false; auto c = WidgetMessage::Type::kEmptyMessage; @@ -78,10 +82,8 @@ auto KeyboardInput::HandleKey(const SDL_Keysym* keysym, bool repeat, bool down) case SDLK_SPACE: case SDLK_KP_ENTER: case SDLK_RETURN: - if (!repeat) { - c = WidgetMessage::Type::kActivate; - pass = true; - } + c = WidgetMessage::Type::kActivate; + pass = true; break; case SDLK_ESCAPE: // (limit to kb1 so we don't get double-beeps on failure) @@ -123,32 +125,44 @@ auto KeyboardInput::HandleKey(const SDL_Keysym* keysym, bool repeat, bool down) } } if (pass) { - g_base->ui->SendWidgetMessage(WidgetMessage(c, keysym)); + // For movement and key press widget events, set up repeats. + // Otherwise run a single time immediately. + switch (c) { + case WidgetMessage::Type::kMoveUp: + case WidgetMessage::Type::kMoveDown: + case WidgetMessage::Type::kMoveLeft: + case WidgetMessage::Type::kMoveRight: + case WidgetMessage::Type::kKey: + // Note: Need to pass keysym along as a value; not a pointer. + ui_repeater_ = Repeater::New( + g_base->app_adapter->GetKeyRepeatDelay(), + g_base->app_adapter->GetKeyRepeatInterval(), + [c, keysym = *keysym] { + g_base->ui->SendWidgetMessage(WidgetMessage(c, &keysym)); + }); + break; + default: + g_base->ui->SendWidgetMessage(WidgetMessage(c, keysym)); + break; + } } return (pass); } } // Bring up menu if start is pressed. - if (keysym->sym == start_key_ && !repeat && !g_base->ui->MainMenuVisible()) { + if (keysym->sym == start_key_ && !g_base->ui->MainMenuVisible()) { g_base->ui->PushMainMenuPressCall(this); return true; } -// Clion seems to think child_keyboard_input_ will never be set here (it will). -#pragma clang diagnostic push -#pragma ide diagnostic ignored "UnreachableCode" -#pragma ide diagnostic ignored "ConstantConditionsOC" - // At this point, if we have a child input, let it try to handle things. if (child_keyboard_input_ && enable_child_) { - if (child_keyboard_input_->HandleKey(keysym, repeat, down)) { + if (child_keyboard_input_->HandleKey(keysym, down)) { return true; } } -#pragma clang diagnostic pop - if (!AttachedToPlayer()) { if (down && ((keysym->sym == jump_key_) || (keysym->sym == punch_key_) @@ -173,152 +187,151 @@ auto KeyboardInput::HandleKey(const SDL_Keysym* keysym, bool repeat, bool down) // (removing init values from input_type and input_type_2 gives a // 'possibly uninited value used' warning but leaving them gives a // 'values unused' warning. Grumble.) - explicit_bool(input_type - == (explicit_bool(false) ? input_type_2 : InputType::kLast)); + // explicit_bool(input_type + // == (explicit_bool(false) ? input_type_2 : + // InputType::kLast)); - if (!repeat) { - // Keyboard 1 supports assigned keys plus arrow keys if they're unused. - if (keysym->sym == left_key_ - || (device_number() == 1 && keysym->sym == SDLK_LEFT - && !left_key_assigned())) { - player_input = true; - input_type = InputType::kLeftRight; - left_held_ = down; - if (down) { - if (right_held_) { - input_value = 0; - } else { - input_value = -32767; - } + // Keyboard 1 supports assigned keys plus arrow keys if they're unused. + if (keysym->sym == left_key_ + || (device_number() == 1 && keysym->sym == SDLK_LEFT + && !left_key_assigned())) { + player_input = true; + input_type = InputType::kLeftRight; + left_held_ = down; + if (down) { + if (right_held_) { + input_value = 0; } else { - if (right_held_) { - input_value = 32767; - } - } - } else if (keysym->sym == right_key_ - || (device_number() == 1 && keysym->sym == SDLK_RIGHT - && !right_key_assigned())) { - // Keyboard 1 supports assigned keys plus arrow keys if they're unused. - player_input = true; - input_type = InputType::kLeftRight; - right_held_ = down; - if (down) { - if (left_held_) { - input_value = 0; - } else { - input_value = 32767; - } - } else { - if (left_held_) { - input_value = -32767; - } - } - } else if (keysym->sym == up_key_ - || (device_number() == 1 && keysym->sym == SDLK_UP - && !up_key_assigned())) { - player_input = true; - input_type = InputType::kUpDown; - up_held_ = down; - if (down) { - if (down_held_) { - input_value = 0; - } else { - input_value = 32767; - } - } else { - if (down_held_) input_value = -32767; - } - } else if (keysym->sym == down_key_ - || (device_number() == 1 && keysym->sym == SDLK_DOWN - && !down_key_assigned())) { - player_input = true; - input_type = InputType::kUpDown; - down_held_ = down; - if (down) { - if (up_held_) { - input_value = 0; - } else { - input_value = -32767; - } - } else { - if (up_held_) input_value = 32767; - } - } else if (keysym->sym == punch_key_) { - player_input = true; - UpdateRun(keysym->sym, down); - if (down) { - input_type = InputType::kPunchPress; - } else { - input_type = InputType::kPunchRelease; - } - } else if (keysym->sym == bomb_key_) { - player_input = true; - UpdateRun(keysym->sym, down); - if (down) - input_type = InputType::kBombPress; - else - input_type = InputType::kBombRelease; - } else if (keysym->sym == hold_position_key_) { - player_input = true; - if (down) { - input_type = InputType::kHoldPositionPress; - } else { - input_type = InputType::kHoldPositionRelease; - } - } else if (keysym->sym == pick_up_key_) { - player_input = true; - UpdateRun(keysym->sym, down); - if (down) { - input_type = InputType::kPickUpPress; - } else { - input_type = InputType::kPickUpRelease; - } - } else if ((device_number() == 1 && keysym->sym == SDLK_RETURN) - || (device_number() == 1 && keysym->sym == SDLK_KP_ENTER) - || keysym->sym == jump_key_) { - // Keyboard 1 claims certain keys if they are otherwise unclaimed - // (arrow keys, enter/return, etc). - player_input = true; - UpdateRun(keysym->sym, down); - if (down) { - input_type = InputType::kJumpPress; - have_input_2 = true; - input_type_2 = InputType::kFlyPress; - } else { - input_type = InputType::kJumpRelease; - have_input_2 = true; - input_type_2 = InputType::kFlyRelease; + input_value = -32767; } } else { - // Any other keys get processed as run keys. - // keypad keys go to player 2 - anything else to player 1. - switch (keysym->sym) { - case SDLK_KP_0: - case SDLK_KP_1: - case SDLK_KP_2: - case SDLK_KP_3: - case SDLK_KP_4: - case SDLK_KP_5: - case SDLK_KP_6: - case SDLK_KP_7: - case SDLK_KP_8: - case SDLK_KP_9: - case SDLK_KP_PLUS: - case SDLK_KP_MINUS: - case SDLK_KP_ENTER: - if (device_number() == 2) { - UpdateRun(keysym->sym, down); - return true; - } - break; - default: - if (device_number() == 1) { - UpdateRun(keysym->sym, down); - return true; - } - break; + if (right_held_) { + input_value = 32767; } } + } else if (keysym->sym == right_key_ + || (device_number() == 1 && keysym->sym == SDLK_RIGHT + && !right_key_assigned())) { + // Keyboard 1 supports assigned keys plus arrow keys if they're unused. + player_input = true; + input_type = InputType::kLeftRight; + right_held_ = down; + if (down) { + if (left_held_) { + input_value = 0; + } else { + input_value = 32767; + } + } else { + if (left_held_) { + input_value = -32767; + } + } + } else if (keysym->sym == up_key_ + || (device_number() == 1 && keysym->sym == SDLK_UP + && !up_key_assigned())) { + player_input = true; + input_type = InputType::kUpDown; + up_held_ = down; + if (down) { + if (down_held_) { + input_value = 0; + } else { + input_value = 32767; + } + } else { + if (down_held_) input_value = -32767; + } + } else if (keysym->sym == down_key_ + || (device_number() == 1 && keysym->sym == SDLK_DOWN + && !down_key_assigned())) { + player_input = true; + input_type = InputType::kUpDown; + down_held_ = down; + if (down) { + if (up_held_) { + input_value = 0; + } else { + input_value = -32767; + } + } else { + if (up_held_) input_value = 32767; + } + } else if (keysym->sym == punch_key_) { + player_input = true; + UpdateRun_(keysym->sym, down); + if (down) { + input_type = InputType::kPunchPress; + } else { + input_type = InputType::kPunchRelease; + } + } else if (keysym->sym == bomb_key_) { + player_input = true; + UpdateRun_(keysym->sym, down); + if (down) + input_type = InputType::kBombPress; + else + input_type = InputType::kBombRelease; + } else if (keysym->sym == hold_position_key_) { + player_input = true; + if (down) { + input_type = InputType::kHoldPositionPress; + } else { + input_type = InputType::kHoldPositionRelease; + } + } else if (keysym->sym == pick_up_key_) { + player_input = true; + UpdateRun_(keysym->sym, down); + if (down) { + input_type = InputType::kPickUpPress; + } else { + input_type = InputType::kPickUpRelease; + } + } else if ((device_number() == 1 && keysym->sym == SDLK_RETURN) + || (device_number() == 1 && keysym->sym == SDLK_KP_ENTER) + || keysym->sym == jump_key_) { + // Keyboard 1 claims certain keys if they are otherwise unclaimed + // (arrow keys, enter/return, etc). + player_input = true; + UpdateRun_(keysym->sym, down); + if (down) { + input_type = InputType::kJumpPress; + have_input_2 = true; + input_type_2 = InputType::kFlyPress; + } else { + input_type = InputType::kJumpRelease; + have_input_2 = true; + input_type_2 = InputType::kFlyRelease; + } + } else { + // Any other keys get processed as run keys. + // keypad keys go to player 2 - anything else to player 1. + switch (keysym->sym) { + case SDLK_KP_0: + case SDLK_KP_1: + case SDLK_KP_2: + case SDLK_KP_3: + case SDLK_KP_4: + case SDLK_KP_5: + case SDLK_KP_6: + case SDLK_KP_7: + case SDLK_KP_8: + case SDLK_KP_9: + case SDLK_KP_PLUS: + case SDLK_KP_MINUS: + case SDLK_KP_ENTER: + if (device_number() == 2) { + UpdateRun_(keysym->sym, down); + return true; + } + break; + default: + if (device_number() == 1) { + UpdateRun_(keysym->sym, down); + return true; + } + break; + } } if (player_input) { @@ -344,7 +357,7 @@ void KeyboardInput::ResetHeldStates() { } } -void KeyboardInput::UpdateRun(SDL_Keycode key, bool down) { +void KeyboardInput::UpdateRun_(SDL_Keycode key, bool down) { bool was_held = (!keys_held_.empty()); if (down) { keys_held_.insert(key); @@ -407,51 +420,51 @@ void KeyboardInput::UpdateMapping() { int val = cl ? cl->GetControllerValue(this, "buttonJump") : -1; jump_key_ = (val == -1) ? jump_key_default : (SDL_Keycode)val; - UpdateArrowKeys(jump_key_); + UpdateArrowKeys_(jump_key_); val = cl ? cl->GetControllerValue(this, "buttonPunch") : -1; punch_key_ = (val == -1) ? punch_key_default : (SDL_Keycode)val; - UpdateArrowKeys(punch_key_); + UpdateArrowKeys_(punch_key_); val = cl ? cl->GetControllerValue(this, "buttonBomb") : -1; bomb_key_ = (val == -1) ? bomb_key_default : (SDL_Keycode)val; - UpdateArrowKeys(bomb_key_); + UpdateArrowKeys_(bomb_key_); val = cl ? cl->GetControllerValue(this, "buttonPickUp") : -1; pick_up_key_ = (val == -1) ? pick_up_key_default : (SDL_Keycode)val; - UpdateArrowKeys(pick_up_key_); + UpdateArrowKeys_(pick_up_key_); val = cl ? cl->GetControllerValue(this, "buttonHoldPosition") : -1; hold_position_key_ = (val == -1) ? hold_position_key_default : (SDL_Keycode)val; - UpdateArrowKeys(hold_position_key_); + UpdateArrowKeys_(hold_position_key_); val = cl ? cl->GetControllerValue(this, "buttonStart") : -1; start_key_ = (val == -1) ? start_key_default : (SDL_Keycode)val; - UpdateArrowKeys(start_key_); + UpdateArrowKeys_(start_key_); val = cl ? cl->GetControllerValue(this, "buttonUp") : -1; up_key_ = (val == -1) ? up_key_default : (SDL_Keycode)val; - UpdateArrowKeys(up_key_); + UpdateArrowKeys_(up_key_); val = cl ? cl->GetControllerValue(this, "buttonDown") : -1; down_key_ = (val == -1) ? down_key_default : (SDL_Keycode)val; - UpdateArrowKeys(down_key_); + UpdateArrowKeys_(down_key_); val = cl ? cl->GetControllerValue(this, "buttonLeft") : -1; left_key_ = (val == -1) ? left_key_default : (SDL_Keycode)val; - UpdateArrowKeys(left_key_); + UpdateArrowKeys_(left_key_); val = cl ? cl->GetControllerValue(this, "buttonRight") : -1; right_key_ = (val == -1) ? right_key_default : (SDL_Keycode)val; - UpdateArrowKeys(right_key_); + UpdateArrowKeys_(right_key_); enable_child_ = true; up_held_ = down_held_ = left_held_ = right_held_ = false; } -void KeyboardInput::UpdateArrowKeys(SDL_Keycode key) { +void KeyboardInput::UpdateArrowKeys_(SDL_Keycode key) { if (key == SDLK_UP) { up_key_assigned_ = true; } else if (key == SDLK_DOWN) { @@ -465,7 +478,6 @@ void KeyboardInput::UpdateArrowKeys(SDL_Keycode key) { auto KeyboardInput::GetButtonName(int index) -> std::string { return g_base->platform->GetKeyName(index); - // return InputDevice::GetButtonName(index); } auto KeyboardInput::GetRawDeviceName() -> std::string { return "Keyboard"; } diff --git a/src/ballistica/base/input/device/keyboard_input.h b/src/ballistica/base/input/device/keyboard_input.h index 6d790e9c..8138b5c6 100644 --- a/src/ballistica/base/input/device/keyboard_input.h +++ b/src/ballistica/base/input/device/keyboard_input.h @@ -8,6 +8,7 @@ #include "ballistica/base/input/device/input_device.h" #include "ballistica/core/platform/support/min_sdl.h" +#include "ballistica/shared/foundation/object.h" namespace ballistica::base { @@ -15,7 +16,7 @@ class KeyboardInput : public InputDevice { public: explicit KeyboardInput(KeyboardInput* parent); ~KeyboardInput() override; - auto HandleKey(const SDL_Keysym* keysym, bool repeat, bool down) -> bool; + auto HandleKey(const SDL_Keysym* keysym, bool down) -> bool; void UpdateMapping() override; auto GetRawDeviceName() -> std::string override; void ResetHeldStates() override; @@ -29,8 +30,17 @@ class KeyboardInput : public InputDevice { auto GetButtonName(int index) -> std::string override; private: - void UpdateArrowKeys(SDL_Keycode key); - void UpdateRun(SDL_Keycode key, bool down); + void UpdateArrowKeys_(SDL_Keycode key); + void UpdateRun_(SDL_Keycode key, bool down); + bool down_held_ : 1 {}; + bool up_held_ : 1 {}; + bool left_held_ : 1 {}; + bool right_held_ : 1 {}; + bool enable_child_ : 1 {}; + bool left_key_assigned_ : 1 {}; + bool right_key_assigned_ : 1 {}; + bool up_key_assigned_ : 1 {}; + bool down_key_assigned_ : 1 {}; SDL_Keycode up_key_{}; SDL_Keycode down_key_{}; SDL_Keycode left_key_{}; @@ -41,18 +51,10 @@ class KeyboardInput : public InputDevice { SDL_Keycode pick_up_key_{}; SDL_Keycode hold_position_key_{}; SDL_Keycode start_key_{}; - bool down_held_{}; - bool up_held_{}; - bool left_held_{}; - bool right_held_{}; - bool enable_child_{}; - bool left_key_assigned_{}; - bool right_key_assigned_{}; - bool up_key_assigned_{}; - bool down_key_assigned_{}; KeyboardInput* parent_keyboard_input_{}; KeyboardInput* child_keyboard_input_{}; std::set keys_held_; + Object::Ref ui_repeater_; }; } // namespace ballistica::base diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index acefa84b..dfca9fd0 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -159,12 +159,11 @@ void Input::AnnounceConnects_() { // For the first announcement just say "X controllers detected" and don't // have a sound. - if (first_print && g_core->GetAppTimeSeconds() < 5.0) { + if (first_print && g_core->GetAppTimeSeconds() < 2.0) { first_print = false; // Disabling this completely on Android for now; we often get large // numbers of devices there that aren't actually devices. - bool do_print_initial_counts{!g_buildconfig.ostype_android()}; // If there's been several connected, just give a number. @@ -243,7 +242,7 @@ void Input::ShowStandardInputDeviceConnectedMessage_(InputDevice* j) { g_base->logic->DeleteAppTimer(connect_print_timer_id_); } connect_print_timer_id_ = g_base->logic->NewAppTimer( - 250, false, NewLambdaRunnable([this] { AnnounceConnects_(); })); + 250, false, NewLambdaRunnable([this] { AnnounceConnects_(); }).Get()); } void Input::ShowStandardInputDeviceDisconnectedMessage_(InputDevice* j) { @@ -258,7 +257,7 @@ void Input::ShowStandardInputDeviceDisconnectedMessage_(InputDevice* j) { g_base->logic->DeleteAppTimer(disconnect_print_timer_id_); } disconnect_print_timer_id_ = g_base->logic->NewAppTimer( - 250, false, NewLambdaRunnable([this] { AnnounceDisconnects_(); })); + 250, false, NewLambdaRunnable([this] { AnnounceDisconnects_(); }).Get()); } void Input::PushAddInputDeviceCall(InputDevice* input_device, @@ -802,6 +801,7 @@ void Input::ProcessStressTesting(int player_count) { (*test_input).Reset(); } } + while (stress_test_time_ < time) { stress_test_time_++; for (auto& test_input : test_inputs_) { @@ -815,7 +815,7 @@ void Input::PushTextInputEvent(const std::string& text) { g_base->logic->event_loop()->PushCall([this, text] { MarkInputActive(); - // If if the app doesn't want direct text input right now. + // If the app doesn't want direct text input right now, ignore. if (!g_base->app_adapter->HasDirectKeyboardInput()) { return; } @@ -848,6 +848,7 @@ void Input::PushTextInputEvent(const std::string& text) { && g_base->ui->dev_console()->HandleTextEditing(text)) { return; } + g_base->ui->SendWidgetMessage(WidgetMessage( WidgetMessage::Type::kTextInput, nullptr, 0, 0, 0, 0, text.c_str())); }); @@ -986,6 +987,34 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) { return; } + // Nowadays we don't want the OS to deliver repeat events to us, + // so filter out any that we get and make noise that they should stop. We + // explicitly handle repeats for UI purposes at the InputDevice or Widget + // level now. + if (keys_held_.find(keysym.sym) != keys_held_.end()) { + // Look out for several repeats coming in within the span of a few + // seconds and complain if it happens. This should allow for the random + // fluke repeat key press event due to funky OS circumstances. + static int count{}; + static seconds_t last_count_reset_time{}; + auto now = g_core->GetAppTimeSeconds(); + if (now - last_count_reset_time > 2.0) { + count = 0; + last_count_reset_time = now; + } else { + count++; + if (count > 10) { + BA_LOG_ONCE( + LogLevel::kWarning, + "Input::HandleKeyPress_ seems to be getting passed repeat key" + " press events. Only initial press events should be passed."); + } + } + return; + } + + keys_held_.insert(keysym.sym); + // If someone is capturing these events, give them a crack at it. if (keyboard_input_capture_press_) { if (keyboard_input_capture_press_(keysym)) { @@ -998,52 +1027,44 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) { // ideally we should use the modifiers bundled with the key presses) UpdateModKeyStates_(&keysym, true); - bool repeat_press; - if (keys_held_.count(keysym.sym) != 0) { - repeat_press = true; - } else { - repeat_press = false; - keys_held_.insert(keysym.sym); - } - // Mobile-specific stuff. - if (g_buildconfig.ostype_ios_tvos() || g_buildconfig.ostype_android()) { - switch (keysym.sym) { - // FIXME: See if this stuff is still necessary. Was this perhaps - // specifically to support the console? - case SDLK_DELETE: - case SDLK_RETURN: - case SDLK_KP_ENTER: - case SDLK_BACKSPACE: { - // FIXME: I don't remember what this was put here for, but now that - // we have hardware keyboards it crashes text fields by sending - // them a TEXT_INPUT message with no string.. I made them resistant - // to that case but wondering if we can take this out? - g_base->ui->SendWidgetMessage( - WidgetMessage(WidgetMessage::Type::kTextInput, &keysym)); - break; - } - default: - break; - } - } + // if (g_buildconfig.ostype_ios_tvos() || g_buildconfig.ostype_android()) { + // switch (keysym.sym) { + // // FIXME: See if this stuff is still necessary. Was this perhaps + // // specifically to support the console? + // case SDLK_DELETE: + // case SDLK_RETURN: + // case SDLK_KP_ENTER: + // case SDLK_BACKSPACE: { + // // FIXME: I don't remember what this was put here for, but now that + // // we have hardware keyboards it crashes text fields by sending + // // them a TEXT_INPUT message with no string.. I made them resistant + // // to that case but wondering if we can take this out? + // g_base->ui->SendWidgetMessage( + // WidgetMessage(WidgetMessage::Type::kTextInput, &keysym)); + // break; + // } + // default: + // break; + // } + // } // Explicitly handle fullscreen-toggles in some cases. if (g_base->app_adapter->FullscreenControlAvailable()) { bool do_toggle{}; // On our Mac SDL builds we support ctrl+F for toggling fullscreen. // On our nice Cocoa build, fullscreening happens magically through the - // view menu fullscreen controls. + // view menu fullscreen control's shortcut. if (g_buildconfig.ostype_macos() && !g_buildconfig.xcode_build()) { - if (!repeat_press && keysym.sym == SDLK_f && ((keysym.mod & KMOD_CTRL))) { + if (keysym.sym == SDLK_f && ((keysym.mod & KMOD_CTRL))) { do_toggle = true; } } - // On Windows we support both F11 and Alt+Enter for toggling fullscreen. - if (g_buildconfig.ostype_windows()) { - if (!repeat_press - && (keysym.sym == SDLK_F11 - || (keysym.sym == SDLK_RETURN && ((keysym.mod & KMOD_ALT))))) { + // On Windows and Linux we support both F11 and Alt+Enter for toggling + // fullscreen. + if (g_buildconfig.ostype_windows() || g_buildconfig.ostype_linux()) { + if ((keysym.sym == SDLK_F11 + || (keysym.sym == SDLK_RETURN && ((keysym.mod & KMOD_ALT))))) { do_toggle = true; } } @@ -1055,26 +1076,21 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) { } } - // Control-Q quits. On Mac, the usual Cmd-Q gets handled implicitly by the - // app-adapter. - // UPDATE: Disabling this for now. Looks like standard OS shortcuts like - // Alt+F4 on windows or Cmd-Q on Mac are doing the right thing with SDL - // builds these days so these are not needed. - // if (!repeat_press && keysym.sym == SDLK_q && (keysym.mod & KMOD_CTRL)) { - // g_base->QuitApp(true); - // return; - // } - - // Let the console intercept stuff if it wants at this point. + // Dev Console. if (auto* console = g_base->ui->dev_console()) { + if (keysym.sym == SDLK_BACKQUOTE || keysym.sym == SDLK_F2) { + // (reset input so characters don't continue walking and stuff) + g_base->input->ResetHoldStates(); + console->ToggleState(); + return; + } if (console->HandleKeyPress(&keysym)) { return; } } // Ctrl-V or Cmd-V sends paste commands to any interested text fields. - // Command-Q or Control-Q quits. - if (!repeat_press && keysym.sym == SDLK_v + if (keysym.sym == SDLK_v && ((keysym.mod & KMOD_CTRL) || (keysym.mod & KMOD_GUI))) { g_base->ui->SendWidgetMessage(WidgetMessage(WidgetMessage::Type::kPaste)); return; @@ -1082,93 +1098,89 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) { bool handled = false; - // None of the following stuff accepts key repeats. - if (!repeat_press) { - switch (keysym.sym) { - // Menu button on android/etc. pops up the menu. - case SDLK_MENU: { - if (!g_base->ui->MainMenuVisible()) { - g_base->ui->PushMainMenuPressCall(touch_input_); - } - handled = true; - break; + switch (keysym.sym) { + // Menu button on android/etc. pops up the menu. + case SDLK_MENU: { + if (!g_base->ui->MainMenuVisible()) { + g_base->ui->PushMainMenuPressCall(touch_input_); } - - case SDLK_EQUALS: - case SDLK_PLUS: - if (keysym.mod & KMOD_CTRL) { - g_base->app_mode()->ChangeGameSpeed(1); - handled = true; - } - break; - - case SDLK_MINUS: - if (keysym.mod & KMOD_CTRL) { - g_base->app_mode()->ChangeGameSpeed(-1); - handled = true; - } - break; - - case SDLK_F5: { - if (g_base->ui->PartyIconVisible()) { - g_base->ui->ActivatePartyIcon(); - } - handled = true; - break; - } - - case SDLK_F7: - assert(g_base->logic->event_loop()); - g_base->logic->event_loop()->PushCall( - [] { g_base->graphics->ToggleManualCamera(); }); - handled = true; - break; - - case SDLK_F8: - assert(g_base->logic->event_loop()); - g_base->logic->event_loop()->PushCall( - [] { g_base->graphics->ToggleNetworkDebugDisplay(); }); - handled = true; - break; - - case SDLK_F9: - g_base->python->objs().PushCall( - BasePython::ObjID::kLanguageTestToggleCall); - handled = true; - break; - - case SDLK_F10: - assert(g_base->logic->event_loop()); - g_base->logic->event_loop()->PushCall( - [] { g_base->graphics->ToggleDebugDraw(); }); - handled = true; - break; - - case SDLK_ESCAPE: - - if (!g_base->ui->MainMenuVisible()) { - // There's no main menu up. Ask for one. - - // Note: keyboard_input_ may be nullptr but escape key should - // still function for menus; it just won't claim ownership. - g_base->ui->PushMainMenuPressCall(keyboard_input_); - } else { - // Ok there *is* a main menu up. Send it a cancel message. - g_base->ui->SendWidgetMessage( - WidgetMessage(WidgetMessage::Type::kCancel)); - } - handled = true; - break; - - default: - break; + handled = true; + break; } + + case SDLK_EQUALS: + case SDLK_PLUS: + if (keysym.mod & KMOD_CTRL) { + g_base->app_mode()->ChangeGameSpeed(1); + handled = true; + } + break; + + case SDLK_MINUS: + if (keysym.mod & KMOD_CTRL) { + g_base->app_mode()->ChangeGameSpeed(-1); + handled = true; + } + break; + + case SDLK_F5: { + if (g_base->ui->PartyIconVisible()) { + g_base->ui->ActivatePartyIcon(); + } + handled = true; + break; + } + + case SDLK_F7: + assert(g_base->logic->event_loop()); + g_base->logic->event_loop()->PushCall( + [] { g_base->graphics->ToggleManualCamera(); }); + handled = true; + break; + + case SDLK_F8: + assert(g_base->logic->event_loop()); + g_base->logic->event_loop()->PushCall( + [] { g_base->graphics->ToggleNetworkDebugDisplay(); }); + handled = true; + break; + + case SDLK_F9: + g_base->python->objs().PushCall( + BasePython::ObjID::kLanguageTestToggleCall); + handled = true; + break; + + case SDLK_F10: + assert(g_base->logic->event_loop()); + g_base->logic->event_loop()->PushCall( + [] { g_base->graphics->ToggleDebugDraw(); }); + handled = true; + break; + + case SDLK_ESCAPE: + if (!g_base->ui->MainMenuVisible()) { + // There's no main menu up. Ask for one. + + // Note: keyboard_input_ may be nullptr but escape key should + // still function for menus; it just won't claim ownership. + g_base->ui->PushMainMenuPressCall(keyboard_input_); + } else { + // Ok there *is* a main menu up. Send it a cancel message. + g_base->ui->SendWidgetMessage( + WidgetMessage(WidgetMessage::Type::kCancel)); + } + handled = true; + break; + + default: + break; } - // If we haven't claimed it, pass it along as potential player/widget input. + // If we haven't handled this, pass it along as potential player/widget input. if (!handled) { if (keyboard_input_) { - keyboard_input_->HandleKey(&keysym, repeat_press, true); + keyboard_input_->HandleKey(&keysym, true); } } } @@ -1184,7 +1196,7 @@ void Input::HandleKeyRelease_(const SDL_Keysym& keysym) { // In some cases we may receive duplicate key-release events (if a // keyboard reset was run, it deals out key releases, but then the // keyboard driver issues them as well). - if (keys_held_.count(keysym.sym) == 0) { + if (keys_held_.find(keysym.sym) == keys_held_.end()) { return; } @@ -1205,7 +1217,7 @@ void Input::HandleKeyRelease_(const SDL_Keysym& keysym) { } if (keyboard_input_) { - keyboard_input_->HandleKey(&keysym, false, false); + keyboard_input_->HandleKey(&keysym, false); } } diff --git a/src/ballistica/base/logic/logic.cc b/src/ballistica/base/logic/logic.cc index 67a05cf2..030229c2 100644 --- a/src/ballistica/base/logic/logic.cc +++ b/src/ballistica/base/logic/logic.cc @@ -100,7 +100,7 @@ void Logic::OnGraphicsReady() { // variety of rates anyway. NOTE: This length is currently milliseconds. headless_display_time_step_timer_ = event_loop()->NewTimer( kHeadlessMinDisplayTimeStep / 1000, true, - NewLambdaRunnable([this] { StepDisplayTime_(); })); + NewLambdaRunnable([this] { StepDisplayTime_(); }).Get()); } else { // In gui mode, push an initial frame to the graphics server. From this // point it will be self-sustaining, sending us a frame request each @@ -133,9 +133,9 @@ void Logic::CompleteAppBootstrapping_() { // Set up our timers. process_pending_work_timer_ = event_loop()->NewTimer( - 0, true, NewLambdaRunnable([this] { ProcessPendingWork_(); })); + 0, true, NewLambdaRunnable([this] { ProcessPendingWork_(); }).Get()); asset_prune_timer_ = event_loop()->NewTimer( - 2345, true, NewLambdaRunnable([] { g_base->assets->Prune(); })); + 2345, true, NewLambdaRunnable([] { g_base->assets->Prune(); }).Get()); // Let our initial dummy app-mode know it has become active. g_base->app_mode()->OnActivate(); @@ -635,8 +635,8 @@ void Logic::NotifyOfPendingAssetLoads() { UpdatePendingWorkTimer_(); } -auto Logic::NewAppTimer(millisecs_t length, bool repeat, - const Object::Ref& runnable) -> int { +auto Logic::NewAppTimer(millisecs_t length, bool repeat, Runnable* runnable) + -> int { // App-Timers simply get injected into our loop and run alongside our own // stuff. assert(g_base->InLogicThread()); @@ -667,7 +667,7 @@ auto Logic::NewDisplayTimer(microsecs_t length, bool repeat, assert(g_base->InLogicThread()); int offset = 0; Timer* t = display_timers_->NewTimer(g_core->GetAppTimeMicrosecs(), length, - offset, repeat ? -1 : 0, runnable); + offset, repeat ? -1 : 0, runnable.Get()); return t->id(); } diff --git a/src/ballistica/base/logic/logic.h b/src/ballistica/base/logic/logic.h index b215be32..3974392b 100644 --- a/src/ballistica/base/logic/logic.h +++ b/src/ballistica/base/logic/logic.h @@ -89,8 +89,7 @@ class Logic { void HandleInterruptSignal(); void HandleTerminateSignal(); - auto NewAppTimer(millisecs_t length, bool repeat, - const Object::Ref& runnable) -> int; + auto NewAppTimer(millisecs_t length, bool repeat, Runnable* runnable) -> int; void DeleteAppTimer(int timer_id); void SetAppTimerLength(int timer_id, millisecs_t length); diff --git a/src/ballistica/base/platform/apple/base_platform_apple.cc b/src/ballistica/base/platform/apple/base_platform_apple.cc index 55226812..833d8003 100644 --- a/src/ballistica/base/platform/apple/base_platform_apple.cc +++ b/src/ballistica/base/platform/apple/base_platform_apple.cc @@ -4,11 +4,14 @@ #include "ballistica/base/platform/apple/base_platform_apple.h" #if BA_XCODE_BUILD -#include +#include "ballistica/base/platform/apple/apple_utils.h" +#include "ballistica/base/platform/apple/from_swift.h" #endif #if BA_XCODE_BUILD -#include "ballistica/base/platform/apple/apple_utils.h" +// This needs to be below ballistica headers since it relies on +// some types in them but does not include headers itself. +#include #endif namespace ballistica::base { @@ -48,9 +51,9 @@ void BasePlatformApple::PurchaseAck(const std::string& purchase, void BasePlatformApple::DoOpenURL(const std::string& url) { #if BA_XCODE_BUILD #if BA_OSTYPE_MACOS - BallisticaKit::CocoaFromCppOpenURL(url); + BallisticaKit::CocoaFromCpp::OpenURL(url); #else - BallisticaKit::UIKitFromCppOpenURL(url); + BallisticaKit::UIKitFromCpp::OpenURL(url); #endif // BA_OSTYPE_MACOS #else diff --git a/src/ballistica/base/python/class/python_class_app_timer.cc b/src/ballistica/base/python/class/python_class_app_timer.cc index dd75823f..0202a91d 100644 --- a/src/ballistica/base/python/class/python_class_app_timer.cc +++ b/src/ballistica/base/python/class/python_class_app_timer.cc @@ -95,7 +95,7 @@ auto PythonClassAppTimer::tp_new(PyTypeObject* type, PyObject* args, self->timer_id_ = g_base->logic->NewAppTimer( static_cast(length * 1000.0), repeat, - Object::New(call_obj)); + Object::New(call_obj).Get()); self->have_timer_ = true; diff --git a/src/ballistica/base/python/methods/python_methods_app.cc b/src/ballistica/base/python/methods/python_methods_app.cc index befd17d3..471c6c08 100644 --- a/src/ballistica/base/python/methods/python_methods_app.cc +++ b/src/ballistica/base/python/methods/python_methods_app.cc @@ -366,7 +366,7 @@ static auto PyAppTimer(PyObject* self, PyObject* args, PyObject* keywds) } g_base->logic->NewAppTimer( static_cast(length * 1000.0), false, - Object::New(call_obj)); + Object::New(call_obj).Get()); Py_RETURN_NONE; BA_PYTHON_CATCH; } @@ -1645,6 +1645,52 @@ static PyMethodDef PyAudioShutdownIsCompleteDef = { "(internal)\n", }; +// ----------------------- graphics_shutdown_begin ----------------------------- + +static auto PyGraphicsShutdownBegin(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + + g_base->app_adapter->PushGraphicsContextCall( + [] { g_base->graphics_server->Shutdown(); }); + + Py_RETURN_NONE; + + BA_PYTHON_CATCH; +} + +static PyMethodDef PyGraphicsShutdownBeginDef = { + "graphics_shutdown_begin", // name + (PyCFunction)PyGraphicsShutdownBegin, // method + METH_NOARGS, // flags + + "graphics_shutdown_begin() -> None\n" + "\n" + "(internal)\n", +}; + +// -------------------- graphics_shutdown_is_complete -------------------------- + +static auto PyGraphicsShutdownIsComplete(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + + if (g_base->graphics_server->shutdown_completed()) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; + + BA_PYTHON_CATCH; +} + +static PyMethodDef PyGraphicsShutdownIsCompleteDef = { + "graphics_shutdown_is_complete", // name + (PyCFunction)PyGraphicsShutdownIsComplete, // method + METH_NOARGS, // flags + + "graphics_shutdown_is_complete() -> bool\n" + "\n" + "(internal)\n", +}; + // ----------------------------------------------------------------------------- auto PythonMethodsApp::GetMethods() -> std::vector { @@ -1702,6 +1748,8 @@ auto PythonMethodsApp::GetMethods() -> std::vector { PyDevConsoleInputAdapterFinishDef, PyAudioShutdownBeginDef, PyAudioShutdownIsCompleteDef, + PyGraphicsShutdownBeginDef, + PyGraphicsShutdownIsCompleteDef, }; } diff --git a/src/ballistica/base/python/methods/python_methods_graphics.cc b/src/ballistica/base/python/methods/python_methods_graphics.cc index 63eac46f..1e489461 100644 --- a/src/ballistica/base/python/methods/python_methods_graphics.cc +++ b/src/ballistica/base/python/methods/python_methods_graphics.cc @@ -536,6 +536,7 @@ static auto PyFadeScreen(PyObject* self, PyObject* args, PyObject* keywds) &endcall)) { return nullptr; } + BA_PRECONDITION(g_base->InLogicThread()); g_base->graphics->FadeScreen(static_cast(fade), static_cast(1000.0f * time), endcall); Py_RETURN_NONE; diff --git a/src/ballistica/base/support/app_timer.h b/src/ballistica/base/support/app_timer.h index e116c26a..966ef01b 100644 --- a/src/ballistica/base/support/app_timer.h +++ b/src/ballistica/base/support/app_timer.h @@ -13,12 +13,17 @@ namespace ballistica::base { class AppTimer : public Object { public: - AppTimer(millisecs_t length, bool repeat, - const Object::Ref& runnable) { + AppTimer(millisecs_t length, bool repeat, Runnable* runnable) { assert(g_base->InLogicThread()); timer_id_ = base::g_base->logic->NewAppTimer(length, repeat, runnable); } + template + static auto New(millisecs_t length, bool repeat, const F& lambda) { + return Object::New(length, repeat, + NewLambdaRunnable(lambda).Get()); + } + void SetLength(millisecs_t length) { assert(g_base->InLogicThread()); base::g_base->logic->SetAppTimerLength(timer_id_, length); @@ -32,13 +37,6 @@ class AppTimer : public Object { int timer_id_; }; -/// Create a AppTimer from a raw lambda. -template -auto NewAppTimer(millisecs_t length, bool repeat, const F& lambda) - -> Object::Ref { - return Object::New(length, repeat, NewLambdaRunnable(lambda)); -} - } // namespace ballistica::base #endif // BALLISTICA_BASE_SUPPORT_APP_TIMER_H_ diff --git a/src/ballistica/base/support/repeater.cc b/src/ballistica/base/support/repeater.cc new file mode 100644 index 00000000..1593da15 --- /dev/null +++ b/src/ballistica/base/support/repeater.cc @@ -0,0 +1,58 @@ +// Released under the MIT License. See LICENSE for details. + +#include "ballistica/base/support/repeater.h" + +#include "ballistica/base/app_adapter/app_adapter.h" +#include "ballistica/base/support/app_timer.h" +#include "ballistica/shared/foundation/event_loop.h" + +namespace ballistica::base { +Repeater::Repeater(seconds_t initial_delay, seconds_t repeat_delay, + Runnable* runnable) + : initial_delay_(initial_delay), + repeat_delay_(repeat_delay), + runnable_(runnable) { + assert(g_base->InLogicThread()); + assert(initial_delay >= 0.0); + assert(repeat_delay >= 0.0); + + // Let's go ahead and run our initial time in a deferred call; + // this is generally safer than running in the middle of whatever UI + // code set this up. + auto weak_this = Object::WeakRef(this); + g_base->logic->event_loop()->PushCall([weak_this] { + if (weak_this.Exists()) { + weak_this->runnable_->RunAndLogErrors(); + if (!weak_this.Exists()) { + // Runnable might have killed us. + return; + } + // Kick off our initial delay timer (generally the longer one). + weak_this->timer_ = AppTimer::New( + static_cast(weak_this->initial_delay_ * 1000.0), false, + [weak_this] { + // Timer should not have fired if we died. + assert(weak_this.Exists()); + weak_this->runnable_->RunAndLogErrors(); + if (!weak_this.Exists()) { + // Runnable might have killed us. + return; + } + // Kick off our repeat timer (generally the short one). + weak_this->timer_ = AppTimer::New( + static_cast(weak_this->repeat_delay_ * 1000.0), + true, [weak_this] { + // Timer should not have fired if we died. + assert(weak_this.Exists()); + weak_this->runnable_->RunAndLogErrors(); + // Doesn't matter if Runnable killed us since we don't + // touch anything for the remainder of this function. + }); + }); + } + }); +} + +Repeater::~Repeater() { assert(g_base->InLogicThread()); } + +} // namespace ballistica::base diff --git a/src/ballistica/base/support/repeater.h b/src/ballistica/base/support/repeater.h new file mode 100644 index 00000000..19355a38 --- /dev/null +++ b/src/ballistica/base/support/repeater.h @@ -0,0 +1,35 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_BASE_SUPPORT_REPEATER_H_ +#define BALLISTICA_BASE_SUPPORT_REPEATER_H_ + +#include "ballistica/base/base.h" +#include "ballistica/shared/foundation/object.h" +#include "ballistica/shared/generic/lambda_runnable.h" + +namespace ballistica::base { + +/// Runs some code immediately and then repeatedly after a delay. Useful for +/// jobs such as selecting ui elements while keys or buttons are held. +class Repeater : public Object { + public: + Repeater(seconds_t initial_delay, seconds_t repeat_delay, Runnable* runnable); + ~Repeater(); + + template + static auto New(seconds_t initial_delay, seconds_t repeat_delay, + const F& lambda) { + return Object::New(initial_delay, repeat_delay, + NewLambdaRunnable(lambda).Get()); + } + + private: + seconds_t initial_delay_; + seconds_t repeat_delay_; + Object::Ref timer_; + Object::Ref runnable_; +}; + +} // namespace ballistica::base + +#endif // BALLISTICA_BASE_SUPPORT_REPEATER_H_ diff --git a/src/ballistica/base/ui/dev_console.cc b/src/ballistica/base/ui/dev_console.cc index 8b7dc05a..f0ac5365 100644 --- a/src/ballistica/base/ui/dev_console.cc +++ b/src/ballistica/base/ui/dev_console.cc @@ -2,6 +2,7 @@ #include "ballistica/base/ui/dev_console.h" +#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/app_mode/app_mode.h" #include "ballistica/base/audio/audio.h" #include "ballistica/base/graphics/component/simple_component.h" @@ -11,6 +12,7 @@ #include "ballistica/base/logic/logic.h" #include "ballistica/base/platform/base_platform.h" #include "ballistica/base/python/base_python.h" +#include "ballistica/base/support/repeater.h" #include "ballistica/base/ui/ui.h" #include "ballistica/shared/foundation/event_loop.h" #include "ballistica/shared/generic/utils.h" @@ -20,14 +22,12 @@ namespace ballistica::base { // How much of the screen the console covers when it is at full size. -const float kDevConsoleSize = 0.9f; -const int kDevConsoleLineLimit = 80; -const int kDevConsoleStringBreakUpSize = 1950; -const int kDevConsoleActivateKey1 = SDLK_BACKQUOTE; -const int kDevConsoleActivateKey2 = SDLK_F2; +const float kDevConsoleSize{0.9f}; +const int kDevConsoleLineLimit{80}; +const int kDevConsoleStringBreakUpSize{1950}; const float kDevConsoleTabButtonCornerRadius{16.0f}; -const double kTransitionSeconds = 0.15; +const double kTransitionSeconds{0.15}; enum class DevConsoleHAnchor_ { kLeft, kCenter, kRight }; enum class DevButtonStyle_ { kNormal, kDark }; @@ -171,11 +171,7 @@ class DevConsole::Text_ : public DevConsole::Widget_ { } void Draw(RenderPass* pass, float bottom) override { - Vector3f fgcolor; - Vector3f bgcolor; - fgcolor = Vector3f{0.8f, 0.7f, 0.8f}; - bgcolor = Vector3f{0.25, 0.2f, 0.3f}; - + auto fgcolor = Vector3f{0.8f, 0.7f, 0.8f}; DrawText(pass, &text_group, scale, bottom, x + XOffs(h_attach), y, fgcolor); } }; @@ -327,7 +323,6 @@ class DevConsole::ToggleButton_ : public DevConsole::Widget_ { void Draw(RenderPass* pass, float bottom) override { DrawRect(pass, &mesh, bottom, x + XOffs(attach), y, width, height, - pressed ? Vector3f{0.5f, 0.2f, 1.0f} : on ? Vector3f{0.5f, 0.4f, 0.6f} : Vector3f{0.25, 0.2f, 0.3f}); @@ -448,14 +443,11 @@ DevConsole::DevConsole() { if (g_buildconfig.test_build()) { title += " (test)"; } - title_text_group_.SetText(title); built_text_group_.SetText("Built: " __DATE__ " " __TIME__); prompt_text_group_.SetText(">"); } -DevConsole::~DevConsole() = default; - void DevConsole::RefreshTabButtons_() { // IMPORTANT: This code should always be run in its own top level call and // never directly from user code. Otherwise we can wind up mucking with @@ -695,22 +687,25 @@ void DevConsole::InputAdapterFinish() { auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { assert(g_base->InLogicThread()); + // Any presses or releases cancels repeat actions. + key_repeater_.Clear(); + // Handle our toggle buttons no matter whether we're active. - switch (keysym->sym) { - case kDevConsoleActivateKey1: - case kDevConsoleActivateKey2: { - if (!g_buildconfig.demo_build() && !g_buildconfig.arcade_build()) { - // (reset input so characters don't continue walking and stuff) - g_base->input->ResetHoldStates(); - if (auto console = g_base->ui->dev_console()) { - console->ToggleState(); - } - } - return true; - } - default: - break; - } + // switch (keysym->sym) { + // case kDevConsoleActivateKey1: + // case kDevConsoleActivateKey2: { + // if (!g_buildconfig.demo_build() && !g_buildconfig.arcade_build()) { + // // (reset input so characters don't continue walking and stuff) + // g_base->input->ResetHoldStates(); + // if (auto console = g_base->ui->dev_console()) { + // console->ToggleState(); + // } + // } + // return true; + // } + // default: + // break; + // } if (state_ == State_::kInactive) { return false; @@ -725,18 +720,21 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { break; } - // Handle some stuff only with the Python terminal visible. - if (python_terminal_visible_) { + // If we support direct keyboard input, and python terminal is showing, + // handle some keys directly. + if (python_terminal_visible_ && g_base->ui->UIHasDirectKeyboardInput()) { switch (keysym->sym) { - case SDLK_BACKSPACE: - case SDLK_DELETE: { - std::vector unichars = - Utils::UnicodeFromUTF8(input_string_, "fjco38"); - if (!unichars.empty()) { - unichars.resize(unichars.size() - 1); - input_string_ = Utils::UTF8FromUnicode(unichars); - input_text_dirty_ = true; - } + case SDLK_BACKSPACE: { + key_repeater_ = Repeater::New( + g_base->app_adapter->GetKeyRepeatDelay(), + g_base->app_adapter->GetKeyRepeatInterval(), [this] { + auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38"); + if (!unichars.empty()) { + unichars.resize(unichars.size() - 1); + input_string_ = Utils::UTF8FromUnicode(unichars); + input_text_dirty_ = true; + } + }); break; } case SDLK_UP: @@ -772,8 +770,20 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { break; } } + return true; } - return true; + + // By default don't claim key events; we want to be able to show the + // console while still playing/navigating normally. + return false; +} + +auto DevConsole::HandleKeyRelease(const SDL_Keysym* keysym) -> bool { + // Any presses or releases cancels repeat actions. + key_repeater_.Clear(); + + // Otherwise absorb *all* key-ups when we're active. + return state_ != State_::kInactive; } void DevConsole::Exec() { @@ -879,17 +889,6 @@ auto DevConsole::HandleTextEditing(const std::string& text) -> bool { return true; } -auto DevConsole::HandleKeyRelease(const SDL_Keysym* keysym) -> bool { - // Always absorb our activate keys. - if (keysym->sym == kDevConsoleActivateKey1 - || keysym->sym == kDevConsoleActivateKey2) { - return true; - } - - // Otherwise absorb *all* key-ups when we're active. - return state_ != State_::kInactive; -} - void DevConsole::Print(const std::string& s_in) { assert(g_base->InLogicThread()); std::string s = Utils::GetValidUTF8(s_in.c_str(), "cspr"); diff --git a/src/ballistica/base/ui/dev_console.h b/src/ballistica/base/ui/dev_console.h index c362ed6d..e7134c70 100644 --- a/src/ballistica/base/ui/dev_console.h +++ b/src/ballistica/base/ui/dev_console.h @@ -20,7 +20,6 @@ const float kDevConsoleZDepth = 0.0f; class DevConsole { public: DevConsole(); - ~DevConsole(); auto IsActive() const -> bool { return (state_ != State_::kInactive); } auto HandleTextEditing(const std::string& text) -> bool; auto HandleKeyPress(const SDL_Keysym* keysym) -> bool; @@ -82,18 +81,18 @@ class DevConsole { void RefreshTabButtons_(); void RefreshTabContents_(); - bool input_text_dirty_{true}; - bool input_enabled_{}; - bool last_line_mesh_dirty_{true}; - bool python_terminal_visible_{}; - bool python_terminal_pressed_{}; - bool refresh_pending_{}; - int ui_lock_count_{}; + int input_history_position_{}; + int ui_lock_count_ : 1 {}; + bool input_text_dirty_ : 1 {true}; + bool input_enabled_ : 1 {}; + bool last_line_mesh_dirty_ : 1 {true}; + bool python_terminal_visible_ : 1 {}; + bool python_terminal_pressed_ : 1 {}; + bool refresh_pending_ : 1 {}; + double transition_start_{}; State_ state_{State_::kInactive}; State_ state_prev_{State_::kInactive}; millisecs_t last_input_text_change_time_{}; - double transition_start_{}; - int input_history_position_{}; ImageMesh bg_mesh_; ImageMesh stripe_mesh_; ImageMesh border_mesh_; @@ -103,15 +102,15 @@ class DevConsole { TextGroup input_text_group_; std::string last_line_; std::string input_string_; - std::list tabs_{"Python", "AppModes", "Logging", "Graphics", - "UI"}; - std::string active_tab_{"Python"}; + std::list tabs_; + std::string active_tab_; PythonRef string_edit_adapter_; - Object::Ref last_line_mesh_group_; std::list input_history_; std::list output_lines_; std::vector > widgets_; std::vector > tab_buttons_; + Object::Ref last_line_mesh_group_; + Object::Ref key_repeater_; }; } // namespace ballistica::base diff --git a/src/ballistica/base/ui/ui.cc b/src/ballistica/base/ui/ui.cc index e9b50093..06930e4c 100644 --- a/src/ballistica/base/ui/ui.cc +++ b/src/ballistica/base/ui/ui.cc @@ -194,7 +194,7 @@ auto UI::UIHasDirectKeyboardInput() const -> bool { // we'll probably want to pop up a controller-centric on-screen-keyboard // thingie instead. auto* ui_input_device = g_base->ui->GetUIInputDevice(); - if (auto* keyboard = g_base->ui->GetUIInputDevice()) { + if (auto* keyboard = g_base->input->keyboard_input()) { if (ui_input_device == keyboard || ui_input_device == nullptr) { return true; } @@ -532,7 +532,7 @@ void UI::OnAssetsAvailable() { assert(g_base->InLogicThread()); // Spin up the dev console. - if (!g_core->HeadlessMode()) { + if (!g_core->HeadlessMode() && !g_buildconfig.demo_build()) { assert(dev_console_ == nullptr); dev_console_ = new DevConsole(); diff --git a/src/ballistica/base/ui/ui.h b/src/ballistica/base/ui/ui.h index 02cecbb7..7ed5dd92 100644 --- a/src/ballistica/base/ui/ui.h +++ b/src/ballistica/base/ui/ui.h @@ -17,6 +17,14 @@ class Widget; namespace ballistica::base { +/// Delay before moving through elements in the UI when a key/button/stick +/// is held +const seconds_t kUINavigationRepeatDelay{0.25}; + +/// Interval after the initial delay when moving through UI elements when a +/// key/button/stick is held. +const seconds_t kUINavigationRepeatInterval{0.1}; + // Our global UI subsystem. This acts as a manager/wrapper for individual UI // feature-sets that provide specific UI functionality. class UI { @@ -84,10 +92,10 @@ class UI { auto GetUIInputDevice() const -> InputDevice*; /// Return true if there is a full desktop-style hardware keyboard - /// attached and the active UI InputDevice is set to it or not set. This + /// attached and no non-keyboard device is currently controlling the UI. This /// also may take language or user preferences into account. Editable text /// elements can use this to opt in to accepting key events directly - /// instead of popping up a string edit dialog. + /// instead of popping up string edit dialogs. auto UIHasDirectKeyboardInput() const -> bool; /// Schedule a back button press. Can be called from any thread. diff --git a/src/ballistica/core/platform/apple/core_platform_apple.cc b/src/ballistica/core/platform/apple/core_platform_apple.cc index 04d79880..c864f3ad 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.cc +++ b/src/ballistica/core/platform/apple/core_platform_apple.cc @@ -4,7 +4,6 @@ #include "ballistica/core/platform/apple/core_platform_apple.h" #if BA_XCODE_BUILD -#include #include #endif @@ -12,6 +11,14 @@ #if BA_XCODE_BUILD #include "ballistica/base/platform/apple/apple_utils.h" +#include "ballistica/base/platform/apple/from_swift.h" +#include "ballistica/shared/math/rect.h" +#endif + +#if BA_XCODE_BUILD +// This needs to be below ballistica headers since it relies on +// some types in them but does not include headers itself. +#include #endif namespace ballistica::core { @@ -31,7 +38,7 @@ auto CorePlatformApple::GetDeviceV1AccountUUIDPrefix() -> std::string { // Legacy for device-accounts; don't modify this code. auto CorePlatformApple::GetRealLegacyDeviceUUID(std::string* uuid) -> bool { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - *uuid = base::AppleUtils::GetMacUUID(); + *uuid = std::string(BallisticaKit::CocoaFromCpp::GetLegacyDeviceUUID()); return true; #endif #if BA_OSTYPE_IOS_TVOS @@ -69,7 +76,8 @@ auto CorePlatformApple::GetDeviceUUIDInputs() -> std::list { std::list out; #if BA_OSTYPE_MACOS #if BA_XCODE_BUILD - out.push_back(base::AppleUtils::GetMacUUID()); + out.push_back( + std::string(BallisticaKit::CocoaFromCpp::GetLegacyDeviceUUID())); #else // BA_XCODE_BUILD out.push_back(GetMacUUIDFallback()); #endif // BA_XCODE_BUILD @@ -96,28 +104,13 @@ auto CorePlatformApple::DoGetConfigDirectoryMonolithicDefault() printf("FIXME: get proper default-config-dir\n"); return std::string(getenv("HOME")) + "/Library"; #elif BA_OSTYPE_MACOS && BA_XCODE_BUILD - return base::AppleUtils::GetApplicationSupportPath() + "/BallisticaKit"; + return std::string(BallisticaKit::CocoaFromCpp::GetApplicationSupportPath()) + + "/BallisticaKit"; #else return CorePlatform::DoGetConfigDirectoryMonolithicDefault(); #endif } -auto CorePlatformApple::GetLocale() -> std::string { -#if BA_XCODE_BUILD - return BallisticaKit::FromCppGetLocaleString(); -#else - return CorePlatform::GetLocale(); -#endif -} - -auto CorePlatformApple::DoGetDeviceName() -> std::string { -#if BA_OSTYPE_MACOS && BA_XCODE_BUILD - return base::AppleUtils::GetDeviceName(); -#else - return CorePlatform::DoGetDeviceName(); -#endif -} - auto CorePlatformApple::DoHasTouchScreen() -> bool { #if BA_OSTYPE_IOS return true; @@ -134,7 +127,7 @@ auto CorePlatformApple::GetDefaultUIScale() -> UIScale { return UIScale::kSmall; } #else - // Default case handles mac & tvos. + // The default case handles mac & tvos. return CorePlatform::GetDefaultUIScale(); #endif } @@ -163,37 +156,37 @@ void CorePlatformApple::EmitPlatformLog(const std::string& name, LogLevel level, auto CorePlatformApple::DoGetDataDirectoryMonolithicDefault() -> std::string { #if BA_XCODE_BUILD - return BallisticaKit::FromCppGetResourcesPath(); + return BallisticaKit::FromCpp::GetResourcesPath(); #else // Fall back to default. return CorePlatform::DoGetDataDirectoryMonolithicDefault(); #endif } -void CorePlatformApple::GetTextBoundsAndWidth(const std::string& text, Rect* r, - float* width) { -#if BA_XCODE_BUILD && !BA_HEADLESS_BUILD - base::AppleUtils::GetTextBoundsAndWidth(text, r, width); -#else - CorePlatform::GetTextBoundsAndWidth(text, r, width); +#if BA_XCODE_BUILD +class TextTextureWrapper_ { + public: + TextTextureWrapper_(int width, int height, + const std::vector& strings, + const std::vector& positions, + const std::vector& widths, float scale) + : data{BallisticaKit::TextTextureData::init(width, height, strings, + positions, widths, scale)} {} + BallisticaKit::TextTextureData data; +}; #endif -} - -void CorePlatformApple::FreeTextTexture(void* tex) { -#if BA_XCODE_BUILD && !BA_HEADLESS_BUILD - base::AppleUtils::FreeTextTexture(tex); -#else - CorePlatform::FreeTextTexture(tex); -#endif -} auto CorePlatformApple::CreateTextTexture( int width, int height, const std::vector& strings, const std::vector& positions, const std::vector& widths, float scale) -> void* { #if BA_XCODE_BUILD && !BA_HEADLESS_BUILD - return base::AppleUtils::CreateTextTexture(width, height, strings, positions, - widths, scale); + auto* wrapper = + new TextTextureWrapper_(width, height, strings, positions, widths, scale); + // wrapper->old = base::AppleUtils::CreateTextTexture(width, height, strings, + // positions, widths, + // scale); + return wrapper; #else return CorePlatform::CreateTextTexture(width, height, strings, positions, widths, scale); @@ -202,12 +195,45 @@ auto CorePlatformApple::CreateTextTexture( auto CorePlatformApple::GetTextTextureData(void* tex) -> uint8_t* { #if BA_XCODE_BUILD && !BA_HEADLESS_BUILD - return base::AppleUtils::GetTextTextureData(tex); + auto* wrapper = static_cast(tex); + return static_cast(wrapper->data.getTextTextureData()); + // return base::AppleUtils::GetTextTextureData(wrapper->old); #else return CorePlatform::GetTextTextureData(tex); #endif } +void CorePlatformApple::GetTextBoundsAndWidth(const std::string& text, Rect* r, + float* width) { +#if BA_XCODE_BUILD && !BA_HEADLESS_BUILD + + auto vals = BallisticaKit::TextTextureData::getTextBoundsAndWidth(text); + assert(vals.getCount() == 5); + r->l = vals[0]; + r->r = vals[1]; + r->b = vals[2]; + r->t = vals[3]; + *width = vals[4]; + +// base::AppleUtils::GetTextBoundsAndWidth(text, r, width); +// printf("GOT BOUNDS l=%.2f r=%.2f b=%.2f t=%.2f w=%.2f\n", r->l, r->r, r->b, +// r->t, *width); printf("SWIFT BOUNDS l=%.2f r=%.2f b=%.2f t=%.2f w=%.2f\n", +// vals[0], vals[1], vals[2], vals[3], vals[4]); +#else + CorePlatform::GetTextBoundsAndWidth(text, r, width); +#endif +} + +void CorePlatformApple::FreeTextTexture(void* tex) { +#if BA_XCODE_BUILD && !BA_HEADLESS_BUILD + auto* wrapper = static_cast(tex); + // base::AppleUtils::FreeTextTexture(wrapper->old); + delete wrapper; +#else + CorePlatform::FreeTextTexture(tex); +#endif +} + void CorePlatformApple::SubmitScore(const std::string& game, const std::string& version, int64_t score) { #if BA_USE_GAME_CENTER @@ -278,15 +304,18 @@ void CorePlatformApple::GameCenterLogin() { auto CorePlatformApple::IsOSPlayingMusic() -> bool { #if BA_XCODE_BUILD - return base::AppleUtils::IsMusicPlaying(); + // FIXME - should look into doing this properly these days, or whether + // this is still needed at all. + return false; + // return base::AppleUtils::IsMusicPlaying(); #else return CorePlatform::IsOSPlayingMusic(); #endif } void CorePlatformApple::OpenFileExternally(const std::string& path) { -#if BA_XCODE_BUILD - base::AppleUtils::EditTextFile(path.c_str()); +#if BA_OSTYPE_MACOS && BA_XCODE_BUILD + BallisticaKit::CocoaFromCpp::OpenFileExternally(path); #else CorePlatform::OpenFileExternally(path); #endif @@ -294,7 +323,7 @@ void CorePlatformApple::OpenFileExternally(const std::string& path) { void CorePlatformApple::OpenDirExternally(const std::string& path) { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - BallisticaKit::CocoaFromCppOpenDirExternally(path); + BallisticaKit::CocoaFromCpp::OpenDirExternally(path); #else CorePlatform::OpenDirExternally(path); #endif diff --git a/src/ballistica/core/platform/apple/core_platform_apple.h b/src/ballistica/core/platform/apple/core_platform_apple.h index 6419215d..93923c0a 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.h +++ b/src/ballistica/core/platform/apple/core_platform_apple.h @@ -21,8 +21,8 @@ class CorePlatformApple : public CorePlatform { auto GenerateUUID() -> std::string override; auto DoGetConfigDirectoryMonolithicDefault() -> std::optional override; - auto GetLocale() -> std::string override; - auto DoGetDeviceName() -> std::string override; + // auto GetLocale() -> std::string override; + // auto DoGetDeviceName() -> std::string override; auto DoHasTouchScreen() -> bool override; auto GetDefaultUIScale() -> UIScale override; auto IsRunningOnDesktop() -> bool override; diff --git a/src/ballistica/core/platform/support/min_sdl.h b/src/ballistica/core/platform/support/min_sdl.h index b827e46d..e20e4010 100644 --- a/src/ballistica/core/platform/support/min_sdl.h +++ b/src/ballistica/core/platform/support/min_sdl.h @@ -328,7 +328,7 @@ typedef enum { #define SDLK_SCANCODE_MASK (1 << 30) #define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK) -enum { +enum SDL_KeycodeEnum { SDLK_UNKNOWN = 0, SDLK_RETURN = '\r', diff --git a/src/ballistica/scene_v1/python/class/python_class_base_timer.cc b/src/ballistica/scene_v1/python/class/python_class_base_timer.cc index 0e095b7a..faa8f8d6 100644 --- a/src/ballistica/scene_v1/python/class/python_class_base_timer.cc +++ b/src/ballistica/scene_v1/python/class/python_class_base_timer.cc @@ -94,7 +94,7 @@ auto PythonClassBaseTimer::tp_new(PyTypeObject* type, PyObject* args, self->timer_id_ = SceneV1Context::Current().NewTimer( TimeType::kBase, static_cast(length * 1000.0), static_cast(repeat), - Object::New(call_obj)); + Object::New(call_obj).Get()); self->have_timer_ = true; return reinterpret_cast(self); diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_timer.cc b/src/ballistica/scene_v1/python/class/python_class_scene_timer.cc index e505b6ad..f9a8c608 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_timer.cc +++ b/src/ballistica/scene_v1/python/class/python_class_scene_timer.cc @@ -100,7 +100,7 @@ auto PythonClassSceneTimer::tp_new(PyTypeObject* type, PyObject* args, self->timer_id_ = SceneV1Context::Current().NewTimer( TimeType::kSim, static_cast(length * 1000.0), static_cast(repeat), - Object::New(call_obj)); + Object::New(call_obj).Get()); self->have_timer_ = true; return reinterpret_cast(self); diff --git a/src/ballistica/scene_v1/python/methods/python_methods_scene.cc b/src/ballistica/scene_v1/python/methods/python_methods_scene.cc index 77b887bb..ab7e2e73 100644 --- a/src/ballistica/scene_v1/python/methods/python_methods_scene.cc +++ b/src/ballistica/scene_v1/python/methods/python_methods_scene.cc @@ -98,7 +98,7 @@ static auto PyTimer(PyObject* self, PyObject* args, PyObject* keywds) SceneV1Context::Current().NewTimer( TimeType::kSim, static_cast(length * 1000.0), static_cast(repeat), - Object::New(call_obj)); + Object::New(call_obj).Get()); Py_RETURN_NONE; BA_PYTHON_CATCH; @@ -207,7 +207,7 @@ static auto PyBaseTimer(PyObject* self, PyObject* args, PyObject* keywds) SceneV1Context::Current().NewTimer( TimeType::kBase, static_cast(length * 1000.0), static_cast(repeat), - Object::New(call_obj)); + Object::New(call_obj).Get()); Py_RETURN_NONE; BA_PYTHON_CATCH; diff --git a/src/ballistica/scene_v1/support/host_activity.cc b/src/ballistica/scene_v1/support/host_activity.cc index b357fbb7..17fe55bd 100644 --- a/src/ballistica/scene_v1/support/host_activity.cc +++ b/src/ballistica/scene_v1/support/host_activity.cc @@ -178,7 +178,7 @@ void HostActivity::Start() { // Create our step timer - gets called whenever scene should step. step_scene_timer_id_ = host_session->NewTimer(TimeType::kBase, kGameStepMilliseconds, true, - NewLambdaRunnable([this] { StepScene(); })); + NewLambdaRunnable([this] { StepScene(); }).Get()); session_base_timer_ids_.push_back(step_scene_timer_id_); UpdateStepTimerLength(); } @@ -363,7 +363,7 @@ auto HostActivity::globals_node() const -> GlobalsNode* { } auto HostActivity::NewSimTimer(millisecs_t length, bool repeat, - const Object::Ref& runnable) -> int { + Runnable* runnable) -> int { if (shutting_down_) { BA_LOG_PYTHON_TRACE_ONCE( "WARNING: Creating game timer during host-activity shutdown"); @@ -384,7 +384,7 @@ auto HostActivity::NewSimTimer(millisecs_t length, bool repeat, } auto HostActivity::NewBaseTimer(millisecs_t length, bool repeat, - const Object::Ref& runnable) -> int { + Runnable* runnable) -> int { if (shutting_down_) { BA_LOG_PYTHON_TRACE_ONCE( "WARNING: Creating session-time timer during host-activity shutdown"); @@ -543,10 +543,10 @@ void HostActivity::DumpFullState(SessionStream* out) { } auto HostActivity::NewTimer(TimeType timetype, TimerMedium length, bool repeat, - const Object::Ref& runnable) -> int { + Runnable* runnable) -> int { // Make sure the runnable passed in is reference-managed already. // (we may not add an initial reference ourself) - assert(runnable.IsValidManagedObject()); + assert(Object::IsValidManagedObject(runnable)); // We currently support game and base timers. switch (timetype) { diff --git a/src/ballistica/scene_v1/support/host_activity.h b/src/ballistica/scene_v1/support/host_activity.h index 5f583ff9..507e75d0 100644 --- a/src/ballistica/scene_v1/support/host_activity.h +++ b/src/ballistica/scene_v1/support/host_activity.h @@ -25,7 +25,7 @@ class HostActivity : public SceneV1Context { // ContextTarget time/timer support. auto NewTimer(TimeType timetype, TimerMedium length, bool repeat, - const Object::Ref& runnable) -> int override; + Runnable* runnable) -> int override; void DeleteTimer(TimeType timetype, int timer_id) override; auto GetTime(TimeType timetype) -> millisecs_t override; @@ -77,11 +77,9 @@ class HostActivity : public SceneV1Context { private: void HandleOutOfBoundsNodes(); - auto NewSimTimer(millisecs_t length, bool repeat, - const Object::Ref& runnable) -> int; + auto NewSimTimer(millisecs_t length, bool repeat, Runnable* runnable) -> int; void DeleteSimTimer(int timer_id); - auto NewBaseTimer(millisecs_t length, bool repeat, - const Object::Ref& runnable) -> int; + auto NewBaseTimer(millisecs_t length, bool repeat, Runnable* runnable) -> int; void DeleteBaseTimer(int timer_id); void UpdateStepTimerLength(); void StepScene(); diff --git a/src/ballistica/scene_v1/support/host_session.cc b/src/ballistica/scene_v1/support/host_session.cc index a5d04506..9c726733 100644 --- a/src/ballistica/scene_v1/support/host_session.cc +++ b/src/ballistica/scene_v1/support/host_session.cc @@ -40,7 +40,7 @@ HostSession::HostSession(PyObject* session_type_obj) // Create a timer to step our session scene. step_scene_timer_ = base_timers_.NewTimer(base_time_millisecs_, kGameStepMilliseconds, 0, -1, - NewLambdaRunnable([this] { StepScene(); })); + NewLambdaRunnable([this] { StepScene(); }).Get()); // Set up our output-stream, which will go to a replay and/or the network. // We don't dump to a replay if we're doing the main menu; that replay @@ -766,8 +766,8 @@ void HostSession::GetCorrectionMessages( } auto HostSession::NewTimer(TimeType timetype, TimerMedium length, bool repeat, - const Object::Ref& runnable) -> int { - assert(runnable.IsValidManagedObject()); + Runnable* runnable) -> int { + assert(Object::IsValidManagedObject(runnable)); // We currently support game and base timers. switch (timetype) { diff --git a/src/ballistica/scene_v1/support/host_session.h b/src/ballistica/scene_v1/support/host_session.h index d17de58d..cf53cccf 100644 --- a/src/ballistica/scene_v1/support/host_session.h +++ b/src/ballistica/scene_v1/support/host_session.h @@ -38,7 +38,7 @@ class HostSession : public Session { // ContextTarget time/timer support auto NewTimer(TimeType timetype, TimerMedium length, bool repeat, - const Object::Ref& runnable) -> int override; + Runnable* runnable) -> int override; void DeleteTimer(TimeType timetype, int timer_id) override; auto GetTime(TimeType timetype) -> millisecs_t override; diff --git a/src/ballistica/scene_v1/support/scene_v1_context.cc b/src/ballistica/scene_v1/support/scene_v1_context.cc index d4f8f9c5..fa3becf2 100644 --- a/src/ballistica/scene_v1/support/scene_v1_context.cc +++ b/src/ballistica/scene_v1/support/scene_v1_context.cc @@ -55,12 +55,10 @@ auto SceneV1Context::GetAsHostActivity() -> HostActivity* { return nullptr; } auto SceneV1Context::GetMutableScene() -> Scene* { return nullptr; } auto SceneV1Context::NewTimer(TimeType timetype, TimerMedium length, - bool repeat, - const Object::Ref& runnable) -> int { + bool repeat, Runnable* runnable) -> int { // Make sure the passed runnable has a ref-count already // (don't want them to rely on us to create initial one). - assert(runnable.Exists()); - assert(Object::IsValidManagedObject(runnable.Get())); + assert(Object::IsValidManagedObject(runnable)); switch (timetype) { case TimeType::kSim: diff --git a/src/ballistica/scene_v1/support/scene_v1_context.h b/src/ballistica/scene_v1/support/scene_v1_context.h index 16414ecd..60e27916 100644 --- a/src/ballistica/scene_v1/support/scene_v1_context.h +++ b/src/ballistica/scene_v1/support/scene_v1_context.h @@ -61,7 +61,7 @@ class SceneV1Context : public base::Context { // Default NewTimer implementation throws a descriptive error, so it can // be useful to fall back on for unsupported cases. virtual auto NewTimer(TimeType timetype, TimerMedium length, bool repeat, - const Object::Ref& runnable) -> int; + Runnable* runnable) -> int; virtual void DeleteTimer(TimeType timetype, int timer_id); virtual auto GetTexture(const std::string& name) -> Object::Ref; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 8a23ce50..747e6a9a 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 = 21491; +const int kEngineBuildNumber = 21510; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/foundation/event_loop.cc b/src/ballistica/shared/foundation/event_loop.cc index 9133557b..f6e9850d 100644 --- a/src/ballistica/shared/foundation/event_loop.cc +++ b/src/ballistica/shared/foundation/event_loop.cc @@ -607,11 +607,11 @@ auto EventLoop::AreEventLoopsSuspended() -> bool { return g_core->event_loops_suspended; } -auto EventLoop::NewTimer(millisecs_t length, bool repeat, - const Object::Ref& runnable) -> Timer* { +auto EventLoop::NewTimer(millisecs_t length, bool repeat, Runnable* runnable) + -> Timer* { assert(g_core); assert(ThreadIsCurrent()); - assert(runnable.Exists()); + assert(Object::IsValidManagedObject(runnable)); return timers_.NewTimer(g_core->GetAppTimeMillisecs(), length, 0, repeat ? -1 : 0, runnable); } diff --git a/src/ballistica/shared/foundation/event_loop.h b/src/ballistica/shared/foundation/event_loop.h index 40f03631..2551b00a 100644 --- a/src/ballistica/shared/foundation/event_loop.h +++ b/src/ballistica/shared/foundation/event_loop.h @@ -56,8 +56,7 @@ class EventLoop { auto identifier() const -> EventLoopID { return identifier_; } // Register a timer to run on the thread. - auto NewTimer(millisecs_t length, bool repeat, - const Object::Ref& runnable) -> Timer*; + auto NewTimer(millisecs_t length, bool repeat, Runnable* runnable) -> Timer*; Timer* GetTimer(int id); void DeleteTimer(int id); diff --git a/src/ballistica/shared/generic/timer_list.cc b/src/ballistica/shared/generic/timer_list.cc index 84dd97f5..7bcf8b27 100644 --- a/src/ballistica/shared/generic/timer_list.cc +++ b/src/ballistica/shared/generic/timer_list.cc @@ -160,10 +160,11 @@ auto TimerList::GetExpiredTimer(TimerMedium target_time) -> Timer* { auto TimerList::NewTimer(TimerMedium current_time, TimerMedium length, TimerMedium offset, int repeat_count, - const Object::Ref& runnable) -> Timer* { + Runnable* runnable) -> Timer* { assert(!are_clearing_); auto* t = new Timer(this, next_timer_id_++, current_time, length, offset, repeat_count); + assert(Object::IsValidManagedObject(runnable)); t->runnable_ = runnable; // Clion (correctly) points out that t may get deallocated in this call, diff --git a/src/ballistica/shared/generic/timer_list.h b/src/ballistica/shared/generic/timer_list.h index 6c0957e2..a954b759 100644 --- a/src/ballistica/shared/generic/timer_list.h +++ b/src/ballistica/shared/generic/timer_list.h @@ -22,8 +22,8 @@ class TimerList { // Create a timer with provided runnable. auto NewTimer(TimerMedium current_time, TimerMedium length, - TimerMedium offset, int repeat_count, - const Object::Ref& runnable) -> Timer*; + TimerMedium offset, int repeat_count, Runnable* runnable) + -> Timer*; // Return a timer by its id, or nullptr if the timer no longer exists. auto GetTimer(int id) -> Timer*; diff --git a/src/ballistica/ui_v1/widget/button_widget.cc b/src/ballistica/ui_v1/widget/button_widget.cc index 25300269..e8ce6a37 100644 --- a/src/ballistica/ui_v1/widget/button_widget.cc +++ b/src/ballistica/ui_v1/widget/button_widget.cc @@ -485,8 +485,8 @@ auto ButtonWidget::HandleMessage(const base::WidgetMessage& m) -> bool { pressed_ = true; if (repeat_) { - repeat_timer_ = - base::NewAppTimer(300, true, [this] { OnRepeatTimerExpired(); }); + repeat_timer_ = base::AppTimer::New( + 300, true, [this] { OnRepeatTimerExpired(); }); // If we're a repeat button we trigger immediately. // (waiting till mouse up sort of defeats the purpose here) diff --git a/src/ballistica/ui_v1/widget/h_scroll_widget.cc b/src/ballistica/ui_v1/widget/h_scroll_widget.cc index d94c89f8..c8d23371 100644 --- a/src/ballistica/ui_v1/widget/h_scroll_widget.cc +++ b/src/ballistica/ui_v1/widget/h_scroll_widget.cc @@ -405,7 +405,7 @@ auto HScrollWidget::HandleMessage(const base::WidgetMessage& m) -> bool { // Top level touches eventually get passed as mouse-downs if no // scrolling has started. if (static_cast(m.type)) { - touch_delay_timer_ = base::NewAppTimer( + touch_delay_timer_ = base::AppTimer::New( 150, false, [this] { OnTouchDelayTimerExpired(); }); } diff --git a/src/ballistica/ui_v1/widget/scroll_widget.cc b/src/ballistica/ui_v1/widget/scroll_widget.cc index 6e83222f..de48022c 100644 --- a/src/ballistica/ui_v1/widget/scroll_widget.cc +++ b/src/ballistica/ui_v1/widget/scroll_widget.cc @@ -330,7 +330,7 @@ auto ScrollWidget::HandleMessage(const base::WidgetMessage& m) -> bool { // After a short delay we go ahead and handle this as a regular // click if it hasn't turned into a scroll or a child scroll. if (!child_is_scrolling_) { - touch_delay_timer_ = base::NewAppTimer( + touch_delay_timer_ = base::AppTimer::New( 150, false, [this] { OnTouchDelayTimerExpired(); }); } } diff --git a/src/ballistica/ui_v1/widget/text_widget.cc b/src/ballistica/ui_v1/widget/text_widget.cc index edeeeaea..f6957b82 100644 --- a/src/ballistica/ui_v1/widget/text_widget.cc +++ b/src/ballistica/ui_v1/widget/text_widget.cc @@ -659,7 +659,6 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool { if (m.has_keysym && !ShouldUseStringEditor_()) { last_carat_change_time_millisecs_ = static_cast(g_base->logic->display_time() * 1000.0); - text_group_dirty_ = true; bool claimed = false; switch (m.keysym.sym) { @@ -724,112 +723,29 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool { break; } if (!claimed) { - // Pop in a char. - if (editable()) { - claimed = true; - - // #if BA_SDL2_BUILD || BA_MINSDL_BUILD - // // On SDL2, chars come through as TEXT_INPUT messages; - // // can ignore this. - // #else - // std::vector unichars = - // Utils::UnicodeFromUTF8(text_raw_, "2jf987"); - // int len = static_cast(unichars.size()); - - // if (len < max_chars_) { - // if ((m.keysym.unicode >= 32) && (m.keysym.sym != SDLK_TAB)) - // { - // claimed = true; - // int pos = carat_position_; - // if (pos > len) pos = len; - // unichars.insert(unichars.begin() + pos, - // m.keysym.unicode); text_raw_ = - // Utils::UTF8FromUnicode(unichars); text_translation_dirty_ - // = true; carat_position_++; - // } else { - // // These don't seem to come through cleanly as unicode: - // // FIXME - should re-check this on SDL2 builds - - // claimed = true; - // std::string s; - // uint32_t pos = carat_position_; - // if (pos > len) pos = len; - // switch (m.keysym.sym) { - // case SDLK_KP0: - // s = '0'; - // break; - // case SDLK_KP1: - // s = '1'; - // break; - // case SDLK_KP2: - // s = '2'; - // break; - // case SDLK_KP3: - // s = '3'; - // break; - // case SDLK_KP4: - // s = '4'; - // break; - // case SDLK_KP5: - // s = '5'; - // break; - // case SDLK_KP6: - // s = '6'; - // break; - // case SDLK_KP7: - // s = '7'; - // break; - // case SDLK_KP8: - // s = '8'; - // break; - // case SDLK_KP9: - // s = '9'; - // break; - // case SDLK_KP_PERIOD: - // s = '.'; - // break; - // case SDLK_KP_DIVIDE: - // s = '/'; - // break; - // case SDLK_KP_MULTIPLY: - // s = '*'; - // break; - // case SDLK_KP_MINUS: - // s = '-'; - // break; - // case SDLK_KP_PLUS: - // s = '+'; - // break; - // case SDLK_KP_EQUALS: - // s = '='; - // break; - // default: - // break; - // } - // if (s.size() > 0) { - // unichars.insert(unichars.begin() + pos, s[0]); - // text_raw_ = Utils::UTF8FromUnicode(unichars); - // text_translation_dirty_ = true; - // carat_position_++; - // } - // } - // } - // #endif // BA_SDL2_BUILD - } + // Direct text edits come through as seperate events, but we still + // want to claim key down events here; otherwise they'll do weird + // stuff like navigate to other widgets. + claimed = true; } return claimed; } switch (m.type) { case base::WidgetMessage::Type::kTextInput: { - // If we're using an edit dialog, any attempted text input just kicks us - // over to that. - if (editable() && ShouldUseStringEditor_()) { - InvokeStringEditor_(); - } else { - // Otherwise apply the text directly. - if (editable() && m.sval != nullptr) { - AddCharsToText_(*m.sval); - return true; + if (editable()) { + if (ShouldUseStringEditor_()) { + // Normally we shouldn't be getting direct text input events in + // situations where we're using string editors, but it still might + // be possible; for instance if a game controller is driving the + // ui when a key is typed. We simply ignore the event in that case + // because otherwise the text input would be fighting with the + // string-editor. + } else { + // Apply text directly. + if (m.sval != nullptr) { + AddCharsToText_(*m.sval); + return true; + } } } break; From f4aec571baedf0912c54630f26cab5ed04e9fb6d Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 26 Oct 2023 10:33:50 -0700 Subject: [PATCH 09/25] controller connect timing tweaks --- .efrocachemap | 40 ++++++++++++++--------------- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/base/input/input.cc | 10 +++++--- src/ballistica/shared/ballistica.cc | 2 +- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index b24be883..bb57bebf 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "c98fdb967f44411171c3d7fde1c74471", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "5514854ae459adab968120a361692cd5", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "83bcfb3af22b61e5c35972d989b3f7f8", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "a63758734d93eb969fe482b56c8d1ed2", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "7e68a605645c70fca06e4f4d5155bb0c", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0598aa59718bb8404c3b007c22123c75", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "9c86d900fc1bc2d6f3bdb4c3e26149da", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "37f5996151f983b45925ad15dce2d0e9", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "b8560855bf772b3e74f2a8f190f54885", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "55c777fa3afd720089223fb949478502", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "81a41ddca9da9060d5d5034a84845674", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "536825d983f4a3bcec018b0295005bdb", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "1733a9610de15f77dd8df3effcca1516", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "f7434d47c371f0baaae676d288847351", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "d16ea39c50f41117697789dafb249200", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "55d18233c5b887af17afcb266a8c5597", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c4df3b76ef890daf48e8181cffd4cd82", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "eb609d02a0897c671e40519faad3365b", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "0c0d303a440e852d0112c3a5aa75ef36", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "bdd6b2c15d6718a6c99ee287d965f022", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "b3aaa8011f040ba38b1abcff978e3c85", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "f5623a29f71cf5363ff72fe4436340b1", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9f5ec716df130f92e9b055e9fca4bbc8", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "327f6b0da02ecf72006ff88dd37b31ac", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "ede687d69269225dc788851fc4515ccf", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "16029a78e585822f78fe4619beba456c", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8f091556ac938da89cab226d9bb59dec", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "08ea82e016ce2d7ac8d687a795e7a179", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "91d4f5cb9b13eb6f2964187fd7ff9cc5", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "ed93c1d02f14dc147d2d84c8f919568c", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "5e3eb1b9195fcbf3ec477392b15bff23", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "b6cf7d6cf47f8bbf1b3c4f28ba9c7854", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f044e3d1d94751272c02f864ddafbe6b", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "aa56b6e21eb82ca8af11a248bde876d1", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "4ee8ff4b9d37bbc3d7a7db73168f8888", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "dc62f105598c866680a0fd150b83ea0a", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "a04e0837368e5eae80ec084a898b79d8", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "cd5b75cfa4cf0bfd478092ef812006c4", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "4decefaeffa74fb89f39834960c8fd5f", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "73087f5f43a6e9d4b10529824d671d6b", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "c9ef036408f0832cd068a34365485e0b", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249", diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d37890f..829ff616 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21510, api 8, 2023-10-26) +### 1.7.28 (build 21512, api 8, 2023-10-26) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index d2bc7bfe..1c6f98c8 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21510 +TARGET_BALLISTICA_BUILD = 21512 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index dfca9fd0..e1a591da 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -155,11 +155,13 @@ void Input::CreateTouchInput() { } void Input::AnnounceConnects_() { + assert(g_base->InLogicThread()); + static bool first_print = true; // For the first announcement just say "X controllers detected" and don't // have a sound. - if (first_print && g_core->GetAppTimeSeconds() < 2.0) { + if (first_print && g_core->GetAppTimeSeconds() < 3.0) { first_print = false; // Disabling this completely on Android for now; we often get large @@ -237,12 +239,14 @@ void Input::ShowStandardInputDeviceConnectedMessage_(InputDevice* j) { } newly_connected_controllers_.push_back(j->GetDeviceName() + suffix); - // Set a timer to go off and announce the accumulated additions. + // Set a timer to go off and announce controller additions. This allows + // several connecting at (almost) the same time to be announced as a + // single event. if (connect_print_timer_id_ != 0) { g_base->logic->DeleteAppTimer(connect_print_timer_id_); } connect_print_timer_id_ = g_base->logic->NewAppTimer( - 250, false, NewLambdaRunnable([this] { AnnounceConnects_(); }).Get()); + 500, false, NewLambdaRunnable([this] { AnnounceConnects_(); }).Get()); } void Input::ShowStandardInputDeviceDisconnectedMessage_(InputDevice* j) { diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 747e6a9a..d34c69ce 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 = 21510; +const int kEngineBuildNumber = 21512; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; From f0ebe2bce83c378df166957028a706864a065618 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 26 Oct 2023 12:58:01 -0700 Subject: [PATCH 10/25] cleaned up clipboard support --- .efrocachemap | 56 ++++++------ CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- .../python/bauiv1lib/gather/privatetab.py | 4 +- .../ba_data/python/bauiv1lib/mainmenu.py | 2 +- .../base/app_adapter/app_adapter.cc | 54 ++++++++++++ src/ballistica/base/app_adapter/app_adapter.h | 26 +++++- .../base/app_adapter/app_adapter_apple.cc | 37 ++++++++ .../base/app_adapter/app_adapter_apple.h | 4 + .../base/app_adapter/app_adapter_sdl.cc | 22 +++++ .../base/app_adapter/app_adapter_sdl.h | 4 + src/ballistica/base/input/input.cc | 9 ++ src/ballistica/base/platform/base_platform.h | 3 +- .../python/methods/python_methods_misc.cc | 9 +- .../platform/apple/core_platform_apple.cc | 32 ------- .../core/platform/apple/core_platform_apple.h | 6 -- src/ballistica/core/platform/core_platform.cc | 86 ------------------- src/ballistica/core/platform/core_platform.h | 39 ++------- src/ballistica/shared/ballistica.cc | 2 +- src/ballistica/ui_v1/widget/text_widget.cc | 7 +- 20 files changed, 207 insertions(+), 199 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index bb57bebf..374386c9 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "b3aaa8011f040ba38b1abcff978e3c85", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "f5623a29f71cf5363ff72fe4436340b1", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9f5ec716df130f92e9b055e9fca4bbc8", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "327f6b0da02ecf72006ff88dd37b31ac", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "ede687d69269225dc788851fc4515ccf", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "16029a78e585822f78fe4619beba456c", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8f091556ac938da89cab226d9bb59dec", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "08ea82e016ce2d7ac8d687a795e7a179", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "91d4f5cb9b13eb6f2964187fd7ff9cc5", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "ed93c1d02f14dc147d2d84c8f919568c", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "5e3eb1b9195fcbf3ec477392b15bff23", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "b6cf7d6cf47f8bbf1b3c4f28ba9c7854", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f044e3d1d94751272c02f864ddafbe6b", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "aa56b6e21eb82ca8af11a248bde876d1", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "4ee8ff4b9d37bbc3d7a7db73168f8888", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "dc62f105598c866680a0fd150b83ea0a", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "a04e0837368e5eae80ec084a898b79d8", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "cd5b75cfa4cf0bfd478092ef812006c4", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "4decefaeffa74fb89f39834960c8fd5f", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "73087f5f43a6e9d4b10529824d671d6b", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "671499f10be5561b64b7c1e8551f71bc", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "8834461aaef9d915828b460426bb16b6", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9be5746f3cdb8fdbeb01c3fba0f3cd04", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "1a4e1fb4230ffe937bc11890943bab67", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "809fd63da80c54076100f18c8cde6ba8", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "bb3574370f0d601abb9443dc2285689b", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2b1d99684649040257bfe95b0c5a21d9", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "3a4eaac355dc1ed691aa946f9470fd80", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0cdebb143458f5248efb0227e875d5d4", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "a4eae535e631ac6d0aaa3fa9203656cf", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d2dcb9d5f1201e98ba83b547fb7a317e", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6cf3c416280b71e5b16516cfb063b198", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "a01e3ef9ec790c0bc385995e598c18dd", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "427e518fd557950c4f8fec0b8fca3c86", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b6a2f1c128e3b1c035eff76f38100566", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "deb872ab495ab8e713ba564b7bc4f169", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c647c1e19b2c3a2bee028ef8215945d5", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "ce133f1e838b8b6d3b9b4fd7c516d5d8", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "f41eb8f74e5cf7a36cc8bbda1eef1933", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "00ae0c9d9351140edc42ed18b719a2bf", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "c9ef036408f0832cd068a34365485e0b", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "2b57cf28eeadf43d09b1d780a5db1423", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "3314d791a9ab37ea81be824460c63d14", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "2b57cf28eeadf43d09b1d780a5db1423", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "bd63402d48fce829f16d59c6c1f87977", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "de24c4e6f661f6201b933af3343084cc", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "84904f537e435d09c06b4b6c10abea7d", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "22a32d161e85baa6c6459412a368bf82", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "f43972d496e1953fdc30ff094a22a0d1", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c069093fb4773f3feac13236d474ecf1", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4d745c03bbeab02c5f69bed1ae376933", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "c1e1321bb0d5bb74211377e0f5cae45c", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "eda80e0bcb2332fb400e4487aa821fda", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "ae70908e8821b275a7c62541288761c3", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4dcc80f1087a342df7f0e13225c6a0d8", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "e83c284f0ee5c9bf9e02bdd5e83de604", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "92bbe105f7bbff92ebe621710bb13629", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "f3c9b10ab0dbc35214b20c3323255ea1", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "df9efe46d688a585157edfe5d3b9e912", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "3c76a27db96c7c277682430ec980d9ce", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index 829ff616..c69fd5fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21512, api 8, 2023-10-26) +### 1.7.28 (build 21516, api 8, 2023-10-26) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 1c6f98c8..e58e986c 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21512 +TARGET_BALLISTICA_BUILD = 21516 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py index 1cf4e43a..952b862c 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py @@ -458,9 +458,9 @@ class PrivateGatherTab(GatherTab): scale=1.5, size=(300, 50), editable=True, + max_chars=20, description=bui.Lstr(resource='gatherWindow.partyCodeText'), autoselect=True, - maxwidth=250, h_align='left', v_align='center', text='', @@ -962,7 +962,7 @@ class PrivateGatherTab(GatherTab): code = cast(str, bui.textwidget(query=self._join_party_code_text)) if not code: bui.screenmessage( - bui.Lstr(resource='internal.invalidAddressErrorText'), + bui.Lstr(translate=('serverResponses', 'Invalid code.')), color=(1, 0, 0), ) bui.getsound('error').play() diff --git a/src/assets/ba_data/python/bauiv1lib/mainmenu.py b/src/assets/ba_data/python/bauiv1lib/mainmenu.py index d1a00332..cacb3fdf 100644 --- a/src/assets/ba_data/python/bauiv1lib/mainmenu.py +++ b/src/assets/ba_data/python/bauiv1lib/mainmenu.py @@ -1318,7 +1318,7 @@ class MainMenuWindow(bui.Window): bui.app.classic.resume() if self._root_widget: bui.containerwidget(edit=self._root_widget, transition='out_right') - bui.app.ui_v1.clear_main_menu_window() + bui.app.ui_v1.clear_main_menu_window(transition='out_right') # If there's callbacks waiting for this window to go away, call them. for call in bui.app.ui_v1.main_menu_resume_callbacks: diff --git a/src/ballistica/base/app_adapter/app_adapter.cc b/src/ballistica/base/app_adapter/app_adapter.cc index ee84b319..bb89794f 100644 --- a/src/ballistica/base/app_adapter/app_adapter.cc +++ b/src/ballistica/base/app_adapter/app_adapter.cc @@ -318,4 +318,58 @@ auto AppAdapter::GetGraphicsClientContext() -> GraphicsClientContext* { auto AppAdapter::GetKeyRepeatDelay() -> float { return 0.3f; } auto AppAdapter::GetKeyRepeatInterval() -> float { return 0.08f; } +auto AppAdapter::ClipboardIsSupported() -> bool { + // We only call our actual virtual function once. + if (!have_clipboard_is_supported_) { + clipboard_is_supported_ = DoClipboardIsSupported(); + have_clipboard_is_supported_ = true; + } + return clipboard_is_supported_; +} + +auto AppAdapter::ClipboardHasText() -> bool { + // If subplatform says they don't support clipboards, don't even ask. + if (!ClipboardIsSupported()) { + return false; + } + return DoClipboardHasText(); +} + +void AppAdapter::ClipboardSetText(const std::string& text) { + // If subplatform says they don't support clipboards, this is an error. + if (!ClipboardIsSupported()) { + throw Exception("ClipboardSetText called with no clipboard support.", + PyExcType::kRuntime); + } + DoClipboardSetText(text); +} + +auto AppAdapter::ClipboardGetText() -> std::string { + // If subplatform says they don't support clipboards, this is an error. + if (!ClipboardIsSupported()) { + throw Exception("ClipboardGetText called with no clipboard support.", + PyExcType::kRuntime); + } + return DoClipboardGetText(); +} + +auto AppAdapter::DoClipboardIsSupported() -> bool { return false; } + +auto AppAdapter::DoClipboardHasText() -> bool { + // Shouldn't get here since we default to no clipboard support. + FatalError("Shouldn't get here."); + return false; +} + +void AppAdapter::DoClipboardSetText(const std::string& text) { + // Shouldn't get here since we default to no clipboard support. + FatalError("Shouldn't get here."); +} + +auto AppAdapter::DoClipboardGetText() -> std::string { + // Shouldn't get here since we default to no clipboard support. + FatalError("Shouldn't get here."); + return ""; +} + } // namespace ballistica::base diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index 829c236d..e32864bb 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -207,6 +207,22 @@ class AppAdapter { virtual auto GetKeyRepeatDelay() -> float; virtual auto GetKeyRepeatInterval() -> float; + /// Return whether clipboard operations are supported at all. This gets + /// called when determining whether to display clipboard related UI + /// elements/etc. + auto ClipboardIsSupported() -> bool; + + /// Return whether there is currently text on the clipboard. + auto ClipboardHasText() -> bool; + + /// Set current clipboard text. Raises an Exception if clipboard is + /// unsupported. + void ClipboardSetText(const std::string& text); + + /// Return current text from the clipboard. Raises an Exception if + /// clipboard is unsupported or if there's no text on the clipboard. + auto ClipboardGetText() -> std::string; + protected: AppAdapter(); virtual ~AppAdapter(); @@ -219,10 +235,18 @@ class AppAdapter { /// context. By default this is simply the main thread. virtual void DoPushGraphicsContextRunnable(Runnable* runnable); + virtual auto DoClipboardIsSupported() -> bool; + virtual auto DoClipboardHasText() -> bool; + virtual void DoClipboardSetText(const std::string& text); + virtual auto DoClipboardGetText() -> std::string; + private: void OnAppSuspend_(); void OnAppUnsuspend_(); - bool app_suspended_{}; + + bool app_suspended_ : 1 {}; + bool have_clipboard_is_supported_ : 1 {}; + bool clipboard_is_supported_ : 1 {}; }; } // namespace ballistica::base diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.cc b/src/ballistica/base/app_adapter/app_adapter_apple.cc index 737b89bf..17ac5c8a 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -7,6 +7,7 @@ #include "ballistica/base/graphics/graphics.h" #include "ballistica/base/graphics/graphics_server.h" #include "ballistica/base/logic/logic.h" +#include "ballistica/base/platform/apple/apple_utils.h" #include "ballistica/base/platform/apple/from_swift.h" #include "ballistica/base/support/app_config.h" #include "ballistica/shared/ballistica.h" @@ -245,6 +246,42 @@ auto AppAdapterApple::GetKeyRepeatInterval() -> float { #endif } +auto AppAdapterApple::DoClipboardIsSupported() -> bool { +#if BA_XCODE_BUILD + return BallisticaKit::CocoaFromCpp::ClipboardIsSupported(); +#else + return CorePlatform::DoClipboardIsSupported(); +#endif +} + +auto AppAdapterApple::DoClipboardHasText() -> bool { +#if BA_XCODE_BUILD + return BallisticaKit::CocoaFromCpp::ClipboardHasText(); +#else + return CorePlatform::DoClipboardHasText(); +#endif +} + +void AppAdapterApple::DoClipboardSetText(const std::string& text) { +#if BA_XCODE_BUILD + BallisticaKit::CocoaFromCpp::ClipboardSetText(text); +#else + CorePlatform::DoClipboardSetText(text); +#endif +} + +auto AppAdapterApple::DoClipboardGetText() -> std::string { +#if BA_XCODE_BUILD + auto contents = BallisticaKit::CocoaFromCpp::ClipboardGetText(); + if (contents) { + return std::string(contents.get()); + } + throw Exception("No text on clipboard."); +#else + return CorePlatform::DoClipboardGetText(); +#endif +} + } // namespace ballistica::base #endif // BA_XCODE_BUILD diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.h b/src/ballistica/base/app_adapter/app_adapter_apple.h index d1c9823d..c86f081f 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.h +++ b/src/ballistica/base/app_adapter/app_adapter_apple.h @@ -53,6 +53,10 @@ class AppAdapterApple : public AppAdapter { void SetHardwareCursorVisible(bool visible) override; void TerminateApp() override; void ApplyGraphicsSettings(const GraphicsSettings* settings) override; + auto DoClipboardIsSupported() -> bool override; + auto DoClipboardHasText() -> bool override; + void DoClipboardSetText(const std::string& text) override; + auto DoClipboardGetText() -> std::string override; private: class ScopedAllowGraphics_; diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.cc b/src/ballistica/base/app_adapter/app_adapter_sdl.cc index 6def0c9f..3d7e8ca0 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -834,6 +834,28 @@ auto AppAdapterSDL::HasDirectKeyboardInput() -> bool { return true; } +auto AppAdapterSDL::DoClipboardIsSupported() -> bool { return true; } + +auto AppAdapterSDL::DoClipboardHasText() -> bool { + return SDL_HasClipboardText(); +} + +void AppAdapterSDL::DoClipboardSetText(const std::string& text) { + SDL_SetClipboardText(text.c_str()); +} + +auto AppAdapterSDL::DoClipboardGetText() -> std::string { + // Go through SDL functionality on SDL based platforms; + // otherwise default to no clipboard. + char* out = SDL_GetClipboardText(); + if (out == nullptr) { + throw Exception("Error fetching clipboard contents.", PyExcType::kRuntime); + } + std::string out_s{out}; + SDL_free(out); + return out_s; +} + } // namespace ballistica::base #endif // BA_SDL_BUILD diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.h b/src/ballistica/base/app_adapter/app_adapter_sdl.h index 585c29f1..49be24f7 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.h +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.h @@ -52,6 +52,10 @@ class AppAdapterSDL : public AppAdapter { auto InGraphicsContext() -> bool override; void DoPushGraphicsContextRunnable(Runnable* runnable) override; void CursorPositionForDraw(float* x, float* y) override; + auto DoClipboardIsSupported() -> bool override; + auto DoClipboardHasText() -> bool override; + void DoClipboardSetText(const std::string& text) override; + auto DoClipboardGetText() -> std::string override; private: class ScopedAllowGraphics_; diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index e1a591da..bbde01f1 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -829,6 +829,15 @@ void Input::PushTextInputEvent(const std::string& text) { return; } + // Also ignore if there are any mod keys being held. + // We process some of our own keyboard shortcuts and don't + // want text input to come through at the same time. + if (keys_held_.contains(SDLK_LCTRL) || keys_held_.contains(SDLK_RCTRL) + || keys_held_.contains(SDLK_LALT) || keys_held_.contains(SDLK_RALT) + || keys_held_.contains(SDLK_LGUI) || keys_held_.contains(SDLK_RGUI)) { + return; + } + // We try to handle char filtering here (to keep it consistent across // platforms) but make a stink if they sent us something that we can't // at least translate to unicode. diff --git a/src/ballistica/base/platform/base_platform.h b/src/ballistica/base/platform/base_platform.h index 82f38679..85d19b39 100644 --- a/src/ballistica/base/platform/base_platform.h +++ b/src/ballistica/base/platform/base_platform.h @@ -71,6 +71,7 @@ class BasePlatform { /// active/inactive. virtual void LoginAdapterBackEndActiveChange(const std::string& login_type, bool active); + #pragma mark MISC -------------------------------------------------------------- /// Do we define a platform-specific string editor? This is something like @@ -115,8 +116,8 @@ class BasePlatform { /// class versions can go here. virtual void PostInit(); + bool ran_base_post_init_ : 1 {}; PythonRef string_edit_adapter_{}; - bool ran_base_post_init_{}; std::string public_device_uuid_; }; diff --git a/src/ballistica/base/python/methods/python_methods_misc.cc b/src/ballistica/base/python/methods/python_methods_misc.cc index b7d1f2a9..e6391281 100644 --- a/src/ballistica/base/python/methods/python_methods_misc.cc +++ b/src/ballistica/base/python/methods/python_methods_misc.cc @@ -5,6 +5,7 @@ #include #include +#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/assets/sound_asset.h" #include "ballistica/base/input/input.h" #include "ballistica/base/platform/base_platform.h" @@ -128,7 +129,7 @@ static PyMethodDef PyHasTouchScreenDef = { static auto PyClipboardIsSupported(PyObject* self) -> PyObject* { BA_PYTHON_TRY; - if (g_core->platform->ClipboardIsSupported()) { + if (g_base->app_adapter->ClipboardIsSupported()) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -154,7 +155,7 @@ static PyMethodDef PyClipboardIsSupportedDef = { static auto PyClipboardHasText(PyObject* self) -> PyObject* { BA_PYTHON_TRY; - if (g_core->platform->ClipboardHasText()) { + if (g_base->app_adapter->ClipboardHasText()) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -187,7 +188,7 @@ static auto PyClipboardSetText(PyObject* self, PyObject* args, PyObject* keywds) const_cast(kwlist), &value)) { return nullptr; } - g_core->platform->ClipboardSetText(value); + g_base->app_adapter->ClipboardSetText(value); Py_RETURN_NONE; BA_PYTHON_CATCH; } @@ -211,7 +212,7 @@ static PyMethodDef PyClipboardSetTextDef = { static auto PyClipboardGetText(PyObject* self) -> PyObject* { BA_PYTHON_TRY; - return PyUnicode_FromString(g_core->platform->ClipboardGetText().c_str()); + return PyUnicode_FromString(g_base->app_adapter->ClipboardGetText().c_str()); Py_RETURN_FALSE; BA_PYTHON_CATCH; } diff --git a/src/ballistica/core/platform/apple/core_platform_apple.cc b/src/ballistica/core/platform/apple/core_platform_apple.cc index c864f3ad..ac64502f 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.cc +++ b/src/ballistica/core/platform/apple/core_platform_apple.cc @@ -400,38 +400,6 @@ auto CorePlatformApple::GetSubplatformName() -> std::string { #endif } -auto CorePlatformApple::DoClipboardIsSupported() -> bool { -#if BA_XCODE_BUILD - return base::AppleUtils::ClipboardIsSupported(); -#else - return CorePlatform::DoClipboardIsSupported(); -#endif -} - -auto CorePlatformApple::DoClipboardHasText() -> bool { -#if BA_XCODE_BUILD - return base::AppleUtils::ClipboardHasText(); -#else - return CorePlatform::DoClipboardHasText(); -#endif -} - -void CorePlatformApple::DoClipboardSetText(const std::string& text) { -#if BA_XCODE_BUILD - base::AppleUtils::ClipboardSetText(text); -#else - CorePlatform::DoClipboardSetText(text); -#endif -} - -auto CorePlatformApple::DoClipboardGetText() -> std::string { -#if BA_XCODE_BUILD - return base::AppleUtils::ClipboardGetText(); -#else - return CorePlatform::DoClipboardGetText(); -#endif -} - } // namespace ballistica::core #endif // BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS diff --git a/src/ballistica/core/platform/apple/core_platform_apple.h b/src/ballistica/core/platform/apple/core_platform_apple.h index 93923c0a..215cb74a 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.h +++ b/src/ballistica/core/platform/apple/core_platform_apple.h @@ -21,8 +21,6 @@ class CorePlatformApple : public CorePlatform { auto GenerateUUID() -> std::string override; auto DoGetConfigDirectoryMonolithicDefault() -> std::optional override; - // auto GetLocale() -> std::string override; - // auto DoGetDeviceName() -> std::string override; auto DoHasTouchScreen() -> bool override; auto GetDefaultUIScale() -> UIScale override; auto IsRunningOnDesktop() -> bool override; @@ -61,10 +59,6 @@ class CorePlatformApple : public CorePlatform { auto GetPlatformName() -> std::string override; auto GetSubplatformName() -> std::string override; - auto DoClipboardIsSupported() -> bool override; - auto DoClipboardHasText() -> bool override; - void DoClipboardSetText(const std::string& text) override; - auto DoClipboardGetText() -> std::string override; auto GetDeviceUUIDInputs() -> std::list override; protected: diff --git a/src/ballistica/core/platform/core_platform.cc b/src/ballistica/core/platform/core_platform.cc index 35a9e4e1..92973146 100644 --- a/src/ballistica/core/platform/core_platform.cc +++ b/src/ballistica/core/platform/core_platform.cc @@ -1053,92 +1053,6 @@ auto CorePlatform::GetCurrentWholeSeconds() -> int64_t { .count(); } -auto CorePlatform::ClipboardIsSupported() -> bool { - // We only call our actual virtual function once. - if (!have_clipboard_is_supported_) { - clipboard_is_supported_ = DoClipboardIsSupported(); - have_clipboard_is_supported_ = true; - } - return clipboard_is_supported_; -} - -auto CorePlatform::ClipboardHasText() -> bool { - // If subplatform says they don't support clipboards, don't even ask. - if (!ClipboardIsSupported()) { - return false; - } - return DoClipboardHasText(); -} - -void CorePlatform::ClipboardSetText(const std::string& text) { - // If subplatform says they don't support clipboards, this is an error. - if (!ClipboardIsSupported()) { - throw Exception("ClipboardSetText called with no clipboard support.", - PyExcType::kRuntime); - } - DoClipboardSetText(text); -} - -auto CorePlatform::ClipboardGetText() -> std::string { - // If subplatform says they don't support clipboards, this is an error. - if (!ClipboardIsSupported()) { - throw Exception("ClipboardGetText called with no clipboard support.", - PyExcType::kRuntime); - } - return DoClipboardGetText(); -} - -auto CorePlatform::DoClipboardIsSupported() -> bool { - // Go through SDL functionality on SDL based platforms; - // otherwise default to no clipboard. -#if BA_SDL_BUILD - return true; -#else - return false; -#endif -} - -auto CorePlatform::DoClipboardHasText() -> bool { - // Go through SDL functionality on SDL based platforms; - // otherwise default to no clipboard. -#if BA_SDL_BUILD - return SDL_HasClipboardText(); -#else - // Shouldn't get here since we default to no clipboard support. - FatalError("Shouldn't get here."); - return false; -#endif -} - -void CorePlatform::DoClipboardSetText(const std::string& text) { - // Go through SDL functionality on SDL based platforms; - // otherwise default to no clipboard. -#if BA_SDL_BUILD - SDL_SetClipboardText(text.c_str()); -#else - // Shouldn't get here since we default to no clipboard support. - FatalError("Shouldn't get here."); -#endif -} - -auto CorePlatform::DoClipboardGetText() -> std::string { - // Go through SDL functionality on SDL based platforms; - // otherwise default to no clipboard. -#if BA_SDL_BUILD - char* out = SDL_GetClipboardText(); - if (out == nullptr) { - throw Exception("Error fetching clipboard contents.", PyExcType::kRuntime); - } - std::string out_s{out}; - SDL_free(out); - return out_s; -#else - // Shouldn't get here since we default to no clipboard support. - FatalError("Shouldn't get here."); - return ""; -#endif -} - auto CorePlatform::System(const char* cmd) -> int { // By default can support this everywhere outside of Apple's more // sandboxed platforms (iOS and equivalent). Actually should check diff --git a/src/ballistica/core/platform/core_platform.h b/src/ballistica/core/platform/core_platform.h index 23fd4fae..b3890170 100644 --- a/src/ballistica/core/platform/core_platform.h +++ b/src/ballistica/core/platform/core_platform.h @@ -76,24 +76,6 @@ class CorePlatform { /// requires the path to already exist. auto AbsPath(const std::string& path, std::string* outpath) -> bool; -#pragma mark CLIPBOARD --------------------------------------------------------- - - /// Return whether clipboard operations are supported at all. This gets - /// called when determining whether to display clipboard related UI - /// elements/etc. - auto ClipboardIsSupported() -> bool; - - /// Return whether there is currently text on the clipboard. - auto ClipboardHasText() -> bool; - - /// Set current clipboard text. Raises an Exception if clipboard is - /// unsupported. - void ClipboardSetText(const std::string& text); - - /// Return current text from the clipboard. Raises an Exception if - /// clipboard is unsupported or if there's no text on the clipboard. - auto ClipboardGetText() -> std::string; - #pragma mark PRINTING/LOGGING -------------------------------------------------- /// Display a message to any default log for the platform (android log, @@ -456,11 +438,6 @@ class CorePlatform { /// Generate a random UUID string. virtual auto GenerateUUID() -> std::string; - virtual auto DoClipboardIsSupported() -> bool; - virtual auto DoClipboardHasText() -> bool; - virtual void DoClipboardSetText(const std::string& text); - virtual auto DoClipboardGetText() -> std::string; - /// Print a log message to be included in crash logs or other debug /// mechanisms (example: Crashlytics). V1-cloud-log messages get forwarded /// to here as well. It can be useful to call this directly to report extra @@ -473,15 +450,13 @@ class CorePlatform { virtual ~CorePlatform(); private: - bool is_stdin_a_terminal_{}; - bool have_has_touchscreen_value_{}; - bool have_touchscreen_{}; - bool is_tegra_k1_{}; - bool have_clipboard_is_supported_{}; - bool clipboard_is_supported_{}; - bool made_volatile_data_dir_{}; - bool have_device_uuid_{}; - bool ran_base_post_init_{}; + bool is_stdin_a_terminal_ : 1 {}; + bool have_has_touchscreen_value_ : 1 {}; + bool have_touchscreen_ : 1 {}; + bool is_tegra_k1_ : 1 {}; + bool made_volatile_data_dir_ : 1 {}; + bool have_device_uuid_ : 1 {}; + bool ran_base_post_init_ : 1 {}; millisecs_t start_time_millisecs_{}; std::string device_name_; std::string legacy_device_uuid_; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index d34c69ce..047ad453 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 = 21512; +const int kEngineBuildNumber = 21516; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/ui_v1/widget/text_widget.cc b/src/ballistica/ui_v1/widget/text_widget.cc index f6957b82..c6b02019 100644 --- a/src/ballistica/ui_v1/widget/text_widget.cc +++ b/src/ballistica/ui_v1/widget/text_widget.cc @@ -2,6 +2,7 @@ #include "ballistica/ui_v1/widget/text_widget.h" +#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/audio/audio.h" #include "ballistica/base/graphics/component/empty_component.h" #include "ballistica/base/graphics/component/simple_component.h" @@ -648,10 +649,10 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool { // If we're doing inline editing, handle clipboard paste. if (editable() && !ShouldUseStringEditor_() && m.type == base::WidgetMessage::Type::kPaste) { - if (g_core->platform->ClipboardIsSupported()) { - if (g_core->platform->ClipboardHasText()) { + if (g_base->app_adapter->ClipboardIsSupported()) { + if (g_base->app_adapter->ClipboardHasText()) { // Just enter it char by char as if we had typed it... - AddCharsToText_(g_core->platform->ClipboardGetText()); + AddCharsToText_(g_base->app_adapter->ClipboardGetText()); } } } From 11212bfb521d753a7201c30cbb2b910493596f9d Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 26 Oct 2023 19:50:46 -0700 Subject: [PATCH 11/25] lots of dev console terminal improvements --- .efrocachemap | 88 ++-- CHANGELOG.md | 5 +- ballisticakit-cmake/CMakeLists.txt | 2 + .../Generic/BallisticaKitGeneric.vcxproj | 2 + .../BallisticaKitGeneric.vcxproj.filters | 6 + .../Headless/BallisticaKitHeadless.vcxproj | 2 + .../BallisticaKitHeadless.vcxproj.filters | 6 + src/assets/ba_data/python/baenv.py | 2 +- .../base/app_adapter/app_adapter.cc | 47 -- src/ballistica/base/app_adapter/app_adapter.h | 4 +- .../base/app_adapter/app_adapter_apple.cc | 16 +- .../base/app_adapter/app_adapter_sdl.cc | 20 +- src/ballistica/base/assets/assets_server.cc | 1 - src/ballistica/base/base.cc | 8 +- src/ballistica/base/graphics/graphics.cc | 122 ++--- src/ballistica/base/graphics/graphics.h | 4 +- .../base/graphics/mesh/nine_patch_mesh.h | 2 +- .../graphics/support/graphics_settings.cc | 1 - src/ballistica/base/input/input.cc | 41 +- src/ballistica/base/platform/base_platform.cc | 65 --- src/ballistica/base/platform/base_platform.h | 16 +- .../base/support/base_build_switches.cc | 120 +++++ .../base/support/base_build_switches.h | 20 + src/ballistica/base/support/repeater.cc | 1 - src/ballistica/base/ui/dev_console.cc | 434 ++++++++++++++---- src/ballistica/base/ui/dev_console.h | 22 +- src/ballistica/scene_v1/node/flag_node.cc | 1 - .../scene_v1/support/scene_v1_app_mode.cc | 1 - src/ballistica/shared/ballistica.cc | 2 +- src/ballistica/shared/foundation/object.h | 21 +- src/ballistica/ui_v1/python/ui_v1_python.cc | 1 - src/ballistica/ui_v1/ui_v1.cc | 2 - 32 files changed, 710 insertions(+), 375 deletions(-) create mode 100644 src/ballistica/base/support/base_build_switches.cc create mode 100644 src/ballistica/base/support/base_build_switches.h diff --git a/.efrocachemap b/.efrocachemap index 374386c9..5d375637 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,50 +4056,50 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "671499f10be5561b64b7c1e8551f71bc", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "8834461aaef9d915828b460426bb16b6", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9be5746f3cdb8fdbeb01c3fba0f3cd04", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "1a4e1fb4230ffe937bc11890943bab67", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "809fd63da80c54076100f18c8cde6ba8", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "bb3574370f0d601abb9443dc2285689b", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2b1d99684649040257bfe95b0c5a21d9", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "3a4eaac355dc1ed691aa946f9470fd80", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0cdebb143458f5248efb0227e875d5d4", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "a4eae535e631ac6d0aaa3fa9203656cf", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d2dcb9d5f1201e98ba83b547fb7a317e", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6cf3c416280b71e5b16516cfb063b198", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "a01e3ef9ec790c0bc385995e598c18dd", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "427e518fd557950c4f8fec0b8fca3c86", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b6a2f1c128e3b1c035eff76f38100566", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "deb872ab495ab8e713ba564b7bc4f169", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c647c1e19b2c3a2bee028ef8215945d5", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "ce133f1e838b8b6d3b9b4fd7c516d5d8", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "f41eb8f74e5cf7a36cc8bbda1eef1933", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "00ae0c9d9351140edc42ed18b719a2bf", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "c9ef036408f0832cd068a34365485e0b", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "becf7a70c7c0d7bb5bfe731dde5e0249", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "c9ef036408f0832cd068a34365485e0b", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "5bd8bcd68e03939501d192b7cda55d64", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "a8545c0c985eef9219c351773c5c6127", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "5bd8bcd68e03939501d192b7cda55d64", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "a8545c0c985eef9219c351773c5c6127", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "1e2c088713c47ff47d9aa312ebb0bd1a", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "e6bbe6c564c65cb498edc58daec1e084", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "1e2c088713c47ff47d9aa312ebb0bd1a", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "e6bbe6c564c65cb498edc58daec1e084", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "98df65aba607e74eb5c0c7305903ac29", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "2b57cf28eeadf43d09b1d780a5db1423", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "3314d791a9ab37ea81be824460c63d14", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "2b57cf28eeadf43d09b1d780a5db1423", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "eda80e0bcb2332fb400e4487aa821fda", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "ae70908e8821b275a7c62541288761c3", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4dcc80f1087a342df7f0e13225c6a0d8", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "e83c284f0ee5c9bf9e02bdd5e83de604", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "92bbe105f7bbff92ebe621710bb13629", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "f3c9b10ab0dbc35214b20c3323255ea1", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "df9efe46d688a585157edfe5d3b9e912", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "3c76a27db96c7c277682430ec980d9ce", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6e54cc75974a155e910b1095f8f559a8", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "d097531acccd231becb2a2b5bb1d2f23", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "35b551aae90a7d75f75237db93544279", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "d6081f21ed1100f44aeb4c36f7d28680", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "1d181331c45918c6d7e71630430aa011", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "1b7671e483412e63304755961e328d3f", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8ee7a3b0674e89d286e6c28b5992da30", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "a2dd4ce5321e0127bdc9e7a1c4354aa6", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d16e4cb4509fa427772c1894cc2db29d", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "7e5deafeec61b8520a4d22a5eef80f03", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "370fb623fa824ffad97750de5d1ff844", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "cf34e338f3c7d58afc70dc6742671584", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "6a075263de9be1db381eeb5ea8874ba9", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "0eef1925d2cf63eecad74e6932f624b1", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "de533e42f98a6081e96d1f7e96306fcd", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "91640f1b899fadf077d6844efdf6d37c", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c29e6e391970ede95bd90b9dec830ecc", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "2c1391f2da73fe58a2e1a815106eebf5", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "90532e99fc87ef4a8a9b1f5d9737d008", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a7bd331931da44fe268f4adda5cddb9b", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "b46b30262b58e96e994211631b470efb", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "6cc41e3401daf2e72b884fbfe0fe92b3", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "b46b30262b58e96e994211631b470efb", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "6cc41e3401daf2e72b884fbfe0fe92b3", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "b915f8a091643d99fd28e8d636063185", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "cb5de031162e4ff0cb5f030adf331a12", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "b915f8a091643d99fd28e8d636063185", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "cb5de031162e4ff0cb5f030adf331a12", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "be2a7322e1ddbb38ba0d22dd94a565e3", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "b257bbc06d82fc912653806c01a42c15", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "611631809a455737d7d9c0b04c89aa6b", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "bfe702cdf9cd260ab8cb4593afc6a3af", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4a367d3b2354d60259cc68fa25004eb0", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "fc5d98c16dbb42846ef653dc860f4508", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "683fafa75e39f0b33ef22cff53b124e6", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "1f9099d422aaed13d038e64b629e7827", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "76ee096dfbb8993cbb05a3425e429e0a", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "719478dd5e71b7096801f6bd0b701b4f", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index c69fd5fd..65543034 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21516, api 8, 2023-10-26) +### 1.7.28 (build 21522, api 8, 2023-10-26) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years @@ -164,6 +164,9 @@ - Dev console no longer claims key events unless the Python tab is showing and there is a hardware keyboard attached. This allows showing dev console tabs above gameplay without interfering with it. +- Added clipboard paste support to the dev console python terminal. +- Added various text editing functionality to the dev console python terminal + (cursor movement, deleting chars and words, etc.) ### 1.7.27 (build 21282, api 8, 2023-08-30) diff --git a/ballisticakit-cmake/CMakeLists.txt b/ballisticakit-cmake/CMakeLists.txt index 13214011..443a6adc 100644 --- a/ballisticakit-cmake/CMakeLists.txt +++ b/ballisticakit-cmake/CMakeLists.txt @@ -436,6 +436,8 @@ set(BALLISTICA_SOURCES ${BA_SRC_ROOT}/ballistica/base/support/app_config.cc ${BA_SRC_ROOT}/ballistica/base/support/app_config.h ${BA_SRC_ROOT}/ballistica/base/support/app_timer.h + ${BA_SRC_ROOT}/ballistica/base/support/base_build_switches.cc + ${BA_SRC_ROOT}/ballistica/base/support/base_build_switches.h ${BA_SRC_ROOT}/ballistica/base/support/classic_soft.h ${BA_SRC_ROOT}/ballistica/base/support/context.cc ${BA_SRC_ROOT}/ballistica/base/support/context.h diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj index 68e39f6f..3a4e6a25 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj @@ -428,6 +428,8 @@ + + diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters index 761cf81f..90ed3d40 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters @@ -718,6 +718,12 @@ ballistica\base\support + + ballistica\base\support + + + ballistica\base\support + ballistica\base\support diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj index 02f49c4b..7b5fa892 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj @@ -423,6 +423,8 @@ + + diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters index 761cf81f..90ed3d40 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters @@ -718,6 +718,12 @@ ballistica\base\support + + ballistica\base\support + + + ballistica\base\support + ballistica\base\support diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index e58e986c..653ff56d 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21516 +TARGET_BALLISTICA_BUILD = 21522 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/app_adapter/app_adapter.cc b/src/ballistica/base/app_adapter/app_adapter.cc index bb89794f..b781b04b 100644 --- a/src/ballistica/base/app_adapter/app_adapter.cc +++ b/src/ballistica/base/app_adapter/app_adapter.cc @@ -2,64 +2,17 @@ #include "ballistica/base/app_adapter/app_adapter.h" -#if BA_OSTYPE_ANDROID // Remove conditional once android sources are public. -#include "ballistica/base/app_adapter/app_adapter_android.h" -#endif -#include "ballistica/base/app_adapter/app_adapter_apple.h" -#include "ballistica/base/app_adapter/app_adapter_headless.h" -#include "ballistica/base/app_adapter/app_adapter_sdl.h" -#include "ballistica/base/app_adapter/app_adapter_vr.h" -#include "ballistica/base/graphics/graphics_server.h" #include "ballistica/base/graphics/renderer/renderer.h" #include "ballistica/base/input/input.h" #include "ballistica/base/networking/network_reader.h" #include "ballistica/base/networking/networking.h" -#include "ballistica/base/platform/base_platform.h" #include "ballistica/base/python/base_python.h" #include "ballistica/base/support/app_config.h" -#include "ballistica/base/support/stress_test.h" #include "ballistica/base/ui/ui.h" #include "ballistica/shared/foundation/event_loop.h" -#include "ballistica/shared/python/python.h" namespace ballistica::base { -auto AppAdapter::Create() -> AppAdapter* { - assert(g_core); - -// TEMP - need to init sdl on our legacy mac build even though its not -// technically an SDL app. Kill this once the old mac build is gone. -#if BA_LEGACY_MACOS_BUILD - AppAdapterSDL::InitSDL(); -#endif - - AppAdapter* app_adapter{}; - -#if BA_HEADLESS_BUILD - app_adapter = new AppAdapterHeadless(); -#elif BA_OSTYPE_ANDROID - app_adapter = new AppAdapterAndroid(); -#elif BA_XCODE_BUILD - app_adapter = new AppAdapterApple(); -#elif BA_RIFT_BUILD - // Rift build can spin up in either VR or regular mode. - if (g_core->vr_mode) { - app_adapter = new AppAdapterVR(); - } else { - app_adapter = new AppAdapterSDL(); - } -#elif BA_CARDBOARD_BUILD - app_adapter = new AppAdapterVR(); -#elif BA_SDL_BUILD - app_adapter = new AppAdapterSDL(); -#else -#error No app adapter defined for this build. -#endif - - assert(app_adapter); - return app_adapter; -} - AppAdapter::AppAdapter() = default; AppAdapter::~AppAdapter() = default; diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index e32864bb..6570d8a4 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -15,8 +15,7 @@ namespace ballistica::base { /// all might share the same CorePlatform and BasePlatform classes. class AppAdapter { public: - /// Instantiate the AppAdapter subclass for the current build. - static auto Create() -> AppAdapter*; + AppAdapter(); /// Called in the main thread when the app is being started. virtual void OnMainThreadStartApp(); @@ -224,7 +223,6 @@ class AppAdapter { auto ClipboardGetText() -> std::string; protected: - AppAdapter(); virtual ~AppAdapter(); /// Push a raw pointer Runnable to the platform's 'main' thread. The main diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.cc b/src/ballistica/base/app_adapter/app_adapter_apple.cc index 17ac5c8a..0e5ae5f7 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -247,38 +247,38 @@ auto AppAdapterApple::GetKeyRepeatInterval() -> float { } auto AppAdapterApple::DoClipboardIsSupported() -> bool { -#if BA_XCODE_BUILD +#if BA_OSTYPE_MACOS return BallisticaKit::CocoaFromCpp::ClipboardIsSupported(); #else - return CorePlatform::DoClipboardIsSupported(); + return AppAdapter::DoClipboardIsSupported(); #endif } auto AppAdapterApple::DoClipboardHasText() -> bool { -#if BA_XCODE_BUILD +#if BA_OSTYPE_MACOS return BallisticaKit::CocoaFromCpp::ClipboardHasText(); #else - return CorePlatform::DoClipboardHasText(); + return AppAdapter::DoClipboardHasText(); #endif } void AppAdapterApple::DoClipboardSetText(const std::string& text) { -#if BA_XCODE_BUILD +#if BA_OSTYPE_MACOS BallisticaKit::CocoaFromCpp::ClipboardSetText(text); #else - CorePlatform::DoClipboardSetText(text); + AppAdapter::DoClipboardSetText(text); #endif } auto AppAdapterApple::DoClipboardGetText() -> std::string { -#if BA_XCODE_BUILD +#if BA_OSTYPE_MACOS auto contents = BallisticaKit::CocoaFromCpp::ClipboardGetText(); if (contents) { return std::string(contents.get()); } throw Exception("No text on clipboard."); #else - return CorePlatform::DoClipboardGetText(); + return AppAdapter::DoClipboardGetText(); #endif } diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.cc b/src/ballistica/base/app_adapter/app_adapter_sdl.cc index 3d7e8ca0..5c432800 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -807,23 +807,9 @@ void AppAdapterSDL::CursorPositionForDraw(float* x, float* y) { auto AppAdapterSDL::FullscreenControlAvailable() const -> bool { return true; } auto AppAdapterSDL::FullscreenControlKeyShortcut() const -> std::optional { - if (g_buildconfig.ostype_windows()) { - // On Windows we support F11 and Alt+Enter to toggle fullscreen. Let's - // mention Alt+Enter which seems like it might be more commonly used - return "Alt+Enter"; - } - if (g_buildconfig.ostype_macos()) { - // The Mac+SDL situation is a bit of a mess. By default, there is 'Enter - // Full Screen' in the window menu which is mapped to fn-F, but that - // will only work if a window was created in SDL as windowed. If we - // fullscreen that window and restart the app, we'll then have a *real* - // fullscreen sdl window and that shortcut won't work anymore. So to - // keep things consistent we advertise ctrl-f which we always handle - // ourselves. Maybe this situation will be cleaned up in SDL 3, but its - // not a huge deal anyway since our Cocoa Mac version behaves cleanly. - return "Ctrl+F"; - } - return {}; + // On our SDL build we support F11 and Alt+Enter to toggle fullscreen. + // Let's mention Alt+Enter which seems like it might be more commonly used + return "Alt+Enter"; }; auto AppAdapterSDL::SupportsVSync() -> bool const { return true; } diff --git a/src/ballistica/base/assets/assets_server.cc b/src/ballistica/base/assets/assets_server.cc index 102c6027..9c89f00e 100644 --- a/src/ballistica/base/assets/assets_server.cc +++ b/src/ballistica/base/assets/assets_server.cc @@ -5,7 +5,6 @@ #include "ballistica/base/assets/asset.h" #include "ballistica/base/assets/assets.h" #include "ballistica/base/graphics/graphics.h" -#include "ballistica/base/graphics/graphics_server.h" #include "ballistica/base/support/huffman.h" #include "ballistica/shared/foundation/event_loop.h" diff --git a/src/ballistica/base/base.cc b/src/ballistica/base/base.cc index b7e4abb3..2871e6ac 100644 --- a/src/ballistica/base/base.cc +++ b/src/ballistica/base/base.cc @@ -20,12 +20,12 @@ #include "ballistica/base/python/class/python_class_feature_set_data.h" #include "ballistica/base/python/support/python_context_call.h" #include "ballistica/base/support/app_config.h" +#include "ballistica/base/support/base_build_switches.h" #include "ballistica/base/support/huffman.h" #include "ballistica/base/support/plus_soft.h" #include "ballistica/base/support/stdio_console.h" #include "ballistica/base/support/stress_test.h" #include "ballistica/base/ui/dev_console.h" -#include "ballistica/base/ui/ui.h" #include "ballistica/base/ui/ui_delegate.h" #include "ballistica/core/python/core_python.h" #include "ballistica/shared/foundation/event_loop.h" @@ -39,7 +39,7 @@ core::CoreFeatureSet* g_core{}; BaseFeatureSet* g_base{}; BaseFeatureSet::BaseFeatureSet() - : app_adapter{AppAdapter::Create()}, + : app_adapter{BaseBuildSwitches::CreateAppAdapter()}, app_config{new AppConfig()}, app_mode_{AppModeEmpty::GetSingleton()}, assets{new Assets()}, @@ -51,7 +51,7 @@ BaseFeatureSet::BaseFeatureSet() bg_dynamics_server{g_core->HeadlessMode() ? nullptr : new BGDynamicsServer}, context_ref{new ContextRef(nullptr)}, - graphics{Graphics::Create()}, + graphics{BaseBuildSwitches::CreateGraphics()}, graphics_server{new GraphicsServer()}, huffman{new Huffman()}, input{new Input()}, @@ -59,7 +59,7 @@ BaseFeatureSet::BaseFeatureSet() network_reader{new NetworkReader()}, network_writer{new NetworkWriter()}, networking{new Networking()}, - platform{BasePlatform::Create()}, + platform{BaseBuildSwitches::CreatePlatform()}, python{new BasePython()}, stdio_console{g_buildconfig.enable_stdio_console() ? new StdioConsole() : nullptr}, diff --git a/src/ballistica/base/graphics/graphics.cc b/src/ballistica/base/graphics/graphics.cc index 7f405a9d..7bc51e39 100644 --- a/src/ballistica/base/graphics/graphics.cc +++ b/src/ballistica/base/graphics/graphics.cc @@ -5,28 +5,23 @@ #include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/app_mode/app_mode.h" #include "ballistica/base/dynamics/bg/bg_dynamics.h" -#include "ballistica/base/graphics/component/empty_component.h" #include "ballistica/base/graphics/component/object_component.h" #include "ballistica/base/graphics/component/post_process_component.h" #include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/special_component.h" #include "ballistica/base/graphics/component/sprite_component.h" #include "ballistica/base/graphics/graphics_server.h" -#include "ballistica/base/graphics/graphics_vr.h" +#include "ballistica/base/graphics/mesh/nine_patch_mesh.h" #include "ballistica/base/graphics/support/camera.h" #include "ballistica/base/graphics/support/net_graph.h" #include "ballistica/base/graphics/text/text_graphics.h" #include "ballistica/base/input/input.h" #include "ballistica/base/logic/logic.h" -#include "ballistica/base/platform/base_platform.h" #include "ballistica/base/python/support/python_context_call.h" #include "ballistica/base/support/app_config.h" -#include "ballistica/base/ui/dev_console.h" #include "ballistica/base/ui/ui.h" -#include "ballistica/core/core.h" #include "ballistica/shared/foundation/event_loop.h" #include "ballistica/shared/generic/utils.h" -#include "ballistica/shared/python/python.h" namespace ballistica::base { @@ -36,14 +31,6 @@ const float kProgressBarZDepth{0.0f}; const int kProgressBarFadeTime{500}; const float kDebugImgZDepth{-0.04f}; -auto Graphics::Create() -> Graphics* { -#if BA_VR_BUILD - return new GraphicsVR(); -#else - return new Graphics(); -#endif -} - auto Graphics::IsShaderTransparent(ShadingType c) -> bool { switch (c) { case ShadingType::kSimpleColorTransparent: @@ -231,11 +218,9 @@ auto Graphics::VSyncFromAppConfig() -> VSyncRequest { } auto Graphics::GraphicsQualityFromAppConfig() -> GraphicsQualityRequest { - // Graphics quality. std::string gqualstr = g_base->app_config->Resolve(AppConfig::StringID::kGraphicsQuality); GraphicsQualityRequest graphics_quality_requested; - if (gqualstr == "Auto") { graphics_quality_requested = GraphicsQualityRequest::kAuto; } else if (gqualstr == "Higher") { @@ -361,33 +346,36 @@ auto Graphics::GetShadowDensity(float x, float y, float z) -> float { class Graphics::ScreenMessageEntry { public: - ScreenMessageEntry(std::string s_in, bool align_left_in, uint32_t c, - const Vector3f& color_in, TextureAsset* texture_in, - TextureAsset* tint_texture_in, const Vector3f& tint_in, - const Vector3f& tint2_in) - : align_left(align_left_in), + ScreenMessageEntry(std::string text, bool top_style, uint32_t c, + const Vector3f& color, TextureAsset* texture, + TextureAsset* tint_texture, const Vector3f& tint, + const Vector3f& tint2) + : top_style(top_style), creation_time(c), - s_raw(std::move(s_in)), - color(color_in), - texture(texture_in), - tint_texture(tint_texture_in), - tint(tint_in), - tint2(tint2_in) {} + s_raw(std::move(text)), + color(color), + texture(texture), + tint_texture(tint_texture), + tint(tint), + tint2(tint2) {} auto GetText() -> TextGroup&; void UpdateTranslation(); - bool align_left; + bool top_style; uint32_t creation_time; Vector3f color; Vector3f tint; Vector3f tint2; std::string s_raw; std::string s_translated; + float str_width{}; + float str_height{}; Object::Ref texture; Object::Ref tint_texture; float v_smoothed{}; bool translation_dirty{true}; bool mesh_dirty{true}; millisecs_t smooth_time{}; + Object::Ref shadow_mesh_; private: Object::Ref s_mesh_; @@ -578,7 +566,8 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { SimpleComponent c(pass); c.SetTransparent(true); c.SetTexture( - g_base->assets->SysTexture(SysTextureID::kSoftRectVertical)); + // g_base->assets->SysTexture(SysTextureID::kSoftRectVertical)); + g_base->assets->SysTexture(SysTextureID::kShadowSharp)); float screen_width = g_base->graphics->screen_virtual_width(); @@ -591,6 +580,10 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { // Update the translation if need be. i->UpdateTranslation(); + // Don't actually need the text just yet but need shadow mesh + // which is calculated as part of it. + i->GetText(); + millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time; youngest_age = std::min(youngest_age, age); float s_extra = 1.0f; @@ -609,9 +602,9 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { } a *= 0.8f; - if (vr) { - a *= 0.8f; - } + // if (vr) { + // a *= 0.8f; + // } if (i->translation_dirty) { BA_LOG_ONCE( @@ -619,10 +612,9 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { "Found dirty translation on screenmessage draw pass 1; raw=" + i->s_raw); } - float str_height = - g_base->text_graphics->GetStringHeight(i->s_translated.c_str()); - float str_width = - g_base->text_graphics->GetStringWidth(i->s_translated.c_str()); + + float str_height = i->str_height; + float str_width = i->str_width; if ((str_width * scale) > (screen_width - 40)) { s_extra *= ((screen_width - 40) / (str_width * scale)); @@ -639,7 +631,7 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { if (age < 100) { fade = 1.0f; } else { - fade = std::max(0.0f, (200.0f - static_cast(age)) / 100.0f); + fade = std::max(0.07f, (200.0f - static_cast(age)) / 100.0f); } c.SetColor(r * fade, g * fade, b * fade, a); @@ -663,22 +655,28 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { c.Translate(screen_width * 0.5f, i->v_smoothed, vr ? 60 : kScreenMessageZDepth); - if (vr) { - // Let's drop down a bit in vr mode. - c.Translate(0, -10.0f, 0); - c.Scale((str_width + 60) * scale * s_extra, - (str_height + 20) * scale * s_extra); - // Align our bottom with where we just scaled from. - c.Translate(0, 0.5f, 0); - } else { - c.Scale((str_width + 110) * scale * s_extra, - (str_height + 40) * scale * s_extra); + // if (vr) { + // // Let's drop down a bit in vr mode. + // // c.Translate(0, -10.0f, 0); + // // c.Scale((str_width + 60) * scale * s_extra, + // // (str_height + 20) * scale * s_extra); + // c.Scale(scale * s_extra, scale * s_extra); + + // // Align our bottom with where we just scaled from. + // c.Translate(0, 0.5f, 0); + { + // c.Scale((str_width + 110) * scale * s_extra, + // (str_height + 40) * scale * s_extra); + c.Scale(scale * s_extra, scale * s_extra); + c.Translate(0, 20); // Align our bottom with where we just scaled from. c.Translate(0, 0.5f, 0); } - c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1)); + // c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1)); + assert(i->shadow_mesh_.Exists()); + c.DrawMesh(i->shadow_mesh_.Get()); } v += scale * (36 + str_height); @@ -721,10 +719,8 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { "Found dirty translation on screenmessage draw pass 2; raw=" + i->s_raw); } - float str_height = - g_base->text_graphics->GetStringHeight(i->s_translated.c_str()); - float str_width = - g_base->text_graphics->GetStringWidth(i->s_translated.c_str()); + float str_height = i->str_height; + float str_width = i->str_width; if ((str_width * scale) > (screen_width - 40)) { s_extra *= ((screen_width - 40) / (str_width * scale)); @@ -1964,8 +1960,28 @@ auto Graphics::ScreenMessageEntry::GetText() -> TextGroup& { if (mesh_dirty) { s_mesh_->SetText( s_translated, - align_left ? TextMesh::HAlign::kLeft : TextMesh::HAlign::kCenter, + top_style ? TextMesh::HAlign::kLeft : TextMesh::HAlign::kCenter, TextMesh::VAlign::kBottom); + + str_width = g_base->text_graphics->GetStringWidth(s_translated.c_str()); + str_height = g_base->text_graphics->GetStringHeight(s_translated.c_str()); + + if (!top_style) { + float x_extend = 40.0f; + float y_extend = 40.0f; + float y_offset = -10.0f; + float corner_radius = 60.0f; + float width_fin = str_width + x_extend * 2.0f; + float height_fin = str_height + y_extend * 2.0f; + float x_border = + NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin); + float y_border = + NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin); + shadow_mesh_ = Object::New( + -0.5f * width_fin, -y_extend + y_offset, 0.0f, width_fin, height_fin, + x_border, y_border, x_border, y_border); + } + mesh_dirty = false; } return *s_mesh_; diff --git a/src/ballistica/base/graphics/graphics.h b/src/ballistica/base/graphics/graphics.h index 4c244dd3..1e9736ed 100644 --- a/src/ballistica/base/graphics/graphics.h +++ b/src/ballistica/base/graphics/graphics.h @@ -53,8 +53,7 @@ const float kCursorZDepth{0.9f}; // Client class for graphics operations (used from the logic thread). class Graphics { public: - /// Instantiate the Graphics subclass for the current build. - static auto Create() -> Graphics*; + Graphics(); void OnAppStart(); void OnAppPause(); @@ -370,7 +369,6 @@ class Graphics { protected: class ScreenMessageEntry; - Graphics(); virtual ~Graphics(); virtual void DoDrawFade(FrameDef* frame_def, float amt); static void CalcVirtualRes_(float* x, float* y); diff --git a/src/ballistica/base/graphics/mesh/nine_patch_mesh.h b/src/ballistica/base/graphics/mesh/nine_patch_mesh.h index fad02593..64b6638d 100644 --- a/src/ballistica/base/graphics/mesh/nine_patch_mesh.h +++ b/src/ballistica/base/graphics/mesh/nine_patch_mesh.h @@ -18,7 +18,7 @@ class NinePatchMesh : public MeshIndexedSimpleFull { /// Calculate a border value for a NinePatchMesh based on dimensions and a /// desired max corner radius. For calculating left or right borders, - /// matching_dimension should be width and other_dimension should be + /// `matching_dimension` should be width and `other_dimension` should be /// height. For top or bottom borders it is the opposite. static auto BorderForRadius(float corner_radius, float matching_dimension, float other_dimension) -> float { diff --git a/src/ballistica/base/graphics/support/graphics_settings.cc b/src/ballistica/base/graphics/support/graphics_settings.cc index a132fe88..fd2a5ed0 100644 --- a/src/ballistica/base/graphics/support/graphics_settings.cc +++ b/src/ballistica/base/graphics/support/graphics_settings.cc @@ -6,7 +6,6 @@ #include "ballistica/base/graphics/graphics.h" #include "ballistica/base/support/app_config.h" -#include "ballistica/shared/foundation/object.h" namespace ballistica::base { diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index bbde01f1..4a983659 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -12,10 +12,8 @@ #include "ballistica/base/input/device/touch_input.h" #include "ballistica/base/logic/logic.h" #include "ballistica/base/python/base_python.h" -#include "ballistica/base/support/app_config.h" #include "ballistica/base/ui/dev_console.h" #include "ballistica/base/ui/ui.h" -#include "ballistica/shared/buildconfig/buildconfig_common.h" #include "ballistica/shared/foundation/event_loop.h" #include "ballistica/shared/generic/utils.h" @@ -838,6 +836,13 @@ void Input::PushTextInputEvent(const std::string& text) { return; } + // Ignore back-tick and tilde because we use that key to toggle the console. + // FIXME: Perhaps should allow typing it if some control-character is + // held? + if (text == "`" || text == "~") { + return; + } + // We try to handle char filtering here (to keep it consistent across // platforms) but make a stink if they sent us something that we can't // at least translate to unicode. @@ -1065,17 +1070,9 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) { // Explicitly handle fullscreen-toggles in some cases. if (g_base->app_adapter->FullscreenControlAvailable()) { bool do_toggle{}; - // On our Mac SDL builds we support ctrl+F for toggling fullscreen. - // On our nice Cocoa build, fullscreening happens magically through the - // view menu fullscreen control's shortcut. - if (g_buildconfig.ostype_macos() && !g_buildconfig.xcode_build()) { - if (keysym.sym == SDLK_f && ((keysym.mod & KMOD_CTRL))) { - do_toggle = true; - } - } - // On Windows and Linux we support both F11 and Alt+Enter for toggling + // On our SDL builds we support both F11 and Alt+Enter for toggling // fullscreen. - if (g_buildconfig.ostype_windows() || g_buildconfig.ostype_linux()) { + if (g_buildconfig.sdl_build()) { if ((keysym.sym == SDLK_F11 || (keysym.sym == SDLK_RETURN && ((keysym.mod & KMOD_ALT))))) { do_toggle = true; @@ -1089,6 +1086,19 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) { } } + // Ctrl-V or Cmd-V sends paste commands to the console or any interested + // text fields. + if (keysym.sym == SDLK_v + && ((keysym.mod & KMOD_CTRL) || (keysym.mod & KMOD_GUI))) { + if (auto* console = g_base->ui->dev_console()) { + if (console->PasteFromClipboard()) { + return; + } + } + g_base->ui->SendWidgetMessage(WidgetMessage(WidgetMessage::Type::kPaste)); + return; + } + // Dev Console. if (auto* console = g_base->ui->dev_console()) { if (keysym.sym == SDLK_BACKQUOTE || keysym.sym == SDLK_F2) { @@ -1102,13 +1112,6 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) { } } - // Ctrl-V or Cmd-V sends paste commands to any interested text fields. - if (keysym.sym == SDLK_v - && ((keysym.mod & KMOD_CTRL) || (keysym.mod & KMOD_GUI))) { - g_base->ui->SendWidgetMessage(WidgetMessage(WidgetMessage::Type::kPaste)); - return; - } - bool handled = false; switch (keysym.sym) { diff --git a/src/ballistica/base/platform/base_platform.cc b/src/ballistica/base/platform/base_platform.cc index 9be958c2..75eb59c8 100644 --- a/src/ballistica/base/platform/base_platform.cc +++ b/src/ballistica/base/platform/base_platform.cc @@ -16,73 +16,8 @@ #include "ballistica/shared/python/python.h" #include "ballistica/shared/python/python_sys.h" -// ------------------------- PLATFORM SELECTION -------------------------------- - -// This ugly chunk of macros simply pulls in the correct platform class header -// for each platform and defines the actual class g_base->platform will be. - -// Android --------------------------------------------------------------------- - -#if BA_OSTYPE_ANDROID -#if BA_GOOGLE_BUILD -#include "ballistica/base/platform/android/google/base_plat_andr_google.h" -#define BA_PLATFORM_CLASS BasePlatformAndroidGoogle -#elif BA_AMAZON_BUILD -#include "ballistica/base/platform/android/amazon/base_plat_andr_amazon.h" -#define BA_PLATFORM_CLASS BasePlatformAndroidAmazon -#elif BA_CARDBOARD_BUILD -#include "ballistica/base/platform/android/cardboard/base_pl_an_cardboard.h" -#define BA_PLATFORM_CLASS BasePlatformAndroidCardboard -#else // Generic android. -#include "ballistica/base/platform/android/base_platform_android.h" -#define BA_PLATFORM_CLASS BasePlatformAndroid -#endif // (Android subplatform) - -// Apple ----------------------------------------------------------------------- - -#elif BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS -#include "ballistica/base/platform/apple/base_platform_apple.h" -#define BA_PLATFORM_CLASS BasePlatformApple - -// Windows --------------------------------------------------------------------- - -#elif BA_OSTYPE_WINDOWS -#if BA_RIFT_BUILD -#include "ballistica/base/platform/windows/base_platform_windows_oculus.h" -#define BA_PLATFORM_CLASS BasePlatformWindowsOculus -#else // generic windows -#include "ballistica/base/platform/windows/base_platform_windows.h" -#define BA_PLATFORM_CLASS BasePlatformWindows -#endif // windows subtype - -// Linux ----------------------------------------------------------------------- - -#elif BA_OSTYPE_LINUX -#include "ballistica/base/platform/linux/base_platform_linux.h" -#define BA_PLATFORM_CLASS BasePlatformLinux -#else - -// Generic --------------------------------------------------------------------- - -#define BA_PLATFORM_CLASS BasePlatform - -#endif - -// ----------------------- END PLATFORM SELECTION ------------------------------ - -#ifndef BA_PLATFORM_CLASS -#error no BA_PLATFORM_CLASS defined for this platform -#endif - namespace ballistica::base { -auto BasePlatform::Create() -> BasePlatform* { - auto platform = new BA_PLATFORM_CLASS(); - platform->PostInit(); - assert(platform->ran_base_post_init_); - return platform; -} - BasePlatform::BasePlatform() = default; void BasePlatform::PostInit() { diff --git a/src/ballistica/base/platform/base_platform.h b/src/ballistica/base/platform/base_platform.h index 85d19b39..63e1b043 100644 --- a/src/ballistica/base/platform/base_platform.h +++ b/src/ballistica/base/platform/base_platform.h @@ -15,8 +15,12 @@ namespace ballistica::base { /// with a single platform (Windows, Mac, etc.). class BasePlatform { public: - /// Instantiate the CorePlatform subclass for the current build. - static auto Create() -> BasePlatform*; + BasePlatform(); + + /// Called after our singleton has been instantiated. Any construction + /// functionality requiring virtual functions resolving to their final + /// class versions can go here. + virtual void PostInit(); #pragma mark APP EVENTS / LIFECYCLE -------------------------------------------- @@ -95,6 +99,8 @@ class BasePlatform { /// Must be called in the logic thread. void StringEditorCancel(); + auto ran_base_post_init() const { return ran_base_post_init_; } + protected: /// Pop up a text edit dialog. virtual void DoInvokeStringEditor(const std::string& title, @@ -107,15 +113,9 @@ class BasePlatform { /// Make a purchase. virtual void DoPurchase(const std::string& item); - BasePlatform(); virtual ~BasePlatform(); private: - /// Called after our singleton has been instantiated. Any construction - /// functionality requiring virtual functions resolving to their final - /// class versions can go here. - virtual void PostInit(); - bool ran_base_post_init_ : 1 {}; PythonRef string_edit_adapter_{}; std::string public_device_uuid_; diff --git a/src/ballistica/base/support/base_build_switches.cc b/src/ballistica/base/support/base_build_switches.cc new file mode 100644 index 00000000..96abc907 --- /dev/null +++ b/src/ballistica/base/support/base_build_switches.cc @@ -0,0 +1,120 @@ +// Released under the MIT License. See LICENSE for details. + +#include "ballistica/base/support/base_build_switches.h" + +#if BA_OSTYPE_ANDROID +#include "ballistica/base/app_adapter/app_adapter_android.h" +#endif +#include "ballistica/base/app_adapter/app_adapter_apple.h" +#include "ballistica/base/app_adapter/app_adapter_headless.h" +#include "ballistica/base/app_adapter/app_adapter_sdl.h" +#include "ballistica/base/app_adapter/app_adapter_vr.h" +#include "ballistica/base/graphics/graphics.h" +#include "ballistica/base/graphics/graphics_vr.h" + +// ------------------------- PLATFORM SELECTION -------------------------------- + +// This ugly chunk of macros simply pulls in the correct platform class header +// for each platform and defines the actual class g_base->platform will be. + +// Android --------------------------------------------------------------------- + +#if BA_OSTYPE_ANDROID +#if BA_GOOGLE_BUILD +#include "ballistica/base/platform/android/google/base_plat_andr_google.h" +#define BA_PLATFORM_CLASS BasePlatformAndroidGoogle +#elif BA_AMAZON_BUILD +#include "ballistica/base/platform/android/amazon/base_plat_andr_amazon.h" +#define BA_PLATFORM_CLASS BasePlatformAndroidAmazon +#elif BA_CARDBOARD_BUILD +#include "ballistica/base/platform/android/cardboard/base_pl_an_cardboard.h" +#define BA_PLATFORM_CLASS BasePlatformAndroidCardboard +#else // Generic android. +#include "ballistica/base/platform/android/base_platform_android.h" +#define BA_PLATFORM_CLASS BasePlatformAndroid +#endif // (Android subplatform) + +// Apple ----------------------------------------------------------------------- + +#elif BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS +#include "ballistica/base/platform/apple/base_platform_apple.h" +#define BA_PLATFORM_CLASS BasePlatformApple + +// Windows --------------------------------------------------------------------- + +#elif BA_OSTYPE_WINDOWS +#if BA_RIFT_BUILD +#include "ballistica/base/platform/windows/base_platform_windows_oculus.h" +#define BA_PLATFORM_CLASS BasePlatformWindowsOculus +#else // generic windows +#include "ballistica/base/platform/windows/base_platform_windows.h" +#define BA_PLATFORM_CLASS BasePlatformWindows +#endif // windows subtype + +// Linux ----------------------------------------------------------------------- + +#elif BA_OSTYPE_LINUX +#include "ballistica/base/platform/linux/base_platform_linux.h" +#define BA_PLATFORM_CLASS BasePlatformLinux +#else + +// Generic --------------------------------------------------------------------- + +#define BA_PLATFORM_CLASS BasePlatform + +#endif + +// ----------------------- END PLATFORM SELECTION ------------------------------ + +#ifndef BA_PLATFORM_CLASS +#error no BA_PLATFORM_CLASS defined for this platform +#endif + +namespace ballistica::base { + +auto BaseBuildSwitches::CreatePlatform() -> BasePlatform* { + auto platform = new BA_PLATFORM_CLASS(); + platform->PostInit(); + assert(platform->ran_base_post_init()); + return platform; +} + +auto BaseBuildSwitches::CreateGraphics() -> Graphics* { +#if BA_VR_BUILD + return new GraphicsVR(); +#else + return new Graphics(); +#endif +} + +auto BaseBuildSwitches::CreateAppAdapter() -> AppAdapter* { + assert(g_core); + + AppAdapter* app_adapter{}; + +#if BA_HEADLESS_BUILD + app_adapter = new AppAdapterHeadless(); +#elif BA_OSTYPE_ANDROID + app_adapter = new AppAdapterAndroid(); +#elif BA_XCODE_BUILD + app_adapter = new AppAdapterApple(); +#elif BA_RIFT_BUILD + // Rift build can spin up in either VR or regular mode. + if (g_core->vr_mode) { + app_adapter = new AppAdapterVR(); + } else { + app_adapter = new AppAdapterSDL(); + } +#elif BA_CARDBOARD_BUILD + app_adapter = new AppAdapterVR(); +#elif BA_SDL_BUILD + app_adapter = new AppAdapterSDL(); +#else +#error No app adapter defined for this build. +#endif + + assert(app_adapter); + return app_adapter; +} + +} // namespace ballistica::base diff --git a/src/ballistica/base/support/base_build_switches.h b/src/ballistica/base/support/base_build_switches.h new file mode 100644 index 00000000..ea5b4ba4 --- /dev/null +++ b/src/ballistica/base/support/base_build_switches.h @@ -0,0 +1,20 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_BASE_SUPPORT_BASE_BUILD_SWITCHES_H_ +#define BALLISTICA_BASE_SUPPORT_BASE_BUILD_SWITCHES_H_ + +#include "ballistica/base/base.h" + +namespace ballistica::base { + +/// Constructs various app components based on the current build config. +class BaseBuildSwitches { + public: + static auto CreateGraphics() -> Graphics*; + static auto CreatePlatform() -> BasePlatform*; + static auto CreateAppAdapter() -> AppAdapter*; +}; + +} // namespace ballistica::base + +#endif // BALLISTICA_BASE_SUPPORT_BASE_BUILD_SWITCHES_H_ diff --git a/src/ballistica/base/support/repeater.cc b/src/ballistica/base/support/repeater.cc index 1593da15..c7d58d5e 100644 --- a/src/ballistica/base/support/repeater.cc +++ b/src/ballistica/base/support/repeater.cc @@ -2,7 +2,6 @@ #include "ballistica/base/support/repeater.h" -#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/support/app_timer.h" #include "ballistica/shared/foundation/event_loop.h" diff --git a/src/ballistica/base/ui/dev_console.cc b/src/ballistica/base/ui/dev_console.cc index f0ac5365..6940c271 100644 --- a/src/ballistica/base/ui/dev_console.cc +++ b/src/ballistica/base/ui/dev_console.cc @@ -8,7 +8,6 @@ #include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/mesh/nine_patch_mesh.h" #include "ballistica/base/graphics/text/text_graphics.h" -#include "ballistica/base/input/input.h" #include "ballistica/base/logic/logic.h" #include "ballistica/base/platform/base_platform.h" #include "ballistica/base/python/base_python.h" @@ -85,6 +84,11 @@ static auto XOffs(DevConsoleHAnchor_ attach) -> float { return 0.0f; } +static auto IsValidHungryChar_(uint32_t this_char) -> bool { + return ((this_char >= 65 && this_char <= 90) + || (this_char >= 97 && this_char <= 122)); +} + static void DrawRect(RenderPass* pass, Mesh* mesh, float bottom, float x, float y, float width, float height, const Vector3f& bgcolor) { @@ -677,6 +681,11 @@ void DevConsole::set_input_string(const std::string& val) { assert(g_base->InLogicThread()); input_string_ = val; input_text_dirty_ = true; + // Move carat to end. + carat_char_ = + static_cast(Utils::UnicodeFromUTF8(input_string_, "fj43t").size()); + assert(CaratCharValid_()); + carat_dirty_ = true; } void DevConsole::InputAdapterFinish() { @@ -690,28 +699,11 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { // Any presses or releases cancels repeat actions. key_repeater_.Clear(); - // Handle our toggle buttons no matter whether we're active. - // switch (keysym->sym) { - // case kDevConsoleActivateKey1: - // case kDevConsoleActivateKey2: { - // if (!g_buildconfig.demo_build() && !g_buildconfig.arcade_build()) { - // // (reset input so characters don't continue walking and stuff) - // g_base->input->ResetHoldStates(); - // if (auto console = g_base->ui->dev_console()) { - // console->ToggleState(); - // } - // } - // return true; - // } - // default: - // break; - // } - if (state_ == State_::kInactive) { return false; } - // Handle some stuff only while active. + // Stuff we always look for. switch (keysym->sym) { case SDLK_ESCAPE: Dismiss(); @@ -720,56 +712,228 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { break; } - // If we support direct keyboard input, and python terminal is showing, - // handle some keys directly. + // Stuff we look for only when direct keyboard input is enabled and our + // Python terminal is up. if (python_terminal_visible_ && g_base->ui->UIHasDirectKeyboardInput()) { + bool do_carat_right{}; + bool do_hungry_carat_right{}; + bool do_carat_left{}; + bool do_hungry_carat_left{}; + bool do_history_up{}; + bool do_history_down{}; + bool do_backspace{}; + bool do_hungry_backspace{}; + bool do_move_to_end{}; + bool do_move_to_beginning{}; + bool do_kill_line{}; switch (keysym->sym) { case SDLK_BACKSPACE: { - key_repeater_ = Repeater::New( - g_base->app_adapter->GetKeyRepeatDelay(), - g_base->app_adapter->GetKeyRepeatInterval(), [this] { - auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38"); - if (!unichars.empty()) { - unichars.resize(unichars.size() - 1); - input_string_ = Utils::UTF8FromUnicode(unichars); - input_text_dirty_ = true; - } - }); + if (keysym->mod & KMOD_ALT) { + do_hungry_backspace = true; + } else { + do_backspace = true; + } break; } case SDLK_UP: - case SDLK_DOWN: { - if (input_history_.empty()) { - break; - } - if (keysym->sym == SDLK_UP) { - input_history_position_++; + do_history_up = true; + break; + case SDLK_DOWN: + do_history_down = true; + break; + case SDLK_RIGHT: + if (keysym->mod & KMOD_ALT) { + do_hungry_carat_right = true; } else { - input_history_position_--; - } - int input_history_position_used = - (input_history_position_ - 1) - % static_cast(input_history_.size()); - int j = 0; - for (auto& i : input_history_) { - if (j == input_history_position_used) { - input_string_ = i; - input_text_dirty_ = true; - break; - } - j++; + do_carat_right = true; + } + break; + case SDLK_LEFT: + if (keysym->mod & KMOD_ALT) { + do_hungry_carat_left = true; + } else { + do_carat_left = true; } break; - } case SDLK_KP_ENTER: case SDLK_RETURN: { Exec(); break; } + + // Wheeee emacs key shortcuts!! + case SDLK_n: + if (keysym->mod & KMOD_CTRL) { + do_history_down = true; + } + break; + case SDLK_f: + if (keysym->mod & KMOD_CTRL) { + do_carat_right = true; + } else if (keysym->mod & KMOD_ALT) { + do_hungry_carat_right = true; + } + break; + case SDLK_b: + if (keysym->mod & KMOD_CTRL) { + do_carat_left = true; + } else if (keysym->mod & KMOD_ALT) { + do_hungry_carat_left = true; + } + break; + case SDLK_p: + if (keysym->mod & KMOD_CTRL) { + do_history_up = true; + } + break; + case SDLK_a: + if (keysym->mod & KMOD_CTRL) { + do_move_to_beginning = true; + } + break; + case SDLK_e: + if (keysym->mod & KMOD_CTRL) { + do_move_to_end = true; + } + break; + case SDLK_k: + if (keysym->mod & KMOD_CTRL) { + do_kill_line = true; + } + default: { break; } } + if (do_kill_line) { + auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38"); + assert(CaratCharValid_()); + unichars.resize(carat_char_); + assert(CaratCharValid_()); + input_string_ = Utils::UTF8FromUnicode(unichars); + input_text_dirty_ = true; + carat_dirty_ = true; + } + if (do_move_to_beginning) { + carat_char_ = 0; + assert(CaratCharValid_()); + carat_dirty_ = true; + } + if (do_move_to_end) { + // Move carat to end. + carat_char_ = static_cast( + Utils::UnicodeFromUTF8(input_string_, "fj43t").size()); + assert(CaratCharValid_()); + carat_dirty_ = true; + } + if (do_hungry_backspace || do_hungry_carat_left) { + auto do_delete = do_hungry_backspace; + key_repeater_ = Repeater::New( + g_base->app_adapter->GetKeyRepeatDelay(), + g_base->app_adapter->GetKeyRepeatInterval(), [this, do_delete] { + auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38"); + bool found_valid{}; + // Delete/move until we've found at least one valid char and the + // stop at the first invalid one. + while (carat_char_ > 0) { + assert(CaratCharValid_()); + auto this_char = unichars[carat_char_ - 1]; + auto is_valid = IsValidHungryChar_(this_char); + if (found_valid && !is_valid) { + break; + } + if (is_valid) { + found_valid = true; + } + if (do_delete) { + unichars.erase(unichars.begin() + carat_char_ - 1); + } + carat_char_ -= 1; + assert(CaratCharValid_()); + } + input_string_ = Utils::UTF8FromUnicode(unichars); + input_text_dirty_ = true; + carat_dirty_ = true; + }); + } + if (do_hungry_carat_right) { + key_repeater_ = Repeater::New( + g_base->app_adapter->GetKeyRepeatDelay(), + g_base->app_adapter->GetKeyRepeatInterval(), [this] { + auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38"); + bool found_valid{}; + // Move until we've found at least one valid char and the + // stop at the first invalid one. + while (carat_char_ < unichars.size()) { + assert(CaratCharValid_()); + auto this_char = unichars[carat_char_]; + auto is_valid = IsValidHungryChar_(this_char); + if (found_valid && !is_valid) { + break; + } + if (is_valid) { + found_valid = true; + } + carat_char_ += 1; + assert(CaratCharValid_()); + } + carat_dirty_ = true; + }); + } + if (do_backspace) { + key_repeater_ = Repeater::New( + g_base->app_adapter->GetKeyRepeatDelay(), + g_base->app_adapter->GetKeyRepeatInterval(), [this] { + auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38"); + if (!unichars.empty() && carat_char_ > 0) { + assert(CaratCharValid_()); + unichars.erase(unichars.begin() + carat_char_ - 1); + input_string_ = Utils::UTF8FromUnicode(unichars); + input_text_dirty_ = true; + carat_char_ -= 1; + assert(CaratCharValid_()); + carat_dirty_ = true; + } + }); + } + if (do_carat_left || do_carat_right) { + key_repeater_ = Repeater::New( + g_base->app_adapter->GetKeyRepeatDelay(), + g_base->app_adapter->GetKeyRepeatInterval(), + [do_carat_left, do_carat_right, this] { + int offset = do_carat_right ? 1 : -1; + carat_char_ = std::clamp( + carat_char_ + offset, 0, + static_cast( + Utils::UnicodeFromUTF8(input_string_, "fffwe").size())); + assert(CaratCharValid_()); + carat_dirty_ = true; + }); + } + + if ((do_history_up || do_history_down) && !input_history_.empty()) { + if (do_history_up) { + input_history_position_++; + } else { + input_history_position_--; + } + int input_history_position_used = + (input_history_position_ - 1) + % static_cast(input_history_.size()); + int j = 0; + for (auto& i : input_history_) { + if (j == input_history_position_used) { + input_string_ = i; + carat_char_ = static_cast( + Utils::UnicodeFromUTF8(input_string_, "fffwe").size()); + assert(CaratCharValid_()); + input_text_dirty_ = true; + carat_dirty_ = true; + break; + } + j++; + } + } return true; } @@ -778,6 +942,24 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { return false; } +auto DevConsole::HandleTextEditing(const std::string& text) -> bool { + assert(g_base->InLogicThread()); + if (state_ == State_::kInactive) { + return false; + } + assert(CaratCharValid_()); + auto unichars = Utils::UnicodeFromUTF8(input_string_, "jfof8"); + auto addunichars = Utils::UnicodeFromUTF8(text, "jfoef8"); + unichars.insert(unichars.begin() + carat_char_, addunichars.begin(), + addunichars.end()); + input_string_ = Utils::UTF8FromUnicode(unichars); + input_text_dirty_ = true; + carat_char_ += addunichars.size(); + assert(CaratCharValid_()); + carat_dirty_ = true; + return true; +} + auto DevConsole::HandleKeyRelease(const SDL_Keysym* keysym) -> bool { // Any presses or releases cancels repeat actions. key_repeater_.Clear(); @@ -804,7 +986,17 @@ void DevConsole::Exec() { input_history_.pop_back(); } input_string_.resize(0); + carat_char_ = 0; + assert(CaratCharValid_()); input_text_dirty_ = true; + carat_dirty_ = true; +} + +// Just for sanity testing. +auto DevConsole::CaratCharValid_() -> bool { + return carat_char_ >= 0 + && carat_char_ + <= Utils::UnicodeFromUTF8(input_string_, "fwewffe").size(); } void DevConsole::SubmitPythonCommand_(const std::string& command) { @@ -871,24 +1063,6 @@ void DevConsole::ToggleState() { transition_start_ = g_base->logic->display_time(); } -auto DevConsole::HandleTextEditing(const std::string& text) -> bool { - assert(g_base->InLogicThread()); - if (state_ == State_::kInactive) { - return false; - } - - // Ignore back-tick because we use that key to toggle the console. - // - // FIXME: Perhaps should allow typing it if some control-character is - // held? - if (text == "`") { - return false; - } - input_string_ += text; - input_text_dirty_ = true; - return true; -} - void DevConsole::Print(const std::string& s_in) { assert(g_base->InLogicThread()); std::string s = Utils::GetValidUTF8(s_in.c_str(), "cspr"); @@ -1013,13 +1187,14 @@ void DevConsole::Draw(FrameDef* frame_def) { if (input_text_dirty_) { input_text_group_.SetText(input_string_); input_text_dirty_ = false; - last_input_text_change_time_ = pass->frame_def()->app_time_millisecs(); } { SimpleComponent c(pass); c.SetFlatness(1.0f); c.SetTransparent(true); c.SetColor(0.4f, 0.33f, 0.45f, 0.8f); + + // Build. int elem_count = built_text_group_.GetElementCount(); for (int e = 0; e < elem_count; e++) { c.SetTexture(built_text_group_.GetElementTexture(e)); @@ -1031,6 +1206,8 @@ void DevConsole::Draw(FrameDef* frame_def) { c.DrawMesh(built_text_group_.GetElementMesh(e)); } } + + // Title. elem_count = title_text_group_.GetElementCount(); for (int e = 0; e < elem_count; e++) { c.SetTexture(title_text_group_.GetElementTexture(e)); @@ -1041,6 +1218,8 @@ void DevConsole::Draw(FrameDef* frame_def) { c.DrawMesh(title_text_group_.GetElementMesh(e)); } } + + // Prompt. elem_count = prompt_text_group_.GetElementCount(); for (int e = 0; e < elem_count; e++) { c.SetTexture(prompt_text_group_.GetElementTexture(e)); @@ -1052,6 +1231,8 @@ void DevConsole::Draw(FrameDef* frame_def) { c.DrawMesh(prompt_text_group_.GetElementMesh(e)); } } + + // Input line. elem_count = input_text_group_.GetElementCount(); for (int e = 0; e < elem_count; e++) { c.SetTexture(input_text_group_.GetElementTexture(e)); @@ -1065,21 +1246,34 @@ void DevConsole::Draw(FrameDef* frame_def) { } // Carat. + if (!carat_mesh_.Exists()) { + UpdateCarat_(); + } millisecs_t real_time = pass->frame_def()->app_time_millisecs(); if (real_time % 200 < 100 - || (real_time - last_input_text_change_time_ < 100)) { + || (real_time - last_carat_x_change_time_ < 100)) { SimpleComponent c(pass); c.SetTransparent(true); - c.SetColor(1, 1, 1, 0.7f); + c.SetTexture(g_base->assets->SysTexture(SysTextureID::kShadow)); + c.SetColor(0.8, 0.0, 1.0, 0.3f); + // c.SetPremultiplied(true); { auto xf = c.ScopedTransform(); - c.Translate( - (19.0f - + g_base->text_graphics->GetStringWidth(input_string_) * 0.5f) - * bs, - bottom + 22.5f * bs, kDevConsoleZDepth); - c.Scale(6.0f * bs, 12.0f * bs, 1.0f); - c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1)); + auto carat_x = GetCaratX_(); + c.Translate(15.0f * bs, bottom + 14.5f * bs, kDevConsoleZDepth); + c.Scale(0.5f * bs, 0.5f * bs, 1.0f); + c.Translate(carat_x, 0.0f, 0.0f); + c.DrawMesh(carat_glow_mesh_.Get()); + } + c.SetTexture(g_base->assets->SysTexture(SysTextureID::kShadowSharp)); + c.SetColor(1.0, 1.0, 1.0, 1.0f); + { + auto xf = c.ScopedTransform(); + auto carat_x = GetCaratX_(); + c.Translate(15.0f * bs, bottom + 14.5f * bs, kDevConsoleZDepth); + c.Scale(0.5f * bs, 0.5f * bs, 1.0f); + c.Translate(carat_x, 0.0f, 0.0f); + c.DrawMesh(carat_mesh_.Get()); } } @@ -1191,4 +1385,86 @@ void DevConsole::StepDisplayTime() { } } +auto DevConsole::PasteFromClipboard() -> bool { + if (state_ != State_::kInactive) { + if (python_terminal_visible_) { + if (g_base->app_adapter->ClipboardIsSupported()) { + if (g_base->app_adapter->ClipboardHasText()) { + auto text = g_base->app_adapter->ClipboardGetText(); + if (strstr(text.c_str(), "\n") || strstr(text.c_str(), "\r")) { + g_base->audio->PlaySound( + g_base->assets->SysSound(SysSoundID::kErrorBeep)); + ScreenMessage("Can only paste single lines of text.", + Vector3f(1.0f, 0.0f, 0.0f)); + } else { + HandleTextEditing(text); + } + // Ok, we either pasted or complained, so consider it handled. + return true; + } + } + } + } + return false; +} + +void DevConsole::UpdateCarat_() { + auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjfwef"); + auto unichars_clamped = unichars; + + unichars_clamped.resize(carat_char_); + auto clamped_str = Utils::UTF8FromUnicode(unichars_clamped); + carat_x_ = g_base->text_graphics->GetStringWidth(clamped_str); + + // Use a base width if we're not covering a char, and use the char's width + // if we are. + float width = 14.0f; + if (carat_char_ < unichars.size()) { + std::vector covered_char{unichars[carat_char_]}; + auto covered_char_str = Utils::UTF8FromUnicode(covered_char); + width = + std::max(3.0f, g_base->text_graphics->GetStringWidth(covered_char_str)); + } + + float height = 32.0f; + float x_extend = 15.0f; + float y_extend = 20.0f; + float x_offset = 2.0f; + float y_offset = -0.0f; + float corner_radius = 20.0f; + float width_fin = width + x_extend * 2.0f; + float height_fin = height + y_extend * 2.0f; + float x_border = + NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin); + float y_border = + NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin); + carat_glow_mesh_ = Object::New( + -x_extend + x_offset, -y_extend + y_offset, 0.0f, width_fin, height_fin, + x_border, y_border, x_border, y_border); + + corner_radius = 3.0f; + x_extend = 0.0f; + y_extend = -3.0f; + x_offset = 1.0f; + y_offset = 0.0f; + width_fin = width + x_extend * 2.0f; + height_fin = height + y_extend * 2.0f; + x_border = + NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin); + y_border = + NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin); + carat_mesh_ = Object::New( + -x_extend + x_offset, -y_extend + y_offset, 0.0f, width_fin, height_fin, + x_border, y_border, x_border, y_border); +} + +auto DevConsole::GetCaratX_() -> float { + if (carat_dirty_) { + last_carat_x_change_time_ = g_core->GetAppTimeMillisecs(); + UpdateCarat_(); + carat_dirty_ = false; + } + return carat_x_; +} + } // namespace ballistica::base diff --git a/src/ballistica/base/ui/dev_console.h b/src/ballistica/base/ui/dev_console.h index e7134c70..7e080ace 100644 --- a/src/ballistica/base/ui/dev_console.h +++ b/src/ballistica/base/ui/dev_console.h @@ -8,6 +8,7 @@ #include #include +#include "ballistica/base/graphics/mesh/nine_patch_mesh.h" #include "ballistica/base/graphics/renderer/renderer.h" #include "ballistica/shared/foundation/object.h" #include "ballistica/shared/python/python_ref.h" @@ -32,6 +33,9 @@ class DevConsole { /// Tell the console to quietly go away no matter what state it is in. void Dismiss(); + /// Attempt to Paste. Returns true if it happened. + auto PasteFromClipboard() -> bool; + /// Print text to the console. void Print(const std::string& s_in); void Draw(FrameDef* frame_def); @@ -75,6 +79,9 @@ class DevConsole { class OutputLine_; enum class State_ : uint8_t { kInactive, kMini, kFull }; + auto CaratCharValid_() -> bool; + auto GetCaratX_() -> float; + void UpdateCarat_(); auto Bottom_() const -> float; void SubmitPythonCommand_(const std::string& command); void InvokeStringEditor_(); @@ -82,17 +89,20 @@ class DevConsole { void RefreshTabContents_(); int input_history_position_{}; - int ui_lock_count_ : 1 {}; + int ui_lock_count_{}; + int carat_char_{0}; + State_ state_{State_::kInactive}; + State_ state_prev_{State_::kInactive}; bool input_text_dirty_ : 1 {true}; bool input_enabled_ : 1 {}; bool last_line_mesh_dirty_ : 1 {true}; bool python_terminal_visible_ : 1 {}; bool python_terminal_pressed_ : 1 {}; bool refresh_pending_ : 1 {}; - double transition_start_{}; - State_ state_{State_::kInactive}; - State_ state_prev_{State_::kInactive}; - millisecs_t last_input_text_change_time_{}; + bool carat_dirty_ : 1 {true}; + float carat_x_{}; + seconds_t transition_start_{}; + millisecs_t last_carat_x_change_time_{}; ImageMesh bg_mesh_; ImageMesh stripe_mesh_; ImageMesh border_mesh_; @@ -111,6 +121,8 @@ class DevConsole { std::vector > tab_buttons_; Object::Ref last_line_mesh_group_; Object::Ref key_repeater_; + Object::Ref carat_mesh_; + Object::Ref carat_glow_mesh_; }; } // namespace ballistica::base diff --git a/src/ballistica/scene_v1/node/flag_node.cc b/src/ballistica/scene_v1/node/flag_node.cc index 05b26746..ede8eb98 100644 --- a/src/ballistica/scene_v1/node/flag_node.cc +++ b/src/ballistica/scene_v1/node/flag_node.cc @@ -5,7 +5,6 @@ #include "ballistica/base/dynamics/bg/bg_dynamics_shadow.h" #include "ballistica/base/graphics/component/object_component.h" #include "ballistica/base/graphics/component/simple_component.h" -#include "ballistica/base/graphics/graphics_server.h" #include "ballistica/base/graphics/support/area_of_interest.h" #include "ballistica/base/graphics/support/camera.h" #include "ballistica/scene_v1/assets/scene_texture.h" diff --git a/src/ballistica/scene_v1/support/scene_v1_app_mode.cc b/src/ballistica/scene_v1/support/scene_v1_app_mode.cc index 9fec9239..59b25ae8 100644 --- a/src/ballistica/scene_v1/support/scene_v1_app_mode.cc +++ b/src/ballistica/scene_v1/support/scene_v1_app_mode.cc @@ -11,7 +11,6 @@ #include "ballistica/base/python/base_python.h" #include "ballistica/base/support/app_config.h" #include "ballistica/base/support/plus_soft.h" -#include "ballistica/base/ui/ui.h" #include "ballistica/scene_v1/connection/connection_set.h" #include "ballistica/scene_v1/connection/connection_to_client_udp.h" #include "ballistica/scene_v1/connection/connection_to_host.h" diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 047ad453..8046fdc8 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 = 21516; +const int kEngineBuildNumber = 21522; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/foundation/object.h b/src/ballistica/shared/foundation/object.h index c4f39b5d..53b9eeea 100644 --- a/src/ballistica/shared/foundation/object.h +++ b/src/ballistica/shared/foundation/object.h @@ -13,15 +13,8 @@ namespace ballistica { /// Objects supporting strong and weak referencing and thread enforcement. class Object { - protected: - /// Our base constructor is marked protected because we *require* Objects - /// to be dynamically allocated. This allows us extra measures of control - /// over their construction and destruction, and it does not seem that - /// there is a pressing use case for a statically allocated Object that - /// would justify diluting that control. - Object(); - public: + Object(); virtual ~Object(); // Object classes can provide descriptive names for themselves; these are @@ -575,6 +568,10 @@ class Object { [[nodiscard]] static auto New(ARGS&&... args) -> Object::Ref { auto* ptr = new TALLOC(std::forward(args)...); #if BA_DEBUG_BUILD + /// Objects assume they are statically allocated by default; it's up + /// to us to tell them when they're not. + ptr->object_is_static_allocated_ = false; + /// Make sure things aren't creating strong refs to themselves in their /// constructors. if (ptr->object_has_been_strong_reffed_) { @@ -599,6 +596,10 @@ class Object { [[nodiscard]] static auto NewDeferred(ARGS&&... args) -> T* { T* ptr = new T(std::forward(args)...); #if BA_DEBUG_BUILD + /// Objects assume they are statically allocated by default; it's up + /// to us to tell them when they're not. + ptr->object_is_static_allocated_ = false; + /// Make sure things aren't creating strong refs to themselves in their /// constructors. if (ptr->object_has_been_strong_reffed_) { @@ -650,6 +651,9 @@ class Object { [[nodiscard]] static auto NewUnmanaged(ARGS&&... args) -> T* { T* ptr = new T(std::forward(args)...); #if BA_DEBUG_BUILD + /// Objects assume they are statically allocated by default; it's up + /// to us to tell them when they're not. + ptr->object_is_static_allocated_ = false; ptr->object_is_unmanaged_ = true; #endif return ptr; @@ -668,6 +672,7 @@ class Object { auto operator new(size_t size) -> void* { return new char[size]; } void ObjectUpdateForAcquire(); + bool object_is_static_allocated_ : 1 {true}; bool object_has_been_strong_reffed_ : 1 {}; bool object_is_ref_counted_ : 1 {}; bool object_is_pending_deferred_ : 1 {}; diff --git a/src/ballistica/ui_v1/python/ui_v1_python.cc b/src/ballistica/ui_v1/python/ui_v1_python.cc index d76ecd34..f12321b0 100644 --- a/src/ballistica/ui_v1/python/ui_v1_python.cc +++ b/src/ballistica/ui_v1/python/ui_v1_python.cc @@ -2,7 +2,6 @@ #include "ballistica/ui_v1/python/ui_v1_python.h" -#include "ballistica/base/assets/assets.h" #include "ballistica/base/audio/audio.h" #include "ballistica/base/input/device/keyboard_input.h" #include "ballistica/base/input/input.h" diff --git a/src/ballistica/ui_v1/ui_v1.cc b/src/ballistica/ui_v1/ui_v1.cc index 30083701..cf8ffc9d 100644 --- a/src/ballistica/ui_v1/ui_v1.cc +++ b/src/ballistica/ui_v1/ui_v1.cc @@ -3,10 +3,8 @@ #include "ballistica/ui_v1/ui_v1.h" #include "ballistica/base/app_mode/app_mode.h" -#include "ballistica/base/audio/audio.h" #include "ballistica/base/graphics/component/empty_component.h" #include "ballistica/base/input/input.h" -#include "ballistica/base/python/base_python.h" #include "ballistica/base/support/app_config.h" #include "ballistica/ui_v1/python/ui_v1_python.h" #include "ballistica/ui_v1/support/root_ui.h" From c2f6bf9120ae75b49d67077e23b9c36f86ec06ae Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 27 Oct 2023 08:53:00 -0700 Subject: [PATCH 12/25] lang updates and polishing --- .efrocachemap | 72 ++++++++++++++--------------- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/shared/ballistica.cc | 2 +- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 5d375637..b0333494 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,9 +421,9 @@ "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", - "build/assets/ba_data/data/langdata.json": "2a2c4783fddc4b24d07b4ce0d8a74393", - "build/assets/ba_data/data/languages/arabic.json": "295c559911fa251f401f8cdcad91c226", - "build/assets/ba_data/data/languages/belarussian.json": "e151808b6b4f6dc159cf55ee62adad3c", + "build/assets/ba_data/data/langdata.json": "d53c301a74d3b116b00f6abf5a53b16f", + "build/assets/ba_data/data/languages/arabic.json": "c21378ee214a9dd0cb2971cd46b74374", + "build/assets/ba_data/data/languages/belarussian.json": "4d89ed5f9c615771d4fa2bb1834942d3", "build/assets/ba_data/data/languages/chinese.json": "0a9d9534e7329d1e886adae6fdc007c4", "build/assets/ba_data/data/languages/chinesetraditional.json": "f858da49be0a5374157c627857751078", "build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa", @@ -432,19 +432,19 @@ "build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e", "build/assets/ba_data/data/languages/english.json": "6fb6ec37e79064edb4b8864eabdd024d", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", - "build/assets/ba_data/data/languages/filipino.json": "2efdfb879135b196a272dd47fc2039a2", + "build/assets/ba_data/data/languages/filipino.json": "afbda3adf14555e1567ee63c32e340e7", "build/assets/ba_data/data/languages/french.json": "4e218dcd488fa63e7db5b4da2261b9e1", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", "build/assets/ba_data/data/languages/gibberish.json": "63c6212c774622346f3ad0d87ff31e80", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", - "build/assets/ba_data/data/languages/indonesian.json": "53961b1484a1831f32bec2cc2941e672", - "build/assets/ba_data/data/languages/italian.json": "58ecf53a963dbeca1bbf3605e5ab6a2f", + "build/assets/ba_data/data/languages/indonesian.json": "d7f1cafecad05e0dcd34345e0088c4de", + "build/assets/ba_data/data/languages/italian.json": "b998195a8c5e745dca953ca54745a5f6", "build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2", "build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38", - "build/assets/ba_data/data/languages/persian.json": "a391d80ff58ea22926499e4b19d2c0d0", - "build/assets/ba_data/data/languages/polish.json": "7a4a6cb882cf90dad32e6607215525bf", + "build/assets/ba_data/data/languages/persian.json": "4585070bd509600019ec8dc3bb47bfb8", + "build/assets/ba_data/data/languages/polish.json": "6677925c370390f1f53bcb737cb00fa8", "build/assets/ba_data/data/languages/portuguese.json": "51e362956f89da3eec980f587c092253", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", "build/assets/ba_data/data/languages/russian.json": "561504cca28eb3204ac194950029e565", @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6e54cc75974a155e910b1095f8f559a8", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "d097531acccd231becb2a2b5bb1d2f23", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "35b551aae90a7d75f75237db93544279", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "d6081f21ed1100f44aeb4c36f7d28680", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "1d181331c45918c6d7e71630430aa011", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "1b7671e483412e63304755961e328d3f", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8ee7a3b0674e89d286e6c28b5992da30", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "a2dd4ce5321e0127bdc9e7a1c4354aa6", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d16e4cb4509fa427772c1894cc2db29d", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "7e5deafeec61b8520a4d22a5eef80f03", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "370fb623fa824ffad97750de5d1ff844", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "cf34e338f3c7d58afc70dc6742671584", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "6a075263de9be1db381eeb5ea8874ba9", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "0eef1925d2cf63eecad74e6932f624b1", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "de533e42f98a6081e96d1f7e96306fcd", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "91640f1b899fadf077d6844efdf6d37c", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c29e6e391970ede95bd90b9dec830ecc", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "2c1391f2da73fe58a2e1a815106eebf5", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "90532e99fc87ef4a8a9b1f5d9737d008", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a7bd331931da44fe268f4adda5cddb9b", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "094b4c35b814b4362548f39c606e8340", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "718ca38bd807617b717127f57b15b4db", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "187653e68c40efcaa7b0be472f3d0e11", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "d83ad495c68954582533e020741e8b67", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "9c558719c535b6caf04bd2acc3f1d814", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "dc81652da50da892eaa883fc51d05232", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "f9f2a7e0ad4a7b0b1dc70d3d3fd87bf3", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "fec33beeadac82b3110384833fe468ec", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "2ce01b857e405f5c4c8bc34ce4ceffa2", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "ec5dc2f69d87bdee515bcac8a9ed8a0c", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "7b581247e0dfc805bc2f9f6660fb4947", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "ee8fd59311c5d6f394284eb35db525ae", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "6030bf17d98bba9e46af37262001b0b9", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "c4664b39a64e86a56effd4e786fa3512", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5103e47d603b77a3e473abc7640887fb", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "543582ac07c3f388078ef84f24e85748", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "d7aaba481668cc06df15702094f85de7", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "992ccd07ef6717381ecd6c8ebf84e902", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "25a11175b27acc766ec02dc4a4ec86be", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "fd087e2654ba73cf4ddce328b012e23c", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "b257bbc06d82fc912653806c01a42c15", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "611631809a455737d7d9c0b04c89aa6b", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "bfe702cdf9cd260ab8cb4593afc6a3af", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4a367d3b2354d60259cc68fa25004eb0", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "fc5d98c16dbb42846ef653dc860f4508", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "683fafa75e39f0b33ef22cff53b124e6", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "1f9099d422aaed13d038e64b629e7827", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "76ee096dfbb8993cbb05a3425e429e0a", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "719478dd5e71b7096801f6bd0b701b4f", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7dbcf548c44407baad81a680bf08856e", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "14d512d2c10d74907653e102b5e86592", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "50865a4f46834954473d94ef217a2420", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "6ae64c31cdd77da2ef0c29e7131c9a0c", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "1791fd1babc070e7d6dfb9fe257fc8bf", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "801cb1351809a815f60decd90fe8877c", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "9652a72608a71583785bac7495a5397f", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "5072cccbd6c70f3a2183bd0242ba1f76", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index 65543034..8d078e5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21522, api 8, 2023-10-26) +### 1.7.28 (build 21523, api 8, 2023-10-27) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 653ff56d..6bc82def 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21522 +TARGET_BALLISTICA_BUILD = 21523 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 8046fdc8..2500df98 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 = 21522; +const int kEngineBuildNumber = 21523; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; From 55841a7431f30e60c973c02657b7b429eda97e42 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 27 Oct 2023 09:29:16 -0700 Subject: [PATCH 13/25] Latest public/internal sync. --- .../ba_data/python/bauiv1lib/gather/publictab.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py index 20ad8e15..fd963eec 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py @@ -963,7 +963,6 @@ class PublicGatherTab(GatherTab): self._update_party_rows() def _update_party_rows(self) -> None: - plus = bui.app.plus assert plus is not None @@ -980,10 +979,7 @@ class PublicGatherTab(GatherTab): edit=self._host_scrollwidget, claims_up_down=(len(self._parties_displayed) > 0), ) - bui.textwidget( - edit=self._no_servers_text, - text='' - ) + bui.textwidget(edit=self._no_servers_text, text='') # Clip if we have more UI rows than parties to show. clipcount = len(self._ui_rows) - len(self._parties_displayed) @@ -997,10 +993,10 @@ class PublicGatherTab(GatherTab): if ( plus.get_v1_account_state() == 'signed_in' and cast(str, bui.textwidget(query=text)) == '' - ): + ): bui.textwidget( edit=self._no_servers_text, - text=bui.Lstr(resource='noServerFoundText') + text=bui.Lstr(resource='noServerFoundText'), ) return From f31087db646bd872ea550057fc194be3668c8a05 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 27 Oct 2023 10:08:56 -0700 Subject: [PATCH 14/25] tidying up PRs --- .efrocachemap | 44 +++++++++---------- CHANGELOG.md | 9 +++- src/assets/ba_data/python/baenv.py | 2 +- .../ba_data/python/bascenev1/_session.py | 14 ++++-- .../python/bauiv1lib/gather/publictab.py | 10 ++--- src/ballistica/base/graphics/graphics.cc | 6 ++- src/ballistica/shared/ballistica.cc | 2 +- src/ballistica/ui_v1/widget/text_widget.cc | 11 +++-- 8 files changed, 59 insertions(+), 39 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index b0333494..5451b16b 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -430,12 +430,12 @@ "build/assets/ba_data/data/languages/czech.json": "93c5fe0d884d95435da6c675f64e30e0", "build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e", "build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e", - "build/assets/ba_data/data/languages/english.json": "6fb6ec37e79064edb4b8864eabdd024d", + "build/assets/ba_data/data/languages/english.json": "b0c8dc8bd35a5606e5d3318d7cb52cba", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/filipino.json": "afbda3adf14555e1567ee63c32e340e7", "build/assets/ba_data/data/languages/french.json": "4e218dcd488fa63e7db5b4da2261b9e1", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", - "build/assets/ba_data/data/languages/gibberish.json": "63c6212c774622346f3ad0d87ff31e80", + "build/assets/ba_data/data/languages/gibberish.json": "d9022a7e655da5ac41b9cef7f3b114a6", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "094b4c35b814b4362548f39c606e8340", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "718ca38bd807617b717127f57b15b4db", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "187653e68c40efcaa7b0be472f3d0e11", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "d83ad495c68954582533e020741e8b67", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "9c558719c535b6caf04bd2acc3f1d814", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "dc81652da50da892eaa883fc51d05232", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "f9f2a7e0ad4a7b0b1dc70d3d3fd87bf3", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "fec33beeadac82b3110384833fe468ec", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "2ce01b857e405f5c4c8bc34ce4ceffa2", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "ec5dc2f69d87bdee515bcac8a9ed8a0c", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "7b581247e0dfc805bc2f9f6660fb4947", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "ee8fd59311c5d6f394284eb35db525ae", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "6030bf17d98bba9e46af37262001b0b9", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "c4664b39a64e86a56effd4e786fa3512", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5103e47d603b77a3e473abc7640887fb", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "543582ac07c3f388078ef84f24e85748", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "d7aaba481668cc06df15702094f85de7", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "992ccd07ef6717381ecd6c8ebf84e902", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "25a11175b27acc766ec02dc4a4ec86be", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "fd087e2654ba73cf4ddce328b012e23c", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "b5f5272bf4b390ebfa144474f65d1fdc", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "1c4b400a17662dd30ca597772d1ae38d", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "2abf39c5efb01fb97559f8818dbd4210", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "2d446e30ca6d2d9d65c1c2ebed2b7485", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "9586be74d1f801fdae227ee508ff84ee", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "ce099f4bfbdf1c57f83b23fff97c554e", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "caf89cb6fc0d745490766f2fc4982c99", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "fe8bfae5f47af29da1bc6a387b6fa999", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "889737fad009958817a09c1018c56ad3", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "4c4d570c468e3f21813860311b3bf8a5", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "58735d1e9cf8d9beaf57a9291c4c38d2", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "d5c3ff47f16d668a1e26c16611890767", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "93883b7e8933955a733f51abe07dc8ec", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "0ca0076dc51f986ae6fad3b7bf2da507", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "d4e32f23bf4a6bac11d9dc9809fac181", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "aad14a5bf8bbb0731cf8886967995118", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "9a99df09f0d09da7e929a8aeb4d39205", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "bbbc58ea77b688f3c4b4edb406f7efbc", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "14f284fa6ac9e4fdcb4e0976a73c3969", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "926ebddaa448b27b2841104b5139c83a", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", diff --git a/CHANGELOG.md b/CHANGELOG.md index 80965ef3..91087c5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21523, api 8, 2023-10-27) +### 1.7.28 (build 21524, api 8, 2023-10-27) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years @@ -167,6 +167,13 @@ - Added clipboard paste support to the dev console python terminal. - Added various text editing functionality to the dev console python terminal (cursor movement, deleting chars and words, etc.) +- Internal on-screen-keyboard now has a cancel button (thanks vishal332008!) +- Public servers list now shows 'No servers found' if there are no servers to + show instead of just remaining mysteriously blank (thanks vishal332008!) +- Players are now prevented from rejoining a session for 10 seconds after they + leave to prevent game exploits. Note this is different than the existing + system that prevents joining a *party* for 10 seconds; this covers people + who never leave the party (Thanks EraOSBeta!). ### 1.7.27 (build 21282, api 8, 2023-08-30) diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 6bc82def..99237e60 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21523 +TARGET_BALLISTICA_BUILD = 21524 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bascenev1/_session.py b/src/assets/ba_data/python/bascenev1/_session.py index 481249d9..843db5d3 100644 --- a/src/assets/ba_data/python/bascenev1/_session.py +++ b/src/assets/ba_data/python/bascenev1/_session.py @@ -18,7 +18,10 @@ if TYPE_CHECKING: import bascenev1 -TIMEOUT = 10 +# How long someone who left the session (but not the party) must +# wait to rejoin the session again. Intended to prevent game exploits +# such as skipping respawn waits. +REJOIN_COOLDOWN = 10 class Session: @@ -206,6 +209,7 @@ class Session: # Instantiate our session globals node which will apply its settings. self._sessionglobalsnode = _bascenev1.newnode('sessionglobals') + # Rejoin cooldown stuff. self._players_on_wait: dict = {} self._player_requested_identifiers: dict = {} self._waitlist_timers: dict = {} @@ -260,11 +264,14 @@ class Session: ) return False + # Rejoin cooldown. identifier = player.get_v1_account_id() if identifier: leave_time = self._players_on_wait.get(identifier) if leave_time: - diff = str(math.ceil(TIMEOUT - babase.apptime() + leave_time)) + diff = str( + math.ceil(REJOIN_COOLDOWN - babase.apptime() + leave_time) + ) _bascenev1.broadcastmessage( babase.Lstr( translate=( @@ -297,12 +304,13 @@ class Session: activity = self._activity_weak() + # Rejoin cooldown. identifier = self._player_requested_identifiers.get(sessionplayer.id) if identifier: self._players_on_wait[identifier] = babase.apptime() with babase.ContextRef.empty(): self._waitlist_timers[identifier] = babase.AppTimer( - TIMEOUT, + REJOIN_COOLDOWN, babase.Call(self._remove_player_from_waitlist, identifier), ) diff --git a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py index fd963eec..dc2b2dc3 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py @@ -361,7 +361,7 @@ class PublicGatherTab(GatherTab): self._last_server_list_query_time: float | None = None self._join_list_column: bui.Widget | None = None self._join_status_text: bui.Widget | None = None - self._no_servers_text: bui.Widget | None = None + self._no_servers_found_text: bui.Widget | None = None self._host_max_party_size_value: bui.Widget | None = None self._host_max_party_size_minus_button: (bui.Widget | None) = None self._host_max_party_size_plus_button: (bui.Widget | None) = None @@ -659,7 +659,7 @@ class PublicGatherTab(GatherTab): color=(0.6, 0.6, 0.6), position=(c_width * 0.5, c_height * 0.5), ) - self._no_servers_text = bui.textwidget( + self._no_servers_found_text = bui.textwidget( parent=self._container, text='', size=(0, 0), @@ -979,7 +979,7 @@ class PublicGatherTab(GatherTab): edit=self._host_scrollwidget, claims_up_down=(len(self._parties_displayed) > 0), ) - bui.textwidget(edit=self._no_servers_text, text='') + bui.textwidget(edit=self._no_servers_found_text, text='') # Clip if we have more UI rows than parties to show. clipcount = len(self._ui_rows) - len(self._parties_displayed) @@ -995,8 +995,8 @@ class PublicGatherTab(GatherTab): and cast(str, bui.textwidget(query=text)) == '' ): bui.textwidget( - edit=self._no_servers_text, - text=bui.Lstr(resource='noServerFoundText'), + edit=self._no_servers_found_text, + text=bui.Lstr(resource='noServersFoundText'), ) return diff --git a/src/ballistica/base/graphics/graphics.cc b/src/ballistica/base/graphics/graphics.cc index 7bc51e39..790f955d 100644 --- a/src/ballistica/base/graphics/graphics.cc +++ b/src/ballistica/base/graphics/graphics.cc @@ -600,7 +600,7 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { } else { a = 1; } - a *= 0.8f; + a *= 0.7f; // if (vr) { // a *= 0.8f; @@ -631,6 +631,8 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { if (age < 100) { fade = 1.0f; } else { + // Don't fade ALL the way to black; leaves a tiny bit of color + // showing which looks nice. fade = std::max(0.07f, (200.0f - static_cast(age)) / 100.0f); } c.SetColor(r * fade, g * fade, b * fade, a); @@ -1969,7 +1971,7 @@ auto Graphics::ScreenMessageEntry::GetText() -> TextGroup& { if (!top_style) { float x_extend = 40.0f; float y_extend = 40.0f; - float y_offset = -10.0f; + float y_offset = -5.0f; float corner_radius = 60.0f; float width_fin = str_width + x_extend * 2.0f; float height_fin = str_height + y_extend * 2.0f; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 2500df98..c852613d 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 = 21523; +const int kEngineBuildNumber = 21524; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/ui_v1/widget/text_widget.cc b/src/ballistica/ui_v1/widget/text_widget.cc index c6b02019..61781355 100644 --- a/src/ballistica/ui_v1/widget/text_widget.cc +++ b/src/ballistica/ui_v1/widget/text_widget.cc @@ -468,6 +468,11 @@ void TextWidget::set_res_scale(float res_scale) { void TextWidget::SetText(const std::string& text_in_raw) { std::string text_in = Utils::GetValidUTF8(text_in_raw.c_str(), "twst1"); + // Ignore redundant sets. + if (text_in == text_raw_) { + return; + } + // In some cases we want to make sure this is a valid resource-string // since catching the error here is much more useful than if we catch // it at draw-time. However this is expensive so we only do it for debug @@ -510,10 +515,6 @@ void TextWidget::SetText(const std::string& text_in_raw) { Python::PrintStackTrace(); } } - if (text_in != text_raw_) { - text_translation_dirty_ = true; - } - text_raw_ = text_in; // Do our clamping in unicode-space. if (Utils::UTF8StringLength(text_raw_.c_str()) > max_chars_) { @@ -522,6 +523,8 @@ void TextWidget::SetText(const std::string& text_in_raw) { uni.resize(static_cast(max_chars_)); text_raw_ = Utils::UTF8FromUnicode(uni); } + text_translation_dirty_ = true; + text_raw_ = text_in; carat_position_ = 9999; } From 03675a22a3df384c0ac73fd775efdbd2c399d719 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 27 Oct 2023 10:28:59 -0700 Subject: [PATCH 15/25] fix for server join-request flood attack --- .efrocachemap | 40 +++++++++---------- CHANGELOG.md | 4 +- src/assets/ba_data/python/baenv.py | 2 +- .../support/client_input_device_delegate.cc | 8 +++- .../support/scene_v1_input_device_delegate.cc | 4 +- src/ballistica/shared/ballistica.cc | 2 +- 6 files changed, 34 insertions(+), 26 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 5451b16b..f7d58d47 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "b5f5272bf4b390ebfa144474f65d1fdc", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "1c4b400a17662dd30ca597772d1ae38d", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "2abf39c5efb01fb97559f8818dbd4210", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "2d446e30ca6d2d9d65c1c2ebed2b7485", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "9586be74d1f801fdae227ee508ff84ee", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "ce099f4bfbdf1c57f83b23fff97c554e", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "caf89cb6fc0d745490766f2fc4982c99", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "fe8bfae5f47af29da1bc6a387b6fa999", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "889737fad009958817a09c1018c56ad3", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "4c4d570c468e3f21813860311b3bf8a5", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "58735d1e9cf8d9beaf57a9291c4c38d2", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "d5c3ff47f16d668a1e26c16611890767", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "93883b7e8933955a733f51abe07dc8ec", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "0ca0076dc51f986ae6fad3b7bf2da507", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "d4e32f23bf4a6bac11d9dc9809fac181", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "aad14a5bf8bbb0731cf8886967995118", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "9a99df09f0d09da7e929a8aeb4d39205", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "bbbc58ea77b688f3c4b4edb406f7efbc", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "14f284fa6ac9e4fdcb4e0976a73c3969", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "926ebddaa448b27b2841104b5139c83a", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "bd21ea70f4aace3ddd6e86d19ca04707", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "eb9196d69cb13de5c02f8f205396ac8d", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "20e1738da78d266882053a21ad74d2d4", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "f2a2815bbfcbeff6041ade83999132a6", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "21c30ed4e87963efa9bbb401903d9bdd", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "ee324f4377ffe3135f0ce6ad62609281", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "76046cdfbb2ee3a2906b230f347c4361", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "ef80af070e2fecda641469df8828375a", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "7ff933a5f3a8bac754897df4a3e3d723", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "c4d26e212c3c824e25cf5bbf27465f34", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "0ab3966d350a39c39a28fa7b93ef1d08", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "e76707372e761bfd1d3b1d56cb76b91f", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f1581f72dbfe22cf7ba5be436e80a5a3", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "b52af8580dcd6cac224d840a043be2a4", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "3fb98c6e7c82b533441c437188bbd1ce", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ba62c05d2486524a2eef989898a4e57f", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e872cfeade334bf471ce71f536571ff3", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d688622611dde4d4b3ef0e14f87d0931", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "81887892b133fdf6df2249f8b1265e50", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "9325a017d3382c6979afd0d597727c46", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", diff --git a/CHANGELOG.md b/CHANGELOG.md index 91087c5a..71a6bcdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21524, api 8, 2023-10-27) +### 1.7.28 (build 21525, api 8, 2023-10-27) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years @@ -174,6 +174,8 @@ leave to prevent game exploits. Note this is different than the existing system that prevents joining a *party* for 10 seconds; this covers people who never leave the party (Thanks EraOSBeta!). +- Fixes an issue where servers could be crashed by flooding them with join + requests (Thanks for the heads-up Era!). ### 1.7.27 (build 21282, api 8, 2023-08-30) diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 99237e60..1dd9e557 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21524 +TARGET_BALLISTICA_BUILD = 21525 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/scene_v1/support/client_input_device_delegate.cc b/src/ballistica/scene_v1/support/client_input_device_delegate.cc index 8c0972ca..1d2ef24d 100644 --- a/src/ballistica/scene_v1/support/client_input_device_delegate.cc +++ b/src/ballistica/scene_v1/support/client_input_device_delegate.cc @@ -29,8 +29,14 @@ void ClientInputDeviceDelegate::AttachToLocalPlayer(Player* player) { } // We also need to send an old-style message as a fallback. + // // FIXME: Can remove this once backwards-compat-protocol is > 29. - { + // + // UPDATE: Only send this if player id fits. This could cause problems + // for older clients in very rare cases, but the only alternative is + // to not support those clients. I doubt there are many such old + // clients out there anyway. + if (player->id() < 256) { std::vector data(3); data[0] = BA_MESSAGE_ATTACH_REMOTE_PLAYER; data[1] = static_cast_check_fit(remote_device_id_); diff --git a/src/ballistica/scene_v1/support/scene_v1_input_device_delegate.cc b/src/ballistica/scene_v1/support/scene_v1_input_device_delegate.cc index c516adf1..0afe1ccf 100644 --- a/src/ballistica/scene_v1/support/scene_v1_input_device_delegate.cc +++ b/src/ballistica/scene_v1/support/scene_v1_input_device_delegate.cc @@ -73,8 +73,8 @@ void SceneV1InputDeviceDelegate::RequestPlayer() { return; } - // If we have a local host-session, ask it for a player.. otherwise if we have - // a client-session, ask it for a player. + // If we have a local host-session, ask it for a player.. otherwise if we + // have a client-session, ask it for a player. assert(g_base->logic); if (auto* hs = dynamic_cast(appmode->GetForegroundSession())) { { diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index c852613d..70294d7f 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 = 21524; +const int kEngineBuildNumber = 21525; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; From 1115983bcc6cef177bb241b8662cdeb68e4d7974 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 27 Oct 2023 15:58:10 -0700 Subject: [PATCH 16/25] various input and config cleanup --- .efrocachemap | 56 ++++++------- CHANGELOG.md | 18 ++++- src/assets/.asset_manifest_public.json | 2 - src/assets/Makefile | 2 - src/assets/ba_data/python/babase/_app.py | 16 +--- .../ba_data/python/babase/_appconfig.py | 41 ++-------- src/assets/ba_data/python/baclassic/_input.py | 9 ++- .../ba_data/python/baclassic/_subsystem.py | 9 --- src/assets/ba_data/python/baenv.py | 2 +- .../bascenev1lib/actor/controlsguide.py | 77 ++++++------------ .../ba_data/python/bauiv1lib/configerror.py | 80 ------------------- .../python/bauiv1lib/settings/gamepad.py | 73 ++++++++--------- .../bauiv1lib/settings/gamepadadvanced.py | 2 +- .../python/bauiv1lib/settings/keyboard.py | 8 +- .../base/input/device/joystick_input.cc | 7 +- .../base/input/device/joystick_input.h | 6 +- .../base/python/methods/python_methods_app.cc | 2 +- src/ballistica/base/ui/dev_console.cc | 8 +- src/ballistica/shared/ballistica.cc | 2 +- 19 files changed, 145 insertions(+), 275 deletions(-) delete mode 100644 src/assets/ba_data/python/bauiv1lib/configerror.py diff --git a/.efrocachemap b/.efrocachemap index f7d58d47..95a2a68d 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "bd21ea70f4aace3ddd6e86d19ca04707", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "eb9196d69cb13de5c02f8f205396ac8d", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "20e1738da78d266882053a21ad74d2d4", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "f2a2815bbfcbeff6041ade83999132a6", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "21c30ed4e87963efa9bbb401903d9bdd", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "ee324f4377ffe3135f0ce6ad62609281", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "76046cdfbb2ee3a2906b230f347c4361", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "ef80af070e2fecda641469df8828375a", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "7ff933a5f3a8bac754897df4a3e3d723", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "c4d26e212c3c824e25cf5bbf27465f34", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "0ab3966d350a39c39a28fa7b93ef1d08", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "e76707372e761bfd1d3b1d56cb76b91f", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f1581f72dbfe22cf7ba5be436e80a5a3", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "b52af8580dcd6cac224d840a043be2a4", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "3fb98c6e7c82b533441c437188bbd1ce", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ba62c05d2486524a2eef989898a4e57f", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e872cfeade334bf471ce71f536571ff3", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d688622611dde4d4b3ef0e14f87d0931", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "81887892b133fdf6df2249f8b1265e50", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "9325a017d3382c6979afd0d597727c46", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "637b3e06d6536db39d816e0b5820c0ab", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "e3a0ad82944e80528a227807a9a9ba6d", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f8252819a3d84a2c3be5e3ed938e5f8b", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "7e8682e4ef71b0d432576ce8f879b3b2", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "eb3a79d46714a2585da45f66ae5352eb", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "1ebb8b160059182d79b586f40f4bb207", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "b51ff49b8e145ebee0d5a3f8c2e517fb", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "9eecb06461e9798439c4d15399b7d28a", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "7ffd1e3961eb68f820ff044f2ba62cf9", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "3ab890f1e4116739bce0e2c141440773", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d6d47b5b7bf720c0936a53deffe07359", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0ce0fcd7d19e767db721eb43f58424f7", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "4fac89dcba67096cd2f84f0b687b1880", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "0df3b09ffdf3dc519cea1a3a9fb959d2", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "8eb92b2fa10d56cfee3fd8da179cfda7", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "b0764a6280bfbe926b655df8f946e8e2", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "f69383ecdafab7a37907898fcbf98fa1", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "617e7ca8f4ed3d3f726ba9567a15732e", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9133fee71d08209b5ac82f772edae5c9", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "1cfd194e81bb849e337b34df43157ba8", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "b257bbc06d82fc912653806c01a42c15", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7dbcf548c44407baad81a680bf08856e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "14d512d2c10d74907653e102b5e86592", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "50865a4f46834954473d94ef217a2420", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "6ae64c31cdd77da2ef0c29e7131c9a0c", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "1791fd1babc070e7d6dfb9fe257fc8bf", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "801cb1351809a815f60decd90fe8877c", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "9652a72608a71583785bac7495a5397f", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "5072cccbd6c70f3a2183bd0242ba1f76", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "693493fea9a0068d67d05ac32c53d938", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "0ad9cd9671e260ea90f97a3334a063d0", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "0dc8f56e25b1bb2b67bdb6f1b65c56b6", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "02bfe33e3189d0993aff1884cae95ccf", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "7867875c532b032ace05fef64e278635", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "7dfdd479341808a7301158591caac092", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "3604c049578423bce477d0be543529f4", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "57b11043daad1545cd2abb0c13f43db7", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index 71a6bcdb..1a6d0354 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21525, api 8, 2023-10-27) +### 1.7.28 (build 21528, api 8, 2023-10-27) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years @@ -176,6 +176,22 @@ who never leave the party (Thanks EraOSBeta!). - Fixes an issue where servers could be crashed by flooding them with join requests (Thanks for the heads-up Era!). +- The engine will now ignore empty device config dicts and fall back to + defaults; these could theoretically happen if device config code fails + somewhere and it previously would leave the device mysteriously inoperable. +- The game will now show for controls with no bindings in the in-game + guide and controller/keyboard config screens. +- Fixed a crash that could occur if SDL couldn't find a name for connected + joystick. +- Simplified the app's handling of broken config files. Previously it would do + various complex things such as offering to edit the broken config on desktop + builds, avoiding overwriting broken configs, and automatically loading + previous configs. Now, if it finds a broken config, it will simply back it up + to a .broken file, log an error message, and then start up normally with a + default config. This way, things are more consistent across platforms, and + technical users can still fix and restore their old configs. Note that the app + still also writes .prev configs for extra security, though it no longer uses + them for anything itself. ### 1.7.27 (build 21282, api 8, 2023-08-30) diff --git a/src/assets/.asset_manifest_public.json b/src/assets/.asset_manifest_public.json index 9c4f56a5..4ff9c920 100644 --- a/src/assets/.asset_manifest_public.json +++ b/src/assets/.asset_manifest_public.json @@ -366,7 +366,6 @@ "ba_data/python/bauiv1lib/__pycache__/characterpicker.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/colorpicker.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/config.cpython-311.opt-1.pyc", - "ba_data/python/bauiv1lib/__pycache__/configerror.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/confirm.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/continues.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/__pycache__/creditslist.cpython-311.opt-1.pyc", @@ -417,7 +416,6 @@ "ba_data/python/bauiv1lib/characterpicker.py", "ba_data/python/bauiv1lib/colorpicker.py", "ba_data/python/bauiv1lib/config.py", - "ba_data/python/bauiv1lib/configerror.py", "ba_data/python/bauiv1lib/confirm.py", "ba_data/python/bauiv1lib/continues.py", "ba_data/python/bauiv1lib/coop/__init__.py", diff --git a/src/assets/Makefile b/src/assets/Makefile index 5af7a60c..b801f3c5 100644 --- a/src/assets/Makefile +++ b/src/assets/Makefile @@ -341,7 +341,6 @@ SCRIPT_TARGETS_PY_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/characterpicker.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/colorpicker.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/config.py \ - $(BUILD_DIR)/ba_data/python/bauiv1lib/configerror.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/confirm.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/continues.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/coop/__init__.py \ @@ -615,7 +614,6 @@ SCRIPT_TARGETS_PYC_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/characterpicker.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/colorpicker.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/config.cpython-311.opt-1.pyc \ - $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/configerror.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/confirm.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/continues.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/coop/__pycache__/__init__.cpython-311.opt-1.pyc \ diff --git a/src/assets/ba_data/python/babase/_app.py b/src/assets/ba_data/python/babase/_app.py index c22aee9f..b014d677 100644 --- a/src/assets/ba_data/python/babase/_app.py +++ b/src/assets/ba_data/python/babase/_app.py @@ -184,7 +184,6 @@ class App: # foregrounded; can be a simple way to determine if network data # should be refreshed/etc. self.fg_state = 0 - self.config_file_healthy: bool = False self._subsystems: list[AppSubsystem] = [] self._native_bootstrapping_completed = False @@ -433,7 +432,7 @@ class App: """(internal)""" from babase._appconfig import read_app_config - self._config, self.config_file_healthy = read_app_config() + self._config = read_app_config() def handle_deep_link(self, url: str) -> None: """Handle a deep link URL.""" @@ -583,19 +582,6 @@ class App: self._aioloop = _asyncio.setup_asyncio() self.health_monitor = AppHealthMonitor() - # Only proceed if our config file is healthy so we don't - # overwrite a broken one or whatnot and wipe out data. - if not self.config_file_healthy: - if self.classic is not None: - handled = self.classic.show_config_error_window() - if handled: - return - - # For now on other systems we just overwrite the bum config. - # At this point settings are already set; lets just commit - # them to disk. - _appconfig.commit_app_config(force=True) - # __FEATURESET_APP_SUBSYSTEM_CREATE_BEGIN__ # This section generated by batools.appmodule; do not edit. diff --git a/src/assets/ba_data/python/babase/_appconfig.py b/src/assets/ba_data/python/babase/_appconfig.py index f34ff8ab..92efc73c 100644 --- a/src/assets/ba_data/python/babase/_appconfig.py +++ b/src/assets/ba_data/python/babase/_appconfig.py @@ -101,15 +101,13 @@ class AppConfig(dict): self.commit() -def read_app_config() -> tuple[AppConfig, bool]: +def read_app_config() -> AppConfig: """Read the app config.""" import os import json - config_file_healthy = False - - # NOTE: it is assumed that this only gets called once and the - # config object will not change from here on out + # NOTE: it is assumed that this only gets called once and the config + # object will not change from here on out config_file_path = _babase.app.env.config_file_path config_contents = '' try: @@ -119,20 +117,16 @@ def read_app_config() -> tuple[AppConfig, bool]: config = AppConfig(json.loads(config_contents)) else: config = AppConfig() - config_file_healthy = True except Exception: logging.exception( - "Error reading config file at time %.3f: '%s'.", + "Error reading config file '%s' at time %.3f.\n" + "Backing up broken config to'%s.broken'.", + config_file_path, _babase.apptime(), config_file_path, ) - # Whenever this happens lets back up the broken one just in case it - # gets overwritten accidentally. - logging.info( - "Backing up current config file to '%s.broken'", config_file_path - ) try: import shutil @@ -141,23 +135,10 @@ def read_app_config() -> tuple[AppConfig, bool]: logging.exception('Error copying broken config.') config = AppConfig() - # Now attempt to read one of our 'prev' backup copies. - prev_path = config_file_path + '.prev' - try: - if os.path.exists(prev_path): - with open(prev_path, encoding='utf-8') as infile: - config_contents = infile.read() - config = AppConfig(json.loads(config_contents)) - else: - config = AppConfig() - config_file_healthy = True - logging.info('Successfully read backup config.') - except Exception: - logging.exception('Error reading prev backup config.') - return config, config_file_healthy + return config -def commit_app_config(force: bool = False) -> None: +def commit_app_config() -> None: """Commit the config to persistent storage. Category: **General Utility Functions** @@ -167,10 +148,4 @@ def commit_app_config(force: bool = False) -> None: plus = _babase.app.plus assert plus is not None - if not _babase.app.config_file_healthy and not force: - logging.warning( - 'Current config file is broken; ' - 'skipping write to avoid losing settings.' - ) - return plus.mark_config_dirty() diff --git a/src/assets/ba_data/python/baclassic/_input.py b/src/assets/ba_data/python/baclassic/_input.py index e3cc0546..6d60b50a 100644 --- a/src/assets/ba_data/python/baclassic/_input.py +++ b/src/assets/ba_data/python/baclassic/_input.py @@ -40,7 +40,14 @@ def get_input_device_mapped_value( mapping = ccfgs[devicename][unique_id] elif 'default' in ccfgs[devicename]: mapping = ccfgs[devicename]['default'] - if mapping is not None: + + # We now use the config mapping *only* if it is not empty. + # There have been cases of config writing code messing up + # and leaving empty dicts in the app config, which currently + # leaves the device unusable. Alternatively, we'd perhaps + # want to fall back to defaults for individual missing + # values, but that is a bigger change we can make later. + if isinstance(mapping, dict) and mapping: return mapping.get(name, -1) if platform == 'windows': diff --git a/src/assets/ba_data/python/baclassic/_subsystem.py b/src/assets/ba_data/python/baclassic/_subsystem.py index 757661fc..f8aba3bc 100644 --- a/src/assets/ba_data/python/baclassic/_subsystem.py +++ b/src/assets/ba_data/python/baclassic/_subsystem.py @@ -627,15 +627,6 @@ class ClassicSubsystem(babase.AppSubsystem): """(internal)""" return bascenev1.get_foreground_host_activity() - def show_config_error_window(self) -> bool: - """(internal)""" - if self.platform in ('mac', 'linux', 'windows'): - from bauiv1lib.configerror import ConfigErrorWindow - - babase.pushcall(ConfigErrorWindow) - return True - return False - def value_test( self, arg: str, diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 1dd9e557..55329257 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21525 +TARGET_BALLISTICA_BUILD = 21528 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py b/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py index 18854e5d..e29245b6 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py @@ -264,10 +264,19 @@ class ControlsGuide(bs.Actor): bs.timer(delay, bs.WeakCall(self._start_updating)) @staticmethod - def _meaningful_button_name(device: bs.InputDevice, button: int) -> str: + def _meaningful_button_name( + device: bs.InputDevice, button_name: str + ) -> str: """Return a flattened string button name; empty for non-meaningful.""" if not device.has_meaningful_button_names: return '' + assert bs.app.classic is not None + button = bs.app.classic.get_input_device_mapped_value( + device, button_name + ) + # -1 means unset; let's show that. + if button == -1: + return bs.Lstr(resource='configGamepadWindow.unsetText').evaluate() return device.get_button_name(button).evaluate() def _start_updating(self) -> None: @@ -289,10 +298,10 @@ class ControlsGuide(bs.Actor): def _check_fade_in(self) -> None: assert bs.app.classic is not None - # If we have a touchscreen, we only fade in if we have a player with - # an input device that is *not* the touchscreen. - # (otherwise it is confusing to see the touchscreen buttons right - # next to our display buttons) + # If we have a touchscreen, we only fade in if we have a player + # with an input device that is *not* the touchscreen. Otherwise + # it is confusing to see the touchscreen buttons right next to + # our display buttons. touchscreen: bs.InputDevice | None = bs.getinputdevice( 'TouchScreen', '#1', doraise=False ) @@ -318,15 +327,7 @@ class ControlsGuide(bs.Actor): 'buttonBomb', 'buttonPickUp', ): - if ( - self._meaningful_button_name( - device, - bs.app.classic.get_input_device_mapped_value( - device, name - ), - ) - != '' - ): + if self._meaningful_button_name(device, name) != '': fade_in = True break if fade_in: @@ -401,58 +402,30 @@ class ControlsGuide(bs.Actor): # We only care about movement buttons in the case of keyboards. if all_keyboards: right_button_names.add( - device.get_button_name( - classic.get_input_device_mapped_value( - device, 'buttonRight' - ) - ) + self._meaningful_button_name(device, 'buttonRight') ) left_button_names.add( - device.get_button_name( - classic.get_input_device_mapped_value( - device, 'buttonLeft' - ) - ) + self._meaningful_button_name(device, 'buttonLeft') ) down_button_names.add( - device.get_button_name( - classic.get_input_device_mapped_value( - device, 'buttonDown' - ) - ) + self._meaningful_button_name(device, 'buttonDown') ) up_button_names.add( - device.get_button_name( - classic.get_input_device_mapped_value( - device, 'buttonUp' - ) - ) + self._meaningful_button_name(device, 'buttonUp') ) # Ignore empty values; things like the remote app or # wiimotes can return these. - bname = self._meaningful_button_name( - device, - classic.get_input_device_mapped_value(device, 'buttonPunch'), - ) + bname = self._meaningful_button_name(device, 'buttonPunch') if bname != '': punch_button_names.add(bname) - bname = self._meaningful_button_name( - device, - classic.get_input_device_mapped_value(device, 'buttonJump'), - ) + bname = self._meaningful_button_name(device, 'buttonJump') if bname != '': jump_button_names.add(bname) - bname = self._meaningful_button_name( - device, - classic.get_input_device_mapped_value(device, 'buttonBomb'), - ) + bname = self._meaningful_button_name(device, 'buttonBomb') if bname != '': bomb_button_names.add(bname) - bname = self._meaningful_button_name( - device, - classic.get_input_device_mapped_value(device, 'buttonPickUp'), - ) + bname = self._meaningful_button_name(device, 'buttonPickUp') if bname != '': pickup_button_names.add(bname) @@ -582,8 +555,8 @@ class ControlsGuide(bs.Actor): if msg.immediate: self._die() else: - # If they don't need immediate, - # fade out our nodes and die later. + # If they don't need immediate, fade out our nodes and + # die later. for node in self._nodes: bs.animate(node, 'opacity', {0: node.opacity, 3.0: 0.0}) bs.timer(3.1, bs.WeakCall(self._die)) diff --git a/src/assets/ba_data/python/bauiv1lib/configerror.py b/src/assets/ba_data/python/bauiv1lib/configerror.py deleted file mode 100644 index c64a31d6..00000000 --- a/src/assets/ba_data/python/bauiv1lib/configerror.py +++ /dev/null @@ -1,80 +0,0 @@ -# Released under the MIT License. See LICENSE for details. -# -"""UI for dealing with broken config files.""" - -from __future__ import annotations - -import bauiv1 as bui - - -class ConfigErrorWindow(bui.Window): - """Window for dealing with a broken config.""" - - def __init__(self) -> None: - self._config_file_path = bui.app.env.config_file_path - width = 800 - super().__init__( - bui.containerwidget(size=(width, 400), transition='in_right') - ) - padding = 20 - bui.textwidget( - parent=self._root_widget, - position=(padding, 220 + 60), - size=(width - 2 * padding, 100 - 2 * padding), - h_align='center', - v_align='top', - scale=0.73, - text=( - f'Error reading {bui.appnameupper()} config file' - ':\n\n\nCheck the console' - ' (press ~ twice) for details.\n\nWould you like to quit and' - ' try to fix it by hand\nor overwrite it with defaults?\n\n' - '(high scores, player profiles, etc will be lost if you' - ' overwrite)' - ), - ) - bui.textwidget( - parent=self._root_widget, - position=(padding, 198 + 60), - size=(width - 2 * padding, 100 - 2 * padding), - h_align='center', - v_align='top', - scale=0.5, - text=self._config_file_path, - ) - quit_button = bui.buttonwidget( - parent=self._root_widget, - position=(35, 30), - size=(240, 54), - label='Quit and Edit', - on_activate_call=self._quit, - ) - bui.buttonwidget( - parent=self._root_widget, - position=(width - 370, 30), - size=(330, 54), - label='Overwrite with Defaults', - on_activate_call=self._defaults, - ) - bui.containerwidget( - edit=self._root_widget, - cancel_button=quit_button, - selected_child=quit_button, - ) - - def _quit(self) -> None: - bui.apptimer(0.001, self._edit_and_quit) - bui.lock_all_input() - - def _edit_and_quit(self) -> None: - bui.open_file_externally(self._config_file_path) - bui.apptimer(0.1, bui.quit) - - def _defaults(self) -> None: - bui.containerwidget(edit=self._root_widget, transition='out_left') - bui.getsound('gunCocking').play() - bui.screenmessage('settings reset.', color=(1, 1, 0)) - - # At this point settings are already set; lets just commit them - # to disk. - bui.commit_app_config(force=True) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py index c9780d15..eeb12dad 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py @@ -545,20 +545,25 @@ class GamepadSettingsWindow(bui.Window): if 'analogStickLR' + self._ext in self._settings else 5 if self._is_secondary - else 1 + else None ) sval2 = ( self._settings['analogStickUD' + self._ext] if 'analogStickUD' + self._ext in self._settings else 6 if self._is_secondary - else 2 - ) - return ( - self._input.get_axis_name(sval1) - + ' / ' - + self._input.get_axis_name(sval2) + else None ) + print('got', sval1, sval2) + assert isinstance(sval1, (int, type(None))) + assert isinstance(sval2, (int, type(None))) + if sval1 is not None and sval2 is not None: + return ( + self._input.get_axis_name(sval1) + + ' / ' + + self._input.get_axis_name(sval2) + ) + return bui.Lstr(resource=self._r + '.unsetText') # If they're looking for triggers. if control in ['triggerRun1' + self._ext, 'triggerRun2' + self._ext]: @@ -573,7 +578,7 @@ class GamepadSettingsWindow(bui.Window): return str(1.0) # For dpad buttons: show individual buttons if any are set. - # Otherwise show whichever dpad is set (defaulting to 1). + # Otherwise show whichever dpad is set. dpad_buttons = [ 'buttonLeft' + self._ext, 'buttonRight' + self._ext, @@ -588,24 +593,28 @@ class GamepadSettingsWindow(bui.Window): return bui.Lstr(resource=self._r + '.unsetText') # No dpad buttons - show the dpad number for all 4. - return bui.Lstr( - value='${A} ${B}', - subs=[ - ('${A}', bui.Lstr(resource=self._r + '.dpadText')), - ( - '${B}', - str( - self._settings['dpad' + self._ext] - if 'dpad' + self._ext in self._settings - else 2 - if self._is_secondary - else 1 - ), - ), - ], + dpadnum = ( + self._settings['dpad' + self._ext] + if 'dpad' + self._ext in self._settings + else 2 + if self._is_secondary + else None ) + assert isinstance(dpadnum, (int, type(None))) + if dpadnum is not None: + return bui.Lstr( + value='${A} ${B}', + subs=[ + ('${A}', bui.Lstr(resource=self._r + '.dpadText')), + ( + '${B}', + str(dpadnum), + ), + ], + ) + return bui.Lstr(resource=self._r + '.unsetText') - # other buttons.. + # Other buttons. if control in self._settings: return self._input.get_button_name(self._settings[control]) return bui.Lstr(resource=self._r + '.unsetText') @@ -616,9 +625,7 @@ class GamepadSettingsWindow(bui.Window): event: dict[str, Any], dialog: AwaitGamepadInputWindow, ) -> None: - # pylint: disable=too-many-nested-blocks # pylint: disable=too-many-branches - # pylint: disable=too-many-statements assert self._settings is not None ext = self._ext @@ -648,10 +655,6 @@ class GamepadSettingsWindow(bui.Window): if btn in self._settings: del self._settings[btn] if event['hat'] == (2 if self._is_secondary else 1): - # Exclude value in default case. - if 'dpad' + ext in self._settings: - del self._settings['dpad' + ext] - else: self._settings['dpad' + ext] = event['hat'] # Update the 4 dpad button txt widgets. @@ -680,10 +683,6 @@ class GamepadSettingsWindow(bui.Window): if abs(event['value']) > 0.5: axis = event['axis'] if axis == (5 if self._is_secondary else 1): - # Exclude value in default case. - if 'analogStickLR' + ext in self._settings: - del self._settings['analogStickLR' + ext] - else: self._settings['analogStickLR' + ext] = axis bui.textwidget( edit=self._textwidgets['analogStickLR' + ext], @@ -713,10 +712,6 @@ class GamepadSettingsWindow(bui.Window): lr_axis = 5 if self._is_secondary else 1 if axis != lr_axis: if axis == (6 if self._is_secondary else 2): - # Exclude value in default case. - if 'analogStickUD' + ext in self._settings: - del self._settings['analogStickUD' + ext] - else: self._settings['analogStickUD' + ext] = axis bui.textwidget( edit=self._textwidgets['analogStickLR' + ext], @@ -795,7 +790,7 @@ class GamepadSettingsWindow(bui.Window): ), ) - bui.apptimer(0, doit) + bui.pushcall(doit) return btn def _cancel(self) -> None: diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py index ae50be7b..d44300f0 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py @@ -452,7 +452,7 @@ class GamepadAdvancedSettingsWindow(bui.Window): ), ) - bui.apptimer(0, doit) + bui.pushcall(doit) return btn, btn2 def _inc( diff --git a/src/assets/ba_data/python/bauiv1lib/settings/keyboard.py b/src/assets/ba_data/python/bauiv1lib/settings/keyboard.py index 6f37aabb..60aab600 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/keyboard.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/keyboard.py @@ -213,6 +213,12 @@ class ConfigKeyboardWindow(bui.Window): scale=1.0, ) + def _pretty_button_name(self, button_name: str) -> bui.Lstr: + button_id = self._settings[button_name] + if button_id == -1: + return bs.Lstr(resource='configGamepadWindow.unsetText') + return self._input.get_button_name(button_id) + def _capture_button( self, pos: tuple[float, float], @@ -250,7 +256,7 @@ class ConfigKeyboardWindow(bui.Window): v_align='top', scale=uiscale, maxwidth=maxwidth, - text=self._input.get_button_name(self._settings[button]), + text=self._pretty_button_name(button), ) bui.buttonwidget( edit=btn, diff --git a/src/ballistica/base/input/device/joystick_input.cc b/src/ballistica/base/input/device/joystick_input.cc index 08ad4148..910f9459 100644 --- a/src/ballistica/base/input/device/joystick_input.cc +++ b/src/ballistica/base/input/device/joystick_input.cc @@ -65,7 +65,12 @@ JoystickInput::JoystickInput(int sdl_joystick_id, // that instead. // #if BA_SDL2_BUILD sdl_joystick_id_ = SDL_JoystickInstanceID(sdl_joystick_); - raw_sdl_joystick_name_ = SDL_JoystickName(sdl_joystick_); + if (auto* name = SDL_JoystickName(sdl_joystick_)) { + raw_sdl_joystick_name_ = name; + } else { + // This can return nullptr if SDL can't find a name. + raw_sdl_joystick_name_ = "Unknown Controller"; + } // Special case: on windows, xinput stuff comes in with unique names // "XInput Controller #3", etc. Let's replace these with simply "XInput diff --git a/src/ballistica/base/input/device/joystick_input.h b/src/ballistica/base/input/device/joystick_input.h index 5748f702..0444bb19 100644 --- a/src/ballistica/base/input/device/joystick_input.h +++ b/src/ballistica/base/input/device/joystick_input.h @@ -126,12 +126,12 @@ class JoystickInput : public InputDevice { bool calibrate_ : 1 {}; bool can_configure_ : 1 {}; - int hat_{}; - int analog_lr_{}; + int hat_{0}; + int analog_lr_{0}; int analog_ud_{1}; // Mappings of ba buttons to SDL buttons. - int jump_button_{}; + int jump_button_{0}; int punch_button_{1}; int bomb_button_{2}; int pickup_button_{3}; diff --git a/src/ballistica/base/python/methods/python_methods_app.cc b/src/ballistica/base/python/methods/python_methods_app.cc index 471c6c08..48db4269 100644 --- a/src/ballistica/base/python/methods/python_methods_app.cc +++ b/src/ballistica/base/python/methods/python_methods_app.cc @@ -602,7 +602,7 @@ static auto PyCommitConfig(PyObject* self, PyObject* args, PyObject* keywds) } fclose(f_out); - // Now backup any existing config to .prev. + // Now move any existing config to .prev. if (g_core->platform->FilePathExists(path)) { // On windows, rename doesn't overwrite existing files.. need to kill // the old explicitly. diff --git a/src/ballistica/base/ui/dev_console.cc b/src/ballistica/base/ui/dev_console.cc index 6940c271..cec733a8 100644 --- a/src/ballistica/base/ui/dev_console.cc +++ b/src/ballistica/base/ui/dev_console.cc @@ -864,7 +864,7 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { bool found_valid{}; // Move until we've found at least one valid char and the // stop at the first invalid one. - while (carat_char_ < unichars.size()) { + while (carat_char_ < static_cast(unichars.size())) { assert(CaratCharValid_()); auto this_char = unichars[carat_char_]; auto is_valid = IsValidHungryChar_(this_char); @@ -995,8 +995,8 @@ void DevConsole::Exec() { // Just for sanity testing. auto DevConsole::CaratCharValid_() -> bool { return carat_char_ >= 0 - && carat_char_ - <= Utils::UnicodeFromUTF8(input_string_, "fwewffe").size(); + && carat_char_ <= static_cast( + Utils::UnicodeFromUTF8(input_string_, "fwewffe").size()); } void DevConsole::SubmitPythonCommand_(const std::string& command) { @@ -1419,7 +1419,7 @@ void DevConsole::UpdateCarat_() { // Use a base width if we're not covering a char, and use the char's width // if we are. float width = 14.0f; - if (carat_char_ < unichars.size()) { + if (carat_char_ < static_cast(unichars.size())) { std::vector covered_char{unichars[carat_char_]}; auto covered_char_str = Utils::UTF8FromUnicode(covered_char); width = diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 70294d7f..d7bbd454 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 = 21525; +const int kEngineBuildNumber = 21528; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; From d35f479f825bc0a2bc96a2e8cfe68541f541f569 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 27 Oct 2023 18:54:35 -0700 Subject: [PATCH 17/25] language updates, dev-console polishing, internal time format cleanup --- .efrocachemap | 94 +++++++++---------- CHANGELOG.md | 12 ++- ballisticakit-cmake/CMakeLists.txt | 1 + .../Generic/BallisticaKitGeneric.vcxproj | 1 + .../BallisticaKitGeneric.vcxproj.filters | 3 + .../Headless/BallisticaKitHeadless.vcxproj | 1 + .../BallisticaKitHeadless.vcxproj.filters | 3 + src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/base/assets/assets_server.cc | 4 +- src/ballistica/base/audio/audio_server.cc | 6 +- src/ballistica/base/base.h | 1 + .../base/graphics/support/camera.cc | 44 ++++----- src/ballistica/base/graphics/support/camera.h | 72 +++++++------- src/ballistica/base/input/input.cc | 6 +- src/ballistica/base/logic/logic.cc | 29 +++--- src/ballistica/base/logic/logic.h | 10 +- .../python/class/python_class_app_timer.cc | 2 +- .../class/python_class_display_timer.cc | 2 +- .../base/python/methods/python_methods_app.cc | 4 +- src/ballistica/base/support/app_timer.h | 7 +- src/ballistica/base/support/display_timer.h | 42 +++++++++ src/ballistica/base/support/repeater.cc | 12 +-- src/ballistica/base/support/repeater.h | 3 +- src/ballistica/base/ui/dev_console.cc | 64 +++++++++++-- src/ballistica/shared/ballistica.cc | 2 +- .../shared/foundation/event_loop.cc | 24 +++-- src/ballistica/shared/foundation/event_loop.h | 33 +++---- 27 files changed, 294 insertions(+), 190 deletions(-) create mode 100644 src/ballistica/base/support/display_timer.h diff --git a/.efrocachemap b/.efrocachemap index 95a2a68d..3dcc07ae 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,7 +421,7 @@ "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", - "build/assets/ba_data/data/langdata.json": "d53c301a74d3b116b00f6abf5a53b16f", + "build/assets/ba_data/data/langdata.json": "b2fbc1751bd168470392de5370c196f4", "build/assets/ba_data/data/languages/arabic.json": "c21378ee214a9dd0cb2971cd46b74374", "build/assets/ba_data/data/languages/belarussian.json": "4d89ed5f9c615771d4fa2bb1834942d3", "build/assets/ba_data/data/languages/chinese.json": "0a9d9534e7329d1e886adae6fdc007c4", @@ -447,10 +447,10 @@ "build/assets/ba_data/data/languages/polish.json": "6677925c370390f1f53bcb737cb00fa8", "build/assets/ba_data/data/languages/portuguese.json": "51e362956f89da3eec980f587c092253", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", - "build/assets/ba_data/data/languages/russian.json": "561504cca28eb3204ac194950029e565", + "build/assets/ba_data/data/languages/russian.json": "6e524210149d95479d6cbfd3506c630b", "build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69", "build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef", - "build/assets/ba_data/data/languages/spanish.json": "5a4dbd505060dd02d634bd4de4d5faab", + "build/assets/ba_data/data/languages/spanish.json": "b179da96097e2b4df9f0397da672be69", "build/assets/ba_data/data/languages/swedish.json": "77d671f10613291ebf9c71da66f18a18", "build/assets/ba_data/data/languages/tamil.json": "65ab7798d637fa62a703750179eeb723", "build/assets/ba_data/data/languages/thai.json": "33f63753c9af9a5b238d229a0bf23fbc", @@ -4056,50 +4056,50 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "637b3e06d6536db39d816e0b5820c0ab", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "e3a0ad82944e80528a227807a9a9ba6d", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f8252819a3d84a2c3be5e3ed938e5f8b", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "7e8682e4ef71b0d432576ce8f879b3b2", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "eb3a79d46714a2585da45f66ae5352eb", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "1ebb8b160059182d79b586f40f4bb207", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "b51ff49b8e145ebee0d5a3f8c2e517fb", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "9eecb06461e9798439c4d15399b7d28a", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "7ffd1e3961eb68f820ff044f2ba62cf9", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "3ab890f1e4116739bce0e2c141440773", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d6d47b5b7bf720c0936a53deffe07359", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0ce0fcd7d19e767db721eb43f58424f7", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "4fac89dcba67096cd2f84f0b687b1880", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "0df3b09ffdf3dc519cea1a3a9fb959d2", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "8eb92b2fa10d56cfee3fd8da179cfda7", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "b0764a6280bfbe926b655df8f946e8e2", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "f69383ecdafab7a37907898fcbf98fa1", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "617e7ca8f4ed3d3f726ba9567a15732e", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9133fee71d08209b5ac82f772edae5c9", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "1cfd194e81bb849e337b34df43157ba8", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "476e9cf1fb229a023babd799a6e535f1", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "cf2a61fae8e8cd757864202a09e71255", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "b46b30262b58e96e994211631b470efb", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "6cc41e3401daf2e72b884fbfe0fe92b3", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "b46b30262b58e96e994211631b470efb", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "6cc41e3401daf2e72b884fbfe0fe92b3", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "b915f8a091643d99fd28e8d636063185", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "cb5de031162e4ff0cb5f030adf331a12", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "b915f8a091643d99fd28e8d636063185", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "cb5de031162e4ff0cb5f030adf331a12", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "be2a7322e1ddbb38ba0d22dd94a565e3", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "b257bbc06d82fc912653806c01a42c15", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "1920c5412307a78aa658c3366c86b7fc", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "693493fea9a0068d67d05ac32c53d938", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "0ad9cd9671e260ea90f97a3334a063d0", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "0dc8f56e25b1bb2b67bdb6f1b65c56b6", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "02bfe33e3189d0993aff1884cae95ccf", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "7867875c532b032ace05fef64e278635", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "7dfdd479341808a7301158591caac092", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "3604c049578423bce477d0be543529f4", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "57b11043daad1545cd2abb0c13f43db7", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "d81b7738fc395f6f926aabaee1920925", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "70d7de73a945afbe78f6ba94dd0fd78c", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "5ee9cf8e99fb9fbc6b80ef7fa6840be5", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "8eb65d8768f338c7188de404d584068f", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "4422950377f4194463b38533487b81df", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "3e85a676808245e0a279e2fb28fad8fc", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "50ac87225e3b4ac843d83fcec96ef542", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "ce8fedb78aac2ec288697fbace511d68", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "9db6948f77ff98d109e799d4d97266f7", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "517b1d6326879fd7ae1ad17d96e7c9ee", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b49b73a09460467bba983c301d33feb8", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "7b4741075224986c1776bc9e538b80cc", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f8a1e3030d6e9129f95ab5b7ea171134", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "615505f555b1ecf567ac00c1a71d4073", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "257f4ec71878b30f0a3619d8a5a278d8", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0d4a6355de77872b17b4ed2856cfd3e3", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e76d8896417d7c468b743f865f6d317a", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "1f7b66a5c7bf998f9d59fa28ef1a2dc5", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "a537bc369c09da6384a47e878b7dd11d", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "0b34b2bdfc77cb1f8c3968c16b304307", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "844bab8bf2324a35e4f71510fb4065f3", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "0320ab824c7b9271dfdd6361dcd51d82", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "844bab8bf2324a35e4f71510fb4065f3", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "0320ab824c7b9271dfdd6361dcd51d82", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "28ec03fb21247269ea16b7dc31cc37c9", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "80e61c0f2a2e665eaa6260b60ca92144", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "28ec03fb21247269ea16b7dc31cc37c9", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "80e61c0f2a2e665eaa6260b60ca92144", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "773c691b680d407f050d11a0814048cd", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "22158f39a92f54838ca05f38e7f635a9", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "773c691b680d407f050d11a0814048cd", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "22158f39a92f54838ca05f38e7f635a9", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "8d88b975df7ccff1af919ea738dcbc0f", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "f7de016cce83b57002b87f42575c2287", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "054de6792232f57d2ad4a5a81e5b7e5f", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "f7de016cce83b57002b87f42575c2287", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7f38979e847d5b3abef78acf83e41334", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "10ebbf27705f024b696c92db94d75506", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "287f846d6d424639348a02030f2bace9", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0a2987deb121f5eb044c220079c17d50", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "97b59f0376cc0bff65bc8f583127e62b", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c7421859bac7d02acb487784573cffd9", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "8e70dcb1e9c6a046473d2fec13796b76", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "104baba8083e75102f81c6e1c6b552b5", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a6d0354..a0bab389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21528, api 8, 2023-10-27) +### 1.7.28 (build 21531, api 8, 2023-10-27) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years @@ -192,6 +192,16 @@ technical users can still fix and restore their old configs. Note that the app still also writes .prev configs for extra security, though it no longer uses them for anything itself. +- Converted more internal engine time values from milliseconds to microseconds, + including things like the internal EventLoop timeline. Please holler if you + notice anything running 1000x too fast or slow. In general my strategy going + forward is to use microseconds for exact internal time values but to mostly + expose float seconds to the user on the Python layer. There were starting to + be a few cases were integer milliseconds was not enough precision for internal + values. For instance, if we run with unclamped framerates and hit several + hundred FPS, milliseconds per frame would drop to 0 which could cause + problems. Note that scenev1 will be remaining on milliseconds internally for + compatibility reasons. Scenev2 should move to microseconds though. ### 1.7.27 (build 21282, api 8, 2023-08-30) diff --git a/ballisticakit-cmake/CMakeLists.txt b/ballisticakit-cmake/CMakeLists.txt index 443a6adc..c4d1ed64 100644 --- a/ballisticakit-cmake/CMakeLists.txt +++ b/ballisticakit-cmake/CMakeLists.txt @@ -441,6 +441,7 @@ set(BALLISTICA_SOURCES ${BA_SRC_ROOT}/ballistica/base/support/classic_soft.h ${BA_SRC_ROOT}/ballistica/base/support/context.cc ${BA_SRC_ROOT}/ballistica/base/support/context.h + ${BA_SRC_ROOT}/ballistica/base/support/display_timer.h ${BA_SRC_ROOT}/ballistica/base/support/huffman.cc ${BA_SRC_ROOT}/ballistica/base/support/huffman.h ${BA_SRC_ROOT}/ballistica/base/support/plus_soft.h diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj index 3a4e6a25..fc194878 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj @@ -433,6 +433,7 @@ + diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters index 90ed3d40..078cbd38 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters @@ -733,6 +733,9 @@ ballistica\base\support + + ballistica\base\support + ballistica\base\support diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj index 7b5fa892..b4f73ad3 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj @@ -428,6 +428,7 @@ + diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters index 90ed3d40..078cbd38 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters @@ -733,6 +733,9 @@ ballistica\base\support + + ballistica\base\support + ballistica\base\support diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 55329257..1d1469c6 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21528 +TARGET_BALLISTICA_BUILD = 21531 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/assets/assets_server.cc b/src/ballistica/base/assets/assets_server.cc index 9c89f00e..aaf27ba5 100644 --- a/src/ballistica/base/assets/assets_server.cc +++ b/src/ballistica/base/assets/assets_server.cc @@ -25,7 +25,7 @@ void AssetsServer::OnAppStartInThread() { // Ask our thread to give us periodic processing time (close to but // not *exactly* one second; try to avoid aliasing with similar updates). process_timer_ = event_loop()->NewTimer( - 987, true, NewLambdaRunnable([this] { Process(); }).Get()); + 987 * 1000, true, NewLambdaRunnable([this] { Process(); }).Get()); } void AssetsServer::PushPendingPreload(Object::Ref* asset_ref_ptr) { @@ -258,7 +258,7 @@ void AssetsServer::Process() { // we're writing a replay.. otherwise just sleep indefinitely. if (pending_preloads_.empty() && pending_preloads_audio_.empty()) { if (writing_replay_) { - process_timer_->SetLength(1000); + process_timer_->SetLength(1000 * 1000); } else { process_timer_->SetLength(-1); } diff --git a/src/ballistica/base/audio/audio_server.cc b/src/ballistica/base/audio/audio_server.cc index adcdee40..a7a9ad1a 100644 --- a/src/ballistica/base/audio/audio_server.cc +++ b/src/ballistica/base/audio/audio_server.cc @@ -32,9 +32,9 @@ LPALCDEVICEPAUSESOFT alcDevicePauseSOFT; LPALCDEVICERESUMESOFT alcDeviceResumeSOFT; #endif -const int kAudioProcessIntervalNormal{500}; -const int kAudioProcessIntervalFade{50}; -const int kAudioProcessIntervalPendingLoad{1}; +const int kAudioProcessIntervalNormal{500 * 1000}; +const int kAudioProcessIntervalFade{50 * 1000}; +const int kAudioProcessIntervalPendingLoad{1 * 1000}; #if BA_DEBUG_BUILD || BA_TEST_BUILD const bool kShowInUseSounds{}; diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index 07ab3f2e..f4b04101 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -53,6 +53,7 @@ class ClassicSoftInterface; class CollisionMeshAsset; class CollisionCache; class DevConsole; +class DisplayTimer; class Context; class ContextRef; class DataAsset; diff --git a/src/ballistica/base/graphics/support/camera.cc b/src/ballistica/base/graphics/support/camera.cc index d12ad130..050057b1 100644 --- a/src/ballistica/base/graphics/support/camera.cc +++ b/src/ballistica/base/graphics/support/camera.cc @@ -23,8 +23,7 @@ const float kPanMax = 9.0f; const float kPanMin = -9.0f; Camera::Camera() - : last_mode_set_time_(g_core->GetAppTimeMillisecs()), - lock_panning_(g_core->IsVRMode()), + : lock_panning_(g_core->IsVRMode()), pan_speed_scale_(g_core->IsVRMode() ? 0.3f : 1.0f) {} Camera::~Camera() = default; @@ -607,7 +606,8 @@ void Camera::Update(millisecs_t elapsed) { float damping = 0.006f; float damping2 = 0.006f; float xy_blend_speed = 0.0002f; - millisecs_t real_time = g_core->GetAppTimeMillisecs(); + time_ += elapsed; + // millisecs_t real_time = g_core->GetAppTimeMillisecs(); // Prevent camera "explosions" if we've been unable to update for a while. elapsed = std::min(millisecs_t{100}, elapsed); @@ -653,18 +653,18 @@ void Camera::Update(millisecs_t elapsed) { } if (!g_core->IsVRMode()) { - smooth_speed_.x += elapsedf * rand_component - * (-0.5f - + Utils::precalc_rand_1((real_time / rand_incr_1) - % kPrecalcRandsCount)); - smooth_speed_.y += elapsedf * rand_component - * (-0.5f - + Utils::precalc_rand_2((real_time / rand_incr_2) - % kPrecalcRandsCount)); - smooth_speed_.z += elapsedf * rand_component - * (-0.5f - + Utils::precalc_rand_3((real_time / rand_incr_3) - % kPrecalcRandsCount)); + smooth_speed_.x += + elapsedf * rand_component + * (-0.5f + + Utils::precalc_rand_1((time_ / rand_incr_1) % kPrecalcRandsCount)); + smooth_speed_.y += + elapsedf * rand_component + * (-0.5f + + Utils::precalc_rand_2((time_ / rand_incr_2) % kPrecalcRandsCount)); + smooth_speed_.z += + elapsedf * rand_component + * (-0.5f + + Utils::precalc_rand_3((time_ / rand_incr_3) % kPrecalcRandsCount)); } if (RandomFloat() < 0.1f && !g_core->IsVRMode()) { @@ -714,15 +714,14 @@ void Camera::Update(millisecs_t elapsed) { shake_vel_.x += 0.05f * shake_amount_ * (0.5f - - Utils::precalc_rand_1(real_time % 122 * i % kPrecalcRandsCount)); + - Utils::precalc_rand_1(time_ % 122 * i % kPrecalcRandsCount)); shake_vel_.y += 0.05f * shake_amount_ * (0.5f - - Utils::precalc_rand_2(real_time % 323 * i % kPrecalcRandsCount)); + - Utils::precalc_rand_2(time_ % 323 * i % kPrecalcRandsCount)); shake_vel_.z += 0.05f * shake_amount_ - * (0.5f - - Utils::precalc_rand_3(real_time % 76 * i % kPrecalcRandsCount)); + * (0.5f - Utils::precalc_rand_3(time_ % 76 * i % kPrecalcRandsCount)); } for (int j = 0; j < iterations; j++) { @@ -740,8 +739,8 @@ void Camera::Update(millisecs_t elapsed) { uint32_t interval = g_core->IsVRMode() ? 50 : 100; // Occasionally, update microphone position for audio. - if (real_time - last_listener_update_time_ > interval) { - last_listener_update_time_ = real_time; + if (time_ - last_listener_update_time_ > interval) { + last_listener_update_time_ = time_; bool do_regular_update = true; if (g_core->IsVRMode()) { #if BA_VR_MODE @@ -891,7 +890,8 @@ void Camera::SetMode(CameraMode m) { if (mode_ != m) { mode_ = m; smooth_next_frame_ = false; - last_mode_set_time_ = g_core->GetAppTimeMillisecs(); + // last_mode_set_time_ = g_core->GetAppTimeMillisecs(); + // last_mode_set_time_ = time_; heading_ = kInitialHeading; } } diff --git a/src/ballistica/base/graphics/support/camera.h b/src/ballistica/base/graphics/support/camera.h index 7b13bb4c..f6fe6504 100644 --- a/src/ballistica/base/graphics/support/camera.h +++ b/src/ballistica/base/graphics/support/camera.h @@ -92,37 +92,51 @@ class Camera : public Object { void set_pan_speed_scale(float val) { pan_speed_scale_ = val; } private: - float pan_speed_scale_{1.0f}; - bool lock_panning_{}; - Vector3f vr_offset_{0.0f, 0.0f, 0.0f}; - Vector3f vr_extra_offset_{0.0f, 0.0f, 0.0f}; - Vector3f vr_offset_smooth_{0.0f, 0.0f, 0.0f}; - millisecs_t last_mode_set_time_{}; - std::list areas_of_interest_; CameraMode mode_{CameraMode::kFollow}; - bool manual_{}; - bool smooth_next_frame_{}; - bool have_real_areas_of_interest_{}; + bool manual_ : 1 {}; + bool smooth_next_frame_ : 1 {}; + bool have_real_areas_of_interest_ : 1 {}; + bool lock_panning_ : 1 {}; // Manual stuff. - bool panning_{}; - bool orbiting_{}; - bool rolling_{}; - bool trucking_{}; - bool alt_down_{}; - bool cmd_down_{}; - bool ctrl_down_{}; - bool mouse_left_down_{}; - bool mouse_middle_down_{}; - bool mouse_right_down_{}; + bool panning_ : 1 {}; + bool orbiting_ : 1 {}; + bool rolling_ : 1 {}; + bool trucking_ : 1 {}; + bool alt_down_ : 1 {}; + bool cmd_down_ : 1 {}; + bool ctrl_down_ : 1 {}; + bool mouse_left_down_ : 1 {}; + bool mouse_middle_down_ : 1 {}; + bool mouse_right_down_ : 1 {}; + + bool happy_thoughts_mode_ : 1 {}; + bool x_constrained_ : 1 {true}; + float pan_speed_scale_{1.0f}; float heading_{kInitialHeading}; - Vector3f extra_pos_{0.0f, 0.0f, 0.0f}; - Vector3f extra_pos_2_{0.0f, 0.0f, 0.0f}; float area_of_interest_bounds_[6]{-9999, -9999, -9999, 9999, 9999, 9999}; float pan_pos_{}; float pan_speed_{}; float pan_target_{}; float shake_amount_{}; + float target_radius_{2.0f}; + float target_radius_smoothed_{2.0f}; + float field_of_view_x_{5.0f}; + float field_of_view_y_{kCameraFOVY}; + float field_of_view_x_smoothed_{1.0f}; + float field_of_view_y_smoothed_{1.0f}; + float min_target_radius_{5.0f}; + float area_of_interest_near_{1.0f}; + float area_of_interest_far_{2.0f}; + float xy_constrain_blend_{0.5f}; + // millisecs_t last_mode_set_time_{}; + millisecs_t last_listener_update_time_{}; + millisecs_t time_{}; + Vector3f vr_offset_{0.0f, 0.0f, 0.0f}; + Vector3f vr_extra_offset_{0.0f, 0.0f, 0.0f}; + Vector3f vr_offset_smooth_{0.0f, 0.0f, 0.0f}; + Vector3f extra_pos_{0.0f, 0.0f, 0.0f}; + Vector3f extra_pos_2_{0.0f, 0.0f, 0.0f}; Vector3f shake_pos_{0.0f, 0.0f, 0.0f}; Vector3f shake_vel_{0.0f, 0.0f, 0.0f}; Vector3f position_{0.0f, 1.0f, -1.0f}; @@ -131,20 +145,8 @@ class Camera : public Object { Vector3f position_offset_smoothed_{0.0f, 0.0f, 0.0f}; Vector3f smooth_speed_{0.0f, 0.0f, 0.0f}; Vector3f smooth_speed_2_{0.0f, 0.0f, 0.0f}; - float target_radius_{2.0f}; - float target_radius_smoothed_{2.0f}; - float field_of_view_x_{5.0f}; - float field_of_view_y_{kCameraFOVY}; - float field_of_view_x_smoothed_{1.0f}; - float field_of_view_y_smoothed_{1.0f}; - millisecs_t last_listener_update_time_{}; - bool happy_thoughts_mode_{}; - float min_target_radius_{5.0f}; Vector3f up_{0.0f, 1.0f, 0.0f}; - float area_of_interest_near_{1.0f}; - float area_of_interest_far_{2.0f}; - bool x_constrained_{true}; - float xy_constrain_blend_{0.5f}; + std::list areas_of_interest_; std::vector area_of_interest_points_{{0.0f, 0.0f, 0.0f}}; }; diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index 4a983659..14b5c443 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -244,7 +244,8 @@ void Input::ShowStandardInputDeviceConnectedMessage_(InputDevice* j) { g_base->logic->DeleteAppTimer(connect_print_timer_id_); } connect_print_timer_id_ = g_base->logic->NewAppTimer( - 500, false, NewLambdaRunnable([this] { AnnounceConnects_(); }).Get()); + 500 * 1000, false, + NewLambdaRunnable([this] { AnnounceConnects_(); }).Get()); } void Input::ShowStandardInputDeviceDisconnectedMessage_(InputDevice* j) { @@ -259,7 +260,8 @@ void Input::ShowStandardInputDeviceDisconnectedMessage_(InputDevice* j) { g_base->logic->DeleteAppTimer(disconnect_print_timer_id_); } disconnect_print_timer_id_ = g_base->logic->NewAppTimer( - 250, false, NewLambdaRunnable([this] { AnnounceDisconnects_(); }).Get()); + 250 * 1000, false, + NewLambdaRunnable([this] { AnnounceDisconnects_(); }).Get()); } void Input::PushAddInputDeviceCall(InputDevice* input_device, diff --git a/src/ballistica/base/logic/logic.cc b/src/ballistica/base/logic/logic.cc index 030229c2..a57852ec 100644 --- a/src/ballistica/base/logic/logic.cc +++ b/src/ballistica/base/logic/logic.cc @@ -99,7 +99,7 @@ void Logic::OnGraphicsReady() { // Anyone dealing in display-time should be able to handle a wide // variety of rates anyway. NOTE: This length is currently milliseconds. headless_display_time_step_timer_ = event_loop()->NewTimer( - kHeadlessMinDisplayTimeStep / 1000, true, + kHeadlessMinDisplayTimeStep, true, NewLambdaRunnable([this] { StepDisplayTime_(); }).Get()); } else { // In gui mode, push an initial frame to the graphics server. From this @@ -134,8 +134,9 @@ void Logic::CompleteAppBootstrapping_() { // Set up our timers. process_pending_work_timer_ = event_loop()->NewTimer( 0, true, NewLambdaRunnable([this] { ProcessPendingWork_(); }).Get()); - asset_prune_timer_ = event_loop()->NewTimer( - 2345, true, NewLambdaRunnable([] { g_base->assets->Prune(); }).Get()); + // asset_prune_timer_ = event_loop()->NewTimer( + // 2345 * 1000, true, NewLambdaRunnable([] { g_base->assets->Prune(); + // }).Get()); // Let our initial dummy app-mode know it has become active. g_base->app_mode()->OnActivate(); @@ -381,9 +382,7 @@ void Logic::OnAppModeChanged() { "Resetting headless display step timer due to app-mode change."); } assert(headless_display_time_step_timer_); - // NOTE: This is currently milliseconds. - headless_display_time_step_timer_->SetLength(kHeadlessMinDisplayTimeStep - / 1000); + headless_display_time_step_timer_->SetLength(kHeadlessMinDisplayTimeStep); } } @@ -439,8 +438,8 @@ void Logic::PostUpdateDisplayTimeForHeadlessMode_() { Log(LogLevel::kDebug, buffer); } - auto sleep_millisecs = headless_display_step_microsecs / 1000; - headless_display_time_step_timer_->SetLength(sleep_millisecs); + auto sleep_microsecs = headless_display_step_microsecs; + headless_display_time_step_timer_->SetLength(sleep_microsecs); } void Logic::UpdateDisplayTimeForFrameDraw_() { @@ -581,7 +580,7 @@ void Logic::UpdatePendingWorkTimer_() { // If there's loading to do, keep at it rather vigorously. if (have_pending_loads_) { assert(process_pending_work_timer_); - process_pending_work_timer_->SetLength(1); + process_pending_work_timer_->SetLength(1000); } else { // Otherwise we've got nothing to do; go to sleep until something // changes. @@ -635,7 +634,7 @@ void Logic::NotifyOfPendingAssetLoads() { UpdatePendingWorkTimer_(); } -auto Logic::NewAppTimer(millisecs_t length, bool repeat, Runnable* runnable) +auto Logic::NewAppTimer(microsecs_t length, bool repeat, Runnable* runnable) -> int { // App-Timers simply get injected into our loop and run alongside our own // stuff. @@ -649,7 +648,7 @@ void Logic::DeleteAppTimer(int timer_id) { event_loop()->DeleteTimer(timer_id); } -void Logic::SetAppTimerLength(int timer_id, millisecs_t length) { +void Logic::SetAppTimerLength(int timer_id, microsecs_t length) { assert(g_base->InLogicThread()); Timer* t = event_loop()->GetTimer(timer_id); if (t) { @@ -660,14 +659,14 @@ void Logic::SetAppTimerLength(int timer_id, millisecs_t length) { } } -auto Logic::NewDisplayTimer(microsecs_t length, bool repeat, - const Object::Ref& runnable) -> int { +auto Logic::NewDisplayTimer(microsecs_t length, bool repeat, Runnable* runnable) + -> int { // Display-Timers go into a timer-list that we exec explicitly when we // step display-time. assert(g_base->InLogicThread()); int offset = 0; - Timer* t = display_timers_->NewTimer(g_core->GetAppTimeMicrosecs(), length, - offset, repeat ? -1 : 0, runnable.Get()); + Timer* t = display_timers_->NewTimer(display_time_microsecs_, length, offset, + repeat ? -1 : 0, runnable); return t->id(); } diff --git a/src/ballistica/base/logic/logic.h b/src/ballistica/base/logic/logic.h index 3974392b..2e21436e 100644 --- a/src/ballistica/base/logic/logic.h +++ b/src/ballistica/base/logic/logic.h @@ -89,12 +89,12 @@ class Logic { void HandleInterruptSignal(); void HandleTerminateSignal(); - auto NewAppTimer(millisecs_t length, bool repeat, Runnable* runnable) -> int; + auto NewAppTimer(microsecs_t length, bool repeat, Runnable* runnable) -> int; void DeleteAppTimer(int timer_id); - void SetAppTimerLength(int timer_id, millisecs_t length); + void SetAppTimerLength(int timer_id, microsecs_t length); - auto NewDisplayTimer(microsecs_t length, bool repeat, - const Object::Ref& runnable) -> int; + auto NewDisplayTimer(microsecs_t length, bool repeat, Runnable* runnable) + -> int; void DeleteDisplayTimer(int timer_id); void SetDisplayTimerLength(int timer_id, microsecs_t length); @@ -148,8 +148,6 @@ class Logic { bool shutdown_completed_ : 1 {}; bool graphics_ready_ : 1 {}; Timer* process_pending_work_timer_{}; - Timer* asset_prune_timer_{}; - Timer* debug_timer_{}; EventLoop* event_loop_{}; std::unique_ptr display_timers_; }; diff --git a/src/ballistica/base/python/class/python_class_app_timer.cc b/src/ballistica/base/python/class/python_class_app_timer.cc index 0202a91d..1ef19306 100644 --- a/src/ballistica/base/python/class/python_class_app_timer.cc +++ b/src/ballistica/base/python/class/python_class_app_timer.cc @@ -94,7 +94,7 @@ auto PythonClassAppTimer::tp_new(PyTypeObject* type, PyObject* args, auto runnable(Object::New(call_obj)); self->timer_id_ = g_base->logic->NewAppTimer( - static_cast(length * 1000.0), repeat, + static_cast(length * 1000000.0), repeat, Object::New(call_obj).Get()); self->have_timer_ = true; diff --git a/src/ballistica/base/python/class/python_class_display_timer.cc b/src/ballistica/base/python/class/python_class_display_timer.cc index eb9330bf..d95d7918 100644 --- a/src/ballistica/base/python/class/python_class_display_timer.cc +++ b/src/ballistica/base/python/class/python_class_display_timer.cc @@ -104,7 +104,7 @@ auto PythonClassDisplayTimer::tp_new(PyTypeObject* type, PyObject* args, } self->timer_id_ = g_base->logic->NewDisplayTimer( static_cast(length * 1000000.0), repeat, - Object::New(call_obj)); + Object::New(call_obj).Get()); self->have_timer_ = true; diff --git a/src/ballistica/base/python/methods/python_methods_app.cc b/src/ballistica/base/python/methods/python_methods_app.cc index 48db4269..ba299479 100644 --- a/src/ballistica/base/python/methods/python_methods_app.cc +++ b/src/ballistica/base/python/methods/python_methods_app.cc @@ -365,7 +365,7 @@ static auto PyAppTimer(PyObject* self, PyObject* args, PyObject* keywds) throw Exception("Timer length cannot be < 0.", PyExcType::kValue); } g_base->logic->NewAppTimer( - static_cast(length * 1000.0), false, + static_cast(length * 1000000.0), false, Object::New(call_obj).Get()); Py_RETURN_NONE; BA_PYTHON_CATCH; @@ -459,7 +459,7 @@ static auto PyDisplayTimer(PyObject* self, PyObject* args, PyObject* keywds) } g_base->logic->NewDisplayTimer( static_cast(length * 1000000.0), false, - Object::New(call_obj)); + Object::New(call_obj).Get()); Py_RETURN_NONE; BA_PYTHON_CATCH; } diff --git a/src/ballistica/base/support/app_timer.h b/src/ballistica/base/support/app_timer.h index 966ef01b..876c3a65 100644 --- a/src/ballistica/base/support/app_timer.h +++ b/src/ballistica/base/support/app_timer.h @@ -13,21 +13,22 @@ namespace ballistica::base { class AppTimer : public Object { public: - AppTimer(millisecs_t length, bool repeat, Runnable* runnable) { + AppTimer(microsecs_t length, bool repeat, Runnable* runnable) { assert(g_base->InLogicThread()); timer_id_ = base::g_base->logic->NewAppTimer(length, repeat, runnable); } template - static auto New(millisecs_t length, bool repeat, const F& lambda) { + static auto New(microsecs_t length, bool repeat, const F& lambda) { return Object::New(length, repeat, NewLambdaRunnable(lambda).Get()); } - void SetLength(millisecs_t length) { + void SetLength(microsecs_t length) { assert(g_base->InLogicThread()); base::g_base->logic->SetAppTimerLength(timer_id_, length); } + ~AppTimer() override { assert(g_base->InLogicThread()); base::g_base->logic->DeleteAppTimer(timer_id_); diff --git a/src/ballistica/base/support/display_timer.h b/src/ballistica/base/support/display_timer.h new file mode 100644 index 00000000..1936ed8d --- /dev/null +++ b/src/ballistica/base/support/display_timer.h @@ -0,0 +1,42 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_BASE_SUPPORT_DISPLAY_TIMER_H_ +#define BALLISTICA_BASE_SUPPORT_DISPLAY_TIMER_H_ + +#include "ballistica/base/base.h" +#include "ballistica/base/logic/logic.h" +#include "ballistica/shared/ballistica.h" +#include "ballistica/shared/foundation/object.h" +#include "ballistica/shared/generic/lambda_runnable.h" + +namespace ballistica::base { + +class DisplayTimer : public Object { + public: + DisplayTimer(microsecs_t length, bool repeat, Runnable* runnable) { + assert(g_base->InLogicThread()); + timer_id_ = base::g_base->logic->NewDisplayTimer(length, repeat, runnable); + } + + template + static auto New(microsecs_t length, bool repeat, const F& lambda) { + return Object::New(length, repeat, + NewLambdaRunnable(lambda).Get()); + } + + void SetLength(microsecs_t length) { + assert(g_base->InLogicThread()); + base::g_base->logic->SetDisplayTimerLength(timer_id_, length); + } + ~DisplayTimer() override { + assert(g_base->InLogicThread()); + base::g_base->logic->DeleteDisplayTimer(timer_id_); + } + + private: + int timer_id_; +}; + +} // namespace ballistica::base + +#endif // BALLISTICA_BASE_SUPPORT_DISPLAY_TIMER_H_ diff --git a/src/ballistica/base/support/repeater.cc b/src/ballistica/base/support/repeater.cc index c7d58d5e..8528ce12 100644 --- a/src/ballistica/base/support/repeater.cc +++ b/src/ballistica/base/support/repeater.cc @@ -2,7 +2,7 @@ #include "ballistica/base/support/repeater.h" -#include "ballistica/base/support/app_timer.h" +#include "ballistica/base/support/display_timer.h" #include "ballistica/shared/foundation/event_loop.h" namespace ballistica::base { @@ -27,9 +27,9 @@ Repeater::Repeater(seconds_t initial_delay, seconds_t repeat_delay, return; } // Kick off our initial delay timer (generally the longer one). - weak_this->timer_ = AppTimer::New( - static_cast(weak_this->initial_delay_ * 1000.0), false, - [weak_this] { + weak_this->timer_ = DisplayTimer::New( + static_cast(weak_this->initial_delay_ * 1000000.0), + false, [weak_this] { // Timer should not have fired if we died. assert(weak_this.Exists()); weak_this->runnable_->RunAndLogErrors(); @@ -38,8 +38,8 @@ Repeater::Repeater(seconds_t initial_delay, seconds_t repeat_delay, return; } // Kick off our repeat timer (generally the short one). - weak_this->timer_ = AppTimer::New( - static_cast(weak_this->repeat_delay_ * 1000.0), + weak_this->timer_ = DisplayTimer::New( + static_cast(weak_this->repeat_delay_ * 1000000.0), true, [weak_this] { // Timer should not have fired if we died. assert(weak_this.Exists()); diff --git a/src/ballistica/base/support/repeater.h b/src/ballistica/base/support/repeater.h index 19355a38..2568ac24 100644 --- a/src/ballistica/base/support/repeater.h +++ b/src/ballistica/base/support/repeater.h @@ -11,6 +11,7 @@ namespace ballistica::base { /// Runs some code immediately and then repeatedly after a delay. Useful for /// jobs such as selecting ui elements while keys or buttons are held. +/// Uses display-time so emphasizes visual smoothness over accuracy. class Repeater : public Object { public: Repeater(seconds_t initial_delay, seconds_t repeat_delay, Runnable* runnable); @@ -26,7 +27,7 @@ class Repeater : public Object { private: seconds_t initial_delay_; seconds_t repeat_delay_; - Object::Ref timer_; + Object::Ref timer_; Object::Ref runnable_; }; diff --git a/src/ballistica/base/ui/dev_console.cc b/src/ballistica/base/ui/dev_console.cc index cec733a8..793617a2 100644 --- a/src/ballistica/base/ui/dev_console.cc +++ b/src/ballistica/base/ui/dev_console.cc @@ -85,8 +85,10 @@ static auto XOffs(DevConsoleHAnchor_ attach) -> float { } static auto IsValidHungryChar_(uint32_t this_char) -> bool { + // Include letters, numbers, and underscore. return ((this_char >= 65 && this_char <= 90) - || (this_char >= 97 && this_char <= 122)); + || (this_char >= 97 && this_char <= 122) + || (this_char >= 48 && this_char <= 57) || this_char == '_'); } static void DrawRect(RenderPass* pass, Mesh* mesh, float bottom, float x, @@ -722,7 +724,9 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { bool do_history_up{}; bool do_history_down{}; bool do_backspace{}; + bool do_forward_delete{}; bool do_hungry_backspace{}; + bool do_hungry_forward_delete{}; bool do_move_to_end{}; bool do_move_to_beginning{}; bool do_kill_line{}; @@ -735,6 +739,20 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { } break; } + case SDLK_DELETE: { + if (keysym->mod & KMOD_ALT) { + do_hungry_forward_delete = true; + } else { + do_forward_delete = true; + } + break; + } + case SDLK_HOME: + do_move_to_beginning = true; + break; + case SDLK_END: + do_move_to_end = true; + break; case SDLK_UP: do_history_up = true; break; @@ -791,6 +809,13 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { do_move_to_beginning = true; } break; + case SDLK_d: + if (keysym->mod & KMOD_CTRL) { + do_forward_delete = true; + } else if (keysym->mod & KMOD_ALT) { + do_hungry_forward_delete = true; + } + break; case SDLK_e: if (keysym->mod & KMOD_CTRL) { do_move_to_end = true; @@ -800,7 +825,6 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { if (keysym->mod & KMOD_CTRL) { do_kill_line = true; } - default: { break; } @@ -851,15 +875,18 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { carat_char_ -= 1; assert(CaratCharValid_()); } - input_string_ = Utils::UTF8FromUnicode(unichars); - input_text_dirty_ = true; + if (do_delete) { + input_string_ = Utils::UTF8FromUnicode(unichars); + input_text_dirty_ = true; + } carat_dirty_ = true; }); } - if (do_hungry_carat_right) { + if (do_hungry_forward_delete || do_hungry_carat_right) { + auto do_delete = do_hungry_forward_delete; key_repeater_ = Repeater::New( g_base->app_adapter->GetKeyRepeatDelay(), - g_base->app_adapter->GetKeyRepeatInterval(), [this] { + g_base->app_adapter->GetKeyRepeatInterval(), [this, do_delete] { auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco38"); bool found_valid{}; // Move until we've found at least one valid char and the @@ -874,9 +901,17 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { if (is_valid) { found_valid = true; } - carat_char_ += 1; + if (do_delete) { + unichars.erase(unichars.begin() + carat_char_); + } else { + carat_char_ += 1; + } assert(CaratCharValid_()); } + if (do_delete) { + input_string_ = Utils::UTF8FromUnicode(unichars); + input_text_dirty_ = true; + } carat_dirty_ = true; }); } @@ -896,6 +931,21 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { } }); } + if (do_forward_delete) { + key_repeater_ = Repeater::New( + g_base->app_adapter->GetKeyRepeatDelay(), + g_base->app_adapter->GetKeyRepeatInterval(), [this] { + auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco33"); + if (!unichars.empty() && carat_char_ < unichars.size()) { + assert(CaratCharValid_()); + unichars.erase(unichars.begin() + carat_char_); + input_string_ = Utils::UTF8FromUnicode(unichars); + input_text_dirty_ = true; + carat_dirty_ = true; // Didn't move but might change size. + assert(CaratCharValid_()); + } + }); + } if (do_carat_left || do_carat_right) { key_repeater_ = Repeater::New( g_base->app_adapter->GetKeyRepeatDelay(), diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index d7bbd454..3eeb626b 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 = 21528; +const int kEngineBuildNumber = 21531; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/foundation/event_loop.cc b/src/ballistica/shared/foundation/event_loop.cc index f6e9850d..c04245e7 100644 --- a/src/ballistica/shared/foundation/event_loop.cc +++ b/src/ballistica/shared/foundation/event_loop.cc @@ -217,12 +217,12 @@ void EventLoop::WaitForNextEvent_(bool single_cycle) { // If we've got active timers, wait for messages with a timeout so we can // run the next timer payload. if (!suspended_ && timers_.ActiveTimerCount() > 0) { - millisecs_t apptime = g_core->GetAppTimeMillisecs(); - millisecs_t wait_time = timers_.TimeToNextExpire(apptime); + microsecs_t apptime = g_core->GetAppTimeMicrosecs(); + microsecs_t wait_time = timers_.TimeToNextExpire(apptime); if (wait_time > 0) { std::unique_lock lock(thread_message_mutex_); if (thread_messages_.empty()) { - thread_message_cv_.wait_for(lock, std::chrono::milliseconds(wait_time), + thread_message_cv_.wait_for(lock, std::chrono::microseconds(wait_time), [this] { // Go back to sleep on spurious wakeups // if we didn't wind up with any new @@ -298,8 +298,6 @@ void EventLoop::Run_(bool single_cycle) { assert(!suspended_); RunSuspendCallbacks_(); suspended_ = true; - last_suspend_time_ = g_core->GetAppTimeMillisecs(); - messages_since_suspended_ = 0; break; } case ThreadMessage_::Type::kUnsuspend: { @@ -319,7 +317,7 @@ void EventLoop::Run_(bool single_cycle) { } if (!suspended_) { - timers_.Run(g_core->GetAppTimeMillisecs()); + timers_.Run(g_core->GetAppTimeMicrosecs()); RunPendingRunnables_(); } @@ -607,12 +605,12 @@ auto EventLoop::AreEventLoopsSuspended() -> bool { return g_core->event_loops_suspended; } -auto EventLoop::NewTimer(millisecs_t length, bool repeat, Runnable* runnable) +auto EventLoop::NewTimer(microsecs_t length, bool repeat, Runnable* runnable) -> Timer* { assert(g_core); assert(ThreadIsCurrent()); assert(Object::IsValidManagedObject(runnable)); - return timers_.NewTimer(g_core->GetAppTimeMillisecs(), length, 0, + return timers_.NewTimer(g_core->GetAppTimeMicrosecs(), length, 0, repeat ? -1 : 0, runnable); } @@ -774,8 +772,8 @@ auto EventLoop::CheckPushRunnableSafety_() -> bool { void EventLoop::AcquireGIL_() { assert(g_base_soft && g_base_soft->InLogicThread()); auto debug_timing{g_core->core_config().debug_timing}; - millisecs_t startms{debug_timing ? core::CorePlatform::GetCurrentMillisecs() - : 0}; + millisecs_t startmillisecs{ + debug_timing ? core::CorePlatform::GetCurrentMillisecs() : 0}; if (py_thread_state_) { PyEval_RestoreThread(py_thread_state_); @@ -783,10 +781,10 @@ void EventLoop::AcquireGIL_() { } if (debug_timing) { - auto duration{core::CorePlatform::GetCurrentMillisecs() - startms}; + auto duration{core::CorePlatform::GetCurrentMillisecs() - startmillisecs}; if (duration > (1000 / 120)) { - Log(LogLevel::kInfo, - "GIL acquire took too long (" + std::to_string(duration) + " ms)."); + Log(LogLevel::kInfo, "GIL acquire took too long (" + + std::to_string(duration) + " millisecs)."); } } } diff --git a/src/ballistica/shared/foundation/event_loop.h b/src/ballistica/shared/foundation/event_loop.h index 2551b00a..5a9649e6 100644 --- a/src/ballistica/shared/foundation/event_loop.h +++ b/src/ballistica/shared/foundation/event_loop.h @@ -45,21 +45,17 @@ class EventLoop { auto thread_id() const -> std::thread::id { return thread_id_; } - // Needed in rare cases where we jump physical threads. - // (Our 'main' thread on Android can switch under us as - // rendering contexts are recreated in new threads/etc.) - // void set_thread_id(std::thread::id id) { thread_id_ = id; } - void RunToCompletion(); void RunSingleCycle(); auto identifier() const -> EventLoopID { return identifier_; } - // Register a timer to run on the thread. - auto NewTimer(millisecs_t length, bool repeat, Runnable* runnable) -> Timer*; + /// Register a timer to run on the thread. + auto NewTimer(microsecs_t length, bool repeat, Runnable* runnable) -> Timer*; Timer* GetTimer(int id); void DeleteTimer(int id); + /// Add a runnable to this thread's event-loop. /// Pass a Runnable that has been allocated with NewUnmanaged(). /// It will be owned and disposed of by the thread. @@ -160,26 +156,21 @@ class EventLoop { void* auto_release_pool_{}; #endif - bool bootstrapped_{}; - bool writing_tally_{}; - bool suspended_{}; - bool done_{}; - bool acquires_python_gil_{}; EventLoopID identifier_{EventLoopID::kInvalid}; - millisecs_t last_suspend_time_{}; - int listen_sd_{}; - int messages_since_suspended_{}; - millisecs_t last_suspended_message_report_time_{}; - millisecs_t last_complaint_time_{}; - ThreadSource source_; + ThreadSource source_{}; + bool bootstrapped_ : 1 {}; + bool writing_tally_ : 1 {}; + bool suspended_ : 1 {}; + bool done_ : 1 {}; + bool acquires_python_gil_ : 1 {}; std::thread::id thread_id_{}; + std::condition_variable thread_message_cv_; + std::condition_variable client_listener_cv_; std::list> runnables_; std::list suspend_callbacks_; std::list unsuspend_callbacks_; - std::condition_variable thread_message_cv_; - std::condition_variable client_listener_cv_; - std::mutex thread_message_mutex_; std::list thread_messages_; + std::mutex thread_message_mutex_; std::mutex client_listener_mutex_; std::list> data_to_client_; PyThreadState* py_thread_state_{}; From 113be1841657b54ec45821d1124762e780868240 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 31 Oct 2023 12:09:33 -0700 Subject: [PATCH 18/25] wired stress testing back up and other polishing --- .efrocachemap | 94 +-- CHANGELOG.md | 10 +- ballisticakit-cmake/CMakeLists.txt | 6 +- .../Generic/BallisticaKitGeneric.vcxproj | 6 +- .../BallisticaKitGeneric.vcxproj.filters | 18 +- .../Headless/BallisticaKitHeadless.vcxproj | 6 +- .../BallisticaKitHeadless.vcxproj.filters | 18 +- config/projectconfig.json | 3 +- src/assets/ba_data/python/babase/__init__.py | 2 - .../ba_data/python/baclassic/_benchmark.py | 8 +- src/assets/ba_data/python/baclassic/_music.py | 13 +- src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/base/base.cc | 9 +- src/ballistica/base/base.h | 5 +- src/ballistica/base/graphics/graphics.cc | 533 +---------------- src/ballistica/base/graphics/graphics.h | 17 +- .../base/graphics/support/screen_messages.cc | 538 ++++++++++++++++++ .../base/graphics/support/screen_messages.h | 37 ++ .../base/input/device/test_input.cc | 4 +- src/ballistica/base/input/device/test_input.h | 17 +- src/ballistica/base/input/input.cc | 53 -- src/ballistica/base/input/input.h | 4 - .../base/input/support/remote_app_server.cc | 16 +- src/ballistica/base/logic/logic.cc | 2 +- .../platform/apple/base_platform_apple.cc | 4 +- .../base/python/methods/python_methods_app.cc | 28 - .../python/methods/python_methods_graphics.cc | 3 +- src/ballistica/base/support/app_timer.h | 12 +- src/ballistica/base/support/display_timer.h | 13 +- src/ballistica/base/support/repeater.cc | 10 +- src/ballistica/base/support/stress_test.h | 25 - src/ballistica/base/ui/dev_console.cc | 8 +- src/ballistica/classic/classic.cc | 6 +- src/ballistica/classic/classic.h | 4 + .../python/methods/python_methods_classic.cc | 37 +- .../{base => classic}/support/stress_test.cc | 80 ++- src/ballistica/classic/support/stress_test.h | 33 ++ .../platform/apple/core_platform_apple.cc | 70 ++- .../core/platform/apple/core_platform_apple.h | 6 +- src/ballistica/core/platform/core_platform.cc | 4 +- src/ballistica/core/platform/core_platform.h | 13 +- .../python/methods/python_methods_scene.cc | 3 +- .../scene_v1/support/client_session.cc | 3 +- src/ballistica/shared/ballistica.cc | 2 +- .../shared/foundation/event_loop.cc | 38 +- src/ballistica/shared/foundation/event_loop.h | 4 +- src/ballistica/ui_v1/widget/button_widget.cc | 8 +- .../ui_v1/widget/h_scroll_widget.cc | 2 +- src/ballistica/ui_v1/widget/scroll_widget.cc | 2 +- tools/batools/pruneincludes.py | 7 + tools/batools/xcodeproject.py | 13 +- 51 files changed, 1001 insertions(+), 858 deletions(-) create mode 100644 src/ballistica/base/graphics/support/screen_messages.cc create mode 100644 src/ballistica/base/graphics/support/screen_messages.h delete mode 100644 src/ballistica/base/support/stress_test.h rename src/ballistica/{base => classic}/support/stress_test.cc (61%) create mode 100644 src/ballistica/classic/support/stress_test.h diff --git a/.efrocachemap b/.efrocachemap index 3dcc07ae..4d5f5d4d 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,7 +421,7 @@ "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", - "build/assets/ba_data/data/langdata.json": "b2fbc1751bd168470392de5370c196f4", + "build/assets/ba_data/data/langdata.json": "0b15d171ebcc56d324875b48436b58c2", "build/assets/ba_data/data/languages/arabic.json": "c21378ee214a9dd0cb2971cd46b74374", "build/assets/ba_data/data/languages/belarussian.json": "4d89ed5f9c615771d4fa2bb1834942d3", "build/assets/ba_data/data/languages/chinese.json": "0a9d9534e7329d1e886adae6fdc007c4", @@ -440,7 +440,7 @@ "build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", "build/assets/ba_data/data/languages/indonesian.json": "d7f1cafecad05e0dcd34345e0088c4de", - "build/assets/ba_data/data/languages/italian.json": "b998195a8c5e745dca953ca54745a5f6", + "build/assets/ba_data/data/languages/italian.json": "e4acd4e58ef8db78f3369bf881f84c55", "build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2", "build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38", "build/assets/ba_data/data/languages/persian.json": "4585070bd509600019ec8dc3bb47bfb8", @@ -454,7 +454,7 @@ "build/assets/ba_data/data/languages/swedish.json": "77d671f10613291ebf9c71da66f18a18", "build/assets/ba_data/data/languages/tamil.json": "65ab7798d637fa62a703750179eeb723", "build/assets/ba_data/data/languages/thai.json": "33f63753c9af9a5b238d229a0bf23fbc", - "build/assets/ba_data/data/languages/turkish.json": "776d1a0c9ef2333a9110d93558ab19e2", + "build/assets/ba_data/data/languages/turkish.json": "71fd6c59650c03164a94d884bc7e5263", "build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2", "build/assets/ba_data/data/languages/venetian.json": "9fe1a58d9e5dfb00f31ce3b2eb9993f4", "build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba", @@ -4056,50 +4056,50 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "d81b7738fc395f6f926aabaee1920925", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "70d7de73a945afbe78f6ba94dd0fd78c", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "5ee9cf8e99fb9fbc6b80ef7fa6840be5", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "8eb65d8768f338c7188de404d584068f", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "4422950377f4194463b38533487b81df", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "3e85a676808245e0a279e2fb28fad8fc", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "50ac87225e3b4ac843d83fcec96ef542", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "ce8fedb78aac2ec288697fbace511d68", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "9db6948f77ff98d109e799d4d97266f7", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "517b1d6326879fd7ae1ad17d96e7c9ee", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b49b73a09460467bba983c301d33feb8", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "7b4741075224986c1776bc9e538b80cc", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f8a1e3030d6e9129f95ab5b7ea171134", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "615505f555b1ecf567ac00c1a71d4073", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "257f4ec71878b30f0a3619d8a5a278d8", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0d4a6355de77872b17b4ed2856cfd3e3", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e76d8896417d7c468b743f865f6d317a", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "1f7b66a5c7bf998f9d59fa28ef1a2dc5", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "a537bc369c09da6384a47e878b7dd11d", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "0b34b2bdfc77cb1f8c3968c16b304307", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "844bab8bf2324a35e4f71510fb4065f3", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "0320ab824c7b9271dfdd6361dcd51d82", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "844bab8bf2324a35e4f71510fb4065f3", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "0320ab824c7b9271dfdd6361dcd51d82", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "28ec03fb21247269ea16b7dc31cc37c9", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "80e61c0f2a2e665eaa6260b60ca92144", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "28ec03fb21247269ea16b7dc31cc37c9", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "80e61c0f2a2e665eaa6260b60ca92144", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "773c691b680d407f050d11a0814048cd", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "22158f39a92f54838ca05f38e7f635a9", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "773c691b680d407f050d11a0814048cd", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "22158f39a92f54838ca05f38e7f635a9", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "8d88b975df7ccff1af919ea738dcbc0f", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "f7de016cce83b57002b87f42575c2287", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "054de6792232f57d2ad4a5a81e5b7e5f", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "f7de016cce83b57002b87f42575c2287", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7f38979e847d5b3abef78acf83e41334", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "10ebbf27705f024b696c92db94d75506", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "287f846d6d424639348a02030f2bace9", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0a2987deb121f5eb044c220079c17d50", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "97b59f0376cc0bff65bc8f583127e62b", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c7421859bac7d02acb487784573cffd9", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "8e70dcb1e9c6a046473d2fec13796b76", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "104baba8083e75102f81c6e1c6b552b5", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ad6316e04f09de546d25171512f783b2", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "19495e4313121d5574ab69efcbbcedd7", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "d8f215de52d492ce1790d9e1714b4cec", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b057d6d9627c7400496080c48dd344cd", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "1bd60c4476b7471364be2534d3cb8185", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "011bceb35c7f53b98f2ab79798409679", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "0055dfac758acdeb5a39e436da5d71be", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "2daa69d1df9927e6fc17b0aabd5c62f6", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "2159ce4b648b1172e3d2f349e61f2b1b", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "26163f755e45586da35c1ed6499c0416", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "410c70d8d833458616a0056972e558c4", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6e4473952a022e30340b6decae9da58a", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "0c63291b5842dafcfae558ef3c36d35a", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "7195da4e4abae862f41c28764b35662b", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5a6ad8a9f0d5cd964661df32ac4efb47", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "376059ea5f812ace7629ad29a8d77a9a", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "7a0c87d9e673b28157845f71ff957df6", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "3603019e3dbf055c37f5fabbe9538c48", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "14f6e17cc5698341ed5607834107e608", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "679703f9ec7c6f9c0708c9b13c9c6c06", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "e4952c83427611c5a66a864d8bb3bc4f", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "55df380ad6f3b38094bc82f6bb2a34bb", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "e4952c83427611c5a66a864d8bb3bc4f", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "55df380ad6f3b38094bc82f6bb2a34bb", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "f37c917e8336be6afe86842fc0cd1586", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "aaf0413c15988e332d27b7fd6eb1ba1f", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "f37c917e8336be6afe86842fc0cd1586", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "aaf0413c15988e332d27b7fd6eb1ba1f", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "f66008360fc266ada358731656dfa91a", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "712cd1dda7661826129b8023949ebebe", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "f66008360fc266ada358731656dfa91a", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "712cd1dda7661826129b8023949ebebe", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "5488eb05a8c45904243ff5cb1fc483cd", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "55aef97c30ade6b21e93b7d8a45ae670", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "519d0d2895489e5905e65e53384b96ba", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "55aef97c30ade6b21e93b7d8a45ae670", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "c9e82195e722512599ec7edcb456c78d", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "18b47849e222dd7b1bef9bd1a07473c9", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6c44557f5392bb3cd2d9a983add52d0b", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0bd4099b6b594f62b806c9d74a84095a", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a36752eee64f76c1868937247aaaee32", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "9ac33f02579ee14e4ad6a0b6b5a82a36", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "87bc0ff42442b60c817805ab07c65769", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "cedd1f2c367b84c20377c282453825f2", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index a0bab389..ad501f17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21531, api 8, 2023-10-27) +### 1.7.28 (build 21543, api 8, 2023-10-31) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years @@ -196,10 +196,10 @@ including things like the internal EventLoop timeline. Please holler if you notice anything running 1000x too fast or slow. In general my strategy going forward is to use microseconds for exact internal time values but to mostly - expose float seconds to the user on the Python layer. There were starting to - be a few cases were integer milliseconds was not enough precision for internal - values. For instance, if we run with unclamped framerates and hit several - hundred FPS, milliseconds per frame would drop to 0 which could cause + expose float seconds to the user, especially on the Python layer. There were + starting to be a few cases were integer milliseconds was not enough precision + for internal values. For instance, if we run with unclamped framerates and hit + several hundred FPS, milliseconds per frame would drop to 0 which caused some problems. Note that scenev1 will be remaining on milliseconds internally for compatibility reasons. Scenev2 should move to microseconds though. diff --git a/ballisticakit-cmake/CMakeLists.txt b/ballisticakit-cmake/CMakeLists.txt index c4d1ed64..12934e4e 100644 --- a/ballisticakit-cmake/CMakeLists.txt +++ b/ballisticakit-cmake/CMakeLists.txt @@ -360,6 +360,8 @@ set(BALLISTICA_SOURCES ${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.cc ${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.h ${BA_SRC_ROOT}/ballistica/base/graphics/support/render_command_buffer.h + ${BA_SRC_ROOT}/ballistica/base/graphics/support/screen_messages.cc + ${BA_SRC_ROOT}/ballistica/base/graphics/support/screen_messages.h ${BA_SRC_ROOT}/ballistica/base/graphics/text/font_page_map_data.h ${BA_SRC_ROOT}/ballistica/base/graphics/text/text_graphics.cc ${BA_SRC_ROOT}/ballistica/base/graphics/text/text_graphics.h @@ -449,8 +451,6 @@ set(BALLISTICA_SOURCES ${BA_SRC_ROOT}/ballistica/base/support/repeater.h ${BA_SRC_ROOT}/ballistica/base/support/stdio_console.cc ${BA_SRC_ROOT}/ballistica/base/support/stdio_console.h - ${BA_SRC_ROOT}/ballistica/base/support/stress_test.cc - ${BA_SRC_ROOT}/ballistica/base/support/stress_test.h ${BA_SRC_ROOT}/ballistica/base/ui/dev_console.cc ${BA_SRC_ROOT}/ballistica/base/ui/dev_console.h ${BA_SRC_ROOT}/ballistica/base/ui/ui.cc @@ -463,6 +463,8 @@ set(BALLISTICA_SOURCES ${BA_SRC_ROOT}/ballistica/classic/python/classic_python.h ${BA_SRC_ROOT}/ballistica/classic/python/methods/python_methods_classic.cc ${BA_SRC_ROOT}/ballistica/classic/python/methods/python_methods_classic.h + ${BA_SRC_ROOT}/ballistica/classic/support/stress_test.cc + ${BA_SRC_ROOT}/ballistica/classic/support/stress_test.h ${BA_SRC_ROOT}/ballistica/classic/support/v1_account.cc ${BA_SRC_ROOT}/ballistica/classic/support/v1_account.h ${BA_SRC_ROOT}/ballistica/core/core.cc diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj index fc194878..ff64f440 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj @@ -352,6 +352,8 @@ + + @@ -441,8 +443,6 @@ - - @@ -455,6 +455,8 @@ + + diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters index 078cbd38..441851e6 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters @@ -490,6 +490,12 @@ ballistica\base\graphics\support + + ballistica\base\graphics\support + + + ballistica\base\graphics\support + ballistica\base\graphics\text @@ -757,12 +763,6 @@ ballistica\base\support - - ballistica\base\support - - - ballistica\base\support - ballistica\base\ui @@ -799,6 +799,12 @@ ballistica\classic\python\methods + + ballistica\classic\support + + + ballistica\classic\support + ballistica\classic\support diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj index b4f73ad3..c3b0779c 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj @@ -347,6 +347,8 @@ + + @@ -436,8 +438,6 @@ - - @@ -450,6 +450,8 @@ + + diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters index 078cbd38..441851e6 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters @@ -490,6 +490,12 @@ ballistica\base\graphics\support + + ballistica\base\graphics\support + + + ballistica\base\graphics\support + ballistica\base\graphics\text @@ -757,12 +763,6 @@ ballistica\base\support - - ballistica\base\support - - - ballistica\base\support - ballistica\base\ui @@ -799,6 +799,12 @@ ballistica\classic\python\methods + + ballistica\classic\support + + + ballistica\classic\support + ballistica\classic\support diff --git a/config/projectconfig.json b/config/projectconfig.json index 6dbb5ae0..68dd6d90 100644 --- a/config/projectconfig.json +++ b/config/projectconfig.json @@ -10,7 +10,8 @@ "src/ballistica/base/graphics/texture/ktx.cc", "src/ballistica/core/platform/android/android_gl3.h", "src/ballistica/base/platform/apple/app_delegate.h", - "src/ballistica/base/platform/apple/scripting_bridge_music.h", + "src/ballistica/base/platform/apple/MacMusicApp.h", + "src/ballistica/base/platform/apple/MacMusicAppScriptingBridge.h", "src/ballistica/core/platform/android/utf8/checked.h", "src/ballistica/core/platform/android/utf8/unchecked.h", "src/ballistica/core/platform/android/utf8/core.h", diff --git a/src/assets/ba_data/python/babase/__init__.py b/src/assets/ba_data/python/babase/__init__.py index 9eb09af0..e15a774a 100644 --- a/src/assets/ba_data/python/babase/__init__.py +++ b/src/assets/ba_data/python/babase/__init__.py @@ -85,7 +85,6 @@ from _babase import ( screenmessage, set_analytics_screen, set_low_level_config_value, - set_stress_testing, set_thread_name, set_ui_input_device, show_progress_bar, @@ -303,7 +302,6 @@ __all__ = [ 'SessionTeamNotFoundError', 'set_analytics_screen', 'set_low_level_config_value', - 'set_stress_testing', 'set_thread_name', 'set_ui_input_device', 'show_progress_bar', diff --git a/src/assets/ba_data/python/baclassic/_benchmark.py b/src/assets/ba_data/python/baclassic/_benchmark.py index 18e04335..6bb22743 100644 --- a/src/assets/ba_data/python/baclassic/_benchmark.py +++ b/src/assets/ba_data/python/baclassic/_benchmark.py @@ -8,6 +8,7 @@ from typing import TYPE_CHECKING import babase import bascenev1 +import _baclassic if TYPE_CHECKING: from typing import Any, Sequence @@ -84,7 +85,8 @@ def run_stress_test( def stop_stress_test() -> None: """End a running stress test.""" - babase.set_stress_testing(False, 0) + + _baclassic.set_stress_testing(False, 0) assert babase.app.classic is not None try: if babase.app.classic.stress_test_reset_timer is not None: @@ -134,14 +136,14 @@ def start_stress_test(args: dict[str, Any]) -> None: babase.Call(bascenev1.new_host_session, FreeForAllSession), ), ) - babase.set_stress_testing(True, args['player_count']) + _baclassic.set_stress_testing(True, args['player_count']) babase.app.classic.stress_test_reset_timer = babase.AppTimer( args['round_duration'], babase.Call(_reset_stress_test, args) ) def _reset_stress_test(args: dict[str, Any]) -> None: - babase.set_stress_testing(False, args['player_count']) + _baclassic.set_stress_testing(False, args['player_count']) babase.screenmessage('Resetting stress test...') session = bascenev1.get_foreground_host_session() assert session is not None diff --git a/src/assets/ba_data/python/baclassic/_music.py b/src/assets/ba_data/python/baclassic/_music.py index bdda3a3a..8f439d79 100644 --- a/src/assets/ba_data/python/baclassic/_music.py +++ b/src/assets/ba_data/python/baclassic/_music.py @@ -165,15 +165,16 @@ class MusicSubsystem: def supports_soundtrack_entry_type(self, entry_type: str) -> bool: """Return whether provided soundtrack entry type is supported here.""" - uas = babase.env()['legacy_user_agent_string'] - assert isinstance(uas, str) - - # FIXME: Generalize this. + # Note to self; can't access babase.app.classic here because + # we are called during its construction. + env = babase.env() + platform = env.get('platform') + assert isinstance(platform, str) if entry_type == 'iTunesPlaylist': - return 'Mac' in uas + return platform == 'mac' and babase.is_xcode_build() if entry_type in ('musicFile', 'musicFolder'): return ( - 'android' in uas + platform == 'android' and babase.android_get_external_files_dir() is not None ) if entry_type == 'default': diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 1d1469c6..f3969a7d 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21531 +TARGET_BALLISTICA_BUILD = 21543 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/base.cc b/src/ballistica/base/base.cc index 2871e6ac..00953ffa 100644 --- a/src/ballistica/base/base.cc +++ b/src/ballistica/base/base.cc @@ -9,6 +9,7 @@ #include "ballistica/base/audio/audio_server.h" #include "ballistica/base/dynamics/bg/bg_dynamics_server.h" #include "ballistica/base/graphics/graphics_server.h" +#include "ballistica/base/graphics/support/screen_messages.h" #include "ballistica/base/graphics/text/text_graphics.h" #include "ballistica/base/input/input.h" #include "ballistica/base/logic/logic.h" @@ -20,11 +21,11 @@ #include "ballistica/base/python/class/python_class_feature_set_data.h" #include "ballistica/base/python/support/python_context_call.h" #include "ballistica/base/support/app_config.h" +#include "ballistica/base/support/app_timer.h" #include "ballistica/base/support/base_build_switches.h" #include "ballistica/base/support/huffman.h" #include "ballistica/base/support/plus_soft.h" #include "ballistica/base/support/stdio_console.h" -#include "ballistica/base/support/stress_test.h" #include "ballistica/base/ui/dev_console.h" #include "ballistica/base/ui/ui_delegate.h" #include "ballistica/core/python/core_python.h" @@ -63,7 +64,6 @@ BaseFeatureSet::BaseFeatureSet() python{new BasePython()}, stdio_console{g_buildconfig.enable_stdio_console() ? new StdioConsole() : nullptr}, - stress_test_{new StressTest()}, text_graphics{new TextGraphics()}, ui{new UI()}, utils{new Utils()} { @@ -465,8 +465,9 @@ auto BaseFeatureSet::InGraphicsContext() const -> bool { void BaseFeatureSet::ScreenMessage(const std::string& s, const Vector3f& color) { - logic->event_loop()->PushCall( - [this, s, color] { graphics->AddScreenMessage(s, color); }); + logic->event_loop()->PushCall([this, s, color] { + graphics->screenmessages->AddScreenMessage(s, color); + }); } void BaseFeatureSet::DoV1CloudLog(const std::string& msg) { diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index f4b04101..2503a134 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -102,12 +102,12 @@ class RemoteAppServer; class RemoteControlInput; class Repeater; class ScoreToBeat; +class ScreenMessages; class AppAdapterSDL; class SDLContext; class SoundAsset; class SpriteMesh; class StdioConsole; -class StressTest; class Module; class TestInput; class TextGroup; @@ -752,8 +752,6 @@ class BaseFeatureSet : public FeatureSetNativeComponent, void set_app_mode(AppMode* mode); auto* app_mode() const { return app_mode_; } - auto* stress_test() const { return stress_test_; } - /// Whether we're running under ballisticakit_server.py /// (affects some app behavior). auto server_wrapper_managed() { return server_wrapper_managed_; } @@ -776,7 +774,6 @@ class BaseFeatureSet : public FeatureSetNativeComponent, AppMode* app_mode_; PlusSoftInterface* plus_soft_{}; ClassicSoftInterface* classic_soft_{}; - StressTest* stress_test_; std::mutex shutdown_suppress_lock_; bool shutdown_suppress_disallowed_{}; diff --git a/src/ballistica/base/graphics/graphics.cc b/src/ballistica/base/graphics/graphics.cc index 790f955d..7fe3f3e9 100644 --- a/src/ballistica/base/graphics/graphics.cc +++ b/src/ballistica/base/graphics/graphics.cc @@ -11,25 +11,23 @@ #include "ballistica/base/graphics/component/special_component.h" #include "ballistica/base/graphics/component/sprite_component.h" #include "ballistica/base/graphics/graphics_server.h" -#include "ballistica/base/graphics/mesh/nine_patch_mesh.h" #include "ballistica/base/graphics/support/camera.h" #include "ballistica/base/graphics/support/net_graph.h" -#include "ballistica/base/graphics/text/text_graphics.h" +#include "ballistica/base/graphics/support/screen_messages.h" #include "ballistica/base/input/input.h" #include "ballistica/base/logic/logic.h" #include "ballistica/base/python/support/python_context_call.h" #include "ballistica/base/support/app_config.h" #include "ballistica/base/ui/ui.h" #include "ballistica/shared/foundation/event_loop.h" -#include "ballistica/shared/generic/utils.h" namespace ballistica::base { -const float kScreenMessageZDepth{-0.06f}; -const float kScreenMeshZDepth{-0.05f}; +const float kScreenTextZDepth{-0.06f}; const float kProgressBarZDepth{0.0f}; const int kProgressBarFadeTime{500}; const float kDebugImgZDepth{-0.04f}; +const float kScreenMeshZDepth{-0.05f}; auto Graphics::IsShaderTransparent(ShadingType c) -> bool { switch (c) { @@ -80,7 +78,7 @@ auto Graphics::IsShaderTransparent(ShadingType c) -> bool { } } -Graphics::Graphics() = default; +Graphics::Graphics() : screenmessages{new ScreenMessages()} {} Graphics::~Graphics() = default; void Graphics::OnAppStart() { assert(g_base->InLogicThread()); } @@ -344,43 +342,6 @@ auto Graphics::GetShadowDensity(float x, float y, float z) -> float { } } -class Graphics::ScreenMessageEntry { - public: - ScreenMessageEntry(std::string text, bool top_style, uint32_t c, - const Vector3f& color, TextureAsset* texture, - TextureAsset* tint_texture, const Vector3f& tint, - const Vector3f& tint2) - : top_style(top_style), - creation_time(c), - s_raw(std::move(text)), - color(color), - texture(texture), - tint_texture(tint_texture), - tint(tint), - tint2(tint2) {} - auto GetText() -> TextGroup&; - void UpdateTranslation(); - bool top_style; - uint32_t creation_time; - Vector3f color; - Vector3f tint; - Vector3f tint2; - std::string s_raw; - std::string s_translated; - float str_width{}; - float str_height{}; - Object::Ref texture; - Object::Ref tint_texture; - float v_smoothed{}; - bool translation_dirty{true}; - bool mesh_dirty{true}; - millisecs_t smooth_time{}; - Object::Ref shadow_mesh_; - - private: - Object::Ref s_mesh_; -}; - // Draw controls and things that lie on top of the action. void Graphics::DrawMiscOverlays(FrameDef* frame_def) { RenderPass* pass = frame_def->overlay_pass(); @@ -398,7 +359,6 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { last_fps_ = total_frames_rendered - last_total_frames_rendered_; last_total_frames_rendered_ = total_frames_rendered; } - float v{}; if (show_fps_) { char fps_str[32]; @@ -460,7 +420,7 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { { auto xf = c.ScopedTransform(); c.Translate(14.0f + (show_fps_ ? 30.0f : 0.0f), 0.1f, - kScreenMessageZDepth); + kScreenTextZDepth); c.Scale(0.7f, 0.7f); c.DrawMesh(ping_text_group_->GetElementMesh(e)); } @@ -488,7 +448,7 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { c.SetFlatness(1.0f); { auto xf = c.ScopedTransform(); - c.Translate(4.0f, (show_fps_ ? 66.0f : 40.0f), kScreenMessageZDepth); + c.Translate(4.0f, (show_fps_ ? 66.0f : 40.0f), kScreenTextZDepth); c.Scale(0.7f, 0.7f); c.DrawMesh(net_info_text_group_->GetElementMesh(e)); } @@ -516,392 +476,7 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { } } - // Screen messages (bottom). - { - // Delete old ones. - if (!screen_messages_.empty()) { - millisecs_t cutoff; - if (g_core->GetAppTimeMillisecs() > 5000) { - cutoff = g_core->GetAppTimeMillisecs() - 5000; - for (auto i = screen_messages_.begin(); i != screen_messages_.end();) { - if (i->creation_time < cutoff) { - auto next = i; - next++; - screen_messages_.erase(i); - i = next; - } else { - i++; - } - } - } - } - - // Delete if we have too many. - while ((screen_messages_.size()) > 4) { - screen_messages_.erase(screen_messages_.begin()); - } - - // Draw all existing. - if (!screen_messages_.empty()) { - bool vr = g_core->IsVRMode(); - - // These are less disruptive in the middle for menus but at the bottom - // during gameplay. - float start_v = g_base->graphics->screen_virtual_height() * 0.05f; - float scale; - switch (g_base->ui->scale()) { - case UIScale::kSmall: - scale = 1.5f; - break; - case UIScale::kMedium: - scale = 1.2f; - break; - default: - scale = 1.0f; - break; - } - - // Shadows. - { - SimpleComponent c(pass); - c.SetTransparent(true); - c.SetTexture( - // g_base->assets->SysTexture(SysTextureID::kSoftRectVertical)); - g_base->assets->SysTexture(SysTextureID::kShadowSharp)); - - float screen_width = g_base->graphics->screen_virtual_width(); - - v = start_v; - - millisecs_t youngest_age = 9999; - - for (auto i = screen_messages_.rbegin(); i != screen_messages_.rend(); - i++) { - // Update the translation if need be. - i->UpdateTranslation(); - - // Don't actually need the text just yet but need shadow mesh - // which is calculated as part of it. - i->GetText(); - - millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time; - youngest_age = std::min(youngest_age, age); - float s_extra = 1.0f; - if (age < 100) { - s_extra = std::min(1.2f, 1.2f * (static_cast(age) / 100.0f)); - } else if (age < 150) { - s_extra = - 1.2f - 0.2f * ((150.0f - static_cast(age)) / 50.0f); - } - - float a; - if (age > 3000) { - a = 1.0f - static_cast(age - 3000) / 2000; - } else { - a = 1; - } - a *= 0.7f; - - // if (vr) { - // a *= 0.8f; - // } - - if (i->translation_dirty) { - BA_LOG_ONCE( - LogLevel::kWarning, - "Found dirty translation on screenmessage draw pass 1; raw=" - + i->s_raw); - } - - float str_height = i->str_height; - float str_width = i->str_width; - - if ((str_width * scale) > (screen_width - 40)) { - s_extra *= ((screen_width - 40) / (str_width * scale)); - } - - float r = i->color.x; - float g = i->color.y; - float b = i->color.z; - GetSafeColor(&r, &g, &b); - - float v_extra = scale * (static_cast(youngest_age) * 0.01f); - - float fade; - if (age < 100) { - fade = 1.0f; - } else { - // Don't fade ALL the way to black; leaves a tiny bit of color - // showing which looks nice. - fade = std::max(0.07f, (200.0f - static_cast(age)) / 100.0f); - } - c.SetColor(r * fade, g * fade, b * fade, a); - - { - auto xf = c.ScopedTransform(); - - // This logic needs to run at a fixed hz or it breaks on high frame - // rates. - auto now_millisecs = pass->frame_def()->display_time_millisecs(); - i->smooth_time = std::max(i->smooth_time, now_millisecs - 100); - while (i->smooth_time < now_millisecs) { - i->smooth_time += 1000 / 60; - if (i->v_smoothed == 0.0f) { - i->v_smoothed = v + v_extra; - } else { - float smoothing = 0.8f; - i->v_smoothed = smoothing * i->v_smoothed - + (1.0f - smoothing) * (v + v_extra); - } - } - - c.Translate(screen_width * 0.5f, i->v_smoothed, - vr ? 60 : kScreenMessageZDepth); - - // if (vr) { - // // Let's drop down a bit in vr mode. - // // c.Translate(0, -10.0f, 0); - // // c.Scale((str_width + 60) * scale * s_extra, - // // (str_height + 20) * scale * s_extra); - // c.Scale(scale * s_extra, scale * s_extra); - - // // Align our bottom with where we just scaled from. - // c.Translate(0, 0.5f, 0); - { - // c.Scale((str_width + 110) * scale * s_extra, - // (str_height + 40) * scale * s_extra); - c.Scale(scale * s_extra, scale * s_extra); - c.Translate(0, 20); - - // Align our bottom with where we just scaled from. - c.Translate(0, 0.5f, 0); - } - // c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1)); - assert(i->shadow_mesh_.Exists()); - c.DrawMesh(i->shadow_mesh_.Get()); - } - - v += scale * (36 + str_height); - if (v > g_base->graphics->screen_virtual_height() + 30) { - break; - } - } - c.Submit(); - } - - // Now the strings themselves. - { - SimpleComponent c(pass); - c.SetTransparent(true); - - float screen_width = g_base->graphics->screen_virtual_width(); - v = start_v; - millisecs_t youngest_age = 9999; - - for (auto i = screen_messages_.rbegin(); i != screen_messages_.rend(); - i++) { - millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time; - youngest_age = std::min(youngest_age, age); - float s_extra = 1.0f; - if (age < 100) { - s_extra = std::min(1.2f, 1.2f * (static_cast(age) / 100.0f)); - } else if (age < 150) { - s_extra = - 1.2f - 0.2f * ((150.0f - static_cast(age)) / 50.0f); - } - float a; - if (age > 3000) { - a = 1.0f - static_cast(age - 3000) / 2000; - } else { - a = 1; - } - if (i->translation_dirty) { - BA_LOG_ONCE( - LogLevel::kWarning, - "Found dirty translation on screenmessage draw pass 2; raw=" - + i->s_raw); - } - float str_height = i->str_height; - float str_width = i->str_width; - - if ((str_width * scale) > (screen_width - 40)) { - s_extra *= ((screen_width - 40) / (str_width * scale)); - } - float r = i->color.x; - float g = i->color.y; - float b = i->color.z; - GetSafeColor(&r, &g, &b, 0.85f); - - int elem_count = i->GetText().GetElementCount(); - for (int e = 0; e < elem_count; e++) { - // Gracefully skip unloaded textures. - TextureAsset* t = i->GetText().GetElementTexture(e); - if (!t->preloaded()) { - continue; - } - c.SetTexture(t); - if (i->GetText().GetElementCanColor(e)) { - c.SetColor(r, g, b, a); - } else { - c.SetColor(1, 1, 1, a); - } - c.SetFlatness(i->GetText().GetElementMaxFlatness(e)); - { - auto xf = c.ScopedTransform(); - c.Translate(screen_width * 0.5f, i->v_smoothed, - vr ? 150 : kScreenMessageZDepth); - c.Scale(scale * s_extra, scale * s_extra); - c.Translate(0, 20); - c.DrawMesh(i->GetText().GetElementMesh(e)); - } - } - - v += scale * (36 + str_height); - if (v > g_base->graphics->screen_virtual_height() + 30) { - break; - } - } - c.Submit(); - } - } - } - - // Screen messages (top). - { - // Delete old ones. - if (!screen_messages_top_.empty()) { - millisecs_t cutoff; - if (g_core->GetAppTimeMillisecs() > 5000) { - cutoff = g_core->GetAppTimeMillisecs() - 5000; - for (auto i = screen_messages_top_.begin(); - i != screen_messages_top_.end();) { - if (i->creation_time < cutoff) { - auto next = i; - next++; - screen_messages_top_.erase(i); - i = next; - } else { - i++; - } - } - } - } - - // Delete if we have too many. - while ((screen_messages_top_.size()) > 6) { - screen_messages_top_.erase(screen_messages_top_.begin()); - } - - if (!screen_messages_top_.empty()) { - SimpleComponent c(pass); - c.SetTransparent(true); - - // Draw all existing. - float h = pass->virtual_width() - 300.0f; - v = g_base->graphics->screen_virtual_height() - 50.0f; - - float v_base = g_base->graphics->screen_virtual_height(); - float last_v = -999.0f; - - float min_spacing = 25.0f; - - for (auto i = screen_messages_top_.rbegin(); - i != screen_messages_top_.rend(); i++) { - // Update the translation if need be. - i->UpdateTranslation(); - - millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time; - float s_extra = 1.0f; - if (age < 100) { - s_extra = std::min(1.1f, 1.1f * (static_cast(age) / 100.0f)); - } else if (age < 150) { - s_extra = 1.1f - 0.1f * ((150.0f - static_cast(age)) / 50.0f); - } - - float a; - if (age > 3000) { - a = 1.0f - static_cast(age - 3000) / 2000; - } else { - a = 1; - } - - // This logic needs to run at a fixed hz or it breaks on high frame - // rates. - auto now_millisecs = pass->frame_def()->display_time_millisecs(); - i->smooth_time = std::max(i->smooth_time, now_millisecs - 100); - while (i->smooth_time < now_millisecs) { - i->smooth_time += 1000 / 60; - i->v_smoothed += 0.1f; - if (i->v_smoothed - last_v < min_spacing) { - i->v_smoothed += - 8.0f * (1.0f - ((i->v_smoothed - last_v) / min_spacing)); - } - } - last_v = i->v_smoothed; - - // Draw the image if they provided one. - if (i->texture.Exists()) { - c.Submit(); - - SimpleComponent c2(pass); - c2.SetTransparent(true); - c2.SetTexture(i->texture); - if (i->tint_texture.Exists()) { - c2.SetColorizeTexture(i->tint_texture.Get()); - c2.SetColorizeColor(i->tint.x, i->tint.y, i->tint.z); - c2.SetColorizeColor2(i->tint2.x, i->tint2.y, i->tint2.z); - c2.SetMaskTexture( - g_base->assets->SysTexture(SysTextureID::kCharacterIconMask)); - } - c2.SetColor(1, 1, 1, a); - { - auto xf = c2.ScopedTransform(); - c2.Translate(h - 14, v_base + 10 + i->v_smoothed, - kScreenMessageZDepth); - c2.Scale(22.0f * s_extra, 22.0f * s_extra); - c2.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1)); - } - c2.Submit(); - } - - float r = i->color.x; - float g = i->color.y; - float b = i->color.z; - GetSafeColor(&r, &g, &b); - - int elem_count = i->GetText().GetElementCount(); - for (int e = 0; e < elem_count; e++) { - // Gracefully skip unloaded textures. - TextureAsset* t = i->GetText().GetElementTexture(e); - if (!t->preloaded()) { - continue; - } - c.SetTexture(t); - if (i->GetText().GetElementCanColor(e)) { - c.SetColor(r, g, b, a); - } else { - c.SetColor(1, 1, 1, a); - } - c.SetShadow(-0.003f * i->GetText().GetElementUScale(e), - -0.003f * i->GetText().GetElementVScale(e), 0.0f, - 1.0f * a); - c.SetFlatness(i->GetText().GetElementMaxFlatness(e)); - c.SetMaskUV2Texture(i->GetText().GetElementMaskUV2Texture(e)); - { - auto xf = c.ScopedTransform(); - c.Translate(h, v_base + 2 + i->v_smoothed, kScreenMessageZDepth); - c.Scale(0.6f * s_extra, 0.6f * s_extra); - c.DrawMesh(i->GetText().GetElementMesh(e)); - } - } - assert(!i->translation_dirty); - v -= g_base->text_graphics->GetStringHeight(i->s_translated.c_str()) - * 0.6f - + 8.0f; - } - c.Submit(); - } - } + screenmessages->DrawMiscOverlays(frame_def); } auto Graphics::GetDebugGraph(const std::string& name, bool smoothed) @@ -947,32 +522,6 @@ void Graphics::GetSafeColor(float* red, float* green, float* blue, } } -void Graphics::AddScreenMessage(const std::string& msg, const Vector3f& color, - bool top, TextureAsset* texture, - TextureAsset* tint_texture, - const Vector3f& tint, const Vector3f& tint2) { - assert(g_base->InLogicThread()); - - // So we know we're always dealing with valid utf8. - std::string m = Utils::GetValidUTF8(msg.c_str(), "ga9msg"); - - if (top) { - float start_v = -40.0f; - if (!screen_messages_top_.empty()) { - start_v = std::min( - start_v, - std::max(-100.0f, screen_messages_top_.back().v_smoothed - 25.0f)); - } - screen_messages_top_.emplace_back(m, true, g_core->GetAppTimeMillisecs(), - color, texture, tint_texture, tint, - tint2); - screen_messages_top_.back().v_smoothed = start_v; - } else { - screen_messages_.emplace_back(m, false, g_core->GetAppTimeMillisecs(), - color, texture, tint_texture, tint, tint2); - } -} - void Graphics::Reset() { assert(g_base->InLogicThread()); fade_ = 0; @@ -982,9 +531,7 @@ void Graphics::Reset() { camera_ = Object::New(); } - // Wipe out top screen messages since they might be using textures that are - // being reset. Bottom ones are ok since they have no textures. - screen_messages_top_.clear(); + screenmessages->Reset(); } void Graphics::InitInternalComponents(FrameDef* frame_def) { @@ -1609,16 +1156,6 @@ void Graphics::DrawBlotches(FrameDef* frame_def) { } } -void Graphics::ClearScreenMessageTranslations() { - assert(g_base && g_base->InLogicThread()); - for (auto&& i : screen_messages_) { - i.translation_dirty = true; - } - for (auto&& i : screen_messages_top_) { - i.translation_dirty = true; - } -} - void Graphics::ReturnCompletedFrameDef(FrameDef* frame_def) { std::scoped_lock lock(frame_def_delete_list_mutex_); g_base->graphics->frame_def_delete_list_.push_back(frame_def); @@ -1949,46 +1486,6 @@ void Graphics::DrawRadialMeter(MeshIndexedSimpleFull* m, float amt) { } } -auto Graphics::ScreenMessageEntry::GetText() -> TextGroup& { - if (translation_dirty) { - BA_LOG_ONCE( - LogLevel::kWarning, - "Found dirty translation on screenmessage GetText; raw=" + s_raw); - } - if (!s_mesh_.Exists()) { - s_mesh_ = Object::New(); - mesh_dirty = true; - } - if (mesh_dirty) { - s_mesh_->SetText( - s_translated, - top_style ? TextMesh::HAlign::kLeft : TextMesh::HAlign::kCenter, - TextMesh::VAlign::kBottom); - - str_width = g_base->text_graphics->GetStringWidth(s_translated.c_str()); - str_height = g_base->text_graphics->GetStringHeight(s_translated.c_str()); - - if (!top_style) { - float x_extend = 40.0f; - float y_extend = 40.0f; - float y_offset = -5.0f; - float corner_radius = 60.0f; - float width_fin = str_width + x_extend * 2.0f; - float height_fin = str_height + y_extend * 2.0f; - float x_border = - NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin); - float y_border = - NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin); - shadow_mesh_ = Object::New( - -0.5f * width_fin, -y_extend + y_offset, 0.0f, width_fin, height_fin, - x_border, y_border, x_border, y_border); - } - - mesh_dirty = false; - } - return *s_mesh_; -} - void Graphics::OnScreenSizeChange() {} void Graphics::CalcVirtualRes_(float* x, float* y) { @@ -2042,15 +1539,6 @@ void Graphics::SetScreenResolution(float x, float y) { UpdateInitialGraphicsSettingsSend_(); } -void Graphics::ScreenMessageEntry::UpdateTranslation() { - if (translation_dirty) { - s_translated = g_base->assets->CompileResourceString( - s_raw, "Graphics::ScreenMessageEntry::UpdateTranslation"); - translation_dirty = false; - mesh_dirty = true; - } -} - auto Graphics::CubeMapFromReflectionType(ReflectionType reflection_type) -> SysCubeMapTextureID { switch (reflection_type) { @@ -2130,8 +1618,8 @@ void Graphics::LanguageChanged() { Log(LogLevel::kWarning, "Graphics::LanguageChanged() called during draw; should not happen."); } - // Also clear translations on all screen-messages. - ClearScreenMessageTranslations(); + + screenmessages->ClearScreenMessageTranslations(); } auto Graphics::GraphicsQualityFromRequest(GraphicsQualityRequest request, @@ -2154,6 +1642,7 @@ auto Graphics::GraphicsQualityFromRequest(GraphicsQualityRequest request, return GraphicsQuality::kLow; } } + auto Graphics::TextureQualityFromRequest(TextureQualityRequest request, TextureQuality auto_val) -> TextureQuality { diff --git a/src/ballistica/base/graphics/graphics.h b/src/ballistica/base/graphics/graphics.h index 1e9736ed..115f0adc 100644 --- a/src/ballistica/base/graphics/graphics.h +++ b/src/ballistica/base/graphics/graphics.h @@ -118,8 +118,6 @@ class Graphics { return res_y_virtual_; } - void ClearScreenMessageTranslations(); - // Given a point in space, returns the shadow density that should be drawn // into the shadow pass. Does this belong somewhere else? auto GetShadowDensity(float x, float y, float z) -> float; @@ -127,14 +125,6 @@ class Graphics { static void GetSafeColor(float* r, float* g, float* b, float target_intensity = 0.6f); - // Print a message to the on-screen list. - void AddScreenMessage(const std::string& msg, - const Vector3f& color = {1, 1, 1}, bool top = false, - TextureAsset* texture = nullptr, - TextureAsset* tint_texture = nullptr, - const Vector3f& tint = {1, 1, 1}, - const Vector3f& tint2 = {1, 1, 1}); - // Fade the local screen in or out over the given time period. void FadeScreen(bool to, millisecs_t time, PyObject* endcall); @@ -366,9 +356,9 @@ class Graphics { return client_context_snapshot_.Get()->Get(); } - protected: - class ScreenMessageEntry; + ScreenMessages* const screenmessages; + protected: virtual ~Graphics(); virtual void DoDrawFade(FrameDef* frame_def, float amt); static void CalcVirtualRes_(float* x, float* y); @@ -446,8 +436,6 @@ class Graphics { std::map> debug_graphs_; std::mutex frame_def_delete_list_mutex_; std::list> clean_frame_commands_; - std::list screen_messages_; - std::list screen_messages_top_; std::vector recycle_frame_defs_; std::vector blotch_indices_; std::vector blotch_verts_; @@ -466,7 +454,6 @@ class Graphics { float gyro_mag_test_{}; float overlay_node_z_depth_{}; float progress_bar_progress_{}; - float screen_gamma_{1.0f}; float shadow_lower_bottom_{-4.0f}; float shadow_lower_top_{4.0f}; float shadow_upper_bottom_{30.0f}; diff --git a/src/ballistica/base/graphics/support/screen_messages.cc b/src/ballistica/base/graphics/support/screen_messages.cc new file mode 100644 index 00000000..4dcebfd0 --- /dev/null +++ b/src/ballistica/base/graphics/support/screen_messages.cc @@ -0,0 +1,538 @@ +// Released under the MIT License. See LICENSE for details. + +#include "ballistica/base/graphics/support/screen_messages.h" + +#include "ballistica/base/graphics/component/simple_component.h" +#include "ballistica/base/graphics/mesh/nine_patch_mesh.h" +#include "ballistica/base/graphics/text/text_graphics.h" +#include "ballistica/base/ui/ui.h" +#include "ballistica/shared/generic/utils.h" + +namespace ballistica::base { + +const float kScreenMessageZDepth{-0.06f}; + +class ScreenMessages::ScreenMessageEntry { + public: + ScreenMessageEntry(std::string text, bool top_style, uint32_t c, + const Vector3f& color, TextureAsset* texture, + TextureAsset* tint_texture, const Vector3f& tint, + const Vector3f& tint2) + : top_style(top_style), + creation_time(c), + s_raw(std::move(text)), + color(color), + texture(texture), + tint_texture(tint_texture), + tint(tint), + tint2(tint2) {} + auto GetText() -> TextGroup&; + void UpdateTranslation(); + bool top_style; + uint32_t creation_time; + Vector3f color; + Vector3f tint; + Vector3f tint2; + std::string s_raw; + std::string s_translated; + float str_width{}; + float str_height{}; + Object::Ref texture; + Object::Ref tint_texture; + float v_smoothed{}; + bool translation_dirty{true}; + bool mesh_dirty{true}; + millisecs_t smooth_time{}; + Object::Ref shadow_mesh_; + + private: + Object::Ref s_mesh_; +}; + +ScreenMessages::ScreenMessages() = default; + +void ScreenMessages::DrawMiscOverlays(FrameDef* frame_def) { + RenderPass* pass = frame_def->overlay_pass(); + + // Screen messages (bottom). + { + // Delete old ones. + if (!screen_messages_.empty()) { + millisecs_t cutoff; + if (g_core->GetAppTimeMillisecs() > 5000) { + cutoff = g_core->GetAppTimeMillisecs() - 5000; + for (auto i = screen_messages_.begin(); i != screen_messages_.end();) { + if (i->creation_time < cutoff) { + auto next = i; + next++; + screen_messages_.erase(i); + i = next; + } else { + i++; + } + } + } + } + + // Delete if we have too many. + while ((screen_messages_.size()) > 4) { + screen_messages_.erase(screen_messages_.begin()); + } + + // Draw all existing. + if (!screen_messages_.empty()) { + bool vr = g_core->IsVRMode(); + + // These are less disruptive in the middle for menus but at the bottom + // during gameplay. + float start_v = g_base->graphics->screen_virtual_height() * 0.05f; + float scale; + switch (g_base->ui->scale()) { + case UIScale::kSmall: + scale = 1.5f; + break; + case UIScale::kMedium: + scale = 1.2f; + break; + default: + scale = 1.0f; + break; + } + + // Shadows. + { + SimpleComponent c(pass); + c.SetTransparent(true); + c.SetTexture( + // g_base->assets->SysTexture(SysTextureID::kSoftRectVertical)); + g_base->assets->SysTexture(SysTextureID::kShadowSharp)); + + float screen_width = g_base->graphics->screen_virtual_width(); + + float v = start_v; + + millisecs_t youngest_age = 9999; + + for (auto i = screen_messages_.rbegin(); i != screen_messages_.rend(); + i++) { + // Update the translation if need be. + i->UpdateTranslation(); + + // Don't actually need the text just yet but need shadow mesh + // which is calculated as part of it. + i->GetText(); + + millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time; + youngest_age = std::min(youngest_age, age); + float s_extra = 1.0f; + if (age < 100) { + s_extra = std::min(1.2f, 1.2f * (static_cast(age) / 100.0f)); + } else if (age < 150) { + s_extra = + 1.2f - 0.2f * ((150.0f - static_cast(age)) / 50.0f); + } + + float a; + if (age > 3000) { + a = 1.0f - static_cast(age - 3000) / 2000; + } else { + a = 1; + } + a *= 0.7f; + + // if (vr) { + // a *= 0.8f; + // } + + if (i->translation_dirty) { + BA_LOG_ONCE( + LogLevel::kWarning, + "Found dirty translation on screenmessage draw pass 1; raw=" + + i->s_raw); + } + + float str_height = i->str_height; + float str_width = i->str_width; + + if ((str_width * scale) > (screen_width - 40)) { + s_extra *= ((screen_width - 40) / (str_width * scale)); + } + + float r = i->color.x; + float g = i->color.y; + float b = i->color.z; + Graphics::GetSafeColor(&r, &g, &b); + + float v_extra = scale * (static_cast(youngest_age) * 0.01f); + + float fade; + if (age < 100) { + fade = 1.0f; + } else { + // Don't fade ALL the way to black; leaves a tiny bit of color + // showing which looks nice. + fade = std::max(0.07f, (200.0f - static_cast(age)) / 100.0f); + } + c.SetColor(r * fade, g * fade, b * fade, a); + + { + auto xf = c.ScopedTransform(); + + // This logic needs to run at a fixed hz or it breaks on high frame + // rates. + auto now_millisecs = pass->frame_def()->display_time_millisecs(); + i->smooth_time = std::max(i->smooth_time, now_millisecs - 100); + while (i->smooth_time < now_millisecs) { + i->smooth_time += 1000 / 60; + if (i->v_smoothed == 0.0f) { + i->v_smoothed = v + v_extra; + } else { + float smoothing = 0.8f; + i->v_smoothed = smoothing * i->v_smoothed + + (1.0f - smoothing) * (v + v_extra); + } + } + + c.Translate(screen_width * 0.5f, i->v_smoothed, + vr ? 60 : kScreenMessageZDepth); + + // if (vr) { + // // Let's drop down a bit in vr mode. + // // c.Translate(0, -10.0f, 0); + // // c.Scale((str_width + 60) * scale * s_extra, + // // (str_height + 20) * scale * s_extra); + // c.Scale(scale * s_extra, scale * s_extra); + + // // Align our bottom with where we just scaled from. + // c.Translate(0, 0.5f, 0); + { + // c.Scale((str_width + 110) * scale * s_extra, + // (str_height + 40) * scale * s_extra); + c.Scale(scale * s_extra, scale * s_extra); + c.Translate(0, 20); + + // Align our bottom with where we just scaled from. + c.Translate(0, 0.5f, 0); + } + // c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1)); + assert(i->shadow_mesh_.Exists()); + c.DrawMesh(i->shadow_mesh_.Get()); + } + + v += scale * (36 + str_height); + if (v > g_base->graphics->screen_virtual_height() + 30) { + break; + } + } + c.Submit(); + } + + // Now the strings themselves. + { + SimpleComponent c(pass); + c.SetTransparent(true); + + float screen_width = g_base->graphics->screen_virtual_width(); + float v = start_v; + millisecs_t youngest_age = 9999; + + for (auto i = screen_messages_.rbegin(); i != screen_messages_.rend(); + i++) { + millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time; + youngest_age = std::min(youngest_age, age); + float s_extra = 1.0f; + if (age < 100) { + s_extra = std::min(1.2f, 1.2f * (static_cast(age) / 100.0f)); + } else if (age < 150) { + s_extra = + 1.2f - 0.2f * ((150.0f - static_cast(age)) / 50.0f); + } + float a; + if (age > 3000) { + a = 1.0f - static_cast(age - 3000) / 2000; + } else { + a = 1; + } + if (i->translation_dirty) { + BA_LOG_ONCE( + LogLevel::kWarning, + "Found dirty translation on screenmessage draw pass 2; raw=" + + i->s_raw); + } + float str_height = i->str_height; + float str_width = i->str_width; + + if ((str_width * scale) > (screen_width - 40)) { + s_extra *= ((screen_width - 40) / (str_width * scale)); + } + float r = i->color.x; + float g = i->color.y; + float b = i->color.z; + Graphics::GetSafeColor(&r, &g, &b, 0.85f); + + int elem_count = i->GetText().GetElementCount(); + for (int e = 0; e < elem_count; e++) { + // Gracefully skip unloaded textures. + TextureAsset* t = i->GetText().GetElementTexture(e); + if (!t->preloaded()) { + continue; + } + c.SetTexture(t); + if (i->GetText().GetElementCanColor(e)) { + c.SetColor(r, g, b, a); + } else { + c.SetColor(1, 1, 1, a); + } + c.SetFlatness(i->GetText().GetElementMaxFlatness(e)); + { + auto xf = c.ScopedTransform(); + c.Translate(screen_width * 0.5f, i->v_smoothed, + vr ? 150 : kScreenMessageZDepth); + c.Scale(scale * s_extra, scale * s_extra); + c.Translate(0, 20); + c.DrawMesh(i->GetText().GetElementMesh(e)); + } + } + + v += scale * (36 + str_height); + if (v > g_base->graphics->screen_virtual_height() + 30) { + break; + } + } + c.Submit(); + } + } + } + + // Screen messages (top). + { + // Delete old ones. + if (!screen_messages_top_.empty()) { + millisecs_t cutoff; + if (g_core->GetAppTimeMillisecs() > 5000) { + cutoff = g_core->GetAppTimeMillisecs() - 5000; + for (auto i = screen_messages_top_.begin(); + i != screen_messages_top_.end();) { + if (i->creation_time < cutoff) { + auto next = i; + next++; + screen_messages_top_.erase(i); + i = next; + } else { + i++; + } + } + } + } + + // Delete if we have too many. + while ((screen_messages_top_.size()) > 6) { + screen_messages_top_.erase(screen_messages_top_.begin()); + } + + if (!screen_messages_top_.empty()) { + SimpleComponent c(pass); + c.SetTransparent(true); + + // Draw all existing. + float h = pass->virtual_width() - 300.0f; + float v = g_base->graphics->screen_virtual_height() - 50.0f; + + float v_base = g_base->graphics->screen_virtual_height(); + float last_v = -999.0f; + + float min_spacing = 25.0f; + + for (auto i = screen_messages_top_.rbegin(); + i != screen_messages_top_.rend(); i++) { + // Update the translation if need be. + i->UpdateTranslation(); + + millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time; + float s_extra = 1.0f; + if (age < 100) { + s_extra = std::min(1.1f, 1.1f * (static_cast(age) / 100.0f)); + } else if (age < 150) { + s_extra = 1.1f - 0.1f * ((150.0f - static_cast(age)) / 50.0f); + } + + float a; + if (age > 3000) { + a = 1.0f - static_cast(age - 3000) / 2000; + } else { + a = 1; + } + + // This logic needs to run at a fixed hz or it breaks on high frame + // rates. + auto now_millisecs = pass->frame_def()->display_time_millisecs(); + i->smooth_time = std::max(i->smooth_time, now_millisecs - 100); + while (i->smooth_time < now_millisecs) { + i->smooth_time += 1000 / 60; + i->v_smoothed += 0.1f; + if (i->v_smoothed - last_v < min_spacing) { + i->v_smoothed += + 8.0f * (1.0f - ((i->v_smoothed - last_v) / min_spacing)); + } + } + last_v = i->v_smoothed; + + // Draw the image if they provided one. + if (i->texture.Exists()) { + c.Submit(); + + SimpleComponent c2(pass); + c2.SetTransparent(true); + c2.SetTexture(i->texture); + if (i->tint_texture.Exists()) { + c2.SetColorizeTexture(i->tint_texture.Get()); + c2.SetColorizeColor(i->tint.x, i->tint.y, i->tint.z); + c2.SetColorizeColor2(i->tint2.x, i->tint2.y, i->tint2.z); + c2.SetMaskTexture( + g_base->assets->SysTexture(SysTextureID::kCharacterIconMask)); + } + c2.SetColor(1, 1, 1, a); + { + auto xf = c2.ScopedTransform(); + c2.Translate(h - 14, v_base + 10 + i->v_smoothed, + kScreenMessageZDepth); + c2.Scale(22.0f * s_extra, 22.0f * s_extra); + c2.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1)); + } + c2.Submit(); + } + + float r = i->color.x; + float g = i->color.y; + float b = i->color.z; + Graphics::GetSafeColor(&r, &g, &b); + + int elem_count = i->GetText().GetElementCount(); + for (int e = 0; e < elem_count; e++) { + // Gracefully skip unloaded textures. + TextureAsset* t = i->GetText().GetElementTexture(e); + if (!t->preloaded()) { + continue; + } + c.SetTexture(t); + if (i->GetText().GetElementCanColor(e)) { + c.SetColor(r, g, b, a); + } else { + c.SetColor(1, 1, 1, a); + } + c.SetShadow(-0.003f * i->GetText().GetElementUScale(e), + -0.003f * i->GetText().GetElementVScale(e), 0.0f, + 1.0f * a); + c.SetFlatness(i->GetText().GetElementMaxFlatness(e)); + c.SetMaskUV2Texture(i->GetText().GetElementMaskUV2Texture(e)); + { + auto xf = c.ScopedTransform(); + c.Translate(h, v_base + 2 + i->v_smoothed, kScreenMessageZDepth); + c.Scale(0.6f * s_extra, 0.6f * s_extra); + c.DrawMesh(i->GetText().GetElementMesh(e)); + } + } + assert(!i->translation_dirty); + v -= g_base->text_graphics->GetStringHeight(i->s_translated.c_str()) + * 0.6f + + 8.0f; + } + c.Submit(); + } + } +} + +void ScreenMessages::AddScreenMessage(const std::string& msg, + const Vector3f& color, bool top, + TextureAsset* texture, + TextureAsset* tint_texture, + const Vector3f& tint, + const Vector3f& tint2) { + assert(g_base->InLogicThread()); + + // So we know we're always dealing with valid utf8. + std::string m = Utils::GetValidUTF8(msg.c_str(), "ga9msg"); + + if (top) { + float start_v = -40.0f; + if (!screen_messages_top_.empty()) { + start_v = std::min( + start_v, + std::max(-100.0f, screen_messages_top_.back().v_smoothed - 25.0f)); + } + screen_messages_top_.emplace_back(m, true, g_core->GetAppTimeMillisecs(), + color, texture, tint_texture, tint, + tint2); + screen_messages_top_.back().v_smoothed = start_v; + } else { + screen_messages_.emplace_back(m, false, g_core->GetAppTimeMillisecs(), + color, texture, tint_texture, tint, tint2); + } +} + +void ScreenMessages::Reset() { + // Wipe out top screen messages since they might be using textures that are + // being reset. Bottom ones are ok since they have no textures. + screen_messages_top_.clear(); +} + +void ScreenMessages::ClearScreenMessageTranslations() { + assert(g_base && g_base->InLogicThread()); + for (auto&& i : screen_messages_) { + i.translation_dirty = true; + } + for (auto&& i : screen_messages_top_) { + i.translation_dirty = true; + } +} + +auto ScreenMessages::ScreenMessageEntry::GetText() -> TextGroup& { + if (translation_dirty) { + BA_LOG_ONCE( + LogLevel::kWarning, + "Found dirty translation on screenmessage GetText; raw=" + s_raw); + } + if (!s_mesh_.Exists()) { + s_mesh_ = Object::New(); + mesh_dirty = true; + } + if (mesh_dirty) { + s_mesh_->SetText( + s_translated, + top_style ? TextMesh::HAlign::kLeft : TextMesh::HAlign::kCenter, + TextMesh::VAlign::kBottom); + + str_width = g_base->text_graphics->GetStringWidth(s_translated.c_str()); + str_height = g_base->text_graphics->GetStringHeight(s_translated.c_str()); + + if (!top_style) { + float x_extend = 40.0f; + float y_extend = 40.0f; + float y_offset = -5.0f; + float corner_radius = 60.0f; + float width_fin = str_width + x_extend * 2.0f; + float height_fin = str_height + y_extend * 2.0f; + float x_border = + NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin); + float y_border = + NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin); + shadow_mesh_ = Object::New( + -0.5f * width_fin, -y_extend + y_offset, 0.0f, width_fin, height_fin, + x_border, y_border, x_border, y_border); + } + + mesh_dirty = false; + } + return *s_mesh_; +} + +void ScreenMessages::ScreenMessageEntry::UpdateTranslation() { + if (translation_dirty) { + s_translated = g_base->assets->CompileResourceString( + s_raw, "Graphics::ScreenMessageEntry::UpdateTranslation"); + translation_dirty = false; + mesh_dirty = true; + } +} + +} // namespace ballistica::base diff --git a/src/ballistica/base/graphics/support/screen_messages.h b/src/ballistica/base/graphics/support/screen_messages.h new file mode 100644 index 00000000..91652149 --- /dev/null +++ b/src/ballistica/base/graphics/support/screen_messages.h @@ -0,0 +1,37 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_BASE_GRAPHICS_SUPPORT_SCREEN_MESSAGES_H_ +#define BALLISTICA_BASE_GRAPHICS_SUPPORT_SCREEN_MESSAGES_H_ + +#include "ballistica/base/base.h" +#include "ballistica/shared/math/vector3f.h" + +namespace ballistica::base { + +/// Wrangles a set of screen-messages. +class ScreenMessages { + public: + ScreenMessages(); + + void ClearScreenMessageTranslations(); + + // Print a message to the on-screen list. + void AddScreenMessage(const std::string& msg, + const Vector3f& color = {1, 1, 1}, bool top = false, + TextureAsset* texture = nullptr, + TextureAsset* tint_texture = nullptr, + const Vector3f& tint = {1, 1, 1}, + const Vector3f& tint2 = {1, 1, 1}); + + void DrawMiscOverlays(FrameDef* frame_def); + void Reset(); + + private: + class ScreenMessageEntry; + std::list screen_messages_; + std::list screen_messages_top_; +}; + +} // namespace ballistica::base + +#endif // BALLISTICA_BASE_GRAPHICS_SUPPORT_SCREEN_MESSAGES_H_ diff --git a/src/ballistica/base/input/device/test_input.cc b/src/ballistica/base/input/device/test_input.cc index 7e20a291..b7491c2e 100644 --- a/src/ballistica/base/input/device/test_input.cc +++ b/src/ballistica/base/input/device/test_input.cc @@ -22,7 +22,7 @@ TestInput::~TestInput() { } void TestInput::Reset() { - assert(g_core->InMainThread()); + assert(g_base->InLogicThread()); reset_ = true; } @@ -33,7 +33,7 @@ void TestInput::HandleAlreadyPressedTwice() { } void TestInput::Process(millisecs_t time) { - assert(g_core->InMainThread()); + assert(g_base->InLogicThread()); if (reset_) { reset_ = false; diff --git a/src/ballistica/base/input/device/test_input.h b/src/ballistica/base/input/device/test_input.h index 34e2e4ce..b89accf4 100644 --- a/src/ballistica/base/input/device/test_input.h +++ b/src/ballistica/base/input/device/test_input.h @@ -16,20 +16,21 @@ class TestInput { private: void HandleAlreadyPressedTwice(); + int lr_{}; int ud_{}; - bool jump_pressed_{}; - bool bomb_pressed_{}; - bool pickup_pressed_{}; - bool punch_pressed_{}; + int join_press_count_{}; + bool jump_pressed_ : 1 {}; + bool bomb_pressed_ : 1 {}; + bool pickup_pressed_ : 1 {}; + bool punch_pressed_ : 1 {}; + bool print_non_join_ : 1 {}; + bool print_already_did2_ : 1 {}; + bool reset_ : 1 {true}; millisecs_t next_event_time_{}; millisecs_t join_start_time_{}; millisecs_t join_end_time_{9999}; - int join_press_count_{}; - bool reset_{true}; JoystickInput* joystick_{}; - bool print_non_join_{}; - bool print_already_did2_{}; }; } // namespace ballistica::base diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index 14b5c443..5b33f2a4 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -8,7 +8,6 @@ #include "ballistica/base/graphics/support/camera.h" #include "ballistica/base/input/device/joystick_input.h" #include "ballistica/base/input/device/keyboard_input.h" -#include "ballistica/base/input/device/test_input.h" #include "ballistica/base/input/device/touch_input.h" #include "ballistica/base/logic/logic.h" #include "ballistica/base/python/base_python.h" @@ -762,58 +761,6 @@ void Input::PrintLockLabels_() { Log(LogLevel::kError, s); } -void Input::ProcessStressTesting(int player_count) { - assert(g_core->InMainThread()); - assert(player_count >= 0); - - millisecs_t time = g_core->GetAppTimeMillisecs(); - - // FIXME: If we don't check for stress_test_last_leave_time_ we totally - // confuse the game.. need to be able to survive that. - - // Kill some off if we have too many. - while (static_cast(test_inputs_.size()) > player_count) { - delete test_inputs_.front(); - test_inputs_.pop_front(); - } - - // If we have less than full test-inputs, add one randomly. - if (static_cast(test_inputs_.size()) < player_count - && ((rand() % 1000 < 10))) { // NOLINT - test_inputs_.push_back(new TestInput()); - } - - // Every so often lets kill the oldest one off. - if (explicit_bool(true)) { - if (test_inputs_.size() > 0 && (rand() % 2000 < 3)) { // NOLINT - stress_test_last_leave_time_ = time; - - // Usually do oldest; sometimes newest. - if (rand() % 5 == 0) { // NOLINT - delete test_inputs_.back(); - test_inputs_.pop_back(); - } else { - delete test_inputs_.front(); - test_inputs_.pop_front(); - } - } - } - - if (time - stress_test_time_ > 1000) { - stress_test_time_ = time; // reset.. - for (auto& test_input : test_inputs_) { - (*test_input).Reset(); - } - } - - while (stress_test_time_ < time) { - stress_test_time_++; - for (auto& test_input : test_inputs_) { - (*test_input).Process(stress_test_time_); - } - } -} - void Input::PushTextInputEvent(const std::string& text) { assert(g_base->logic->event_loop()); g_base->logic->event_loop()->PushCall([this, text] { diff --git a/src/ballistica/base/input/input.h b/src/ballistica/base/input/input.h index e256a2ff..9c33ecd2 100644 --- a/src/ballistica/base/input/input.h +++ b/src/ballistica/base/input/input.h @@ -114,7 +114,6 @@ class Input { // something. auto HaveControllerWithPlayer() -> bool; auto HaveRemoteAppController() -> bool; - void ProcessStressTesting(int player_count); auto keyboard_input() const -> KeyboardInput* { return keyboard_input_; } auto keyboard_input_2() const -> KeyboardInput* { return keyboard_input_2_; } void CreateTouchInput(); @@ -205,7 +204,6 @@ class Input { std::list input_lock_permanent_labels_; std::list input_unlock_permanent_labels_; std::list recent_input_locks_unlocks_; - std::list test_inputs_; std::list newly_connected_controllers_; std::list newly_disconnected_controllers_; std::unordered_map > @@ -214,8 +212,6 @@ class Input { std::set keys_held_; millisecs_t last_input_device_count_update_time_{}; millisecs_t last_input_temp_lock_time_{}; - millisecs_t stress_test_time_{}; - millisecs_t stress_test_last_leave_time_{}; void* single_touch_{}; KeyboardInput* keyboard_input_{}; KeyboardInput* keyboard_input_2_{}; diff --git a/src/ballistica/base/input/support/remote_app_server.cc b/src/ballistica/base/input/support/remote_app_server.cc index 1ab678df..d5f78b95 100644 --- a/src/ballistica/base/input/support/remote_app_server.cc +++ b/src/ballistica/base/input/support/remote_app_server.cc @@ -5,6 +5,7 @@ #include "ballistica/base/assets/assets.h" #include "ballistica/base/audio/audio.h" #include "ballistica/base/graphics/graphics.h" +#include "ballistica/base/graphics/support/screen_messages.h" #include "ballistica/base/input/input.h" #include "ballistica/base/logic/logic.h" #include "ballistica/base/networking/network_reader.h" @@ -162,7 +163,8 @@ void RemoteAppServer::HandleData(int socket, uint8_t* buffer, size_t amt, g_base->assets->GetResourceString("controllerDisconnectedText"); Utils::StringReplaceOne(&s, "${CONTROLLER}", m); g_base->logic->event_loop()->PushCall([s] { - g_base->graphics->AddScreenMessage(s, Vector3f(1, 1, 1)); + g_base->graphics->screenmessages->AddScreenMessage( + s, Vector3f(1, 1, 1)); }); g_base->logic->event_loop()->PushCall([] { g_base->audio->PlaySound( @@ -369,8 +371,10 @@ auto RemoteAppServer::GetClient(int request_id, struct sockaddr* addr, std::string s = g_base->assets->GetResourceString("controllerReconnectedText"); Utils::StringReplaceOne(&s, "${CONTROLLER}", m); - g_base->logic->event_loop()->PushCall( - [s] { g_base->graphics->AddScreenMessage(s, Vector3f(1, 1, 1)); }); + g_base->logic->event_loop()->PushCall([s] { + g_base->graphics->screenmessages->AddScreenMessage(s, + Vector3f(1, 1, 1)); + }); g_base->logic->event_loop()->PushCall([] { g_base->audio->PlaySound( g_base->assets->SysSound(SysSoundID::kGunCock)); @@ -416,8 +420,10 @@ auto RemoteAppServer::GetClient(int request_id, struct sockaddr* addr, std::string s = g_base->assets->GetResourceString("controllerConnectedText"); Utils::StringReplaceOne(&s, "${CONTROLLER}", m); - g_base->logic->event_loop()->PushCall( - [s] { g_base->graphics->AddScreenMessage(s, Vector3f(1, 1, 1)); }); + g_base->logic->event_loop()->PushCall([s] { + g_base->graphics->screenmessages->AddScreenMessage(s, + Vector3f(1, 1, 1)); + }); g_base->logic->event_loop()->PushCall([] { g_base->audio->PlaySound( diff --git a/src/ballistica/base/logic/logic.cc b/src/ballistica/base/logic/logic.cc index a57852ec..909a8ddd 100644 --- a/src/ballistica/base/logic/logic.cc +++ b/src/ballistica/base/logic/logic.cc @@ -580,7 +580,7 @@ void Logic::UpdatePendingWorkTimer_() { // If there's loading to do, keep at it rather vigorously. if (have_pending_loads_) { assert(process_pending_work_timer_); - process_pending_work_timer_->SetLength(1000); + process_pending_work_timer_->SetLength(1 * 1000); } else { // Otherwise we've got nothing to do; go to sleep until something // changes. diff --git a/src/ballistica/base/platform/apple/base_platform_apple.cc b/src/ballistica/base/platform/apple/base_platform_apple.cc index 833d8003..9bfc4a3e 100644 --- a/src/ballistica/base/platform/apple/base_platform_apple.cc +++ b/src/ballistica/base/platform/apple/base_platform_apple.cc @@ -19,7 +19,7 @@ namespace ballistica::base { BasePlatformApple::BasePlatformApple() { // On iOS, keep the device from falling asleep in our app #if BA_OSTYPE_IOS_TVOS - AppleUtils::DisableIdleTimer(); + // AppleUtils::DisableIdleTimer(); #endif } @@ -41,7 +41,7 @@ void BasePlatformApple::RestorePurchases() { void BasePlatformApple::PurchaseAck(const std::string& purchase, const std::string& order_id) { -#if BA_XCODE_BUILD +#if BA_XCODE_BUILD && BA_USE_STORE_KIT AppleUtils::PurchaseAck(purchase, order_id); #else BasePlatform::PurchaseAck(purchase, order_id); diff --git a/src/ballistica/base/python/methods/python_methods_app.cc b/src/ballistica/base/python/methods/python_methods_app.cc index ba299479..265906fd 100644 --- a/src/ballistica/base/python/methods/python_methods_app.cc +++ b/src/ballistica/base/python/methods/python_methods_app.cc @@ -9,7 +9,6 @@ #include "ballistica/base/logic/logic.h" #include "ballistica/base/python/base_python.h" #include "ballistica/base/python/support/python_context_call_runnable.h" -#include "ballistica/base/support/stress_test.h" #include "ballistica/base/ui/dev_console.h" #include "ballistica/base/ui/ui.h" #include "ballistica/shared/foundation/event_loop.h" @@ -784,32 +783,6 @@ static PyMethodDef PyEnvDef = { "This info is now exposed through babase.App; refer to those docs for\n" "info on specific elements."}; -// -------------------------- set_stress_testing ------------------------------- - -static auto PySetStressTesting(PyObject* self, PyObject* args) -> PyObject* { - BA_PYTHON_TRY; - int enable; - int player_count; - if (!PyArg_ParseTuple(args, "pi", &enable, &player_count)) { - return nullptr; - } - g_base->app_adapter->PushMainThreadCall([enable, player_count] { - g_base->stress_test()->Set(enable, player_count); - }); - Py_RETURN_NONE; - BA_PYTHON_CATCH; -} - -static PyMethodDef PySetStressTestingDef = { - "set_stress_testing", // name - PySetStressTesting, // method - METH_VARARGS, // flags - - "set_stress_testing(testing: bool, player_count: int) -> None\n" - "\n" - "(internal)", -}; - // -------------------------------- emit_log ----------------------------------- static auto PyEmitLog(PyObject* self, PyObject* args, PyObject* keywds) @@ -1702,7 +1675,6 @@ auto PythonMethodsApp::GetMethods() -> std::vector { PyCanDisplayFullUnicodeDef, PyEmitLogDef, PyV1CloudLogDef, - PySetStressTestingDef, PyEnvDef, PyPreEnvDef, PyCommitConfigDef, diff --git a/src/ballistica/base/python/methods/python_methods_graphics.cc b/src/ballistica/base/python/methods/python_methods_graphics.cc index 1e489461..d2ab871f 100644 --- a/src/ballistica/base/python/methods/python_methods_graphics.cc +++ b/src/ballistica/base/python/methods/python_methods_graphics.cc @@ -6,6 +6,7 @@ #include "ballistica/base/assets/assets.h" #include "ballistica/base/graphics/graphics.h" #include "ballistica/base/graphics/support/camera.h" +#include "ballistica/base/graphics/support/screen_messages.h" #include "ballistica/base/graphics/text/text_graphics.h" #include "ballistica/base/logic/logic.h" #include "ballistica/base/python/base_python.h" @@ -74,7 +75,7 @@ static auto PyScreenMessage(PyObject* self, PyObject* args, PyObject* keywds) } // This version simply displays it locally. - g_base->graphics->AddScreenMessage(message_str, color); + g_base->graphics->screenmessages->AddScreenMessage(message_str, color); Py_RETURN_NONE; BA_PYTHON_CATCH; diff --git a/src/ballistica/base/support/app_timer.h b/src/ballistica/base/support/app_timer.h index 876c3a65..6289ab75 100644 --- a/src/ballistica/base/support/app_timer.h +++ b/src/ballistica/base/support/app_timer.h @@ -13,20 +13,22 @@ namespace ballistica::base { class AppTimer : public Object { public: - AppTimer(microsecs_t length, bool repeat, Runnable* runnable) { + AppTimer(seconds_t length, bool repeat, Runnable* runnable) { assert(g_base->InLogicThread()); - timer_id_ = base::g_base->logic->NewAppTimer(length, repeat, runnable); + timer_id_ = base::g_base->logic->NewAppTimer( + static_cast(length * 1000000.0), repeat, runnable); } template - static auto New(microsecs_t length, bool repeat, const F& lambda) { + static auto New(seconds_t length, bool repeat, const F& lambda) { return Object::New(length, repeat, NewLambdaRunnable(lambda).Get()); } - void SetLength(microsecs_t length) { + void SetLength(seconds_t length) { assert(g_base->InLogicThread()); - base::g_base->logic->SetAppTimerLength(timer_id_, length); + base::g_base->logic->SetAppTimerLength( + timer_id_, static_cast(length * 1000000.0)); } ~AppTimer() override { diff --git a/src/ballistica/base/support/display_timer.h b/src/ballistica/base/support/display_timer.h index 1936ed8d..f8f72db8 100644 --- a/src/ballistica/base/support/display_timer.h +++ b/src/ballistica/base/support/display_timer.h @@ -13,21 +13,24 @@ namespace ballistica::base { class DisplayTimer : public Object { public: - DisplayTimer(microsecs_t length, bool repeat, Runnable* runnable) { + DisplayTimer(seconds_t length, bool repeat, Runnable* runnable) { assert(g_base->InLogicThread()); - timer_id_ = base::g_base->logic->NewDisplayTimer(length, repeat, runnable); + timer_id_ = base::g_base->logic->NewDisplayTimer( + static_cast(length * 1000000.0), repeat, runnable); } template - static auto New(microsecs_t length, bool repeat, const F& lambda) { + static auto New(seconds_t length, bool repeat, const F& lambda) { return Object::New(length, repeat, NewLambdaRunnable(lambda).Get()); } - void SetLength(microsecs_t length) { + void SetLength(seconds_t length) { assert(g_base->InLogicThread()); - base::g_base->logic->SetDisplayTimerLength(timer_id_, length); + base::g_base->logic->SetDisplayTimerLength( + timer_id_, static_cast(length * 1000000.0)); } + ~DisplayTimer() override { assert(g_base->InLogicThread()); base::g_base->logic->DeleteDisplayTimer(timer_id_); diff --git a/src/ballistica/base/support/repeater.cc b/src/ballistica/base/support/repeater.cc index 8528ce12..899a9cce 100644 --- a/src/ballistica/base/support/repeater.cc +++ b/src/ballistica/base/support/repeater.cc @@ -27,9 +27,8 @@ Repeater::Repeater(seconds_t initial_delay, seconds_t repeat_delay, return; } // Kick off our initial delay timer (generally the longer one). - weak_this->timer_ = DisplayTimer::New( - static_cast(weak_this->initial_delay_ * 1000000.0), - false, [weak_this] { + weak_this->timer_ = + DisplayTimer::New(weak_this->initial_delay_, false, [weak_this] { // Timer should not have fired if we died. assert(weak_this.Exists()); weak_this->runnable_->RunAndLogErrors(); @@ -38,9 +37,8 @@ Repeater::Repeater(seconds_t initial_delay, seconds_t repeat_delay, return; } // Kick off our repeat timer (generally the short one). - weak_this->timer_ = DisplayTimer::New( - static_cast(weak_this->repeat_delay_ * 1000000.0), - true, [weak_this] { + weak_this->timer_ = + DisplayTimer::New(weak_this->repeat_delay_, true, [weak_this] { // Timer should not have fired if we died. assert(weak_this.Exists()); weak_this->runnable_->RunAndLogErrors(); diff --git a/src/ballistica/base/support/stress_test.h b/src/ballistica/base/support/stress_test.h deleted file mode 100644 index 6da0ec7b..00000000 --- a/src/ballistica/base/support/stress_test.h +++ /dev/null @@ -1,25 +0,0 @@ -// Released under the MIT License. See LICENSE for details. - -#ifndef BALLISTICA_BASE_SUPPORT_STRESS_TEST_H_ -#define BALLISTICA_BASE_SUPPORT_STRESS_TEST_H_ - -#include "ballistica/shared/ballistica.h" - -namespace ballistica::base { - -class StressTest { - public: - void Set(bool enable, int player_count); - void Update(); - - private: - FILE* stress_test_stats_file_{}; - millisecs_t last_stress_test_update_time_{}; - bool stress_testing_{}; - int stress_test_player_count_{8}; - int last_total_frames_rendered_{}; -}; - -} // namespace ballistica::base - -#endif // BALLISTICA_BASE_SUPPORT_STRESS_TEST_H_ diff --git a/src/ballistica/base/ui/dev_console.cc b/src/ballistica/base/ui/dev_console.cc index 793617a2..1f0ccab8 100644 --- a/src/ballistica/base/ui/dev_console.cc +++ b/src/ballistica/base/ui/dev_console.cc @@ -6,7 +6,6 @@ #include "ballistica/base/app_mode/app_mode.h" #include "ballistica/base/audio/audio.h" #include "ballistica/base/graphics/component/simple_component.h" -#include "ballistica/base/graphics/mesh/nine_patch_mesh.h" #include "ballistica/base/graphics/text/text_graphics.h" #include "ballistica/base/logic/logic.h" #include "ballistica/base/platform/base_platform.h" @@ -1299,14 +1298,13 @@ void DevConsole::Draw(FrameDef* frame_def) { if (!carat_mesh_.Exists()) { UpdateCarat_(); } - millisecs_t real_time = pass->frame_def()->app_time_millisecs(); - if (real_time % 200 < 100 - || (real_time - last_carat_x_change_time_ < 100)) { + millisecs_t app_time = pass->frame_def()->app_time_millisecs(); + millisecs_t since_change = app_time - last_carat_x_change_time_; + if (since_change < 300 || since_change % 1000 < 500) { SimpleComponent c(pass); c.SetTransparent(true); c.SetTexture(g_base->assets->SysTexture(SysTextureID::kShadow)); c.SetColor(0.8, 0.0, 1.0, 0.3f); - // c.SetPremultiplied(true); { auto xf = c.ScopedTransform(); auto carat_x = GetCaratX_(); diff --git a/src/ballistica/classic/classic.cc b/src/ballistica/classic/classic.cc index 11abf286..56a42e41 100644 --- a/src/ballistica/classic/classic.cc +++ b/src/ballistica/classic/classic.cc @@ -2,7 +2,9 @@ #include "ballistica/classic/classic.h" +#include "ballistica/base/support/app_timer.h" #include "ballistica/classic/python/classic_python.h" +#include "ballistica/classic/support/stress_test.h" #include "ballistica/classic/support/v1_account.h" #include "ballistica/core/platform/core_platform.h" #include "ballistica/scene_v1/python/scene_v1_python.h" @@ -54,7 +56,9 @@ void ClassicFeatureSet::OnModuleExec(PyObject* module) { } ClassicFeatureSet::ClassicFeatureSet() - : python{new ClassicPython()}, v1_account{new V1Account()} { + : python{new ClassicPython()}, + v1_account{new V1Account()}, + stress_test_{new StressTest()} { // We're a singleton. If there's already one of us, something's wrong. assert(g_classic == nullptr); } diff --git a/src/ballistica/classic/classic.h b/src/ballistica/classic/classic.h index 97cbe97f..efba8d9d 100644 --- a/src/ballistica/classic/classic.h +++ b/src/ballistica/classic/classic.h @@ -28,6 +28,7 @@ namespace ballistica::classic { // Predeclared types our feature-set provides. class ClassicFeatureSet; class ClassicPython; +class StressTest; class V1Account; enum class V1AccountType { @@ -107,9 +108,12 @@ class ClassicFeatureSet : public FeatureSetNativeComponent, void set_v1_account_type(V1AccountType tp) { v1_account_type_ = tp; } void PlayMusic(const std::string& music_type, bool continuous) override; + auto* stress_test() const { return stress_test_; } + private: ClassicFeatureSet(); V1AccountType v1_account_type_{V1AccountType::kInvalid}; + StressTest* stress_test_; }; } // namespace ballistica::classic diff --git a/src/ballistica/classic/python/methods/python_methods_classic.cc b/src/ballistica/classic/python/methods/python_methods_classic.cc index 6f6765c0..9fab53da 100644 --- a/src/ballistica/classic/python/methods/python_methods_classic.cc +++ b/src/ballistica/classic/python/methods/python_methods_classic.cc @@ -4,7 +4,10 @@ #include "ballistica/base/graphics/graphics.h" #include "ballistica/base/graphics/support/camera.h" +#include "ballistica/base/logic/logic.h" +#include "ballistica/classic/support/stress_test.h" #include "ballistica/scene_v1/support/scene_v1_app_mode.h" +#include "ballistica/shared/foundation/event_loop.h" #include "ballistica/shared/python/python.h" #include "ballistica/shared/python/python_sys.h" @@ -145,10 +148,42 @@ static PyMethodDef PyValueTestDef = { "(internal)", }; +// -------------------------- set_stress_testing ------------------------------- + +static auto PySetStressTesting(PyObject* self, PyObject* args) -> PyObject* { + BA_PYTHON_TRY; + int enable; + int player_count; + if (!PyArg_ParseTuple(args, "pi", &enable, &player_count)) { + return nullptr; + } + // g_base->app_adapter->PushMainThreadCall([enable, player_count] { + // g_base->stress_test()->Set(enable, player_count); + // }); + g_base->logic->event_loop()->PushCall([enable, player_count] { + g_classic->stress_test()->Set(enable, player_count); + }); + Py_RETURN_NONE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PySetStressTestingDef = { + "set_stress_testing", // name + PySetStressTesting, // method + METH_VARARGS, // flags + + "set_stress_testing(testing: bool, player_count: int) -> None\n" + "\n" + "(internal)", +}; + // ----------------------------------------------------------------------------- auto PythonMethodsClassic::GetMethods() -> std::vector { - return {PyValueTestDef}; + return { + PyValueTestDef, + PySetStressTestingDef, + }; } #pragma clang diagnostic pop diff --git a/src/ballistica/base/support/stress_test.cc b/src/ballistica/classic/support/stress_test.cc similarity index 61% rename from src/ballistica/base/support/stress_test.cc rename to src/ballistica/classic/support/stress_test.cc index 0438e972..b92e6074 100644 --- a/src/ballistica/base/support/stress_test.cc +++ b/src/ballistica/classic/support/stress_test.cc @@ -1,15 +1,18 @@ // Released under the MIT License. See LICENSE for details. -#include "ballistica/base/support/stress_test.h" +#include "ballistica/classic/support/stress_test.h" #include "ballistica/base/graphics/graphics_server.h" #include "ballistica/base/graphics/renderer/renderer.h" +#include "ballistica/base/input/device/test_input.h" #include "ballistica/base/input/input.h" +#include "ballistica/base/support/app_timer.h" +#include "ballistica/classic/classic.h" -namespace ballistica::base { +namespace ballistica::classic { void StressTest::Set(bool enable, int player_count) { - assert(g_core->InMainThread()); + assert(g_base->InLogicThread()); bool was_stress_testing = stress_testing_; stress_testing_ = enable; stress_test_player_count_ = player_count; @@ -28,17 +31,22 @@ void StressTest::Set(bool enable, int player_count) { // Assume zero if there's no graphics yet. last_total_frames_rendered_ = 0; } + + update_timer_ = base::AppTimer::New(1.0 / 30.0, true, [this] { Update(); }); + } + if (!stress_testing_) { + update_timer_.Clear(); } } void StressTest::Update() { - assert(g_core->InMainThread()); + assert(g_base->InLogicThread()); // Handle a little misc stuff here. // If we're currently running stress-tests, update that stuff. if (stress_testing_ && g_base->input) { // Update our fake inputs to make our dudes run around. - g_base->input->ProcessStressTesting(stress_test_player_count_); + ProcessInputs(stress_test_player_count_); // Every 10 seconds update our stress-test stats. millisecs_t t = g_core->GetAppTimeMillisecs(); @@ -51,10 +59,10 @@ void StressTest::Update() { stress_test_stats_file_ = g_core->platform->FOpen(f_name.c_str(), "wb"); if (stress_test_stats_file_ != nullptr) { - fprintf( - stress_test_stats_file_, - "time,averageFps,nodes,meshes,collision_meshes,textures,sounds," - "pssMem,sharedDirtyMem,privateDirtyMem\n"); + fprintf(stress_test_stats_file_, + "time,averageFps,nodes,meshes,collision_meshes,textures," + "sounds," + "pssMem,sharedDirtyMem,privateDirtyMem\n"); fflush(stress_test_stats_file_); } } @@ -98,4 +106,56 @@ void StressTest::Update() { } } -} // namespace ballistica::base +void StressTest::ProcessInputs(int player_count) { + assert(g_base->InLogicThread()); + assert(player_count >= 0); + + millisecs_t time = g_core->GetAppTimeMillisecs(); + + // FIXME: If we don't check for stress_test_last_leave_time_ we totally + // confuse the game.. need to be able to survive that. + + // Kill some off if we have too many. + while (static_cast(test_inputs_.size()) > player_count) { + delete test_inputs_.front(); + test_inputs_.pop_front(); + } + + // If we have less than full test-inputs, add one randomly. + if (static_cast(test_inputs_.size()) < player_count + && ((rand() % 1000 < 10))) { // NOLINT + test_inputs_.push_back(new base::TestInput()); + } + + // Every so often lets kill the oldest one off. + if (explicit_bool(true)) { + if (test_inputs_.size() > 0 && (rand() % 2000 < 3)) { // NOLINT + stress_test_last_leave_time_ = time; + + // Usually do oldest; sometimes newest. + if (rand() % 5 == 0) { // NOLINT + delete test_inputs_.back(); + test_inputs_.pop_back(); + } else { + delete test_inputs_.front(); + test_inputs_.pop_front(); + } + } + } + + if (time - stress_test_time_ > 1000) { + stress_test_time_ = time; // reset.. + for (auto& test_input : test_inputs_) { + (*test_input).Reset(); + } + } + + while (stress_test_time_ < time) { + stress_test_time_++; + for (auto& test_input : test_inputs_) { + (*test_input).Process(stress_test_time_); + } + } +} + +} // namespace ballistica::classic diff --git a/src/ballistica/classic/support/stress_test.h b/src/ballistica/classic/support/stress_test.h new file mode 100644 index 00000000..96c5fd71 --- /dev/null +++ b/src/ballistica/classic/support/stress_test.h @@ -0,0 +1,33 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_CLASSIC_SUPPORT_STRESS_TEST_H_ +#define BALLISTICA_CLASSIC_SUPPORT_STRESS_TEST_H_ + +#include "ballistica/base/base.h" +#include "ballistica/shared/ballistica.h" +#include "ballistica/shared/foundation/object.h" + +namespace ballistica::classic { + +class StressTest { + public: + void Set(bool enable, int player_count); + void Update(); + + private: + void ProcessInputs(int player_count); + std::list test_inputs_; + + millisecs_t stress_test_time_{}; + millisecs_t stress_test_last_leave_time_{}; + int stress_test_player_count_{8}; + int last_total_frames_rendered_{}; + bool stress_testing_ : 1 {}; + millisecs_t last_stress_test_update_time_{}; + FILE* stress_test_stats_file_{}; + Object::Ref update_timer_{}; +}; + +} // namespace ballistica::classic + +#endif // BALLISTICA_CLASSIC_SUPPORT_STRESS_TEST_H_ diff --git a/src/ballistica/core/platform/apple/core_platform_apple.cc b/src/ballistica/core/platform/apple/core_platform_apple.cc index ac64502f..5c9d4cd6 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.cc +++ b/src/ballistica/core/platform/apple/core_platform_apple.cc @@ -42,7 +42,8 @@ auto CorePlatformApple::GetRealLegacyDeviceUUID(std::string* uuid) -> bool { return true; #endif #if BA_OSTYPE_IOS_TVOS - *uuid = base::AppleUtils::GetIOSUUID(); + *uuid = std::string(BallisticaKit::UIKitFromCpp::GetLegacyDeviceUUID()); + // *uuid = base::AppleUtils::GetIOSUUID(); return true; #endif return false; @@ -84,7 +85,9 @@ auto CorePlatformApple::GetDeviceUUIDInputs() -> std::list { #endif // BA_OSTYPE_MACOS #if BA_OSTYPE_IOS_TVOS - out.push_back(base::AppleUtils::GetIOSUUID()); + // out.push_back(base::AppleUtils::GetIOSUUID()); + out.push_back( + std::string(BallisticaKit::UIKitFromCpp::GetLegacyDeviceUUID())); #endif return out; } @@ -121,7 +124,8 @@ auto CorePlatformApple::DoHasTouchScreen() -> bool { auto CorePlatformApple::GetDefaultUIScale() -> UIScale { #if BA_OSTYPE_IOS - if (base::AppleUtils::IsTablet()) { + if (BallisticaKit::UIKitFromCpp::IsTablet()) { + // if (base::AppleUtils::IsTablet()) { return UIScale::kMedium; } else { return UIScale::kSmall; @@ -278,21 +282,21 @@ void CorePlatformApple::ShowOnlineScoreUI(const std::string& show, #endif } -auto CorePlatformApple::NewAutoReleasePool() -> void* { -#if BA_XCODE_BUILD - return base::AppleUtils::NewAutoReleasePool(); -#else - return CorePlatform::NewAutoReleasePool(); -#endif -} +// auto CorePlatformApple::NewAutoReleasePool() -> void* { +// #if BA_XCODE_BUILD +// return base::AppleUtils::NewAutoReleasePool(); +// #else +// return CorePlatform::NewAutoReleasePool(); +// #endif +// } -void CorePlatformApple::DrainAutoReleasePool(void* pool) { -#if BA_XCODE_BUILD - base::AppleUtils::DrainAutoReleasePool(pool); -#else - CorePlatform::DrainAutoReleasePool(pool); -#endif -} +// void CorePlatformApple::DrainAutoReleasePool(void* pool) { +// #if BA_XCODE_BUILD +// base::AppleUtils::DrainAutoReleasePool(pool); +// #else +// CorePlatform::DrainAutoReleasePool(pool); +// #endif +// } void CorePlatformApple::GameCenterLogin() { #if BA_USE_GAME_CENTER @@ -331,50 +335,68 @@ void CorePlatformApple::OpenDirExternally(const std::string& path) { void CorePlatformApple::MacMusicAppInit() { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - base::AppleUtils::MacMusicAppInit(); + BallisticaKit::CocoaFromCpp::MacMusicAppInit(); + // base::AppleUtils::MacMusicAppInit(); #else CorePlatform::MacMusicAppInit(); #endif } auto CorePlatformApple::MacMusicAppGetVolume() -> int { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - return static_cast(base::AppleUtils::MacMusicAppGetVolume()); + return BallisticaKit::CocoaFromCpp::MacMusicAppGetVolume(); + // return static_cast(base::AppleUtils::MacMusicAppGetVolume()); #else return CorePlatform::MacMusicAppGetVolume(); #endif } void CorePlatformApple::MacMusicAppSetVolume(int volume) { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - base::AppleUtils::MacMusicAppSetVolume(volume); + return BallisticaKit::CocoaFromCpp::MacMusicAppSetVolume(volume); + // base::AppleUtils::MacMusicAppSetVolume(volume); #else CorePlatform::MacMusicAppSetVolume(volume); #endif } + +// KILL THIS. void CorePlatformApple::MacMusicAppGetLibrarySource() { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - base::AppleUtils::MacMusicAppGetLibrarySource(); + // base::AppleUtils::MacMusicAppGetLibrarySource(); #else CorePlatform::MacMusicAppGetLibrarySource(); #endif } void CorePlatformApple::MacMusicAppStop() { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - base::AppleUtils::MacMusicAppStop(); + return BallisticaKit::CocoaFromCpp::MacMusicAppStop(); + // base::AppleUtils::MacMusicAppStop(); #else CorePlatform::MacMusicAppStop(); #endif } + auto CorePlatformApple::MacMusicAppPlayPlaylist(const std::string& playlist) -> bool { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - return base::AppleUtils::MacMusicAppPlayPlaylist(playlist.c_str()); + return BallisticaKit::CocoaFromCpp::MacMusicAppPlayPlaylist(playlist); + // return base::AppleUtils::MacMusicAppPlayPlaylist(playlist.c_str()); #else return CorePlatform::MacMusicAppPlayPlaylist(playlist); #endif } + auto CorePlatformApple::MacMusicAppGetPlaylists() -> std::list { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - return base::AppleUtils::MacMusicAppGetPlaylists(); + BallisticaKit::CocoaFromCpp::MacMusicAppGetPlaylists(); + // mac_music_app_playlists_.clear(); + // mac_music_app_playlists_.push_back("foof"); + // mac_music_app_playlists_.push_back("barf"); + // std::list out; + // for (auto&& val : vals) { + // out.push_back(std::string(val)); + // } + // return out; + return mac_music_app_playlists(); #else return CorePlatform::MacMusicAppGetPlaylists(); #endif diff --git a/src/ballistica/core/platform/apple/core_platform_apple.h b/src/ballistica/core/platform/apple/core_platform_apple.h index 215cb74a..bfbb019e 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.h +++ b/src/ballistica/core/platform/apple/core_platform_apple.h @@ -42,8 +42,8 @@ class CorePlatformApple : public CorePlatform { -> bool override; void ShowOnlineScoreUI(const std::string& show, const std::string& game, const std::string& game_version) override; - auto NewAutoReleasePool() -> void* override; - void DrainAutoReleasePool(void* pool) override; + // auto NewAutoReleasePool() -> void* override; + // void DrainAutoReleasePool(void* pool) override; void ResetAchievements() override; void GameCenterLogin() override; auto IsOSPlayingMusic() -> bool override; @@ -63,8 +63,6 @@ class CorePlatformApple : public CorePlatform { protected: auto DoGetDataDirectoryMonolithicDefault() -> std::string override; - - private: }; } // namespace ballistica::core diff --git a/src/ballistica/core/platform/core_platform.cc b/src/ballistica/core/platform/core_platform.cc index 92973146..f4303b89 100644 --- a/src/ballistica/core/platform/core_platform.cc +++ b/src/ballistica/core/platform/core_platform.cc @@ -721,9 +721,9 @@ auto CorePlatform::DemangleCXXSymbol(const std::string& s) -> std::string { #endif } -auto CorePlatform::NewAutoReleasePool() -> void* { throw Exception(); } +// auto CorePlatform::NewAutoReleasePool() -> void* { throw Exception(); } -void CorePlatform::DrainAutoReleasePool(void* pool) { throw Exception(); } +// void CorePlatform::DrainAutoReleasePool(void* pool) { throw Exception(); } void CorePlatform::ResetAchievements() { Log(LogLevel::kError, "ResetAchievements() unimplemented"); diff --git a/src/ballistica/core/platform/core_platform.h b/src/ballistica/core/platform/core_platform.h index b3890170..96a1bbe8 100644 --- a/src/ballistica/core/platform/core_platform.h +++ b/src/ballistica/core/platform/core_platform.h @@ -205,8 +205,8 @@ class CorePlatform { #pragma mark APPLE ------------------------------------------------------------- - virtual auto NewAutoReleasePool() -> void*; - virtual void DrainAutoReleasePool(void* pool); + // virtual auto NewAutoReleasePool() -> void*; + // virtual void DrainAutoReleasePool(void* pool); // FIXME: Can we consolidate these with the general music playback calls? virtual void MacMusicAppInit(); virtual auto MacMusicAppGetVolume() -> int; @@ -396,6 +396,11 @@ class CorePlatform { /// Are we being run from a terminal? (should we show prompts, etc?). auto is_stdin_a_terminal() const { return is_stdin_a_terminal_; } + void set_music_app_playlists(const std::list& playlists) { + mac_music_app_playlists_ = playlists; + } + auto mac_music_app_playlists() const { return mac_music_app_playlists_; } + protected: /// Are we being run from a terminal? (should we show prompts, etc?). virtual auto GetIsStdinATerminal() -> bool; @@ -445,7 +450,6 @@ class CorePlatform { /// 'noteworthy' or presented to the user as standard Log() calls are. virtual void HandleDebugLog(const std::string& msg); - protected: CorePlatform(); virtual ~CorePlatform(); @@ -462,6 +466,9 @@ class CorePlatform { std::string legacy_device_uuid_; std::string volatile_data_dir_; std::string replays_dir_; + + // temp. + std::list mac_music_app_playlists_; }; /// For capturing and printing stack-traces and related errors. Platforms diff --git a/src/ballistica/scene_v1/python/methods/python_methods_scene.cc b/src/ballistica/scene_v1/python/methods/python_methods_scene.cc index ab7e2e73..9cf3846e 100644 --- a/src/ballistica/scene_v1/python/methods/python_methods_scene.cc +++ b/src/ballistica/scene_v1/python/methods/python_methods_scene.cc @@ -6,6 +6,7 @@ #include "ballistica/base/dynamics/bg/bg_dynamics.h" #include "ballistica/base/graphics/graphics.h" +#include "ballistica/base/graphics/support/screen_messages.h" #include "ballistica/base/python/base_python.h" #include "ballistica/base/python/class/python_class_simple_sound.h" #include "ballistica/base/python/support/python_context_call_runnable.h" @@ -755,7 +756,7 @@ static auto PyBroadcastMessage(PyObject* self, PyObject* args, PyObject* keywds) } // Now display it locally. - g_base->graphics->AddScreenMessage( + g_base->graphics->screenmessages->AddScreenMessage( message, color, static_cast(top), texture ? texture->texture_data() : nullptr, tint_texture ? tint_texture->texture_data() : nullptr, tint_color, diff --git a/src/ballistica/scene_v1/support/client_session.cc b/src/ballistica/scene_v1/support/client_session.cc index d10e11e4..f796c64c 100644 --- a/src/ballistica/scene_v1/support/client_session.cc +++ b/src/ballistica/scene_v1/support/client_session.cc @@ -5,6 +5,7 @@ #include "ballistica/base/audio/audio.h" #include "ballistica/base/dynamics/bg/bg_dynamics.h" #include "ballistica/base/graphics/graphics.h" +#include "ballistica/base/graphics/support/screen_messages.h" #include "ballistica/base/networking/networking.h" #include "ballistica/scene_v1/assets/scene_collision_mesh.h" #include "ballistica/scene_v1/assets/scene_mesh.h" @@ -819,7 +820,7 @@ void ClientSession::Update(int time_advance_millisecs, double time_advance) { std::string s = ReadString(); float f[9]; ReadFloats(9, f); - g_base->graphics->AddScreenMessage( + g_base->graphics->screenmessages->AddScreenMessage( s, Vector3f(f[0], f[1], f[2]), true, texture->texture_data(), tint_texture->texture_data(), Vector3f(f[3], f[4], f[5]), Vector3f(f[6], f[7], f[8])); diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 3eeb626b..57058bcc 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 = 21531; +const int kEngineBuildNumber = 21543; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/foundation/event_loop.cc b/src/ballistica/shared/foundation/event_loop.cc index c04245e7..88b7ad5b 100644 --- a/src/ballistica/shared/foundation/event_loop.cc +++ b/src/ballistica/shared/foundation/event_loop.cc @@ -251,24 +251,24 @@ void EventLoop::WaitForNextEvent_(bool single_cycle) { // Note to self (Oct '23): can probably kill this at some point, // but am still using some non-ARC objc stuff from logic thread // so should keep it around just a bit longer just in case. -void EventLoop::LoopUpkeep_(bool single_cycle) { - assert(g_core); - // Keep our autorelease pool clean on mac/ios - // FIXME: Should define a CorePlatform::ThreadHelper or something - // so we don't have platform-specific code here. -#if BA_XCODE_BUILD - // Let's not do autorelease pools when being called ad-hoc, - // since in that case we're part of another run loop - // (and its crashing on drain for some reason) - if (!single_cycle) { - if (auto_release_pool_) { - g_core->platform->DrainAutoReleasePool(auto_release_pool_); - auto_release_pool_ = nullptr; - } - auto_release_pool_ = g_core->platform->NewAutoReleasePool(); - } -#endif -} +// void EventLoop::LoopUpkeep_(bool single_cycle) { +// assert(g_core); +// // Keep our autorelease pool clean on mac/ios +// // FIXME: Should define a CorePlatform::ThreadHelper or something +// // so we don't have platform-specific code here. +// #if BA_XCODE_BUILD +// // Let's not do autorelease pools when being called ad-hoc, +// // since in that case we're part of another run loop +// // (and its crashing on drain for some reason) +// if (!single_cycle) { +// if (auto_release_pool_) { +// g_core->platform->DrainAutoReleasePool(auto_release_pool_); +// auto_release_pool_ = nullptr; +// } +// auto_release_pool_ = g_core->platform->NewAutoReleasePool(); +// } +// #endif +//} void EventLoop::RunToCompletion() { Run_(false); } void EventLoop::RunSingleCycle() { Run_(true); } @@ -276,7 +276,7 @@ void EventLoop::RunSingleCycle() { Run_(true); } void EventLoop::Run_(bool single_cycle) { assert(g_core); while (true) { - LoopUpkeep_(single_cycle); + // LoopUpkeep_(single_cycle); WaitForNextEvent_(single_cycle); diff --git a/src/ballistica/shared/foundation/event_loop.h b/src/ballistica/shared/foundation/event_loop.h index 5a9649e6..9bb2d057 100644 --- a/src/ballistica/shared/foundation/event_loop.h +++ b/src/ballistica/shared/foundation/event_loop.h @@ -149,11 +149,11 @@ class EventLoop { void BootstrapThread_(); - void LoopUpkeep_(bool single_cycle); + // void LoopUpkeep_(bool single_cycle); // FIXME: Should generalize this to some sort of PlatformThreadData class. #if BA_XCODE_BUILD - void* auto_release_pool_{}; + // void* auto_release_pool_{}; #endif EventLoopID identifier_{EventLoopID::kInvalid}; diff --git a/src/ballistica/ui_v1/widget/button_widget.cc b/src/ballistica/ui_v1/widget/button_widget.cc index e8ce6a37..29c6db6a 100644 --- a/src/ballistica/ui_v1/widget/button_widget.cc +++ b/src/ballistica/ui_v1/widget/button_widget.cc @@ -57,7 +57,7 @@ void ButtonWidget::OnRepeatTimerExpired() { DoActivate(true); // Speed up repeats after the first. - repeat_timer_->SetLength(150); + repeat_timer_->SetLength(0.150); } else { repeat_timer_.Clear(); } @@ -165,7 +165,9 @@ void ButtonWidget::Draw(base::RenderPass* pass, bool draw_transparent) { // Account for our icon if we have it. float s_width_available = std::max(30.0f, width_ - 30); - if (show_icons) s_width_available -= (34.0f * icon_scale_); + if (show_icons) { + s_width_available -= (34.0f * icon_scale_); + } if ((string_width * string_scale) > s_width_available) { float squish_scale = s_width_available / (string_width * string_scale); @@ -486,7 +488,7 @@ auto ButtonWidget::HandleMessage(const base::WidgetMessage& m) -> bool { if (repeat_) { repeat_timer_ = base::AppTimer::New( - 300, true, [this] { OnRepeatTimerExpired(); }); + 0.3, true, [this] { OnRepeatTimerExpired(); }); // If we're a repeat button we trigger immediately. // (waiting till mouse up sort of defeats the purpose here) diff --git a/src/ballistica/ui_v1/widget/h_scroll_widget.cc b/src/ballistica/ui_v1/widget/h_scroll_widget.cc index c8d23371..40b832fc 100644 --- a/src/ballistica/ui_v1/widget/h_scroll_widget.cc +++ b/src/ballistica/ui_v1/widget/h_scroll_widget.cc @@ -406,7 +406,7 @@ auto HScrollWidget::HandleMessage(const base::WidgetMessage& m) -> bool { // scrolling has started. if (static_cast(m.type)) { touch_delay_timer_ = base::AppTimer::New( - 150, false, [this] { OnTouchDelayTimerExpired(); }); + 0.150, false, [this] { OnTouchDelayTimerExpired(); }); } // If we're handling a scroll-touch, take note that we need to diff --git a/src/ballistica/ui_v1/widget/scroll_widget.cc b/src/ballistica/ui_v1/widget/scroll_widget.cc index de48022c..67ce6d2c 100644 --- a/src/ballistica/ui_v1/widget/scroll_widget.cc +++ b/src/ballistica/ui_v1/widget/scroll_widget.cc @@ -331,7 +331,7 @@ auto ScrollWidget::HandleMessage(const base::WidgetMessage& m) -> bool { // click if it hasn't turned into a scroll or a child scroll. if (!child_is_scrolling_) { touch_delay_timer_ = base::AppTimer::New( - 150, false, [this] { OnTouchDelayTimerExpired(); }); + 0.150, false, [this] { OnTouchDelayTimerExpired(); }); } } } diff --git a/tools/batools/pruneincludes.py b/tools/batools/pruneincludes.py index 3a282fa0..b34fa2be 100755 --- a/tools/batools/pruneincludes.py +++ b/tools/batools/pruneincludes.py @@ -60,8 +60,15 @@ class Pruner: entries = self._get_entries() + processed_paths = set[str]() + with tempfile.TemporaryDirectory() as tempdir: for entry in entries: + # Entries list might have repeats. + if entry.file in processed_paths: + continue + processed_paths.add(entry.file) + if not entry.file.startswith(cwd): raise CleanError( f'compile-commands file {entry.file}' diff --git a/tools/batools/xcodeproject.py b/tools/batools/xcodeproject.py index 911efc4f..42ba6339 100644 --- a/tools/batools/xcodeproject.py +++ b/tools/batools/xcodeproject.py @@ -50,7 +50,7 @@ def update_xcode_project( for p in all_source_files if os.path.splitext(p)[1] in suffixes ), - has_app_delegate_mm=True, + # has_app_delegate_mm=True, projname=projname, ) else: @@ -64,7 +64,7 @@ def update_xcode_project( for p in all_source_files if os.path.splitext(p)[1] in suffixes ), - has_app_delegate_mm=True, + # has_app_delegate_mm=True, projname=projname, ) @@ -83,7 +83,7 @@ class Updater: existing_data: str, sources: list[str], projname: str, - has_app_delegate_mm: bool = False, + # has_app_delegate_mm: bool = False, ) -> None: if not path.endswith('.xcodeproj'): raise RuntimeError(f"Path does not end in .xcodeproj: '{path}'.") @@ -93,7 +93,7 @@ class Updater: self.existing_data = existing_data self.sources = sources self.project = None - self.has_app_delegate_mm = has_app_delegate_mm + # self.has_app_delegate_mm = has_app_delegate_mm # Project name variations. self.pnameu = projname @@ -165,8 +165,8 @@ class Updater: srcgrp = self._get_unique_group(f'{self.pnameu} Shared') self.add_paths(srcgrp) - if self.has_app_delegate_mm: - self.mod_app_delegate_mm() + # if self.has_app_delegate_mm: + # self.mod_app_delegate_mm() # Groups we made should be sorted already since we sorted while # building them, but let's sort the top level group we placed @@ -302,6 +302,7 @@ class Updater: ) return grps[0] + # (No longer used; just leaving here as reference though) def mod_app_delegate_mm(self) -> None: """Set per-file compiler flags.""" files = self.project.get_files_by_name('app_delegate.mm') From 586db8bd5ecc1df668fdc65abb503582356d1657 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 31 Oct 2023 21:34:59 -0700 Subject: [PATCH 19/25] implemented language autoselect for new apple builds --- .efrocachemap | 94 +++++++++---------- CHANGELOG.md | 2 +- config/spinoffconfig.py | 1 + src/assets/ba_data/python/babase/__init__.py | 2 - .../ba_data/python/baclassic/macmusicapp.py | 8 +- src/assets/ba_data/python/baenv.py | 2 +- .../base/app_adapter/app_adapter.cc | 23 ----- src/ballistica/base/app_adapter/app_adapter.h | 6 +- .../base/app_adapter/app_adapter_sdl.cc | 7 +- src/ballistica/base/base.cc | 4 + src/ballistica/base/base.h | 2 + src/ballistica/base/input/input.cc | 18 ++-- src/ballistica/base/input/input.h | 2 +- .../base/python/methods/python_methods_app.cc | 20 ---- src/ballistica/base/ui/dev_console.cc | 7 +- .../platform/apple/core_platform_apple.cc | 20 ++-- .../core/platform/apple/core_platform_apple.h | 8 +- src/ballistica/core/platform/core_platform.cc | 4 - src/ballistica/core/platform/core_platform.h | 5 +- src/ballistica/core/support/base_soft.h | 1 + src/ballistica/shared/ballistica.cc | 2 +- .../shared/foundation/fatal_error.cc | 58 +++++++----- tools/batools/xcodeproject.py | 10 +- 23 files changed, 143 insertions(+), 163 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 4d5f5d4d..800cb9af 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -424,7 +424,7 @@ "build/assets/ba_data/data/langdata.json": "0b15d171ebcc56d324875b48436b58c2", "build/assets/ba_data/data/languages/arabic.json": "c21378ee214a9dd0cb2971cd46b74374", "build/assets/ba_data/data/languages/belarussian.json": "4d89ed5f9c615771d4fa2bb1834942d3", - "build/assets/ba_data/data/languages/chinese.json": "0a9d9534e7329d1e886adae6fdc007c4", + "build/assets/ba_data/data/languages/chinese.json": "1ff4350df6d81c3b1b765fddace6b4c8", "build/assets/ba_data/data/languages/chinesetraditional.json": "f858da49be0a5374157c627857751078", "build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa", "build/assets/ba_data/data/languages/czech.json": "93c5fe0d884d95435da6c675f64e30e0", @@ -439,12 +439,12 @@ "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", - "build/assets/ba_data/data/languages/indonesian.json": "d7f1cafecad05e0dcd34345e0088c4de", + "build/assets/ba_data/data/languages/indonesian.json": "15a50690e5588d4acd3e07dfdaf755b0", "build/assets/ba_data/data/languages/italian.json": "e4acd4e58ef8db78f3369bf881f84c55", "build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2", "build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38", "build/assets/ba_data/data/languages/persian.json": "4585070bd509600019ec8dc3bb47bfb8", - "build/assets/ba_data/data/languages/polish.json": "6677925c370390f1f53bcb737cb00fa8", + "build/assets/ba_data/data/languages/polish.json": "5e25428554893155a5f81f3eeb418bae", "build/assets/ba_data/data/languages/portuguese.json": "51e362956f89da3eec980f587c092253", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", "build/assets/ba_data/data/languages/russian.json": "6e524210149d95479d6cbfd3506c630b", @@ -4056,50 +4056,50 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ad6316e04f09de546d25171512f783b2", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "19495e4313121d5574ab69efcbbcedd7", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "d8f215de52d492ce1790d9e1714b4cec", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b057d6d9627c7400496080c48dd344cd", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "1bd60c4476b7471364be2534d3cb8185", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "011bceb35c7f53b98f2ab79798409679", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "0055dfac758acdeb5a39e436da5d71be", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "2daa69d1df9927e6fc17b0aabd5c62f6", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "2159ce4b648b1172e3d2f349e61f2b1b", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "26163f755e45586da35c1ed6499c0416", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "410c70d8d833458616a0056972e558c4", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6e4473952a022e30340b6decae9da58a", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "0c63291b5842dafcfae558ef3c36d35a", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "7195da4e4abae862f41c28764b35662b", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5a6ad8a9f0d5cd964661df32ac4efb47", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "376059ea5f812ace7629ad29a8d77a9a", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "7a0c87d9e673b28157845f71ff957df6", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "3603019e3dbf055c37f5fabbe9538c48", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "14f6e17cc5698341ed5607834107e608", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "679703f9ec7c6f9c0708c9b13c9c6c06", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "e4952c83427611c5a66a864d8bb3bc4f", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "55df380ad6f3b38094bc82f6bb2a34bb", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "e4952c83427611c5a66a864d8bb3bc4f", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "55df380ad6f3b38094bc82f6bb2a34bb", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "f37c917e8336be6afe86842fc0cd1586", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "aaf0413c15988e332d27b7fd6eb1ba1f", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "f37c917e8336be6afe86842fc0cd1586", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "aaf0413c15988e332d27b7fd6eb1ba1f", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "f66008360fc266ada358731656dfa91a", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "712cd1dda7661826129b8023949ebebe", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "f66008360fc266ada358731656dfa91a", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "712cd1dda7661826129b8023949ebebe", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "5488eb05a8c45904243ff5cb1fc483cd", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "55aef97c30ade6b21e93b7d8a45ae670", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "519d0d2895489e5905e65e53384b96ba", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "55aef97c30ade6b21e93b7d8a45ae670", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "c9e82195e722512599ec7edcb456c78d", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "18b47849e222dd7b1bef9bd1a07473c9", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6c44557f5392bb3cd2d9a983add52d0b", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0bd4099b6b594f62b806c9d74a84095a", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a36752eee64f76c1868937247aaaee32", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "9ac33f02579ee14e4ad6a0b6b5a82a36", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "87bc0ff42442b60c817805ab07c65769", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "cedd1f2c367b84c20377c282453825f2", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "437a7184a3f56da917ec92e0f1d08392", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "c990f7765be45e603eaa1040a11d20f2", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "b891b240768e0c1961d82a05357f36fb", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "7778d9df2d0c4e07d2ea46b3c6b8ca1f", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "eac8b98c72cd8edbf1ed97237052ac05", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "6ee06879d656a68802dc42c483ea5a2b", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "58b8437cc04dbc63587e8c379bcdb316", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "40422d250bc84faf876642f8c6181132", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0c5d44d847c3df3178e5b890c234bccd", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "8e58ab0f0faa58b6bdc8130062171a1d", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "18e33eab40af6efc10454206249b5b91", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0465c41b9364c56494768ac41766529b", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "2bb0a2f4402ee90e1c2e03f75dd6e090", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "328d7b3a7ce3564dc7d1b4f315842291", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "079097fc77e50024f6231de94c9e1fbc", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "9bb781a88ecddf84ca84cbdc14ee0a78", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "17ca9956767731b2cce7c12ec15e37f4", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "c0c9a0e54434f54bad8cd057bacab4e2", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "ab77f95bd46cae158aaccd53091c3bfb", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "bd05a3124893ff649a48afc6ff9fdf20", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d9f919fe87d497529cd8aed24a961ea3", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "56972014971024060e6014c2027debd2", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d9f919fe87d497529cd8aed24a961ea3", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "56972014971024060e6014c2027debd2", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "3b0da9dfd7b2efe967aaafd3e68d4a86", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "d4889e0f44a762e4bf067af33e8885e1", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "3b0da9dfd7b2efe967aaafd3e68d4a86", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "d4889e0f44a762e4bf067af33e8885e1", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "5d6b77d2280ad8366f1386f7af0d8e6b", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "0c8ab52403a77eb7a11137afb6946f8b", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "5d6b77d2280ad8366f1386f7af0d8e6b", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "0c8ab52403a77eb7a11137afb6946f8b", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "85ab9b2e82eb2ddca6e915b4a3c3589e", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "39a0f3efabd9d2f62202ef9790e5cecd", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "2609429078b69b48c3cda49abac7065c", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "39a0f3efabd9d2f62202ef9790e5cecd", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7f3de02f9481408b02ebfd1253452b30", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "a56a0aecab25961be71f364bd29eecaf", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "cbc394d29f300aac67374c586f07e3dd", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "ceba6e421ed2ccd51114bfdd239881d9", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "eaa568b2aee0f4cd4e186cee7ac98a9a", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e13fdefc582d9c86a3b5f9cb4e5781f5", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1f1065b864ddd2e6b376835c09bf809b", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "9eab26a8053f011ab0247e67bf59ecf3", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index ad501f17..827e1817 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21543, api 8, 2023-10-31) +### 1.7.28 (build 21551, api 8, 2023-10-31) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/config/spinoffconfig.py b/config/spinoffconfig.py index 490697b0..3fe2bca1 100644 --- a/config/spinoffconfig.py +++ b/config/spinoffconfig.py @@ -274,6 +274,7 @@ ctx.filter_file_extensions = { '.frag', '.vert', '.xcsettings', + '.xcstrings', '.filters', } diff --git a/src/assets/ba_data/python/babase/__init__.py b/src/assets/ba_data/python/babase/__init__.py index e15a774a..a511d570 100644 --- a/src/assets/ba_data/python/babase/__init__.py +++ b/src/assets/ba_data/python/babase/__init__.py @@ -64,7 +64,6 @@ from _babase import ( is_running_on_fire_tv, is_xcode_build, lock_all_input, - mac_music_app_get_library_source, mac_music_app_get_playlists, mac_music_app_get_volume, mac_music_app_init, @@ -265,7 +264,6 @@ __all__ = [ 'lock_all_input', 'LoginAdapter', 'Lstr', - 'mac_music_app_get_library_source', 'mac_music_app_get_playlists', 'mac_music_app_get_volume', 'mac_music_app_init', diff --git a/src/assets/ba_data/python/baclassic/macmusicapp.py b/src/assets/ba_data/python/baclassic/macmusicapp.py index 1b87fbf1..27b0e126 100644 --- a/src/assets/ba_data/python/baclassic/macmusicapp.py +++ b/src/assets/ba_data/python/baclassic/macmusicapp.py @@ -80,14 +80,13 @@ class _MacMusicAppThread(threading.Thread): def run(self) -> None: """Run the Music.app thread.""" babase.set_thread_name('BA_MacMusicAppThread') - babase.mac_music_app_init() # Let's mention to the user we're launching Music.app in case # it causes any funny business (this used to background the app # sometimes, though I think that is fixed now) def do_print() -> None: babase.apptimer( - 1.0, + 0.5, babase.Call( babase.screenmessage, babase.Lstr(resource='usingItunesText'), @@ -97,9 +96,8 @@ class _MacMusicAppThread(threading.Thread): babase.pushcall(do_print, from_other_thread=True) - # Here we grab this to force the actual launch. - babase.mac_music_app_get_volume() - babase.mac_music_app_get_library_source() + babase.mac_music_app_init() + done = False while not done: self._commands_available.wait() diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index f3969a7d..963ee465 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21543 +TARGET_BALLISTICA_BUILD = 21551 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/app_adapter/app_adapter.cc b/src/ballistica/base/app_adapter/app_adapter.cc index b781b04b..7aba2807 100644 --- a/src/ballistica/base/app_adapter/app_adapter.cc +++ b/src/ballistica/base/app_adapter/app_adapter.cc @@ -20,31 +20,8 @@ AppAdapter::~AppAdapter() = default; auto AppAdapter::ManagesMainThreadEventLoop() const -> bool { return true; } void AppAdapter::OnMainThreadStartApp() { - assert(g_base); assert(g_core); assert(g_core->InMainThread()); - - // Add some common input devices where applicable. More specific ones (SDL - // Joysticks, etc.) get added in subclasses. - - // FIXME: This stuff should probably go elsewhere. - if (!g_core->HeadlessMode()) { - // If we've got a nice themed hardware cursor, show it. Otherwise we'll - // render it manually, which is laggier but gets the job done. - // g_base->platform->SetHardwareCursorVisible(g_buildconfig.hardware_cursor()); - - // On desktop systems we just assume keyboard input exists and add it - // immediately. - if (g_core->platform->IsRunningOnDesktop()) { - g_base->input->PushCreateKeyboardInputDevices(); - } - - // On non-tv, non-desktop, non-vr systems, create a touchscreen input. - if (!g_core->platform->IsRunningOnTV() && !g_core->IsVRMode() - && !g_core->platform->IsRunningOnDesktop()) { - g_base->input->CreateTouchInput(); - } - } } void AppAdapter::OnAppStart() { assert(g_base->InLogicThread()); } diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index 6570d8a4..5c2ce998 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -222,9 +222,6 @@ class AppAdapter { /// clipboard is unsupported or if there's no text on the clipboard. auto ClipboardGetText() -> std::string; - protected: - virtual ~AppAdapter(); - /// Push a raw pointer Runnable to the platform's 'main' thread. The main /// thread should call its RunAndLogErrors() method and then delete it. virtual void DoPushMainThreadRunnable(Runnable* runnable) = 0; @@ -233,6 +230,9 @@ class AppAdapter { /// context. By default this is simply the main thread. virtual void DoPushGraphicsContextRunnable(Runnable* runnable); + protected: + virtual ~AppAdapter(); + virtual auto DoClipboardIsSupported() -> bool; virtual auto DoClipboardHasText() -> bool; virtual void DoClipboardSetText(const std::string& text); diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.cc b/src/ballistica/base/app_adapter/app_adapter_sdl.cc index 5c432800..6921f82d 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -51,6 +51,8 @@ AppAdapterSDL::AppAdapterSDL() { } void AppAdapterSDL::OnMainThreadStartApp() { + AppAdapter::OnMainThreadStartApp(); + // App is starting. Let's fire up the ol' SDL. uint32_t sdl_flags{SDL_INIT_VIDEO | SDL_INIT_JOYSTICK}; @@ -79,9 +81,8 @@ void AppAdapterSDL::OnMainThreadStartApp() { sdl_runnable_event_id_ = SDL_RegisterEvents(1); assert(sdl_runnable_event_id_ != (uint32_t)-1); - // Note: parent class can add some input devices so need to bring up sdl - // before we let it run. That code should maybe be relocated/refactored. - AppAdapter::OnMainThreadStartApp(); + // SDL builds just assume keyboard input is available. + g_base->input->PushCreateKeyboardInputDevices(); if (g_buildconfig.enable_sdl_joysticks()) { // We want events from joysticks. diff --git a/src/ballistica/base/base.cc b/src/ballistica/base/base.cc index 00953ffa..644d3125 100644 --- a/src/ballistica/base/base.cc +++ b/src/ballistica/base/base.cc @@ -722,4 +722,8 @@ void BaseFeatureSet::QuitApp(bool confirm, QuitType quit_type) { } } +void BaseFeatureSet::PushMainThreadRunnable(Runnable* runnable) { + app_adapter->DoPushMainThreadRunnable(runnable); +} + } // namespace ballistica::base diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index 2503a134..c452e739 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -723,6 +723,8 @@ class BaseFeatureSet : public FeatureSetNativeComponent, /// loading. void OnAssetsAvailable(); + void PushMainThreadRunnable(Runnable* runnable) override; + // Const subsystems. AppAdapter* const app_adapter; AppConfig* const app_config; diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index 5b33f2a4..fe66c1a9 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -144,12 +144,9 @@ auto Input::GetNewNumberedIdentifier_(const std::string& name, return full_id; } -void Input::CreateTouchInput() { - assert(g_core->InMainThread()); - assert(touch_input_ == nullptr); - touch_input_ = Object::NewDeferred(); - PushAddInputDeviceCall(touch_input_, false); -} +// void Input::CreateTouchInput() { +// assert(g_core->InMainThread()); +// } void Input::AnnounceConnects_() { assert(g_base->InLogicThread()); @@ -559,7 +556,14 @@ void Input::UpdateEnabledControllerSubsystems_() { // } } -void Input::OnAppStart() { assert(g_base->InLogicThread()); } +void Input::OnAppStart() { + assert(g_base->InLogicThread()); + if (g_core->platform->HasTouchScreen()) { + assert(touch_input_ == nullptr); + touch_input_ = Object::NewDeferred(); + PushAddInputDeviceCall(touch_input_, false); + } +} void Input::OnAppPause() { assert(g_base->InLogicThread()); } diff --git a/src/ballistica/base/input/input.h b/src/ballistica/base/input/input.h index 9c33ecd2..aa404385 100644 --- a/src/ballistica/base/input/input.h +++ b/src/ballistica/base/input/input.h @@ -116,7 +116,7 @@ class Input { auto HaveRemoteAppController() -> bool; auto keyboard_input() const -> KeyboardInput* { return keyboard_input_; } auto keyboard_input_2() const -> KeyboardInput* { return keyboard_input_2_; } - void CreateTouchInput(); + // void CreateTouchInput(); void PushTextInputEvent(const std::string& text); void PushKeyPressEventSimple(int keycode); diff --git a/src/ballistica/base/python/methods/python_methods_app.cc b/src/ballistica/base/python/methods/python_methods_app.cc index 265906fd..2d13c813 100644 --- a/src/ballistica/base/python/methods/python_methods_app.cc +++ b/src/ballistica/base/python/methods/python_methods_app.cc @@ -1088,25 +1088,6 @@ static PyMethodDef PyMacMusicAppSetVolumeDef = { "(internal)", }; -// ------------------------ mac_music_app_get_library -------------------------- - -static auto PyMacMusicAppGetLibrarySource(PyObject* self, PyObject* args, - PyObject* keywds) -> PyObject* { - BA_PYTHON_TRY; - g_core->platform->MacMusicAppGetLibrarySource(); - Py_RETURN_NONE; - BA_PYTHON_CATCH; -} - -static PyMethodDef PyMacMusicAppGetLibrarySourceDef = { - "mac_music_app_get_library_source", // name - (PyCFunction)PyMacMusicAppGetLibrarySource, // method - METH_VARARGS | METH_KEYWORDS, // flags - - "mac_music_app_get_library_source() -> None\n" - "\n" - "(internal)"}; - // --------------------------- mac_music_app_stop ------------------------------ static auto PyMacMusicAppStop(PyObject* self, PyObject* args, PyObject* keywds) @@ -1695,7 +1676,6 @@ auto PythonMethodsApp::GetMethods() -> std::vector { PyMacMusicAppInitDef, PyMacMusicAppGetVolumeDef, PyMacMusicAppSetVolumeDef, - PyMacMusicAppGetLibrarySourceDef, PyMacMusicAppStopDef, PyMacMusicAppPlayPlaylistDef, PyMacMusicAppGetPlaylistsDef, diff --git a/src/ballistica/base/ui/dev_console.cc b/src/ballistica/base/ui/dev_console.cc index 1f0ccab8..7ea9fd67 100644 --- a/src/ballistica/base/ui/dev_console.cc +++ b/src/ballistica/base/ui/dev_console.cc @@ -1295,7 +1295,10 @@ void DevConsole::Draw(FrameDef* frame_def) { } // Carat. - if (!carat_mesh_.Exists()) { + if (!carat_mesh_.Exists() || carat_dirty_) { + // Note: we explicitly update here if carat is dirty because + // that updates last_carat_change_time_ which affects whether + // we draw or not. GetCaratX_() only updates it *if* we draw. UpdateCarat_(); } millisecs_t app_time = pass->frame_def()->app_time_millisecs(); @@ -1457,6 +1460,7 @@ auto DevConsole::PasteFromClipboard() -> bool { } void DevConsole::UpdateCarat_() { + last_carat_x_change_time_ = g_core->GetAppTimeMillisecs(); auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjfwef"); auto unichars_clamped = unichars; @@ -1508,7 +1512,6 @@ void DevConsole::UpdateCarat_() { auto DevConsole::GetCaratX_() -> float { if (carat_dirty_) { - last_carat_x_change_time_ = g_core->GetAppTimeMillisecs(); UpdateCarat_(); carat_dirty_ = false; } diff --git a/src/ballistica/core/platform/apple/core_platform_apple.cc b/src/ballistica/core/platform/apple/core_platform_apple.cc index 5c9d4cd6..2ddce42d 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.cc +++ b/src/ballistica/core/platform/apple/core_platform_apple.cc @@ -10,7 +10,6 @@ #include #if BA_XCODE_BUILD -#include "ballistica/base/platform/apple/apple_utils.h" #include "ballistica/base/platform/apple/from_swift.h" #include "ballistica/shared/math/rect.h" #endif @@ -358,14 +357,6 @@ void CorePlatformApple::MacMusicAppSetVolume(int volume) { #endif } -// KILL THIS. -void CorePlatformApple::MacMusicAppGetLibrarySource() { -#if BA_OSTYPE_MACOS && BA_XCODE_BUILD - // base::AppleUtils::MacMusicAppGetLibrarySource(); -#else - CorePlatform::MacMusicAppGetLibrarySource(); -#endif -} void CorePlatformApple::MacMusicAppStop() { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD return BallisticaKit::CocoaFromCpp::MacMusicAppStop(); @@ -422,6 +413,17 @@ auto CorePlatformApple::GetSubplatformName() -> std::string { #endif } +auto CorePlatformApple::GetLocale() -> std::string { +#if BA_XCODE_BUILD + if (!locale_.has_value()) { + locale_ = std::string(BallisticaKit::FromCpp::GetLocaleString()); + } + return *locale_; +#else + return CorePlatform::GetLocale(); +#endif +} + } // namespace ballistica::core #endif // BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS diff --git a/src/ballistica/core/platform/apple/core_platform_apple.h b/src/ballistica/core/platform/apple/core_platform_apple.h index bfbb019e..000f79f1 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.h +++ b/src/ballistica/core/platform/apple/core_platform_apple.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -42,8 +43,6 @@ class CorePlatformApple : public CorePlatform { -> bool override; void ShowOnlineScoreUI(const std::string& show, const std::string& game, const std::string& game_version) override; - // auto NewAutoReleasePool() -> void* override; - // void DrainAutoReleasePool(void* pool) override; void ResetAchievements() override; void GameCenterLogin() override; auto IsOSPlayingMusic() -> bool override; @@ -52,7 +51,6 @@ class CorePlatformApple : public CorePlatform { void MacMusicAppInit() override; auto MacMusicAppGetVolume() -> int override; void MacMusicAppSetVolume(int volume) override; - void MacMusicAppGetLibrarySource() override; void MacMusicAppStop() override; auto MacMusicAppPlayPlaylist(const std::string& playlist) -> bool override; auto MacMusicAppGetPlaylists() -> std::list override; @@ -60,9 +58,13 @@ class CorePlatformApple : public CorePlatform { auto GetSubplatformName() -> std::string override; auto GetDeviceUUIDInputs() -> std::list override; + auto GetLocale() -> std::string override; protected: auto DoGetDataDirectoryMonolithicDefault() -> std::string override; + + private: + std::optional locale_; }; } // namespace ballistica::core diff --git a/src/ballistica/core/platform/core_platform.cc b/src/ballistica/core/platform/core_platform.cc index f4303b89..787b517f 100644 --- a/src/ballistica/core/platform/core_platform.cc +++ b/src/ballistica/core/platform/core_platform.cc @@ -814,10 +814,6 @@ void CorePlatform::MacMusicAppSetVolume(int volume) { Log(LogLevel::kError, "MacMusicAppSetVolume() unimplemented"); } -void CorePlatform::MacMusicAppGetLibrarySource() { - Log(LogLevel::kError, "MacMusicAppGetLibrarySource() unimplemented"); -} - void CorePlatform::MacMusicAppStop() { Log(LogLevel::kError, "MacMusicAppStop() unimplemented"); } diff --git a/src/ballistica/core/platform/core_platform.h b/src/ballistica/core/platform/core_platform.h index 96a1bbe8..03a5d20a 100644 --- a/src/ballistica/core/platform/core_platform.h +++ b/src/ballistica/core/platform/core_platform.h @@ -211,10 +211,9 @@ class CorePlatform { virtual void MacMusicAppInit(); virtual auto MacMusicAppGetVolume() -> int; virtual void MacMusicAppSetVolume(int volume); - virtual void MacMusicAppGetLibrarySource(); - virtual void MacMusicAppStop(); - virtual auto MacMusicAppPlayPlaylist(const std::string& playlist) -> bool; virtual auto MacMusicAppGetPlaylists() -> std::list; + virtual auto MacMusicAppPlayPlaylist(const std::string& playlist) -> bool; + virtual void MacMusicAppStop(); #pragma mark TEXT RENDERING ---------------------------------------------------- diff --git a/src/ballistica/core/support/base_soft.h b/src/ballistica/core/support/base_soft.h index 31c83d30..1a9ba259 100644 --- a/src/ballistica/core/support/base_soft.h +++ b/src/ballistica/core/support/base_soft.h @@ -44,6 +44,7 @@ class BaseSoftInterface { virtual auto IsAppStarted() const -> bool = 0; virtual auto IsAppBootstrapped() const -> bool = 0; virtual auto GetReturnValue() const -> int = 0; + virtual void PushMainThreadRunnable(Runnable* runnable) = 0; }; } // namespace ballistica::core diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 57058bcc..eb9b8922 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 = 21543; +const int kEngineBuildNumber = 21551; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/foundation/fatal_error.cc b/src/ballistica/shared/foundation/fatal_error.cc index 71bac44c..967e6a30 100644 --- a/src/ballistica/shared/foundation/fatal_error.cc +++ b/src/ballistica/shared/foundation/fatal_error.cc @@ -5,6 +5,8 @@ #include "ballistica/core/platform/core_platform.h" #include "ballistica/core/support/base_soft.h" #include "ballistica/shared/foundation/logging.h" +#include "ballistica/shared/generic/lambda_runnable.h" +#include "ballistica/shared/python/python.h" namespace ballistica { @@ -131,32 +133,38 @@ void FatalError::DoBlockingFatalErrorDialog(const std::string& message) { // done. if (g_core->InMainThread()) { g_core->platform->BlockingFatalErrorDialog(message); - } else { - printf("FIXME REIMPLEMENT BLOCKING FATAL ERROR FOR BG THREAD\n"); - // bool started{}; - // bool finished{}; - // bool* startedptr{&started}; - // bool* finishedptr{&finished}; - // g_core->main_event_loop()->PushCall([message, startedptr, finishedptr] { - // *startedptr = true; - // g_core->platform->BlockingFatalErrorDialog(message); - // *finishedptr = true; - // }); + } else if (g_base_soft) { + bool started{}; + bool finished{}; + bool* startedptr{&started}; + bool* finishedptr{&finished}; - // // Wait a short amount of time for the main thread to take action. - // // There's a chance that it can't (if threads are paused, if it is - // // blocked on a synchronous call to another thread, etc.) so if we don't - // // see something happening soon, just give up on showing a dialog. - // auto starttime = core::CorePlatform::GetCurrentMillisecs(); - // while (!started) { - // if (core::CorePlatform::GetCurrentMillisecs() - starttime > 1000) { - // return; - // } - // core::CorePlatform::SleepMillisecs(10); - // } - // while (!finished) { - // core::CorePlatform::SleepMillisecs(10); - // } + // If our thread is holding the GIL, release it to give the main + // thread a better chance to get to the point of displaying the fatal error. + if (Python::HaveGIL()) { + Python::PermanentlyReleaseGIL(); + } + g_base_soft->PushMainThreadRunnable( + NewLambdaRunnableUnmanaged([message, startedptr, finishedptr] { + *startedptr = true; + g_core->platform->BlockingFatalErrorDialog(message); + *finishedptr = true; + })); + + // Wait a short amount of time for the main thread to take action. + // There's a chance that it can't (if threads are paused, if it is + // blocked on a synchronous call to another thread, etc.) so if we don't + // see something happening soon, just give up on showing a dialog. + auto starttime = core::CorePlatform::GetCurrentMillisecs(); + while (!started) { + if (core::CorePlatform::GetCurrentMillisecs() - starttime > 3000) { + return; + } + core::CorePlatform::SleepMillisecs(10); + } + while (!finished) { + core::CorePlatform::SleepMillisecs(10); + } } } diff --git a/tools/batools/xcodeproject.py b/tools/batools/xcodeproject.py index 42ba6339..0d331df6 100644 --- a/tools/batools/xcodeproject.py +++ b/tools/batools/xcodeproject.py @@ -416,11 +416,15 @@ class Updater: ) def _target_names_for_file(self, filename: str) -> list[str] | None: - # Cocoa stuff only applies to our macOS build. + # Cocoa stuff only applies to our macOS targets. if filename.startswith('Cocoa') and filename.endswith('.swift'): - return [f'{self.pnameu} macOS'] + return [ + f'{self.pnameu} macOS TestBuild', + f'{self.pnameu} macOS AppStore', + f'{self.pnameu} macOS Steam', + ] - # UIKit stuff applies to our iOS/tvOS builds. + # UIKit stuff applies to our iOS/tvOS targets. if filename.startswith('UIKit') and filename.endswith('.swift'): return [f'{self.pnameu} iOS', f'{self.pnameu} tvOS'] From 4047a5c9daf4b3713d19582d92bb777628c7a385 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 1 Nov 2023 16:25:44 -0700 Subject: [PATCH 20/25] wired apple builds up to show game controller button names provided by the framework --- .efrocachemap | 64 +++++++++---------- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- .../bascenev1lib/actor/controlsguide.py | 11 ++-- .../python/bauiv1lib/settings/gamepad.py | 1 - .../base/input/device/joystick_input.cc | 10 +++ .../base/input/device/joystick_input.h | 8 ++- src/ballistica/shared/ballistica.cc | 2 +- 8 files changed, 58 insertions(+), 42 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 800cb9af..54c96d18 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -1524,9 +1524,9 @@ "build/assets/ba_data/textures/fontBig.ktx": "94b56c2488d6c9ebabfbbb740eca07dd", "build/assets/ba_data/textures/fontBig.pvr": "dff3f6c04a8c7b0bb937001640b42c8d", "build/assets/ba_data/textures/fontBig_preview.png": "f8b15cb04f0deca7774def335a72f053", - "build/assets/ba_data/textures/fontExtras.dds": "7ab11df1b3a3daa651dfad34219b89f5", - "build/assets/ba_data/textures/fontExtras.ktx": "30c3c8ca2cdf1209ff177017bb10f0a8", - "build/assets/ba_data/textures/fontExtras.pvr": "fd3b0bd902c30e4b7aa5fe00e1eec4be", + "build/assets/ba_data/textures/fontExtras.dds": "0a5a39028853c443cd88bc2492cb6ad9", + "build/assets/ba_data/textures/fontExtras.ktx": "5b14075ce3d1d29c6d5635602e2176d8", + "build/assets/ba_data/textures/fontExtras.pvr": "8cc68ca85ba327c20c45bad73b000d8c", "build/assets/ba_data/textures/fontExtras2.dds": "18063a12912dadc9528afd90d1cf2369", "build/assets/ba_data/textures/fontExtras2.ktx": "36da7f6cfbfb8d32fb14371de0a8f660", "build/assets/ba_data/textures/fontExtras2.pvr": "7a4e8e64ac05313b1782fb5b958150d0", @@ -1539,7 +1539,7 @@ "build/assets/ba_data/textures/fontExtras4.ktx": "6d872ac15e2e874c1252f63b4584722b", "build/assets/ba_data/textures/fontExtras4.pvr": "6a0a0a1a8bbbc3ee9d6b8b914e7aa697", "build/assets/ba_data/textures/fontExtras4_preview.png": "363e2647621917b3821c9068267d2516", - "build/assets/ba_data/textures/fontExtras_preview.png": "9c9c58aff612e7b6386f3522c0b4f1f6", + "build/assets/ba_data/textures/fontExtras_preview.png": "b6503267cc15e9e2524f41fabd94e773", "build/assets/ba_data/textures/fontSmall0.dds": "b30bfe5f9e436be7be8b5eae6e8490c3", "build/assets/ba_data/textures/fontSmall0.ktx": "7e6058f37e6c5a4ea628f35b5f92c227", "build/assets/ba_data/textures/fontSmall0.pvr": "c66e3d6aa1f7def83aaacd8a6c9185e5", @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "437a7184a3f56da917ec92e0f1d08392", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "c990f7765be45e603eaa1040a11d20f2", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "b891b240768e0c1961d82a05357f36fb", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "7778d9df2d0c4e07d2ea46b3c6b8ca1f", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "eac8b98c72cd8edbf1ed97237052ac05", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "6ee06879d656a68802dc42c483ea5a2b", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "58b8437cc04dbc63587e8c379bcdb316", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "40422d250bc84faf876642f8c6181132", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0c5d44d847c3df3178e5b890c234bccd", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "8e58ab0f0faa58b6bdc8130062171a1d", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "18e33eab40af6efc10454206249b5b91", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0465c41b9364c56494768ac41766529b", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "2bb0a2f4402ee90e1c2e03f75dd6e090", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "328d7b3a7ce3564dc7d1b4f315842291", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "079097fc77e50024f6231de94c9e1fbc", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "9bb781a88ecddf84ca84cbdc14ee0a78", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "17ca9956767731b2cce7c12ec15e37f4", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "c0c9a0e54434f54bad8cd057bacab4e2", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "ab77f95bd46cae158aaccd53091c3bfb", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "bd05a3124893ff649a48afc6ff9fdf20", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "c1b15ac7e2c82bd82b97cb109e2eda55", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "890bf4dcce18e5c9bcaea42a69e3c4e4", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "84cb3bc48affe53ac615b8ad94d7ee80", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ebfc636ad2b39dd441f80937996dd83d", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "e43e64e55f5456a606f0be8aa025f579", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "480e90cb5c8c676283ffd3a4f8e50dcf", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "e24d2cd8656f5f5c5dc02db28fe3c1dd", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "b10596b46ada2101a8c0769cc722f426", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "5dd458a30196c39bc9e334f1a9d5b3a4", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "43ab8ae4b7c5ededde417f0f01aa00f5", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "24fb0ffabb00de09ec9b63103534639b", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "2788e7b24f36c51ec4ec603a30ac5ae2", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "9f5fbf290252d070e98aab13f305c7dc", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "3be3c2402c33445e7fe5aa1cadc5fb19", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "ff8ebebe327730c091a2f1d55865be5d", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ca29146d034f7ea18c0948b0a42f99d0", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "2ecabf751c7d10a3b5b80b134b3d5162", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "05c9d29f361c523ce785d8d5d8311278", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "c72df8dd7b8830cf54c186b77fbe1c4c", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "2bf6f80b765ef15a4394ad370370b6af", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d9f919fe87d497529cd8aed24a961ea3", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "56972014971024060e6014c2027debd2", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d9f919fe87d497529cd8aed24a961ea3", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "39a0f3efabd9d2f62202ef9790e5cecd", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "2609429078b69b48c3cda49abac7065c", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "39a0f3efabd9d2f62202ef9790e5cecd", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7f3de02f9481408b02ebfd1253452b30", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "a56a0aecab25961be71f364bd29eecaf", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "cbc394d29f300aac67374c586f07e3dd", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "ceba6e421ed2ccd51114bfdd239881d9", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "eaa568b2aee0f4cd4e186cee7ac98a9a", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e13fdefc582d9c86a3b5f9cb4e5781f5", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1f1065b864ddd2e6b376835c09bf809b", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "9eab26a8053f011ab0247e67bf59ecf3", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "350146c7495a8bb828bec1a6782e3619", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "2be7ecb0dfd69fb74b60b7b60cd5c1e6", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "dff90dc36b0c809b08941684093db4a6", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "291720ae84da8daa1b3ae12dfde5713e", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "9c598f1db7b3ec0d80106c63e55a0062", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "620fe910d6f506645d4d4882b6b0c31d", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "27212e46c4b7e57d32a523b13de8fafd", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "36e695121b06f4b04e0e6d9d588189b4", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index 827e1817..d5542dd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21551, api 8, 2023-10-31) +### 1.7.28 (build 21554, api 8, 2023-11-01) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 963ee465..4ce5be99 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21551 +TARGET_BALLISTICA_BUILD = 21554 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py b/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py index e29245b6..23c4a977 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py @@ -35,7 +35,7 @@ class ControlsGuide(bs.Actor): delay: is the time in seconds before the overlay fades in. lifespan: if not None, the overlay will fade back out and die after - that long (in milliseconds). + that long (in seconds). bright: if True, brighter colors will be used; handy when showing over gameplay but may be too bright for join-screens, etc. @@ -50,6 +50,7 @@ class ControlsGuide(bs.Actor): offs5 = 43.0 * scale ouya = False maxw = 50 + xtweak = -2.8 * scale self._lifespan = lifespan self._dead = False self._bright = bright @@ -117,7 +118,7 @@ class ControlsGuide(bs.Actor): 'host_only': True, 'shadow': 1.0, 'maxwidth': maxw, - 'position': (pos[0], pos[1] - offs5), + 'position': (pos[0] + xtweak, pos[1] - offs5), 'color': clr, }, ) @@ -145,7 +146,7 @@ class ControlsGuide(bs.Actor): 'host_only': True, 'shadow': 1.0, 'maxwidth': maxw, - 'position': (pos[0], pos[1] - offs5), + 'position': (pos[0] + xtweak, pos[1] - offs5), 'color': clr, }, ) @@ -173,7 +174,7 @@ class ControlsGuide(bs.Actor): 'host_only': True, 'shadow': 1.0, 'maxwidth': maxw, - 'position': (pos[0], pos[1] - offs5), + 'position': (pos[0] + xtweak, pos[1] - offs5), 'color': clr, }, ) @@ -201,7 +202,7 @@ class ControlsGuide(bs.Actor): 'host_only': True, 'shadow': 1.0, 'maxwidth': maxw, - 'position': (pos[0], pos[1] - offs5), + 'position': (pos[0] + xtweak, pos[1] - offs5), 'color': clr, }, ) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py index eeb12dad..3c67b23f 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py @@ -554,7 +554,6 @@ class GamepadSettingsWindow(bui.Window): if self._is_secondary else None ) - print('got', sval1, sval2) assert isinstance(sval1, (int, type(None))) assert isinstance(sval2, (int, type(None))) if sval1 is not None and sval2 is not None: diff --git a/src/ballistica/base/input/device/joystick_input.cc b/src/ballistica/base/input/device/joystick_input.cc index 910f9459..be7e4ab4 100644 --- a/src/ballistica/base/input/device/joystick_input.cc +++ b/src/ballistica/base/input/device/joystick_input.cc @@ -148,7 +148,17 @@ auto JoystickInput::HasMeaningfulButtonNames() -> bool { return g_buildconfig.ostype_android(); } +void JoystickInput::SetButtonName(int button, const std::string& name) { + button_names_[button] = name; +} + auto JoystickInput::GetButtonName(int index) -> std::string { + // First check any explicit ones we were passed. + auto i = button_names_.find(index); + if (i != button_names_.end()) { + return i->second; + } + // FIXME: Should get fancier here now that PS4 and XBone // controllers are supported through this. if (is_mfi_controller_) { diff --git a/src/ballistica/base/input/device/joystick_input.h b/src/ballistica/base/input/device/joystick_input.h index 0444bb19..985fc78c 100644 --- a/src/ballistica/base/input/device/joystick_input.h +++ b/src/ballistica/base/input/device/joystick_input.h @@ -3,6 +3,7 @@ #ifndef BALLISTICA_BASE_INPUT_DEVICE_JOYSTICK_INPUT_H_ #define BALLISTICA_BASE_INPUT_DEVICE_JOYSTICK_INPUT_H_ +#include #include #include @@ -49,7 +50,6 @@ class JoystickInput : public InputDevice { auto GetPartyButtonName() const -> std::string override; - auto GetButtonName(int index) -> std::string override; auto GetAxisName(int index) -> std::string override; auto IsController() -> bool override { return true; } @@ -73,6 +73,11 @@ class JoystickInput : public InputDevice { auto HasMeaningfulButtonNames() -> bool override; + auto GetButtonName(int index) -> std::string override; + + /// Custom controller types can pass in controller-specific button names. + void SetButtonName(int button, const std::string& name); + protected: auto GetRawDeviceName() -> std::string override; auto GetDeviceExtraDescription() -> std::string override; @@ -185,6 +190,7 @@ class JoystickInput : public InputDevice { std::string custom_device_name_; std::string raw_sdl_joystick_name_; std::string raw_sdl_joystick_identifier_; + std::map button_names_; Object::Ref ui_repeater_; BA_DISALLOW_CLASS_COPIES(JoystickInput); diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index eb9b8922..755f62c9 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 = 21551; +const int kEngineBuildNumber = 21554; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; From 544e26f129a5512e4b0f96c8a106aafad9367882 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 1 Nov 2023 19:43:18 -0700 Subject: [PATCH 21/25] mac key name cleanup --- .efrocachemap | 56 +++++++++---------- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- src/assets/ba_data/python/bauiv1lib/config.py | 8 ++- .../python/bauiv1lib/settings/audio.py | 6 +- .../base/app_adapter/app_adapter.cc | 6 ++ src/ballistica/base/app_adapter/app_adapter.h | 3 + .../base/app_adapter/app_adapter_apple.cc | 5 ++ .../base/app_adapter/app_adapter_apple.h | 1 + .../base/app_adapter/app_adapter_sdl.cc | 4 ++ .../base/app_adapter/app_adapter_sdl.h | 2 + .../base/input/device/keyboard_input.cc | 2 +- src/ballistica/base/platform/base_platform.cc | 15 ----- src/ballistica/base/platform/base_platform.h | 5 -- .../base/platform/support/min_sdl_key_names.h | 16 ++++++ src/ballistica/shared/ballistica.cc | 2 +- tools/efrotools/xcodebuild.py | 28 ++++++++++ 17 files changed, 108 insertions(+), 55 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 54c96d18..a6f3ff31 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "c1b15ac7e2c82bd82b97cb109e2eda55", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "890bf4dcce18e5c9bcaea42a69e3c4e4", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "84cb3bc48affe53ac615b8ad94d7ee80", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ebfc636ad2b39dd441f80937996dd83d", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "e43e64e55f5456a606f0be8aa025f579", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "480e90cb5c8c676283ffd3a4f8e50dcf", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "e24d2cd8656f5f5c5dc02db28fe3c1dd", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "b10596b46ada2101a8c0769cc722f426", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "5dd458a30196c39bc9e334f1a9d5b3a4", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "43ab8ae4b7c5ededde417f0f01aa00f5", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "24fb0ffabb00de09ec9b63103534639b", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "2788e7b24f36c51ec4ec603a30ac5ae2", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "9f5fbf290252d070e98aab13f305c7dc", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "3be3c2402c33445e7fe5aa1cadc5fb19", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "ff8ebebe327730c091a2f1d55865be5d", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ca29146d034f7ea18c0948b0a42f99d0", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "2ecabf751c7d10a3b5b80b134b3d5162", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "05c9d29f361c523ce785d8d5d8311278", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "c72df8dd7b8830cf54c186b77fbe1c4c", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "2bf6f80b765ef15a4394ad370370b6af", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "1204dd2c8c75de926c75e4502f57078c", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "264ac33e0b3a273ffd7ef9769dde5cf6", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "2fa0bf5f0a41977b5ec6b00ed4f17e2a", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ef726bab56ae11cf3ef215e01e21c9ad", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "f5d464b59bf9cdb8c1196c7884e2f173", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "56c886224798634fcea2ddfb5591ce45", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8fb46e16a41be252433e01b1fe8e5beb", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "19fb1ea3b52056948eb8cb09527ebe8f", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "4abe83d555baef553005792bb2afba97", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "0166ad734496b21d70e4d830cbb1ec19", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "bfd52a1ce35dfbabc57e6de74e2a61d0", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "f5a7ecb24c30c46f3ea7d340f3373fdb", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "3a9e88a6e7242f7488a59c9d8c42e8ee", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "fba815a45d4eec03f9d03d3adcb65261", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "f4ee5cbc285b34d905dbc28dbcd25762", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "3fd648584a9a1168b2c7e5cb4e6e18b9", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "47e28b96a08f68902cbe206e6ba652d1", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "fd7b02a98cc446f848f5c19182737b62", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "5218e7604faabfb6b5574d756753edc8", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "cc3a4942b16dbd28698cfa677e1bd4ac", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d9f919fe87d497529cd8aed24a961ea3", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "56972014971024060e6014c2027debd2", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d9f919fe87d497529cd8aed24a961ea3", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "39a0f3efabd9d2f62202ef9790e5cecd", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "2609429078b69b48c3cda49abac7065c", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "39a0f3efabd9d2f62202ef9790e5cecd", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "350146c7495a8bb828bec1a6782e3619", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "2be7ecb0dfd69fb74b60b7b60cd5c1e6", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "dff90dc36b0c809b08941684093db4a6", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "291720ae84da8daa1b3ae12dfde5713e", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "9c598f1db7b3ec0d80106c63e55a0062", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "620fe910d6f506645d4d4882b6b0c31d", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "27212e46c4b7e57d32a523b13de8fafd", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "36e695121b06f4b04e0e6d9d588189b4", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "61c6cc3186a52a11fb139d223b09cb52", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "783012d8d15a7345b4b73d1b9e0b3981", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "2320d558ecad7debab45d723d4324eae", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "be03efae4c21cd3645754f9dd64e00ad", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "51d50c4a0dae45415ab465f13fdc7a92", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "10a651d1815134112b9dc3e151c6adfa", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4f7c320636d09bc598c38fc1a2db6d7d", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "9e9244b097860ad6a76478b0a1fa137f", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", diff --git a/CHANGELOG.md b/CHANGELOG.md index d5542dd9..406457b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21554, api 8, 2023-11-01) +### 1.7.28 (build 21556, api 8, 2023-11-01) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 4ce5be99..d63e8638 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21554 +TARGET_BALLISTICA_BUILD = 21556 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bauiv1lib/config.py b/src/assets/ba_data/python/bauiv1lib/config.py index 15032cfa..763a3704 100644 --- a/src/assets/ba_data/python/bauiv1lib/config.py +++ b/src/assets/ba_data/python/bauiv1lib/config.py @@ -93,6 +93,7 @@ class ConfigNumberEdit: displayname: str | bui.Lstr | None = None, changesound: bool = True, textscale: float = 1.0, + as_percent: bool = False, ): if displayname is None: displayname = configkey @@ -103,6 +104,7 @@ class ConfigNumberEdit: self._increment = increment self._callback = callback self._value = bui.app.config.resolve(configkey) + self._as_percent = as_percent self.nametext = bui.textwidget( parent=parent, @@ -166,4 +168,8 @@ class ConfigNumberEdit: bui.app.config.apply_and_commit() def _update_display(self) -> None: - bui.textwidget(edit=self.valuetext, text=f'{self._value:.1f}') + if self._as_percent: + val = f'{round(self._value*100.0)}%' + else: + val = f'{self._value:.1f}' + bui.textwidget(edit=self.valuetext, text=val) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/audio.py b/src/assets/ba_data/python/bauiv1lib/settings/audio.py index bfe71e40..643e23fa 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/audio.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/audio.py @@ -121,7 +121,8 @@ class AudioSettingsWindow(bui.Window): displayname=bui.Lstr(resource=self._r + '.soundVolumeText'), minval=0.0, maxval=1.0, - increment=0.1, + increment=0.05, + as_percent=True, ) if bui.app.ui_v1.use_toolbars: bui.widget( @@ -137,9 +138,10 @@ class AudioSettingsWindow(bui.Window): displayname=bui.Lstr(resource=self._r + '.musicVolumeText'), minval=0.0, maxval=1.0, - increment=0.1, + increment=0.05, callback=music.music_volume_changed, changesound=False, + as_percent=True, ) v -= 0.5 * spacing diff --git a/src/ballistica/base/app_adapter/app_adapter.cc b/src/ballistica/base/app_adapter/app_adapter.cc index 7aba2807..085dae67 100644 --- a/src/ballistica/base/app_adapter/app_adapter.cc +++ b/src/ballistica/base/app_adapter/app_adapter.cc @@ -302,4 +302,10 @@ auto AppAdapter::DoClipboardGetText() -> std::string { return ""; } +auto AppAdapter::GetKeyName(int keycode) -> std::string { + BA_LOG_ONCE(LogLevel::kWarning, + "CorePlatform::GetKeyName not implemented here."); + return "?"; +} + } // namespace ballistica::base diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index 5c2ce998..c2ae868c 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -230,6 +230,9 @@ class AppAdapter { /// context. By default this is simply the main thread. virtual void DoPushGraphicsContextRunnable(Runnable* runnable); + // Return a name for a ballistica keyboard keycode. + virtual auto GetKeyName(int keycode) -> std::string; + protected: virtual ~AppAdapter(); diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.cc b/src/ballistica/base/app_adapter/app_adapter_apple.cc index 0e5ae5f7..858b1698 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -9,6 +9,7 @@ #include "ballistica/base/logic/logic.h" #include "ballistica/base/platform/apple/apple_utils.h" #include "ballistica/base/platform/apple/from_swift.h" +#include "ballistica/base/platform/support/min_sdl_key_names.h" #include "ballistica/base/support/app_config.h" #include "ballistica/shared/ballistica.h" #include "ballistica/shared/foundation/event_loop.h" @@ -282,6 +283,10 @@ auto AppAdapterApple::DoClipboardGetText() -> std::string { #endif } +auto AppAdapterApple::GetKeyName(int keycode) -> std::string { + return MinSDL_GetKeyName(keycode); +} + } // namespace ballistica::base #endif // BA_XCODE_BUILD diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.h b/src/ballistica/base/app_adapter/app_adapter_apple.h index c86f081f..8be9828d 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.h +++ b/src/ballistica/base/app_adapter/app_adapter_apple.h @@ -43,6 +43,7 @@ class AppAdapterApple : public AppAdapter { auto GetKeyRepeatDelay() -> float override; auto GetKeyRepeatInterval() -> float override; + auto GetKeyName(int keycode) -> std::string override; protected: void DoPushMainThreadRunnable(Runnable* runnable) override; diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.cc b/src/ballistica/base/app_adapter/app_adapter_sdl.cc index 6921f82d..f5d4ceb4 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -843,6 +843,10 @@ auto AppAdapterSDL::DoClipboardGetText() -> std::string { return out_s; } +auto AppAdapterSDL::GetKeyName(int keycode) -> std::string { + return SDL_GetKeyName(static_cast(keycode)); +} + } // namespace ballistica::base #endif // BA_SDL_BUILD diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.h b/src/ballistica/base/app_adapter/app_adapter_sdl.h index 49be24f7..0219ae07 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.h +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.h @@ -45,6 +45,8 @@ class AppAdapterSDL : public AppAdapter { auto GetGraphicsSettings() -> GraphicsSettings* override; + auto GetKeyName(int keycode) -> std::string override; + protected: void DoPushMainThreadRunnable(Runnable* runnable) override; void RunMainThreadEventLoopToCompletion() override; diff --git a/src/ballistica/base/input/device/keyboard_input.cc b/src/ballistica/base/input/device/keyboard_input.cc index ba9b3cab..0da1eeb5 100644 --- a/src/ballistica/base/input/device/keyboard_input.cc +++ b/src/ballistica/base/input/device/keyboard_input.cc @@ -477,7 +477,7 @@ void KeyboardInput::UpdateArrowKeys_(SDL_Keycode key) { } auto KeyboardInput::GetButtonName(int index) -> std::string { - return g_base->platform->GetKeyName(index); + return g_base->app_adapter->GetKeyName(index); } auto KeyboardInput::GetRawDeviceName() -> std::string { return "Keyboard"; } diff --git a/src/ballistica/base/platform/base_platform.cc b/src/ballistica/base/platform/base_platform.cc index 75eb59c8..d6a2cfff 100644 --- a/src/ballistica/base/platform/base_platform.cc +++ b/src/ballistica/base/platform/base_platform.cc @@ -7,7 +7,6 @@ #include "ballistica/base/base.h" #include "ballistica/base/input/input.h" #include "ballistica/base/logic/logic.h" -#include "ballistica/base/platform/support/min_sdl_key_names.h" #include "ballistica/base/python/base_python.h" #include "ballistica/base/ui/ui.h" #include "ballistica/core/core.h" @@ -27,20 +26,6 @@ void BasePlatform::PostInit() { BasePlatform::~BasePlatform() = default; -auto BasePlatform::GetKeyName(int keycode) -> std::string { - // On our actual SDL platforms we're trying to be *pure* sdl so - // call their function for this. Otherwise we call our own version - // of it which is basically the same thing (at least for now). -#if BA_MINSDL_BUILD - return MinSDL_GetKeyName(keycode); -#elif BA_SDL_BUILD - return SDL_GetKeyName(static_cast(keycode)); -#else - Log(LogLevel::kWarn, "CorePlatform::GetKeyName not implemented here."); - return "?"; -#endif -} - void BasePlatform::LoginAdapterGetSignInToken(const std::string& login_type, int attempt_id) { // Default implementation simply calls completion callback immediately. diff --git a/src/ballistica/base/platform/base_platform.h b/src/ballistica/base/platform/base_platform.h index 63e1b043..d6bca6bb 100644 --- a/src/ballistica/base/platform/base_platform.h +++ b/src/ballistica/base/platform/base_platform.h @@ -61,11 +61,6 @@ class BasePlatform { /// Called when the app should set itself up to intercept ctrl-c presses. virtual void SetupInterruptHandling(); -#pragma mark INPUT DEVICES ----------------------------------------------------- - - // Return a name for a ballistica keycode. - virtual auto GetKeyName(int keycode) -> std::string; - #pragma mark ACCOUNTS ---------------------------------------------------------- /// Called when a Python LoginAdapter is requesting an explicit sign-in. diff --git a/src/ballistica/base/platform/support/min_sdl_key_names.h b/src/ballistica/base/platform/support/min_sdl_key_names.h index f26912c8..57eae886 100644 --- a/src/ballistica/base/platform/support/min_sdl_key_names.h +++ b/src/ballistica/base/platform/support/min_sdl_key_names.h @@ -367,6 +367,22 @@ auto MinSDL_GetKeyName(int keycode) -> std::string { static char name[8]; char* end; + // Handle a few specially per platform. + if (g_buildconfig.ostype_macos()) { + switch (key) { + case SDLK_LGUI: + return "Left Command"; + case SDLK_RGUI: + return "Right Command"; + case SDLK_LALT: + return "Left Option"; + case SDLK_RALT: + return "Right Option"; + default: + break; + } + } + if (key & SDLK_SCANCODE_MASK) { return GetScancodeName((SDL_Scancode)(key & ~SDLK_SCANCODE_MASK)); } diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 755f62c9..6b0a60e7 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 = 21554; +const int kEngineBuildNumber = 21556; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/tools/efrotools/xcodebuild.py b/tools/efrotools/xcodebuild.py index 718a4dbd..c221ef7b 100644 --- a/tools/efrotools/xcodebuild.py +++ b/tools/efrotools/xcodebuild.py @@ -55,6 +55,7 @@ class SigningConfig: class _Section(Enum): COMPILEC = 'CompileC' + COMPILEXCSTRINGS = 'CompileXCStrings' SWIFTCOMPILE = 'SwiftCompile' SWIFTGENERATEPCH = 'SwiftGeneratePch' SWIFTDRIVER = 'SwiftDriver' @@ -91,6 +92,7 @@ class _Section(Enum): EXTRACTAPPINTENTSMETADATA = 'ExtractAppIntentsMetadata' SWIFTMERGEGENERATEDHEADERS = 'SwiftMergeGeneratedHeaders' GENERATEDSYMFILE = 'GenerateDSYMFile' + GENERATEASSETSYMBOLS = 'GenerateAssetSymbols' class XCodeBuild: @@ -575,6 +577,12 @@ class XCodeBuild: line, ignore_line_starts=['builtin-validationUtility'], ) + elif self._section is _Section.COMPILEXCSTRINGS: + self._print_simple_section_line( + line, + prefix='Compiling strings', + ignore_line_start_tails=['/xcstringstool'], + ) elif self._section is _Section.CONVERTICONSETFILE: self._print_simple_section_line( line, @@ -653,6 +661,9 @@ class XCodeBuild: '/copypng', '/iconutil', ], + ignore_containing=[ + 'note: detected encoding of input file as Unicode (UTF-8)' + ], ) elif self._section is _Section.PROCESSPRODUCTPACKAGING: if '.net.froemling.ballistica.ios"' in line: @@ -689,6 +700,17 @@ class XCodeBuild: '"com.apple.Music.library.read",', ], ) + elif self._section is _Section.GENERATEASSETSYMBOLS: + self._print_simple_section_line( + line, + ignore_containing=[ + '/* com.apple.actool.compilation-results */', + '/GeneratedAssetSymbols-Index.plist', + '/GeneratedAssetSymbols.h', + '/GeneratedAssetSymbols.swift', + ], + ) + elif self._section is _Section.PROCESSPRODUCTPACKAGINGDER: self._print_simple_section_line( line, @@ -944,12 +966,16 @@ class XCodeBuild: prefix_index: int | None = None, ignore_line_starts: list[str] | None = None, ignore_line_start_tails: list[str] | None = None, + ignore_containing: list[str] | None = None, prefix_unexpected: bool = True, ) -> None: + # pylint: disable=too-many-branches if ignore_line_starts is None: ignore_line_starts = [] if ignore_line_start_tails is None: ignore_line_start_tails = [] + if ignore_containing is None: + ignore_containing = [] # First line of the section. if self._section_line_count == 0: @@ -975,6 +1001,8 @@ class XCodeBuild: return if any(splits[0].endswith(tail) for tail in ignore_line_start_tails): return + if any(c in line for c in ignore_containing): + return # Fall back on printing anything we don't recognize. if prefix is None and prefix_unexpected: From 0d2a9c19b5cbc1cb56772023b279a31d08c0b8c5 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 7 Nov 2023 08:31:30 -0800 Subject: [PATCH 22/25] lang updates, mac/apple work, polishing --- .efrocachemap | 118 +++++++++--------- CHANGELOG.md | 5 +- .../ba_data/python/babase/_accountv2.py | 47 +++---- src/assets/ba_data/python/babase/_hooks.py | 25 ++++ src/assets/ba_data/python/babase/_login.py | 7 +- src/assets/ba_data/python/baenv.py | 2 +- .../ba_data/python/baplus/_subsystem.py | 2 +- .../ba_data/python/bauiv1lib/store/browser.py | 2 +- .../base/app_adapter/app_adapter_apple.cc | 7 ++ .../base/app_adapter/app_adapter_apple.h | 2 + src/ballistica/base/base.cc | 37 ++++++ src/ballistica/base/base.h | 11 ++ .../platform/apple/base_platform_apple.cc | 11 +- src/ballistica/base/python/base_python.h | 2 + .../python/methods/python_methods_misc.cc | 22 ++++ src/ballistica/base/support/plus_soft.h | 1 + src/ballistica/base/ui/dev_console.cc | 3 +- .../python/methods/python_methods_classic.cc | 3 - .../platform/apple/core_platform_apple.cc | 27 ++++ .../core/platform/apple/core_platform_apple.h | 3 + src/ballistica/core/platform/core_platform.cc | 25 ++-- src/ballistica/core/platform/core_platform.h | 20 ++- .../platform/linux/core_platform_linux.cc | 51 +++++++- .../core/platform/linux/core_platform_linux.h | 2 + .../platform/windows/core_platform_windows.cc | 30 ++++- .../platform/windows/core_platform_windows.h | 1 + src/ballistica/shared/ballistica.cc | 2 +- .../shared/buildconfig/buildconfig_cmake.h | 12 +- .../shared/buildconfig/buildconfig_common.h | 5 + .../buildconfig/buildconfig_windows_common.h | 11 +- src/ballistica/shared/python/python_ref.cc | 6 + src/ballistica/shared/python/python_ref.h | 2 + .../python/methods/python_methods_ui_v1.cc | 4 +- src/meta/babasemeta/pyembed/binding_base.py | 2 + tools/bacommon/login.py | 5 + tools/batools/build.py | 4 +- tools/batools/xcodeproject.py | 12 +- 37 files changed, 404 insertions(+), 127 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index a6f3ff31..7130d838 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,40 +421,40 @@ "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", - "build/assets/ba_data/data/langdata.json": "0b15d171ebcc56d324875b48436b58c2", - "build/assets/ba_data/data/languages/arabic.json": "c21378ee214a9dd0cb2971cd46b74374", + "build/assets/ba_data/data/langdata.json": "d3d2ff5c566f5ebbfd4c2cb838bddec8", + "build/assets/ba_data/data/languages/arabic.json": "cb5ad1bc4ce57a43902ef2f8770d3721", "build/assets/ba_data/data/languages/belarussian.json": "4d89ed5f9c615771d4fa2bb1834942d3", - "build/assets/ba_data/data/languages/chinese.json": "1ff4350df6d81c3b1b765fddace6b4c8", + "build/assets/ba_data/data/languages/chinese.json": "a87b1ebef100d9cdce0d29123735e90c", "build/assets/ba_data/data/languages/chinesetraditional.json": "f858da49be0a5374157c627857751078", "build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa", "build/assets/ba_data/data/languages/czech.json": "93c5fe0d884d95435da6c675f64e30e0", "build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e", "build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e", - "build/assets/ba_data/data/languages/english.json": "b0c8dc8bd35a5606e5d3318d7cb52cba", + "build/assets/ba_data/data/languages/english.json": "0e84003f1d3ebf3d48e00ec962c96de4", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/filipino.json": "afbda3adf14555e1567ee63c32e340e7", - "build/assets/ba_data/data/languages/french.json": "4e218dcd488fa63e7db5b4da2261b9e1", + "build/assets/ba_data/data/languages/french.json": "49ff6d211537b8003b8241438dca661d", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", - "build/assets/ba_data/data/languages/gibberish.json": "d9022a7e655da5ac41b9cef7f3b114a6", + "build/assets/ba_data/data/languages/gibberish.json": "efcc8b133365c9080f99decb75acde02", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", - "build/assets/ba_data/data/languages/indonesian.json": "15a50690e5588d4acd3e07dfdaf755b0", - "build/assets/ba_data/data/languages/italian.json": "e4acd4e58ef8db78f3369bf881f84c55", + "build/assets/ba_data/data/languages/indonesian.json": "d7e06971ae1df89ac070593d6ca5cd10", + "build/assets/ba_data/data/languages/italian.json": "840a44facc3f203be505e97ce517e008", "build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2", "build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38", - "build/assets/ba_data/data/languages/persian.json": "4585070bd509600019ec8dc3bb47bfb8", + "build/assets/ba_data/data/languages/persian.json": "07162e160abd7452d1b25d069425653b", "build/assets/ba_data/data/languages/polish.json": "5e25428554893155a5f81f3eeb418bae", - "build/assets/ba_data/data/languages/portuguese.json": "51e362956f89da3eec980f587c092253", + "build/assets/ba_data/data/languages/portuguese.json": "a1af6ebf382969cbe16083fbfdb445da", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", - "build/assets/ba_data/data/languages/russian.json": "6e524210149d95479d6cbfd3506c630b", + "build/assets/ba_data/data/languages/russian.json": "a88a107d9643084ecec41649c1d6300e", "build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69", "build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef", - "build/assets/ba_data/data/languages/spanish.json": "b179da96097e2b4df9f0397da672be69", + "build/assets/ba_data/data/languages/spanish.json": "af2d0fd078144dc649da0bb10bb1f5cd", "build/assets/ba_data/data/languages/swedish.json": "77d671f10613291ebf9c71da66f18a18", - "build/assets/ba_data/data/languages/tamil.json": "65ab7798d637fa62a703750179eeb723", + "build/assets/ba_data/data/languages/tamil.json": "b4de1a2851afe4869c82e9acd94cd89c", "build/assets/ba_data/data/languages/thai.json": "33f63753c9af9a5b238d229a0bf23fbc", - "build/assets/ba_data/data/languages/turkish.json": "71fd6c59650c03164a94d884bc7e5263", + "build/assets/ba_data/data/languages/turkish.json": "c3674336e746bf7b23617a6ff296c69a", "build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2", "build/assets/ba_data/data/languages/venetian.json": "9fe1a58d9e5dfb00f31ce3b2eb9993f4", "build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba", @@ -4056,53 +4056,53 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "1204dd2c8c75de926c75e4502f57078c", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "264ac33e0b3a273ffd7ef9769dde5cf6", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "2fa0bf5f0a41977b5ec6b00ed4f17e2a", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ef726bab56ae11cf3ef215e01e21c9ad", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "f5d464b59bf9cdb8c1196c7884e2f173", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "56c886224798634fcea2ddfb5591ce45", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8fb46e16a41be252433e01b1fe8e5beb", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "19fb1ea3b52056948eb8cb09527ebe8f", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "4abe83d555baef553005792bb2afba97", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "0166ad734496b21d70e4d830cbb1ec19", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "bfd52a1ce35dfbabc57e6de74e2a61d0", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "f5a7ecb24c30c46f3ea7d340f3373fdb", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "3a9e88a6e7242f7488a59c9d8c42e8ee", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "fba815a45d4eec03f9d03d3adcb65261", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "f4ee5cbc285b34d905dbc28dbcd25762", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "3fd648584a9a1168b2c7e5cb4e6e18b9", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "47e28b96a08f68902cbe206e6ba652d1", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "fd7b02a98cc446f848f5c19182737b62", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "5218e7604faabfb6b5574d756753edc8", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "cc3a4942b16dbd28698cfa677e1bd4ac", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d9f919fe87d497529cd8aed24a961ea3", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "56972014971024060e6014c2027debd2", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d9f919fe87d497529cd8aed24a961ea3", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "56972014971024060e6014c2027debd2", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "3b0da9dfd7b2efe967aaafd3e68d4a86", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "d4889e0f44a762e4bf067af33e8885e1", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "3b0da9dfd7b2efe967aaafd3e68d4a86", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "d4889e0f44a762e4bf067af33e8885e1", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "5d6b77d2280ad8366f1386f7af0d8e6b", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "0c8ab52403a77eb7a11137afb6946f8b", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "5d6b77d2280ad8366f1386f7af0d8e6b", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "0c8ab52403a77eb7a11137afb6946f8b", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "85ab9b2e82eb2ddca6e915b4a3c3589e", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "39a0f3efabd9d2f62202ef9790e5cecd", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "2609429078b69b48c3cda49abac7065c", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "39a0f3efabd9d2f62202ef9790e5cecd", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "61c6cc3186a52a11fb139d223b09cb52", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "783012d8d15a7345b4b73d1b9e0b3981", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "2320d558ecad7debab45d723d4324eae", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "be03efae4c21cd3645754f9dd64e00ad", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "51d50c4a0dae45415ab465f13fdc7a92", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "10a651d1815134112b9dc3e151c6adfa", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4f7c320636d09bc598c38fc1a2db6d7d", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "9e9244b097860ad6a76478b0a1fa137f", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "19845a4215bc313b1a4dd9d69942265a", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "40617b9787763afac039ad0d4fc6eadd", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f824e95be076fe725529fade8e67c7bf", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b9fc05ff4ea772b67d13e4fa502d7e96", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "94ab7152a2e807a0a5a86f15fa994ef1", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "2b8826ec31f972d3695f3cc764c2d948", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "e4c860d74e777557c7450ad2768397a3", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "95aadd6ff910cc97d713d89e7b4b7204", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f9716cc12cd895de300a0e2f4081d26c", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "27b743836b3026b1188fbc61e88ac63f", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "33fded513bdfc0a71e58c29f5f491b2e", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "71c7005881cff6ff7746d5727c2707a5", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "ee418012d124c7f3268e9f533a865d74", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "8653169242b6f5b1fdb3649585da37ed", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "d02f8dd537b65dcd1580f97dc215a2f4", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "7da065b3e1a360df7bc0f0b047e26a8d", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "8845c707fa5c004f33b84e6515d7de27", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "91cfbdc3c4ed14bb7febd1ebee73a652", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "34fb266dcb2900931232fc4807d646ad", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "7820f6e29bf5f06ca395ca0e939bb24c", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "542350a6380ee39396048bf7e311492e", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "55e5254a8d2b7a57a70daf0e49c9f3de", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "542350a6380ee39396048bf7e311492e", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "55e5254a8d2b7a57a70daf0e49c9f3de", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "e5f96639a0806a7c6a7e76c3c602d71e", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "aa334ef3a0b9883c64a979abfac03614", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "e5f96639a0806a7c6a7e76c3c602d71e", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "aa334ef3a0b9883c64a979abfac03614", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "d8e77274adbd49f54cb0ae10932a1cd4", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "00d78e3bd28bb2d151f6b2dabb28bf6b", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "d8e77274adbd49f54cb0ae10932a1cd4", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "00d78e3bd28bb2d151f6b2dabb28bf6b", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "7062c43dfcb22a4dab751d4d63a77bcc", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "d5d54553e6069cb258bc2aee960de714", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "aad9457aaa3f0d12be511fcec6168090", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "d5d54553e6069cb258bc2aee960de714", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "ab4eae4c6dff6e748e67017d21f1e8c8", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "f5eac099166269081a9ba49b354979d5", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "52ae423620dede6bfd35face89277298", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0fa3164cb9bedac84418c5223b1c8b05", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "b4051c8e3eca5a9d2b1d1fd613c0e563", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "0a3fed54d59a681df074d56c3dc76268", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "42f69e30b6cf087bbc01fa5e508f1e6c", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "08d7f5d30a2c84e2f325d51f08e0611a", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", - "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", + "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", "src/ballistica/base/mgen/pyembed/binding_base_app.inc": "00f81f9bd92386ec12a6e60170678a98", "src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3", "src/ballistica/core/mgen/pyembed/binding_core.inc": "9d0a3c9636138e35284923e0c8311c69", diff --git a/CHANGELOG.md b/CHANGELOG.md index 406457b2..fc9444dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21556, api 8, 2023-11-01) +### 1.7.28 (build 21570, api 8, 2023-11-07) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years @@ -202,6 +202,9 @@ several hundred FPS, milliseconds per frame would drop to 0 which caused some problems. Note that scenev1 will be remaining on milliseconds internally for compatibility reasons. Scenev2 should move to microseconds though. +- The V2 account id for the signed in account is now available at + `ba*.app.plus.accounts.primary.accountid` (alongside some other existing + account info). ### 1.7.27 (build 21282, api 8, 2023-08-30) diff --git a/src/assets/ba_data/python/babase/_accountv2.py b/src/assets/ba_data/python/babase/_accountv2.py index 78d138f1..4e22f6d3 100644 --- a/src/assets/ba_data/python/babase/_accountv2.py +++ b/src/assets/ba_data/python/babase/_accountv2.py @@ -31,6 +31,8 @@ class AccountV2Subsystem: """ def __init__(self) -> None: + from babase._login import LoginAdapterGPGS + # Whether or not everything related to an initial login # (or lack thereof) has completed. This includes things like # workspace syncing. Completion of this is what flips the app @@ -45,15 +47,7 @@ class AccountV2Subsystem: self._implicit_state_changed = False self._can_do_auto_sign_in = True - if _babase.app.classic is None: - raise RuntimeError('Needs updating for no-classic case.') - - if ( - _babase.app.classic.platform == 'android' - and _babase.app.classic.subplatform == 'google' - ): - from babase._login import LoginAdapterGPGS - + if _babase.using_google_play_game_services(): self.login_adapters[LoginType.GPGS] = LoginAdapterGPGS() def on_app_loading(self) -> None: @@ -62,10 +56,6 @@ class AccountV2Subsystem: for adapter in self.login_adapters.values(): adapter.on_app_loading() - def set_primary_credentials(self, credentials: str | None) -> None: - """Set credentials for the primary app account.""" - raise NotImplementedError('This should be overridden.') - def have_primary_credentials(self) -> bool: """Are credentials currently set for the primary app account? @@ -80,10 +70,6 @@ class AccountV2Subsystem: """The primary account for the app, or None if not logged in.""" return self.do_get_primary() - def do_get_primary(self) -> AccountV2Handle | None: - """Internal - should be overridden by subclass.""" - return None - def on_primary_account_changed( self, account: AccountV2Handle | None ) -> None: @@ -259,6 +245,14 @@ class AccountV2Subsystem: # We may want to auto-sign-in based on this new state. self._update_auto_sign_in() + def do_get_primary(self) -> AccountV2Handle | None: + """Internal - should be overridden by subclass.""" + raise NotImplementedError('This should be overridden.') + + def set_primary_credentials(self, credentials: str | None) -> None: + """Set credentials for the primary app account.""" + raise NotImplementedError('This should be overridden.') + def _update_auto_sign_in(self) -> None: plus = _babase.app.plus assert plus is not None @@ -419,14 +413,21 @@ class AccountV2Handle: used with some operations such as cloud messaging. """ - def __init__(self) -> None: - self.tag = '?' + accountid: str + tag: str + workspacename: str | None + workspaceid: str | None + logins: dict[LoginType, str] - self.workspacename: str | None = None - self.workspaceid: str | None = None + # def __init__(self) -> None: - # Login types and their display-names associated with this account. - self.logins: dict[LoginType, str] = {} + # self.workspacename: str | None = None + # self.workspaceid: str | None = None + + # # Login types and their display-names associated with this account. + # self.logins: dict[LoginType, str] = {} + + # self.accountid: str = def __enter__(self) -> None: """Support for "with" statement. diff --git a/src/assets/ba_data/python/babase/_hooks.py b/src/assets/ba_data/python/babase/_hooks.py index 8ea73a5e..52aaf840 100644 --- a/src/assets/ba_data/python/babase/_hooks.py +++ b/src/assets/ba_data/python/babase/_hooks.py @@ -33,6 +33,23 @@ def reset_to_main_menu() -> None: logging.warning('reset_to_main_menu: no-op due to classic not present.') +def get_v2_account_id() -> str | None: + """Return the current V2 account id if signed in, or None if not.""" + try: + plus = _babase.app.plus + if plus is not None: + account = plus.accounts.primary + if account is not None: + accountid = account.accountid + # (Avoids mypy complaints when plus is not present) + assert isinstance(accountid, (str, type(None))) + return accountid + return None + except Exception: + logging.exception('Error fetching v2 account id.') + return None + + def store_config_fullscreen_on() -> None: """The OS has changed our fullscreen state and we should take note.""" _babase.app.config['Fullscreen'] = True @@ -123,6 +140,14 @@ def error_message() -> None: _babase.screenmessage(Lstr(resource='errorText'), color=(1, 0, 0)) +def success_message() -> None: + from babase._language import Lstr + + if _babase.app.env.gui: + _babase.getsimplesound('dingSmall').play() + _babase.screenmessage(Lstr(resource='successText'), color=(0, 1, 0)) + + def purchase_not_valid_error() -> None: from babase._language import Lstr diff --git a/src/assets/ba_data/python/babase/_login.py b/src/assets/ba_data/python/babase/_login.py index f6c761c4..68b2ba62 100644 --- a/src/assets/ba_data/python/babase/_login.py +++ b/src/assets/ba_data/python/babase/_login.py @@ -340,8 +340,8 @@ class LoginAdapter: class LoginAdapterNative(LoginAdapter): """A login adapter that does its work in the native layer.""" - def __init__(self) -> None: - super().__init__(LoginType.GPGS) + def __init__(self, login_type: LoginType) -> None: + super().__init__(login_type) # Store int ids for in-flight attempts since they may go through # various platform layers and back. @@ -375,3 +375,6 @@ class LoginAdapterNative(LoginAdapter): class LoginAdapterGPGS(LoginAdapterNative): """Google Play Game Services adapter.""" + + def __init__(self) -> None: + super().__init__(LoginType.GPGS) diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index d63e8638..45e77e5a 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21556 +TARGET_BALLISTICA_BUILD = 21570 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/baplus/_subsystem.py b/src/assets/ba_data/python/baplus/_subsystem.py index 00d4f0bf..97a9cdb5 100644 --- a/src/assets/ba_data/python/baplus/_subsystem.py +++ b/src/assets/ba_data/python/baplus/_subsystem.py @@ -1,6 +1,6 @@ # Released under the MIT License. See LICENSE for details. # -"""Provides classic app subsystem.""" +"""Provides plus app subsystem.""" from __future__ import annotations from typing import TYPE_CHECKING diff --git a/src/assets/ba_data/python/bauiv1lib/store/browser.py b/src/assets/ba_data/python/bauiv1lib/store/browser.py index 269a8164..03af613a 100644 --- a/src/assets/ba_data/python/bauiv1lib/store/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/store/browser.py @@ -352,7 +352,7 @@ class StoreBrowserWindow(bui.Window): plus = bui.app.plus assert plus is not None - if plus.get_v1_account_state() != 'signed_in': + if plus.accounts.primary is None: account.show_sign_in_prompt() else: plus.restore_purchases() diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.cc b/src/ballistica/base/app_adapter/app_adapter_apple.cc index 858b1698..73ce68a3 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -51,6 +51,13 @@ void AppAdapterApple::DoPushMainThreadRunnable(Runnable* runnable) { BallisticaKit::FromCpp::PushRawRunnableToMain(runnable); } +void AppAdapterApple::OnMainThreadStartApp() { + AppAdapter::OnMainThreadStartApp(); +#if BA_USE_STORE_KIT + BallisticaKit::StoreKitContext::onAppStart(); +#endif +} + void AppAdapterApple::DoApplyAppConfig() { assert(g_base->InLogicThread()); } void AppAdapterApple::ApplyGraphicsSettings(const GraphicsSettings* settings) { diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.h b/src/ballistica/base/app_adapter/app_adapter_apple.h index 8be9828d..a7fee4a3 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.h +++ b/src/ballistica/base/app_adapter/app_adapter_apple.h @@ -26,6 +26,8 @@ class AppAdapterApple : public AppAdapter { return val; } + void OnMainThreadStartApp() override; + auto ManagesMainThreadEventLoop() const -> bool override; void DoApplyAppConfig() override; diff --git a/src/ballistica/base/base.cc b/src/ballistica/base/base.cc index 644d3125..6a7a18cd 100644 --- a/src/ballistica/base/base.cc +++ b/src/ballistica/base/base.cc @@ -151,6 +151,43 @@ auto BaseFeatureSet::IsBaseCompletelyImported() -> bool { return base_import_completed_ && base_native_import_completed_; } +void BaseFeatureSet::SuccessScreenMessage() { + if (auto* event_loop = logic->event_loop()) { + event_loop->PushCall([this] { + python->objs().Get(BasePython::ObjID::kSuccessMessageCall).Call(); + }); + } else { + Log(LogLevel::kError, + "SuccessScreenMessage called without logic event_loop in place."); + } +} + +void BaseFeatureSet::ErrorScreenMessage() { + if (auto* event_loop = logic->event_loop()) { + event_loop->PushCall([this] { + python->objs().Get(BasePython::ObjID::kErrorMessageCall).Call(); + }); + } else { + Log(LogLevel::kError, + "ErrorScreenMessage called without logic event_loop in place."); + } +} + +auto BaseFeatureSet::GetV2AccountID() -> std::optional { + auto gil = Python::ScopedInterpreterLock(); + auto result = + python->objs().Get(BasePython::ObjID::kGetV2AccountIdCall).Call(); + if (result.Exists()) { + if (result.ValueIsNone()) { + return {}; + } + return result.ValueAsString(); + } else { + Log(LogLevel::kError, "GetV2AccountID() py call errored."); + return {}; + } +} + void BaseFeatureSet::OnAssetsAvailable() { assert(InLogicThread()); diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index c452e739..27243583 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -632,6 +632,13 @@ class BaseFeatureSet : public FeatureSetNativeComponent, return *context_ref; } + /// Utility call to print 'Success!' with a happy sound. + /// Safe to call from any thread. + void SuccessScreenMessage(); + /// Utility call to print 'Error.' with a beep sound. + /// Safe to call from any thread. + void ErrorScreenMessage(); + void SetCurrentContext(const ContextRef& context); /// Try to load the plus feature-set and return whether it is available. @@ -725,6 +732,10 @@ class BaseFeatureSet : public FeatureSetNativeComponent, void PushMainThreadRunnable(Runnable* runnable) override; + /// Return the currently signed in V2 account id as + /// reported by the Python layer. + auto GetV2AccountID() -> std::optional; + // Const subsystems. AppAdapter* const app_adapter; AppConfig* const app_config; diff --git a/src/ballistica/base/platform/apple/base_platform_apple.cc b/src/ballistica/base/platform/apple/base_platform_apple.cc index 9bfc4a3e..62119df5 100644 --- a/src/ballistica/base/platform/apple/base_platform_apple.cc +++ b/src/ballistica/base/platform/apple/base_platform_apple.cc @@ -25,7 +25,8 @@ BasePlatformApple::BasePlatformApple() { void BasePlatformApple::DoPurchase(const std::string& item) { #if BA_USE_STORE_KIT - AppleUtils::DoStoreKitPurchase(item); + BallisticaKit::StoreKitContext::purchase(item); + // AppleUtils::DoStoreKitPurchase(item); #else BasePlatform::DoPurchase(item); #endif @@ -33,7 +34,8 @@ void BasePlatformApple::DoPurchase(const std::string& item) { void BasePlatformApple::RestorePurchases() { #if BA_USE_STORE_KIT - AppleUtils::DoStoreKitPurchaseRestore(); + BallisticaKit::StoreKitContext::restorePurchases(); + // AppleUtils::DoStoreKitPurchaseRestore(); #else BasePlatform::RestorePurchases(); #endif @@ -41,8 +43,9 @@ void BasePlatformApple::RestorePurchases() { void BasePlatformApple::PurchaseAck(const std::string& purchase, const std::string& order_id) { -#if BA_XCODE_BUILD && BA_USE_STORE_KIT - AppleUtils::PurchaseAck(purchase, order_id); +#if BA_USE_STORE_KIT + BallisticaKit::StoreKitContext::purchaseAck(purchase, order_id); + // AppleUtils::PurchaseAck(purchase, order_id); #else BasePlatform::PurchaseAck(purchase, order_id); #endif diff --git a/src/ballistica/base/python/base_python.h b/src/ballistica/base/python/base_python.h index dc31d93f..5646cabe 100644 --- a/src/ballistica/base/python/base_python.h +++ b/src/ballistica/base/python/base_python.h @@ -48,6 +48,7 @@ class BasePython { kTemporarilyUnavailableMessageCall, kInProgressMessageCall, kErrorMessageCall, + kSuccessMessageCall, kPurchaseNotValidErrorCall, kPurchaseAlreadyInProgressErrorCall, kVROrientationResetCBMessageCall, @@ -111,6 +112,7 @@ class BasePython { kGetDevConsoleTabNamesCall, kAppDevConsoleDoRefreshTabCall, kUnsupportedControllerMessageCall, + kGetV2AccountIdCall, kLast // Sentinel; must be at end. }; diff --git a/src/ballistica/base/python/methods/python_methods_misc.cc b/src/ballistica/base/python/methods/python_methods_misc.cc index e6391281..95ec7032 100644 --- a/src/ballistica/base/python/methods/python_methods_misc.cc +++ b/src/ballistica/base/python/methods/python_methods_misc.cc @@ -1682,6 +1682,27 @@ static PyMethodDef PyAssetLoadsAllowedDef = { "(internal)", }; +// -------------------- using_google_play_game_services ------------------------ + +static auto PyUsingGooglePlayGameServices(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + if (g_buildconfig.use_google_play_game_services()) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PyUsingGooglePlayGameServicesDef = { + "using_google_play_game_services", // name + (PyCFunction)PyUsingGooglePlayGameServices, // method + METH_NOARGS, // flags + + "using_google_play_game_services() -> bool\n" + "\n" + "(internal)", +}; + // ----------------------------------------------------------------------------- auto PythonMethodsMisc::GetMethods() -> std::vector { @@ -1745,6 +1766,7 @@ auto PythonMethodsMisc::GetMethods() -> std::vector { PyDevConsoleBaseScaleDef, PyDevConsoleRequestRefreshDef, PyAssetLoadsAllowedDef, + PyUsingGooglePlayGameServicesDef, }; } diff --git a/src/ballistica/base/support/plus_soft.h b/src/ballistica/base/support/plus_soft.h index b2b387e1..00994d3b 100644 --- a/src/ballistica/base/support/plus_soft.h +++ b/src/ballistica/base/support/plus_soft.h @@ -33,6 +33,7 @@ class PlusSoftInterface { virtual auto PutLog(bool fatal) -> bool = 0; virtual void AAT() = 0; virtual void AATE() = 0; + virtual auto GAHU() -> std::optional = 0; virtual void V1LoginDidChange() = 0; virtual void SetAdCompletionCall(PyObject* obj, bool pass_actually_showed) = 0; diff --git a/src/ballistica/base/ui/dev_console.cc b/src/ballistica/base/ui/dev_console.cc index 7ea9fd67..437b81a4 100644 --- a/src/ballistica/base/ui/dev_console.cc +++ b/src/ballistica/base/ui/dev_console.cc @@ -935,7 +935,8 @@ auto DevConsole::HandleKeyPress(const SDL_Keysym* keysym) -> bool { g_base->app_adapter->GetKeyRepeatDelay(), g_base->app_adapter->GetKeyRepeatInterval(), [this] { auto unichars = Utils::UnicodeFromUTF8(input_string_, "fjco33"); - if (!unichars.empty() && carat_char_ < unichars.size()) { + if (!unichars.empty() + && carat_char_ < static_cast(unichars.size())) { assert(CaratCharValid_()); unichars.erase(unichars.begin() + carat_char_); input_string_ = Utils::UTF8FromUnicode(unichars); diff --git a/src/ballistica/classic/python/methods/python_methods_classic.cc b/src/ballistica/classic/python/methods/python_methods_classic.cc index 9fab53da..52780c22 100644 --- a/src/ballistica/classic/python/methods/python_methods_classic.cc +++ b/src/ballistica/classic/python/methods/python_methods_classic.cc @@ -157,9 +157,6 @@ static auto PySetStressTesting(PyObject* self, PyObject* args) -> PyObject* { if (!PyArg_ParseTuple(args, "pi", &enable, &player_count)) { return nullptr; } - // g_base->app_adapter->PushMainThreadCall([enable, player_count] { - // g_base->stress_test()->Set(enable, player_count); - // }); g_base->logic->event_loop()->PushCall([enable, player_count] { g_classic->stress_test()->Set(enable, player_count); }); diff --git a/src/ballistica/core/platform/apple/core_platform_apple.cc b/src/ballistica/core/platform/apple/core_platform_apple.cc index 2ddce42d..0e880f50 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.cc +++ b/src/ballistica/core/platform/apple/core_platform_apple.cc @@ -34,6 +34,33 @@ auto CorePlatformApple::GetDeviceV1AccountUUIDPrefix() -> std::string { #endif } +auto CorePlatformApple::DoGetDeviceName() -> std::string { +#if BA_OSTYPE_MACOS && BA_XCODE_BUILD + // Ask swift for a pretty name if possible. + auto val = BallisticaKit::CocoaFromCpp::GetDeviceName(); + if (val) { + return val.get(); + } +#elif BA_OSTYPE_IOS_TVOS && BA_XCODE_BUILD + return BallisticaKit::UIKitFromCpp::GetDeviceName(); +#endif + return CorePlatform::DoGetDeviceName(); +} + +auto CorePlatformApple::DoGetDeviceDescription() -> std::string { +#if BA_OSTYPE_MACOS && BA_XCODE_BUILD + return BallisticaKit::CocoaFromCpp::GetDeviceModelName(); +#endif + return CorePlatform::DoGetDeviceDescription(); +} + +auto CorePlatformApple::GetOSVersionString() -> std::string { +#if BA_XCODE_BUILD + return BallisticaKit::FromCpp::GetOSVersion(); +#endif + return CorePlatform::GetOSVersionString(); +} + // Legacy for device-accounts; don't modify this code. auto CorePlatformApple::GetRealLegacyDeviceUUID(std::string* uuid) -> bool { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD diff --git a/src/ballistica/core/platform/apple/core_platform_apple.h b/src/ballistica/core/platform/apple/core_platform_apple.h index 000f79f1..13af2ba8 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.h +++ b/src/ballistica/core/platform/apple/core_platform_apple.h @@ -59,6 +59,9 @@ class CorePlatformApple : public CorePlatform { auto GetDeviceUUIDInputs() -> std::list override; auto GetLocale() -> std::string override; + auto DoGetDeviceName() -> std::string override; + auto DoGetDeviceDescription() -> std::string override; + auto GetOSVersionString() -> std::string override; protected: auto DoGetDataDirectoryMonolithicDefault() -> std::string override; diff --git a/src/ballistica/core/platform/core_platform.cc b/src/ballistica/core/platform/core_platform.cc index 787b517f..322a06d6 100644 --- a/src/ballistica/core/platform/core_platform.cc +++ b/src/ballistica/core/platform/core_platform.cc @@ -112,6 +112,8 @@ void CorePlatform::PostInit() { // this sometimes (mainly on windows). Should look into that // more closely or at least log it somewhere. device_name_ = Utils::GetValidUTF8(DoGetDeviceName().c_str(), "dn"); + device_description_ = + Utils::GetValidUTF8(DoGetDeviceDescription().c_str(), "fc"); ran_base_post_init_ = true; // Are we running in a terminal? @@ -424,6 +426,11 @@ auto CorePlatform::GetDeviceName() -> std::string { return device_name_; } +auto CorePlatform::GetDeviceDescription() -> std::string { + assert(ran_base_post_init_); + return device_description_; +} + auto CorePlatform::DoGetDeviceName() -> std::string { // Check devicename in env_var char* devicename; @@ -439,7 +446,11 @@ auto CorePlatform::DoGetDeviceName() -> std::string { nbuffer[sizeof(nbuffer) - 1] = 0; // Make sure its terminated. return nbuffer; } - return "Untitled Device"; + return "Unnamed Device"; +} + +auto CorePlatform::DoGetDeviceDescription() -> std::string { + return "Unknown Device Type"; } auto CorePlatform::IsRunningOnTV() -> bool { return false; } @@ -567,7 +578,7 @@ auto CorePlatform::GetIsStdinATerminal() -> bool { auto CorePlatform::GetOSVersionString() -> std::string { return ""; } auto CorePlatform::GetLegacyUserAgentString() -> std::string { - std::string device = GetDeviceName(); + std::string device = GetDeviceDescription(); std::string version = GetOSVersionString(); if (!version.empty()) { version = " " + version; @@ -597,7 +608,7 @@ auto CorePlatform::GetLegacyUserAgentString() -> std::string { subplatform = "DeMo"; } else if (g_buildconfig.arcade_build()) { subplatform = "ArCd"; - } else { + } else if (g_buildconfig.test_build()) { subplatform = "TstB"; } @@ -608,10 +619,10 @@ auto CorePlatform::GetLegacyUserAgentString() -> std::string { subplatform += " OnTV"; } - std::string out{std::string("BallisticaKit ") + kEngineVersion + subplatform - + " (" + std::to_string(kEngineBuildNumber) + ") (" - + g_buildconfig.platform_string() + version + "; " + device - + "; " + GetLocale() + ")"}; + std::string out{std::string("BallisticaKit ") + kEngineVersion + " (" + + std::to_string(kEngineBuildNumber) + ")" + subplatform + + " (" + g_buildconfig.platform_string() + version + "; " + + device + "; " + GetLocale() + ")"}; // This gets shipped to various places which might choke on fancy unicode // characters, so let's limit to simple ascii. diff --git a/src/ballistica/core/platform/core_platform.h b/src/ballistica/core/platform/core_platform.h index 03a5d20a..98ec4857 100644 --- a/src/ballistica/core/platform/core_platform.h +++ b/src/ballistica/core/platform/core_platform.h @@ -116,13 +116,15 @@ class CorePlatform { /// Return the directory where game replay files live. auto GetReplaysDir() -> std::string; - /// Return en_US or whatnot. + /// Return something like `en_US` or whatnot. virtual auto GetLocale() -> std::string; /// Get the older more complex user-agent-string, used for communication - /// with v1 servers/etc. This can go away eventually. - auto GetLegacyUserAgentString() -> std::string; + /// with v1 servers/etc. This should go away eventually. + virtual auto GetLegacyUserAgentString() -> std::string; + /// Return a human readable os version such as "10.4.2". + /// Can return a blank string when not known/relevant. virtual auto GetOSVersionString() -> std::string; /// Set an environment variable as utf8, overwriting if it already exists. @@ -135,6 +137,9 @@ class CorePlatform { /// results, etc. auto GetDeviceName() -> std::string; + /// Return a general identifier for the hardware device. + auto GetDeviceDescription() -> std::string; + /// Get a UUID for use with things like device-accounts. This function /// should not be used for other purposes, should not be modified, and /// eventually should go away after device accounts are phased out. Also, @@ -407,9 +412,15 @@ class CorePlatform { /// Called once per platform to determine touchscreen presence. virtual auto DoHasTouchScreen() -> bool; - /// Platforms should override this to provide device name. + /// Platforms should override this to provide a device name suitable for + /// displaying in network join lists/etc. Technically this is more like + /// hostname. virtual auto DoGetDeviceName() -> std::string; + /// Platforms should override this to provide a generic description of the + /// device; something like "iPhone 12 Pro". + virtual auto DoGetDeviceDescription() -> std::string; + /// Attempt to actually create a directory. /// Should *not* raise Exceptions if it already exists or if quiet is true. virtual void DoMakeDir(const std::string& dir, bool quiet); @@ -462,6 +473,7 @@ class CorePlatform { bool ran_base_post_init_ : 1 {}; millisecs_t start_time_millisecs_{}; std::string device_name_; + std::string device_description_; std::string legacy_device_uuid_; std::string volatile_data_dir_; std::string replays_dir_; diff --git a/src/ballistica/core/platform/linux/core_platform_linux.cc b/src/ballistica/core/platform/linux/core_platform_linux.cc index 855503ac..c6e32e87 100644 --- a/src/ballistica/core/platform/linux/core_platform_linux.cc +++ b/src/ballistica/core/platform/linux/core_platform_linux.cc @@ -3,8 +3,10 @@ #if BA_OSTYPE_LINUX #include "ballistica/core/platform/linux/core_platform_linux.h" -#include +#include +#include +#include #include namespace ballistica::core { @@ -29,6 +31,53 @@ std::string CorePlatformLinux::GenerateUUID() { return val; } +auto CorePlatformLinux::DoGetDeviceDescription() -> std::string { + // Let's look for something pretty like "Ubuntu 20.04", etc. + FILE* file = fopen("/etc/os-release", "r"); + std::optional out; + if (file != NULL) { + char line[256]; // Adjust the buffer size as needed + + while (fgets(line, sizeof(line), file)) { + if (strstr(line, "PRETTY_NAME=") != nullptr) { + // Extract the distribution name and version + char* start = strchr(line, '"'); + char* end = strrchr(line, '"'); + if (start != nullptr && end != nullptr) { + *end = '\0'; // Remove the trailing quote + out = start + 1; + } + break; + } + } + fclose(file); + } + if (out.has_value()) { + return *out; + } + return CorePlatform::GetDeviceDescription(); +} + +auto CorePlatformLinux::GetOSVersionString() -> std::string { + std::optional out; + struct utsname uts; + if (uname(&uts) == 0) { + out = uts.release; + + // Try to parse 3 version numbers. + unsigned int major, minor, bugfix; + if (sscanf(uts.release, "%u.%u.%u", &major, &minor, &bugfix) == 3) { + char buf[128]; + snprintf(buf, sizeof(buf), "%.u.%u.%u", major, minor, bugfix); + out = buf; + } + } + if (out.has_value()) { + return *out; + } + return CorePlatform::GetOSVersionString(); +} + auto CorePlatformLinux::GetDeviceUUIDInputs() -> std::list { std::list out; diff --git a/src/ballistica/core/platform/linux/core_platform_linux.h b/src/ballistica/core/platform/linux/core_platform_linux.h index 2bdcbf97..22834b6c 100644 --- a/src/ballistica/core/platform/linux/core_platform_linux.h +++ b/src/ballistica/core/platform/linux/core_platform_linux.h @@ -21,6 +21,8 @@ class CorePlatformLinux : public CorePlatform { auto GetPlatformName() -> std::string override; auto GetSubplatformName() -> std::string override; auto GetDeviceUUIDInputs() -> std::list override; + auto DoGetDeviceDescription() -> std::string override; + auto GetOSVersionString() -> std::string override; }; } // namespace ballistica::core diff --git a/src/ballistica/core/platform/windows/core_platform_windows.cc b/src/ballistica/core/platform/windows/core_platform_windows.cc index 8a44a78e..7a3d06ac 100644 --- a/src/ballistica/core/platform/windows/core_platform_windows.cc +++ b/src/ballistica/core/platform/windows/core_platform_windows.cc @@ -814,15 +814,33 @@ std::string CorePlatformWindows::DoGetDeviceName() { wchar_t computer_name[256]; DWORD computer_name_size = 256; int result = GetComputerName(computer_name, &computer_name_size); - if (result == 0) { - device_name = "BallisticaKit Game"; - } else { + if (result != 0) { device_name = UTF8Encode(computer_name); - if (device_name.size() == 0) { - device_name = "BallisticaKit Game"; + if (device_name.size() != 0) { + return device_name; } } - return device_name; + // Fall back on default. + return CorePlatform::DoGetDeviceName(); +} + +std::string CorePlatformWindows::DoGetDeviceDescription() { + std::string device_name; + wchar_t computer_name[256]; + DWORD computer_name_size = 256; + + // We currently return computer name for both the device name + // and description. Is there a way to get a more hardware-y name + // (like manufacturer make/model?) + int result = GetComputerName(computer_name, &computer_name_size); + if (result != 0) { + device_name = UTF8Encode(computer_name); + if (device_name.size() != 0) { + return device_name; + } + } + // Fall back on default. + return CorePlatform::DoGetDeviceDescription(); } bool CorePlatformWindows::DoHasTouchScreen() { return false; } diff --git a/src/ballistica/core/platform/windows/core_platform_windows.h b/src/ballistica/core/platform/windows/core_platform_windows.h index fe77ae71..ede060eb 100644 --- a/src/ballistica/core/platform/windows/core_platform_windows.h +++ b/src/ballistica/core/platform/windows/core_platform_windows.h @@ -40,6 +40,7 @@ class CorePlatformWindows : public CorePlatform { void DoMakeDir(const std::string& dir, bool quiet) override; auto GetLocale() -> std::string override; auto DoGetDeviceName() -> std::string override; + auto DoGetDeviceDescription() -> std::string override; auto DoHasTouchScreen() -> bool override; void EmitPlatformLog(const std::string& name, LogLevel level, const std::string& msg) override; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 6b0a60e7..30eefd20 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 = 21556; +const int kEngineBuildNumber = 21570; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/buildconfig/buildconfig_cmake.h b/src/ballistica/shared/buildconfig/buildconfig_cmake.h index d8a338eb..e4d69fcb 100644 --- a/src/ballistica/shared/buildconfig/buildconfig_cmake.h +++ b/src/ballistica/shared/buildconfig/buildconfig_cmake.h @@ -13,9 +13,9 @@ // We currently support regular and client builds on 64 bit mac posix #if __amd64__ -#define BA_PLATFORM_STRING "x86_64_macos" +#define BA_PLATFORM_STRING "macos x86_64" #elif __aarch64__ -#define BA_PLATFORM_STRING "arm64_macos" +#define BA_PLATFORM_STRING "macos arm64" #else #error Unknown processor architecture. #endif @@ -26,16 +26,16 @@ #elif __linux__ #if __amd64__ -#define BA_PLATFORM_STRING "x86_64_linux" +#define BA_PLATFORM_STRING "linux x86_64" #define BA_OSTYPE_LINUX 1 #elif __i386__ -#define BA_PLATFORM_STRING "x86_32_linux" +#define BA_PLATFORM_STRING "linux x86" #define BA_OSTYPE_LINUX 1 #elif __arm__ -#define BA_PLATFORM_STRING "arm_linux" +#define BA_PLATFORM_STRING "linux arm" #define BA_OSTYPE_LINUX 1 #elif __aarch64__ -#define BA_PLATFORM_STRING "arm64_linux" +#define BA_PLATFORM_STRING "linux arm64" #define BA_OSTYPE_LINUX 1 #else diff --git a/src/ballistica/shared/buildconfig/buildconfig_common.h b/src/ballistica/shared/buildconfig/buildconfig_common.h index 7c68aa97..62ff658f 100644 --- a/src/ballistica/shared/buildconfig/buildconfig_common.h +++ b/src/ballistica/shared/buildconfig/buildconfig_common.h @@ -166,6 +166,10 @@ namespace ballistica { #define BA_AMAZON_BUILD 0 #endif +#ifndef BA_STEAM_BUILD +#define BA_STEAM_BUILD 0 +#endif + #ifndef BA_GOOGLE_BUILD #define BA_GOOGLE_BUILD 0 #endif @@ -259,6 +263,7 @@ class BuildConfig { bool google_build() const { return EXPBOOL_(BA_GOOGLE_BUILD); } bool demo_build() const { return EXPBOOL_(BA_DEMO_BUILD); } bool arcade_build() const { return EXPBOOL_(BA_ARCADE_BUILD); } + bool steam_build() const { return EXPBOOL_(BA_STEAM_BUILD); } bool contains_python_dist() const { return EXPBOOL_(BA_CONTAINS_PYTHON_DIST); } diff --git a/src/ballistica/shared/buildconfig/buildconfig_windows_common.h b/src/ballistica/shared/buildconfig/buildconfig_windows_common.h index 86654b77..69c62f06 100644 --- a/src/ballistica/shared/buildconfig/buildconfig_windows_common.h +++ b/src/ballistica/shared/buildconfig/buildconfig_windows_common.h @@ -32,7 +32,16 @@ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -#define BA_PLATFORM_STRING "x86_windows" +#if defined(_M_ARM64) +#define BA_PLATFORM_STRING "windows arm64" +#elif defined(_M_IX86) +#define BA_PLATFORM_STRING "windows x86" +#elif defined(_M_X64) +#define BA_PLATFORM_STRING "windows x86_64" +#else +#error unknown cpu architecture +#endif + #define BA_OSTYPE_WINDOWS 1 #define BA_SOCKET_SEND_DATA_TYPE char diff --git a/src/ballistica/shared/python/python_ref.cc b/src/ballistica/shared/python/python_ref.cc index de883e13..51f0d88c 100644 --- a/src/ballistica/shared/python/python_ref.cc +++ b/src/ballistica/shared/python/python_ref.cc @@ -151,6 +151,12 @@ auto PythonRef::Type() const -> PythonRef { return {PyObject_Type(obj_), PythonRef::kSteal}; } +auto PythonRef::ValueIsNone() const -> bool { + assert(Python::HaveGIL()); + ThrowIfUnset(); + return obj_ == Py_None; +} + auto PythonRef::ValueAsLString() const -> std::string { assert(Python::HaveGIL()); ThrowIfUnset(); diff --git a/src/ballistica/shared/python/python_ref.h b/src/ballistica/shared/python/python_ref.h index 0370dffe..141aeebf 100644 --- a/src/ballistica/shared/python/python_ref.h +++ b/src/ballistica/shared/python/python_ref.h @@ -162,6 +162,8 @@ class PythonRef { /// Return the object's Python type object. auto Type() const -> PythonRef; + auto ValueIsNone() const -> bool; + /// For string and babase.Lstr types, returns a utf8 string. /// Throws an exception for other types. auto ValueAsLString() const -> std::string; diff --git a/src/ballistica/ui_v1/python/methods/python_methods_ui_v1.cc b/src/ballistica/ui_v1/python/methods/python_methods_ui_v1.cc index 6b1cdf49..8b1c6811 100644 --- a/src/ballistica/ui_v1/python/methods/python_methods_ui_v1.cc +++ b/src/ballistica/ui_v1/python/methods/python_methods_ui_v1.cc @@ -2717,14 +2717,14 @@ static auto PyOpenURL(PyObject* self, PyObject* args, PyObject* keywds) return nullptr; } // Need to pass a self-contained string to a lambda; not a char*. - std::string address2{address}; + std::string address_s{address}; assert(g_base->app_adapter); if (force_internal) { g_base->ui->ShowURL(address); } else { g_base->app_adapter->PushMainThreadCall( - [address2] { g_base->platform->OpenURL(address2); }); + [address_s] { g_base->platform->OpenURL(address_s); }); } Py_RETURN_NONE; BA_PYTHON_CATCH; diff --git a/src/meta/babasemeta/pyembed/binding_base.py b/src/meta/babasemeta/pyembed/binding_base.py index 95e1da12..ec06b3d5 100644 --- a/src/meta/babasemeta/pyembed/binding_base.py +++ b/src/meta/babasemeta/pyembed/binding_base.py @@ -31,6 +31,7 @@ values = [ _hooks.temporarily_unavailable_message, # kTemporarilyUnavailableMessageCall _hooks.in_progress_message, # kInProgressMessageCall _hooks.error_message, # kErrorMessageCall + _hooks.success_message, # kSuccessMessageCall _hooks.purchase_not_valid_error, # kPurchaseNotValidErrorCall _hooks.purchase_already_in_progress_error, # kPurchaseAlreadyInProgressErrorCall _hooks.orientation_reset_cb_message, # kVROrientationResetCBMessageCall @@ -57,6 +58,7 @@ values = [ _hooks.string_edit_adapter_can_be_replaced, # kStringEditAdapterCanBeReplacedCall _hooks.get_dev_console_tab_names, # kGetDevConsoleTabNamesCall _hooks.unsupported_controller_message, # kUnsupportedControllerMessageCall + _hooks.get_v2_account_id, # kGetV2AccountIdCall _language.Lstr, # kLStrClass _general.Call, # kCallClass _apputils.garbage_collect_session_end, # kGarbageCollectSessionEndCall diff --git a/tools/bacommon/login.py b/tools/bacommon/login.py index c8ec0057..2d6e5053 100644 --- a/tools/bacommon/login.py +++ b/tools/bacommon/login.py @@ -20,6 +20,9 @@ class LoginType(Enum): # Google Play Game Services GPGS = 'gpgs' + # Apple's Game Center + GAME_CENTER = 'game_center' + @property def displayname(self) -> str: """Human readable name for this value.""" @@ -29,3 +32,5 @@ class LoginType(Enum): return 'Email/Password' case cls.GPGS: return 'Google Play Games' + case cls.GAME_CENTER: + return 'Game Center' diff --git a/tools/batools/build.py b/tools/batools/build.py index 682c7cf3..004ab926 100644 --- a/tools/batools/build.py +++ b/tools/batools/build.py @@ -43,8 +43,8 @@ class PyRequirement: # remove our custom module based stuff soon if nobody complains, which # would free us to theoretically move to a requirements.txt based setup. PY_REQUIREMENTS = [ - PyRequirement(pipname='pylint', minversion=[3, 0, 1]), - PyRequirement(pipname='mypy', minversion=[1, 6, 0]), + PyRequirement(pipname='pylint', minversion=[3, 0, 2]), + PyRequirement(pipname='mypy', minversion=[1, 6, 1]), PyRequirement(pipname='cpplint', minversion=[1, 6, 1]), PyRequirement(pipname='pytest', minversion=[7, 4, 2]), PyRequirement(pipname='pytz', minversion=[2023, 3]), diff --git a/tools/batools/xcodeproject.py b/tools/batools/xcodeproject.py index 0d331df6..54afaae9 100644 --- a/tools/batools/xcodeproject.py +++ b/tools/batools/xcodeproject.py @@ -423,10 +423,20 @@ class Updater: f'{self.pnameu} macOS AppStore', f'{self.pnameu} macOS Steam', ] + # A few things only for AppStore bound builds. + if filename == 'StoreKitContext.swift': + return [ + f'{self.pnameu} iOS', + f'{self.pnameu} tvOS', + f'{self.pnameu} macOS AppStore', + ] # UIKit stuff applies to our iOS/tvOS targets. if filename.startswith('UIKit') and filename.endswith('.swift'): - return [f'{self.pnameu} iOS', f'{self.pnameu} tvOS'] + return [ + f'{self.pnameu} iOS', + f'{self.pnameu} tvOS', + ] # Everything else applies to everything. return None From 310660403be67b47295d2ac191a4f5a067a22636 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 9 Nov 2023 12:59:19 -0800 Subject: [PATCH 23/25] closing in on mac app store update finally --- .efrocachemap | 116 ++++++++-------- CHANGELOG.md | 2 +- config/spinoffconfig.py | 1 + .../ba_data/python/babase/_accountv2.py | 14 +- .../ba_data/python/babase/_devconsole.py | 6 +- src/assets/ba_data/python/babase/_hooks.py | 1 + src/assets/ba_data/python/babase/_login.py | 43 +++--- src/assets/ba_data/python/baenv.py | 2 +- .../python/bauiv1lib/account/settings.py | 128 ++++++++++++------ .../python/bauiv1lib/settings/advanced.py | 4 + .../base/app_adapter/app_adapter_apple.cc | 25 ++-- .../base/graphics/gl/renderer_gl.cc | 63 +++++---- .../platform/apple/base_platform_apple.cc | 32 ++++- .../base/platform/apple/base_platform_apple.h | 4 + src/ballistica/base/platform/base_platform.h | 4 +- .../python/methods/python_methods_misc.cc | 22 +++ .../platform/apple/core_platform_apple.cc | 70 +++++----- .../core/platform/apple/core_platform_apple.h | 2 +- src/ballistica/core/platform/core_platform.cc | 2 +- src/ballistica/core/platform/core_platform.h | 2 +- src/ballistica/shared/ballistica.cc | 2 +- tools/bacommon/login.py | 6 + tools/batools/project/_checks.py | 6 +- tools/batools/xcodeproject.py | 2 +- tools/efro/error.py | 2 +- tools/efro/message/_receiver.py | 11 +- tools/efrotools/pybuild.py | 18 +-- 27 files changed, 373 insertions(+), 217 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 7130d838..abd945a9 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,41 +421,41 @@ "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", - "build/assets/ba_data/data/langdata.json": "d3d2ff5c566f5ebbfd4c2cb838bddec8", - "build/assets/ba_data/data/languages/arabic.json": "cb5ad1bc4ce57a43902ef2f8770d3721", - "build/assets/ba_data/data/languages/belarussian.json": "4d89ed5f9c615771d4fa2bb1834942d3", + "build/assets/ba_data/data/langdata.json": "dca47b4976752e76e852f7a4be2c7aa3", + "build/assets/ba_data/data/languages/arabic.json": "e0001d8542c904bc3c98a174f256efd9", + "build/assets/ba_data/data/languages/belarussian.json": "7fe38341815ca6ff4d95224196e7a67e", "build/assets/ba_data/data/languages/chinese.json": "a87b1ebef100d9cdce0d29123735e90c", "build/assets/ba_data/data/languages/chinesetraditional.json": "f858da49be0a5374157c627857751078", "build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa", "build/assets/ba_data/data/languages/czech.json": "93c5fe0d884d95435da6c675f64e30e0", "build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e", "build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e", - "build/assets/ba_data/data/languages/english.json": "0e84003f1d3ebf3d48e00ec962c96de4", + "build/assets/ba_data/data/languages/english.json": "2fa464db3fe6bffa16a50c18dfbdc1a6", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/filipino.json": "afbda3adf14555e1567ee63c32e340e7", "build/assets/ba_data/data/languages/french.json": "49ff6d211537b8003b8241438dca661d", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", - "build/assets/ba_data/data/languages/gibberish.json": "efcc8b133365c9080f99decb75acde02", + "build/assets/ba_data/data/languages/gibberish.json": "1ade258922bcee1544c9c6015eeb8324", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", - "build/assets/ba_data/data/languages/indonesian.json": "d7e06971ae1df89ac070593d6ca5cd10", - "build/assets/ba_data/data/languages/italian.json": "840a44facc3f203be505e97ce517e008", + "build/assets/ba_data/data/languages/indonesian.json": "ba39cade3c965b2ddbee122880b6f0db", + "build/assets/ba_data/data/languages/italian.json": "b19a9f0b868a6c89e13a04609bf377dd", "build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2", "build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38", - "build/assets/ba_data/data/languages/persian.json": "07162e160abd7452d1b25d069425653b", - "build/assets/ba_data/data/languages/polish.json": "5e25428554893155a5f81f3eeb418bae", - "build/assets/ba_data/data/languages/portuguese.json": "a1af6ebf382969cbe16083fbfdb445da", + "build/assets/ba_data/data/languages/persian.json": "89f5c6f900317aaa20ec520e5fd65d32", + "build/assets/ba_data/data/languages/polish.json": "8bb8f7baa5efcf6cdd627140d209c2b2", + "build/assets/ba_data/data/languages/portuguese.json": "7374b6a5cadcf573ee4ab4a5b4bc8c0a", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", - "build/assets/ba_data/data/languages/russian.json": "a88a107d9643084ecec41649c1d6300e", + "build/assets/ba_data/data/languages/russian.json": "9e068a3afdec43b207c83aedfb812e82", "build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69", "build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef", - "build/assets/ba_data/data/languages/spanish.json": "af2d0fd078144dc649da0bb10bb1f5cd", - "build/assets/ba_data/data/languages/swedish.json": "77d671f10613291ebf9c71da66f18a18", + "build/assets/ba_data/data/languages/spanish.json": "0fca8361c6873e6445f0bea34a211b78", + "build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac", "build/assets/ba_data/data/languages/tamil.json": "b4de1a2851afe4869c82e9acd94cd89c", "build/assets/ba_data/data/languages/thai.json": "33f63753c9af9a5b238d229a0bf23fbc", "build/assets/ba_data/data/languages/turkish.json": "c3674336e746bf7b23617a6ff296c69a", - "build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2", + "build/assets/ba_data/data/languages/ukrainian.json": "e5c861187c4c6db37d1a033f4ef3dd5a", "build/assets/ba_data/data/languages/venetian.json": "9fe1a58d9e5dfb00f31ce3b2eb9993f4", "build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba", "build/assets/ba_data/data/maps/big_g.json": "1dd301d490643088a435ce75df971054", @@ -4056,50 +4056,50 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "19845a4215bc313b1a4dd9d69942265a", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "40617b9787763afac039ad0d4fc6eadd", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f824e95be076fe725529fade8e67c7bf", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b9fc05ff4ea772b67d13e4fa502d7e96", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "94ab7152a2e807a0a5a86f15fa994ef1", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "2b8826ec31f972d3695f3cc764c2d948", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "e4c860d74e777557c7450ad2768397a3", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "95aadd6ff910cc97d713d89e7b4b7204", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f9716cc12cd895de300a0e2f4081d26c", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "27b743836b3026b1188fbc61e88ac63f", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "33fded513bdfc0a71e58c29f5f491b2e", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "71c7005881cff6ff7746d5727c2707a5", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "ee418012d124c7f3268e9f533a865d74", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "8653169242b6f5b1fdb3649585da37ed", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "d02f8dd537b65dcd1580f97dc215a2f4", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "7da065b3e1a360df7bc0f0b047e26a8d", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "8845c707fa5c004f33b84e6515d7de27", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "91cfbdc3c4ed14bb7febd1ebee73a652", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "34fb266dcb2900931232fc4807d646ad", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "7820f6e29bf5f06ca395ca0e939bb24c", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "542350a6380ee39396048bf7e311492e", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "55e5254a8d2b7a57a70daf0e49c9f3de", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "542350a6380ee39396048bf7e311492e", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "55e5254a8d2b7a57a70daf0e49c9f3de", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "e5f96639a0806a7c6a7e76c3c602d71e", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "aa334ef3a0b9883c64a979abfac03614", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "e5f96639a0806a7c6a7e76c3c602d71e", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "aa334ef3a0b9883c64a979abfac03614", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "d8e77274adbd49f54cb0ae10932a1cd4", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "00d78e3bd28bb2d151f6b2dabb28bf6b", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "d8e77274adbd49f54cb0ae10932a1cd4", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "00d78e3bd28bb2d151f6b2dabb28bf6b", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "7062c43dfcb22a4dab751d4d63a77bcc", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "d5d54553e6069cb258bc2aee960de714", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "aad9457aaa3f0d12be511fcec6168090", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "d5d54553e6069cb258bc2aee960de714", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "ab4eae4c6dff6e748e67017d21f1e8c8", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "f5eac099166269081a9ba49b354979d5", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "52ae423620dede6bfd35face89277298", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0fa3164cb9bedac84418c5223b1c8b05", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "b4051c8e3eca5a9d2b1d1fd613c0e563", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "0a3fed54d59a681df074d56c3dc76268", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "42f69e30b6cf087bbc01fa5e508f1e6c", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "08d7f5d30a2c84e2f325d51f08e0611a", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "64292918215b9d3e6fc3d470db4c92b1", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "84c840b57ed000407a8b34e9c5015b54", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "bc6fc246d6e0551a18f161183ee89ad5", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "bc87c32aee50fbc67ca0531c536e7f10", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "bcf55f1a1e8e317dc355ebf2ea301d10", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0ad6f5cea06d4c0754d1763610c7be90", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2c1c99e0850749741e23e5db7fb45b22", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "960dee8cee9d2fe500629583668eee14", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "1eb609e4f8ba0cf740d9c7b8cbbbf4d3", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "80418b80ad17e283a65b85142b0b490d", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "1527e8235b808c6bdf5f2850875d1843", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0e8c85459f90cc0a1355aecad5b5306e", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "6c718c797dfaf2b85ce7bd5d6c7f9d8a", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "5eefb534d193a9fa06b413a9d5a05969", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "2dedf11d5e4ffa9ec02eb6025a9b3460", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "3a3075f5f28cbfe9cd302e9c371b9ed4", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "275342bb44f1f5edde893a9775eb0130", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "4866c1b244b493b99da24aa1bc965bb7", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "c2181a4564b675762f89e2bc3314332f", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "ac4a176d550b219aa3cb1f46ad738a66", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "f812111f1eb4ea76e99558305ce3980f", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "c16c1b360b27850f1ac4d3dc55194b0a", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "f812111f1eb4ea76e99558305ce3980f", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "c16c1b360b27850f1ac4d3dc55194b0a", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "473c84d44b472d3ae73df6a2f1b56839", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "970c415cbb7a3087a163fa6e96e634a1", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "473c84d44b472d3ae73df6a2f1b56839", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "970c415cbb7a3087a163fa6e96e634a1", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "86498db547380838a1c95b45ef17d28b", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "bf11ae92718ae3dd5116d623799dd27f", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "86498db547380838a1c95b45ef17d28b", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "bf11ae92718ae3dd5116d623799dd27f", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "147c5a5210a55978060381cc44a122db", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "380d456bc409849174a36c5d2f61aa1b", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "4fae9b286a6d1c5c729c49c483c1422a", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "380d456bc409849174a36c5d2f61aa1b", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "5bee4eaf62c401c65c94513eb3ac18fd", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "69438fa6a8c70381f355ff3fb94c5a13", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "ad27b9e1e63733ba10c34ae5fd8246df", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "5b1b8ac6e3022b633477c3989957fa81", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "d2364a2d49ba3268691fb7e1134c9359", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "a6436bf9a9fb5531b837d9be20c2834b", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "a502732d3df4e7ff6b5086cb1f9bbb08", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "5470de767289dca9b88678e69a1ecca4", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", diff --git a/CHANGELOG.md b/CHANGELOG.md index fc9444dd..fd4d6073 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21570, api 8, 2023-11-07) +### 1.7.28 (build 21578, api 8, 2023-11-09) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/config/spinoffconfig.py b/config/spinoffconfig.py index 3fe2bca1..1cbbc0f8 100644 --- a/config/spinoffconfig.py +++ b/config/spinoffconfig.py @@ -103,6 +103,7 @@ ctx.src_unchecked_paths = { 'ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/*/*.png', 'ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/*/*/*.png', 'ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/*/*/*/*/*.png', + 'ballisticakit-xcode/BallisticaKit.xcodeproj/xcuserdata', 'ballisticakit-android/BallisticaKit/src/*/res/*/*.png', 'ballisticakit-android/BallisticaKit/src/*/assets/ballistica_files', 'ballisticakit-android/local.properties', diff --git a/src/assets/ba_data/python/babase/_accountv2.py b/src/assets/ba_data/python/babase/_accountv2.py index 4e22f6d3..ab76ae1c 100644 --- a/src/assets/ba_data/python/babase/_accountv2.py +++ b/src/assets/ba_data/python/babase/_accountv2.py @@ -31,7 +31,7 @@ class AccountV2Subsystem: """ def __init__(self) -> None: - from babase._login import LoginAdapterGPGS + from babase._login import LoginAdapterGPGS, LoginAdapterGameCenter # Whether or not everything related to an initial login # (or lack thereof) has completed. This includes things like @@ -47,8 +47,13 @@ class AccountV2Subsystem: self._implicit_state_changed = False self._can_do_auto_sign_in = True + adapter: LoginAdapter if _babase.using_google_play_game_services(): - self.login_adapters[LoginType.GPGS] = LoginAdapterGPGS() + adapter = LoginAdapterGPGS() + self.login_adapters[adapter.login_type] = adapter + if _babase.using_game_center(): + adapter = LoginAdapterGameCenter() + self.login_adapters[adapter.login_type] = adapter def on_app_loading(self) -> None: """Should be called at standard on_app_loading time.""" @@ -128,6 +133,8 @@ class AccountV2Subsystem: """An implicit sign-in happened (called by native layer).""" from babase._login import LoginAdapter + assert _babase.in_logic_thread() + with _babase.ContextRef.empty(): self.login_adapters[login_type].set_implicit_login_state( LoginAdapter.ImplicitLoginState( @@ -137,6 +144,7 @@ class AccountV2Subsystem: def on_implicit_sign_out(self, login_type: LoginType) -> None: """An implicit sign-out happened (called by native layer).""" + assert _babase.in_logic_thread() with _babase.ContextRef.empty(): self.login_adapters[login_type].set_implicit_login_state(None) @@ -260,7 +268,7 @@ class AccountV2Subsystem: # If implicit state has changed, try to respond. if self._implicit_state_changed: if self._implicit_signed_in_adapter is None: - # If implicit back-end is signed out, follow suit + # If implicit back-end has signed out, we follow suit # immediately; no need to wait for network connectivity. if DEBUG_LOG: logging.debug( diff --git a/src/assets/ba_data/python/babase/_devconsole.py b/src/assets/ba_data/python/babase/_devconsole.py index 9e0ca0cd..fb63c9e7 100644 --- a/src/assets/ba_data/python/babase/_devconsole.py +++ b/src/assets/ba_data/python/babase/_devconsole.py @@ -3,6 +3,7 @@ """Dev-Console functionality.""" from __future__ import annotations +import os from typing import TYPE_CHECKING from dataclasses import dataclass import logging @@ -154,9 +155,10 @@ class DevConsoleSubsystem: # All tabs in the dev-console. Add your own stuff here via # plugins or whatnot. self.tabs: list[DevConsoleTabEntry] = [ - DevConsoleTabEntry('Python', DevConsoleTabPython), - DevConsoleTabEntry('Test', DevConsoleTabTest), + DevConsoleTabEntry('Python', DevConsoleTabPython) ] + if os.environ.get('BA_DEV_CONSOLE_TEST_TAB', '0') == '1': + self.tabs.append(DevConsoleTabEntry('Test', DevConsoleTabTest)) self.is_refreshing = False def do_refresh_tab(self, tabname: str) -> None: diff --git a/src/assets/ba_data/python/babase/_hooks.py b/src/assets/ba_data/python/babase/_hooks.py index 52aaf840..535d3084 100644 --- a/src/assets/ba_data/python/babase/_hooks.py +++ b/src/assets/ba_data/python/babase/_hooks.py @@ -337,6 +337,7 @@ def implicit_sign_in( from bacommon.login import LoginType assert _babase.app.plus is not None + _babase.app.plus.accounts.on_implicit_sign_in( login_type=LoginType(login_type_str), login_id=login_id, diff --git a/src/assets/ba_data/python/babase/_login.py b/src/assets/ba_data/python/babase/_login.py index 68b2ba62..084c2730 100644 --- a/src/assets/ba_data/python/babase/_login.py +++ b/src/assets/ba_data/python/babase/_login.py @@ -17,7 +17,7 @@ if TYPE_CHECKING: from typing import Callable -DEBUG_LOG = False +DEBUG_LOG = True class LoginAdapter: @@ -149,7 +149,7 @@ class LoginAdapter: result_cb: Callable[[LoginAdapter, SignInResult | Exception], None], description: str, ) -> None: - """Attempt an explicit sign in via this adapter. + """Attempt to sign in via this adapter. This can be called even if the back-end is not implicitly signed in; the adapter will attempt to sign in if possible. An exception will @@ -161,7 +161,7 @@ class LoginAdapter: # Have been seeing multiple sign-in attempts come through # nearly simultaneously which can be problematic server-side. # Let's error if a sign-in attempt is made within a few seconds - # of the last one to address this. + # of the last one to try and address this. now = time.monotonic() appnow = _babase.apptime() if self._last_sign_in_time is not None: @@ -229,6 +229,7 @@ class LoginAdapter: def _got_sign_in_response( response: bacommon.cloud.SignInResponse | Exception, ) -> None: + # This likely means we couldn't communicate with the server. if isinstance(response, Exception): if DEBUG_LOG: logging.debug( @@ -239,20 +240,18 @@ class LoginAdapter: ) _babase.pushcall(Call(result_cb, self, response)) else: - if DEBUG_LOG: - logging.debug( - 'LoginAdapter: %s adapter got successful' - ' sign-in response', - self.login_type.name, - ) + # This means our credentials were explicitly rejected. if response.credentials is None: result2: LoginAdapter.SignInResult | Exception = ( - RuntimeError( - 'No credentials returned after' - ' submitting sign-in-token.' - ) + RuntimeError('Sign-in-token was rejected.') ) else: + if DEBUG_LOG: + logging.debug( + 'LoginAdapter: %s adapter got successful' + ' sign-in response', + self.login_type.name, + ) result2 = self.SignInResult( credentials=response.credentials ) @@ -269,7 +268,7 @@ class LoginAdapter: on_response=_got_sign_in_response, ) - # Kick off the process by fetching a sign-in token. + # Kick off the sign-in process by fetching a sign-in token. self.get_sign_in_token(completion_cb=_got_sign_in_token_result) def is_back_end_active(self) -> bool: @@ -282,11 +281,10 @@ class LoginAdapter: """Get a sign-in token from the adapter back end. This token is then passed to the master-server to complete the - login process. - The adapter can use this opportunity to bring up account creation - UI, call its internal sign_in function, etc. as needed. - The provided completion_cb should then be called with either a token - or None if sign in failed or was cancelled. + sign-in process. The adapter can use this opportunity to bring + up account creation UI, call its internal sign_in function, etc. + as needed. The provided completion_cb should then be called with + either a token or None if sign in failed or was cancelled. """ from babase._general import Call @@ -378,3 +376,10 @@ class LoginAdapterGPGS(LoginAdapterNative): def __init__(self) -> None: super().__init__(LoginType.GPGS) + + +class LoginAdapterGameCenter(LoginAdapterNative): + """Apple Game Center adapter.""" + + def __init__(self) -> None: + super().__init__(LoginType.GAME_CENTER) diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 45e77e5a..dc2f986b 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21570 +TARGET_BALLISTICA_BUILD = 21578 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bauiv1lib/account/settings.py b/src/assets/ba_data/python/bauiv1lib/account/settings.py index 4cea92da..94502e91 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/settings.py +++ b/src/assets/ba_data/python/bauiv1lib/account/settings.py @@ -64,12 +64,13 @@ class AccountSettingsWindow(bui.Window): ) # Currently we can only reset achievements on game-center. - v1_account_type: str | None - if self._v1_signed_in: - v1_account_type = plus.get_v1_account_type() - else: - v1_account_type = None - self._can_reset_achievements = v1_account_type == 'Game Center' + # v1_account_type: str | None + # if self._v1_signed_in: + # v1_account_type = plus.get_v1_account_type() + # else: + # v1_account_type = None + # self._can_reset_achievements = v1_account_type == 'Game Center' + self._can_reset_achievements = False app = bui.app assert app.classic is not None @@ -98,6 +99,9 @@ class AccountSettingsWindow(bui.Window): if LoginType.GPGS in plus.accounts.login_adapters: self._show_sign_in_buttons.append('Google Play') + if LoginType.GAME_CENTER in plus.accounts.login_adapters: + self._show_sign_in_buttons.append('Game Center') + # Always want to show our web-based v2 login option. self._show_sign_in_buttons.append('V2Proxy') @@ -242,6 +246,16 @@ class AccountSettingsWindow(bui.Window): False if gpgs_adapter is None else gpgs_adapter.is_back_end_active() ) + # Ditto for Game Center. + game_center_adapter = plus.accounts.login_adapters.get( + LoginType.GAME_CENTER + ) + is_game_center = ( + False + if game_center_adapter is None + else game_center_adapter.is_back_end_active() + ) + show_signed_in_as = self._v1_signed_in signed_in_as_space = 95.0 @@ -258,6 +272,11 @@ class AccountSettingsWindow(bui.Window): and self._signing_in_adapter is None and 'Google Play' in self._show_sign_in_buttons ) + show_game_center_sign_in_button = ( + v1_state == 'signed_out' + and self._signing_in_adapter is None + and 'Game Center' in self._show_sign_in_buttons + ) show_v2_proxy_sign_in_button = ( v1_state == 'signed_out' and self._signing_in_adapter is None @@ -281,11 +300,9 @@ class AccountSettingsWindow(bui.Window): show_linked_accounts_text = self._v1_signed_in linked_accounts_text_space = 60.0 - show_achievements_button = self._v1_signed_in and v1_account_type in ( - 'Google Play', - 'Local', - 'V2', - ) + # Always show achievements except in the game-center case where + # its unified UI covers them. + show_achievements_button = self._v1_signed_in and not is_game_center achievements_button_space = 60.0 show_achievements_text = ( @@ -353,6 +370,8 @@ class AccountSettingsWindow(bui.Window): self._sub_height += signing_in_text_space if show_google_play_sign_in_button: self._sub_height += sign_in_button_space + if show_game_center_sign_in_button: + self._sub_height += sign_in_button_space if show_v2_proxy_sign_in_button: self._sub_height += sign_in_button_space if show_device_sign_in_button: @@ -477,22 +496,6 @@ class AccountSettingsWindow(bui.Window): if show_sign_in_benefits: v -= sign_in_benefits_space - app = bui.app - assert app.classic is not None - extra: str | bui.Lstr | None - if ( - app.classic.platform in ['mac', 'ios'] - and app.classic.subplatform == 'appstore' - ): - extra = bui.Lstr( - value='\n${S}', - subs=[ - ('${S}', bui.Lstr(resource='signInWithGameCenterText')) - ], - ) - else: - extra = '' - bui.textwidget( parent=self._subcontainer, position=( @@ -500,16 +503,7 @@ class AccountSettingsWindow(bui.Window): v + sign_in_benefits_space * 0.4, ), size=(0, 0), - text=bui.Lstr( - value='${A}${B}', - subs=[ - ( - '${A}', - bui.Lstr(resource=self._r + '.signInInfoText'), - ), - ('${B}', extra), - ], - ), + text=bui.Lstr(resource=self._r + '.signInInfoText'), max_height=sign_in_benefits_space * 0.9, scale=0.9, color=(0.75, 0.7, 0.8), @@ -554,7 +548,13 @@ class AccountSettingsWindow(bui.Window): ( '${B}', bui.Lstr( - resource=self._r + '.signInWithGooglePlayText' + resource=self._r + '.signInWithText', + subs=[ + ( + '${SERVICE}', + bui.Lstr(resource='googlePlayText'), + ) + ], ), ), ], @@ -572,6 +572,45 @@ class AccountSettingsWindow(bui.Window): bui.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100) self._sign_in_text = None + if show_game_center_sign_in_button: + button_width = 350 + v -= sign_in_button_space + self._sign_in_google_play_button = btn = bui.buttonwidget( + parent=self._subcontainer, + position=((self._sub_width - button_width) * 0.5, v - 20), + autoselect=True, + size=(button_width, 60), + label=bui.Lstr( + value='${A}${B}', + subs=[ + ( + '${A}', + bui.charstr(bui.SpecialChar.GAME_CENTER_LOGO), + ), + ( + '${B}', + bui.Lstr( + resource=self._r + '.signInWithText', + subs=[('${SERVICE}', 'Game Center')], + ), + ), + ], + ), + on_activate_call=lambda: self._sign_in_press( + LoginType.GAME_CENTER + ), + ) + if first_selectable is None: + first_selectable = btn + if bui.app.ui_v1.use_toolbars: + bui.widget( + edit=btn, + right_widget=bui.get_special_widget('party_button'), + ) + bui.widget(edit=btn, left_widget=bbtn) + bui.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100) + self._sign_in_text = None + if show_v2_proxy_sign_in_button: button_width = 350 v -= sign_in_button_space @@ -748,7 +787,11 @@ class AccountSettingsWindow(bui.Window): v -= game_service_button_space * 0.85 v1_account_type = plus.get_v1_account_type() if v1_account_type == 'Game Center': - v1_account_type_name = bui.Lstr(resource='gameCenterText') + # Update: Apparently Game Center is just called 'Game Center' + # in all languages. Can revisit if not true. + # https://developer.apple.com/forums/thread/725779 + v1_account_type_name = bui.Lstr(value='Game Center') + # v1_account_type_name = bui.Lstr(resource='gameCenterText') else: raise ValueError( "unknown account type: '" + str(v1_account_type) + "'" @@ -1469,8 +1512,11 @@ class AccountSettingsWindow(bui.Window): if isinstance(result, Exception): # For now just make a bit of noise if anything went wrong; # can get more specific as needed later. - logging.warning('Got error in v2 sign-in result: %s.', result) - bui.screenmessage(bui.Lstr(resource='errorText'), color=(1, 0, 0)) + logging.warning('Got error in v2 sign-in result: %s', result) + bui.screenmessage( + bui.Lstr(resource='internal.signInNoConnectionText'), + color=(1, 0, 0), + ) bui.getsound('error').play() else: # Success! Plug in these credentials which will begin diff --git a/src/assets/ba_data/python/bauiv1lib/settings/advanced.py b/src/assets/ba_data/python/bauiv1lib/settings/advanced.py index 930ecaa3..e7724815 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/advanced.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/advanced.py @@ -807,6 +807,8 @@ class AdvancedSettingsWindow(bui.Window): sel_name = 'ModdingGuide' elif sel == self._language_inform_checkbox: sel_name = 'LangInform' + elif sel == self._show_dev_console_button_check_box.widget: + sel_name = 'ShowDevConsole' else: raise ValueError(f'unrecognized selection \'{sel}\'') elif sel == self._back_button: @@ -870,6 +872,8 @@ class AdvancedSettingsWindow(bui.Window): sel = self._modding_guide_button elif sel_name == 'LangInform': sel = self._language_inform_checkbox + elif sel_name == 'ShowDevConsole': + sel = self._show_dev_console_button_check_box.widget else: sel = None if sel is not None: diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.cc b/src/ballistica/base/app_adapter/app_adapter_apple.cc index 73ce68a3..cccdba35 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -48,7 +48,7 @@ auto AppAdapterApple::ManagesMainThreadEventLoop() const -> bool { void AppAdapterApple::DoPushMainThreadRunnable(Runnable* runnable) { // Kick this along to swift. - BallisticaKit::FromCpp::PushRawRunnableToMain(runnable); + BallisticaKit::FromCpp::pushRawRunnableToMain(runnable); } void AppAdapterApple::OnMainThreadStartApp() { @@ -56,6 +56,9 @@ void AppAdapterApple::OnMainThreadStartApp() { #if BA_USE_STORE_KIT BallisticaKit::StoreKitContext::onAppStart(); #endif +#if BA_USE_GAME_CENTER + BallisticaKit::GameCenterContext::onAppStart(); +#endif } void AppAdapterApple::DoApplyAppConfig() { assert(g_base->InLogicThread()); } @@ -196,13 +199,13 @@ void AppAdapterApple::SetHardwareCursorVisible(bool visible) { assert(g_core->InMainThread()); #if BA_OSTYPE_MACOS - BallisticaKit::CocoaFromCpp::SetCursorVisible(visible); + BallisticaKit::CocoaFromCpp::setCursorVisible(visible); #endif } void AppAdapterApple::TerminateApp() { #if BA_OSTYPE_MACOS - BallisticaKit::CocoaFromCpp::TerminateApp(); + BallisticaKit::CocoaFromCpp::terminateApp(); #else AppAdapter::TerminateApp(); #endif @@ -219,7 +222,7 @@ auto AppAdapterApple::FullscreenControlAvailable() const -> bool { auto AppAdapterApple::FullscreenControlGet() const -> bool { #if BA_OSTYPE_MACOS - return BallisticaKit::CocoaFromCpp::GetMainWindowIsFullscreen(); + return BallisticaKit::CocoaFromCpp::getMainWindowIsFullscreen(); #else return false; #endif @@ -227,7 +230,7 @@ auto AppAdapterApple::FullscreenControlGet() const -> bool { void AppAdapterApple::FullscreenControlSet(bool fullscreen) { #if BA_OSTYPE_MACOS - return BallisticaKit::CocoaFromCpp::SetMainWindowFullscreen(fullscreen); + return BallisticaKit::CocoaFromCpp::setMainWindowFullscreen(fullscreen); #endif } @@ -240,7 +243,7 @@ auto AppAdapterApple::HasDirectKeyboardInput() -> bool { return true; }; auto AppAdapterApple::GetKeyRepeatDelay() -> float { #if BA_OSTYPE_MACOS - return BallisticaKit::CocoaFromCpp::GetKeyRepeatDelay(); + return BallisticaKit::CocoaFromCpp::getKeyRepeatDelay(); #else return AppAdapter::GetKeyRepeatDelay(); #endif @@ -248,7 +251,7 @@ auto AppAdapterApple::GetKeyRepeatDelay() -> float { auto AppAdapterApple::GetKeyRepeatInterval() -> float { #if BA_OSTYPE_MACOS - return BallisticaKit::CocoaFromCpp::GetKeyRepeatInterval(); + return BallisticaKit::CocoaFromCpp::getKeyRepeatInterval(); #else return AppAdapter::GetKeyRepeatDelay(); #endif @@ -256,7 +259,7 @@ auto AppAdapterApple::GetKeyRepeatInterval() -> float { auto AppAdapterApple::DoClipboardIsSupported() -> bool { #if BA_OSTYPE_MACOS - return BallisticaKit::CocoaFromCpp::ClipboardIsSupported(); + return BallisticaKit::CocoaFromCpp::clipboardIsSupported(); #else return AppAdapter::DoClipboardIsSupported(); #endif @@ -264,7 +267,7 @@ auto AppAdapterApple::DoClipboardIsSupported() -> bool { auto AppAdapterApple::DoClipboardHasText() -> bool { #if BA_OSTYPE_MACOS - return BallisticaKit::CocoaFromCpp::ClipboardHasText(); + return BallisticaKit::CocoaFromCpp::clipboardHasText(); #else return AppAdapter::DoClipboardHasText(); #endif @@ -272,7 +275,7 @@ auto AppAdapterApple::DoClipboardHasText() -> bool { void AppAdapterApple::DoClipboardSetText(const std::string& text) { #if BA_OSTYPE_MACOS - BallisticaKit::CocoaFromCpp::ClipboardSetText(text); + BallisticaKit::CocoaFromCpp::clipboardSetText(text); #else AppAdapter::DoClipboardSetText(text); #endif @@ -280,7 +283,7 @@ void AppAdapterApple::DoClipboardSetText(const std::string& text) { auto AppAdapterApple::DoClipboardGetText() -> std::string { #if BA_OSTYPE_MACOS - auto contents = BallisticaKit::CocoaFromCpp::ClipboardGetText(); + auto contents = BallisticaKit::CocoaFromCpp::clipboardGetText(); if (contents) { return std::string(contents.get()); } diff --git a/src/ballistica/base/graphics/gl/renderer_gl.cc b/src/ballistica/base/graphics/gl/renderer_gl.cc index adb60eae..b20b6e0f 100644 --- a/src/ballistica/base/graphics/gl/renderer_gl.cc +++ b/src/ballistica/base/graphics/gl/renderer_gl.cc @@ -453,44 +453,51 @@ void RendererGL::CheckGLCapabilities_() { } auto RendererGL::GetMSAASamplesForFramebuffer_(int width, int height) -> int { -#if BA_RIFT_BUILD - return 4; -#else - // We currently aim for 4 up to 800 height and 2 beyond that. - if (height > 800) { - return 2; + if (g_buildconfig.ostype_android()) { + // We currently aim for 4 up to 800 height and 2 beyond that. + if (height > 800) { + return 2; + } else { + return 4; + } } else { return 4; } -#endif } void RendererGL::UpdateMSAAEnabled_() { -#if BA_RIFT_BUILD - if (msaa_max_samples_rgb8_ > 0) { + if (g_buildconfig.ostype_macos()) { + // Let's go ahead and flip this on for Apple Silicon Macs. +#if __aarch64__ enable_msaa_ = true; +#else + enable_msaa_ = false; +#endif + } else if (g_buildconfig.rift_build()) { + if (msaa_max_samples_rgb8_ > 0) { + enable_msaa_ = true; + } else { + enable_msaa_ = false; + } + } else if (g_buildconfig.ostype_android()) { + // lets allow full 1080p msaa with newer stuff.. + int max_msaa_res = is_tegra_k1_ ? 1200 : 800; + + // To start, see if it looks like we support msaa on paper. + enable_msaa_ = + ((screen_render_target()->physical_height() + <= static_cast(max_msaa_res)) + && (msaa_max_samples_rgb8_ > 0) && (msaa_max_samples_rgb565_ > 0)); + + // Ok, lets be careful here; msaa blitting/etc seems to be particular in + // terms of supported formats/etc so let's only enable it on + // explicitly-tested hardware for now. + if (!is_tegra_4_ && !is_tegra_k1_ && !is_recent_adreno_) { + enable_msaa_ = false; + } } else { enable_msaa_ = false; } -#else - - // lets allow full 1080p msaa with newer stuff.. - int max_msaa_res = is_tegra_k1_ ? 1200 : 800; - - // To start, see if it looks like we support msaa on paper. - enable_msaa_ = - ((screen_render_target()->physical_height() - <= static_cast(max_msaa_res)) - && (msaa_max_samples_rgb8_ > 0) && (msaa_max_samples_rgb565_ > 0)); - - // Ok, lets be careful here; msaa blitting/etc seems to be particular in - // terms of supported formats/etc so let's only enable it on - // explicitly-tested hardware for now. - if (!is_tegra_4_ && !is_tegra_k1_ && !is_recent_adreno_) { - enable_msaa_ = false; - } - -#endif // BA_RIFT_BUILD } auto RendererGL::IsMSAAEnabled() const -> bool { return enable_msaa_; } diff --git a/src/ballistica/base/platform/apple/base_platform_apple.cc b/src/ballistica/base/platform/apple/base_platform_apple.cc index 62119df5..66227ce8 100644 --- a/src/ballistica/base/platform/apple/base_platform_apple.cc +++ b/src/ballistica/base/platform/apple/base_platform_apple.cc @@ -54,9 +54,9 @@ void BasePlatformApple::PurchaseAck(const std::string& purchase, void BasePlatformApple::DoOpenURL(const std::string& url) { #if BA_XCODE_BUILD #if BA_OSTYPE_MACOS - BallisticaKit::CocoaFromCpp::OpenURL(url); + BallisticaKit::CocoaFromCpp::openURL(url); #else - BallisticaKit::UIKitFromCpp::OpenURL(url); + BallisticaKit::UIKitFromCpp::openURL(url); #endif // BA_OSTYPE_MACOS #else @@ -65,6 +65,34 @@ void BasePlatformApple::DoOpenURL(const std::string& url) { #endif // BA_XCODE_BUILD } +void BasePlatformApple::LoginAdapterGetSignInToken( + const std::string& login_type, int attempt_id) { +#if BA_USE_GAME_CENTER + if (login_type == "game_center") { + BallisticaKit::GameCenterContext::getSignInToken(attempt_id); + } else { + Log(LogLevel::kError, + "Got unexpected get-sign-in-token login-type: " + login_type); + } +#else + BasePlatform::LoginAdapterGetSignInToken(login_type, attempt_id); +#endif +} + +void BasePlatformApple::LoginAdapterBackEndActiveChange( + const std::string& login_type, bool active) { +#if BA_USE_GAME_CENTER + if (login_type == "game_center") { + BallisticaKit::GameCenterContext::backEndActiveChange(active); + } else { + Log(LogLevel::kError, + "Got unexpected back-end-active-change login-type: " + login_type); + } +#else + BasePlatform::LoginAdapterBackEndActiveChange(login_type, active); +#endif +} + } // namespace ballistica::base #endif // BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS diff --git a/src/ballistica/base/platform/apple/base_platform_apple.h b/src/ballistica/base/platform/apple/base_platform_apple.h index d0fbaad8..9ccc5bb1 100644 --- a/src/ballistica/base/platform/apple/base_platform_apple.h +++ b/src/ballistica/base/platform/apple/base_platform_apple.h @@ -16,6 +16,10 @@ class BasePlatformApple : public BasePlatform { void PurchaseAck(const std::string& purchase, const std::string& order_id) override; void DoOpenURL(const std::string& url) override; + void LoginAdapterGetSignInToken(const std::string& login_type, + int attempt_id) override; + void LoginAdapterBackEndActiveChange(const std::string& login_type, + bool active) override; }; } // namespace ballistica::base diff --git a/src/ballistica/base/platform/base_platform.h b/src/ballistica/base/platform/base_platform.h index d6bca6bb..6470074a 100644 --- a/src/ballistica/base/platform/base_platform.h +++ b/src/ballistica/base/platform/base_platform.h @@ -64,10 +64,12 @@ class BasePlatform { #pragma mark ACCOUNTS ---------------------------------------------------------- /// Called when a Python LoginAdapter is requesting an explicit sign-in. + /// See the LoginAdapter class in Python for usage details. virtual void LoginAdapterGetSignInToken(const std::string& login_type, int attempt_id); /// Called when a Python LoginAdapter is informing us that a back-end is - /// active/inactive. + /// active/inactive. See the LoginAdapter class in Python for usage + /// details. virtual void LoginAdapterBackEndActiveChange(const std::string& login_type, bool active); diff --git a/src/ballistica/base/python/methods/python_methods_misc.cc b/src/ballistica/base/python/methods/python_methods_misc.cc index 95ec7032..0ce7625c 100644 --- a/src/ballistica/base/python/methods/python_methods_misc.cc +++ b/src/ballistica/base/python/methods/python_methods_misc.cc @@ -1703,6 +1703,27 @@ static PyMethodDef PyUsingGooglePlayGameServicesDef = { "(internal)", }; +// ---------------------------- using_game_center ------------------------------ + +static auto PyUsingGameCenter(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + if (g_buildconfig.use_game_center()) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PyUsingGameCenterDef = { + "using_game_center", // name + (PyCFunction)PyUsingGameCenter, // method + METH_NOARGS, // flags + + "using_game_center() -> bool\n" + "\n" + "(internal)", +}; + // ----------------------------------------------------------------------------- auto PythonMethodsMisc::GetMethods() -> std::vector { @@ -1767,6 +1788,7 @@ auto PythonMethodsMisc::GetMethods() -> std::vector { PyDevConsoleRequestRefreshDef, PyAssetLoadsAllowedDef, PyUsingGooglePlayGameServicesDef, + PyUsingGameCenterDef, }; } diff --git a/src/ballistica/core/platform/apple/core_platform_apple.cc b/src/ballistica/core/platform/apple/core_platform_apple.cc index 0e880f50..2122cfe6 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.cc +++ b/src/ballistica/core/platform/apple/core_platform_apple.cc @@ -37,26 +37,26 @@ auto CorePlatformApple::GetDeviceV1AccountUUIDPrefix() -> std::string { auto CorePlatformApple::DoGetDeviceName() -> std::string { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD // Ask swift for a pretty name if possible. - auto val = BallisticaKit::CocoaFromCpp::GetDeviceName(); + auto val = BallisticaKit::CocoaFromCpp::getDeviceName(); if (val) { return val.get(); } #elif BA_OSTYPE_IOS_TVOS && BA_XCODE_BUILD - return BallisticaKit::UIKitFromCpp::GetDeviceName(); + return BallisticaKit::UIKitFromCpp::getDeviceName(); #endif return CorePlatform::DoGetDeviceName(); } auto CorePlatformApple::DoGetDeviceDescription() -> std::string { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - return BallisticaKit::CocoaFromCpp::GetDeviceModelName(); + return BallisticaKit::CocoaFromCpp::getDeviceModelName(); #endif return CorePlatform::DoGetDeviceDescription(); } auto CorePlatformApple::GetOSVersionString() -> std::string { #if BA_XCODE_BUILD - return BallisticaKit::FromCpp::GetOSVersion(); + return BallisticaKit::FromCpp::getOSVersion(); #endif return CorePlatform::GetOSVersionString(); } @@ -64,11 +64,11 @@ auto CorePlatformApple::GetOSVersionString() -> std::string { // Legacy for device-accounts; don't modify this code. auto CorePlatformApple::GetRealLegacyDeviceUUID(std::string* uuid) -> bool { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - *uuid = std::string(BallisticaKit::CocoaFromCpp::GetLegacyDeviceUUID()); + *uuid = std::string(BallisticaKit::CocoaFromCpp::getLegacyDeviceUUID()); return true; #endif #if BA_OSTYPE_IOS_TVOS - *uuid = std::string(BallisticaKit::UIKitFromCpp::GetLegacyDeviceUUID()); + *uuid = std::string(BallisticaKit::UIKitFromCpp::getLegacyDeviceUUID()); // *uuid = base::AppleUtils::GetIOSUUID(); return true; #endif @@ -104,7 +104,7 @@ auto CorePlatformApple::GetDeviceUUIDInputs() -> std::list { #if BA_OSTYPE_MACOS #if BA_XCODE_BUILD out.push_back( - std::string(BallisticaKit::CocoaFromCpp::GetLegacyDeviceUUID())); + std::string(BallisticaKit::CocoaFromCpp::getLegacyDeviceUUID())); #else // BA_XCODE_BUILD out.push_back(GetMacUUIDFallback()); #endif // BA_XCODE_BUILD @@ -113,7 +113,7 @@ auto CorePlatformApple::GetDeviceUUIDInputs() -> std::list { #if BA_OSTYPE_IOS_TVOS // out.push_back(base::AppleUtils::GetIOSUUID()); out.push_back( - std::string(BallisticaKit::UIKitFromCpp::GetLegacyDeviceUUID())); + std::string(BallisticaKit::UIKitFromCpp::getLegacyDeviceUUID())); #endif return out; } @@ -133,7 +133,7 @@ auto CorePlatformApple::DoGetConfigDirectoryMonolithicDefault() printf("FIXME: get proper default-config-dir\n"); return std::string(getenv("HOME")) + "/Library"; #elif BA_OSTYPE_MACOS && BA_XCODE_BUILD - return std::string(BallisticaKit::CocoaFromCpp::GetApplicationSupportPath()) + return std::string(BallisticaKit::CocoaFromCpp::getApplicationSupportPath()) + "/BallisticaKit"; #else return CorePlatform::DoGetConfigDirectoryMonolithicDefault(); @@ -150,7 +150,7 @@ auto CorePlatformApple::DoHasTouchScreen() -> bool { auto CorePlatformApple::GetDefaultUIScale() -> UIScale { #if BA_OSTYPE_IOS - if (BallisticaKit::UIKitFromCpp::IsTablet()) { + if (BallisticaKit::UIKitFromCpp::isTablet()) { // if (base::AppleUtils::IsTablet()) { return UIScale::kMedium; } else { @@ -186,7 +186,7 @@ void CorePlatformApple::EmitPlatformLog(const std::string& name, LogLevel level, auto CorePlatformApple::DoGetDataDirectoryMonolithicDefault() -> std::string { #if BA_XCODE_BUILD - return BallisticaKit::FromCpp::GetResourcesPath(); + return BallisticaKit::FromCpp::getResourcesPath(); #else // Fall back to default. return CorePlatform::DoGetDataDirectoryMonolithicDefault(); @@ -267,7 +267,8 @@ void CorePlatformApple::FreeTextTexture(void* tex) { void CorePlatformApple::SubmitScore(const std::string& game, const std::string& version, int64_t score) { #if BA_USE_GAME_CENTER - base::AppleUtils::SubmitScore(game, version, score); + BallisticaKit::GameCenterContext::submitScore(game, version, score); + // base::AppleUtils::SubmitScore(game, version, score); #else CorePlatform::SubmitScore(game, version, score); #endif @@ -275,7 +276,8 @@ void CorePlatformApple::SubmitScore(const std::string& game, void CorePlatformApple::ReportAchievement(const std::string& achievement) { #if BA_USE_GAME_CENTER - base::AppleUtils::ReportAchievement(achievement); + BallisticaKit::GameCenterContext::reportAchievement(achievement); + // base::AppleUtils::ReportAchievement(achievement); #else CorePlatform::ReportAchievement(achievement); #endif @@ -283,7 +285,8 @@ void CorePlatformApple::ReportAchievement(const std::string& achievement) { void CorePlatformApple::ResetAchievements() { #if BA_USE_GAME_CENTER - base::AppleUtils::ResetGameCenterAchievements(); + BallisticaKit::GameCenterContext::resetAchievements(); + // base::AppleUtils::ResetGameCenterAchievements(); #else CorePlatform::ResetAchievements(); #endif @@ -292,7 +295,8 @@ void CorePlatformApple::ResetAchievements() { auto CorePlatformApple::HaveLeaderboard(const std::string& game, const std::string& config) -> bool { #if BA_USE_GAME_CENTER - return base::AppleUtils::HaveGameCenterLeaderboard(game, config); + return BallisticaKit::GameCenterContext::haveLeaderboard(game, config); + // return base::AppleUtils::HaveGameCenterLeaderboard(game, config); #else return CorePlatform::HaveLeaderboard(game, config); #endif @@ -302,7 +306,8 @@ void CorePlatformApple::ShowOnlineScoreUI(const std::string& show, const std::string& game, const std::string& game_version) { #if BA_USE_GAME_CENTER - base::AppleUtils::ShowOnlineScoreUI(show, game, game_version); + BallisticaKit::GameCenterContext::showOnlineScoreUI(show, game, game_version); + // base::AppleUtils::ShowOnlineScoreUI(show, game, game_version); #else CorePlatform::ShowOnlineScoreUI(show, game, game_version); #endif @@ -324,13 +329,14 @@ void CorePlatformApple::ShowOnlineScoreUI(const std::string& show, // #endif // } -void CorePlatformApple::GameCenterLogin() { -#if BA_USE_GAME_CENTER - base::AppleUtils::DoGameCenterLogin(); -#else - CorePlatform::GameCenterLogin(); -#endif -} +// void CorePlatformApple::GameCenterLogin() { +// #if BA_USE_GAME_CENTER +// BallisticaKit::GameCenterContext::signIn(); +// // base::AppleUtils::DoGameCenterLogin(); +// #else +// CorePlatform::GameCenterLogin(); +// #endif +// } auto CorePlatformApple::IsOSPlayingMusic() -> bool { #if BA_XCODE_BUILD @@ -345,7 +351,7 @@ auto CorePlatformApple::IsOSPlayingMusic() -> bool { void CorePlatformApple::OpenFileExternally(const std::string& path) { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - BallisticaKit::CocoaFromCpp::OpenFileExternally(path); + BallisticaKit::CocoaFromCpp::openFileExternally(path); #else CorePlatform::OpenFileExternally(path); #endif @@ -353,7 +359,7 @@ void CorePlatformApple::OpenFileExternally(const std::string& path) { void CorePlatformApple::OpenDirExternally(const std::string& path) { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - BallisticaKit::CocoaFromCpp::OpenDirExternally(path); + BallisticaKit::CocoaFromCpp::openDirExternally(path); #else CorePlatform::OpenDirExternally(path); #endif @@ -361,7 +367,7 @@ void CorePlatformApple::OpenDirExternally(const std::string& path) { void CorePlatformApple::MacMusicAppInit() { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - BallisticaKit::CocoaFromCpp::MacMusicAppInit(); + BallisticaKit::CocoaFromCpp::macMusicAppInit(); // base::AppleUtils::MacMusicAppInit(); #else CorePlatform::MacMusicAppInit(); @@ -369,7 +375,7 @@ void CorePlatformApple::MacMusicAppInit() { } auto CorePlatformApple::MacMusicAppGetVolume() -> int { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - return BallisticaKit::CocoaFromCpp::MacMusicAppGetVolume(); + return BallisticaKit::CocoaFromCpp::macMusicAppGetVolume(); // return static_cast(base::AppleUtils::MacMusicAppGetVolume()); #else return CorePlatform::MacMusicAppGetVolume(); @@ -377,7 +383,7 @@ auto CorePlatformApple::MacMusicAppGetVolume() -> int { } void CorePlatformApple::MacMusicAppSetVolume(int volume) { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - return BallisticaKit::CocoaFromCpp::MacMusicAppSetVolume(volume); + return BallisticaKit::CocoaFromCpp::macMusicAppSetVolume(volume); // base::AppleUtils::MacMusicAppSetVolume(volume); #else CorePlatform::MacMusicAppSetVolume(volume); @@ -386,7 +392,7 @@ void CorePlatformApple::MacMusicAppSetVolume(int volume) { void CorePlatformApple::MacMusicAppStop() { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - return BallisticaKit::CocoaFromCpp::MacMusicAppStop(); + return BallisticaKit::CocoaFromCpp::macMusicAppStop(); // base::AppleUtils::MacMusicAppStop(); #else CorePlatform::MacMusicAppStop(); @@ -396,7 +402,7 @@ void CorePlatformApple::MacMusicAppStop() { auto CorePlatformApple::MacMusicAppPlayPlaylist(const std::string& playlist) -> bool { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - return BallisticaKit::CocoaFromCpp::MacMusicAppPlayPlaylist(playlist); + return BallisticaKit::CocoaFromCpp::macMusicAppPlayPlaylist(playlist); // return base::AppleUtils::MacMusicAppPlayPlaylist(playlist.c_str()); #else return CorePlatform::MacMusicAppPlayPlaylist(playlist); @@ -405,7 +411,7 @@ auto CorePlatformApple::MacMusicAppPlayPlaylist(const std::string& playlist) auto CorePlatformApple::MacMusicAppGetPlaylists() -> std::list { #if BA_OSTYPE_MACOS && BA_XCODE_BUILD - BallisticaKit::CocoaFromCpp::MacMusicAppGetPlaylists(); + BallisticaKit::CocoaFromCpp::macMusicAppGetPlaylists(); // mac_music_app_playlists_.clear(); // mac_music_app_playlists_.push_back("foof"); // mac_music_app_playlists_.push_back("barf"); @@ -443,7 +449,7 @@ auto CorePlatformApple::GetSubplatformName() -> std::string { auto CorePlatformApple::GetLocale() -> std::string { #if BA_XCODE_BUILD if (!locale_.has_value()) { - locale_ = std::string(BallisticaKit::FromCpp::GetLocaleString()); + locale_ = std::string(BallisticaKit::FromCpp::getLocaleString()); } return *locale_; #else diff --git a/src/ballistica/core/platform/apple/core_platform_apple.h b/src/ballistica/core/platform/apple/core_platform_apple.h index 13af2ba8..3d8bc6dd 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.h +++ b/src/ballistica/core/platform/apple/core_platform_apple.h @@ -44,7 +44,7 @@ class CorePlatformApple : public CorePlatform { void ShowOnlineScoreUI(const std::string& show, const std::string& game, const std::string& game_version) override; void ResetAchievements() override; - void GameCenterLogin() override; + // void GameCenterLogin() override; auto IsOSPlayingMusic() -> bool override; void OpenFileExternally(const std::string& path) override; void OpenDirExternally(const std::string& path) override; diff --git a/src/ballistica/core/platform/core_platform.cc b/src/ballistica/core/platform/core_platform.cc index 322a06d6..e20c5155 100644 --- a/src/ballistica/core/platform/core_platform.cc +++ b/src/ballistica/core/platform/core_platform.cc @@ -740,7 +740,7 @@ void CorePlatform::ResetAchievements() { Log(LogLevel::kError, "ResetAchievements() unimplemented"); } -void CorePlatform::GameCenterLogin() { throw Exception(); } +// void CorePlatform::GameCenterLogin() { throw Exception(); } void CorePlatform::RunEvents() {} diff --git a/src/ballistica/core/platform/core_platform.h b/src/ballistica/core/platform/core_platform.h index 98ec4857..d57bcb8b 100644 --- a/src/ballistica/core/platform/core_platform.h +++ b/src/ballistica/core/platform/core_platform.h @@ -239,7 +239,7 @@ class CorePlatform { virtual void SignInV1(const std::string& account_type); virtual void SignOutV1(); - virtual void GameCenterLogin(); + // virtual void GameCenterLogin(); virtual void V1LoginDidChange(); /// Returns the ID to use for the device account. diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 30eefd20..c60fe6e0 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 = 21570; +const int kEngineBuildNumber = 21578; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/tools/bacommon/login.py b/tools/bacommon/login.py index 2d6e5053..1c32775e 100644 --- a/tools/bacommon/login.py +++ b/tools/bacommon/login.py @@ -11,6 +11,12 @@ if TYPE_CHECKING: pass +# NOTE TO SELF: +# Whenever adding login types here, make sure to update all +# basn nodes before trying to send values through to bamaster, +# as they need to be extractable by basn en route. + + class LoginType(Enum): """Types of logins available.""" diff --git a/tools/batools/project/_checks.py b/tools/batools/project/_checks.py index 6de16e06..3955fa22 100755 --- a/tools/batools/project/_checks.py +++ b/tools/batools/project/_checks.py @@ -590,4 +590,8 @@ def check_misc(self: ProjectUpdater) -> None: if ( '// V2 Master Server:\n' '\n' '// PROD\n' '#if 1\n' ) not in msconfig: - raise CleanError('Not using prod v2 master server.') + if ( + os.environ.get('BA_ALLOW_NON_PROD_V2_MASTER_SERVER', '0') + != '1' + ): + raise CleanError('Not using prod v2 master server.') diff --git a/tools/batools/xcodeproject.py b/tools/batools/xcodeproject.py index 54afaae9..3a15fcad 100644 --- a/tools/batools/xcodeproject.py +++ b/tools/batools/xcodeproject.py @@ -424,7 +424,7 @@ class Updater: f'{self.pnameu} macOS Steam', ] # A few things only for AppStore bound builds. - if filename == 'StoreKitContext.swift': + if filename in {'StoreKitContext.swift', 'GameCenterContext.swift'}: return [ f'{self.pnameu} iOS', f'{self.pnameu} tvOS', diff --git a/tools/efro/error.py b/tools/efro/error.py index f2045ce9..7f902162 100644 --- a/tools/efro/error.py +++ b/tools/efro/error.py @@ -107,7 +107,7 @@ class AuthenticationError(Exception): def is_urllib_communication_error(exc: BaseException, url: str | None) -> bool: """Is the provided exception from urllib a communication-related error? - Url, if provided can provide extra context for when to treat an error + Url, if provided, can provide extra context for when to treat an error as such an error. This should be passed an exception which resulted from opening or diff --git a/tools/efro/message/_receiver.py b/tools/efro/message/_receiver.py index 6659f76b..f8c38783 100644 --- a/tools/efro/message/_receiver.py +++ b/tools/efro/message/_receiver.py @@ -310,7 +310,9 @@ class MessageReceiver: msgtype.__qualname__, ) else: - logging.exception('Error in efro.message handling.') + logging.exception( + 'Error handling raw efro.message. msg=%s', msg + ) return rstr def handle_raw_message_async( @@ -367,7 +369,12 @@ class MessageReceiver: msgtype.__qualname__, ) else: - logging.exception('Error in efro.message handling.') + logging.exception( + 'Error handling raw async efro.message.' + ' msgtype=%s msg_decoded=%s.', + msgtype, + msg_decoded, + ) return rstr async def _handle_raw_message_async( diff --git a/tools/efrotools/pybuild.py b/tools/efrotools/pybuild.py index e561a314..79a6dd7b 100644 --- a/tools/efrotools/pybuild.py +++ b/tools/efrotools/pybuild.py @@ -14,7 +14,7 @@ from efrotools import readfile, writefile, replace_exact # Python version we build here (not necessarily same as we use in repo). PY_VER_ANDROID = '3.11' -PY_VER_EXACT_ANDROID = '3.11.5' +PY_VER_EXACT_ANDROID = '3.11.6' PY_VER_APPLE = '3.11' PY_VER_EXACT_APPLE = '3.11.5' @@ -36,25 +36,25 @@ VERSION_MIN_TVOS = '9.0' # See https://stackoverflow.com/questions/74059978/ # why-is-lldb-generating-exc-bad-instruction-with-user-compiled-library-on-macos # -# For now will try to ride out this LTS version as long as possible. -OPENSSL_VER_APPLE = '3.0.10' -OPENSSL_VER_ANDROID = '3.0.10' +# For now will try to ride out this 3.0 LTS version as long as possible. +OPENSSL_VER_APPLE = '3.0.12' +OPENSSL_VER_ANDROID = '3.0.12' LIBFFI_VER_APPLE = '3.4.4' BZIP2_VER_APPLE = '1.0.8' -XZ_VER_APPLE = '5.4.4' +XZ_VER_APPLE = '5.4.5' # Android repo doesn't seem to be getting updated much so manually # bumping various versions to keep things up to date. ZLIB_VER_ANDROID = '1.3' -XZ_VER_ANDROID = '5.4.4' +XZ_VER_ANDROID = '5.4.5' BZIP2_VER_ANDROID = '1.0.8' GDBM_VER_ANDROID = '1.23' LIBFFI_VER_ANDROID = '3.4.4' -LIBUUID_VER_ANDROID = ('2.38', '2.38.1') -NCURSES_VER_ANDROID = '6.3' +LIBUUID_VER_ANDROID = ('2.39', '2.39.2') +NCURSES_VER_ANDROID = '6.4' READLINE_VER_ANDROID = '8.2' -SQLITE_VER_ANDROID = ('2023', '3430000') +SQLITE_VER_ANDROID = ('2023', '3440000') # Filenames we prune from Python lib dirs in source repo to cut down on # size. From 8fd4c45b85e676abc795aa083c6e0e9c9b058dcd Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 9 Nov 2023 15:43:25 -0800 Subject: [PATCH 24/25] added native-review-request to replace old hand-rolled one --- .efrocachemap | 56 +++++++++---------- CHANGELOG.md | 2 +- src/assets/ba_data/python/babase/__init__.py | 4 ++ src/assets/ba_data/python/babase/_login.py | 2 +- src/assets/ba_data/python/baenv.py | 2 +- src/assets/ba_data/python/bauiv1/__init__.py | 4 ++ .../ba_data/python/bauiv1lib/specialoffer.py | 20 +++++-- .../base/app_adapter/app_adapter.cc | 9 +++ src/ballistica/base/app_adapter/app_adapter.h | 12 +++- .../base/app_adapter/app_adapter_apple.cc | 17 ++++++ .../base/app_adapter/app_adapter_apple.h | 2 + .../python/methods/python_methods_misc.cc | 41 ++++++++++++++ src/ballistica/shared/ballistica.cc | 2 +- 13 files changed, 134 insertions(+), 39 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index abd945a9..231e23a9 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "64292918215b9d3e6fc3d470db4c92b1", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "84c840b57ed000407a8b34e9c5015b54", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "bc6fc246d6e0551a18f161183ee89ad5", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "bc87c32aee50fbc67ca0531c536e7f10", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "bcf55f1a1e8e317dc355ebf2ea301d10", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0ad6f5cea06d4c0754d1763610c7be90", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2c1c99e0850749741e23e5db7fb45b22", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "960dee8cee9d2fe500629583668eee14", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "1eb609e4f8ba0cf740d9c7b8cbbbf4d3", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "80418b80ad17e283a65b85142b0b490d", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "1527e8235b808c6bdf5f2850875d1843", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0e8c85459f90cc0a1355aecad5b5306e", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "6c718c797dfaf2b85ce7bd5d6c7f9d8a", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "5eefb534d193a9fa06b413a9d5a05969", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "2dedf11d5e4ffa9ec02eb6025a9b3460", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "3a3075f5f28cbfe9cd302e9c371b9ed4", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "275342bb44f1f5edde893a9775eb0130", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "4866c1b244b493b99da24aa1bc965bb7", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "c2181a4564b675762f89e2bc3314332f", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "ac4a176d550b219aa3cb1f46ad738a66", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6b30c7563c501435ee9c9d7584124a3d", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "cde906637ab2fd52c7c6752d20c8e5a1", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "fa4c9dddd31d0ae5b5537a70415679b4", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "0ea542deeb3be561b45805e31fff618d", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "09ca80b37e18c24e705e33409fb14cf7", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "057150cf0c86920df2ceba78a0413e15", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8b9db0a31ad3186b24bf57700285b7ed", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "1252e817e42616e35357e4aa7f30c1f3", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0fa88240fcf21fb4a8030212731c5c47", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "8fca31f8837dfb689b9c2b8ee0529fab", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "15f7e176817e7b509567764b98ef8a1a", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "ac68b0113512aaa47d91a3a585124181", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f5caed9be4b5f59aa4a4bffb6d2ba7d7", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "578bdfea257f3913c82fa200c858197a", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "a2fea38fdebf4c687249758c63cae3c7", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "866c89a141e141340de210cb5b6025d6", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e79d9be3f30cd6aee49ca99cb246a1fd", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "1ea429286200a9db50aa91233c61d13a", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "eb37b75b93f6faa872b270d6e88c3a18", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "c330e1a356877ead65e039dfb59f46ab", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "f812111f1eb4ea76e99558305ce3980f", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "c16c1b360b27850f1ac4d3dc55194b0a", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "f812111f1eb4ea76e99558305ce3980f", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "380d456bc409849174a36c5d2f61aa1b", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "4fae9b286a6d1c5c729c49c483c1422a", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "380d456bc409849174a36c5d2f61aa1b", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "5bee4eaf62c401c65c94513eb3ac18fd", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "69438fa6a8c70381f355ff3fb94c5a13", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "ad27b9e1e63733ba10c34ae5fd8246df", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "5b1b8ac6e3022b633477c3989957fa81", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "d2364a2d49ba3268691fb7e1134c9359", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "a6436bf9a9fb5531b837d9be20c2834b", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "a502732d3df4e7ff6b5086cb1f9bbb08", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "5470de767289dca9b88678e69a1ecca4", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "8cba13ddabc6c29b7360483d35e83b4c", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "9f3a011a47e4b924af06bf22d12eeedd", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "63272196776f495960f4a837d93e1bd5", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "9944dc011d9efc9525e728277c278d29", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a768ba2d0cc92b4e8a6362bd49cf0a1e", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "67b3ba3f7e7bb1b38f03ea28792ffab5", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "763663746aa11e24970ac1de4c579310", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "8b3169ff64c31243ba401703d95ae0e0", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", diff --git a/CHANGELOG.md b/CHANGELOG.md index fd4d6073..3aacb4ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21578, api 8, 2023-11-09) +### 1.7.28 (build 21581, api 8, 2023-11-09) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/src/assets/ba_data/python/babase/__init__.py b/src/assets/ba_data/python/babase/__init__.py index a511d570..3b0c723a 100644 --- a/src/assets/ba_data/python/babase/__init__.py +++ b/src/assets/ba_data/python/babase/__init__.py @@ -74,6 +74,8 @@ from _babase import ( music_player_set_volume, music_player_shutdown, music_player_stop, + native_review_request, + native_review_request_supported, native_stack_trace, print_load_info, pushcall, @@ -276,6 +278,8 @@ __all__ = [ 'music_player_set_volume', 'music_player_shutdown', 'music_player_stop', + 'native_review_request', + 'native_review_request_supported', 'native_stack_trace', 'NodeNotFoundError', 'normalized_color', diff --git a/src/assets/ba_data/python/babase/_login.py b/src/assets/ba_data/python/babase/_login.py index 084c2730..63cbd450 100644 --- a/src/assets/ba_data/python/babase/_login.py +++ b/src/assets/ba_data/python/babase/_login.py @@ -17,7 +17,7 @@ if TYPE_CHECKING: from typing import Callable -DEBUG_LOG = True +DEBUG_LOG = False class LoginAdapter: diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index dc2f986b..b16645ca 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21578 +TARGET_BALLISTICA_BUILD = 21581 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bauiv1/__init__.py b/src/assets/ba_data/python/bauiv1/__init__.py index 535d6719..9ff875a9 100644 --- a/src/assets/ba_data/python/bauiv1/__init__.py +++ b/src/assets/ba_data/python/bauiv1/__init__.py @@ -66,6 +66,8 @@ from babase import ( lock_all_input, LoginAdapter, Lstr, + native_review_request, + native_review_request_supported, NotFoundError, Permission, Plugin, @@ -191,6 +193,8 @@ __all__ = [ 'LoginAdapter', 'Lstr', 'Mesh', + 'native_review_request', + 'native_review_request_supported', 'NotFoundError', 'open_file_externally', 'open_url', diff --git a/src/assets/ba_data/python/bauiv1lib/specialoffer.py b/src/assets/ba_data/python/bauiv1lib/specialoffer.py index 7fe7729c..af6621a8 100644 --- a/src/assets/ba_data/python/bauiv1lib/specialoffer.py +++ b/src/assets/ba_data/python/bauiv1lib/specialoffer.py @@ -518,10 +518,13 @@ def show_offer() -> bool: assert plus is not None app = bui.app - assert app.classic is not None + if app.classic is None: + raise RuntimeError( + 'Classic feature-set is required to show offers.' + ) - # Space things out a bit so we don't hit the poor user with an ad and - # then an in-game offer. + # Space things out a bit so we don't hit the poor user with an + # ad and then an in-game offer. has_been_long_enough_since_ad = True if app.classic.ads.last_ad_completion_time is not None and ( bui.apptime() - app.classic.ads.last_ad_completion_time < 30.0 @@ -532,8 +535,9 @@ def show_offer() -> bool: app.classic.special_offer is not None and has_been_long_enough_since_ad ): - # Special case: for pro offers, store this in our prefs so we - # can re-show it if the user kills us (set phasers to 'NAG'!!!). + # Special case: for pro offers, store this in our prefs so + # we can re-show it if the user kills us (set phasers to + # 'NAG'!!!). if app.classic.special_offer.get('item') == 'pro_fullprice': cfg = app.config cfg['pendingSpecialOffer'] = { @@ -543,7 +547,11 @@ def show_offer() -> bool: cfg.commit() if app.classic.special_offer['item'] == 'rating': - feedback.ask_for_rating() + # Go with a native thing if we've got one. + if bui.native_review_request_supported(): + bui.native_review_request() + else: + feedback.ask_for_rating() else: SpecialOfferWindow(app.classic.special_offer) diff --git a/src/ballistica/base/app_adapter/app_adapter.cc b/src/ballistica/base/app_adapter/app_adapter.cc index 085dae67..5f0a8b59 100644 --- a/src/ballistica/base/app_adapter/app_adapter.cc +++ b/src/ballistica/base/app_adapter/app_adapter.cc @@ -308,4 +308,13 @@ auto AppAdapter::GetKeyName(int keycode) -> std::string { return "?"; } +auto AppAdapter::NativeReviewRequestSupported() -> bool { return false; } + +void AppAdapter::NativeReviewRequest() { + BA_PRECONDITION(NativeReviewRequestSupported()); + PushMainThreadCall([this] { DoNativeReviewRequest(); }); +} + +void AppAdapter::DoNativeReviewRequest() { FatalError("Fixme unimplemented."); } + } // namespace ballistica::base diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index c2ae868c..7ae86045 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -230,9 +230,15 @@ class AppAdapter { /// context. By default this is simply the main thread. virtual void DoPushGraphicsContextRunnable(Runnable* runnable); - // Return a name for a ballistica keyboard keycode. + /// Return a name for a ballistica keyboard keycode. virtual auto GetKeyName(int keycode) -> std::string; + /// Return whether there is a native 'review-this-app' prompt. + virtual auto NativeReviewRequestSupported() -> bool; + + /// Asynchronously kick off a native review request. + void NativeReviewRequest(); + protected: virtual ~AppAdapter(); @@ -241,6 +247,10 @@ class AppAdapter { virtual void DoClipboardSetText(const std::string& text); virtual auto DoClipboardGetText() -> std::string; + /// Override to implement native review requests. Will be called in the + /// main thread. + virtual void DoNativeReviewRequest(); + private: void OnAppSuspend_(); void OnAppUnsuspend_(); diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.cc b/src/ballistica/base/app_adapter/app_adapter_apple.cc index cccdba35..885f8092 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -297,6 +297,23 @@ auto AppAdapterApple::GetKeyName(int keycode) -> std::string { return MinSDL_GetKeyName(keycode); } +auto AppAdapterApple::NativeReviewRequestSupported() -> bool { + // StoreKit currently supports this everywhere except tvOS. + if (g_buildconfig.xcode_build() && g_buildconfig.use_store_kit() + && !g_buildconfig.ostype_tvos()) { + return true; + } + return false; +} + +void AppAdapterApple::DoNativeReviewRequest() { +#if BA_XCODE_BUILD && BA_USE_STORE_KIT && !BA_OSTYPE_TVOS + BallisticaKit::StoreKitContext::requestReview(); +#else + FatalError("This should not be getting called."); +#endif +} + } // namespace ballistica::base #endif // BA_XCODE_BUILD diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.h b/src/ballistica/base/app_adapter/app_adapter_apple.h index a7fee4a3..036bf820 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.h +++ b/src/ballistica/base/app_adapter/app_adapter_apple.h @@ -46,6 +46,7 @@ class AppAdapterApple : public AppAdapter { auto GetKeyRepeatDelay() -> float override; auto GetKeyRepeatInterval() -> float override; auto GetKeyName(int keycode) -> std::string override; + auto NativeReviewRequestSupported() -> bool override; protected: void DoPushMainThreadRunnable(Runnable* runnable) override; @@ -60,6 +61,7 @@ class AppAdapterApple : public AppAdapter { auto DoClipboardHasText() -> bool override; void DoClipboardSetText(const std::string& text) override; auto DoClipboardGetText() -> std::string override; + void DoNativeReviewRequest() override; private: class ScopedAllowGraphics_; diff --git a/src/ballistica/base/python/methods/python_methods_misc.cc b/src/ballistica/base/python/methods/python_methods_misc.cc index 0ce7625c..bf4783e2 100644 --- a/src/ballistica/base/python/methods/python_methods_misc.cc +++ b/src/ballistica/base/python/methods/python_methods_misc.cc @@ -1724,6 +1724,45 @@ static PyMethodDef PyUsingGameCenterDef = { "(internal)", }; +// --------------------- native_review_request_supported ----------------------- + +static auto PyNativeReviewRequestSupported(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + if (g_base->app_adapter->NativeReviewRequestSupported()) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PyNativeReviewRequestSupportedDef = { + "native_review_request_supported", // name + (PyCFunction)PyNativeReviewRequestSupported, // method + METH_NOARGS, // flags + + "native_review_request_supported() -> bool\n" + "\n" + "(internal)", +}; + +// -------------------------- native_review_request ---------------------------- + +static auto PyNativeReviewRequest(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + g_base->app_adapter->NativeReviewRequest(); + Py_RETURN_NONE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PyNativeReviewRequestDef = { + "native_review_request", // name + (PyCFunction)PyNativeReviewRequest, // method + METH_NOARGS, // flags + + "native_review_request() -> None\n" + "\n" + "(internal)", +}; // ----------------------------------------------------------------------------- auto PythonMethodsMisc::GetMethods() -> std::vector { @@ -1789,6 +1828,8 @@ auto PythonMethodsMisc::GetMethods() -> std::vector { PyAssetLoadsAllowedDef, PyUsingGooglePlayGameServicesDef, PyUsingGameCenterDef, + PyNativeReviewRequestSupportedDef, + PyNativeReviewRequestDef, }; } diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index c60fe6e0..66ae5776 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 = 21578; +const int kEngineBuildNumber = 21581; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; From 53002639bdd1279e8a09de30b765f78be374229b Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 9 Nov 2023 18:09:18 -0800 Subject: [PATCH 25/25] tidying --- .efrocachemap | 60 ++++++------- CHANGELOG.md | 2 +- .../ba_data/python/babase/_accountv2.py | 10 --- src/assets/ba_data/python/baenv.py | 2 +- .../python/bauiv1lib/account/settings.py | 85 +++++++++++++++++++ .../base/graphics/gl/renderer_gl.cc | 8 +- src/ballistica/shared/ballistica.cc | 2 +- 7 files changed, 123 insertions(+), 46 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 231e23a9..62b7c7dd 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -430,12 +430,12 @@ "build/assets/ba_data/data/languages/czech.json": "93c5fe0d884d95435da6c675f64e30e0", "build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e", "build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e", - "build/assets/ba_data/data/languages/english.json": "2fa464db3fe6bffa16a50c18dfbdc1a6", + "build/assets/ba_data/data/languages/english.json": "fe32cbe79483153db283e363da039a7a", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/filipino.json": "afbda3adf14555e1567ee63c32e340e7", "build/assets/ba_data/data/languages/french.json": "49ff6d211537b8003b8241438dca661d", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", - "build/assets/ba_data/data/languages/gibberish.json": "1ade258922bcee1544c9c6015eeb8324", + "build/assets/ba_data/data/languages/gibberish.json": "00a9f70bccdfa407043e69a42e5b944c", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6b30c7563c501435ee9c9d7584124a3d", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "cde906637ab2fd52c7c6752d20c8e5a1", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "fa4c9dddd31d0ae5b5537a70415679b4", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "0ea542deeb3be561b45805e31fff618d", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "09ca80b37e18c24e705e33409fb14cf7", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "057150cf0c86920df2ceba78a0413e15", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8b9db0a31ad3186b24bf57700285b7ed", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "1252e817e42616e35357e4aa7f30c1f3", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0fa88240fcf21fb4a8030212731c5c47", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "8fca31f8837dfb689b9c2b8ee0529fab", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "15f7e176817e7b509567764b98ef8a1a", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "ac68b0113512aaa47d91a3a585124181", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f5caed9be4b5f59aa4a4bffb6d2ba7d7", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "578bdfea257f3913c82fa200c858197a", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "a2fea38fdebf4c687249758c63cae3c7", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "866c89a141e141340de210cb5b6025d6", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e79d9be3f30cd6aee49ca99cb246a1fd", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "1ea429286200a9db50aa91233c61d13a", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "eb37b75b93f6faa872b270d6e88c3a18", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "c330e1a356877ead65e039dfb59f46ab", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "a2c1b1a31a42a24e5f2188983ff97c0e", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "8d146105a6df3376ec2f575401f29ec2", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "5e0e63f5fea108212bfb35c4fdc05dd2", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "85797e98f9a21f168a986b7eb3219688", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "95bc2213d2fb30e8248ddf06764a3663", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "f09d7055120d50f37b605ff3a4cbf61d", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8f23de3825b9e9cf6ed4715125aeb956", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "f7b88875b37a39db57d77bebb05f822f", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0b719dc609de364814299a5baa9a5b0b", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "07aa53835bdd2d2a4113d61a89a7da1d", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "1a1c4db580157e38effe4b81c35aca52", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "1e44d0a7160d442b1eb4d348952b0d06", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "a85fcf6a12483bde66559dbdce88b730", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "d53e31771fe31615c66bd0d1e1292b2f", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "e1804380d5ebec56f8f0af2e2547316e", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "d9665cdf870247b6d8e9475419b04038", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "0cac36823713816d03a6922b96cecd0a", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "bd741122315ced7b703de1fed2d372cd", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "f11edd5da3ce1a3e804bfc61b7ca9c1e", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "3d647f5f63b3ac3900903cf72496cef2", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "f812111f1eb4ea76e99558305ce3980f", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "c16c1b360b27850f1ac4d3dc55194b0a", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "f812111f1eb4ea76e99558305ce3980f", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "380d456bc409849174a36c5d2f61aa1b", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "4fae9b286a6d1c5c729c49c483c1422a", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "380d456bc409849174a36c5d2f61aa1b", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "8cba13ddabc6c29b7360483d35e83b4c", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "9f3a011a47e4b924af06bf22d12eeedd", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "63272196776f495960f4a837d93e1bd5", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "9944dc011d9efc9525e728277c278d29", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a768ba2d0cc92b4e8a6362bd49cf0a1e", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "67b3ba3f7e7bb1b38f03ea28792ffab5", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "763663746aa11e24970ac1de4c579310", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "8b3169ff64c31243ba401703d95ae0e0", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "93f75d31841fe18d6bc66681c99b05a1", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "cd6500ab076fa3bdff92fc8b65bc1d64", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "0dcde1146f11e4cfd3d609f4330f7a9a", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "663e6ed62de0f857fd9a4de57067dbd3", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "ae28db2f400d3b778d4a011a72339757", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "3b13cdbaf70cf43d0a14b7a2dd744945", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "54798340a1dfedaa9052aeee180e28ff", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "18b635d88c074261a3be4f45e8244340", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aacb4ae..650440be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21581, api 8, 2023-11-09) +### 1.7.28 (build 21583, api 8, 2023-11-09) - Massively cleaned up code related to rendering and window systems (OpenGL, SDL, etc). This code had been growing into a nasty tangle for 15 years diff --git a/src/assets/ba_data/python/babase/_accountv2.py b/src/assets/ba_data/python/babase/_accountv2.py index ab76ae1c..d1baa52d 100644 --- a/src/assets/ba_data/python/babase/_accountv2.py +++ b/src/assets/ba_data/python/babase/_accountv2.py @@ -427,16 +427,6 @@ class AccountV2Handle: workspaceid: str | None logins: dict[LoginType, str] - # def __init__(self) -> None: - - # self.workspacename: str | None = None - # self.workspaceid: str | None = None - - # # Login types and their display-names associated with this account. - # self.logins: dict[LoginType, str] = {} - - # self.accountid: str = - def __enter__(self) -> None: """Support for "with" statement. diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index b16645ca..c784b9a5 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21581 +TARGET_BALLISTICA_BUILD = 21583 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bauiv1lib/account/settings.py b/src/assets/ba_data/python/bauiv1lib/account/settings.py index 94502e91..52d9a7e9 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/settings.py +++ b/src/assets/ba_data/python/bauiv1lib/account/settings.py @@ -231,6 +231,8 @@ class AccountSettingsWindow(bui.Window): plus = bui.app.plus assert plus is not None + via_lines: list[str] = [] + primary_v2_account = plus.accounts.primary v1_state = plus.get_v1_account_state() @@ -259,6 +261,40 @@ class AccountSettingsWindow(bui.Window): show_signed_in_as = self._v1_signed_in signed_in_as_space = 95.0 + # To reduce confusion about the whole V2 account situation for + # people used to seeing their Google Play Games or Game Center + # account name and icon and whatnot, let's show those underneath + # the V2 tag to help communicate that they are in fact logged in + # through that account. + via_space = 25.0 + if show_signed_in_as and bui.app.plus is not None: + primary_account = bui.app.plus.accounts.primary + if primary_account is not None: + # Show Google Play Games account name if the current account + # has such a login attached. + lname = primary_account.logins.get(LoginType.GPGS) + if lname is not None: + icontxt = bui.charstr( + bui.SpecialChar.GOOGLE_PLAY_GAMES_LOGO + ) + via_lines.append(f'{icontxt}{lname}') + + # Show Game Center account name if the current account + # has such a login attached. + lname = primary_account.logins.get(LoginType.GAME_CENTER) + if lname is not None: + icontxt = bui.charstr(bui.SpecialChar.GAME_CENTER_LOGO) + via_lines.append(f'{icontxt}{lname}') + + # TEMP TESTING + if bool(False): + icontxt = bui.charstr(bui.SpecialChar.GAME_CENTER_LOGO) + via_lines.append(f'{icontxt}FloofDibble') + icontxt = bui.charstr( + bui.SpecialChar.GOOGLE_PLAY_GAMES_LOGO + ) + via_lines.append(f'{icontxt}StinkBobble') + show_sign_in_benefits = not self._v1_signed_in sign_in_benefits_space = 80.0 @@ -366,6 +402,7 @@ class AccountSettingsWindow(bui.Window): self._sub_height = 60.0 if show_signed_in_as: self._sub_height += signed_in_as_space + self._sub_height += via_space * len(via_lines) if show_signing_in_text: self._sub_height += signing_in_text_space if show_google_play_sign_in_button: @@ -485,6 +522,54 @@ class AccountSettingsWindow(bui.Window): v -= signed_in_as_space * 0.4 + for via in via_lines: + v -= via_space * 0.1 + sscale = 0.7 + swidth = ( + bui.get_string_width(via, suppress_warning=True) * sscale + ) + bui.textwidget( + parent=self._subcontainer, + position=(self._sub_width * 0.5, v), + size=(0, 0), + text=via, + scale=sscale, + color=(0.6, 0.6, 0.6), + flatness=1.0, + shadow=0.0, + h_align='center', + v_align='center', + ) + bui.textwidget( + parent=self._subcontainer, + position=(self._sub_width * 0.5 - swidth * 0.5 - 5, v), + size=(0, 0), + text=bui.Lstr( + value='(${VIA}', + subs=[('${VIA}', bui.Lstr(resource='viaText'))], + ), + scale=0.6, + color=(0.4, 0.6, 0.4, 0.5), + flatness=1.0, + shadow=0.0, + h_align='right', + v_align='center', + ) + bui.textwidget( + parent=self._subcontainer, + position=(self._sub_width * 0.5 + swidth * 0.5 + 10, v), + size=(0, 0), + text=')', + scale=0.6, + color=(0.4, 0.6, 0.4, 0.5), + flatness=1.0, + shadow=0.0, + h_align='right', + v_align='center', + ) + + v -= via_space * 0.9 + else: self._account_name_text = None self._account_name_what_is_text = None diff --git a/src/ballistica/base/graphics/gl/renderer_gl.cc b/src/ballistica/base/graphics/gl/renderer_gl.cc index b20b6e0f..c24db341 100644 --- a/src/ballistica/base/graphics/gl/renderer_gl.cc +++ b/src/ballistica/base/graphics/gl/renderer_gl.cc @@ -185,9 +185,11 @@ void RendererGL::CheckGLCapabilities_() { basestr = "OpenGL"; } - Log(LogLevel::kInfo, std::string("Using ") + basestr + " (vendor: " + vendor - + ", renderer: " + renderer - + ", version: " + version_str + ")."); + if (g_buildconfig.debug_build()) { + Log(LogLevel::kInfo, std::string("Using ") + basestr + " (vendor: " + vendor + + ", renderer: " + renderer + + ", version: " + version_str + ")."); + } // Build a vector of extensions. Newer GLs give us extensions as lists // already, but on older ones we may need to break a single string apart diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 66ae5776..40022420 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 = 21581; +const int kEngineBuildNumber = 21583; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8;