From 2d8b33ceeb72de667f2f027fa16657e61f3adcdb Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 16 Oct 2023 13:38:40 -0700 Subject: [PATCH 1/9] cleaning up fullscreen-toggling and other keyboard shortcuts --- .efrocachemap | 102 ++++++++-------- CHANGELOG.md | 5 +- src/assets/ba_data/python/babase/__init__.py | 10 +- src/assets/ba_data/python/babase/_app.py | 8 ++ src/assets/ba_data/python/babase/_hooks.py | 16 ++- src/assets/ba_data/python/baenv.py | 6 +- src/assets/ba_data/python/bauiv1/__init__.py | 10 +- .../python/bauiv1lib/settings/graphics.py | 38 +++--- .../base/app_adapter/app_adapter.cc | 31 ++++- src/ballistica/base/app_adapter/app_adapter.h | 24 +++- .../base/app_adapter/app_adapter_sdl.cc | 33 +++++- .../base/app_adapter/app_adapter_sdl.h | 4 +- src/ballistica/base/input/input.cc | 40 +++++-- src/ballistica/base/python/base_python.h | 2 + .../python/methods/python_methods_graphics.cc | 112 +++++++++++++++--- src/ballistica/shared/ballistica.cc | 2 +- src/meta/babasemeta/pyembed/binding_base.py | 2 + 17 files changed, 331 insertions(+), 114 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 665bb33f..2466070f 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": "992c5c5ce292132c4f011f39e0d13de8", + "build/assets/ba_data/data/langdata.json": "d21a1b7c9444ae7787944498f3ed6482", "build/assets/ba_data/data/languages/arabic.json": "d1f900ab5aa2433d402bd46ed1149cc7", "build/assets/ba_data/data/languages/belarussian.json": "e151808b6b4f6dc159cf55ee62adad3c", "build/assets/ba_data/data/languages/chinese.json": "8d889accdd49334591209bdaf6eaf02f", @@ -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": "b38d54aecf3ac47b8d8ca97d8bab3006", + "build/assets/ba_data/data/languages/english.json": "e70277fc6325126d3d893524c8df03c9", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/filipino.json": "347f38524816691170d266708fe25894", "build/assets/ba_data/data/languages/french.json": "d8527da977a563185de25ef02bacf826", - "build/assets/ba_data/data/languages/german.json": "549754d2a530d825200c6126be56df5c", - "build/assets/ba_data/data/languages/gibberish.json": "837423db378b3e7679683805826aa26e", + "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", + "build/assets/ba_data/data/languages/gibberish.json": "7863ceeedb1e87eef46f7769bae5f842", "build/assets/ba_data/data/languages/greek.json": "a65d78f912e9a89f98de004405167a6a", "build/assets/ba_data/data/languages/hindi.json": "88ee0cda537bab9ac827def5e236fe1a", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", @@ -447,12 +447,12 @@ "build/assets/ba_data/data/languages/polish.json": "e1a1a801851924748ad38fa68216439a", "build/assets/ba_data/data/languages/portuguese.json": "9fcd6b4da9e5d0dc0e337ab00b5debe2", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", - "build/assets/ba_data/data/languages/russian.json": "910cf653497654a16d5c4f067d6def22", + "build/assets/ba_data/data/languages/russian.json": "7f1689fff58321fdaa632cb9c45105df", "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": "0122b0b24aa111ab259af02bbae9b7b6", "build/assets/ba_data/data/languages/swedish.json": "77d671f10613291ebf9c71da66f18a18", - "build/assets/ba_data/data/languages/tamil.json": "b9d4b4e107456ea6420ee0f9d9d7a03e", + "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": "9d7e58c9062dc517c3779c255a9b3142", "build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2", @@ -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": "8ea626f6dd70d998ee77c58fffc51545", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "d7ad10904fe7c4d4555366ccb1feedcb", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a9eea92d521e97b1772b5e44b402ce8a", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "57043f40971d800d27ee6d646aae8d61", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "3e4009d7fa4b90abc526f56361ecab05", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "334cdc0688e66a1bc75cd05bae1729c7", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "95278d80378be5b61026253492cbfa70", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "0a3da8e5264a7b733960e83a0e8c4bba", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "a089d4aaa39e18553cf0a70a77b4cfcd", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "e66c4eceb79710b8fda2bfea781e241a", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "6b3021b9a7584da86bbb95324e81e851", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6fe90d50f905a0da9fa52c39a458d1e3", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "afc7ed826486aec82613832865177570", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "ae8b6dad770793188aad8e2966189bb3", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "7622dde1a021152cac42e7db3e803392", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "8a4b1e521bf668cc6ec6a65519defb12", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "9a69c0d4c9ae319595843b16f14795fc", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "89c02260fb4781f5e293658cecbb363f", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "3165d4230069c22300abfff8abf1d714", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "41e46dfdbb542e3e823f6aee87e93ac9", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "20cc128ff9d44f9d74e4301c6d49f48f", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "f93bc8f98ee31f39b54ab46264eccb22", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "20cc128ff9d44f9d74e4301c6d49f48f", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "f93bc8f98ee31f39b54ab46264eccb22", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "1565f3b227843827d692cb3ef65847b6", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "d8d74c6c40db43054ccc7d27920cfbfe", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "1565f3b227843827d692cb3ef65847b6", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "d8d74c6c40db43054ccc7d27920cfbfe", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "43bdfa8acd84e9cf2e443ce8e923c229", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "d935dc21becdfd65bec51c5f5b2fd770", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "43bdfa8acd84e9cf2e443ce8e923c229", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "d935dc21becdfd65bec51c5f5b2fd770", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "6d49ad39f194480da458b431405f5a2b", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c8715c85010ea431d7346f40f5421819", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "49775819d4ba9af15061080d17377a18", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c8715c85010ea431d7346f40f5421819", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "750c2964308cd3f3e5986fcda9a25706", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "772af7da6a115f53b0b3f6a4afd3baec", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "178c1a53a7ad50297aed68d0ca3a1476", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "b011bc2b6437995f2d33f5215b4ffa36", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a758a4f98336208381b093aacb735878", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "6c86545fab2327105114676a20ca5e68", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "f75525fdc9f7db4a81ca9bae6a79add5", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "2e297069baec404d43ccdb18abeef658", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "05edee29f50c1d6bee9d3de307248ea6", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "df3990491fab9ac0538e75f347683a94", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a7efd60daa1a52b0e30a7a9616cc727a", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "2b964e4df219ccf31d204c701abf8b6e", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "67845ed4ac3307559448f9f323e3408f", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "b5934ad96454b3fb945a388141166f17", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "cfec3ecd22fa9467a65f8878efa2b911", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "e748d9e8a1f9b9287194f03a5a9f66d2", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f3897d23722ab9cf60614dea1abace10", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "74881b34024a827de91dc4e302123548", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "82b5a5410419a738ffb1007f736644c2", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "f732999c2601cf656b850f5f3e9570f4", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "0da70003570c3f392a0f87a823c2adc3", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "1535ddde4b8532a412df37567a1a29a3", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "e04124a9110037eabe1aac45a98891db", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "c07e02b94aa9f50f21bb6571d3a2d5e5", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "ce594cf55f33b80664e5e2c9d59a4ba1", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "26e0fec05e2813fa3e41aa36e3b43df3", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "3957607929916c7ea7f8cde6487e2101", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "96680b806f2997e75904b4222a1e0536", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "80ff019ab0715f68dc4cae15c7a9fdab", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "bbe53e6685130822cbba276f63b76dcb", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "80ff019ab0715f68dc4cae15c7a9fdab", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "bbe53e6685130822cbba276f63b76dcb", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "0d0737d71a7efe201e5ebadeb5f12c71", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "895099e15bad328666f71869f6f09b79", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "0d0737d71a7efe201e5ebadeb5f12c71", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "895099e15bad328666f71869f6f09b79", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "79e38e7d6eb4a5810bbb22e94d4e87ee", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "2cf7ef381bc7408c21f4ea444815233e", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "79e38e7d6eb4a5810bbb22e94d4e87ee", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "2cf7ef381bc7408c21f4ea444815233e", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "5d457e3b58015c9da26a7911a6c8ed5a", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "70d5ec6b86c91c787a182da729737951", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "444861c2242f3f0b9e09046b6cbf0245", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "70d5ec6b86c91c787a182da729737951", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "4c37ef02c9d97ebf58e9cd4055b557a7", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "5450d7efd2aec4481be61a1315d78af2", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "42a5fefe21fdffdfb62a0f236b33193e", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "d8f2d5d50cfedfff5b1ce1c9c7c52ef4", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "f19d0d8db9b776291dc3bc99f402608e", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c1dea4974ce3723ded4391eca5ae2bfc", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "cf3bbe5f15e76197937e67cfaf2f0a32", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "2b8c93e04d1876a787b2a8befbbde004", "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": "ba8ce3ca3858b4c2d20db68f99b788b2", + "src/ballistica/base/mgen/pyembed/binding_base.inc": "bb96031e3f844704fcc9a0549a6d2c41", "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 21aade8c..fd8a507c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21465, api 8, 2023-10-14) +### 1.7.28 (build 21468, api 8, 2023-10-16) - 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 @@ -146,7 +146,8 @@ rates are high. - Added a proper graceful shutdown process for the audio server. This should result in fewer ugly pops and warning messages when the app is quit. - +- Tidied up some keyboard shortcuts to be more platform-appropriate. For + example, toggling fullscreen on Windows is now Alt+Enter or F11. ### 1.7.27 (build 21282, api 8, 2023-08-30) diff --git a/src/assets/ba_data/python/babase/__init__.py b/src/assets/ba_data/python/babase/__init__.py index fa542c74..9eb09af0 100644 --- a/src/assets/ba_data/python/babase/__init__.py +++ b/src/assets/ba_data/python/babase/__init__.py @@ -27,7 +27,10 @@ from _babase import ( apptime, apptimer, AppTimer, - can_toggle_fullscreen, + fullscreen_control_available, + fullscreen_control_get, + fullscreen_control_key_shortcut, + fullscreen_control_set, charstr, clipboard_get_text, clipboard_has_text, @@ -200,7 +203,10 @@ __all__ = [ 'apptimer', 'AppTimer', 'Call', - 'can_toggle_fullscreen', + 'fullscreen_control_available', + 'fullscreen_control_get', + 'fullscreen_control_key_shortcut', + 'fullscreen_control_set', 'charstr', 'clipboard_get_text', 'clipboard_has_text', diff --git a/src/assets/ba_data/python/babase/_app.py b/src/assets/ba_data/python/babase/_app.py index 84147e5d..ffd1f05d 100644 --- a/src/assets/ba_data/python/babase/_app.py +++ b/src/assets/ba_data/python/babase/_app.py @@ -895,10 +895,18 @@ class App: import asyncio # Spin and wait for anything blocking shutdown to complete. + starttime = _babase.apptime() _babase.lifecyclelog('shutdown-suppress wait begin') while _babase.shutdown_suppress_count() > 0: await asyncio.sleep(0.001) _babase.lifecyclelog('shutdown-suppress wait end') + duration = _babase.apptime() - starttime + if duration > 1.0: + logging.warning( + 'Shutdown-suppressions delayed shutdown longer than ideal ' + '(%.2f seconds).', + duration, + ) async def _fade_and_shutdown_graphics(self) -> None: import asyncio diff --git a/src/assets/ba_data/python/babase/_hooks.py b/src/assets/ba_data/python/babase/_hooks.py index 90dde9be..69881e96 100644 --- a/src/assets/ba_data/python/babase/_hooks.py +++ b/src/assets/ba_data/python/babase/_hooks.py @@ -33,18 +33,30 @@ def reset_to_main_menu() -> None: logging.warning('reset_to_main_menu: no-op due to classic not present.') -def set_config_fullscreen_on() -> None: +def store_config_fullscreen_on() -> None: """The OS has changed our fullscreen state and we should take note.""" _babase.app.config['Fullscreen'] = True _babase.app.config.commit() -def set_config_fullscreen_off() -> None: +def store_config_fullscreen_off() -> None: """The OS has changed our fullscreen state and we should take note.""" _babase.app.config['Fullscreen'] = False _babase.app.config.commit() +def set_config_fullscreen_on() -> None: + """Set and store fullscreen state""" + _babase.app.config['Fullscreen'] = True + _babase.app.config.apply_and_commit() + + +def set_config_fullscreen_off() -> None: + """The OS has changed our fullscreen state and we should take note.""" + _babase.app.config['Fullscreen'] = False + _babase.app.config.apply_and_commit() + + def not_signed_in_screen_message() -> None: from babase._language import Lstr diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index b832f68b..16de717b 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -40,7 +40,7 @@ if TYPE_CHECKING: # the last load. Either way, however, multiple execs will happen in some # form. # -# So we need to do a few things to handle that situation gracefully. +# To handle that situation gracefully, we need to do a few things: # # - First, we need to store any mutable global state in the __main__ # module; not in ourself. This way, alternate versions of ourself will @@ -48,11 +48,11 @@ if TYPE_CHECKING: # # - Second, we should avoid the use of isinstance and similar calls for # our types. An EnvConfig we create would technically be a different -# type than that created by an alternate baenv. +# type than an EnvConfig created by an alternate baenv. # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21465 +TARGET_BALLISTICA_BUILD = 21468 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 3d3a7b42..535d6719 100644 --- a/src/assets/ba_data/python/bauiv1/__init__.py +++ b/src/assets/ba_data/python/bauiv1/__init__.py @@ -31,7 +31,10 @@ from babase import ( apptimer, AppTimer, Call, - can_toggle_fullscreen, + fullscreen_control_available, + fullscreen_control_get, + fullscreen_control_key_shortcut, + fullscreen_control_set, charstr, clipboard_is_supported, clipboard_set_text, @@ -139,7 +142,10 @@ __all__ = [ 'buttonwidget', 'Call', 'can_show_ad', - 'can_toggle_fullscreen', + 'fullscreen_control_available', + 'fullscreen_control_get', + 'fullscreen_control_key_shortcut', + 'fullscreen_control_set', 'charstr', 'checkboxwidget', 'clipboard_is_supported', diff --git a/src/assets/ba_data/python/bauiv1lib/settings/graphics.py b/src/assets/ba_data/python/bauiv1lib/settings/graphics.py index ec6879b4..1c235095 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/graphics.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/graphics.py @@ -52,7 +52,7 @@ class GraphicsSettingsWindow(bui.Window): self._show_fullscreen = False fullscreen_spacing_top = spacing * 0.2 fullscreen_spacing = spacing * 1.2 - if bui.can_toggle_fullscreen(): + if bui.fullscreen_control_available(): self._show_fullscreen = True height += fullscreen_spacing + fullscreen_spacing_top @@ -122,21 +122,29 @@ class GraphicsSettingsWindow(bui.Window): self._fullscreen_checkbox: bui.Widget | None = None if self._show_fullscreen: v -= fullscreen_spacing_top - self._fullscreen_checkbox = ConfigCheckBox( + # Fullscreen control does not necessarily talk to the + # app config so we have to wrangle it manually instead of + # using a config-checkbox. + label = bui.Lstr(resource=f'{self._r}.fullScreenText') + + # Show keyboard shortcut alongside the control if they + # provide one. + shortcut = bui.fullscreen_control_key_shortcut() + if shortcut is not None: + label = bui.Lstr( + value='$(NAME) [$(SHORTCUT)]', + subs=[('$(NAME)', label), ('$(SHORTCUT)', shortcut)], + ) + self._fullscreen_checkbox = bui.checkboxwidget( parent=self._root_widget, position=(100, v), - maxwidth=200, + value=bui.fullscreen_control_get(), + on_value_change_call=bui.fullscreen_control_set, + maxwidth=250, size=(300, 30), - configkey='Fullscreen', - displayname=bui.Lstr( - resource=self._r - + ( - '.fullScreenCmdText' - if app.classic.platform == 'mac' - else '.fullScreenCtrlText' - ) - ), - ).widget + text=label, + ) + if not self._have_selected_child: bui.containerwidget( edit=self._root_widget, @@ -528,8 +536,10 @@ class GraphicsSettingsWindow(bui.Window): and bui.apptime() - self._last_max_fps_set_time > 1.0 ): self._apply_max_fps() + if self._show_fullscreen: + # Keep the fullscreen checkbox up to date with the current value. bui.checkboxwidget( edit=self._fullscreen_checkbox, - value=bui.app.config.resolve('Fullscreen'), + value=bui.fullscreen_control_get(), ) diff --git a/src/ballistica/base/app_adapter/app_adapter.cc b/src/ballistica/base/app_adapter/app_adapter.cc index f7fb480c..80391e90 100644 --- a/src/ballistica/base/app_adapter/app_adapter.cc +++ b/src/ballistica/base/app_adapter/app_adapter.cc @@ -15,6 +15,8 @@ #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" @@ -239,7 +241,7 @@ void AppAdapter::DoExitMainThreadEventLoop() { FatalError("DoExitMainThreadEventLoop is not implemented here."); } -auto AppAdapter::CanToggleFullscreen() -> bool const { return false; } +auto AppAdapter::FullscreenControlAvailable() const -> bool { return false; } auto AppAdapter::SupportsVSync() -> bool const { return false; } @@ -253,6 +255,29 @@ void AppAdapter::DoPushGraphicsContextRunnable(Runnable* runnable) { DoPushMainThreadRunnable(runnable); } +auto AppAdapter::FullscreenControlGet() const -> bool { + assert(g_base->InLogicThread()); + + // By default, just go through config (assume we have full control over + // the fullscreen state ourself). + return g_base->app_config->Resolve(AppConfig::BoolID::kFullscreen); +} + +void AppAdapter::FullscreenControlSet(bool fullscreen) { + assert(g_base->InLogicThread()); + // By default, just set these in the config and apply it (assumes config + // changes get plugged into actual fullscreen state). + g_base->python->objs() + .Get(fullscreen ? BasePython::ObjID::kSetConfigFullscreenOnCall + : BasePython::ObjID::kSetConfigFullscreenOffCall) + .Call(); +} + +auto AppAdapter::FullscreenControlKeyShortcut() const + -> std::optional { + return {}; +} + void AppAdapter::CursorPositionForDraw(float* x, float* y) { assert(x && y); @@ -271,9 +296,7 @@ auto AppAdapter::ShouldUseCursor() -> bool { return true; } auto AppAdapter::HasHardwareCursor() -> bool { return false; } -void AppAdapter::SetHardwareCursorVisible(bool visible) { - printf("SHOULD SET VIS %d\n", static_cast(visible)); -} +void AppAdapter::SetHardwareCursorVisible(bool visible) {} auto AppAdapter::CanSoftQuit() -> bool { return false; } auto AppAdapter::CanBackQuit() -> bool { return false; } diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index 427f536c..7b6339d9 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -113,9 +113,27 @@ class AppAdapter { auto app_suspended() const { return app_suspended_; } /// Return whether this AppAdapter supports a 'fullscreen' toggle for its - /// display. This currently will simply affect whether that option is - /// available in display settings or via a hotkey. - virtual auto CanToggleFullscreen() -> bool const; + /// display. This will affect whether that option is available in display + /// settings or via a hotkey. Must be called from the logic thread. + virtual auto FullscreenControlAvailable() const -> bool; + + /// AppAdapters supporting a 'fullscreen' control should return the + /// current fullscreen state here. By default this simply returns the + /// app-config fullscreen value (so assumes the actual state is synced to + /// that). Must be called from the logic thread. + virtual auto FullscreenControlGet() const -> bool; + + /// AppAdapters supporting a 'fullscreen' control should set the + /// current fullscreen state here. By default this simply sets the + /// app-config fullscreen value (so assumes the actual state is synced to + /// that). Must be called from the logic thread. + virtual void FullscreenControlSet(bool fullscreen); + + /// AppAdapters supporting a 'fullscreen' control can return a key name + /// here to display if they support toggling via key ('ctrl-F', etc.). + /// Must be called from the logic thread. + virtual auto FullscreenControlKeyShortcut() const + -> std::optional; /// Return whether this AppAdapter supports vsync controls for its display. virtual auto SupportsVSync() -> bool const; diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.cc b/src/ballistica/base/app_adapter/app_adapter_sdl.cc index 75443228..30c03ee4 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -363,8 +363,10 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) { // If they hit the window close button, skip the confirm. g_base->QuitApp(false); } else { - // By default, confirm before quitting. - g_base->QuitApp(true); + // For all other quits we might want to default to a confirm dialog. + // Update: going to try without confirm for a bit and see how that + // feels. + g_base->QuitApp(false); } break; @@ -394,7 +396,7 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) { fullscreen_ = true; g_base->logic->event_loop()->PushCall([] { g_base->python->objs() - .Get(BasePython::ObjID::kSetConfigFullscreenOnCall) + .Get(BasePython::ObjID::kStoreConfigFullscreenOnCall) .Call(); }); } @@ -407,7 +409,7 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) { fullscreen_ = false; g_base->logic->event_loop()->PushCall([] { g_base->python->objs() - .Get(BasePython::ObjID::kSetConfigFullscreenOffCall) + .Get(BasePython::ObjID::kStoreConfigFullscreenOffCall) .Call(); }); } @@ -818,7 +820,28 @@ void AppAdapterSDL::CursorPositionForDraw(float* x, float* y) { *y = immediate_y; } -auto AppAdapterSDL::CanToggleFullscreen() -> bool const { return true; } +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 {}; +}; + auto AppAdapterSDL::SupportsVSync() -> bool const { return true; } auto AppAdapterSDL::SupportsMaxFPS() -> bool const { return true; } diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.h b/src/ballistica/base/app_adapter/app_adapter_sdl.h index cc0f0405..78223a24 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.h +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.h @@ -34,7 +34,9 @@ class AppAdapterSDL : public AppAdapter { auto TryRender() -> bool; - auto CanToggleFullscreen() -> bool const override; + auto FullscreenControlAvailable() const -> bool override; + auto FullscreenControlKeyShortcut() const + -> std::optional override; auto SupportsVSync() -> bool const override; auto SupportsMaxFPS() -> bool const override; diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index 06d31f27..c3b27059 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -15,6 +15,7 @@ #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" @@ -997,10 +998,26 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) { } } - // Command-F or Control-F toggles full-screen if the app-adapter supports it. - if (g_base->app_adapter->CanToggleFullscreen()) { - if (!repeat_press && keysym.sym == SDLK_f - && ((keysym.mod & KMOD_CTRL) || (keysym.mod & KMOD_GUI))) { + // 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. + if (g_buildconfig.ostype_macos() && !g_buildconfig.xcode_build()) { + if (!repeat_press && 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))))) { + do_toggle = true; + } + } + if (do_toggle) { g_base->python->objs() .Get(BasePython::ObjID::kToggleFullscreenCall) .Call(); @@ -1008,12 +1025,15 @@ void Input::HandleKeyPress_(const SDL_Keysym& keysym) { } } - // Control-Q quits. On Mac, the usual Cmd-Q gets handled - // by the app-adapter implicitly. - if (!repeat_press && keysym.sym == SDLK_q && (keysym.mod & KMOD_CTRL)) { - g_base->QuitApp(true); - return; - } + // 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. if (auto* console = g_base->ui->dev_console()) { diff --git a/src/ballistica/base/python/base_python.h b/src/ballistica/base/python/base_python.h index 7b807b1b..fc70c6db 100644 --- a/src/ballistica/base/python/base_python.h +++ b/src/ballistica/base/python/base_python.h @@ -38,6 +38,8 @@ class BasePython { kConfig, kAppOnNativeBootstrappingCompleteCall, kResetToMainMenuCall, + kStoreConfigFullscreenOnCall, + kStoreConfigFullscreenOffCall, kSetConfigFullscreenOnCall, kSetConfigFullscreenOffCall, kNotSignedInScreenMessageCall, diff --git a/src/ballistica/base/python/methods/python_methods_graphics.cc b/src/ballistica/base/python/methods/python_methods_graphics.cc index 99ef62c8..0ebf464b 100644 --- a/src/ballistica/base/python/methods/python_methods_graphics.cc +++ b/src/ballistica/base/python/methods/python_methods_graphics.cc @@ -12,6 +12,7 @@ #include "ballistica/base/python/support/python_context_call_runnable.h" #include "ballistica/core/core.h" #include "ballistica/core/platform/core_platform.h" +#include "ballistica/shared/foundation/macros.h" #include "ballistica/shared/generic/utils.h" #include "ballistica/shared/python/python.h" #include "ballistica/shared/python/python_sys.h" @@ -345,8 +346,7 @@ static PyMethodDef PySafeColorDef = { // ------------------------ get_max_graphics_quality --------------------------- -static auto PyGetMaxGraphicsQuality(PyObject* self, PyObject* args) - -> PyObject* { +static auto PyGetMaxGraphicsQuality(PyObject* self) -> PyObject* { BA_PYTHON_TRY; if (g_base->graphics && g_base->graphics->has_supports_high_quality_graphics_value() @@ -359,9 +359,9 @@ static auto PyGetMaxGraphicsQuality(PyObject* self, PyObject* args) } static PyMethodDef PyGetMaxGraphicsQualityDef = { - "get_max_graphics_quality", // name - PyGetMaxGraphicsQuality, // method - METH_VARARGS, // flags + "get_max_graphics_quality", // name + (PyCFunction)PyGetMaxGraphicsQuality, // method + METH_NOARGS, // flags "get_max_graphics_quality() -> str\n" "\n" @@ -619,24 +619,105 @@ static PyMethodDef PyGetDisplayResolutionDef = { "display. Returns None if resolutions cannot be directly set.", }; -// ------------------------- can_toggle_fullscreen ---------------------------- +// ---------------------- fullscreen_control_available ------------------------- -static auto PyCanToggleFullscreen(PyObject* self) -> PyObject* { +static auto PyFullscreenControlAvailable(PyObject* self) -> PyObject* { BA_PYTHON_TRY; - if (g_base->app_adapter->CanToggleFullscreen()) { + BA_PRECONDITION(g_base->InLogicThread()); + if (g_base->app_adapter->FullscreenControlAvailable()) { Py_RETURN_TRUE; } Py_RETURN_FALSE; BA_PYTHON_CATCH; } -static PyMethodDef PyCanToggleFullscreenDef = { - "can_toggle_fullscreen", // name - (PyCFunction)PyCanToggleFullscreen, // method - METH_NOARGS, // flags +static PyMethodDef PyFullscreenControlAvailableDef = { + "fullscreen_control_available", // name + (PyCFunction)PyFullscreenControlAvailable, // method + METH_NOARGS, // flags - "can_toggle_fullscreen() -> bool\n" + "fullscreen_control_available() -> bool\n" + "\n" + "(internal)\n", +}; + +// --------------------- fullscreen_control_key_shortcut ----------------------- + +static auto PyFullscreenControlKeyShortcut(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + + BA_PRECONDITION(g_base->InLogicThread()); + BA_PRECONDITION(g_base->app_adapter->FullscreenControlAvailable()); + + auto val = g_base->app_adapter->FullscreenControlKeyShortcut(); + if (val.has_value()) { + return PyUnicode_FromString(val->c_str()); + } + Py_RETURN_NONE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PyFullscreenControlKeyShortcutDef = { + "fullscreen_control_key_shortcut", // name + (PyCFunction)PyFullscreenControlKeyShortcut, // method + METH_NOARGS, // flags + + "fullscreen_control_key_shortcut() -> str | None\n" + "\n" + "(internal)\n", +}; + +// ------------------------ fullscreen_control_get ----------------------------- + +static auto PyFullscreenControlGet(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + + BA_PRECONDITION(g_base->InLogicThread()); + if (g_base->app_adapter->FullscreenControlGet()) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PyFullscreenControlGetDef = { + "fullscreen_control_get", // name + (PyCFunction)PyFullscreenControlGet, // method + METH_NOARGS, // flags + + "fullscreen_control_get() -> bool\n" + "\n" + "(internal)\n", +}; + +// ------------------------ fullscreen_control_set ----------------------------- + +static auto PyFullscreenControlSet(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { + BA_PYTHON_TRY; + + BA_PRECONDITION(g_base->InLogicThread()); + + int val{}; + static const char* kwlist[] = {"val", nullptr}; + if (!PyArg_ParseTupleAndKeywords(args, keywds, "p", + const_cast(kwlist), &val)) { + return nullptr; + } + + g_base->app_adapter->FullscreenControlSet(val); + + Py_RETURN_NONE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PyFullscreenControlSetDef = { + "fullscreen_control_set", // name + (PyCFunction)PyFullscreenControlSet, // method + METH_VARARGS | METH_KEYWORDS, // flags + + "fullscreen_control_set(val: bool) -> None\n" "\n" "(internal)\n", }; @@ -728,10 +809,13 @@ auto PythonMethodsGraphics::GetMethods() -> std::vector { PyGetMaxGraphicsQualityDef, PySafeColorDef, PyCharStrDef, - PyCanToggleFullscreenDef, + PyFullscreenControlAvailableDef, PySupportsVSyncDef, PySupportsMaxFPSDef, PyShowProgressBarDef, + PyFullscreenControlKeyShortcutDef, + PyFullscreenControlGetDef, + PyFullscreenControlSetDef, }; } diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index c67f264a..9b9f86f4 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 = 21465; +const int kEngineBuildNumber = 21468; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/meta/babasemeta/pyembed/binding_base.py b/src/meta/babasemeta/pyembed/binding_base.py index 5e71b25a..848803bd 100644 --- a/src/meta/babasemeta/pyembed/binding_base.py +++ b/src/meta/babasemeta/pyembed/binding_base.py @@ -21,6 +21,8 @@ from babase import ( # The C++ layer looks for this variable: values = [ _hooks.reset_to_main_menu, # kResetToMainMenuCall + _hooks.store_config_fullscreen_on, # kStoreConfigFullscreenOnCall + _hooks.store_config_fullscreen_off, # kStoreConfigFullscreenOffCall _hooks.set_config_fullscreen_on, # kSetConfigFullscreenOnCall _hooks.set_config_fullscreen_off, # kSetConfigFullscreenOffCall _hooks.not_signed_in_screen_message, # kNotSignedInScreenMessageCall From e0f6f2a516ed0f990205be644fb795d2bdf03df7 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 16 Oct 2023 14:44:29 -0700 Subject: [PATCH 2/9] langs and tidying --- .efrocachemap | 44 +++++++++---------- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- .../base/app_adapter/app_adapter_apple.cc | 28 ++++++++++++ .../base/app_adapter/app_adapter_apple.h | 6 +++ src/ballistica/shared/ballistica.cc | 2 +- 6 files changed, 59 insertions(+), 25 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 2466070f..b74f6387 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": "d21a1b7c9444ae7787944498f3ed6482", + "build/assets/ba_data/data/langdata.json": "1b939f3099af72667d06820b1474ffb9", "build/assets/ba_data/data/languages/arabic.json": "d1f900ab5aa2433d402bd46ed1149cc7", "build/assets/ba_data/data/languages/belarussian.json": "e151808b6b4f6dc159cf55ee62adad3c", "build/assets/ba_data/data/languages/chinese.json": "8d889accdd49334591209bdaf6eaf02f", @@ -450,7 +450,7 @@ "build/assets/ba_data/data/languages/russian.json": "7f1689fff58321fdaa632cb9c45105df", "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": "0122b0b24aa111ab259af02bbae9b7b6", + "build/assets/ba_data/data/languages/spanish.json": "bd1e3a209f2e129e8aafe668cf48a26a", "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,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": "05edee29f50c1d6bee9d3de307248ea6", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "df3990491fab9ac0538e75f347683a94", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a7efd60daa1a52b0e30a7a9616cc727a", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "2b964e4df219ccf31d204c701abf8b6e", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "67845ed4ac3307559448f9f323e3408f", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "b5934ad96454b3fb945a388141166f17", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "cfec3ecd22fa9467a65f8878efa2b911", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "e748d9e8a1f9b9287194f03a5a9f66d2", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f3897d23722ab9cf60614dea1abace10", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "74881b34024a827de91dc4e302123548", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "82b5a5410419a738ffb1007f736644c2", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "f732999c2601cf656b850f5f3e9570f4", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "0da70003570c3f392a0f87a823c2adc3", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "1535ddde4b8532a412df37567a1a29a3", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "e04124a9110037eabe1aac45a98891db", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "c07e02b94aa9f50f21bb6571d3a2d5e5", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "ce594cf55f33b80664e5e2c9d59a4ba1", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "26e0fec05e2813fa3e41aa36e3b43df3", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "3957607929916c7ea7f8cde6487e2101", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "96680b806f2997e75904b4222a1e0536", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ce0628aa40119fda33a0070fc5a5849f", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "6ae8e5b1d931d316b27f2026a24492da", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "755ff319a078d9fdbc80908a6f062e66", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "954aa4169a4e0b84bd071ac0555b098f", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b430a78b9b6c479dd37adf97f8a6cee0", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "c78ad812d6811a87e6652f59cc727990", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "64f608500550bcfe2fe0747280676875", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "ef3c3bc20a9ca9def33aca446364fd92", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "98192e4d10863f86de556baa3aa3eb52", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "fffa329c0f999c39ecc7c537b333480c", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "2b2c521bc2a3afcfbfd8d87869a43dea", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "1b0c69b48e6b1d354d7e444d5f92731a", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "8e55eb7c0cfb5268cca54c455f567f85", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "7aa66285bd814f121850b6cfb782ab40", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "69397f3a8bbad81f8c8d9295528dd41b", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "55c0ebaada6f257620f3ba0225087114", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "68dd9d4782fdd2e7ef26fa34d336d6d0", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "44f7bd9b24fef5ee1ff749b0a61b03b9", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "dee3013cbc5ea749943bc0544b41c0ec", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "fb35137239d263b18e0ae80dac8acb29", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "80ff019ab0715f68dc4cae15c7a9fdab", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "bbe53e6685130822cbba276f63b76dcb", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "80ff019ab0715f68dc4cae15c7a9fdab", diff --git a/CHANGELOG.md b/CHANGELOG.md index fd8a507c..dae6ae79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21468, api 8, 2023-10-16) +### 1.7.28 (build 21471, api 8, 2023-10-16) - 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 16de717b..9ccbb945 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 = 21468 +TARGET_BALLISTICA_BUILD = 21471 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.cc b/src/ballistica/base/app_adapter/app_adapter_apple.cc index 13ebe5a8..9c224905 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -202,6 +202,34 @@ void AppAdapterApple::TerminateApp() { #endif } +auto AppAdapterApple::FullscreenControlAvailable() const -> bool { + // Currently Mac only. Any window-management stuff elsewhere such as + // iPadOS is out of our hands. + if (g_buildconfig.ostype_macos()) { + return true; + } + return false; +} + +auto AppAdapterApple::FullscreenControlGet() const -> bool { +#if BA_OSTYPE_MACOS + return BallisticaKit::CocoaFromCppGetMainWindowIsFullscreen(); +#else + return false; +#endif +} + +void AppAdapterApple::FullscreenControlSet(bool fullscreen) { +#if BA_OSTYPE_MACOS + return BallisticaKit::CocoaFromCppSetMainWindowFullscreen(fullscreen); +#endif +} + +auto AppAdapterApple::FullscreenControlKeyShortcut() const + -> std::optional { + return "fn+F"; +} + } // 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 09ccdbc2..da14b971 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.h +++ b/src/ballistica/base/app_adapter/app_adapter_apple.h @@ -34,6 +34,12 @@ class AppAdapterApple : public AppAdapter { /// Called by FromSwift. void SetScreenResolution(float pixel_width, float pixel_height); + auto FullscreenControlAvailable() const -> bool override; + auto FullscreenControlGet() const -> bool override; + void FullscreenControlSet(bool fullscreen) override; + auto FullscreenControlKeyShortcut() const + -> std::optional override; + protected: void DoPushMainThreadRunnable(Runnable* runnable) override; void DoPushGraphicsContextRunnable(Runnable* runnable) override; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 9b9f86f4..a1bf9730 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 = 21468; +const int kEngineBuildNumber = 21471; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; From da1a43b4ca8faa27db7370fd77b55fe01e64303b Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 16 Oct 2023 15:16:33 -0700 Subject: [PATCH 3/9] fixed a crash-bug in open_url --- .efrocachemap | 56 +++++++++---------- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- .../python/bauiv1lib/account/settings.py | 2 +- src/ballistica/shared/ballistica.cc | 2 +- .../python/methods/python_methods_ui_v1.cc | 7 ++- 6 files changed, 37 insertions(+), 34 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index b74f6387..ba270cbd 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": "ce0628aa40119fda33a0070fc5a5849f", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "6ae8e5b1d931d316b27f2026a24492da", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "755ff319a078d9fdbc80908a6f062e66", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "954aa4169a4e0b84bd071ac0555b098f", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b430a78b9b6c479dd37adf97f8a6cee0", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "c78ad812d6811a87e6652f59cc727990", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "64f608500550bcfe2fe0747280676875", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "ef3c3bc20a9ca9def33aca446364fd92", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "98192e4d10863f86de556baa3aa3eb52", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "fffa329c0f999c39ecc7c537b333480c", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "2b2c521bc2a3afcfbfd8d87869a43dea", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "1b0c69b48e6b1d354d7e444d5f92731a", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "8e55eb7c0cfb5268cca54c455f567f85", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "7aa66285bd814f121850b6cfb782ab40", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "69397f3a8bbad81f8c8d9295528dd41b", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "55c0ebaada6f257620f3ba0225087114", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "68dd9d4782fdd2e7ef26fa34d336d6d0", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "44f7bd9b24fef5ee1ff749b0a61b03b9", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "dee3013cbc5ea749943bc0544b41c0ec", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "fb35137239d263b18e0ae80dac8acb29", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "32bb83a4f89e01aa643757b0cb13b109", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "e710eeae8cc6ebfafe869b860528437c", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "605497ca84eba13f05d08fb16cba5741", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "3b88d767fc74e9169a24c707e5f1b075", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "edc3598904990e1224bbb922c5a49034", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "3e4cfe6ef623f8c6263ebd4be0837762", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "6a76e3a83ad2129cc1eefe627fd53d48", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "6245c26fe2355a955ed668fbf39545c9", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "330b0cc59fc767d5263ef2136f7a7611", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "09230899c32ad2ad72a45849937206b3", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "3ea59821a409a4ebca355ed3ce6efb05", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "9a54eca69f5746b02eeddd3b91cc4411", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "ef7fca726c6fb0324412efe93c01ad90", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "430599b16acfbc01b769539d422434b0", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "dc41efdaf2d6d441545008a55c6fa465", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "78a7ce5e1d4502da430f452dd66ff8fc", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "75062e8500654d7041127bad885e3d41", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "9bc73b6a26c1a3337a28b55de99e1c9e", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d78640a51f84484fdbe5bcdded3e4262", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "55ec3263f4ed2f62c9a6825dd7a54169", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "80ff019ab0715f68dc4cae15c7a9fdab", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "bbe53e6685130822cbba276f63b76dcb", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "80ff019ab0715f68dc4cae15c7a9fdab", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "70d5ec6b86c91c787a182da729737951", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "444861c2242f3f0b9e09046b6cbf0245", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "70d5ec6b86c91c787a182da729737951", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "4c37ef02c9d97ebf58e9cd4055b557a7", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "5450d7efd2aec4481be61a1315d78af2", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "42a5fefe21fdffdfb62a0f236b33193e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "d8f2d5d50cfedfff5b1ce1c9c7c52ef4", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "f19d0d8db9b776291dc3bc99f402608e", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c1dea4974ce3723ded4391eca5ae2bfc", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "cf3bbe5f15e76197937e67cfaf2f0a32", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "2b8c93e04d1876a787b2a8befbbde004", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "864a9cbab9f9585aee77de74198a7972", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "74b8380f81af7e753f474432d90a29ff", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "adaf30a163aecc89a70c796bbbe26834", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0dac2937a62d13700550dbc73e1c0d2c", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "df398f3b1cf28ef14c6cc6f5983f2180", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "87465318edc11b17f84de48d555d895a", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "0744a823a205fa95a12f7fe3ecb480cc", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "859de1201dd68abbd308f95514a6375b", "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": "bb96031e3f844704fcc9a0549a6d2c41", diff --git a/CHANGELOG.md b/CHANGELOG.md index dae6ae79..fc387fa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21471, api 8, 2023-10-16) +### 1.7.28 (build 21473, api 8, 2023-10-16) - 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 9ccbb945..643c752b 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 = 21471 +TARGET_BALLISTICA_BUILD = 21473 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 50959d01..4cea92da 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/settings.py +++ b/src/assets/ba_data/python/bauiv1lib/account/settings.py @@ -704,7 +704,7 @@ class AccountSettingsWindow(bui.Window): position=((self._sub_width - button_width) * 0.5, v + 30), autoselect=True, size=(button_width, 60), - label=bui.Lstr(resource=self._r + '.manageAccountText'), + label=bui.Lstr(resource=f'{self._r}.manageAccountText'), color=(0.55, 0.5, 0.6), icon=bui.gettexture('settingsIcon'), textcolor=(0.75, 0.7, 0.8), diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index a1bf9730..a9cb1129 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 = 21471; +const int kEngineBuildNumber = 21473; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; 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 f03b6841..6b1cdf49 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 @@ -2708,7 +2708,7 @@ static PyMethodDef PyBackPressDef = { static auto PyOpenURL(PyObject* self, PyObject* args, PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; - const char* address = nullptr; + const char* address{}; int force_internal{0}; static const char* kwlist[] = {"address", "force_internal", nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|p", @@ -2716,12 +2716,15 @@ static auto PyOpenURL(PyObject* self, PyObject* args, PyObject* keywds) &force_internal)) { return nullptr; } + // Need to pass a self-contained string to a lambda; not a char*. + std::string address2{address}; + assert(g_base->app_adapter); if (force_internal) { g_base->ui->ShowURL(address); } else { g_base->app_adapter->PushMainThreadCall( - [address] { g_base->platform->OpenURL(address); }); + [address2] { g_base->platform->OpenURL(address2); }); } Py_RETURN_NONE; BA_PYTHON_CATCH; From a3b51abb03b5c4adc69784ab0c770e130da3e9c7 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 17 Oct 2023 21:10:56 -0700 Subject: [PATCH 4/9] more work on revamped mac and android builds --- .efrocachemap | 102 +++++++++--------- CHANGELOG.md | 2 +- src/assets/ba_data/python/babase/_app.py | 2 +- src/assets/ba_data/python/baenv.py | 2 +- .../python/bauiv1lib/settings/controls.py | 7 +- .../base/app_adapter/app_adapter.cc | 1 + src/ballistica/base/app_adapter/app_adapter.h | 10 ++ .../base/app_adapter/app_adapter_apple.cc | 2 + .../base/app_adapter/app_adapter_apple.h | 2 + .../base/app_adapter/app_adapter_sdl.cc | 5 + .../base/app_adapter/app_adapter_sdl.h | 2 + src/ballistica/base/input/input.cc | 66 ++++++++---- src/ballistica/base/ui/ui.cc | 18 ++-- src/ballistica/shared/ballistica.cc | 2 +- src/ballistica/ui_v1/widget/text_widget.cc | 9 +- 15 files changed, 141 insertions(+), 91 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index ba270cbd..95f67d38 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,10 +421,10 @@ "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": "1b939f3099af72667d06820b1474ffb9", - "build/assets/ba_data/data/languages/arabic.json": "d1f900ab5aa2433d402bd46ed1149cc7", + "build/assets/ba_data/data/langdata.json": "7a5f49ae1738b012a6d7c16740af80a0", + "build/assets/ba_data/data/languages/arabic.json": "295c559911fa251f401f8cdcad91c226", "build/assets/ba_data/data/languages/belarussian.json": "e151808b6b4f6dc159cf55ee62adad3c", - "build/assets/ba_data/data/languages/chinese.json": "8d889accdd49334591209bdaf6eaf02f", + "build/assets/ba_data/data/languages/chinese.json": "b0d4e874ba8d22c8fd0d7a0eaaf96ac9", "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", @@ -440,21 +440,21 @@ "build/assets/ba_data/data/languages/hindi.json": "88ee0cda537bab9ac827def5e236fe1a", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", "build/assets/ba_data/data/languages/indonesian.json": "bff88ce57744a639810b93a1d1dd79f4", - "build/assets/ba_data/data/languages/italian.json": "338e7a03dff47f4eefc0ca3a995cd4f4", + "build/assets/ba_data/data/languages/italian.json": "58ecf53a963dbeca1bbf3605e5ab6a2f", "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": "71cc5b33abda0f285b970b8cc4a014a8", "build/assets/ba_data/data/languages/polish.json": "e1a1a801851924748ad38fa68216439a", "build/assets/ba_data/data/languages/portuguese.json": "9fcd6b4da9e5d0dc0e337ab00b5debe2", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", - "build/assets/ba_data/data/languages/russian.json": "7f1689fff58321fdaa632cb9c45105df", + "build/assets/ba_data/data/languages/russian.json": "70f79c606ccc5ec7bd6ce0303fdece70", "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": "bd1e3a209f2e129e8aafe668cf48a26a", + "build/assets/ba_data/data/languages/spanish.json": "6ccd728df4766be1969434d6f04c36d2", "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": "9d7e58c9062dc517c3779c255a9b3142", + "build/assets/ba_data/data/languages/turkish.json": "42318070b817663f671d78a9c8f3019c", "build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2", "build/assets/ba_data/data/languages/venetian.json": "88595b7ee696b4094d7874c3c4188852", "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": "32bb83a4f89e01aa643757b0cb13b109", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "e710eeae8cc6ebfafe869b860528437c", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "605497ca84eba13f05d08fb16cba5741", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "3b88d767fc74e9169a24c707e5f1b075", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "edc3598904990e1224bbb922c5a49034", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "3e4cfe6ef623f8c6263ebd4be0837762", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "6a76e3a83ad2129cc1eefe627fd53d48", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "6245c26fe2355a955ed668fbf39545c9", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "330b0cc59fc767d5263ef2136f7a7611", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "09230899c32ad2ad72a45849937206b3", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "3ea59821a409a4ebca355ed3ce6efb05", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "9a54eca69f5746b02eeddd3b91cc4411", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "ef7fca726c6fb0324412efe93c01ad90", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "430599b16acfbc01b769539d422434b0", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "dc41efdaf2d6d441545008a55c6fa465", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "78a7ce5e1d4502da430f452dd66ff8fc", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "75062e8500654d7041127bad885e3d41", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "9bc73b6a26c1a3337a28b55de99e1c9e", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d78640a51f84484fdbe5bcdded3e4262", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "55ec3263f4ed2f62c9a6825dd7a54169", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "80ff019ab0715f68dc4cae15c7a9fdab", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "bbe53e6685130822cbba276f63b76dcb", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "80ff019ab0715f68dc4cae15c7a9fdab", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "bbe53e6685130822cbba276f63b76dcb", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "0d0737d71a7efe201e5ebadeb5f12c71", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "895099e15bad328666f71869f6f09b79", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "0d0737d71a7efe201e5ebadeb5f12c71", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "895099e15bad328666f71869f6f09b79", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "79e38e7d6eb4a5810bbb22e94d4e87ee", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "2cf7ef381bc7408c21f4ea444815233e", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "79e38e7d6eb4a5810bbb22e94d4e87ee", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "2cf7ef381bc7408c21f4ea444815233e", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "5d457e3b58015c9da26a7911a6c8ed5a", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "70d5ec6b86c91c787a182da729737951", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "444861c2242f3f0b9e09046b6cbf0245", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "70d5ec6b86c91c787a182da729737951", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "864a9cbab9f9585aee77de74198a7972", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "74b8380f81af7e753f474432d90a29ff", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "adaf30a163aecc89a70c796bbbe26834", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0dac2937a62d13700550dbc73e1c0d2c", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "df398f3b1cf28ef14c6cc6f5983f2180", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "87465318edc11b17f84de48d555d895a", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "0744a823a205fa95a12f7fe3ecb480cc", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "859de1201dd68abbd308f95514a6375b", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ece14cc6d7a449f581c810a2d6d3449d", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "b0b75bde134af8c73aa1f7e239bd84dc", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f0742e77993c006a5f2df3e9bee6732e", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b803f154b4bf2aeb908a603fa7888301", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "2be90b3e6fc6908448a7677dd3cfb594", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4d12d1887901f7c77b5df965bb0b4622", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "987f4e024c7ed08e58223369b40aa309", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7dd6ce5ab63d9d255029fb907cf6fb63", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "ad505c3ad979b2cf52c664ee79798575", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "3773aa5c6d396b4c38883321067f5523", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "748f3877c0ac40f48ebc5d8aab442173", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "2d059f03286603ac416718eb262241ab", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "3bd988564ed41c15b4d0f493eced88ef", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "f01539e046d72d86d63da0b4b6fc28df", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "d554e6d3ef9709ad7d7c848633901089", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "967375f76d43831afd7e10208502dcc1", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "7dba8e8a0b8ffbe7f8d73b33b0c41ed5", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "11ccabb65197c9f2e3059ac434888e11", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "8d79aece6620eb017896a7e816a78f0d", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a3331c3d60962e7f0c2b62728bf7f43e", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "1636f9569ee8b8a6c0abed5c9e31e3f7", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "3fc153ee973090358916b90938429931", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "1636f9569ee8b8a6c0abed5c9e31e3f7", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "3fc153ee973090358916b90938429931", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "1c7ed5b60c2961cf7d1a918157f90bce", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "0cbfd345b7e6a02d2a6bdfe7966d03d1", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "1c7ed5b60c2961cf7d1a918157f90bce", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "0cbfd345b7e6a02d2a6bdfe7966d03d1", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "1360496e008c0d0fb631b2fde94e0d54", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "f64f8060f46a1f7088c7aadef33220dd", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "1360496e008c0d0fb631b2fde94e0d54", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "f64f8060f46a1f7088c7aadef33220dd", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "dc45874c7796f4fc740c224243efac28", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c7e7528347b1ec5bc37b13ed8ae88df1", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "abeca8c975a6cd5766fc90df99e8dcd1", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c7e7528347b1ec5bc37b13ed8ae88df1", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7aa3fa305f66461ec5e5bbc550aa742d", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "89c02f2300860fded6b44855f9b8407f", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "69f97da125d43fc396eeaea8013cb133", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "9e56ac32e0cc2785811a162de68c69da", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a62570a46fed2002590be0bafe5055e8", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "b2a10b1eb917197da8f981d5a5daed44", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "c3af2f896ddb7a0b5f2ee2f35bac0318", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "30628de8aa6a7d9cfccf09f102ff9953", "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": "bb96031e3f844704fcc9a0549a6d2c41", diff --git a/CHANGELOG.md b/CHANGELOG.md index fc387fa0..37afc519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21473, api 8, 2023-10-16) +### 1.7.28 (build 21479, api 8, 2023-10-17) - 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/_app.py b/src/assets/ba_data/python/babase/_app.py index ffd1f05d..ec0e0d8b 100644 --- a/src/assets/ba_data/python/babase/_app.py +++ b/src/assets/ba_data/python/babase/_app.py @@ -903,7 +903,7 @@ class App: duration = _babase.apptime() - starttime if duration > 1.0: logging.warning( - 'Shutdown-suppressions delayed shutdown longer than ideal ' + 'Shutdown-suppressions lasted longer than ideal ' '(%.2f seconds).', duration, ) diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 643c752b..9c68772d 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 = 21473 +TARGET_BALLISTICA_BUILD = 21479 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bauiv1lib/settings/controls.py b/src/assets/ba_data/python/bauiv1lib/settings/controls.py index 0b9abd39..168df15c 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/controls.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/controls.py @@ -98,9 +98,11 @@ class ControlsSettingsWindow(bui.Window): # made-for-iOS/Mac systems # (we can run into problems where devices register as one of each # type otherwise).. + # UPDATE: We always use the apple system these days (which should + # support older controllers). So no need for a switch. show_mac_controller_subsystem = False - if platform == 'mac' and bui.is_xcode_build(): - show_mac_controller_subsystem = True + # if platform == 'mac' and bui.is_xcode_build(): + # show_mac_controller_subsystem = True if show_mac_controller_subsystem: height += spacing * 1.5 @@ -311,6 +313,7 @@ class ControlsSettingsWindow(bui.Window): maxwidth=width * 0.8, ) v -= spacing + if show_mac_controller_subsystem: PopupMenu( parent=self._root_widget, diff --git a/src/ballistica/base/app_adapter/app_adapter.cc b/src/ballistica/base/app_adapter/app_adapter.cc index 80391e90..566383ac 100644 --- a/src/ballistica/base/app_adapter/app_adapter.cc +++ b/src/ballistica/base/app_adapter/app_adapter.cc @@ -303,5 +303,6 @@ auto AppAdapter::CanBackQuit() -> bool { return false; } void AppAdapter::DoBackQuit() { FatalError("Fixme unimplemented."); } void AppAdapter::DoSoftQuit() { FatalError("Fixme unimplemented."); } void AppAdapter::TerminateApp() { FatalError("Fixme unimplemented."); } +auto AppAdapter::HasDirectKeyboardInput() -> bool { return false; } } // namespace ballistica::base diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index 7b6339d9..67879ca8 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -171,6 +171,16 @@ class AppAdapter { /// this point. virtual void TerminateApp(); + /// Should return whether there is a keyboard attached that will deliver + /// direct text-editing related events to the app. When this is false, + /// alternate entry methods such as keyboard-entry-dialogs and on-screen + /// keyboards will be used. This value can change based on conditions such + /// as a hardware keyboard getting attached or detached or the language + /// 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. + virtual auto HasDirectKeyboardInput() -> bool; + 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 9c224905..53c4f771 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -230,6 +230,8 @@ auto AppAdapterApple::FullscreenControlKeyShortcut() const return "fn+F"; } +auto AppAdapterApple::HasDirectKeyboardInput() -> bool { return true; }; + } // 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 da14b971..133966b1 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.h +++ b/src/ballistica/base/app_adapter/app_adapter_apple.h @@ -40,6 +40,8 @@ class AppAdapterApple : public AppAdapter { auto FullscreenControlKeyShortcut() const -> std::optional override; + auto HasDirectKeyboardInput() -> bool 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 30c03ee4..51552e14 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -845,6 +845,11 @@ auto AppAdapterSDL::FullscreenControlKeyShortcut() const auto AppAdapterSDL::SupportsVSync() -> bool const { return true; } auto AppAdapterSDL::SupportsMaxFPS() -> bool const { return true; } +auto AppAdapterSDL::HasDirectKeyboardInput() -> bool { + // We always provide direct keyboard events. + return true; +} + } // 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 78223a24..9f57b127 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.h +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.h @@ -40,6 +40,8 @@ class AppAdapterSDL : public AppAdapter { auto SupportsVSync() -> bool const override; auto SupportsMaxFPS() -> bool const override; + auto HasDirectKeyboardInput() -> bool override; + protected: void DoPushMainThreadRunnable(Runnable* runnable) override; void RunMainThreadEventLoopToCompletion() override; diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index c3b27059..736ecc37 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -533,23 +533,28 @@ void Input::UpdateEnabledControllerSubsystems_() { // First off, on mac, let's update whether we want to completely ignore // either the classic or the iOS/Mac controller subsystems. - if (g_buildconfig.ostype_macos()) { - std::string sys = g_base->app_config->Resolve( - AppConfig::StringID::kMacControllerSubsystem); - if (sys == "Classic") { - ignore_mfi_controllers_ = true; - ignore_sdl_controllers_ = false; - } else if (sys == "MFi") { - ignore_mfi_controllers_ = false; - ignore_sdl_controllers_ = true; - } else if (sys == "Both") { - ignore_mfi_controllers_ = false; - ignore_sdl_controllers_ = false; - } else { - BA_LOG_ONCE(LogLevel::kError, - "Invalid mac-controller-subsystem value: '" + sys + "'"); - } - } + // + // UPDATE - these days we're mfi-only on our xcode builds (which should + // support older controllers too). So we don't need to touch ignore vals + // anywhere since we'll not get sdl ones on those builds. + + // if (g_buildconfig.ostype_macos()) { + // std::string sys = g_base->app_config->Resolve( + // AppConfig::StringID::kMacControllerSubsystem); + // if (sys == "Classic") { + // ignore_mfi_controllers_ = true; + // ignore_sdl_controllers_ = false; + // } else if (sys == "MFi") { + // ignore_mfi_controllers_ = false; + // ignore_sdl_controllers_ = true; + // } else if (sys == "Both") { + // ignore_mfi_controllers_ = false; + // ignore_sdl_controllers_ = false; + // } else { + // BA_LOG_ONCE(LogLevel::kError, + // "Invalid mac-controller-subsystem value: '" + sys + "'"); + // } + // } } void Input::OnAppStart() { assert(g_base->InLogicThread()); } @@ -810,10 +815,35 @@ void Input::PushTextInputEvent(const std::string& text) { g_base->logic->event_loop()->PushCall([this, text] { MarkInputActive(); - // Ignore if input is locked. + // If if the app doesn't want direct text input right now. + if (!g_base->app_adapter->HasDirectKeyboardInput()) { + return; + } + + // Ignore if input is locked. if (IsInputLocked()) { 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. + if (!Utils::IsValidUTF8(text)) { + Log(LogLevel::kWarning, "PushTextInputEvent passed invalid utf-8 text."); + return; + } + + // Now scan through unicode vals and ignore stuff like tabs and newlines + // and backspaces. We want to limit this mechanism to direct simple + // lines of text. Anything needing something fancier should go through a + // proper OS-managed text input dialog or whatnot. + auto univals = Utils::UnicodeFromUTF8(text, "80ff83"); + for (auto&& unival : univals) { + if (unival < 32) { + return; + } + } + if (g_base && g_base->ui->dev_console() != nullptr && g_base->ui->dev_console()->HandleTextEditing(text)) { return; diff --git a/src/ballistica/base/ui/ui.cc b/src/ballistica/base/ui/ui.cc index 34ce797d..e9b50093 100644 --- a/src/ballistica/base/ui/ui.cc +++ b/src/ballistica/base/ui/ui.cc @@ -2,6 +2,7 @@ #include "ballistica/base/ui/ui.h" +#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/audio/audio.h" #include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/input/device/keyboard_input.h" @@ -184,15 +185,14 @@ void UI::HandleMouseUp(int button, float x, float y) { } auto UI::UIHasDirectKeyboardInput() const -> bool { - // Currently limiting this to desktop operating systems, but should - // generalize this, as situations such as tablets with hardware keyboards - // should behave similarly to desktop PCs. Though perhaps we should make - // this optional everywhere (or language dependent) since direct keyboard - // input might not work well for some languages even on desktops. - if (g_buildconfig.ostype_macos() || g_buildconfig.ostype_windows() - || g_buildconfig.ostype_linux()) { - // Return true if we've got a keyboard attached and either it or nothing - // is active. + // As a first gate, ask the app-adapter if it is providing keyboard + // events at all. + if (g_base->app_adapter->HasDirectKeyboardInput()) { + // Ok, direct keyboard input is a thing. + // Now let's also require the keyboard (or nothing) to be currently + // driving the UI. If something like a game-controller is driving, + // 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 (ui_input_device == keyboard || ui_input_device == nullptr) { diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index a9cb1129..ff991ab1 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 = 21473; +const int kEngineBuildNumber = 21479; 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 2225580c..edeeeaea 100644 --- a/src/ballistica/ui_v1/widget/text_widget.cc +++ b/src/ballistica/ui_v1/widget/text_widget.cc @@ -562,12 +562,7 @@ void TextWidget::Activate() { } auto TextWidget::ShouldUseStringEditor_() const -> bool { - if (g_core->HeadlessMode()) { - BA_LOG_ONCE( - LogLevel::kError, - "ShouldUseStringEditDialog_ called in headless; should not happen."); - return false; - } + assert(!g_core->HeadlessMode()); // Should not get called here. // Obscure cases such as the text-widget *on* our built-in on-screen // editor (obviously it should itself not pop up an editor). @@ -581,7 +576,7 @@ auto TextWidget::ShouldUseStringEditor_() const -> bool { return true; } - // If we can take direct key events, no string-editor needed. + // If the UI is getting fed actual keyboard events, no string-editor needed. return !g_base->ui->UIHasDirectKeyboardInput(); } From b5b34b4455509c2aa3a6224932d761d1ab22a2c6 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 20 Oct 2023 18:07:15 -0700 Subject: [PATCH 5/9] cleaned up interaction between graphics server and client which will make alternate renderers more doable --- .efrocachemap | 106 +++--- CHANGELOG.md | 2 +- ballisticakit-cmake/CMakeLists.txt | 5 + .../Generic/BallisticaKitGeneric.vcxproj | 5 + .../BallisticaKitGeneric.vcxproj.filters | 15 + .../Headless/BallisticaKitHeadless.vcxproj | 5 + .../BallisticaKitHeadless.vcxproj.filters | 15 + src/assets/ba_data/python/babase/_env.py | 6 +- src/assets/ba_data/python/baenv.py | 2 +- .../base/app_adapter/app_adapter.cc | 12 +- src/ballistica/base/app_adapter/app_adapter.h | 21 ++ .../base/app_adapter/app_adapter_apple.cc | 108 +++--- .../base/app_adapter/app_adapter_apple.h | 19 +- .../base/app_adapter/app_adapter_headless.cc | 13 +- .../base/app_adapter/app_adapter_headless.h | 2 + .../base/app_adapter/app_adapter_sdl.cc | 329 +++++++++++------- .../base/app_adapter/app_adapter_sdl.h | 20 +- .../base/app_adapter/app_adapter_vr.cc | 3 +- src/ballistica/base/app_mode/app_mode.cc | 2 - src/ballistica/base/app_mode/app_mode.h | 2 - src/ballistica/base/assets/assets.cc | 16 +- src/ballistica/base/assets/assets.h | 18 +- src/ballistica/base/assets/assets_server.cc | 15 +- src/ballistica/base/assets/texture_asset.cc | 66 ++-- src/ballistica/base/audio/audio.cc | 14 + src/ballistica/base/audio/audio.h | 43 ++- src/ballistica/base/base.cc | 4 + src/ballistica/base/base.h | 3 + .../base/dynamics/bg/bg_dynamics.cc | 14 +- .../base/dynamics/bg/bg_dynamics_server.cc | 3 +- .../base/dynamics/bg/bg_dynamics_server.h | 1 + .../base/graphics/gl/program/program_gl.h | 31 +- .../base/graphics/gl/renderer_gl.cc | 5 +- src/ballistica/base/graphics/graphics.cc | 197 +++++++++-- src/ballistica/base/graphics/graphics.h | 257 ++++++++------ .../base/graphics/graphics_server.cc | 280 +++++++++------ .../base/graphics/graphics_server.h | 134 +++---- .../base/graphics/renderer/render_pass.cc | 2 +- .../base/graphics/renderer/render_pass.h | 2 +- .../base/graphics/renderer/renderer.cc | 10 +- .../base/graphics/renderer/renderer.h | 2 - .../base/graphics/support/camera.cc | 2 +- .../base/graphics/support/frame_def.cc | 43 ++- .../base/graphics/support/frame_def.h | 59 ++-- .../support/graphics_client_context.cc | 23 ++ .../support/graphics_client_context.h | 31 ++ .../graphics/support/graphics_settings.cc | 27 ++ .../base/graphics/support/graphics_settings.h | 33 ++ src/ballistica/base/input/input.cc | 12 +- src/ballistica/base/logic/logic.cc | 4 +- src/ballistica/base/logic/logic.h | 29 +- .../platform/apple/base_platform_apple.cc | 8 +- .../base/python/methods/python_methods_app.cc | 20 +- .../python/methods/python_methods_graphics.cc | 15 +- .../platform/apple/core_platform_apple.cc | 8 +- .../core/platform/apple/core_platform_apple.h | 4 +- src/ballistica/core/platform/core_platform.cc | 17 +- src/ballistica/core/platform/core_platform.h | 10 +- .../platform/windows/core_platform_windows.cc | 7 +- .../platform/windows/core_platform_windows.h | 4 +- src/ballistica/core/python/core_python.cc | 4 +- src/ballistica/core/python/core_python.h | 2 +- src/ballistica/scene_v1/dynamics/collision.h | 11 +- src/ballistica/scene_v1/dynamics/dynamics.cc | 86 ++--- src/ballistica/scene_v1/dynamics/dynamics.h | 89 +++-- .../material/impact_sound_material_action.cc | 8 +- .../dynamics/material/material_context.cc | 12 +- .../material/roll_sound_material_action.cc | 10 +- .../material/skid_sound_material_action.cc | 8 +- .../scene_v1/dynamics/rigid_body.cc | 15 +- src/ballistica/scene_v1/node/flag_node.cc | 119 +++---- src/ballistica/scene_v1/node/flag_node.h | 11 +- src/ballistica/scene_v1/node/node.h | 1 - src/ballistica/scene_v1/node/prop_node.cc | 2 +- src/ballistica/scene_v1/node/shield_node.cc | 4 +- src/ballistica/scene_v1/node/spaz_node.cc | 135 ++++--- src/ballistica/scene_v1/node/spaz_node.h | 2 +- .../scene_v1/support/host_activity.cc | 3 - .../scene_v1/support/host_activity.h | 1 - .../scene_v1/support/host_session.cc | 10 - .../scene_v1/support/host_session.h | 1 - src/ballistica/scene_v1/support/scene.cc | 9 +- src/ballistica/scene_v1/support/scene.h | 1 - .../scene_v1/support/scene_v1_app_mode.cc | 9 - .../scene_v1/support/scene_v1_app_mode.h | 1 - src/ballistica/scene_v1/support/session.cc | 2 - src/ballistica/scene_v1/support/session.h | 1 - src/ballistica/shared/ballistica.cc | 2 +- .../shared/foundation/fatal_error.cc | 6 +- src/ballistica/shared/foundation/logging.cc | 8 +- src/ballistica/shared/foundation/logging.h | 11 +- src/ballistica/shared/foundation/object.cc | 9 +- src/ballistica/shared/foundation/object.h | 224 ++++++------ src/ballistica/shared/generic/snapshot.h | 26 ++ src/tools/pcommandbatch/pcommandbatch.c | 11 +- tools/efrotools/xcodebuild.py | 4 +- 96 files changed, 1823 insertions(+), 1200 deletions(-) create mode 100644 src/ballistica/base/graphics/support/graphics_client_context.cc create mode 100644 src/ballistica/base/graphics/support/graphics_client_context.h create mode 100644 src/ballistica/base/graphics/support/graphics_settings.cc create mode 100644 src/ballistica/base/graphics/support/graphics_settings.h create mode 100644 src/ballistica/shared/generic/snapshot.h diff --git a/.efrocachemap b/.efrocachemap index 95f67d38..4f28e4fe 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": "7a5f49ae1738b012a6d7c16740af80a0", + "build/assets/ba_data/data/langdata.json": "1a960da2db069ca3926b8ee6b8f82df7", "build/assets/ba_data/data/languages/arabic.json": "295c559911fa251f401f8cdcad91c226", "build/assets/ba_data/data/languages/belarussian.json": "e151808b6b4f6dc159cf55ee62adad3c", "build/assets/ba_data/data/languages/chinese.json": "b0d4e874ba8d22c8fd0d7a0eaaf96ac9", @@ -433,30 +433,30 @@ "build/assets/ba_data/data/languages/english.json": "e70277fc6325126d3d893524c8df03c9", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/filipino.json": "347f38524816691170d266708fe25894", - "build/assets/ba_data/data/languages/french.json": "d8527da977a563185de25ef02bacf826", + "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": "7863ceeedb1e87eef46f7769bae5f842", - "build/assets/ba_data/data/languages/greek.json": "a65d78f912e9a89f98de004405167a6a", - "build/assets/ba_data/data/languages/hindi.json": "88ee0cda537bab9ac827def5e236fe1a", + "build/assets/ba_data/data/languages/gibberish.json": "b8dfd407fb7fd9b268129c364b70ca54", + "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": "bff88ce57744a639810b93a1d1dd79f4", + "build/assets/ba_data/data/languages/indonesian.json": "53961b1484a1831f32bec2cc2941e672", "build/assets/ba_data/data/languages/italian.json": "58ecf53a963dbeca1bbf3605e5ab6a2f", "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": "71cc5b33abda0f285b970b8cc4a014a8", + "build/assets/ba_data/data/languages/persian.json": "a391d80ff58ea22926499e4b19d2c0d0", "build/assets/ba_data/data/languages/polish.json": "e1a1a801851924748ad38fa68216439a", "build/assets/ba_data/data/languages/portuguese.json": "9fcd6b4da9e5d0dc0e337ab00b5debe2", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", "build/assets/ba_data/data/languages/russian.json": "70f79c606ccc5ec7bd6ce0303fdece70", "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": "6ccd728df4766be1969434d6f04c36d2", + "build/assets/ba_data/data/languages/spanish.json": "e72e394f94b99d3e838c1b81a9d17615", "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": "42318070b817663f671d78a9c8f3019c", "build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2", - "build/assets/ba_data/data/languages/venetian.json": "88595b7ee696b4094d7874c3c4188852", + "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", "build/assets/ba_data/data/maps/bridgit.json": "6aea74805f4880cc11237c5734a24422", @@ -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": "ece14cc6d7a449f581c810a2d6d3449d", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "b0b75bde134af8c73aa1f7e239bd84dc", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f0742e77993c006a5f2df3e9bee6732e", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b803f154b4bf2aeb908a603fa7888301", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "2be90b3e6fc6908448a7677dd3cfb594", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4d12d1887901f7c77b5df965bb0b4622", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "987f4e024c7ed08e58223369b40aa309", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7dd6ce5ab63d9d255029fb907cf6fb63", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "ad505c3ad979b2cf52c664ee79798575", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "3773aa5c6d396b4c38883321067f5523", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "748f3877c0ac40f48ebc5d8aab442173", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "2d059f03286603ac416718eb262241ab", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "3bd988564ed41c15b4d0f493eced88ef", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "f01539e046d72d86d63da0b4b6fc28df", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "d554e6d3ef9709ad7d7c848633901089", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "967375f76d43831afd7e10208502dcc1", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "7dba8e8a0b8ffbe7f8d73b33b0c41ed5", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "11ccabb65197c9f2e3059ac434888e11", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "8d79aece6620eb017896a7e816a78f0d", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a3331c3d60962e7f0c2b62728bf7f43e", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "1636f9569ee8b8a6c0abed5c9e31e3f7", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "3fc153ee973090358916b90938429931", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "1636f9569ee8b8a6c0abed5c9e31e3f7", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "3fc153ee973090358916b90938429931", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "1c7ed5b60c2961cf7d1a918157f90bce", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "0cbfd345b7e6a02d2a6bdfe7966d03d1", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "1c7ed5b60c2961cf7d1a918157f90bce", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "0cbfd345b7e6a02d2a6bdfe7966d03d1", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "1360496e008c0d0fb631b2fde94e0d54", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "f64f8060f46a1f7088c7aadef33220dd", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "1360496e008c0d0fb631b2fde94e0d54", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "f64f8060f46a1f7088c7aadef33220dd", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "dc45874c7796f4fc740c224243efac28", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c7e7528347b1ec5bc37b13ed8ae88df1", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "abeca8c975a6cd5766fc90df99e8dcd1", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c7e7528347b1ec5bc37b13ed8ae88df1", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7aa3fa305f66461ec5e5bbc550aa742d", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "89c02f2300860fded6b44855f9b8407f", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "69f97da125d43fc396eeaea8013cb133", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "9e56ac32e0cc2785811a162de68c69da", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a62570a46fed2002590be0bafe5055e8", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "b2a10b1eb917197da8f981d5a5daed44", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "c3af2f896ddb7a0b5f2ee2f35bac0318", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "30628de8aa6a7d9cfccf09f102ff9953", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "48b5a58b401a2b22b88491f7bcd0e22a", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "6d83849db3e1398503e2bb682eb4323e", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "b054c284b778dc77edc9c9b046303f46", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b16789743a603fac02763c09bbca446b", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "ab0a78d42cc511b4041478205e892897", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4bbb41936ffe72a7fe9bdc803761b937", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "a1427251545496f84c4d4e2d90e6e25a", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "729bec30bafe25cac07f920c0cc30ab8", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f8b086fdf6bca929ebc75b117b80f522", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "7d8f3ffe791e5a665ecbb2c517483814", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "5f4207138b152a110593c6c5ea8a9b32", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "4211f250197995e7df6942d32cffd202", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "40be1e38cbac3baf88dee161eeb912e1", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "d4aacb95a1855e969d1cc8db33732c40", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "570f49dc1de66e3fe75d76ee5f9306e0", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ad319e6fb3cd7043a597f0780de42a98", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "4c15b26f43b4cb81f433beeb927c8aa6", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "a06aaa7a95abb56d49ba7925cc503a28", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "82619b88184faf3ef7ae4bf41ea282ce", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "61251e6fe58347224750fdf30d4bf8bc", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "bbd5b31cd9b4d30e48ce46e2cf968fcf", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "4e11b895cbf2e1339cf34bc06c54a4ea", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "bbd5b31cd9b4d30e48ce46e2cf968fcf", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "4e11b895cbf2e1339cf34bc06c54a4ea", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "b483573e1ef7e6be1090c67187e9d1d8", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "ae5f87286947575463c386cfe1c443e4", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "b483573e1ef7e6be1090c67187e9d1d8", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "ae5f87286947575463c386cfe1c443e4", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "cf4e9ef8006953c365b0928c68f5a21b", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "2692dc69f7cb2501f0aaa8675f559987", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "cf4e9ef8006953c365b0928c68f5a21b", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "2692dc69f7cb2501f0aaa8675f559987", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "840e96e79a56393c353184475cf28fbc", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "d0940a2237c33b922cf3747cbf3910ef", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "52ccfcbba95dcf3d06620748690446be", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "8369a217dc8cd95db308851de9f35d86", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6bc8e9e67a0cbe50ab2c6891d454570f", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "2ce9d1659647bca4725f404d192c3554", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "8fd2fd1ec12170942823e809332e8cb9", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "f40bd1a61620168791b88901975ea8ee", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4e3f244ac43cd400ffdbd2ac2e887399", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "a5e5e62c259e23429eca4af7054cc7cb", "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": "bb96031e3f844704fcc9a0549a6d2c41", diff --git a/CHANGELOG.md b/CHANGELOG.md index 37afc519..eda3bcdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21479, api 8, 2023-10-17) +### 1.7.28 (build 21486, api 8, 2023-10-20) - 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/ballisticakit-cmake/CMakeLists.txt b/ballisticakit-cmake/CMakeLists.txt index b9050756..297cfe0b 100644 --- a/ballisticakit-cmake/CMakeLists.txt +++ b/ballisticakit-cmake/CMakeLists.txt @@ -353,6 +353,10 @@ set(BALLISTICA_SOURCES ${BA_SRC_ROOT}/ballistica/base/graphics/support/camera.h ${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.cc ${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.h + ${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_client_context.cc + ${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_client_context.h + ${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_settings.cc + ${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_settings.h ${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 @@ -688,6 +692,7 @@ set(BALLISTICA_SOURCES ${BA_SRC_ROOT}/ballistica/shared/generic/lambda_runnable.h ${BA_SRC_ROOT}/ballistica/shared/generic/runnable.cc ${BA_SRC_ROOT}/ballistica/shared/generic/runnable.h + ${BA_SRC_ROOT}/ballistica/shared/generic/snapshot.h ${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.cc ${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.h ${BA_SRC_ROOT}/ballistica/shared/generic/utf8.cc diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj index 3ec34dcc..affcd239 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj @@ -345,6 +345,10 @@ + + + + @@ -680,6 +684,7 @@ + diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters index f77535ec..b3e5ebdf 100644 --- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters +++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters @@ -469,6 +469,18 @@ ballistica\base\graphics\support + + ballistica\base\graphics\support + + + ballistica\base\graphics\support + + + ballistica\base\graphics\support + + + ballistica\base\graphics\support + ballistica\base\graphics\support @@ -1474,6 +1486,9 @@ ballistica\shared\generic + + ballistica\shared\generic + ballistica\shared\generic diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj index 505b71c1..82d010b3 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj @@ -340,6 +340,10 @@ + + + + @@ -675,6 +679,7 @@ + diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters index f77535ec..b3e5ebdf 100644 --- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters +++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters @@ -469,6 +469,18 @@ ballistica\base\graphics\support + + ballistica\base\graphics\support + + + ballistica\base\graphics\support + + + ballistica\base\graphics\support + + + ballistica\base\graphics\support + ballistica\base\graphics\support @@ -1474,6 +1486,9 @@ ballistica\shared\generic + + ballistica\shared\generic + ballistica\shared\generic diff --git a/src/assets/ba_data/python/babase/_env.py b/src/assets/ba_data/python/babase/_env.py index 1e386689..2af28c23 100644 --- a/src/assets/ba_data/python/babase/_env.py +++ b/src/assets/ba_data/python/babase/_env.py @@ -185,10 +185,8 @@ def _feed_logs_to_babase(log_handler: LogHandler) -> None: def _on_log(entry: LogEntry) -> None: # Forward this along to the engine to display in the in-app # console, in the Android log, etc. - _babase.display_log( - name=entry.name, - level=entry.level.name, - message=entry.message, + _babase.emit_log( + name=entry.name, level=entry.level.name, message=entry.message ) # We also want to feed some logs to the old v1-cloud-log system. diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 9c68772d..b34bebc9 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 = 21479 +TARGET_BALLISTICA_BUILD = 21486 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 566383ac..a7f1cf89 100644 --- a/src/ballistica/base/app_adapter/app_adapter.cc +++ b/src/ballistica/base/app_adapter/app_adapter.cc @@ -2,7 +2,7 @@ #include "ballistica/base/app_adapter/app_adapter.h" -#if BA_OSTYPE_ANDROID +#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" @@ -305,4 +305,14 @@ void AppAdapter::DoSoftQuit() { FatalError("Fixme unimplemented."); } void AppAdapter::TerminateApp() { FatalError("Fixme unimplemented."); } auto AppAdapter::HasDirectKeyboardInput() -> bool { return false; } +void AppAdapter::ApplyGraphicsSettings(const GraphicsSettings* settings) {} + +auto AppAdapter::GetGraphicsSettings() -> GraphicsSettings* { + return new GraphicsSettings(); +} + +auto AppAdapter::GetGraphicsClientContext() -> GraphicsClientContext* { + return new GraphicsClientContext(); +} + } // namespace ballistica::base diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index 67879ca8..606b5113 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -30,6 +30,16 @@ class AppAdapter { virtual void OnScreenSizeChange(); virtual void DoApplyAppConfig(); + /// When called, should allocate an instance of a GraphicsSettings + /// subclass using 'new', fill it out, and return it. Runs in the logic + /// thread. + virtual auto GetGraphicsSettings() -> GraphicsSettings*; + + /// When called, should allocate an instance of a GraphicsClientContext + /// subclass using 'new', fill it out, and return it. Runs in the graphics + /// context. + virtual auto GetGraphicsClientContext() -> GraphicsClientContext*; + /// Return whether this class manages the main thread event loop itself. /// Default is true. If this is true, RunMainThreadEventLoopToCompletion() /// will be called to run the app. This should return false on builds @@ -181,6 +191,17 @@ class AppAdapter { /// should be callable from any thread. virtual auto HasDirectKeyboardInput() -> bool; + /// Called in the graphics context to apply new settings coming in from + /// the logic subsystem. This will be called initially to jump-start the + /// graphics system as well as before frame draws to update any new + /// settings coming in. + /// + /// Whenever graphics settings will result in a change to the graphics + /// context (ie: something visible to rendering code in the logic thread) + /// the adapter should call g_base->graphics_server->set_context() with + /// the updated context. + virtual void ApplyGraphicsSettings(const GraphicsSettings* settings); + 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 53c4f771..69b36034 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -44,58 +44,27 @@ void AppAdapterApple::DoPushMainThreadRunnable(Runnable* runnable) { BallisticaKit::FromCppPushRawRunnableToMain(runnable); } -void AppAdapterApple::DoApplyAppConfig() { - assert(g_base->InLogicThread()); +void AppAdapterApple::DoApplyAppConfig() { assert(g_base->InLogicThread()); } - g_base->graphics_server->PushSetScreenPixelScaleCall( - g_base->app_config->Resolve(AppConfig::FloatID::kScreenPixelScale)); +void AppAdapterApple::ApplyGraphicsSettings(const GraphicsSettings* settings) { + auto* graphics_server = g_base->graphics_server; - auto graphics_quality_requested = - g_base->graphics->GraphicsQualityFromAppConfig(); - - auto texture_quality_requested = - g_base->graphics->TextureQualityFromAppConfig(); - - g_base->app_adapter->PushGraphicsContextCall([=] { - SetScreen_(texture_quality_requested, graphics_quality_requested); - }); -} - -void AppAdapterApple::SetScreen_( - TextureQualityRequest texture_quality_requested, - GraphicsQualityRequest graphics_quality_requested) { - // If we know what we support, filter our request types to what is - // supported. This will keep us from rebuilding contexts if request type - // is flipping between different types that we don't support. - if (g_base->graphics->has_supports_high_quality_graphics_value()) { - if (!g_base->graphics->supports_high_quality_graphics() - && graphics_quality_requested > GraphicsQualityRequest::kMedium) { - graphics_quality_requested = GraphicsQualityRequest::kMedium; - } - } - - auto* gs = g_base->graphics_server; + // We need a full renderer reload if quality values have changed + // or if we don't have a renderer yet. + bool need_full_reload = ((graphics_server->texture_quality_requested() + != settings->texture_quality) + || (graphics_server->graphics_quality_requested() + != settings->graphics_quality)); // We need a full renderer reload if quality values have changed or if we - // don't have one yet. - bool need_full_reload = - ((gs->texture_quality_requested() != texture_quality_requested) - || (gs->graphics_quality_requested() != graphics_quality_requested) - || !gs->texture_quality_set() || !gs->graphics_quality_set()); + // don't yet have a renderer. if (need_full_reload) { - ReloadRenderer_(graphics_quality_requested, texture_quality_requested); + ReloadRenderer_(settings); } - - // Let the logic thread know we've got a graphics system up and running. - // It may use this cue to kick off asset loads and other bootstrapping. - g_base->logic->event_loop()->PushCall( - [] { g_base->logic->OnGraphicsReady(); }); } -void AppAdapterApple::ReloadRenderer_( - GraphicsQualityRequest graphics_quality_requested, - TextureQualityRequest texture_quality_requested) { +void AppAdapterApple::ReloadRenderer_(const GraphicsSettings* settings) { auto* gs = g_base->graphics_server; if (gs->renderer() && gs->renderer_loaded()) { @@ -109,11 +78,11 @@ void AppAdapterApple::ReloadRenderer_( // along the latest real resolution just before each frame draw, but we // need *something* here or else we'll get errors due to framebuffers // getting made at size 0/etc. - g_base->graphics_server->SetScreenResolution(320.0, 240.0); + // g_base->graphics_server->SetScreenResolution(320.0, 240.0); // Update graphics quality based on request. - gs->set_graphics_quality_requested(graphics_quality_requested); - gs->set_texture_quality_requested(texture_quality_requested); + gs->set_graphics_quality_requested(settings->graphics_quality); + gs->set_texture_quality_requested(settings->texture_quality); // (Re)load stuff with these latest quality settings. gs->LoadRenderer(); @@ -123,12 +92,6 @@ void AppAdapterApple::UpdateScreenSizes_() { assert(g_base->app_adapter->InGraphicsContext()); } -void AppAdapterApple::SetScreenResolution(float pixel_width, - float pixel_height) { - auto allow = ScopedAllowGraphics_(this); - g_base->graphics_server->SetScreenResolution(pixel_width, pixel_height); -} - auto AppAdapterApple::TryRender() -> bool { auto allow = ScopedAllowGraphics_(this); @@ -146,10 +109,45 @@ auto AppAdapterApple::TryRender() -> bool { call->RunAndLogErrors(); delete call; } - // Lastly render. - return g_base->graphics_server->TryRender(); - return true; + // Lastly, render. + auto result = g_base->graphics_server->TryRender(); + + // A little trick to make mac resizing look a lot smoother. Because we + // render in a background thread, we often don't render at the most up to + // date window size during a window resize. Normally this makes our image + // jerk around in an ugly way, but if we just re-render once or twice in + // those cases we mostly always get the most up to date window size. + if (result && resize_friendly_frames_ > 0) { + // Leave this enabled for just a few frames every time it is set. + // (so just in case it breaks we won't draw each frame serveral times for + // eternity). + resize_friendly_frames_ -= 1; + + // Keep on drawing until the drawn window size + // 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 + - 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) { + result = g_base->graphics_server->TryRender(); + } else { + break; + } + } + } + + return result; +} + +void AppAdapterApple::EnableResizeFriendlyMode(int width, int height) { + resize_friendly_frames_ = 5; + resize_target_resolution_ = Vector2f(width, height); } auto AppAdapterApple::InGraphicsContext() -> bool { diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.h b/src/ballistica/base/app_adapter/app_adapter_apple.h index 133966b1..d800759d 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.h +++ b/src/ballistica/base/app_adapter/app_adapter_apple.h @@ -11,6 +11,7 @@ #include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/shared/generic/runnable.h" +#include "ballistica/shared/math/vector2f.h" namespace ballistica::base { @@ -32,7 +33,7 @@ class AppAdapterApple : public AppAdapter { auto TryRender() -> bool; /// Called by FromSwift. - void SetScreenResolution(float pixel_width, float pixel_height); + // void SetScreenResolution(float pixel_width, float pixel_height); auto FullscreenControlAvailable() const -> bool override; auto FullscreenControlGet() const -> bool override; @@ -42,6 +43,8 @@ class AppAdapterApple : public AppAdapter { auto HasDirectKeyboardInput() -> bool override; + void EnableResizeFriendlyMode(int width, int height); + protected: void DoPushMainThreadRunnable(Runnable* runnable) override; void DoPushGraphicsContextRunnable(Runnable* runnable) override; @@ -50,16 +53,18 @@ class AppAdapterApple : public AppAdapter { auto HasHardwareCursor() -> bool override; void SetHardwareCursorVisible(bool visible) override; void TerminateApp() override; + void ApplyGraphicsSettings(const GraphicsSettings* settings) override; private: - void UpdateScreenSizes_(); class ScopedAllowGraphics_; - void SetScreen_(TextureQualityRequest texture_quality_requested, - GraphicsQualityRequest graphics_quality_requested); - void ReloadRenderer_(GraphicsQualityRequest graphics_quality_requested, - TextureQualityRequest texture_quality_requested); + + void UpdateScreenSizes_(); + void ReloadRenderer_(const GraphicsSettings* settings); + std::thread::id graphics_thread_{}; - bool graphics_allowed_; + bool graphics_allowed_ : 1 {}; + uint8_t resize_friendly_frames_{}; + Vector2f resize_target_resolution_{-1.0f, -1.0f}; std::mutex graphics_calls_mutex_; std::vector graphics_calls_; }; diff --git a/src/ballistica/base/app_adapter/app_adapter_headless.cc b/src/ballistica/base/app_adapter/app_adapter_headless.cc index 2b8339bb..bc313f33 100644 --- a/src/ballistica/base/app_adapter/app_adapter_headless.cc +++ b/src/ballistica/base/app_adapter/app_adapter_headless.cc @@ -4,6 +4,7 @@ #include "ballistica/base/app_adapter/app_adapter_headless.h" #include "ballistica/base/graphics/graphics_server.h" +#include "ballistica/base/graphics/support/graphics_client_context.h" #include "ballistica/shared/ballistica.h" namespace ballistica::base { @@ -19,12 +20,7 @@ void AppAdapterHeadless::OnMainThreadStartApp() { new EventLoop(EventLoopID::kMain, ThreadSource::kWrapCurrent); } -void AppAdapterHeadless::DoApplyAppConfig() { - // Normal graphical app-adapters kick off screen creation here - // which then leads to remaining app bootstrapping. We create - // a 'null' screen purely for the same effect. - PushMainThreadCall([] { g_base->graphics_server->SetNullGraphics(); }); -} +void AppAdapterHeadless::DoApplyAppConfig() {} void AppAdapterHeadless::RunMainThreadEventLoopToCompletion() { assert(g_core->InMainThread()); @@ -40,6 +36,11 @@ void AppAdapterHeadless::DoExitMainThreadEventLoop() { main_event_loop_->Exit(); } +auto AppAdapterHeadless::GetGraphicsClientContext() -> GraphicsClientContext* { + // Special dummy form. + return new GraphicsClientContext(0); +} + } // namespace ballistica::base #endif // BA_HEADLESS_BUILD diff --git a/src/ballistica/base/app_adapter/app_adapter_headless.h b/src/ballistica/base/app_adapter/app_adapter_headless.h index 6d687bb2..2df675ea 100644 --- a/src/ballistica/base/app_adapter/app_adapter_headless.h +++ b/src/ballistica/base/app_adapter/app_adapter_headless.h @@ -17,6 +17,8 @@ class AppAdapterHeadless : public AppAdapter { void DoApplyAppConfig() override; + auto GetGraphicsClientContext() -> GraphicsClientContext* override; + protected: void DoPushMainThreadRunnable(Runnable* runnable) override; void RunMainThreadEventLoopToCompletion() override; diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.cc b/src/ballistica/base/app_adapter/app_adapter_sdl.cc index 51552e14..a77ee149 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -104,32 +104,115 @@ void AppAdapterSDL::OnMainThreadStartApp() { SDL_ShowCursor(SDL_DISABLE); } +/// Our particular flavor of graphics settings. +struct AppAdapterSDL::GraphicsSettings_ : public GraphicsSettings { + bool fullscreen = g_base->app_config->Resolve(AppConfig::BoolID::kFullscreen); + VSyncRequest vsync = g_base->graphics->VSyncFromAppConfig(); + int max_fps = g_base->app_config->Resolve(AppConfig::IntID::kMaxFPS); +}; + void AppAdapterSDL::DoApplyAppConfig() { assert(g_base->InLogicThread()); - g_base->graphics_server->PushSetScreenPixelScaleCall( - g_base->app_config->Resolve(AppConfig::FloatID::kScreenPixelScale)); - - auto graphics_quality_requested = - g_base->graphics->GraphicsQualityFromAppConfig(); - - auto texture_quality_requested = - g_base->graphics->TextureQualityFromAppConfig(); - // Android res string. // std::string android_res = // g_base->app_config->Resolve(AppConfig::StringID::kResolutionAndroid); +} - bool fullscreen = g_base->app_config->Resolve(AppConfig::BoolID::kFullscreen); +auto AppAdapterSDL::GetGraphicsSettings() -> GraphicsSettings* { + assert(g_base->InLogicThread()); + return new GraphicsSettings_(); +} - auto vsync = g_base->graphics->VSyncFromAppConfig(); - int max_fps = g_base->app_config->Resolve(AppConfig::IntID::kMaxFPS); +void AppAdapterSDL::ApplyGraphicsSettings( + const GraphicsSettings* settings_base) { + assert(g_core->InMainThread()); + assert(!g_core->HeadlessMode()); - // Tell the main thread to set up the screen with these settings. - g_base->app_adapter->PushMainThreadCall([=] { - SetScreen_(fullscreen, max_fps, vsync, texture_quality_requested, - graphics_quality_requested); - }); + // In strict mode, allow graphics stuff while in here. + auto allow = ScopedAllowGraphics_(this); + + // Settings will always be our subclass (since we created it). + auto* settings = static_cast(settings_base); + + // Apply any changes. + bool do_toggle_fs{}; + bool do_set_existing_fullscreen{}; + + auto* graphics_server = g_base->graphics_server; + + // We need a full renderer reload if quality values have changed + // or if we don't have a renderer yet. + bool need_full_reload = ((sdl_window_ == nullptr + || graphics_server->texture_quality_requested() + != settings->texture_quality) + || (graphics_server->graphics_quality_requested() + != settings->graphics_quality)); + + if (need_full_reload) { + ReloadRenderer_(settings); + } else if (settings->fullscreen != fullscreen_) { + SDL_SetWindowFullscreen( + sdl_window_, settings->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + fullscreen_ = settings->fullscreen; + } + + // VSync always gets set independent of the screen (though we set it down + // here to make sure we have a screen when its set). + VSync vsync; + switch (settings->vsync) { + case VSyncRequest::kNever: + vsync = VSync::kNever; + break; + case VSyncRequest::kAlways: + vsync = VSync::kAlways; + break; + case VSyncRequest::kAuto: + vsync = VSync::kAdaptive; + break; + default: + vsync = VSync::kNever; + break; + } + if (vsync != vsync_) { + switch (vsync) { + case VSync::kUnset: + case VSync::kNever: { + SDL_GL_SetSwapInterval(0); + vsync_actually_enabled_ = false; + break; + } + case VSync::kAlways: { + SDL_GL_SetSwapInterval(1); + vsync_actually_enabled_ = true; + break; + } + case VSync::kAdaptive: { + // In this case, let's try setting to 'adaptive' and turn it off if + // that is unsupported. + auto result = SDL_GL_SetSwapInterval(-1); + if (result == 0) { + vsync_actually_enabled_ = true; + } else { + SDL_GL_SetSwapInterval(0); + vsync_actually_enabled_ = false; + } + break; + } + } + vsync_ = vsync; + } + + // This we can set anytime. Probably could have just set it from the logic + // thread where we read it, but let's be pedantic and keep everything to + // the main thread. + max_fps_ = settings->max_fps; + + // Take -1 to mean no max. Otherwise clamp to a reasonable range. + if (max_fps_ != -1) { + max_fps_ = std::max(10, max_fps_); + max_fps_ = std::min(99999, max_fps_); + } } void AppAdapterSDL::RunMainThreadEventLoopToCompletion() { @@ -158,7 +241,7 @@ void AppAdapterSDL::RunMainThreadEventLoopToCompletion() { auto AppAdapterSDL::TryRender() -> bool { if (strict_graphics_context_) { - // In strict mode, allow graphics stuff in here. Normally we allow it + // In strict mode, allow graphics stuff in here. Otherwise we allow it // anywhere in the main thread. auto allow = ScopedAllowGraphics_(this); @@ -179,7 +262,7 @@ auto AppAdapterSDL::TryRender() -> bool { // Lastly render. return g_base->graphics_server->TryRender(); } else { - // Simple path; just render. + // Simpler path; just render. return g_base->graphics_server->TryRender(); } } @@ -188,7 +271,7 @@ void AppAdapterSDL::SleepUntilNextEventCycle_(microsecs_t cycle_start_time) { // Special case: if we're hidden, we simply sleep for a long bit; no fancy // timing. if (hidden_) { - g_core->platform->SleepMillisecs(100); + g_core->platform->SleepSeconds(0.1); return; } @@ -359,7 +442,7 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) { break; case SDL_QUIT: - if (g_core->GetAppTimeMillisecs() - last_windowevent_close_time_ < 100) { + if (g_core->GetAppTimeSeconds() - last_windowevent_close_time_ < 0.1) { // If they hit the window close button, skip the confirm. g_base->QuitApp(false); } else { @@ -380,7 +463,7 @@ void AppAdapterSDL::HandleSDLEvent_(const SDL_Event& event) { case SDL_WINDOWEVENT_CLOSE: { // Simply note that this happened. We use this to adjust our // SDL_QUIT behavior (quit is called right after this). - last_windowevent_close_time_ = g_core->GetAppTimeMillisecs(); + last_windowevent_close_time_ = g_core->GetAppTimeSeconds(); break; } @@ -546,114 +629,96 @@ auto AppAdapterSDL::GetSDLJoystickInput_(int sdl_joystick_id) const return nullptr; // Epic fail. } -void AppAdapterSDL::SetScreen_( - bool fullscreen, int max_fps, VSyncRequest vsync_requested, - TextureQualityRequest texture_quality_requested, - GraphicsQualityRequest graphics_quality_requested) { - assert(g_core->InMainThread()); - assert(!g_core->HeadlessMode()); +// void AppAdapterSDL::ApplyGraphicsSettings_(const GraphicsSettings_* settings) +// { +// assert(g_core->InMainThread()); +// assert(!g_core->HeadlessMode()); - // In strict mode, allow graphics stuff in here. - auto allow = ScopedAllowGraphics_(this); +// // In strict mode, allow graphics stuff while in here. +// auto allow = ScopedAllowGraphics_(this); - // If we know what we support, filter our request types to what is - // supported. This will keep us from rebuilding contexts if request type - // is flipping between different types that we don't support. - if (g_base->graphics->has_supports_high_quality_graphics_value()) { - if (!g_base->graphics->supports_high_quality_graphics() - && graphics_quality_requested > GraphicsQualityRequest::kMedium) { - graphics_quality_requested = GraphicsQualityRequest::kMedium; - } - } +// bool do_toggle_fs{}; +// bool do_set_existing_fullscreen{}; - bool do_toggle_fs{}; - bool do_set_existing_fullscreen{}; +// auto* graphics_server = g_base->graphics_server; - auto* gs = g_base->graphics_server; +// // We need a full renderer reload if quality values have changed +// // or if we don't have a renderer yet. +// bool need_full_reload = ((sdl_window_ == nullptr +// || graphics_server->texture_quality_requested() +// != settings->texture_quality) +// || (graphics_server->graphics_quality_requested() +// != settings->graphics_quality)); - // We need a full renderer reload if quality values have changed - // or if we don't have one yet. - bool need_full_reload = - ((sdl_window_ == nullptr - || gs->texture_quality_requested() != texture_quality_requested) - || (gs->graphics_quality_requested() != graphics_quality_requested) - || !gs->texture_quality_set() || !gs->graphics_quality_set()); +// if (need_full_reload) { +// ReloadRenderer_(settings->fullscreen, settings->graphics_quality, +// settings->texture_quality); +// } else if (settings->fullscreen != fullscreen_) { +// SDL_SetWindowFullscreen( +// sdl_window_, settings->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : +// 0); +// fullscreen_ = settings->fullscreen; +// } - if (need_full_reload) { - ReloadRenderer_(fullscreen, graphics_quality_requested, - texture_quality_requested); - } else if (fullscreen != fullscreen_) { - SDL_SetWindowFullscreen(sdl_window_, - fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - fullscreen_ = fullscreen; - } +// // VSync always gets set independent of the screen (though we set it down +// // here to make sure we have a screen when its set). +// VSync vsync; +// switch (settings->vsync) { +// case VSyncRequest::kNever: +// vsync = VSync::kNever; +// break; +// case VSyncRequest::kAlways: +// vsync = VSync::kAlways; +// break; +// case VSyncRequest::kAuto: +// vsync = VSync::kAdaptive; +// break; +// default: +// vsync = VSync::kNever; +// break; +// } +// if (vsync != vsync_) { +// switch (vsync) { +// case VSync::kUnset: +// case VSync::kNever: { +// SDL_GL_SetSwapInterval(0); +// vsync_actually_enabled_ = false; +// break; +// } +// case VSync::kAlways: { +// SDL_GL_SetSwapInterval(1); +// vsync_actually_enabled_ = true; +// break; +// } +// case VSync::kAdaptive: { +// // In this case, let's try setting to 'adaptive' and turn it off if +// // that is unsupported. +// auto result = SDL_GL_SetSwapInterval(-1); +// if (result == 0) { +// vsync_actually_enabled_ = true; +// } else { +// SDL_GL_SetSwapInterval(0); +// vsync_actually_enabled_ = false; +// } +// break; +// } +// } +// vsync_ = vsync; +// } - // VSync always gets set independent of the screen (though we set it down - // here to make sure we have a screen when its set). - VSync vsync; - switch (vsync_requested) { - case VSyncRequest::kNever: - vsync = VSync::kNever; - break; - case VSyncRequest::kAlways: - vsync = VSync::kAlways; - break; - case VSyncRequest::kAuto: - vsync = VSync::kAdaptive; - break; - default: - vsync = VSync::kNever; - break; - } - if (vsync != vsync_) { - switch (vsync) { - case VSync::kUnset: - case VSync::kNever: { - SDL_GL_SetSwapInterval(0); - vsync_actually_enabled_ = false; - break; - } - case VSync::kAlways: { - SDL_GL_SetSwapInterval(1); - vsync_actually_enabled_ = true; - break; - } - case VSync::kAdaptive: { - // In this case, let's try setting to 'adaptive' and turn it off if - // that is unsupported. - auto result = SDL_GL_SetSwapInterval(-1); - if (result == 0) { - vsync_actually_enabled_ = true; - } else { - SDL_GL_SetSwapInterval(0); - vsync_actually_enabled_ = false; - } - break; - } - } - vsync_ = vsync; - } +// // This we can set anytime. Probably could have just set it from the logic +// // thread where we read it, but let's be pedantic and keep everything to +// // the main thread. +// max_fps_ = settings->max_fps; - // This we can set anytime. Probably could have just set it from the logic - // thread where we read it, but let's be pedantic and keep everything to - // the main thread. - max_fps_ = max_fps; +// // Take -1 to mean no max. Otherwise clamp to a reasonable range. +// if (max_fps_ != -1) { +// max_fps_ = std::max(10, max_fps_); +// max_fps_ = std::min(99999, max_fps_); +// } +// } - // Take -1 to mean no max. Otherwise clamp to a reasonable range. - if (max_fps_ != -1) { - max_fps_ = std::max(10, max_fps_); - max_fps_ = std::min(99999, max_fps_); - } - - // Let the logic thread know we've got a graphics system up and running. - // It may use this cue to kick off asset loads and other bootstrapping. - g_base->logic->event_loop()->PushCall( - [] { g_base->logic->OnGraphicsReady(); }); -} - -void AppAdapterSDL::ReloadRenderer_( - bool fullscreen, GraphicsQualityRequest graphics_quality_requested, - TextureQualityRequest texture_quality_requested) { +void AppAdapterSDL::ReloadRenderer_(const GraphicsSettings_* settings) { assert(g_base->app_adapter->InGraphicsContext()); auto* gs = g_base->graphics_server; @@ -664,7 +729,7 @@ void AppAdapterSDL::ReloadRenderer_( // If we don't haven't yet, create our window and renderer. if (!sdl_window_) { - fullscreen_ = fullscreen; + fullscreen_ = settings->fullscreen; // A reasonable default window size. auto width = static_cast(kBaseVirtualResX * 0.8f); @@ -672,7 +737,7 @@ void AppAdapterSDL::ReloadRenderer_( uint32_t flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE; - if (fullscreen) { + if (settings->fullscreen) { flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } @@ -729,15 +794,16 @@ void AppAdapterSDL::ReloadRenderer_( } } - // Update graphics quality based on request. - gs->set_graphics_quality_requested(graphics_quality_requested); - gs->set_texture_quality_requested(texture_quality_requested); + // Update graphics-server's qualities based on request. + gs->set_graphics_quality_requested(settings->graphics_quality); + gs->set_texture_quality_requested(settings->texture_quality); gs->LoadRenderer(); } void AppAdapterSDL::UpdateScreenSizes_() { - assert(g_base->app_adapter->InGraphicsContext()); + // This runs in the main thread in response to SDL events. + assert(g_core->InMainThread()); // Grab logical window dimensions (points?). This is the coordinate space // SDL's events deal in. @@ -749,8 +815,13 @@ void AppAdapterSDL::UpdateScreenSizes_() { // dimensions. int pixels_x, pixels_y; SDL_GL_GetDrawableSize(sdl_window_, &pixels_x, &pixels_y); - g_base->graphics_server->SetScreenResolution(static_cast(pixels_x), - static_cast(pixels_y)); + + // Push this over to the logic thread which owns the canonical value + // for this. + g_base->logic->event_loop()->PushCall([pixels_x, pixels_y] { + g_base->graphics->SetScreenResolution(static_cast(pixels_x), + static_cast(pixels_y)); + }); } auto AppAdapterSDL::InGraphicsContext() -> bool { diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.h b/src/ballistica/base/app_adapter/app_adapter_sdl.h index 9f57b127..585c29f1 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.h +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.h @@ -41,6 +41,9 @@ class AppAdapterSDL : public AppAdapter { auto SupportsMaxFPS() -> bool const override; auto HasDirectKeyboardInput() -> bool override; + void ApplyGraphicsSettings(const GraphicsSettings* settings) override; + + auto GetGraphicsSettings() -> GraphicsSettings* override; protected: void DoPushMainThreadRunnable(Runnable* runnable) override; @@ -52,14 +55,11 @@ class AppAdapterSDL : public AppAdapter { private: class ScopedAllowGraphics_; - void SetScreen_(bool fullscreen, int max_fps, VSyncRequest vsync_requested, - TextureQualityRequest texture_quality_requested, - GraphicsQualityRequest graphics_quality_requested); + struct GraphicsSettings_; + void HandleSDLEvent_(const SDL_Event& event); void UpdateScreenSizes_(); - void ReloadRenderer_(bool fullscreen, - GraphicsQualityRequest graphics_quality_requested, - TextureQualityRequest texture_quality_requested); + void ReloadRenderer_(const GraphicsSettings_* settings); void OnSDLJoystickAdded_(int index); void OnSDLJoystickRemoved_(int index); // Given an SDL joystick ID, returns our Ballistica input for it. @@ -70,6 +70,7 @@ class AppAdapterSDL : public AppAdapter { void RemoveSDLInputDevice_(int index); void SleepUntilNextEventCycle_(microsecs_t cycle_start_time); + int max_fps_{60}; bool done_ : 1 {}; bool fullscreen_ : 1 {}; bool vsync_actually_enabled_ : 1 {}; @@ -85,17 +86,16 @@ class AppAdapterSDL : public AppAdapter { /// that require such a setup. bool strict_graphics_context_ : 1 {}; bool strict_graphics_allowed_ : 1 {}; - std::mutex strict_graphics_calls_mutex_; - std::vector strict_graphics_calls_; VSync vsync_{VSync::kUnset}; uint32_t sdl_runnable_event_id_{}; - int max_fps_{60}; + std::mutex strict_graphics_calls_mutex_; + std::vector strict_graphics_calls_; microsecs_t oversleep_{}; std::vector sdl_joysticks_; Vector2f window_size_{1.0f, 1.0f}; SDL_Window* sdl_window_{}; void* sdl_gl_context_{}; - millisecs_t last_windowevent_close_time_{}; + seconds_t last_windowevent_close_time_{}; }; } // namespace ballistica::base diff --git a/src/ballistica/base/app_adapter/app_adapter_vr.cc b/src/ballistica/base/app_adapter/app_adapter_vr.cc index bfa614cd..703dbca2 100644 --- a/src/ballistica/base/app_adapter/app_adapter_vr.cc +++ b/src/ballistica/base/app_adapter/app_adapter_vr.cc @@ -40,7 +40,8 @@ void AppAdapterVR::PushVRSimpleRemoteStateCall( } void AppAdapterVR::VRSetDrawDimensions(int w, int h) { - g_base->graphics_server->SetScreenResolution(w, h); + FatalError("FIXME UPDATE SET-SCREEN-RESOLUTION"); + // g_base->graphics_server->SetScreenResolution(w, h); } void AppAdapterVR::VRPreDraw() { diff --git a/src/ballistica/base/app_mode/app_mode.cc b/src/ballistica/base/app_mode/app_mode.cc index 5953f720..e87ab5a6 100644 --- a/src/ballistica/base/app_mode/app_mode.cc +++ b/src/ballistica/base/app_mode/app_mode.cc @@ -36,8 +36,6 @@ void AppMode::HandleGameQuery(const char* buffer, size_t size, auto AppMode::DoesWorldFillScreen() -> bool { return false; } -void AppMode::GraphicsQualityChanged(GraphicsQuality quality) {} - void AppMode::DrawWorld(FrameDef* frame_def) {} void AppMode::ChangeGameSpeed(int offs) {} diff --git a/src/ballistica/base/app_mode/app_mode.h b/src/ballistica/base/app_mode/app_mode.h index 119f7659..5a12fa0d 100644 --- a/src/ballistica/base/app_mode/app_mode.h +++ b/src/ballistica/base/app_mode/app_mode.h @@ -62,8 +62,6 @@ class AppMode { virtual void DrawWorld(FrameDef* frame_def); - virtual void GraphicsQualityChanged(GraphicsQuality quality); - /// Called whenever screen size changes. virtual void OnScreenSizeChange(); diff --git a/src/ballistica/base/assets/assets.cc b/src/ballistica/base/assets/assets.cc index a8da1408..e00b84f3 100644 --- a/src/ballistica/base/assets/assets.cc +++ b/src/ballistica/base/assets/assets.cc @@ -82,8 +82,9 @@ void Assets::StartLoading() { assert(g_base); assert(g_base->audio_server && g_base->assets_server && g_base->graphics_server); - assert(g_base->graphics_server->texture_compression_types_are_set()); - assert(g_base->graphics_server->texture_quality_set()); + assert(g_base->graphics->has_client_context()); + // assert(g_base->graphics_server->texture_compression_types_are_set()); + // assert(g_base->graphics_server->texture_quality_set()); assert(!asset_loads_allowed_); // We should only be called once. asset_loads_allowed_ = true; @@ -1102,10 +1103,13 @@ auto Assets::FindAssetFile(FileType type, const std::string& name) } } - assert(g_base->graphics_server - && g_base->graphics_server->texture_compression_types_are_set()); - assert(g_base->graphics_server - && g_base->graphics_server->texture_quality_set()); + // Make sure we know what compression/quality to use. + assert(g_base->graphics->has_client_context()); + // assert(g_base->graphics_server + // && + // g_base->graphics_server->texture_compression_types_are_set()); + // assert(g_base->graphics_server + // && g_base->graphics_server->texture_quality_set()); prefix = "textures/"; #if BA_OSTYPE_ANDROID && !BA_ANDROID_DDS_BUILD diff --git a/src/ballistica/base/assets/assets.h b/src/ballistica/base/assets/assets.h index 6db00287..cbfa7ba1 100644 --- a/src/ballistica/base/assets/assets.h +++ b/src/ballistica/base/assets/assets.h @@ -136,20 +136,21 @@ class Assets { std::unordered_map >* c_list) -> Object::Ref; - std::vector asset_paths_; + int language_state_{}; bool have_pending_loads_[static_cast(AssetType::kLast)]{}; + + // Will be true while a AssetListLock exists. Good to debug-verify this + // during any asset list access. + bool asset_lists_locked_ : 1 {}; + bool asset_loads_allowed_ : 1 {}; + bool sys_assets_loaded_ : 1 {}; + + std::vector asset_paths_; std::unordered_map packages_; // For use by AssetListLock; don't manually acquire. std::mutex asset_lists_mutex_; - // Will be true while a AssetListLock exists. Good to debug-verify this - // during any asset list access. - bool asset_lists_locked_{}; - - // 'hard-wired' internal assets - bool asset_loads_allowed_{}; - bool sys_assets_loaded_{}; std::vector > system_textures_; std::vector > system_cube_map_textures_; std::vector > system_sounds_; @@ -177,7 +178,6 @@ class Assets { // Text & Language (need to mold this into more asset-like concepts). std::mutex language_mutex_; std::unordered_map language_; - int language_state_{}; std::mutex special_char_mutex_; std::unordered_map special_char_strings_; }; diff --git a/src/ballistica/base/assets/assets_server.cc b/src/ballistica/base/assets/assets_server.cc index e5352ddb..0fddc71f 100644 --- a/src/ballistica/base/assets/assets_server.cc +++ b/src/ballistica/base/assets/assets_server.cc @@ -4,6 +4,7 @@ #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" @@ -221,12 +222,18 @@ void AssetsServer::WriteReplayMessages() { void AssetsServer::Process() { // Make sure we don't do any loading until we know what kind/quality of // textures we'll be loading. - if (!g_base->assets || !g_base->graphics_server - || !g_base->graphics_server - ->texture_compression_types_are_set() // NOLINT - || !g_base->graphics_server->texture_quality_set()) { + + // FIXME - we'll need to revisit this when adding support for + // renderer switches, since this is not especially thread-safe. + + if (!g_base->graphics->has_client_context()) { return; } + // if (!g_base->assets || + // || !g_base->graphics->texture_compression_types_are_set() // NOLINT + // || !g_base->graphics_server->texture_quality_set()) { + // return; + // } // Process exactly 1 preload item. Empty out our non-audio list first // (audio is less likely to cause noticeable hitches if it needs to be loaded diff --git a/src/ballistica/base/assets/texture_asset.cc b/src/ballistica/base/assets/texture_asset.cc index b43c13bb..aa757cb4 100644 --- a/src/ballistica/base/assets/texture_asset.cc +++ b/src/ballistica/base/assets/texture_asset.cc @@ -93,11 +93,14 @@ auto TextureAsset::GetNameFull() const -> std::string { void TextureAsset::DoPreload() { assert(valid_); - assert(g_base->graphics_server - && g_base->graphics_server->texture_compression_types_are_set()); + // Make sure we're not loading without knowing what texture types we + // support. + // assert(g_base->graphics->has_client_context()); + // assert(g_base->graphics_server + // && g_base->graphics_server->texture_compression_types_are_set()); - // We figure out which LOD should be our base level based on quality. - TextureQuality texture_quality = g_base->graphics_server->texture_quality(); + // Figure out which LOD should be our base level based on texture quality. + auto texture_quality = g_base->graphics->placeholder_texture_quality(); // If we're a text-texture. if (packer_.Exists()) { @@ -218,12 +221,14 @@ void TextureAsset::DoPreload() { &preload_datas_[0].base_level); // We should only be loading this if we support etc1 in hardware. - assert(g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kETC1)); + assert(g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kETC1)); // Decompress dxt1/dxt5 ones if we don't natively support S3TC. - if (!g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kS3TC)) { + if (!g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kS3TC)) { if ((preload_datas_[0].formats[preload_datas_[0].base_level] == TextureFormat::kDXT5) || (preload_datas_[0].formats[preload_datas_[0].base_level] @@ -241,8 +246,9 @@ void TextureAsset::DoPreload() { &preload_datas_[0].base_level); // Decompress dxt1/dxt5 if we don't natively support it. - if (!g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kS3TC)) { + if (!g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kS3TC)) { preload_datas_[0].ConvertToUncompressed(this); } } else if (!strcmp(file_name_full_.c_str() + file_name_size - 4, @@ -264,16 +270,18 @@ void TextureAsset::DoPreload() { == TextureFormat::kETC2_RGB) || (preload_datas_[0].formats[preload_datas_[0].base_level] == TextureFormat::kETC2_RGBA)) - && (!g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kETC2))) { + && (!g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kETC2))) { preload_datas_[0].ConvertToUncompressed(this); } // Decompress etc1 if we don't natively support it. if ((preload_datas_[0].formats[preload_datas_[0].base_level] == TextureFormat::kETC1) - && (!g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kETC1))) { + && (!g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kETC1))) { preload_datas_[0].ConvertToUncompressed(this); } @@ -287,8 +295,9 @@ void TextureAsset::DoPreload() { &preload_datas_[0].base_level); // We should only be loading this if we support pvr in hardware. - assert(g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kPVR)); + assert( + g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType(TextureCompressionType::kPVR)); } else if (!strcmp(file_name_full_.c_str() + file_name_size - 4, ".nop")) { // Dummy path for headless; nothing to do here. @@ -342,12 +351,14 @@ void TextureAsset::DoPreload() { } // We should only be loading this if we support etc1 in hardware. - assert(g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kETC1)); + assert(g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kETC1)); // Decompress dxt1/dxt5 ones if we don't natively support S3TC. - if (!g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kS3TC)) { + if (!g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kS3TC)) { if ((preload_datas_[d].formats[preload_datas_[d].base_level] == TextureFormat::kDXT5) || (preload_datas_[d].formats[preload_datas_[d].base_level] @@ -365,8 +376,9 @@ void TextureAsset::DoPreload() { &preload_datas_[d].base_level); // Decompress dxt1/dxt5 if we don't natively support it. - if (!g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kS3TC)) { + if (!g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kS3TC)) { preload_datas_[d].ConvertToUncompressed(this); } } else if (!strcmp(file_name_full_.c_str() + file_name_size - 4, @@ -383,16 +395,18 @@ void TextureAsset::DoPreload() { == TextureFormat::kETC2_RGB) || (preload_datas_[d].formats[preload_datas_[d].base_level] == TextureFormat::kETC2_RGBA)) - && (!g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kETC2))) { + && (!g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kETC2))) { preload_datas_[d].ConvertToUncompressed(this); } // Decompress etc1 if we don't natively support it. if ((preload_datas_[d].formats[preload_datas_[d].base_level] == TextureFormat::kETC1) - && (!g_base->graphics_server->SupportsTextureCompressionType( - TextureCompressionType::kETC1))) { + && (!g_base->graphics->placeholder_client_context() + ->SupportsTextureCompressionType( + TextureCompressionType::kETC1))) { preload_datas_[d].ConvertToUncompressed(this); } diff --git a/src/ballistica/base/audio/audio.cc b/src/ballistica/base/audio/audio.cc index f7daba43..f1ddb876 100644 --- a/src/ballistica/base/audio/audio.cc +++ b/src/ballistica/base/audio/audio.cc @@ -5,6 +5,7 @@ #include "ballistica/base/assets/sound_asset.h" #include "ballistica/base/audio/audio_server.h" #include "ballistica/base/audio/audio_source.h" +#include "ballistica/base/graphics/graphics.h" #include "ballistica/base/support/app_config.h" #include "ballistica/shared/foundation/event_loop.h" @@ -12,6 +13,19 @@ namespace ballistica::base { Audio::Audio() = default; +auto Audio::UseLowQualityAudio() -> bool { + assert(g_base->InLogicThread()); + // Currently just piggybacking off graphics quality here. + if (g_core->HeadlessMode() || g_base->graphics->has_client_context()) { + return true; + } + // We don't have a frame-def to look at so need to calc this ourself; ugh. + auto quality = Graphics::GraphicsQualityFromRequest( + g_base->graphics->settings()->graphics_quality, + g_base->graphics->client_context()->auto_graphics_quality); + return quality < GraphicsQuality::kMedium; +} + void Audio::Reset() { assert(g_base->InLogicThread()); g_base->audio_server->PushResetCall(); diff --git a/src/ballistica/base/audio/audio.h b/src/ballistica/base/audio/audio.h index d3126565..9c87daec 100644 --- a/src/ballistica/base/audio/audio.h +++ b/src/ballistica/base/audio/audio.h @@ -29,36 +29,41 @@ class Audio { virtual void OnScreenSizeChange(); virtual void StepDisplayTime(); + /// Can be keyed off of to cut corners in audio (leaving sounds out, etc.) + /// Currently just piggybacks off graphics quality settings but this logic + /// may get fancier in the future. + auto UseLowQualityAudio() -> bool; + void SetVolumes(float music_volume, float sound_volume); void SetListenerPosition(const Vector3f& p); void SetListenerOrientation(const Vector3f& forward, const Vector3f& up); void SetSoundPitch(float pitch); - // Return a pointer to a locked sound source, or nullptr if they're all busy. - // The sound source will be reset to standard settings (no loop, fade 1, pos - // 0,0,0, etc.). - // Send the source any immediate commands and then unlock it. - // For later modifications, re-retrieve the sound with GetPlayingSound() + /// Return a pointer to a locked sound source, or nullptr if they're all busy. + /// The sound source will be reset to standard settings (no loop, fade 1, pos + /// 0,0,0, etc.). + /// Send the source any immediate commands and then unlock it. + /// For later modifications, re-retrieve the sound with GetPlayingSound() auto SourceBeginNew() -> AudioSource*; - // If a sound play id is playing, locks and returns its sound source. - // on success, you must unlock the source once done with it. + /// If a sound play id is playing, locks and returns its sound source. + /// on success, you must unlock the source once done with it. auto SourceBeginExisting(uint32_t play_id, int debug_id) -> AudioSource*; - // Return true if the sound id is currently valid. This is not guaranteed - // to be super accurate, but can be used to determine if a sound is still - // playing. + /// Return true if the sound id is currently valid. This is not guaranteed + /// to be super accurate, but can be used to determine if a sound is still + /// playing. auto IsSoundPlaying(uint32_t play_id) -> bool; - // Simple one-shot play functions. + /// Simple one-shot play functions. auto PlaySound(SoundAsset* s, float volume = 1.0f) -> std::optional; auto PlaySoundAtPosition(SoundAsset* sound, float volume, float x, float y, float z) -> std::optional; - // Call this if you want to prevent repeated plays of the same sound. It'll - // tell you if the sound has been played recently. The one-shot sound-play - // functions use this under the hood. (PlaySound, PlaySoundAtPosition). + /// Call this if you want to prevent repeated plays of the same sound. It'll + /// tell you if the sound has been played recently. The one-shot sound-play + /// functions use this under the hood. (PlaySound, PlaySoundAtPosition). auto ShouldPlay(SoundAsset* s) -> bool; // Hmm; shouldn't these be accessed through the Source class? @@ -73,15 +78,15 @@ class Audio { } private: - // Flat list of client sources indexed by id. + /// Flat list of client sources indexed by id. std::vector client_sources_; - // List of sources that are ready to use. - // This is kept filled by the audio thread - // and used by the client. + /// List of sources that are ready to use. + /// This is kept filled by the audio thread + /// and used by the client. std::vector available_sources_; - // This must be locked whenever accessing the availableSources list. + /// This must be locked whenever accessing the availableSources list. std::mutex available_sources_mutex_; }; diff --git a/src/ballistica/base/base.cc b/src/ballistica/base/base.cc index 822b02fd..c834d38a 100644 --- a/src/ballistica/base/base.cc +++ b/src/ballistica/base/base.cc @@ -420,6 +420,10 @@ auto BaseFeatureSet::IsUnmodifiedBlessedBuild() -> bool { return false; } +auto BaseFeatureSet::InMainThread() const -> bool { + return g_core->InMainThread(); +} + auto BaseFeatureSet::InAssetsThread() const -> bool { if (auto* loop = assets_server->event_loop()) { return loop->ThreadIsCurrent(); diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index c2bd3a43..fa413c36 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -59,6 +59,8 @@ class DataAsset; class FrameDef; class Graphics; class GraphicsServer; +struct GraphicsSettings; +struct GraphicsClientContext; class Huffman; class ImageMesh; class Input; @@ -662,6 +664,7 @@ class BaseFeatureSet : public FeatureSetNativeComponent, /// allowing certain functionality before this time. auto IsBaseCompletelyImported() -> bool; + auto InMainThread() const -> bool; auto InAssetsThread() const -> bool override; auto InLogicThread() const -> bool override; auto InAudioThread() const -> bool override; diff --git a/src/ballistica/base/dynamics/bg/bg_dynamics.cc b/src/ballistica/base/dynamics/bg/bg_dynamics.cc index a1b82815..231a964b 100644 --- a/src/ballistica/base/dynamics/bg/bg_dynamics.cc +++ b/src/ballistica/base/dynamics/bg/bg_dynamics.cc @@ -39,10 +39,15 @@ void BGDynamics::Emit(const BGDynamicsEmission& e) { void BGDynamics::Step(const Vector3f& cam_pos, int step_millisecs) { assert(g_base->InLogicThread()); + // Don't actually start doing anything until there's a + // client-graphics-context. We need this to calculate qualities/etc. + if (!g_base->graphics->has_client_context()) { + return; + } + // The BG dynamics thread just processes steps as fast as it can; // we need to throttle what we send or tell it to cut back if its behind int step_count = g_base->bg_dynamics_server->step_count(); - // printf("STEP COUNT %d\n", step_count); // If we're really getting behind, start pruning stuff. if (step_count > 3) { @@ -62,6 +67,9 @@ void BGDynamics::Step(const Vector3f& cam_pos, int step_millisecs) { // Pass a newly allocated raw pointer to the bg-dynamics thread; it takes care // of disposing it when done. auto d = Object::NewDeferred(); + d->graphics_quality = Graphics::GraphicsQualityFromRequest( + g_base->graphics->settings()->graphics_quality, + g_base->graphics->client_context()->auto_graphics_quality); d->step_millisecs = step_millisecs; d->cam_pos = cam_pos; @@ -174,7 +182,7 @@ void BGDynamics::Draw(FrameDef* frame_def) { // In high-quality, we draw in the overlay pass so that we don't get wiped // out by depth-of-field. - bool draw_in_overlay = (frame_def->quality() >= GraphicsQuality::kHigh); + bool draw_in_overlay = frame_def->quality() >= GraphicsQuality::kHigh; SpriteComponent c(draw_in_overlay ? frame_def->overlay_3d_pass() : frame_def->beauty_pass()); c.SetCameraAligned(true); @@ -232,7 +240,7 @@ void BGDynamics::Draw(FrameDef* frame_def) { tendrils_mesh_->SetIndexData(ds->tendril_indices); tendrils_mesh_->SetData( Object::Ref>(ds->tendril_vertices)); - bool draw_in_overlay = (frame_def->quality() >= GraphicsQuality::kHigh); + bool draw_in_overlay = frame_def->quality() >= GraphicsQuality::kHigh; SmokeComponent c(draw_in_overlay ? frame_def->overlay_3d_pass() : frame_def->beauty_pass()); c.SetOverlay(draw_in_overlay); diff --git a/src/ballistica/base/dynamics/bg/bg_dynamics_server.cc b/src/ballistica/base/dynamics/bg/bg_dynamics_server.cc index 424e46c5..d0ff57bf 100644 --- a/src/ballistica/base/dynamics/bg/bg_dynamics_server.cc +++ b/src/ballistica/base/dynamics/bg/bg_dynamics_server.cc @@ -2282,7 +2282,8 @@ void BGDynamicsServer::Step(StepData* step_data) { auto ref(Object::CompleteDeferred(step_data)); // Keep our quality in sync with the graphics thread's. - graphics_quality_ = g_base->graphics_server->graphics_quality(); + graphics_quality_ = step_data->graphics_quality; + assert(graphics_quality_ != GraphicsQuality::kUnset); cam_pos_ = step_data->cam_pos; diff --git a/src/ballistica/base/dynamics/bg/bg_dynamics_server.h b/src/ballistica/base/dynamics/bg/bg_dynamics_server.h index 46918f45..f52694f0 100644 --- a/src/ballistica/base/dynamics/bg/bg_dynamics_server.h +++ b/src/ballistica/base/dynamics/bg/bg_dynamics_server.h @@ -73,6 +73,7 @@ class BGDynamicsServer { auto GetDefaultOwnerThread() const -> EventLoopID override { return EventLoopID::kBGDynamics; } + GraphicsQuality graphics_quality{}; int step_millisecs{}; Vector3f cam_pos{0.0f, 0.0f, 0.0f}; diff --git a/src/ballistica/base/graphics/gl/program/program_gl.h b/src/ballistica/base/graphics/gl/program/program_gl.h index 437d2723..84f1f57b 100644 --- a/src/ballistica/base/graphics/gl/program/program_gl.h +++ b/src/ballistica/base/graphics/gl/program/program_gl.h @@ -238,10 +238,10 @@ class RendererGL::ProgramGL { // Update matrices as necessary. - uint32_t mvpState = + int mvp_state = g_base->graphics_server->GetModelViewProjectionMatrixState(); - if (mvpState != mvp_state_) { - mvp_state_ = mvpState; + if (mvp_state != mvp_state_) { + mvp_state_ = mvp_state; glUniformMatrix4fv( mvp_uniform_, 1, 0, g_base->graphics_server->GetModelViewProjectionMatrix().m); @@ -251,7 +251,7 @@ class RendererGL::ProgramGL { if (pflags_ & PFLAG_USES_MODEL_WORLD_MATRIX) { // With world space points this would be identity; don't waste time. assert(!(pflags_ & PFLAG_WORLD_SPACE_PTS)); - uint32_t state = g_base->graphics_server->GetModelWorldMatrixState(); + int state = g_base->graphics_server->GetModelWorldMatrixState(); if (state != model_world_matrix_state_) { model_world_matrix_state_ = state; glUniformMatrix4fv(model_world_matrix_uniform_, 1, 0, @@ -264,8 +264,7 @@ class RendererGL::ProgramGL { // With world space points this would be identity; don't waste time. assert(!(pflags_ & PFLAG_WORLD_SPACE_PTS)); // There's no state for just modelview but this works. - uint32_t state = - g_base->graphics_server->GetModelViewProjectionMatrixState(); + int state = g_base->graphics_server->GetModelViewProjectionMatrixState(); if (state != model_view_matrix_state_) { model_view_matrix_state_ = state; glUniformMatrix4fv(model_view_matrix_uniform_, 1, 0, @@ -275,7 +274,7 @@ class RendererGL::ProgramGL { BA_DEBUG_CHECK_GL_ERROR; if (pflags_ & PFLAG_USES_CAM_POS) { - uint32_t state = g_base->graphics_server->cam_pos_state(); + int state = g_base->graphics_server->cam_pos_state(); if (state != cam_pos_state_) { cam_pos_state_ = state; const Vector3f& p(g_base->graphics_server->cam_pos()); @@ -285,7 +284,7 @@ class RendererGL::ProgramGL { BA_DEBUG_CHECK_GL_ERROR; if (pflags_ & PFLAG_USES_CAM_ORIENT_MATRIX) { - uint32_t state = g_base->graphics_server->GetCamOrientMatrixState(); + int state = g_base->graphics_server->GetCamOrientMatrixState(); if (state != cam_orient_matrix_state_) { cam_orient_matrix_state_ = state; glUniformMatrix4fv(cam_orient_matrix_uniform_, 1, 0, @@ -295,7 +294,7 @@ class RendererGL::ProgramGL { BA_DEBUG_CHECK_GL_ERROR; if (pflags_ & PFLAG_USES_SHADOW_PROJECTION_MATRIX) { - uint32_t state = + int state = g_base->graphics_server->light_shadow_projection_matrix_state(); if (state != light_shadow_projection_matrix_state_) { light_shadow_projection_matrix_state_ = state; @@ -336,19 +335,19 @@ class RendererGL::ProgramGL { Object::Ref vertex_shader_; std::string name_; GLuint program_{}; - int pflags_{}; - uint32_t mvp_state_{}; GLint mvp_uniform_{}; GLint model_world_matrix_uniform_{}; GLint model_view_matrix_uniform_{}; GLint light_shadow_projection_matrix_uniform_{}; - uint32_t light_shadow_projection_matrix_state_{}; - uint32_t model_world_matrix_state_{}; - uint32_t model_view_matrix_state_{}; GLint cam_pos_uniform_{}; - uint32_t cam_pos_state_{}; GLint cam_orient_matrix_uniform_{}; - GLuint cam_orient_matrix_state_{}; + int cam_orient_matrix_state_{}; + int light_shadow_projection_matrix_state_{}; + int pflags_{}; + int mvp_state_{}; + int cam_pos_state_{}; + int model_world_matrix_state_{}; + int model_view_matrix_state_{}; BA_DISALLOW_CLASS_COPIES(ProgramGL); }; diff --git a/src/ballistica/base/graphics/gl/renderer_gl.cc b/src/ballistica/base/graphics/gl/renderer_gl.cc index ffa42e0f..adb60eae 100644 --- a/src/ballistica/base/graphics/gl/renderer_gl.cc +++ b/src/ballistica/base/graphics/gl/renderer_gl.cc @@ -366,7 +366,7 @@ void RendererGL::CheckGLCapabilities_() { // Both GL 3 and GL ES 3.0 support depth textures (and thus our high // quality mode) as a core feature. - g_base->graphics->SetSupportsHighQualityGraphics(true); + // g_base->graphics->SetSupportsHighQualityGraphics(true); // Store the tex-compression type we support. BA_DEBUG_CHECK_GL_ERROR; @@ -2598,7 +2598,8 @@ void RendererGL::RetainShader_(ProgramGL* p) { shaders_.emplace_back(p); } void RendererGL::Load() { assert(g_base->app_adapter->InGraphicsContext()); assert(!data_loaded_); - assert(g_base->graphics_server->graphics_quality_set()); + assert(g_base->graphics_server->graphics_quality() + != GraphicsQuality::kUnset); BA_DEBUG_CHECK_GL_ERROR; if (!got_screen_framebuffer_) { got_screen_framebuffer_ = true; diff --git a/src/ballistica/base/graphics/graphics.cc b/src/ballistica/base/graphics/graphics.cc index 5582a189..773e85dd 100644 --- a/src/ballistica/base/graphics/graphics.cc +++ b/src/ballistica/base/graphics/graphics.cc @@ -115,9 +115,14 @@ void Graphics::OnAppShutdownComplete() { assert(g_base->InLogicThread()); } void Graphics::DoApplyAppConfig() { assert(g_base->InLogicThread()); + // Any time we load the config we ship a new graphics-settings to + // the graphics server since something likely changed. + graphics_settings_dirty_ = true; + show_fps_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowFPS); show_ping_ = g_base->app_config->Resolve(AppConfig::BoolID::kShowPing); - tv_border_ = g_base->app_config->Resolve(AppConfig::BoolID::kEnableTVBorder); + // tv_border_ = + // g_base->app_config->Resolve(AppConfig::BoolID::kEnableTVBorder); bool disable_camera_shake = g_base->app_config->Resolve(AppConfig::BoolID::kDisableCameraShake); @@ -126,6 +131,52 @@ void Graphics::DoApplyAppConfig() { bool disable_camera_gyro = g_base->app_config->Resolve(AppConfig::BoolID::kDisableCameraGyro); set_camera_gyro_explicitly_disabled(disable_camera_gyro); + + applied_app_config_ = true; + + // At this point we may want to send initial graphics settings to the + // graphics server if we haven't. + UpdateInitialGraphicsSettingsSend_(); +} + +void Graphics::UpdateInitialGraphicsSettingsSend_() { + assert(g_base->InLogicThread()); + if (sent_initial_graphics_settings_) { + return; + } + + // We need to send an initial graphics-settings to the server to kick + // things off, but we need a few things to be in place first. + auto app_config_ready = applied_app_config_; + // At some point we may want to wait to know our actual screen res before + // sending. This won't apply everywhere though since on some platforms the + // screen doesn't exist until we send this. + auto screen_resolution_ready = true; + + if (app_config_ready && screen_resolution_ready) { + // Update/grab the current settings snapshot. + auto* settings = GetGraphicsSettingsSnapshot(); + + // We need to explicitly push settings to the graphics server to kick + // things off. We need to keep this settings instance alive until + // handled by the graphics context (which might be in another thread + // where we're not allowed to muck with settings' refs from). So let's + // explicitly increment its refcount here in the logic thread now and + // then push a call back here to decrement it when we're done. + settings->ObjectIncrementStrongRefCount(); + // auto* s = settings_.Get(); + g_base->app_adapter->PushGraphicsContextCall([settings] { + assert(g_base->app_adapter->InGraphicsContext()); + g_base->graphics_server->ApplySettings(settings->Get()); + g_base->logic->event_loop()->PushCall([settings] { + // Release our strong ref back here in the logic thread. + assert(g_base->InLogicThread()); + settings->ObjectDecrementStrongRefCount(); + }); + }); + + sent_initial_graphics_settings_ = true; + } } void Graphics::StepDisplayTime() { assert(g_base->InLogicThread()); } @@ -976,6 +1027,20 @@ auto Graphics::GetEmptyFrameDef() -> FrameDef* { return frame_def; } +auto Graphics::GetGraphicsSettingsSnapshot() -> Snapshot* { + assert(g_base->InLogicThread()); + + // If need be, ask the app-adapter to build us a new settings instance. + if (graphics_settings_dirty_) { + auto* new_settings = g_base->app_adapter->GetGraphicsSettings(); + new_settings->index = next_settings_index_++; + settings_snapshot_ = Object::New>(new_settings); + graphics_settings_dirty_ = false; + } + assert(settings_snapshot_.Exists()); + return settings_snapshot_.Get(); +} + void Graphics::ClearFrameDefDeleteList() { assert(g_base->InLogicThread()); std::scoped_lock lock(frame_def_delete_list_mutex_); @@ -1120,6 +1185,8 @@ void Graphics::DrawDevUI(FrameDef* frame_def) { void Graphics::BuildAndPushFrameDef() { assert(g_base->InLogicThread()); + + BA_PRECONDITION_FATAL(g_base->logic->app_bootstrapping_complete()); assert(camera_.Exists()); assert(!g_core->HeadlessMode()); @@ -1128,10 +1195,6 @@ void Graphics::BuildAndPushFrameDef() { assert(!building_frame_def_); building_frame_def_ = true; - // We should not be building/pushing any frames until the native - // layer is fully bootstrapped. - BA_PRECONDITION_FATAL(g_base->logic->app_bootstrapping_complete()); - microsecs_t app_time_microsecs = g_core->GetAppTimeMicrosecs(); // Store how much time this frame_def represents. @@ -1187,13 +1250,6 @@ void Graphics::BuildAndPushFrameDef() { internal_components_inited_ = true; } - // If graphics quality has changed since our last draw, inform anyone who - // wants to know. - if (last_frame_def_graphics_quality_ != frame_def->quality()) { - last_frame_def_graphics_quality_ = frame_def->quality(); - g_base->app_mode()->GraphicsQualityChanged(frame_def->quality()); - } - ApplyCamera(frame_def); if (progress_bar_) { @@ -1254,7 +1310,7 @@ void Graphics::BuildAndPushFrameDef() { RunCleanFrameCommands(); } - frame_def->Finalize(); + frame_def->Complete(); // Include all mesh-data loads and unloads that have accumulated up to // this point the graphics thread will have to handle these before @@ -1555,11 +1611,6 @@ void Graphics::DrawBlotches(FrameDef* frame_def) { } } -void Graphics::SetSupportsHighQualityGraphics(bool s) { - supports_high_quality_graphics_ = s; - has_supports_high_quality_graphics_value_ = true; -} - void Graphics::ClearScreenMessageTranslations() { assert(g_base && g_base->InLogicThread()); for (auto&& i : screen_messages_) { @@ -1922,20 +1973,55 @@ auto Graphics::ScreenMessageEntry::GetText() -> TextGroup& { void Graphics::OnScreenSizeChange() {} -void Graphics::SetScreenSize(float virtual_width, float virtual_height, - float pixel_width, float pixel_height) { +void Graphics::CalcVirtualRes_(float* x, float* y) { + float x_in = *x; + float y_in = *y; + if (*x / *y > static_cast(kBaseVirtualResX) + / static_cast(kBaseVirtualResY)) { + *y = kBaseVirtualResY; + *x = *y * (x_in / y_in); + } else { + *x = kBaseVirtualResX; + *y = *x * (y_in / x_in); + } +} + +void Graphics::SetScreenResolution(float x, float y) { assert(g_base->InLogicThread()); - res_x_virtual_ = virtual_width; - res_y_virtual_ = virtual_height; - res_x_ = pixel_width; - res_y_ = pixel_height; + + // Ignore redundant sets. + if (res_x_ == x && res_y_ == y) { + return; + } + + // We'll need to ship a new settings to the server with this change. + graphics_settings_dirty_ = true; + + res_x_ = x; + res_y_ = y; + + // Calc virtual res. In vr mode our virtual res is independent of our + // screen size (since it gets drawn to an overlay). + if (g_core->IsVRMode()) { + res_x_virtual_ = kBaseVirtualResX; + res_y_virtual_ = kBaseVirtualResY; + } else { + res_x_virtual_ = res_x_; + res_y_virtual_ = res_y_; + CalcVirtualRes_(&res_x_virtual_, &res_y_virtual_); + } // Need to rebuild internal components (some are sized to the screen). internal_components_inited_ = false; - // This will inform all applicable logic thread subsystems. - g_base->logic->OnScreenSizeChange(virtual_width, virtual_height, pixel_width, - pixel_height); + // Inform all our logic thread buddies of this change. + g_base->logic->OnScreenSizeChange(res_x_virtual_, res_y_virtual_, res_x_, + res_y_); + + // This may trigger us sending initial graphics settings to the + // graphics-server to kick off drawing. + got_screen_resolution_ = true; + UpdateInitialGraphicsSettingsSend_(); } void Graphics::ScreenMessageEntry::UpdateTranslation() { @@ -2030,4 +2116,61 @@ void Graphics::LanguageChanged() { ClearScreenMessageTranslations(); } +auto Graphics::GraphicsQualityFromRequest(GraphicsQualityRequest request, + GraphicsQuality auto_val) + -> GraphicsQuality { + switch (request) { + case GraphicsQualityRequest::kLow: + return GraphicsQuality::kLow; + case GraphicsQualityRequest::kMedium: + return GraphicsQuality::kMedium; + case GraphicsQualityRequest::kHigh: + return GraphicsQuality::kHigh; + case GraphicsQualityRequest::kHigher: + return GraphicsQuality::kHigher; + case GraphicsQualityRequest::kAuto: + return auto_val; + default: + Log(LogLevel::kError, "Unhandled GraphicsQualityRequest value: " + + std::to_string(static_cast(request))); + return GraphicsQuality::kLow; + } +} +auto Graphics::TextureQualityFromRequest(TextureQualityRequest request, + TextureQuality auto_val) + -> TextureQuality { + switch (request) { + case TextureQualityRequest::kLow: + return TextureQuality::kLow; + case TextureQualityRequest::kMedium: + return TextureQuality::kMedium; + case TextureQualityRequest::kHigh: + return TextureQuality::kHigh; + case TextureQualityRequest::kAuto: + return auto_val; + default: + Log(LogLevel::kError, "Unhandled TextureQualityRequest value: " + + std::to_string(static_cast(request))); + return TextureQuality::kLow; + } +} + +void Graphics::set_client_context(Snapshot* context) { + assert(g_base->InLogicThread()); + + // Currently we only expect this to be set once. That will change + // once we support renderer swapping/etc. + assert(!g_base->logic->graphics_ready()); + assert(!client_context_snapshot_.Exists()); + client_context_snapshot_ = context; + + // Update our static placeholder value (we don't want to calc it dynamically + // since it can be accessed from other threads). + texture_quality_placeholder_ = TextureQualityFromRequest( + settings()->texture_quality, client_context()->auto_texture_quality); + + // Let the logic system know its free to proceed beyond bootstrapping. + g_base->logic->OnGraphicsReady(); +} + } // namespace ballistica::base diff --git a/src/ballistica/base/graphics/graphics.h b/src/ballistica/base/graphics/graphics.h index 92e6c18f..022e58d8 100644 --- a/src/ballistica/base/graphics/graphics.h +++ b/src/ballistica/base/graphics/graphics.h @@ -6,13 +6,15 @@ #include #include #include -#include #include #include #include "ballistica/base/base.h" +#include "ballistica/base/graphics/support/graphics_client_context.h" +#include "ballistica/base/graphics/support/graphics_settings.h" #include "ballistica/shared/foundation/object.h" #include "ballistica/shared/foundation/types.h" +#include "ballistica/shared/generic/snapshot.h" #include "ballistica/shared/math/matrix44f.h" #include "ballistica/shared/math/rect.h" #include "ballistica/shared/math/vector2f.h" @@ -62,10 +64,10 @@ class Graphics { void OnScreenSizeChange(); void DoApplyAppConfig(); - /// Called by the graphics server to keep us up to date in the logic - /// thread. Dispatches the news to all logic subsystems that care. - void SetScreenSize(float virtual_width, float virtual_height, - float physical_width, float physical_height); + /// Should be called by the app-adapter to keep the engine informed + /// on the drawable area it has to work with (in pixels). + void SetScreenResolution(float x, float y); + void StepDisplayTime(); auto TextureQualityFromAppConfig() -> TextureQualityRequest; @@ -97,13 +99,25 @@ class Graphics { // Called when the GraphicsServer has sent us a frame-def for deletion. void ReturnCompletedFrameDef(FrameDef* frame_def); - auto screen_pixel_width() const { return res_x_; } - auto screen_pixel_height() const { return res_y_; } + auto screen_pixel_width() const { + assert(g_base->InLogicThread()); + return res_x_; + } + auto screen_pixel_height() const { + assert(g_base->InLogicThread()); + return res_y_; + } - // Return the size of the virtual screen. This value should always + // Return the current size of the virtual screen. This value should always // be used for interface positioning, etc. - auto screen_virtual_width() const { return res_x_virtual_; } - auto screen_virtual_height() const { return res_y_virtual_; } + auto screen_virtual_width() const { + assert(g_base->InLogicThread()); + return res_x_virtual_; + } + auto screen_virtual_height() const { + assert(g_base->InLogicThread()); + return res_y_virtual_; + } void ClearScreenMessageTranslations(); @@ -226,10 +240,10 @@ class Graphics { float upper_top); void ReleaseFadeEndCommand(); - auto tv_border() const { - assert(g_base->InLogicThread()); - return tv_border_; - } + // 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. @@ -270,17 +284,6 @@ class Graphics { return y * (res_y_virtual_ / res_y_); } - // FIXME: This should probably move to Renderer or AppAdapter once we - // support switching renderers. - auto supports_high_quality_graphics() const { - assert(has_supports_high_quality_graphics_value_); - return supports_high_quality_graphics_; - } - void SetSupportsHighQualityGraphics(bool s); - auto has_supports_high_quality_graphics_value() const { - return has_supports_high_quality_graphics_value_; - } - void set_internal_components_inited(bool val) { internal_components_inited_ = val; } @@ -322,19 +325,65 @@ class Graphics { camera_gyro_explicitly_disabled_ = disabled; } + auto* settings() const { + assert(g_base->InLogicThread()); + assert(settings_snapshot_.Exists()); + return settings_snapshot_.Get()->Get(); + } + + auto GetGraphicsSettingsSnapshot() -> Snapshot*; + + /// Called by the graphics-server when a new client context is ready. + void set_client_context(Snapshot* context); + + auto has_client_context() -> bool { + return client_context_snapshot_.Exists(); + } + + auto client_context() const -> const GraphicsClientContext* { + assert(g_base->InLogicThread()); + assert(client_context_snapshot_.Exists()); + return client_context_snapshot_.Get()->Get(); + } + + static auto GraphicsQualityFromRequest(GraphicsQualityRequest request, + GraphicsQuality auto_val) + -> GraphicsQuality; + static auto TextureQualityFromRequest(TextureQualityRequest request, + TextureQuality auto_val) + -> TextureQuality; + + /// For temporary use from arbitrary threads. This should be removed when + /// possible and replaced with proper safe thread-specific access patterns + /// (so we can support switching renderers/etc.). + auto placeholder_texture_quality() const { + assert(client_context_snapshot_.Exists()); + return texture_quality_placeholder_; + } + + /// 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.). + 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 + // can happen though. + assert(client_context_snapshot_.Exists()); + return client_context_snapshot_.Get()->Get(); + } + protected: + class ScreenMessageEntry; + Graphics(); virtual ~Graphics(); virtual void DoDrawFade(FrameDef* frame_def, float amt); - - private: - class ScreenMessageEntry; + static void CalcVirtualRes_(float* x, float* y); void DrawBoxingGlovesTest(FrameDef* frame_def); void DrawBlotches(FrameDef* frame_def); void DrawCursor(FrameDef* frame_def); void DrawFades(FrameDef* frame_def); void DrawDebugBuffers(RenderPass* pass); - void UpdateAndDrawProgressBar(FrameDef* frame_def); void DoDrawBlotch(std::vector* indices, std::vector* verts, const Vector3f& pos, @@ -347,44 +396,47 @@ class Graphics { void DrawProgressBar(RenderPass* pass, float opacity); void UpdateProgressBarProgress(float target); void UpdateGyro(microsecs_t time, microsecs_t elapsed); + void UpdateInitialGraphicsSettingsSend_(); - bool drawing_transparent_only_{}; - bool drawing_opaque_only_{}; - bool has_supports_high_quality_graphics_value_{}; - bool supports_high_quality_graphics_{}; - bool internal_components_inited_{}; - bool fade_out_{true}; - bool progress_bar_{}; - bool progress_bar_fade_in_{}; - bool debug_draw_{}; - bool network_debug_display_enabled_{}; - bool hardware_cursor_visible_{}; - bool camera_shake_disabled_{}; - bool camera_gyro_explicitly_disabled_{}; - bool gyro_enabled_{true}; - bool show_fps_{}; - bool show_ping_{}; - bool show_net_info_{}; - bool tv_border_{}; - bool floor_reflection_{}; - bool building_frame_def_{}; - bool shadow_ortho_{}; - bool fetched_overlay_node_z_depth_{}; - bool gyro_broken_{}; - GraphicsQuality last_frame_def_graphics_quality_{GraphicsQuality::kUnset}; - std::list> clean_frame_commands_; - std::vector mesh_data_creates_; - std::vector mesh_data_destroys_; - microsecs_t last_create_frame_def_time_microsecs_{}; - millisecs_t last_create_frame_def_time_millisecs_{}; + int last_total_frames_rendered_{}; + int last_fps_{}; + int progress_bar_loads_{}; + int frame_def_count_{}; + int frame_def_count_filtered_{}; + int next_settings_index_{}; + TextureQuality texture_quality_placeholder_{}; + bool drawing_transparent_only_ : 1 {}; + bool drawing_opaque_only_ : 1 {}; + bool internal_components_inited_ : 1 {}; + bool fade_out_ : 1 {true}; + bool progress_bar_ : 1 {}; + bool progress_bar_fade_in_ : 1 {}; + bool debug_draw_ : 1 {}; + bool network_debug_display_enabled_ : 1 {}; + bool hardware_cursor_visible_ : 1 {}; + bool camera_shake_disabled_ : 1 {}; + bool camera_gyro_explicitly_disabled_ : 1 {}; + bool gyro_enabled_ : 1 {true}; + bool show_fps_ : 1 {}; + bool show_ping_ : 1 {}; + bool show_net_info_ : 1 {}; + bool tv_border_ : 1 {}; + bool floor_reflection_ : 1 {}; + bool building_frame_def_ : 1 {}; + bool shadow_ortho_ : 1 {}; + bool fetched_overlay_node_z_depth_ : 1 {}; + bool gyro_broken_ : 1 {}; + bool set_fade_start_on_next_draw_ : 1 {}; + bool graphics_settings_dirty_ : 1 {true}; + bool applied_app_config_ : 1 {}; + bool sent_initial_graphics_settings_ : 1 {}; + bool got_screen_resolution_ : 1 {}; Vector3f shadow_offset_{0.0f, 0.0f, 0.0f}; Vector2f shadow_scale_{1.0f, 1.0f}; Vector3f tint_{1.0f, 1.0f, 1.0f}; Vector3f ambient_color_{1.0f, 1.0f, 1.0f}; Vector3f vignette_outer_{0.0f, 0.0f, 0.0f}; Vector3f vignette_inner_{1.0f, 1.0f, 1.0f}; - std::vector recycle_frame_defs_; - millisecs_t last_jitter_update_time_{}; Vector3f jitter_{0.0f, 0.0f, 0.0f}; Vector3f accel_smoothed_{0.0f, 0.0f, 0.0f}; Vector3f accel_smoothed2_{0.0f, 0.0f, 0.0f}; @@ -394,8 +446,50 @@ class Graphics { Vector3f tilt_smoothed_{0.0f, 0.0f, 0.0f}; Vector3f tilt_vel_{0.0f, 0.0f, 0.0f}; Vector3f tilt_pos_{0.0f, 0.0f, 0.0f}; + Vector3f gyro_vals_{0.0f, 0.0, 0.0f}; + std::string fps_string_; + std::string ping_string_; + std::string net_info_string_; + 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_; + std::vector blotch_soft_indices_; + std::vector blotch_soft_verts_; + std::vector blotch_soft_obj_indices_; + std::vector blotch_soft_obj_verts_; + std::vector frame_def_delete_list_; + std::vector mesh_data_creates_; + std::vector mesh_data_destroys_; + float fade_{}; + float res_x_{256.0f}; + float res_y_{256.0f}; + float res_x_virtual_{256.0f}; + float res_y_virtual_{256.0f}; 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}; + float shadow_upper_top_{40.0f}; + 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_{}; + millisecs_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_{}; Object::Ref screen_mesh_; Object::Ref progress_bar_bottom_mesh_; Object::Ref progress_bar_top_mesh_; @@ -406,49 +500,10 @@ class Graphics { Object::Ref shadow_blotch_mesh_; Object::Ref shadow_blotch_soft_mesh_; Object::Ref shadow_blotch_soft_obj_mesh_; - std::string fps_string_; - std::string ping_string_; - std::string net_info_string_; - std::vector blotch_indices_; - std::vector blotch_verts_; - std::vector blotch_soft_indices_; - std::vector blotch_soft_verts_; - std::vector blotch_soft_obj_indices_; - std::vector blotch_soft_obj_verts_; - std::map> debug_graphs_; - std::mutex frame_def_delete_list_mutex_; - std::vector frame_def_delete_list_; Object::Ref camera_; - millisecs_t next_stat_update_time_{}; - int last_total_frames_rendered_{}; - int last_fps_{}; - std::list screen_messages_; - std::list screen_messages_top_; - bool set_fade_start_on_next_draw_{}; - millisecs_t fade_start_{}; - millisecs_t fade_time_{}; - float fade_{}; - Vector3f gyro_vals_{0.0f, 0.0, 0.0f}; - float res_x_{100}; - float res_y_{100}; - float res_x_virtual_{100}; - float res_y_virtual_{100}; - int progress_bar_loads_{}; - millisecs_t progress_bar_end_time_{-9999}; - millisecs_t last_progress_bar_draw_time_{}; - millisecs_t last_progress_bar_start_time_{}; - 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}; - float shadow_upper_top_{40.0f}; - millisecs_t last_cursor_visibility_event_time_{}; - microsecs_t next_frame_number_filtered_increment_time_{}; - int64_t frame_def_count_{}; - int64_t frame_def_count_filtered_{}; - microsecs_t last_suppress_gyro_time_{}; Object::Ref fade_end_call_; + Object::Ref> settings_snapshot_; + Object::Ref> client_context_snapshot_; }; } // namespace ballistica::base diff --git a/src/ballistica/base/graphics/graphics_server.cc b/src/ballistica/base/graphics/graphics_server.cc index 8a89c655..33025a94 100644 --- a/src/ballistica/base/graphics/graphics_server.cc +++ b/src/ballistica/base/graphics/graphics_server.cc @@ -32,15 +32,88 @@ void GraphicsServer::EnqueueFrameDef(FrameDef* framedef) { } } +void GraphicsServer::ApplySettings(const GraphicsSettings* settings) { + assert(g_base->InGraphicsContext()); + + // Only push each unique settings instance through once. + if (settings->index == settings_index_) { + return; + } + settings_index_ = settings->index; + + assert(settings->resolution.x >= 0.0f && settings->resolution.y >= 0.0f + && settings->resolution_virtual.x >= 0.0f + && settings->resolution_virtual.y >= 0.0f); + + // Pull a few things out ourself such as screen resolution. + tv_border_ = settings->tv_border; + if (renderer_) { + renderer_->set_pixel_scale(settings->pixel_scale); + } + // Note: not checking virtual res here; assuming it only changes when + // actual res changes. + if (res_x_ != settings->resolution.x || res_y_ != settings->resolution.y) { + res_x_ = settings->resolution.x; + res_y_ = settings->resolution.y; + res_x_virtual_ = settings->resolution_virtual.x; + res_y_virtual_ = settings->resolution_virtual.y; + if (renderer_) { + renderer_->OnScreenSizeChange(); + } + } + + // Kick this over to the app-adapter to apply whatever settings they + // gathered for themself. + g_base->app_adapter->ApplyGraphicsSettings(settings); + + // Lastly, if we've not yet sent a context to the client, do so. + if (client_context_ == nullptr) { + set_client_context(g_base->app_adapter->GetGraphicsClientContext()); + } +} + +void GraphicsServer::set_client_context(GraphicsClientContext* context) { + assert(g_base->InGraphicsContext()); + + // We have to do a bit of a song and dance with these context pointers. + // We wrap the context in an immutable object wrapper which is owned by + // the logic thread and that takes care of killing it when no longer + // used there, but we also need to keep it alive here in our thread. + // (which may not be the logic thread). So to accomplish that, we + // immediately ship a refcount increment over to the logic thread, and + // once we're done with an obj we ship a decrement. + + auto* old_wrapper = client_context_; + auto* new_wrapper = + Object::NewDeferred>(context); + + client_context_ = new_wrapper; + + g_base->logic->event_loop()->PushCall([old_wrapper, new_wrapper] { + // (This has to happen in logic thread). + auto ref = Object::CompleteDeferred(new_wrapper); + + // Free the old one which the graphics server doesn't need anymore. + if (old_wrapper) { + old_wrapper->ObjectDecrementStrongRefCount(); + } + + // Keep the new one alive for the graphics server. + ref->ObjectIncrementStrongRefCount(); + + // Plug the new one in for logic to start using. + g_base->graphics->set_client_context(new_wrapper); + }); +} + auto GraphicsServer::TryRender() -> bool { assert(g_base->app_adapter->InGraphicsContext()); bool success{}; if (FrameDef* frame_def = WaitForRenderFrameDef_()) { - // Apply settings such as tv-mode that were passed along via the - // frame-def. - ApplyFrameDefSettings(frame_def); + // Apply any new graphics settings passed along via the frame-def. + ApplySettings(frame_def->settings()); // Note: we run mesh-updates on each frame-def that comes through even // if we don't actually render the frame. @@ -58,6 +131,7 @@ auto GraphicsServer::TryRender() -> bool { // Send this frame_def back to the logic thread for deletion or recycling. g_base->graphics->ReturnCompletedFrameDef(frame_def); } + return success; } @@ -113,11 +187,6 @@ auto GraphicsServer::WaitForRenderFrameDef_() -> FrameDef* { return nullptr; } -void GraphicsServer::ApplyFrameDefSettings(FrameDef* frame_def) { - assert(g_base->app_adapter->InGraphicsContext()); - tv_border_ = frame_def->tv_border(); -} - // Runs any mesh updates contained in the frame-def. void GraphicsServer::RunFrameDefMeshUpdates(FrameDef* frame_def) { assert(g_base->app_adapter->InGraphicsContext()); @@ -250,14 +319,15 @@ void GraphicsServer::SetNullGraphics() { SetTextureCompressionTypes(c_types); graphics_quality_requested_ = GraphicsQualityRequest::kLow; graphics_quality_ = GraphicsQuality::kLow; - graphics_quality_set_ = true; + // graphics_quality_set_ = true; texture_quality_requested_ = TextureQualityRequest::kLow; texture_quality_ = TextureQuality::kLow; - texture_quality_set_ = true; + // texture_quality_set_ = true; + FatalError("FIXME REWORK THIS"); // Let the logic thread know screen creation is done (or lack thereof). - g_base->logic->event_loop()->PushCall( - [] { g_base->logic->OnGraphicsReady(); }); + // g_base->logic->event_loop()->PushCall( + // [] { g_base->logic->OnGraphicsReady(); }); } void GraphicsServer::set_renderer(Renderer* renderer) { @@ -279,59 +349,43 @@ void GraphicsServer::LoadRenderer() { return; } - switch (graphics_quality_requested_) { - case GraphicsQualityRequest::kLow: - graphics_quality_ = GraphicsQuality::kLow; - break; - case GraphicsQualityRequest::kMedium: - graphics_quality_ = GraphicsQuality::kMedium; - break; - case GraphicsQualityRequest::kHigh: - graphics_quality_ = GraphicsQuality::kHigh; - break; - case GraphicsQualityRequest::kHigher: - graphics_quality_ = GraphicsQuality::kHigher; - break; - case GraphicsQualityRequest::kAuto: - graphics_quality_ = renderer_->GetAutoGraphicsQuality(); - break; - default: - Log(LogLevel::kError, - "Unhandled GraphicsQualityRequest value: " - + std::to_string(static_cast(graphics_quality_requested_))); - graphics_quality_ = GraphicsQuality::kLow; - } + graphics_quality_ = Graphics::GraphicsQualityFromRequest( + graphics_quality_requested_, renderer_->GetAutoGraphicsQuality()); + + 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; + // 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; + // 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(); @@ -389,56 +443,56 @@ void GraphicsServer::UnloadRenderer() { } // Given physical res, calculate virtual res. -void GraphicsServer::CalcVirtualRes_(float* x, float* y) { - float x_in = *x; - float y_in = *y; - if (*x / *y > static_cast(kBaseVirtualResX) - / static_cast(kBaseVirtualResY)) { - *y = kBaseVirtualResY; - *x = *y * (x_in / y_in); - } else { - *x = kBaseVirtualResX; - *y = *x * (y_in / x_in); - } -} +// void GraphicsServer::CalcVirtualRes_(float* x, float* y) { +// float x_in = *x; +// float y_in = *y; +// if (*x / *y > static_cast(kBaseVirtualResX) +// / static_cast(kBaseVirtualResY)) { +// *y = kBaseVirtualResY; +// *x = *y * (x_in / y_in); +// } else { +// *x = kBaseVirtualResX; +// *y = *x * (y_in / x_in); +// } +// } -void GraphicsServer::UpdateVirtualScreenRes_() { - assert(g_base->app_adapter->InGraphicsContext()); +// void GraphicsServer::UpdateVirtualScreenRes_() { +// assert(g_base->app_adapter->InGraphicsContext()); - // In vr mode our virtual res is independent of our screen size. - // (since it gets drawn to an overlay) - if (g_core->IsVRMode()) { - res_x_virtual_ = kBaseVirtualResX; - res_y_virtual_ = kBaseVirtualResY; - } else { - res_x_virtual_ = res_x_; - res_y_virtual_ = res_y_; - CalcVirtualRes_(&res_x_virtual_, &res_y_virtual_); - } -} +// // In vr mode our virtual res is independent of our screen size. +// // (since it gets drawn to an overlay) +// if (g_core->IsVRMode()) { +// res_x_virtual_ = kBaseVirtualResX; +// res_y_virtual_ = kBaseVirtualResY; +// } else { +// res_x_virtual_ = res_x_; +// res_y_virtual_ = res_y_; +// CalcVirtualRes_(&res_x_virtual_, &res_y_virtual_); +// } +// } -void GraphicsServer::SetScreenResolution(float h, float v) { - assert(g_base->app_adapter->InGraphicsContext()); +// void GraphicsServer::SetScreenResolution(float h, float v) { +// assert(g_base->app_adapter->InGraphicsContext()); - // Ignore redundant sets. - if (res_x_ == h && res_y_ == v) { - return; - } - res_x_ = h; - res_y_ = v; - UpdateVirtualScreenRes_(); +// // Ignore redundant sets. +// if (res_x_ == h && res_y_ == v) { +// return; +// } +// res_x_ = h; +// res_y_ = v; +// // UpdateVirtualScreenRes_(); - // Inform renderer of the change. - if (renderer_) { - renderer_->OnScreenSizeChange(); - } +// // Inform renderer of the change. +// if (renderer_) { +// renderer_->OnScreenSizeChange(); +// } - // Inform all logic thread bits of this change. - g_base->logic->event_loop()->PushCall( - [vx = res_x_virtual_, vy = res_y_virtual_, x = res_x_, y = res_y_] { - g_base->graphics->SetScreenSize(vx, vy, x, y); - }); -} +// // Inform all logic thread bits of this change. +// g_base->logic->event_loop()->PushCall( +// [vx = res_x_virtual_, vy = res_y_virtual_, x = res_x_, y = res_y_] { +// g_base->graphics->SetScreenSize(vx, vy, x, y); +// }); +// } // FIXME: Shouldn't have android-specific code in here. void GraphicsServer::HandlePushAndroidRes(const std::string& android_res) { @@ -579,15 +633,15 @@ void GraphicsServer::PushReloadMediaCall() { g_base->app_adapter->PushGraphicsContextCall([this] { ReloadMedia_(); }); } -void GraphicsServer::PushSetScreenPixelScaleCall(float pixel_scale) { - g_base->app_adapter->PushGraphicsContextCall([this, pixel_scale] { - assert(g_base->app_adapter->InGraphicsContext()); - if (!renderer_) { - return; - } - renderer_->set_pixel_scale(pixel_scale); - }); -} +// void GraphicsServer::PushSetScreenPixelScaleCall(float pixel_scale) { +// g_base->app_adapter->PushGraphicsContextCall([this, pixel_scale] { +// assert(g_base->app_adapter->InGraphicsContext()); +// if (!renderer_) { +// return; +// } +// renderer_->set_pixel_scale(pixel_scale); +// }); +// } void GraphicsServer::PushComponentUnloadCall( const std::vector*>& components) { diff --git a/src/ballistica/base/graphics/graphics_server.h b/src/ballistica/base/graphics/graphics_server.h index 40309f8d..abc333f2 100644 --- a/src/ballistica/base/graphics/graphics_server.h +++ b/src/ballistica/base/graphics/graphics_server.h @@ -11,6 +11,7 @@ #include "ballistica/base/base.h" #include "ballistica/shared/foundation/object.h" +#include "ballistica/shared/generic/snapshot.h" #include "ballistica/shared/math/matrix44f.h" namespace ballistica::base { @@ -51,16 +52,18 @@ class GraphicsServer { return renderer_loaded_; } + void ApplySettings(const GraphicsSettings* settings); + /// The AppAdapter should call this to inform the engine of screen size /// changes. Changes will be applied to the server and then sent to the /// logic thread to apply to various app systems (ui, etc.). - void SetScreenResolution(float h, float v); + // void SetScreenResolution(float h, float v); /// Used by headless builds to init the graphics-server into a /// non-functional state. void SetNullGraphics(); - void PushSetScreenPixelScaleCall(float pixel_scale); + // void PushSetScreenPixelScaleCall(float pixel_scale); void PushReloadMediaCall(); void PushRemoveRenderHoldCall(); void PushComponentUnloadCall( @@ -71,8 +74,6 @@ class GraphicsServer { /// rendering. void EnqueueFrameDef(FrameDef* framedef); - void ApplyFrameDefSettings(FrameDef* frame_def); - void RunFrameDefMeshUpdates(FrameDef* frame_def); // Renders shadow passes and other common parts of a frame_def. @@ -108,9 +109,7 @@ class GraphicsServer { projection_matrix_state_++; } - auto projection_matrix_state() -> uint32_t { - return projection_matrix_state_; - } + auto projection_matrix_state() { return projection_matrix_state_; } void SetLightShadowProjectionMatrix(const Matrix44f& p) { // This will generally get repeatedly set to the same value @@ -121,61 +120,57 @@ class GraphicsServer { } } - auto light_shadow_projection_matrix_state() const -> uint32_t { + auto light_shadow_projection_matrix_state() const { return light_shadow_projection_matrix_state_; } - auto light_shadow_projection_matrix() const -> const Matrix44f& { + const auto& light_shadow_projection_matrix() const { return light_shadow_projection_matrix_; } // Return the modelview * projection matrix. - auto GetModelViewProjectionMatrix() -> const Matrix44f& { + const auto& GetModelViewProjectionMatrix() { UpdateModelViewProjectionMatrix_(); return model_view_projection_matrix_; } - auto GetModelViewProjectionMatrixState() -> uint32_t { + auto GetModelViewProjectionMatrixState() { UpdateModelViewProjectionMatrix_(); return model_view_projection_matrix_state_; } - auto GetModelWorldMatrix() -> const Matrix44f& { + const auto& GetModelWorldMatrix() { UpdateModelWorldMatrix_(); return model_world_matrix_; } - auto GetModelWorldMatrixState() -> uint32_t { + auto GetModelWorldMatrixState() { UpdateModelWorldMatrix_(); return model_world_matrix_state_; } - auto cam_pos() -> const Vector3f& { return cam_pos_; } + const auto& cam_pos() { return cam_pos_; } - auto cam_pos_state() -> uint32_t { return cam_pos_state_; } + auto cam_pos_state() { return cam_pos_state_; } - auto GetCamOrientMatrix() -> const Matrix44f& { + const auto& GetCamOrientMatrix() { UpdateCamOrientMatrix_(); return cam_orient_matrix_; } - auto GetCamOrientMatrixState() -> uint32_t { + auto GetCamOrientMatrixState() { UpdateCamOrientMatrix_(); return cam_orient_matrix_state_; } - auto model_view_matrix() const -> const Matrix44f& { - return model_view_matrix_; - } + const auto& model_view_matrix() const { return model_view_matrix_; } void SetModelViewMatrix(const Matrix44f& m) { model_view_matrix_ = m; model_view_projection_matrix_dirty_ = model_world_matrix_dirty_ = true; } - auto projection_matrix() const -> const Matrix44f& { - return projection_matrix_; - } + const auto& projection_matrix() const { return projection_matrix_; } void PushTransform() { model_view_stack_.push_back(model_view_matrix_); @@ -209,32 +204,34 @@ class GraphicsServer { model_view_projection_matrix_dirty_ = model_world_matrix_dirty_ = true; } - auto quality() const -> GraphicsQuality { - assert(graphics_quality_set_); + auto quality() const { + assert(InGraphicsContext_()); + assert(graphics_quality_ != GraphicsQuality::kUnset); return graphics_quality_; } - auto texture_quality() const -> TextureQuality { - assert(texture_quality_set_); + auto texture_quality() const { + assert(InGraphicsContext_()); + assert(texture_quality_ != TextureQuality::kUnset); return texture_quality_; } - auto screen_pixel_width() const -> float { + auto screen_pixel_width() const { assert(InGraphicsContext_()); return res_x_; } - auto screen_pixel_height() const -> float { + auto screen_pixel_height() const { assert(InGraphicsContext_()); return res_y_; } - auto screen_virtual_width() const -> float { + auto screen_virtual_width() const { assert(InGraphicsContext_()); return res_x_virtual_; } - auto screen_virtual_height() const -> float { + auto screen_virtual_height() const { assert(InGraphicsContext_()); return res_y_virtual_; } @@ -244,45 +241,69 @@ class GraphicsServer { return tv_border_; } - auto graphics_quality_set() const { return graphics_quality_set_; } + // auto graphics_quality_set() const { + // return graphics_quality_ != GraphicsQuality::kUnset; + // } - auto texture_quality_set() const { return texture_quality_set_; } + // auto texture_quality_set() const { + // return texture_quality_ != TextureQuality::kUnset; + // } auto SupportsTextureCompressionType(TextureCompressionType t) const -> bool { + assert(InGraphicsContext_()); assert(texture_compression_types_set_); return ((texture_compression_types_ & (0x01u << static_cast(t))) != 0u); } + void SetTextureCompressionTypes( const std::list& types); - auto texture_compression_types_are_set() const { - return texture_compression_types_set_; - } + // 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_; } auto graphics_quality_requested() const { + assert(InGraphicsContext_()); return graphics_quality_requested_; } void set_graphics_quality_requested(GraphicsQualityRequest val) { + assert(InGraphicsContext_()); graphics_quality_requested_ = val; } void set_texture_quality_requested(TextureQualityRequest val) { + assert(InGraphicsContext_()); texture_quality_requested_ = val; } - auto graphics_quality() const { return graphics_quality_; } + auto graphics_quality() const { + assert(InGraphicsContext_()); + return graphics_quality_; + } - auto texture_quality_requested() const { return texture_quality_requested_; } + auto texture_quality_requested() const { + assert(InGraphicsContext_()); + return texture_quality_requested_; + } void HandlePushAndroidRes(const std::string& android_res); + auto texture_compression_types() const { + assert(texture_compression_types_set_); + return texture_compression_types_; + } + private: + /// Pass a freshly allocated GraphicsContext instance, which the graphics + /// system will take ownership of. + void set_client_context(GraphicsClientContext* context); + // So we don't have to include app_adapter.h here for asserts. auto InGraphicsContext_() const -> bool; @@ -293,8 +314,8 @@ class GraphicsServer { auto WaitForRenderFrameDef_() -> FrameDef*; // Update virtual screen dimensions based on the current physical ones. - static void CalcVirtualRes_(float* x, float* y); - void UpdateVirtualScreenRes_(); + // static void CalcVirtualRes_(float* x, float* y); + // void UpdateVirtualScreenRes_(); void UpdateCamOrientMatrix_(); void ReloadMedia_(); void UpdateModelViewProjectionMatrix_() { @@ -314,23 +335,17 @@ class GraphicsServer { } bool renderer_loaded_ : 1 {}; - bool v_sync_ : 1 {}; - bool auto_vsync_ : 1 {}; bool model_view_projection_matrix_dirty_ : 1 {true}; bool model_world_matrix_dirty_ : 1 {true}; - bool graphics_quality_set_ : 1 {}; - bool texture_quality_set_ : 1 {}; bool tv_border_ : 1 {}; bool renderer_context_lost_ : 1 {}; bool texture_compression_types_set_ : 1 {}; bool cam_orient_matrix_dirty_ : 1 {true}; - TextureQualityRequest texture_quality_requested_{ - TextureQualityRequest::kUnset}; - TextureQuality texture_quality_{TextureQuality::kLow}; - GraphicsQualityRequest graphics_quality_requested_{ - GraphicsQualityRequest::kUnset}; - GraphicsQuality graphics_quality_{GraphicsQuality::kUnset}; - int render_hold_{}; + 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_{}; @@ -340,20 +355,21 @@ class GraphicsServer { Matrix44f projection_matrix_{kMatrix44fIdentity}; Matrix44f model_view_projection_matrix_{kMatrix44fIdentity}; Matrix44f model_world_matrix_{kMatrix44fIdentity}; - std::vector model_view_stack_; uint32_t texture_compression_types_{}; - uint32_t projection_matrix_state_{1}; - uint32_t model_view_projection_matrix_state_{1}; - uint32_t model_world_matrix_state_{1}; - uint32_t light_shadow_projection_matrix_state_{1}; - uint32_t cam_pos_state_{1}; - uint32_t cam_orient_matrix_state_{1}; + int render_hold_{}; + int projection_matrix_state_{}; + int model_view_projection_matrix_state_{}; + int model_world_matrix_state_{}; + int light_shadow_projection_matrix_state_{}; + int cam_pos_state_{}; + int cam_orient_matrix_state_{}; + int settings_index_{-1}; Vector3f cam_pos_{0.0f, 0.0f, 0.0f}; Vector3f cam_target_{0.0f, 0.0f, 0.0f}; Matrix44f light_shadow_projection_matrix_{kMatrix44fIdentity}; Matrix44f cam_orient_matrix_ = kMatrix44fIdentity; + std::vector model_view_stack_; std::list mesh_datas_; - Timer* render_timer_{}; Renderer* renderer_{}; FrameDef* frame_def_{}; std::mutex frame_def_mutex_{}; diff --git a/src/ballistica/base/graphics/renderer/render_pass.cc b/src/ballistica/base/graphics/renderer/render_pass.cc index 966dbbda..39a265b1 100644 --- a/src/ballistica/base/graphics/renderer/render_pass.cc +++ b/src/ballistica/base/graphics/renderer/render_pass.cc @@ -487,7 +487,7 @@ void RenderPass::SetFrustum(float near_val, float far_val) { g_base->graphics_server->SetProjectionMatrix(projection_matrix_); } -void RenderPass::Finalize() { +void RenderPass::Complete() { if (UsesWorldLists()) { for (auto& command : commands_) { command->Finalize(); diff --git a/src/ballistica/base/graphics/renderer/render_pass.h b/src/ballistica/base/graphics/renderer/render_pass.h index d52f3817..90abb2b7 100644 --- a/src/ballistica/base/graphics/renderer/render_pass.h +++ b/src/ballistica/base/graphics/renderer/render_pass.h @@ -112,7 +112,7 @@ class RenderPass { return model_view_projection_matrix_; } auto HasDrawCommands() const -> bool; - void Finalize(); + void Complete(); void Reset(); // Whether this pass draws stuff from the per-shader command lists diff --git a/src/ballistica/base/graphics/renderer/renderer.cc b/src/ballistica/base/graphics/renderer/renderer.cc index 88f36c98..9aeae8f0 100644 --- a/src/ballistica/base/graphics/renderer/renderer.cc +++ b/src/ballistica/base/graphics/renderer/renderer.cc @@ -35,10 +35,12 @@ void Renderer::PreprocessFrameDef(FrameDef* frame_def) { // If this frame_def was made in a different quality mode than we're // currently in, don't attempt to render it. - if (frame_def->quality() != g_base->graphics_server->quality()) { - frame_def->set_rendering(false); - return; - } + // UPDATE - scratch that; we now set our quality FROM the frame def. + // if (frame_def->quality() != g_base->graphics_server->quality()) { + // frame_def->set_rendering(false); + // return; + // } + frame_def->set_rendering(true); // Some VR environments muck with render states before/after diff --git a/src/ballistica/base/graphics/renderer/renderer.h b/src/ballistica/base/graphics/renderer/renderer.h index 9f5198a0..0ab47c42 100644 --- a/src/ballistica/base/graphics/renderer/renderer.h +++ b/src/ballistica/base/graphics/renderer/renderer.h @@ -82,7 +82,6 @@ class Renderer { auto light_pitch() const -> float { return light_pitch_; } auto light_heading() const -> float { return light_heading_; } void set_pixel_scale(float s) { pixel_scale_requested_ = s; } - // void set_screen_gamma(float val) { screen_gamma_requested_ = val; } void set_debug_draw_mode(bool debugModeIn) { debug_draw_mode_ = debugModeIn; } auto debug_draw_mode() -> bool { return debug_draw_mode_; } @@ -269,7 +268,6 @@ class Renderer { Vector3f vignette_outer_{0.0f, 0.0f, 0.0f}; Vector3f vignette_inner_{1.0f, 1.0f, 1.0f}; int shadow_res_{-1}; - // float screen_gamma_requested_{1.0f}; float screen_gamma_{1.0f}; float pixel_scale_requested_{1.0f}; float pixel_scale_{1.0f}; diff --git a/src/ballistica/base/graphics/support/camera.cc b/src/ballistica/base/graphics/support/camera.cc index aa0554df..d12ad130 100644 --- a/src/ballistica/base/graphics/support/camera.cc +++ b/src/ballistica/base/graphics/support/camera.cc @@ -1013,7 +1013,7 @@ void Camera::ApplyToFrameDef(FrameDef* frame_def) { up_, 4, 1000.0f, -1.0f, // Auto x fov. final_fov_y - * (g_base->graphics->tv_border() ? (1.0f + kTVBorder) : 1.0f), + * (frame_def->settings()->tv_border ? (1.0f + kTVBorder) : 1.0f), false, 0, 0, 0, 0, // Not using tangent fovs. area_of_interest_points_); } diff --git a/src/ballistica/base/graphics/support/frame_def.cc b/src/ballistica/base/graphics/support/frame_def.cc index 06def221..52c2ed80 100644 --- a/src/ballistica/base/graphics/support/frame_def.cc +++ b/src/ballistica/base/graphics/support/frame_def.cc @@ -49,6 +49,13 @@ auto FrameDef::GetOverlayFlatPass() -> RenderPass* { void FrameDef::Reset() { assert(g_base->InLogicThread()); + + // Update & grab the current settings. + settings_snapshot_ = g_base->graphics->GetGraphicsSettingsSnapshot(); + + auto* settings = settings_snapshot_->Get(); + auto* client_context = g_base->graphics->client_context(); + app_time_microsecs_ = 0; display_time_microsecs_ = 0; display_time_elapsed_microsecs_ = 0; @@ -68,11 +75,17 @@ void FrameDef::Reset() { mesh_index_sizes_.clear(); mesh_buffers_.clear(); - quality_ = g_base->graphics_server->quality(); + quality_ = Graphics::GraphicsQualityFromRequest( + settings->graphics_quality, client_context->auto_graphics_quality); - assert(g_base->graphics->has_supports_high_quality_graphics_value()); + texture_quality_ = Graphics::TextureQualityFromRequest( + settings->texture_quality, client_context->auto_texture_quality); + + // pixel_scale_ = g_base->graphics->settings()->pixel_scale; + + // assert(g_base->graphics->has_supports_high_quality_graphics_value()); orbiting_ = (g_base->graphics->camera()->mode() == CameraMode::kOrbit); - tv_border_ = g_base->graphics->tv_border(); + // tv_border_ = g_base->graphics->tv_border(); shadow_offset_ = g_base->graphics->shadow_offset(); shadow_scale_ = g_base->graphics->shadow_scale(); @@ -99,21 +112,21 @@ void FrameDef::Reset() { beauty_pass_->set_floor_reflection(g_base->graphics->floor_reflection()); } -void FrameDef::Finalize() { +void FrameDef::Complete() { assert(!defining_component_); - light_pass_->Finalize(); - light_shadow_pass_->Finalize(); - beauty_pass_->Finalize(); - beauty_pass_bg_->Finalize(); - overlay_pass_->Finalize(); - overlay_front_pass_->Finalize(); + light_pass_->Complete(); + light_shadow_pass_->Complete(); + beauty_pass_->Complete(); + beauty_pass_bg_->Complete(); + overlay_pass_->Complete(); + overlay_front_pass_->Complete(); if (g_core->IsVRMode()) { - overlay_fixed_pass_->Finalize(); - overlay_flat_pass_->Finalize(); - vr_cover_pass_->Finalize(); + overlay_fixed_pass_->Complete(); + overlay_flat_pass_->Complete(); + vr_cover_pass_->Complete(); } - overlay_3d_pass_->Finalize(); - blit_pass_->Finalize(); + overlay_3d_pass_->Complete(); + blit_pass_->Complete(); } void FrameDef::AddMesh(Mesh* mesh) { diff --git a/src/ballistica/base/graphics/support/frame_def.h b/src/ballistica/base/graphics/support/frame_def.h index 41341028..d839c52e 100644 --- a/src/ballistica/base/graphics/support/frame_def.h +++ b/src/ballistica/base/graphics/support/frame_def.h @@ -7,13 +7,14 @@ #include #include "ballistica/base/assets/asset.h" +#include "ballistica/shared/generic/snapshot.h" #include "ballistica/shared/math/matrix44f.h" #include "ballistica/shared/math/vector2f.h" namespace ballistica::base { /// A flattened representation of a frame; generated by the logic thread and -/// sent to the graphics thread to render. +/// sent to the graphics server to render. class FrameDef { public: auto light_pass() -> RenderPass* { return light_pass_.get(); } @@ -49,15 +50,15 @@ class FrameDef { // A number incremented for each frame renderered. Note that graphics code // should not plug this directly into things like flash calculations since - // frame-rates will vary a lot these days. A 30hz flash will look a lot + // frame-rates vary a lot these days. A 30hz flash will look a lot // different than a 240hz flash. Use frame_number_filtered() for such // purposes. auto frame_number() const { return frame_number_; } // A number incremented for each frame rendered, but a maximum of 60 times - // per second. Code for drawing flashes or other exact effects should use - // this value instead of regular frame_number so that things don't turn - // muddy at extremely high frame rates. + // per second. Code for drawing flashes or other crisp blink-y effects + // should use this value instead of regular frame_number so that things + // don't turn muddy at extremely high frame rates. auto frame_number_filtered() const { return frame_number_filtered_; } // Returns the display-time this frame-def was created at (tries to match @@ -66,14 +67,19 @@ class FrameDef { auto display_time_millisecs() const -> millisecs_t { return display_time_microsecs_ / 1000; } + auto display_time_microsecs() const -> microsecs_t { return display_time_microsecs_; } - auto display_time() const -> double { - return static_cast(display_time_microsecs_) / 1000000.0; + + auto display_time() const -> seconds_t { + return static_cast(display_time_microsecs_) / 1000000.0; + } + + auto display_time_elapsed() const -> seconds_t { + return static_cast(display_time_elapsed_microsecs_) / 1000000.0; } - // How much display time does this frame-def represent. auto display_time_elapsed_millisecs() const -> millisecs_t { return display_time_elapsed_millisecs_; } @@ -82,7 +88,9 @@ class FrameDef { return display_time_elapsed_microsecs_; } - auto quality() const -> GraphicsQuality { return quality_; } + auto quality() const { return quality_; } + auto texture_quality() const { return texture_quality_; } + auto orbiting() const -> bool { return orbiting_; } auto shadow_offset() const -> const Vector3f& { return shadow_offset_; } auto shadow_scale() const -> const Vector2f& { return shadow_scale_; } @@ -115,11 +123,12 @@ class FrameDef { vr_overlay_screen_matrix_fixed_ = mat; } - // Effects requiring availability of a depth texture should - // check this to determine whether they should draw. - auto has_depth_texture() const -> bool { + // Effects requiring availability of a depth texture should check this to + // determine whether they should draw. + auto HasDepthTexture() const -> bool { return (quality_ >= GraphicsQuality::kHigh); } + void AddComponent(const Object::Ref& component) { // Add a reference to this component only if we havn't yet. if (component->last_frame_def_num() != frame_number_) { @@ -134,7 +143,7 @@ class FrameDef { FrameDef(); ~FrameDef(); void Reset(); - void Finalize(); + void Complete(); void set_display_time_elapsed_microsecs(microsecs_t val) { display_time_elapsed_microsecs_ = val; @@ -187,7 +196,7 @@ class FrameDef { auto media_components() const -> const std::vector>& { return media_components_; } - auto tv_border() const { return tv_border_; } + // auto tv_border() const { return tv_border_; } void set_camera_mode(CameraMode val) { camera_mode_ = val; } void set_rendering(bool val) { rendering_ = val; } @@ -204,18 +213,27 @@ class FrameDef { } #endif + // auto pixel_scale() const { return pixel_scale_; } + + auto* settings() const { + assert(settings_snapshot_.Exists()); + return settings_snapshot_->Get(); + } + private: - bool needs_clear_{}; - bool rendering_{}; - bool orbiting_{}; - bool tv_border_{}; - bool shadow_ortho_{}; + Object::Ref> settings_snapshot_; + bool needs_clear_ : 1 {}; + bool rendering_ : 1 {}; + bool orbiting_ : 1 {}; + // bool tv_border_ : 1 {}; + bool shadow_ortho_ : 1 {}; BenchmarkType benchmark_type_{BenchmarkType::kNone}; CameraMode camera_mode_{CameraMode::kFollow}; Vector3f cam_original_{0.0f, 0.0f, 0.0f}; Vector3f cam_target_original_{0.0f, 0.0f, 0.0f}; Vector3f shake_original_{0.0f, 0.0f, 0.0f}; float vr_near_clip_{}; + // float pixel_scale_{}; Matrix44f vr_overlay_screen_matrix_ = kMatrix44fIdentity; Matrix44f vr_overlay_screen_matrix_fixed_ = kMatrix44fIdentity; std::vector mesh_data_creates_; @@ -245,7 +263,8 @@ class FrameDef { std::unique_ptr vr_cover_pass_; std::unique_ptr overlay_3d_pass_; std::unique_ptr blit_pass_; - GraphicsQuality quality_{GraphicsQuality::kLow}; + GraphicsQuality quality_{}; + TextureQuality texture_quality_{}; microsecs_t app_time_microsecs_{}; microsecs_t display_time_microsecs_{}; microsecs_t display_time_elapsed_microsecs_{}; diff --git a/src/ballistica/base/graphics/support/graphics_client_context.cc b/src/ballistica/base/graphics/support/graphics_client_context.cc new file mode 100644 index 00000000..5201cdc9 --- /dev/null +++ b/src/ballistica/base/graphics/support/graphics_client_context.cc @@ -0,0 +1,23 @@ +// Released under the MIT License. See LICENSE for details. + +#include "ballistica/base/graphics/support/graphics_client_context.h" + +#include "ballistica/base/graphics/graphics_server.h" +#include "ballistica/base/graphics/renderer/renderer.h" + +namespace ballistica::base { + +GraphicsClientContext::GraphicsClientContext() + : auto_graphics_quality{g_base->graphics_server->renderer() + ->GetAutoGraphicsQuality()}, + auto_texture_quality{ + g_base->graphics_server->renderer()->GetAutoTextureQuality()}, + texture_compression_types{ + g_base->graphics_server->texture_compression_types()} {} + +GraphicsClientContext::GraphicsClientContext(int dummy) + : auto_graphics_quality{GraphicsQuality::kLow}, + auto_texture_quality{TextureQuality::kLow}, + texture_compression_types{0} {} + +} // namespace ballistica::base diff --git a/src/ballistica/base/graphics/support/graphics_client_context.h b/src/ballistica/base/graphics/support/graphics_client_context.h new file mode 100644 index 00000000..c130413d --- /dev/null +++ b/src/ballistica/base/graphics/support/graphics_client_context.h @@ -0,0 +1,31 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_CLIENT_CONTEXT_H_ +#define BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_CLIENT_CONTEXT_H_ + +#include "ballistica/base/base.h" + +namespace ballistica::base { + +/// Represents a valid graphics setup delivered by the graphics server to +/// the logic thread. It contains various info about concrete graphics +/// settings and capabilities. +struct GraphicsClientContext { + GraphicsClientContext(); + + /// Special constructor to create a dummy context (used by headless builds). + explicit GraphicsClientContext(int dummy); + + auto SupportsTextureCompressionType(TextureCompressionType t) const -> bool { + return ((texture_compression_types & (0x01u << static_cast(t))) + != 0u); + } + + GraphicsQuality auto_graphics_quality; + TextureQuality auto_texture_quality; + uint32_t texture_compression_types; +}; + +} // namespace ballistica::base + +#endif // BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_CLIENT_CONTEXT_H_ diff --git a/src/ballistica/base/graphics/support/graphics_settings.cc b/src/ballistica/base/graphics/support/graphics_settings.cc new file mode 100644 index 00000000..a132fe88 --- /dev/null +++ b/src/ballistica/base/graphics/support/graphics_settings.cc @@ -0,0 +1,27 @@ +// Released under the MIT License. See LICENSE for details. + +#include "ballistica/base/graphics/support/graphics_settings.h" + +#include + +#include "ballistica/base/graphics/graphics.h" +#include "ballistica/base/support/app_config.h" +#include "ballistica/shared/foundation/object.h" + +namespace ballistica::base { + +GraphicsSettings::GraphicsSettings() + + : resolution{g_base->graphics->screen_pixel_width(), + g_base->graphics->screen_pixel_height()}, + resolution_virtual{g_base->graphics->screen_virtual_width(), + g_base->graphics->screen_virtual_height()}, + pixel_scale{std::clamp( + g_base->app_config->Resolve(AppConfig::FloatID::kScreenPixelScale), + 0.1f, 1.0f)}, + graphics_quality{g_base->graphics->GraphicsQualityFromAppConfig()}, + texture_quality{g_base->graphics->TextureQualityFromAppConfig()}, + tv_border{ + g_base->app_config->Resolve(AppConfig::BoolID::kEnableTVBorder)} {} + +} // namespace ballistica::base diff --git a/src/ballistica/base/graphics/support/graphics_settings.h b/src/ballistica/base/graphics/support/graphics_settings.h new file mode 100644 index 00000000..89ce31ea --- /dev/null +++ b/src/ballistica/base/graphics/support/graphics_settings.h @@ -0,0 +1,33 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_SETTINGS_H_ +#define BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_SETTINGS_H_ + +#include "ballistica/base/base.h" +#include "ballistica/shared/math/vector2f.h" + +namespace ballistica::base { + +/// A set of settings for graphics, covering things like screen +/// resolution, texture quality, etc. These are filled out by the +/// AppAdapter in the logic thread and passed up to the GraphicsServer +/// either through standalone calls or attached to a FrameDef. Generally +/// AppAdapters define their own subclass of this containing additional +/// settings specific to themselves or the renderer(s) they use. +struct GraphicsSettings { + GraphicsSettings(); + // Each new settings instance will be assigned a unique incrementing index. + int index{-1}; + + // Some standard settings used by most renderers. + Vector2f resolution; + Vector2f resolution_virtual; + float pixel_scale; + GraphicsQualityRequest graphics_quality; + TextureQualityRequest texture_quality; + bool tv_border; +}; + +} // namespace ballistica::base + +#endif // BALLISTICA_BASE_GRAPHICS_SUPPORT_GRAPHICS_SETTINGS_H_ diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index 736ecc37..551b499c 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -159,16 +159,16 @@ void Input::AnnounceConnects_() { // For the first announcement just say "X controllers detected" and don't // have a sound. - if (first_print && g_core->GetAppTimeMillisecs() < 10000) { + if (first_print && g_core->GetAppTimeSeconds() < 5.0) { first_print = false; - // Disabling this completely for now; being more lenient with devices - // allowed on Android means this will often come back with large - // numbers. - bool do_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. - if (explicit_bool(do_print)) { + if (explicit_bool(do_print_initial_counts)) { if (newly_connected_controllers_.size() > 1) { std::string s = g_base->assets->GetResourceString("controllersDetectedText"); diff --git a/src/ballistica/base/logic/logic.cc b/src/ballistica/base/logic/logic.cc index f752c635..67a05cf2 100644 --- a/src/ballistica/base/logic/logic.cc +++ b/src/ballistica/base/logic/logic.cc @@ -76,11 +76,11 @@ void Logic::OnAppStart() { void Logic::OnGraphicsReady() { assert(g_base->InLogicThread()); - if (on_initial_screen_creation_complete_called_) { + if (graphics_ready_) { // Only want to fire this logic the first time. return; } - on_initial_screen_creation_complete_called_ = true; + graphics_ready_ = true; // Ok; graphics-server is telling us we've got a screen (or no screen in // the case of headless-mode). We use this as a cue to kick off our diff --git a/src/ballistica/base/logic/logic.h b/src/ballistica/base/logic/logic.h index 18852d62..b215be32 100644 --- a/src/ballistica/base/logic/logic.h +++ b/src/ballistica/base/logic/logic.h @@ -4,7 +4,6 @@ #define BALLISTICA_BASE_LOGIC_LOGIC_H_ #include -#include #include #include "ballistica/shared/foundation/object.h" @@ -118,6 +117,8 @@ class Logic { auto shutting_down() const { return shutting_down_; } auto shutdown_completed() const { return shutdown_completed_; } + auto graphics_ready() const { return graphics_ready_; } + private: void UpdateDisplayTimeForFrameDraw_(); void UpdateDisplayTimeForHeadlessMode_(); @@ -127,31 +128,31 @@ class Logic { void UpdatePendingWorkTimer_(); void StepDisplayTime_(); - double display_time_{}; - double display_time_increment_{1.0 / 60.0}; + seconds_t display_time_{}; + seconds_t display_time_increment_{1.0 / 60.0}; microsecs_t display_time_microsecs_{}; microsecs_t display_time_increment_microsecs_{1000000 / 60}; - // GUI scheduling. - double last_display_time_update_app_time_{-1.0}; - double recent_display_time_increments_[kDisplayTimeSampleCount]{}; - int recent_display_time_increments_index_{-1}; - // Headless scheduling. Timer* headless_display_time_step_timer_{}; - Timer* process_pending_work_timer_{}; - Timer* asset_prune_timer_{}; - Timer* debug_timer_{}; - EventLoop* event_loop_{}; - std::unique_ptr display_timers_; + // GUI scheduling. + seconds_t last_display_time_update_app_time_{-1.0}; + seconds_t recent_display_time_increments_[kDisplayTimeSampleCount]{}; + int recent_display_time_increments_index_{-1}; + bool app_bootstrapping_complete_ : 1 {}; bool have_pending_loads_ : 1 {}; bool debug_log_display_time_ : 1 {}; bool applied_app_config_ : 1 {}; bool shutting_down_ : 1 {}; bool shutdown_completed_ : 1 {}; - bool on_initial_screen_creation_complete_called_ : 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_; }; } // namespace ballistica::base diff --git a/src/ballistica/base/platform/apple/base_platform_apple.cc b/src/ballistica/base/platform/apple/base_platform_apple.cc index ef83cd71..fc18f79c 100644 --- a/src/ballistica/base/platform/apple/base_platform_apple.cc +++ b/src/ballistica/base/platform/apple/base_platform_apple.cc @@ -4,6 +4,7 @@ #include "ballistica/base/platform/apple/base_platform_apple.h" #if BA_XCODE_BUILD +#include #include #endif #include @@ -53,9 +54,14 @@ 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); +#else + BallisticaKit::UIKitFromCppOpenURL(url); +#endif // Go ahead and do this ourself. Though perhaps the default // Python path would be fine. - AppleUtils::OpenURL(url.c_str()); + // AppleUtils::OpenURL(url.c_str()); #else // Otherwise go with the default (Python webbrowser module). BasePlatform::DoOpenURL(url); diff --git a/src/ballistica/base/python/methods/python_methods_app.cc b/src/ballistica/base/python/methods/python_methods_app.cc index 94792ad4..befd17d3 100644 --- a/src/ballistica/base/python/methods/python_methods_app.cc +++ b/src/ballistica/base/python/methods/python_methods_app.cc @@ -810,9 +810,9 @@ static PyMethodDef PySetStressTestingDef = { "(internal)", }; -// ------------------------------ display_log ---------------------------------- +// -------------------------------- emit_log ----------------------------------- -static auto PyDisplayLog(PyObject* self, PyObject* args, PyObject* keywds) +static auto PyEmitLog(PyObject* self, PyObject* args, PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {"name", "level", "message", nullptr}; @@ -839,25 +839,25 @@ static auto PyDisplayLog(PyObject* self, PyObject* args, PyObject* keywds) level = LogLevel::kCritical; } else { // Assume we should avoid Log() calls here since it could infinite loop. - fprintf(stderr, "Invalid log level to display_log(): %s\n", levelstr); + fprintf(stderr, "Invalid log level to emit_log(): %s\n", levelstr); level = LogLevel::kInfo; } - Logging::DisplayLog(name, level, message); + Logging::EmitLog(name, level, message); Py_RETURN_NONE; BA_PYTHON_CATCH; } -static PyMethodDef PyDisplayLogDef = { - "display_log", // name - (PyCFunction)PyDisplayLog, // method +static PyMethodDef PyEmitLogDef = { + "emit_log", // name + (PyCFunction)PyEmitLog, // method METH_VARARGS | METH_KEYWORDS, // flags - "display_log(name: str, level: str, message: str) -> None\n" + "emit_log(name: str, level: str, message: str) -> None\n" "\n" "(internal)\n" "\n" - "Sends a log message to the in-game console and any per-platform\n" + "Sends a log message to the in-app console and any per-platform\n" "log destinations (Android log, etc.). This generally is not called\n" "directly and should instead be fed Python logging output.", }; @@ -1654,7 +1654,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector { PyAppNameUpperDef, PyIsXCodeBuildDef, PyCanDisplayFullUnicodeDef, - PyDisplayLogDef, + PyEmitLogDef, PyV1CloudLogDef, PySetStressTestingDef, PyEnvDef, diff --git a/src/ballistica/base/python/methods/python_methods_graphics.cc b/src/ballistica/base/python/methods/python_methods_graphics.cc index 0ebf464b..63eac46f 100644 --- a/src/ballistica/base/python/methods/python_methods_graphics.cc +++ b/src/ballistica/base/python/methods/python_methods_graphics.cc @@ -348,13 +348,14 @@ static PyMethodDef PySafeColorDef = { static auto PyGetMaxGraphicsQuality(PyObject* self) -> PyObject* { BA_PYTHON_TRY; - if (g_base->graphics - && g_base->graphics->has_supports_high_quality_graphics_value() - && g_base->graphics->supports_high_quality_graphics()) { - return Py_BuildValue("s", "High"); - } else { - return Py_BuildValue("s", "Medium"); - } + // if (g_base->graphics + // && g_base->graphics->has_supports_high_quality_graphics_value() + // && g_base->graphics->supports_high_quality_graphics()) { + // return Py_BuildValue("s", "High"); + // } else { + // return Py_BuildValue("s", "Medium"); + // } + return Py_BuildValue("s", "Higher"); 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 b227b817..04d79880 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.cc +++ b/src/ballistica/core/platform/apple/core_platform_apple.cc @@ -147,17 +147,17 @@ auto CorePlatformApple::IsRunningOnDesktop() -> bool { #endif } -void CorePlatformApple::DisplayLog(const std::string& name, LogLevel level, - const std::string& msg) { +void CorePlatformApple::EmitPlatformLog(const std::string& name, LogLevel level, + const std::string& msg) { #if BA_XCODE_BUILD && !BA_HEADLESS_BUILD // HMM: do we want to use proper logging APIs here or simple printing? // base::AppleUtils::NSLogStr(msg); - CorePlatform::DisplayLog(name, level, msg); + CorePlatform::EmitPlatformLog(name, level, msg); #else // Fall back to default handler... - CorePlatform::DisplayLog(name, level, msg); + CorePlatform::EmitPlatformLog(name, level, msg); #endif } diff --git a/src/ballistica/core/platform/apple/core_platform_apple.h b/src/ballistica/core/platform/apple/core_platform_apple.h index 4198f7e8..6419215d 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.h +++ b/src/ballistica/core/platform/apple/core_platform_apple.h @@ -26,8 +26,8 @@ class CorePlatformApple : public CorePlatform { auto DoHasTouchScreen() -> bool override; auto GetDefaultUIScale() -> UIScale override; auto IsRunningOnDesktop() -> bool override; - void DisplayLog(const std::string& name, LogLevel level, - const std::string& msg) override; + void EmitPlatformLog(const std::string& name, LogLevel level, + const std::string& msg) override; void GetTextBoundsAndWidth(const std::string& text, Rect* r, float* width) override; void FreeTextTexture(void* tex) override; diff --git a/src/ballistica/core/platform/core_platform.cc b/src/ballistica/core/platform/core_platform.cc index 338d451d..35a9e4e1 100644 --- a/src/ballistica/core/platform/core_platform.cc +++ b/src/ballistica/core/platform/core_platform.cc @@ -465,12 +465,17 @@ auto CorePlatform::IsRunningOnDesktop() -> bool { return true; } -void CorePlatform::SleepMillisecs(millisecs_t ms) { - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +void CorePlatform::SleepSeconds(seconds_t duration) { + std::this_thread::sleep_for( + std::chrono::microseconds(static_cast(duration * 1000000))); } -void CorePlatform::SleepMicrosecs(millisecs_t ms) { - std::this_thread::sleep_for(std::chrono::microseconds(ms)); +void CorePlatform::SleepMillisecs(millisecs_t duration) { + std::this_thread::sleep_for(std::chrono::milliseconds(duration)); +} + +void CorePlatform::SleepMicrosecs(millisecs_t duration) { + std::this_thread::sleep_for(std::chrono::microseconds(duration)); } #pragma clang diagnostic push @@ -481,8 +486,8 @@ auto CorePlatform::GetDefaultUIScale() -> UIScale { return UIScale::kLarge; } -void CorePlatform::DisplayLog(const std::string& name, LogLevel level, - const std::string& msg) { +void CorePlatform::EmitPlatformLog(const std::string& name, LogLevel level, + const std::string& msg) { // Do nothing by default. } diff --git a/src/ballistica/core/platform/core_platform.h b/src/ballistica/core/platform/core_platform.h index df05291a..23fd4fae 100644 --- a/src/ballistica/core/platform/core_platform.h +++ b/src/ballistica/core/platform/core_platform.h @@ -99,8 +99,8 @@ class CorePlatform { /// Display a message to any default log for the platform (android log, /// etc.) Note that this can be called from any thread. Default /// implementation does nothing. - virtual void DisplayLog(const std::string& name, LogLevel level, - const std::string& msg); + virtual void EmitPlatformLog(const std::string& name, LogLevel level, + const std::string& msg); #pragma mark ENVIRONMENT ------------------------------------------------------- @@ -381,9 +381,9 @@ class CorePlatform { /// to not go backwards. static auto GetCurrentWholeSeconds() -> int64_t; - static void SleepMillisecs(millisecs_t ms); - - static void SleepMicrosecs(microsecs_t ms); + static void SleepSeconds(seconds_t duration); + static void SleepMillisecs(millisecs_t duration); + static void SleepMicrosecs(microsecs_t duration); /// Given a C++ symbol, attempt to return a pretty one. virtual auto DemangleCXXSymbol(const std::string& s) -> std::string; diff --git a/src/ballistica/core/platform/windows/core_platform_windows.cc b/src/ballistica/core/platform/windows/core_platform_windows.cc index f7e08276..8a44a78e 100644 --- a/src/ballistica/core/platform/windows/core_platform_windows.cc +++ b/src/ballistica/core/platform/windows/core_platform_windows.cc @@ -827,11 +827,12 @@ std::string CorePlatformWindows::DoGetDeviceName() { bool CorePlatformWindows::DoHasTouchScreen() { return false; } -void CorePlatformWindows::DisplayLog(const std::string& name, LogLevel level, - const std::string& msg) { +void CorePlatformWindows::EmitPlatformLog(const std::string& name, + LogLevel level, + const std::string& msg) { // if (have_stdin_stdout_) { // // On headless builds we use default handler (simple stdout). - // return CorePlatform::DisplayLog(msg); + // return CorePlatform::EmitPlatformLog(msg); // } // Also spit this out as a debug-string for when running from msvc. diff --git a/src/ballistica/core/platform/windows/core_platform_windows.h b/src/ballistica/core/platform/windows/core_platform_windows.h index ddc1054a..fe77ae71 100644 --- a/src/ballistica/core/platform/windows/core_platform_windows.h +++ b/src/ballistica/core/platform/windows/core_platform_windows.h @@ -41,8 +41,8 @@ class CorePlatformWindows : public CorePlatform { auto GetLocale() -> std::string override; auto DoGetDeviceName() -> std::string override; auto DoHasTouchScreen() -> bool override; - void DisplayLog(const std::string& name, LogLevel level, - const std::string& msg) override; + void EmitPlatformLog(const std::string& name, LogLevel level, + const std::string& msg) override; void SetEnv(const std::string& name, const std::string& value) override; auto GetEnv(const std::string& name) -> std::optional override; auto GetIsStdinATerminal() -> bool override; diff --git a/src/ballistica/core/python/core_python.cc b/src/ballistica/core/python/core_python.cc index 1794ae97..dcebb4a6 100644 --- a/src/ballistica/core/python/core_python.cc +++ b/src/ballistica/core/python/core_python.cc @@ -307,8 +307,8 @@ void CorePython::LoggingCall(LogLevel loglevel, const std::string& msg) { "CorePython::LoggingCall() called before Python" " logging available."}; if (g_core->platform) { - g_core->platform->DisplayLog("root", LogLevel::kError, errmsg); - g_core->platform->DisplayLog("root", loglevel, msg); + g_core->platform->EmitPlatformLog("root", LogLevel::kError, errmsg); + g_core->platform->EmitPlatformLog("root", loglevel, msg); } fprintf(stderr, "%s\n%s\n", errmsg, msg.c_str()); } diff --git a/src/ballistica/core/python/core_python.h b/src/ballistica/core/python/core_python.h index 2aa49e42..fef471f4 100644 --- a/src/ballistica/core/python/core_python.h +++ b/src/ballistica/core/python/core_python.h @@ -45,7 +45,7 @@ class CorePython { /// Calls Python logging function (logging.error, logging.warning, etc.) /// Can be called from any thread at any time. If called before Python - /// logging is available, logs locally using Logging::DisplayLog() + /// logging is available, logs locally using Logging::EmitPlatformLog() /// (with an added warning). void LoggingCall(LogLevel loglevel, const std::string& msg); void ImportPythonObjs(); diff --git a/src/ballistica/scene_v1/dynamics/collision.h b/src/ballistica/scene_v1/dynamics/collision.h index 65add53b..242ca422 100644 --- a/src/ballistica/scene_v1/dynamics/collision.h +++ b/src/ballistica/scene_v1/dynamics/collision.h @@ -12,11 +12,12 @@ namespace ballistica::scene_v1 { -// Stores info about an occurring collision. -// Note than just because a collision exists between two parts doesn't mean -// they're physically colliding in the simulation. It is just a shortcut to -// determine what behavior, if any, exists between two parts which are currently -// overlapping in the simulation. +/// Stores info about an occurring collision. +/// +/// Note than just because a collision exists between two parts doesn't mean +/// they're physically colliding in the simulation. It is just a shortcut to +/// determine what behavior, if any, exists between two parts which are +/// currently overlapping in the simulation. class Collision : public Object { public: explicit Collision(Scene* scene) : src_context(scene), dst_context(scene) {} diff --git a/src/ballistica/scene_v1/dynamics/dynamics.cc b/src/ballistica/scene_v1/dynamics/dynamics.cc index 4403f25c..ba6e5564 100644 --- a/src/ballistica/scene_v1/dynamics/dynamics.cc +++ b/src/ballistica/scene_v1/dynamics/dynamics.cc @@ -66,77 +66,77 @@ void do_dBodyGetLocalFeedback(dBodyID b, dReal px, dReal py, dReal pz, // Stores info about a collision needing a reset // (used when parts change materials). -class Dynamics::CollisionReset { +class Dynamics::CollisionReset_ { public: int node1; int node2; int part1; int part2; - CollisionReset(int node1_in, int part1_in, int node2_in, int part2_in) + CollisionReset_(int node1_in, int part1_in, int node2_in, int part2_in) : node1(node1_in), node2(node2_in), part1(part1_in), part2(part2_in) {} }; -class Dynamics::CollisionEvent { +class Dynamics::CollisionEvent_ { public: Object::Ref action; Object::Ref collision; Object::WeakRef node1; // first event node Object::WeakRef node2; // second event node - CollisionEvent(Node* node1_in, Node* node2_in, - const Object::Ref& action_in, - const Object::Ref& collision_in) + CollisionEvent_(Node* node1_in, Node* node2_in, + const Object::Ref& action_in, + const Object::Ref& collision_in) : node1(node1_in), node2(node2_in), action(action_in), collision(collision_in) {} }; -class Dynamics::SrcPartCollideMap { +class Dynamics::SrcPartCollideMap_ { public: std::unordered_map > dst_part_collisions; }; -class Dynamics::DstNodeCollideMap { +class Dynamics::DstNodeCollideMap_ { public: - std::unordered_map src_parts; + std::unordered_map src_parts; int collideDisabled; - DstNodeCollideMap() : collideDisabled(0) {} - ~DstNodeCollideMap() = default; + DstNodeCollideMap_() : collideDisabled(0) {} + ~DstNodeCollideMap_() = default; }; -class Dynamics::SrcNodeCollideMap { +class Dynamics::SrcNodeCollideMap_ { public: - std::unordered_map dst_nodes; + std::unordered_map dst_nodes; }; -class Dynamics::Impl { +class Dynamics::Impl_ { public: - explicit Impl(Dynamics* dynamics) : dynamics_(dynamics) {} + explicit Impl_(Dynamics* dynamics) : dynamics_(dynamics) {} // NOTE: we need to implement this here in an Impl class because // gcc currently chokes on unordered_maps with forward-declared types, // so we can't have this in our header without pushing all our map/collision // types there too. void HandleDisconnect( - const std::unordered_map::iterator& + const std::unordered_map::iterator& i, - const std::unordered_map::iterator& + const std::unordered_map::iterator& j, - const std::unordered_map::iterator& k, + const std::unordered_map::iterator& k, const std::unordered_map >::iterator& l); private: Dynamics* dynamics_{}; // Contains in-progress collisions for current nodes. - std::unordered_map node_collisions_; + std::unordered_map node_collisions_; friend class Dynamics; }; Dynamics::Dynamics(Scene* scene_in) : scene_(scene_in), collision_cache_(new base::CollisionCache()), - impl_(std::make_unique(this)) { - ResetODE(); + impl_(std::make_unique(this)) { + ResetODE_(); } Dynamics::~Dynamics() { @@ -145,7 +145,7 @@ Dynamics::~Dynamics() { "Dynamics going down within Process() call;" " should not happen."); } - ShutdownODE(); + ShutdownODE_(); } void Dynamics::Draw(base::FrameDef* frame_def) { @@ -203,7 +203,7 @@ void Dynamics::RemoveTrimesh(dGeomID g) { throw Exception("trimesh not found"); } -auto Dynamics::AreColliding(const Part& p1_in, const Part& p2_in) -> bool { +auto Dynamics::AreColliding_(const Part& p1_in, const Part& p2_in) -> bool { const Part* p1; const Part* p2; if (IsInStoreOrder(p1_in.node()->id(), p1_in.id(), p2_in.node()->id(), @@ -279,7 +279,7 @@ auto Dynamics::GetCollision(Part* p1_in, Part* p2_in, MaterialContext** cc1, p2->ApplyMaterials(*cc2, p2, p1); // If either disabled collisions between these two nodes, store that. - DstNodeCollideMap* dncm = + DstNodeCollideMap_* dncm = &impl_->node_collisions_[p1->node()->id()].dst_nodes[p2->node()->id()]; if (!(*cc1)->node_collide || !(*cc2)->node_collide) { dncm->collideDisabled = true; @@ -319,10 +319,12 @@ auto Dynamics::GetCollision(Part* p1_in, Part* p2_in, MaterialContext** cc1, return &(*(i.first->second)); } -void Dynamics::Impl::HandleDisconnect( - const std::unordered_map::iterator& i, - const std::unordered_map::iterator& j, - const std::unordered_map::iterator& k, +void Dynamics::Impl_::HandleDisconnect( + const std::unordered_map::iterator& + i, + const std::unordered_map::iterator& + j, + const std::unordered_map::iterator& k, const std::unordered_map >::iterator& l) { // Handle disconnect equivalents if they were colliding. if (l->second->collide) { @@ -367,7 +369,7 @@ void Dynamics::Impl::HandleDisconnect( k->second.dst_part_collisions.erase(l); } -void Dynamics::ProcessCollisions() { +void Dynamics::ProcessCollision_() { processing_collisions_ = true; collision_count_ = 0; @@ -441,10 +443,10 @@ void Dynamics::ProcessCollisions() { // Process all standard collisions. This will trigger our callback which // do the real work (add collisions to list, store commands to be // called, etc). - dSpaceCollide(ode_space_, this, &DoCollideCallback); + dSpaceCollide(ode_space_, this, &DoCollideCallback_); // Collide our trimeshes against everything. - collision_cache_->CollideAgainstSpace(ode_space_, this, &DoCollideCallback); + collision_cache_->CollideAgainstSpace(ode_space_, this, &DoCollideCallback_); // Do a bit of precalc each cycle. collision_cache_->Precalc(); @@ -453,9 +455,9 @@ void Dynamics::ProcessCollisions() { // setting parts' currently-colliding-with lists // based on current info, // removing unclaimed collisions and empty groups. - std::unordered_map::iterator i_next; - std::unordered_map::iterator j_next; - std::unordered_map::iterator k_next; + std::unordered_map::iterator i_next; + std::unordered_map::iterator j_next; + std::unordered_map::iterator k_next; std::unordered_map >::iterator l_next; for (auto i = impl_->node_collisions_.begin(); i != impl_->node_collisions_.end(); i = i_next) { @@ -507,26 +509,26 @@ void Dynamics::ProcessCollisions() { collision_events_.clear(); } -void Dynamics::process() { +void Dynamics::Process() { in_process_ = true; // Update this once so we can recycle results. real_time_ = g_core->GetAppTimeMillisecs(); - ProcessCollisions(); + ProcessCollision_(); dWorldQuickStep(ode_world_, kGameStepSeconds); dJointGroupEmpty(ode_contact_group_); in_process_ = false; } -void Dynamics::DoCollideCallback(void* data, dGeomID o1, dGeomID o2) { +void Dynamics::DoCollideCallback_(void* data, dGeomID o1, dGeomID o2) { auto* d = static_cast(data); - d->CollideCallback(o1, o2); + d->CollideCallback_(o1, o2); } // Run collisions for everything. Store any callbacks that will need to be made // and run them after all collision constraints are made. // This way we know all bodies and their associated nodes, etc are valid // throughout collision processing. -void Dynamics::CollideCallback(dGeomID o1, dGeomID o2) { +void Dynamics::CollideCallback_(dGeomID o1, dGeomID o2) { dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); @@ -1103,7 +1105,7 @@ void Dynamics::CollideCallback(dGeomID o1, dGeomID o2) { } } -void Dynamics::ShutdownODE() { +void Dynamics::ShutdownODE_() { if (ode_space_) { dSpaceDestroy(ode_space_); ode_space_ = nullptr; @@ -1118,8 +1120,8 @@ void Dynamics::ShutdownODE() { } } -void Dynamics::ResetODE() { - ShutdownODE(); +void Dynamics::ResetODE_() { + ShutdownODE_(); ode_world_ = dWorldCreate(); assert(ode_world_); dWorldSetGravity(ode_world_, 0, -20, 0); diff --git a/src/ballistica/scene_v1/dynamics/dynamics.h b/src/ballistica/scene_v1/dynamics/dynamics.h index 9e29780c..413b3b2b 100644 --- a/src/ballistica/scene_v1/dynamics/dynamics.h +++ b/src/ballistica/scene_v1/dynamics/dynamics.h @@ -4,7 +4,6 @@ #define BALLISTICA_SCENE_V1_DYNAMICS_DYNAMICS_H_ #include -#include #include #include "ballistica/base/base.h" @@ -16,12 +15,12 @@ namespace ballistica::scene_v1 { class Dynamics : public Object { public: - explicit Dynamics(Scene* scene_in); + explicit Dynamics(Scene* scene); ~Dynamics() override; void Draw(base::FrameDef* frame_def); // Draw any debug stuff, etc. auto ode_world() -> dWorldID { return ode_world_; } - auto getContactGroup() -> dJointGroupID { return ode_contact_group_; } - auto space() -> dSpaceID { return ode_space_; } + auto ode_contact_group() -> dJointGroupID { return ode_contact_group_; } + auto ode_space() -> dSpaceID { return ode_space_; } // Discontinues a collision. Used by parts when changing materials // so that new collisions may enter effect. @@ -37,6 +36,7 @@ class Dynamics : public Object { : active_collide_src_node_) .Get(); } + // Used by collision callbacks - internal. auto GetActiveCollideDstNode() -> Node* { assert(active_collision_); @@ -49,19 +49,19 @@ class Dynamics : public Object { } // Used by collide message handlers. - void set_collide_message_state(bool inCollideMessageIn, - bool target_other_in = false) { - in_collide_message_ = inCollideMessageIn; - collide_message_reverse_order_ = target_other_in; + void set_collide_message_state(bool in_collide_message, + bool target_other = false) { + in_collide_message_ = in_collide_message; + collide_message_reverse_order_ = target_other; } - auto in_collide_message() const -> bool { return in_collide_message_; } - void process(); - void increment_skid_sound_count() { skid_sound_count_++; } - void decrement_skid_sound_count() { skid_sound_count_--; } - auto skid_sound_count() const -> int { return skid_sound_count_; } - void incrementRollSoundCount() { roll_sound_count_++; } - void decrement_roll_sound_count() { roll_sound_count_--; } - auto getRollSoundCount() const -> int { return roll_sound_count_; } + auto in_collide_message() const { return in_collide_message_; } + void Process(); + void IncrementSkidSoundCount() { skid_sound_count_++; } + void DecrementSkidSoundCount() { skid_sound_count_--; } + auto skid_sound_count() const { return skid_sound_count_; } + void IncrementRollSoundCount() { roll_sound_count_++; } + void DecrementRollSoundCount() { roll_sound_count_--; } + auto roll_sound_count() const { return roll_sound_count_; } // We do some fancy collision testing stuff for trimeshes instead // of going through regular ODE space collision testing.. so we have @@ -69,55 +69,52 @@ class Dynamics : public Object { void AddTrimesh(dGeomID g); void RemoveTrimesh(dGeomID g); - auto collision_count() const -> int { return collision_count_; } - auto process_real_time() const -> millisecs_t { return real_time_; } - auto last_impact_sound_time() const -> millisecs_t { - return last_impact_sound_time_; - } - auto in_process() const -> bool { return in_process_; } + auto collision_count() const { return collision_count_; } + auto process_real_time() const { return real_time_; } + auto last_impact_sound_time() const { return last_impact_sound_time_; } + auto in_process() const { return in_process_; } private: - auto AreColliding(const Part& p1, const Part& p2) -> bool; - class SrcNodeCollideMap; - class DstNodeCollideMap; - class SrcPartCollideMap; - class CollisionEvent; - class CollisionReset; - class Impl; - std::vector collision_resets_; + auto AreColliding_(const Part& p1, const Part& p2) -> bool; + class SrcNodeCollideMap_; + class DstNodeCollideMap_; + class SrcPartCollideMap_; + class CollisionEvent_; + class CollisionReset_; + class Impl_; + std::vector collision_resets_; // Return a collision object between these two parts, // creating a new one if need be. auto GetCollision(Part* p1, Part* p2, MaterialContext** cc1, MaterialContext** cc2) -> Collision*; - std::vector collision_events_; - void ResetODE(); - void ShutdownODE(); - static void DoCollideCallback(void* data, dGeomID o1, dGeomID o2); - void CollideCallback(dGeomID o1, dGeomID o2); - void ProcessCollisions(); + std::vector collision_events_; + void ResetODE_(); + void ShutdownODE_(); + static void DoCollideCallback_(void* data, dGeomID o1, dGeomID o2); + void CollideCallback_(dGeomID o1, dGeomID o2); + void ProcessCollision_(); - std::unique_ptr impl_; - bool processing_collisions_{}; + int skid_sound_count_{}; + int roll_sound_count_{}; + int collision_count_{}; + bool in_process_ : 1 {}; + bool in_collide_message_ : 1 {}; + bool collide_message_reverse_order_ : 1 {}; + bool processing_collisions_ : 1 {}; dWorldID ode_world_{}; dJointGroupID ode_contact_group_{}; dSpaceID ode_space_{}; millisecs_t real_time_{}; - bool in_process_{}; - std::vector trimeshes_; millisecs_t last_impact_sound_time_{}; - int skid_sound_count_{}; - int roll_sound_count_{}; - int collision_count_{}; Scene* scene_{}; - bool in_collide_message_{}; - bool collide_message_reverse_order_{}; Collision* active_collision_{}; Object::WeakRef active_collide_src_node_; Object::WeakRef active_collide_dst_node_; + std::vector trimeshes_; + std::unique_ptr impl_; std::unique_ptr collision_cache_; - friend class Impl; }; } // namespace ballistica::scene_v1 diff --git a/src/ballistica/scene_v1/dynamics/material/impact_sound_material_action.cc b/src/ballistica/scene_v1/dynamics/material/impact_sound_material_action.cc index baae54f2..667a88af 100644 --- a/src/ballistica/scene_v1/dynamics/material/impact_sound_material_action.cc +++ b/src/ballistica/scene_v1/dynamics/material/impact_sound_material_action.cc @@ -2,7 +2,7 @@ #include "ballistica/scene_v1/dynamics/material/impact_sound_material_action.h" -#include "ballistica/base/graphics/graphics_server.h" +#include "ballistica/base/audio/audio.h" #include "ballistica/scene_v1/dynamics/dynamics.h" #include "ballistica/scene_v1/dynamics/material/material_context.h" #include "ballistica/scene_v1/support/client_session.h" @@ -50,10 +50,8 @@ void ImpactSoundMaterialAction::Apply(MaterialContext* context, assert(context->dynamics.Exists()); assert(context->dynamics->in_process()); - // For now lets avoid this in low-quality graphics mode (should we make - // a low-quality sound mode?) - if (g_base->graphics_server - && g_base->graphics_server->quality() < base::GraphicsQuality::kMedium) { + // Avoid this if we're cutting corners. + if (g_base->audio->UseLowQualityAudio()) { return; } diff --git a/src/ballistica/scene_v1/dynamics/material/material_context.cc b/src/ballistica/scene_v1/dynamics/material/material_context.cc index 42ea5284..eab72da9 100644 --- a/src/ballistica/scene_v1/dynamics/material/material_context.cc +++ b/src/ballistica/scene_v1/dynamics/material/material_context.cc @@ -42,7 +42,7 @@ MaterialContext::SkidSoundEntry::SkidSoundEntry( assert(context->dynamics.Exists()); #endif assert(context->dynamics->in_process()); - context->dynamics->increment_skid_sound_count(); + context->dynamics->IncrementSkidSoundCount(); } MaterialContext::SkidSoundEntry::SkidSoundEntry(MaterialContext* context_in, @@ -57,13 +57,13 @@ MaterialContext::SkidSoundEntry::SkidSoundEntry(MaterialContext* context_in, assert(context); assert(context->dynamics.Exists()); assert(context->dynamics->in_process()); - context->dynamics->increment_skid_sound_count(); + context->dynamics->IncrementSkidSoundCount(); } MaterialContext::SkidSoundEntry::~SkidSoundEntry() { assert(context); assert(context->dynamics.Exists()); - context->dynamics->decrement_skid_sound_count(); + context->dynamics->DecrementSkidSoundCount(); if (playing) { g_base->audio->PushSourceFadeOutCall(play_id, 200); } @@ -81,7 +81,7 @@ MaterialContext::RollSoundEntry::RollSoundEntry(MaterialContext* context_in, assert(context); assert(context->dynamics.Exists()); assert(context->dynamics->in_process()); - context->dynamics->incrementRollSoundCount(); + context->dynamics->IncrementRollSoundCount(); } MaterialContext::RollSoundEntry::RollSoundEntry( @@ -90,13 +90,13 @@ MaterialContext::RollSoundEntry::RollSoundEntry( assert(context); assert(context->dynamics.Exists()); assert(context->dynamics->in_process()); - context->dynamics->incrementRollSoundCount(); + context->dynamics->IncrementRollSoundCount(); } MaterialContext::RollSoundEntry::~RollSoundEntry() { assert(context); assert(context->dynamics.Exists()); - context->dynamics->decrement_roll_sound_count(); + context->dynamics->DecrementRollSoundCount(); if (playing) { g_base->audio->PushSourceFadeOutCall(play_id, 200); } diff --git a/src/ballistica/scene_v1/dynamics/material/roll_sound_material_action.cc b/src/ballistica/scene_v1/dynamics/material/roll_sound_material_action.cc index 763dc28b..e6ea2b64 100644 --- a/src/ballistica/scene_v1/dynamics/material/roll_sound_material_action.cc +++ b/src/ballistica/scene_v1/dynamics/material/roll_sound_material_action.cc @@ -2,7 +2,7 @@ #include "ballistica/scene_v1/dynamics/material/roll_sound_material_action.h" -#include "ballistica/base/graphics/graphics_server.h" +#include "ballistica/base/audio/audio.h" #include "ballistica/scene_v1/dynamics/dynamics.h" #include "ballistica/scene_v1/dynamics/material/material_context.h" #include "ballistica/scene_v1/support/client_session.h" @@ -34,16 +34,14 @@ void RollSoundMaterialAction::Apply(MaterialContext* context, assert(context->dynamics.Exists()); assert(context->dynamics->in_process()); - // For now lets avoid this in low-quality graphics mode - // (should we make a low-quality sound mode?) - if (g_base->graphics - && g_base->graphics_server->quality() < base::GraphicsQuality::kMedium) { + // Avoid this if we're cutting corners. + if (g_base->audio->UseLowQualityAudio()) { return; } // Let's limit the amount of skid-sounds we spawn, otherwise we'll // start using up all our sound resources on skids when things get messy - if (context->dynamics->getRollSoundCount() < 2) { + if (context->dynamics->roll_sound_count() < 2) { context->roll_sounds.emplace_back(context, sound.Get(), target_impulse, volume); context->complex_sound = true; diff --git a/src/ballistica/scene_v1/dynamics/material/skid_sound_material_action.cc b/src/ballistica/scene_v1/dynamics/material/skid_sound_material_action.cc index a8c8f381..3aa71a6c 100644 --- a/src/ballistica/scene_v1/dynamics/material/skid_sound_material_action.cc +++ b/src/ballistica/scene_v1/dynamics/material/skid_sound_material_action.cc @@ -2,7 +2,7 @@ #include "ballistica/scene_v1/dynamics/material/skid_sound_material_action.h" -#include "ballistica/base/graphics/graphics_server.h" +#include "ballistica/base/audio/audio.h" #include "ballistica/scene_v1/dynamics/dynamics.h" #include "ballistica/scene_v1/dynamics/material/material_context.h" #include "ballistica/scene_v1/support/client_session.h" @@ -34,10 +34,8 @@ void SkidSoundMaterialAction::Apply(MaterialContext* context, assert(context->dynamics.Exists()); assert(context->dynamics->in_process()); - // For now lets avoid this in low-quality graphics mode - // (should we make a low-quality sound mode?). - if (g_base->graphics_server - && g_base->graphics_server->quality() < base::GraphicsQuality::kMedium) { + // Avoid this if we're cutting corners. + if (g_base->audio->UseLowQualityAudio()) { return; } diff --git a/src/ballistica/scene_v1/dynamics/rigid_body.cc b/src/ballistica/scene_v1/dynamics/rigid_body.cc index 84588e9a..e0b76192 100644 --- a/src/ballistica/scene_v1/dynamics/rigid_body.cc +++ b/src/ballistica/scene_v1/dynamics/rigid_body.cc @@ -65,23 +65,23 @@ RigidBody::RigidBody(int id_in, Part* part_in, Type type_in, Shape shape_in, case Shape::kSphere: { dimensions_[0] = dimensions_[1] = dimensions_[2] = 0.3f; geoms_.resize(1); - geoms_[0] = dCreateSphere(dynamics_->space(), dimensions_[0]); + geoms_[0] = dCreateSphere(dynamics_->ode_space(), dimensions_[0]); break; } case Shape::kBox: { dimensions_[0] = dimensions_[1] = dimensions_[2] = 0.6f; geoms_.resize(1); - geoms_[0] = dCreateBox(dynamics_->space(), dimensions_[0], dimensions_[1], - dimensions_[2]); + geoms_[0] = dCreateBox(dynamics_->ode_space(), dimensions_[0], + dimensions_[1], dimensions_[2]); break; } case Shape::kCapsule: { dimensions_[0] = dimensions_[1] = 0.3f; geoms_.resize(1); - geoms_[0] = - dCreateCCylinder(dynamics_->space(), dimensions_[0], dimensions_[1]); + geoms_[0] = dCreateCCylinder(dynamics_->ode_space(), dimensions_[0], + dimensions_[1]); break; } @@ -98,14 +98,15 @@ RigidBody::RigidBody(int id_in, Part* part_in, Type type_in, Shape shape_in, Vector3f p = Matrix44fRotate(Vector3f(0, 1, 0), static_cast(i) * inc) * Vector3f(offset, 0, 0); - geoms_[i * 2] = dCreateGeomTransform(dynamics_->space()); + geoms_[i * 2] = dCreateGeomTransform(dynamics_->ode_space()); geoms_[i * 2 + 1] = dCreateSphere(nullptr, sub_rad); dGeomTransformSetGeom(geoms_[i * 2], geoms_[i * 2 + 1]); dGeomSetPosition(geoms_[i * 2 + 1], p.v[0], p.v[1], p.v[2]); } // One last center sphere to keep stuff from getting stuck in our middle. - geoms_[geoms_.size() - 1] = dCreateSphere(dynamics_->space(), sub_rad); + geoms_[geoms_.size() - 1] = + dCreateSphere(dynamics_->ode_space(), sub_rad); break; } diff --git a/src/ballistica/scene_v1/node/flag_node.cc b/src/ballistica/scene_v1/node/flag_node.cc index 202b3ecf..d0bae293 100644 --- a/src/ballistica/scene_v1/node/flag_node.cc +++ b/src/ballistica/scene_v1/node/flag_node.cc @@ -129,9 +129,6 @@ FlagNode::FlagNode(Scene* scene) : Node(scene, node_type), part_(this) { mesh_.SetIndexData(indices); mesh_.SetStaticData(v_static); - - // Create our shadow set. - UpdateForGraphicsQuality(g_base->graphics_server->quality()); } auto FlagNode::getPosition() const -> std::vector { @@ -257,6 +254,11 @@ void FlagNode::HandleMessage(const char* data_in) { } void FlagNode::Draw(base::FrameDef* frame_def) { + if (graphics_quality_ != frame_def->quality()) { + graphics_quality_ = frame_def->quality(); + UpdateForGraphicsQuality(graphics_quality_); + } + // Flag cloth. { // Update the dynamic portion of our mesh data. @@ -311,45 +313,60 @@ void FlagNode::Draw(base::FrameDef* frame_def) { FullShadowSet* full_shadows = full_shadow_set_.Get(); - if (full_shadows) { - // Pole bottom. - { - full_shadows->shadow_pole_bottom_.GetValues(&s_scale, &s_density); - const Vector3f& p(full_shadows->shadow_pole_bottom_.GetPosition()); - g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0, - s_density * 0.25f); - } + // Update our shadow objects. + if (!g_core->HeadlessMode()) { + dBodyID b = body_->body(); + assert(b); + dVector3 p; + if (FullShadowSet* full_shadows = full_shadow_set_.Get()) { + full_shadows->shadow_flag_.SetPosition( + flag_points_[kFlagSizeX * (kFlagSizeY / 2) + (kFlagSizeX / 2)]); + dBodyGetRelPointPos(b, 0, 0, kFlagHeight * -0.4f, p); + full_shadows->shadow_pole_bottom_.SetPosition(Vector3f(p)); + full_shadows->shadow_pole_middle_.SetPosition( + Vector3f(dBodyGetPosition(b))); + dBodyGetRelPointPos(b, 0, 0, kFlagHeight * 0.4f, p); + full_shadows->shadow_pole_top_.SetPosition(Vector3f(p)); + // Pole bottom. + { + full_shadows->shadow_pole_bottom_.GetValues(&s_scale, &s_density); + const Vector3f& p(full_shadows->shadow_pole_bottom_.GetPosition()); + g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0, + s_density * 0.25f); + } - // Pole middle. - { - full_shadows->shadow_pole_middle_.GetValues(&s_scale, &s_density); - const Vector3f& p(full_shadows->shadow_pole_middle_.GetPosition()); - g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0, - s_density * 0.25f); - } + // Pole middle. + { + full_shadows->shadow_pole_middle_.GetValues(&s_scale, &s_density); + const Vector3f& p(full_shadows->shadow_pole_middle_.GetPosition()); + g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0, + s_density * 0.25f); + } - // Pole top. - { - full_shadows->shadow_pole_middle_.GetValues(&s_scale, &s_density); - const Vector3f& p(full_shadows->shadow_pole_top_.GetPosition()); - g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0, - s_density * 0.25f); - } + // Pole top. + { + full_shadows->shadow_pole_middle_.GetValues(&s_scale, &s_density); + const Vector3f& p(full_shadows->shadow_pole_top_.GetPosition()); + g_base->graphics->DrawBlotch(p, 0.4f * s_scale, 0, 0, 0, + s_density * 0.25f); + } - // Flag center. - { - full_shadows->shadow_flag_.GetValues(&s_scale, &s_density); - const Vector3f& p(full_shadows->shadow_flag_.GetPosition()); + // Flag center. + { + full_shadows->shadow_flag_.GetValues(&s_scale, &s_density); + const Vector3f& p(full_shadows->shadow_flag_.GetPosition()); + g_base->graphics->DrawBlotch(p, 0.8f * s_scale, 0, 0, 0, + s_density * 0.3f); + } + + } else if (SimpleShadowSet* simple_shadows = simple_shadow_set_.Get()) { + dBodyGetRelPointPos(b, 0, 0, kFlagHeight * -0.3f, p); + simple_shadows->shadow_.SetPosition(Vector3f(p)); + simple_shadows->shadow_.GetValues(&s_scale, &s_density); + const Vector3f& p(simple_shadows->shadow_.GetPosition()); g_base->graphics->DrawBlotch(p, 0.8f * s_scale, 0, 0, 0, - s_density * 0.3f); + s_density * 0.5f); } - } else { - SimpleShadowSet* simple_shadows = simple_shadow_set_.Get(); - assert(simple_shadows); - simple_shadows->shadow_.GetValues(&s_scale, &s_density); - const Vector3f& p(simple_shadows->shadow_.GetPosition()); - g_base->graphics->DrawBlotch(p, 0.8f * s_scale, 0, 0, 0, - s_density * 0.5f); } c.Submit(); } @@ -398,30 +415,6 @@ void FlagNode::Step() { // FIXME: This should probably happen for RBDs automatically? body_->UpdateBlending(); - // Update our shadow objects. - dBodyID b = body_->body(); - assert(b); - - if (!g_core->HeadlessMode()) { - dVector3 p; - FullShadowSet* full_shadows = full_shadow_set_.Get(); - if (full_shadows) { - full_shadows->shadow_flag_.SetPosition( - flag_points_[kFlagSizeX * (kFlagSizeY / 2) + (kFlagSizeX / 2)]); - dBodyGetRelPointPos(b, 0, 0, kFlagHeight * -0.4f, p); - full_shadows->shadow_pole_bottom_.SetPosition(Vector3f(p)); - full_shadows->shadow_pole_middle_.SetPosition( - Vector3f(dBodyGetPosition(b))); - dBodyGetRelPointPos(b, 0, 0, kFlagHeight * 0.4f, p); - full_shadows->shadow_pole_top_.SetPosition(Vector3f(p)); - } else { - SimpleShadowSet* simple_shadows = simple_shadow_set_.Get(); - assert(simple_shadows); - dBodyGetRelPointPos(b, 0, 0, kFlagHeight * -0.3f, p); - simple_shadows->shadow_.SetPosition(Vector3f(p)); - } - } - if (dBodyIsEnabled(body_->body())) { // Try to keep upright by pushing the top of the // flag to be above the bottom. @@ -675,10 +668,6 @@ void FlagNode::GetRigidBodyPickupLocations(int id, float* obj, float* character, hand1[2] = -0.05f; } -void FlagNode::OnGraphicsQualityChanged(base::GraphicsQuality q) { - UpdateForGraphicsQuality(q); -} - void FlagNode::UpdateForGraphicsQuality(base::GraphicsQuality quality) { if (!g_core->HeadlessMode()) { if (quality >= base::GraphicsQuality::kMedium) { diff --git a/src/ballistica/scene_v1/node/flag_node.h b/src/ballistica/scene_v1/node/flag_node.h index 717338cb..3dbd9a52 100644 --- a/src/ballistica/scene_v1/node/flag_node.h +++ b/src/ballistica/scene_v1/node/flag_node.h @@ -44,10 +44,13 @@ class FlagNode : public Node { void UpdateDimensions(); void ResetFlagMesh(); void UpdateFlagMesh(); - void OnGraphicsQualityChanged(base::GraphicsQuality q) override; void UpdateForGraphicsQuality(base::GraphicsQuality q); void UpdateSpringPoint(int p1, int p2, float rest_length); - base::AreaOfInterest* area_of_interest_ = nullptr; + + base::GraphicsQuality graphics_quality_{}; + bool light_weight_ : 1 {}; + bool have_flag_impulse_ : 1 {}; + base::AreaOfInterest* area_of_interest_{}; Part part_; std::vector color_ = {1.0f, 1.0f, 1.0f}; Object::Ref body_; @@ -56,15 +59,13 @@ class FlagNode : public Node { Object::Ref full_shadow_set_; Object::Ref simple_shadow_set_; int wind_rand_{}; + int footing_{}; float wind_rand_x_{}; float wind_rand_y_{}; float wind_rand_z_{}; float flag_impulse_add_x_{}; float flag_impulse_add_y_{}; float flag_impulse_add_z_{}; - bool have_flag_impulse_{}; - int footing_{}; - bool light_weight_{}; Vector3f flag_points_[25]{}; Vector3f flag_normals_[25]{}; Vector3f flag_velocities_[25]{}; diff --git a/src/ballistica/scene_v1/node/node.h b/src/ballistica/scene_v1/node/node.h index 83078d3f..bd68613c 100644 --- a/src/ballistica/scene_v1/node/node.h +++ b/src/ballistica/scene_v1/node/node.h @@ -40,7 +40,6 @@ class Node : public Object { /// Called when the language changes. virtual void OnLanguageChange() {} - virtual void OnGraphicsQualityChanged(base::GraphicsQuality q) {} /// The node can rule out collisions between particular bodies using this. virtual auto PreFilterCollision(RigidBody* b1, RigidBody* r2) -> bool { diff --git a/src/ballistica/scene_v1/node/prop_node.cc b/src/ballistica/scene_v1/node/prop_node.cc index 4f48492c..ed94268a 100644 --- a/src/ballistica/scene_v1/node/prop_node.cc +++ b/src/ballistica/scene_v1/node/prop_node.cc @@ -576,7 +576,7 @@ auto PropNode::CollideCallback(dContact* c, int count, dBodyGetMass(b2, &m); dJointID j = dJointCreateFixed(scene()->dynamics()->ode_world(), - scene()->dynamics()->getContactGroup()); + scene()->dynamics()->ode_contact_group()); dJointAttach(j, b1, b2); dJointSetFixed(j); dJointSetFixedSpringMode(j, 1, 1, false); diff --git a/src/ballistica/scene_v1/node/shield_node.cc b/src/ballistica/scene_v1/node/shield_node.cc index f1e73e39..df28bee8 100644 --- a/src/ballistica/scene_v1/node/shield_node.cc +++ b/src/ballistica/scene_v1/node/shield_node.cc @@ -260,7 +260,7 @@ void ShieldNode::Draw(base::FrameDef* frame_def) { c.Submit(); // Nifty intersection effects in fancy graphics mode. - if (frame_def->has_depth_texture()) { + if (frame_def->HasDepthTexture()) { base::ShieldComponent c2(frame_def->overlay_3d_pass()); { auto xf = c2.ScopedTransform(); @@ -273,7 +273,7 @@ void ShieldNode::Draw(base::FrameDef* frame_def) { } c2.Submit(); } - if (frame_def->has_depth_texture()) { + if (frame_def->HasDepthTexture()) { base::PostProcessComponent c2(frame_def->blit_pass()); c2.SetNormalDistort(distort); { diff --git a/src/ballistica/scene_v1/node/spaz_node.cc b/src/ballistica/scene_v1/node/spaz_node.cc index d89f7618..b316888c 100644 --- a/src/ballistica/scene_v1/node/spaz_node.cc +++ b/src/ballistica/scene_v1/node/spaz_node.cc @@ -916,9 +916,6 @@ SpazNode::SpazNode(Scene* scene) // Give joints initial vals. UpdateJoints(); - // FIXME: should do this on draw. - UpdateForGraphicsQuality(g_base->graphics_server->quality()); - // We want to have an area of interest by default. SetIsAreaOfInterest(true); @@ -2079,40 +2076,6 @@ void SpazNode::Step() { } } - // Update shadows. -#if !BA_HEADLESS_BUILD - FullShadowSet* full_shadows = full_shadow_set_.Get(); - if (full_shadows) { - full_shadows->torso_shadow_.SetPosition( - Vector3f(dBodyGetPosition(body_torso_->body()))); - full_shadows->head_shadow_.SetPosition( - Vector3f(dBodyGetPosition(body_head_->body()))); - full_shadows->pelvis_shadow_.SetPosition( - Vector3f(dBodyGetPosition(body_pelvis_->body()))); - full_shadows->lower_left_leg_shadow_.SetPosition( - Vector3f(dBodyGetPosition(lower_left_leg_body_->body()))); - full_shadows->lower_right_leg_shadow_.SetPosition( - Vector3f(dBodyGetPosition(lower_right_leg_body_->body()))); - full_shadows->upper_left_leg_shadow_.SetPosition( - Vector3f(dBodyGetPosition(upper_left_leg_body_->body()))); - full_shadows->upper_right_leg_shadow_.SetPosition( - Vector3f(dBodyGetPosition(upper_right_leg_body_->body()))); - full_shadows->lower_right_arm_shadow_.SetPosition( - Vector3f(dBodyGetPosition(lower_right_arm_body_->body()))); - full_shadows->upper_right_arm_shadow_.SetPosition( - Vector3f(dBodyGetPosition(upper_right_arm_body_->body()))); - full_shadows->lower_left_arm_shadow_.SetPosition( - Vector3f(dBodyGetPosition(lower_left_arm_body_->body()))); - full_shadows->upper_left_arm_shadow_.SetPosition( - Vector3f(dBodyGetPosition(upper_left_arm_body_->body()))); - } else { - SimpleShadowSet* simple_shadows = simple_shadow_set_.Get(); - assert(simple_shadows); - simple_shadows->shadow_.SetPosition( - Vector3f(dBodyGetPosition(body_pelvis_->body()))); - } -#endif // !BA_HEADLESS_BUILD - // Update wings if we've got 'em. if (wings_) { float maxDist = 0.8f; @@ -4547,6 +4510,11 @@ static void DrawRadialMeter(base::MeshIndexedSimpleFull* m, void SpazNode::Draw(base::FrameDef* frame_def) { #if !BA_HEADLESS_BUILD + if (graphics_quality_ != frame_def->quality()) { + graphics_quality_ = frame_def->quality(); + UpdateForGraphicsQuality(graphics_quality_); + } + #if BA_OSTYPE_MACOS if (g_base->graphics_server->renderer()->debug_draw_mode()) { base::SimpleComponent c(frame_def->overlay_3d_pass()); @@ -5356,49 +5324,68 @@ void SpazNode::Draw(base::FrameDef* frame_def) { sc[2] = weight * freeze_color[2] + (1.0f - weight) * sc[2]; } - FullShadowSet* full_shadows = full_shadow_set_.Get(); - if (full_shadows) { - DrawBrightSpot(full_shadows->lower_left_leg_shadow_, 0.3f * death_scale, - death_fade * (frozen_ ? 0.3f : 0.2f), sc); - DrawBrightSpot(full_shadows->lower_right_leg_shadow_, 0.3f * death_scale, - death_fade * (frozen_ ? 0.3f : 0.2f), sc); - DrawBrightSpot(full_shadows->head_shadow_, 0.45f * death_scale, - death_fade * (frozen_ ? 0.8f : 0.14f), sc); - } + // Update and draw shadows. + if (!g_core->HeadlessMode()) { + if (FullShadowSet* full_shadows = full_shadow_set_.Get()) { + full_shadows->torso_shadow_.SetPosition( + Vector3f(dBodyGetPosition(body_torso_->body()))); + full_shadows->head_shadow_.SetPosition( + Vector3f(dBodyGetPosition(body_head_->body()))); + full_shadows->pelvis_shadow_.SetPosition( + Vector3f(dBodyGetPosition(body_pelvis_->body()))); + full_shadows->lower_left_leg_shadow_.SetPosition( + Vector3f(dBodyGetPosition(lower_left_leg_body_->body()))); + full_shadows->lower_right_leg_shadow_.SetPosition( + Vector3f(dBodyGetPosition(lower_right_leg_body_->body()))); + full_shadows->upper_left_leg_shadow_.SetPosition( + Vector3f(dBodyGetPosition(upper_left_leg_body_->body()))); + full_shadows->upper_right_leg_shadow_.SetPosition( + Vector3f(dBodyGetPosition(upper_right_leg_body_->body()))); + full_shadows->lower_right_arm_shadow_.SetPosition( + Vector3f(dBodyGetPosition(lower_right_arm_body_->body()))); + full_shadows->upper_right_arm_shadow_.SetPosition( + Vector3f(dBodyGetPosition(upper_right_arm_body_->body()))); + full_shadows->lower_left_arm_shadow_.SetPosition( + Vector3f(dBodyGetPosition(lower_left_arm_body_->body()))); + full_shadows->upper_left_arm_shadow_.SetPosition( + Vector3f(dBodyGetPosition(upper_left_arm_body_->body()))); - if (full_shadows) { - DrawShadow(full_shadows->torso_shadow_, 0.19f * death_scale, 0.9f, sc); - DrawShadow(full_shadows->head_shadow_, 0.15f * death_scale, 0.7f, sc); - DrawShadow(full_shadows->pelvis_shadow_, 0.15f * death_scale, 0.7f, sc); - DrawShadow(full_shadows->lower_left_leg_shadow_, 0.08f * death_scale, - 1.0f, sc); - DrawShadow(full_shadows->lower_right_leg_shadow_, 0.08f * death_scale, - 1.0f, sc); - DrawShadow(full_shadows->upper_left_leg_shadow_, 0.08f * death_scale, - 1.0f, sc); - DrawShadow(full_shadows->upper_right_leg_shadow_, 0.08f * death_scale, - 1.0f, sc); - DrawShadow(full_shadows->upper_left_arm_shadow_, 0.08f * death_scale, - 0.5f, sc); - DrawShadow(full_shadows->lower_left_arm_shadow_, 0.08f * death_scale, - 0.3f, sc); - DrawShadow(full_shadows->lower_right_arm_shadow_, 0.08f * death_scale, - 0.3f, sc); - DrawShadow(full_shadows->upper_right_arm_shadow_, 0.08f * death_scale, - 0.5f, sc); - } else { - SimpleShadowSet* simple_shadows = simple_shadow_set_.Get(); - assert(simple_shadows); - DrawShadow(simple_shadows->shadow_, 0.2f * death_scale, 2.0f, sc); + DrawBrightSpot(full_shadows->lower_left_leg_shadow_, 0.3f * death_scale, + death_fade * (frozen_ ? 0.3f : 0.2f), sc); + DrawBrightSpot(full_shadows->lower_right_leg_shadow_, + 0.3f * death_scale, death_fade * (frozen_ ? 0.3f : 0.2f), + sc); + DrawBrightSpot(full_shadows->head_shadow_, 0.45f * death_scale, + death_fade * (frozen_ ? 0.8f : 0.14f), sc); + DrawShadow(full_shadows->torso_shadow_, 0.19f * death_scale, 0.9f, sc); + DrawShadow(full_shadows->head_shadow_, 0.15f * death_scale, 0.7f, sc); + DrawShadow(full_shadows->pelvis_shadow_, 0.15f * death_scale, 0.7f, sc); + DrawShadow(full_shadows->lower_left_leg_shadow_, 0.08f * death_scale, + 1.0f, sc); + DrawShadow(full_shadows->lower_right_leg_shadow_, 0.08f * death_scale, + 1.0f, sc); + DrawShadow(full_shadows->upper_left_leg_shadow_, 0.08f * death_scale, + 1.0f, sc); + DrawShadow(full_shadows->upper_right_leg_shadow_, 0.08f * death_scale, + 1.0f, sc); + DrawShadow(full_shadows->upper_left_arm_shadow_, 0.08f * death_scale, + 0.5f, sc); + DrawShadow(full_shadows->lower_left_arm_shadow_, 0.08f * death_scale, + 0.3f, sc); + DrawShadow(full_shadows->lower_right_arm_shadow_, 0.08f * death_scale, + 0.3f, sc); + DrawShadow(full_shadows->upper_right_arm_shadow_, 0.08f * death_scale, + 0.5f, sc); + } else if (SimpleShadowSet* simple_shadows = simple_shadow_set_.Get()) { + simple_shadows->shadow_.SetPosition( + Vector3f(dBodyGetPosition(body_pelvis_->body()))); + DrawShadow(simple_shadows->shadow_, 0.2f * death_scale, 2.0f, sc); + } } } #endif // !BA_HEADLESS_BUILD } // NOLINT (yes i know this is too big) -void SpazNode::OnGraphicsQualityChanged(base::GraphicsQuality q) { - UpdateForGraphicsQuality(q); -} - void SpazNode::UpdateForGraphicsQuality(base::GraphicsQuality quality) { #if !BA_HEADLESS_BUILD if (quality >= base::GraphicsQuality::kMedium) { diff --git a/src/ballistica/scene_v1/node/spaz_node.h b/src/ballistica/scene_v1/node/spaz_node.h index 26b71a3a..3440ef59 100644 --- a/src/ballistica/scene_v1/node/spaz_node.h +++ b/src/ballistica/scene_v1/node/spaz_node.h @@ -277,7 +277,6 @@ class SpazNode : public Node { // Reset to a standing, non-moving state at the given point. void Stand(float x, float y, float z, float angle); - void OnGraphicsQualityChanged(base::GraphicsQuality q) override; void UpdateForGraphicsQuality(base::GraphicsQuality q); void UpdateAreaOfInterest(); auto CollideCallback(dContact* c, int count, RigidBody* colliding_body, @@ -515,6 +514,7 @@ class SpazNode : public Node { bool has_eyelids_{true}; bool running_{}; bool billboard_cross_out_{}; + base::GraphicsQuality graphics_quality_{}; Object::Ref hair_front_right_body_; JointFixedEF* hair_front_right_joint_{}; Object::Ref hair_front_left_body_; diff --git a/src/ballistica/scene_v1/support/host_activity.cc b/src/ballistica/scene_v1/support/host_activity.cc index 5fc1b899..b357fbb7 100644 --- a/src/ballistica/scene_v1/support/host_activity.cc +++ b/src/ballistica/scene_v1/support/host_activity.cc @@ -483,9 +483,6 @@ void HostActivity::PruneSessionBaseTimers() { void HostActivity::OnScreenSizeChange() { scene()->OnScreenSizeChange(); } void HostActivity::LanguageChanged() { scene()->LanguageChanged(); } void HostActivity::DebugSpeedMultChanged() { UpdateStepTimerLength(); } -void HostActivity::GraphicsQualityChanged(base::GraphicsQuality q) { - scene()->GraphicsQualityChanged(q); -} void HostActivity::Draw(base::FrameDef* frame_def) { if (!started_) { diff --git a/src/ballistica/scene_v1/support/host_activity.h b/src/ballistica/scene_v1/support/host_activity.h index ad4d998d..5f583ff9 100644 --- a/src/ballistica/scene_v1/support/host_activity.h +++ b/src/ballistica/scene_v1/support/host_activity.h @@ -57,7 +57,6 @@ class HostActivity : public SceneV1Context { void OnScreenSizeChange(); void LanguageChanged(); void DebugSpeedMultChanged(); - void GraphicsQualityChanged(base::GraphicsQuality q); // Used to register python calls created in this context so we can make sure // they got properly cleaned up. diff --git a/src/ballistica/scene_v1/support/host_session.cc b/src/ballistica/scene_v1/support/host_session.cc index 0601c0bb..a5d04506 100644 --- a/src/ballistica/scene_v1/support/host_session.cc +++ b/src/ballistica/scene_v1/support/host_session.cc @@ -154,16 +154,6 @@ void HostSession::LanguageChanged() { } } -void HostSession::GraphicsQualityChanged(base::GraphicsQuality q) { - // Let our internal scene know. - scene()->GraphicsQualityChanged(q); - - // Let all our activities know. - for (auto&& i : host_activities_) { - i->GraphicsQualityChanged(q); - } -} - auto HostSession::DoesFillScreen() const -> bool { // FIXME not necessarily the case. return true; diff --git a/src/ballistica/scene_v1/support/host_session.h b/src/ballistica/scene_v1/support/host_session.h index 40b370f4..d17de58d 100644 --- a/src/ballistica/scene_v1/support/host_session.h +++ b/src/ballistica/scene_v1/support/host_session.h @@ -70,7 +70,6 @@ class HostSession : public Session { void Draw(base::FrameDef* f) override; void OnScreenSizeChange() override; void LanguageChanged() override; - void GraphicsQualityChanged(base::GraphicsQuality q) override; void DebugSpeedMultChanged() override; auto GetHostSession() -> HostSession* override; auto GetMutableScene() -> Scene* override; diff --git a/src/ballistica/scene_v1/support/scene.cc b/src/ballistica/scene_v1/support/scene.cc index a8b3b162..f45b5de3 100644 --- a/src/ballistica/scene_v1/support/scene.cc +++ b/src/ballistica/scene_v1/support/scene.cc @@ -166,7 +166,7 @@ void Scene::Step() { } // Lastly step our sim. - dynamics_->process(); + dynamics_->Process(); time_ += kGameStepMilliseconds; stepnum_++; @@ -227,13 +227,6 @@ void Scene::DeleteNode(Node* node) { } } -void Scene::GraphicsQualityChanged(base::GraphicsQuality q) { - assert(g_base->InLogicThread()); - for (auto&& i : nodes_) { - i->OnGraphicsQualityChanged(q); - } -} - void Scene::OnScreenSizeChange() { assert(g_base->InLogicThread()); for (auto&& i : nodes_) { diff --git a/src/ballistica/scene_v1/support/scene.h b/src/ballistica/scene_v1/support/scene.h index e7780c2c..6cdf1891 100644 --- a/src/ballistica/scene_v1/support/scene.h +++ b/src/ballistica/scene_v1/support/scene.h @@ -43,7 +43,6 @@ class Scene : public Object { void SetMapBounds(float x, float y, float z, float X, float Y, float Z); void OnScreenSizeChange(); void LanguageChanged(); - void GraphicsQualityChanged(base::GraphicsQuality q); auto out_of_bounds_nodes() -> const std::vector >& { return out_of_bounds_nodes_; } 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 4b3d3c01..9fec9239 100644 --- a/src/ballistica/scene_v1/support/scene_v1_app_mode.cc +++ b/src/ballistica/scene_v1/support/scene_v1_app_mode.cc @@ -1312,15 +1312,6 @@ void SceneV1AppMode::SetPublicPartyStatsURL(const std::string& url) { } } -void SceneV1AppMode::GraphicsQualityChanged(base::GraphicsQuality quality) { - for (auto&& i : sessions_) { - if (!i.Exists()) { - continue; - } - i->GraphicsQualityChanged(quality); - } -} - void SceneV1AppMode::SetPublicPartyPlayerCount(int count) { assert(g_base->InLogicThread()); if (count == public_party_player_count_) { diff --git a/src/ballistica/scene_v1/support/scene_v1_app_mode.h b/src/ballistica/scene_v1/support/scene_v1_app_mode.h index 769c7081..7c98470c 100644 --- a/src/ballistica/scene_v1/support/scene_v1_app_mode.h +++ b/src/ballistica/scene_v1/support/scene_v1_app_mode.h @@ -172,7 +172,6 @@ class SceneV1AppMode : public base::AppMode { sockaddr_storage* from) override; void DrawWorld(base::FrameDef* frame_def) override; auto DoesWorldFillScreen() -> bool override; - void GraphicsQualityChanged(base::GraphicsQuality quality) override; void RunMainMenu(); auto dynamics_sync_time() const { return dynamics_sync_time_; } diff --git a/src/ballistica/scene_v1/support/session.cc b/src/ballistica/scene_v1/support/session.cc index feceb6d0..5ddde60e 100644 --- a/src/ballistica/scene_v1/support/session.cc +++ b/src/ballistica/scene_v1/support/session.cc @@ -33,8 +33,6 @@ void Session::OnScreenSizeChange() {} void Session::LanguageChanged() {} -void Session::GraphicsQualityChanged(base::GraphicsQuality q) {} - void Session::DebugSpeedMultChanged() {} void Session::DumpFullState(SessionStream* out) { diff --git a/src/ballistica/scene_v1/support/session.h b/src/ballistica/scene_v1/support/session.h index 3892e2a5..5e76d009 100644 --- a/src/ballistica/scene_v1/support/session.h +++ b/src/ballistica/scene_v1/support/session.h @@ -34,7 +34,6 @@ class Session : public SceneV1Context { virtual auto GetForegroundContext() -> base::ContextRef; virtual void OnScreenSizeChange(); virtual void LanguageChanged(); - virtual void GraphicsQualityChanged(base::GraphicsQuality q); virtual void DebugSpeedMultChanged(); auto benchmark_type() const -> base::BenchmarkType { return benchmark_type_; } void set_benchmark_type(base::BenchmarkType val) { benchmark_type_ = val; } diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index ff991ab1..0be21980 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 = 21479; +const int kEngineBuildNumber = 21486; 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 901394cf..71bac44c 100644 --- a/src/ballistica/shared/foundation/fatal_error.cc +++ b/src/ballistica/shared/foundation/fatal_error.cc @@ -92,7 +92,7 @@ void FatalError::ReportFatalError(const std::string& message, // momentarily, and also go to platform-specific logging and good ol' // stderr. Logging::V1CloudLog(logmsg); - Logging::DisplayLog("root", LogLevel::kCritical, logmsg); + Logging::EmitLog("root", LogLevel::kCritical, logmsg); fprintf(stderr, "%s\n", logmsg.c_str()); std::string prefix = "FATAL-ERROR-LOG:"; @@ -175,10 +175,10 @@ auto FatalError::HandleFatalError(bool exit_cleanly, // bring the app down ourself. if (!in_top_level_exception_handler) { if (exit_cleanly) { - Logging::DisplayLog("root", LogLevel::kCritical, "Calling exit(1)..."); + Logging::EmitLog("root", LogLevel::kCritical, "Calling exit(1)..."); exit(1); } else { - Logging::DisplayLog("root", LogLevel::kCritical, "Calling abort()..."); + Logging::EmitLog("root", LogLevel::kCritical, "Calling abort()..."); abort(); } } diff --git a/src/ballistica/shared/foundation/logging.cc b/src/ballistica/shared/foundation/logging.cc index e8fc9f33..9e84b713 100644 --- a/src/ballistica/shared/foundation/logging.cc +++ b/src/ballistica/shared/foundation/logging.cc @@ -20,16 +20,16 @@ void Logging::Log(LogLevel level, const std::string& msg) { g_core->python->LoggingCall(level, msg); } -void Logging::DisplayLog(const std::string& name, LogLevel level, - const std::string& msg) { - // Print to the in-app console (with a newline added). +void Logging::EmitLog(const std::string& name, LogLevel level, + const std::string& msg) { + // Print to the dev console. if (g_base_soft) { g_base_soft->PushDevConsolePrintCall(msg + "\n"); } // Ship to platform-specific display mechanisms (android log, etc). if (g_core) { - g_core->platform->DisplayLog(name, level, msg); + g_core->platform->EmitPlatformLog(name, level, msg); } } diff --git a/src/ballistica/shared/foundation/logging.h b/src/ballistica/shared/foundation/logging.h index 792665d2..d08b56e0 100644 --- a/src/ballistica/shared/foundation/logging.h +++ b/src/ballistica/shared/foundation/logging.h @@ -29,12 +29,11 @@ class Logging { /// babase is imported may not be visible in the app for that same reason. static void Log(LogLevel level, const std::string& msg); - /// Immediately display a log message in the in-app console, - /// platform-specific logs, etc. This generally should not be called - /// directly but instead wired up to display messages coming from the - /// Python logging system. - static void DisplayLog(const std::string& name, LogLevel level, - const std::string& msg); + /// Send a log message to the in-app console, platform-specific logs, etc. + /// This generally should not be called directly but instead wired up to + /// log messages coming through the Python logging system. + static void EmitLog(const std::string& name, LogLevel level, + const std::string& msg); /// Write a message to the v1 cloud log. This is considered legacy and /// will be phased out eventually. diff --git a/src/ballistica/shared/foundation/object.cc b/src/ballistica/shared/foundation/object.cc index a24dd221..1324e8d5 100644 --- a/src/ballistica/shared/foundation/object.cc +++ b/src/ballistica/shared/foundation/object.cc @@ -20,7 +20,6 @@ using core::g_core; Object::Object() { #if BA_DEBUG_BUILD // Mark when we were born. - // NOTE: Using core's internal globals here; don't do this normally. assert(g_core); object_birth_time_ = g_core->GetAppTimeMillisecs(); @@ -41,7 +40,6 @@ Object::Object() { Object::~Object() { #if BA_DEBUG_BUILD { - // NOTE: using core's internal globals here; don't do this normally! assert(g_core); // Pull ourself from the global obj list. std::scoped_lock lock(g_core->object_list_mutex); @@ -70,6 +68,7 @@ Object::~Object() { #endif // BA_DEBUG_BUILD // Invalidate all our weak refs. + // // We could call Release() on each but we'd have to deactivate the // thread-check since virtual functions won't work as expected in a // destructor. Also we can take a few shortcuts here since we know @@ -85,7 +84,6 @@ Object::~Object() { auto Object::GetObjectTypeName() const -> std::string { // Default implementation just returns type name. - // Note: using core's globals directly; don't normally do this! if (g_core) { return g_core->platform->DemangleCXXSymbol(typeid(*this).name()); } @@ -112,7 +110,6 @@ auto Object::GetThreadOwnership() const -> Object::ThreadOwnership { void Object::LsObjects() { #if BA_DEBUG_BUILD - // Note: using core's internal globals here; don't normally do this. assert(g_core); std::string s; { @@ -192,12 +189,12 @@ void Object::ObjectUpdateForAcquire() { } } -void Object::ObjectThreadCheck() { +void Object::ObjectThreadCheck() const { if (!thread_checks_enabled_) { return; } - ThreadOwnership thread_ownership = GetThreadOwnership(); + auto thread_ownership = GetThreadOwnership(); // Special case; graphics context (not simply a thread so have to handle // specially). diff --git a/src/ballistica/shared/foundation/object.h b/src/ballistica/shared/foundation/object.h index 91c38c46..c4f39b5d 100644 --- a/src/ballistica/shared/foundation/object.h +++ b/src/ballistica/shared/foundation/object.h @@ -12,23 +12,26 @@ namespace ballistica { /// Objects supporting strong and weak referencing and thread enforcement. -/// A rule or two for for Objects: -/// Don't throw exceptions out of object destructors; -/// This will break references to that object and lead to crashes if/when they -/// are used. class Object { - public: + 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: virtual ~Object(); - // Object classes can provide descriptive names for themselves; - // these are used for debugging and other purposes. - // The default is to use the C++ symbol name, demangling it when possible. - // IMPORTANT: Do not rely on this being consistent across builds/platforms. + // Object classes can provide descriptive names for themselves; these are + // used for debugging and other purposes. The default is to use the C++ + // symbol name, demangling it when possible. IMPORTANT: Do not rely on + // this being consistent across builds/platforms. virtual auto GetObjectTypeName() const -> std::string; - // Provide a brief description of this particular object; by default returns - // type-name plus address. + // Provide a brief description of this particular object; by default + // returns type-name plus address. virtual auto GetObjectDescription() const -> std::string; enum class ThreadOwnership { @@ -42,25 +45,26 @@ class Object { #if BA_DEBUG_BUILD - /// This is called when adding or removing a reference to an Object; - /// it can perform sanity-tests to make sure references are not being - /// added at incorrect times or from incorrect threads. - /// The default implementation uses the per-object - /// ThreadOwnership/EventLoopID values accessible below. NOTE: this - /// check runs only in the debug build so don't add any logical side-effects! - virtual void ObjectThreadCheck(); + /// This is called when adding or removing a reference to an Object; it + /// can perform sanity-tests to make sure references are not being added + /// at incorrect times or from incorrect threads. The default + /// implementation uses the per-object ThreadOwnership/EventLoopID values + /// accessible below. + /// + /// NOTE: This check runs *only* in the debug build so don't include any + /// logical side-effects in these checks! + void ObjectThreadCheck() const; #endif - /// Called by the default ObjectThreadCheck() to determine ThreadOwnership - /// for an Object. The default uses the object's individual value - /// (which defaults to ThreadOwnership::kClassDefault and can be set via - /// SetThreadOwnership()) + /// Called by the default ObjectThreadCheck() to determine ownership for + /// an Object. By default, an object is owned by a specific thread, + /// defaulting to the logic thread. virtual auto GetThreadOwnership() const -> ThreadOwnership; - /// Return the exact thread to check for with ThreadOwnership::kClassDefault - /// (in the default ObjectThreadCheck implementation at least). - /// Default returns EventLoopID::kLogic + /// Return the exact thread to check for with + /// ThreadOwnership::kClassDefault (in the default ObjectThreadCheck + /// implementation at least). Default returns EventLoopID::kLogic virtual auto GetDefaultOwnerThread() const -> EventLoopID; /// Set thread ownership for an individual object. @@ -73,12 +77,12 @@ class Object { #endif } - // Return true if the provided obj ptr is not null, is ref-counted, and has at - // least 1 strong ref. This is generally a good thing for calls accepting - // object ptrs to check. It is considered bad practice to perform operations - // with not-yet-reffed objects. Note that in some cases this may return - // false positives, so only use this as a sanity check and only take action - // for a negative result. + // Return true if the provided obj ptr is not null, is ref-counted, and + // has at least 1 strong ref. This is generally a good thing for calls + // accepting object ptrs to check. It is considered bad practice to + // perform operations with not-yet-reffed objects. Note that in some cases + // this may return false positives, so only use this as a sanity check and + // only take action for a negative result. static auto IsValidManagedObject(Object* obj) -> bool { if (!obj) { return false; @@ -91,11 +95,11 @@ class Object { return (obj->object_strong_ref_count_ > 0); } - // Return true if the object seems to be valid and was allocated as unmanaged. - // Code that plans to explicitly delete raw passed pointers can check this - // for peace of mind. Note that for some build types this will return false - // positives, so only use this as a sanity check and only take action for - // negative results. + // Return true if the object seems to be valid and was allocated as + // unmanaged. Code that plans to explicitly delete raw passed pointers can + // check this for peace of mind. Note that for some build types this will + // return false positives, so only use this as a sanity check and only + // take action for negative results. static auto IsValidUnmanagedObject(Object* obj) -> bool { if (!obj) { return false; @@ -108,12 +112,53 @@ class Object { return false; } #endif - // We don't store specifics in release builds; assume everything is peachy. + // We don't store specifics in release builds; assume everything is + // peachy. return true; } + auto object_strong_ref_count() const -> int { return object_strong_ref_count_; } + + /// Increment the strong reference count for an Object. In most cases you + /// should let Ref objects handle this for you and not call this directly. + void ObjectIncrementStrongRefCount() { +#if BA_DEBUG_BUILD + ObjectUpdateForAcquire(); + ObjectThreadCheck(); + + // Obvs shouldn't be referencing dead stuff. + assert(!object_is_dead_); + + // Complain if trying ot create a ref to a non-ref-counted obj. + if (!object_is_ref_counted_) { + FatalError("Attempting to create a strong-ref to non-refcounted obj: " + + GetObjectDescription()); + } + object_has_been_strong_reffed_ = true; +#endif // BA_DEBUG_BUILD + + object_strong_ref_count_++; + } + + /// Decrement the strong reference count for the Object, deleting it if it + /// hits zero. In most cases you should let Ref objects handle this for + /// you and not call this directly. + void ObjectDecrementStrongRefCount() { +#if BA_DEBUG_BUILD + ObjectThreadCheck(); +#endif + assert(object_strong_ref_count_ > 0); + object_strong_ref_count_--; + if (object_strong_ref_count_ == 0) { +#if BA_DEBUG_BUILD + object_is_dead_ = true; +#endif + delete this; + } + } + template class Ref; template @@ -193,9 +238,8 @@ class Object { PyExcType::kReference); } - // Yes, reinterpret_cast is evil, but we make sure - // we only operate on cases where this is valid - // (see Acquire()). + // Yes, reinterpret_cast is evil, but we make sure we only operate on + // cases where this is valid (see Acquire()). return *reinterpret_cast(obj_); } @@ -207,8 +251,8 @@ class Object { PyExcType::kReference); } - // Yes, reinterpret_cast is evil, but we make sure we only operate - // on cases where this is valid (see Acquire()). + // Yes, reinterpret_cast is evil, but we make sure we only operate on + // cases where this is valid (see Acquire()). return reinterpret_cast(obj_); } @@ -263,8 +307,8 @@ class Object { auto operator=(U* ptr) -> WeakRef& { Release(); - // Go through our template type instead of assigning directly - // to our Object* so we catch invalid assigns at compile-time. + // Go through our template type instead of assigning directly to our + // Object* so we catch invalid assigns at compile-time. T* tmp = ptr; if (tmp) Acquire(tmp); @@ -295,13 +339,13 @@ class Object { // Default constructor. WeakRef() = default; - /// Copy constructor. Note that, by making this explicit, we require code - /// to be a bit more verbose. For example, we can't just do 'return - /// some_ref;' from a function and instead have to do 'return - /// Object::WeakRef(some_ref)'. However I feel this extra - /// verbosity is good; we're tossing around a mix of pointers and - /// strong-refs and weak-refs so it's good to be aware exactly where refs - /// are being added/etc. + /// Copy constructor. Note that, by making this explicit, we require + /// code to be a bit more verbose. For example, we can't just do 'return + /// some_ref;' from a function that returns a WeakRef and instead have + /// to do 'return Object::WeakRef(some_ref)'. However I feel + /// this extra verbosity is good; we're tossing around a mix of pointers + /// and strong-refs and weak-refs so it's good to be aware exactly where + /// refs are being added/etc. explicit WeakRef(const WeakRef& ref) { *this = ref.Get(); } /// Create from a pointer of any compatible type. @@ -469,13 +513,13 @@ class Object { /// Default constructor. Ref() = default; - /// Copy constructor. Note that, by making this explicit, we require code - /// to be a bit more verbose. For example, we can't just do 'return - /// some_ref;' from a function and instead have to do 'return - /// Object::Ref(some_ref)'. However I feel this extra verbosity - /// is good; we're tossing around a mix of pointers and strong-refs and - /// weak-refs so it's good to be aware exactly where refs are being - /// added/etc. + /// Copy constructor. Note that, by making this explicit, we require + /// code to be a bit more verbose. For example, we can't just do 'return + /// some_ref;' from a function that returns a Ref and instead have to do + /// 'return Object::Ref(some_ref)'. However I feel this extra + /// verbosity is good; we're tossing around a mix of pointers and + /// strong-refs and weak-refs so it's good to be aware exactly where + /// refs are being added/etc. explicit Ref(const Ref& ref) { *this = ref.Get(); } /// Create from a compatible pointer. @@ -505,42 +549,16 @@ class Object { PyExcType::kReference); } -#if BA_DEBUG_BUILD - obj->ObjectUpdateForAcquire(); - obj->ObjectThreadCheck(); - - // Obvs shouldn't be referencing dead stuff. - assert(!obj->object_is_dead_); - - // Complain if trying ot create a ref to a non-ref-counted obj. - if (!obj->object_is_ref_counted_) { - FatalError("Attempting to create a strong-ref to non-refcounted obj: " - + obj->GetObjectDescription()); - } - obj->object_has_been_strong_reffed_ = true; -#endif // BA_DEBUG_BUILD - - obj->object_strong_ref_count_++; + obj->ObjectIncrementStrongRefCount(); obj_ = obj; } void Release() { if (obj_ != nullptr) { -#if BA_DEBUG_BUILD - obj_->ObjectThreadCheck(); -#endif - assert(obj_->object_strong_ref_count_ > 0); - obj_->object_strong_ref_count_--; - T* tmp = obj_; - - // Invalidate ref *before* delete to avoid potential double-release. + auto* obj = obj_; + // Invalidate ref *before* to avoid potential recursive-release. obj_ = nullptr; - if (tmp->object_strong_ref_count_ == 0) { -#if BA_DEBUG_BUILD - tmp->object_is_dead_ = true; -#endif - delete tmp; - } + obj->ObjectDecrementStrongRefCount(); } } T* obj_{}; @@ -549,10 +567,10 @@ class Object { /// Object::New(): The preferred way to create ref-counted Objects. /// Allocates a new Object with the provided args and returns a strong /// reference to it. - /// Generally you pass a single type to be instantiated and returned, - /// but you can optionally specify the two separately. - /// (for instance you may want to create a Button but return - /// a Ref to a Widget) + /// + /// Generally you pass a single type to be instantiated and returned, but + /// you can optionally specify the two separately. For example, you may + /// want to create a Button but return a Ref to a Widget. template [[nodiscard]] static auto New(ARGS&&... args) -> Object::Ref { auto* ptr = new TALLOC(std::forward(args)...); @@ -642,17 +660,19 @@ class Object { private: #if BA_DEBUG_BUILD - // Making operator new private here to help ensure all of our dynamic - // allocation/deallocation goes through our special functions (New(), - // NewDeferred(), etc.). However, sticking with original new for release - // builds since it may handle corner cases that this does not. + // Making operator new private here purely to help enforce all of our + // dynamic allocation/deallocation going through our special functions + // (New(), NewDeferred(), etc.). However, sticking with original new for + // release builds since we don't actually intend to muck with its runtime + // behavior and the default might be somehow smarter than ours here. auto operator new(size_t size) -> void* { return new char[size]; } void ObjectUpdateForAcquire(); - bool object_has_been_strong_reffed_{}; - bool object_is_ref_counted_{}; - bool object_is_pending_deferred_{}; - bool object_is_unmanaged_{}; - bool object_is_dead_{}; + + bool object_has_been_strong_reffed_ : 1 {}; + bool object_is_ref_counted_ : 1 {}; + bool object_is_pending_deferred_ : 1 {}; + bool object_is_unmanaged_ : 1 {}; + bool object_is_dead_ : 1 {}; Object* object_next_{}; Object* object_prev_{}; ThreadOwnership thread_ownership_{ThreadOwnership::kClassDefault}; @@ -661,8 +681,8 @@ class Object { millisecs_t object_birth_time_{}; bool object_printed_warning_{}; #endif - int object_strong_ref_count_{}; WeakRefBase* object_weak_refs_{}; + int object_strong_ref_count_{}; BA_DISALLOW_CLASS_COPIES(Object); }; // Object diff --git a/src/ballistica/shared/generic/snapshot.h b/src/ballistica/shared/generic/snapshot.h new file mode 100644 index 00000000..c5591c92 --- /dev/null +++ b/src/ballistica/shared/generic/snapshot.h @@ -0,0 +1,26 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_SHARED_GENERIC_SNAPSHOT_H_ +#define BALLISTICA_SHARED_GENERIC_SNAPSHOT_H_ + +#include "ballistica/shared/foundation/object.h" + +namespace ballistica { + +/// Wraps a const instance of some type in a logic-thread-owned Object. To +/// use this, allocate some object using new(), fill it out, and pass it to +/// this which will take ownership and expose it as a const. +template +class Snapshot : public Object { + public: + explicit Snapshot(T* data) : data_{data} { assert(data); } + ~Snapshot() { delete data_; } + auto* Get() const { return data_; } + + private: + const T* data_; +}; + +} // namespace ballistica + +#endif // BALLISTICA_SHARED_GENERIC_SNAPSHOT_H_ diff --git a/src/tools/pcommandbatch/pcommandbatch.c b/src/tools/pcommandbatch/pcommandbatch.c index 28fbb5c3..1137ac10 100644 --- a/src/tools/pcommandbatch/pcommandbatch.c +++ b/src/tools/pcommandbatch/pcommandbatch.c @@ -307,7 +307,7 @@ int establish_connection_(const struct Context_* ctx) { retry_attempt + 1); } } else if (errno == ECONNREFUSED) { - // Am seeing this very rarely on random one-off commands. I'm + // Am seeing these very rarely on random one-off commands. I'm // guessing there's some race condition at the OS level where the // port-file write goes through before the socket is actually truly // accepting connections. A retry should succeed. @@ -318,6 +318,15 @@ int establish_connection_(const struct Context_* ctx) { ctx->instance_prefix, ctx->instance_num, ctx->pid, retry_attempt + 1); } + } else if (errno == EINVAL) { + // Saw this randomly once on Mac. Not sure what could have led to it. + if (ctx->verbose) { + fprintf(stderr, + "pcommandbatch client %s_%d (pid %d): got EINVAL" + " on connect attempt %d.\n", + ctx->instance_prefix, ctx->instance_num, ctx->pid, + retry_attempt + 1); + } } else { // Currently not retrying on other errors. fprintf(stderr, diff --git a/tools/efrotools/xcodebuild.py b/tools/efrotools/xcodebuild.py index 7933d72d..718a4dbd 100644 --- a/tools/efrotools/xcodebuild.py +++ b/tools/efrotools/xcodebuild.py @@ -983,8 +983,8 @@ class XCodeBuild: # on to clarify in that case (unless requested not to). assert self._section is not None sys.stdout.write( - f'{Clr.YLW}Unexpected {self._section.value}' - f' Output:{Clr.RST} {line}' + f'{Clr.YLW}Unfiltered Output (Section {self._section.value}):' + f'{Clr.RST} {line}' ) else: sys.stdout.write(line) From daa2f571ce2d3a101e149912f5437348657b2b88 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 20 Oct 2023 18:27:17 -0700 Subject: [PATCH 6/9] tidying --- .efrocachemap | 56 ++++++------ CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/base/app_adapter/app_adapter.h | 5 -- .../base/app_adapter/app_adapter_apple.cc | 6 -- .../base/app_adapter/app_adapter_apple.h | 4 - .../base/app_adapter/app_adapter_sdl.cc | 89 ------------------- .../base/graphics/graphics_server.cc | 19 ---- .../base/graphics/graphics_server.h | 10 --- src/ballistica/shared/ballistica.cc | 2 +- 10 files changed, 31 insertions(+), 164 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 4f28e4fe..018b6d0c 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": "48b5a58b401a2b22b88491f7bcd0e22a", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "6d83849db3e1398503e2bb682eb4323e", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "b054c284b778dc77edc9c9b046303f46", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b16789743a603fac02763c09bbca446b", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "ab0a78d42cc511b4041478205e892897", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4bbb41936ffe72a7fe9bdc803761b937", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "a1427251545496f84c4d4e2d90e6e25a", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "729bec30bafe25cac07f920c0cc30ab8", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f8b086fdf6bca929ebc75b117b80f522", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "7d8f3ffe791e5a665ecbb2c517483814", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "5f4207138b152a110593c6c5ea8a9b32", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "4211f250197995e7df6942d32cffd202", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "40be1e38cbac3baf88dee161eeb912e1", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "d4aacb95a1855e969d1cc8db33732c40", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "570f49dc1de66e3fe75d76ee5f9306e0", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ad319e6fb3cd7043a597f0780de42a98", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "4c15b26f43b4cb81f433beeb927c8aa6", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "a06aaa7a95abb56d49ba7925cc503a28", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "82619b88184faf3ef7ae4bf41ea282ce", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "61251e6fe58347224750fdf30d4bf8bc", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "a88d77584445b56200f7a4d8114479e8", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "4e88d22f136619fefd64f6ae0fd7e52c", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a955ca7a92a1e76c93a3af5ffd0fcdf8", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "1d00f4ee25aff23dd1a12fa08a1427c7", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "8917a834461b62e8e31baf6d31f50dc6", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "a1292d9dfb8880ddfac6d6b0313ad9e9", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "b417628417ee7c7d652da528ab0df59f", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7d5f3261fa944c79e3b5e80751c4ec02", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "afcc34bd2e482a0913ca9105413840ab", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "c4c62a908705df5c136a3df2eb58f67a", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "3e25752aea8cdc0ae68fb49869dfe79f", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "64ccbd2e2d2f3322663ca1b496b362ba", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "ab7725c946a92f76e0eb739d6c0e5c74", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "5190ee608b6b5b62a97620cae58241d3", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "aa29ab65e0c4d22bc81f85198c74c39f", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "89dddd6606408d3d9990992b8ae52deb", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "330b671091d23f4259dff471a006e40b", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "709017df7f0de395cc2c8ec2d22b5fac", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d4f9a706114fdb3763f4982c87608ed6", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "d6532d25e4f8541402fcf1d7b0160048", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "bbd5b31cd9b4d30e48ce46e2cf968fcf", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "4e11b895cbf2e1339cf34bc06c54a4ea", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "bbd5b31cd9b4d30e48ce46e2cf968fcf", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "d0940a2237c33b922cf3747cbf3910ef", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "48c4873dae2344c1d4092a1d85dab424", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "52ccfcbba95dcf3d06620748690446be", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "8369a217dc8cd95db308851de9f35d86", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6bc8e9e67a0cbe50ab2c6891d454570f", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "2ce9d1659647bca4725f404d192c3554", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "8fd2fd1ec12170942823e809332e8cb9", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "f40bd1a61620168791b88901975ea8ee", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4e3f244ac43cd400ffdbd2ac2e887399", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "a5e5e62c259e23429eca4af7054cc7cb", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "dbb1863afd32a5624a5ef949fe8b48aa", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "11cd1f5e8099c505f429d224e0d8dcbf", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "bb9c8c00b6ef5b66422910f8cf9ccc83", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "fe8dfa263afab3982571178b0f2cff68", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "7f83d9986e6f0d66ed54692e740c2769", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "6f67485c14b38415888360bb3122a721", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "ea6d6a2bcdf18995af09452be534c947", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "3290cee0f4d306788ebd8a60c608e5f5", "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": "bb96031e3f844704fcc9a0549a6d2c41", diff --git a/CHANGELOG.md b/CHANGELOG.md index eda3bcdd..81e96b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21486, api 8, 2023-10-20) +### 1.7.28 (build 21487, api 8, 2023-10-20) - 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 b34bebc9..7b8bcc0d 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 = 21486 +TARGET_BALLISTICA_BUILD = 21487 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/app_adapter/app_adapter.h b/src/ballistica/base/app_adapter/app_adapter.h index 606b5113..25fb83de 100644 --- a/src/ballistica/base/app_adapter/app_adapter.h +++ b/src/ballistica/base/app_adapter/app_adapter.h @@ -195,11 +195,6 @@ class AppAdapter { /// the logic subsystem. This will be called initially to jump-start the /// graphics system as well as before frame draws to update any new /// settings coming in. - /// - /// Whenever graphics settings will result in a change to the graphics - /// context (ie: something visible to rendering code in the logic thread) - /// the adapter should call g_base->graphics_server->set_context() with - /// the updated context. virtual void ApplyGraphicsSettings(const GraphicsSettings* settings); protected: diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.cc b/src/ballistica/base/app_adapter/app_adapter_apple.cc index 69b36034..aaefa65e 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.cc +++ b/src/ballistica/base/app_adapter/app_adapter_apple.cc @@ -74,12 +74,6 @@ void AppAdapterApple::ReloadRenderer_(const GraphicsSettings* settings) { gs->set_renderer(new RendererGL()); } - // Set a dummy screen resolution to start with. The main thread will kick - // along the latest real resolution just before each frame draw, but we - // need *something* here or else we'll get errors due to framebuffers - // getting made at size 0/etc. - // g_base->graphics_server->SetScreenResolution(320.0, 240.0); - // Update graphics quality based on request. gs->set_graphics_quality_requested(settings->graphics_quality); gs->set_texture_quality_requested(settings->texture_quality); diff --git a/src/ballistica/base/app_adapter/app_adapter_apple.h b/src/ballistica/base/app_adapter/app_adapter_apple.h index d800759d..9217299b 100644 --- a/src/ballistica/base/app_adapter/app_adapter_apple.h +++ b/src/ballistica/base/app_adapter/app_adapter_apple.h @@ -32,9 +32,6 @@ class AppAdapterApple : public AppAdapter { /// Called by FromSwift. auto TryRender() -> bool; - /// Called by FromSwift. - // void SetScreenResolution(float pixel_width, float pixel_height); - auto FullscreenControlAvailable() const -> bool override; auto FullscreenControlGet() const -> bool override; void FullscreenControlSet(bool fullscreen) override; @@ -42,7 +39,6 @@ class AppAdapterApple : public AppAdapter { -> std::optional override; auto HasDirectKeyboardInput() -> bool override; - void EnableResizeFriendlyMode(int width, int height); protected: diff --git a/src/ballistica/base/app_adapter/app_adapter_sdl.cc b/src/ballistica/base/app_adapter/app_adapter_sdl.cc index a77ee149..b43f8397 100644 --- a/src/ballistica/base/app_adapter/app_adapter_sdl.cc +++ b/src/ballistica/base/app_adapter/app_adapter_sdl.cc @@ -629,95 +629,6 @@ auto AppAdapterSDL::GetSDLJoystickInput_(int sdl_joystick_id) const return nullptr; // Epic fail. } -// void AppAdapterSDL::ApplyGraphicsSettings_(const GraphicsSettings_* settings) -// { -// assert(g_core->InMainThread()); -// assert(!g_core->HeadlessMode()); - -// // In strict mode, allow graphics stuff while in here. -// auto allow = ScopedAllowGraphics_(this); - -// bool do_toggle_fs{}; -// bool do_set_existing_fullscreen{}; - -// auto* graphics_server = g_base->graphics_server; - -// // We need a full renderer reload if quality values have changed -// // or if we don't have a renderer yet. -// bool need_full_reload = ((sdl_window_ == nullptr -// || graphics_server->texture_quality_requested() -// != settings->texture_quality) -// || (graphics_server->graphics_quality_requested() -// != settings->graphics_quality)); - -// if (need_full_reload) { -// ReloadRenderer_(settings->fullscreen, settings->graphics_quality, -// settings->texture_quality); -// } else if (settings->fullscreen != fullscreen_) { -// SDL_SetWindowFullscreen( -// sdl_window_, settings->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : -// 0); -// fullscreen_ = settings->fullscreen; -// } - -// // VSync always gets set independent of the screen (though we set it down -// // here to make sure we have a screen when its set). -// VSync vsync; -// switch (settings->vsync) { -// case VSyncRequest::kNever: -// vsync = VSync::kNever; -// break; -// case VSyncRequest::kAlways: -// vsync = VSync::kAlways; -// break; -// case VSyncRequest::kAuto: -// vsync = VSync::kAdaptive; -// break; -// default: -// vsync = VSync::kNever; -// break; -// } -// if (vsync != vsync_) { -// switch (vsync) { -// case VSync::kUnset: -// case VSync::kNever: { -// SDL_GL_SetSwapInterval(0); -// vsync_actually_enabled_ = false; -// break; -// } -// case VSync::kAlways: { -// SDL_GL_SetSwapInterval(1); -// vsync_actually_enabled_ = true; -// break; -// } -// case VSync::kAdaptive: { -// // In this case, let's try setting to 'adaptive' and turn it off if -// // that is unsupported. -// auto result = SDL_GL_SetSwapInterval(-1); -// if (result == 0) { -// vsync_actually_enabled_ = true; -// } else { -// SDL_GL_SetSwapInterval(0); -// vsync_actually_enabled_ = false; -// } -// break; -// } -// } -// vsync_ = vsync; -// } - -// // This we can set anytime. Probably could have just set it from the logic -// // thread where we read it, but let's be pedantic and keep everything to -// // the main thread. -// max_fps_ = settings->max_fps; - -// // Take -1 to mean no max. Otherwise clamp to a reasonable range. -// if (max_fps_ != -1) { -// max_fps_ = std::max(10, max_fps_); -// max_fps_ = std::min(99999, max_fps_); -// } -// } - void AppAdapterSDL::ReloadRenderer_(const GraphicsSettings_* settings) { assert(g_base->app_adapter->InGraphicsContext()); diff --git a/src/ballistica/base/graphics/graphics_server.cc b/src/ballistica/base/graphics/graphics_server.cc index 33025a94..98351f47 100644 --- a/src/ballistica/base/graphics/graphics_server.cc +++ b/src/ballistica/base/graphics/graphics_server.cc @@ -311,25 +311,6 @@ void GraphicsServer::ReloadLostRenderer() { }); } -void GraphicsServer::SetNullGraphics() { - // We don't actually make or update a renderer in headless, but we - // still need to set our list of supported textures types/etc. to avoid - // complaints. - std::list c_types; - SetTextureCompressionTypes(c_types); - graphics_quality_requested_ = GraphicsQualityRequest::kLow; - graphics_quality_ = GraphicsQuality::kLow; - // graphics_quality_set_ = true; - texture_quality_requested_ = TextureQualityRequest::kLow; - texture_quality_ = TextureQuality::kLow; - // texture_quality_set_ = true; - - FatalError("FIXME REWORK THIS"); - // Let the logic thread know screen creation is done (or lack thereof). - // g_base->logic->event_loop()->PushCall( - // [] { g_base->logic->OnGraphicsReady(); }); -} - void GraphicsServer::set_renderer(Renderer* renderer) { assert(g_base->app_adapter->InGraphicsContext()); assert(!renderer_loaded_); diff --git a/src/ballistica/base/graphics/graphics_server.h b/src/ballistica/base/graphics/graphics_server.h index abc333f2..ed2cbd5b 100644 --- a/src/ballistica/base/graphics/graphics_server.h +++ b/src/ballistica/base/graphics/graphics_server.h @@ -54,16 +54,6 @@ class GraphicsServer { void ApplySettings(const GraphicsSettings* settings); - /// The AppAdapter should call this to inform the engine of screen size - /// changes. Changes will be applied to the server and then sent to the - /// logic thread to apply to various app systems (ui, etc.). - // void SetScreenResolution(float h, float v); - - /// Used by headless builds to init the graphics-server into a - /// non-functional state. - void SetNullGraphics(); - - // void PushSetScreenPixelScaleCall(float pixel_scale); void PushReloadMediaCall(); void PushRemoveRenderHoldCall(); void PushComponentUnloadCall( diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 0be21980..06a5ad67 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 = 21486; +const int kEngineBuildNumber = 21487; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; From 92fdd4b04326c0e095c54ccdfd8d16b56cc95a5d Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 20 Oct 2023 22:24:49 -0700 Subject: [PATCH 7/9] mac build polishing --- .efrocachemap | 78 +++++++++---------- CHANGELOG.md | 2 +- src/assets/ba_data/python/babase/_hooks.py | 14 ++++ src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/base/assets/assets.cc | 5 +- src/ballistica/base/assets/assets.h | 2 + src/ballistica/base/base.cc | 4 + src/ballistica/base/base.h | 13 +++- src/ballistica/base/python/base_python.h | 1 + .../python/methods/python_methods_misc.cc | 24 ++++++ src/ballistica/core/support/base_soft.h | 1 + src/ballistica/shared/ballistica.cc | 2 +- src/ballistica/shared/python/python_ref.cc | 4 + src/ballistica/shared/python/python_ref.h | 1 + src/meta/babasemeta/pyembed/binding_base.py | 1 + 15 files changed, 106 insertions(+), 48 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 018b6d0c..35d2bad2 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": "e70277fc6325126d3d893524c8df03c9", + "build/assets/ba_data/data/languages/english.json": "550aecdf2530832a8c095c2bda9ea8f0", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/filipino.json": "347f38524816691170d266708fe25894", "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": "b8dfd407fb7fd9b268129c364b70ca54", + "build/assets/ba_data/data/languages/gibberish.json": "517e9c79ce8242af82366bbdaaf678a4", "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,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": "a88d77584445b56200f7a4d8114479e8", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "4e88d22f136619fefd64f6ae0fd7e52c", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a955ca7a92a1e76c93a3af5ffd0fcdf8", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "1d00f4ee25aff23dd1a12fa08a1427c7", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "8917a834461b62e8e31baf6d31f50dc6", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "a1292d9dfb8880ddfac6d6b0313ad9e9", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "b417628417ee7c7d652da528ab0df59f", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7d5f3261fa944c79e3b5e80751c4ec02", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "afcc34bd2e482a0913ca9105413840ab", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "c4c62a908705df5c136a3df2eb58f67a", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "3e25752aea8cdc0ae68fb49869dfe79f", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "64ccbd2e2d2f3322663ca1b496b362ba", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "ab7725c946a92f76e0eb739d6c0e5c74", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "5190ee608b6b5b62a97620cae58241d3", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "aa29ab65e0c4d22bc81f85198c74c39f", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "89dddd6606408d3d9990992b8ae52deb", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "330b671091d23f4259dff471a006e40b", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "709017df7f0de395cc2c8ec2d22b5fac", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d4f9a706114fdb3763f4982c87608ed6", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "d6532d25e4f8541402fcf1d7b0160048", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "bbd5b31cd9b4d30e48ce46e2cf968fcf", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "f029c0682da29f46e5c9782bd2567f82", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "d2fe151ab5836d1f60b85bdc7d7880b1", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "ca6b96c7c6f77ab6ca93698da0022cb6", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "5342b4e44c8f414b34582ceec0ef0c8d", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "67e06b38ba6e5fa44fcb0b196618dda7", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "5a1a366e4458f48230a8856a04e3d15a", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "c1f9b4a7e4d8aef89de664fd19178b17", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7608557c57d636c81213afe0a68cd921", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "31465c3f4b869d6d2a4a004bcf43c058", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "4092f2c09d4717cbe22a9847733458ea", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "a98776c44ceae70a5582fa3a31894f42", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "107c108da827cc647d26ea8e20e5a02a", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "d4e3d6b79648d478003282e20b583cf3", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "396f882b13a97bec718222d14be7a825", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "118e5039eb06c8d641baa3a94c511a20", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "2c4b12f038ad8eb9838860b8cce2f491", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "650b1181dda309c492abe2a26cedfd9a", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "32ac6359eb0296a319ddfcba3fcd04bc", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "731540517a251db7332d0f841d686d01", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a19df9a09272d486666a4cb28702cf2b", + "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": "bbd5b31cd9b4d30e48ce46e2cf968fcf", + "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": "b483573e1ef7e6be1090c67187e9d1d8", + "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": "b483573e1ef7e6be1090c67187e9d1d8", + "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": "cf4e9ef8006953c365b0928c68f5a21b", + "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": "cf4e9ef8006953c365b0928c68f5a21b", + "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": "840e96e79a56393c353184475cf28fbc", + "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": "d0940a2237c33b922cf3747cbf3910ef", + "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": "dbb1863afd32a5624a5ef949fe8b48aa", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "11cd1f5e8099c505f429d224e0d8dcbf", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "bb9c8c00b6ef5b66422910f8cf9ccc83", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "fe8dfa263afab3982571178b0f2cff68", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "7f83d9986e6f0d66ed54692e740c2769", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "6f67485c14b38415888360bb3122a721", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "ea6d6a2bcdf18995af09452be534c947", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "3290cee0f4d306788ebd8a60c608e5f5", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "13615b9d10736d72e3b3bec605518645", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "99369ccd4edfe5cc2d54b18aa77ca1cb", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "33a19e9eb9bd9b655cbe70d8e250425b", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "021114e14a72c621dc6fb7d4b3e41b5f", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "cff4a800e4ea1cdb7690d088a4db0abb", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "107e289fb15a0d3177ed16aa8f076041", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4d031e12072278cf78570b64a2f7e533", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "d7e631f313c7b99d92c41efaf6305b65", "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": "bb96031e3f844704fcc9a0549a6d2c41", + "src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706", "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 81e96b70..72a3dce1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21487, api 8, 2023-10-20) +### 1.7.28 (build 21488, api 8, 2023-10-20) - 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/_hooks.py b/src/assets/ba_data/python/babase/_hooks.py index 69881e96..8ea73a5e 100644 --- a/src/assets/ba_data/python/babase/_hooks.py +++ b/src/assets/ba_data/python/babase/_hooks.py @@ -389,3 +389,17 @@ def string_edit_adapter_can_be_replaced(adapter: StringEditAdapter) -> bool: def get_dev_console_tab_names() -> list[str]: """Return the current set of dev-console tab names.""" return [t.name for t in _babase.app.devconsole.tabs] + + +def unsupported_controller_message(name: str) -> None: + """Print a message when an unsupported controller is connected.""" + from babase._language import Lstr + + # Ick; this can get called early in the bootstrapping process + # before we're allowed to load assets. Guard against that. + if _babase.asset_loads_allowed(): + _babase.getsimplesound('error').play() + _babase.screenmessage( + Lstr(resource='unsupportedControllerText', subs=[('${NAME}', name)]), + color=(1, 0, 0), + ) diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 7b8bcc0d..1b03a2f8 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 = 21487 +TARGET_BALLISTICA_BUILD = 21488 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/base/assets/assets.cc b/src/ballistica/base/assets/assets.cc index e00b84f3..1fe097d1 100644 --- a/src/ballistica/base/assets/assets.cc +++ b/src/ballistica/base/assets/assets.cc @@ -83,10 +83,9 @@ void Assets::StartLoading() { assert(g_base->audio_server && g_base->assets_server && g_base->graphics_server); assert(g_base->graphics->has_client_context()); - // assert(g_base->graphics_server->texture_compression_types_are_set()); - // assert(g_base->graphics_server->texture_quality_set()); - assert(!asset_loads_allowed_); // We should only be called once. + // We should only be called once. + assert(!asset_loads_allowed_); asset_loads_allowed_ = true; // Just grab the lock once for all this stuff for efficiency. diff --git a/src/ballistica/base/assets/assets.h b/src/ballistica/base/assets/assets.h index cbfa7ba1..0dc756ec 100644 --- a/src/ballistica/base/assets/assets.h +++ b/src/ballistica/base/assets/assets.h @@ -117,6 +117,8 @@ class Assets { auto language_state() const { return language_state_; } + auto asset_loads_allowed() const { return asset_loads_allowed_; } + private: static void MarkAssetForLoad(Asset* c); void LoadSystemTexture(SysTextureID id, const char* name); diff --git a/src/ballistica/base/base.cc b/src/ballistica/base/base.cc index c834d38a..b7e4abb3 100644 --- a/src/ballistica/base/base.cc +++ b/src/ballistica/base/base.cc @@ -662,6 +662,10 @@ void BaseFeatureSet::DoPushObjCall(const PythonObjectSetBase* objset, int id, auto BaseFeatureSet::IsAppStarted() const -> bool { return app_started_; } +auto BaseFeatureSet::IsAppBootstrapped() const -> bool { + return logic->app_bootstrapping_complete(); +} + auto BaseFeatureSet::ShutdownSuppressBegin() -> bool { std::scoped_lock lock(shutdown_suppress_lock_); diff --git a/src/ballistica/base/base.h b/src/ballistica/base/base.h index fa413c36..473e5edf 100644 --- a/src/ballistica/base/base.h +++ b/src/ballistica/base/base.h @@ -675,11 +675,18 @@ class BaseFeatureSet : public FeatureSetNativeComponent, /// High level screen-message call usable from any thread. void ScreenMessage(const std::string& s, const Vector3f& color) override; - /// Has StartApp been called (and completely finished its work)? - /// Code that sends calls/messages to other threads or otherwise uses - /// app functionality may want to check this to avoid crashes. + /// Has StartApp been called (and completely finished its work)? Code that + /// sends calls/messages to other threads or otherwise uses app + /// functionality may want to check this to avoid crashes. Note that some + /// app functionality such as loading assets is not available until + /// IsAppBootstrapped returns true. This call is thread safe. auto IsAppStarted() const -> bool override; + /// Has the app bootstrapping phase completed? The bootstrapping phase + /// involves initial screen/graphics setup. Asset loading is not allowed + /// until it is complete. + auto IsAppBootstrapped() const -> bool override; + void PlusDirectSendV1CloudLogs(const std::string& prefix, const std::string& suffix, bool instant, int* result) override; diff --git a/src/ballistica/base/python/base_python.h b/src/ballistica/base/python/base_python.h index fc70c6db..dc31d93f 100644 --- a/src/ballistica/base/python/base_python.h +++ b/src/ballistica/base/python/base_python.h @@ -110,6 +110,7 @@ class BasePython { kDevConsoleStringEditAdapterClass, kGetDevConsoleTabNamesCall, kAppDevConsoleDoRefreshTabCall, + kUnsupportedControllerMessageCall, 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 2f968b12..b7d1f2a9 100644 --- a/src/ballistica/base/python/methods/python_methods_misc.cc +++ b/src/ballistica/base/python/methods/python_methods_misc.cc @@ -33,6 +33,8 @@ static auto PyGetSimpleSound(PyObject* self, PyObject* args, PyObject* keywds) const_cast(kwlist), &name)) { return nullptr; } + BA_PRECONDITION(g_base->InLogicThread()); + BA_PRECONDITION(g_base->assets->asset_loads_allowed()); { Assets::AssetListLock lock; return PythonClassSimpleSound::Create(g_base->assets->GetSound(name)); @@ -1658,6 +1660,27 @@ static PyMethodDef PyDevConsoleRequestRefreshDef = { "(internal)", }; +// -------------------------- asset_loads_allowed ------------------------------ + +static auto PyAssetLoadsAllowed(PyObject* self) -> PyObject* { + BA_PYTHON_TRY; + if (g_base->assets->asset_loads_allowed()) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PyAssetLoadsAllowedDef = { + "asset_loads_allowed", // name + (PyCFunction)PyAssetLoadsAllowed, // method + METH_NOARGS, // flags + + "asset_loads_allowed() -> bool\n" + "\n" + "(internal)", +}; + // ----------------------------------------------------------------------------- auto PythonMethodsMisc::GetMethods() -> std::vector { @@ -1720,6 +1743,7 @@ auto PythonMethodsMisc::GetMethods() -> std::vector { PyDevConsoleTabHeightDef, PyDevConsoleBaseScaleDef, PyDevConsoleRequestRefreshDef, + PyAssetLoadsAllowedDef, }; } diff --git a/src/ballistica/core/support/base_soft.h b/src/ballistica/core/support/base_soft.h index 49fc62c9..31c83d30 100644 --- a/src/ballistica/core/support/base_soft.h +++ b/src/ballistica/core/support/base_soft.h @@ -42,6 +42,7 @@ class BaseSoftInterface { virtual void DoPushObjCall(const PythonObjectSetBase* objset, int id, const std::string& arg) = 0; virtual auto IsAppStarted() const -> bool = 0; + virtual auto IsAppBootstrapped() const -> bool = 0; virtual auto GetReturnValue() const -> int = 0; }; diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 06a5ad67..4d5638db 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 = 21487; +const int kEngineBuildNumber = 21488; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/python/python_ref.cc b/src/ballistica/shared/python/python_ref.cc index e57a9aa4..de883e13 100644 --- a/src/ballistica/shared/python/python_ref.cc +++ b/src/ballistica/shared/python/python_ref.cc @@ -118,6 +118,10 @@ auto PythonRef::FromString(const std::string& val) -> PythonRef { return Stolen(PyUnicode_FromString(val.c_str())); } +auto PythonRef::SingleStringTuple(const std::string& val) -> PythonRef { + return Stolen(Py_BuildValue("(s)", val.c_str())); +} + auto PythonRef::Str() const -> std::string { assert(Python::HaveGIL()); if (!obj_) { diff --git a/src/ballistica/shared/python/python_ref.h b/src/ballistica/shared/python/python_ref.h index bdcf020b..0370dffe 100644 --- a/src/ballistica/shared/python/python_ref.h +++ b/src/ballistica/shared/python/python_ref.h @@ -68,6 +68,7 @@ class PythonRef { /// Shortcut to create a string object. static auto FromString(const std::string& val) -> PythonRef; + static auto SingleStringTuple(const std::string& val) -> PythonRef; /// Assignment from another PythonRef acquires a reference to the object /// referenced by other if there is one. If other has no reference, any diff --git a/src/meta/babasemeta/pyembed/binding_base.py b/src/meta/babasemeta/pyembed/binding_base.py index 848803bd..95e1da12 100644 --- a/src/meta/babasemeta/pyembed/binding_base.py +++ b/src/meta/babasemeta/pyembed/binding_base.py @@ -56,6 +56,7 @@ values = [ _hooks.show_post_purchase_message, # kShowPostPurchaseMessageCall _hooks.string_edit_adapter_can_be_replaced, # kStringEditAdapterCanBeReplacedCall _hooks.get_dev_console_tab_names, # kGetDevConsoleTabNamesCall + _hooks.unsupported_controller_message, # kUnsupportedControllerMessageCall _language.Lstr, # kLStrClass _general.Call, # kCallClass _apputils.garbage_collect_session_end, # kGarbageCollectSessionEndCall From 64032d0b26803730c5f294f870123a07cb094a03 Mon Sep 17 00:00:00 2001 From: Eric Date: Sat, 21 Oct 2023 11:30:01 -0700 Subject: [PATCH 8/9] lang updates and controller polishing --- .efrocachemap | 68 +++++++++---------- CHANGELOG.md | 2 +- src/assets/ba_data/python/baenv.py | 2 +- .../bauiv1lib/settings/gamepadselect.py | 21 +++--- src/ballistica/base/graphics/graphics.cc | 10 +-- src/ballistica/base/graphics/graphics.h | 2 +- .../base/graphics/support/frame_def.h | 4 +- src/ballistica/base/input/input.cc | 31 ++++----- src/ballistica/base/input/input.h | 53 ++++++++------- .../platform/apple/base_platform_apple.cc | 33 ++------- .../base/platform/apple/base_platform_apple.h | 4 -- src/ballistica/scene_v1/node/flag_node.cc | 2 - .../python/class/python_class_input_device.cc | 17 ++++- src/ballistica/shared/ballistica.cc | 2 +- 14 files changed, 120 insertions(+), 131 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 35d2bad2..6554ee30 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": "1a960da2db069ca3926b8ee6b8f82df7", + "build/assets/ba_data/data/langdata.json": "35edefb8290f4fb38c5e3e70395fc449", "build/assets/ba_data/data/languages/arabic.json": "295c559911fa251f401f8cdcad91c226", "build/assets/ba_data/data/languages/belarussian.json": "e151808b6b4f6dc159cf55ee62adad3c", "build/assets/ba_data/data/languages/chinese.json": "b0d4e874ba8d22c8fd0d7a0eaaf96ac9", @@ -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": "550aecdf2530832a8c095c2bda9ea8f0", + "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": "347f38524816691170d266708fe25894", "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": "517e9c79ce8242af82366bbdaaf678a4", + "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", @@ -445,12 +445,12 @@ "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": "e1a1a801851924748ad38fa68216439a", - "build/assets/ba_data/data/languages/portuguese.json": "9fcd6b4da9e5d0dc0e337ab00b5debe2", + "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": "70f79c606ccc5ec7bd6ce0303fdece70", + "build/assets/ba_data/data/languages/russian.json": "561504cca28eb3204ac194950029e565", "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": "e72e394f94b99d3e838c1b81a9d17615", + "build/assets/ba_data/data/languages/spanish.json": "5a4dbd505060dd02d634bd4de4d5faab", "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,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": "f029c0682da29f46e5c9782bd2567f82", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "d2fe151ab5836d1f60b85bdc7d7880b1", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "ca6b96c7c6f77ab6ca93698da0022cb6", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "5342b4e44c8f414b34582ceec0ef0c8d", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "67e06b38ba6e5fa44fcb0b196618dda7", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "5a1a366e4458f48230a8856a04e3d15a", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "c1f9b4a7e4d8aef89de664fd19178b17", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7608557c57d636c81213afe0a68cd921", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "31465c3f4b869d6d2a4a004bcf43c058", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "4092f2c09d4717cbe22a9847733458ea", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "a98776c44ceae70a5582fa3a31894f42", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "107c108da827cc647d26ea8e20e5a02a", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "d4e3d6b79648d478003282e20b583cf3", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "396f882b13a97bec718222d14be7a825", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "118e5039eb06c8d641baa3a94c511a20", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "2c4b12f038ad8eb9838860b8cce2f491", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "650b1181dda309c492abe2a26cedfd9a", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "32ac6359eb0296a319ddfcba3fcd04bc", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "731540517a251db7332d0f841d686d01", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a19df9a09272d486666a4cb28702cf2b", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "8944236c082e32b7efc83fdd1d2bb430", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "7d78e977704b352be09dc49ae159c0ac", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "1c587e1330b55458dfc200f08bf6e6fc", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b9f429f8cbc3961dde9bae4344ec74f5", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "91876ba2b9041ac6b6fbfcdc058342dd", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "8c2dd693f97a910a70e82efdeff1b9d4", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "590edd47cf70f08866b9ced6c46751f1", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "e0ddb169dce06925d6b3fbde8a2cda45", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "8bc979f113254f1329d0219809bca9f1", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "674d3495c9b3483d712673219383888d", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "c219bdcb9d0897650b72708ba3a17e5e", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "c2a9c82807644a4676dae69630ff8237", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "aa12830328b2c64b8d4970197ba5c49f", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "8569f2c15b113f206846152a49dbcd6d", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "49b7f50beed3e8c5abfd7f6faa4d7b90", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "78fbc9b9503b30231b9effd281322829", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c88f1beb143dd3306b556b5490e8b381", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "110bf4b9e5c99d4b354ace22272e902e", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9d62f0c0fed46365b203728079580085", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "c2ccf9cec0af9b12620eb74237647583", "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", @@ -4092,14 +4092,14 @@ "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": "13615b9d10736d72e3b3bec605518645", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "99369ccd4edfe5cc2d54b18aa77ca1cb", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "33a19e9eb9bd9b655cbe70d8e250425b", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "021114e14a72c621dc6fb7d4b3e41b5f", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "cff4a800e4ea1cdb7690d088a4db0abb", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "107e289fb15a0d3177ed16aa8f076041", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4d031e12072278cf78570b64a2f7e533", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "d7e631f313c7b99d92c41efaf6305b65", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "235ff7a30762e89fce4142e4150d46a4", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "e13e823133fcdcf8409ee8978892162b", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "0388a3c7a202c13466d20d2e45d7645e", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "a1fb2d14a0876f5759dc825c10723b17", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "5eb03f1247c6cd2e0bc75a4e459712f6", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "4d49ef90fbde5813d4b9dd22f0f8c55b", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "2782be4d66289e98fa93076e953d4488", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "f3b6ea4d34a50620e26f6d4ef6ddad17", "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 72a3dce1..5e8b2b13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21488, api 8, 2023-10-20) +### 1.7.28 (build 21489, api 8, 2023-10-21) - 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 1b03a2f8..3c8ce180 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 = 21488 +TARGET_BALLISTICA_BUILD = 21489 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py index 9534ec8d..b576d422 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py @@ -29,16 +29,16 @@ def gamepad_configure_callback(event: dict[str, Any]) -> None: logging.exception('Error transitioning out main_menu_window.') bui.getsound('activateBeep').play() bui.getsound('swish').play() - inputdevice = event['input_device'] - assert isinstance(inputdevice, bs.InputDevice) - if inputdevice.allows_configuring: + device = event['input_device'] + assert isinstance(device, bs.InputDevice) + if device.allows_configuring: bui.app.ui_v1.set_main_menu_window( - gamepad.GamepadSettingsWindow(inputdevice).get_root_widget() + gamepad.GamepadSettingsWindow(device).get_root_widget() ) else: width = 700 height = 200 - button_width = 100 + button_width = 80 uiscale = bui.app.ui_v1.uiscale dlg = bui.containerwidget( scale=( @@ -52,8 +52,13 @@ def gamepad_configure_callback(event: dict[str, Any]) -> None: transition='in_right', ) bui.app.ui_v1.set_main_menu_window(dlg) - device_name = inputdevice.name - if device_name == 'iDevice': + + if device.allows_configuring_in_system_settings: + msg = bui.Lstr( + resource='configureDeviceInSystemSettingsText', + subs=[('${DEVICE}', device.name)], + ) + elif device.is_controller_app: msg = bui.Lstr( resource='bsRemoteConfigureInAppText', subs=[('${REMOTE_APP_NAME}', bui.get_remote_app_name())], @@ -61,7 +66,7 @@ def gamepad_configure_callback(event: dict[str, Any]) -> None: else: msg = bui.Lstr( resource='cantConfigureDeviceText', - subs=[('${DEVICE}', device_name)], + subs=[('${DEVICE}', device.name)], ) bui.textwidget( parent=dlg, diff --git a/src/ballistica/base/graphics/graphics.cc b/src/ballistica/base/graphics/graphics.cc index 773e85dd..cc01e49f 100644 --- a/src/ballistica/base/graphics/graphics.cc +++ b/src/ballistica/base/graphics/graphics.cc @@ -1521,10 +1521,10 @@ void Graphics::DoDrawFade(FrameDef* frame_def, float amt) { void Graphics::DrawCursor(FrameDef* frame_def) { assert(g_base->InLogicThread()); - millisecs_t app_time_millisecs = frame_def->app_time_millisecs(); + auto app_time = frame_def->app_time(); - bool can_show_cursor = g_base->app_adapter->ShouldUseCursor(); - bool should_show_cursor = + auto can_show_cursor = g_base->app_adapter->ShouldUseCursor(); + auto should_show_cursor = camera_->manual() || g_base->input->IsCursorVisible(); if (g_base->app_adapter->HasHardwareCursor()) { @@ -1538,9 +1538,9 @@ void Graphics::DrawCursor(FrameDef* frame_def) { // Ship this state when it changes and also every now and then just in // case things go wonky. if (new_cursor_visibility != hardware_cursor_visible_ - || app_time_millisecs - last_cursor_visibility_event_time_ > 2000) { + || app_time - last_cursor_visibility_event_time_ > 2.137) { hardware_cursor_visible_ = new_cursor_visibility; - last_cursor_visibility_event_time_ = app_time_millisecs; + last_cursor_visibility_event_time_ = app_time; g_base->app_adapter->PushMainThreadCall([this] { assert(g_core && g_core->InMainThread()); g_base->app_adapter->SetHardwareCursorVisible(hardware_cursor_visible_); diff --git a/src/ballistica/base/graphics/graphics.h b/src/ballistica/base/graphics/graphics.h index 022e58d8..f04ff79c 100644 --- a/src/ballistica/base/graphics/graphics.h +++ b/src/ballistica/base/graphics/graphics.h @@ -485,7 +485,7 @@ class Graphics { millisecs_t last_progress_bar_draw_time_{}; millisecs_t last_progress_bar_start_time_{}; microsecs_t last_suppress_gyro_time_{}; - millisecs_t last_cursor_visibility_event_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_{}; diff --git a/src/ballistica/base/graphics/support/frame_def.h b/src/ballistica/base/graphics/support/frame_def.h index d839c52e..828095fa 100644 --- a/src/ballistica/base/graphics/support/frame_def.h +++ b/src/ballistica/base/graphics/support/frame_def.h @@ -44,8 +44,8 @@ class FrameDef { return app_time_microsecs_ / 1000; } auto app_time_microsecs() const -> microsecs_t { return app_time_microsecs_; } - auto app_time() const -> double { - return static_cast(app_time_microsecs_) / 1000000.0; + auto app_time() const { + return static_cast(app_time_microsecs_) / 1000000.0; } // A number incremented for each frame renderered. Note that graphics code diff --git a/src/ballistica/base/input/input.cc b/src/ballistica/base/input/input.cc index 551b499c..acefa84b 100644 --- a/src/ballistica/base/input/input.cc +++ b/src/ballistica/base/input/input.cc @@ -1297,7 +1297,7 @@ void Input::HandleSmoothMouseScroll_(const Vector2f& velocity, bool momentum) { WidgetMessage(WidgetMessage::Type::kMouseWheelVelocityH, nullptr, cursor_pos_x_, cursor_pos_y_, velocity.x, momentum)); - last_mouse_move_time_ = g_core->GetAppTimeMillisecs(); + last_mouse_move_time_ = g_core->GetAppTimeSeconds(); mouse_move_count_++; Camera* camera = g_base->graphics->camera(); @@ -1333,7 +1333,7 @@ void Input::HandleMouseMotion_(const Vector2f& position) { cursor_pos_y_ = g_base->graphics->PixelToVirtualY( position.y * g_base->graphics->screen_pixel_height()); - last_mouse_move_time_ = g_core->GetAppTimeMillisecs(); + last_mouse_move_time_ = g_core->GetAppTimeSeconds(); mouse_move_count_++; // If we have a touch-input in editing mode, pass along events to it. @@ -1374,7 +1374,7 @@ void Input::HandleMouseDown_(int button, const Vector2f& position) { return; } - last_mouse_move_time_ = g_core->GetAppTimeMillisecs(); + last_mouse_move_time_ = g_core->GetAppTimeSeconds(); mouse_move_count_++; // Convert normalized view coords to our virtual ones. @@ -1439,8 +1439,8 @@ void Input::HandleMouseUp_(int button, const Vector2f& position) { position.y * g_base->graphics->screen_pixel_height()); // If we have a touch-input in editing mode, pass along events to it. - // (it usually handles its own events but here we want it to play nice - // with stuff under it by blocking touches, etc) + // It usually handles its own events but here we want it to play nice + // with stuff under it by blocking touches, etc. if (touch_input_ && touch_input_->editing()) { touch_input_->HandleTouchUp(reinterpret_cast(1), cursor_pos_x_, cursor_pos_y_); @@ -1481,9 +1481,6 @@ void Input::HandleTouchEvent_(const TouchEvent& e) { MarkInputActive(); - // float x = e.x; - // float y = e.y; - if (g_buildconfig.ostype_ios_tvos()) { printf("FIXME: update touch handling\n"); } @@ -1513,8 +1510,8 @@ void Input::HandleTouchEvent_(const TouchEvent& e) { } } - // We keep track of one 'single' touch which we pass along as - // mouse events which covers most UI stuff. + // We keep track of one 'single' touch which we pass along as mouse events + // which covers most UI stuff. if (e.type == TouchEvent::Type::kDown && single_touch_ == nullptr) { single_touch_ = e.touch; HandleMouseDown_(SDL_BUTTON_LEFT, Vector2f(e.x, e.y)); @@ -1524,8 +1521,8 @@ void Input::HandleTouchEvent_(const TouchEvent& e) { HandleMouseMotion_(Vector2f(e.x, e.y)); } - // Currently just applying touch-cancel the same as touch-up here; - // perhaps should be smarter in the future. + // Currently just applying touch-cancel the same as touch-up here; perhaps + // should be smarter in the future. if ((e.type == TouchEvent::Type::kUp || e.type == TouchEvent::Type::kCanceled) && (e.touch == single_touch_ || e.overall)) { single_touch_ = nullptr; @@ -1579,13 +1576,9 @@ auto Input::IsCursorVisible() const -> bool { } bool val; - // Show our cursor if any dialogs/windows are up or else if its been moved - // very recently. - if (g_base->ui->MainMenuVisible()) { - val = (g_core->GetAppTimeMillisecs() - last_mouse_move_time_ < 5000); - } else { - val = (g_core->GetAppTimeMillisecs() - last_mouse_move_time_ < 1000); - } + // Show our cursor only if its been moved recently. + val = (g_core->GetAppTimeSeconds() - last_mouse_move_time_ < 2.071); + return val; } diff --git a/src/ballistica/base/input/input.h b/src/ballistica/base/input/input.h index b38aea5c..e256a2ff 100644 --- a/src/ballistica/base/input/input.h +++ b/src/ballistica/base/input/input.h @@ -11,6 +11,7 @@ #include "ballistica/base/base.h" #include "ballistica/shared/foundation/object.h" +#include "ballistica/shared/foundation/types.h" namespace ballistica::base { @@ -179,49 +180,49 @@ class Input { void DestroyKeyboardInputDevices_(); void AddFakeMods_(SDL_Keysym* sym); - HandleKeyPressCall* keyboard_input_capture_press_{}; - HandleKeyReleaseCall* keyboard_input_capture_release_{}; - HandleJoystickEventCall* joystick_input_capture_{}; - bool input_active_{}; - millisecs_t input_idle_time_{}; - int local_active_input_device_count_{}; - millisecs_t last_get_local_active_input_device_count_check_time_{}; - std::unordered_map > - reserved_identifiers_; - int max_controller_count_so_far_{}; - std::list newly_connected_controllers_; - std::list newly_disconnected_controllers_; int connect_print_timer_id_{}; int disconnect_print_timer_id_{}; - bool have_button_using_inputs_{}; - bool have_start_activated_default_button_inputs_{}; - bool have_non_touch_inputs_{}; + int max_controller_count_so_far_{}; + int local_active_input_device_count_{}; + int mouse_move_count_{}; + int input_lock_count_temp_{}; + int input_lock_count_permanent_{}; + bool input_active_ : 1 {}; + bool have_button_using_inputs_ : 1 {}; + bool have_start_activated_default_button_inputs_ : 1 {}; + bool have_non_touch_inputs_ : 1 {}; + bool ignore_mfi_controllers_ : 1 {}; + bool ignore_sdl_controllers_ : 1 {}; + millisecs_t input_idle_time_{}; + millisecs_t last_get_local_active_input_device_count_check_time_{}; float cursor_pos_x_{}; float cursor_pos_y_{}; millisecs_t last_click_time_{}; millisecs_t double_click_time_{200}; - millisecs_t last_mouse_move_time_{}; - int mouse_move_count_{}; - std::vector > input_devices_; - KeyboardInput* keyboard_input_{}; - KeyboardInput* keyboard_input_2_{}; - TouchInput* touch_input_{}; - int input_lock_count_temp_{}; - int input_lock_count_permanent_{}; + seconds_t last_mouse_move_time_{}; std::list input_lock_temp_labels_; std::list input_unlock_temp_labels_; 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 > + reserved_identifiers_; + std::vector > input_devices_; std::set keys_held_; millisecs_t last_input_device_count_update_time_{}; millisecs_t last_input_temp_lock_time_{}; - bool ignore_mfi_controllers_{}; - bool ignore_sdl_controllers_{}; - std::list test_inputs_; millisecs_t stress_test_time_{}; millisecs_t stress_test_last_leave_time_{}; void* single_touch_{}; + KeyboardInput* keyboard_input_{}; + KeyboardInput* keyboard_input_2_{}; + TouchInput* touch_input_{}; + HandleKeyPressCall* keyboard_input_capture_press_{}; + HandleKeyReleaseCall* keyboard_input_capture_release_{}; + HandleJoystickEventCall* joystick_input_capture_{}; }; } // namespace ballistica::base diff --git a/src/ballistica/base/platform/apple/base_platform_apple.cc b/src/ballistica/base/platform/apple/base_platform_apple.cc index fc18f79c..55226812 100644 --- a/src/ballistica/base/platform/apple/base_platform_apple.cc +++ b/src/ballistica/base/platform/apple/base_platform_apple.cc @@ -5,9 +5,7 @@ #if BA_XCODE_BUILD #include -#include #endif -#include #if BA_XCODE_BUILD #include "ballistica/base/platform/apple/apple_utils.h" @@ -15,12 +13,7 @@ namespace ballistica::base { -#if BA_OSTYPE_MACOS && BA_XCODE_BUILD && BA_SDL_BUILD -extern void DoSetCursor(bool show); -#endif - -BasePlatformApple::BasePlatformApple() { // NOLINT: trivial constructor false - // positive +BasePlatformApple::BasePlatformApple() { // On iOS, keep the device from falling asleep in our app #if BA_OSTYPE_IOS_TVOS AppleUtils::DisableIdleTimer(); @@ -58,25 +51,13 @@ void BasePlatformApple::DoOpenURL(const std::string& url) { BallisticaKit::CocoaFromCppOpenURL(url); #else BallisticaKit::UIKitFromCppOpenURL(url); -#endif - // Go ahead and do this ourself. Though perhaps the default - // Python path would be fine. - // AppleUtils::OpenURL(url.c_str()); -#else - // Otherwise go with the default (Python webbrowser module). - BasePlatform::DoOpenURL(url); -#endif -} +#endif // BA_OSTYPE_MACOS -// void BasePlatformApple::SetHardwareCursorVisible(bool visible) { -// // Set our nifty custom hardware cursor on mac; -// // otherwise fall back to default. -// #if BA_OSTYPE_MACOS && BA_XCODE_BUILD && !BA_HEADLESS_BUILD && BA_SDL_BUILD -// base::DoSetCursor(visible); -// #else -// return BasePlatform::SetHardwareCursorVisible(visible); -// #endif -// } +#else + // For non-xcode builds, go with the default (Python webbrowser module). + BasePlatform::DoOpenURL(url); +#endif // BA_XCODE_BUILD +} } // namespace ballistica::base diff --git a/src/ballistica/base/platform/apple/base_platform_apple.h b/src/ballistica/base/platform/apple/base_platform_apple.h index 50cf78cc..d0fbaad8 100644 --- a/src/ballistica/base/platform/apple/base_platform_apple.h +++ b/src/ballistica/base/platform/apple/base_platform_apple.h @@ -11,15 +11,11 @@ namespace ballistica::base { class BasePlatformApple : public BasePlatform { public: BasePlatformApple(); - void DoPurchase(const std::string& item) override; void RestorePurchases() override; void PurchaseAck(const std::string& purchase, const std::string& order_id) override; - void DoOpenURL(const std::string& url) override; - - private: }; } // namespace ballistica::base diff --git a/src/ballistica/scene_v1/node/flag_node.cc b/src/ballistica/scene_v1/node/flag_node.cc index d0bae293..05b26746 100644 --- a/src/ballistica/scene_v1/node/flag_node.cc +++ b/src/ballistica/scene_v1/node/flag_node.cc @@ -311,8 +311,6 @@ void FlagNode::Draw(base::FrameDef* frame_def) { c.SetTexture(g_base->assets->SysTexture(base::SysTextureID::kShadow)); c.SetTransparent(true); - FullShadowSet* full_shadows = full_shadow_set_.Get(); - // Update our shadow objects. if (!g_core->HeadlessMode()) { dBodyID b = body_->body(); diff --git a/src/ballistica/scene_v1/python/class/python_class_input_device.cc b/src/ballistica/scene_v1/python/class/python_class_input_device.cc index 77e473bf..515f2c35 100644 --- a/src/ballistica/scene_v1/python/class/python_class_input_device.cc +++ b/src/ballistica/scene_v1/python/class/python_class_input_device.cc @@ -32,7 +32,12 @@ void PythonClassInputDevice::SetupType(PyTypeObject* cls) { "Attributes:\n" "\n" " allows_configuring (bool):\n" - " Whether the input-device can be configured.\n" + " Whether the input-device can be configured in the app.\n" + "\n" + " allows_configuring_in_system_settings (bool):\n" + " Whether the input-device can be configured in the system.\n" + " setings app. This can be used to redirect the user to go there\n" + " if they attempt to configure the device.\n" "\n" " has_meaningful_button_names (bool):\n" " Whether button names returned by this instance match labels\n" @@ -189,6 +194,16 @@ auto PythonClassInputDevice::tp_getattro(PythonClassInputDevice* self, } else { Py_RETURN_FALSE; } + } else if (!strcmp(s, "allows_configuring_in_system_settings")) { + auto* d = self->input_device_delegate_->Get(); + if (!d) { + throw Exception(PyExcType::kInputDeviceNotFound); + } + if (d->input_device().IsMFiController()) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } } else if (!strcmp(s, "has_meaningful_button_names")) { auto* d = self->input_device_delegate_->Get(); if (!d) { diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 4d5638db..6580892d 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 = 21488; +const int kEngineBuildNumber = 21489; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; From a2ff9ab87262811cd9c09acb8d351f0e4bc87dfa Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 22 Oct 2023 11:25:01 -0700 Subject: [PATCH 9/9] langs and polishing --- .efrocachemap | 66 ++++++++++++++--------------- CHANGELOG.md | 8 +++- src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/shared/ballistica.cc | 2 +- tools/efrotools/pcommands.py | 21 +++++++-- tools/pcommand | 1 + 6 files changed, 60 insertions(+), 40 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 6554ee30..b7a571d2 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,10 +421,10 @@ "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": "35edefb8290f4fb38c5e3e70395fc449", + "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/languages/chinese.json": "b0d4e874ba8d22c8fd0d7a0eaaf96ac9", + "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", "build/assets/ba_data/data/languages/czech.json": "93c5fe0d884d95435da6c675f64e30e0", @@ -432,7 +432,7 @@ "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": "347f38524816691170d266708fe25894", + "build/assets/ba_data/data/languages/filipino.json": "2efdfb879135b196a272dd47fc2039a2", "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", @@ -444,7 +444,7 @@ "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": "e1a1a801851924748ad38fa68216439a", + "build/assets/ba_data/data/languages/polish.json": "7a4a6cb882cf90dad32e6607215525bf", "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", @@ -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": "42318070b817663f671d78a9c8f3019c", + "build/assets/ba_data/data/languages/turkish.json": "776d1a0c9ef2333a9110d93558ab19e2", "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,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": "8944236c082e32b7efc83fdd1d2bb430", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "7d78e977704b352be09dc49ae159c0ac", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "1c587e1330b55458dfc200f08bf6e6fc", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b9f429f8cbc3961dde9bae4344ec74f5", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "91876ba2b9041ac6b6fbfcdc058342dd", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "8c2dd693f97a910a70e82efdeff1b9d4", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "590edd47cf70f08866b9ced6c46751f1", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "e0ddb169dce06925d6b3fbde8a2cda45", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "8bc979f113254f1329d0219809bca9f1", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "674d3495c9b3483d712673219383888d", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "c219bdcb9d0897650b72708ba3a17e5e", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "c2a9c82807644a4676dae69630ff8237", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "aa12830328b2c64b8d4970197ba5c49f", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "8569f2c15b113f206846152a49dbcd6d", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "49b7f50beed3e8c5abfd7f6faa4d7b90", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "78fbc9b9503b30231b9effd281322829", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c88f1beb143dd3306b556b5490e8b381", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "110bf4b9e5c99d4b354ace22272e902e", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9d62f0c0fed46365b203728079580085", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "c2ccf9cec0af9b12620eb74237647583", + "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", @@ -4092,14 +4092,14 @@ "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": "235ff7a30762e89fce4142e4150d46a4", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "e13e823133fcdcf8409ee8978892162b", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "0388a3c7a202c13466d20d2e45d7645e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "a1fb2d14a0876f5759dc825c10723b17", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "5eb03f1247c6cd2e0bc75a4e459712f6", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "4d49ef90fbde5813d4b9dd22f0f8c55b", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "2782be4d66289e98fa93076e953d4488", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "f3b6ea4d34a50620e26f6d4ef6ddad17", + "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", "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 5e8b2b13..46e6c34d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.28 (build 21489, api 8, 2023-10-21) +### 1.7.28 (build 21491, api 8, 2023-10-22) - 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 @@ -148,6 +148,12 @@ result in fewer ugly pops and warning messages when the app is quit. - Tidied up some keyboard shortcuts to be more platform-appropriate. For example, toggling fullscreen on Windows is now Alt+Enter or F11. +- Fancy rebuilt Mac build should now automatically sync its frame rate to the + display its running on (using CVDisplayLinks, not VSync). +- Mac build is now relying solely on Apple's Game Controller Framework, which + 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. ### 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 3c8ce180..0d19c817 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 = 21489 +TARGET_BALLISTICA_BUILD = 21491 TARGET_BALLISTICA_VERSION = '1.7.28' diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 6580892d..8a23ce50 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 = 21489; +const int kEngineBuildNumber = 21491; const char* kEngineVersion = "1.7.28"; const int kEngineApiVersion = 8; diff --git a/tools/efrotools/pcommands.py b/tools/efrotools/pcommands.py index 207befb0..52e9440c 100644 --- a/tools/efrotools/pcommands.py +++ b/tools/efrotools/pcommands.py @@ -98,10 +98,8 @@ def xcodebuild() -> None: XCodeBuild(projroot=str(pcommand.PROJROOT), args=sys.argv[2:]).run() -def xcoderun() -> None: - """Run an xcode build in the terminal.""" +def _xcodepath(executable: bool) -> str: import os - import subprocess from efro.error import CleanError from efrotools.xcodebuild import project_build_path @@ -114,12 +112,27 @@ def xcoderun() -> None: project_path = os.path.abspath(sys.argv[2]) scheme = sys.argv[3] configuration = sys.argv[4] - path = project_build_path( + return project_build_path( projroot=str(pcommand.PROJROOT), project_path=project_path, scheme=scheme, configuration=configuration, + executable=executable, ) + + +def xcodeshow() -> None: + """Open folder containing xcode build in the finder.""" + import subprocess + + subprocess.run(['open', _xcodepath(executable=False)], check=True) + + +def xcoderun() -> None: + """Run an xcode build in the terminal.""" + import subprocess + + path = _xcodepath(executable=True) subprocess.run(path, check=True) diff --git a/tools/pcommand b/tools/pcommand index fb5b2e4c..5cd05df5 100755 --- a/tools/pcommand +++ b/tools/pcommand @@ -52,6 +52,7 @@ from efrotools.pcommands import ( try_repeat, xcodebuild, xcoderun, + xcodeshow, tweak_empty_py_files, make_ensure, make_target_debug,