Merge branch 'efroemling:master' into master

This commit is contained in:
Loup 2024-03-19 18:57:12 +05:30 committed by GitHub
commit 6dd94567a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 796 additions and 361 deletions

78
.efrocachemap generated
View File

@ -421,7 +421,7 @@
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
"build/assets/ba_data/data/langdata.json": "8409781047f46ca6627eacdfc0b4d3d3", "build/assets/ba_data/data/langdata.json": "5e534cd5bb06b149a9ee4713e8d75577",
"build/assets/ba_data/data/languages/arabic.json": "2c2915e10124bb8f69206da9c608d57c", "build/assets/ba_data/data/languages/arabic.json": "2c2915e10124bb8f69206da9c608d57c",
"build/assets/ba_data/data/languages/belarussian.json": "09954e550d13d3d9cb5a635a1d32a151", "build/assets/ba_data/data/languages/belarussian.json": "09954e550d13d3d9cb5a635a1d32a151",
"build/assets/ba_data/data/languages/chinese.json": "bb51b5aa614830c561e8fe2542a9ab8a", "build/assets/ba_data/data/languages/chinese.json": "bb51b5aa614830c561e8fe2542a9ab8a",
@ -430,31 +430,31 @@
"build/assets/ba_data/data/languages/czech.json": "15be4fd59895135bad0265f79b362d5b", "build/assets/ba_data/data/languages/czech.json": "15be4fd59895135bad0265f79b362d5b",
"build/assets/ba_data/data/languages/danish.json": "8e57db30c5250df2abff14a822f83ea7", "build/assets/ba_data/data/languages/danish.json": "8e57db30c5250df2abff14a822f83ea7",
"build/assets/ba_data/data/languages/dutch.json": "b0900d572c9141897d53d6574c471343", "build/assets/ba_data/data/languages/dutch.json": "b0900d572c9141897d53d6574c471343",
"build/assets/ba_data/data/languages/english.json": "0a95fdbc1564161bc7c8b419b0c03651", "build/assets/ba_data/data/languages/english.json": "48fe4c6f97b07420238244309b54a61e",
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
"build/assets/ba_data/data/languages/filipino.json": "5226bf247fa1c8f4406360644f3fa15f", "build/assets/ba_data/data/languages/filipino.json": "d2c943fda759269563d871ea99fe76f8",
"build/assets/ba_data/data/languages/french.json": "917e4174d6f0eb7f00c27fd79cfbb924", "build/assets/ba_data/data/languages/french.json": "917e4174d6f0eb7f00c27fd79cfbb924",
"build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad",
"build/assets/ba_data/data/languages/gibberish.json": "5533873020e51186beb2f209adbbfb08", "build/assets/ba_data/data/languages/gibberish.json": "a1afce99249645003017ebec50e716fe",
"build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3",
"build/assets/ba_data/data/languages/hindi.json": "90f54663e15d85a163f1848a8e9d8d07", "build/assets/ba_data/data/languages/hindi.json": "90f54663e15d85a163f1848a8e9d8d07",
"build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e",
"build/assets/ba_data/data/languages/indonesian.json": "9103845242b572aa8ba48e24f81ddb68", "build/assets/ba_data/data/languages/indonesian.json": "9103845242b572aa8ba48e24f81ddb68",
"build/assets/ba_data/data/languages/italian.json": "55c350f8f5039802138ffc1013f14ed3", "build/assets/ba_data/data/languages/italian.json": "6653a2c84646914064f41442aca23d4d",
"build/assets/ba_data/data/languages/korean.json": "4e3524327a0174250aff5e1ef4c0c597", "build/assets/ba_data/data/languages/korean.json": "4e3524327a0174250aff5e1ef4c0c597",
"build/assets/ba_data/data/languages/malay.json": "f6ce0426d03a62612e3e436ed5d1be1f", "build/assets/ba_data/data/languages/malay.json": "f6ce0426d03a62612e3e436ed5d1be1f",
"build/assets/ba_data/data/languages/persian.json": "07eddcf92d3dcc7a745ea74e2b0007c8", "build/assets/ba_data/data/languages/persian.json": "835ea1d84ec197972f7ca3adb945fb88",
"build/assets/ba_data/data/languages/polish.json": "9d22c6643c097c4cb268d0d6b6319cd4", "build/assets/ba_data/data/languages/polish.json": "9d22c6643c097c4cb268d0d6b6319cd4",
"build/assets/ba_data/data/languages/portuguese.json": "a48df1d11a088a1a2e6e3f66627444be", "build/assets/ba_data/data/languages/portuguese.json": "a48df1d11a088a1a2e6e3f66627444be",
"build/assets/ba_data/data/languages/romanian.json": "b3e46efd6f869dbd78014570e037c290", "build/assets/ba_data/data/languages/romanian.json": "b3e46efd6f869dbd78014570e037c290",
"build/assets/ba_data/data/languages/russian.json": "0590f49889616b5279be569dea926e17", "build/assets/ba_data/data/languages/russian.json": "3efaaf5eac320fceef029501dec4109b",
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69", "build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
"build/assets/ba_data/data/languages/slovak.json": "c00fb27cf982ffad5a4370ad3b16bd21", "build/assets/ba_data/data/languages/slovak.json": "c00fb27cf982ffad5a4370ad3b16bd21",
"build/assets/ba_data/data/languages/spanish.json": "b2edb923fdca973a16f0efb1acc26a97", "build/assets/ba_data/data/languages/spanish.json": "a15adbfeb16be4a956e34b2515b60f10",
"build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac", "build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac",
"build/assets/ba_data/data/languages/tamil.json": "b9fcc523639f55e05c7f4e7914f3321a", "build/assets/ba_data/data/languages/tamil.json": "b9fcc523639f55e05c7f4e7914f3321a",
"build/assets/ba_data/data/languages/thai.json": "1d665629361f302693dead39de8fa945", "build/assets/ba_data/data/languages/thai.json": "1d665629361f302693dead39de8fa945",
"build/assets/ba_data/data/languages/turkish.json": "db71f3776072b7a15ef37b1bb1245795", "build/assets/ba_data/data/languages/turkish.json": "fcd90d63b5d3eae3eda5e94174008327",
"build/assets/ba_data/data/languages/ukrainian.json": "3d75d21205c82db34fb1a1b014592747", "build/assets/ba_data/data/languages/ukrainian.json": "3d75d21205c82db34fb1a1b014592747",
"build/assets/ba_data/data/languages/venetian.json": "035034e0b4de696a41bf753ab4d0e194", "build/assets/ba_data/data/languages/venetian.json": "035034e0b4de696a41bf753ab4d0e194",
"build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba", "build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba",
@ -1368,6 +1368,10 @@
"build/assets/ba_data/textures/circleZigZag.pvr": "4b300a401102daa24755c1d156e81ada", "build/assets/ba_data/textures/circleZigZag.pvr": "4b300a401102daa24755c1d156e81ada",
"build/assets/ba_data/textures/circleZigZag_preview.png": "409fa44a6f89bc745240ec3107042b49", "build/assets/ba_data/textures/circleZigZag_preview.png": "409fa44a6f89bc745240ec3107042b49",
"build/assets/ba_data/textures/circle_preview.png": "84b94c4bf16e27e9483fe683e4e2f5f7", "build/assets/ba_data/textures/circle_preview.png": "84b94c4bf16e27e9483fe683e4e2f5f7",
"build/assets/ba_data/textures/clayStroke.dds": "1ae7ab8d1e212aca724f7313f1b57e61",
"build/assets/ba_data/textures/clayStroke.ktx": "8c648180e290a4acfff1196fa358f042",
"build/assets/ba_data/textures/clayStroke.pvr": "84c31a1a8ab4ea051a5b6a804dd952df",
"build/assets/ba_data/textures/clayStroke_preview.png": "ec248139546f51c007148ef0250a5e0c",
"build/assets/ba_data/textures/coin.dds": "e69e7ba8ff87d5ed9ca7c7ab96d13546", "build/assets/ba_data/textures/coin.dds": "e69e7ba8ff87d5ed9ca7c7ab96d13546",
"build/assets/ba_data/textures/coin.ktx": "d1de4b2fd4fe028b889ed53a829f9a72", "build/assets/ba_data/textures/coin.ktx": "d1de4b2fd4fe028b889ed53a829f9a72",
"build/assets/ba_data/textures/coin.pvr": "b8477ed7afdc5e460843e4d8413a2c08", "build/assets/ba_data/textures/coin.pvr": "b8477ed7afdc5e460843e4d8413a2c08",
@ -4061,26 +4065,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "db921cf43e8ebf733712fb5bbc673f66", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "aff4f4ed3c7632315212878c9bfd41db",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "4be0f3a7a88da423847863af41ac9c63", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "c5b8a89455932e54784830c3320b5547",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "7c92d738e7cc724de2ca31cb876224e6", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "ffb96514e1f56af56ec8423fa7dff9d2",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "c2f69ed83f77b602e2a2b2b1c1c78cc6", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "8ddbc4c0bf72f21cae20b97112c998f8",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b1c766d4ce567f965c53ff2a4c5c85f4", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "2aef304e97b7a7a6efb0422150395b3b",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "86ebbd9111f8a0fe7905cef7aba1f6db", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "365a17b83735ac688f273bf458962bf4",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8182f4e00ad579eb4c7be5ec1ddca8cb", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "b8a56ad0bc13aa39e557304c4b15c06f",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "3d9e0e7ad8706133e61fb7f7127c3ff5", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "8a194395a2d25232e02397a09816e818",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "5f98bf8b11376161a6f2f60900703f8a", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "5a3993e59d989f58d3ed3100b97f63e0",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "99d7d247a422eaa46737e3232408e879", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "63efabd180e84a3cd8d44f427671ad79",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "ffd6ad4dda003e9cd1434aa4a5bc9b09", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d2525592bc459b41ecc915e65058e828",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "216efc77915b75f39f0f15c2806bfbb9", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "d5d8c6df24d117ff48dcbd4a1b934fc3",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "ad9829c065248ee3cde01b6a31deafed", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "06c837822168039b0cbdbb63a5bb4bd3",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "3e9e4e1761fd763eb584598fc0a3ad0a", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "90b4a005c41d482c3e51c7da9ab306ee",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "7522a6fcac27b2579f9cc0b712ce413b", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "05a62ba9e4d8dc91de80cbeb18d44622",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0c92e386ab7406da6a719131321bf592", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "49b0b163e779691643720b44f44563d2",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "608cb03aef4dc547aa7433f83f898911", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "cfed19e557d4dd7ab7a1c92039bef8ca",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "db136c26a3a37611aef68046f2fab62c", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "4670e91666540dbcc2909e9f8de3a2d5",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "3edbd652fbc7afe69f60335bab00875a", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "58048dc1ad1f1329f35c3948040db414",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "48e5cd932b8c322be18b593508d5c451", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "db60223aab0a714d626651109e20c6f1",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d9865523059d8cf11b2bef4b9da9a8c9", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d9865523059d8cf11b2bef4b9da9a8c9",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "56d6440f62c271c4ce9ef520400395a3", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "56d6440f62c271c4ce9ef520400395a3",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d9865523059d8cf11b2bef4b9da9a8c9", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d9865523059d8cf11b2bef4b9da9a8c9",
@ -4097,14 +4101,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c2cf0dc227e41a826c913d12e117c316", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c2cf0dc227e41a826c913d12e117c316",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "fbdc80e41c5883b4a893d2f0786e377f", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "fbdc80e41c5883b4a893d2f0786e377f",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c2cf0dc227e41a826c913d12e117c316", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c2cf0dc227e41a826c913d12e117c316",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "73e6dd8dfba14ad1528d154ec43188c1", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "199c8650599d295ca799b29e0bb4c7e7",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "dfdb92bb0d84c405374e7da63c0eea4d", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "bc136717d320ca791624141b3a246483",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "c20a6bd8ea7212f52c291fb6134a9bad", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "09113b8b33af70c34c3f980e3cc8581d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0e994a801d91149256f2200f75cf58d6", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "483ab966856762e946dfc04e635630d9",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "de98295b7373dcf3c31d3cc5a135578b", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "f1702ea6d5b6bae2b77e5a3184b1d417",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "65e5b683dfa92a02909e8182d6b25d6e", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "47c9475678346309d9abe9cf78b4ab13",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "f1e4e29d76abdb38e92a93f45135d1d8", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "85e2286dbde53af296f02859f08cdc1a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "8089cf4b541d14dc38ae71f3d05bde8e", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "80c5e2d583ce36bca136be488aa06a0c",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d", "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.inc": "72bfed2cce8ff19741989dec28302f3f",

View File

@ -1,4 +1,4 @@
### 1.7.33 (build 21778, api 8, 2024-03-13) ### 1.7.33 (build 21794, api 8, 2024-03-15)
- Stress test input-devices are now a bit smarter; they won't press any buttons - 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). 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 - Added a 'Show Demos When Idle' option in advanced settings. If enabled, the
@ -40,21 +40,36 @@
EraOSBeta!) EraOSBeta!)
- Added a UI for customizing Series Length in Teams and Points-to-Win in FFA - Added a UI for customizing Series Length in Teams and Points-to-Win in FFA
(Thanks EraOSBeta!) (Thanks EraOSBeta!)
- Implemented HEX code support to the advanced color picker (Thanks 3alTemp!)
- Players leaving the game after getting hurt will now grant kills. (Thanks
Temp!)
- Sphinx based Python documentation generation is now wired up (Thanks - Sphinx based Python documentation generation is now wired up (Thanks
Loup-Garou911XD!) Loup-Garou911XD!)
- Renaming & overwriting existing profiles is no longer possible (Thanks Temp!) - Renaming & overwriting existing profiles is no longer possible (Thanks Temp!)
- Cleaned up builds when running under WSL. Things like `make mypy` should now
work correctly there, and it should now be possible to build and run either
Linux or Windows builds there.
- Added an `allow_clear_button` arg to bauiv1.textwidget() which can be used to
disable the 'X' button that clears editable text widgets.
### 1.7.32 (build 21741, api 8, 2023-12-20) ### 1.7.32 (build 21741, api 8, 2023-12-20)
- Fixed a screen message that no one will ever see (Thanks vishal332008?...) - Fixed a screen message that no one will ever see (Thanks vishal332008?...)
- Plugins window now displays 'No Plugins Installed' when no plugins are present (Thanks vishal332008!) - Plugins window now displays 'No Plugins Installed' when no plugins are present
- Old messages are now displayed as soon as you press 'Unmute Chat' (Thanks vishal332008!) (Thanks vishal332008!)
- Old messages are now displayed as soon as you press 'Unmute Chat' (Thanks
vishal332008!)
- Added an 'Add to Favorites' entry to the party menu (Thanks vishal332008!) - Added an 'Add to Favorites' entry to the party menu (Thanks vishal332008!)
- Now displays 'No Parties Added' in favorites tab if no favorites are present (Thanks vishal332008!) - Now displays 'No Parties Added' in favorites tab if no favorites are present
(Thanks vishal332008!)
- Now shows character icons in the profiles list window (Thanks vishal332008!) - Now shows character icons in the profiles list window (Thanks vishal332008!)
- Added a Random button for names in the Player Profiles window (Thanks vishal332008!) - Added a Random button for names in the Player Profiles window (Thanks
- Fixed a bug where no server is selected by default in the favorites tab (Thanks vishal332008!) vishal332008!)
- Fixed a bug where no replay is selected by default in the watch tab (Thanks vishal332008!) - Fixed a bug where no server is selected by default in the favorites tab
- Fixed a bug where no profile is selected by default in the profile tab (Thanks vishal332008!) (Thanks vishal332008!)
- Fixed a bug where no replay is selected by default in the watch tab (Thanks
vishal332008!)
- Fixed a bug where no profile is selected by default in the profile tab (Thanks
vishal332008!)
- Fixed a number of UI screens so that ugly window edges are no longer visible - Fixed a number of UI screens so that ugly window edges are no longer visible
in corners on modern ultra wide phone displays. in corners on modern ultra wide phone displays.
- Added a `player_rejoin_cooldown` server config option. This defaults to 10 - Added a `player_rejoin_cooldown` server config option. This defaults to 10

