From 91d9142b60ec8e1acff0d2cb5c0783a3f6b89c67 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 9 Sep 2022 23:13:32 -0700 Subject: [PATCH] renamed App to AppFlavor and AppGlobals to App --- .efrocachemap | 88 ++-- CHANGELOG.md | 2 +- .../ba_data/python/._bainternal_sources_hash | 2 +- assets/src/ba_data/python/ba/_bootstrap.py | 2 +- ballisticacore-cmake/CMakeLists.txt | 12 +- .../Generic/BallisticaCoreGeneric.vcxproj | 12 +- .../BallisticaCoreGeneric.vcxproj.filters | 20 +- .../Headless/BallisticaCoreHeadless.vcxproj | 12 +- .../BallisticaCoreHeadless.vcxproj.filters | 20 +- src/ballistica/app/app.cc | 391 +---------------- src/ballistica/app/app.h | 188 +++------ src/ballistica/app/app_flavor.cc | 395 ++++++++++++++++++ src/ballistica/app/app_flavor.h | 147 +++++++ ...headless_app.cc => app_flavor_headless.cc} | 8 +- src/ballistica/app/app_flavor_headless.h | 20 + .../app/{vr_app.cc => app_flavor_vr.cc} | 26 +- .../app/{vr_app.h => app_flavor_vr.h} | 23 +- src/ballistica/app/app_globals.cc | 18 - src/ballistica/app/app_globals.h | 94 ----- src/ballistica/app/headless_app.h | 20 - src/ballistica/audio/audio_server.cc | 2 +- src/ballistica/ballistica.cc | 79 ++-- src/ballistica/ballistica.h | 4 +- src/ballistica/core/fatal_error.cc | 6 +- src/ballistica/core/logging.cc | 28 +- src/ballistica/core/object.cc | 24 +- src/ballistica/core/thread.cc | 45 +- src/ballistica/core/thread.h | 4 +- src/ballistica/core/types.h | 6 +- src/ballistica/game/account.cc | 13 +- src/ballistica/game/game.cc | 60 ++- src/ballistica/game/game_stream.cc | 18 +- src/ballistica/game/player_spec.cc | 4 +- src/ballistica/game/session/client_session.cc | 9 +- .../game/session/net_client_session.cc | 17 +- src/ballistica/game/session/session.cc | 6 +- src/ballistica/generic/utils.cc | 20 +- src/ballistica/graphics/graphics.cc | 8 +- src/ballistica/graphics/graphics_server.cc | 8 +- src/ballistica/graphics/renderer.cc | 6 +- src/ballistica/graphics/vr_graphics.cc | 2 +- src/ballistica/input/device/input_device.cc | 4 +- src/ballistica/input/device/joystick.cc | 9 +- src/ballistica/input/device/touch_input.cc | 6 +- src/ballistica/input/input.cc | 11 +- src/ballistica/input/remote_app.cc | 4 +- src/ballistica/input/std_input_module.cc | 6 +- src/ballistica/networking/networking.cc | 2 +- src/ballistica/networking/telnet_server.cc | 10 +- src/ballistica/platform/platform.cc | 59 ++- src/ballistica/platform/platform.h | 2 +- src/ballistica/platform/sdl/sdl_app.cc | 18 +- src/ballistica/platform/sdl/sdl_app.h | 13 +- .../python/methods/python_methods_app.cc | 7 +- .../python/methods/python_methods_gameplay.cc | 4 +- .../python/methods/python_methods_input.cc | 8 +- .../methods/python_methods_networking.cc | 8 +- .../python/methods/python_methods_system.cc | 49 +-- .../python/methods/python_methods_ui.cc | 10 +- src/ballistica/python/python.cc | 5 +- src/ballistica/scene/scene.cc | 40 +- src/ballistica/ui/console.cc | 8 +- src/ballistica/ui/ui.cc | 2 +- src/ballistica/ui/widget/text_widget.cc | 4 +- 64 files changed, 1075 insertions(+), 1083 deletions(-) create mode 100644 src/ballistica/app/app_flavor.cc create mode 100644 src/ballistica/app/app_flavor.h rename src/ballistica/app/{headless_app.cc => app_flavor_headless.cc} (70%) create mode 100644 src/ballistica/app/app_flavor_headless.h rename src/ballistica/app/{vr_app.cc => app_flavor_vr.cc} (78%) rename src/ballistica/app/{vr_app.h => app_flavor_vr.h} (64%) delete mode 100644 src/ballistica/app/app_globals.cc delete mode 100644 src/ballistica/app/app_globals.h delete mode 100644 src/ballistica/app/headless_app.h diff --git a/.efrocachemap b/.efrocachemap index b2429eb8..15bf8e53 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -3995,50 +3995,50 @@ "assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e", "assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34", "ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a", - "build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/9c/ed/0ae26a2512696e003eb3f7dd1ee5", - "build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/6b/8f/cc9774b5a4a4feaae3006ea0db82", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/17/70/eb50b7cc07116befdc0ad36960fc", - "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/44/48/3ecb935394935983e25e667d3819", - "build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/82/10/7f94dfa5fd5fa3473394fce58977", - "build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/83/8e/68be1304b09685223a6e88202960", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4b/3f/3708b5d1839611d77a54e962059e", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/03/ce/4d5816d91764f05c90214427913b", - "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/43/8b/2666b8e3fbd8d34544092ca45bf4", - "build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ab/2d/3673b348cbc00eb761fa5f23ffa2", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/89/29/ead51be015acb0b5803b07ed6f1e", - "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1d/8d/72f67643af92c32c82364827a430", - "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/54/02/1c83ca2ed283f71e2d73d59b684b", - "build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ea/1c/6a518c25ea6d4222dd65d44252a0", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/51/60/f77a0cd12b6c27a13126764a790c", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/69/59/6a345958e24e295547264baacf17", - "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/19/0c/d44240c9cf46cccae04e65a7f434", - "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/9c/7e/1ed6f76e5cdf290810e762d8cf43", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/19/4f/914677c28d694003cad9091f751f", - "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/ec/3f/c38f346059fcd19ef049ce3a253a", - "build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8f/63/9dc4b8c56eaf6ee5259e4b60bc46", - "build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e3/25/692a46a2437c11055c58d95f0a10", - "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/06/8f/1f7fcebee0a16c8f843cabebba1c", - "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ec/c2/51a05d1066c208b3a17e8828238e", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a8/e3/88791ad2fbd654a60e6652e64554", - "build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6b/06/86d995f8ea1b6e27ac3b9818e267", - "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f3/7d/b632f966f8ae8c39dc9015fb8eee", - "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e9/9e/39dd389564d0a14f01bdb54b82ce", - "build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/cb/7e/e865aa9e850350deefa7a826b89e", - "build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/9d/1f/20ea75eb2a38a5aa740aebf68893", - "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/35/87/49cc3fb53218a2c19633551d0f38", - "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ac/38/4fc5345b0bbc0cc6965d510b2074", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b3/b0/c4f8ff30c9b62d2d0dbc926095fa", - "build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ec/96/b22889b59ba3279627d8de232a23", - "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0e/6b/3b6758dd4b6b63ab9f666af9396a", - "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/65/8c/6fa15f798f6ca73d753571f8cd4b", - "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/2d/af/9cc4b56883bcd72f65b9a814c401", - "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/5a/18/c0ff4809d4550c794a516a320ed1", - "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/27/25/4b3bd86f0ad71b2ad29ea8a9837d", - "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/2f/1a/29105b0e71173826d2ea404982b6", - "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/b7/8a/3f0476b3981a630cc6ef8f1ec364", - "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/4d/32/9ffcdc35d17ac6c9e3bb2bfd0e3c", - "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/be/f0/8901dcd613fec9e58d02b08dce4b", - "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/e3/c1/f79676f11b4f4778e26933ba42d7", + "build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ad/15/3b9d4eb830dd3f65266b90544461", + "build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/3f/94/ce703438b67755c530ca90d7147e", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/57/49/aef9dbd58c9638d2f57c61fa9dee", + "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/53/73/7aee5551f9aa8c60bfa36ce86889", + "build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/8d/cd/61b3022a6a3620bb9a0d288a3a07", + "build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/67/d3/7e7b3147c119bcf9edc62f271755", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/41/81/b4225f4df31a6bb482eee912d1e7", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8a/3e/9a284ee8d8cb75fef73f31c95a8f", + "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/a5/a2/69829de7375f981ac01464d1271c", + "build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/8f/de/c40022e95c0d51e3ea7d68713ac8", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2a/e3/74cdea89e9606f525ae01f5fb860", + "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c2/b3/8f5c7076b293ce6a961b23321ebe", + "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/45/4b/43950780d121290a40cb444e86c4", + "build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/74/6c/5c8a7cab586c813a07d5180e25c2", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ca/36/94c0d402ec38ffdd74cd165f51c3", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b7/a9/14ea5150ad61a43b5780975551ac", + "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/23/72/2bdc1106cdf2aa163a591e7c47b8", + "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/1e/d9/5a7fd190b86683bef223c1cdb0b6", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/2e/f1/27b90831c9a25d2b9d06a266e931", + "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/17/ce/d3e33370c016fc8110e6dddd120f", + "build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/32/b0/df61f7b69d796fbdf2aa0d11974b", + "build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/42/31/a45e87e70e5d5232956586620f35", + "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/94/5e/6ac9534c08e600201b04d28a6069", + "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/5f/5d/52e74182f459f5b7b55ae07b36c6", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7b/9d/367338622b31482a8ef87621f5aa", + "build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a8/18/4dff9ab6b2529d258a2ee5607d0c", + "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/79/b9/e5e9d0f92f82f6cf35abf0c049cf", + "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4c/b4/2c65b84265e0b2d576317ca86e77", + "build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d1/86/635b942e0837be18e6d9d859f2c4", + "build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b0/f5/3da5acc926ca5e6c02307b8a16a6", + "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a3/51/d624ac150603304183ba23d369a2", + "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e2/51/5eb2216e4cdc531c500244316f1d", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b1/2b/c72179ed1d11ae7e11f429b90ae9", + "build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/52/78/cca5ff0fcc837467cd23239537c7", + "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e7/6e/eb7102dd939e85172d729ba471b8", + "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e7/92/b7c90b5dbf614aa056cf467f73e0", + "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/cf/d9/52c1c145efa1a24ebf54dd71f691", + "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/31/15/ef849aeaf5a9cc2169e6ec4998c8", + "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/86/a7/def29184cd6e947469726ae382e1", + "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/5f/30/42705d0b580994d1345c34651170", + "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/2f/b1/6a6e8cf45fc5afa4085bf90a526f", + "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/7e/fb/e7eaee33c6196f9204a2997fc65c", + "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/5a/39/e00cddb91e8eca83b117235c1332", + "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/07/dd/6e331996e6e6907f05a21abc20a6", "src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/7d/3e/229a581cb2454ed856f1d8b564a7", "src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/98/12/571b2160d69d42580e8f31fa6a8d" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 728f06e7..70701bdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.7 (build 20796, api 7, 2022-09-09) +### 1.7.7 (build 20798, api 7, 2022-09-09) - Added `ba.app.meta.load_exported_classes()` for loading classes discovered by the meta subsystem cleanly in a background thread. - Improved logging of missing playlist game types. - Some ba.Lstr functionality can now be used in background threads. diff --git a/assets/src/ba_data/python/._bainternal_sources_hash b/assets/src/ba_data/python/._bainternal_sources_hash index 26863289..4f6f8751 100644 --- a/assets/src/ba_data/python/._bainternal_sources_hash +++ b/assets/src/ba_data/python/._bainternal_sources_hash @@ -1 +1 @@ -265405600297036989512577170988205019181 \ No newline at end of file +64954916459680243860176377055051806996 \ No newline at end of file diff --git a/assets/src/ba_data/python/ba/_bootstrap.py b/assets/src/ba_data/python/ba/_bootstrap.py index 870e9a6d..490f64f5 100644 --- a/assets/src/ba_data/python/ba/_bootstrap.py +++ b/assets/src/ba_data/python/ba/_bootstrap.py @@ -38,7 +38,7 @@ def bootstrap() -> None: # Give a soft warning if we're being used with a different binary # version than we expect. - expected_build = 20796 + expected_build = 20798 running_build: int = env['build_number'] if running_build != expected_build: print( diff --git a/ballisticacore-cmake/CMakeLists.txt b/ballisticacore-cmake/CMakeLists.txt index 010064e4..0f58aa0a 100644 --- a/ballisticacore-cmake/CMakeLists.txt +++ b/ballisticacore-cmake/CMakeLists.txt @@ -202,14 +202,14 @@ add_executable(ballisticacore ${BA_SRC_ROOT}/ballistica/app/app.h ${BA_SRC_ROOT}/ballistica/app/app_config.cc ${BA_SRC_ROOT}/ballistica/app/app_config.h - ${BA_SRC_ROOT}/ballistica/app/app_globals.cc - ${BA_SRC_ROOT}/ballistica/app/app_globals.h - ${BA_SRC_ROOT}/ballistica/app/headless_app.cc - ${BA_SRC_ROOT}/ballistica/app/headless_app.h + ${BA_SRC_ROOT}/ballistica/app/app_flavor.cc + ${BA_SRC_ROOT}/ballistica/app/app_flavor.h + ${BA_SRC_ROOT}/ballistica/app/app_flavor_headless.cc + ${BA_SRC_ROOT}/ballistica/app/app_flavor_headless.h + ${BA_SRC_ROOT}/ballistica/app/app_flavor_vr.cc + ${BA_SRC_ROOT}/ballistica/app/app_flavor_vr.h ${BA_SRC_ROOT}/ballistica/app/stress_test.cc ${BA_SRC_ROOT}/ballistica/app/stress_test.h - ${BA_SRC_ROOT}/ballistica/app/vr_app.cc - ${BA_SRC_ROOT}/ballistica/app/vr_app.h ${BA_SRC_ROOT}/ballistica/audio/al_sys.cc ${BA_SRC_ROOT}/ballistica/audio/al_sys.h ${BA_SRC_ROOT}/ballistica/audio/audio.cc diff --git a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj index e262bb74..06cae3fd 100644 --- a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj +++ b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj @@ -193,14 +193,14 @@ - - - - + + + + + + - - diff --git a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters index 72b42275..0db00d48 100644 --- a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters +++ b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters @@ -13,16 +13,22 @@ ballistica\app - + ballistica\app - + ballistica\app - + ballistica\app - + + ballistica\app + + + ballistica\app + + ballistica\app @@ -31,12 +37,6 @@ ballistica\app - - ballistica\app - - - ballistica\app - ballistica\audio diff --git a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj index e1c85303..ccbacee1 100644 --- a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj +++ b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj @@ -188,14 +188,14 @@ - - - - + + + + + + - - diff --git a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters index 72b42275..0db00d48 100644 --- a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters +++ b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters @@ -13,16 +13,22 @@ ballistica\app - + ballistica\app - + ballistica\app - + ballistica\app - + + ballistica\app + + + ballistica\app + + ballistica\app @@ -31,12 +37,6 @@ ballistica\app - - ballistica\app - - - ballistica\app - ballistica\audio diff --git a/src/ballistica/app/app.cc b/src/ballistica/app/app.cc index 7c2843e1..55ef7da0 100644 --- a/src/ballistica/app/app.cc +++ b/src/ballistica/app/app.cc @@ -2,394 +2,17 @@ #include "ballistica/app/app.h" -#include "ballistica/app/stress_test.h" -#include "ballistica/core/thread.h" -#include "ballistica/game/game.h" -#include "ballistica/graphics/graphics_server.h" -#include "ballistica/graphics/renderer.h" -#include "ballistica/input/device/touch_input.h" -#include "ballistica/input/input.h" -#include "ballistica/networking/network_reader.h" -#include "ballistica/networking/networking.h" -#include "ballistica/networking/telnet_server.h" -#include "ballistica/python/python.h" +#include namespace ballistica { -App::App(Thread* thread) - : thread_(thread), stress_test_(std::make_unique()) { - assert(g_app == nullptr); - g_app = this; - - // So anyone who needs to use the 'main' thread id can get at it... - Thread::UpdateMainThreadID(); - - // We modify some app behavior when run under the server manager. - auto* envval = getenv("BA_SERVER_WRAPPER_MANAGED"); - server_wrapper_managed_ = (envval && strcmp(envval, "1") == 0); -} - -void App::PostInit() { - // If we've got a nice themed hardware cursor, show it. - // Otherwise, hide the hardware cursor; we'll draw it in software. - // (need to run this in postinit because SDL/etc. may not be inited yet - // as of App::App()). - g_platform->SetHardwareCursorVisible(g_buildconfig.hardware_cursor()); -} - -auto App::ManagesEventLoop() const -> bool { - // We have 2 redundant values for essentially the same thing; - // should get rid of IsEventPushMode() once we've created - // App subclasses for our various platforms. - return !g_platform->IsEventPushMode(); -} - -void App::RunRenderUpkeepCycle() { - // This should only be used in cases where the OS is handling the event loop. - assert(!ManagesEventLoop()); - if (ManagesEventLoop()) { - return; +App::App(int argc_in, char** argv_in) + : argc{argc_in}, argv{argv_in}, main_thread_id{std::this_thread::get_id()} { + // Enable extra timing logs via env var. + const char* debug_timing_env = getenv("BA_DEBUG_TIMING"); + if (debug_timing_env != nullptr && !strcmp(debug_timing_env, "1")) { + debug_timing = true; } - - // Pump thread messages (we're being driven by frame-draw callbacks - // so this is the only place that it gets done at). - thread()->RunEventLoop(true); // Single pass only. - - // Now do the general app event cycle for whoever needs to process things. - RunEvents(); -} - -void App::RebuildLostGLContext() { - assert(InMainThread()); - assert(g_graphics_server); - if (g_graphics_server) { - g_graphics_server->RebuildLostContext(); - } -} - -void App::DrawFrame(bool during_resize) { - assert(InMainThread()); - - // It's possible to receive frames before we're ready to draw. - if (!g_graphics_server || !g_graphics_server->renderer()) { - return; - } - - millisecs_t starttime = GetRealTime(); - - // A resize-draw event means that we're drawing due to a window resize. - // In this case we ignore regular draw events for a short while - // afterwards which makes resizing smoother. - // FIXME: should figure out the *correct* way to handle this; - // I believe the underlying cause here is some sort of context contention - // across threads. - if (during_resize) { - last_resize_draw_event_time_ = starttime; - } else { - if (starttime - last_resize_draw_event_time_ < (1000 / 30)) { - return; - } - } - g_graphics_server->TryRender(); - RunRenderUpkeepCycle(); -} - -void App::SetScreenResolution(float width, float height) { - assert(InMainThread()); - if (!HeadlessMode()) { - g_graphics_server->VideoResize(width, height); - } -} - -void App::PushShutdownCompleteCall() { - thread()->PushCall([this] { ShutdownComplete(); }); -} - -void App::ShutdownComplete() { - assert(InMainThread()); - assert(g_platform); - - done_ = true; - - // Kill our own event loop (or tell the OS to kill its). - if (ManagesEventLoop()) { - thread()->Quit(); - } else { - g_platform->QuitApp(); - } -} - -void App::RunEvents() { - // there's probably a better place for this... - stress_test_->Update(); - - // Give platforms a chance to pump/handle their own events. - // FIXME: now that we have app class overrides, platform should really - // not be doing event handling. (need to fix rift build). - g_platform->RunEvents(); -} - -void App::UpdatePauseResume() { - if (actually_paused_) { - // Unpause if no one wants pause. - if (!sys_paused_app_) { - OnResume(); - actually_paused_ = false; - } - } else { - // Pause if anyone wants. - if (sys_paused_app_) { - OnPause(); - actually_paused_ = true; - } - } -} - -void App::OnPause() { - assert(InMainThread()); - - // Avoid reading gyro values for a short time to avoid hitches when restored. - g_graphics->SetGyroEnabled(false); - - // IMPORTANT: Any on-pause related stuff that threads need to do must - // be done from registered pause-callbacks. If we instead push runnables - // to them from here they may or may not be called before the thread - // is actually paused. - - Thread::SetThreadsPaused(true); - - assert(g_networking); - g_networking->Pause(); - - assert(g_network_reader); - if (g_network_reader) { - g_network_reader->Pause(); - } - - if (g_app_globals->telnet_server) { - g_app_globals->telnet_server->Pause(); - } - - g_platform->OnAppPause(); -} - -void App::OnResume() { - assert(InMainThread()); - last_app_resume_time_ = GetRealTime(); - Thread::SetThreadsPaused(false); - - g_platform->OnAppResume(); - g_networking->Resume(); - g_network_reader->Resume(); - - if (g_app_globals->telnet_server) { - g_app_globals->telnet_server->Resume(); - } - - // Also let the Python layer do what it needs to - // (starting/stopping music, etc.). - g_python->PushObjCall(Python::ObjID::kHandleAppResumeCall); - g_game->PushOnAppResumeCall(); - - g_graphics->SetGyroEnabled(true); - - // When resuming from a paused state, we may want to - // pause whatever game was running when we last were active. - // TODO(efro): we should make this smarter so it doesn't happen if - // we're in a network game or something that we can't pause; - // bringing up the menu doesn't really accomplish anything there. - if (g_app_globals->should_pause) { - g_app_globals->should_pause = false; - - // If we've been completely backgrounded, - // send a menu-press command to the game; this will - // bring up a pause menu if we're in the game/etc. - g_game->PushMainMenuPressCall(nullptr); - } -} - -auto App::GetProductPrice(const std::string& product) -> std::string { - std::scoped_lock lock(product_prices_mutex_); - auto i = product_prices_.find(product); - if (i == product_prices_.end()) { - return ""; - } else { - return i->second; - } -} - -void App::SetProductPrice(const std::string& product, - const std::string& price) { - std::scoped_lock lock(product_prices_mutex_); - product_prices_[product] = price; -} - -void App::PauseApp() { - assert(InMainThread()); - Platform::DebugLog("PauseApp@" - + std::to_string(Platform::GetCurrentMilliseconds())); - assert(!sys_paused_app_); - sys_paused_app_ = true; - UpdatePauseResume(); -} - -void App::ResumeApp() { - assert(InMainThread()); - Platform::DebugLog("ResumeApp@" - + std::to_string(Platform::GetCurrentMilliseconds())); - assert(sys_paused_app_); - sys_paused_app_ = false; - UpdatePauseResume(); -} - -void App::DidFinishRenderingFrame(FrameDef* frame) {} - -void App::PrimeEventPump() { - assert(!ManagesEventLoop()); - - // Pump events manually until a screen gets created. - // At that point we use frame-draws to drive our event loop. - while (!g_graphics_server->initial_screen_created()) { - g_main_thread->RunEventLoop(true); - Platform::SleepMS(1); - } -} - -#pragma mark Push-Calls - -void App::PushShowOnlineScoreUICall(const std::string& show, - const std::string& game, - const std::string& game_version) { - thread()->PushCall([show, game, game_version] { - assert(InMainThread()); - g_platform->ShowOnlineScoreUI(show, game, game_version); - }); -} - -void App::PushNetworkSetupCall(int port, int telnet_port, bool enable_telnet, - const std::string& telnet_password) { - thread()->PushCall([port, telnet_port, enable_telnet, telnet_password] { - assert(InMainThread()); - // Kick these off if they don't exist. - // (do we want to support changing ports on existing ones?) - if (g_network_reader == nullptr) { - new NetworkReader(port); - } - if (g_app_globals->telnet_server == nullptr && enable_telnet) { - new TelnetServer(telnet_port); - assert(g_app_globals->telnet_server); - if (telnet_password.empty()) { - g_app_globals->telnet_server->SetPassword(nullptr); - } else { - g_app_globals->telnet_server->SetPassword(telnet_password.c_str()); - } - } - }); -} - -void App::PushPurchaseAckCall(const std::string& purchase, - const std::string& order_id) { - thread()->PushCall( - [purchase, order_id] { g_platform->PurchaseAck(purchase, order_id); }); -} - -void App::PushGetScoresToBeatCall(const std::string& level, - const std::string& config, - void* py_callback) { - thread()->PushCall([level, config, py_callback] { - assert(InMainThread()); - g_platform->GetScoresToBeat(level, config, py_callback); - }); -} - -void App::PushPurchaseCall(const std::string& item) { - thread()->PushCall([item] { - assert(InMainThread()); - g_platform->Purchase(item); - }); -} - -void App::PushRestorePurchasesCall() { - thread()->PushCall([] { - assert(InMainThread()); - g_platform->RestorePurchases(); - }); -} - -void App::PushOpenURLCall(const std::string& url) { - thread()->PushCall([url] { g_platform->OpenURL(url); }); -} - -void App::PushGetFriendScoresCall(const std::string& game, - const std::string& game_version, void* data) { - thread()->PushCall([game, game_version, data] { - g_platform->GetFriendScores(game, game_version, data); - }); -} - -void App::PushSubmitScoreCall(const std::string& game, - const std::string& game_version, int64_t score) { - thread()->PushCall([game, game_version, score] { - g_platform->SubmitScore(game, game_version, score); - }); -} - -void App::PushAchievementReportCall(const std::string& achievement) { - thread()->PushCall( - [achievement] { g_platform->ReportAchievement(achievement); }); -} - -void App::PushStringEditCall(const std::string& name, const std::string& value, - int max_chars) { - thread()->PushCall([name, value, max_chars] { - static millisecs_t last_edit_time = 0; - millisecs_t t = GetRealTime(); - - // Ignore if too close together. - // (in case second request comes in before first takes effect). - if (t - last_edit_time < 1000) { - return; - } - last_edit_time = t; - assert(InMainThread()); - g_platform->EditText(name, value, max_chars); - }); -} - -void App::PushSetStressTestingCall(bool enable, int player_count) { - thread()->PushCall([this, enable, player_count] { - stress_test_->SetStressTesting(enable, player_count); - }); -} - -void App::PushResetAchievementsCall() { - thread()->PushCall([] { g_platform->ResetAchievements(); }); -} - -void App::OnBootstrapComplete() { - assert(InMainThread()); - assert(g_input); - - if (!HeadlessMode()) { - // On desktop systems we just assume keyboard input exists and add it - // immediately. - if (g_platform->IsRunningOnDesktop()) { - g_input->PushCreateKeyboardInputDevices(); - } - - // On non-tv, non-desktop, non-vr systems, create a touchscreen input. - if (!g_platform->IsRunningOnTV() && !IsVRMode() - && !g_platform->IsRunningOnDesktop()) { - g_input->CreateTouchInput(); - } - } -} - -void App::PushCursorUpdate(bool vis) { - thread()->PushCall([vis] { - assert(InMainThread()); - g_platform->SetHardwareCursorVisible(vis); - }); } } // namespace ballistica diff --git a/src/ballistica/app/app.h b/src/ballistica/app/app.h index 2f6052af..c3d3546c 100644 --- a/src/ballistica/app/app.h +++ b/src/ballistica/app/app.h @@ -3,144 +3,90 @@ #ifndef BALLISTICA_APP_APP_H_ #define BALLISTICA_APP_APP_H_ -#include #include #include +#include #include +#include -#include "ballistica/app/stress_test.h" #include "ballistica/ballistica.h" namespace ballistica { -/// Our high level app interface module. -/// It runs in the main thread and is what platform wrappers -/// should primarily interact with. +// The first thing the engine does is allocate an instance of this as g_globals. +// As much as possible, previously static/global values should be moved to here, +// ideally as a temporary measure until they can be placed as non-static members +// in the proper classes. +// Any use of non-trivial global/static values such as class instances should be +// avoided since it can introduce ambiguities during init and teardown. +// For more explanation, see the 'Static and Global Variables' section in the +// Google C++ Style Guide. class App { public: - explicit App(Thread* thread); + App(int argc, char** argv); - /// This gets run after the constructor completes. - /// Any setup that may trigger a virtual method/etc. should go here. - auto PostInit() -> void; + /// Program argument count (on applicable platforms). + int argc{}; - /// Return whether this class runs its own event loop. - /// If true, BallisticaMain() will continuously ask the app for events - /// until the app is quit, at which point BallisticaMain() returns. - /// If false, BallisticaMain returns immediately and it is assumed - /// that the OS handles the app lifecycle and pushes events to the app - /// via callbacks/etc. - auto ManagesEventLoop() const -> bool; + /// Program argument values (on applicable platforms). + char** argv{}; - /// Called for non-event-loop apps to give them an opportunity to - /// ensure they are self-sustaining. For instance, an app relying on - /// frame-draws for its main thread event processing may need to - /// manually pump events until frame rendering begins. - virtual auto PrimeEventPump() -> void; + bool threads_paused{}; + std::unordered_map node_types; + std::unordered_map node_types_by_id; + std::unordered_map node_message_types; + std::vector node_message_formats; + bool workspaces_in_use{}; + bool replay_open{}; + std::vector pausable_threads; + TouchInput* touch_input{}; + std::string console_startup_messages; + std::mutex log_mutex; + std::string log; + bool put_log{}; + bool log_full{}; + int master_server_source{0}; + int session_count{}; + bool shutting_down{}; + bool have_incentivized_ad{true}; + bool should_pause{}; + TelnetServer* telnet_server{}; + Console* console{}; + bool reset_vr_orientation{}; + bool user_ran_commands{}; + V1AccountType account_type{V1AccountType::kInvalid}; + bool remote_server_accepting_connections{true}; + std::string exec_command; + std::string user_agent_string{"BA_USER_AGENT_UNSET (" BA_PLATFORM_STRING ")"}; + int return_value{}; + bool debug_timing{}; + std::thread::id main_thread_id{}; + bool is_bootstrapped{}; + bool args_handled{}; + std::string user_config_dir; + bool started_suicide{}; - /// Handle any pending OS events. - /// On normal graphical builds this is triggered by RunRenderUpkeepCycle(); - /// timer intervals for headless builds, etc. - /// Should process any pending OS events, etc. - virtual auto RunEvents() -> void; + // Maximum time in milliseconds to buffer game input/output before sending + // it over the network. + int buffer_time{0}; - // These should be called by the window, view-controller, sdl, - // or whatever is driving the app. They must be called from the main thread. + // How often we send dynamics resync messages. + int dynamics_sync_time{500}; - /// Should be called on mobile when the app is backgrounded. - /// Pauses threads, closes network sockets, etc. - auto PauseApp() -> void; + // How many steps we sample for each bucket. + int delay_bucket_samples{60}; - auto paused() const -> bool { return actually_paused_; } - - /// Should be called on mobile when the app is foregrounded. - /// Spins threads back up, re-opens network sockets, etc. - auto ResumeApp() -> void; - - /// The last time the app was resumed (uses GetRealTime() value). - auto last_app_resume_time() const -> millisecs_t { - return last_app_resume_time_; - } - - /// Should be called when the window/screen resolution changes. - auto SetScreenResolution(float width, float height) -> void; - - /// Should be called if the platform detects the GL context was lost. - auto RebuildLostGLContext() -> void; - - /// Attempt to draw a frame. - auto DrawFrame(bool during_resize = false) -> void; - - /// Used on platforms where our main thread event processing is driven by - /// frame-draw commands given to us. This should be called after drawing - /// a frame in order to bring game state up to date and process OS events. - auto RunRenderUpkeepCycle() -> void; - - /// Called by the graphics-server when drawing completes for a frame. - virtual auto DidFinishRenderingFrame(FrameDef* frame) -> void; - - /// Return the price of an IAP product as a human-readable string, - /// or an empty string if not found. - /// FIXME: move this to platform. - auto GetProductPrice(const std::string& product) -> std::string; - auto SetProductPrice(const std::string& product, const std::string& price) - -> void; - - auto done() const -> bool { return done_; } - - /// Whether we're running under ballisticacore_server.py - /// (affects some app behavior). - auto server_wrapper_managed() const -> bool { - return server_wrapper_managed_; - } - - virtual auto OnBootstrapComplete() -> void; - - // Deferred calls that can be made from other threads. - - auto PushCursorUpdate(bool vis) -> void; - auto PushShowOnlineScoreUICall(const std::string& show, - const std::string& game, - const std::string& game_version) -> void; - auto PushGetFriendScoresCall(const std::string& game, - const std::string& game_version, void* data) - -> void; - auto PushSubmitScoreCall(const std::string& game, - const std::string& game_version, int64_t score) - -> void; - auto PushAchievementReportCall(const std::string& achievement) -> void; - auto PushGetScoresToBeatCall(const std::string& level, - const std::string& config, void* py_callback) - -> void; - auto PushOpenURLCall(const std::string& url) -> void; - auto PushStringEditCall(const std::string& name, const std::string& value, - int max_chars) -> void; - auto PushSetStressTestingCall(bool enable, int player_count) -> void; - auto PushPurchaseCall(const std::string& item) -> void; - auto PushRestorePurchasesCall() -> void; - auto PushResetAchievementsCall() -> void; - auto PushPurchaseAckCall(const std::string& purchase, - const std::string& order_id) -> void; - auto PushNetworkSetupCall(int port, int telnet_port, bool enable_telnet, - const std::string& telnet_password) -> void; - auto PushShutdownCompleteCall() -> void; - auto thread() const -> Thread* { return thread_; } - - private: - auto UpdatePauseResume() -> void; - auto OnPause() -> void; - auto OnResume() -> void; - auto ShutdownComplete() -> void; - Thread* thread_{}; - bool done_{}; - bool server_wrapper_managed_{}; - bool sys_paused_app_{}; - bool actually_paused_{}; - std::unique_ptr stress_test_; - millisecs_t last_resize_draw_event_time_{}; - millisecs_t last_app_resume_time_{}; - std::unordered_map product_prices_; - std::mutex product_prices_mutex_; + bool vr_mode{g_buildconfig.vr_build()}; + millisecs_t real_time{}; + millisecs_t last_real_time_ticks{}; + std::mutex real_time_mutex; + std::mutex thread_name_map_mutex; + std::unordered_map thread_name_map; +#if BA_DEBUG_BUILD + std::mutex object_list_mutex; + Object* object_list_first{}; + int object_count{0}; +#endif }; } // namespace ballistica diff --git a/src/ballistica/app/app_flavor.cc b/src/ballistica/app/app_flavor.cc new file mode 100644 index 00000000..37d59fc7 --- /dev/null +++ b/src/ballistica/app/app_flavor.cc @@ -0,0 +1,395 @@ +// Released under the MIT License. See LICENSE for details. + +#include "ballistica/app/app_flavor.h" + +#include "ballistica/app/stress_test.h" +#include "ballistica/core/thread.h" +#include "ballistica/game/game.h" +#include "ballistica/graphics/graphics_server.h" +#include "ballistica/graphics/renderer.h" +#include "ballistica/input/device/touch_input.h" +#include "ballistica/input/input.h" +#include "ballistica/networking/network_reader.h" +#include "ballistica/networking/networking.h" +#include "ballistica/networking/telnet_server.h" +#include "ballistica/python/python.h" + +namespace ballistica { + +AppFlavor::AppFlavor(Thread* thread) + : thread_(thread), stress_test_(std::make_unique()) { + // assert(g_app_flavor == nullptr); + // g_app_flavor = this; + + // We modify some app behavior when run under the server manager. + auto* envval = getenv("BA_SERVER_WRAPPER_MANAGED"); + server_wrapper_managed_ = (envval && strcmp(envval, "1") == 0); +} + +void AppFlavor::PostInit() { + // If we've got a nice themed hardware cursor, show it. + // Otherwise, hide the hardware cursor; we'll draw it in software. + // (need to run this in postinit because SDL/etc. may not be inited yet + // as of AppFlavor::AppFlavor()). + g_platform->SetHardwareCursorVisible(g_buildconfig.hardware_cursor()); +} + +auto AppFlavor::ManagesEventLoop() const -> bool { + // We have 2 redundant values for essentially the same thing; + // should get rid of IsEventPushMode() once we've created + // AppFlavor subclasses for our various platforms. + return !g_platform->IsEventPushMode(); +} + +void AppFlavor::RunRenderUpkeepCycle() { + // This should only be used in cases where the OS is handling the event loop. + assert(!ManagesEventLoop()); + if (ManagesEventLoop()) { + return; + } + + // Pump thread messages (we're being driven by frame-draw callbacks + // so this is the only place that it gets done at). + thread()->RunEventLoop(true); // Single pass only. + + // Now do the general app event cycle for whoever needs to process things. + RunEvents(); +} + +void AppFlavor::RebuildLostGLContext() { + assert(InMainThread()); + assert(g_graphics_server); + if (g_graphics_server) { + g_graphics_server->RebuildLostContext(); + } +} + +void AppFlavor::DrawFrame(bool during_resize) { + assert(InMainThread()); + + // It's possible to receive frames before we're ready to draw. + if (!g_graphics_server || !g_graphics_server->renderer()) { + return; + } + + millisecs_t starttime = GetRealTime(); + + // A resize-draw event means that we're drawing due to a window resize. + // In this case we ignore regular draw events for a short while + // afterwards which makes resizing smoother. + // FIXME: should figure out the *correct* way to handle this; + // I believe the underlying cause here is some sort of context contention + // across threads. + if (during_resize) { + last_resize_draw_event_time_ = starttime; + } else { + if (starttime - last_resize_draw_event_time_ < (1000 / 30)) { + return; + } + } + g_graphics_server->TryRender(); + RunRenderUpkeepCycle(); +} + +void AppFlavor::SetScreenResolution(float width, float height) { + assert(InMainThread()); + if (!HeadlessMode()) { + g_graphics_server->VideoResize(width, height); + } +} + +void AppFlavor::PushShutdownCompleteCall() { + thread()->PushCall([this] { ShutdownComplete(); }); +} + +void AppFlavor::ShutdownComplete() { + assert(InMainThread()); + assert(g_platform); + + done_ = true; + + // Kill our own event loop (or tell the OS to kill its). + if (ManagesEventLoop()) { + thread()->Quit(); + } else { + g_platform->QuitApp(); + } +} + +void AppFlavor::RunEvents() { + // there's probably a better place for this... + stress_test_->Update(); + + // Give platforms a chance to pump/handle their own events. + // FIXME: now that we have app class overrides, platform should really + // not be doing event handling. (need to fix rift build). + g_platform->RunEvents(); +} + +void AppFlavor::UpdatePauseResume() { + if (actually_paused_) { + // Unpause if no one wants pause. + if (!sys_paused_app_) { + OnResume(); + actually_paused_ = false; + } + } else { + // Pause if anyone wants. + if (sys_paused_app_) { + OnPause(); + actually_paused_ = true; + } + } +} + +void AppFlavor::OnPause() { + assert(InMainThread()); + + // Avoid reading gyro values for a short time to avoid hitches when restored. + g_graphics->SetGyroEnabled(false); + + // IMPORTANT: Any on-pause related stuff that threads need to do must + // be done from registered pause-callbacks. If we instead push runnables + // to them from here they may or may not be called before the thread + // is actually paused. + + Thread::SetThreadsPaused(true); + + assert(g_networking); + g_networking->Pause(); + + assert(g_network_reader); + if (g_network_reader) { + g_network_reader->Pause(); + } + + if (g_app->telnet_server) { + g_app->telnet_server->Pause(); + } + + g_platform->OnAppPause(); +} + +void AppFlavor::OnResume() { + assert(InMainThread()); + last_app_resume_time_ = GetRealTime(); + Thread::SetThreadsPaused(false); + + g_platform->OnAppResume(); + g_networking->Resume(); + g_network_reader->Resume(); + + if (g_app->telnet_server) { + g_app->telnet_server->Resume(); + } + + // Also let the Python layer do what it needs to + // (starting/stopping music, etc.). + g_python->PushObjCall(Python::ObjID::kHandleAppResumeCall); + g_game->PushOnAppResumeCall(); + + g_graphics->SetGyroEnabled(true); + + // When resuming from a paused state, we may want to + // pause whatever game was running when we last were active. + // TODO(efro): we should make this smarter so it doesn't happen if + // we're in a network game or something that we can't pause; + // bringing up the menu doesn't really accomplish anything there. + if (g_app->should_pause) { + g_app->should_pause = false; + + // If we've been completely backgrounded, + // send a menu-press command to the game; this will + // bring up a pause menu if we're in the game/etc. + g_game->PushMainMenuPressCall(nullptr); + } +} + +auto AppFlavor::GetProductPrice(const std::string& product) -> std::string { + std::scoped_lock lock(product_prices_mutex_); + auto i = product_prices_.find(product); + if (i == product_prices_.end()) { + return ""; + } else { + return i->second; + } +} + +void AppFlavor::SetProductPrice(const std::string& product, + const std::string& price) { + std::scoped_lock lock(product_prices_mutex_); + product_prices_[product] = price; +} + +void AppFlavor::PauseApp() { + assert(InMainThread()); + Platform::DebugLog("PauseApp@" + + std::to_string(Platform::GetCurrentMilliseconds())); + assert(!sys_paused_app_); + sys_paused_app_ = true; + UpdatePauseResume(); +} + +void AppFlavor::ResumeApp() { + assert(InMainThread()); + Platform::DebugLog("ResumeApp@" + + std::to_string(Platform::GetCurrentMilliseconds())); + assert(sys_paused_app_); + sys_paused_app_ = false; + UpdatePauseResume(); +} + +void AppFlavor::DidFinishRenderingFrame(FrameDef* frame) {} + +void AppFlavor::PrimeEventPump() { + assert(!ManagesEventLoop()); + + // Pump events manually until a screen gets created. + // At that point we use frame-draws to drive our event loop. + while (!g_graphics_server->initial_screen_created()) { + thread()->RunEventLoop(true); + Platform::SleepMS(1); + } +} + +#pragma mark Push-Calls + +void AppFlavor::PushShowOnlineScoreUICall(const std::string& show, + const std::string& game, + const std::string& game_version) { + thread()->PushCall([show, game, game_version] { + assert(InMainThread()); + g_platform->ShowOnlineScoreUI(show, game, game_version); + }); +} + +void AppFlavor::PushNetworkSetupCall(int port, int telnet_port, + bool enable_telnet, + const std::string& telnet_password) { + thread()->PushCall([port, telnet_port, enable_telnet, telnet_password] { + assert(InMainThread()); + // Kick these off if they don't exist. + // (do we want to support changing ports on existing ones?) + if (g_network_reader == nullptr) { + new NetworkReader(port); + } + if (g_app->telnet_server == nullptr && enable_telnet) { + new TelnetServer(telnet_port); + assert(g_app->telnet_server); + if (telnet_password.empty()) { + g_app->telnet_server->SetPassword(nullptr); + } else { + g_app->telnet_server->SetPassword(telnet_password.c_str()); + } + } + }); +} + +void AppFlavor::PushPurchaseAckCall(const std::string& purchase, + const std::string& order_id) { + thread()->PushCall( + [purchase, order_id] { g_platform->PurchaseAck(purchase, order_id); }); +} + +void AppFlavor::PushGetScoresToBeatCall(const std::string& level, + const std::string& config, + void* py_callback) { + thread()->PushCall([level, config, py_callback] { + assert(InMainThread()); + g_platform->GetScoresToBeat(level, config, py_callback); + }); +} + +void AppFlavor::PushPurchaseCall(const std::string& item) { + thread()->PushCall([item] { + assert(InMainThread()); + g_platform->Purchase(item); + }); +} + +void AppFlavor::PushRestorePurchasesCall() { + thread()->PushCall([] { + assert(InMainThread()); + g_platform->RestorePurchases(); + }); +} + +void AppFlavor::PushOpenURLCall(const std::string& url) { + thread()->PushCall([url] { g_platform->OpenURL(url); }); +} + +void AppFlavor::PushGetFriendScoresCall(const std::string& game, + const std::string& game_version, + void* data) { + thread()->PushCall([game, game_version, data] { + g_platform->GetFriendScores(game, game_version, data); + }); +} + +void AppFlavor::PushSubmitScoreCall(const std::string& game, + const std::string& game_version, + int64_t score) { + thread()->PushCall([game, game_version, score] { + g_platform->SubmitScore(game, game_version, score); + }); +} + +void AppFlavor::PushAchievementReportCall(const std::string& achievement) { + thread()->PushCall( + [achievement] { g_platform->ReportAchievement(achievement); }); +} + +void AppFlavor::PushStringEditCall(const std::string& name, + const std::string& value, int max_chars) { + thread()->PushCall([name, value, max_chars] { + static millisecs_t last_edit_time = 0; + millisecs_t t = GetRealTime(); + + // Ignore if too close together. + // (in case second request comes in before first takes effect). + if (t - last_edit_time < 1000) { + return; + } + last_edit_time = t; + assert(InMainThread()); + g_platform->EditText(name, value, max_chars); + }); +} + +void AppFlavor::PushSetStressTestingCall(bool enable, int player_count) { + thread()->PushCall([this, enable, player_count] { + stress_test_->SetStressTesting(enable, player_count); + }); +} + +void AppFlavor::PushResetAchievementsCall() { + thread()->PushCall([] { g_platform->ResetAchievements(); }); +} + +void AppFlavor::OnBootstrapComplete() { + assert(InMainThread()); + assert(g_input); + + if (!HeadlessMode()) { + // On desktop systems we just assume keyboard input exists and add it + // immediately. + if (g_platform->IsRunningOnDesktop()) { + g_input->PushCreateKeyboardInputDevices(); + } + + // On non-tv, non-desktop, non-vr systems, create a touchscreen input. + if (!g_platform->IsRunningOnTV() && !IsVRMode() + && !g_platform->IsRunningOnDesktop()) { + g_input->CreateTouchInput(); + } + } +} + +void AppFlavor::PushCursorUpdate(bool vis) { + thread()->PushCall([vis] { + assert(InMainThread()); + g_platform->SetHardwareCursorVisible(vis); + }); +} + +} // namespace ballistica diff --git a/src/ballistica/app/app_flavor.h b/src/ballistica/app/app_flavor.h new file mode 100644 index 00000000..14688fb4 --- /dev/null +++ b/src/ballistica/app/app_flavor.h @@ -0,0 +1,147 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_APP_APP_FLAVOR_H_ +#define BALLISTICA_APP_APP_FLAVOR_H_ + +#include +#include +#include +#include + +#include "ballistica/app/stress_test.h" +#include "ballistica/ballistica.h" + +namespace ballistica { + +/// Defines our high level app behavior. +class AppFlavor { + public: + explicit AppFlavor(Thread* thread); + + /// Should be run after the instance is created and assigned. + /// Any setup that may trigger virtual methods or lookups via global + /// should go here. + auto PostInit() -> void; + + /// Return whether this class runs its own event loop. + /// If true, BallisticaMain() will continuously ask the app for events + /// until the app is quit, at which point BallisticaMain() returns. + /// If false, BallisticaMain returns immediately and it is assumed + /// that the OS handles the app lifecycle and pushes events to the app + /// via callbacks/etc. + auto ManagesEventLoop() const -> bool; + + /// Called for non-event-loop apps to give them an opportunity to + /// ensure they are self-sustaining. For instance, an app relying on + /// frame-draws for its main thread event processing may need to + /// manually pump events until frame rendering begins. + virtual auto PrimeEventPump() -> void; + + /// Handle any pending OS events. + /// On normal graphical builds this is triggered by RunRenderUpkeepCycle(); + /// timer intervals for headless builds, etc. + /// Should process any pending OS events, etc. + virtual auto RunEvents() -> void; + + // These should be called by the window, view-controller, sdl, + // or whatever is driving the app. They must be called from the main thread. + + /// Should be called on mobile when the app is backgrounded. + /// Pauses threads, closes network sockets, etc. + auto PauseApp() -> void; + + auto paused() const -> bool { return actually_paused_; } + + /// Should be called on mobile when the app is foregrounded. + /// Spins threads back up, re-opens network sockets, etc. + auto ResumeApp() -> void; + + /// The last time the app was resumed (uses GetRealTime() value). + auto last_app_resume_time() const -> millisecs_t { + return last_app_resume_time_; + } + + /// Should be called when the window/screen resolution changes. + auto SetScreenResolution(float width, float height) -> void; + + /// Should be called if the platform detects the GL context was lost. + auto RebuildLostGLContext() -> void; + + /// Attempt to draw a frame. + auto DrawFrame(bool during_resize = false) -> void; + + /// Used on platforms where our main thread event processing is driven by + /// frame-draw commands given to us. This should be called after drawing + /// a frame in order to bring game state up to date and process OS events. + auto RunRenderUpkeepCycle() -> void; + + /// Called by the graphics-server when drawing completes for a frame. + virtual auto DidFinishRenderingFrame(FrameDef* frame) -> void; + + /// Return the price of an IAP product as a human-readable string, + /// or an empty string if not found. + /// FIXME: move this to platform. + auto GetProductPrice(const std::string& product) -> std::string; + auto SetProductPrice(const std::string& product, const std::string& price) + -> void; + + auto done() const -> bool { return done_; } + + /// Whether we're running under ballisticacore_server.py + /// (affects some app behavior). + auto server_wrapper_managed() const -> bool { + return server_wrapper_managed_; + } + + virtual auto OnBootstrapComplete() -> void; + + // Deferred calls that can be made from other threads. + + auto PushCursorUpdate(bool vis) -> void; + auto PushShowOnlineScoreUICall(const std::string& show, + const std::string& game, + const std::string& game_version) -> void; + auto PushGetFriendScoresCall(const std::string& game, + const std::string& game_version, void* data) + -> void; + auto PushSubmitScoreCall(const std::string& game, + const std::string& game_version, int64_t score) + -> void; + auto PushAchievementReportCall(const std::string& achievement) -> void; + auto PushGetScoresToBeatCall(const std::string& level, + const std::string& config, void* py_callback) + -> void; + auto PushOpenURLCall(const std::string& url) -> void; + auto PushStringEditCall(const std::string& name, const std::string& value, + int max_chars) -> void; + auto PushSetStressTestingCall(bool enable, int player_count) -> void; + auto PushPurchaseCall(const std::string& item) -> void; + auto PushRestorePurchasesCall() -> void; + auto PushResetAchievementsCall() -> void; + auto PushPurchaseAckCall(const std::string& purchase, + const std::string& order_id) -> void; + auto PushNetworkSetupCall(int port, int telnet_port, bool enable_telnet, + const std::string& telnet_password) -> void; + auto PushShutdownCompleteCall() -> void; + auto thread() const -> Thread* { return thread_; } + + private: + auto UpdatePauseResume() -> void; + auto OnPause() -> void; + auto OnResume() -> void; + auto ShutdownComplete() -> void; + Thread* thread_{}; + bool done_{}; + bool server_wrapper_managed_{}; + bool sys_paused_app_{}; + bool actually_paused_{}; + std::unique_ptr stress_test_; + millisecs_t last_resize_draw_event_time_{}; + millisecs_t last_app_resume_time_{}; + std::unordered_map product_prices_; + std::mutex product_prices_mutex_; +}; + +} // namespace ballistica + +#endif // BALLISTICA_APP_APP_FLAVOR_H_ diff --git a/src/ballistica/app/headless_app.cc b/src/ballistica/app/app_flavor_headless.cc similarity index 70% rename from src/ballistica/app/headless_app.cc rename to src/ballistica/app/app_flavor_headless.cc index 4da24f9e..2e83bc05 100644 --- a/src/ballistica/app/headless_app.cc +++ b/src/ballistica/app/app_flavor_headless.cc @@ -1,7 +1,7 @@ // Released under the MIT License. See LICENSE for details. #if BA_HEADLESS_BUILD -#include "ballistica/app/headless_app.h" +#include "ballistica/app/app_flavor_headless.h" #include "ballistica/ballistica.h" @@ -9,13 +9,13 @@ namespace ballistica { // We could technically use the vanilla App class here since we're not // changing anything. -HeadlessApp::HeadlessApp(Thread* thread) : App(thread) { +AppFlavorHeadless::AppFlavorHeadless(Thread* thread) : AppFlavor(thread) { // Handle a few misc things like stress-test updates. // (SDL builds set up a similar timer so we need to also). // This can probably go away at some point. this->thread()->NewTimer(10, true, NewLambdaRunnable([this] { - assert(g_app); - g_app->RunEvents(); + assert(g_app_flavor); + g_app_flavor->RunEvents(); })); } diff --git a/src/ballistica/app/app_flavor_headless.h b/src/ballistica/app/app_flavor_headless.h new file mode 100644 index 00000000..2dead6c3 --- /dev/null +++ b/src/ballistica/app/app_flavor_headless.h @@ -0,0 +1,20 @@ +// Released under the MIT License. See LICENSE for details. + +#ifndef BALLISTICA_APP_APP_FLAVOR_HEADLESS_H_ +#define BALLISTICA_APP_APP_FLAVOR_HEADLESS_H_ +#if BA_HEADLESS_BUILD + +#include "ballistica/app/app_flavor.h" +#include "ballistica/core/thread.h" + +namespace ballistica { + +class AppFlavorHeadless : public AppFlavor { + public: + explicit AppFlavorHeadless(Thread* thread); +}; + +} // namespace ballistica + +#endif // BA_HEADLESS_BUILD +#endif // BALLISTICA_APP_APP_FLAVOR_HEADLESS_H_ diff --git a/src/ballistica/app/vr_app.cc b/src/ballistica/app/app_flavor_vr.cc similarity index 78% rename from src/ballistica/app/vr_app.cc rename to src/ballistica/app/app_flavor_vr.cc index 2fa3569f..129d8b51 100644 --- a/src/ballistica/app/vr_app.cc +++ b/src/ballistica/app/app_flavor_vr.cc @@ -1,7 +1,7 @@ // Released under the MIT License. See LICENSE for details. #if BA_VR_BUILD -#include "ballistica/app/vr_app.h" +#include "ballistica/app/app_flavor_vr.h" #include "ballistica/core/thread.h" #include "ballistica/game/game.h" @@ -10,9 +10,9 @@ namespace ballistica { -VRApp::VRApp(Thread* thread) : App(thread) {} +AppFlavorVR::AppFlavorVR(Thread* thread) : AppFlavor(thread) {} -auto VRApp::PushVRSimpleRemoteStateCall(const VRSimpleRemoteState& state) +auto AppFlavorVR::PushVRSimpleRemoteStateCall(const VRSimpleRemoteState& state) -> void { thread()->PushCall([this, state] { // Convert this to a full hands state, adding in some simple elbow @@ -36,11 +36,11 @@ auto VRApp::PushVRSimpleRemoteStateCall(const VRSimpleRemoteState& state) }); } -auto VRApp::VRSetDrawDimensions(int w, int h) -> void { +auto AppFlavorVR::VRSetDrawDimensions(int w, int h) -> void { g_graphics_server->VideoResize(w, h); } -void VRApp::VRPreDraw() { +void AppFlavorVR::VRPreDraw() { if (!g_graphics_server || !g_graphics_server->renderer()) { return; } @@ -57,7 +57,7 @@ void VRApp::VRPreDraw() { } } -auto VRApp::VRPostDraw() -> void { +auto AppFlavorVR::VRPostDraw() -> void { assert(InMainThread()); if (!g_graphics_server || !g_graphics_server->renderer()) { return; @@ -69,15 +69,15 @@ auto VRApp::VRPostDraw() -> void { RunRenderUpkeepCycle(); } -auto VRApp::VRSetHead(float tx, float ty, float tz, float yaw, float pitch, - float roll) -> void { +auto AppFlavorVR::VRSetHead(float tx, float ty, float tz, float yaw, + float pitch, float roll) -> void { assert(InMainThread()); Renderer* renderer = g_graphics_server->renderer(); if (renderer == nullptr) return; renderer->VRSetHead(tx, ty, tz, yaw, pitch, roll); } -auto VRApp::VRSetHands(const VRHandsState& state) -> void { +auto AppFlavorVR::VRSetHands(const VRHandsState& state) -> void { assert(InMainThread()); // Pass this along to the renderer (in this same thread) for drawing @@ -90,10 +90,10 @@ auto VRApp::VRSetHands(const VRHandsState& state) -> void { g_game->PushVRHandsState(state); } -auto VRApp::VRDrawEye(int eye, float yaw, float pitch, float roll, float tan_l, - float tan_r, float tan_b, float tan_t, float eye_x, - float eye_y, float eye_z, int viewport_x, int viewport_y) - -> void { +auto AppFlavorVR::VRDrawEye(int eye, float yaw, float pitch, float roll, + float tan_l, float tan_r, float tan_b, float tan_t, + float eye_x, float eye_y, float eye_z, + int viewport_x, int viewport_y) -> void { if (!g_graphics_server || !g_graphics_server->renderer()) { return; } diff --git a/src/ballistica/app/vr_app.h b/src/ballistica/app/app_flavor_vr.h similarity index 64% rename from src/ballistica/app/vr_app.h rename to src/ballistica/app/app_flavor_vr.h index 2b1a7111..e0620275 100644 --- a/src/ballistica/app/vr_app.h +++ b/src/ballistica/app/app_flavor_vr.h @@ -1,15 +1,15 @@ // Released under the MIT License. See LICENSE for details. -#ifndef BALLISTICA_APP_VR_APP_H_ -#define BALLISTICA_APP_VR_APP_H_ +#ifndef BALLISTICA_APP_APP_FLAVOR_VR_H_ +#define BALLISTICA_APP_APP_FLAVOR_VR_H_ #if BA_VR_BUILD -#include "ballistica/app/app.h" +#include "ballistica/app/app_flavor.h" namespace ballistica { -class VRApp : public App { +class AppFlavorVR : public AppFlavor { public: /// For passing in state of Daydream remote (and maybe gear vr?..). struct VRSimpleRemoteState { @@ -19,14 +19,15 @@ class VRApp : public App { float r2 = 0.0f; }; - /// Return g_app as a VRApp. (assumes it actually is one). - static auto get() -> VRApp* { - assert(g_app != nullptr); - assert(dynamic_cast(g_app) == static_cast(g_app)); - return static_cast(g_app); + /// Return g_app_flavor as a AppFlavorVR. (assumes it actually is one). + static auto get() -> AppFlavorVR* { + assert(g_app_flavor != nullptr); + assert(dynamic_cast(g_app_flavor) + == static_cast(g_app_flavor)); + return static_cast(g_app_flavor); } - explicit VRApp(Thread* thread); + explicit AppFlavorVR(Thread* thread); auto PushVRSimpleRemoteStateCall(const VRSimpleRemoteState& state) -> void; auto VRSetDrawDimensions(int w, int h) -> void; auto VRPreDraw() -> void; @@ -46,4 +47,4 @@ class VRApp : public App { } // namespace ballistica #endif // BA_VR_BUILD -#endif // BALLISTICA_APP_VR_APP_H_ +#endif // BALLISTICA_APP_APP_FLAVOR_VR_H_ diff --git a/src/ballistica/app/app_globals.cc b/src/ballistica/app/app_globals.cc deleted file mode 100644 index 96d019b7..00000000 --- a/src/ballistica/app/app_globals.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Released under the MIT License. See LICENSE for details. - -#include "ballistica/app/app_globals.h" - -#include - -namespace ballistica { - -AppGlobals::AppGlobals(int argc_in, char** argv_in) - : argc{argc_in}, argv{argv_in}, main_thread_id{std::this_thread::get_id()} { - // Enable extra timing logs via env var. - const char* debug_timing_env = getenv("BA_DEBUG_TIMING"); - if (debug_timing_env != nullptr && !strcmp(debug_timing_env, "1")) { - debug_timing = true; - } -} - -} // namespace ballistica diff --git a/src/ballistica/app/app_globals.h b/src/ballistica/app/app_globals.h deleted file mode 100644 index e65d510a..00000000 --- a/src/ballistica/app/app_globals.h +++ /dev/null @@ -1,94 +0,0 @@ -// Released under the MIT License. See LICENSE for details. - -#ifndef BALLISTICA_APP_APP_GLOBALS_H_ -#define BALLISTICA_APP_APP_GLOBALS_H_ - -#include -#include -#include -#include -#include - -#include "ballistica/ballistica.h" - -namespace ballistica { - -// The first thing the engine does is allocate an instance of this as g_globals. -// As much as possible, previously static/global values should be moved to here, -// ideally as a temporary measure until they can be placed as non-static members -// in the proper classes. -// Any use of non-trivial global/static values such as class instances should be -// avoided since it can introduce ambiguities during init and teardown. -// For more explanation, see the 'Static and Global Variables' section in the -// Google C++ Style Guide. -class AppGlobals { - public: - AppGlobals(int argc, char** argv); - - /// Program argument count (on applicable platforms). - int argc{}; - - /// Program argument values (on applicable platforms). - char** argv{}; - - bool threads_paused{}; - std::unordered_map node_types; - std::unordered_map node_types_by_id; - std::unordered_map node_message_types; - std::vector node_message_formats; - bool workspaces_in_use{}; - bool replay_open{}; - std::vector pausable_threads; - TouchInput* touch_input{}; - std::string console_startup_messages; - std::mutex log_mutex; - std::string log; - bool put_log{}; - bool log_full{}; - int master_server_source{0}; - int session_count{}; - bool shutting_down{}; - bool have_incentivized_ad{true}; - bool should_pause{}; - TelnetServer* telnet_server{}; - Console* console{}; - bool reset_vr_orientation{}; - bool user_ran_commands{}; - V1AccountType account_type{V1AccountType::kInvalid}; - bool remote_server_accepting_connections{true}; - std::string exec_command; - std::string user_agent_string{"BA_USER_AGENT_UNSET (" BA_PLATFORM_STRING ")"}; - int return_value{}; - bool debug_timing{}; - std::thread::id main_thread_id{}; - bool is_bootstrapped{}; - bool args_handled{}; - std::string user_config_dir; - bool started_suicide{}; - - // Maximum time in milliseconds to buffer game input/output before sending - // it over the network. - int buffer_time{0}; - - // How often we send dynamics resync messages. - int dynamics_sync_time{500}; - - // How many steps we sample for each bucket. - int delay_bucket_samples{60}; - - bool vr_mode{g_buildconfig.vr_build()}; - millisecs_t real_time{}; - millisecs_t last_real_time_ticks{}; - std::mutex real_time_mutex; - std::mutex thread_name_map_mutex; - std::unordered_map thread_name_map; -#if BA_DEBUG_BUILD - std::mutex object_list_mutex; - Object* object_list_first{}; - int object_count{0}; -#endif -}; - -} // namespace ballistica - -#endif // BALLISTICA_APP_APP_GLOBALS_H_ diff --git a/src/ballistica/app/headless_app.h b/src/ballistica/app/headless_app.h deleted file mode 100644 index 660b7213..00000000 --- a/src/ballistica/app/headless_app.h +++ /dev/null @@ -1,20 +0,0 @@ -// Released under the MIT License. See LICENSE for details. - -#ifndef BALLISTICA_APP_HEADLESS_APP_H_ -#define BALLISTICA_APP_HEADLESS_APP_H_ -#if BA_HEADLESS_BUILD - -#include "ballistica/app/app.h" -#include "ballistica/core/thread.h" - -namespace ballistica { - -class HeadlessApp : public App { - public: - explicit HeadlessApp(Thread* thread); -}; - -} // namespace ballistica - -#endif // BA_HEADLESS_BUILD -#endif // BALLISTICA_APP_HEADLESS_APP_H_ diff --git a/src/ballistica/audio/audio_server.cc b/src/ballistica/audio/audio_server.cc index 598bbc2e..5e3f4727 100644 --- a/src/ballistica/audio/audio_server.cc +++ b/src/ballistica/audio/audio_server.cc @@ -2,7 +2,7 @@ #include "ballistica/audio/audio_server.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/audio/al_sys.h" #include "ballistica/audio/audio.h" #include "ballistica/audio/audio_source.h" diff --git a/src/ballistica/ballistica.cc b/src/ballistica/ballistica.cc index adad6424..9e8a4227 100644 --- a/src/ballistica/ballistica.cc +++ b/src/ballistica/ballistica.cc @@ -4,7 +4,7 @@ #include -#include "ballistica/app/app.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/audio/audio_server.h" #include "ballistica/core/fatal_error.h" #include "ballistica/core/logging.h" @@ -22,19 +22,19 @@ namespace ballistica { // These are set automatically via script; don't modify them here. -const int kAppBuildNumber = 20796; +const int kAppBuildNumber = 20798; const char* kAppVersion = "1.7.7"; // Our standalone globals. // These are separated out for easy access. -// Everything else should go into AppGlobals (or more ideally into a class). +// Everything else should go into App (or more ideally into a class). int g_early_log_writes{10}; Account* g_account{}; AppConfig* g_app_config{}; -AppGlobals* g_app_globals{}; -AppInternal* g_app_internal{}; App* g_app{}; +AppInternal* g_app_internal{}; +AppFlavor* g_app_flavor{}; Audio* g_audio{}; AudioServer* g_audio_server{}; BGDynamics* g_bg_dynamics{}; @@ -86,28 +86,36 @@ auto BallisticaMain(int argc, char** argv) -> int { // Phase 1: Create and provision all globals. // ------------------------------------------------------------------------- - g_app_globals = new AppGlobals(argc, argv); - g_app_internal = GetAppInternal(); + // Absolute bare-bones basics. + g_app = new App(argc, argv); g_platform = Platform::Create(); + + // If we're not running under a Python executable, we need to set up + // our own Python environment. + assert(g_python == nullptr); + g_python = new Python(); + + // Create a Thread wrapper around the current (main) thread. + g_main_thread = new Thread(ThreadIdentifier::kMain, ThreadType::kMain); + Thread::UpdateMainThreadID(); + + // Spin up our specific app variation (VR, headless, regular, etc.) + g_app_flavor = g_platform->CreateAppFlavor(); + g_app_flavor->PostInit(); + g_account = new Account(); g_utils = new Utils(); Scene::Init(); - // Create a Thread wrapper around the current (main) thread. - g_main_thread = new Thread(ThreadIdentifier::kMain, ThreadType::kMain); - - // Spin up g_app. - g_platform->CreateApp(); - // Spin up our other standard threads. - auto* media_thread = new Thread(ThreadIdentifier::kMedia); - g_app_globals->pausable_threads.push_back(media_thread); - auto* audio_thread = new Thread(ThreadIdentifier::kAudio); - g_app_globals->pausable_threads.push_back(audio_thread); - auto* logic_thread = new Thread(ThreadIdentifier::kLogic); - g_app_globals->pausable_threads.push_back(logic_thread); - auto* network_write_thread = new Thread(ThreadIdentifier::kNetworkWrite); - g_app_globals->pausable_threads.push_back(network_write_thread); + auto* media_thread{new Thread(ThreadIdentifier::kMedia)}; + g_app->pausable_threads.push_back(media_thread); + auto* audio_thread{new Thread(ThreadIdentifier::kAudio)}; + g_app->pausable_threads.push_back(audio_thread); + auto* logic_thread{new Thread(ThreadIdentifier::kLogic)}; + g_app->pausable_threads.push_back(logic_thread); + auto* network_write_thread{new Thread(ThreadIdentifier::kNetworkWrite)}; + g_app->pausable_threads.push_back(network_write_thread); // Spin up our subsystems in those threads. logic_thread->PushCallSynchronous( @@ -127,7 +135,7 @@ auto BallisticaMain(int argc, char** argv) -> int { g_platform->CreateAuxiliaryModules(); // Ok at this point we can be considered up-and-running. - g_app_globals->is_bootstrapped = true; + g_app->is_bootstrapped = true; // ------------------------------------------------------------------------- // Phase 2: Set things in motion. @@ -135,7 +143,7 @@ auto BallisticaMain(int argc, char** argv) -> int { // Let the app and platform do whatever else it wants here such as adding // initial input devices/etc. - g_app->OnBootstrapComplete(); + g_app_flavor->OnBootstrapComplete(); g_platform->OnBootstrapComplete(); // Ok; now that we're bootstrapped, tell the game thread to read and apply @@ -146,7 +154,7 @@ auto BallisticaMain(int argc, char** argv) -> int { // Phase 3/4: Create a screen and/or kick off game (in other threads). // ------------------------------------------------------------------------- - if (g_app->ManagesEventLoop()) { + if (g_app_flavor->ManagesEventLoop()) { // On our event-loop-managing platforms we now simply sit in our event // loop until the app is quit. g_main_thread->RunEventLoop(false); @@ -157,7 +165,7 @@ auto BallisticaMain(int argc, char** argv) -> int { // if the main thread event loop is driven by frame draws, it may need // to manually pump events until drawing begins (otherwise it will never // process the 'create-screen' event and wind up deadlocked). - g_app->PrimeEventPump(); + g_app_flavor->PrimeEventPump(); } } catch (const std::exception& exc) { std::string error_msg = @@ -182,16 +190,16 @@ auto BallisticaMain(int argc, char** argv) -> int { } g_platform->WillExitMain(false); - return g_app_globals->return_value; + return g_app->return_value; } auto GetRealTime() -> millisecs_t { millisecs_t t = g_platform->GetTicks(); // If we're at a different time than our last query, do our funky math. - if (t != g_app_globals->last_real_time_ticks) { - std::scoped_lock lock(g_app_globals->real_time_mutex); - millisecs_t passed = t - g_app_globals->last_real_time_ticks; + if (t != g_app->last_real_time_ticks) { + std::scoped_lock lock(g_app->real_time_mutex); + millisecs_t passed = t - g_app->last_real_time_ticks; // GetTicks() is supposed to be monotonic, but I've seen 'passed' // equal -1 even when it is using std::chrono::steady_clock. Let's do @@ -205,10 +213,10 @@ auto GetRealTime() -> millisecs_t { passed = 250; } } - g_app_globals->real_time += passed; - g_app_globals->last_real_time_ticks = t; + g_app->real_time += passed; + g_app->last_real_time_ticks = t; } - return g_app_globals->real_time; + return g_app->real_time; } auto FatalError(const std::string& message) -> void { @@ -251,8 +259,7 @@ auto InLogicThread() -> bool { } auto InMainThread() -> bool { - return (g_app_globals - && std::this_thread::get_id() == g_app_globals->main_thread_id); + return (g_app && std::this_thread::get_id() == g_app->main_thread_id); } auto InGraphicsThread() -> bool { @@ -280,7 +287,7 @@ auto Log(const std::string& msg, bool to_stdout, bool to_server) -> void { Logging::Log(msg, to_stdout, to_server); } -auto IsVRMode() -> bool { return g_app_globals->vr_mode; } +auto IsVRMode() -> bool { return g_app->vr_mode; } void ScreenMessage(const std::string& s, const Vector3f& color) { if (g_game) { @@ -298,7 +305,7 @@ auto GetCurrentThreadName() -> std::string { return Thread::GetCurrentThreadName(); } -auto IsBootstrapped() -> bool { return g_app_globals->is_bootstrapped; } +auto IsBootstrapped() -> bool { return g_app->is_bootstrapped; } } // namespace ballistica diff --git a/src/ballistica/ballistica.h b/src/ballistica/ballistica.h index f6ab51bd..325b02a0 100644 --- a/src/ballistica/ballistica.h +++ b/src/ballistica/ballistica.h @@ -118,9 +118,9 @@ const float kGameStepSeconds = // Globals. extern int g_early_log_writes; extern Account* g_account; -extern App* g_app; +extern AppFlavor* g_app_flavor; extern AppConfig* g_app_config; -extern AppGlobals* g_app_globals; +extern App* g_app; extern AppInternal* g_app_internal; extern Audio* g_audio; extern AudioServer* g_audio_server; diff --git a/src/ballistica/core/fatal_error.cc b/src/ballistica/core/fatal_error.cc index 7a85df82..8459de92 100644 --- a/src/ballistica/core/fatal_error.cc +++ b/src/ballistica/core/fatal_error.cc @@ -2,7 +2,7 @@ #include "ballistica/core/fatal_error.h" -#include "ballistica/app/app.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/core/logging.h" #include "ballistica/core/thread.h" #include "ballistica/internal/app_internal.h" @@ -80,7 +80,7 @@ auto FatalError::ReportFatalError(const std::string& message, // If we have no globals yet, include this message explicitly // since it won't be part of the standard log. - if (g_app_globals == nullptr) { + if (g_app == nullptr) { suffix = logmsg; } g_app_internal->DirectSendLogs(prefix, suffix, true, &result); @@ -110,7 +110,7 @@ auto FatalError::DoBlockingFatalErrorDialog(const std::string& message) bool finished{}; bool* startedptr{&started}; bool* finishedptr{&finished}; - g_app->thread()->PushCall([message, startedptr, finishedptr] { + g_app_flavor->thread()->PushCall([message, startedptr, finishedptr] { *startedptr = true; g_platform->BlockingFatalErrorDialog(message); *finishedptr = true; diff --git a/src/ballistica/core/logging.cc b/src/ballistica/core/logging.cc index 26594cb2..5635ceb4 100644 --- a/src/ballistica/core/logging.cc +++ b/src/ballistica/core/logging.cc @@ -4,7 +4,7 @@ #include -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/game.h" #include "ballistica/internal/app_internal.h" #include "ballistica/networking/telnet_server.h" @@ -27,8 +27,8 @@ static void PrintCommon(const std::string& s) { } } // Print to any telnet clients. - if (g_app_globals && g_app_globals->telnet_server) { - g_app_globals->telnet_server->PushPrint(s); + if (g_app && g_app->telnet_server) { + g_app->telnet_server->PushPrint(s); } } @@ -68,18 +68,18 @@ void Logging::Log(const std::string& msg, bool to_stdout, bool to_server) { } // Add to our complete log. - if (g_app_globals != nullptr) { - std::scoped_lock lock(g_app_globals->log_mutex); - if (!g_app_globals->log_full) { - (g_app_globals->log) += (msg + "\n"); - if ((g_app_globals->log).size() > 10000) { + if (g_app != nullptr) { + std::scoped_lock lock(g_app->log_mutex); + if (!g_app->log_full) { + (g_app->log) += (msg + "\n"); + if ((g_app->log).size() > 10000) { // Allow some reasonable overflow for last statement. - if ((g_app_globals->log).size() > 100000) { + if ((g_app->log).size() > 100000) { // FIXME: This could potentially chop up utf-8 chars. - (g_app_globals->log).resize(100000); + (g_app->log).resize(100000); } - g_app_globals->log += "\n\n"; - g_app_globals->log_full = true; + g_app->log += "\n\n"; + g_app->log_full = true; } } } @@ -87,7 +87,7 @@ void Logging::Log(const std::string& msg, bool to_stdout, bool to_server) { // If the game is fully bootstrapped, let the Python layer handle logs. // It will group log messages intelligently and ship them to the // master server with various other context info included. - if (g_app_globals && g_app_globals->is_bootstrapped) { + if (g_app && g_app->is_bootstrapped) { assert(g_python != nullptr); g_python->PushObjCall(Python::ObjID::kHandleLogCall); } else { @@ -100,7 +100,7 @@ void Logging::Log(const std::string& msg, bool to_stdout, bool to_server) { // If we're an early enough error, our global log isn't even available, // so include this specific message as a suffix instead. - if (g_app_globals == nullptr) { + if (g_app == nullptr) { logsuffix = msg; } g_app_internal->DirectSendLogs(logprefix, logsuffix, false); diff --git a/src/ballistica/core/object.cc b/src/ballistica/core/object.cc index 67f5e9e9..15634bcf 100644 --- a/src/ballistica/core/object.cc +++ b/src/ballistica/core/object.cc @@ -5,7 +5,7 @@ #include #include -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/generic/utils.h" #include "ballistica/platform/platform.h" @@ -15,8 +15,8 @@ void Object::PrintObjects() { #if BA_DEBUG_BUILD std::string s; { - std::scoped_lock lock(g_app_globals->object_list_mutex); - s = std::to_string(g_app_globals->object_count) + " Objects at time " + std::scoped_lock lock(g_app->object_list_mutex); + s = std::to_string(g_app->object_count) + " Objects at time " + std::to_string(GetRealTime()) + ";"; if (explicit_bool(true)) { @@ -24,7 +24,7 @@ void Object::PrintObjects() { // Tally up counts for all types. int count = 0; - for (Object* o = g_app_globals->object_list_first; o != nullptr; + for (Object* o = g_app->object_list_first; o != nullptr; o = o->object_next_) { count++; std::string obj_name = o->GetObjectTypeName(); @@ -51,7 +51,7 @@ void Object::PrintObjects() { for (auto&& i : sorted) { s += "\n " + std::to_string(i.first) + ": " + i.second; } - assert(count == g_app_globals->object_count); + assert(count == g_app->object_count); } } Log(s); @@ -66,30 +66,30 @@ Object::Object() { object_birth_time_ = GetRealTime(); // Add ourself to the global object list. - std::scoped_lock lock(g_app_globals->object_list_mutex); + std::scoped_lock lock(g_app->object_list_mutex); object_prev_ = nullptr; - object_next_ = g_app_globals->object_list_first; - g_app_globals->object_list_first = this; + object_next_ = g_app->object_list_first; + g_app->object_list_first = this; if (object_next_) { object_next_->object_prev_ = this; } - g_app_globals->object_count++; + g_app->object_count++; #endif // BA_DEBUG_BUILD } Object::~Object() { #if BA_DEBUG_BUILD // Pull ourself from the global obj list. - std::scoped_lock lock(g_app_globals->object_list_mutex); + std::scoped_lock lock(g_app->object_list_mutex); if (object_next_) { object_next_->object_prev_ = object_prev_; } if (object_prev_) { object_prev_->object_next_ = object_next_; } else { - g_app_globals->object_list_first = object_next_; + g_app->object_list_first = object_next_; } - g_app_globals->object_count--; + g_app->object_count--; // More sanity checks. if (object_strong_ref_count_ != 0) { diff --git a/src/ballistica/core/thread.cc b/src/ballistica/core/thread.cc index c197f637..4929338e 100644 --- a/src/ballistica/core/thread.cc +++ b/src/ballistica/core/thread.cc @@ -2,7 +2,7 @@ #include "ballistica/core/thread.h" -#include "ballistica/app/app.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/core/fatal_error.h" #include "ballistica/platform/platform.h" #include "ballistica/python/python.h" @@ -10,16 +10,16 @@ namespace ballistica { void Thread::SetInternalThreadName(const std::string& name) { - std::scoped_lock lock(g_app_globals->thread_name_map_mutex); + std::scoped_lock lock(g_app->thread_name_map_mutex); std::thread::id thread_id = std::this_thread::get_id(); - g_app_globals->thread_name_map[std::this_thread::get_id()] = name; + g_app->thread_name_map[std::this_thread::get_id()] = name; } void Thread::ClearCurrentThreadName() { - std::scoped_lock lock(g_app_globals->thread_name_map_mutex); - auto i = g_app_globals->thread_name_map.find(std::this_thread::get_id()); - if (i != g_app_globals->thread_name_map.end()) { - g_app_globals->thread_name_map.erase(i); + std::scoped_lock lock(g_app->thread_name_map_mutex); + auto i = g_app->thread_name_map.find(std::this_thread::get_id()); + if (i != g_app->thread_name_map.end()) { + g_app->thread_name_map.erase(i); } } @@ -28,11 +28,11 @@ void Thread::UpdateMainThreadID() { // This gets called a lot and it may happen before we are spun up, // so just ignore it in that case.. - if (g_app_globals) { - g_app_globals->main_thread_id = current_id; - } if (g_app) { - g_app->thread()->set_thread_id(current_id); + g_app->main_thread_id = current_id; + } + if (g_app_flavor) { + g_app_flavor->thread()->set_thread_id(current_id); } } @@ -66,7 +66,7 @@ auto Thread::RunMediaThread(void* data) -> int { void Thread::SetPaused(bool paused) { // Can be toggled from the main thread only. - assert(std::this_thread::get_id() == g_app_globals->main_thread_id); + assert(std::this_thread::get_id() == g_app->main_thread_id); PushThreadMessage(ThreadMessage(paused ? ThreadMessage::Type::kPause : ThreadMessage::Type::kResume)); } @@ -258,7 +258,7 @@ Thread::Thread(ThreadIdentifier identifier_in, ThreadType type_in) case ThreadType::kMain: { // We've got no thread of our own to launch // so we run our setup stuff right here instead of off in some. - assert(std::this_thread::get_id() == g_app_globals->main_thread_id); + assert(std::this_thread::get_id() == g_app->main_thread_id); thread_id_ = std::this_thread::get_id(); // Set our own thread-id-to-name mapping. @@ -452,8 +452,7 @@ void Thread::PushThreadMessage(const ThreadMessage& t) { } // Show count periodically. - if ((std::this_thread::get_id() == g_app_globals->main_thread_id) - && foo > 100) { + if ((std::this_thread::get_id() == g_app->main_thread_id) && foo > 100) { foo = 0; Log("MSG COUNT " + std::to_string(thread_message_count_)); } @@ -482,15 +481,13 @@ void Thread::PushThreadMessage(const ThreadMessage& t) { } void Thread::SetThreadsPaused(bool paused) { - g_app_globals->threads_paused = paused; - for (auto&& i : g_app_globals->pausable_threads) { + g_app->threads_paused = paused; + for (auto&& i : g_app->pausable_threads) { i->SetPaused(paused); } } -auto Thread::AreThreadsPaused() -> bool { - return g_app_globals->threads_paused; -} +auto Thread::AreThreadsPaused() -> bool { return g_app->threads_paused; } auto Thread::NewTimer(millisecs_t length, bool repeat, const Object::Ref& runnable) -> Timer* { @@ -500,13 +497,13 @@ auto Thread::NewTimer(millisecs_t length, bool repeat, } auto Thread::GetCurrentThreadName() -> std::string { - if (g_app_globals == nullptr) { + if (g_app == nullptr) { return "unknown(not-yet-inited)"; } { - std::scoped_lock lock(g_app_globals->thread_name_map_mutex); - auto i = g_app_globals->thread_name_map.find(std::this_thread::get_id()); - if (i != g_app_globals->thread_name_map.end()) { + std::scoped_lock lock(g_app->thread_name_map_mutex); + auto i = g_app->thread_name_map.find(std::this_thread::get_id()); + if (i != g_app->thread_name_map.end()) { return i->second; } } diff --git a/src/ballistica/core/thread.h b/src/ballistica/core/thread.h index 7435531f..4feabd0d 100644 --- a/src/ballistica/core/thread.h +++ b/src/ballistica/core/thread.h @@ -10,7 +10,7 @@ #include #include -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/ballistica.h" #include "ballistica/generic/lambda_runnable.h" #include "ballistica/generic/timer_list.h" @@ -141,7 +141,7 @@ class Thread { // FIXME: Should generalize this to some sort of PlatformThreadData class. #if BA_XCODE_BUILD - void* auto_release_pool_ = nullptr; + void* auto_release_pool_{}; #endif // These are all exactly the same, but by running different ones for diff --git a/src/ballistica/core/types.h b/src/ballistica/core/types.h index 310795a4..ffb27cf6 100644 --- a/src/ballistica/core/types.h +++ b/src/ballistica/core/types.h @@ -35,9 +35,9 @@ typedef int64_t millisecs_t; // to keep compile times down. class Account; -class App; +class AppFlavor; class AppConfig; -class AppGlobals; +class App; class AppInternal; class AreaOfInterest; class Audio; @@ -196,7 +196,7 @@ class Utils; class Vector2f; class Vector3f; class Vector4f; -class VRApp; +class AppFlavorVR; class VRGraphics; class Widget; diff --git a/src/ballistica/game/account.cc b/src/ballistica/game/account.cc index 40ce85c0..da5670c4 100644 --- a/src/ballistica/game/account.cc +++ b/src/ballistica/game/account.cc @@ -2,7 +2,7 @@ #include "ballistica/game/account.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/game.h" #include "ballistica/generic/utils.h" #include "ballistica/internal/app_internal.h" @@ -152,23 +152,22 @@ void Account::SetLogin(V1AccountType account_type, V1LoginState login_state, // We call out to Python so need to be in game thread. assert(InLogicThread()); - if (login_state_ != login_state - || g_app_globals->account_type != account_type || login_id_ != login_id - || login_name_ != login_name) { + if (login_state_ != login_state || g_app->account_type != account_type + || login_id_ != login_id || login_name_ != login_name) { // Special case: if they sent a sign-out for an account type that is // currently not signed in, ignore it. if (login_state == V1LoginState::kSignedOut - && (account_type != g_app_globals->account_type)) { + && (account_type != g_app->account_type)) { // No-op. } else { login_state_ = login_state; - g_app_globals->account_type = account_type; + g_app->account_type = account_type; login_id_ = login_id; login_name_ = Utils::GetValidUTF8(login_name.c_str(), "gthm"); // If they signed out of an account, account type switches to invalid. if (login_state == V1LoginState::kSignedOut) { - g_app_globals->account_type = V1AccountType::kInvalid; + g_app->account_type = V1AccountType::kInvalid; } login_state_num_ += 1; call_login_did_change = true; diff --git a/src/ballistica/game/game.cc b/src/ballistica/game/game.cc index bfb9bf72..31399a63 100644 --- a/src/ballistica/game/game.cc +++ b/src/ballistica/game/game.cc @@ -2,8 +2,8 @@ #include "ballistica/game/game.h" -#include "ballistica/app/app.h" #include "ballistica/app/app_config.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/audio/audio.h" #include "ballistica/core/thread.h" #include "ballistica/dynamics/bg/bg_dynamics.h" @@ -105,11 +105,11 @@ Game::Game(Thread* thread) assert(g_input == nullptr); g_input = new Input(); + g_app_internal = GetAppInternal(); + // Init python and apply our settings immediately. // This way we can get started loading stuff in the background // and it'll come in with the correct texture quality etc. - assert(g_python == nullptr); - g_python = new Python(); g_python->Reset(true); // We're the thread that 'owns' python so we need to wrangle the GIL. @@ -294,8 +294,8 @@ void Game::InitialScreenCreated() { // we need it to be possible to load textures/etc. before the renderer // exists. if (!HeadlessMode()) { - assert(!g_app_globals->console); - g_app_globals->console = new Console(); + assert(!g_app->console); + g_app->console = new Console(); } // Set up our timers. @@ -331,8 +331,8 @@ void Game::RunAppLaunchCommands() { ran_app_launch_commands_ = true; // If we were passed launch command args, run them. - if (!g_app_globals->exec_command.empty()) { - bool success = PythonCommand(g_app_globals->exec_command, BA_BCFN).Run(); + if (!g_app->exec_command.empty()) { + bool success = PythonCommand(g_app->exec_command, BA_BCFN).Run(); if (!success) { exit(1); } @@ -662,8 +662,7 @@ void Game::Update() { in_update_ = false; // Report excessively long updates. - if (g_app_globals->debug_timing - && real_time >= next_long_update_report_time_) { + if (g_app->debug_timing && real_time >= next_long_update_report_time_) { auto duration{Platform::GetCurrentMilliseconds() - startms}; // Complain when our full update takes longer than 1/60th second. @@ -690,9 +689,9 @@ void Game::Reset() { PruneSessions(); // If all is well our sessions should all be dead. - if (g_app_globals->session_count != 0) { + if (g_app->session_count != 0) { Log("Error: session-count is non-zero (" - + std::to_string(g_app_globals->session_count) + ") on Game::Reset."); + + std::to_string(g_app->session_count) + ") on Game::Reset."); } // Note: we don't clear real-time timers anymore. Should we?.. @@ -897,7 +896,7 @@ void Game::LaunchHostSession(PyObject* session_type_obj, void Game::RunMainMenu() { assert(InLogicThread()); - if (g_app_globals->shutting_down) { + if (g_app->shutting_down) { return; } assert(g_python); @@ -917,8 +916,8 @@ void Game::PushInGameConsoleScriptCommand(const std::string& command) { // These are always run in whichever context is 'visible'. ScopedSetContext cp(GetForegroundContext()); PythonCommand cmd(command, ""); - if (!g_app_globals->user_ran_commands) { - g_app_globals->user_ran_commands = true; + if (!g_app->user_ran_commands) { + g_app->user_ran_commands = true; } if (cmd.CanEval()) { PyObject* obj = cmd.RunReturnObj(true, nullptr); @@ -926,8 +925,8 @@ void Game::PushInGameConsoleScriptCommand(const std::string& command) { PyObject* s = PyObject_Repr(obj); if (s) { const char* c = PyUnicode_AsUTF8(s); - if (g_app_globals->console) { - g_app_globals->console->Print(std::string(c) + "\n"); + if (g_app->console) { + g_app->console->Print(std::string(c) + "\n"); } Py_DECREF(s); } @@ -946,8 +945,8 @@ void Game::PushStdinScriptCommand(const std::string& command) { // These are always run in whichever context is 'visible'. ScopedSetContext cp(GetForegroundContext()); PythonCommand cmd(command, ""); - if (!g_app_globals->user_ran_commands) { - g_app_globals->user_ran_commands = true; + if (!g_app->user_ran_commands) { + g_app->user_ran_commands = true; } // Eval this if possible (so we can possibly print return value). @@ -956,7 +955,7 @@ void Game::PushStdinScriptCommand(const std::string& command) { // Print the value if we're running directly from a terminal // (or being run under the server-manager) if ((g_platform->is_stdin_a_terminal() - || g_app->server_wrapper_managed()) + || g_app_flavor->server_wrapper_managed()) && obj != Py_None) { PyObject* s = PyObject_Repr(obj); if (s) { @@ -981,7 +980,7 @@ void Game::PushInterruptSignalCall() { // Special case; when running under the server-wrapper, we completely // ignore interrupt signals (the wrapper acts on them). - if (g_app->server_wrapper_managed()) { + if (g_app_flavor->server_wrapper_managed()) { return; } @@ -1206,8 +1205,7 @@ void Game::PushConfirmQuitCall() { // If input is locked, just quit immediately.. a confirm screen wouldn't // work anyway if (g_input->IsInputLocked() - || (g_app_globals->console != nullptr - && g_app_globals->console->active())) { + || (g_app->console != nullptr && g_app->console->active())) { // Just go through _ba.quit() // FIXME: Shouldn't need to go out to the python layer here... g_python->obj(Python::ObjID::kQuitCall).Call(); @@ -1342,7 +1340,7 @@ void Game::ApplyConfig() { } if (!HeadlessMode()) { - g_app_globals->remote_server_accepting_connections = + g_app->remote_server_accepting_connections = g_app_config->Resolve(AppConfig::BoolID::kEnableRemoteApp); } @@ -1413,8 +1411,8 @@ void Game::ApplyConfig() { std::string telnet_password = g_app_config->Resolve(AppConfig::StringID::kTelnetPassword); - g_app->PushNetworkSetupCall(port, telnet_port, enable_telnet, - telnet_password); + g_app_flavor->PushNetworkSetupCall(port, telnet_port, enable_telnet, + telnet_password); bool disable_camera_shake = g_app_config->Resolve(AppConfig::BoolID::kDisableCameraShake); @@ -1460,7 +1458,7 @@ void Game::PushHavePendingLoadsDoneCall() { void Game::ToggleConsole() { assert(InLogicThread()); - if (auto console = g_app_globals->console) { + if (auto console = g_app->console) { console->ToggleState(); } } @@ -1469,10 +1467,10 @@ void Game::PushConsolePrintCall(const std::string& msg) { thread()->PushCall([msg] { // Send them to the console if its been created or store them // for when it is (unless we're headless in which case it never will). - if (auto console = g_app_globals->console) { + if (auto console = g_app->console) { console->Print(msg); } else if (!HeadlessMode()) { - g_app_globals->console_startup_messages += msg; + g_app->console_startup_messages += msg; } }); } @@ -1491,8 +1489,8 @@ void Game::PushShutdownCall(bool soft) { void Game::Shutdown(bool soft) { assert(InLogicThread()); - if (!g_app_globals->shutting_down) { - g_app_globals->shutting_down = true; + if (!g_app->shutting_down) { + g_app->shutting_down = true; // Nuke the app if we get stuck shutting down. Utils::StartSuicideTimer("shutdown", 10000); @@ -1511,7 +1509,7 @@ void Game::Shutdown(bool soft) { // Ideally we'd want to give some of the above stuff // a few seconds to complete, but just calling it done for now. - g_app->PushShutdownCompleteCall(); + g_app_flavor->PushShutdownCompleteCall(); } } diff --git a/src/ballistica/game/game_stream.cc b/src/ballistica/game/game_stream.cc index db1de9a8..71beb4e3 100644 --- a/src/ballistica/game/game_stream.cc +++ b/src/ballistica/game/game_stream.cc @@ -2,7 +2,7 @@ #include "ballistica/game/game_stream.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/dynamics/bg/bg_dynamics.h" #include "ballistica/dynamics/material/material.h" #include "ballistica/dynamics/material/material_action.h" @@ -34,13 +34,13 @@ GameStream::GameStream(HostSession* host_session, bool save_replay) writing_replay_(false) { if (save_replay) { // Sanity check - we should only ever be writing one replay at once. - if (g_app_globals->replay_open) { + if (g_app->replay_open) { Log("ERROR: g_replay_open true at replay start; shouldn't happen."); } assert(g_media_server); g_media_server->PushBeginWriteReplayCall(); writing_replay_ = true; - g_app_globals->replay_open = true; + g_app->replay_open = true; } // If we're the live output-stream from a host-session, @@ -56,10 +56,10 @@ GameStream::~GameStream() { if (writing_replay_) { // Sanity check: We should only ever be writing one replay at once. - if (!g_app_globals->replay_open) { + if (!g_app->replay_open) { Log("ERROR: g_replay_open false at replay close; shouldn't happen."); } - g_app_globals->replay_open = false; + g_app->replay_open = false; assert(g_media_server); g_media_server->PushEndWriteReplayCall(); writing_replay_ = false; @@ -189,13 +189,13 @@ void GameStream::Fail() { Log("Error writing replay file"); if (writing_replay_) { // Sanity check: We should only ever be writing one replay at once. - if (!g_app_globals->replay_open) { + if (!g_app->replay_open) { Log("ERROR: g_replay_open false at replay close; shouldn't happen."); } assert(g_media_server); g_media_server->PushEndWriteReplayCall(); writing_replay_ = false; - g_app_globals->replay_open = false; + g_app->replay_open = false; } } @@ -437,7 +437,7 @@ void GameStream::EndCommand(bool is_time_set) { // Now if its been long enough *AND* this is a time-step command, send. millisecs_t real_time = GetRealTime(); millisecs_t diff = real_time - last_send_time_; - if (is_time_set && diff >= g_app_globals->buffer_time) { + if (is_time_set && diff >= g_app->buffer_time) { ShipSessionCommandsMessage(); // Also, as long as we're here, fire off a physics-correction packet every @@ -447,7 +447,7 @@ void GameStream::EndCommand(bool is_time_set) { // commands; otherwise the client will get the correction that accounts // for commands that they haven't been sent yet. diff = real_time - last_physics_correction_time_; - if (diff >= g_app_globals->dynamics_sync_time) { + if (diff >= g_app->dynamics_sync_time) { last_physics_correction_time_ = real_time; SendPhysicsCorrection(true); } diff --git a/src/ballistica/game/player_spec.cc b/src/ballistica/game/player_spec.cc index 48b8f637..c41c6f29 100644 --- a/src/ballistica/game/player_spec.cc +++ b/src/ballistica/game/player_spec.cc @@ -2,7 +2,7 @@ #include "ballistica/game/player_spec.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/account.h" #include "ballistica/game/game.h" #include "ballistica/generic/json.h" @@ -77,7 +77,7 @@ auto PlayerSpec::GetSpecString() const -> std::string { auto PlayerSpec::GetAccountPlayerSpec() -> PlayerSpec { PlayerSpec spec; if (g_account->GetLoginState() == V1LoginState::kSignedIn) { - spec.account_type_ = g_app_globals->account_type; + spec.account_type_ = g_app->account_type; spec.name_ = Utils::GetValidUTF8(g_account->GetLoginName().c_str(), "bsgaps"); } else { diff --git a/src/ballistica/game/session/client_session.cc b/src/ballistica/game/session/client_session.cc index e2a46085..30453ffe 100644 --- a/src/ballistica/game/session/client_session.cc +++ b/src/ballistica/game/session/client_session.cc @@ -2,7 +2,7 @@ #include "ballistica/game/session/client_session.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/audio/audio.h" #include "ballistica/dynamics/bg/bg_dynamics.h" #include "ballistica/dynamics/material/material.h" @@ -333,14 +333,13 @@ void ClientSession::Update(int time_advance) { int32_t vals[3]; // scene-id, nodetype-id, node-id ReadInt32_3(vals); Scene* scene = GetScene(vals[0]); - assert(g_app_globals != nullptr); + assert(g_app != nullptr); if (vals[1] < 0 - || vals[1] >= static_cast( - g_app_globals->node_types_by_id.size())) { + || vals[1] >= static_cast(g_app->node_types_by_id.size())) { throw Exception("invalid node type id"); } - NodeType* node_type = g_app_globals->node_types_by_id[vals[1]]; + NodeType* node_type = g_app->node_types_by_id[vals[1]]; // Fail if we get a ridiculous number of nodes. // FIXME: should enforce this on the server side too. diff --git a/src/ballistica/game/session/net_client_session.cc b/src/ballistica/game/session/net_client_session.cc index a60407c9..477d1c89 100644 --- a/src/ballistica/game/session/net_client_session.cc +++ b/src/ballistica/game/session/net_client_session.cc @@ -2,7 +2,7 @@ #include "ballistica/game/session/net_client_session.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/connection/connection_to_host.h" #include "ballistica/graphics/graphics.h" #include "ballistica/graphics/net_graph.h" @@ -12,22 +12,22 @@ namespace ballistica { NetClientSession::NetClientSession() { // Sanity check: we should only ever be writing one replay at once. - if (g_app_globals->replay_open) { + if (g_app->replay_open) { Log("ERROR: g_replay_open true at netclient start; shouldn't happen."); } assert(g_media_server); g_media_server->PushBeginWriteReplayCall(); writing_replay_ = true; - g_app_globals->replay_open = true; + g_app->replay_open = true; } NetClientSession::~NetClientSession() { if (writing_replay_) { // Sanity check: we should only ever be writing one replay at once. - if (!g_app_globals->replay_open) { + if (!g_app->replay_open) { Log("ERROR: g_replay_open false at net-client close; shouldn't happen."); } - g_app_globals->replay_open = false; + g_app->replay_open = false; assert(g_media_server); g_media_server->PushEndWriteReplayCall(); writing_replay_ = false; @@ -59,7 +59,7 @@ void NetClientSession::Update(int time_advance) { } auto NetClientSession::GetBucketNum() -> int { - return (delay_sample_counter_ / g_app_globals->delay_bucket_samples) + return (delay_sample_counter_ / g_app->delay_bucket_samples) % static_cast(buckets_.size()); } @@ -69,8 +69,7 @@ auto NetClientSession::UpdateBuffering() -> void { { // Change bucket every `g_delay_samples` samples. int bucketnum{GetBucketNum()}; - int bucket_iteration = - delay_sample_counter_ % g_app_globals->delay_bucket_samples; + int bucket_iteration = delay_sample_counter_ % g_app->delay_bucket_samples; delay_sample_counter_++; SampleBucket& bucket{buckets_[bucketnum]}; if (bucket_iteration == 0) { @@ -79,7 +78,7 @@ auto NetClientSession::UpdateBuffering() -> void { // After the last sample in each bucket, update our smoothed values with // the full sample set in the bucket. - if (bucket_iteration == g_app_globals->delay_bucket_samples - 1) { + if (bucket_iteration == g_app->delay_bucket_samples - 1) { float smoothing = 0.7f; last_bucket_max_delay_ = static_cast(bucket.max_delay_from_projection); diff --git a/src/ballistica/game/session/session.cc b/src/ballistica/game/session/session.cc index 07a8293b..6085642f 100644 --- a/src/ballistica/game/session/session.cc +++ b/src/ballistica/game/session/session.cc @@ -2,19 +2,19 @@ #include "ballistica/game/session/session.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/game.h" namespace ballistica { Session::Session() { - g_app_globals->session_count++; + g_app->session_count++; // New sessions immediately become foreground. g_game->SetForegroundSession(this); } -Session::~Session() { g_app_globals->session_count--; } +Session::~Session() { g_app->session_count--; } void Session::Update(int time_advance) {} diff --git a/src/ballistica/generic/utils.cc b/src/ballistica/generic/utils.cc index 58b134c2..a7f341d1 100644 --- a/src/ballistica/generic/utils.cc +++ b/src/ballistica/generic/utils.cc @@ -5,7 +5,7 @@ #include #include -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/generic/huffman.h" #include "ballistica/generic/json.h" #include "ballistica/generic/utf8.h" @@ -113,14 +113,12 @@ Utils::Utils() { // Remember that results can vary per compiler; make sure we match // any one of the expected formats. - static_assert(static_type_name_constexpr() - == "ballistica::AppGlobals *" - || static_type_name_constexpr() - == "ballistica::AppGlobals*" - || static_type_name_constexpr() - == "class ballistica::AppGlobals*" - || static_type_name_constexpr() - == "AppGlobals*"); + static_assert( + static_type_name_constexpr() == "ballistica::App *" + || static_type_name_constexpr() == "ballistica::App*" + || static_type_name_constexpr() + == "class ballistica::App*" + || static_type_name_constexpr() == "App*"); Object::Ref testnode{}; static_assert( static_type_name_constexpr() @@ -502,9 +500,9 @@ static void WaitThenDie(millisecs_t wait, const std::string& action) { } void Utils::StartSuicideTimer(const std::string& action, millisecs_t delay) { - if (!g_app_globals->started_suicide) { + if (!g_app->started_suicide) { new std::thread(WaitThenDie, delay, action); - g_app_globals->started_suicide = true; + g_app->started_suicide = true; } } diff --git a/src/ballistica/graphics/graphics.cc b/src/ballistica/graphics/graphics.cc index 50e69f10..ef1949db 100644 --- a/src/ballistica/graphics/graphics.cc +++ b/src/ballistica/graphics/graphics.cc @@ -3,7 +3,7 @@ #include "ballistica/graphics/graphics.h" #include "ballistica/app/app.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/dynamics/bg/bg_dynamics.h" #include "ballistica/game/connection/connection_set.h" #include "ballistica/game/connection/connection_to_client.h" @@ -1043,8 +1043,8 @@ void Graphics::BuildAndPushFrameDef() { DrawMiscOverlays(overlay_pass); // Draw console. - if (!HeadlessMode() && g_app_globals->console) { - g_app_globals->console->Draw(overlay_pass); + if (!HeadlessMode() && g_app->console) { + g_app->console->Draw(overlay_pass); } DrawCursor(overlay_pass, real_time); @@ -1339,7 +1339,7 @@ void Graphics::DrawCursor(RenderPass* pass, millisecs_t real_time) { || real_time - last_cursor_visibility_event_time_ > 2000) { hardware_cursor_visible_ = new_cursor_visibility; last_cursor_visibility_event_time_ = real_time; - g_app->PushCursorUpdate(hardware_cursor_visible_); + g_app_flavor->PushCursorUpdate(hardware_cursor_visible_); } } else { // Draw software cursor. diff --git a/src/ballistica/graphics/graphics_server.cc b/src/ballistica/graphics/graphics_server.cc index 84720d23..fe7b7862 100644 --- a/src/ballistica/graphics/graphics_server.cc +++ b/src/ballistica/graphics/graphics_server.cc @@ -10,7 +10,7 @@ #if BA_SDL_BUILD #include "ballistica/platform/sdl/sdl_app.h" #else -#include "ballistica/app/app.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/graphics/frame_def.h" #include "ballistica/graphics/mesh/mesh_data.h" #include "ballistica/graphics/renderer.h" @@ -70,7 +70,7 @@ auto GraphicsServer::GetRenderFrameDef() -> FrameDef* { // If the app says it's minimized minimized, don't do anything. // (on iOS we'll get shut down if we make GL calls in this state, etc) - if (g_app->paused()) { + if (g_app_flavor->paused()) { return nullptr; } @@ -150,7 +150,7 @@ void GraphicsServer::FinishRenderFrameDef(FrameDef* frame_def) { // Let the app know a frame render is complete (it may need to do a // swap/etc). - g_app->DidFinishRenderingFrame(frame_def); + g_app_flavor->DidFinishRenderingFrame(frame_def); } } @@ -749,7 +749,7 @@ void GraphicsServer::PushSetVSyncCall(bool sync, bool auto_sync) { if (g_buildconfig.sdl_build()) { // Even if we were built with SDL, we may not be running in sdl-app-mode // (for instance, Rift in VR mode). Only do this if we're an sdl app. - if (auto app = dynamic_cast(g_app)) { + if (auto app = dynamic_cast(g_app_flavor)) { v_sync_ = sync; auto_vsync_ = auto_sync; if (gl_context_) { diff --git a/src/ballistica/graphics/renderer.cc b/src/ballistica/graphics/renderer.cc index f38d66e2..f5fe3ed4 100644 --- a/src/ballistica/graphics/renderer.cc +++ b/src/ballistica/graphics/renderer.cc @@ -10,7 +10,7 @@ #endif #if BA_VR_BUILD -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/graphics/vr_graphics.h" #endif @@ -317,8 +317,8 @@ void Renderer::VRPreprocess(FrameDef* frame_def) { * Matrix44fTranslate(vr_raw_head_tx_, vr_raw_head_ty_, vr_raw_head_tz_) * vr_base_transform_; - if (g_app_globals->reset_vr_orientation) { - g_app_globals->reset_vr_orientation = false; + if (g_app->reset_vr_orientation) { + g_app->reset_vr_orientation = false; } Vector3f translate = vr_transform_head_.GetTranslate(); diff --git a/src/ballistica/graphics/vr_graphics.cc b/src/ballistica/graphics/vr_graphics.cc index 643eed77..ebb6a81e 100644 --- a/src/ballistica/graphics/vr_graphics.cc +++ b/src/ballistica/graphics/vr_graphics.cc @@ -3,7 +3,7 @@ #include "ballistica/graphics/vr_graphics.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/game.h" #include "ballistica/graphics/camera.h" #include "ballistica/graphics/component/object_component.h" diff --git a/src/ballistica/input/device/input_device.cc b/src/ballistica/input/device/input_device.cc index ef05b9f4..16926d6f 100644 --- a/src/ballistica/input/device/input_device.cc +++ b/src/ballistica/input/device/input_device.cc @@ -5,7 +5,7 @@ #include #include -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/connection/connection_to_host.h" #include "ballistica/game/player.h" #include "ballistica/game/session/host_session.h" @@ -251,7 +251,7 @@ void InputDevice::ShipBufferIfFull() { size_t size = remote_input_commands_buffer_.size(); if (size > 2 && (static_cast(real_time - last_remote_input_commands_send_time_) - >= g_app_globals->buffer_time + >= g_app->buffer_time || size > 400)) { last_remote_input_commands_send_time_ = real_time; hc->SendReliableMessage(remote_input_commands_buffer_); diff --git a/src/ballistica/input/device/joystick.cc b/src/ballistica/input/device/joystick.cc index 492b3b6e..292c1c01 100644 --- a/src/ballistica/input/device/joystick.cc +++ b/src/ballistica/input/device/joystick.cc @@ -3,7 +3,7 @@ #include "ballistica/input/device/joystick.h" #include "ballistica/app/app.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/audio/audio.h" #include "ballistica/core/thread.h" #include "ballistica/game/connection/connection_set.h" @@ -304,9 +304,10 @@ Joystick::~Joystick() { // here in the game thread.. if (sdl_joystick_) { #if BA_ENABLE_SDL_JOYSTICKS - assert(g_app); + assert(g_app_flavor); auto joystick = sdl_joystick_; - g_app->thread()->PushCall([joystick] { SDL_JoystickClose(joystick); }); + g_app_flavor->thread()->PushCall( + [joystick] { SDL_JoystickClose(joystick); }); sdl_joystick_ = nullptr; #else Log("sdl_joystick_ set in non-sdl-joystick build destructor."); @@ -770,7 +771,7 @@ void Joystick::HandleSDLEvent(const SDL_Event* e) { if (e->jbutton.button == vr_reorient_button_ && IsVRMode()) { ScreenMessage(g_game->GetResourceString("vrOrientationResetText"), {0, 1, 0}); - g_app_globals->reset_vr_orientation = true; + g_app->reset_vr_orientation = true; return; } } diff --git a/src/ballistica/input/device/touch_input.cc b/src/ballistica/input/device/touch_input.cc index 39bc30d5..500b699e 100644 --- a/src/ballistica/input/device/touch_input.cc +++ b/src/ballistica/input/device/touch_input.cc @@ -2,8 +2,8 @@ #include "ballistica/input/device/touch_input.h" +#include "ballistica/app/app.h" #include "ballistica/app/app_config.h" -#include "ballistica/app/app_globals.h" #include "ballistica/game/host_activity.h" #include "ballistica/game/player.h" #include "ballistica/graphics/camera.h" @@ -82,8 +82,8 @@ TouchInput::TouchInput() { break; } - assert(g_app_globals->touch_input == nullptr); - g_app_globals->touch_input = this; + assert(g_app->touch_input == nullptr); + g_app->touch_input = this; } TouchInput::~TouchInput() = default; diff --git a/src/ballistica/input/input.cc b/src/ballistica/input/input.cc index b7a2cefb..9af81231 100644 --- a/src/ballistica/input/input.cc +++ b/src/ballistica/input/input.cc @@ -2,8 +2,8 @@ #include "ballistica/input/input.h" +#include "ballistica/app/app.h" #include "ballistica/app/app_config.h" -#include "ballistica/app/app_globals.h" #include "ballistica/audio/audio.h" #include "ballistica/core/thread.h" #include "ballistica/game/player.h" @@ -1095,8 +1095,7 @@ void Input::PushTextInputEvent(const std::string& text) { if (IsInputLocked()) { return; } - if (g_app_globals->console != nullptr - && g_app_globals->console->HandleTextEditing(text)) { + if (g_app->console != nullptr && g_app->console->HandleTextEditing(text)) { return; } g_ui->SendWidgetMessage(WidgetMessage(WidgetMessage::Type::kTextInput, @@ -1213,8 +1212,7 @@ void Input::HandleKeyPress(const SDL_Keysym* keysym) { } // Let the console intercept stuff if it wants at this point. - if (g_app_globals->console != nullptr - && g_app_globals->console->HandleKeyPress(keysym)) { + if (g_app->console != nullptr && g_app->console->HandleKeyPress(keysym)) { return; } @@ -1351,8 +1349,7 @@ void Input::HandleKeyRelease(const SDL_Keysym* keysym) { bool handled = false; - if (g_app_globals->console != nullptr - && g_app_globals->console->HandleKeyRelease(keysym)) { + if (g_app->console != nullptr && g_app->console->HandleKeyRelease(keysym)) { handled = true; } diff --git a/src/ballistica/input/remote_app.cc b/src/ballistica/input/remote_app.cc index 5afe1fd6..b76a7fac 100644 --- a/src/ballistica/input/remote_app.cc +++ b/src/ballistica/input/remote_app.cc @@ -9,7 +9,7 @@ #endif -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/game.h" #include "ballistica/generic/utils.h" #include "ballistica/input/input.h" @@ -346,7 +346,7 @@ auto RemoteAppServer::GetClient(int request_id, struct sockaddr* addr, size_t addr_len, const char* name, bool using_v2) -> int { // If we're not accepting connections at all, reject 'em. - if (!g_app_globals->remote_server_accepting_connections) { + if (!g_app->remote_server_accepting_connections) { return -1; } diff --git a/src/ballistica/input/std_input_module.cc b/src/ballistica/input/std_input_module.cc index 0537af8d..8f662be0 100644 --- a/src/ballistica/input/std_input_module.cc +++ b/src/ballistica/input/std_input_module.cc @@ -6,7 +6,7 @@ #include #endif -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/core/thread.h" #include "ballistica/game/game.h" #include "ballistica/platform/platform.h" @@ -28,7 +28,7 @@ void StdInputModule::PushBeginReadCall() { // results of the last script-command message we may have just sent. if (stdin_is_terminal) { g_game->thread()->PushCall([] { - if (!g_app_globals->shutting_down) { + if (!g_app->shutting_down) { printf(">>> "); fflush(stdout); } @@ -66,7 +66,7 @@ void StdInputModule::PushBeginReadCall() { if (g_buildconfig.windows_console_build()) { Platform::SleepMS(250); } - if (!g_app_globals->shutting_down) { + if (!g_app->shutting_down) { printf("Stdin EOF reached. Use Ctrl-C to quit.\n"); fflush(stdout); } diff --git a/src/ballistica/networking/networking.cc b/src/ballistica/networking/networking.cc index e35296a6..14304ecd 100644 --- a/src/ballistica/networking/networking.cc +++ b/src/ballistica/networking/networking.cc @@ -2,7 +2,7 @@ #include "ballistica/networking/networking.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/player_spec.h" #include "ballistica/networking/network_reader.h" #include "ballistica/networking/sockaddr.h" diff --git a/src/ballistica/networking/telnet_server.cc b/src/ballistica/networking/telnet_server.cc index a1e6eb7d..224afaca 100644 --- a/src/ballistica/networking/telnet_server.cc +++ b/src/ballistica/networking/telnet_server.cc @@ -2,7 +2,7 @@ #include "ballistica/networking/telnet_server.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/core/context.h" #include "ballistica/core/thread.h" #include "ballistica/game/game.h" @@ -16,8 +16,8 @@ namespace ballistica { TelnetServer::TelnetServer(int port) : port_(port) { thread_ = new std::thread(RunThreadStatic, this); - assert(g_app_globals->telnet_server == nullptr); - g_app_globals->telnet_server = this; + assert(g_app->telnet_server == nullptr); + g_app->telnet_server = this; // NOTE: we consider access implicitly granted on headless builds // since we can't pop up the request dialog. @@ -192,8 +192,8 @@ void TelnetServer::PushTelnetScriptCommand(const std::string& command) { g_game->thread()->PushCall([this, command] { // These are always run in whichever context is 'visible'. ScopedSetContext cp(g_game->GetForegroundContext()); - if (!g_app_globals->user_ran_commands) { - g_app_globals->user_ran_commands = true; + if (!g_app->user_ran_commands) { + g_app->user_ran_commands = true; } PythonCommand cmd(command, ""); if (cmd.CanEval()) { diff --git a/src/ballistica/platform/platform.cc b/src/ballistica/platform/platform.cc index 1ed29e2b..0a074a7c 100644 --- a/src/ballistica/platform/platform.cc +++ b/src/ballistica/platform/platform.cc @@ -19,7 +19,7 @@ #include -#include "ballistica/app/app.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/core/thread.h" #include "ballistica/dynamics/bg/bg_dynamics_server.h" #include "ballistica/game/friend_score_set.h" @@ -37,11 +37,11 @@ #include "ballistica/python/python.h" #if BA_HEADLESS_BUILD -#include "ballistica/app/headless_app.h" +#include "ballistica/app/app_flavor_headless.h" #endif #if BA_VR_BUILD -#include "ballistica/app/vr_app.h" +#include "ballistica/app/app_flavor_vr.h" #endif // ------------------------- PLATFORM SELECTION -------------------------------- @@ -427,12 +427,12 @@ auto Platform::GetErrnoString() -> std::string { // This does not vary across versions. auto Platform::GetConfigDirectory() -> std::string { // Make sure args have been handled since we use them. - assert(g_app_globals->args_handled); + assert(g_app->args_handled); if (!have_config_dir_) { // If the user provided cfgdir as an arg. - if (!g_app_globals->user_config_dir.empty()) { - config_dir_ = g_app_globals->user_config_dir; + if (!g_app->user_config_dir.empty()) { + config_dir_ = g_app->user_config_dir; } else { config_dir_ = GetDefaultConfigDirectory(); } @@ -555,7 +555,7 @@ static void Init() { } } - g_app_globals->user_agent_string = g_platform->GetUserAgentString(); + g_app->user_agent_string = g_platform->GetUserAgentString(); // Figure out where our data is and chdir there. g_platform->SetupDataDirectory(); @@ -570,8 +570,8 @@ static void Init() { #pragma ide diagnostic ignored "NullDereferences" static void HandleArgs(int argc, char** argv) { - assert(!g_app_globals->args_handled); - g_app_globals->args_handled = true; + assert(!g_app->args_handled); + g_app->args_handled = true; // If there's just one arg and it's "--version", return the version. if (argc == 2 && !strcmp(argv[1], "--version")) { @@ -583,10 +583,10 @@ static void HandleArgs(int argc, char** argv) { for (int i = 1; i < argc; ++i) { // In our rift build, a '-2d' arg causes us to run in regular 2d mode. if (g_buildconfig.rift_build() && !strcmp(argv[i], "-2d")) { - g_app_globals->vr_mode = false; + g_app->vr_mode = false; } else if (!strcmp(argv[i], "-exec")) { if (i + 1 < argc) { - g_app_globals->exec_command = argv[i + 1]; + g_app->exec_command = argv[i + 1]; } else { printf("%s", "Error: expected arg after -exec\n"); fflush(stdout); @@ -604,11 +604,11 @@ static void HandleArgs(int argc, char** argv) { } } else if (!strcmp(argv[i], "-cfgdir")) { if (i + 1 < argc) { - g_app_globals->user_config_dir = argv[i + 1]; + g_app->user_config_dir = argv[i + 1]; // Need to convert this to an abs path since we chdir soon. bool success = - g_platform->AbsPath(argv[i + 1], &g_app_globals->user_config_dir); + g_platform->AbsPath(argv[i + 1], &g_app->user_config_dir); if (!success) { // This can fail if the path doesn't exist. if (!g_platform->FilePathExists(argv[i + 1])) { @@ -632,24 +632,24 @@ static void HandleArgs(int argc, char** argv) { // In Android's case we have to pull our exec arg from the java/kotlin layer. if (g_buildconfig.ostype_android()) { - g_app_globals->exec_command = g_platform->GetAndroidExecArg(); + g_app->exec_command = g_platform->GetAndroidExecArg(); } // TEMP/HACK: hard code launch args. if (explicit_bool(false)) { if (g_buildconfig.ostype_android()) { - g_app_globals->exec_command = - "import ba.internal; ba.internal.run_stress_test()"; + g_app->exec_command = "import ba.internal; ba.internal.run_stress_test()"; } } } -void Platform::CreateApp() { - assert(g_app_globals); +auto Platform::CreateAppFlavor() -> AppFlavor* { + assert(g_app); assert(InMainThread()); + assert(g_main_thread); // Hmm do these belong here?... - HandleArgs(g_app_globals->argc, g_app_globals->argv); + HandleArgs(g_app->argc, g_app->argv); Init(); // TEMP - need to init sdl on our legacy mac build even though its not @@ -659,24 +659,21 @@ void Platform::CreateApp() { #endif #if BA_HEADLESS_BUILD - new HeadlessApp(g_main_thread); + return new AppFlavorHeadless(g_main_thread); #elif BA_RIFT_BUILD // Rift build can spin up in either VR or regular mode. - if (g_app_globals->vr_mode) { - new VRApp(g_main_thread); + if (g_app->vr_mode) { + return new AppFlavorVR(g_main_thread); } else { - new SDLApp(g_main_thread); + return new SDLApp(g_main_thread); } #elif BA_CARDBOARD_BUILD - new VRApp(g_main_thread); + return new AppFlavorVR(g_main_thread); #elif BA_SDL_BUILD - new SDLApp(g_main_thread); + return new SDLApp(g_main_thread); #else - new App(g_main_thread); + return new AppFlavor(g_main_thread); #endif - - // Let app do any init it needs to after it is fully constructed. - g_app->PostInit(); } auto Platform::CreateGraphics() -> Graphics* { @@ -702,7 +699,7 @@ auto Platform::GetKeyName(int keycode) -> std::string { void Platform::CreateAuxiliaryModules() { #if !BA_HEADLESS_BUILD auto* bg_dynamics_thread = new Thread(ThreadIdentifier::kBGDynamics); - g_app_globals->pausable_threads.push_back(bg_dynamics_thread); + g_app->pausable_threads.push_back(bg_dynamics_thread); #endif #if !BA_HEADLESS_BUILD bg_dynamics_thread->PushCallSynchronous( @@ -1096,7 +1093,7 @@ void Platform::SetHardwareCursorVisible(bool visible) { #endif } -void Platform::QuitApp() { exit(g_app_globals->return_value); } +void Platform::QuitApp() { exit(g_app->return_value); } void Platform::GetScoresToBeat(const std::string& level, const std::string& config, void* py_callback) { diff --git a/src/ballistica/platform/platform.h b/src/ballistica/platform/platform.h index 13c81e0a..f1596019 100644 --- a/src/ballistica/platform/platform.h +++ b/src/ballistica/platform/platform.h @@ -49,7 +49,7 @@ class Platform { virtual auto PostInit() -> void; /// Create the proper App module and add it to the main_thread. - auto CreateApp() -> void; + auto CreateAppFlavor() -> AppFlavor*; /// Create the appropriate Graphics subclass for the app. auto CreateGraphics() -> Graphics*; diff --git a/src/ballistica/platform/sdl/sdl_app.cc b/src/ballistica/platform/sdl/sdl_app.cc index c7909201..589723ea 100644 --- a/src/ballistica/platform/sdl/sdl_app.cc +++ b/src/ballistica/platform/sdl/sdl_app.cc @@ -232,8 +232,8 @@ void SDLApp::HandleSDLEvent(const SDL_Event& event) { auto FilterSDLEvent(const SDL_Event* event) -> int { try { // If this event is coming from this thread, handle it immediately. - if (std::this_thread::get_id() == g_app_globals->main_thread_id) { - auto app = static_cast_check_type(g_app); + if (std::this_thread::get_id() == g_app->main_thread_id) { + auto app = static_cast_check_type(g_app_flavor); assert(app); if (app) { app->HandleSDLEvent(*event); @@ -319,7 +319,7 @@ void SDLApp::InitSDL() { #endif } -SDLApp::SDLApp(Thread* thread) : App(thread) { +SDLApp::SDLApp(Thread* thread) : AppFlavor(thread) { InitSDL(); // If we're not running our own even loop, we set up a filter to intercept @@ -342,14 +342,14 @@ SDLApp::SDLApp(Thread* thread) : App(thread) { // thing, except that we're free to handle other matters concurrently // instead of being locked in a delay call. this->thread()->NewTimer(10, true, NewLambdaRunnable([this] { - assert(g_app); - g_app->RunEvents(); + assert(g_app_flavor); + g_app_flavor->RunEvents(); })); } } void SDLApp::RunEvents() { - App::RunEvents(); + AppFlavor::RunEvents(); // Now run all pending SDL events until we run out or we're told to quit. SDL_Event event; @@ -359,7 +359,7 @@ void SDLApp::RunEvents() { } void SDLApp::DidFinishRenderingFrame(FrameDef* frame) { - App::DidFinishRenderingFrame(frame); + AppFlavor::DidFinishRenderingFrame(frame); SwapBuffers(); } @@ -489,7 +489,7 @@ void SDLApp::SetAutoVSync(bool enable) { } void SDLApp::OnBootstrapComplete() { - App::OnBootstrapComplete(); + AppFlavor::OnBootstrapComplete(); if (!HeadlessMode() && g_buildconfig.enable_sdl_joysticks()) { // Add initial sdl joysticks. any added/removed after this will be handled @@ -513,7 +513,7 @@ void SDLApp::SDLJoystickConnected(int device_index) { // We add all existing inputs when bootstrapping is complete; we should // never be getting these before that happens. - if (g_input == nullptr || g_app == nullptr || !IsBootstrapped()) { + if (g_input == nullptr || g_app_flavor == nullptr || !IsBootstrapped()) { Log("Unexpected SDLJoystickConnected early in boot sequence."); return; } diff --git a/src/ballistica/platform/sdl/sdl_app.h b/src/ballistica/platform/sdl/sdl_app.h index 4d2fa085..9215f266 100644 --- a/src/ballistica/platform/sdl/sdl_app.h +++ b/src/ballistica/platform/sdl/sdl_app.h @@ -7,12 +7,12 @@ #include -#include "ballistica/app/app.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/math/vector2f.h" namespace ballistica { -class SDLApp : public App { +class SDLApp : public AppFlavor { public: static auto InitSDL() -> void; explicit SDLApp(Thread* thread); @@ -24,11 +24,12 @@ class SDLApp : public App { static auto SDLJoystickDisconnected(int index) -> void; auto OnBootstrapComplete() -> void override; - /// Return g_app as a SDLApp. (assumes it actually is one). + /// Return g_app_flavor as a SDLApp. (assumes it actually is one). static SDLApp* get() { - assert(g_app != nullptr); - assert(dynamic_cast(g_app) == static_cast(g_app)); - return static_cast(g_app); + assert(g_app_flavor != nullptr); + assert(dynamic_cast(g_app_flavor) + == static_cast(g_app_flavor)); + return static_cast(g_app_flavor); } auto SetInitialScreenDimensions(const Vector2f& dimensions) -> void; diff --git a/src/ballistica/python/methods/python_methods_app.cc b/src/ballistica/python/methods/python_methods_app.cc index cd187454..2b2fa725 100644 --- a/src/ballistica/python/methods/python_methods_app.cc +++ b/src/ballistica/python/methods/python_methods_app.cc @@ -3,7 +3,7 @@ #include "ballistica/python/methods/python_methods_app.h" #include "ballistica/app/app.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/core/logging.h" #include "ballistica/game/connection/connection_set.h" #include "ballistica/game/game_stream.h" @@ -764,7 +764,7 @@ auto PyEnv(PyObject* self) -> PyObject* { "build_number", kAppBuildNumber, "config_file_path", config_path.c_str(), "locale", g_platform->GetLocale().c_str(), - "user_agent_string", g_app_globals->user_agent_string.c_str(), + "user_agent_string", g_app->user_agent_string.c_str(), "version", kAppVersion, "debug_build", is_debug_build_obj, "test_build", is_test_build_obj, @@ -800,7 +800,8 @@ auto PySetStressTesting(PyObject* self, PyObject* args) -> PyObject* { if (!PyArg_ParseTuple(args, "pi", &testing, &player_count)) { return nullptr; } - g_app->PushSetStressTestingCall(static_cast(testing), player_count); + g_app_flavor->PushSetStressTestingCall(static_cast(testing), + player_count); Py_RETURN_NONE; BA_PYTHON_CATCH; } diff --git a/src/ballistica/python/methods/python_methods_gameplay.cc b/src/ballistica/python/methods/python_methods_gameplay.cc index 9786c7e4..8b59b903 100644 --- a/src/ballistica/python/methods/python_methods_gameplay.cc +++ b/src/ballistica/python/methods/python_methods_gameplay.cc @@ -4,7 +4,7 @@ #include -#include "ballistica/app/app.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/dynamics/bg/bg_dynamics.h" #include "ballistica/dynamics/collision.h" #include "ballistica/dynamics/dynamics.h" @@ -505,7 +505,7 @@ auto PyGetScoresToBeat(PyObject* self, PyObject* args, PyObject* keywds) // Allocate a Call object for this and pass its pointer to the main thread; // we'll ref/de-ref it when it comes back. auto* call = Object::NewDeferred(callback_obj); - g_app->PushGetScoresToBeatCall(level, config, call); + g_app_flavor->PushGetScoresToBeatCall(level, config, call); Py_RETURN_NONE; BA_PYTHON_CATCH; } diff --git a/src/ballistica/python/methods/python_methods_input.cc b/src/ballistica/python/methods/python_methods_input.cc index 6d7343f8..c03bf5b4 100644 --- a/src/ballistica/python/methods/python_methods_input.cc +++ b/src/ballistica/python/methods/python_methods_input.cc @@ -2,7 +2,7 @@ #include "ballistica/python/methods/python_methods_input.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/game.h" #include "ballistica/input/device/input_device.h" #include "ballistica/input/device/touch_input.h" @@ -33,7 +33,7 @@ auto PyGetConfigurableGamePads(PyObject* self, PyObject* args) -> PyObject* { auto PyHaveTouchScreenInput(PyObject* self, PyObject* args) -> PyObject* { BA_PYTHON_TRY; - if (g_app_globals->touch_input) { + if (g_app->touch_input) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; @@ -47,8 +47,8 @@ auto PySetTouchscreenEditing(PyObject* self, PyObject* args) -> PyObject* { if (!PyArg_ParseTuple(args, "p", &editing)) { return nullptr; } - if (g_app_globals->touch_input) { - g_app_globals->touch_input->set_editing(static_cast(editing)); + if (g_app->touch_input) { + g_app->touch_input->set_editing(static_cast(editing)); } Py_RETURN_NONE; BA_PYTHON_CATCH; diff --git a/src/ballistica/python/methods/python_methods_networking.cc b/src/ballistica/python/methods/python_methods_networking.cc index 148286c9..8066dfd5 100644 --- a/src/ballistica/python/methods/python_methods_networking.cc +++ b/src/ballistica/python/methods/python_methods_networking.cc @@ -2,7 +2,7 @@ #include "ballistica/python/methods/python_methods_networking.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/game/connection/connection_set.h" #include "ballistica/game/connection/connection_to_client.h" #include "ballistica/game/connection/connection_to_host.h" @@ -328,7 +328,7 @@ auto PySetMasterServerSource(PyObject* self, PyObject* args) -> PyObject* { + "."); source = 1; } - g_app_globals->master_server_source = source; + g_app->master_server_source = source; Py_RETURN_NONE; BA_PYTHON_CATCH; } @@ -343,8 +343,8 @@ auto PySetTelnetAccessEnabled(PyObject* self, PyObject* args, PyObject* keywds) const_cast(kwlist), &enable)) { return nullptr; } - if (g_app_globals->telnet_server) { - g_app_globals->telnet_server->SetAccessEnabled(static_cast(enable)); + if (g_app->telnet_server) { + g_app->telnet_server->SetAccessEnabled(static_cast(enable)); } else { throw Exception("Telnet server not enabled."); } diff --git a/src/ballistica/python/methods/python_methods_system.cc b/src/ballistica/python/methods/python_methods_system.cc index 42f9fca9..4081c087 100644 --- a/src/ballistica/python/methods/python_methods_system.cc +++ b/src/ballistica/python/methods/python_methods_system.cc @@ -7,7 +7,7 @@ #include "ballistica/app/app.h" #include "ballistica/app/app_config.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/game/game_stream.h" #include "ballistica/game/host_activity.h" #include "ballistica/game/session/host_session.h" @@ -76,10 +76,10 @@ auto PyIsRunningOnOuya(PyObject* self, PyObject* args) -> PyObject* { auto PySetUpSigInt(PyObject* self) -> PyObject* { BA_PYTHON_TRY; - if (g_app) { + if (g_app_flavor) { g_platform->SetupInterruptHandling(); } else { - Log("SigInt handler called before g_app exists."); + Log("SigInt handler called before g_app_flavor exists."); } Py_RETURN_NONE; BA_PYTHON_CATCH; @@ -186,9 +186,8 @@ auto PyExtraHashValue(PyObject* self, PyObject* args, PyObject* keywds) return nullptr; } const char* h = - ((g_app_globals->user_ran_commands || g_app_globals->workspaces_in_use) - ? "cjief3l" - : "wofocj8"); + ((g_app->user_ran_commands || g_app->workspaces_in_use) ? "cjief3l" + : "wofocj8"); return PyUnicode_FromString(h); BA_PYTHON_CATCH; } @@ -202,7 +201,7 @@ auto PyGetIdleTime(PyObject* self, PyObject* args) -> PyObject* { auto PyHasUserRunCommands(PyObject* self, PyObject* args) -> PyObject* { BA_PYTHON_TRY; - if (g_app_globals->user_ran_commands) { + if (g_app->user_ran_commands) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -211,7 +210,7 @@ auto PyHasUserRunCommands(PyObject* self, PyObject* args) -> PyObject* { auto PyWorkspacesInUse(PyObject* self, PyObject* args) -> PyObject* { BA_PYTHON_TRY; - if (g_app_globals->workspaces_in_use) { + if (g_app->workspaces_in_use) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -257,33 +256,31 @@ auto PyValueTest(PyObject* self, PyObject* args, PyObject* keywds) double return_val = 0.0f; if (!strcmp(arg, "bufferTime")) { if (have_change) { - g_app_globals->buffer_time += static_cast(change); + g_app->buffer_time += static_cast(change); } if (have_absolute) { - g_app_globals->buffer_time = static_cast(absolute); + g_app->buffer_time = static_cast(absolute); } - g_app_globals->buffer_time = std::max(0, g_app_globals->buffer_time); - return_val = g_app_globals->buffer_time; + g_app->buffer_time = std::max(0, g_app->buffer_time); + return_val = g_app->buffer_time; } else if (!strcmp(arg, "delaySampling")) { if (have_change) { - g_app_globals->delay_bucket_samples += static_cast(change); + g_app->delay_bucket_samples += static_cast(change); } if (have_absolute) { - g_app_globals->buffer_time = static_cast(absolute); + g_app->buffer_time = static_cast(absolute); } - g_app_globals->delay_bucket_samples = - std::max(1, g_app_globals->delay_bucket_samples); - return_val = g_app_globals->delay_bucket_samples; + g_app->delay_bucket_samples = std::max(1, g_app->delay_bucket_samples); + return_val = g_app->delay_bucket_samples; } else if (!strcmp(arg, "dynamicsSyncTime")) { if (have_change) { - g_app_globals->dynamics_sync_time += static_cast(change); + g_app->dynamics_sync_time += static_cast(change); } if (have_absolute) { - g_app_globals->dynamics_sync_time = static_cast(absolute); + g_app->dynamics_sync_time = static_cast(absolute); } - g_app_globals->dynamics_sync_time = - std::max(0, g_app_globals->dynamics_sync_time); - return_val = g_app_globals->dynamics_sync_time; + g_app->dynamics_sync_time = std::max(0, g_app->dynamics_sync_time); + return_val = g_app->dynamics_sync_time; } else if (!strcmp(arg, "showNetInfo")) { if (have_change && change > 0.5f) { g_graphics->set_show_net_info(true); @@ -524,7 +521,7 @@ auto PyGetVolatileDataDirectory(PyObject* self, PyObject* args) -> PyObject* { auto PyIsLogFull(PyObject* self, PyObject* args) -> PyObject* { BA_PYTHON_TRY; - if (g_app_globals->log_full) { + if (g_app->log_full) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -535,8 +532,8 @@ auto PyGetLog(PyObject* self, PyObject* args, PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; std::string log_fin; { - std::scoped_lock lock(g_app_globals->log_mutex); - log_fin = g_app_globals->log; + std::scoped_lock lock(g_app->log_mutex); + log_fin = g_app->log; } // we want to use something with error handling here since the last // bit of this string could be truncated utf8 chars.. @@ -549,7 +546,7 @@ auto PyMarkLogSent(PyObject* self, PyObject* args, PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; // this way we won't try to send it at shutdown time and whatnot - g_app_globals->put_log = true; + g_app->put_log = true; Py_RETURN_NONE; BA_PYTHON_CATCH; } diff --git a/src/ballistica/python/methods/python_methods_ui.cc b/src/ballistica/python/methods/python_methods_ui.cc index 4196edb6..71b2dedc 100644 --- a/src/ballistica/python/methods/python_methods_ui.cc +++ b/src/ballistica/python/methods/python_methods_ui.cc @@ -3,7 +3,7 @@ #include "ballistica/python/methods/python_methods_ui.h" #include "ballistica/app/app.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/game/account.h" #include "ballistica/game/connection/connection_set.h" #include "ballistica/game/game.h" @@ -1872,7 +1872,7 @@ auto PyShowOnlineScoreUI(PyObject* self, PyObject* args, PyObject* keywds) if (game_version_obj != Py_None) { game_version = Python::GetPyString(game_version_obj); } - g_app->PushShowOnlineScoreUICall(show, game, game_version); + g_app_flavor->PushShowOnlineScoreUICall(show, game, game_version); Py_RETURN_NONE; BA_PYTHON_CATCH; } @@ -2102,7 +2102,7 @@ auto PyHaveIncentivizedAd(PyObject* self, PyObject* args, PyObject* keywds) const_cast(kwlist))) { return nullptr; } - if (g_app_globals->have_incentivized_ad) { + if (g_app->have_incentivized_ad) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; @@ -2163,8 +2163,8 @@ auto PyOpenURL(PyObject* self, PyObject* args, PyObject* keywds) -> PyObject* { const_cast(kwlist), &address)) { return nullptr; } - assert(g_app); - g_app->PushOpenURLCall(address); + assert(g_app_flavor); + g_app_flavor->PushOpenURLCall(address); Py_RETURN_NONE; BA_PYTHON_CATCH; } diff --git a/src/ballistica/python/python.cc b/src/ballistica/python/python.cc index 1a9c8e33..a2b0f7ba 100644 --- a/src/ballistica/python/python.cc +++ b/src/ballistica/python/python.cc @@ -2,7 +2,7 @@ #include "ballistica/python/python.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/audio/audio.h" #include "ballistica/core/thread.h" #include "ballistica/dynamics/material/material.h" @@ -889,6 +889,7 @@ static auto PyInit__ba() -> PyObject* { void Python::Reset(bool do_init) { assert(InLogicThread()); assert(g_python); + assert(g_platform); bool was_inited = inited_; @@ -2286,7 +2287,7 @@ void Python::LogContextAuto() { } void Python::AcquireGIL() { - auto debug_timing{g_app_globals->debug_timing}; + auto debug_timing{g_app->debug_timing}; millisecs_t startms{debug_timing ? Platform::GetCurrentMilliseconds() : 0}; if (thread_state_) { diff --git a/src/ballistica/scene/scene.cc b/src/ballistica/scene/scene.cc index 48d2d2cb..9bc1d71a 100644 --- a/src/ballistica/scene/scene.cc +++ b/src/ballistica/scene/scene.cc @@ -2,7 +2,7 @@ #include "ballistica/scene/scene.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/audio/audio.h" #include "ballistica/dynamics/bg/bg_dynamics.h" #include "ballistica/dynamics/dynamics.h" @@ -69,10 +69,10 @@ void Scene::Init() { TimeDisplayNode::InitType()}; int next_type_id = 0; - assert(g_app_globals != nullptr); + assert(g_app != nullptr); for (auto* t : node_types) { - g_app_globals->node_types[t->name()] = t; - g_app_globals->node_types_by_id[next_type_id] = t; + g_app->node_types[t->name()] = t; + g_app->node_types_by_id[next_type_id] = t; t->set_id(next_type_id++); } @@ -97,13 +97,13 @@ void Scene::Init() { void Scene::SetupNodeMessageType(const std::string& name, NodeMessageType val, const std::string& format) { - assert(g_app_globals != nullptr); - g_app_globals->node_message_types[name] = val; + assert(g_app != nullptr); + g_app->node_message_types[name] = val; assert(static_cast(val) >= 0); - if (g_app_globals->node_message_formats.size() <= static_cast(val)) { - g_app_globals->node_message_formats.resize(static_cast(val) + 1); + if (g_app->node_message_formats.size() <= static_cast(val)) { + g_app->node_message_formats.resize(static_cast(val) + 1); } - g_app_globals->node_message_formats[static_cast(val)] = format; + g_app->node_message_formats[static_cast(val)] = format; } auto Scene::GetGameStream() const -> GameStream* { @@ -191,17 +191,17 @@ void Scene::Draw(FrameDef* frame_def) { } auto Scene::GetNodeMessageType(const std::string& type) -> NodeMessageType { - assert(g_app_globals != nullptr); - auto i = g_app_globals->node_message_types.find(type); - if (i == g_app_globals->node_message_types.end()) { + assert(g_app != nullptr); + auto i = g_app->node_message_types.find(type); + if (i == g_app->node_message_types.end()) { throw Exception("Invalid node-message type: '" + type + "'"); } return i->second; } auto Scene::GetNodeMessageTypeName(NodeMessageType t) -> std::string { - assert(g_app_globals != nullptr); - for (auto&& i : g_app_globals->node_message_types) { + assert(g_app != nullptr); + for (auto&& i : g_app->node_message_types) { if (i.second == t) { return i.first; } @@ -335,11 +335,11 @@ void Scene::LanguageChanged() { } auto Scene::GetNodeMessageFormat(NodeMessageType type) -> const char* { - assert(g_app_globals != nullptr); - if ((unsigned int)type >= g_app_globals->node_message_formats.size()) { + assert(g_app != nullptr); + if ((unsigned int)type >= g_app->node_message_formats.size()) { return nullptr; } - return g_app_globals->node_message_formats[static_cast(type)].c_str(); + return g_app->node_message_formats[static_cast(type)].c_str(); } auto Scene::NewNode(const std::string& type_string, const std::string& name, @@ -359,9 +359,9 @@ auto Scene::NewNode(const std::string& type_string, const std::string& name, // Should never change the scene while we're stepping it. assert(!in_step_); - assert(g_app_globals != nullptr); - auto i = g_app_globals->node_types.find(type_string); - if (i == g_app_globals->node_types.end()) { + assert(g_app != nullptr); + auto i = g_app->node_types.find(type_string); + if (i == g_app->node_types.end()) { throw Exception("Invalid node type: '" + type_string + "'"); } auto node = Object::MakeRefCounted(i->second->Create(this)); diff --git a/src/ballistica/ui/console.cc b/src/ballistica/ui/console.cc index 1dbd692f..cc9ffc5a 100644 --- a/src/ballistica/ui/console.cc +++ b/src/ballistica/ui/console.cc @@ -2,7 +2,7 @@ #include "ballistica/ui/console.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/audio/audio.h" #include "ballistica/game/game.h" #include "ballistica/generic/utils.h" @@ -36,9 +36,9 @@ Console::Console() { prompt_text_group_.SetText(">"); // Print whatever is already in the log. - if (!g_app_globals->console_startup_messages.empty()) { - Print(g_app_globals->console_startup_messages); - g_app_globals->console_startup_messages = ""; + if (!g_app->console_startup_messages.empty()) { + Print(g_app->console_startup_messages); + g_app->console_startup_messages = ""; } } diff --git a/src/ballistica/ui/ui.cc b/src/ballistica/ui/ui.cc index 29c5a1c1..967a96a9 100644 --- a/src/ballistica/ui/ui.cc +++ b/src/ballistica/ui/ui.cc @@ -2,7 +2,7 @@ #include "ballistica/ui/ui.h" -#include "ballistica/app/app_globals.h" +#include "ballistica/app/app.h" #include "ballistica/audio/audio.h" #include "ballistica/generic/lambda_runnable.h" #include "ballistica/graphics/component/empty_component.h" diff --git a/src/ballistica/ui/widget/text_widget.cc b/src/ballistica/ui/widget/text_widget.cc index 0d7b510b..064d3323 100644 --- a/src/ballistica/ui/widget/text_widget.cc +++ b/src/ballistica/ui/widget/text_widget.cc @@ -2,7 +2,7 @@ #include "ballistica/ui/widget/text_widget.h" -#include "ballistica/app/app.h" +#include "ballistica/app/app_flavor.h" #include "ballistica/audio/audio.h" #include "ballistica/game/game.h" #include "ballistica/generic/utils.h" @@ -547,7 +547,7 @@ void TextWidget::BringUpEditDialog() { use_internal_dialog = false; // store ourself as the current text-widget and kick off an edit android_string_edit_widget_ = this; - g_app->PushStringEditCall(description_, text_raw_, max_chars_); + g_app_flavor->PushStringEditCall(description_, text_raw_, max_chars_); } } }