mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-24 16:06:51 +08:00
renamed App to AppFlavor and AppGlobals to App
This commit is contained in:
parent
5ccaad64d6
commit
91d9142b60
@ -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"
|
||||
}
|
||||
@ -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.
|
||||
|
||||
@ -1 +1 @@
|
||||
265405600297036989512577170988205019181
|
||||
64954916459680243860176377055051806996
|
||||
@ -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(
|
||||
|
||||
@ -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
|
||||
|
||||
@ -193,14 +193,14 @@
|
||||
<ClInclude Include="..\..\src\ballistica\app\app.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_config.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_config.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_globals.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_globals.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\headless_app.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\headless_app.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor_headless.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor_headless.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor_vr.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor_vr.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\stress_test.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\stress_test.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\vr_app.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\vr_app.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\audio\al_sys.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\audio\al_sys.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\audio\audio.cc" />
|
||||
|
||||
@ -13,16 +13,22 @@
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_config.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_globals.cc">
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor.cc">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_globals.h">
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\headless_app.cc">
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor_headless.cc">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\app\headless_app.h">
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor_headless.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor_vr.cc">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor_vr.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\stress_test.cc">
|
||||
@ -31,12 +37,6 @@
|
||||
<ClInclude Include="..\..\src\ballistica\app\stress_test.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\vr_app.cc">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\app\vr_app.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\audio\al_sys.cc">
|
||||
<Filter>ballistica\audio</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@ -188,14 +188,14 @@
|
||||
<ClInclude Include="..\..\src\ballistica\app\app.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_config.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_config.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_globals.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_globals.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\headless_app.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\headless_app.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor_headless.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor_headless.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor_vr.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor_vr.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\stress_test.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\stress_test.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\app\vr_app.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\app\vr_app.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\audio\al_sys.cc" />
|
||||
<ClInclude Include="..\..\src\ballistica\audio\al_sys.h" />
|
||||
<ClCompile Include="..\..\src\ballistica\audio\audio.cc" />
|
||||
|
||||
@ -13,16 +13,22 @@
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_config.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_globals.cc">
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor.cc">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_globals.h">
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\headless_app.cc">
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor_headless.cc">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\app\headless_app.h">
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor_headless.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\app_flavor_vr.cc">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\app\app_flavor_vr.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\stress_test.cc">
|
||||
@ -31,12 +37,6 @@
|
||||
<ClInclude Include="..\..\src\ballistica\app\stress_test.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\app\vr_app.cc">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ballistica\app\vr_app.h">
|
||||
<Filter>ballistica\app</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ballistica\audio\al_sys.cc">
|
||||
<Filter>ballistica\audio</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@ -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 <cstring>
|
||||
|
||||
namespace ballistica {
|
||||
|
||||
App::App(Thread* thread)
|
||||
: thread_(thread), stress_test_(std::make_unique<StressTest>()) {
|
||||
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
|
||||
|
||||
@ -3,144 +3,90 @@
|
||||
#ifndef BALLISTICA_APP_APP_H_
|
||||
#define BALLISTICA_APP_APP_H_
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#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<std::string, NodeType*> node_types;
|
||||
std::unordered_map<int, NodeType*> node_types_by_id;
|
||||
std::unordered_map<std::string, NodeMessageType> node_message_types;
|
||||
std::vector<std::string> node_message_formats;
|
||||
bool workspaces_in_use{};
|
||||
bool replay_open{};
|
||||
std::vector<Thread*> 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<StressTest> stress_test_;
|
||||
millisecs_t last_resize_draw_event_time_{};
|
||||
millisecs_t last_app_resume_time_{};
|
||||
std::unordered_map<std::string, std::string> 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<std::thread::id, std::string> thread_name_map;
|
||||
#if BA_DEBUG_BUILD
|
||||
std::mutex object_list_mutex;
|
||||
Object* object_list_first{};
|
||||
int object_count{0};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace ballistica
|
||||
|
||||
395
src/ballistica/app/app_flavor.cc
Normal file
395
src/ballistica/app/app_flavor.cc
Normal file
@ -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<StressTest>()) {
|
||||
// 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
|
||||
147
src/ballistica/app/app_flavor.h
Normal file
147
src/ballistica/app/app_flavor.h
Normal file
@ -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 <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#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<StressTest> stress_test_;
|
||||
millisecs_t last_resize_draw_event_time_{};
|
||||
millisecs_t last_app_resume_time_{};
|
||||
std::unordered_map<std::string, std::string> product_prices_;
|
||||
std::mutex product_prices_mutex_;
|
||||
};
|
||||
|
||||
} // namespace ballistica
|
||||
|
||||
#endif // BALLISTICA_APP_APP_FLAVOR_H_
|
||||
@ -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();
|
||||
}));
|
||||
}
|
||||
|
||||
20
src/ballistica/app/app_flavor_headless.h
Normal file
20
src/ballistica/app/app_flavor_headless.h
Normal file
@ -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_
|
||||
@ -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;
|
||||
}
|
||||
@ -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<VRApp*>(g_app) == static_cast<VRApp*>(g_app));
|
||||
return static_cast<VRApp*>(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<AppFlavorVR*>(g_app_flavor)
|
||||
== static_cast<AppFlavorVR*>(g_app_flavor));
|
||||
return static_cast<AppFlavorVR*>(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_
|
||||
@ -1,18 +0,0 @@
|
||||
// Released under the MIT License. See LICENSE for details.
|
||||
|
||||
#include "ballistica/app/app_globals.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
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
|
||||
@ -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 <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#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<std::string, NodeType*> node_types;
|
||||
std::unordered_map<int, NodeType*> node_types_by_id;
|
||||
std::unordered_map<std::string, NodeMessageType> node_message_types;
|
||||
std::vector<std::string> node_message_formats;
|
||||
bool workspaces_in_use{};
|
||||
bool replay_open{};
|
||||
std::vector<Thread*> 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<std::thread::id, std::string> 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_
|
||||
@ -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_
|
||||
@ -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"
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#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
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#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<max log size reached>\n";
|
||||
g_app_globals->log_full = true;
|
||||
g_app->log += "\n<max log size reached>\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);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#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) {
|
||||
|
||||
@ -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>& 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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, "<in-game-console>");
|
||||
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, "<stdin>");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<int>(
|
||||
g_app_globals->node_types_by_id.size())) {
|
||||
|| vals[1] >= static_cast<int>(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.
|
||||
|
||||
@ -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<int>(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<float>(bucket.max_delay_from_projection);
|
||||
|
||||
@ -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) {}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#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<decltype(g_app_globals)>()
|
||||
== "ballistica::AppGlobals *"
|
||||
|| static_type_name_constexpr<decltype(g_app_globals)>()
|
||||
== "ballistica::AppGlobals*"
|
||||
|| static_type_name_constexpr<decltype(g_app_globals)>()
|
||||
== "class ballistica::AppGlobals*"
|
||||
|| static_type_name_constexpr<decltype(g_app_globals)>()
|
||||
== "AppGlobals*");
|
||||
static_assert(
|
||||
static_type_name_constexpr<decltype(g_app)>() == "ballistica::App *"
|
||||
|| static_type_name_constexpr<decltype(g_app)>() == "ballistica::App*"
|
||||
|| static_type_name_constexpr<decltype(g_app)>()
|
||||
== "class ballistica::App*"
|
||||
|| static_type_name_constexpr<decltype(g_app)>() == "App*");
|
||||
Object::Ref<Node> testnode{};
|
||||
static_assert(
|
||||
static_type_name_constexpr<decltype(testnode)>()
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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<SDLApp*>(g_app)) {
|
||||
if (auto app = dynamic_cast<SDLApp*>(g_app_flavor)) {
|
||||
v_sync_ = sync;
|
||||
auto_vsync_ = auto_sync;
|
||||
if (gl_context_) {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
#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<int>(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_);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#include <cstring>
|
||||
#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);
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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, "<telnet>");
|
||||
if (cmd.CanEval()) {
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#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) {
|
||||
|
||||
@ -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*;
|
||||
|
||||
@ -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<SDLApp*>(g_app);
|
||||
if (std::this_thread::get_id() == g_app->main_thread_id) {
|
||||
auto app = static_cast_check_type<SDLApp*>(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;
|
||||
}
|
||||
|
||||
@ -7,12 +7,12 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#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<SDLApp*>(g_app) == static_cast<SDLApp*>(g_app));
|
||||
return static_cast<SDLApp*>(g_app);
|
||||
assert(g_app_flavor != nullptr);
|
||||
assert(dynamic_cast<SDLApp*>(g_app_flavor)
|
||||
== static_cast<SDLApp*>(g_app_flavor));
|
||||
return static_cast<SDLApp*>(g_app_flavor);
|
||||
}
|
||||
auto SetInitialScreenDimensions(const Vector2f& dimensions) -> void;
|
||||
|
||||
|
||||
@ -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<bool>(testing), player_count);
|
||||
g_app_flavor->PushSetStressTestingCall(static_cast<bool>(testing),
|
||||
player_count);
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
#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<PythonContextCall>(callback_obj);
|
||||
g_app->PushGetScoresToBeatCall(level, config, call);
|
||||
g_app_flavor->PushGetScoresToBeatCall(level, config, call);
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
@ -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<bool>(editing));
|
||||
if (g_app->touch_input) {
|
||||
g_app->touch_input->set_editing(static_cast<bool>(editing));
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
|
||||
@ -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<char**>(kwlist), &enable)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (g_app_globals->telnet_server) {
|
||||
g_app_globals->telnet_server->SetAccessEnabled(static_cast<bool>(enable));
|
||||
if (g_app->telnet_server) {
|
||||
g_app->telnet_server->SetAccessEnabled(static_cast<bool>(enable));
|
||||
} else {
|
||||
throw Exception("Telnet server not enabled.");
|
||||
}
|
||||
|
||||
@ -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<int>(change);
|
||||
g_app->buffer_time += static_cast<int>(change);
|
||||
}
|
||||
if (have_absolute) {
|
||||
g_app_globals->buffer_time = static_cast<int>(absolute);
|
||||
g_app->buffer_time = static_cast<int>(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<int>(change);
|
||||
g_app->delay_bucket_samples += static_cast<int>(change);
|
||||
}
|
||||
if (have_absolute) {
|
||||
g_app_globals->buffer_time = static_cast<int>(absolute);
|
||||
g_app->buffer_time = static_cast<int>(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<int>(change);
|
||||
g_app->dynamics_sync_time += static_cast<int>(change);
|
||||
}
|
||||
if (have_absolute) {
|
||||
g_app_globals->dynamics_sync_time = static_cast<int>(absolute);
|
||||
g_app->dynamics_sync_time = static_cast<int>(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;
|
||||
}
|
||||
|
||||
@ -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<char**>(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<char**>(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;
|
||||
}
|
||||
|
||||
@ -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_) {
|
||||
|
||||
@ -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<int>(val) >= 0);
|
||||
if (g_app_globals->node_message_formats.size() <= static_cast<size_t>(val)) {
|
||||
g_app_globals->node_message_formats.resize(static_cast<size_t>(val) + 1);
|
||||
if (g_app->node_message_formats.size() <= static_cast<size_t>(val)) {
|
||||
g_app->node_message_formats.resize(static_cast<size_t>(val) + 1);
|
||||
}
|
||||
g_app_globals->node_message_formats[static_cast<size_t>(val)] = format;
|
||||
g_app->node_message_formats[static_cast<size_t>(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<int>(type)].c_str();
|
||||
return g_app->node_message_formats[static_cast<int>(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<Node>(i->second->Create(this));
|
||||
|
||||
@ -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 = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user