122
Makefile
View File

@ -151,7 +151,7 @@ meta-clean:
# few things such as localconfig.json). # few things such as localconfig.json).
clean: clean:
$(CHECK_CLEAN_SAFETY) $(CHECK_CLEAN_SAFETY)
rm -rf build # Handle this part ourself; can confuse git. rm -rf build # Kill this ourself; can confuse git if contains other repos.
git clean -dfx $(ROOT_CLEAN_IGNORES) git clean -dfx $(ROOT_CLEAN_IGNORES)
# Show what clean would delete without actually deleting it. # Show what clean would delete without actually deleting it.
@ -210,37 +210,42 @@ pcommandbatch_speed_test: prereqs
# Prebuilt binaries for various platforms. # Prebuilt binaries for various platforms.
# WSL is Linux but running under Windows, so it can target either. By default
# we want these top level targets (prefab-gui-debug, etc.) to yield native
# Windows builds from WSL, but this env var can be set to override that.
BA_WSL_TARGETS_WINDOWS ?= 1
# Assemble & run a gui debug build for this platform. # Assemble & run a gui debug build for this platform.
prefab-gui-debug: prefab-gui-debug-build prefab-gui-debug: prefab-gui-debug-build
$($(shell $(PCOMMAND) prefab_run_var gui-debug)) $($(shell $(WSLU) $(PCOMMAND) prefab_run_var gui-debug))
# Assemble & run a gui release build for this platform. # Assemble & run a gui release build for this platform.
prefab-gui-release: prefab-gui-release-build prefab-gui-release: prefab-gui-release-build
$($(shell $(PCOMMAND) prefab_run_var gui-release)) $($(shell $(WSLU) $(PCOMMAND) prefab_run_var gui-release))
# Assemble a debug build for this platform. # Assemble a debug build for this platform.
prefab-gui-debug-build: prefab-gui-debug-build:
@$(PCOMMAND) make_prefab gui-debug $(WSLU) $(PCOMMAND) make_prefab gui-debug
# Assemble a release build for this platform. # Assemble a release build for this platform.
prefab-gui-release-build: prefab-gui-release-build:
@$(PCOMMAND) make_prefab gui-release $(WSLU) $(PCOMMAND) make_prefab gui-release
# Assemble & run a server debug build for this platform. # Assemble & run a server debug build for this platform.
prefab-server-debug: prefab-server-debug-build prefab-server-debug: prefab-server-debug-build
$($(shell $(PCOMMAND) prefab_run_var server-debug)) $($(shell $(WSLU) $(PCOMMAND) prefab_run_var server-debug))
# Assemble & run a server release build for this platform. # Assemble & run a server release build for this platform.
prefab-server-release: prefab-server-release-build prefab-server-release: prefab-server-release-build
$($(shell $(PCOMMAND) prefab_run_var server-release)) $($(shell $(WSLU) $(PCOMMAND) prefab_run_var server-release))
# Assemble a server debug build for this platform. # Assemble a server debug build for this platform.
prefab-server-debug-build: prefab-server-debug-build:
@$(PCOMMAND) make_prefab server-debug $(WSLU) $(PCOMMAND) make_prefab server-debug
# Assemble a server release build for this platform. # Assemble a server release build for this platform.
prefab-server-release-build: prefab-server-release-build:
@$(PCOMMAND) make_prefab server-release $(WSLU) $(PCOMMAND) make_prefab server-release
# Clean all prefab builds. # Clean all prefab builds.
prefab-clean: prefab-clean:
@ -261,11 +266,11 @@ RUN_PREFAB_MAC_ARM64_GUI_DEBUG = cd build/prefab/full/mac_arm64_gui/debug \
prefab-mac-x86-64-gui-debug: prefab-mac-x86-64-gui-debug-build prefab-mac-x86-64-gui-debug: prefab-mac-x86-64-gui-debug-build
@$(PCOMMAND) ensure_prefab_platform mac_x86_64 @$(PCOMMAND) ensure_prefab_platform mac_x86_64
@$(RUN_PREFAB_MAC_X86_64_GUI_DEBUG) $(RUN_PREFAB_MAC_X86_64_GUI_DEBUG)
prefab-mac-arm64-gui-debug: prefab-mac-arm64-gui-debug-build prefab-mac-arm64-gui-debug: prefab-mac-arm64-gui-debug-build
@$(PCOMMAND) ensure_prefab_platform mac_arm64 @$(PCOMMAND) ensure_prefab_platform mac_arm64
@$(RUN_PREFAB_MAC_ARM64_GUI_DEBUG) $(RUN_PREFAB_MAC_ARM64_GUI_DEBUG)
prefab-mac-x86-64-gui-debug-build: prereqs assets-cmake \ prefab-mac-x86-64-gui-debug-build: prereqs assets-cmake \
build/prefab/full/mac_x86_64_gui/debug/ballisticakit build/prefab/full/mac_x86_64_gui/debug/ballisticakit
@ -291,11 +296,11 @@ RUN_PREFAB_MAC_ARM64_GUI_RELEASE = cd build/prefab/full/mac_arm64_gui/release \
prefab-mac-x86-64-gui-release: prefab-mac-x86-64-gui-release-build prefab-mac-x86-64-gui-release: prefab-mac-x86-64-gui-release-build
@$(PCOMMAND) ensure_prefab_platform mac_x86_64 @$(PCOMMAND) ensure_prefab_platform mac_x86_64
@$(RUN_PREFAB_MAC_X86_64_GUI_RELEASE) $(RUN_PREFAB_MAC_X86_64_GUI_RELEASE)
prefab-mac-arm64-gui-release: prefab-mac-arm64-gui_release-build prefab-mac-arm64-gui-release: prefab-mac-arm64-gui_release-build
@$(PCOMMAND) ensure_prefab_platform mac_arm64 @$(PCOMMAND) ensure_prefab_platform mac_arm64
@$(RUN_PREFAB_MAC_ARM64_GUI_RELEASE) $(RUN_PREFAB_MAC_ARM64_GUI_RELEASE)
prefab-mac-x86-64-gui-release-build: prereqs assets-cmake \ prefab-mac-x86-64-gui-release-build: prereqs assets-cmake \
build/prefab/full/mac_x86_64_gui/release/ballisticakit build/prefab/full/mac_x86_64_gui/release/ballisticakit
@ -325,7 +330,7 @@ prefab-mac-x86-64-server-debug: prefab-mac-x86-64-server-debug-build
prefab-mac-arm64-server-debug: prefab-mac-arm64-server-debug-build prefab-mac-arm64-server-debug: prefab-mac-arm64-server-debug-build
@$(PCOMMAND) ensure_prefab_platform mac_arm64 @$(PCOMMAND) ensure_prefab_platform mac_arm64
@$(RUN_PREFAB_MAC_ARM64_SERVER_DEBUG) $(RUN_PREFAB_MAC_ARM64_SERVER_DEBUG)
prefab-mac-x86-64-server-debug-build: prereqs assets-server \ prefab-mac-x86-64-server-debug-build: prereqs assets-server \
build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless
@ -351,11 +356,11 @@ RUN_PREFAB_MAC_ARM64_SERVER_RELEASE = cd \
prefab-mac-x86-64-server-release: prefab-mac-x86-64-server-release-build prefab-mac-x86-64-server-release: prefab-mac-x86-64-server-release-build
@$(PCOMMAND) ensure_prefab_platform mac_x86_64 @$(PCOMMAND) ensure_prefab_platform mac_x86_64
@$(RUN_PREFAB_MAC_X86_64_SERVER_RELEASE) $(RUN_PREFAB_MAC_X86_64_SERVER_RELEASE)
prefab-mac-arm64-server-release: prefab-mac-arm64-server-release-build prefab-mac-arm64-server-release: prefab-mac-arm64-server-release-build
@$(PCOMMAND) ensure_prefab_platform mac_arm64 @$(PCOMMAND) ensure_prefab_platform mac_arm64
@$(RUN_PREFAB_MAC_ARM64_SERVER_RELEASE) $(RUN_PREFAB_MAC_ARM64_SERVER_RELEASE)
prefab-mac-x86-64-server-release-build: prereqs assets-server \ prefab-mac-x86-64-server-release-build: prereqs assets-server \
build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless
@ -382,12 +387,12 @@ RUN_PREFAB_LINUX_ARM64_GUI_DEBUG = cd \
build/prefab/full/linux_arm64_gui/debug && ./ballisticakit build/prefab/full/linux_arm64_gui/debug && ./ballisticakit
prefab-linux-x86-64-gui-debug: prefab-linux-x86-64-gui-debug-build prefab-linux-x86-64-gui-debug: prefab-linux-x86-64-gui-debug-build
@$(PCOMMAND) ensure_prefab_platform linux_x86_64 @$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_x86_64
@$(RUN_PREFAB_LINUX_X86_64_GUI_DEBUG) $(RUN_PREFAB_LINUX_X86_64_GUI_DEBUG)
prefab-linux-arm64-gui-debug: prefab-linux-arm64-gui-debug-build prefab-linux-arm64-gui-debug: prefab-linux-arm64-gui-debug-build
@$(PCOMMAND) ensure_prefab_platform linux_arm64 @$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64
@$(RUN_PREFAB_LINUX_ARM64_GUI_DEBUG) $(RUN_PREFAB_LINUX_ARM64_GUI_DEBUG)
prefab-linux-x86-64-gui-debug-build: prereqs assets-cmake \ prefab-linux-x86-64-gui-debug-build: prereqs assets-cmake \
build/prefab/full/linux_x86_64_gui/debug/ballisticakit build/prefab/full/linux_x86_64_gui/debug/ballisticakit
@ -412,12 +417,12 @@ RUN_PREFAB_LINUX_ARM64_GUI_RELEASE = cd \
build/prefab/full/linux_arm64_gui/release && ./ballisticakit build/prefab/full/linux_arm64_gui/release && ./ballisticakit
prefab-linux-x86-64-gui-release: prefab-linux-x86-64-gui-release-build prefab-linux-x86-64-gui-release: prefab-linux-x86-64-gui-release-build
@$(PCOMMAND) ensure_prefab_platform linux_x86_64 @$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_x86_64
@$(RUN_PREFAB_LINUX_X86_64_GUI_RELEASE) $(RUN_PREFAB_LINUX_X86_64_GUI_RELEASE)
prefab-linux-arm64-gui-release: prefab-linux-arm64-gui-release-build prefab-linux-arm64-gui-release: prefab-linux-arm64-gui-release-build
@$(PCOMMAND) ensure_prefab_platform linux_arm64 @$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64
@$(RUN_PREFAB_LINUX_ARM64_GUI_RELEASE) $(RUN_PREFAB_LINUX_ARM64_GUI_RELEASE)
prefab-linux-x86-64-gui-release-build: prereqs assets-cmake \ prefab-linux-x86-64-gui-release-build: prereqs assets-cmake \
build/prefab/full/linux_x86_64_gui/release/ballisticakit build/prefab/full/linux_x86_64_gui/release/ballisticakit
@ -442,12 +447,12 @@ RUN_PREFAB_LINUX_ARM64_SERVER_DEBUG = cd \
build/prefab/full/linux_arm64_server/debug && ./ballisticakit_server build/prefab/full/linux_arm64_server/debug && ./ballisticakit_server
prefab-linux-x86-64-server-debug: prefab-linux-x86-64-server-debug-build prefab-linux-x86-64-server-debug: prefab-linux-x86-64-server-debug-build
@$(PCOMMAND) ensure_prefab_platform linux_x86_64 @$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_x86_64
@$(RUN_PREFAB_LINUX_X86_64_SERVER_DEBUG) $(RUN_PREFAB_LINUX_X86_64_SERVER_DEBUG)
prefab-linux-arm64-server-debug: prefab-linux-arm64-server-debug-build prefab-linux-arm64-server-debug: prefab-linux-arm64-server-debug-build
@$(PCOMMAND) ensure_prefab_platform linux_arm64 @$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64
@$(RUN_PREFAB_LINUX_ARM64_SERVER_DEBUG) $(RUN_PREFAB_LINUX_ARM64_SERVER_DEBUG)
prefab-linux-x86-64-server-debug-build: prereqs assets-server \ prefab-linux-x86-64-server-debug-build: prereqs assets-server \
build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless
@ -474,12 +479,12 @@ RUN_PREFAB_LINUX_ARM64_SERVER_RELEASE = cd \
build/prefab/full/linux_arm64_server/release && ./ballisticakit_server build/prefab/full/linux_arm64_server/release && ./ballisticakit_server
prefab-linux-x86-64-server-release: prefab-linux-x86-64-server-release-build prefab-linux-x86-64-server-release: prefab-linux-x86-64-server-release-build
@$(PCOMMAND) ensure_prefab_platform linux_x86_64 @$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_x86_64
@$(RUN_PREFAB_LINUX_X86_64_SERVER_RELEASE) $(RUN_PREFAB_LINUX_X86_64_SERVER_RELEASE)
prefab-linux-arm64-server-release: prefab-linux-arm64-server-release-build prefab-linux-arm64-server-release: prefab-linux-arm64-server-release-build
@$(PCOMMAND) ensure_prefab_platform linux_arm64 @$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64
@$(RUN_PREFAB_LINUX_ARM64_SERVER_RELEASE) $(RUN_PREFAB_LINUX_ARM64_SERVER_RELEASE)
prefab-linux-x86-64-server-release-build: prereqs assets-server \ prefab-linux-x86-64-server-release-build: prereqs assets-server \
build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless
@ -503,8 +508,8 @@ RUN_PREFAB_WINDOWS_X86_GUI_DEBUG = cd build/prefab/full/windows_x86_gui/debug \
&& ./BallisticaKit.exe && ./BallisticaKit.exe
prefab-windows-x86-gui-debug: prefab-windows-x86-gui-debug-build prefab-windows-x86-gui-debug: prefab-windows-x86-gui-debug-build
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@$(RUN_PREFAB_WINDOWS_X86_GUI_DEBUG) $(RUN_PREFAB_WINDOWS_X86_GUI_DEBUG)
prefab-windows-x86-gui-debug-build: prereqs assets-windows-$(WINPLAT_X86) \ prefab-windows-x86-gui-debug-build: prereqs assets-windows-$(WINPLAT_X86) \
build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe
@ -526,8 +531,8 @@ RUN_PREFAB_WINDOWS_X86_GUI_RELEASE = cd \
build/prefab/full/windows_x86_gui/release && ./BallisticaKit.exe build/prefab/full/windows_x86_gui/release && ./BallisticaKit.exe
prefab-windows-x86-gui-release: prefab-windows-x86-gui-release-build prefab-windows-x86-gui-release: prefab-windows-x86-gui-release-build
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@$(RUN_PREFAB_WINDOWS_X86_GUI_RELEASE) $(RUN_PREFAB_WINDOWS_X86_GUI_RELEASE)
prefab-windows-x86-gui-release-build: prereqs \ prefab-windows-x86-gui-release-build: prereqs \
assets-windows-$(WINPLAT_X86) \ assets-windows-$(WINPLAT_X86) \
@ -551,8 +556,8 @@ RUN_PREFAB_WINDOWS_X86_SERVER_DEBUG = cd \
&& dist/python_d.exe ballisticakit_server.py && dist/python_d.exe ballisticakit_server.py
prefab-windows-x86-server-debug: prefab-windows-x86-server-debug-build prefab-windows-x86-server-debug: prefab-windows-x86-server-debug-build
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@$(RUN_PREFAB_WINDOWS_X86_SERVER_DEBUG) $(RUN_PREFAB_WINDOWS_X86_SERVER_DEBUG)
prefab-windows-x86-server-debug-build: prereqs \ prefab-windows-x86-server-debug-build: prereqs \
assets-windows-$(WINPLAT_X86) \ assets-windows-$(WINPLAT_X86) \
@ -576,8 +581,8 @@ RUN_PREFAB_WINDOWS_X86_SERVER_RELEASE = cd \
&& dist/python.exe -O ballisticakit_server.py && dist/python.exe -O ballisticakit_server.py
prefab-windows-x86-server-release: prefab-windows-x86-server-release-build prefab-windows-x86-server-release: prefab-windows-x86-server-release-build
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@$(RUN_PREFAB_WINDOWS_X86_SERVER_RELEASE) $(RUN_PREFAB_WINDOWS_X86_SERVER_RELEASE)
prefab-windows-x86-server-release-build: prereqs \ prefab-windows-x86-server-release-build: prereqs \
assets-windows-$(WINPLAT_X86) \ assets-windows-$(WINPLAT_X86) \
@ -964,66 +969,66 @@ WINDOWS_CONFIGURATION ?= Debug
# Stage assets and other files so a built binary will run. # Stage assets and other files so a built binary will run.
windows-staging: assets-windows resources meta windows-staging: assets-windows resources meta
$(STAGE_BUILD) -win-$(WINPLT) -$(WINCFGLC) build/windows/$(WINCFG)_$(WINPLT) @$(STAGE_BUILD) -win-$(WINPLT) -$(WINCFGLC) build/windows/$(WINCFG)_$(WINPLT)
# Build and run a debug windows build (from WSL). # Build and run a debug windows build (from WSL).
windows-debug: windows-debug-build windows-debug: windows-debug-build
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
build/windows/Debug_Win32/BallisticaKitGeneric.exe build/windows/Debug_Win32/BallisticaKitGeneric.exe
# Build and run a release windows build (from WSL). # Build and run a release windows build (from WSL).
windows-release: windows-release-build windows-release: windows-release-build
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
build/windows/Release_Win32/BallisticaKitGeneric.exe build/windows/Release_Win32/BallisticaKitGeneric.exe
# Build a debug windows build (from WSL). # Build a debug windows build (from WSL).
windows-debug-build: \ windows-debug-build: prereqs \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \ build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@$(PCOMMAND) wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging
WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 \ WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 \
$(MAKE) _windows-wsl-build $(MAKE) _windows-wsl-build
# Rebuild a debug windows build (from WSL). # Rebuild a debug windows build (from WSL).
windows-debug-rebuild: \ windows-debug-rebuild: prereqs \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \ build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@$(PCOMMAND) wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging
WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 \ WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Debug WINDOWS_PLATFORM=Win32 \
$(MAKE) _windows-wsl-rebuild $(MAKE) _windows-wsl-rebuild
# Build a release windows build (from WSL). # Build a release windows build (from WSL).
windows-release-build: \ windows-release-build: prereqs \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \ build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@$(PCOMMAND) wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging
WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 \ WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 \
$(MAKE) _windows-wsl-build $(MAKE) _windows-wsl-build
# Rebuild a release windows build (from WSL). # Rebuild a release windows build (from WSL).
windows-release-rebuild: \ windows-release-rebuild: prereqs \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \ build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb
@$(PCOMMAND) ensure_prefab_platform windows_x86 @$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@$(PCOMMAND) wsl_build_check_win_drive @$(PCOMMAND) wsl_build_check_win_drive
WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 $(MAKE) windows-staging
WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 \ WINDOWS_PROJECT=Generic WINDOWS_CONFIGURATION=Release WINDOWS_PLATFORM=Win32 \
$(MAKE) _windows-wsl-rebuild $(MAKE) _windows-wsl-rebuild
# Remove all non-git-managed files in windows subdir. # Remove all non-git-managed files in windows subdir.
windows-clean: windows-clean: prereqs
@$(CHECK_CLEAN_SAFETY) @$(CHECK_CLEAN_SAFETY)
git clean -dfx ballisticakit-windows git clean -dfx ballisticakit-windows
rm -rf build/windows $(LAZYBUILDDIR) rm -rf build/windows $(LAZYBUILDDIR)
# Show what would be cleaned. # Show what would be cleaned.
windows-clean-list: windows-clean-list: prereqs
@$(CHECK_CLEAN_SAFETY) @$(CHECK_CLEAN_SAFETY)
git clean -dnx ballisticakit-windows git clean -dnx ballisticakit-windows
echo would also remove build/windows $(LAZYBUILDDIR) echo would also remove build/windows $(LAZYBUILDDIR)
@ -1145,8 +1150,8 @@ cmake-modular-server-clean:
# Stage assets for building/running within CLion. # Stage assets for building/running within CLion.
clion-staging: assets-cmake resources meta clion-staging: assets-cmake resources meta
$(STAGE_BUILD) -cmake -debug build/clion_debug @$(STAGE_BUILD) -cmake -debug build/clion_debug
$(STAGE_BUILD) -cmake -release build/clion_release @$(STAGE_BUILD) -cmake -release build/clion_release
# Tell make which of these targets don't represent files. # Tell make which of these targets don't represent files.
.PHONY: cmake cmake-build cmake-clean cmake-server cmake-server-build \ .PHONY: cmake cmake-build cmake-clean cmake-server cmake-server-build \
@ -1245,6 +1250,13 @@ _WMSBE_2 = \\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\"
_WMSBE_1B = /mnt/c/Program Files/Microsoft Visual Studio/2022 _WMSBE_1B = /mnt/c/Program Files/Microsoft Visual Studio/2022
_WMSBE_2B = /Community/MSBuild/Current/Bin/MSBuild.exe _WMSBE_2B = /Community/MSBuild/Current/Bin/MSBuild.exe
# Sets WSL build type to the user's choice (defaults to Windows).
WSLU=BA_WSL_TARGETS_WINDOWS=$(BA_WSL_TARGETS_WINDOWS)
# Sets WSL build type to Linux.
WSLL=BA_WSL_TARGETS_WINDOWS=0
# Sets WSL build type to Windows.
WSLW=BA_WSL_TARGETS_WINDOWS=1
VISUAL_STUDIO_VERSION = -property:VisualStudioVersion=17 VISUAL_STUDIO_VERSION = -property:VisualStudioVersion=17
WIN_MSBUILD_EXE = $(_WMSBE_1)$(_WMSBE_2) WIN_MSBUILD_EXE = $(_WMSBE_1)$(_WMSBE_2)
WIN_MSBUILD_EXE_B = "$(_WMSBE_1B)$(_WMSBE_2B)" WIN_MSBUILD_EXE_B = "$(_WMSBE_1B)$(_WMSBE_2B)"

