wired stress testing back up and other polishing

This commit is contained in:
Eric 2023-10-31 12:09:33 -07:00
parent d35f479f82
commit 113be18416
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
51 changed files with 1001 additions and 858 deletions

94
.efrocachemap generated
View File

@ -421,7 +421,7 @@
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
"build/assets/ba_data/data/langdata.json": "b2fbc1751bd168470392de5370c196f4",
"build/assets/ba_data/data/langdata.json": "0b15d171ebcc56d324875b48436b58c2",
"build/assets/ba_data/data/languages/arabic.json": "c21378ee214a9dd0cb2971cd46b74374",
"build/assets/ba_data/data/languages/belarussian.json": "4d89ed5f9c615771d4fa2bb1834942d3",
"build/assets/ba_data/data/languages/chinese.json": "0a9d9534e7329d1e886adae6fdc007c4",
@ -440,7 +440,7 @@
"build/assets/ba_data/data/languages/hindi.json": "8ea0c58a44a24edb131d0e53b074d1f6",
"build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e",
"build/assets/ba_data/data/languages/indonesian.json": "d7f1cafecad05e0dcd34345e0088c4de",
"build/assets/ba_data/data/languages/italian.json": "b998195a8c5e745dca953ca54745a5f6",
"build/assets/ba_data/data/languages/italian.json": "e4acd4e58ef8db78f3369bf881f84c55",
"build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2",
"build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38",
"build/assets/ba_data/data/languages/persian.json": "4585070bd509600019ec8dc3bb47bfb8",
@ -454,7 +454,7 @@
"build/assets/ba_data/data/languages/swedish.json": "77d671f10613291ebf9c71da66f18a18",
"build/assets/ba_data/data/languages/tamil.json": "65ab7798d637fa62a703750179eeb723",
"build/assets/ba_data/data/languages/thai.json": "33f63753c9af9a5b238d229a0bf23fbc",
"build/assets/ba_data/data/languages/turkish.json": "776d1a0c9ef2333a9110d93558ab19e2",
"build/assets/ba_data/data/languages/turkish.json": "71fd6c59650c03164a94d884bc7e5263",
"build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2",
"build/assets/ba_data/data/languages/venetian.json": "9fe1a58d9e5dfb00f31ce3b2eb9993f4",
"build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba",
@ -4056,50 +4056,50 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "d81b7738fc395f6f926aabaee1920925",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "70d7de73a945afbe78f6ba94dd0fd78c",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "5ee9cf8e99fb9fbc6b80ef7fa6840be5",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "8eb65d8768f338c7188de404d584068f",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "4422950377f4194463b38533487b81df",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "3e85a676808245e0a279e2fb28fad8fc",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "50ac87225e3b4ac843d83fcec96ef542",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "ce8fedb78aac2ec288697fbace511d68",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "9db6948f77ff98d109e799d4d97266f7",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "517b1d6326879fd7ae1ad17d96e7c9ee",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b49b73a09460467bba983c301d33feb8",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "7b4741075224986c1776bc9e538b80cc",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f8a1e3030d6e9129f95ab5b7ea171134",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "615505f555b1ecf567ac00c1a71d4073",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "257f4ec71878b30f0a3619d8a5a278d8",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0d4a6355de77872b17b4ed2856cfd3e3",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e76d8896417d7c468b743f865f6d317a",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "1f7b66a5c7bf998f9d59fa28ef1a2dc5",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "a537bc369c09da6384a47e878b7dd11d",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "0b34b2bdfc77cb1f8c3968c16b304307",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "844bab8bf2324a35e4f71510fb4065f3",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "0320ab824c7b9271dfdd6361dcd51d82",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "844bab8bf2324a35e4f71510fb4065f3",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "0320ab824c7b9271dfdd6361dcd51d82",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "28ec03fb21247269ea16b7dc31cc37c9",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "80e61c0f2a2e665eaa6260b60ca92144",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "28ec03fb21247269ea16b7dc31cc37c9",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "80e61c0f2a2e665eaa6260b60ca92144",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "773c691b680d407f050d11a0814048cd",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "22158f39a92f54838ca05f38e7f635a9",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "773c691b680d407f050d11a0814048cd",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "22158f39a92f54838ca05f38e7f635a9",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "8d88b975df7ccff1af919ea738dcbc0f",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "f7de016cce83b57002b87f42575c2287",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "054de6792232f57d2ad4a5a81e5b7e5f",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "f7de016cce83b57002b87f42575c2287",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7f38979e847d5b3abef78acf83e41334",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "10ebbf27705f024b696c92db94d75506",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "287f846d6d424639348a02030f2bace9",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0a2987deb121f5eb044c220079c17d50",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "97b59f0376cc0bff65bc8f583127e62b",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c7421859bac7d02acb487784573cffd9",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "8e70dcb1e9c6a046473d2fec13796b76",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "104baba8083e75102f81c6e1c6b552b5",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ad6316e04f09de546d25171512f783b2",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "19495e4313121d5574ab69efcbbcedd7",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "d8f215de52d492ce1790d9e1714b4cec",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b057d6d9627c7400496080c48dd344cd",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "1bd60c4476b7471364be2534d3cb8185",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "011bceb35c7f53b98f2ab79798409679",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "0055dfac758acdeb5a39e436da5d71be",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "2daa69d1df9927e6fc17b0aabd5c62f6",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "2159ce4b648b1172e3d2f349e61f2b1b",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "26163f755e45586da35c1ed6499c0416",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "410c70d8d833458616a0056972e558c4",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6e4473952a022e30340b6decae9da58a",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "0c63291b5842dafcfae558ef3c36d35a",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "7195da4e4abae862f41c28764b35662b",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5a6ad8a9f0d5cd964661df32ac4efb47",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "376059ea5f812ace7629ad29a8d77a9a",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "7a0c87d9e673b28157845f71ff957df6",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "3603019e3dbf055c37f5fabbe9538c48",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "14f6e17cc5698341ed5607834107e608",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "679703f9ec7c6f9c0708c9b13c9c6c06",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "e4952c83427611c5a66a864d8bb3bc4f",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "55df380ad6f3b38094bc82f6bb2a34bb",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "e4952c83427611c5a66a864d8bb3bc4f",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "55df380ad6f3b38094bc82f6bb2a34bb",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "f37c917e8336be6afe86842fc0cd1586",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "aaf0413c15988e332d27b7fd6eb1ba1f",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "f37c917e8336be6afe86842fc0cd1586",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "aaf0413c15988e332d27b7fd6eb1ba1f",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "f66008360fc266ada358731656dfa91a",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "712cd1dda7661826129b8023949ebebe",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "f66008360fc266ada358731656dfa91a",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "712cd1dda7661826129b8023949ebebe",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "5488eb05a8c45904243ff5cb1fc483cd",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "55aef97c30ade6b21e93b7d8a45ae670",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "519d0d2895489e5905e65e53384b96ba",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "55aef97c30ade6b21e93b7d8a45ae670",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "c9e82195e722512599ec7edcb456c78d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "18b47849e222dd7b1bef9bd1a07473c9",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6c44557f5392bb3cd2d9a983add52d0b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0bd4099b6b594f62b806c9d74a84095a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a36752eee64f76c1868937247aaaee32",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "9ac33f02579ee14e4ad6a0b6b5a82a36",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "87bc0ff42442b60c817805ab07c65769",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "cedd1f2c367b84c20377c282453825f2",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "6df0f34207346d89a72924249ddd4706",

View File

@ -1,4 +1,4 @@
### 1.7.28 (build 21531, api 8, 2023-10-27)
### 1.7.28 (build 21543, api 8, 2023-10-31)
- Massively cleaned up code related to rendering and window systems (OpenGL,
SDL, etc). This code had been growing into a nasty tangle for 15 years
@ -196,10 +196,10 @@
including things like the internal EventLoop timeline. Please holler if you
notice anything running 1000x too fast or slow. In general my strategy going
forward is to use microseconds for exact internal time values but to mostly
expose float seconds to the user on the Python layer. There were starting to
be a few cases were integer milliseconds was not enough precision for internal
values. For instance, if we run with unclamped framerates and hit several
hundred FPS, milliseconds per frame would drop to 0 which could cause
expose float seconds to the user, especially on the Python layer. There were
starting to be a few cases were integer milliseconds was not enough precision
for internal values. For instance, if we run with unclamped framerates and hit
several hundred FPS, milliseconds per frame would drop to 0 which caused some
problems. Note that scenev1 will be remaining on milliseconds internally for
compatibility reasons. Scenev2 should move to microseconds though.

View File

