renamed App to AppFlavor and AppGlobals to App

This commit is contained in:
Eric 2022-09-09 23:13:32 -07:00
parent 5ccaad64d6
commit 91d9142b60
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
64 changed files with 1075 additions and 1083 deletions

View File

@ -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"
}

View File

@ -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.

View File

@ -1 +1 @@
265405600297036989512577170988205019181
64954916459680243860176377055051806996

View File

@ -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(

View File

@ -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

View File

@ -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" />

View File

@ -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>

View File

@ -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" />

View File

@ -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>

View File

@ -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

View File

@ -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

View 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

View 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_

View File

@ -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();
}));
}

View 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_

View File

@ -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;
}

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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_

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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.

View File

@ -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);

View File

@ -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) {}

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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_) {

View File

@ -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();

View File

@ -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"

View File

@ -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_);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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"

View File

@ -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()) {

View File

@ -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) {

View File

@ -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*;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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.");
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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_) {

View File

@ -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));

View File

@ -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 = "";
}
}

View File

@ -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"

View File

@ -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_);
}
}
}