View File

@ -1389,6 +1389,10 @@
"ba_data/textures/circleZigZag.pvr", "ba_data/textures/circleZigZag.pvr",
"ba_data/textures/circleZigZag_preview.png", "ba_data/textures/circleZigZag_preview.png",
"ba_data/textures/circle_preview.png", "ba_data/textures/circle_preview.png",
"ba_data/textures/clayStroke.dds",
"ba_data/textures/clayStroke.ktx",
"ba_data/textures/clayStroke.pvr",
"ba_data/textures/clayStroke_preview.png",
"ba_data/textures/coin.dds", "ba_data/textures/coin.dds",
"ba_data/textures/coin.ktx", "ba_data/textures/coin.ktx",
"ba_data/textures/coin.pvr", "ba_data/textures/coin.pvr",

View File

@ -5697,6 +5697,7 @@ TEX2D_DDS_TARGETS = \
$(BUILD_DIR)/ba_data/textures/circleOutlineNoAlpha.dds \ $(BUILD_DIR)/ba_data/textures/circleOutlineNoAlpha.dds \
$(BUILD_DIR)/ba_data/textures/circleShadow.dds \ $(BUILD_DIR)/ba_data/textures/circleShadow.dds \
$(BUILD_DIR)/ba_data/textures/circleZigZag.dds \ $(BUILD_DIR)/ba_data/textures/circleZigZag.dds \
$(BUILD_DIR)/ba_data/textures/clayStroke.dds \
$(BUILD_DIR)/ba_data/textures/coin.dds \ $(BUILD_DIR)/ba_data/textures/coin.dds \
$(BUILD_DIR)/ba_data/textures/controllerIcon.dds \ $(BUILD_DIR)/ba_data/textures/controllerIcon.dds \
$(BUILD_DIR)/ba_data/textures/courtyardLevelColor.dds \ $(BUILD_DIR)/ba_data/textures/courtyardLevelColor.dds \
@ -6101,6 +6102,7 @@ TEX2D_PVR_TARGETS = \
$(BUILD_DIR)/ba_data/textures/circleOutlineNoAlpha.pvr \ $(BUILD_DIR)/ba_data/textures/circleOutlineNoAlpha.pvr \
$(BUILD_DIR)/ba_data/textures/circleShadow.pvr \ $(BUILD_DIR)/ba_data/textures/circleShadow.pvr \
$(BUILD_DIR)/ba_data/textures/circleZigZag.pvr \ $(BUILD_DIR)/ba_data/textures/circleZigZag.pvr \
$(BUILD_DIR)/ba_data/textures/clayStroke.pvr \
$(BUILD_DIR)/ba_data/textures/coin.pvr \ $(BUILD_DIR)/ba_data/textures/coin.pvr \
$(BUILD_DIR)/ba_data/textures/controllerIcon.pvr \ $(BUILD_DIR)/ba_data/textures/controllerIcon.pvr \
$(BUILD_DIR)/ba_data/textures/courtyardLevelColor.pvr \ $(BUILD_DIR)/ba_data/textures/courtyardLevelColor.pvr \
@ -6505,6 +6507,7 @@ TEX2D_KTX_TARGETS = \
$(BUILD_DIR)/ba_data/textures/circleOutlineNoAlpha.ktx \ $(BUILD_DIR)/ba_data/textures/circleOutlineNoAlpha.ktx \
$(BUILD_DIR)/ba_data/textures/circleShadow.ktx \ $(BUILD_DIR)/ba_data/textures/circleShadow.ktx \
$(BUILD_DIR)/ba_data/textures/circleZigZag.ktx \ $(BUILD_DIR)/ba_data/textures/circleZigZag.ktx \
$(BUILD_DIR)/ba_data/textures/clayStroke.ktx \
$(BUILD_DIR)/ba_data/textures/coin.ktx \ $(BUILD_DIR)/ba_data/textures/coin.ktx \
$(BUILD_DIR)/ba_data/textures/controllerIcon.ktx \ $(BUILD_DIR)/ba_data/textures/controllerIcon.ktx \
$(BUILD_DIR)/ba_data/textures/courtyardLevelColor.ktx \ $(BUILD_DIR)/ba_data/textures/courtyardLevelColor.ktx \
@ -6909,6 +6912,7 @@ TEX2D_PREVIEW_PNG_TARGETS = \
$(BUILD_DIR)/ba_data/textures/circleShadow_preview.png \ $(BUILD_DIR)/ba_data/textures/circleShadow_preview.png \
$(BUILD_DIR)/ba_data/textures/circleZigZag_preview.png \ $(BUILD_DIR)/ba_data/textures/circleZigZag_preview.png \
$(BUILD_DIR)/ba_data/textures/circle_preview.png \ $(BUILD_DIR)/ba_data/textures/circle_preview.png \
$(BUILD_DIR)/ba_data/textures/clayStroke_preview.png \
$(BUILD_DIR)/ba_data/textures/coin_preview.png \ $(BUILD_DIR)/ba_data/textures/coin_preview.png \
$(BUILD_DIR)/ba_data/textures/controllerIcon_preview.png \ $(BUILD_DIR)/ba_data/textures/controllerIcon_preview.png \
$(BUILD_DIR)/ba_data/textures/courtyardLevelColor_preview.png \ $(BUILD_DIR)/ba_data/textures/courtyardLevelColor_preview.png \

View File

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

View File

