mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-26 17:03:14 +08:00
Merge branch 'master' into master
This commit is contained in:
commit
0224e2a0da
92
.efrocachemap
generated
92
.efrocachemap
generated
@ -421,21 +421,21 @@
|
||||
"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": "fae88cbb2a5b9c24096f2e43452114a2",
|
||||
"build/assets/ba_data/data/langdata.json": "e71fd5c04d15c544dc15bc15bbe0798a",
|
||||
"build/assets/ba_data/data/languages/arabic.json": "0db32e21b6d5337ccca478381744aa88",
|
||||
"build/assets/ba_data/data/languages/belarussian.json": "a112dfca3e188387516788bd8229c5b0",
|
||||
"build/assets/ba_data/data/languages/chinese.json": "ff9a595726f0aff42a39be576d0ff037",
|
||||
"build/assets/ba_data/data/languages/chinesetraditional.json": "f858da49be0a5374157c627857751078",
|
||||
"build/assets/ba_data/data/languages/chinese.json": "93f3ca9f90d86dc7c8d0923f5f11ef46",
|
||||
"build/assets/ba_data/data/languages/chinesetraditional.json": "319565f8a15667488f48dbce59278e39",
|
||||
"build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa",
|
||||
"build/assets/ba_data/data/languages/czech.json": "c9d518a324870066b987b8f412881dd3",
|
||||
"build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e",
|
||||
"build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e",
|
||||
"build/assets/ba_data/data/languages/english.json": "2434e127b6788e3128d3523fcb1b8994",
|
||||
"build/assets/ba_data/data/languages/dutch.json": "5cbf1a68a9d93dee00dbc27f834d878a",
|
||||
"build/assets/ba_data/data/languages/english.json": "1c4037fea1066d39d6eced419f314f35",
|
||||
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
|
||||
"build/assets/ba_data/data/languages/filipino.json": "e750fb1a95e4c5611115f9ece9ecab53",
|
||||
"build/assets/ba_data/data/languages/french.json": "163362f7b33866ef069cae62d0387551",
|
||||
"build/assets/ba_data/data/languages/filipino.json": "f897776672925499ecda8960b3aae607",
|
||||
"build/assets/ba_data/data/languages/french.json": "8bc35eb4b20a0b30c3348bcc9a3844a6",
|
||||
"build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad",
|
||||
"build/assets/ba_data/data/languages/gibberish.json": "e24d391c9fd12f9afa92f7ff65a06d23",
|
||||
"build/assets/ba_data/data/languages/gibberish.json": "b461539243e8efe3137137b886256ba7",
|
||||
"build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3",
|
||||
"build/assets/ba_data/data/languages/hindi.json": "8848f6b0caec0fcf9d85bc6e683809ec",
|
||||
"build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e",
|
||||
@ -450,13 +450,13 @@
|
||||
"build/assets/ba_data/data/languages/russian.json": "9d0b40586301a82e532c4a250d5f6d58",
|
||||
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
|
||||
"build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef",
|
||||
"build/assets/ba_data/data/languages/spanish.json": "42f857c40dbd4b637e3866849489f7d1",
|
||||
"build/assets/ba_data/data/languages/spanish.json": "8d43556cb55cdfa4408fd19a4646b824",
|
||||
"build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac",
|
||||
"build/assets/ba_data/data/languages/tamil.json": "b4de1a2851afe4869c82e9acd94cd89c",
|
||||
"build/assets/ba_data/data/languages/thai.json": "77755219bbf5fb7eea0d6b226684f403",
|
||||
"build/assets/ba_data/data/languages/turkish.json": "ab149ebbd57cf4daa3cf8f310d91519a",
|
||||
"build/assets/ba_data/data/languages/ukrainian.json": "e5c861187c4c6db37d1a033f4ef3dd5a",
|
||||
"build/assets/ba_data/data/languages/venetian.json": "a559a5608d2e0b4708f7a4dee42ff354",
|
||||
"build/assets/ba_data/data/languages/turkish.json": "72fac3a6fd13ebb74fb4d68b9323e7d4",
|
||||
"build/assets/ba_data/data/languages/ukrainian.json": "b54a38e93deebafa5706ba2d1f626892",
|
||||
"build/assets/ba_data/data/languages/venetian.json": "8e9714d98a85e428ce3543fc49188a46",
|
||||
"build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba",
|
||||
"build/assets/ba_data/data/maps/big_g.json": "1dd301d490643088a435ce75df971054",
|
||||
"build/assets/ba_data/data/maps/bridgit.json": "6aea74805f4880cc11237c5734a24422",
|
||||
@ -1528,9 +1528,9 @@
|
||||
"build/assets/ba_data/textures/fontBig.ktx": "94b56c2488d6c9ebabfbbb740eca07dd",
|
||||
"build/assets/ba_data/textures/fontBig.pvr": "dff3f6c04a8c7b0bb937001640b42c8d",
|
||||
"build/assets/ba_data/textures/fontBig_preview.png": "f8b15cb04f0deca7774def335a72f053",
|
||||
"build/assets/ba_data/textures/fontExtras.dds": "0a5a39028853c443cd88bc2492cb6ad9",
|
||||
"build/assets/ba_data/textures/fontExtras.ktx": "5b14075ce3d1d29c6d5635602e2176d8",
|
||||
"build/assets/ba_data/textures/fontExtras.pvr": "8cc68ca85ba327c20c45bad73b000d8c",
|
||||
"build/assets/ba_data/textures/fontExtras.dds": "d2d20fdde7c6114925ba626ade35151f",
|
||||
"build/assets/ba_data/textures/fontExtras.ktx": "2dde1a343493a9329792d7042116d301",
|
||||
"build/assets/ba_data/textures/fontExtras.pvr": "80ab1f61fafba22ce0259177944beabf",
|
||||
"build/assets/ba_data/textures/fontExtras2.dds": "18063a12912dadc9528afd90d1cf2369",
|
||||
"build/assets/ba_data/textures/fontExtras2.ktx": "36da7f6cfbfb8d32fb14371de0a8f660",
|
||||
"build/assets/ba_data/textures/fontExtras2.pvr": "7a4e8e64ac05313b1782fb5b958150d0",
|
||||
@ -1543,7 +1543,7 @@
|
||||
"build/assets/ba_data/textures/fontExtras4.ktx": "6d872ac15e2e874c1252f63b4584722b",
|
||||
"build/assets/ba_data/textures/fontExtras4.pvr": "6a0a0a1a8bbbc3ee9d6b8b914e7aa697",
|
||||
"build/assets/ba_data/textures/fontExtras4_preview.png": "363e2647621917b3821c9068267d2516",
|
||||
"build/assets/ba_data/textures/fontExtras_preview.png": "b6503267cc15e9e2524f41fabd94e773",
|
||||
"build/assets/ba_data/textures/fontExtras_preview.png": "182e41ed4042207404a95e17efbdcee7",
|
||||
"build/assets/ba_data/textures/fontSmall0.dds": "b30bfe5f9e436be7be8b5eae6e8490c3",
|
||||
"build/assets/ba_data/textures/fontSmall0.ktx": "7e6058f37e6c5a4ea628f35b5f92c227",
|
||||
"build/assets/ba_data/textures/fontSmall0.pvr": "c66e3d6aa1f7def83aaacd8a6c9185e5",
|
||||
@ -4060,26 +4060,26 @@
|
||||
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
||||
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
||||
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "5f7e668a6a904ba8c0fe391654a8211b",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "77cd63dbc1760a3d1bb55753794701b0",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9f674a5b767f798b350ef30d84968d44",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "84546f0452561d3f6519d296a9e9b2ca",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "3122dbce63fb248c9ebe66d545be8480",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4004c01a3ea1a7b62544f08f14e76f9e",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "cd9b5b9ae925cef7417d2b86fd0f0489",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "35c2b307e5d228b105315b8d022d31d2",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "90993c873a2d1ca7b593992e52b1865a",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "46119cb9ff99629ca16471f51032bac7",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "8cac6eff8eb4f9e453a669b6f239b8a5",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "3e20c91bf8948354a0e167faa5c184e9",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "52ff216e1b0394a07bf178b8eea8c269",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "32d85cc58ade8e7a63dfb604ef175553",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "fdf3da5251bc0d3b8f4e5a5b2e0d4b94",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "c03afc18b7aa72ab065381be985f48ae",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "67a58d483ac028f9fc59112b59463a99",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "0800d71a41320664bacba49822e8b442",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9019d9b48cefa45a7a16bae6bd696896",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "90eca6cc81b0a2c39fd1d41d0d029f04",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "c5e053c4b83c085c21f7445f7d53cb7c",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "2a4ba9065e50bf327b0fc582007ad6ed",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "683b185c89662b0b751a42906464e386",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "a3c6c3ac394ba54117930e1c7aea1812",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "e3fda2b9dad14b6919ea97a61d21489b",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "e5343c505d4c2f1b3b547e867dab3d41",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "6a723038a6157d810cb6c9d7a921826a",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "39ff22b4a24581bca7c2918b4d10c691",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "abb2c71fa426bc836f38b661afb5e3f7",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "aff057b7be5f10c3e87fb71739bd786b",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "c4a32ca21b1621239378d689068015dd",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "41854e470df59e6cace772a620a915ac",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f4acd58fdcb43cc5ad104c6530240f4e",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "a0939128bbd12ebddd19691cbd2a8bdb",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "9a9aadd78d7dc65663e622e6f41ca944",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "5cbd8b0b2a33bfc132b24ebe0798c732",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "339ac97c0591caf6f78f2c9712b1ea19",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "8411b4ae387975f17d1f255e879fbd9c",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "364cbe9a490300dc423e76be2dadd32f",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "a186829073b2a809be8e7505477b7108",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "db535f0ca1e01af825f75f204fbc8928",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "97d51afca996ae15b61fd9f409a00459",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "db535f0ca1e01af825f75f204fbc8928",
|
||||
@ -4096,21 +4096,21 @@
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "452623f0495dd4375e5b5d9b80d643d5",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "ca49b32ed573feea11613d62cd89840c",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "452623f0495dd4375e5b5d9b80d643d5",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "ff81e6eeea861f59e71db628bc64918b",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "ba89e5949d1cdf2b857089feb901285c",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "5e063f8acc0e0e9f35f82480d7dbf143",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "1f0d14fcc16dd0d4896d91c75e32be25",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "251d3dd0bc9a6418eb1cb5176bb5509c",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "96c003edb87b3f506d1b15af461487c3",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "274ebd634f05b23653719ef973119cf5",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "796edace73f874ebf46054b2a1ff0ba1",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "3981a2a3291a86349f99626b35a76a56",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "fdfe72ba7bcb6b2cbcedf144dce4fa44",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "b2178a56d5395f61cc33a70b50d87506",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "7869a7a14c57859529fd564c4a8ad1b1",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "6f244022dc28a358eec48524ab04e810",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "94906a8bee71a52820ae294f5267c5bc",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "a61ddb3fc5375e948612d19f282b00c1",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "abc867cddab0f02c74e0a39a866d58cc",
|
||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
|
||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "97efb93f4bfd8e8b09f2db24398e29fc",
|
||||
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",
|
||||
"src/ballistica/core/mgen/pyembed/binding_core.inc": "9d0a3c9636138e35284923e0c8311c69",
|
||||
"src/ballistica/core/mgen/pyembed/env.inc": "8be46e5818f360d10b7b0224a9e91d07",
|
||||
"src/ballistica/core/mgen/pyembed/env.inc": "f015d726b44d2922112fc14d9f146d8b",
|
||||
"src/ballistica/core/mgen/python_modules_monolithic.h": "fb967ed1c7db0c77d8deb4f00a7103c5",
|
||||
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "c25b263f2a31fb5ebe057db07d144879",
|
||||
"src/ballistica/template_fs/mgen/pyembed/binding_template_fs.inc": "44a45492db057bf7f7158c3b0fa11f0f",
|
||||
|
||||
28
CHANGELOG.md
28
CHANGELOG.md
@ -1,6 +1,18 @@
|
||||
### 1.7.33 (build 21743, api 8, 2023-12-21)
|
||||
### 1.7.33 (build 21756, api 8, 2024-01-05)
|
||||
- Exposed an override for `bascenev1.Session`'s max players on servers (by EraOSBeta)
|
||||
- Added UI for customizing teams and FFA series length (by EraOSBeta, idea by 3alTemp)
|
||||
- Stress test input-devices are now a bit smarter; they won't press any buttons
|
||||
while UIs are up (this could cause lots of chaos if it happened).
|
||||
- Added a 'Show Demos When Idle' option in advanced settings. If enabled, the
|
||||
game will show gameplay demos (a slightly modified form of the stress test)
|
||||
periodically after sitting idle at the main menu for a bit. Like an old arcade
|
||||
game. I added this for an upcoming conference appearance but though people
|
||||
might like to enable it in other cases.
|
||||
- Replays now have a play/pause button alongside the speed adjustment buttons
|
||||
(Thanks vishal332008!)
|
||||
- Players now get points for killing bots with their own bombs by catching it
|
||||
and throwing it back at them. This is actually old logic but was disabled due
|
||||
to a logic flaw, but should be fixed now. (Thanks VinniTR!)
|
||||
|
||||
### 1.7.32 (build 21741, api 8, 2023-12-20)
|
||||
- Fixed a screen message that no one will ever see (Thanks vishal332008?...)
|
||||
@ -478,7 +490,7 @@
|
||||
you run into any problems because of this and we can make an option to use the
|
||||
old behavior where Ballistica's app and site paths get placed at the end.
|
||||
- It is now possible to manually run the app loop even on monolithic builds;
|
||||
just do `PYTHONPATH=ba_data/python ./ballisticacore -c "import baenv;
|
||||
just do `PYTHONPATH=ba_data/python ./ballisticakit -c "import baenv;
|
||||
baenv.configure(); import babase; babase.app.run()"`. This is basically the
|
||||
same thing modular builds are doing except that they use a regular Python
|
||||
interpreter instead of the ballisticakit binary.
|
||||
@ -809,7 +821,7 @@
|
||||
future, the default BallisticaKit app may be expanded with editing
|
||||
functionality and I feel the name 'Kit' fits better for something used that
|
||||
way than 'Core' does.
|
||||
- The `ballisticakit_internal` precompiled library has been renamed to
|
||||
- The `ballisticacore_internal` precompiled library has been renamed to
|
||||
`ballistica_plus`. This name better describes what it actually is (basically
|
||||
precompiled native portion of the `plus` feature set). Also by removing the
|
||||
'kit' from the end it will no longer be renamed in spinoff projects, meaning
|
||||
@ -1561,7 +1573,7 @@
|
||||
`prefab-gui-debug` (more consistent with the existing `prefab-server-debug`
|
||||
targets).
|
||||
- Windows builds now go to build/windows instead of
|
||||
`ballisticakit_windows/build`.
|
||||
`ballisticacore_windows/build`.
|
||||
- Lots of project reorganization to allow things such as documentation or the
|
||||
dummy `_ba.py` module to be rebuilt from the public repo.
|
||||
- Added network flood attack mitigation.
|
||||
@ -2217,7 +2229,7 @@
|
||||
|
||||
### 1.4.111 (14286)
|
||||
|
||||
- BallisticaKit Pro now unlocks 2 additional characters
|
||||
- BombSquad Pro now unlocks 2 additional characters
|
||||
- multi-line chat messages are now clamped down to 1 line; should prevent
|
||||
annoying multi-line fullscreen message spam
|
||||
|
||||
@ -2294,7 +2306,7 @@
|
||||
### 1.4.95 (14236)
|
||||
|
||||
- added a port option to the config, so it's now possible to host multiple
|
||||
parties on one machine (note that ballisticakit 1.4.95+ is required to connect
|
||||
parties on one machine (note that bombsquad 1.4.95+ is required to connect
|
||||
ports aside from 43210)
|
||||
|
||||
### 1.4.95 (14234)
|
||||
@ -2304,14 +2316,14 @@
|
||||
|
||||
### 1.4.95 (14233)
|
||||
|
||||
- ballisticakit (both `bs_headless` and regular) now reads commands from
|
||||
- bombsquad (both `bs_headless` and regular) now reads commands from
|
||||
standard input, making it easier to run commands via scripts or the terminal
|
||||
- server now runs using a 'server' account-type instead of the local 'device'
|
||||
account. (avoids daily-ticket-reward messages and other stuff that's not
|
||||
relevant to servers)
|
||||
- the server script now passes args to the game as a json file instead of
|
||||
individual args; this should keep things cleaner and more expandable
|
||||
- the `ballisticakit_server` script also now reads commands from stdin, allowing
|
||||
- the `bombsquad_server` script also now reads commands from stdin, allowing
|
||||
reconfiguring server settings on the fly
|
||||
- added more options such as the ability to set game series lengths and to host
|
||||
a non-public party
|
||||
|
||||
@ -76,8 +76,8 @@ play some games. Or make them. Maybe both.
|
||||
of what's planned for when. And for the record, the answer to that particular
|
||||
question is basically '1.8'.
|
||||
|
||||
* **Q: When will BombSquad be released on iOS / Steam / Switch / XBox /
|
||||
Playstation / My Toaster??**
|
||||
* **Q: When will BombSquad be released on iOS / Steam / Switch / Xbox /
|
||||
PlayStation / My toaster??**
|
||||
* A: The 2.0 update will be the big 'relaunch' release and the plan is to
|
||||
launch on at least iOS and Steam at that time. I'm trying to get there as fast
|
||||
as I can. As far as consoles, I'd love to and hope to at some point but have
|
||||
|
||||
@ -48,6 +48,7 @@ from _babase import (
|
||||
fatal_error,
|
||||
get_display_resolution,
|
||||
get_immediate_return_code,
|
||||
get_input_idle_time,
|
||||
get_low_level_config_value,
|
||||
get_max_graphics_quality,
|
||||
get_replays_dir,
|
||||
@ -236,6 +237,7 @@ __all__ = [
|
||||
'garbage_collect',
|
||||
'get_display_resolution',
|
||||
'get_immediate_return_code',
|
||||
'get_input_idle_time',
|
||||
'get_ip_address_type',
|
||||
'get_low_level_config_value',
|
||||
'get_max_graphics_quality',
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import babase
|
||||
@ -48,64 +49,74 @@ def run_cpu_benchmark() -> None:
|
||||
bascenev1.new_host_session(BenchmarkSession, benchmark_type='cpu')
|
||||
|
||||
|
||||
@dataclass
|
||||
class _StressTestArgs:
|
||||
playlist_type: str
|
||||
playlist_name: str
|
||||
player_count: int
|
||||
round_duration: int
|
||||
attract_mode: bool
|
||||
|
||||
|
||||
def run_stress_test(
|
||||
playlist_type: str = 'Random',
|
||||
playlist_name: str = '__default__',
|
||||
player_count: int = 8,
|
||||
round_duration: int = 30,
|
||||
attract_mode: bool = False,
|
||||
) -> None:
|
||||
"""Run a stress test."""
|
||||
|
||||
babase.screenmessage(
|
||||
"Beginning stress test.. use 'End Test' to stop testing.",
|
||||
color=(1, 1, 0),
|
||||
)
|
||||
with babase.ContextRef.empty():
|
||||
start_stress_test(
|
||||
{
|
||||
'playlist_type': playlist_type,
|
||||
'playlist_name': playlist_name,
|
||||
'player_count': player_count,
|
||||
'round_duration': round_duration,
|
||||
}
|
||||
if not attract_mode:
|
||||
babase.screenmessage(
|
||||
"Beginning stress test.. use 'End Test' to stop testing.",
|
||||
color=(1, 1, 0),
|
||||
)
|
||||
_start_stress_test(
|
||||
_StressTestArgs(
|
||||
playlist_type=playlist_type,
|
||||
playlist_name=playlist_name,
|
||||
player_count=player_count,
|
||||
round_duration=round_duration,
|
||||
attract_mode=attract_mode,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def stop_stress_test() -> None:
|
||||
"""End a running stress test."""
|
||||
|
||||
_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:
|
||||
babase.screenmessage('Ending stress test...', color=(1, 1, 0))
|
||||
except Exception:
|
||||
pass
|
||||
babase.app.classic.stress_test_reset_timer = None
|
||||
|
||||
_baclassic.set_stress_testing(False, 0, False)
|
||||
babase.app.classic.stress_test_update_timer = None
|
||||
babase.app.classic.stress_test_update_timer_2 = None
|
||||
|
||||
|
||||
def start_stress_test(args: dict[str, Any]) -> None:
|
||||
def _start_stress_test(args: _StressTestArgs) -> None:
|
||||
"""(internal)"""
|
||||
from bascenev1 import DualTeamSession, FreeForAllSession
|
||||
|
||||
assert babase.app.classic is not None
|
||||
|
||||
appconfig = babase.app.config
|
||||
playlist_type = args['playlist_type']
|
||||
playlist_type = args.playlist_type
|
||||
if playlist_type == 'Random':
|
||||
if random.random() < 0.5:
|
||||
playlist_type = 'Teams'
|
||||
else:
|
||||
playlist_type = 'Free-For-All'
|
||||
babase.screenmessage(
|
||||
'Running Stress Test (listType="'
|
||||
+ playlist_type
|
||||
+ '", listName="'
|
||||
+ args['playlist_name']
|
||||
+ '")...'
|
||||
)
|
||||
if not args.attract_mode:
|
||||
babase.screenmessage(
|
||||
'Running Stress Test (listType="'
|
||||
+ playlist_type
|
||||
+ '", listName="'
|
||||
+ args.playlist_name
|
||||
+ '")...'
|
||||
)
|
||||
if playlist_type == 'Teams':
|
||||
appconfig['Team Tournament Playlist Selection'] = args['playlist_name']
|
||||
appconfig['Team Tournament Playlist Selection'] = args.playlist_name
|
||||
appconfig['Team Tournament Playlist Randomize'] = 1
|
||||
babase.apptimer(
|
||||
1.0,
|
||||
@ -115,7 +126,7 @@ def start_stress_test(args: dict[str, Any]) -> None:
|
||||
),
|
||||
)
|
||||
else:
|
||||
appconfig['Free-for-All Playlist Selection'] = args['playlist_name']
|
||||
appconfig['Free-for-All Playlist Selection'] = args.playlist_name
|
||||
appconfig['Free-for-All Playlist Randomize'] = 1
|
||||
babase.apptimer(
|
||||
1.0,
|
||||
@ -124,19 +135,38 @@ def start_stress_test(args: dict[str, Any]) -> None:
|
||||
babase.Call(bascenev1.new_host_session, FreeForAllSession),
|
||||
),
|
||||
)
|
||||
_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)
|
||||
_baclassic.set_stress_testing(True, args.player_count, args.attract_mode)
|
||||
babase.app.classic.stress_test_update_timer = babase.AppTimer(
|
||||
args.round_duration, babase.Call(_reset_stress_test, args)
|
||||
)
|
||||
if args.attract_mode:
|
||||
babase.app.classic.stress_test_update_timer_2 = babase.AppTimer(
|
||||
0.48, babase.Call(_update_attract_mode_test, args), repeat=True
|
||||
)
|
||||
|
||||
|
||||
def _reset_stress_test(args: dict[str, Any]) -> None:
|
||||
_baclassic.set_stress_testing(False, args['player_count'])
|
||||
babase.screenmessage('Resetting stress test...')
|
||||
def _update_attract_mode_test(args: _StressTestArgs) -> None:
|
||||
if babase.get_input_idle_time() < 5.0:
|
||||
_reset_stress_test(args)
|
||||
|
||||
|
||||
def _reset_stress_test(args: _StressTestArgs) -> None:
|
||||
_baclassic.set_stress_testing(False, args.player_count, False)
|
||||
if not args.attract_mode:
|
||||
babase.screenmessage('Resetting stress test...')
|
||||
session = bascenev1.get_foreground_host_session()
|
||||
assert session is not None
|
||||
session.end()
|
||||
babase.apptimer(1.0, babase.Call(start_stress_test, args))
|
||||
|
||||
assert babase.app.classic is not None
|
||||
babase.app.classic.stress_test_update_timer = None
|
||||
babase.app.classic.stress_test_update_timer_2 = None
|
||||
|
||||
# For regular stress tests we keep the party going. For attract-mode
|
||||
# we just end back at the main menu. If things are idle there then
|
||||
# we'll get sent back to a new stress test.
|
||||
if not args.attract_mode:
|
||||
babase.apptimer(1.0, babase.Call(_start_stress_test, args))
|
||||
|
||||
|
||||
def run_gpu_benchmark() -> None:
|
||||
|
||||
@ -69,7 +69,8 @@ class ClassicSubsystem(babase.AppSubsystem):
|
||||
|
||||
# Misc.
|
||||
self.tips: list[str] = []
|
||||
self.stress_test_reset_timer: babase.AppTimer | None = None
|
||||
self.stress_test_update_timer: babase.AppTimer | None = None
|
||||
self.stress_test_update_timer_2: babase.AppTimer | None = None
|
||||
self.value_test_defaults: dict = {}
|
||||
self.special_offer: dict | None = None
|
||||
self.ping_thread_count = 0
|
||||
@ -555,11 +556,18 @@ class ClassicSubsystem(babase.AppSubsystem):
|
||||
playlist_name: str = '__default__',
|
||||
player_count: int = 8,
|
||||
round_duration: int = 30,
|
||||
attract_mode: bool = False,
|
||||
) -> None:
|
||||
"""Run a stress test."""
|
||||
from baclassic._benchmark import run_stress_test as run
|
||||
|
||||
run(playlist_type, playlist_name, player_count, round_duration)
|
||||
run(
|
||||
playlist_type=playlist_type,
|
||||
playlist_name=playlist_name,
|
||||
player_count=player_count,
|
||||
round_duration=round_duration,
|
||||
attract_mode=attract_mode,
|
||||
)
|
||||
|
||||
def get_input_device_mapped_value(
|
||||
self, device: bascenev1.InputDevice, name: str
|
||||
|
||||
@ -52,7 +52,7 @@ if TYPE_CHECKING:
|
||||
|
||||
# Build number and version of the ballistica binary we expect to be
|
||||
# using.
|
||||
TARGET_BALLISTICA_BUILD = 21743
|
||||
TARGET_BALLISTICA_BUILD = 21756
|
||||
TARGET_BALLISTICA_VERSION = '1.7.33'
|
||||
|
||||
|
||||
@ -350,9 +350,15 @@ def _setup_paths(
|
||||
# platforms where there is no write access to said built-in
|
||||
# stuff.
|
||||
check_dir = Path(user_python_dir, 'sys', TARGET_BALLISTICA_VERSION)
|
||||
if check_dir.is_dir():
|
||||
app_python_dir = str(check_dir)
|
||||
is_user_app_python_dir = True
|
||||
try:
|
||||
if check_dir.is_dir():
|
||||
app_python_dir = str(check_dir)
|
||||
is_user_app_python_dir = True
|
||||
except PermissionError:
|
||||
logging.warning(
|
||||
"PermissionError checking user-app-python-dir path '%s'.",
|
||||
check_dir,
|
||||
)
|
||||
|
||||
# Ok, now apply these to sys.path.
|
||||
|
||||
|
||||
@ -103,6 +103,7 @@ from _bascenev1 import (
|
||||
host_scan_cycle,
|
||||
InputDevice,
|
||||
is_in_replay,
|
||||
is_replay_paused,
|
||||
ls_input_devices,
|
||||
ls_objects,
|
||||
Material,
|
||||
@ -112,11 +113,13 @@ from _bascenev1 import (
|
||||
newactivity,
|
||||
newnode,
|
||||
Node,
|
||||
pause_replay,
|
||||
printnodes,
|
||||
protocol_version,
|
||||
release_gamepad_input,
|
||||
release_keyboard_input,
|
||||
reset_random_player_names,
|
||||
resume_replay,
|
||||
broadcastmessage,
|
||||
SessionData,
|
||||
SessionPlayer,
|
||||
@ -354,6 +357,7 @@ __all__ = [
|
||||
'IntSetting',
|
||||
'is_in_replay',
|
||||
'is_point_in_box',
|
||||
'is_replay_paused',
|
||||
'JoinActivity',
|
||||
'Level',
|
||||
'Lobby',
|
||||
@ -376,6 +380,7 @@ __all__ = [
|
||||
'normalized_color',
|
||||
'NotFoundError',
|
||||
'OutOfBoundsMessage',
|
||||
'pause_replay',
|
||||
'PickedUpMessage',
|
||||
'PickUpMessage',
|
||||
'Player',
|
||||
@ -396,6 +401,7 @@ __all__ = [
|
||||
'release_gamepad_input',
|
||||
'release_keyboard_input',
|
||||
'reset_random_player_names',
|
||||
'resume_replay',
|
||||
'safecolor',
|
||||
'screenmessage',
|
||||
'SceneV1AppMode',
|
||||
|
||||
@ -441,7 +441,7 @@ class Chooser:
|
||||
# list might have changed.
|
||||
input_device = self._sessionplayer.inputdevice
|
||||
is_remote = input_device.is_remote_client
|
||||
is_test_input = input_device.name.startswith('TestInput')
|
||||
is_test_input = input_device.is_test_input
|
||||
|
||||
# Pull this player's list of unlocked characters.
|
||||
if is_remote:
|
||||
|
||||
@ -70,6 +70,10 @@ class MultiTeamSession(Session):
|
||||
|
||||
show_tutorial = cfg.get('Show Tutorial', True)
|
||||
|
||||
# Special case: don't show tutorial while stress testing.
|
||||
if classic.stress_test_update_timer is not None:
|
||||
show_tutorial = False
|
||||
|
||||
self._tutorial_activity_instance: bascenev1.Activity | None
|
||||
if show_tutorial:
|
||||
from bascenev1lib.tutorial import TutorialActivity
|
||||
|
||||
@ -266,7 +266,7 @@ class Session:
|
||||
# Limit player counts *unless* we're in a stress test.
|
||||
if (
|
||||
babase.app.classic is not None
|
||||
and babase.app.classic.stress_test_reset_timer is None
|
||||
and babase.app.classic.stress_test_update_timer is None
|
||||
):
|
||||
if len(self.sessionplayers) >= self.max_players >= 0:
|
||||
# Print a rejection message *only* to the client trying to
|
||||
|
||||
@ -67,7 +67,9 @@ class TeamGameActivity(GameActivity[PlayerT, TeamT]):
|
||||
# On the first game, show the controls UI momentarily.
|
||||
# (unless we're being run in co-op mode, in which case we leave
|
||||
# it up to them)
|
||||
if not isinstance(self.session, CoopSession):
|
||||
if not isinstance(self.session, CoopSession) and getattr(
|
||||
self, 'show_controls_guide', True
|
||||
):
|
||||
attrname = '_have_shown_ctrl_help_overlay'
|
||||
if not getattr(self.session, attrname, False):
|
||||
delay = 4.0
|
||||
|
||||
@ -1145,14 +1145,12 @@ class Bomb(bs.Actor):
|
||||
self.explode()
|
||||
elif isinstance(msg, ImpactMessage):
|
||||
self._handle_impact()
|
||||
# Ok the logic below looks like it was backwards to me.
|
||||
# Disabling for now; can bring back if need be.
|
||||
# elif isinstance(msg, bs.PickedUpMessage):
|
||||
# # Change our source to whoever just picked us up *only* if it
|
||||
# # is None. This way we can get points for killing bots with their
|
||||
# # own bombs. Hmm would there be a downside to this?
|
||||
# if self._source_player is not None:
|
||||
# self._source_player = msg.node.source_player
|
||||
elif isinstance(msg, bs.PickedUpMessage):
|
||||
# Change our source to whoever just picked us up *only* if it
|
||||
# is None. This way we can get points for killing bots with their
|
||||
# own bombs. Hmm would there be a downside to this?
|
||||
if self._source_player is None:
|
||||
self._source_player = msg.node.source_player
|
||||
elif isinstance(msg, SplatMessage):
|
||||
self._handle_splat()
|
||||
elif isinstance(msg, bs.DroppedMessage):
|
||||
|
||||
@ -42,6 +42,7 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
||||
self._language: str | None = None
|
||||
self._update_timer: bs.Timer | None = None
|
||||
self._news: NewsDisplay | None = None
|
||||
self._attract_mode_timer: bs.Timer | None = None
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
# pylint: disable=too-many-locals
|
||||
@ -83,7 +84,7 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
||||
'scale': scale,
|
||||
'position': (0, 10),
|
||||
'vr_depth': -10,
|
||||
'text': '\xa9 2011-2023 Eric Froemling',
|
||||
'text': '\xa9 2011-2024 Eric Froemling',
|
||||
},
|
||||
)
|
||||
)
|
||||
@ -295,6 +296,10 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
||||
if not (env.demo or env.arcade) and not app.ui_v1.use_toolbars:
|
||||
self._news = NewsDisplay(self)
|
||||
|
||||
self._attract_mode_timer = bs.Timer(
|
||||
3.12, self._update_attract_mode, repeat=True
|
||||
)
|
||||
|
||||
# Bring up the last place we were, or start at the main menu otherwise.
|
||||
with bs.ContextRef.empty():
|
||||
from bauiv1lib import specialoffer
|
||||
@ -387,7 +392,7 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
||||
|
||||
bs.app.ui_v1.set_main_menu_window(
|
||||
MainMenuWindow(transition=None).get_root_widget(),
|
||||
from_window=None,
|
||||
from_window=False, # Disable check here.
|
||||
)
|
||||
|
||||
# attempt to show any pending offers immediately.
|
||||
@ -403,6 +408,7 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
||||
bui.apptimer(2.0, specialoffer.show_offer)
|
||||
|
||||
bui.apptimer(2.0, try_again)
|
||||
|
||||
app.classic.main_menu_did_initial_transition = True
|
||||
|
||||
def _update(self) -> None:
|
||||
@ -836,6 +842,26 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
||||
|
||||
bui.apptimer(0.5, _start_menu_music)
|
||||
|
||||
def _update_attract_mode(self) -> None:
|
||||
if bui.app.classic is None:
|
||||
return
|
||||
|
||||
if not bui.app.config.resolve('Show Demos When Idle'):
|
||||
return
|
||||
|
||||
threshold = 20.0
|
||||
|
||||
# If we're idle *and* have been in this activity for that long,
|
||||
# flip over to our cpu demo.
|
||||
if bui.get_input_idle_time() > threshold and bs.time() > threshold:
|
||||
bui.app.classic.run_stress_test(
|
||||
playlist_type='Random',
|
||||
playlist_name='__default__',
|
||||
player_count=8,
|
||||
round_duration=20,
|
||||
attract_mode=True,
|
||||
)
|
||||
|
||||
|
||||
class NewsDisplay:
|
||||
"""Wrangles news display."""
|
||||
|
||||
@ -47,6 +47,7 @@ from babase import (
|
||||
do_once,
|
||||
fade_screen,
|
||||
get_display_resolution,
|
||||
get_input_idle_time,
|
||||
get_ip_address_type,
|
||||
get_low_level_config_value,
|
||||
get_max_graphics_quality,
|
||||
@ -156,6 +157,7 @@ __all__ = [
|
||||
'do_once',
|
||||
'fade_screen',
|
||||
'get_display_resolution',
|
||||
'get_input_idle_time',
|
||||
'get_ip_address_type',
|
||||
'get_low_level_config_value',
|
||||
'get_max_graphics_quality',
|
||||
|
||||
@ -431,13 +431,15 @@ class MainMenuWindow(bui.Window):
|
||||
# media players but this works for now).
|
||||
if bs.is_in_replay():
|
||||
b_size = 50.0
|
||||
b_buffer = 10.0
|
||||
b_buffer_1 = 50.0
|
||||
b_buffer_2 = 10.0
|
||||
t_scale = 0.75
|
||||
assert bui.app.classic is not None
|
||||
uiscale = bui.app.ui_v1.uiscale
|
||||
if uiscale is bui.UIScale.SMALL:
|
||||
b_size *= 0.6
|
||||
b_buffer *= 1.0
|
||||
b_buffer_1 *= 0.8
|
||||
b_buffer_2 *= 1.0
|
||||
v_offs = -40
|
||||
t_scale = 0.5
|
||||
elif uiscale is bui.UIScale.MEDIUM:
|
||||
@ -467,8 +469,8 @@ class MainMenuWindow(bui.Window):
|
||||
btn = bui.buttonwidget(
|
||||
parent=self._root_widget,
|
||||
position=(
|
||||
h - b_size - b_buffer,
|
||||
v - b_size - b_buffer + v_offs,
|
||||
h - b_size - b_buffer_1,
|
||||
v - b_size - b_buffer_2 + v_offs,
|
||||
),
|
||||
button_type='square',
|
||||
size=(b_size, b_size),
|
||||
@ -481,8 +483,8 @@ class MainMenuWindow(bui.Window):
|
||||
draw_controller=btn,
|
||||
text='-',
|
||||
position=(
|
||||
h - b_size * 0.5 - b_buffer,
|
||||
v - b_size * 0.5 - b_buffer + 5 * t_scale + v_offs,
|
||||
h - b_size * 0.5 - b_buffer_1,
|
||||
v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs,
|
||||
),
|
||||
h_align='center',
|
||||
v_align='center',
|
||||
@ -491,7 +493,7 @@ class MainMenuWindow(bui.Window):
|
||||
)
|
||||
btn = bui.buttonwidget(
|
||||
parent=self._root_widget,
|
||||
position=(h + b_buffer, v - b_size - b_buffer + v_offs),
|
||||
position=(h + b_buffer_1, v - b_size - b_buffer_2 + v_offs),
|
||||
button_type='square',
|
||||
size=(b_size, b_size),
|
||||
label='',
|
||||
@ -503,14 +505,27 @@ class MainMenuWindow(bui.Window):
|
||||
draw_controller=btn,
|
||||
text='+',
|
||||
position=(
|
||||
h + b_size * 0.5 + b_buffer,
|
||||
v - b_size * 0.5 - b_buffer + 5 * t_scale + v_offs,
|
||||
h + b_size * 0.5 + b_buffer_1,
|
||||
v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs,
|
||||
),
|
||||
h_align='center',
|
||||
v_align='center',
|
||||
size=(0, 0),
|
||||
scale=3.0 * t_scale,
|
||||
)
|
||||
self._pause_resume_button = btn = bui.buttonwidget(
|
||||
parent=self._root_widget,
|
||||
position=(h - b_size * 0.5, v - b_size - b_buffer_2 + v_offs),
|
||||
button_type='square',
|
||||
size=(b_size, b_size),
|
||||
label=bui.charstr(
|
||||
bui.SpecialChar.PLAY_BUTTON
|
||||
if bs.is_replay_paused()
|
||||
else bui.SpecialChar.PAUSE_BUTTON
|
||||
),
|
||||
autoselect=True,
|
||||
on_activate_call=bui.Call(self._pause_or_resume_replay),
|
||||
)
|
||||
|
||||
def _refresh_not_in_game(
|
||||
self, positions: list[tuple[float, float, float]]
|
||||
@ -1034,6 +1049,20 @@ class MainMenuWindow(bui.Window):
|
||||
),
|
||||
)
|
||||
|
||||
def _pause_or_resume_replay(self) -> None:
|
||||
if bs.is_replay_paused():
|
||||
bs.resume_replay()
|
||||
bui.buttonwidget(
|
||||
edit=self._pause_resume_button,
|
||||
label=bui.charstr(bui.SpecialChar.PAUSE_BUTTON),
|
||||
)
|
||||
else:
|
||||
bs.pause_replay()
|
||||
bui.buttonwidget(
|
||||
edit=self._pause_resume_button,
|
||||
label=bui.charstr(bui.SpecialChar.PLAY_BUTTON),
|
||||
)
|
||||
|
||||
def _quit(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
from bauiv1lib.confirm import QuitWindow
|
||||
@ -1110,7 +1139,7 @@ class MainMenuWindow(bui.Window):
|
||||
session = bs.get_foreground_host_session()
|
||||
return getattr(session, 'benchmark_type', None) == 'cpu' or (
|
||||
bui.app.classic is not None
|
||||
and bui.app.classic.stress_test_reset_timer is not None
|
||||
and bui.app.classic.stress_test_update_timer is not None
|
||||
)
|
||||
|
||||
def _confirm_end_game(self) -> None:
|
||||
|
||||
@ -94,7 +94,7 @@ class AdvancedSettingsWindow(bui.Window):
|
||||
self._scroll_width = self._width - (100 + 2 * x_inset)
|
||||
self._scroll_height = self._height - 115.0
|
||||
self._sub_width = self._scroll_width * 0.95
|
||||
self._sub_height = 766.0
|
||||
self._sub_height = 808.0
|
||||
|
||||
if self._show_always_use_internal_keyboard:
|
||||
self._sub_height += 62
|
||||
@ -489,6 +489,17 @@ class AdvancedSettingsWindow(bui.Window):
|
||||
maxwidth=430,
|
||||
)
|
||||
|
||||
v -= 42
|
||||
self._show_demos_when_idle_check_box = ConfigCheckBox(
|
||||
parent=self._subcontainer,
|
||||
position=(50, v),
|
||||
size=(self._sub_width - 100, 30),
|
||||
configkey='Show Demos When Idle',
|
||||
displayname=bui.Lstr(resource=f'{self._r}.showDemosWhenIdleText'),
|
||||
scale=1.0,
|
||||
maxwidth=430,
|
||||
)
|
||||
|
||||
v -= 42
|
||||
self._disable_camera_shake_check_box = ConfigCheckBox(
|
||||
parent=self._subcontainer,
|
||||
@ -575,12 +586,18 @@ class AdvancedSettingsWindow(bui.Window):
|
||||
up_widget=self._always_use_internal_keyboard_check_box.widget,
|
||||
)
|
||||
else:
|
||||
bui.widget(
|
||||
edit=self._modding_guide_button,
|
||||
up_widget=self._kick_idle_players_check_box.widget,
|
||||
# ew.
|
||||
next_widget_up = (
|
||||
self._disable_gyro_check_box.widget
|
||||
if self._disable_gyro_check_box is not None
|
||||
else self._disable_camera_shake_check_box.widget
|
||||
)
|
||||
bui.widget(
|
||||
edit=self._kick_idle_players_check_box.widget,
|
||||
edit=self._modding_guide_button,
|
||||
up_widget=next_widget_up,
|
||||
)
|
||||
bui.widget(
|
||||
edit=next_widget_up,
|
||||
down_widget=self._modding_guide_button,
|
||||
)
|
||||
|
||||
@ -803,6 +820,8 @@ class AdvancedSettingsWindow(bui.Window):
|
||||
sel_name = 'Benchmarks'
|
||||
elif sel == self._kick_idle_players_check_box.widget:
|
||||
sel_name = 'KickIdlePlayers'
|
||||
elif sel == self._show_demos_when_idle_check_box.widget:
|
||||
sel_name = 'ShowDemosWhenIdle'
|
||||
elif sel == self._show_game_ping_check_box.widget:
|
||||
sel_name = 'ShowPing'
|
||||
elif sel == self._disable_camera_shake_check_box.widget:
|
||||
@ -870,6 +889,8 @@ class AdvancedSettingsWindow(bui.Window):
|
||||
sel = self._benchmarks_button
|
||||
elif sel_name == 'KickIdlePlayers':
|
||||
sel = self._kick_idle_players_check_box.widget
|
||||
elif sel_name == 'ShowDemosWhenIdle':
|
||||
sel = self._show_demos_when_idle_check_box.widget
|
||||
elif sel_name == 'ShowPing':
|
||||
sel = self._show_game_ping_check_box.widget
|
||||
elif sel_name == 'DisableCameraShake':
|
||||
|
||||
@ -4,12 +4,8 @@
|
||||
|
||||
#include "ballistica/base/graphics/renderer/renderer.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/networking/network_reader.h"
|
||||
#include "ballistica/base/networking/networking.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
|
||||
@ -1238,6 +1238,13 @@ void Assets::InitSpecialChars() {
|
||||
special_char_strings_[SpecialChar::kPlayPauseButton] = "\xee\x80\x8E";
|
||||
special_char_strings_[SpecialChar::kFastForwardButton] = "\xee\x80\x8F";
|
||||
special_char_strings_[SpecialChar::kDpadCenterButton] = "\xee\x80\x90";
|
||||
special_char_strings_[SpecialChar::kPlayStationCrossButton] = "\xee\x80\x91";
|
||||
special_char_strings_[SpecialChar::kPlayStationCircleButton] = "\xee\x80\x92";
|
||||
special_char_strings_[SpecialChar::kPlayStationTriangleButton] =
|
||||
"\xee\x80\x93";
|
||||
special_char_strings_[SpecialChar::kPlayStationSquareButton] = "\xee\x80\x94";
|
||||
special_char_strings_[SpecialChar::kPlayButton] = "\xee\x80\x95";
|
||||
special_char_strings_[SpecialChar::kPauseButton] = "\xee\x80\x96";
|
||||
|
||||
special_char_strings_[SpecialChar::kOuyaButtonO] = "\xee\x80\x99";
|
||||
special_char_strings_[SpecialChar::kOuyaButtonU] = "\xee\x80\x9A";
|
||||
@ -1610,10 +1617,6 @@ auto Assets::SysTexture(SysTextureID id) -> TextureAsset* {
|
||||
assert(asset_loads_allowed_ && sys_assets_loaded_);
|
||||
assert(g_base->InLogicThread());
|
||||
assert(static_cast<size_t>(id) < system_textures_.size());
|
||||
// TEMP - tracking down some crashes in the wild.
|
||||
if (!sys_assets_loaded_) {
|
||||
FatalError("SysTexture called before sys assets loaded.");
|
||||
}
|
||||
return system_textures_[static_cast<int>(id)].Get();
|
||||
}
|
||||
|
||||
@ -1621,21 +1624,17 @@ auto Assets::SysCubeMapTexture(SysCubeMapTextureID id) -> TextureAsset* {
|
||||
assert(asset_loads_allowed_ && sys_assets_loaded_);
|
||||
assert(g_base->InLogicThread());
|
||||
assert(static_cast<size_t>(id) < system_cube_map_textures_.size());
|
||||
// TEMP - tracking down some crashes in the wild.
|
||||
if (!sys_assets_loaded_) {
|
||||
FatalError("SysCubeMapTexture called before sys assets loaded.");
|
||||
}
|
||||
return system_cube_map_textures_[static_cast<int>(id)].Get();
|
||||
}
|
||||
|
||||
auto Assets::IsValidSysSound(SysSoundID id) -> bool {
|
||||
return static_cast<size_t>(id) < system_sounds_.size();
|
||||
}
|
||||
|
||||
auto Assets::SysSound(SysSoundID id) -> SoundAsset* {
|
||||
assert(asset_loads_allowed_ && sys_assets_loaded_);
|
||||
assert(g_base->InLogicThread());
|
||||
assert(static_cast<size_t>(id) < system_sounds_.size());
|
||||
// TEMP - tracking down some crashes in the wild.
|
||||
if (!sys_assets_loaded_) {
|
||||
FatalError("SysSound called before sys assets loaded.");
|
||||
}
|
||||
assert(IsValidSysSound(id));
|
||||
return system_sounds_[static_cast<int>(id)].Get();
|
||||
}
|
||||
|
||||
@ -1643,11 +1642,6 @@ auto Assets::SysMesh(SysMeshID id) -> MeshAsset* {
|
||||
assert(asset_loads_allowed_ && sys_assets_loaded_);
|
||||
assert(g_base->InLogicThread());
|
||||
assert(static_cast<size_t>(id) < system_meshes_.size());
|
||||
|
||||
// TEMP - tracking down some crashes in the wild.
|
||||
if (!sys_assets_loaded_) {
|
||||
FatalError("SysMesh called before sys assets loaded.");
|
||||
}
|
||||
return system_meshes_[static_cast<int>(id)].Get();
|
||||
}
|
||||
|
||||
|
||||
@ -76,6 +76,7 @@ class Assets {
|
||||
// available.
|
||||
auto SysTexture(SysTextureID id) -> TextureAsset*;
|
||||
auto SysCubeMapTexture(SysCubeMapTextureID id) -> TextureAsset*;
|
||||
auto IsValidSysSound(SysSoundID id) -> bool;
|
||||
auto SysSound(SysSoundID id) -> SoundAsset*;
|
||||
auto SysMesh(SysMeshID id) -> MeshAsset*;
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/assets/sound_asset.h"
|
||||
#include "ballistica/base/audio/audio_server.h"
|
||||
#include "ballistica/base/audio/audio_source.h"
|
||||
@ -159,6 +160,32 @@ auto Audio::ShouldPlay(SoundAsset* sound) -> bool {
|
||||
return (time - sound->last_play_time() > 50);
|
||||
}
|
||||
|
||||
auto Audio::SafePlaySysSound(SysSoundID sound_id) -> std::optional<uint32_t> {
|
||||
// Save some time on headless.
|
||||
if (g_core->HeadlessMode()) {
|
||||
return {};
|
||||
}
|
||||
if (!g_base->InLogicThread()) {
|
||||
Log(LogLevel::kError,
|
||||
"Audio::SafePlaySysSound called from non-logic thread. id="
|
||||
+ std::to_string(static_cast<int>(sound_id)));
|
||||
return {};
|
||||
}
|
||||
if (!g_base->assets->sys_assets_loaded()) {
|
||||
Log(LogLevel::kWarning,
|
||||
"Audio::SafePlaySysSound called before sys assets loaded. id="
|
||||
+ std::to_string(static_cast<int>(sound_id)));
|
||||
return {};
|
||||
}
|
||||
if (!g_base->assets->IsValidSysSound(sound_id)) {
|
||||
Log(LogLevel::kWarning,
|
||||
"Audio::SafePlaySysSound called with invalid sound_id. id="
|
||||
+ std::to_string(static_cast<int>(sound_id)));
|
||||
return {};
|
||||
}
|
||||
return PlaySound(g_base->assets->SysSound(sound_id));
|
||||
}
|
||||
|
||||
auto Audio::PlaySound(SoundAsset* sound, float volume)
|
||||
-> std::optional<uint32_t> {
|
||||
assert(g_core);
|
||||
|
||||
@ -61,6 +61,10 @@ class Audio {
|
||||
auto PlaySoundAtPosition(SoundAsset* sound, float volume, float x, float y,
|
||||
float z) -> std::optional<uint32_t>;
|
||||
|
||||
/// Load and play a sys sound if possible. Gracefully fail if not
|
||||
/// (possibly logging warnings or errors).
|
||||
auto SafePlaySysSound(SysSoundID sound_id) -> std::optional<uint32_t>;
|
||||
|
||||
/// Call this if you want to prevent repeated plays of the same sound. It'll
|
||||
/// tell you if the sound has been played recently. The one-shot sound-play
|
||||
/// functions use this under the hood. (PlaySound, PlaySoundAtPosition).
|
||||
|
||||
@ -16,12 +16,10 @@
|
||||
#include "ballistica/base/networking/network_reader.h"
|
||||
#include "ballistica/base/networking/network_writer.h"
|
||||
#include "ballistica/base/networking/networking.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#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"
|
||||
|
||||
@ -240,7 +240,7 @@ class RenderComponent {
|
||||
}
|
||||
|
||||
protected:
|
||||
enum class State { kConfiguring, kDrawing, kSubmitted };
|
||||
enum class State : uint8_t { kConfiguring, kDrawing, kSubmitted };
|
||||
void EnsureConfiguring() {
|
||||
if (state_ != State::kConfiguring) {
|
||||
#if BA_DEBUG_BUILD
|
||||
@ -331,8 +331,8 @@ class RenderComponent {
|
||||
// stream.
|
||||
virtual void WriteConfig() = 0;
|
||||
|
||||
RenderCommandBuffer* cmd_buffer_{};
|
||||
State state_{State::kConfiguring};
|
||||
RenderCommandBuffer* cmd_buffer_{};
|
||||
RenderPass* pass_;
|
||||
|
||||
public:
|
||||
|
||||
@ -19,7 +19,7 @@ class RendererGL::MeshAssetDataGL : public MeshAssetRendererData {
|
||||
enum BufferType { kVertices, kIndices, kBufferCount };
|
||||
|
||||
MeshAssetDataGL(const MeshAsset& model, RendererGL* renderer)
|
||||
: renderer_(renderer), fake_vao_(nullptr) {
|
||||
: renderer_(renderer) {
|
||||
#if BA_DEBUG_BUILD
|
||||
name_ = model.GetName();
|
||||
#endif
|
||||
@ -150,7 +150,7 @@ class RendererGL::MeshAssetDataGL : public MeshAssetRendererData {
|
||||
GLuint index_type_{};
|
||||
GLuint vao_{};
|
||||
GLuint vbos_[kBufferCount]{};
|
||||
FakeVertexArrayObject* fake_vao_{};
|
||||
// FakeVertexArrayObject* fake_vao_{};
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -202,7 +202,6 @@ class RendererGL::MeshDataGL : public MeshRendererData {
|
||||
RendererGL* renderer_{};
|
||||
uint32_t elem_count_{};
|
||||
GLuint index_type_{GL_UNSIGNED_SHORT};
|
||||
FakeVertexArrayObject* fake_vao_{};
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -2339,12 +2339,11 @@ void RendererGL::SetDrawAtEqualDepth(bool enable) {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME FIXME FIXME FIXME
|
||||
// turning off GL_DEPTH_TEST also disables
|
||||
// depth writing which we may not want.
|
||||
// It sounds like the proper thing
|
||||
// to do in that case is leave GL_DEPTH_TEST on
|
||||
// and set glDepthFunc(GL_ALWAYS)
|
||||
// FIXME FIXME FIXME FIXME:
|
||||
//
|
||||
// Turning off GL_DEPTH_TEST also disables depth writing which we may not
|
||||
// want. It sounds like the proper thing to do in that case is leave
|
||||
// GL_DEPTH_TEST on and set glDepthFunc(GL_ALWAYS).
|
||||
|
||||
void RendererGL::SetDepthTesting(bool enable) {
|
||||
if (enable != depth_testing_enabled_) {
|
||||
|
||||
@ -39,7 +39,6 @@ namespace ballistica::base {
|
||||
constexpr int kMaxGLTexUnitsUsed = 5;
|
||||
|
||||
class RendererGL : public Renderer {
|
||||
class FakeVertexArrayObject;
|
||||
class TextureDataGL;
|
||||
class MeshAssetDataGL;
|
||||
class MeshDataGL;
|
||||
|
||||
@ -9,7 +9,8 @@
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
// A dynamically defined mesh (unlike a mesh asset which is completely static).
|
||||
/// A dynamically defined mesh (unlike a mesh asset which is completely
|
||||
/// static).
|
||||
class Mesh : public Object {
|
||||
public:
|
||||
auto type() const -> MeshDataType { return type_; }
|
||||
@ -17,7 +18,7 @@ class Mesh : public Object {
|
||||
return mesh_data_client_handle_;
|
||||
}
|
||||
|
||||
// Return whether it is safe to attempt drawing with present data.
|
||||
/// Return whether it is safe to attempt drawing with present data.
|
||||
virtual auto IsValid() const -> bool = 0;
|
||||
auto last_frame_def_num() const -> int64_t { return last_frame_def_num_; }
|
||||
void set_last_frame_def_num(int64_t f) { last_frame_def_num_ = f; }
|
||||
@ -31,14 +32,14 @@ class Mesh : public Object {
|
||||
}
|
||||
|
||||
private:
|
||||
int64_t last_frame_def_num_{};
|
||||
MeshDataType type_{};
|
||||
|
||||
// Renderer data for this mesh. We keep this as a shared pointer
|
||||
// so that frame_defs or other things using this mesh can keep it alive
|
||||
// even if we go away.
|
||||
Object::Ref<MeshDataClientHandle> mesh_data_client_handle_;
|
||||
bool valid_{};
|
||||
int64_t last_frame_def_num_{};
|
||||
|
||||
/// Renderer data for this mesh. We keep this as a shared pointer so that
|
||||
/// frame_defs or other things using this mesh can keep it alive even if
|
||||
/// we go away.
|
||||
Object::Ref<MeshDataClientHandle> mesh_data_client_handle_;
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
// The portion of a mesh that is owned by the graphics thread.
|
||||
// This contains the renderer-specific data (GL buffers, etc)
|
||||
/// The portion of a mesh that is owned by the graphics server. This
|
||||
/// contains the renderer-specific data (GL buffers, etc).
|
||||
class MeshData {
|
||||
public:
|
||||
MeshData(MeshDataType type, MeshDrawType draw_type)
|
||||
|
||||
@ -15,8 +15,8 @@ namespace ballistica::base {
|
||||
// shadow pass, a window, etc.
|
||||
class RenderPass {
|
||||
public:
|
||||
enum class ReflectionSubPass { kRegular, kMirrored };
|
||||
enum class Type {
|
||||
enum class ReflectionSubPass : uint8_t { kRegular, kMirrored };
|
||||
enum class Type : uint8_t {
|
||||
// A pass whose results are projected onto the scene for lighting and
|
||||
// shadow effects. Values lighter than kShadowNeutral will show up as
|
||||
// light and darker than neutral will show up as shadowing. This version
|
||||
@ -152,40 +152,43 @@ class RenderPass {
|
||||
private:
|
||||
void SetFrustum(float near_val, float far_val);
|
||||
|
||||
bool cam_use_fov_tangents_{};
|
||||
bool floor_reflection_{};
|
||||
Type type_{};
|
||||
|
||||
float cam_near_clip_{};
|
||||
float cam_far_clip_{};
|
||||
float cam_fov_x_{};
|
||||
float cam_fov_y_{};
|
||||
float physical_width_{};
|
||||
float physical_height_{};
|
||||
float virtual_width_{};
|
||||
float virtual_height_{};
|
||||
|
||||
// We can now alternately supply left, right, top, bottom frustum tangents.
|
||||
float cam_fov_l_tan_{1.0f};
|
||||
float cam_fov_r_tan_{1.0f};
|
||||
float cam_fov_t_tan_{1.0f};
|
||||
float cam_fov_b_tan_{1.0f};
|
||||
|
||||
Vector3f cam_pos_{0.0f, 0.0f, 0.0f};
|
||||
Vector3f cam_target_{0.0f, 0.0f, 0.0f};
|
||||
Vector3f cam_up_{0.0f, 0.0f, 0.0f};
|
||||
|
||||
Matrix44f tex_project_matrix_{kMatrix44fIdentity};
|
||||
Matrix44f projection_matrix_{kMatrix44fIdentity};
|
||||
Matrix44f model_view_matrix_{kMatrix44fIdentity};
|
||||
Matrix44f model_view_projection_matrix_{kMatrix44fIdentity};
|
||||
FrameDef* frame_def_{};
|
||||
|
||||
std::vector<Vector3f> cam_area_of_interest_points_;
|
||||
|
||||
// Our pass holds sets of draw-commands bucketed by section and
|
||||
// component-type.
|
||||
std::unique_ptr<RenderCommandBuffer>
|
||||
commands_[static_cast<int>(ShadingType::kCount)];
|
||||
std::unique_ptr<RenderCommandBuffer> commands_flat_;
|
||||
std::unique_ptr<RenderCommandBuffer> commands_flat_transparent_;
|
||||
Vector3f cam_pos_{0.0f, 0.0f, 0.0f};
|
||||
Vector3f cam_target_{0.0f, 0.0f, 0.0f};
|
||||
Vector3f cam_up_{0.0f, 0.0f, 0.0f};
|
||||
float cam_near_clip_{};
|
||||
float cam_far_clip_{};
|
||||
float cam_fov_x_{};
|
||||
float cam_fov_y_{};
|
||||
|
||||
// We can now alternately supply left, right, top, bottom frustum tangents.
|
||||
bool cam_use_fov_tangents_{};
|
||||
float cam_fov_l_tan_{1.0f};
|
||||
float cam_fov_r_tan_{1.0f};
|
||||
float cam_fov_t_tan_{1.0f};
|
||||
float cam_fov_b_tan_{1.0f};
|
||||
std::vector<Vector3f> cam_area_of_interest_points_;
|
||||
Type type_{};
|
||||
|
||||
// For lights/shadows.
|
||||
Matrix44f tex_project_matrix_{kMatrix44fIdentity};
|
||||
Matrix44f projection_matrix_{kMatrix44fIdentity};
|
||||
Matrix44f model_view_matrix_{kMatrix44fIdentity};
|
||||
Matrix44f model_view_projection_matrix_{kMatrix44fIdentity};
|
||||
bool floor_reflection_{};
|
||||
FrameDef* frame_def_{};
|
||||
float physical_width_{};
|
||||
float physical_height_{};
|
||||
float virtual_width_{};
|
||||
float virtual_height_{};
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -39,6 +39,7 @@ auto RenderTarget::GetScissorX(float x) const -> float {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto RenderTarget::GetScissorY(float y) const -> float {
|
||||
assert(g_core);
|
||||
if (g_core->vr_mode()) {
|
||||
@ -60,6 +61,7 @@ auto RenderTarget::GetScissorY(float y) const -> float {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto RenderTarget::GetScissorScaleX() const -> float {
|
||||
assert(g_core);
|
||||
if (g_core->vr_mode()) {
|
||||
|
||||
@ -14,7 +14,7 @@ class RenderTarget : public Object {
|
||||
auto GetThreadOwnership() const -> ThreadOwnership override {
|
||||
return ThreadOwnership::kGraphicsContext;
|
||||
}
|
||||
enum class Type { kScreen, kFramebuffer };
|
||||
enum class Type : uint8_t { kScreen, kFramebuffer };
|
||||
explicit RenderTarget(Type type);
|
||||
~RenderTarget() override;
|
||||
|
||||
@ -36,10 +36,10 @@ class RenderTarget : public Object {
|
||||
auto GetScissorY(float y) const -> float;
|
||||
|
||||
protected:
|
||||
float physical_width_{};
|
||||
float physical_height_{};
|
||||
bool depth_{};
|
||||
Type type_{};
|
||||
float physical_width_{};
|
||||
float physical_height_{};
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -193,6 +193,7 @@ class Renderer {
|
||||
virtual void RenderFrameDefEnd() = 0;
|
||||
virtual void CardboardDisableScissor() = 0;
|
||||
virtual void CardboardEnableScissor() = 0;
|
||||
|
||||
#if BA_VR_BUILD
|
||||
void VRTransformToRightHand();
|
||||
void VRTransformToLeftHand();
|
||||
@ -207,30 +208,24 @@ class Renderer {
|
||||
void DrawWorldToCameraBuffer(FrameDef* frame_def);
|
||||
void UpdatePixelScaleAndBackingBuffer(FrameDef* frame_def);
|
||||
void UpdateCameraRenderTargets(FrameDef* frame_def);
|
||||
// #if BA_OSTYPE_MACOS && BA_SDL_BUILD && !BA_SDL2_BUILD
|
||||
// void HandleFunkyMacGammaIssue(FrameDef* frame_def);
|
||||
// #endif
|
||||
void LoadMedia(FrameDef* frame_def);
|
||||
void UpdateDOFParams(FrameDef* frame_def);
|
||||
|
||||
#if BA_VR_BUILD
|
||||
void VRPreprocess(FrameDef* frame_def);
|
||||
void VRUpdateForEyeRender(FrameDef* frame_def);
|
||||
void VRDrawOverlayFlatPass(FrameDef* frame_def);
|
||||
#endif // BA_VR_BUILD
|
||||
|
||||
#if BA_VR_BUILD
|
||||
|
||||
bool vr_use_fov_tangents_{};
|
||||
|
||||
// Raw values from vr system.
|
||||
VRHandsState vr_raw_hands_state_{};
|
||||
float vr_raw_head_tx_{};
|
||||
float vr_raw_head_ty_{};
|
||||
float vr_raw_head_tz_{};
|
||||
float vr_raw_head_yaw_{};
|
||||
float vr_raw_head_pitch_{};
|
||||
float vr_raw_head_roll_{};
|
||||
// Final game-space transforms.
|
||||
Matrix44f vr_base_transform_{kMatrix44fIdentity};
|
||||
Matrix44f vr_transform_right_hand_{kMatrix44fIdentity};
|
||||
Matrix44f vr_transform_left_hand_{kMatrix44fIdentity};
|
||||
Matrix44f vr_transform_head_{kMatrix44fIdentity};
|
||||
// Values for current eye render.
|
||||
bool vr_use_fov_tangents_{};
|
||||
int vr_eye_{};
|
||||
int vr_viewport_x_{};
|
||||
int vr_viewport_y_{};
|
||||
float vr_fov_l_tan_{1.0f};
|
||||
float vr_fov_r_tan_{1.0f};
|
||||
float vr_fov_b_tan_{1.0f};
|
||||
@ -240,37 +235,59 @@ class Renderer {
|
||||
float vr_eye_x_{};
|
||||
float vr_eye_y_{};
|
||||
float vr_eye_z_{};
|
||||
int vr_eye_{};
|
||||
float vr_eye_yaw_{};
|
||||
float vr_eye_pitch_{};
|
||||
float vr_eye_roll_{};
|
||||
int vr_viewport_x_{};
|
||||
int vr_viewport_y_{};
|
||||
float vr_raw_head_tx_{};
|
||||
float vr_raw_head_ty_{};
|
||||
float vr_raw_head_tz_{};
|
||||
float vr_raw_head_yaw_{};
|
||||
float vr_raw_head_pitch_{};
|
||||
float vr_raw_head_roll_{};
|
||||
Matrix44f vr_base_transform_{kMatrix44fIdentity};
|
||||
Matrix44f vr_transform_right_hand_{kMatrix44fIdentity};
|
||||
Matrix44f vr_transform_left_hand_{kMatrix44fIdentity};
|
||||
Matrix44f vr_transform_head_{kMatrix44fIdentity};
|
||||
#endif // BA_VR_BUILD
|
||||
|
||||
// The *actual* current quality (set based on the currently-rendering
|
||||
// frame_def)
|
||||
GraphicsQuality last_render_quality_{GraphicsQuality::kLow};
|
||||
bool debug_draw_mode_{};
|
||||
bool screen_size_dirty_{};
|
||||
bool msaa_enabled_dirty_{};
|
||||
millisecs_t dof_update_time_{};
|
||||
bool dof_delay_{true};
|
||||
bool drawing_reflection_{};
|
||||
bool shadow_ortho_{};
|
||||
|
||||
int last_commands_buffer_size_{};
|
||||
int last_f_vals_buffer_size_{};
|
||||
int last_i_vals_buffer_size_{};
|
||||
int last_meshes_buffer_size_{};
|
||||
int last_textures_buffer_size_{};
|
||||
int frames_rendered_count_{};
|
||||
int blur_res_count_{};
|
||||
int shadow_res_{-1};
|
||||
|
||||
float dof_near_smoothed_{};
|
||||
float dof_far_smoothed_{};
|
||||
bool drawing_reflection_{};
|
||||
int blur_res_count_{};
|
||||
float light_pitch_{};
|
||||
float light_heading_{};
|
||||
float light_tz_{-22.0f};
|
||||
Vector3f shadow_offset_{0.0f, 0.0f, 0.0f};
|
||||
float shadow_scale_x_{1.0f};
|
||||
float shadow_scale_z_{1.0f};
|
||||
bool shadow_ortho_{};
|
||||
float screen_gamma_{1.0f};
|
||||
float pixel_scale_requested_{1.0f};
|
||||
float pixel_scale_{1.0f};
|
||||
|
||||
millisecs_t last_screen_gamma_update_time_{};
|
||||
millisecs_t dof_update_time_{};
|
||||
|
||||
Vector3f shadow_offset_{0.0f, 0.0f, 0.0f};
|
||||
Vector3f tint_{1.0f, 1.0f, 1.0f};
|
||||
Vector3f ambient_color_{1.0f, 1.0f, 1.0f};
|
||||
Vector3f vignette_outer_{0.0f, 0.0f, 0.0f};
|
||||
Vector3f vignette_inner_{1.0f, 1.0f, 1.0f};
|
||||
int shadow_res_{-1};
|
||||
float screen_gamma_{1.0f};
|
||||
float pixel_scale_requested_{1.0f};
|
||||
float pixel_scale_{1.0f};
|
||||
Object::Ref<RenderTarget> screen_render_target_;
|
||||
Object::Ref<RenderTarget> backing_render_target_;
|
||||
Object::Ref<RenderTarget> camera_render_target_;
|
||||
@ -278,18 +295,6 @@ class Renderer {
|
||||
Object::Ref<RenderTarget> light_render_target_;
|
||||
Object::Ref<RenderTarget> light_shadow_render_target_;
|
||||
Object::Ref<RenderTarget> vr_overlay_flat_render_target_;
|
||||
millisecs_t last_screen_gamma_update_time_{};
|
||||
int last_commands_buffer_size_{};
|
||||
int last_f_vals_buffer_size_{};
|
||||
int last_i_vals_buffer_size_{};
|
||||
int last_meshes_buffer_size_{};
|
||||
int last_textures_buffer_size_{};
|
||||
bool debug_draw_mode_{};
|
||||
int frames_rendered_count_{};
|
||||
|
||||
// The *actual* current quality (set based on the
|
||||
// currently-rendering frame_def)
|
||||
GraphicsQuality last_render_quality_{GraphicsQuality::kLow};
|
||||
};
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -52,9 +52,9 @@ InputDevice::~InputDevice() { assert(g_base->InLogicThread()); }
|
||||
// control something please.
|
||||
void InputDevice::RequestPlayer() {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// Make note that we're being used in some way.
|
||||
last_input_time_millisecs_ =
|
||||
static_cast<millisecs_t>(g_base->logic->display_time() * 1000.0);
|
||||
UpdateLastActiveTime();
|
||||
|
||||
delegate_->RequestPlayer();
|
||||
}
|
||||
@ -69,11 +69,19 @@ auto InputDevice::AttachedToPlayer() const -> bool {
|
||||
|
||||
void InputDevice::DetachFromPlayer() { delegate_->DetachFromPlayer(); }
|
||||
|
||||
void InputDevice::UpdateLastInputTime() {
|
||||
// Keep our own individual time, and also let the overall input system
|
||||
// know something happened.
|
||||
last_input_time_millisecs_ =
|
||||
void InputDevice::UpdateLastActiveTime() {
|
||||
// Special case: in attract-mode, prevent our virtual test devices from
|
||||
// affecting input last-active times otherwise it'll kick us out of
|
||||
// attract mode.
|
||||
if (allow_input_in_attract_mode_ && g_base->input->attract_mode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark active time on this specific device.
|
||||
last_active_time_millisecs_ =
|
||||
static_cast<millisecs_t>(g_base->logic->display_time() * 1000.0);
|
||||
|
||||
// Mark input in general as active also.
|
||||
g_base->input->MarkInputActive();
|
||||
}
|
||||
|
||||
@ -81,7 +89,7 @@ void InputDevice::InputCommand(InputType type, float value) {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// Make note that we're being used in some way.
|
||||
UpdateLastInputTime();
|
||||
UpdateLastActiveTime();
|
||||
|
||||
delegate_->InputCommand(type, value);
|
||||
}
|
||||
|
||||
@ -93,8 +93,8 @@ class InputDevice : public Object {
|
||||
/// that button activates default widgets (will cause a start icon to show up
|
||||
/// on them).
|
||||
virtual auto start_button_activates_default_widget() -> bool { return false; }
|
||||
auto last_input_time_millisecs() const -> millisecs_t {
|
||||
return last_input_time_millisecs_;
|
||||
auto last_active_time_millisecs() const -> millisecs_t {
|
||||
return last_active_time_millisecs_;
|
||||
}
|
||||
virtual auto ShouldBeHiddenFromUser() -> bool;
|
||||
|
||||
@ -117,7 +117,7 @@ class InputDevice : public Object {
|
||||
/// been added to the input-device list, have a valid ID, name, etc.
|
||||
virtual void OnAdded() {}
|
||||
|
||||
void UpdateLastInputTime();
|
||||
void UpdateLastActiveTime();
|
||||
|
||||
auto delegate() -> InputDeviceDelegate& {
|
||||
// TEMP - Tracking down a crash in the wild.
|
||||
@ -136,18 +136,27 @@ class InputDevice : public Object {
|
||||
auto custom_default_player_name() const -> std::string {
|
||||
return custom_default_player_name_;
|
||||
}
|
||||
|
||||
void set_custom_default_player_name(const std::string& val) {
|
||||
custom_default_player_name_ = val;
|
||||
}
|
||||
|
||||
auto allow_input_in_attract_mode() const {
|
||||
return allow_input_in_attract_mode_;
|
||||
}
|
||||
|
||||
void set_allow_input_in_attract_mode(bool allow) {
|
||||
allow_input_in_attract_mode_ = allow;
|
||||
}
|
||||
|
||||
private:
|
||||
Object::Ref<InputDeviceDelegate> delegate_;
|
||||
|
||||
// note: this is in base-net-time
|
||||
millisecs_t last_input_time_millisecs_{};
|
||||
millisecs_t last_active_time_millisecs_{};
|
||||
|
||||
int index_{-1}; // Our overall device index.
|
||||
int number_{-1}; // Our type-specific number.
|
||||
bool allow_input_in_attract_mode_{};
|
||||
|
||||
std::string custom_default_player_name_;
|
||||
|
||||
|
||||
@ -44,10 +44,6 @@ JoystickInput::JoystickInput(int sdl_joystick_id,
|
||||
analog_calibration_val = 0.6f;
|
||||
}
|
||||
|
||||
if (custom_device_name == "TestInput") {
|
||||
is_test_input_ = true;
|
||||
}
|
||||
|
||||
sdl_joystick_id_ = sdl_joystick_id;
|
||||
|
||||
// Non-negative values here mean its an SDL joystick.
|
||||
@ -799,7 +795,9 @@ void JoystickInput::HandleSDLEvent(const SDL_Event* e) {
|
||||
|
||||
// Anything that would go to ui also counts to mark us as 'recently-used'.
|
||||
if (would_go_to_ui) {
|
||||
UpdateLastInputTime();
|
||||
if (!(allow_input_in_attract_mode() && g_base->input->attract_mode())) {
|
||||
UpdateLastActiveTime();
|
||||
}
|
||||
}
|
||||
|
||||
if (would_go_to_ui && g_base->ui->GetWidgetForInput(this)) {
|
||||
|
||||
@ -59,6 +59,8 @@ class JoystickInput : public InputDevice {
|
||||
|
||||
auto IsUIOnly() -> bool override { return ui_only_; }
|
||||
|
||||
void set_is_test_input(bool val) { is_test_input_ = val; }
|
||||
|
||||
auto IsTestInput() -> bool override { return is_test_input_; }
|
||||
auto IsRemoteApp() -> bool override { return is_remote_app_; }
|
||||
auto IsMFiController() -> bool override { return is_mfi_controller_; }
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#include "ballistica/base/input/device/keyboard_input.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/support/classic_soft.h"
|
||||
#include "ballistica/base/support/repeater.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
|
||||
@ -4,16 +4,23 @@
|
||||
|
||||
#include "ballistica/base/input/device/joystick_input.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/core/platform/support/min_sdl.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/shared/math/random.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
TestInput::TestInput() {
|
||||
// In attract-mode (pretty demos) we want this to look more like
|
||||
// real people connecting to the game, so just say 'Controller'.
|
||||
const char* device_name =
|
||||
g_base->input->attract_mode() ? "Controller" : "TestInput";
|
||||
|
||||
joystick_ = Object::NewDeferred<JoystickInput>(-1, // not an sdl joystick
|
||||
"TestInput", // device name
|
||||
device_name, // device name
|
||||
false, // allow configuring?
|
||||
false); // calibrate?;
|
||||
joystick_->set_allow_input_in_attract_mode(true);
|
||||
joystick_->set_is_test_input(true);
|
||||
g_base->input->PushAddInputDeviceCall(joystick_, true);
|
||||
}
|
||||
|
||||
@ -56,6 +63,11 @@ void TestInput::Process(millisecs_t time) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do nothing while any UI is up.
|
||||
if (g_base->ui->MainMenuVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
float r = RandomFloat();
|
||||
|
||||
SDL_Event e;
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/shared/foundation/macros.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
|
||||
@ -170,9 +170,6 @@ void Input::AnnounceConnects_() {
|
||||
} else {
|
||||
// If there's been several connected, just give a number.
|
||||
if (newly_connected_controllers_.size() > 1) {
|
||||
for (auto&& s : newly_connected_controllers_) {
|
||||
Log(LogLevel::kInfo, "GOT CONTROLLER " + s);
|
||||
}
|
||||
std::string s =
|
||||
g_base->assets->GetResourceString("controllersConnectedText");
|
||||
Utils::StringReplaceOne(
|
||||
@ -187,7 +184,7 @@ void Input::AnnounceConnects_() {
|
||||
ScreenMessage(s);
|
||||
}
|
||||
if (g_base->assets->sys_assets_loaded()) {
|
||||
g_base->audio->PlaySound(g_base->assets->SysSound(SysSoundID::kGunCock));
|
||||
g_base->audio->SafePlaySysSound(SysSoundID::kGunCock);
|
||||
}
|
||||
}
|
||||
newly_connected_controllers_.clear();
|
||||
@ -210,7 +207,7 @@ void Input::AnnounceDisconnects_() {
|
||||
ScreenMessage(s);
|
||||
}
|
||||
if (g_base->assets->sys_assets_loaded()) {
|
||||
g_base->audio->PlaySound(g_base->assets->SysSound(SysSoundID::kCorkPop));
|
||||
g_base->audio->SafePlaySysSound(SysSoundID::kCorkPop);
|
||||
}
|
||||
|
||||
newly_disconnected_controllers_.clear();
|
||||
@ -392,9 +389,9 @@ void Input::UpdateInputDeviceCounts_() {
|
||||
// just due to those)
|
||||
if (input_device.Exists()
|
||||
&& ((*input_device).IsTouchScreen() || (*input_device).IsKeyboard()
|
||||
|| ((*input_device).last_input_time_millisecs() != 0
|
||||
|| ((*input_device).last_active_time_millisecs() != 0
|
||||
&& current_time_millisecs
|
||||
- (*input_device).last_input_time_millisecs()
|
||||
- (*input_device).last_active_time_millisecs()
|
||||
< 60000))) {
|
||||
total++;
|
||||
if (!(*input_device).IsTouchScreen()) {
|
||||
@ -441,9 +438,9 @@ auto Input::GetLocalActiveInputDeviceCount() -> int {
|
||||
if (input_device.Exists() && !input_device->IsKeyboard()
|
||||
&& !input_device->IsTouchScreen() && !input_device->IsUIOnly()
|
||||
&& input_device->IsLocal()
|
||||
&& (input_device->last_input_time_millisecs() != 0
|
||||
&& (input_device->last_active_time_millisecs() != 0
|
||||
&& current_time_millisecs
|
||||
- input_device->last_input_time_millisecs()
|
||||
- input_device->last_active_time_millisecs()
|
||||
< 60000)) {
|
||||
count++;
|
||||
}
|
||||
@ -639,8 +636,9 @@ void Input::UnlockAllInput(bool permanent, const std::string& label) {
|
||||
permanent ? "permanent unlock: "
|
||||
: "temp unlock: " + label + " time "
|
||||
+ std::to_string(g_core->GetAppTimeMillisecs()));
|
||||
while (recent_input_locks_unlocks_.size() > 10)
|
||||
while (recent_input_locks_unlocks_.size() > 10) {
|
||||
recent_input_locks_unlocks_.pop_front();
|
||||
}
|
||||
|
||||
if (permanent) {
|
||||
input_lock_count_permanent_--;
|
||||
@ -722,15 +720,15 @@ void Input::PrintLockLabels_() {
|
||||
void Input::PushTextInputEvent(const std::string& text) {
|
||||
assert(g_base->logic->event_loop());
|
||||
g_base->logic->event_loop()->PushCall([this, text] {
|
||||
// Mark as active even if input is locked.
|
||||
MarkInputActive();
|
||||
|
||||
// If the app doesn't want direct text input right now, ignore.
|
||||
if (!g_base->app_adapter->HasDirectKeyboardInput()) {
|
||||
if (IsInputLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore if input is locked.
|
||||
if (IsInputLocked()) {
|
||||
// If the app doesn't want direct text input right now, ignore.
|
||||
if (!g_base->app_adapter->HasDirectKeyboardInput()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -795,16 +793,14 @@ void Input::HandleJoystickEvent_(const SDL_Event& event,
|
||||
if (ShouldCompletelyIgnoreInputDevice(input_device)) {
|
||||
return;
|
||||
}
|
||||
if (IsInputLocked()) {
|
||||
|
||||
// Mark as active even if input is locked.
|
||||
input_device->UpdateLastActiveTime();
|
||||
|
||||
if (IsInputLocked(input_device)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make note that we're not idle.
|
||||
MarkInputActive();
|
||||
|
||||
// And that this particular device isn't idle either.
|
||||
input_device->UpdateLastInputTime();
|
||||
|
||||
// If someone is capturing these events, give them a crack at it.
|
||||
if (joystick_input_capture_) {
|
||||
if (joystick_input_capture_(event, input_device)) {
|
||||
@ -905,9 +901,9 @@ void Input::HandleKeyReleaseSimple_(int keycode) {
|
||||
void Input::HandleKeyPress_(const SDL_Keysym& keysym) {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// Mark as active even if input is locked.
|
||||
MarkInputActive();
|
||||
|
||||
// Ignore all key presses if input is locked.
|
||||
if (IsInputLocked()) {
|
||||
return;
|
||||
}
|
||||
@ -1180,8 +1176,9 @@ void Input::PushMouseScrollEvent(const Vector2f& amount) {
|
||||
void Input::HandleMouseScroll_(const Vector2f& amount) {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// If input is locked, allow it to mark us active but nothing more.
|
||||
// Mark as active even if input is locked.
|
||||
MarkInputActive();
|
||||
|
||||
if (IsInputLocked()) {
|
||||
return;
|
||||
}
|
||||
@ -1217,8 +1214,9 @@ void Input::PushSmoothMouseScrollEvent(const Vector2f& velocity,
|
||||
void Input::HandleSmoothMouseScroll_(const Vector2f& velocity, bool momentum) {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// If input is locked, allow it to mark us active but nothing more.
|
||||
// Mark as active even if input is locked.
|
||||
MarkInputActive();
|
||||
|
||||
if (IsInputLocked()) {
|
||||
return;
|
||||
}
|
||||
@ -1259,6 +1257,7 @@ void Input::HandleMouseMotion_(const Vector2f& position) {
|
||||
assert(g_base);
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// Mark as active even if input is locked.
|
||||
MarkInputActive();
|
||||
|
||||
if (IsInputLocked()) {
|
||||
@ -1309,6 +1308,7 @@ void Input::HandleMouseDown_(int button, const Vector2f& position) {
|
||||
assert(g_base);
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// Mark as active even if input is locked.
|
||||
MarkInputActive();
|
||||
|
||||
if (IsInputLocked()) {
|
||||
@ -1416,12 +1416,13 @@ void Input::HandleTouchEvent_(const TouchEvent& e) {
|
||||
assert(g_base->InLogicThread());
|
||||
assert(g_base->graphics);
|
||||
|
||||
// Mark as active even if input is locked.
|
||||
MarkInputActive();
|
||||
|
||||
if (IsInputLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MarkInputActive();
|
||||
|
||||
if (g_buildconfig.ostype_ios_tvos()) {
|
||||
printf("FIXME: update touch handling\n");
|
||||
}
|
||||
@ -1564,4 +1565,11 @@ void Input::LsInputDevices() {
|
||||
Log(LogLevel::kInfo, out);
|
||||
}
|
||||
|
||||
auto Input::ShouldAllowInputInAttractMode_(InputDevice* device) const -> bool {
|
||||
if (device == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return device->allow_input_in_attract_mode();
|
||||
}
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "ballistica/base/base.h"
|
||||
#include "ballistica/shared/foundation/macros.h"
|
||||
#include "ballistica/shared/foundation/object.h"
|
||||
#include "ballistica/shared/foundation/types.h"
|
||||
|
||||
@ -62,7 +63,14 @@ class Input {
|
||||
void Reset();
|
||||
void LockAllInput(bool permanent, const std::string& label);
|
||||
void UnlockAllInput(bool permanent, const std::string& label);
|
||||
auto IsInputLocked() const -> bool {
|
||||
auto IsInputLocked(InputDevice* device = nullptr) const -> bool {
|
||||
// Special case; in attract-mode we ignore all input except our
|
||||
// dummy controllers.
|
||||
if (attract_mode_) {
|
||||
if (!ShouldAllowInputInAttractMode_(device)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return input_lock_count_temp_ > 0 || input_lock_count_permanent_ > 0;
|
||||
}
|
||||
auto cursor_pos_x() const -> float { return cursor_pos_x_; }
|
||||
@ -92,12 +100,7 @@ class Input {
|
||||
}
|
||||
void Draw(FrameDef* frame_def);
|
||||
|
||||
// Get the total idle time for the system.
|
||||
// FIXME - should better coordinate this with InputDevice::getLastUsedTime().
|
||||
// auto GetIdleTime() const -> millisecs_t;
|
||||
|
||||
// Should be called whenever user-input of some form comes through.
|
||||
// void ResetIdleTime() { last_input_time_ = GetAppTimeMillisecs(); }
|
||||
/// Should be called whenever user-input of some form comes through.
|
||||
auto MarkInputActive() { input_active_ = true; }
|
||||
|
||||
// returns true if more than one non-keyboard device has been active recently
|
||||
@ -153,7 +156,11 @@ class Input {
|
||||
void ReleaseJoystickInput();
|
||||
void RebuildInputDeviceDelegates();
|
||||
|
||||
auto attract_mode() const { return attract_mode_; }
|
||||
void set_attract_mode(bool val) { attract_mode_ = val; }
|
||||
|
||||
private:
|
||||
auto ShouldAllowInputInAttractMode_(InputDevice* device) const -> bool;
|
||||
void UpdateInputDeviceCounts_();
|
||||
auto GetNewNumberedIdentifier_(const std::string& name,
|
||||
const std::string& identifier) -> int;
|
||||
@ -183,8 +190,9 @@ class Input {
|
||||
int max_controller_count_so_far_{};
|
||||
int local_active_input_device_count_{};
|
||||
int mouse_move_count_{};
|
||||
int input_lock_count_temp_{};
|
||||
int input_lock_count_permanent_{};
|
||||
int8_t input_lock_count_temp_{};
|
||||
int8_t input_lock_count_permanent_{};
|
||||
bool attract_mode_{};
|
||||
bool input_active_{};
|
||||
bool have_button_using_inputs_{};
|
||||
bool have_start_activated_default_button_inputs_{};
|
||||
|
||||
@ -166,10 +166,8 @@ void RemoteAppServer::HandleData(int socket, uint8_t* buffer, size_t amt,
|
||||
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::kCorkPop));
|
||||
});
|
||||
g_base->logic->event_loop()->PushCall(
|
||||
[] { g_base->audio->SafePlaySysSound(SysSoundID::kCorkPop); });
|
||||
g_base->input->PushRemoveInputDeviceCall(client->joystick_, false);
|
||||
client->joystick_ = nullptr;
|
||||
client->in_use = false;
|
||||
@ -377,8 +375,7 @@ auto RemoteAppServer::GetClient(int request_id, struct sockaddr* addr,
|
||||
});
|
||||
g_base->logic->event_loop()->PushCall([] {
|
||||
if (g_base->assets->asset_loads_allowed()) {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(SysSoundID::kGunCock));
|
||||
g_base->audio->SafePlaySysSound(SysSoundID::kGunCock);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -429,8 +426,7 @@ auto RemoteAppServer::GetClient(int request_id, struct sockaddr* addr,
|
||||
|
||||
g_base->logic->event_loop()->PushCall([] {
|
||||
if (g_base->assets->asset_loads_allowed()) {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(SysSoundID::kGunCock));
|
||||
g_base->audio->SafePlaySysSound(SysSoundID::kGunCock);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -218,7 +218,8 @@ auto NetworkReader::RunThread_() -> int {
|
||||
sd = sd6_;
|
||||
can_read = can_read_6;
|
||||
} else {
|
||||
FatalError("Should not get here.");
|
||||
FatalError("Should not get here; s_index=" + std::to_string(s_index)
|
||||
+ ".");
|
||||
sd = -1;
|
||||
can_read = false;
|
||||
}
|
||||
|
||||
@ -1805,6 +1805,26 @@ static PyMethodDef PyOpenFileExternallyDef = {
|
||||
"Open the provided file in the default external app.",
|
||||
};
|
||||
|
||||
// --------------------------- get_input_idle_time -----------------------------
|
||||
|
||||
static auto PyGetInputIdleTime(PyObject* self) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
|
||||
BA_PRECONDITION(g_base->InLogicThread());
|
||||
return PyFloat_FromDouble(0.001 * g_base->input->input_idle_time());
|
||||
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
static PyMethodDef PyGetInputIdleTimeDef = {
|
||||
"get_input_idle_time", // name
|
||||
(PyCFunction)PyGetInputIdleTime, // method
|
||||
METH_NOARGS, // flags
|
||||
|
||||
"get_input_idle_time() -> float\n"
|
||||
"\n"
|
||||
"Return seconds since any local input occurred (touch, keypress, etc.).",
|
||||
};
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
auto PythonMethodsMisc::GetMethods() -> std::vector<PyMethodDef> {
|
||||
@ -1873,6 +1893,7 @@ auto PythonMethodsMisc::GetMethods() -> std::vector<PyMethodDef> {
|
||||
PyNativeReviewRequestDef,
|
||||
PyTempTestingDef,
|
||||
PyOpenFileExternallyDef,
|
||||
PyGetInputIdleTimeDef,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/core/python/core_python.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/generic/lambda_runnable.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
#include "ballistica/shared/python/python.h"
|
||||
#include "ballistica/shared/python/python_sys.h"
|
||||
|
||||
@ -169,7 +169,6 @@ void AppConfig::CompleteMap(const T& entry_map) {
|
||||
|
||||
void AppConfig::SetupEntries() {
|
||||
// Register all our typed entries.
|
||||
float_entries_[FloatID::kScreenGamma] = FloatEntry("Screen Gamma", 1.0F);
|
||||
float_entries_[FloatID::kScreenPixelScale] =
|
||||
FloatEntry("Screen Pixel Scale", 1.0F);
|
||||
float_entries_[FloatID::kTouchControlsScale] =
|
||||
@ -236,6 +235,8 @@ void AppConfig::SetupEntries() {
|
||||
BoolEntry("Disable Camera Shake", false);
|
||||
bool_entries_[BoolID::kDisableCameraGyro] =
|
||||
BoolEntry("Disable Camera Gyro", false);
|
||||
bool_entries_[BoolID::kShowDemosWhenIdle] =
|
||||
BoolEntry("Show Demos When Idle", false);
|
||||
|
||||
// Now add everything to our name map and make sure all is kosher.
|
||||
CompleteMap(float_entries_);
|
||||
|
||||
@ -9,9 +9,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// FIXME: this system is old and dumb.
|
||||
// Should come up with a better one using the meta system
|
||||
// based on Python dataclassio types or whatnot.
|
||||
// FIXME: this system is old and dumb. It was built to make C++ stuff
|
||||
// type-safe but does not handle the Python side at all. We should come up
|
||||
// with something Python-centric using dataclasses/etc. where a C++
|
||||
// component gets autogenerated via the meta system/etc.
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
@ -24,7 +25,6 @@ class AppConfig {
|
||||
// Our official config values:
|
||||
|
||||
enum class FloatID {
|
||||
kScreenGamma,
|
||||
kScreenPixelScale,
|
||||
kTouchControlsScale,
|
||||
kTouchControlsScaleMovement,
|
||||
@ -74,6 +74,7 @@ class AppConfig {
|
||||
kEnableRemoteApp,
|
||||
kDisableCameraShake,
|
||||
kDisableCameraGyro,
|
||||
kShowDemosWhenIdle,
|
||||
kLast // Sentinel.
|
||||
};
|
||||
|
||||
|
||||
@ -1110,7 +1110,7 @@ void DevConsole::ToggleState() {
|
||||
state_ = State_::kInactive;
|
||||
break;
|
||||
}
|
||||
g_base->audio->PlaySound(g_base->assets->SysSound(SysSoundID::kBlip));
|
||||
g_base->audio->SafePlaySysSound(SysSoundID::kBlip);
|
||||
transition_start_ = g_base->logic->display_time();
|
||||
}
|
||||
|
||||
@ -1445,8 +1445,7 @@ auto DevConsole::PasteFromClipboard() -> bool {
|
||||
if (g_base->ClipboardHasText()) {
|
||||
auto text = g_base->ClipboardGetText();
|
||||
if (strstr(text.c_str(), "\n") || strstr(text.c_str(), "\r")) {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(SysSoundID::kErrorBeep));
|
||||
g_base->audio->SafePlaySysSound(SysSoundID::kErrorBeep);
|
||||
ScreenMessage("Can only paste single lines of text.",
|
||||
Vector3f(1.0f, 0.0f, 0.0f));
|
||||
} else {
|
||||
|
||||
@ -14,8 +14,6 @@
|
||||
#include "ballistica/base/ui/dev_console.h"
|
||||
#include "ballistica/base/ui/ui_delegate.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/foundation/macros.h"
|
||||
#include "ballistica/shared/generic/native_stack_trace.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
@ -427,8 +425,7 @@ auto UI::GetWidgetForInput(InputDevice* input_device) -> ui_v1::Widget* {
|
||||
// they're not the chosen one.
|
||||
if (time - last_widget_input_reject_err_sound_time_ > 5000) {
|
||||
last_widget_input_reject_err_sound_time_ = time;
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(SysSoundID::kErrorBeep));
|
||||
g_base->audio->SafePlaySysSound(SysSoundID::kErrorBeep);
|
||||
print_menu_owner = true;
|
||||
}
|
||||
ret_val = nullptr; // Rejected!
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
#include "ballistica/base/graphics/support/camera.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
#include "ballistica/classic/support/stress_test.h"
|
||||
#include "ballistica/scene_v1/support/scene_v1_app_mode.h"
|
||||
@ -154,11 +155,13 @@ static auto PySetStressTesting(PyObject* self, PyObject* args) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
int enable;
|
||||
int player_count;
|
||||
if (!PyArg_ParseTuple(args, "pi", &enable, &player_count)) {
|
||||
int attract_mode;
|
||||
if (!PyArg_ParseTuple(args, "pip", &enable, &player_count, &attract_mode)) {
|
||||
return nullptr;
|
||||
}
|
||||
g_base->logic->event_loop()->PushCall([enable, player_count] {
|
||||
g_classic->stress_test()->Set(enable, player_count);
|
||||
g_base->logic->event_loop()->PushCall([enable, player_count, attract_mode] {
|
||||
g_classic->stress_test()->Set(enable, player_count, attract_mode);
|
||||
g_base->input->set_attract_mode(enable && attract_mode);
|
||||
});
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
@ -169,7 +172,9 @@ static PyMethodDef PySetStressTestingDef = {
|
||||
PySetStressTesting, // method
|
||||
METH_VARARGS, // flags
|
||||
|
||||
"set_stress_testing(testing: bool, player_count: int) -> None\n"
|
||||
"set_stress_testing(testing: bool,\n"
|
||||
" player_count: int,\n"
|
||||
" attract_mode: bool) -> None\n"
|
||||
"\n"
|
||||
"(internal)",
|
||||
};
|
||||
|
||||
@ -5,22 +5,21 @@
|
||||
#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::classic {
|
||||
|
||||
void StressTest::Set(bool enable, int player_count) {
|
||||
void StressTest::Set(bool enable, int player_count, bool attract_mode) {
|
||||
assert(g_base->InLogicThread());
|
||||
bool was_stress_testing = stress_testing_;
|
||||
stress_testing_ = enable;
|
||||
stress_test_player_count_ = player_count;
|
||||
attract_mode_ = attract_mode;
|
||||
|
||||
// If we're turning on, reset our intervals and things.
|
||||
if (!was_stress_testing && stress_testing_) {
|
||||
// So our first sample is 1 interval from now.
|
||||
// last_stress_test_update_time_ = g_core->GetAppTimeMillisecs();
|
||||
|
||||
// Reset our frames-rendered tally.
|
||||
if (g_base && g_base->graphics_server
|
||||
@ -71,9 +70,11 @@ void StressTest::ProcessInputs(int player_count) {
|
||||
test_inputs_.push_back(new base::TestInput());
|
||||
}
|
||||
|
||||
// Every so often lets kill the oldest one off.
|
||||
// Every so often lets kill the oldest one off (less often in attract-mode
|
||||
// though).
|
||||
int odds = attract_mode_ ? 10000 : 2000;
|
||||
if (explicit_bool(true)) {
|
||||
if (test_inputs_.size() > 0 && (rand() % 2000 < 3)) { // NOLINT
|
||||
if (test_inputs_.size() > 0 && (rand() % odds < 3)) { // NOLINT
|
||||
stress_test_last_leave_time_ = time;
|
||||
|
||||
// Usually do oldest; sometimes newest.
|
||||
|
||||
@ -11,7 +11,7 @@ namespace ballistica::classic {
|
||||
|
||||
class StressTest {
|
||||
public:
|
||||
void Set(bool enable, int player_count);
|
||||
void Set(bool enable, int player_count, bool attract_mode);
|
||||
void Update();
|
||||
|
||||
private:
|
||||
@ -23,8 +23,7 @@ class StressTest {
|
||||
int stress_test_player_count_{8};
|
||||
int last_total_frames_rendered_{};
|
||||
bool stress_testing_{};
|
||||
// millisecs_t last_stress_test_update_time_{};
|
||||
// FILE* stress_test_stats_file_{};
|
||||
bool attract_mode_{};
|
||||
Object::Ref<base::AppTimer> update_timer_{};
|
||||
};
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "ballistica/core/platform/core_platform.h"
|
||||
#include "ballistica/core/python/core_python.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/foundation/types.h"
|
||||
|
||||
namespace ballistica::core {
|
||||
|
||||
@ -75,7 +76,8 @@ void CoreFeatureSet::DoImport(const CoreConfig& config) {
|
||||
// didn't exist before. Can at least add an offset to give an accurate
|
||||
// time though.
|
||||
auto seconds_since_actual_start =
|
||||
static_cast<double>(CorePlatform::GetCurrentMillisecs() - start_millisecs)
|
||||
static_cast<seconds_t>(CorePlatform::GetCurrentMillisecs()
|
||||
- start_millisecs)
|
||||
/ 1000.0;
|
||||
g_core->LifecycleLog("core import begin", -seconds_since_actual_start);
|
||||
g_core->LifecycleLog("core import end");
|
||||
@ -320,9 +322,9 @@ auto CoreFeatureSet::GetAppTimeMicrosecs() -> microsecs_t {
|
||||
return app_time_microsecs_;
|
||||
}
|
||||
|
||||
auto CoreFeatureSet::GetAppTimeSeconds() -> double {
|
||||
auto CoreFeatureSet::GetAppTimeSeconds() -> seconds_t {
|
||||
UpdateAppTime();
|
||||
return static_cast<double>(app_time_microsecs_) / 1000000;
|
||||
return static_cast<seconds_t>(app_time_microsecs_) / 1000000;
|
||||
}
|
||||
|
||||
void CoreFeatureSet::UpdateAppTime() {
|
||||
|
||||
@ -88,7 +88,7 @@ class CoreFeatureSet {
|
||||
/// App-time is basically the total time that the engine has been actively
|
||||
/// running. (The 'App' here is a slight misnomer). It will stop
|
||||
/// progressing while the app is suspended and will never go backwards.
|
||||
auto GetAppTimeSeconds() -> double;
|
||||
auto GetAppTimeSeconds() -> seconds_t;
|
||||
|
||||
/// Are we in the 'main' thread? The thread that first inited Core is
|
||||
/// considered the 'main' thread; on most platforms it is the one where
|
||||
|
||||
@ -244,10 +244,12 @@ void CorePython::MonolithicModeBaEnvConfigure() {
|
||||
auto default_py_dir = std::string("ba_data") + BA_DIRSLASH + "python";
|
||||
auto data_dir_mono_default =
|
||||
g_core->platform->GetDataDirectoryMonolithicDefault();
|
||||
|
||||
// Keep path clean if data-dir val is ".".
|
||||
if (data_dir_mono_default != ".") {
|
||||
default_py_dir = data_dir_mono_default + BA_DIRSLASH + default_py_dir;
|
||||
}
|
||||
|
||||
auto args = PythonRef::Stolen(Py_BuildValue("(s)", default_py_dir.c_str()));
|
||||
objs().Get(ObjID::kPrependSysPathCall).Call(args);
|
||||
|
||||
@ -259,8 +261,9 @@ void CorePython::MonolithicModeBaEnvConfigure() {
|
||||
g_core->platform->GetDataDirectoryMonolithicDefault();
|
||||
std::optional<std::string> user_python_dir =
|
||||
g_core->platform->GetUserPythonDirectoryMonolithicDefault();
|
||||
|
||||
// clang-format off
|
||||
auto kwargs =
|
||||
// clang-format off
|
||||
PythonRef::Stolen(Py_BuildValue(
|
||||
"{"
|
||||
"sO" // config_dir
|
||||
@ -277,14 +280,15 @@ void CorePython::MonolithicModeBaEnvConfigure() {
|
||||
"contains_python_dist",
|
||||
g_buildconfig.contains_python_dist() ? Py_True : Py_False));
|
||||
// clang-format on
|
||||
|
||||
auto result = objs()
|
||||
.Get(ObjID::kBaEnvConfigureCall)
|
||||
.Call(objs().Get(ObjID::kEmptyTuple), kwargs);
|
||||
if (!result.Exists()) {
|
||||
FatalError(
|
||||
"Environment setup failed.\n"
|
||||
"This usually means you are running the app from the wrong location.\n"
|
||||
"See log for details.");
|
||||
FatalError("Environment setup failed (no error info available).");
|
||||
}
|
||||
if (result.ValueIsString()) {
|
||||
FatalError("Environment setup failed:\n" + result.ValueAsString());
|
||||
}
|
||||
g_core->LifecycleLog("baenv.configure() end");
|
||||
}
|
||||
|
||||
@ -82,8 +82,9 @@ ConnectionToClient::~ConnectionToClient() {
|
||||
std::string s = g_base->assets->GetResourceString("playerLeftPartyText");
|
||||
Utils::StringReplaceOne(&s, "${NAME}", peer_spec().GetDisplayString());
|
||||
ScreenMessage(s, {1, 0.5f, 0.0f});
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kCorkPop));
|
||||
if (g_base->assets->sys_assets_loaded()) {
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kCorkPop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,8 +235,9 @@ void ConnectionToClient::HandleGamePacket(const std::vector<uint8_t>& data) {
|
||||
Utils::StringReplaceOne(&s, "${NAME}",
|
||||
peer_spec().GetDisplayString());
|
||||
ScreenMessage(s, {0.5f, 1, 0.5f});
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kGunCock));
|
||||
if (g_base->assets->sys_assets_loaded()) {
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kGunCock);
|
||||
}
|
||||
}
|
||||
|
||||
// Also mark the time for flashing the 'someone just joined your
|
||||
|
||||
@ -45,8 +45,7 @@ ConnectionToHost::~ConnectionToHost() {
|
||||
Utils::StringReplaceOne(&s, "${NAME}", peer_spec().GetDisplayString());
|
||||
}
|
||||
ScreenMessage(s, {1, 0.5f, 0.0f});
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kCorkPop));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kCorkPop);
|
||||
} else {
|
||||
ScreenMessage(g_base->assets->GetResourceString("connectionRejectedText"),
|
||||
{1, 0, 0});
|
||||
@ -413,8 +412,7 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
Utils::StringReplaceOne(
|
||||
&s, "${NAME}", PlayerSpec(str_buffer.data()).GetDisplayString());
|
||||
ScreenMessage(s, {0.5f, 1.0f, 0.5f});
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kGunCock));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kGunCock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -430,8 +428,7 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
Utils::StringReplaceOne(
|
||||
&s, "${NAME}", PlayerSpec(&(str_buffer[0])).GetDisplayString());
|
||||
ScreenMessage(s, {1, 0.5f, 0.0f});
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kCorkPop));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kCorkPop);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -571,8 +568,7 @@ void ConnectionToHost::HandleMessagePacket(const std::vector<uint8_t>& buffer) {
|
||||
Utils::StringReplaceOne(&s, "${NAME}", peer_spec().GetDisplayString());
|
||||
}
|
||||
ScreenMessage(s, {0.5f, 1, 0.5f});
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kGunCock));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kGunCock);
|
||||
|
||||
printed_connect_message_ = true;
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ void PropNode::SetIsAreaOfInterest(bool val) {
|
||||
void PropNode::Draw(base::FrameDef* frame_def) {
|
||||
#if !BA_HEADLESS_BUILD
|
||||
|
||||
// need our texture, mesh, and body to be present to draw..
|
||||
// We need a texture, mesh, and body to be present to draw.
|
||||
if ((!mesh_.Exists()) || (!color_texture_.Exists()) || (!body_.Exists())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -73,6 +73,9 @@ void PythonClassInputDevice::SetupType(PyTypeObject* cls) {
|
||||
" is_remote_client (bool):\n"
|
||||
" Whether this input-device represents a remotely-connected\n"
|
||||
" client.\n"
|
||||
"\n"
|
||||
" is_test_input (bool):\n"
|
||||
" Whether this input-device is a dummy device for testing.\n"
|
||||
"\n";
|
||||
|
||||
cls->tp_new = tp_new;
|
||||
@ -265,6 +268,16 @@ auto PythonClassInputDevice::tp_getattro(PythonClassInputDevice* self,
|
||||
} else {
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
} else if (!strcmp(s, "is_test_input")) {
|
||||
auto* delegate = self->input_device_delegate_->Get();
|
||||
if (!delegate) {
|
||||
throw Exception(PyExcType::kInputDeviceNotFound);
|
||||
}
|
||||
if (delegate->input_device().IsTestInput()) {
|
||||
Py_RETURN_TRUE;
|
||||
} else {
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to generic behavior.
|
||||
|
||||
@ -8,14 +8,12 @@
|
||||
#include "ballistica/core/python/core_python.h"
|
||||
#include "ballistica/scene_v1/connection/connection_set.h"
|
||||
#include "ballistica/scene_v1/connection/connection_to_client.h"
|
||||
#include "ballistica/scene_v1/connection/connection_to_host.h"
|
||||
#include "ballistica/scene_v1/connection/connection_to_host_udp.h"
|
||||
#include "ballistica/scene_v1/python/scene_v1_python.h"
|
||||
#include "ballistica/scene_v1/support/scene_v1_app_mode.h"
|
||||
#include "ballistica/shared/math/vector3f.h"
|
||||
#include "ballistica/shared/networking/sockaddr.h"
|
||||
#include "ballistica/shared/python/python.h"
|
||||
#include "ballistica/shared/python/python_ref.h"
|
||||
#include "ballistica/shared/python/python_sys.h"
|
||||
|
||||
namespace ballistica::scene_v1 {
|
||||
|
||||
@ -1500,6 +1500,74 @@ static PyMethodDef PySetReplaySpeedExponentDef = {
|
||||
"Set replay speed. Actual displayed speed is pow(2, speed).",
|
||||
};
|
||||
|
||||
// -------------------------- is_replay_paused ---------------------------------
|
||||
|
||||
static auto PyIsReplayPaused(PyObject* self, PyObject* args) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
|
||||
if (appmode->is_replay_paused()) {
|
||||
Py_RETURN_TRUE;
|
||||
} else {
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
static PyMethodDef PyIsReplayPausedDef = {
|
||||
"is_replay_paused", // name
|
||||
PyIsReplayPaused, // method
|
||||
METH_VARARGS, // flags
|
||||
|
||||
"is_replay_paused() -> bool\n"
|
||||
"\n"
|
||||
"(internal)\n"
|
||||
"\n"
|
||||
"Returns if Replay is paused or not.",
|
||||
};
|
||||
// ------------------------ pause_replay ---------------------------------------
|
||||
|
||||
static auto PyPauseReplay(PyObject* self, PyObject* args) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
|
||||
appmode->PauseReplay();
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
static PyMethodDef PyPauseReplayDef = {
|
||||
"pause_replay", // name
|
||||
PyPauseReplay, // method
|
||||
METH_VARARGS, // flags
|
||||
|
||||
"pause_replay() -> None\n"
|
||||
"\n"
|
||||
"(internal)\n"
|
||||
"\n"
|
||||
"Pauses replay.",
|
||||
};
|
||||
|
||||
// ------------------------ resume_replay --------------------------------------
|
||||
|
||||
static auto PyResumeReplay(PyObject* self, PyObject* args) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
|
||||
appmode->ResumeReplay();
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
static PyMethodDef PyResumeReplayDef = {
|
||||
"resume_replay", // name
|
||||
PyResumeReplay, // method
|
||||
METH_VARARGS, // flags
|
||||
|
||||
"resume_replay() -> None\n"
|
||||
"\n"
|
||||
"(internal)\n"
|
||||
"\n"
|
||||
"Resumes replay.",
|
||||
};
|
||||
|
||||
// ----------------------- reset_random_player_names ---------------------------
|
||||
|
||||
static auto PyResetRandomPlayerNames(PyObject* self, PyObject* args,
|
||||
@ -1777,6 +1845,9 @@ auto PythonMethodsScene::GetMethods() -> std::vector<PyMethodDef> {
|
||||
PyResetRandomPlayerNamesDef,
|
||||
PySetReplaySpeedExponentDef,
|
||||
PyGetReplaySpeedExponentDef,
|
||||
PyIsReplayPausedDef,
|
||||
PyPauseReplayDef,
|
||||
PyResumeReplayDef,
|
||||
PySetDebugSpeedExponentDef,
|
||||
PyGetGameRosterDef,
|
||||
PyGetForegroundHostActivityDef,
|
||||
|
||||
@ -17,6 +17,9 @@ namespace ballistica::scene_v1 {
|
||||
auto ClientSessionReplay::GetActualTimeAdvanceMillisecs(
|
||||
double base_advance_millisecs) -> double {
|
||||
auto* appmode = SceneV1AppMode::GetActiveOrFatal();
|
||||
if (appmode->is_replay_paused()) {
|
||||
return 0.0;
|
||||
}
|
||||
return base_advance_millisecs * pow(2.0f, appmode->replay_speed_exponent());
|
||||
}
|
||||
|
||||
@ -36,7 +39,7 @@ ClientSessionReplay::~ClientSessionReplay() {
|
||||
|
||||
// we no longer are responsible for feeding clients to this device..
|
||||
appmode->connections()->UnregisterClientController(this);
|
||||
|
||||
appmode->ResumeReplay();
|
||||
if (file_) {
|
||||
fclose(file_);
|
||||
file_ = nullptr;
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include "ballistica/scene_v1/support/scene_v1_app_mode.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/audio/audio_source.h"
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
@ -1160,8 +1159,7 @@ void SceneV1AppMode::LocalDisplayChatMessage(
|
||||
g_scene_v1->python->HandleLocalChatMessage(final_message);
|
||||
}
|
||||
if (!chat_muted_) {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1224,6 +1222,10 @@ void SceneV1AppMode::SetReplaySpeedExponent(int val) {
|
||||
replay_speed_mult_ = powf(2.0f, static_cast<float>(replay_speed_exponent_));
|
||||
}
|
||||
|
||||
void SceneV1AppMode::PauseReplay() { replay_paused_ = true; }
|
||||
|
||||
void SceneV1AppMode::ResumeReplay() { replay_paused_ = false; }
|
||||
|
||||
void SceneV1AppMode::SetDebugSpeedExponent(int val) {
|
||||
debug_speed_exponent_ = val;
|
||||
debug_speed_mult_ = powf(2.0f, static_cast<float>(debug_speed_exponent_));
|
||||
|
||||
@ -96,11 +96,14 @@ class SceneV1AppMode : public base::AppMode {
|
||||
auto debug_speed_mult() const -> float { return debug_speed_mult_; }
|
||||
auto replay_speed_exponent() const -> int { return replay_speed_exponent_; }
|
||||
auto replay_speed_mult() const -> float { return replay_speed_mult_; }
|
||||
auto is_replay_paused() const -> bool { return replay_paused_; }
|
||||
void OnScreenSizeChange() override;
|
||||
auto kick_idle_players() const -> bool { return kick_idle_players_; }
|
||||
void LanguageChanged() override;
|
||||
void SetDebugSpeedExponent(int val);
|
||||
void SetReplaySpeedExponent(int val);
|
||||
void PauseReplay();
|
||||
void ResumeReplay();
|
||||
void set_admin_public_ids(const std::set<std::string>& ids) {
|
||||
admin_public_ids_ = ids;
|
||||
}
|
||||
@ -223,6 +226,7 @@ class SceneV1AppMode : public base::AppMode {
|
||||
bool game_roster_dirty_{};
|
||||
bool kick_vote_in_progress_{};
|
||||
bool kick_voting_enabled_{true};
|
||||
bool replay_paused_{false};
|
||||
|
||||
cJSON* game_roster_{};
|
||||
millisecs_t last_game_roster_send_time_{};
|
||||
|
||||
@ -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 = 21743;
|
||||
const int kEngineBuildNumber = 21756;
|
||||
const char* kEngineVersion = "1.7.33";
|
||||
const int kEngineApiVersion = 8;
|
||||
|
||||
|
||||
@ -11,8 +11,9 @@
|
||||
|
||||
namespace ballistica {
|
||||
|
||||
// Note: implicitly using core's internal globals here, so our behavior is
|
||||
// undefined if core has not been imported by *someone*.
|
||||
// Note: implicitly using core's internal globals here, but we should try to
|
||||
// behave reasonably if they're not inited since fatal errors can happen any
|
||||
// time.
|
||||
using core::g_base_soft;
|
||||
using core::g_core;
|
||||
|
||||
@ -121,8 +122,8 @@ void FatalError::ReportFatalError(const std::string& message,
|
||||
std::string prefix = "FATAL-ERROR-LOG:";
|
||||
std::string suffix;
|
||||
|
||||
// If we have no core state yet, include this message explicitly
|
||||
// since it won't be part of the standard log.
|
||||
// If we have no core state yet, include this message explicitly since it
|
||||
// won't be part of the standard log.
|
||||
if (g_core == nullptr) {
|
||||
suffix = logmsg;
|
||||
}
|
||||
@ -147,7 +148,7 @@ void FatalError::ReportFatalError(const std::string& message,
|
||||
}
|
||||
|
||||
void FatalError::DoBlockingFatalErrorDialog(const std::string& message) {
|
||||
// We should not get here without this intact.
|
||||
// Should not be possible to get here without this intact.
|
||||
assert(g_core);
|
||||
// If we're in the main thread; just fire off the dialog directly.
|
||||
// Otherwise tell the main thread to do it and wait around until it's
|
||||
|
||||
@ -211,6 +211,12 @@ enum class SpecialChar : uint8_t {
|
||||
kPlayPauseButton,
|
||||
kFastForwardButton,
|
||||
kDpadCenterButton,
|
||||
kPlayStationCrossButton,
|
||||
kPlayStationCircleButton,
|
||||
kPlayStationTriangleButton,
|
||||
kPlayStationSquareButton,
|
||||
kPlayButton,
|
||||
kPauseButton,
|
||||
kOuyaButtonO,
|
||||
kOuyaButtonU,
|
||||
kOuyaButtonY,
|
||||
|
||||
@ -157,6 +157,12 @@ auto PythonRef::ValueIsNone() const -> bool {
|
||||
return obj_ == Py_None;
|
||||
}
|
||||
|
||||
auto PythonRef::ValueIsString() const -> bool {
|
||||
assert(Python::HaveGIL());
|
||||
ThrowIfUnset();
|
||||
return Python::IsPyString(obj_);
|
||||
}
|
||||
|
||||
auto PythonRef::ValueAsLString() const -> std::string {
|
||||
assert(Python::HaveGIL());
|
||||
ThrowIfUnset();
|
||||
|
||||
@ -171,6 +171,7 @@ class PythonRef {
|
||||
/// Throws an exception for other types.
|
||||
auto ValueAsLString() const -> std::string;
|
||||
|
||||
auto ValueIsString() const -> bool;
|
||||
auto ValueAsString() const -> std::string;
|
||||
auto ValueAsStringSequence() const -> std::list<std::string>;
|
||||
auto ValueAsOptionalString() const -> std::optional<std::string>;
|
||||
|
||||
@ -5,10 +5,8 @@
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/app_mode/app_mode.h"
|
||||
#include "ballistica/base/assets/sound_asset.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/plus_soft.h"
|
||||
#include "ballistica/ui_v1/python/class/python_class_ui_mesh.h"
|
||||
#include "ballistica/ui_v1/python/class/python_class_ui_sound.h"
|
||||
#include "ballistica/ui_v1/python/class/python_class_ui_texture.h"
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
#include "ballistica/ui_v1/python/class/python_class_ui_texture.h"
|
||||
#include "ballistica/ui_v1/python/class/python_class_widget.h"
|
||||
#include "ballistica/ui_v1/python/methods/python_methods_ui_v1.h"
|
||||
#include "ballistica/ui_v1/widget/text_widget.h"
|
||||
|
||||
namespace ballistica::ui_v1 {
|
||||
|
||||
@ -107,7 +106,7 @@ void UIV1Python::InvokeStringEditor(PyObject* string_edit_adapter_instance) {
|
||||
BA_PRECONDITION(string_edit_adapter_instance);
|
||||
|
||||
base::ScopedSetContext ssc(nullptr);
|
||||
g_base->audio->PlaySound(g_base->assets->SysSound(base::SysSoundID::kSwish));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kSwish);
|
||||
|
||||
PythonRef args(Py_BuildValue("(O)", string_edit_adapter_instance),
|
||||
PythonRef::kSteal);
|
||||
@ -139,7 +138,7 @@ void UIV1Python::InvokeQuitWindow(QuitType quit_type) {
|
||||
}
|
||||
}
|
||||
|
||||
g_base->audio->PlaySound(g_base->assets->SysSound(base::SysSoundID::kSwish));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kSwish);
|
||||
auto py_enum = g_base->python->PyQuitType(quit_type);
|
||||
auto args = PythonRef::Stolen(Py_BuildValue("(O)", py_enum.Get()));
|
||||
objs().Get(UIV1Python::ObjID::kQuitWindowCall).Call(args);
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
#include "ballistica/shared/generic/native_stack_trace.h"
|
||||
#include "ballistica/ui_v1/python/ui_v1_python.h"
|
||||
#include "ballistica/ui_v1/support/root_ui.h"
|
||||
#include "ballistica/ui_v1/widget/root_widget.h"
|
||||
|
||||
@ -557,14 +557,11 @@ void ButtonWidget::DoActivate(bool is_repeat) {
|
||||
if (sound_enabled_) {
|
||||
int r = rand() % 3; // NOLINT
|
||||
if (r == 0) {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kSwish));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kSwish);
|
||||
} else if (r == 1) {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kSwish2));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kSwish2);
|
||||
} else {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kSwish3));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kSwish3);
|
||||
}
|
||||
}
|
||||
if (auto* call = on_activate_call_.Get()) {
|
||||
|
||||
@ -237,7 +237,7 @@ void CheckBoxWidget::SetValue(bool value) {
|
||||
}
|
||||
|
||||
void CheckBoxWidget::Activate() {
|
||||
g_base->audio->PlaySound(g_base->assets->SysSound(base::SysSoundID::kSwish3));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kSwish3);
|
||||
checked_ = !checked_;
|
||||
check_dirty_ = true;
|
||||
last_change_time_ = g_core->GetAppTimeMillisecs();
|
||||
|
||||
@ -607,8 +607,7 @@ auto ContainerWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
|
||||
|
||||
// First click just selects.
|
||||
if (click_count == 1) {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
}
|
||||
} else {
|
||||
// Special case: If we've got a child text widget that's
|
||||
@ -1637,8 +1636,7 @@ void ContainerWidget::SelectDownWidget() {
|
||||
// Avoid tap sounds and whatnot if we're just re-selecting ourself.
|
||||
if (w != selected_widget_) {
|
||||
w->GlobalSelect();
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1702,8 +1700,7 @@ void ContainerWidget::SelectUpWidget() {
|
||||
// Avoid tap sounds and whatnot if we're just re-selecting ourself.
|
||||
if (w != selected_widget_) {
|
||||
w->GlobalSelect();
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1755,8 +1752,7 @@ void ContainerWidget::SelectLeftWidget() {
|
||||
// Avoid tap sounds and whatnot if we're just re-selecting ourself.
|
||||
if (w != selected_widget_) {
|
||||
w->GlobalSelect();
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1808,8 +1804,7 @@ void ContainerWidget::SelectRightWidget() {
|
||||
// Avoid tap sounds and whatnot if we're just re-selecting ourself.
|
||||
if (w != selected_widget_) {
|
||||
w->GlobalSelect();
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1891,8 +1886,7 @@ void ContainerWidget::SelectNextWidget() {
|
||||
}
|
||||
if ((**i).IsSelectable() && (**i).IsSelectableViaKeys()) {
|
||||
SelectWidget(&(**i), SelectionCause::NEXT_SELECTED);
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
@ -1907,8 +1901,7 @@ void ContainerWidget::PrintExitListInstructions(
|
||||
if ((t - old_last_prev_next_time > 250)
|
||||
&& (t - last_list_exit_instructions_print_time_ > 5000)) {
|
||||
last_list_exit_instructions_print_time_ = t;
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kErrorBeep));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kErrorBeep);
|
||||
std::string s = g_base->assets->GetResourceString("arrowsToExitListText");
|
||||
{
|
||||
// Left arrow.
|
||||
@ -1981,8 +1974,7 @@ void ContainerWidget::SelectPrevWidget() {
|
||||
|
||||
if ((**i).IsSelectable() && (**i).IsSelectableViaKeys()) {
|
||||
SelectWidget(&(**i), SelectionCause::PREV_SELECTED);
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include "ballistica/ui_v1/widget/text_widget.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
@ -711,8 +710,7 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
|
||||
case SDLK_KP_ENTER:
|
||||
if (g_buildconfig.ostype_ios_tvos() || g_buildconfig.ostype_android()) {
|
||||
// On mobile, return currently just deselects us.
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kSwish));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kSwish);
|
||||
parent_widget()->SelectWidget(nullptr);
|
||||
return true;
|
||||
} else {
|
||||
@ -847,8 +845,7 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
|
||||
pressed_activate_ =
|
||||
(click_count == 2 || click_activate_) && !editable_;
|
||||
if (click_count == 1) {
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -871,8 +868,7 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
|
||||
carat_position_ = 0;
|
||||
text_group_dirty_ = true;
|
||||
clear_pressed_ = false;
|
||||
g_base->audio->PlaySound(
|
||||
g_base->assets->SysSound(base::SysSoundID::kTap));
|
||||
g_base->audio->SafePlaySysSound(base::SysSoundID::kTap);
|
||||
return true;
|
||||
}
|
||||
clear_pressed_ = false;
|
||||
|
||||
@ -23,16 +23,27 @@ def import_baenv_and_run_configure(
|
||||
data_dir: str | None,
|
||||
user_python_dir: str | None,
|
||||
contains_python_dist: bool,
|
||||
) -> None:
|
||||
"""Import baenv and run its configure method."""
|
||||
import baenv
|
||||
) -> None | str:
|
||||
"""Import baenv and run its configure method.
|
||||
|
||||
baenv.configure(
|
||||
config_dir=config_dir,
|
||||
data_dir=data_dir,
|
||||
user_python_dir=user_python_dir,
|
||||
contains_python_dist=contains_python_dist,
|
||||
)
|
||||
On success, returns None. On Failure, attempts to return an error
|
||||
traceback as a string (logging may not yet be functional at this point
|
||||
so we need to be direct).
|
||||
"""
|
||||
try:
|
||||
import baenv
|
||||
|
||||
baenv.configure(
|
||||
config_dir=config_dir,
|
||||
data_dir=data_dir,
|
||||
user_python_dir=user_python_dir,
|
||||
contains_python_dist=contains_python_dist,
|
||||
)
|
||||
return None
|
||||
except Exception:
|
||||
import traceback
|
||||
|
||||
return traceback.format_exc()
|
||||
|
||||
|
||||
def get_env_config() -> baenv.EnvConfig:
|
||||
|
||||
@ -19,6 +19,11 @@ if TYPE_CHECKING:
|
||||
|
||||
def _get_legal_notice_private() -> str:
|
||||
"""Return the one line legal notice we expect private files to have."""
|
||||
return 'Copyright (c) 2011-2024 Eric Froemling'
|
||||
|
||||
|
||||
def _get_legal_notice_private_prev() -> str:
|
||||
"""Allows us to auto-update."""
|
||||
return 'Copyright (c) 2011-2023 Eric Froemling'
|
||||
|
||||
|
||||
@ -210,6 +215,7 @@ def _check_c_license(
|
||||
# Look for public license line (public or private repo) or private
|
||||
# license line (private repo only)
|
||||
line_private = '// ' + _get_legal_notice_private()
|
||||
line_private_prev = '// ' + _get_legal_notice_private_prev()
|
||||
line_public = get_public_license('c++')
|
||||
lnum = 0
|
||||
|
||||
@ -229,7 +235,7 @@ def _check_c_license(
|
||||
fname,
|
||||
line_number=lnum,
|
||||
expected=line_private,
|
||||
can_auto_update=False,
|
||||
can_auto_update=(lines[lnum] == line_private_prev),
|
||||
)
|
||||
|
||||
|
||||
@ -463,6 +469,7 @@ def _check_python_file_license(
|
||||
if self.license_line_checks:
|
||||
public_license = get_public_license('python')
|
||||
private_license = '# ' + _get_legal_notice_private()
|
||||
private_license_prev = '# ' + _get_legal_notice_private_prev()
|
||||
lnum = copyrightline
|
||||
if len(lines) < lnum + 1:
|
||||
raise RuntimeError('Not enough lines in file:', fname)
|
||||
@ -486,17 +493,27 @@ def _check_python_file_license(
|
||||
f'{disable_note}'
|
||||
)
|
||||
else:
|
||||
if lines[lnum] != public_license and lines[lnum] != private_license:
|
||||
raise CleanError(
|
||||
f'License text not found'
|
||||
f" at '{fname}' line {lnum+1};"
|
||||
f' please correct.\n'
|
||||
f'Expected text (for public files):'
|
||||
f' {public_license}\n'
|
||||
f'Expected text (for private files):'
|
||||
f' {private_license}\n'
|
||||
f'{disable_note}'
|
||||
)
|
||||
if lines[lnum] not in [public_license, private_license]:
|
||||
# Special case: if we find last year's private license
|
||||
# we can update to this year's.
|
||||
if lines[lnum] == private_license_prev:
|
||||
self.add_line_correction(
|
||||
fname,
|
||||
line_number=lnum,
|
||||
expected=private_license,
|
||||
can_auto_update=(lines[lnum] == private_license_prev),
|
||||
)
|
||||
else:
|
||||
raise CleanError(
|
||||
f'License text not found'
|
||||
f" at '{fname}' line {lnum+1};"
|
||||
f' please correct.\n'
|
||||
f'Expected text (for public files):'
|
||||
f' {public_license}\n'
|
||||
f'Expected text (for private files):'
|
||||
f' {private_license}\n'
|
||||
f'{disable_note}'
|
||||
)
|
||||
|
||||
|
||||
def _calc_python_file_copyright_line(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user