@ -360,6 +360,8 @@ set(BALLISTICA_SOURCES
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.cc
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.h
${BA_SRC_ROOT}/ballistica/base/graphics/support/render_command_buffer.h
${BA_SRC_ROOT}/ballistica/base/graphics/support/screen_messages.cc
${BA_SRC_ROOT}/ballistica/base/graphics/support/screen_messages.h
${BA_SRC_ROOT}/ballistica/base/graphics/text/font_page_map_data.h
${BA_SRC_ROOT}/ballistica/base/graphics/text/text_graphics.cc
${BA_SRC_ROOT}/ballistica/base/graphics/text/text_graphics.h
@ -449,8 +451,6 @@ set(BALLISTICA_SOURCES
${BA_SRC_ROOT}/ballistica/base/support/repeater.h
${BA_SRC_ROOT}/ballistica/base/support/stdio_console.cc
${BA_SRC_ROOT}/ballistica/base/support/stdio_console.h
${BA_SRC_ROOT}/ballistica/base/support/stress_test.cc
${BA_SRC_ROOT}/ballistica/base/support/stress_test.h
${BA_SRC_ROOT}/ballistica/base/ui/dev_console.cc
${BA_SRC_ROOT}/ballistica/base/ui/dev_console.h
${BA_SRC_ROOT}/ballistica/base/ui/ui.cc
@ -463,6 +463,8 @@ set(BALLISTICA_SOURCES
${BA_SRC_ROOT}/ballistica/classic/python/classic_python.h
${BA_SRC_ROOT}/ballistica/classic/python/methods/python_methods_classic.cc
${BA_SRC_ROOT}/ballistica/classic/python/methods/python_methods_classic.h
${BA_SRC_ROOT}/ballistica/classic/support/stress_test.cc
${BA_SRC_ROOT}/ballistica/classic/support/stress_test.h
${BA_SRC_ROOT}/ballistica/classic/support/v1_account.cc
${BA_SRC_ROOT}/ballistica/classic/support/v1_account.h
${BA_SRC_ROOT}/ballistica/core/core.cc

View File

@ -352,6 +352,8 @@
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
<ClCompile Include="..\..\src\ballistica\base\graphics\support\screen_messages.cc" />
<ClInclude Include="..\..\src\ballistica\base\graphics\support\screen_messages.h" />
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h" />
<ClCompile Include="..\..\src\ballistica\base\graphics\text\text_graphics.cc" />
<ClInclude Include="..\..\src\ballistica\base\graphics\text\text_graphics.h" />
@ -441,8 +443,6 @@
<ClInclude Include="..\..\src\ballistica\base\support\repeater.h" />
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc" />
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h" />
<ClCompile Include="..\..\src\ballistica\base\support\stress_test.cc" />
<ClInclude Include="..\..\src\ballistica\base\support\stress_test.h" />
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc" />
<ClInclude Include="..\..\src\ballistica\base\ui\dev_console.h" />
<ClCompile Include="..\..\src\ballistica\base\ui\ui.cc" />
@ -455,6 +455,8 @@
<ClInclude Include="..\..\src\ballistica\classic\python\classic_python.h" />
<ClCompile Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.cc" />
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h" />
<ClCompile Include="..\..\src\ballistica\classic\support\stress_test.cc" />
<ClInclude Include="..\..\src\ballistica\classic\support\stress_test.h" />
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc" />
<ClInclude Include="..\..\src\ballistica\classic\support\v1_account.h" />
<ClCompile Include="..\..\src\ballistica\core\core.cc" />

View File

@ -490,6 +490,12 @@
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h">
<Filter>ballistica\base\graphics\support</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\base\graphics\support\screen_messages.cc">
<Filter>ballistica\base\graphics\support</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\base\graphics\support\screen_messages.h">
<Filter>ballistica\base\graphics\support</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h">
<Filter>ballistica\base\graphics\text</Filter>
</ClInclude>
@ -757,12 +763,6 @@
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h">
<Filter>ballistica\base\support</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\base\support\stress_test.cc">
<Filter>ballistica\base\support</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\base\support\stress_test.h">
<Filter>ballistica\base\support</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc">
<Filter>ballistica\base\ui</Filter>
</ClCompile>
@ -799,6 +799,12 @@
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h">
<Filter>ballistica\classic\python\methods</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\classic\support\stress_test.cc">
<Filter>ballistica\classic\support</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\classic\support\stress_test.h">
<Filter>ballistica\classic\support</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc">
<Filter>ballistica\classic\support</Filter>
</ClCompile>

View File

@ -347,6 +347,8 @@
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
<ClCompile Include="..\..\src\ballistica\base\graphics\support\screen_messages.cc" />
<ClInclude Include="..\..\src\ballistica\base\graphics\support\screen_messages.h" />
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h" />
<ClCompile Include="..\..\src\ballistica\base\graphics\text\text_graphics.cc" />
<ClInclude Include="..\..\src\ballistica\base\graphics\text\text_graphics.h" />
@ -436,8 +438,6 @@
<ClInclude Include="..\..\src\ballistica\base\support\repeater.h" />
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc" />
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h" />
<ClCompile Include="..\..\src\ballistica\base\support\stress_test.cc" />
<ClInclude Include="..\..\src\ballistica\base\support\stress_test.h" />
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc" />
<ClInclude Include="..\..\src\ballistica\base\ui\dev_console.h" />
<ClCompile Include="..\..\src\ballistica\base\ui\ui.cc" />
@ -450,6 +450,8 @@
<ClInclude Include="..\..\src\ballistica\classic\python\classic_python.h" />
<ClCompile Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.cc" />
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h" />
<ClCompile Include="..\..\src\ballistica\classic\support\stress_test.cc" />
<ClInclude Include="..\..\src\ballistica\classic\support\stress_test.h" />
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc" />
<ClInclude Include="..\..\src\ballistica\classic\support\v1_account.h" />
<ClCompile Include="..\..\src\ballistica\core\core.cc" />

View File

@ -490,6 +490,12 @@
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h">
<Filter>ballistica\base\graphics\support</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\base\graphics\support\screen_messages.cc">
<Filter>ballistica\base\graphics\support</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\base\graphics\support\screen_messages.h">
<Filter>ballistica\base\graphics\support</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h">
<Filter>ballistica\base\graphics\text</Filter>
</ClInclude>
@ -757,12 +763,6 @@
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h">
<Filter>ballistica\base\support</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\base\support\stress_test.cc">
<Filter>ballistica\base\support</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\base\support\stress_test.h">
<Filter>ballistica\base\support</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc">
<Filter>ballistica\base\ui</Filter>
</ClCompile>
@ -799,6 +799,12 @@
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h">
<Filter>ballistica\classic\python\methods</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\classic\support\stress_test.cc">
<Filter>ballistica\classic\support</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ballistica\classic\support\stress_test.h">
<Filter>ballistica\classic\support</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc">
<Filter>ballistica\classic\support</Filter>
</ClCompile>

View File

@ -10,7 +10,8 @@
"src/ballistica/base/graphics/texture/ktx.cc",
"src/ballistica/core/platform/android/android_gl3.h",
"src/ballistica/base/platform/apple/app_delegate.h",
"src/ballistica/base/platform/apple/scripting_bridge_music.h",
"src/ballistica/base/platform/apple/MacMusicApp.h",
"src/ballistica/base/platform/apple/MacMusicAppScriptingBridge.h",
"src/ballistica/core/platform/android/utf8/checked.h",
"src/ballistica/core/platform/android/utf8/unchecked.h",
"src/ballistica/core/platform/android/utf8/core.h",

View File

@ -85,7 +85,6 @@ from _babase import (
screenmessage,
set_analytics_screen,
set_low_level_config_value,
set_stress_testing,
set_thread_name,
set_ui_input_device,
show_progress_bar,
@ -303,7 +302,6 @@ __all__ = [
'SessionTeamNotFoundError',
'set_analytics_screen',
'set_low_level_config_value',
'set_stress_testing',
'set_thread_name',
'set_ui_input_device',
'show_progress_bar',

View File

@ -8,6 +8,7 @@ from typing import TYPE_CHECKING
import babase
import bascenev1
import _baclassic
if TYPE_CHECKING:
from typing import Any, Sequence
@ -84,7 +85,8 @@ def run_stress_test(
def stop_stress_test() -> None:
"""End a running stress test."""
babase.set_stress_testing(False, 0)
_baclassic.set_stress_testing(False, 0)
assert babase.app.classic is not None
try:
if babase.app.classic.stress_test_reset_timer is not None:
@ -134,14 +136,14 @@ def start_stress_test(args: dict[str, Any]) -> None:
babase.Call(bascenev1.new_host_session, FreeForAllSession),
),
)
babase.set_stress_testing(True, args['player_count'])
_baclassic.set_stress_testing(True, args['player_count'])
babase.app.classic.stress_test_reset_timer = babase.AppTimer(
args['round_duration'], babase.Call(_reset_stress_test, args)
)
def _reset_stress_test(args: dict[str, Any]) -> None:
babase.set_stress_testing(False, args['player_count'])
_baclassic.set_stress_testing(False, args['player_count'])
babase.screenmessage('Resetting stress test...')
session = bascenev1.get_foreground_host_session()
assert session is not None

View File

@ -165,15 +165,16 @@ class MusicSubsystem:
def supports_soundtrack_entry_type(self, entry_type: str) -> bool:
"""Return whether provided soundtrack entry type is supported here."""
uas = babase.env()['legacy_user_agent_string']
assert isinstance(uas, str)
# FIXME: Generalize this.
# Note to self; can't access babase.app.classic here because
# we are called during its construction.
env = babase.env()
platform = env.get('platform')
assert isinstance(platform, str)
if entry_type == 'iTunesPlaylist':
return 'Mac' in uas
return platform == 'mac' and babase.is_xcode_build()
if entry_type in ('musicFile', 'musicFolder'):
return (
'android' in uas
platform == 'android'
and babase.android_get_external_files_dir() is not None
)
if entry_type == 'default':

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21531
TARGET_BALLISTICA_BUILD = 21543
TARGET_BALLISTICA_VERSION = '1.7.28'

View File

@ -9,6 +9,7 @@
#include "ballistica/base/audio/audio_server.h"
#include "ballistica/base/dynamics/bg/bg_dynamics_server.h"
#include "ballistica/base/graphics/graphics_server.h"
#include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/graphics/text/text_graphics.h"
#include "ballistica/base/input/input.h"
#include "ballistica/base/logic/logic.h"
@ -20,11 +21,11 @@
#include "ballistica/base/python/class/python_class_feature_set_data.h"
#include "ballistica/base/python/support/python_context_call.h"
#include "ballistica/base/support/app_config.h"
#include "ballistica/base/support/app_timer.h"
#include "ballistica/base/support/base_build_switches.h"
#include "ballistica/base/support/huffman.h"
#include "ballistica/base/support/plus_soft.h"
#include "ballistica/base/support/stdio_console.h"
#include "ballistica/base/support/stress_test.h"
#include "ballistica/base/ui/dev_console.h"
#include "ballistica/base/ui/ui_delegate.h"
#include "ballistica/core/python/core_python.h"
@ -63,7 +64,6 @@ BaseFeatureSet::BaseFeatureSet()
python{new BasePython()},
stdio_console{g_buildconfig.enable_stdio_console() ? new StdioConsole()
: nullptr},
stress_test_{new StressTest()},
text_graphics{new TextGraphics()},
ui{new UI()},
utils{new Utils()} {
@ -465,8 +465,9 @@ auto BaseFeatureSet::InGraphicsContext() const -> bool {
void BaseFeatureSet::ScreenMessage(const std::string& s,
const Vector3f& color) {
logic->event_loop()->PushCall(
[this, s, color] { graphics->AddScreenMessage(s, color); });
logic->event_loop()->PushCall([this, s, color] {
graphics->screenmessages->AddScreenMessage(s, color);
});
}
void BaseFeatureSet::DoV1CloudLog(const std::string& msg) {

View File

@ -102,12 +102,12 @@ class RemoteAppServer;
class RemoteControlInput;
class Repeater;
class ScoreToBeat;
class ScreenMessages;
class AppAdapterSDL;
class SDLContext;
class SoundAsset;
class SpriteMesh;
class StdioConsole;
class StressTest;
class Module;
class TestInput;
class TextGroup;
@ -752,8 +752,6 @@ class BaseFeatureSet : public FeatureSetNativeComponent,
void set_app_mode(AppMode* mode);
auto* app_mode() const { return app_mode_; }
auto* stress_test() const { return stress_test_; }
/// Whether we're running under ballisticakit_server.py
/// (affects some app behavior).
auto server_wrapper_managed() { return server_wrapper_managed_; }
@ -776,7 +774,6 @@ class BaseFeatureSet : public FeatureSetNativeComponent,
AppMode* app_mode_;
PlusSoftInterface* plus_soft_{};
ClassicSoftInterface* classic_soft_{};
StressTest* stress_test_;
std::mutex shutdown_suppress_lock_;
bool shutdown_suppress_disallowed_{};

View File

@ -11,25 +11,23 @@
#include "ballistica/base/graphics/component/special_component.h"
#include "ballistica/base/graphics/component/sprite_component.h"
#include "ballistica/base/graphics/graphics_server.h"
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
#include "ballistica/base/graphics/support/camera.h"
#include "ballistica/base/graphics/support/net_graph.h"
#include "ballistica/base/graphics/text/text_graphics.h"
#include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/input/input.h"
#include "ballistica/base/logic/logic.h"
#include "ballistica/base/python/support/python_context_call.h"
#include "ballistica/base/support/app_config.h"
#include "ballistica/base/ui/ui.h"
#include "ballistica/shared/foundation/event_loop.h"
#include "ballistica/shared/generic/utils.h"
namespace ballistica::base {
const float kScreenMessageZDepth{-0.06f};
const float kScreenMeshZDepth{-0.05f};
const float kScreenTextZDepth{-0.06f};
const float kProgressBarZDepth{0.0f};
const int kProgressBarFadeTime{500};
const float kDebugImgZDepth{-0.04f};
const float kScreenMeshZDepth{-0.05f};
auto Graphics::IsShaderTransparent(ShadingType c) -> bool {
switch (c) {
@ -80,7 +78,7 @@ auto Graphics::IsShaderTransparent(ShadingType c) -> bool {
}
}
Graphics::Graphics() = default;
Graphics::Graphics() : screenmessages{new ScreenMessages()} {}
Graphics::~Graphics() = default;
void Graphics::OnAppStart() { assert(g_base->InLogicThread()); }
@ -344,43 +342,6 @@ auto Graphics::GetShadowDensity(float x, float y, float z) -> float {
}
}
class Graphics::ScreenMessageEntry {
public:
ScreenMessageEntry(std::string text, bool top_style, uint32_t c,
const Vector3f& color, TextureAsset* texture,
TextureAsset* tint_texture, const Vector3f& tint,
const Vector3f& tint2)
: top_style(top_style),
creation_time(c),
s_raw(std::move(text)),
color(color),
texture(texture),
tint_texture(tint_texture),
tint(tint),
tint2(tint2) {}
auto GetText() -> TextGroup&;
void UpdateTranslation();
bool top_style;
uint32_t creation_time;
Vector3f color;
Vector3f tint;
Vector3f tint2;
std::string s_raw;
std::string s_translated;
float str_width{};
float str_height{};
Object::Ref<TextureAsset> texture;
Object::Ref<TextureAsset> tint_texture;
float v_smoothed{};
bool translation_dirty{true};
bool mesh_dirty{true};
millisecs_t smooth_time{};
Object::Ref<NinePatchMesh> shadow_mesh_;
private:
Object::Ref<TextGroup> s_mesh_;
};
// Draw controls and things that lie on top of the action.
void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
RenderPass* pass = frame_def->overlay_pass();
@ -398,7 +359,6 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
last_fps_ = total_frames_rendered - last_total_frames_rendered_;
last_total_frames_rendered_ = total_frames_rendered;
}
float v{};
if (show_fps_) {
char fps_str[32];
@ -460,7 +420,7 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
{
auto xf = c.ScopedTransform();
c.Translate(14.0f + (show_fps_ ? 30.0f : 0.0f), 0.1f,
kScreenMessageZDepth);
kScreenTextZDepth);
c.Scale(0.7f, 0.7f);
c.DrawMesh(ping_text_group_->GetElementMesh(e));
}
@ -488,7 +448,7 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
c.SetFlatness(1.0f);
{
auto xf = c.ScopedTransform();
c.Translate(4.0f, (show_fps_ ? 66.0f : 40.0f), kScreenMessageZDepth);
c.Translate(4.0f, (show_fps_ ? 66.0f : 40.0f), kScreenTextZDepth);
c.Scale(0.7f, 0.7f);
c.DrawMesh(net_info_text_group_->GetElementMesh(e));
}
@ -516,392 +476,7 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) {
}
}
// Screen messages (bottom).
{
// Delete old ones.
if (!screen_messages_.empty()) {
millisecs_t cutoff;
if (g_core->GetAppTimeMillisecs() > 5000) {
cutoff = g_core->GetAppTimeMillisecs() - 5000;
for (auto i = screen_messages_.begin(); i != screen_messages_.end();) {
if (i->creation_time < cutoff) {
auto next = i;
next++;
screen_messages_.erase(i);
i = next;
} else {
i++;
}
}
}
}
// Delete if we have too many.
while ((screen_messages_.size()) > 4) {
screen_messages_.erase(screen_messages_.begin());
}
// Draw all existing.
if (!screen_messages_.empty()) {
bool vr = g_core->IsVRMode();
// These are less disruptive in the middle for menus but at the bottom
// during gameplay.
float start_v = g_base->graphics->screen_virtual_height() * 0.05f;
float scale;
switch (g_base->ui->scale()) {
case UIScale::kSmall:
scale = 1.5f;
break;
case UIScale::kMedium:
scale = 1.2f;
break;
default:
scale = 1.0f;
break;
}
// Shadows.
{
SimpleComponent c(pass);
c.SetTransparent(true);
c.SetTexture(
// g_base->assets->SysTexture(SysTextureID::kSoftRectVertical));
g_base->assets->SysTexture(SysTextureID::kShadowSharp));
float screen_width = g_base->graphics->screen_virtual_width();
v = start_v;
millisecs_t youngest_age = 9999;
for (auto i = screen_messages_.rbegin(); i != screen_messages_.rend();
i++) {
// Update the translation if need be.
i->UpdateTranslation();
// Don't actually need the text just yet but need shadow mesh
// which is calculated as part of it.
i->GetText();
millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time;
youngest_age = std::min(youngest_age, age);
float s_extra = 1.0f;
if (age < 100) {
s_extra = std::min(1.2f, 1.2f * (static_cast<float>(age) / 100.0f));
} else if (age < 150) {
s_extra =
1.2f - 0.2f * ((150.0f - static_cast<float>(age)) / 50.0f);
}
float a;
if (age > 3000) {
a = 1.0f - static_cast<float>(age - 3000) / 2000;
} else {
a = 1;
}
a *= 0.7f;
// if (vr) {
// a *= 0.8f;
// }
if (i->translation_dirty) {
BA_LOG_ONCE(
LogLevel::kWarning,
"Found dirty translation on screenmessage draw pass 1; raw="
+ i->s_raw);
}
float str_height = i->str_height;
float str_width = i->str_width;
if ((str_width * scale) > (screen_width - 40)) {
s_extra *= ((screen_width - 40) / (str_width * scale));
}
float r = i->color.x;
float g = i->color.y;
float b = i->color.z;
GetSafeColor(&r, &g, &b);
float v_extra = scale * (static_cast<float>(youngest_age) * 0.01f);
float fade;
if (age < 100) {
fade = 1.0f;
} else {
// Don't fade ALL the way to black; leaves a tiny bit of color
// showing which looks nice.
fade = std::max(0.07f, (200.0f - static_cast<float>(age)) / 100.0f);
}
c.SetColor(r * fade, g * fade, b * fade, a);
{
auto xf = c.ScopedTransform();
// This logic needs to run at a fixed hz or it breaks on high frame
// rates.
auto now_millisecs = pass->frame_def()->display_time_millisecs();
i->smooth_time = std::max(i->smooth_time, now_millisecs - 100);
while (i->smooth_time < now_millisecs) {
i->smooth_time += 1000 / 60;
if (i->v_smoothed == 0.0f) {
i->v_smoothed = v + v_extra;
} else {
float smoothing = 0.8f;
i->v_smoothed = smoothing * i->v_smoothed
+ (1.0f - smoothing) * (v + v_extra);
}
}
c.Translate(screen_width * 0.5f, i->v_smoothed,
vr ? 60 : kScreenMessageZDepth);
// if (vr) {
// // Let's drop down a bit in vr mode.
// // c.Translate(0, -10.0f, 0);
// // c.Scale((str_width + 60) * scale * s_extra,
// // (str_height + 20) * scale * s_extra);
// c.Scale(scale * s_extra, scale * s_extra);
// // Align our bottom with where we just scaled from.
// c.Translate(0, 0.5f, 0);
{
// c.Scale((str_width + 110) * scale * s_extra,
// (str_height + 40) * scale * s_extra);
c.Scale(scale * s_extra, scale * s_extra);
c.Translate(0, 20);
// Align our bottom with where we just scaled from.
c.Translate(0, 0.5f, 0);
}
// c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1));
assert(i->shadow_mesh_.Exists());
c.DrawMesh(i->shadow_mesh_.Get());
}
v += scale * (36 + str_height);
if (v > g_base->graphics->screen_virtual_height() + 30) {
break;
}
}
c.Submit();
}
// Now the strings themselves.
{
SimpleComponent c(pass);
c.SetTransparent(true);
float screen_width = g_base->graphics->screen_virtual_width();
v = start_v;
millisecs_t youngest_age = 9999;
for (auto i = screen_messages_.rbegin(); i != screen_messages_.rend();
i++) {
millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time;
youngest_age = std::min(youngest_age, age);
float s_extra = 1.0f;
if (age < 100) {
s_extra = std::min(1.2f, 1.2f * (static_cast<float>(age) / 100.0f));
} else if (age < 150) {
s_extra =
1.2f - 0.2f * ((150.0f - static_cast<float>(age)) / 50.0f);
}
float a;
if (age > 3000) {
a = 1.0f - static_cast<float>(age - 3000) / 2000;
} else {
a = 1;
}
if (i->translation_dirty) {
BA_LOG_ONCE(
LogLevel::kWarning,
"Found dirty translation on screenmessage draw pass 2; raw="
+ i->s_raw);
}
float str_height = i->str_height;
float str_width = i->str_width;
if ((str_width * scale) > (screen_width - 40)) {
s_extra *= ((screen_width - 40) / (str_width * scale));
}
float r = i->color.x;
float g = i->color.y;
float b = i->color.z;
GetSafeColor(&r, &g, &b, 0.85f);
int elem_count = i->GetText().GetElementCount();
for (int e = 0; e < elem_count; e++) {
// Gracefully skip unloaded textures.
TextureAsset* t = i->GetText().GetElementTexture(e);
if (!t->preloaded()) {
continue;
}
c.SetTexture(t);
if (i->GetText().GetElementCanColor(e)) {
c.SetColor(r, g, b, a);
} else {
c.SetColor(1, 1, 1, a);
}
c.SetFlatness(i->GetText().GetElementMaxFlatness(e));
{
auto xf = c.ScopedTransform();
c.Translate(screen_width * 0.5f, i->v_smoothed,
vr ? 150 : kScreenMessageZDepth);
c.Scale(scale * s_extra, scale * s_extra);
c.Translate(0, 20);
c.DrawMesh(i->GetText().GetElementMesh(e));
}
}
v += scale * (36 + str_height);
if (v > g_base->graphics->screen_virtual_height() + 30) {
break;
}
}
c.Submit();
}
}
}
// Screen messages (top).
{
// Delete old ones.
if (!screen_messages_top_.empty()) {
millisecs_t cutoff;
if (g_core->GetAppTimeMillisecs() > 5000) {
cutoff = g_core->GetAppTimeMillisecs() - 5000;
for (auto i = screen_messages_top_.begin();
i != screen_messages_top_.end();) {
if (i->creation_time < cutoff) {
auto next = i;
next++;
screen_messages_top_.erase(i);
i = next;
} else {
i++;
}
}
}
}
// Delete if we have too many.
while ((screen_messages_top_.size()) > 6) {
screen_messages_top_.erase(screen_messages_top_.begin());
}
if (!screen_messages_top_.empty()) {
SimpleComponent c(pass);
c.SetTransparent(true);
// Draw all existing.
float h = pass->virtual_width() - 300.0f;
v = g_base->graphics->screen_virtual_height() - 50.0f;
float v_base = g_base->graphics->screen_virtual_height();
float last_v = -999.0f;
float min_spacing = 25.0f;
for (auto i = screen_messages_top_.rbegin();
i != screen_messages_top_.rend(); i++) {
// Update the translation if need be.
i->UpdateTranslation();
millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time;
float s_extra = 1.0f;
if (age < 100) {
s_extra = std::min(1.1f, 1.1f * (static_cast<float>(age) / 100.0f));
} else if (age < 150) {
s_extra = 1.1f - 0.1f * ((150.0f - static_cast<float>(age)) / 50.0f);
}
float a;
if (age > 3000) {
a = 1.0f - static_cast<float>(age - 3000) / 2000;
} else {
a = 1;
}
// This logic needs to run at a fixed hz or it breaks on high frame
// rates.
auto now_millisecs = pass->frame_def()->display_time_millisecs();
i->smooth_time = std::max(i->smooth_time, now_millisecs - 100);
while (i->smooth_time < now_millisecs) {
i->smooth_time += 1000 / 60;
i->v_smoothed += 0.1f;
if (i->v_smoothed - last_v < min_spacing) {
i->v_smoothed +=
8.0f * (1.0f - ((i->v_smoothed - last_v) / min_spacing));
}
}
last_v = i->v_smoothed;
// Draw the image if they provided one.
if (i->texture.Exists()) {
c.Submit();
SimpleComponent c2(pass);
c2.SetTransparent(true);
c2.SetTexture(i->texture);
if (i->tint_texture.Exists()) {
c2.SetColorizeTexture(i->tint_texture.Get());
c2.SetColorizeColor(i->tint.x, i->tint.y, i->tint.z);
c2.SetColorizeColor2(i->tint2.x, i->tint2.y, i->tint2.z);
c2.SetMaskTexture(
g_base->assets->SysTexture(SysTextureID::kCharacterIconMask));
}
c2.SetColor(1, 1, 1, a);
{
auto xf = c2.ScopedTransform();
c2.Translate(h - 14, v_base + 10 + i->v_smoothed,
kScreenMessageZDepth);
c2.Scale(22.0f * s_extra, 22.0f * s_extra);
c2.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1));
}
c2.Submit();
}
float r = i->color.x;
float g = i->color.y;
float b = i->color.z;
GetSafeColor(&r, &g, &b);
int elem_count = i->GetText().GetElementCount();
for (int e = 0; e < elem_count; e++) {
// Gracefully skip unloaded textures.
TextureAsset* t = i->GetText().GetElementTexture(e);
if (!t->preloaded()) {
continue;
}
c.SetTexture(t);
if (i->GetText().GetElementCanColor(e)) {
c.SetColor(r, g, b, a);
} else {
c.SetColor(1, 1, 1, a);
}
c.SetShadow(-0.003f * i->GetText().GetElementUScale(e),
-0.003f * i->GetText().GetElementVScale(e), 0.0f,
1.0f * a);
c.SetFlatness(i->GetText().GetElementMaxFlatness(e));
c.SetMaskUV2Texture(i->GetText().GetElementMaskUV2Texture(e));
{
auto xf = c.ScopedTransform();
c.Translate(h, v_base + 2 + i->v_smoothed, kScreenMessageZDepth);
c.Scale(0.6f * s_extra, 0.6f * s_extra);
c.DrawMesh(i->GetText().GetElementMesh(e));
}
}
assert(!i->translation_dirty);
v -= g_base->text_graphics->GetStringHeight(i->s_translated.c_str())
* 0.6f
+ 8.0f;
}
c.Submit();
}
}
screenmessages->DrawMiscOverlays(frame_def);
}
auto Graphics::GetDebugGraph(const std::string& name, bool smoothed)
@ -947,32 +522,6 @@ void Graphics::GetSafeColor(float* red, float* green, float* blue,
}
}
void Graphics::AddScreenMessage(const std::string& msg, const Vector3f& color,
bool top, TextureAsset* texture,
TextureAsset* tint_texture,
const Vector3f& tint, const Vector3f& tint2) {
assert(g_base->InLogicThread());
// So we know we're always dealing with valid utf8.
std::string m = Utils::GetValidUTF8(msg.c_str(), "ga9msg");
if (top) {
float start_v = -40.0f;
if (!screen_messages_top_.empty()) {
start_v = std::min(
start_v,
std::max(-100.0f, screen_messages_top_.back().v_smoothed - 25.0f));
}
screen_messages_top_.emplace_back(m, true, g_core->GetAppTimeMillisecs(),
color, texture, tint_texture, tint,
tint2);
screen_messages_top_.back().v_smoothed = start_v;
} else {
screen_messages_.emplace_back(m, false, g_core->GetAppTimeMillisecs(),
color, texture, tint_texture, tint, tint2);
}
}
void Graphics::Reset() {
assert(g_base->InLogicThread());
fade_ = 0;
@ -982,9 +531,7 @@ void Graphics::Reset() {
camera_ = Object::New<Camera>();
}
// Wipe out top screen messages since they might be using textures that are
// being reset. Bottom ones are ok since they have no textures.
screen_messages_top_.clear();
screenmessages->Reset();
}
void Graphics::InitInternalComponents(FrameDef* frame_def) {
@ -1609,16 +1156,6 @@ void Graphics::DrawBlotches(FrameDef* frame_def) {
}
}
void Graphics::ClearScreenMessageTranslations() {
assert(g_base && g_base->InLogicThread());
for (auto&& i : screen_messages_) {
i.translation_dirty = true;
}
for (auto&& i : screen_messages_top_) {
i.translation_dirty = true;
}
}
void Graphics::ReturnCompletedFrameDef(FrameDef* frame_def) {
std::scoped_lock lock(frame_def_delete_list_mutex_);
g_base->graphics->frame_def_delete_list_.push_back(frame_def);
@ -1949,46 +1486,6 @@ void Graphics::DrawRadialMeter(MeshIndexedSimpleFull* m, float amt) {
}
}
auto Graphics::ScreenMessageEntry::GetText() -> TextGroup& {
if (translation_dirty) {
BA_LOG_ONCE(
LogLevel::kWarning,
"Found dirty translation on screenmessage GetText; raw=" + s_raw);
}
if (!s_mesh_.Exists()) {
s_mesh_ = Object::New<TextGroup>();
mesh_dirty = true;
}
if (mesh_dirty) {
s_mesh_->SetText(
s_translated,
top_style ? TextMesh::HAlign::kLeft : TextMesh::HAlign::kCenter,
TextMesh::VAlign::kBottom);
str_width = g_base->text_graphics->GetStringWidth(s_translated.c_str());
str_height = g_base->text_graphics->GetStringHeight(s_translated.c_str());
if (!top_style) {
float x_extend = 40.0f;
float y_extend = 40.0f;
float y_offset = -5.0f;
float corner_radius = 60.0f;
float width_fin = str_width + x_extend * 2.0f;
float height_fin = str_height + y_extend * 2.0f;
float x_border =
NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin);
float y_border =
NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin);
shadow_mesh_ = Object::New<NinePatchMesh>(
-0.5f * width_fin, -y_extend + y_offset, 0.0f, width_fin, height_fin,
x_border, y_border, x_border, y_border);
}
mesh_dirty = false;
}
return *s_mesh_;
}
void Graphics::OnScreenSizeChange() {}
void Graphics::CalcVirtualRes_(float* x, float* y) {
@ -2042,15 +1539,6 @@ void Graphics::SetScreenResolution(float x, float y) {
UpdateInitialGraphicsSettingsSend_();
}
void Graphics::ScreenMessageEntry::UpdateTranslation() {
if (translation_dirty) {
s_translated = g_base->assets->CompileResourceString(
s_raw, "Graphics::ScreenMessageEntry::UpdateTranslation");
translation_dirty = false;
mesh_dirty = true;
}
}
auto Graphics::CubeMapFromReflectionType(ReflectionType reflection_type)
-> SysCubeMapTextureID {
switch (reflection_type) {
@ -2130,8 +1618,8 @@ void Graphics::LanguageChanged() {
Log(LogLevel::kWarning,
"Graphics::LanguageChanged() called during draw; should not happen.");
}
// Also clear translations on all screen-messages.
ClearScreenMessageTranslations();
screenmessages->ClearScreenMessageTranslations();
}
auto Graphics::GraphicsQualityFromRequest(GraphicsQualityRequest request,
@ -2154,6 +1642,7 @@ auto Graphics::GraphicsQualityFromRequest(GraphicsQualityRequest request,
return GraphicsQuality::kLow;
}
}
auto Graphics::TextureQualityFromRequest(TextureQualityRequest request,
TextureQuality auto_val)
-> TextureQuality {

View File

@ -118,8 +118,6 @@ class Graphics {
return res_y_virtual_;
}
void ClearScreenMessageTranslations();
// Given a point in space, returns the shadow density that should be drawn
// into the shadow pass. Does this belong somewhere else?
auto GetShadowDensity(float x, float y, float z) -> float;
@ -127,14 +125,6 @@ class Graphics {
static void GetSafeColor(float* r, float* g, float* b,
float target_intensity = 0.6f);
// Print a message to the on-screen list.
void AddScreenMessage(const std::string& msg,
const Vector3f& color = {1, 1, 1}, bool top = false,
TextureAsset* texture = nullptr,
TextureAsset* tint_texture = nullptr,
const Vector3f& tint = {1, 1, 1},
const Vector3f& tint2 = {1, 1, 1});
// Fade the local screen in or out over the given time period.
void FadeScreen(bool to, millisecs_t time, PyObject* endcall);
@ -366,9 +356,9 @@ class Graphics {
return client_context_snapshot_.Get()->Get();
}
protected:
class ScreenMessageEntry;
ScreenMessages* const screenmessages;
protected:
virtual ~Graphics();
virtual void DoDrawFade(FrameDef* frame_def, float amt);
static void CalcVirtualRes_(float* x, float* y);
@ -446,8 +436,6 @@ class Graphics {
std::map<std::string, Object::Ref<NetGraph>> debug_graphs_;
std::mutex frame_def_delete_list_mutex_;
std::list<Object::Ref<PythonContextCall>> clean_frame_commands_;
std::list<ScreenMessageEntry> screen_messages_;
std::list<ScreenMessageEntry> screen_messages_top_;
std::vector<FrameDef*> recycle_frame_defs_;
std::vector<uint16_t> blotch_indices_;
std::vector<VertexSprite> blotch_verts_;
@ -466,7 +454,6 @@ class Graphics {
float gyro_mag_test_{};
float overlay_node_z_depth_{};
float progress_bar_progress_{};
float screen_gamma_{1.0f};
float shadow_lower_bottom_{-4.0f};
float shadow_lower_top_{4.0f};
float shadow_upper_bottom_{30.0f};

View File

@ -0,0 +1,538 @@
// Released under the MIT License. See LICENSE for details.
#include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
#include "ballistica/base/graphics/text/text_graphics.h"
#include "ballistica/base/ui/ui.h"
#include "ballistica/shared/generic/utils.h"
namespace ballistica::base {
const float kScreenMessageZDepth{-0.06f};
class ScreenMessages::ScreenMessageEntry {
public:
ScreenMessageEntry(std::string text, bool top_style, uint32_t c,
const Vector3f& color, TextureAsset* texture,
TextureAsset* tint_texture, const Vector3f& tint,
const Vector3f& tint2)
: top_style(top_style),
creation_time(c),
s_raw(std::move(text)),
color(color),
texture(texture),
tint_texture(tint_texture),
tint(tint),
tint2(tint2) {}
auto GetText() -> TextGroup&;
void UpdateTranslation();
bool top_style;
uint32_t creation_time;
Vector3f color;
Vector3f tint;
Vector3f tint2;
std::string s_raw;
std::string s_translated;
float str_width{};
float str_height{};
Object::Ref<TextureAsset> texture;
Object::Ref<TextureAsset> tint_texture;
float v_smoothed{};
bool translation_dirty{true};
bool mesh_dirty{true};
millisecs_t smooth_time{};
Object::Ref<NinePatchMesh> shadow_mesh_;
private:
Object::Ref<TextGroup> s_mesh_;
};
ScreenMessages::ScreenMessages() = default;
void ScreenMessages::DrawMiscOverlays(FrameDef* frame_def) {
RenderPass* pass = frame_def->overlay_pass();
// Screen messages (bottom).
{
// Delete old ones.
if (!screen_messages_.empty()) {
millisecs_t cutoff;
if (g_core->GetAppTimeMillisecs() > 5000) {
cutoff = g_core->GetAppTimeMillisecs() - 5000;
for (auto i = screen_messages_.begin(); i != screen_messages_.end();) {
if (i->creation_time < cutoff) {
auto next = i;
next++;
screen_messages_.erase(i);
i = next;
} else {
i++;
}
}
}
}
// Delete if we have too many.
while ((screen_messages_.size()) > 4) {
screen_messages_.erase(screen_messages_.begin());
}
// Draw all existing.
if (!screen_messages_.empty()) {
bool vr = g_core->IsVRMode();
// These are less disruptive in the middle for menus but at the bottom
// during gameplay.
float start_v = g_base->graphics->screen_virtual_height() * 0.05f;
float scale;
switch (g_base->ui->scale()) {
case UIScale::kSmall:
scale = 1.5f;
break;
case UIScale::kMedium:
scale = 1.2f;
break;
default:
scale = 1.0f;
break;
}
// Shadows.
{
SimpleComponent c(pass);
c.SetTransparent(true);
c.SetTexture(
// g_base->assets->SysTexture(SysTextureID::kSoftRectVertical));
g_base->assets->SysTexture(SysTextureID::kShadowSharp));
float screen_width = g_base->graphics->screen_virtual_width();
float v = start_v;
millisecs_t youngest_age = 9999;
for (auto i = screen_messages_.rbegin(); i != screen_messages_.rend();
i++) {
// Update the translation if need be.
i->UpdateTranslation();
// Don't actually need the text just yet but need shadow mesh
// which is calculated as part of it.
i->GetText();
millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time;
youngest_age = std::min(youngest_age, age);
float s_extra = 1.0f;
if (age < 100) {
s_extra = std::min(1.2f, 1.2f * (static_cast<float>(age) / 100.0f));
} else if (age < 150) {
s_extra =
1.2f - 0.2f * ((150.0f - static_cast<float>(age)) / 50.0f);
}
float a;
if (age > 3000) {
a = 1.0f - static_cast<float>(age - 3000) / 2000;
} else {
a = 1;
}
a *= 0.7f;
// if (vr) {
// a *= 0.8f;
// }
if (i->translation_dirty) {
BA_LOG_ONCE(
LogLevel::kWarning,
"Found dirty translation on screenmessage draw pass 1; raw="
+ i->s_raw);
}
float str_height = i->str_height;
float str_width = i->str_width;
if ((str_width * scale) > (screen_width - 40)) {
s_extra *= ((screen_width - 40) / (str_width * scale));
}
float r = i->color.x;
float g = i->color.y;
float b = i->color.z;
Graphics::GetSafeColor(&r, &g, &b);
float v_extra = scale * (static_cast<float>(youngest_age) * 0.01f);
float fade;
if (age < 100) {
fade = 1.0f;
} else {
// Don't fade ALL the way to black; leaves a tiny bit of color
// showing which looks nice.
fade = std::max(0.07f, (200.0f - static_cast<float>(age)) / 100.0f);
}
c.SetColor(r * fade, g * fade, b * fade, a);
{
auto xf = c.ScopedTransform();
// This logic needs to run at a fixed hz or it breaks on high frame
// rates.
auto now_millisecs = pass->frame_def()->display_time_millisecs();
i->smooth_time = std::max(i->smooth_time, now_millisecs - 100);
while (i->smooth_time < now_millisecs) {
i->smooth_time += 1000 / 60;
if (i->v_smoothed == 0.0f) {
i->v_smoothed = v + v_extra;
} else {
float smoothing = 0.8f;
i->v_smoothed = smoothing * i->v_smoothed
+ (1.0f - smoothing) * (v + v_extra);
}
}
c.Translate(screen_width * 0.5f, i->v_smoothed,
vr ? 60 : kScreenMessageZDepth);
// if (vr) {
// // Let's drop down a bit in vr mode.
// // c.Translate(0, -10.0f, 0);
// // c.Scale((str_width + 60) * scale * s_extra,
// // (str_height + 20) * scale * s_extra);
// c.Scale(scale * s_extra, scale * s_extra);
// // Align our bottom with where we just scaled from.
// c.Translate(0, 0.5f, 0);
{
// c.Scale((str_width + 110) * scale * s_extra,
// (str_height + 40) * scale * s_extra);
c.Scale(scale * s_extra, scale * s_extra);
c.Translate(0, 20);
// Align our bottom with where we just scaled from.
c.Translate(0, 0.5f, 0);
}
// c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1));
assert(i->shadow_mesh_.Exists());
c.DrawMesh(i->shadow_mesh_.Get());
}
v += scale * (36 + str_height);
if (v > g_base->graphics->screen_virtual_height() + 30) {
break;
}
}
c.Submit();
}
// Now the strings themselves.
{
SimpleComponent c(pass);
c.SetTransparent(true);
float screen_width = g_base->graphics->screen_virtual_width();
float v = start_v;
millisecs_t youngest_age = 9999;
for (auto i = screen_messages_.rbegin(); i != screen_messages_.rend();
i++) {
millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time;
youngest_age = std::min(youngest_age, age);
float s_extra = 1.0f;
if (age < 100) {
s_extra = std::min(1.2f, 1.2f * (static_cast<float>(age) / 100.0f));
} else if (age < 150) {
s_extra =
1.2f - 0.2f * ((150.0f - static_cast<float>(age)) / 50.0f);
}
float a;
if (age > 3000) {
a = 1.0f - static_cast<float>(age - 3000) / 2000;
} else {
a = 1;
}
if (i->translation_dirty) {
BA_LOG_ONCE(
LogLevel::kWarning,
"Found dirty translation on screenmessage draw pass 2; raw="
+ i->s_raw);
}
float str_height = i->str_height;
float str_width = i->str_width;
if ((str_width * scale) > (screen_width - 40)) {
s_extra *= ((screen_width - 40) / (str_width * scale));
}
float r = i->color.x;
float g = i->color.y;
float b = i->color.z;
Graphics::GetSafeColor(&r, &g, &b, 0.85f);
int elem_count = i->GetText().GetElementCount();
for (int e = 0; e < elem_count; e++) {
// Gracefully skip unloaded textures.
TextureAsset* t = i->GetText().GetElementTexture(e);
if (!t->preloaded()) {
continue;
}
c.SetTexture(t);
if (i->GetText().GetElementCanColor(e)) {
c.SetColor(r, g, b, a);
} else {
c.SetColor(1, 1, 1, a);
}
c.SetFlatness(i->GetText().GetElementMaxFlatness(e));
{
auto xf = c.ScopedTransform();
c.Translate(screen_width * 0.5f, i->v_smoothed,
vr ? 150 : kScreenMessageZDepth);
c.Scale(scale * s_extra, scale * s_extra);
c.Translate(0, 20);
c.DrawMesh(i->GetText().GetElementMesh(e));
}
}
v += scale * (36 + str_height);
if (v > g_base->graphics->screen_virtual_height() + 30) {
break;
}
}
c.Submit();
}
}
}
// Screen messages (top).
{
// Delete old ones.
if (!screen_messages_top_.empty()) {
millisecs_t cutoff;
if (g_core->GetAppTimeMillisecs() > 5000) {
cutoff = g_core->GetAppTimeMillisecs() - 5000;
for (auto i = screen_messages_top_.begin();
i != screen_messages_top_.end();) {
if (i->creation_time < cutoff) {
auto next = i;
next++;
screen_messages_top_.erase(i);
i = next;
} else {
i++;
}
}
}
}
// Delete if we have too many.
while ((screen_messages_top_.size()) > 6) {
screen_messages_top_.erase(screen_messages_top_.begin());
}
if (!screen_messages_top_.empty()) {
SimpleComponent c(pass);
c.SetTransparent(true);
// Draw all existing.
float h = pass->virtual_width() - 300.0f;
float v = g_base->graphics->screen_virtual_height() - 50.0f;
float v_base = g_base->graphics->screen_virtual_height();
float last_v = -999.0f;
float min_spacing = 25.0f;
for (auto i = screen_messages_top_.rbegin();
i != screen_messages_top_.rend(); i++) {
// Update the translation if need be.
i->UpdateTranslation();
millisecs_t age = g_core->GetAppTimeMillisecs() - i->creation_time;
float s_extra = 1.0f;
if (age < 100) {
s_extra = std::min(1.1f, 1.1f * (static_cast<float>(age) / 100.0f));
} else if (age < 150) {
s_extra = 1.1f - 0.1f * ((150.0f - static_cast<float>(age)) / 50.0f);
}
float a;
if (age > 3000) {
a = 1.0f - static_cast<float>(age - 3000) / 2000;
} else {
a = 1;
}
// This logic needs to run at a fixed hz or it breaks on high frame
// rates.
auto now_millisecs = pass->frame_def()->display_time_millisecs();
i->smooth_time = std::max(i->smooth_time, now_millisecs - 100);
while (i->smooth_time < now_millisecs) {
i->smooth_time += 1000 / 60;
i->v_smoothed += 0.1f;
if (i->v_smoothed - last_v < min_spacing) {
i->v_smoothed +=
8.0f * (1.0f - ((i->v_smoothed - last_v) / min_spacing));
}
}
last_v = i->v_smoothed;
// Draw the image if they provided one.
if (i->texture.Exists()) {
c.Submit();
SimpleComponent c2(pass);
c2.SetTransparent(true);
c2.SetTexture(i->texture);
if (i->tint_texture.Exists()) {
c2.SetColorizeTexture(i->tint_texture.Get());
c2.SetColorizeColor(i->tint.x, i->tint.y, i->tint.z);
c2.SetColorizeColor2(i->tint2.x, i->tint2.y, i->tint2.z);
c2.SetMaskTexture(
g_base->assets->SysTexture(SysTextureID::kCharacterIconMask));
}
c2.SetColor(1, 1, 1, a);
{
auto xf = c2.ScopedTransform();
c2.Translate(h - 14, v_base + 10 + i->v_smoothed,
kScreenMessageZDepth);
c2.Scale(22.0f * s_extra, 22.0f * s_extra);
c2.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1));
}
c2.Submit();
}
float r = i->color.x;
float g = i->color.y;
float b = i->color.z;
Graphics::GetSafeColor(&r, &g, &b);
int elem_count = i->GetText().GetElementCount();
for (int e = 0; e < elem_count; e++) {
// Gracefully skip unloaded textures.
TextureAsset* t = i->GetText().GetElementTexture(e);
if (!t->preloaded()) {
continue;
}
c.SetTexture(t);
if (i->GetText().GetElementCanColor(e)) {
c.SetColor(r, g, b, a);
} else {
c.SetColor(1, 1, 1, a);
}
c.SetShadow(-0.003f * i->GetText().GetElementUScale(e),
-0.003f * i->GetText().GetElementVScale(e), 0.0f,
1.0f * a);
c.SetFlatness(i->GetText().GetElementMaxFlatness(e));
c.SetMaskUV2Texture(i->GetText().GetElementMaskUV2Texture(e));
{
auto xf = c.ScopedTransform();
c.Translate(h, v_base + 2 + i->v_smoothed, kScreenMessageZDepth);
c.Scale(0.6f * s_extra, 0.6f * s_extra);
c.DrawMesh(i->GetText().GetElementMesh(e));
}
}
assert(!i->translation_dirty);
v -= g_base->text_graphics->GetStringHeight(i->s_translated.c_str())
* 0.6f
+ 8.0f;
}
c.Submit();
}
}
}
void ScreenMessages::AddScreenMessage(const std::string& msg,
const Vector3f& color, bool top,
TextureAsset* texture,
TextureAsset* tint_texture,
const Vector3f& tint,
const Vector3f& tint2) {
assert(g_base->InLogicThread());
// So we know we're always dealing with valid utf8.
std::string m = Utils::GetValidUTF8(msg.c_str(), "ga9msg");
if (top) {
float start_v = -40.0f;
if (!screen_messages_top_.empty()) {
start_v = std::min(
start_v,
std::max(-100.0f, screen_messages_top_.back().v_smoothed - 25.0f));
}
screen_messages_top_.emplace_back(m, true, g_core->GetAppTimeMillisecs(),
color, texture, tint_texture, tint,
tint2);
screen_messages_top_.back().v_smoothed = start_v;
} else {
screen_messages_.emplace_back(m, false, g_core->GetAppTimeMillisecs(),
color, texture, tint_texture, tint, tint2);
}
}
void ScreenMessages::Reset() {
// Wipe out top screen messages since they might be using textures that are
// being reset. Bottom ones are ok since they have no textures.
screen_messages_top_.clear();
}
void ScreenMessages::ClearScreenMessageTranslations() {
assert(g_base && g_base->InLogicThread());
for (auto&& i : screen_messages_) {
i.translation_dirty = true;
}
for (auto&& i : screen_messages_top_) {
i.translation_dirty = true;
}
}
auto ScreenMessages::ScreenMessageEntry::GetText() -> TextGroup& {
if (translation_dirty) {
BA_LOG_ONCE(
LogLevel::kWarning,
"Found dirty translation on screenmessage GetText; raw=" + s_raw);
}
if (!s_mesh_.Exists()) {
s_mesh_ = Object::New<TextGroup>();
mesh_dirty = true;
}
if (mesh_dirty) {
s_mesh_->SetText(
s_translated,
top_style ? TextMesh::HAlign::kLeft : TextMesh::HAlign::kCenter,
TextMesh::VAlign::kBottom);
str_width = g_base->text_graphics->GetStringWidth(s_translated.c_str());
str_height = g_base->text_graphics->GetStringHeight(s_translated.c_str());
if (!top_style) {
float x_extend = 40.0f;
float y_extend = 40.0f;
float y_offset = -5.0f;
float corner_radius = 60.0f;
float width_fin = str_width + x_extend * 2.0f;
float height_fin = str_height + y_extend * 2.0f;
float x_border =
NinePatchMesh::BorderForRadius(corner_radius, width_fin, height_fin);
float y_border =
NinePatchMesh::BorderForRadius(corner_radius, height_fin, width_fin);
shadow_mesh_ = Object::New<NinePatchMesh>(
-0.5f * width_fin, -y_extend + y_offset, 0.0f, width_fin, height_fin,
x_border, y_border, x_border, y_border);
}
mesh_dirty = false;
}
return *s_mesh_;
}
void ScreenMessages::ScreenMessageEntry::UpdateTranslation() {
if (translation_dirty) {
s_translated = g_base->assets->CompileResourceString(
s_raw, "Graphics::ScreenMessageEntry::UpdateTranslation");
translation_dirty = false;
mesh_dirty = true;
}
}
} // namespace ballistica::base

View File

@ -0,0 +1,37 @@
// Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_BASE_GRAPHICS_SUPPORT_SCREEN_MESSAGES_H_
#define BALLISTICA_BASE_GRAPHICS_SUPPORT_SCREEN_MESSAGES_H_
#include "ballistica/base/base.h"
#include "ballistica/shared/math/vector3f.h"
namespace ballistica::base {
/// Wrangles a set of screen-messages.
class ScreenMessages {
public:
ScreenMessages();
void ClearScreenMessageTranslations();
// Print a message to the on-screen list.
void AddScreenMessage(const std::string& msg,
const Vector3f& color = {1, 1, 1}, bool top = false,
TextureAsset* texture = nullptr,
TextureAsset* tint_texture = nullptr,
const Vector3f& tint = {1, 1, 1},
const Vector3f& tint2 = {1, 1, 1});
void DrawMiscOverlays(FrameDef* frame_def);
void Reset();
private:
class ScreenMessageEntry;
std::list<ScreenMessageEntry> screen_messages_;
std::list<ScreenMessageEntry> screen_messages_top_;
};
} // namespace ballistica::base
#endif // BALLISTICA_BASE_GRAPHICS_SUPPORT_SCREEN_MESSAGES_H_

View File

@ -22,7 +22,7 @@ TestInput::~TestInput() {
}
void TestInput::Reset() {
assert(g_core->InMainThread());
assert(g_base->InLogicThread());
reset_ = true;
}
@ -33,7 +33,7 @@ void TestInput::HandleAlreadyPressedTwice() {
}
void TestInput::Process(millisecs_t time) {
assert(g_core->InMainThread());
assert(g_base->InLogicThread());
if (reset_) {
reset_ = false;

View File

@ -16,20 +16,21 @@ class TestInput {
private:
void HandleAlreadyPressedTwice();
int lr_{};
int ud_{};
bool jump_pressed_{};
bool bomb_pressed_{};
bool pickup_pressed_{};
bool punch_pressed_{};
int join_press_count_{};
bool jump_pressed_ : 1 {};
bool bomb_pressed_ : 1 {};
bool pickup_pressed_ : 1 {};
bool punch_pressed_ : 1 {};
bool print_non_join_ : 1 {};
bool print_already_did2_ : 1 {};
bool reset_ : 1 {true};
millisecs_t next_event_time_{};
millisecs_t join_start_time_{};
millisecs_t join_end_time_{9999};
int join_press_count_{};
bool reset_{true};
JoystickInput* joystick_{};
bool print_non_join_{};
bool print_already_did2_{};
};
} // namespace ballistica::base

View File

@ -8,7 +8,6 @@
#include "ballistica/base/graphics/support/camera.h"
#include "ballistica/base/input/device/joystick_input.h"
#include "ballistica/base/input/device/keyboard_input.h"
#include "ballistica/base/input/device/test_input.h"
#include "ballistica/base/input/device/touch_input.h"
#include "ballistica/base/logic/logic.h"
#include "ballistica/base/python/base_python.h"
@ -762,58 +761,6 @@ void Input::PrintLockLabels_() {
Log(LogLevel::kError, s);
}
void Input::ProcessStressTesting(int player_count) {
assert(g_core->InMainThread());
assert(player_count >= 0);
millisecs_t time = g_core->GetAppTimeMillisecs();
// FIXME: If we don't check for stress_test_last_leave_time_ we totally
// confuse the game.. need to be able to survive that.
// Kill some off if we have too many.
while (static_cast<int>(test_inputs_.size()) > player_count) {
delete test_inputs_.front();
test_inputs_.pop_front();
}
// If we have less than full test-inputs, add one randomly.
if (static_cast<int>(test_inputs_.size()) < player_count
&& ((rand() % 1000 < 10))) { // NOLINT
test_inputs_.push_back(new TestInput());
}
// Every so often lets kill the oldest one off.
if (explicit_bool(true)) {
if (test_inputs_.size() > 0 && (rand() % 2000 < 3)) { // NOLINT
stress_test_last_leave_time_ = time;
// Usually do oldest; sometimes newest.
if (rand() % 5 == 0) { // NOLINT
delete test_inputs_.back();
test_inputs_.pop_back();
} else {
delete test_inputs_.front();
test_inputs_.pop_front();
}
}
}
if (time - stress_test_time_ > 1000) {
stress_test_time_ = time; // reset..
for (auto& test_input : test_inputs_) {
(*test_input).Reset();
}
}
while (stress_test_time_ < time) {
stress_test_time_++;
for (auto& test_input : test_inputs_) {
(*test_input).Process(stress_test_time_);
}
}
}
void Input::PushTextInputEvent(const std::string& text) {
assert(g_base->logic->event_loop());
g_base->logic->event_loop()->PushCall([this, text] {

View File

@ -114,7 +114,6 @@ class Input {
// something.
auto HaveControllerWithPlayer() -> bool;
auto HaveRemoteAppController() -> bool;
void ProcessStressTesting(int player_count);
auto keyboard_input() const -> KeyboardInput* { return keyboard_input_; }
auto keyboard_input_2() const -> KeyboardInput* { return keyboard_input_2_; }
void CreateTouchInput();
@ -205,7 +204,6 @@ class Input {
std::list<std::string> input_lock_permanent_labels_;
std::list<std::string> input_unlock_permanent_labels_;
std::list<std::string> recent_input_locks_unlocks_;
std::list<TestInput*> test_inputs_;
std::list<std::string> newly_connected_controllers_;
std::list<std::string> newly_disconnected_controllers_;
std::unordered_map<std::string, std::unordered_map<std::string, int> >
@ -214,8 +212,6 @@ class Input {
std::set<int> keys_held_;
millisecs_t last_input_device_count_update_time_{};
millisecs_t last_input_temp_lock_time_{};
millisecs_t stress_test_time_{};
millisecs_t stress_test_last_leave_time_{};
void* single_touch_{};
KeyboardInput* keyboard_input_{};
KeyboardInput* keyboard_input_2_{};

View File

@ -5,6 +5,7 @@
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/audio/audio.h"
#include "ballistica/base/graphics/graphics.h"
#include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/input/input.h"
#include "ballistica/base/logic/logic.h"
#include "ballistica/base/networking/network_reader.h"
@ -162,7 +163,8 @@ void RemoteAppServer::HandleData(int socket, uint8_t* buffer, size_t amt,
g_base->assets->GetResourceString("controllerDisconnectedText");
Utils::StringReplaceOne(&s, "${CONTROLLER}", m);
g_base->logic->event_loop()->PushCall([s] {
g_base->graphics->AddScreenMessage(s, Vector3f(1, 1, 1));
g_base->graphics->screenmessages->AddScreenMessage(
s, Vector3f(1, 1, 1));
});
g_base->logic->event_loop()->PushCall([] {
g_base->audio->PlaySound(
@ -369,8 +371,10 @@ auto RemoteAppServer::GetClient(int request_id, struct sockaddr* addr,
std::string s =
g_base->assets->GetResourceString("controllerReconnectedText");
Utils::StringReplaceOne(&s, "${CONTROLLER}", m);
g_base->logic->event_loop()->PushCall(
[s] { g_base->graphics->AddScreenMessage(s, Vector3f(1, 1, 1)); });
g_base->logic->event_loop()->PushCall([s] {
g_base->graphics->screenmessages->AddScreenMessage(s,
Vector3f(1, 1, 1));
});
g_base->logic->event_loop()->PushCall([] {
g_base->audio->PlaySound(
g_base->assets->SysSound(SysSoundID::kGunCock));
@ -416,8 +420,10 @@ auto RemoteAppServer::GetClient(int request_id, struct sockaddr* addr,
std::string s =
g_base->assets->GetResourceString("controllerConnectedText");
Utils::StringReplaceOne(&s, "${CONTROLLER}", m);
g_base->logic->event_loop()->PushCall(
[s] { g_base->graphics->AddScreenMessage(s, Vector3f(1, 1, 1)); });
g_base->logic->event_loop()->PushCall([s] {
g_base->graphics->screenmessages->AddScreenMessage(s,
Vector3f(1, 1, 1));
});
g_base->logic->event_loop()->PushCall([] {
g_base->audio->PlaySound(

View File

@ -580,7 +580,7 @@ void Logic::UpdatePendingWorkTimer_() {
// If there's loading to do, keep at it rather vigorously.
if (have_pending_loads_) {
assert(process_pending_work_timer_);
process_pending_work_timer_->SetLength(1000);
process_pending_work_timer_->SetLength(1 * 1000);
} else {
// Otherwise we've got nothing to do; go to sleep until something
// changes.

View File

@ -19,7 +19,7 @@ namespace ballistica::base {
BasePlatformApple::BasePlatformApple() {
// On iOS, keep the device from falling asleep in our app
#if BA_OSTYPE_IOS_TVOS
AppleUtils::DisableIdleTimer();
// AppleUtils::DisableIdleTimer();
#endif
}
@ -41,7 +41,7 @@ void BasePlatformApple::RestorePurchases() {
void BasePlatformApple::PurchaseAck(const std::string& purchase,
const std::string& order_id) {
#if BA_XCODE_BUILD
#if BA_XCODE_BUILD && BA_USE_STORE_KIT
AppleUtils::PurchaseAck(purchase, order_id);
#else
BasePlatform::PurchaseAck(purchase, order_id);

View File

@ -9,7 +9,6 @@
#include "ballistica/base/logic/logic.h"
#include "ballistica/base/python/base_python.h"
#include "ballistica/base/python/support/python_context_call_runnable.h"
#include "ballistica/base/support/stress_test.h"
#include "ballistica/base/ui/dev_console.h"
#include "ballistica/base/ui/ui.h"
#include "ballistica/shared/foundation/event_loop.h"
@ -784,32 +783,6 @@ static PyMethodDef PyEnvDef = {
"This info is now exposed through babase.App; refer to those docs for\n"
"info on specific elements."};
// -------------------------- set_stress_testing -------------------------------
static auto PySetStressTesting(PyObject* self, PyObject* args) -> PyObject* {
BA_PYTHON_TRY;
int enable;
int player_count;
if (!PyArg_ParseTuple(args, "pi", &enable, &player_count)) {
return nullptr;
}
g_base->app_adapter->PushMainThreadCall([enable, player_count] {
g_base->stress_test()->Set(enable, player_count);
});
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PySetStressTestingDef = {
"set_stress_testing", // name
PySetStressTesting, // method
METH_VARARGS, // flags
"set_stress_testing(testing: bool, player_count: int) -> None\n"
"\n"
"(internal)",
};
// -------------------------------- emit_log -----------------------------------
static auto PyEmitLog(PyObject* self, PyObject* args, PyObject* keywds)
@ -1702,7 +1675,6 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
PyCanDisplayFullUnicodeDef,
PyEmitLogDef,
PyV1CloudLogDef,
PySetStressTestingDef,
PyEnvDef,
PyPreEnvDef,
PyCommitConfigDef,

View File

@ -6,6 +6,7 @@
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/graphics.h"
#include "ballistica/base/graphics/support/camera.h"
#include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/graphics/text/text_graphics.h"
#include "ballistica/base/logic/logic.h"
#include "ballistica/base/python/base_python.h"
@ -74,7 +75,7 @@ static auto PyScreenMessage(PyObject* self, PyObject* args, PyObject* keywds)
}
// This version simply displays it locally.
g_base->graphics->AddScreenMessage(message_str, color);
g_base->graphics->screenmessages->AddScreenMessage(message_str, color);
Py_RETURN_NONE;
BA_PYTHON_CATCH;

View File

@ -13,20 +13,22 @@ namespace ballistica::base {
class AppTimer : public Object {
public:
AppTimer(microsecs_t length, bool repeat, Runnable* runnable) {
AppTimer(seconds_t length, bool repeat, Runnable* runnable) {
assert(g_base->InLogicThread());
timer_id_ = base::g_base->logic->NewAppTimer(length, repeat, runnable);
timer_id_ = base::g_base->logic->NewAppTimer(
static_cast<microsecs_t>(length * 1000000.0), repeat, runnable);
}
template <typename F>
static auto New(microsecs_t length, bool repeat, const F& lambda) {
static auto New(seconds_t length, bool repeat, const F& lambda) {
return Object::New<AppTimer>(length, repeat,
NewLambdaRunnable<F>(lambda).Get());
}
void SetLength(microsecs_t length) {
void SetLength(seconds_t length) {
assert(g_base->InLogicThread());
base::g_base->logic->SetAppTimerLength(timer_id_, length);
base::g_base->logic->SetAppTimerLength(
timer_id_, static_cast<microsecs_t>(length * 1000000.0));
}
~AppTimer() override {

View File

@ -13,21 +13,24 @@ namespace ballistica::base {
class DisplayTimer : public Object {
public:
DisplayTimer(microsecs_t length, bool repeat, Runnable* runnable) {
DisplayTimer(seconds_t length, bool repeat, Runnable* runnable) {
assert(g_base->InLogicThread());
timer_id_ = base::g_base->logic->NewDisplayTimer(length, repeat, runnable);
timer_id_ = base::g_base->logic->NewDisplayTimer(
static_cast<microsecs_t>(length * 1000000.0), repeat, runnable);
}
template <typename F>
static auto New(microsecs_t length, bool repeat, const F& lambda) {
static auto New(seconds_t length, bool repeat, const F& lambda) {
return Object::New<DisplayTimer>(length, repeat,
NewLambdaRunnable<F>(lambda).Get());
}
void SetLength(microsecs_t length) {
void SetLength(seconds_t length) {
assert(g_base->InLogicThread());
base::g_base->logic->SetDisplayTimerLength(timer_id_, length);
base::g_base->logic->SetDisplayTimerLength(
timer_id_, static_cast<microsecs_t>(length * 1000000.0));
}
~DisplayTimer() override {
assert(g_base->InLogicThread());
base::g_base->logic->DeleteDisplayTimer(timer_id_);

View File

@ -27,9 +27,8 @@ Repeater::Repeater(seconds_t initial_delay, seconds_t repeat_delay,
return;
}
// Kick off our initial delay timer (generally the longer one).
weak_this->timer_ = DisplayTimer::New(
static_cast<microsecs_t>(weak_this->initial_delay_ * 1000000.0),
false, [weak_this] {
weak_this->timer_ =
DisplayTimer::New(weak_this->initial_delay_, false, [weak_this] {
// Timer should not have fired if we died.
assert(weak_this.Exists());
weak_this->runnable_->RunAndLogErrors();
@ -38,9 +37,8 @@ Repeater::Repeater(seconds_t initial_delay, seconds_t repeat_delay,
return;
}
// Kick off our repeat timer (generally the short one).
weak_this->timer_ = DisplayTimer::New(
static_cast<microsecs_t>(weak_this->repeat_delay_ * 1000000.0),
true, [weak_this] {
weak_this->timer_ =
DisplayTimer::New(weak_this->repeat_delay_, true, [weak_this] {
// Timer should not have fired if we died.
assert(weak_this.Exists());
weak_this->runnable_->RunAndLogErrors();

View File

@ -1,25 +0,0 @@
// Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_BASE_SUPPORT_STRESS_TEST_H_
#define BALLISTICA_BASE_SUPPORT_STRESS_TEST_H_
#include "ballistica/shared/ballistica.h"
namespace ballistica::base {
class StressTest {
public:
void Set(bool enable, int player_count);
void Update();
private:
FILE* stress_test_stats_file_{};
millisecs_t last_stress_test_update_time_{};
bool stress_testing_{};
int stress_test_player_count_{8};
int last_total_frames_rendered_{};
};
} // namespace ballistica::base
#endif // BALLISTICA_BASE_SUPPORT_STRESS_TEST_H_

View File

@ -6,7 +6,6 @@
#include "ballistica/base/app_mode/app_mode.h"
#include "ballistica/base/audio/audio.h"
#include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
#include "ballistica/base/graphics/text/text_graphics.h"
#include "ballistica/base/logic/logic.h"
#include "ballistica/base/platform/base_platform.h"
@ -1299,14 +1298,13 @@ void DevConsole::Draw(FrameDef* frame_def) {
if (!carat_mesh_.Exists()) {
UpdateCarat_();
}
millisecs_t real_time = pass->frame_def()->app_time_millisecs();
if (real_time % 200 < 100
|| (real_time - last_carat_x_change_time_ < 100)) {
millisecs_t app_time = pass->frame_def()->app_time_millisecs();
millisecs_t since_change = app_time - last_carat_x_change_time_;
if (since_change < 300 || since_change % 1000 < 500) {
SimpleComponent c(pass);
c.SetTransparent(true);
c.SetTexture(g_base->assets->SysTexture(SysTextureID::kShadow));
c.SetColor(0.8, 0.0, 1.0, 0.3f);
// c.SetPremultiplied(true);
{
auto xf = c.ScopedTransform();
auto carat_x = GetCaratX_();

View File

@ -2,7 +2,9 @@
#include "ballistica/classic/classic.h"
#include "ballistica/base/support/app_timer.h"
#include "ballistica/classic/python/classic_python.h"
#include "ballistica/classic/support/stress_test.h"
#include "ballistica/classic/support/v1_account.h"
#include "ballistica/core/platform/core_platform.h"
#include "ballistica/scene_v1/python/scene_v1_python.h"
@ -54,7 +56,9 @@ void ClassicFeatureSet::OnModuleExec(PyObject* module) {
}
ClassicFeatureSet::ClassicFeatureSet()
: python{new ClassicPython()}, v1_account{new V1Account()} {
: python{new ClassicPython()},
v1_account{new V1Account()},
stress_test_{new StressTest()} {
// We're a singleton. If there's already one of us, something's wrong.
assert(g_classic == nullptr);
}

View File

@ -28,6 +28,7 @@ namespace ballistica::classic {
// Predeclared types our feature-set provides.
class ClassicFeatureSet;
class ClassicPython;
class StressTest;
class V1Account;
enum class V1AccountType {
@ -107,9 +108,12 @@ class ClassicFeatureSet : public FeatureSetNativeComponent,
void set_v1_account_type(V1AccountType tp) { v1_account_type_ = tp; }
void PlayMusic(const std::string& music_type, bool continuous) override;
auto* stress_test() const { return stress_test_; }
private:
ClassicFeatureSet();
V1AccountType v1_account_type_{V1AccountType::kInvalid};
StressTest* stress_test_;
};
} // namespace ballistica::classic

View File

@ -4,7 +4,10 @@
#include "ballistica/base/graphics/graphics.h"
#include "ballistica/base/graphics/support/camera.h"
#include "ballistica/base/logic/logic.h"
#include "ballistica/classic/support/stress_test.h"
#include "ballistica/scene_v1/support/scene_v1_app_mode.h"
#include "ballistica/shared/foundation/event_loop.h"
#include "ballistica/shared/python/python.h"
#include "ballistica/shared/python/python_sys.h"
@ -145,10 +148,42 @@ static PyMethodDef PyValueTestDef = {
"(internal)",
};
// -------------------------- set_stress_testing -------------------------------
static auto PySetStressTesting(PyObject* self, PyObject* args) -> PyObject* {
BA_PYTHON_TRY;
int enable;
int player_count;
if (!PyArg_ParseTuple(args, "pi", &enable, &player_count)) {
return nullptr;
}
// g_base->app_adapter->PushMainThreadCall([enable, player_count] {
// g_base->stress_test()->Set(enable, player_count);
// });
g_base->logic->event_loop()->PushCall([enable, player_count] {
g_classic->stress_test()->Set(enable, player_count);
});
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PySetStressTestingDef = {
"set_stress_testing", // name
PySetStressTesting, // method
METH_VARARGS, // flags
"set_stress_testing(testing: bool, player_count: int) -> None\n"
"\n"
"(internal)",
};
// -----------------------------------------------------------------------------
auto PythonMethodsClassic::GetMethods() -> std::vector<PyMethodDef> {
return {PyValueTestDef};
return {
PyValueTestDef,
PySetStressTestingDef,
};
}
#pragma clang diagnostic pop

View File

@ -1,15 +1,18 @@
// Released under the MIT License. See LICENSE for details.
#include "ballistica/base/support/stress_test.h"
#include "ballistica/classic/support/stress_test.h"
#include "ballistica/base/graphics/graphics_server.h"
#include "ballistica/base/graphics/renderer/renderer.h"
#include "ballistica/base/input/device/test_input.h"
#include "ballistica/base/input/input.h"
#include "ballistica/base/support/app_timer.h"
#include "ballistica/classic/classic.h"
namespace ballistica::base {
namespace ballistica::classic {
void StressTest::Set(bool enable, int player_count) {
assert(g_core->InMainThread());
assert(g_base->InLogicThread());
bool was_stress_testing = stress_testing_;
stress_testing_ = enable;
stress_test_player_count_ = player_count;
@ -28,17 +31,22 @@ void StressTest::Set(bool enable, int player_count) {
// Assume zero if there's no graphics yet.
last_total_frames_rendered_ = 0;
}
update_timer_ = base::AppTimer::New(1.0 / 30.0, true, [this] { Update(); });
}
if (!stress_testing_) {
update_timer_.Clear();
}
}
void StressTest::Update() {
assert(g_core->InMainThread());
assert(g_base->InLogicThread());
// Handle a little misc stuff here.
// If we're currently running stress-tests, update that stuff.
if (stress_testing_ && g_base->input) {
// Update our fake inputs to make our dudes run around.
g_base->input->ProcessStressTesting(stress_test_player_count_);
ProcessInputs(stress_test_player_count_);
// Every 10 seconds update our stress-test stats.
millisecs_t t = g_core->GetAppTimeMillisecs();
@ -51,10 +59,10 @@ void StressTest::Update() {
stress_test_stats_file_ =
g_core->platform->FOpen(f_name.c_str(), "wb");
if (stress_test_stats_file_ != nullptr) {
fprintf(
stress_test_stats_file_,
"time,averageFps,nodes,meshes,collision_meshes,textures,sounds,"
"pssMem,sharedDirtyMem,privateDirtyMem\n");
fprintf(stress_test_stats_file_,
"time,averageFps,nodes,meshes,collision_meshes,textures,"
"sounds,"
"pssMem,sharedDirtyMem,privateDirtyMem\n");
fflush(stress_test_stats_file_);
}
}
@ -98,4 +106,56 @@ void StressTest::Update() {
}
}
} // namespace ballistica::base
void StressTest::ProcessInputs(int player_count) {
assert(g_base->InLogicThread());
assert(player_count >= 0);
millisecs_t time = g_core->GetAppTimeMillisecs();
// FIXME: If we don't check for stress_test_last_leave_time_ we totally
// confuse the game.. need to be able to survive that.
// Kill some off if we have too many.
while (static_cast<int>(test_inputs_.size()) > player_count) {
delete test_inputs_.front();
test_inputs_.pop_front();
}
// If we have less than full test-inputs, add one randomly.
if (static_cast<int>(test_inputs_.size()) < player_count
&& ((rand() % 1000 < 10))) { // NOLINT
test_inputs_.push_back(new base::TestInput());
}
// Every so often lets kill the oldest one off.
if (explicit_bool(true)) {
if (test_inputs_.size() > 0 && (rand() % 2000 < 3)) { // NOLINT
stress_test_last_leave_time_ = time;
// Usually do oldest; sometimes newest.
if (rand() % 5 == 0) { // NOLINT
delete test_inputs_.back();
test_inputs_.pop_back();
} else {
delete test_inputs_.front();
test_inputs_.pop_front();
}
}
}
if (time - stress_test_time_ > 1000) {
stress_test_time_ = time; // reset..
for (auto& test_input : test_inputs_) {
(*test_input).Reset();
}
}
while (stress_test_time_ < time) {
stress_test_time_++;
for (auto& test_input : test_inputs_) {
(*test_input).Process(stress_test_time_);
}
}
}
} // namespace ballistica::classic

View File

@ -0,0 +1,33 @@
// Released under the MIT License. See LICENSE for details.
#ifndef BALLISTICA_CLASSIC_SUPPORT_STRESS_TEST_H_
#define BALLISTICA_CLASSIC_SUPPORT_STRESS_TEST_H_
#include "ballistica/base/base.h"
#include "ballistica/shared/ballistica.h"
#include "ballistica/shared/foundation/object.h"
namespace ballistica::classic {
class StressTest {
public:
void Set(bool enable, int player_count);
void Update();
private:
void ProcessInputs(int player_count);
std::list<base::TestInput*> test_inputs_;
millisecs_t stress_test_time_{};
millisecs_t stress_test_last_leave_time_{};
int stress_test_player_count_{8};
int last_total_frames_rendered_{};
bool stress_testing_ : 1 {};
millisecs_t last_stress_test_update_time_{};
FILE* stress_test_stats_file_{};
Object::Ref<base::AppTimer> update_timer_{};
};
} // namespace ballistica::classic
#endif // BALLISTICA_CLASSIC_SUPPORT_STRESS_TEST_H_

View File

@ -42,7 +42,8 @@ auto CorePlatformApple::GetRealLegacyDeviceUUID(std::string* uuid) -> bool {
return true;
#endif
#if BA_OSTYPE_IOS_TVOS
*uuid = base::AppleUtils::GetIOSUUID();
*uuid = std::string(BallisticaKit::UIKitFromCpp::GetLegacyDeviceUUID());
// *uuid = base::AppleUtils::GetIOSUUID();
return true;
#endif
return false;
@ -84,7 +85,9 @@ auto CorePlatformApple::GetDeviceUUIDInputs() -> std::list<std::string> {
#endif // BA_OSTYPE_MACOS
#if BA_OSTYPE_IOS_TVOS
out.push_back(base::AppleUtils::GetIOSUUID());
// out.push_back(base::AppleUtils::GetIOSUUID());
out.push_back(
std::string(BallisticaKit::UIKitFromCpp::GetLegacyDeviceUUID()));
#endif
return out;
}
@ -121,7 +124,8 @@ auto CorePlatformApple::DoHasTouchScreen() -> bool {
auto CorePlatformApple::GetDefaultUIScale() -> UIScale {
#if BA_OSTYPE_IOS
if (base::AppleUtils::IsTablet()) {
if (BallisticaKit::UIKitFromCpp::IsTablet()) {
// if (base::AppleUtils::IsTablet()) {
return UIScale::kMedium;
} else {
return UIScale::kSmall;
@ -278,21 +282,21 @@ void CorePlatformApple::ShowOnlineScoreUI(const std::string& show,
#endif
}
auto CorePlatformApple::NewAutoReleasePool() -> void* {
#if BA_XCODE_BUILD
return base::AppleUtils::NewAutoReleasePool();
#else
return CorePlatform::NewAutoReleasePool();
#endif
}
// auto CorePlatformApple::NewAutoReleasePool() -> void* {
// #if BA_XCODE_BUILD
// return base::AppleUtils::NewAutoReleasePool();
// #else
// return CorePlatform::NewAutoReleasePool();
// #endif
// }
void CorePlatformApple::DrainAutoReleasePool(void* pool) {
#if BA_XCODE_BUILD
base::AppleUtils::DrainAutoReleasePool(pool);
#else
CorePlatform::DrainAutoReleasePool(pool);
#endif
}
// void CorePlatformApple::DrainAutoReleasePool(void* pool) {
// #if BA_XCODE_BUILD
// base::AppleUtils::DrainAutoReleasePool(pool);
// #else
// CorePlatform::DrainAutoReleasePool(pool);
// #endif
// }
void CorePlatformApple::GameCenterLogin() {
#if BA_USE_GAME_CENTER
@ -331,50 +335,68 @@ void CorePlatformApple::OpenDirExternally(const std::string& path) {
void CorePlatformApple::MacMusicAppInit() {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
base::AppleUtils::MacMusicAppInit();
BallisticaKit::CocoaFromCpp::MacMusicAppInit();
// base::AppleUtils::MacMusicAppInit();
#else
CorePlatform::MacMusicAppInit();
#endif
}
auto CorePlatformApple::MacMusicAppGetVolume() -> int {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
return static_cast<int>(base::AppleUtils::MacMusicAppGetVolume());
return BallisticaKit::CocoaFromCpp::MacMusicAppGetVolume();
// return static_cast<int>(base::AppleUtils::MacMusicAppGetVolume());
#else
return CorePlatform::MacMusicAppGetVolume();
#endif
}
void CorePlatformApple::MacMusicAppSetVolume(int volume) {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
base::AppleUtils::MacMusicAppSetVolume(volume);
return BallisticaKit::CocoaFromCpp::MacMusicAppSetVolume(volume);
// base::AppleUtils::MacMusicAppSetVolume(volume);
#else
CorePlatform::MacMusicAppSetVolume(volume);
#endif
}
// KILL THIS.
void CorePlatformApple::MacMusicAppGetLibrarySource() {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
base::AppleUtils::MacMusicAppGetLibrarySource();
// base::AppleUtils::MacMusicAppGetLibrarySource();
#else
CorePlatform::MacMusicAppGetLibrarySource();
#endif
}
void CorePlatformApple::MacMusicAppStop() {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
base::AppleUtils::MacMusicAppStop();
return BallisticaKit::CocoaFromCpp::MacMusicAppStop();
// base::AppleUtils::MacMusicAppStop();
#else
CorePlatform::MacMusicAppStop();
#endif
}
auto CorePlatformApple::MacMusicAppPlayPlaylist(const std::string& playlist)
-> bool {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
return base::AppleUtils::MacMusicAppPlayPlaylist(playlist.c_str());
return BallisticaKit::CocoaFromCpp::MacMusicAppPlayPlaylist(playlist);
// return base::AppleUtils::MacMusicAppPlayPlaylist(playlist.c_str());
#else
return CorePlatform::MacMusicAppPlayPlaylist(playlist);
#endif
}
auto CorePlatformApple::MacMusicAppGetPlaylists() -> std::list<std::string> {
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
return base::AppleUtils::MacMusicAppGetPlaylists();
BallisticaKit::CocoaFromCpp::MacMusicAppGetPlaylists();
// mac_music_app_playlists_.clear();
// mac_music_app_playlists_.push_back("foof");
// mac_music_app_playlists_.push_back("barf");
// std::list<std::string> out;
// for (auto&& val : vals) {
// out.push_back(std::string(val));
// }
// return out;
return mac_music_app_playlists();
#else
return CorePlatform::MacMusicAppGetPlaylists();
#endif

View File

@ -42,8 +42,8 @@ class CorePlatformApple : public CorePlatform {
-> bool override;
void ShowOnlineScoreUI(const std::string& show, const std::string& game,
const std::string& game_version) override;
auto NewAutoReleasePool() -> void* override;
void DrainAutoReleasePool(void* pool) override;
// auto NewAutoReleasePool() -> void* override;
// void DrainAutoReleasePool(void* pool) override;
void ResetAchievements() override;
void GameCenterLogin() override;
auto IsOSPlayingMusic() -> bool override;
@ -63,8 +63,6 @@ class CorePlatformApple : public CorePlatform {
protected:
auto DoGetDataDirectoryMonolithicDefault() -> std::string override;
private:
};
} // namespace ballistica::core

View File

@ -721,9 +721,9 @@ auto CorePlatform::DemangleCXXSymbol(const std::string& s) -> std::string {
#endif
}
auto CorePlatform::NewAutoReleasePool() -> void* { throw Exception(); }
// auto CorePlatform::NewAutoReleasePool() -> void* { throw Exception(); }
void CorePlatform::DrainAutoReleasePool(void* pool) { throw Exception(); }
// void CorePlatform::DrainAutoReleasePool(void* pool) { throw Exception(); }
void CorePlatform::ResetAchievements() {
Log(LogLevel::kError, "ResetAchievements() unimplemented");

View File

@ -205,8 +205,8 @@ class CorePlatform {
#pragma mark APPLE -------------------------------------------------------------
virtual auto NewAutoReleasePool() -> void*;
virtual void DrainAutoReleasePool(void* pool);
// virtual auto NewAutoReleasePool() -> void*;
// virtual void DrainAutoReleasePool(void* pool);
// FIXME: Can we consolidate these with the general music playback calls?
virtual void MacMusicAppInit();
virtual auto MacMusicAppGetVolume() -> int;
@ -396,6 +396,11 @@ class CorePlatform {
/// Are we being run from a terminal? (should we show prompts, etc?).
auto is_stdin_a_terminal() const { return is_stdin_a_terminal_; }
void set_music_app_playlists(const std::list<std::string>& playlists) {
mac_music_app_playlists_ = playlists;
}
auto mac_music_app_playlists() const { return mac_music_app_playlists_; }
protected:
/// Are we being run from a terminal? (should we show prompts, etc?).
virtual auto GetIsStdinATerminal() -> bool;
@ -445,7 +450,6 @@ class CorePlatform {
/// 'noteworthy' or presented to the user as standard Log() calls are.
virtual void HandleDebugLog(const std::string& msg);
protected:
CorePlatform();
virtual ~CorePlatform();
@ -462,6 +466,9 @@ class CorePlatform {
std::string legacy_device_uuid_;
std::string volatile_data_dir_;
std::string replays_dir_;
// temp.
std::list<std::string> mac_music_app_playlists_;
};
/// For capturing and printing stack-traces and related errors. Platforms

View File

@ -6,6 +6,7 @@
#include "ballistica/base/dynamics/bg/bg_dynamics.h"
#include "ballistica/base/graphics/graphics.h"
#include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/python/base_python.h"
#include "ballistica/base/python/class/python_class_simple_sound.h"
#include "ballistica/base/python/support/python_context_call_runnable.h"
@ -755,7 +756,7 @@ static auto PyBroadcastMessage(PyObject* self, PyObject* args, PyObject* keywds)
}
// Now display it locally.
g_base->graphics->AddScreenMessage(
g_base->graphics->screenmessages->AddScreenMessage(
message, color, static_cast<bool>(top),
texture ? texture->texture_data() : nullptr,
tint_texture ? tint_texture->texture_data() : nullptr, tint_color,

View File

@ -5,6 +5,7 @@
#include "ballistica/base/audio/audio.h"
#include "ballistica/base/dynamics/bg/bg_dynamics.h"
#include "ballistica/base/graphics/graphics.h"
#include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/networking/networking.h"
#include "ballistica/scene_v1/assets/scene_collision_mesh.h"
#include "ballistica/scene_v1/assets/scene_mesh.h"
@ -819,7 +820,7 @@ void ClientSession::Update(int time_advance_millisecs, double time_advance) {
std::string s = ReadString();
float f[9];
ReadFloats(9, f);
g_base->graphics->AddScreenMessage(
g_base->graphics->screenmessages->AddScreenMessage(
s, Vector3f(f[0], f[1], f[2]), true, texture->texture_data(),
tint_texture->texture_data(), Vector3f(f[3], f[4], f[5]),
Vector3f(f[6], f[7], f[8]));

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21531;
const int kEngineBuildNumber = 21543;
const char* kEngineVersion = "1.7.28";
const int kEngineApiVersion = 8;

View File

@ -251,24 +251,24 @@ void EventLoop::WaitForNextEvent_(bool single_cycle) {
// Note to self (Oct '23): can probably kill this at some point,
// but am still using some non-ARC objc stuff from logic thread
// so should keep it around just a bit longer just in case.
void EventLoop::LoopUpkeep_(bool single_cycle) {
assert(g_core);
// Keep our autorelease pool clean on mac/ios
// FIXME: Should define a CorePlatform::ThreadHelper or something
// so we don't have platform-specific code here.
#if BA_XCODE_BUILD
// Let's not do autorelease pools when being called ad-hoc,
// since in that case we're part of another run loop
// (and its crashing on drain for some reason)
if (!single_cycle) {
if (auto_release_pool_) {
g_core->platform->DrainAutoReleasePool(auto_release_pool_);
auto_release_pool_ = nullptr;
}
auto_release_pool_ = g_core->platform->NewAutoReleasePool();
}
#endif
}
// void EventLoop::LoopUpkeep_(bool single_cycle) {
// assert(g_core);
// // Keep our autorelease pool clean on mac/ios
// // FIXME: Should define a CorePlatform::ThreadHelper or something
// // so we don't have platform-specific code here.
// #if BA_XCODE_BUILD
// // Let's not do autorelease pools when being called ad-hoc,
// // since in that case we're part of another run loop
// // (and its crashing on drain for some reason)
// if (!single_cycle) {
// if (auto_release_pool_) {
// g_core->platform->DrainAutoReleasePool(auto_release_pool_);
// auto_release_pool_ = nullptr;
// }
// auto_release_pool_ = g_core->platform->NewAutoReleasePool();
// }
// #endif
//}
void EventLoop::RunToCompletion() { Run_(false); }
void EventLoop::RunSingleCycle() { Run_(true); }
@ -276,7 +276,7 @@ void EventLoop::RunSingleCycle() { Run_(true); }
void EventLoop::Run_(bool single_cycle) {
assert(g_core);
while (true) {
LoopUpkeep_(single_cycle);
// LoopUpkeep_(single_cycle);
WaitForNextEvent_(single_cycle);

View File

@ -149,11 +149,11 @@ class EventLoop {
void BootstrapThread_();
void LoopUpkeep_(bool single_cycle);
// void LoopUpkeep_(bool single_cycle);
// FIXME: Should generalize this to some sort of PlatformThreadData class.
#if BA_XCODE_BUILD
void* auto_release_pool_{};
// void* auto_release_pool_{};
#endif
EventLoopID identifier_{EventLoopID::kInvalid};

View File

@ -57,7 +57,7 @@ void ButtonWidget::OnRepeatTimerExpired() {
DoActivate(true);
// Speed up repeats after the first.
repeat_timer_->SetLength(150);
repeat_timer_->SetLength(0.150);
} else {
repeat_timer_.Clear();
}
@ -165,7 +165,9 @@ void ButtonWidget::Draw(base::RenderPass* pass, bool draw_transparent) {
// Account for our icon if we have it.
float s_width_available = std::max(30.0f, width_ - 30);
if (show_icons) s_width_available -= (34.0f * icon_scale_);
if (show_icons) {
s_width_available -= (34.0f * icon_scale_);
}
if ((string_width * string_scale) > s_width_available) {
float squish_scale = s_width_available / (string_width * string_scale);
@ -486,7 +488,7 @@ auto ButtonWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
if (repeat_) {
repeat_timer_ = base::AppTimer::New(
300, true, [this] { OnRepeatTimerExpired(); });
0.3, true, [this] { OnRepeatTimerExpired(); });
// If we're a repeat button we trigger immediately.
// (waiting till mouse up sort of defeats the purpose here)

View File

@ -406,7 +406,7 @@ auto HScrollWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
// scrolling has started.
if (static_cast<int>(m.type)) {
touch_delay_timer_ = base::AppTimer::New(
150, false, [this] { OnTouchDelayTimerExpired(); });
0.150, false, [this] { OnTouchDelayTimerExpired(); });
}
// If we're handling a scroll-touch, take note that we need to

View File

@ -331,7 +331,7 @@ auto ScrollWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
// click if it hasn't turned into a scroll or a child scroll.
if (!child_is_scrolling_) {
touch_delay_timer_ = base::AppTimer::New(
150, false, [this] { OnTouchDelayTimerExpired(); });
0.150, false, [this] { OnTouchDelayTimerExpired(); });
}
}
}

View File

@ -60,8 +60,15 @@ class Pruner:
entries = self._get_entries()
processed_paths = set[str]()
with tempfile.TemporaryDirectory() as tempdir:
for entry in entries:
# Entries list might have repeats.
if entry.file in processed_paths:
continue
processed_paths.add(entry.file)
if not entry.file.startswith(cwd):
raise CleanError(
f'compile-commands file {entry.file}'

View File

@ -50,7 +50,7 @@ def update_xcode_project(
for p in all_source_files
if os.path.splitext(p)[1] in suffixes
),
has_app_delegate_mm=True,
# has_app_delegate_mm=True,
projname=projname,
)
else:
@ -64,7 +64,7 @@ def update_xcode_project(
for p in all_source_files
if os.path.splitext(p)[1] in suffixes
),
has_app_delegate_mm=True,
# has_app_delegate_mm=True,
projname=projname,
)
@ -83,7 +83,7 @@ class Updater:
existing_data: str,
sources: list[str],
projname: str,
has_app_delegate_mm: bool = False,
# has_app_delegate_mm: bool = False,
) -> None:
if not path.endswith('.xcodeproj'):
raise RuntimeError(f"Path does not end in .xcodeproj: '{path}'.")
@ -93,7 +93,7 @@ class Updater:
self.existing_data = existing_data
self.sources = sources
self.project = None
self.has_app_delegate_mm = has_app_delegate_mm
# self.has_app_delegate_mm = has_app_delegate_mm
# Project name variations.
self.pnameu = projname
@ -165,8 +165,8 @@ class Updater:
srcgrp = self._get_unique_group(f'{self.pnameu} Shared')
self.add_paths(srcgrp)
if self.has_app_delegate_mm:
self.mod_app_delegate_mm()
# if self.has_app_delegate_mm:
# self.mod_app_delegate_mm()
# Groups we made should be sorted already since we sorted while
# building them, but let's sort the top level group we placed
@ -302,6 +302,7 @@ class Updater:
)
return grps[0]
# (No longer used; just leaving here as reference though)
def mod_app_delegate_mm(self) -> None:
"""Set per-file compiler flags."""
files = self.project.get_files_by_name('app_delegate.mm')