@ -61,6 +61,10 @@ class CoopSession(Session):
max_players = classic.coop_session_args['max_players'] max_players = classic.coop_session_args['max_players']
else: else:
max_players = app.config.get('Coop Game Max Players', 4) max_players = app.config.get('Coop Game Max Players', 4)
if 'submit_score' in classic.coop_session_args:
submit_score = classic.coop_session_args['submit_score']
else:
submit_score = True
# print('FIXME: COOP SESSION WOULD CALC DEPS.') # print('FIXME: COOP SESSION WOULD CALC DEPS.')
depsets: Sequence[bascenev1.DependencySet] = [] depsets: Sequence[bascenev1.DependencySet] = []
@ -71,6 +75,7 @@ class CoopSession(Session):
team_colors=TEAM_COLORS, team_colors=TEAM_COLORS,
min_players=min_players, min_players=min_players,
max_players=max_players, max_players=max_players,
submit_score=submit_score,
) )
# Tournament-ID if we correspond to a co-op tournament (otherwise None) # Tournament-ID if we correspond to a co-op tournament (otherwise None)
@ -346,7 +351,10 @@ class CoopSession(Session):
self.setactivity(next_game) self.setactivity(next_game)
if not (env.demo or env.arcade): if not (env.demo or env.arcade):
if self.tournament_id is not None: if (
self.tournament_id is not None
and classic.coop_session_args['submit_score']
):
self._custom_menu_ui = [ self._custom_menu_ui = [
{ {
'label': babase.Lstr(resource='restartText'), 'label': babase.Lstr(resource='restartText'),

View File

@ -100,6 +100,7 @@ class Session:
team_colors: Sequence[Sequence[float]] | None = None, team_colors: Sequence[Sequence[float]] | None = None,
min_players: int = 1, min_players: int = 1,
max_players: int = 8, max_players: int = 8,
submit_score: bool = True,
): ):
"""Instantiate a session. """Instantiate a session.
@ -175,6 +176,7 @@ class Session:
if _max_players_override is None if _max_players_override is None
else _max_players_override else _max_players_override
) )
self.submit_score = submit_score
self.customdata = {} self.customdata = {}
self._in_set_activity = False self._in_set_activity = False

View File

@ -125,6 +125,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
self._tournament_time_remaining: float | None = None self._tournament_time_remaining: float | None = None
self._tournament_time_remaining_text: Text | None = None self._tournament_time_remaining_text: Text | None = None
self._tournament_time_remaining_text_timer: bs.BaseTimer | None = None self._tournament_time_remaining_text_timer: bs.BaseTimer | None = None
self._submit_score = self.session.submit_score
# Stuff for activity skip by pressing button # Stuff for activity skip by pressing button
self._birth_time = bs.time() self._birth_time = bs.time()
@ -789,7 +790,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
transition_delay=2.0, transition_delay=2.0,
) )
if self._score is not None: if self._score is not None and self._submit_score:
bs.timer(0.4, bs.WeakCall(self._play_drumroll)) bs.timer(0.4, bs.WeakCall(self._play_drumroll))
# Add us to high scores, filter, and store. # Add us to high scores, filter, and store.
@ -1396,7 +1397,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
assert self._show_info is not None assert self._show_info is not None
available = self._show_info['results'] is not None available = self._show_info['results'] is not None
if available: if available and self._submit_score:
error = ( error = (
self._show_info['results']['error'] self._show_info['results']['error']
if 'error' in self._show_info['results'] if 'error' in self._show_info['results']
@ -1529,7 +1530,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
maxwidth=400, maxwidth=400,
transition_delay=1.0, transition_delay=1.0,
).autoretain() ).autoretain()
else: elif self._submit_score:
ZoomText( ZoomText(
( (
('#' + str(player_rank)) ('#' + str(player_rank))
@ -1752,9 +1753,10 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
transition_delay=0, transition_delay=0,
).autoretain() ).autoretain()
bs.timer(0.35, self._score_display_sound.play) if self._submit_score:
if not error: bs.timer(0.35, self._score_display_sound.play)
bs.timer(0.35, self.cymbal_sound.play) if not error:
bs.timer(0.35, self.cymbal_sound.play)
def _show_fail(self) -> None: def _show_fail(self) -> None:
ZoomText( ZoomText(

View File

@ -223,10 +223,20 @@ class PlayerSpaz(Spaz):
elif isinstance(msg, bs.DieMessage): elif isinstance(msg, bs.DieMessage):
# Report player deaths to the game. # Report player deaths to the game.
if not self._dead: if not self._dead:
# Immediate-mode or left-game deaths don't count as 'kills'. # Was this player killed while being held?
killed = ( was_held = self.held_count > 0 and self.last_player_held_by
not msg.immediate and msg.how is not bs.DeathType.LEFT_GAME # Was this player attacked before death?
was_attacked_recently = (
self.last_player_attacked_by
and bs.time() - self.last_attacked_time < 4.0
) )
# Leaving the game doesn't count as a kill *unless*
# someone does it intentionally while being attacked.
left_game_cleanly = msg.how is bs.DeathType.LEFT_GAME and not (
was_held or was_attacked_recently
)
killed = not (msg.immediate or left_game_cleanly)
activity = self._activity() activity = self._activity()
@ -236,7 +246,7 @@ class PlayerSpaz(Spaz):
else: else:
# If this player was being held at the time of death, # If this player was being held at the time of death,
# the holder is the killer. # the holder is the killer.
if self.held_count > 0 and self.last_player_held_by: if was_held:
killerplayer = self.last_player_held_by killerplayer = self.last_player_held_by
else: else:
# Otherwise, if they were attacked by someone in the # Otherwise, if they were attacked by someone in the
@ -246,10 +256,7 @@ class PlayerSpaz(Spaz):
# all bot kills would register as suicides; need to # all bot kills would register as suicides; need to
# change this from last_player_attacked_by to # change this from last_player_attacked_by to
# something like last_actor_attacked_by to fix that. # something like last_actor_attacked_by to fix that.
if ( if was_attacked_recently:
self.last_player_attacked_by
and bs.time() - self.last_attacked_time < 4.0
):
killerplayer = self.last_player_attacked_by killerplayer = self.last_player_attacked_by
else: else:
# ok, call it a suicide unless we're in co-op # ok, call it a suicide unless we're in co-op

View File

@ -527,7 +527,7 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]):
team.touch_return_timer = None team.touch_return_timer = None
team.touch_return_timer_ticking = None team.touch_return_timer_ticking = None
if team.flag_return_touches < 0: if team.flag_return_touches < 0:
logging.exception('CTF flag_return_touches < 0') logging.error('CTF flag_return_touches < 0', stack_info=True)
def _handle_death_flag_capture(self, player: Player) -> None: def _handle_death_flag_capture(self, player: Player) -> None:
"""Handles flag values when a player dies or leaves the game.""" """Handles flag values when a player dies or leaves the game."""
@ -536,22 +536,29 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]):
return return
team = player.team team = player.team
# For each "point" our player has touched theflag (Could be multiple),
# deduct one from both our player and # For each "point" our player has touched theflag (Could be
# the flag's return touches variable. # multiple), deduct one from both our player and the flag's
# return touches variable.
for _ in range(player.touching_own_flag): for _ in range(player.touching_own_flag):
# Deduct # Deduct
player.touching_own_flag -= 1 player.touching_own_flag -= 1
team.flag_return_touches -= 1
# Update our flag's timer accordingly # (This was only incremented if we have non-zero
# (Prevents immediate resets in case # return-times).
# there might be more people touching it). if float(self.flag_touch_return_time) > 0.0:
if team.flag_return_touches == 0: team.flag_return_touches -= 1
team.touch_return_timer = None # Update our flag's timer accordingly
team.touch_return_timer_ticking = None # (Prevents immediate resets in case
# Safety check, just to be sure! # there might be more people touching it).
if team.flag_return_touches < 0: if team.flag_return_touches == 0:
logging.exception('CTF flag_return_touches < 0') team.touch_return_timer = None
team.touch_return_timer_ticking = None
# Safety check, just to be sure!
if team.flag_return_touches < 0:
logging.error(
'CTF flag_return_touches < 0', stack_info=True
)
def _flash_base(self, team: Team, length: float = 2.0) -> None: def _flash_base(self, team: Team, length: float = 2.0) -> None:
light = bs.newnode( light = bs.newnode(

View File

@ -213,6 +213,8 @@ class ColorPickerExact(PopupWindow):
self._last_press_time = bui.apptime() self._last_press_time = bui.apptime()
self._last_press_color_name: str | None = None self._last_press_color_name: str | None = None
self._last_press_increasing: bool | None = None self._last_press_increasing: bool | None = None
self._hex_timer: bui.AppTimer | None = None
self._hex_prev_text: str = '#FFFFFF'
self._change_speed = 1.0 self._change_speed = 1.0
width = 180.0 width = 180.0
height = 240.0 height = 240.0
@ -229,11 +231,26 @@ class ColorPickerExact(PopupWindow):
) )
self._swatch = bui.imagewidget( self._swatch = bui.imagewidget(
parent=self.root_widget, parent=self.root_widget,
position=(width * 0.5 - 50, height - 70), position=(width * 0.5 - 65 + 5, height - 95),
size=(100, 70), size=(130, 115),
texture=bui.gettexture('buttonSquare'), texture=bui.gettexture('clayStroke'),
color=(1, 0, 0), color=(1, 0, 0),
) )
self._hex_textbox = bui.textwidget(
parent=self.root_widget,
position=(width * 0.5 - 37.5 + 3, height - 51),
max_chars=9,
text='#FFFFFF',
autoselect=True,
size=(75, 30),
v_align='center',
editable=True,
maxwidth=70,
allow_clear_button=False,
force_internal_editing=True,
glow_type='uniform',
)
x = 50 x = 50
y = height - 90 y = height - 90
self._label_r: bui.Widget self._label_r: bui.Widget
@ -288,6 +305,37 @@ class ColorPickerExact(PopupWindow):
# color to the delegate, so start doing that. # color to the delegate, so start doing that.
self._update_for_color() self._update_for_color()
# Update our HEX stuff!
self._update_for_hex()
self._hex_timer = bui.AppTimer(0.025, self._update_for_hex, repeat=True)
def _update_for_hex(self) -> None:
"""Update for any HEX or color change."""
from typing import cast
hextext = cast(str, bui.textwidget(query=self._hex_textbox))
hexcolor: tuple
# Check if our current hex text doesn't match with our old one.
# Convert our current hex text into a color if possible.
if hextext != self._hex_prev_text:
try:
hexcolor = hex_to_color(hextext)
if len(hexcolor) == 4:
r, g, b, a = hexcolor
del a # unused
else:
r, g, b = hexcolor
# Replace the color!
for i, ch in enumerate((r, g, b)):
self._color[i] = max(0.0, min(1.0, ch))
self._update_for_color()
# Usually, a ValueError will occur if the provided hex
# is incomplete, which occurs when in the midst of typing it.
except ValueError:
pass
# Store the current text for our next comparison.
self._hex_prev_text = hextext
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
def _update_for_color(self) -> None: def _update_for_color(self) -> None:
if not self.root_widget: if not self.root_widget:
@ -303,6 +351,16 @@ class ColorPickerExact(PopupWindow):
if self._delegate is not None: if self._delegate is not None:
self._delegate.color_picker_selected_color(self, self._color) self._delegate.color_picker_selected_color(self, self._color)
# Show the HEX code of this color.
r, g, b = self._color
hexcode = color_to_hex(r, g, b, None)
self._hex_prev_text = hexcode
bui.textwidget(
edit=self._hex_textbox,
text=hexcode,
color=color_overlay_func(r, g, b),
)
def _color_change_press(self, color_name: str, increasing: bool) -> None: def _color_change_press(self, color_name: str, increasing: bool) -> None:
# If we get rapid-fire presses, eventually start moving faster. # If we get rapid-fire presses, eventually start moving faster.
current_time = bui.apptime() current_time = bui.apptime()
@ -331,6 +389,8 @@ class ColorPickerExact(PopupWindow):
return self._tag return self._tag
def _transition_out(self) -> None: def _transition_out(self) -> None:
# Kill our timer
self._hex_timer = None
if not self._transitioning_out: if not self._transitioning_out:
self._transitioning_out = True self._transitioning_out = True
if self._delegate is not None: if self._delegate is not None:
@ -342,3 +402,102 @@ class ColorPickerExact(PopupWindow):
if not self._transitioning_out: if not self._transitioning_out:
bui.getsound('swish').play() bui.getsound('swish').play()
self._transition_out() self._transition_out()
def hex_to_color(hex_color: str) -> tuple:
"""Transforms an RGB / RGBA hex code into an rgb1/rgba1 tuple.
Args:
hex_color (str): The HEX color.
Raises:
ValueError: If the provided HEX color isn't 6 or 8 characters long.
Returns:
tuple: The color tuple divided by 255.
"""
# Remove the '#' from the string if provided.
if hex_color.startswith('#'):
hex_color = hex_color.lstrip('#')
# Check if this has a valid length.
hexlength = len(hex_color)
if not hexlength in [6, 8]:
raise ValueError(f'Invalid HEX color provided: "{hex_color}"')
# Convert the hex bytes to their true byte form.
ar, ag, ab, aa = (
(int.from_bytes(bytes.fromhex(hex_color[0:2]))),
(int.from_bytes(bytes.fromhex(hex_color[2:4]))),
(int.from_bytes(bytes.fromhex(hex_color[4:6]))),
(
(int.from_bytes(bytes.fromhex(hex_color[6:8])))
if hexlength == 8
else None
),
)
# Divide all numbers by 255 and return.
nr, ng, nb, na = (
x / 255 if x is not None else None for x in (ar, ag, ab, aa)
)
return (nr, ng, nb, na) if aa is not None else (nr, ng, nb)
def color_to_hex(r: float, g: float, b: float, a: float | None = 1.0) -> str:
"""Converts an rgb1 tuple to a HEX color code.
Args:
r (float): Red.
g (float): Green.
b (float): Blue.
a (float, optional): Alpha. Defaults to 1.0.
Returns:
str: The hexified rgba values.
"""
# Turn our rgb1 to rgb255
nr, ng, nb, na = [
int(min(255, x * 255)) if x is not None else x for x in [r, g, b, a]
]
# Merge all values into their HEX representation.
hex_code = (
f'#{nr:02x}{ng:02x}{nb:02x}{na:02x}'
if na is not None
else f'#{nr:02x}{ng:02x}{nb:02x}'
)
return hex_code
def color_overlay_func(
r: float, g: float, b: float, a: float | None = None
) -> tuple:
"""I could NOT come up with a better function name.
Args:
r (float): Red.
g (float): Green.
b (float): Blue.
a (float | None, optional): Alpha. Defaults to None.
Returns:
tuple: A brighter color if the provided one is dark,
and a darker one if it's darker.
"""
# Calculate the relative luminance using the formula for sRGB
# https://www.w3.org/TR/WCAG20/#relativeluminancedef
def relative_luminance(color: float) -> Any:
if color <= 0.03928:
return color / 12.92
return ((color + 0.055) / 1.055) ** 2.4
luminance = (
0.2126 * relative_luminance(r)
+ 0.7152 * relative_luminance(g)
+ 0.0722 * relative_luminance(b)
)
# Set our color multiplier depending on the provided color's luminance.
luminant = 1.65 if luminance < 0.33 else 0.2
# Multiply our given numbers, making sure
# they don't blend in the original bg.
avg = (0.7 - (r + g + b / 3)) + 0.15
r, g, b = [max(avg, x * luminant) for x in (r, g, b)]
# Include our alpha and ship it!
return (r, g, b, a) if a is not None else (r, g, b)

View File

@ -129,8 +129,8 @@ class PopupMenuWindow(PopupWindow):
if choices_display is None: if choices_display is None:
choices_display = [] choices_display = []
# FIXME: For the moment we base our width on these strings so # FIXME: For the moment we base our width on these strings so we
# we need to flatten them. # need to flatten them.
choices_display_fin: list[str] = [] choices_display_fin: list[str] = []
for choice_display in choices_display: for choice_display in choices_display:
choices_display_fin.append(choice_display.evaluate()) choices_display_fin.append(choice_display.evaluate())
@ -154,9 +154,9 @@ class PopupMenuWindow(PopupWindow):
else: else:
self._height = 20 + len(choices) * 33 self._height = 20 + len(choices) * 33
self._use_scroll = False self._use_scroll = False
self._delegate = None # don't want this stuff called just yet.. self._delegate = None # Don't want this stuff called just yet.
# extend width to fit our longest string (or our max-width) # Extend width to fit our longest string (or our max-width).
for index, choice in enumerate(choices): for index, choice in enumerate(choices):
if len(choices_display_fin) == len(choices): if len(choices_display_fin) == len(choices):
choice_display_name = choices_display_fin[index] choice_display_name = choices_display_fin[index]
@ -185,8 +185,8 @@ class PopupMenuWindow(PopupWindow):
+ 60, + 60,
) )
# init parent class - this will rescale and reposition things as # Init parent class - this will rescale and reposition things as
# needed and create our root widget # needed and create our root widget.
super().__init__( super().__init__(
position, size=(self._width, self._height), scale=self._scale position, size=(self._width, self._height), scale=self._scale
) )
@ -205,7 +205,7 @@ class PopupMenuWindow(PopupWindow):
else: else:
self._offset_widget = bui.containerwidget( self._offset_widget = bui.containerwidget(
parent=self.root_widget, parent=self.root_widget,
position=(30, 15), position=(12, 12),
size=(self._width - 40, self._height), size=(self._width - 40, self._height),
background=False, background=False,
) )
@ -238,6 +238,7 @@ class PopupMenuWindow(PopupWindow):
on_activate_call=self._activate, on_activate_call=self._activate,
v_align='center', v_align='center',
selectable=(not inactive), selectable=(not inactive),
glow_type='uniform',
) )
if choice == self._current_choice: if choice == self._current_choice:
bui.containerwidget( bui.containerwidget(

View File

@ -411,24 +411,11 @@ class ProfileBrowserWindow(bui.Window):
char_index = spazzes.index('Spaz') char_index = spazzes.index('Spaz')
assert isinstance(tval, str) assert isinstance(tval, str)
character = bui.buttonwidget(
parent=self._subcontainer,
position=(0, y_val),
size=(28, 28),
label='',
color=(1, 1, 1),
mask_texture=bui.gettexture('characterIconMask'),
tint_color=color,
tint2_color=_highlight,
texture=icon_textures[char_index],
tint_texture=icon_tint_textures[char_index],
selectable=False,
)
txtw = bui.textwidget( txtw = bui.textwidget(
parent=self._subcontainer, parent=self._subcontainer,
position=(35, y_val), position=(5, y_val),
size=((self._width - 210) / scl, 28), size=((self._width - 210) / scl, 28),
text=bui.Lstr(value=tval), text=bui.Lstr(value=f' {tval}'),
h_align='left', h_align='left',
v_align='center', v_align='center',
on_select_call=bui.WeakCall(self._select, p_name, index), on_select_call=bui.WeakCall(self._select, p_name, index),
@ -439,6 +426,17 @@ class ProfileBrowserWindow(bui.Window):
on_activate_call=bui.Call(self._edit_button.activate), on_activate_call=bui.Call(self._edit_button.activate),
selectable=True, selectable=True,
) )
character = bui.imagewidget(
parent=self._subcontainer,
position=(0, y_val),
size=(30, 30),
color=(1, 1, 1),
mask_texture=bui.gettexture('characterIconMask'),
tint_color=color,
tint2_color=_highlight,
texture=icon_textures[char_index],
tint_texture=icon_tint_textures[char_index],
)
if index == 0: if index == 0:
bui.widget(edit=txtw, up_widget=self._back_button) bui.widget(edit=txtw, up_widget=self._back_button)
if self._selected_profile is None: if self._selected_profile is None:

View File

@ -812,15 +812,22 @@ class GamepadSettingsWindow(bui.Window):
from bauiv1lib.confirm import ConfirmWindow from bauiv1lib.confirm import ConfirmWindow
assert bui.app.classic is not None assert bui.app.classic is not None
ConfirmWindow(
# TODO: Implement a translation string for this! # efro note: I think it's ok to reset without a confirm here
'Are you sure you want to reset your button mapping?\n' # because the user can see pretty clearly what changes and can
'This will also reset your advanced mappings\n' # cancel out of the settings window without saving if they want.
'and secondary controller button mappings.', if bool(False):
self._do_reset, ConfirmWindow(
width=490, # TODO: Implement a translation string for this!
height=150, 'Are you sure you want to reset your button mapping?\n'
) 'This will also reset your advanced mappings\n'
'and secondary controller button mappings.',
self._do_reset,
width=490,
height=150,
)
else:
self._do_reset()
def _do_reset(self) -> None: def _do_reset(self) -> None:
"""Resets the input's mapping settings.""" """Resets the input's mapping settings."""

View File

@ -305,13 +305,20 @@ class ConfigKeyboardWindow(bui.Window):
from bauiv1lib.confirm import ConfirmWindow from bauiv1lib.confirm import ConfirmWindow
assert bui.app.classic is not None assert bui.app.classic is not None
ConfirmWindow(
# TODO: Implement a translation string for this! # efro note: I think it's ok to reset without a confirm here
'Are you sure you want to reset your button mapping?', # because the user can see pretty clearly what changes and can
self._do_reset, # cancel out of the keyboard settings edit if they want.
width=480, if bool(False):
height=95, ConfirmWindow(
) # TODO: Implement a translation string for this!
'Are you sure you want to reset your button mapping?',
self._do_reset,
width=480,
height=95,
)
else:
self._do_reset()
def _do_reset(self) -> None: def _do_reset(self) -> None:
"""Resets the input's mapping settings.""" """Resets the input's mapping settings."""

View File

@ -92,7 +92,7 @@ class ModdingToolsWindow(bui.Window):
parent=self._root_widget, parent=self._root_widget,
position=(0, self._height - 52), position=(0, self._height - 52),
size=(self._width, 25), size=(self._width, 25),
text=bui.Lstr(resource='moddingToolsTitleText'), text=bui.Lstr(resource='settingsWindowAdvanced.moddingToolsText'),
color=app.ui_v1.title_color, color=app.ui_v1.title_color,
h_align='center', h_align='center',
v_align='top', v_align='top',
@ -131,7 +131,7 @@ class ModdingToolsWindow(bui.Window):
position=(self._sub_width / 2 - this_button_width / 2, v - 10), position=(self._sub_width / 2 - this_button_width / 2, v - 10),
size=(this_button_width, 60), size=(this_button_width, 60),
autoselect=True, autoselect=True,
label=bui.Lstr(resource='createUserSystemScriptsText'), label=bui.Lstr(resource='userSystemScriptsCreateText'),
text_scale=1.0, text_scale=1.0,
on_activate_call=babase.modutils.create_user_system_scripts, on_activate_call=babase.modutils.create_user_system_scripts,
) )
@ -142,7 +142,7 @@ class ModdingToolsWindow(bui.Window):
position=(self._sub_width / 2 - this_button_width / 2, v - 10), position=(self._sub_width / 2 - this_button_width / 2, v - 10),
size=(this_button_width, 60), size=(this_button_width, 60),
autoselect=True, autoselect=True,
label=bui.Lstr(resource='deleteUserSystemScriptsText'), label=bui.Lstr(resource='userSystemScriptsDeleteText'),
text_scale=1.0, text_scale=1.0,
on_activate_call=lambda: ConfirmWindow( on_activate_call=lambda: ConfirmWindow(
action=babase.modutils.delete_user_system_scripts, action=babase.modutils.delete_user_system_scripts,
@ -154,7 +154,10 @@ class ModdingToolsWindow(bui.Window):
parent=self._subcontainer, parent=self._subcontainer,
position=(170, v + 10), position=(170, v + 10),
size=(0, 0), size=(0, 0),
text=bui.Lstr(value='UI SIZE :'), text=bui.Lstr(
value='$(S) :',
subs=[('$(S)', bui.Lstr(resource='uiScaleText'))],
),
color=app.ui_v1.title_color, color=app.ui_v1.title_color,
h_align='center', h_align='center',
v_align='center', v_align='center',
@ -172,9 +175,9 @@ class ModdingToolsWindow(bui.Window):
], ],
choices_display=[ choices_display=[
bui.Lstr(resource='autoText'), bui.Lstr(resource='autoText'),
bui.Lstr(resource='smallText'), bui.Lstr(resource='sizeSmallText'),
bui.Lstr(resource='mediumText'), bui.Lstr(resource='sizeMediumText'),
bui.Lstr(resource='largeText'), bui.Lstr(resource='sizeLargeText'),
], ],
current_choice=app.config.get('UI Scale', 'auto'), current_choice=app.config.get('UI Scale', 'auto'),
on_value_change_call=self._set_uiscale, on_value_change_call=self._set_uiscale,

View File

@ -14,7 +14,6 @@ import bauiv1 as bui
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Any, Callable from typing import Any, Callable
import bascenev1 as bs import bascenev1 as bs
@ -32,6 +31,7 @@ class TournamentEntryWindow(PopupWindow):
on_close_call: Callable[[], Any] | None = None, on_close_call: Callable[[], Any] | None = None,
): ):
# Needs some tidying. # Needs some tidying.
# pylint: disable=too-many-locals
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
@ -80,11 +80,21 @@ class TournamentEntryWindow(PopupWindow):
self._tournament_activity = tournament_activity self._tournament_activity = tournament_activity
self._width = 340 self._width: float = 340.0
self._height = 225 self._height: float = 225.0
bg_color = (0.5, 0.4, 0.6) bg_color = (0.5, 0.4, 0.6)
# Show the practice button as long as we're not
# restarting while on a paid tournament run.
self._do_practice = (
self._tournament_activity is None
and bui.app.config.get('tournament_practice_enabled', False)
)
off_p = 0 if not self._do_practice else 48
self._height += off_p * 0.933
# Creates our root_widget. # Creates our root_widget.
super().__init__( super().__init__(
position=position, position=position,
@ -107,7 +117,7 @@ class TournamentEntryWindow(PopupWindow):
self._cancel_button = bui.buttonwidget( self._cancel_button = bui.buttonwidget(
parent=self.root_widget, parent=self.root_widget,
position=(20, self._height - 34), position=(40, self._height - 34),
size=(60, 60), size=(60, 60),
scale=0.5, scale=0.5,
label='', label='',
@ -132,15 +142,15 @@ class TournamentEntryWindow(PopupWindow):
btn = self._pay_with_tickets_button = bui.buttonwidget( btn = self._pay_with_tickets_button = bui.buttonwidget(
parent=self.root_widget, parent=self.root_widget,
position=(30 + x_offs, 60), position=(30 + x_offs, 60 + off_p),
autoselect=True, autoselect=True,
button_type='square', button_type='square',
size=(120, 120), size=(120, 120),
label='', label='',
on_activate_call=self._on_pay_with_tickets_press, on_activate_call=self._on_pay_with_tickets_press,
) )
self._ticket_img_pos = (50 + x_offs, 94) self._ticket_img_pos = (50 + x_offs, 94 + off_p)
self._ticket_img_pos_free = (50 + x_offs, 80) self._ticket_img_pos_free = (50 + x_offs, 80 + off_p)
self._ticket_img = bui.imagewidget( self._ticket_img = bui.imagewidget(
parent=self.root_widget, parent=self.root_widget,
draw_controller=btn, draw_controller=btn,
@ -148,8 +158,8 @@ class TournamentEntryWindow(PopupWindow):
position=self._ticket_img_pos, position=self._ticket_img_pos,
texture=bui.gettexture('tickets'), texture=bui.gettexture('tickets'),
) )
self._ticket_cost_text_position = (87 + x_offs, 88) self._ticket_cost_text_position = (87 + x_offs, 88 + off_p)
self._ticket_cost_text_position_free = (87 + x_offs, 120) self._ticket_cost_text_position_free = (87 + x_offs, 120 + off_p)
self._ticket_cost_text = bui.textwidget( self._ticket_cost_text = bui.textwidget(
parent=self.root_widget, parent=self.root_widget,
draw_controller=btn, draw_controller=btn,
@ -165,7 +175,7 @@ class TournamentEntryWindow(PopupWindow):
self._free_plays_remaining_text = bui.textwidget( self._free_plays_remaining_text = bui.textwidget(
parent=self.root_widget, parent=self.root_widget,
draw_controller=btn, draw_controller=btn,
position=(87 + x_offs, 78), position=(87 + x_offs, 78 + off_p),
size=(0, 0), size=(0, 0),
h_align='center', h_align='center',
v_align='center', v_align='center',
@ -178,7 +188,7 @@ class TournamentEntryWindow(PopupWindow):
if self._do_ad_btn: if self._do_ad_btn:
btn = self._pay_with_ad_btn = bui.buttonwidget( btn = self._pay_with_ad_btn = bui.buttonwidget(
parent=self.root_widget, parent=self.root_widget,
position=(190, 60), position=(190, 60 + off_p),
autoselect=True, autoselect=True,
button_type='square', button_type='square',
size=(120, 120), size=(120, 120),
@ -189,12 +199,12 @@ class TournamentEntryWindow(PopupWindow):
parent=self.root_widget, parent=self.root_widget,
draw_controller=btn, draw_controller=btn,
size=(80, 80), size=(80, 80),
position=(210, 94), position=(210, 94 + off_p),
texture=bui.gettexture('tv'), texture=bui.gettexture('tv'),
) )
self._ad_text_position = (251, 88) self._ad_text_position = (251, 88 + off_p)
self._ad_text_position_remaining = (251, 92) self._ad_text_position_remaining = (251, 92 + off_p)
have_ad_tries_remaining = ( have_ad_tries_remaining = (
self._tournament_info['adTriesRemaining'] is not None self._tournament_info['adTriesRemaining'] is not None
) )
@ -224,7 +234,7 @@ class TournamentEntryWindow(PopupWindow):
self._ad_plays_remaining_text = bui.textwidget( self._ad_plays_remaining_text = bui.textwidget(
parent=self.root_widget, parent=self.root_widget,
draw_controller=btn, draw_controller=btn,
position=(251, 78), position=(251, 78 + off_p),
size=(0, 0), size=(0, 0),
h_align='center', h_align='center',
v_align='center', v_align='center',
@ -236,7 +246,7 @@ class TournamentEntryWindow(PopupWindow):
bui.textwidget( bui.textwidget(
parent=self.root_widget, parent=self.root_widget,
position=(self._width * 0.5, 120), position=(self._width * 0.5, 120 + off_p),
size=(0, 0), size=(0, 0),
h_align='center', h_align='center',
v_align='center', v_align='center',
@ -250,13 +260,26 @@ class TournamentEntryWindow(PopupWindow):
else: else:
self._pay_with_ad_btn = None self._pay_with_ad_btn = None
btn_size = (150, 45)
btn_pos = (self._width / 2 - btn_size[0] / 2, self._width / 2 - 110)
self._practice_button = None
if self._do_practice:
self._practice_button = bui.buttonwidget(
parent=self.root_widget,
position=btn_pos,
autoselect=True,
size=btn_size,
label=bui.Lstr(resource='practiceText'),
on_activate_call=self._on_practice_press,
)
self._get_tickets_button: bui.Widget | None = None self._get_tickets_button: bui.Widget | None = None
self._ticket_count_text: bui.Widget | None = None self._ticket_count_text: bui.Widget | None = None
if not bui.app.ui_v1.use_toolbars: if not bui.app.ui_v1.use_toolbars:
if bui.app.classic.allow_ticket_purchases: if bui.app.classic.allow_ticket_purchases:
self._get_tickets_button = bui.buttonwidget( self._get_tickets_button = bui.buttonwidget(
parent=self.root_widget, parent=self.root_widget,
position=(self._width - 190 + 125, self._height - 34), position=(self._width - 190 + 105, self._height - 34),
autoselect=True, autoselect=True,
scale=0.5, scale=0.5,
size=(120, 60), size=(120, 60),
@ -372,6 +395,8 @@ class TournamentEntryWindow(PopupWindow):
sel = self.root_widget.get_selected_child() sel = self.root_widget.get_selected_child()
if sel == self._pay_with_ad_btn: if sel == self._pay_with_ad_btn:
sel_name = 'Ad' sel_name = 'Ad'
elif sel == self._practice_button:
sel_name = 'Practice'
else: else:
sel_name = 'Tickets' sel_name = 'Tickets'
cfg = bui.app.config cfg = bui.app.config
@ -382,6 +407,8 @@ class TournamentEntryWindow(PopupWindow):
sel_name = bui.app.config.get('Tournament Pay Selection', 'Tickets') sel_name = bui.app.config.get('Tournament Pay Selection', 'Tickets')
if sel_name == 'Ad' and self._pay_with_ad_btn is not None: if sel_name == 'Ad' and self._pay_with_ad_btn is not None:
sel = self._pay_with_ad_btn sel = self._pay_with_ad_btn
elif sel_name == 'Practice' and self._practice_button is not None:
sel = self._practice_button
else: else:
sel = self._pay_with_tickets_button sel = self._pay_with_tickets_button
bui.containerwidget(edit=self.root_widget, selected_child=sel) bui.containerwidget(edit=self.root_widget, selected_child=sel)
@ -537,29 +564,37 @@ class TournamentEntryWindow(PopupWindow):
text=bui.charstr(bui.SpecialChar.TICKET) + t_str, text=bui.charstr(bui.SpecialChar.TICKET) + t_str,
) )
def _launch(self) -> None: def _launch(self, practice: bool = False) -> None:
assert bui.app.classic is not None assert bui.app.classic is not None
if self._launched: if self._launched:
return return
self._launched = True self._launched = True
launched = False launched = False
# If they gave us an existing activity, just restart it. # If they gave us an existing, non-consistent
if self._tournament_activity is not None: # practice activity, just restart it.
if (
self._tournament_activity is not None
and not practice == self._tournament_activity.session.submit_score
):
try: try:
bui.apptimer(0.1, bui.getsound('cashRegister').play) if not practice:
bui.apptimer(0.1, bui.getsound('cashRegister').play)
bui.screenmessage(
bui.Lstr(
translate=(
'serverResponses',
'Entering tournament...',
)
),
color=(0, 1, 0),
)
bui.apptimer(0 if practice else 0.3, self._transition_out)
launched = True
with self._tournament_activity.context: with self._tournament_activity.context:
self._tournament_activity.end( self._tournament_activity.end(
{'outcome': 'restart'}, force=True {'outcome': 'restart'}, force=True
) )
bui.apptimer(0.3, self._transition_out)
launched = True
bui.screenmessage(
bui.Lstr(
translate=('serverResponses', 'Entering tournament...')
),
color=(0, 1, 0),
)
# We can hit exceptions here if _tournament_activity ends before # We can hit exceptions here if _tournament_activity ends before
# our restart attempt happens. # our restart attempt happens.
@ -572,9 +607,16 @@ class TournamentEntryWindow(PopupWindow):
# If we had no existing activity (or were unable to restart it) # If we had no existing activity (or were unable to restart it)
# launch a new session. # launch a new session.
if not launched: if not launched:
bui.apptimer(0.1, bui.getsound('cashRegister').play) if not practice:
bui.apptimer(0.1, bui.getsound('cashRegister').play)
bui.screenmessage(
bui.Lstr(
translate=('serverResponses', 'Entering tournament...')
),
color=(0, 1, 0),
)
bui.apptimer( bui.apptimer(
1.0, 0 if practice else 1.0,
lambda: ( lambda: (
bui.app.classic.launch_coop_game( bui.app.classic.launch_coop_game(
self._tournament_info['game'], self._tournament_info['game'],
@ -582,19 +624,14 @@ class TournamentEntryWindow(PopupWindow):
'min_players': self._tournament_info['minPlayers'], 'min_players': self._tournament_info['minPlayers'],
'max_players': self._tournament_info['maxPlayers'], 'max_players': self._tournament_info['maxPlayers'],
'tournament_id': self._tournament_id, 'tournament_id': self._tournament_id,
'submit_score': not practice,
}, },
) )
if bui.app.classic is not None if bui.app.classic is not None
else None else None
), ),
) )
bui.apptimer(0.7, self._transition_out) bui.apptimer(0 if practice else 1.25, self._transition_out)
bui.screenmessage(
bui.Lstr(
translate=('serverResponses', 'Entering tournament...')
),
color=(0, 1, 0),
)
def _on_pay_with_tickets_press(self) -> None: def _on_pay_with_tickets_press(self) -> None:
from bauiv1lib import getcurrency from bauiv1lib import getcurrency
@ -691,6 +728,25 @@ class TournamentEntryWindow(PopupWindow):
on_completion_call=bui.WeakCall(self._on_ad_complete), on_completion_call=bui.WeakCall(self._on_ad_complete),
) )
def _on_practice_press(self) -> None:
plus = bui.app.plus
assert plus is not None
# If we're already entering, ignore.
if self._entering:
return
# Deny if it looks like the tourney has ended.
if self._seconds_remaining == 0:
bui.screenmessage(
bui.Lstr(resource='tournamentEndedText'), color=(1, 0, 0)
)
bui.getsound('error').play()
return
self._entering = True
self._launch(practice=True)
def _on_ad_complete(self, actually_showed: bool) -> None: def _on_ad_complete(self, actually_showed: bool) -> None:
plus = bui.app.plus plus = bui.app.plus
assert plus is not None assert plus is not None

View File

@ -125,7 +125,7 @@ void BaseFeatureSet::OnModuleExec(PyObject* module) {
// they happen. // they happen.
g_core->python->EnablePythonLoggingCalls(); g_core->python->EnablePythonLoggingCalls();
// Marker we pop down at the very end so other modules can run sanity // A marker we pop down at the very end so other modules can run sanity
// checks to make sure we aren't importing them reciprocally when they // checks to make sure we aren't importing them reciprocally when they
// import us. // import us.
Python::MarkReachedEndOfModule(module); Python::MarkReachedEndOfModule(module);
@ -246,8 +246,8 @@ void BaseFeatureSet::StartApp() {
app_started_ = true; app_started_ = true;
// As the last step of this phase, tell the logic thread to apply the app // As the last step of this phase, tell the logic thread to apply the app
// config which will kick off screen creation and otherwise get the ball // config which will kick off screen creation or otherwise to get the
// rolling. // ball rolling.
{ {
Python::ScopedInterpreterLock gil; Python::ScopedInterpreterLock gil;
python->objs().Get(BasePython::ObjID::kAppPushApplyAppConfigCall).Call(); python->objs().Get(BasePython::ObjID::kAppPushApplyAppConfigCall).Call();

View File

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

View File

@ -328,7 +328,6 @@ void EventLoop::BootstrapThread_() {
assert(!bootstrapped_); assert(!bootstrapped_);
assert(g_core); assert(g_core);
thread_id_ = std::this_thread::get_id(); thread_id_ = std::this_thread::get_id();
const char* id_string;
switch (identifier_) { switch (identifier_) {
case EventLoopID::kLogic: case EventLoopID::kLogic:

View File

@ -1932,6 +1932,7 @@ static auto PyTextWidget(PyObject* self, PyObject* args,
PyObject* query_description_obj = Py_None; PyObject* query_description_obj = Py_None;
PyObject* adapter_finished_obj = Py_None; PyObject* adapter_finished_obj = Py_None;
PyObject* glow_type_obj = Py_None; PyObject* glow_type_obj = Py_None;
PyObject* allow_clear_button_obj = Py_None;
static const char* kwlist[] = {"edit", static const char* kwlist[] = {"edit",
"parent", "parent",
@ -1972,9 +1973,10 @@ static auto PyTextWidget(PyObject* self, PyObject* args,
"query_description", "query_description",
"adapter_finished", "adapter_finished",
"glow_type", "glow_type",
"allow_clear_button",
nullptr}; nullptr};
if (!PyArg_ParseTupleAndKeywords( if (!PyArg_ParseTupleAndKeywords(
args, keywds, "|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", args, keywds, "|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
const_cast<char**>(kwlist), &edit_obj, &parent_obj, &size_obj, const_cast<char**>(kwlist), &edit_obj, &parent_obj, &size_obj,
&pos_obj, &text_obj, &v_align_obj, &h_align_obj, &editable_obj, &pos_obj, &text_obj, &v_align_obj, &h_align_obj, &editable_obj,
&padding_obj, &on_return_press_call_obj, &on_activate_call_obj, &padding_obj, &on_return_press_call_obj, &on_activate_call_obj,
@ -1985,7 +1987,8 @@ static auto PyTextWidget(PyObject* self, PyObject* args,
&shadow_obj, &autoselect_obj, &rotate_obj, &enabled_obj, &shadow_obj, &autoselect_obj, &rotate_obj, &enabled_obj,
&force_internal_editing_obj, &always_show_carat_obj, &big_obj, &force_internal_editing_obj, &always_show_carat_obj, &big_obj,
&extra_touch_border_scale_obj, &res_scale_obj, &query_max_chars_obj, &extra_touch_border_scale_obj, &res_scale_obj, &query_max_chars_obj,
&query_description_obj, &adapter_finished_obj, &glow_type_obj)) &query_description_obj, &adapter_finished_obj, &glow_type_obj,
&allow_clear_button_obj))
return nullptr; return nullptr;
if (!g_base->CurrentContext().IsEmpty()) { if (!g_base->CurrentContext().IsEmpty()) {
@ -2209,6 +2212,9 @@ static auto PyTextWidget(PyObject* self, PyObject* args,
} }
widget->set_glow_type(glow_type); widget->set_glow_type(glow_type);
} }
if (allow_clear_button_obj != Py_None) {
widget->set_allow_clear_button(Python::GetPyBool(allow_clear_button_obj));
}
// If making a new widget, add it at the end. // If making a new widget, add it at the end.
if (edit_obj == Py_None) { if (edit_obj == Py_None) {
@ -2266,7 +2272,8 @@ static PyMethodDef PyTextWidgetDef = {
" query_max_chars: bauiv1.Widget | None = None,\n" " query_max_chars: bauiv1.Widget | None = None,\n"
" query_description: bauiv1.Widget | None = None,\n" " query_description: bauiv1.Widget | None = None,\n"
" adapter_finished: bool | None = None,\n" " adapter_finished: bool | None = None,\n"
" glow_type: str | None = None)\n" " glow_type: str | None = None,\n"
" allow_clear_button: bool | None = None)\n"
" -> bauiv1.Widget\n" " -> bauiv1.Widget\n"
"\n" "\n"
"Create or edit a text widget.\n" "Create or edit a text widget.\n"

View File

@ -30,7 +30,7 @@ TextWidget::TextWidget() {
// FIXME - should generalize this to any controller-only situation. // FIXME - should generalize this to any controller-only situation.
if (g_buildconfig.ostype_android()) { if (g_buildconfig.ostype_android()) {
if (g_base->input->touch_input() == nullptr) { if (g_base->input->touch_input() == nullptr) {
do_clear_button_ = false; implicit_clear_button_ = false;
} }
} }
birth_time_millisecs_ = birth_time_millisecs_ =
@ -253,7 +253,8 @@ void TextWidget::Draw(base::RenderPass* pass, bool draw_transparent) {
// Clear button. // Clear button.
if (editable() && (IsHierarchySelected() || always_show_carat_) if (editable() && (IsHierarchySelected() || always_show_carat_)
&& !text_raw_.empty() && do_clear_button_) { && !text_raw_.empty() && implicit_clear_button_
&& allow_clear_button_) {
base::SimpleComponent c(pass); base::SimpleComponent c(pass);
c.SetTransparent(true); c.SetTransparent(true);
if (clear_pressed_ && clear_mouse_over_) { if (clear_pressed_ && clear_mouse_over_) {
@ -819,7 +820,8 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
if (editable() && (IsHierarchySelected() || always_show_carat_) if (editable() && (IsHierarchySelected() || always_show_carat_)
&& !text_raw_.empty() && (x >= width_ - 35) && !text_raw_.empty() && (x >= width_ - 35)
&& (x < width_ + kClearMargin) && (y > -kClearMargin) && (x < width_ + kClearMargin) && (y > -kClearMargin)
&& (y < height_ + kClearMargin) && do_clear_button_) { && (y < height_ + kClearMargin) && implicit_clear_button_
&& allow_clear_button_) {
clear_pressed_ = clear_mouse_over_ = true; clear_pressed_ = clear_mouse_over_ = true;
return true; return true;
} }

View File

@ -73,6 +73,7 @@ class TextWidget : public Widget {
void set_flatness(float flatness) { flatness_ = flatness; } void set_flatness(float flatness) { flatness_ = flatness; }
void set_shadow(float shadow) { shadow_ = shadow; } void set_shadow(float shadow) { shadow_ = shadow; }
void set_res_scale(float res_scale); void set_res_scale(float res_scale);
void set_allow_clear_button(bool val) { allow_clear_button_ = val; }
auto GetTextWidth() -> float; auto GetTextWidth() -> float;
void OnLanguageChange() override; void OnLanguageChange() override;
void AdapterFinished(); void AdapterFinished();
@ -130,7 +131,8 @@ class TextWidget : public Widget {
bool selectable_{}; bool selectable_{};
bool clear_pressed_{}; bool clear_pressed_{};
bool clear_mouse_over_{}; bool clear_mouse_over_{};
bool do_clear_button_{true}; bool implicit_clear_button_{true};
bool allow_clear_button_{true};
int carat_position_{9999}; int carat_position_{9999};
int max_chars_{99999}; int max_chars_{99999};
float res_scale_{1.0f}; float res_scale_{1.0f};

View File

@ -165,11 +165,16 @@ int get_running_server_port_(const struct Context_* ctx,
cJSON* state_dict = cJSON_Parse(buf); cJSON* state_dict = cJSON_Parse(buf);
if (!state_dict) { if (!state_dict) {
// An un-parseable state file is not a recoverable error; go down hard.
// State files are written and then moved into place so we should never
// see something like a half-written file.
fprintf(stderr, fprintf(stderr,
"Error: pcommandbatch client %s_%d (pid %d): failed to parse state " "Fatal Error: pcommandbatch client %s_%d (pid %d):"
"value.\n", " failed to parse state file value of size %zu.\n",
ctx->instance_prefix, ctx->instance_num, ctx->pid); ctx->instance_prefix, ctx->instance_num, ctx->pid, amt);
return -1; fflush(stderr);
abort();
// return -1;
} }
// If results included output, print it. // If results included output, print it.

View File

@ -1,6 +1,6 @@
# Released under the MIT License. See LICENSE for details. # Released under the MIT License. See LICENSE for details.
# #
"""Utils for wrangling runs of the app. """Utils for wrangling running the app as part of a build.
Manages constructing or downloading it as well as running it. Manages constructing or downloading it as well as running it.
""" """
@ -105,6 +105,9 @@ def acquire_binary(assets: bool, purpose: str) -> str:
if os.environ.get('BA_APP_RUN_ENABLE_BUILDS') == '1': if os.environ.get('BA_APP_RUN_ENABLE_BUILDS') == '1':
# Going the build-it-ourselves route. # Going the build-it-ourselves route.
# Don't need any env mods for this path.
env = None
if os.environ.get('BA_APP_RUN_BUILD_HEADLESS') == '1': if os.environ.get('BA_APP_RUN_BUILD_HEADLESS') == '1':
# User has opted for headless builds. # User has opted for headless builds.
if assets: if assets:
@ -141,16 +144,23 @@ def acquire_binary(assets: bool, purpose: str) -> str:
binary_build_command = ['make', 'cmake-binary'] binary_build_command = ['make', 'cmake-binary']
binary_path = 'build/cmake/debug/staged/ballisticakit' binary_path = 'build/cmake/debug/staged/ballisticakit'
else: else:
# Ok; going with prefab headless stuff. # Ok; going with a downloaded prefab headless build.
# Let the user know how to use their own binaries instead. # By default, prefab build targets on WSL (Linux running on
# Windows) will give us Windows builds which won't work right
# here. Ask it for Linux builds instead.
env = dict(os.environ, BA_WSL_TARGETS_WINDOWS='0')
# Let the user know how to use their own built binaries instead
# if they prefer.
note = '\n' + textwrap.fill( note = '\n' + textwrap.fill(
'NOTE: You can set env-var BA_APP_RUN_ENABLE_BUILDS=1' f'NOTE: You can set env-var BA_APP_RUN_ENABLE_BUILDS=1'
f' to use locally-built binaries for {purpose}' f' to use locally-built binaries for {purpose} instead'
' instead of prefab ones. This will properly reflect any changes' f' of prefab ones. This will properly reflect any changes'
' you\'ve made to the C/C++ layer.', f' you\'ve made to the C/C++ layer.',
80, 80,
) )
if assets: if assets:
print( print(
f'{Clr.SMAG}Fetching prefab binary & assets for' f'{Clr.SMAG}Fetching prefab binary & assets for'
@ -160,6 +170,7 @@ def acquire_binary(assets: bool, purpose: str) -> str:
binary_path = ( binary_path = (
subprocess.run( subprocess.run(
['tools/pcommand', 'prefab_binary_path', 'server-release'], ['tools/pcommand', 'prefab_binary_path', 'server-release'],
env=env,
check=True, check=True,
capture_output=True, capture_output=True,
) )
@ -176,6 +187,7 @@ def acquire_binary(assets: bool, purpose: str) -> str:
binary_path = ( binary_path = (
subprocess.run( subprocess.run(
['tools/pcommand', 'prefab_binary_path', 'server-release'], ['tools/pcommand', 'prefab_binary_path', 'server-release'],
env=env,
check=True, check=True,
capture_output=True, capture_output=True,
) )
@ -184,7 +196,7 @@ def acquire_binary(assets: bool, purpose: str) -> str:
) )
binary_build_command = ['make', binary_path] binary_build_command = ['make', binary_path]
subprocess.run(binary_build_command, check=True) subprocess.run(binary_build_command, env=env, check=True)
if not os.path.exists(binary_path): if not os.path.exists(binary_path):
raise RuntimeError( raise RuntimeError(
f"Binary not found at expected path '{binary_path}'." f"Binary not found at expected path '{binary_path}'."

View File

@ -76,6 +76,87 @@ class PrefabTarget(Enum):
GUI_RELEASE = 'gui-release' GUI_RELEASE = 'gui-release'
SERVER_RELEASE = 'server-release' SERVER_RELEASE = 'server-release'
@property
def buildtype(self) -> str:
"""Return the build type for this target."""
return self.value.split('-')[0]
@property
def buildmode(self) -> str:
"""Return the build mode for this target."""
return self.value.split('-')[1]
class PrefabPlatform(Enum):
"""Distinct os/cpu-arch/etc. combos we support for prefab builds."""
MAC_X86_64 = 'mac_x86_64'
MAC_ARM64 = 'mac_arm64'
WINDOWS_X86 = 'windows_x86'
LINUX_X86_64 = 'linux_x86_64'
LINUX_ARM64 = 'linux_arm64'
@classmethod
def get_current(
cls, wsl_targets_windows: bool | None = None
) -> PrefabPlatform:
"""Get an identifier for the platform running this build.
Pass a bool `wsl_targets_windows` value to cause WSL to target
either native Windows (True) or Linux (False). If this value is
not passed, the env var BA_WSL_TARGETS_WINDOWS is used, and if that
is not set, the default is False (Linux builds).
Throws a RuntimeError on unsupported platforms.
"""
import platform
if wsl_targets_windows is None:
wsl_targets_windows = (
os.environ.get('BA_WSL_TARGETS_WINDOWS', '0') == '1'
)
system = platform.system()
machine = platform.machine()
if system == 'Darwin':
if machine == 'x86_64':
return cls.MAC_X86_64
if machine == 'arm64':
return cls.MAC_ARM64
raise RuntimeError(
f'PrefabPlatform.get_current:'
f' unsupported mac machine type:'
f' {machine}.'
)
if system == 'Linux':
# If it looks like we're in Windows Subsystem for Linux, we may
# want to operate on Windows versions.
if wsl_targets_windows:
if 'microsoft' in platform.uname().release.lower():
if machine == 'x86_64':
# Currently always targeting 32 bit for prefab stuff.
return cls.WINDOWS_X86
# TODO: add support for arm windows
raise RuntimeError(
f'make_prefab: unsupported win machine type: {machine}.'
)
if machine == 'x86_64':
return cls.LINUX_X86_64
if machine == 'aarch64':
return cls.LINUX_ARM64
raise RuntimeError(
f'PrefabPlatform.get_current:'
f' unsupported linux machine type:'
f' {machine}.'
)
raise RuntimeError(
f'PrefabPlatform.get_current:'
f' unrecognized platform:'
f' {platform.system()}.'
)
class LazyBuildCategory(Enum): class LazyBuildCategory(Enum):
"""Types of sources.""" """Types of sources."""
@ -296,49 +377,6 @@ def archive_old_builds(
) )
def get_current_prefab_platform(wsl_gives_windows: bool = True) -> str:
"""Get an identifier for the platform running this build.
Throws a RuntimeError on unsupported platforms.
"""
import platform
system = platform.system()
machine = platform.machine()
if system == 'Darwin':
if machine == 'x86_64':
return 'mac_x86_64'
if machine == 'arm64':
return 'mac_arm64'
raise RuntimeError(
f'make_prefab: unsupported mac machine type:' f' {machine}.'
)
if system == 'Linux':
# If it looks like we're in Windows Subsystem for Linux,
# we may want to operate on Windows versions.
if wsl_gives_windows:
if 'microsoft' in platform.uname().release.lower():
if machine == 'x86_64':
# Currently always targeting 32 bit for prefab stuff.
return 'windows_x86'
# TODO: add support for arm windows
raise RuntimeError(
f'make_prefab: unsupported win machine type: {machine}.'
)
if machine == 'x86_64':
return 'linux_x86_64'
if machine == 'aarch64':
return 'linux_arm64'
raise RuntimeError(
f'make_prefab: unsupported linux machine type:' f' {machine}.'
)
raise RuntimeError(
f'make_prefab: unrecognized platform:' f' {platform.system()}.'
)
def _vstr(nums: Sequence[int]) -> str: def _vstr(nums: Sequence[int]) -> str:
return '.'.join(str(i) for i in nums) return '.'.join(str(i) for i in nums)

View File

@ -487,34 +487,6 @@ def efrocache_get() -> None:
pcommand.clientprint(output) pcommand.clientprint(output)
def get_modern_make() -> None:
"""Print name of a modern make command."""
import platform
import subprocess
pcommand.disallow_in_batch()
# Mac gnu make is outdated (due to newer versions using GPL3 I believe).
# so let's return 'gmake' there which will point to homebrew make which
# should be up to date.
if platform.system() == 'Darwin':
if (
subprocess.run(
['which', 'gmake'], check=False, capture_output=True
).returncode
!= 0
):
print(
'WARNING: this requires gmake (mac system make is too old).'
" Install it with 'brew install make'",
file=sys.stderr,
flush=True,
)
print('gmake')
else:
print('make')
def warm_start_asset_build() -> None: def warm_start_asset_build() -> None:
"""Prep asset builds to run faster.""" """Prep asset builds to run faster."""
import os import os
@ -608,6 +580,24 @@ def checkenv() -> None:
batools.build.checkenv() batools.build.checkenv()
def prefab_platform() -> None:
"""Print the current prefab-platform value."""
from efro.error import CleanError
from batools.build import PrefabPlatform
# Platform determination uses env vars; won't work in batch.
pcommand.disallow_in_batch()
args = pcommand.get_args()
if len(args) != 0:
raise CleanError('No arguments expected.')
current = PrefabPlatform.get_current()
print(current.value, end='')
def ensure_prefab_platform() -> None: def ensure_prefab_platform() -> None:
"""Ensure we are running on a particular prefab platform. """Ensure we are running on a particular prefab platform.
@ -616,50 +606,90 @@ def ensure_prefab_platform() -> None:
the prefab platform may be Windows; not Linux. Also, a 64-bit the prefab platform may be Windows; not Linux. Also, a 64-bit
os may be targeting a 32-bit platform. os may be targeting a 32-bit platform.
""" """
import batools.build
from efro.error import CleanError from efro.error import CleanError
from batools.build import PrefabPlatform
# Platform determination uses env vars; won't work in batch.
pcommand.disallow_in_batch()
args = pcommand.get_args() args = pcommand.get_args()
if len(args) != 1: if len(args) != 1:
raise CleanError('Expected 1 platform name arg.') options = ', '.join(t.value for t in PrefabPlatform)
needed = args[0]
current = batools.build.get_current_prefab_platform()
if current != needed:
raise CleanError( raise CleanError(
f'Incorrect platform: we are {current}, this requires {needed}.' f'Expected 1 PrefabPlatform arg. Options are {options}.'
)
needed = PrefabPlatform(args[0])
current = PrefabPlatform.get_current()
if current is not needed:
raise CleanError(
f'Incorrect platform: we are {current.value},'
f' this requires {needed.value}.'
) )
def prefab_run_var() -> None: def prefab_run_var() -> None:
"""Print the current platform prefab run target var.""" """Print the current platform prefab run target var."""
import batools.build from batools.build import PrefabPlatform
# Platform determination uses env vars; won't work in batch.
pcommand.disallow_in_batch()
args = pcommand.get_args() args = pcommand.get_args()
if len(args) != 1: if len(args) != 1:
raise RuntimeError('Expected 1 arg.') raise RuntimeError('Expected 1 arg.')
base = args[0].replace('-', '_').upper() base = args[0].replace('-', '_').upper()
platform = batools.build.get_current_prefab_platform().upper() platform = PrefabPlatform.get_current().value.upper()
pcommand.clientprint(f'RUN_PREFAB_{platform}_{base}', end='') pcommand.clientprint(f'RUN_PREFAB_{platform}_{base}', end='')
def prefab_binary_path() -> None: def prefab_binary_path() -> None:
"""Print the current platform prefab binary path.""" """Print the path to the current prefab binary."""
import batools.build from typing import assert_never
from efro.error import CleanError
from batools.build import PrefabPlatform, PrefabTarget
# Platform determination uses env vars; won't work in batch.
pcommand.disallow_in_batch() pcommand.disallow_in_batch()
if len(sys.argv) != 3: if len(sys.argv) != 3:
raise RuntimeError('Expected 1 arg.') options = ', '.join(t.value for t in PrefabTarget)
buildtype, buildmode = sys.argv[2].split('-') raise CleanError(f'Expected 1 PrefabTarget arg. Options are {options}.')
platform = batools.build.get_current_prefab_platform()
if buildtype == 'gui': target = PrefabTarget(sys.argv[2])
binpath = 'ballisticakit'
elif buildtype == 'server': buildtype = target.buildtype
binpath = 'dist/ballisticakit_headless' buildmode = target.buildmode
platform = PrefabPlatform.get_current()
if platform is PrefabPlatform.WINDOWS_X86:
if buildtype == 'gui':
binpath = 'BallisticaKit.exe'
elif buildtype == 'server':
binpath = 'dist/BallisticaKitHeadless.exe'
else:
raise ValueError(f"Invalid buildtype '{buildtype}'.")
elif (
platform is PrefabPlatform.MAC_ARM64
or platform is PrefabPlatform.MAC_X86_64
or platform is PrefabPlatform.LINUX_ARM64
or platform is PrefabPlatform.LINUX_X86_64
):
if buildtype == 'gui':
binpath = 'ballisticakit'
elif buildtype == 'server':
binpath = 'dist/ballisticakit_headless'
else:
raise ValueError(f"Invalid buildtype '{buildtype}'.")
else: else:
raise ValueError(f"Invalid buildtype '{buildtype}'.") # Make sure we're covering all options.
assert_never(platform)
print( print(
f'build/prefab/full/{platform}_{buildtype}/{buildmode}/{binpath}', f'build/prefab/full/{platform.value}_{buildtype}/{buildmode}/{binpath}',
end='', end='',
) )
@ -667,20 +697,21 @@ def prefab_binary_path() -> None:
def make_prefab() -> None: def make_prefab() -> None:
"""Run prefab builds for the current platform.""" """Run prefab builds for the current platform."""
import subprocess import subprocess
import batools.build from batools.build import PrefabPlatform, PrefabTarget
# Platform determination uses env vars; won't work in batch.
pcommand.disallow_in_batch() pcommand.disallow_in_batch()
if len(sys.argv) != 3: if len(sys.argv) != 3:
raise RuntimeError('Expected one argument') raise RuntimeError('Expected one argument')
target = batools.build.PrefabTarget(sys.argv[2]) targetstr = PrefabTarget(sys.argv[2]).value
platform = batools.build.get_current_prefab_platform() platformstr = PrefabPlatform.get_current().value
# We use dashes instead of underscores in target names. # We use dashes instead of underscores in target names.
platform = platform.replace('_', '-') platformstr = platformstr.replace('_', '-')
try: try:
subprocess.run( subprocess.run(
['make', f'prefab-{platform}-{target.value}-build'], check=True ['make', f'prefab-{platformstr}-{targetstr}-build'], check=True
) )
except (Exception, KeyboardInterrupt) as exc: except (Exception, KeyboardInterrupt) as exc:
if str(exc): if str(exc):
@ -697,6 +728,7 @@ def lazybuild() -> None:
# This command is not a good candidate for batch since it can be # This command is not a good candidate for batch since it can be
# long running and prints various stuff throughout the process. # long running and prints various stuff throughout the process.
pcommand.disallow_in_batch() pcommand.disallow_in_batch()
args = pcommand.get_args() args = pcommand.get_args()
if len(args) < 3: if len(args) < 3:

View File

@ -204,7 +204,7 @@ def win_ci_install_prereqs() -> None:
# We'll need to pull a handful of things out of efrocache for the # We'll need to pull a handful of things out of efrocache for the
# build to succeed. Normally this would happen through our Makefile # build to succeed. Normally this would happen through our Makefile
# targets but we can't use them under raw window so we need to just # targets but we can't use them under raw Windows so we need to just
# hard-code whatever we need here. # hard-code whatever we need here.
lib_dbg_win32 = 'build/prefab/lib/windows/Debug_Win32' lib_dbg_win32 = 'build/prefab/lib/windows/Debug_Win32'
needed_targets: set[str] = { needed_targets: set[str] = {
@ -256,11 +256,11 @@ def win_ci_binary_build() -> None:
def update_cmake_prefab_lib() -> None: def update_cmake_prefab_lib() -> None:
"""Update prefab internal libs for builds.""" """Update prefab internal libs; run as part of a build."""
import subprocess import subprocess
import os import os
from efro.error import CleanError from efro.error import CleanError
import batools.build from batools.build import PrefabPlatform
pcommand.disallow_in_batch() pcommand.disallow_in_batch()
@ -275,14 +275,18 @@ def update_cmake_prefab_lib() -> None:
raise CleanError(f'Invalid buildtype: {buildtype}') raise CleanError(f'Invalid buildtype: {buildtype}')
if mode not in {'debug', 'release'}: if mode not in {'debug', 'release'}:
raise CleanError(f'Invalid mode: {mode}') raise CleanError(f'Invalid mode: {mode}')
platform = batools.build.get_current_prefab_platform(
wsl_gives_windows=False
)
suffix = '_server' if buildtype == 'server' else '_gui'
target = f'build/prefab/lib/{platform}{suffix}/{mode}/libballisticaplus.a'
# Build the target and then copy it to dst if it doesn't exist there yet # Our 'cmake' build targets use the Linux side of WSL; not native
# or the existing one is older than our target. # Windows.
platform = PrefabPlatform.get_current(wsl_targets_windows=False)
suffix = '_server' if buildtype == 'server' else '_gui'
target = (
f'build/prefab/lib/{platform.value}{suffix}/{mode}/libballisticaplus.a'
)
# Build the target and then copy it to dst if it doesn't exist there
# yet or the existing one is older than our target.
subprocess.run(['make', target], check=True) subprocess.run(['make', target], check=True)
libdir = os.path.join(builddir, 'prefablib') libdir = os.path.join(builddir, 'prefablib')
@ -431,7 +435,7 @@ def wsl_build_check_win_drive() -> None:
!= 0 != 0
): ):
raise CleanError( raise CleanError(
'wslpath not found; you must run this from a WSL environment' "'wslpath' not found. This does not seem to be a WSL environment."
) )
if os.environ.get('WSL_BUILD_CHECK_WIN_DRIVE_IGNORE') == '1': if os.environ.get('WSL_BUILD_CHECK_WIN_DRIVE_IGNORE') == '1':
@ -448,9 +452,12 @@ def wsl_build_check_win_drive() -> None:
.strip() .strip()
) )
# If we're sitting under the linux filesystem, our path # If we're sitting under the linux filesystem, our path will start
# will start with \\wsl$; fail in that case and explain why. # with '\\wsl$' or '\\wsl.localhost' or '\\wsl\'; fail in that case
if not path.startswith('\\\\wsl$'): # and explain why.
if not any(
path.startswith(x) for x in ['\\\\wsl$', '\\\\wsl.', '\\\\wsl\\']
):
return return
def _wrap(txt: str) -> str: def _wrap(txt: str) -> str:
@ -475,7 +482,7 @@ def wsl_build_check_win_drive() -> None:
'Note that WSL2 filesystem performance' 'Note that WSL2 filesystem performance'
' is poor when accessing' ' is poor when accessing'
' native Windows drives, so if Visual Studio builds are not' ' native Windows drives, so if Visual Studio builds are not'
' needed it may be best to keep things' ' needed it may be best to keep things here'
' on the Linux filesystem.' ' on the Linux filesystem.'
' This behavior may differ under WSL1 (untested).' ' This behavior may differ under WSL1 (untested).'
), ),
@ -540,3 +547,31 @@ def wsl_path_to_win() -> None:
if escape: if escape:
out = out.replace('\\', '\\\\') out = out.replace('\\', '\\\\')
print(out, end='') print(out, end='')
def get_modern_make() -> None:
"""Print name of a modern make command."""
import platform
import subprocess
pcommand.disallow_in_batch()
# Mac gnu make is outdated (due to newer versions using GPL3 I believe).
# so let's return 'gmake' there which will point to homebrew make which
# should be up to date.
if platform.system() == 'Darwin':
if (
subprocess.run(
['which', 'gmake'], check=False, capture_output=True
).returncode
!= 0
):
print(
'WARNING: this requires gmake (mac system make is too old).'
" Install it with 'brew install make'",
file=sys.stderr,
flush=True,
)
print('gmake')
else:
print('make')

View File

@ -11,6 +11,7 @@ import subprocess
from functools import partial from functools import partial
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from efro.terminal import Clr
from efrotools import PYVER, extract_arg, extract_flag from efrotools import PYVER, extract_arg, extract_flag
if TYPE_CHECKING: if TYPE_CHECKING:
@ -39,6 +40,7 @@ class AssetStager:
def __init__(self, projroot: str) -> None: def __init__(self, projroot: str) -> None:
self.projroot = projroot self.projroot = projroot
self.desc = 'unknown'
# We always calc src relative to this script. # We always calc src relative to this script.
self.src = f'{self.projroot}/build/assets' self.src = f'{self.projroot}/build/assets'
self.dst: str | None = None self.dst: str | None = None
@ -71,6 +73,12 @@ class AssetStager:
"""Do the thing.""" """Do the thing."""
self._parse_args(args) self._parse_args(args)
print(
f'{Clr.BLU}Staging for {Clr.MAG}{Clr.BLD}{self.desc}{Clr.RST}'
f'{Clr.BLU} at {Clr.MAG}{Clr.BLD}{self.dst}'
f'{Clr.RST}{Clr.BLU}...{Clr.RST}'
)
# Ok, now for every top level dir in src, come up with a nice single # Ok, now for every top level dir in src, come up with a nice single
# command to sync the needed subset of it to dst. # command to sync the needed subset of it to dst.
@ -140,22 +148,27 @@ class AssetStager:
) )
if platform_arg == '-android': if platform_arg == '-android':
self.desc = 'android'
self._parse_android_args(args) self._parse_android_args(args)
elif platform_arg.startswith('-win'): elif platform_arg.startswith('-win'):
self.desc = 'windows'
self._parse_win_args(platform_arg, args) self._parse_win_args(platform_arg, args)
elif platform_arg == '-cmake': elif platform_arg == '-cmake':
self.desc = 'cmake'
self.dst = args[-1] self.dst = args[-1]
self.tex_suffix = '.dds' self.tex_suffix = '.dds'
# Link/copy in a binary *if* builddir is provided. # Link/copy in a binary *if* builddir is provided.
self.include_binary_executable = self.builddir is not None self.include_binary_executable = self.builddir is not None
self.executable_name = 'ballisticakit' self.executable_name = 'ballisticakit'
elif platform_arg == '-cmakemodular': elif platform_arg == '-cmakemodular':
self.desc = 'cmake modular'
self.dst = args[-1] self.dst = args[-1]
self.tex_suffix = '.dds' self.tex_suffix = '.dds'
self.include_python_dylib = True self.include_python_dylib = True
self.include_shell_executable = True self.include_shell_executable = True
self.executable_name = 'ballisticakit' self.executable_name = 'ballisticakit'
elif platform_arg == '-cmakeserver': elif platform_arg == '-cmakeserver':
self.desc = 'cmake server'
self.dst = os.path.join(args[-1], 'dist') self.dst = os.path.join(args[-1], 'dist')
self.serverdst = args[-1] self.serverdst = args[-1]
self.include_textures = False self.include_textures = False
@ -165,6 +178,7 @@ class AssetStager:
self.include_binary_executable = self.builddir is not None self.include_binary_executable = self.builddir is not None
self.executable_name = 'ballisticakit_headless' self.executable_name = 'ballisticakit_headless'
elif platform_arg == '-cmakemodularserver': elif platform_arg == '-cmakemodularserver':
self.desc = 'cmake modular server'
self.dst = os.path.join(args[-1], 'dist') self.dst = os.path.join(args[-1], 'dist')
self.serverdst = args[-1] self.serverdst = args[-1]
self.include_textures = False self.include_textures = False
@ -175,6 +189,7 @@ class AssetStager:
self.executable_name = 'ballisticakit_headless' self.executable_name = 'ballisticakit_headless'
elif platform_arg == '-xcode-mac': elif platform_arg == '-xcode-mac':
self.desc = 'xcode mac'
self.src = os.environ['SOURCE_ROOT'] + '/../build/assets' self.src = os.environ['SOURCE_ROOT'] + '/../build/assets'
self.dst = ( self.dst = (
os.environ['TARGET_BUILD_DIR'] os.environ['TARGET_BUILD_DIR']
@ -184,17 +199,8 @@ class AssetStager:
self.include_pylib = True self.include_pylib = True
self.pylib_src_name = 'pylib-apple' self.pylib_src_name = 'pylib-apple'
self.tex_suffix = '.dds' self.tex_suffix = '.dds'
elif platform_arg == '-xcode-mac-old':
self.src = os.environ['SOURCE_ROOT'] + '/build/assets'
self.dst = (
os.environ['TARGET_BUILD_DIR']
+ '/'
+ os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']
)
self.include_pylib = True
self.pylib_src_name = 'pylib-apple'
self.tex_suffix = '.dds'
elif platform_arg == '-xcode-ios': elif platform_arg == '-xcode-ios':
self.desc = 'xcode ios'
self.src = os.environ['SOURCE_ROOT'] + '/build/assets' self.src = os.environ['SOURCE_ROOT'] + '/build/assets'
self.dst = ( self.dst = (
os.environ['TARGET_BUILD_DIR'] os.environ['TARGET_BUILD_DIR']

View File

@ -96,13 +96,13 @@ from batools.pcommands import (
upper, upper,
efrocache_update, efrocache_update,
efrocache_get, efrocache_get,
get_modern_make,
warm_start_asset_build, warm_start_asset_build,
gen_docs_pdoc, gen_docs_pdoc,
gen_docs_sphinx, gen_docs_sphinx,
list_pip_reqs, list_pip_reqs,
install_pip_reqs, install_pip_reqs,
checkenv, checkenv,
prefab_platform,
ensure_prefab_platform, ensure_prefab_platform,
prefab_run_var, prefab_run_var,
prefab_binary_path, prefab_binary_path,
@ -135,6 +135,7 @@ from batools.pcommands2 import (
tests_warm_start, tests_warm_start,
wsl_path_to_win, wsl_path_to_win,
wsl_build_check_win_drive, wsl_build_check_win_drive,
get_modern_make,
) )
# pylint: enable=unused-import # pylint: enable=unused-import