diff --git a/.efrocachemap b/.efrocachemap index cfb82614..9cce1353 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,42 +421,42 @@ "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", - "build/assets/ba_data/data/langdata.json": "5273cf3bfe2d25d70395690bf3c21825", - "build/assets/ba_data/data/languages/arabic.json": "0db32e21b6d5337ccca478381744aa88", + "build/assets/ba_data/data/langdata.json": "8409781047f46ca6627eacdfc0b4d3d3", + "build/assets/ba_data/data/languages/arabic.json": "2c2915e10124bb8f69206da9c608d57c", "build/assets/ba_data/data/languages/belarussian.json": "09954e550d13d3d9cb5a635a1d32a151", - "build/assets/ba_data/data/languages/chinese.json": "1360ffde06828b63ce4fe956c3c3cd1d", + "build/assets/ba_data/data/languages/chinese.json": "bb51b5aa614830c561e8fe2542a9ab8a", "build/assets/ba_data/data/languages/chinesetraditional.json": "319565f8a15667488f48dbce59278e39", "build/assets/ba_data/data/languages/croatian.json": "e671b9d0c012be1a30f9c15eb1b81860", - "build/assets/ba_data/data/languages/czech.json": "7171420af6d662e3a47b64576850a384", + "build/assets/ba_data/data/languages/czech.json": "15be4fd59895135bad0265f79b362d5b", "build/assets/ba_data/data/languages/danish.json": "8e57db30c5250df2abff14a822f83ea7", "build/assets/ba_data/data/languages/dutch.json": "b0900d572c9141897d53d6574c471343", - "build/assets/ba_data/data/languages/english.json": "28a1c17925aba4f4f908732e5e5cb266", + "build/assets/ba_data/data/languages/english.json": "0a95fdbc1564161bc7c8b419b0c03651", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", - "build/assets/ba_data/data/languages/filipino.json": "fe3f1efcb47efaa23524300d21728933", - "build/assets/ba_data/data/languages/french.json": "cc8ac601f5443dd539893728db983f5c", + "build/assets/ba_data/data/languages/filipino.json": "5226bf247fa1c8f4406360644f3fa15f", + "build/assets/ba_data/data/languages/french.json": "917e4174d6f0eb7f00c27fd79cfbb924", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", - "build/assets/ba_data/data/languages/gibberish.json": "ab9571486f703b8d57eab61dbf1d54d8", + "build/assets/ba_data/data/languages/gibberish.json": "5533873020e51186beb2f209adbbfb08", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/hindi.json": "90f54663e15d85a163f1848a8e9d8d07", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", "build/assets/ba_data/data/languages/indonesian.json": "9103845242b572aa8ba48e24f81ddb68", - "build/assets/ba_data/data/languages/italian.json": "f550810b6866ea9bcf1985b7228f8cff", + "build/assets/ba_data/data/languages/italian.json": "55c350f8f5039802138ffc1013f14ed3", "build/assets/ba_data/data/languages/korean.json": "4e3524327a0174250aff5e1ef4c0c597", - "build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38", - "build/assets/ba_data/data/languages/persian.json": "1a4c74ad9089cd746ad6fda4186c2220", + "build/assets/ba_data/data/languages/malay.json": "f6ce0426d03a62612e3e436ed5d1be1f", + "build/assets/ba_data/data/languages/persian.json": "07eddcf92d3dcc7a745ea74e2b0007c8", "build/assets/ba_data/data/languages/polish.json": "9d22c6643c097c4cb268d0d6b6319cd4", - "build/assets/ba_data/data/languages/portuguese.json": "b52164747c6308fc9d054eb6c0ff3c54", + "build/assets/ba_data/data/languages/portuguese.json": "a48df1d11a088a1a2e6e3f66627444be", "build/assets/ba_data/data/languages/romanian.json": "b3e46efd6f869dbd78014570e037c290", - "build/assets/ba_data/data/languages/russian.json": "30d5f3d2415088e1fb6558fcd6ccfa98", + "build/assets/ba_data/data/languages/russian.json": "0590f49889616b5279be569dea926e17", "build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69", "build/assets/ba_data/data/languages/slovak.json": "c00fb27cf982ffad5a4370ad3b16bd21", - "build/assets/ba_data/data/languages/spanish.json": "e3e9ac8f96f52302a480c7e955aed71f", + "build/assets/ba_data/data/languages/spanish.json": "b2edb923fdca973a16f0efb1acc26a97", "build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac", "build/assets/ba_data/data/languages/tamil.json": "b9fcc523639f55e05c7f4e7914f3321a", "build/assets/ba_data/data/languages/thai.json": "1d665629361f302693dead39de8fa945", - "build/assets/ba_data/data/languages/turkish.json": "2be25c89ca754341f27750e0d595f31e", - "build/assets/ba_data/data/languages/ukrainian.json": "b54a38e93deebafa5706ba2d1f626892", - "build/assets/ba_data/data/languages/venetian.json": "f896fc3df13a42f1bef8813ca80b1a09", + "build/assets/ba_data/data/languages/turkish.json": "db71f3776072b7a15ef37b1bb1245795", + "build/assets/ba_data/data/languages/ukrainian.json": "3d75d21205c82db34fb1a1b014592747", + "build/assets/ba_data/data/languages/venetian.json": "035034e0b4de696a41bf753ab4d0e194", "build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba", "build/assets/ba_data/data/maps/big_g.json": "1dd301d490643088a435ce75df971054", "build/assets/ba_data/data/maps/bridgit.json": "6aea74805f4880cc11237c5734a24422", @@ -3521,6 +3521,7 @@ "build/assets/pylib-apple/zoneinfo/_common.py": "5b52bdac4156dcbac96743fa99468bf2", "build/assets/pylib-apple/zoneinfo/_tzpath.py": "f021e91036bd38590f2ce643b59dc881", "build/assets/pylib-apple/zoneinfo/_zoneinfo.py": "d000d61aa8998d0076c37f96cf40ca69", + "build/assets/sphinx/template/conf.py": "1d00917de95f8f62f372caa1146ff602", "build/assets/windows/Win32/DLLs/_asyncio.pyd": "36024ca5f0f257dd4edfe1a3e92c1a07", "build/assets/windows/Win32/DLLs/_asyncio_d.pyd": "a809fe3d7f3b6931e5f127821d0d30b6", "build/assets/windows/Win32/DLLs/_bz2.pyd": "cf535d3d0a020f0ae5ff20336a56ba3b", @@ -4060,50 +4061,50 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "a7161a4100172e2bb42b838a9851c353", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "9a63e694db2ed7536374c58a45ce65d3", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9668ef38ddc59fadf323cf460c8b692c", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "8f58837d238dba248ae2e23e20bc3f06", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "f8a6e20f3fffd198494adfba4e884588", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "255205c95d519a594041fc239e435883", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "36facf256b69a8c0037370e23c82470d", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "d78aef348baf274f476ce9e344b80122", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f1b9732cc7e7728dcedc39a55d9afea2", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "8cfc0e04c10a315cce91dae041dfc3ff", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "a9fec1930c851f8ed743b08669df2d75", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "a6fcaa9d7eb10412787e4416f3536bb9", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "a39230df064404a3b1dd18a644f2f6d6", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "04e971f62a000383a13eb021e30afa7b", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "a93fe4f0cfb3c2c9061df049068230ac", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0f08a84bb09589991faaca9250171e3c", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "12c079e62d0125b8a24b16e418405ba9", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "eb0d76fd3be03082572b0d835df05252", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "e4268ef0b50e94747081ee83666d80ab", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "f4646fecfed11f5e2b2ee5c892b2940a", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "ee36a39fd0f524989cb68930c89c8868", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "dbed9145e5db116d92aa47cb9e98da39", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "ee36a39fd0f524989cb68930c89c8868", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "dbed9145e5db116d92aa47cb9e98da39", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "dc078f11a4e93062adc7d210fd4f08fb", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "a74bea3380d0fb39f78ac7b7598c1a72", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "dc078f11a4e93062adc7d210fd4f08fb", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "a74bea3380d0fb39f78ac7b7598c1a72", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "b397e020f33132c4dd2280cb1222cd14", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "ff0cb4db976707d25bd401bce80a4882", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "b397e020f33132c4dd2280cb1222cd14", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "ff0cb4db976707d25bd401bce80a4882", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "c464accef921df1325459bdd10c59b84", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "0896e849885cef50bcf33ce863efa7d2", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "e53c808357cc0a2f0da7b870be147083", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "0896e849885cef50bcf33ce863efa7d2", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "f53601899c23c90c2b7e65836c805d8e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "f31b348a7612e5fa3a968f3cc81cefcd", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "b8339779a2571b169f9d63c11aa7dfa3", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "511bc23565e830778d5ff183a201579d", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "b02faf2aa2df1de233a0549295e6b0ed", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "2e07aaa6d445caf3b33d79dc40bd2475", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "00f50fb4a3a9bbecd1b1188b78abae4b", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "88fb67cb3f3752f0b0db1d583f90490d", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "db921cf43e8ebf733712fb5bbc673f66", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "4be0f3a7a88da423847863af41ac9c63", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "7c92d738e7cc724de2ca31cb876224e6", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "c2f69ed83f77b602e2a2b2b1c1c78cc6", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b1c766d4ce567f965c53ff2a4c5c85f4", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "86ebbd9111f8a0fe7905cef7aba1f6db", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "8182f4e00ad579eb4c7be5ec1ddca8cb", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "3d9e0e7ad8706133e61fb7f7127c3ff5", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "20373ee90f8987bed980143d5377ae44", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "99d7d247a422eaa46737e3232408e879", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "079c4fd0b6f8aa50510064704466904b", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "216efc77915b75f39f0f15c2806bfbb9", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "204320756307e1833b284c3180e70319", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "3e9e4e1761fd763eb584598fc0a3ad0a", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b8f587f21f39f35072d6c83116c9ae96", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0c92e386ab7406da6a719131321bf592", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "ce48b60be52023e1942cb493bb2f58fb", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d53ee4e8eed3e1a218db2f927a62c353", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "6597b00a07975230cb3f5b0fa19e0ed4", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "0ff41b8dc440c0490e9ae3bc22c3d201", + "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_server/debug/libballisticaplus.a": "d9865523059d8cf11b2bef4b9da9a8c9", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "56d6440f62c271c4ce9ef520400395a3", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "390a90cf4af1c55662c61ec19f9481bb", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "e55895a55cc40f79be9e2e8095e8adf2", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "390a90cf4af1c55662c61ec19f9481bb", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "e55895a55cc40f79be9e2e8095e8adf2", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "9846a6a3dd3685417fe834b91be8ac74", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "68087f1bac1513e92cabdb59c637e759", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "9846a6a3dd3685417fe834b91be8ac74", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "68087f1bac1513e92cabdb59c637e759", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "72a7370f23c76ed8018999b78d88a545", + "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/release/libballisticaplus.a": "c2cf0dc227e41a826c913d12e117c316", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "b04c0e9f0753d99707dc0091f838c724", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "526a6da71fee4e782a5e881cfc747d53", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "9148df22e55a23d1fc5c0674f476af3e", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "a46936b72035132ddde1dc166b507d7b", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "33595ffc0c36f2280a9215b48284c322", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "432bf79a12258e353a498399d248775f", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "6cd33778d0c471e79b252696a22d69ba", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "a735a0b19249050d2b6b428be6274c37", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index f88e4998..acb36a76 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -9,9 +9,9 @@ jobs: make_linux_x86_64_gui_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -29,9 +29,9 @@ jobs: make_linux_x86_64_server_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -49,9 +49,9 @@ jobs: make_linux_arm64_gui_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -69,9 +69,9 @@ jobs: make_linux_arm64_server_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -89,9 +89,9 @@ jobs: make_mac_x86_64_gui_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -109,9 +109,9 @@ jobs: make_mac_x86_64_server_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -129,9 +129,9 @@ jobs: make_mac_arm64_gui_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -149,9 +149,9 @@ jobs: make_mac_arm64_server_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -169,9 +169,9 @@ jobs: make_windows_x86_gui_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -189,9 +189,9 @@ jobs: make_windows_x86_server_debug_build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -206,3 +206,23 @@ jobs: with: name: windows_x86_server_(debug) path: build/prefab/full/windows_x86_server + make_sphinx_docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + # Remove this once we upgrade to 3.12. + - name: Install typing_extensions (temp) + run: python3.11 -m pip install typing_extensions + - name: Install pip requirements + run: tools/pcommand install_pip_reqs + - name: Make the build + run: make docs-sphinx + - name: Upload the build + uses: actions/upload-artifact@v3 + with: + name: sphinx_html_docs + path: build/sphinx \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70bb196e..5b937d59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,9 +16,9 @@ jobs: check_linux: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -33,9 +33,9 @@ jobs: build_and_test_linux: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -54,9 +54,9 @@ jobs: spinoff_test_linux: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -75,9 +75,9 @@ jobs: feature_set_copy_test_linux: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' # Remove this once we upgrade to 3.12. @@ -102,9 +102,9 @@ jobs: build_and_test_windows: runs-on: windows-2022 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md index 6676a4ae..b8019ec3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.33 (build 21770, api 8, 2024-03-01) +### 1.7.33 (build 21778, api 8, 2024-03-13) - Stress test input-devices are now a bit smarter; they won't press any buttons while UIs are up (this could cause lots of chaos if it happened). - Added a 'Show Demos When Idle' option in advanced settings. If enabled, the @@ -21,6 +21,9 @@ catch problems where a base class changes or removes a method and child classes forget to adapt to the change. - Added a reset button in the input mapping menu. (Thanks Temp!) +- Respawn icons now have dotted steps showing decimal progress to assist + players on calculating when they are gonna respawn. (Thanks 3alTemp!) +- Replays now have rewind/fast-forward buttons!! (Thanks Dliwk, vishal332008!) - Custom spaz "curse_time" values now work properly. (Thanks Temp!) - Implemented `efro.dataclassio.IOMultiType` which will make my life a lot easier. @@ -30,7 +33,17 @@ brostos!). - Fixes a bug where Meteor Shower could make the game-end bell sound twice (Thanks 3alTemp!). - +- Leaving the game or dying while touching your team's flag will no longer + recover & return it indefinitely in a teams game of Capture the Flag. (Thanks + 3alTemp!) +- Added a server config setting for max players (not max clients) (Thanks + EraOSBeta!) +- Added a UI for customizing Series Length in Teams and Points-to-Win in FFA + (Thanks EraOSBeta!) +- Sphinx based Python documentation generation is now wired up (Thanks + Loup-Garou911XD!) +- Renaming & overwriting existing profiles is no longer possible (Thanks Temp!) + ### 1.7.32 (build 21741, api 8, 2023-12-20) - 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!) @@ -73,7 +86,7 @@ intended. Now, however, such commands get scheduled to a current 'ui-operation' and then run *almost* immediately, which should prevent such situations. Please holler if you run into any UI weirdness at this point. - + ### 1.7.30 (build 21697, api 8, 2023-12-08) - Continued work on the big 1.7.28 update. - Got the Android version back up and running. There's been lots of cleanup and @@ -350,7 +363,7 @@ - Added a 'glow_type' arg to `bauiv1.textwidget()` to adjust the glow used when the text is selected. The default is 'gradient' but there is now a 'uniform' option which may look better in some circumstances. - + ### 1.7.27 (build 21282, api 8, 2023-08-30) - Fixed a rare crash that could occur if the app shuts down while a background @@ -471,7 +484,7 @@ Visual Studio Code (and potentially other editors), so am seeing if it is worth officially supporting in addition to or as a replacement for Mypy. See `tools/pcommand pyright` - + ### 1.7.24 (build 21199, api 8, 2023-07-27) - Fixed an issue where respawn icons could disappear in epic mode (Thanks for @@ -526,7 +539,7 @@ can be useful for core engine code to directly and clearly point out problems that cannot be recovered from (Exceptions in such cases can tend to be 'handled' which leads to a broken or crashing app). - + ### 1.7.23 (build 21178, api 8, 2023-07-19) - Network security improvements. (Thanks Dliwk!) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 01fb069c..dd21a689 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -37,12 +37,12 @@ - Added feature ### Vishal332008 -- Bug Fixer +- QoL and Bug Fixer - Modder ### Era0S - Community Suggestions Implementer -- Bug Fixer +- QoL and Bug Fixer - Modder ### VinniTR @@ -51,8 +51,16 @@ ### Rikko - Created the original "reject_recently_left_players" plugin +### SoK +- Modder +- BSE Heartbeat mechanic port + ### Temp (3alTemp) +- Original idea for customizable series length on GUI builds - Modder & Bug Fixer ### brostos - Added support for joining using ipv6 address + +### Loup Garou +- Added sphinx documentation generation \ No newline at end of file diff --git a/Makefile b/Makefile index ddd594fc..e43ffd49 100644 --- a/Makefile +++ b/Makefile @@ -183,6 +183,14 @@ docs: docs-pdoc: @$(PCOMMAND) gen_docs_pdoc +docs-sphinx: + $(MAKE) dummymodules + @$(PCOMMAND) gen_docs_sphinx + +docs-sphinx-clean: + rm -rf .cache/sphinx + rm -rf build/sphinx + pcommandbatch_speed_test: prereqs @$(PCOMMAND) pcommandbatch_speed_test $(PCOMMANDBATCH) diff --git a/config/spinoffconfig.py b/config/spinoffconfig.py index 26e97c36..6844d1c5 100644 --- a/config/spinoffconfig.py +++ b/config/spinoffconfig.py @@ -278,6 +278,7 @@ ctx.filter_file_extensions = { '.xcsettings', '.xcstrings', '.filters', + '.rst', } # ELSE files with these extensions will NOT be filtered. diff --git a/src/assets/.asset_manifest_private.json b/src/assets/.asset_manifest_private.json index 6e46c89e..e7849bc5 100644 --- a/src/assets/.asset_manifest_private.json +++ b/src/assets/.asset_manifest_private.json @@ -4487,6 +4487,8 @@ "pylib-apple/zoneinfo/_common.py", "pylib-apple/zoneinfo/_tzpath.py", "pylib-apple/zoneinfo/_zoneinfo.py", + "sphinx/template/__pycache__/conf.cpython-311.opt-1.pyc", + "sphinx/template/conf.py", "windows/Win32/DLLs/_asyncio.pyd", "windows/Win32/DLLs/_asyncio_d.pyd", "windows/Win32/DLLs/_bz2.pyd", diff --git a/src/assets/.asset_manifest_public.json b/src/assets/.asset_manifest_public.json index 80f06984..575edf24 100644 --- a/src/assets/.asset_manifest_public.json +++ b/src/assets/.asset_manifest_public.json @@ -513,6 +513,7 @@ "ba_data/python/bauiv1lib/settings/__pycache__/gamepadselect.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/graphics.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/keyboard.cpython-311.opt-1.pyc", + "ba_data/python/bauiv1lib/settings/__pycache__/moddingtools.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/nettesting.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/plugins.cpython-311.opt-1.pyc", "ba_data/python/bauiv1lib/settings/__pycache__/pluginsettings.cpython-311.opt-1.pyc", @@ -529,6 +530,7 @@ "ba_data/python/bauiv1lib/settings/gamepadselect.py", "ba_data/python/bauiv1lib/settings/graphics.py", "ba_data/python/bauiv1lib/settings/keyboard.py", + "ba_data/python/bauiv1lib/settings/moddingtools.py", "ba_data/python/bauiv1lib/settings/nettesting.py", "ba_data/python/bauiv1lib/settings/plugins.py", "ba_data/python/bauiv1lib/settings/pluginsettings.py", diff --git a/src/assets/Makefile b/src/assets/Makefile index a92c9ad7..51abad50 100644 --- a/src/assets/Makefile +++ b/src/assets/Makefile @@ -406,6 +406,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/gamepadselect.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/graphics.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/keyboard.py \ + $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/moddingtools.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/nettesting.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/plugins.py \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/pluginsettings.py \ @@ -681,6 +682,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/gamepadselect.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/graphics.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/keyboard.cpython-311.opt-1.pyc \ + $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/moddingtools.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/nettesting.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/plugins.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python/bauiv1lib/settings/__pycache__/pluginsettings.cpython-311.opt-1.pyc \ @@ -2742,7 +2744,8 @@ SCRIPT_TARGETS_PY_PRIVATE_COMMON = \ $(BUILD_DIR)/ba_data/python-site-packages/yaml/resolver.py \ $(BUILD_DIR)/ba_data/python-site-packages/yaml/scanner.py \ $(BUILD_DIR)/ba_data/python-site-packages/yaml/serializer.py \ - $(BUILD_DIR)/ba_data/python-site-packages/yaml/tokens.py + $(BUILD_DIR)/ba_data/python-site-packages/yaml/tokens.py \ + $(BUILD_DIR)/sphinx/template/conf.py SCRIPT_TARGETS_PYC_PRIVATE_COMMON = \ $(BUILD_DIR)/ba_data/python-site-packages/_yaml/__pycache__/__init__.cpython-311.opt-1.pyc \ @@ -2766,7 +2769,8 @@ SCRIPT_TARGETS_PYC_PRIVATE_COMMON = \ $(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/resolver.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/scanner.cpython-311.opt-1.pyc \ $(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/serializer.cpython-311.opt-1.pyc \ - $(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/tokens.cpython-311.opt-1.pyc + $(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/tokens.cpython-311.opt-1.pyc \ + $(BUILD_DIR)/sphinx/template/__pycache__/conf.cpython-311.opt-1.pyc # Rule to copy src asset scripts to dst. # (and make non-writable so I'm less likely to accidentally edit them there) diff --git a/src/assets/ba_data/python/babase/modutils.py b/src/assets/ba_data/python/babase/modutils.py index 7780d1f6..08a58c71 100644 --- a/src/assets/ba_data/python/babase/modutils.py +++ b/src/assets/ba_data/python/babase/modutils.py @@ -136,7 +136,12 @@ def create_user_system_scripts() -> None: path = f'{env.python_directory_user}/sys/{env.version}' pathtmp = path + '_tmp' if os.path.exists(path): - shutil.rmtree(path) + print('Delete Existing User Scripts first!') + _babase.screenmessage( + 'Delete Existing User Scripts first!', + color=(1, 0, 0), + ) + return if os.path.exists(pathtmp): shutil.rmtree(pathtmp) @@ -159,6 +164,7 @@ def create_user_system_scripts() -> None: f"'\nRestart {_babase.appname()} to use them." f' (use babase.quit() to exit the game)' ) + _babase.screenmessage('Created User System Scripts', color=(0, 1, 0)) if app.classic is not None and app.classic.platform == 'android': print( 'Note: the new files may not be visible via ' @@ -183,8 +189,14 @@ def delete_user_system_scripts() -> None: f'Restart {_babase.appname()} to use internal' f' scripts. (use babase.quit() to exit the game)' ) + _babase.screenmessage('Deleted User System Scripts', color=(0, 1, 0)) + _babase.screenmessage( + f'Restart {_babase.appname()} to take effect.', + color=(0, 1, 0), + ) else: print(f"User system scripts not found at '{path}'.") + _babase.screenmessage('User Scripts Not Found', color=(1, 0, 0)) # If the sys path is empty, kill it. dpath = env.python_directory_user + '/sys' diff --git a/src/assets/ba_data/python/baclassic/_accountv1.py b/src/assets/ba_data/python/baclassic/_accountv1.py index e732f135..d0df1f64 100644 --- a/src/assets/ba_data/python/baclassic/_accountv1.py +++ b/src/assets/ba_data/python/baclassic/_accountv1.py @@ -152,9 +152,9 @@ class AccountV1Subsystem: """(internal)""" for entry in info: - cache_entry = self.tournament_info[ - entry['tournamentID'] - ] = copy.deepcopy(entry) + cache_entry = self.tournament_info[entry['tournamentID']] = ( + copy.deepcopy(entry) + ) # Also store the time we received this, so we can adjust # time-remaining values/etc. diff --git a/src/assets/ba_data/python/baclassic/_achievement.py b/src/assets/ba_data/python/baclassic/_achievement.py index 38f6f5b0..3ef3bed8 100644 --- a/src/assets/ba_data/python/baclassic/_achievement.py +++ b/src/assets/ba_data/python/baclassic/_achievement.py @@ -75,9 +75,9 @@ class AchievementSubsystem: def __init__(self) -> None: self.achievements: list[Achievement] = [] - self.achievements_to_display: ( - list[tuple[baclassic.Achievement, bool]] - ) = [] + self.achievements_to_display: list[ + tuple[baclassic.Achievement, bool] + ] = [] self.achievement_display_timer: bascenev1.BaseTimer | None = None self.last_achievement_display_time: float = 0.0 self.achievement_completion_banner_slots: set[int] = set() diff --git a/src/assets/ba_data/python/baclassic/_servermode.py b/src/assets/ba_data/python/baclassic/_servermode.py index 45ee6eb9..a5479955 100644 --- a/src/assets/ba_data/python/baclassic/_servermode.py +++ b/src/assets/ba_data/python/baclassic/_servermode.py @@ -310,9 +310,7 @@ class ServerController: typename = ( 'teams' if result['playlistType'] == 'Team Tournament' - else 'ffa' - if result['playlistType'] == 'Free-for-All' - else '??' + else 'ffa' if result['playlistType'] == 'Free-for-All' else '??' ) plistname = result['playlistName'] print(f'{Clr.SBLU}Got playlist: "{plistname}" ({typename}).{Clr.RST}') @@ -390,14 +388,14 @@ class ServerController: if sessiontype is bascenev1.FreeForAllSession: appcfg['Free-for-All Playlist Selection'] = self._playlist_name - appcfg[ - 'Free-for-All Playlist Randomize' - ] = self._config.playlist_shuffle + appcfg['Free-for-All Playlist Randomize'] = ( + self._config.playlist_shuffle + ) elif sessiontype is bascenev1.DualTeamSession: appcfg['Team Tournament Playlist Selection'] = self._playlist_name - appcfg[ - 'Team Tournament Playlist Randomize' - ] = self._config.playlist_shuffle + appcfg['Team Tournament Playlist Randomize'] = ( + self._config.playlist_shuffle + ) elif sessiontype is bascenev1.CoopSession: classic.coop_session_args = { 'campaign': self._config.coop_campaign, @@ -406,6 +404,10 @@ class ServerController: else: raise RuntimeError(f'Unknown session type {sessiontype}') + appcfg['Teams Series Length'] = self._config.teams_series_length + appcfg['FFA Series Length'] = self._config.ffa_series_length + + # deprecated, left here in order to not break mods classic.teams_series_length = self._config.teams_series_length classic.ffa_series_length = self._config.ffa_series_length @@ -427,6 +429,10 @@ class ServerController: self._config.player_rejoin_cooldown ) + bascenev1.set_max_players_override( + self._config.session_max_players_override + ) + # And here.. we.. go. if self._config.stress_test_players is not None: # Special case: run a stress test. diff --git a/src/assets/ba_data/python/baclassic/_subsystem.py b/src/assets/ba_data/python/baclassic/_subsystem.py index 0889b7de..4bdf1406 100644 --- a/src/assets/ba_data/python/baclassic/_subsystem.py +++ b/src/assets/ba_data/python/baclassic/_subsystem.py @@ -103,8 +103,8 @@ class ClassicSubsystem(babase.AppSubsystem): self.maps: dict[str, type[bascenev1.Map]] = {} # Gameplay. - self.teams_series_length = 7 - self.ffa_series_length = 24 + self.teams_series_length = 7 # deprecated, left for old mods + self.ffa_series_length = 24 # deprecated, left for old mods self.coop_session_args: dict = {} # UI. diff --git a/src/assets/ba_data/python/baclassic/_tournament.py b/src/assets/ba_data/python/baclassic/_tournament.py index 552dca04..242ba527 100644 --- a/src/assets/ba_data/python/baclassic/_tournament.py +++ b/src/assets/ba_data/python/baclassic/_tournament.py @@ -35,9 +35,11 @@ def get_tournament_prize_strings(entry: dict[str, Any]) -> list[str]: prval = ( '' if rng is None - else ('#' + str(rng[0])) - if (rng[0] == rng[1]) - else ('#' + str(rng[0]) + '-' + str(rng[1])) + else ( + ('#' + str(rng[0])) + if (rng[0] == rng[1]) + else ('#' + str(rng[0]) + '-' + str(rng[1])) + ) ) pvval = '' if trophy_type is not None: diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index 64ec5fa4..697bffcd 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21770 +TARGET_BALLISTICA_BUILD = 21778 TARGET_BALLISTICA_VERSION = '1.7.33' @@ -264,6 +264,10 @@ def _calc_data_dir(data_dir: str | None) -> str: def _setup_logging() -> LogHandler: from efro.log import setup_logging, LogLevel + # TODO: should set this up with individual loggers under a top level + # 'ba' logger, and at that point we can kill off the + # suppress_non_root_debug option since we'll only ever need to set + # 'ba' to DEBUG at most. log_handler = setup_logging( log_path=None, level=LogLevel.DEBUG, diff --git a/src/assets/ba_data/python/baplus/_cloud.py b/src/assets/ba_data/python/baplus/_cloud.py index d2e51eb0..32d6d141 100644 --- a/src/assets/ba_data/python/baplus/_cloud.py +++ b/src/assets/ba_data/python/baplus/_cloud.py @@ -57,8 +57,7 @@ class CloudSubsystem(babase.AppSubsystem): on_response: Callable[ [bacommon.cloud.LoginProxyRequestResponse | Exception], None ], - ) -> None: - ... + ) -> None: ... @overload def send_message_cb( @@ -67,24 +66,21 @@ class CloudSubsystem(babase.AppSubsystem): on_response: Callable[ [bacommon.cloud.LoginProxyStateQueryResponse | Exception], None ], - ) -> None: - ... + ) -> None: ... @overload def send_message_cb( self, msg: bacommon.cloud.LoginProxyCompleteMessage, on_response: Callable[[None | Exception], None], - ) -> None: - ... + ) -> None: ... @overload def send_message_cb( self, msg: bacommon.cloud.PingMessage, on_response: Callable[[bacommon.cloud.PingResponse | Exception], None], - ) -> None: - ... + ) -> None: ... @overload def send_message_cb( @@ -93,8 +89,7 @@ class CloudSubsystem(babase.AppSubsystem): on_response: Callable[ [bacommon.cloud.SignInResponse | Exception], None ], - ) -> None: - ... + ) -> None: ... @overload def send_message_cb( @@ -103,8 +98,7 @@ class CloudSubsystem(babase.AppSubsystem): on_response: Callable[ [bacommon.cloud.ManageAccountResponse | Exception], None ], - ) -> None: - ... + ) -> None: ... def send_message_cb( self, @@ -129,20 +123,17 @@ class CloudSubsystem(babase.AppSubsystem): @overload def send_message( self, msg: bacommon.cloud.WorkspaceFetchMessage - ) -> bacommon.cloud.WorkspaceFetchResponse: - ... + ) -> bacommon.cloud.WorkspaceFetchResponse: ... @overload def send_message( self, msg: bacommon.cloud.MerchAvailabilityMessage - ) -> bacommon.cloud.MerchAvailabilityResponse: - ... + ) -> bacommon.cloud.MerchAvailabilityResponse: ... @overload def send_message( self, msg: bacommon.cloud.TestMessage - ) -> bacommon.cloud.TestResponse: - ... + ) -> bacommon.cloud.TestResponse: ... def send_message(self, msg: Message) -> Response | None: """Synchronously send a message to the cloud. @@ -154,14 +145,12 @@ class CloudSubsystem(babase.AppSubsystem): @overload async def send_message_async( self, msg: bacommon.cloud.PromoCodeMessage - ) -> bacommon.cloud.PromoCodeResponse: - ... + ) -> bacommon.cloud.PromoCodeResponse: ... @overload async def send_message_async( self, msg: bacommon.cloud.TestMessage - ) -> bacommon.cloud.TestResponse: - ... + ) -> bacommon.cloud.TestResponse: ... async def send_message_async(self, msg: Message) -> Response | None: """Synchronously send a message to the cloud. diff --git a/src/assets/ba_data/python/bascenev1/__init__.py b/src/assets/ba_data/python/bascenev1/__init__.py index 25c1f5ef..ebfb5418 100644 --- a/src/assets/ba_data/python/bascenev1/__init__.py +++ b/src/assets/ba_data/python/bascenev1/__init__.py @@ -120,6 +120,7 @@ from _bascenev1 import ( release_keyboard_input, reset_random_player_names, resume_replay, + seek_replay, broadcastmessage, SessionData, SessionPlayer, @@ -231,7 +232,11 @@ from bascenev1._settings import ( IntSetting, Setting, ) -from bascenev1._session import Session, set_player_rejoin_cooldown +from bascenev1._session import ( + Session, + set_player_rejoin_cooldown, + set_max_players_override, +) from bascenev1._stats import PlayerScoredMessage, PlayerRecord, Stats from bascenev1._team import SessionTeam, Team, EmptyTeam from bascenev1._teamgame import TeamGameActivity @@ -400,6 +405,7 @@ __all__ = [ 'release_keyboard_input', 'reset_random_player_names', 'resume_replay', + 'seek_replay', 'safecolor', 'screenmessage', 'SceneV1AppMode', @@ -426,6 +432,7 @@ __all__ = [ 'set_public_party_queue_enabled', 'set_public_party_stats_url', 'set_player_rejoin_cooldown', + 'set_max_players_override', 'set_replay_speed_exponent', 'set_touchscreen_editing', 'setmusic', diff --git a/src/assets/ba_data/python/bascenev1/_activitytypes.py b/src/assets/ba_data/python/bascenev1/_activitytypes.py index 9b46b3eb..0102305a 100644 --- a/src/assets/ba_data/python/bascenev1/_activitytypes.py +++ b/src/assets/ba_data/python/bascenev1/_activitytypes.py @@ -203,9 +203,11 @@ class ScoreScreenActivity(Activity[EmptyPlayer, EmptyTeam]): sval = babase.Lstr(resource='pressAnyButtonText') Text( - self._custom_continue_message - if self._custom_continue_message is not None - else sval, + ( + self._custom_continue_message + if self._custom_continue_message is not None + else sval + ), v_attach=Text.VAttach.BOTTOM, h_align=Text.HAlign.CENTER, flash=True, diff --git a/src/assets/ba_data/python/bascenev1/_actor.py b/src/assets/ba_data/python/bascenev1/_actor.py index 178a901d..11f4f07c 100644 --- a/src/assets/ba_data/python/bascenev1/_actor.py +++ b/src/assets/ba_data/python/bascenev1/_actor.py @@ -198,12 +198,14 @@ class Actor: # Overloads to convey our exact return type depending on 'doraise' value. @overload - def getactivity(self, doraise: Literal[True] = True) -> bascenev1.Activity: - ... + def getactivity( + self, doraise: Literal[True] = True + ) -> bascenev1.Activity: ... @overload - def getactivity(self, doraise: Literal[False]) -> bascenev1.Activity | None: - ... + def getactivity( + self, doraise: Literal[False] + ) -> bascenev1.Activity | None: ... def getactivity(self, doraise: bool = True) -> bascenev1.Activity | None: """Return the bascenev1.Activity this Actor is associated with. diff --git a/src/assets/ba_data/python/bascenev1/_gameresults.py b/src/assets/ba_data/python/bascenev1/_gameresults.py index e493939a..8735ff36 100644 --- a/src/assets/ba_data/python/bascenev1/_gameresults.py +++ b/src/assets/ba_data/python/bascenev1/_gameresults.py @@ -42,9 +42,9 @@ class GameResults: self._scores: dict[ int, tuple[weakref.ref[bascenev1.SessionTeam], int | None] ] = {} - self._sessionteams: list[ - weakref.ref[bascenev1.SessionTeam] - ] | None = None + self._sessionteams: list[weakref.ref[bascenev1.SessionTeam]] | None = ( + None + ) self._playerinfos: list[bascenev1.PlayerInfo] | None = None self._lower_is_better: bool | None = None self._score_label: str | None = None diff --git a/src/assets/ba_data/python/bascenev1/_level.py b/src/assets/ba_data/python/bascenev1/_level.py index 2f1906e6..74792e96 100644 --- a/src/assets/ba_data/python/bascenev1/_level.py +++ b/src/assets/ba_data/python/bascenev1/_level.py @@ -73,9 +73,11 @@ class Level: return babase.Lstr( translate=( 'coopLevelNames', - self._displayname - if self._displayname is not None - else self._name, + ( + self._displayname + if self._displayname is not None + else self._name + ), ), subs=[ ('${GAME}', self._gametype.get_display_string(self._settings)) diff --git a/src/assets/ba_data/python/bascenev1/_multiteamsession.py b/src/assets/ba_data/python/bascenev1/_multiteamsession.py index 06a5a2e1..77459baa 100644 --- a/src/assets/ba_data/python/bascenev1/_multiteamsession.py +++ b/src/assets/ba_data/python/bascenev1/_multiteamsession.py @@ -67,8 +67,8 @@ class MultiTeamSession(Session): max_players=self.get_max_players(), ) - self._series_length: int = classic.teams_series_length - self._ffa_series_length: int = classic.ffa_series_length + self._series_length: int = int(cfg.get('Teams Series Length', 7)) + self._ffa_series_length: int = int(cfg.get('FFA Series Length', 24)) show_tutorial = cfg.get('Show Tutorial', True) diff --git a/src/assets/ba_data/python/bascenev1/_playlist.py b/src/assets/ba_data/python/bascenev1/_playlist.py index 35c902c8..013f6e56 100644 --- a/src/assets/ba_data/python/bascenev1/_playlist.py +++ b/src/assets/ba_data/python/bascenev1/_playlist.py @@ -89,18 +89,18 @@ def filter_playlist( 'bs_king_of_the_hill.KingOfTheHillGame', 'bastd.game.kingofthehill.KingOfTheHillGame', ): - entry[ - 'type' - ] = 'bascenev1lib.game.kingofthehill.KingOfTheHillGame' + entry['type'] = ( + 'bascenev1lib.game.kingofthehill.KingOfTheHillGame' + ) if entry['type'] in ( 'Capture_the_Flag.CTFGame', 'bsCaptureTheFlag.CTFGame', 'bs_capture_the_flag.CTFGame', 'bastd.game.capturetheflag.CaptureTheFlagGame', ): - entry[ - 'type' - ] = 'bascenev1lib.game.capturetheflag.CaptureTheFlagGame' + entry['type'] = ( + 'bascenev1lib.game.capturetheflag.CaptureTheFlagGame' + ) if entry['type'] in ( 'Death_Match.DeathMatchGame', 'bsDeathMatch.DeathMatchGame', @@ -163,25 +163,25 @@ def filter_playlist( 'bs_easter_egg_hunt.EasterEggHuntGame', 'bastd.game.easteregghunt.EasterEggHuntGame', ): - entry[ - 'type' - ] = 'bascenev1lib.game.easteregghunt.EasterEggHuntGame' + entry['type'] = ( + 'bascenev1lib.game.easteregghunt.EasterEggHuntGame' + ) if entry['type'] in ( 'bsMeteorShower.MeteorShowerGame', 'bs_meteor_shower.MeteorShowerGame', 'bastd.game.meteorshower.MeteorShowerGame', ): - entry[ - 'type' - ] = 'bascenev1lib.game.meteorshower.MeteorShowerGame' + entry['type'] = ( + 'bascenev1lib.game.meteorshower.MeteorShowerGame' + ) if entry['type'] in ( 'bsTargetPractice.TargetPracticeGame', 'bs_target_practice.TargetPracticeGame', 'bastd.game.targetpractice.TargetPracticeGame', ): - entry[ - 'type' - ] = 'bascenev1lib.game.targetpractice.TargetPracticeGame' + entry['type'] = ( + 'bascenev1lib.game.targetpractice.TargetPracticeGame' + ) gameclass = babase.getclass(entry['type'], GameActivity) diff --git a/src/assets/ba_data/python/bascenev1/_session.py b/src/assets/ba_data/python/bascenev1/_session.py index 9ee55313..9acad485 100644 --- a/src/assets/ba_data/python/bascenev1/_session.py +++ b/src/assets/ba_data/python/bascenev1/_session.py @@ -23,6 +23,9 @@ if TYPE_CHECKING: # such as skipping respawn waits. _g_player_rejoin_cooldown: float = 0.0 +# overrides the session's decision of max_players +_max_players_override: int | None = None + def set_player_rejoin_cooldown(cooldown: float) -> None: """Set the cooldown for individual players rejoining after leaving.""" @@ -30,6 +33,12 @@ def set_player_rejoin_cooldown(cooldown: float) -> None: _g_player_rejoin_cooldown = max(0.0, cooldown) +def set_max_players_override(max_players: int | None) -> None: + """Set the override for how many players can join a session""" + global _max_players_override # pylint: disable=global-statement + _max_players_override = max_players + + class Session: """Defines a high level series of bascenev1.Activity-es. @@ -161,7 +170,11 @@ class Session: self.sessionteams = [] self.sessionplayers = [] self.min_players = min_players - self.max_players = max_players + self.max_players = ( + max_players + if _max_players_override is None + else _max_players_override + ) self.customdata = {} self._in_set_activity = False @@ -255,7 +268,7 @@ class Session: babase.app.classic is not None and babase.app.classic.stress_test_update_timer is None ): - if len(self.sessionplayers) >= self.max_players: + if len(self.sessionplayers) >= self.max_players >= 0: # Print a rejection message *only* to the client trying to # join (prevents spamming everyone else in the game). _bascenev1.getsound('error').play() diff --git a/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py b/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py index a88c418b..12ffc3ad 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py @@ -395,11 +395,15 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): color=(0.45, 0.4, 0.5), position=(160, v_offs + 480), size=(350, 62), - label=bui.Lstr(resource='tournamentStandingsText') - if self.session.tournament_id is not None - else bui.Lstr(resource='worldsBestScoresText') - if self._score_type == 'points' - else bui.Lstr(resource='worldsBestTimesText'), + label=( + bui.Lstr(resource='tournamentStandingsText') + if self.session.tournament_id is not None + else ( + bui.Lstr(resource='worldsBestScoresText') + if self._score_type == 'points' + else bui.Lstr(resource='worldsBestTimesText') + ) + ), autoselect=True, on_activate_call=bui.WeakCall(self._ui_worlds_best), transition_delay=delay + 1.9, @@ -515,9 +519,11 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): bui.containerwidget( edit=rootc, - selected_child=next_button - if (self._newly_complete and self._victory and show_next_button) - else restart_button, + selected_child=( + next_button + if (self._newly_complete and self._victory and show_next_button) + else restart_button + ), on_cancel_call=menu_button.activate, ) @@ -644,14 +650,16 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): and not (env.demo or env.arcade) ): Text( - bs.Lstr( - value='${A}:\n', - subs=[('${A}', bs.Lstr(resource='levelUnlockedText'))], - ) - if self._newly_complete - else bs.Lstr( - value='${A}:\n', - subs=[('${A}', bs.Lstr(resource='nextLevelText'))], + ( + bs.Lstr( + value='${A}:\n', + subs=[('${A}', bs.Lstr(resource='levelUnlockedText'))], + ) + if self._newly_complete + else bs.Lstr( + value='${A}:\n', + subs=[('${A}', bs.Lstr(resource='nextLevelText'))], + ) ), transition=Text.Transition.IN_RIGHT, transition_delay=5.2, @@ -860,11 +868,15 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): ts_h_offs = 210 v_offs = 40 txt = Text( - bs.Lstr(resource='tournamentStandingsText') - if self.session.tournament_id is not None - else bs.Lstr(resource='worldsBestScoresText') - if self._score_type == 'points' - else bs.Lstr(resource='worldsBestTimesText'), + ( + bs.Lstr(resource='tournamentStandingsText') + if self.session.tournament_id is not None + else ( + bs.Lstr(resource='worldsBestScoresText') + if self._score_type == 'points' + else bs.Lstr(resource='worldsBestTimesText') + ) + ), maxwidth=210, position=(ts_h_offs - 10, ts_height / 2 + 25 + v_offs + 20), transition=Text.Transition.IN_LEFT, @@ -882,9 +894,11 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): ts_h_offs = -480 v_offs = 40 Text( - bs.Lstr(resource='yourBestScoresText') - if self._score_type == 'points' - else bs.Lstr(resource='yourBestTimesText'), + ( + bs.Lstr(resource='yourBestScoresText') + if self._score_type == 'points' + else bs.Lstr(resource='yourBestTimesText') + ), maxwidth=210, position=(ts_h_offs - 10, ts_height / 2 + 25 + v_offs + 20), transition=Text.Transition.IN_RIGHT, @@ -948,9 +962,11 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): tdelay1 = times[i][0] tdelay2 = times[i][1] Text( - str(display_scores[i][0]) - if self._score_type == 'points' - else bs.timestring((display_scores[i][0] * 10) / 1000.0), + ( + str(display_scores[i][0]) + if self._score_type == 'points' + else bs.timestring((display_scores[i][0] * 10) / 1000.0) + ), position=( ts_h_offs + 20 + h_offs_extra, v_offs_extra @@ -1127,9 +1143,11 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): tdelay2 = times[i][1] if name_str != '-': Text( - str(score) - if self._score_type == 'points' - else bs.timestring((score * 10) / 1000.0), + ( + str(score) + if self._score_type == 'points' + else bs.timestring((score * 10) / 1000.0) + ), position=( ts_h_offs + 20 + h_offs_extra, v_offs_extra @@ -1313,9 +1331,11 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): if name_str != '-': Text( - str(score) - if self._score_type == 'points' - else bs.timestring((score * 10) / 1000.0), + ( + str(score) + if self._score_type == 'points' + else bs.timestring((score * 10) / 1000.0) + ), position=( ts_h_offs + 20 + h_offs_extra, ts_height / 2 @@ -1689,17 +1709,22 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): ) if not self._newly_complete: Text( - bs.Lstr( - value='${A}${B}', - subs=[ - ('${A}', bs.Lstr(resource='newPersonalBestText')), - ('${B}', was_string), - ], - ) - if new_best - else bs.Lstr( - resource='bestRatingText', - subs=[('${RATING}', str(best_rank))], + ( + bs.Lstr( + value='${A}${B}', + subs=[ + ( + '${A}', + bs.Lstr(resource='newPersonalBestText'), + ), + ('${B}', was_string), + ], + ) + if new_best + else bs.Lstr( + resource='bestRatingText', + subs=[('${RATING}', str(best_rank))], + ) ), position=(0, -165), color=(1, 1, 1, 0.7), @@ -1773,14 +1798,16 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): jitter=1.0, ).autoretain() Text( - bs.Lstr( - value='${A}:', - subs=[('${A}', bs.Lstr(resource='finalScoreText'))], - ) - if self._score_type == 'points' - else bs.Lstr( - value='${A}:', - subs=[('${A}', bs.Lstr(resource='finalTimeText'))], + ( + bs.Lstr( + value='${A}:', + subs=[('${A}', bs.Lstr(resource='finalScoreText'))], + ) + if self._score_type == 'points' + else bs.Lstr( + value='${A}:', + subs=[('${A}', bs.Lstr(resource='finalTimeText'))], + ) ), maxwidth=300, position=(0, 200), diff --git a/src/assets/ba_data/python/bascenev1lib/activity/multiteamscore.py b/src/assets/ba_data/python/bascenev1lib/activity/multiteamscore.py index 7b754014..3a0db16a 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/multiteamscore.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/multiteamscore.py @@ -199,9 +199,9 @@ class MultiTeamScoreScreenActivity(bs.ScoreScreenActivity): ts_v_offset + (voffs + 15) * scale, ), scale=scale, - color=(1.0, 0.9, 0.5, 1.0) - if highlight - else (0.5, 0.5, 0.6, 0.5), + color=( + (1.0, 0.9, 0.5, 1.0) if highlight else (0.5, 0.5, 0.6, 0.5) + ), h_align=Text.HAlign.RIGHT, v_align=Text.VAlign.CENTER, maxwidth=maxwidth, diff --git a/src/assets/ba_data/python/bascenev1lib/activity/multiteamvictory.py b/src/assets/ba_data/python/bascenev1lib/activity/multiteamvictory.py index afc2a26b..e2a09252 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/multiteamvictory.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/multiteamvictory.py @@ -374,9 +374,11 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): tdelay -= 4 * t_incr v_offs -= 40 Text( - str(prec.team.customdata['score']) - if self._is_ffa - else str(prec.score), + ( + str(prec.team.customdata['score']) + if self._is_ffa + else str(prec.score) + ), color=(0.5, 0.5, 0.5, 1.0), position=(ts_h_offs + 230, ts_height / 2 + v_offs), h_align=Text.HAlign.RIGHT, diff --git a/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py b/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py index f3068f0e..d73ea28b 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py @@ -456,9 +456,11 @@ class ControlsGuide(bs.Actor): ( '${B}', bs.Lstr( - resource='holdAnyKeyText' - if all_keyboards - else 'holdAnyButtonText' + resource=( + 'holdAnyKeyText' + if all_keyboards + else 'holdAnyButtonText' + ) ), ), ], diff --git a/src/assets/ba_data/python/bascenev1lib/actor/playerspaz.py b/src/assets/ba_data/python/bascenev1lib/actor/playerspaz.py index 2ea3ead7..58069c54 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/playerspaz.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/playerspaz.py @@ -79,14 +79,12 @@ class PlayerSpaz(Spaz): @overload def getplayer( self, playertype: type[PlayerT], doraise: Literal[False] = False - ) -> PlayerT | None: - ... + ) -> PlayerT | None: ... @overload def getplayer( self, playertype: type[PlayerT], doraise: Literal[True] - ) -> PlayerT: - ... + ) -> PlayerT: ... def getplayer( self, playertype: type[PlayerT], doraise: bool = False diff --git a/src/assets/ba_data/python/bascenev1lib/actor/respawnicon.py b/src/assets/ba_data/python/bascenev1lib/actor/respawnicon.py index 72a14c93..59aa8810 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/respawnicon.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/respawnicon.py @@ -22,7 +22,9 @@ class RespawnIcon: def __init__(self, player: bs.Player, respawn_time: float): """Instantiate with a Player and respawn_time (in seconds).""" + # pylint: disable=too-many-locals self._visible = True + self._dots_epic_only = False on_right, offs_extra, respawn_icons = self._get_context(player) @@ -92,7 +94,7 @@ class RespawnIcon: assert self._name.node bs.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5}) - tpos = (-60 - h_offs if on_right else 60 + h_offs, -192 + offs) + tpos = (-60 - h_offs if on_right else 60 + h_offs, -193 + offs) self._text: bs.NodeActor | None = bs.NodeActor( bs.newnode( 'text', @@ -109,11 +111,37 @@ class RespawnIcon: }, ) ) + dpos = [ipos[0] + (7 if on_right else -7), ipos[1] - 16] + self._dec_text: bs.NodeActor | None = None + if ( + self._dots_epic_only + and bs.getactivity().globalsnode.slow_motion + or not self._dots_epic_only + ): + self._dec_text = bs.NodeActor( + bs.newnode( + 'text', + attrs={ + 'position': dpos, + 'h_attach': 'right' if on_right else 'left', + 'h_align': 'right' if on_right else 'left', + 'scale': 0.65, + 'shadow': 0.5, + 'flatness': 0.5, + 'v_attach': 'top', + 'color': bs.safecolor(icon['tint_color']), + 'text': '', + }, + ) + ) assert self._text.node bs.animate(self._text.node, 'scale', {0: 0, 0.1: 0.9}) + if self._dec_text: + bs.animate(self._dec_text.node, 'scale', {0: 0, 0.1: 0.65}) self._respawn_time = bs.time() + respawn_time + self._dec_timer: bs.Timer | None = None self._update() self._timer: bs.Timer | None = bs.Timer( 1.0, bs.WeakCall(self._update), repeat=True @@ -128,7 +156,7 @@ class RespawnIcon: """Return info on where we should be shown and stored.""" activity = bs.getactivity() - if isinstance(bs.getsession(), bs.DualTeamSession): + if isinstance(activity.session, bs.DualTeamSession): on_right = player.team.id % 2 == 1 # Store a list of icons in the team. @@ -153,12 +181,43 @@ class RespawnIcon: offs_extra = -20 return on_right, offs_extra, icons + def _dec_step(self, display: list) -> None: + if not self._dec_text: + self._dec_timer = None + return + old_text: bs.Lstr | str = self._dec_text.node.text + iterate: int + # Get the following display text using our current one. + try: + iterate = display.index(old_text) + 1 + # If we don't match any in the display list, we + # can assume we've just started iterating. + except ValueError: + iterate = 0 + # Kill the timer if we're at the last iteration. + if iterate >= len(display): + self._dec_timer = None + return + self._dec_text.node.text = display[iterate] + def _update(self) -> None: remaining = int(round(self._respawn_time - bs.time())) + if remaining > 0: assert self._text is not None if self._text.node: self._text.node.text = str(remaining) + if self._dec_text: + # Display our decimal dots. + self._dec_text.node.text = '...' + # Start the timer to tick down. + self._dec_timer = bs.Timer( + 0.25, + bs.WeakCall(self._dec_step, ['..', '.', '']), + repeat=True, + ) else: self._visible = False - self._image = self._text = self._timer = self._name = None + self._image = self._text = self._dec_text = self._timer = ( + self._name + ) = None diff --git a/src/assets/ba_data/python/bascenev1lib/actor/spazbot.py b/src/assets/ba_data/python/bascenev1lib/actor/spazbot.py index bdd8c271..ed91bdbe 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/spazbot.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/spazbot.py @@ -776,7 +776,6 @@ class ChargerBotPro(ChargerBot): color = PRO_BOT_COLOR highlight = PRO_BOT_HIGHLIGHT - default_shields = True default_boxing_gloves = True points_mult = 3 diff --git a/src/assets/ba_data/python/bascenev1lib/actor/tipstext.py b/src/assets/ba_data/python/bascenev1lib/actor/tipstext.py index 7a6335fc..8e20951e 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/tipstext.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/tipstext.py @@ -73,9 +73,11 @@ class TipsText(bs.Actor): next_tip = bs.Lstr( translate=( 'tips', - bs.app.classic.get_next_tip() - if bs.app.classic is not None - else '', + ( + bs.app.classic.get_next_tip() + if bs.app.classic is not None + else '' + ), ), subs=[('${REMOTE_APP_NAME}', get_remote_app_name())], ) diff --git a/src/assets/ba_data/python/bascenev1lib/game/capturetheflag.py b/src/assets/ba_data/python/bascenev1lib/game/capturetheflag.py index 837c3be1..316483f9 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/capturetheflag.py +++ b/src/assets/ba_data/python/bascenev1lib/game/capturetheflag.py @@ -529,6 +529,30 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): if team.flag_return_touches < 0: logging.exception('CTF flag_return_touches < 0') + def _handle_death_flag_capture(self, player: Player) -> None: + """Handles flag values when a player dies or leaves the game.""" + # Don't do anything if the player hasn't touched the flag at all. + if not player.touching_own_flag: + return + + team = player.team + # For each "point" our player has touched theflag (Could be multiple), + # deduct one from both our player and + # the flag's return touches variable. + for _ in range(player.touching_own_flag): + # Deduct + player.touching_own_flag -= 1 + team.flag_return_touches -= 1 + # Update our flag's timer accordingly + # (Prevents immediate resets in case + # there might be more people touching it). + if team.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.exception('CTF flag_return_touches < 0') + def _flash_base(self, team: Team, length: float = 2.0) -> None: light = bs.newnode( 'light', @@ -591,6 +615,7 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): super().handlemessage(msg) # Augment standard behavior. + self._handle_death_flag_capture(msg.getplayer(Player)) self.respawn_player(msg.getplayer(Player)) elif isinstance(msg, FlagDiedMessage): @@ -617,3 +642,8 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): else: super().handlemessage(msg) + + @override + def on_player_leave(self, player: Player) -> None: + """Prevents leaving players from capturing their flag.""" + self._handle_death_flag_capture(player) diff --git a/src/assets/ba_data/python/bascenev1lib/game/onslaught.py b/src/assets/ba_data/python/bascenev1lib/game/onslaught.py index d4644130..b1c2e145 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/onslaught.py +++ b/src/assets/ba_data/python/bascenev1lib/game/onslaught.py @@ -334,29 +334,37 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): Wave( base_angle=130, entries=[ - Spawn(BrawlerBotLite, spacing=5) - if player_count > 1 - else None, + ( + Spawn(BrawlerBotLite, spacing=5) + if player_count > 1 + else None + ), Spawn(BrawlerBotLite, spacing=5), Spacing(30), - Spawn(BomberBotLite, spacing=5) - if player_count > 3 - else None, + ( + Spawn(BomberBotLite, spacing=5) + if player_count > 3 + else None + ), Spawn(BomberBotLite, spacing=5), Spacing(30), Spawn(BrawlerBotLite, spacing=5), - Spawn(BrawlerBotLite, spacing=5) - if player_count > 2 - else None, + ( + Spawn(BrawlerBotLite, spacing=5) + if player_count > 2 + else None + ), ], ), Wave( base_angle=195, entries=[ Spawn(TriggerBot, spacing=90), - Spawn(TriggerBot, spacing=90) - if player_count > 1 - else None, + ( + Spawn(TriggerBot, spacing=90) + if player_count > 1 + else None + ), ], ), ] @@ -367,9 +375,11 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): self._waves = [ Wave( entries=[ - Spawn(ChargerBot, Point.LEFT_UPPER_MORE) - if player_count > 2 - else None, + ( + Spawn(ChargerBot, Point.LEFT_UPPER_MORE) + if player_count > 2 + else None + ), Spawn(ChargerBot, Point.LEFT_UPPER), ] ), @@ -377,36 +387,50 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): entries=[ Spawn(BomberBotStaticLite, Point.TURRET_TOP_RIGHT), Spawn(BrawlerBotLite, Point.RIGHT_UPPER), - Spawn(BrawlerBotLite, Point.RIGHT_LOWER) - if player_count > 1 - else None, - Spawn(BomberBotStaticLite, Point.TURRET_BOTTOM_RIGHT) - if player_count > 2 - else None, + ( + Spawn(BrawlerBotLite, Point.RIGHT_LOWER) + if player_count > 1 + else None + ), + ( + Spawn( + BomberBotStaticLite, Point.TURRET_BOTTOM_RIGHT + ) + if player_count > 2 + else None + ), ] ), Wave( entries=[ Spawn(BomberBotStaticLite, Point.TURRET_BOTTOM_LEFT), Spawn(TriggerBot, Point.LEFT), - Spawn(TriggerBot, Point.LEFT_LOWER) - if player_count > 1 - else None, - Spawn(TriggerBot, Point.LEFT_UPPER) - if player_count > 2 - else None, + ( + Spawn(TriggerBot, Point.LEFT_LOWER) + if player_count > 1 + else None + ), + ( + Spawn(TriggerBot, Point.LEFT_UPPER) + if player_count > 2 + else None + ), ] ), Wave( entries=[ Spawn(BrawlerBotLite, Point.TOP_RIGHT), - Spawn(BrawlerBot, Point.TOP_HALF_RIGHT) - if player_count > 1 - else None, + ( + Spawn(BrawlerBot, Point.TOP_HALF_RIGHT) + if player_count > 1 + else None + ), Spawn(BrawlerBotLite, Point.TOP_LEFT), - Spawn(BrawlerBotLite, Point.TOP_HALF_LEFT) - if player_count > 2 - else None, + ( + Spawn(BrawlerBotLite, Point.TOP_HALF_LEFT) + if player_count > 2 + else None + ), Spawn(BrawlerBot, Point.TOP), Spawn(BomberBotStaticLite, Point.TURRET_TOP_MIDDLE), ] @@ -416,12 +440,16 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): Spawn(TriggerBotStatic, Point.TURRET_BOTTOM_LEFT), Spawn(TriggerBotStatic, Point.TURRET_BOTTOM_RIGHT), Spawn(TriggerBot, Point.BOTTOM), - Spawn(TriggerBot, Point.BOTTOM_HALF_RIGHT) - if player_count > 1 - else None, - Spawn(TriggerBot, Point.BOTTOM_HALF_LEFT) - if player_count > 2 - else None, + ( + Spawn(TriggerBot, Point.BOTTOM_HALF_RIGHT) + if player_count > 1 + else None + ), + ( + Spawn(TriggerBot, Point.BOTTOM_HALF_LEFT) + if player_count > 2 + else None + ), ] ), Wave( @@ -429,12 +457,16 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): Spawn(BomberBotStaticLite, Point.TURRET_TOP_LEFT), Spawn(BomberBotStaticLite, Point.TURRET_TOP_RIGHT), Spawn(ChargerBot, Point.BOTTOM), - Spawn(ChargerBot, Point.BOTTOM_HALF_LEFT) - if player_count > 1 - else None, - Spawn(ChargerBot, Point.BOTTOM_HALF_RIGHT) - if player_count > 2 - else None, + ( + Spawn(ChargerBot, Point.BOTTOM_HALF_LEFT) + if player_count > 1 + else None + ), + ( + Spawn(ChargerBot, Point.BOTTOM_HALF_RIGHT) + if player_count > 2 + else None + ), ] ), ] @@ -446,44 +478,62 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): Wave( base_angle=-50, entries=[ - Spawn(BrawlerBot, spacing=12) - if player_count > 3 - else None, + ( + Spawn(BrawlerBot, spacing=12) + if player_count > 3 + else None + ), Spawn(BrawlerBot, spacing=12), Spawn(BomberBot, spacing=6), - Spawn(BomberBot, spacing=6) - if self._preset is Preset.PRO - else None, - Spawn(BomberBot, spacing=6) - if player_count > 1 - else None, + ( + Spawn(BomberBot, spacing=6) + if self._preset is Preset.PRO + else None + ), + ( + Spawn(BomberBot, spacing=6) + if player_count > 1 + else None + ), Spawn(BrawlerBot, spacing=12), - Spawn(BrawlerBot, spacing=12) - if player_count > 2 - else None, + ( + Spawn(BrawlerBot, spacing=12) + if player_count > 2 + else None + ), ], ), Wave( base_angle=180, entries=[ - Spawn(BrawlerBot, spacing=6) - if player_count > 3 - else None, - Spawn(BrawlerBot, spacing=6) - if self._preset is Preset.PRO - else None, + ( + Spawn(BrawlerBot, spacing=6) + if player_count > 3 + else None + ), + ( + Spawn(BrawlerBot, spacing=6) + if self._preset is Preset.PRO + else None + ), Spawn(BrawlerBot, spacing=6), Spawn(ChargerBot, spacing=45), - Spawn(ChargerBot, spacing=45) - if player_count > 1 - else None, + ( + Spawn(ChargerBot, spacing=45) + if player_count > 1 + else None + ), Spawn(BrawlerBot, spacing=6), - Spawn(BrawlerBot, spacing=6) - if self._preset is Preset.PRO - else None, - Spawn(BrawlerBot, spacing=6) - if player_count > 2 - else None, + ( + Spawn(BrawlerBot, spacing=6) + if self._preset is Preset.PRO + else None + ), + ( + Spawn(BrawlerBot, spacing=6) + if player_count > 2 + else None + ), ], ), Wave( @@ -492,15 +542,21 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): Spawn(ChargerBot, spacing=30), Spawn(TriggerBot, spacing=30), Spawn(TriggerBot, spacing=30), - Spawn(TriggerBot, spacing=30) - if self._preset is Preset.PRO - else None, - Spawn(TriggerBot, spacing=30) - if player_count > 1 - else None, - Spawn(TriggerBot, spacing=30) - if player_count > 3 - else None, + ( + Spawn(TriggerBot, spacing=30) + if self._preset is Preset.PRO + else None + ), + ( + Spawn(TriggerBot, spacing=30) + if player_count > 1 + else None + ), + ( + Spawn(TriggerBot, spacing=30) + if player_count > 3 + else None + ), Spawn(ChargerBot, spacing=30), ], ), @@ -508,16 +564,22 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): base_angle=90, entries=[ Spawn(StickyBot, spacing=50), - Spawn(StickyBot, spacing=50) - if self._preset is Preset.PRO - else None, + ( + Spawn(StickyBot, spacing=50) + if self._preset is Preset.PRO + else None + ), Spawn(StickyBot, spacing=50), - Spawn(StickyBot, spacing=50) - if player_count > 1 - else None, - Spawn(StickyBot, spacing=50) - if player_count > 3 - else None, + ( + Spawn(StickyBot, spacing=50) + if player_count > 1 + else None + ), + ( + Spawn(StickyBot, spacing=50) + if player_count > 3 + else None + ), ], ), Wave( @@ -525,14 +587,18 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): entries=[ Spawn(TriggerBot, spacing=72), Spawn(TriggerBot, spacing=72), - Spawn(TriggerBot, spacing=72) - if self._preset is Preset.PRO - else None, + ( + Spawn(TriggerBot, spacing=72) + if self._preset is Preset.PRO + else None + ), Spawn(TriggerBot, spacing=72), Spawn(TriggerBot, spacing=72), - Spawn(TriggerBot, spacing=36) - if player_count > 2 - else None, + ( + Spawn(TriggerBot, spacing=36) + if player_count > 2 + else None + ), ], ), Wave( @@ -540,15 +606,21 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): entries=[ Spawn(ChargerBotProShielded, spacing=50), Spawn(ChargerBotProShielded, spacing=50), - Spawn(ChargerBotProShielded, spacing=50) - if self._preset is Preset.PRO - else None, - Spawn(ChargerBotProShielded, spacing=50) - if player_count > 1 - else None, - Spawn(ChargerBotProShielded, spacing=50) - if player_count > 2 - else None, + ( + Spawn(ChargerBotProShielded, spacing=50) + if self._preset is Preset.PRO + else None + ), + ( + Spawn(ChargerBotProShielded, spacing=50) + if player_count > 1 + else None + ), + ( + Spawn(ChargerBotProShielded, spacing=50) + if player_count > 2 + else None + ), ], ), ] @@ -566,15 +638,21 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): self._waves = [ Wave( entries=[ - Spawn(BomberBotProStatic, Point.TURRET_TOP_MIDDLE_LEFT) - if hard - else None, + ( + Spawn( + BomberBotProStatic, Point.TURRET_TOP_MIDDLE_LEFT + ) + if hard + else None + ), Spawn( BomberBotProStatic, Point.TURRET_TOP_MIDDLE_RIGHT ), - Spawn(BomberBotProStatic, Point.TURRET_TOP_LEFT) - if player_count > 2 - else None, + ( + Spawn(BomberBotProStatic, Point.TURRET_TOP_LEFT) + if player_count > 2 + else None + ), Spawn(ExplodeyBot, Point.TOP_RIGHT), Delay(4.0), Spawn(ExplodeyBot, Point.TOP_LEFT), @@ -584,9 +662,11 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): entries=[ Spawn(ChargerBot, Point.LEFT), Spawn(ChargerBot, Point.RIGHT), - Spawn(ChargerBot, Point.RIGHT_UPPER_MORE) - if player_count > 2 - else None, + ( + Spawn(ChargerBot, Point.RIGHT_UPPER_MORE) + if player_count > 2 + else None + ), Spawn(BomberBotProStatic, Point.TURRET_TOP_LEFT), Spawn(BomberBotProStatic, Point.TURRET_TOP_RIGHT), ] @@ -594,29 +674,39 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): Wave( entries=[ Spawn(TriggerBotPro, Point.TOP_RIGHT), - Spawn(TriggerBotPro, Point.RIGHT_UPPER_MORE) - if player_count > 1 - else None, + ( + Spawn(TriggerBotPro, Point.RIGHT_UPPER_MORE) + if player_count > 1 + else None + ), Spawn(TriggerBotPro, Point.RIGHT_UPPER), - Spawn(TriggerBotPro, Point.RIGHT_LOWER) - if hard - else None, - Spawn(TriggerBotPro, Point.RIGHT_LOWER_MORE) - if player_count > 2 - else None, + ( + Spawn(TriggerBotPro, Point.RIGHT_LOWER) + if hard + else None + ), + ( + Spawn(TriggerBotPro, Point.RIGHT_LOWER_MORE) + if player_count > 2 + else None + ), Spawn(TriggerBotPro, Point.BOTTOM_RIGHT), ] ), Wave( entries=[ Spawn(ChargerBotProShielded, Point.BOTTOM_RIGHT), - Spawn(ChargerBotProShielded, Point.BOTTOM) - if player_count > 2 - else None, + ( + Spawn(ChargerBotProShielded, Point.BOTTOM) + if player_count > 2 + else None + ), Spawn(ChargerBotProShielded, Point.BOTTOM_LEFT), - Spawn(ChargerBotProShielded, Point.TOP) - if hard - else None, + ( + Spawn(ChargerBotProShielded, Point.TOP) + if hard + else None + ), Spawn(BomberBotProStatic, Point.TURRET_TOP_MIDDLE), ] ), @@ -643,12 +733,21 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): Spawn(BomberBotProStatic, Point.TURRET_TOP_RIGHT), Spawn(BomberBotProStatic, Point.TURRET_BOTTOM_LEFT), Spawn(BomberBotProStatic, Point.TURRET_BOTTOM_RIGHT), - Spawn(BomberBotProStatic, Point.TURRET_TOP_MIDDLE_LEFT) - if hard - else None, - Spawn(BomberBotProStatic, Point.TURRET_TOP_MIDDLE_RIGHT) - if hard - else None, + ( + Spawn( + BomberBotProStatic, Point.TURRET_TOP_MIDDLE_LEFT + ) + if hard + else None + ), + ( + Spawn( + BomberBotProStatic, + Point.TURRET_TOP_MIDDLE_RIGHT, + ) + if hard + else None + ), ] ), ] @@ -667,12 +766,14 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): # Spit out a few powerups and start dropping more shortly. self._drop_powerups( standard_points=True, - poweruptype='curse' - if self._preset in [Preset.UBER, Preset.UBER_EASY] - else ( - 'land_mines' - if self._preset in [Preset.ROOKIE, Preset.ROOKIE_EASY] - else None + poweruptype=( + 'curse' + if self._preset in [Preset.UBER, Preset.UBER_EASY] + else ( + 'land_mines' + if self._preset in [Preset.ROOKIE, Preset.ROOKIE_EASY] + else None + ) ), ) bs.timer(4.0, self._start_powerup_drops) diff --git a/src/assets/ba_data/python/bascenev1lib/game/race.py b/src/assets/ba_data/python/bascenev1lib/game/race.py index 4a35fa4c..6898a2f3 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/race.py +++ b/src/assets/ba_data/python/bascenev1lib/game/race.py @@ -778,9 +778,11 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): assert self._timer is not None if self._timer.has_started(): self._timer.stop( - endtime=None - if self._last_team_time is None - else (self._timer.getstarttime() + self._last_team_time) + endtime=( + None + if self._last_team_time is None + else (self._timer.getstarttime() + self._last_team_time) + ) ) results = bs.GameResults() diff --git a/src/assets/ba_data/python/bascenev1lib/game/runaround.py b/src/assets/ba_data/python/bascenev1lib/game/runaround.py index b970d354..b09d5ed2 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/runaround.py +++ b/src/assets/ba_data/python/bascenev1lib/game/runaround.py @@ -14,7 +14,7 @@ import random import logging from enum import Enum from dataclasses import dataclass -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast, Sequence from typing_extensions import override import bascenev1 as bs @@ -45,7 +45,7 @@ from bascenev1lib.actor.spazbot import ( ) if TYPE_CHECKING: - from typing import Any, Sequence + from typing import Any class Preset(Enum): @@ -190,6 +190,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): self._lives_text: bs.NodeActor | None = None self._flawless = True self._time_bonus_timer: bs.Timer | None = None + self._lives_hbtime: bs.Timer | None = None self._time_bonus_text: bs.NodeActor | None = None self._time_bonus_mult: float | None = None self._wave_text: bs.NodeActor | None = None @@ -279,9 +280,11 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): Spacing(duration=1.0), Spawn(TriggerBot, path=3), Spacing(duration=1.0), - Spawn(TriggerBot, path=1) - if (player_count > 1 and hard) - else None, + ( + Spawn(TriggerBot, path=1) + if (player_count > 1 and hard) + else None + ), Spacing(duration=1.0), Spawn(TriggerBot, path=2) if player_count > 2 else None, Spacing(duration=1.0), @@ -320,17 +323,23 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): Spacing(duration=1.5), Spawn(BomberBotProShielded, path=1) if hard else None, Spacing(duration=1.5) if hard else None, - Spawn(BomberBotProShielded, path=3) - if player_count > 1 - else None, + ( + Spawn(BomberBotProShielded, path=3) + if player_count > 1 + else None + ), Spacing(duration=1.5), - Spawn(BomberBotProShielded, path=2) - if player_count > 2 - else None, + ( + Spawn(BomberBotProShielded, path=2) + if player_count > 2 + else None + ), Spacing(duration=1.5), - Spawn(BomberBotProShielded, path=1) - if player_count > 3 - else None, + ( + Spawn(BomberBotProShielded, path=1) + if player_count > 3 + else None + ), ] ), ] @@ -352,9 +361,11 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): BrawlerBotPro if hard else BrawlerBot, point=Point.BOTTOM_LEFT, ), - Spawn(BrawlerBotPro, point=Point.BOTTOM_RIGHT) - if player_count > 2 - else None, + ( + Spawn(BrawlerBotPro, point=Point.BOTTOM_RIGHT) + if player_count > 2 + else None + ), ] ), Wave( @@ -375,9 +386,11 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): Spawn(BomberBotProShielded, path=3), Spawn(BomberBotProShielded, path=3), Spawn(ChargerBot, point=Point.BOTTOM_RIGHT), - Spawn(ChargerBot, point=Point.BOTTOM_LEFT) - if player_count > 2 - else None, + ( + Spawn(ChargerBot, point=Point.BOTTOM_LEFT) + if player_count > 2 + else None + ), ] ), Wave( @@ -388,12 +401,16 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): Spawn(TriggerBotPro, path=1 if hard else 2), Spawn(TriggerBotPro, path=1 if hard else 2), Spawn(TriggerBotPro, path=1 if hard else 2), - Spawn(TriggerBotPro, path=1 if hard else 2) - if player_count > 1 - else None, - Spawn(TriggerBotPro, path=1 if hard else 2) - if player_count > 3 - else None, + ( + Spawn(TriggerBotPro, path=1 if hard else 2) + if player_count > 1 + else None + ), + ( + Spawn(TriggerBotPro, path=1 if hard else 2) + if player_count > 3 + else None + ), ] ), Wave( @@ -402,12 +419,20 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): TriggerBotProShielded if hard else TriggerBotPro, point=Point.BOTTOM_LEFT, ), - Spawn(TriggerBotProShielded, point=Point.BOTTOM_RIGHT) - if hard - else None, - Spawn(TriggerBotProShielded, point=Point.BOTTOM_RIGHT) - if player_count > 2 - else None, + ( + Spawn( + TriggerBotProShielded, point=Point.BOTTOM_RIGHT + ) + if hard + else None + ), + ( + Spawn( + TriggerBotProShielded, point=Point.BOTTOM_RIGHT + ) + if player_count > 2 + else None + ), Spawn(BomberBot, path=3), Spawn(BomberBot, path=3), Spacing(duration=5.0), @@ -425,15 +450,19 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): Spawn(StickyBot, point=Point.BOTTOM_RIGHT), Spawn(BomberBotProShielded, path=2), Spawn(BomberBotProShielded, path=2), - Spawn(StickyBot, point=Point.BOTTOM_RIGHT) - if player_count > 2 - else None, + ( + Spawn(StickyBot, point=Point.BOTTOM_RIGHT) + if player_count > 2 + else None + ), Spawn(BomberBotProShielded, path=2), Spawn(ExplodeyBot, point=Point.BOTTOM_LEFT), Spawn(BomberBotProShielded, path=2), - Spawn(BomberBotProShielded, path=2) - if player_count > 1 - else None, + ( + Spawn(BomberBotProShielded, path=2) + if player_count > 1 + else None + ), Spacing(duration=5.0), Spawn(StickyBot, point=Point.BOTTOM_LEFT), Spacing(duration=2.0), @@ -461,9 +490,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): l_offs = ( -80 if uiscale is bs.UIScale.SMALL - else -40 - if uiscale is bs.UIScale.MEDIUM - else 0 + else -40 if uiscale is bs.UIScale.MEDIUM else 0 ) self._lives_bg = bs.NodeActor( @@ -525,6 +552,18 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): if self._lives == 0: self._bots.stop_moving() self.continue_or_end_game() + + # Heartbeat behavior + if self._lives < 5: + hbtime = 0.39 + (0.21 * self._lives) + self._lives_hbtime = bs.Timer( + hbtime, lambda: self.heart_dyin(True, hbtime), repeat=True + ) + self.heart_dyin(True) + else: + self._lives_hbtime = None + self.heart_dyin(False) + assert self._lives_text is not None assert self._lives_text.node self._lives_text.node.text = str(self._lives) @@ -1366,3 +1405,43 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): def _set_can_end_wave(self) -> None: self._can_end_wave = True + + def heart_dyin(self, status: bool, time: float = 1.22) -> None: + """Makes the UI heart beat at low health.""" + assert self._lives_bg is not None + if self._lives_bg.node.exists(): + return + heart = self._lives_bg.node + + # Make the heart beat intensely! + if status: + bs.animate_array( + heart, + 'scale', + 2, + { + 0: (90, 90), + time * 0.1: (105, 105), + time * 0.21: (88, 88), + time * 0.42: (90, 90), + time * 0.52: (105, 105), + time * 0.63: (88, 88), + time: (90, 90), + }, + ) + + # Neutralize heartbeat (Done did when dead.) + else: + # Ew; janky old scenev1 has a single 'Node' Python type so + # it thinks heart.scale could be a few different things + # (float, Sequence[float], etc.). So we have to force the + # issue with a cast(). This should go away with scenev2/etc. + bs.animate_array( + heart, + 'scale', + 2, + { + 0.0: cast(Sequence[float], heart.scale), + time: (90, 90), + }, + ) diff --git a/src/assets/ba_data/python/bascenev1lib/game/targetpractice.py b/src/assets/ba_data/python/bascenev1lib/game/targetpractice.py index fdff48f2..42993572 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/targetpractice.py +++ b/src/assets/ba_data/python/bascenev1lib/game/targetpractice.py @@ -321,11 +321,15 @@ class Target(bs.Actor): bs.getsound( 'orchestraHit4' if streak > 3 - else 'orchestraHit3' - if streak > 2 - else 'orchestraHit2' - if streak > 1 - else 'orchestraHit' + else ( + 'orchestraHit3' + if streak > 2 + else ( + 'orchestraHit2' + if streak > 1 + else 'orchestraHit' + ) + ) ).play() elif dist <= self._r2 + self._rfudge: self._nodes[0].color = cdull diff --git a/src/assets/ba_data/python/bauiv1/_subsystem.py b/src/assets/ba_data/python/bauiv1/_subsystem.py index 34d7f5af..e5549609 100644 --- a/src/assets/ba_data/python/bauiv1/_subsystem.py +++ b/src/assets/ba_data/python/bauiv1/_subsystem.py @@ -43,7 +43,10 @@ class UIV1Subsystem(babase.AppSubsystem): self._uiscale: babase.UIScale - interfacetype = env['ui_scale'] + interfacetype = babase.app.config.get('UI Scale', env['ui_scale']) + if interfacetype == 'auto': + interfacetype = env['ui_scale'] + if interfacetype == 'large': self._uiscale = babase.UIScale.LARGE elif interfacetype == 'medium': diff --git a/src/assets/ba_data/python/bauiv1/_uitypes.py b/src/assets/ba_data/python/bauiv1/_uitypes.py index 2f93f227..2c60ad4c 100644 --- a/src/assets/ba_data/python/bauiv1/_uitypes.py +++ b/src/assets/ba_data/python/bauiv1/_uitypes.py @@ -164,9 +164,7 @@ class UIController: entrynew = ( self._dialog_stack[-1] if self._dialog_stack - else self._main_stack[-1] - if self._main_stack - else None + else self._main_stack[-1] if self._main_stack else None ) if entrynew is not None: entrynew.create() diff --git a/src/assets/ba_data/python/bauiv1/onscreenkeyboard.py b/src/assets/ba_data/python/bauiv1/onscreenkeyboard.py index e91972e2..dc020714 100644 --- a/src/assets/ba_data/python/bauiv1/onscreenkeyboard.py +++ b/src/assets/ba_data/python/bauiv1/onscreenkeyboard.py @@ -41,15 +41,13 @@ class OnScreenKeyboardWindow(Window): scale=( 2.0 if uiscale is babase.UIScale.SMALL - else 1.5 - if uiscale is babase.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is babase.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, 0) + if uiscale is babase.UIScale.SMALL + else (0, 0) if uiscale is babase.UIScale.MEDIUM else (0, 0) ), - stack_offset=(0, 0) - if uiscale is babase.UIScale.SMALL - else (0, 0) - if uiscale is babase.UIScale.MEDIUM - else (0, 0), ) ) self._cancel_button = _bauiv1.buttonwidget( @@ -300,9 +298,11 @@ class OnScreenKeyboardWindow(Window): chars = [c.upper() for c in chars] _bauiv1.buttonwidget( edit=self._shift_button, - color=self._key_color_lit - if self._mode == 'caps' - else self._key_color_dark, + color=( + self._key_color_lit + if self._mode == 'caps' + else self._key_color_dark + ), label=babase.charstr(babase.SpecialChar.SHIFT), on_activate_call=self._shift, ) diff --git a/src/assets/ba_data/python/bauiv1lib/account/link.py b/src/assets/ba_data/python/bauiv1lib/account/link.py index 3f1ceb77..79c4fd85 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/link.py +++ b/src/assets/ba_data/python/bauiv1lib/account/link.py @@ -38,9 +38,7 @@ class AccountLinkWindow(bui.Window): base_scale = ( 1.65 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.1 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.1 ) super().__init__( root_widget=bui.containerwidget( @@ -48,9 +46,9 @@ class AccountLinkWindow(bui.Window): transition=transition, scale=base_scale, scale_origin_stack_offset=scale_origin, - stack_offset=(0, -10) - if uiscale is bui.UIScale.SMALL - else (0, 0), + stack_offset=( + (0, -10) if uiscale is bui.UIScale.SMALL else (0, 0) + ), ) ) self._cancel_button = bui.buttonwidget( @@ -159,9 +157,7 @@ class AccountLinkCodeWindow(bui.Window): scale=( 1.8 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/account/settings.py b/src/assets/ba_data/python/bauiv1lib/account/settings.py index f9eab7c7..00448630 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/settings.py +++ b/src/assets/ba_data/python/bauiv1lib/account/settings.py @@ -74,9 +74,7 @@ class AccountSettingsWindow(bui.Window): self._height = ( 390 if uiscale is bui.UIScale.SMALL - else 430 - if uiscale is bui.UIScale.MEDIUM - else 490 + else 430 if uiscale is bui.UIScale.MEDIUM else 490 ) self._sign_in_button = None @@ -112,13 +110,11 @@ class AccountSettingsWindow(bui.Window): scale=( 2.09 if uiscale is bui.UIScale.SMALL - else 1.4 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -19) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -19) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) if uiscale is bui.UIScale.SMALL and app.ui_v1.use_toolbars: @@ -928,9 +924,9 @@ class AccountSettingsWindow(bui.Window): if gpgs_active else 'achievementsIcon' ), - icon_color=(0.8, 0.95, 0.7) - if gpgs_active - else (0.85, 0.8, 0.9), + icon_color=( + (0.8, 0.95, 0.7) if gpgs_active else (0.85, 0.8, 0.9) + ), on_activate_call=( self._on_custom_achievements_press if gpgs_active diff --git a/src/assets/ba_data/python/bauiv1lib/account/unlink.py b/src/assets/ba_data/python/bauiv1lib/account/unlink.py index aa1a9937..ef80dad3 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/unlink.py +++ b/src/assets/ba_data/python/bauiv1lib/account/unlink.py @@ -39,9 +39,7 @@ class AccountUnlinkWindow(bui.Window): base_scale = ( 2.0 if uiscale is bui.UIScale.SMALL - else 1.6 - if uiscale is bui.UIScale.MEDIUM - else 1.1 + else 1.6 if uiscale is bui.UIScale.MEDIUM else 1.1 ) super().__init__( root_widget=bui.containerwidget( @@ -49,9 +47,9 @@ class AccountUnlinkWindow(bui.Window): transition=transition, scale=base_scale, scale_origin_stack_offset=scale_origin, - stack_offset=(0, -10) - if uiscale is bui.UIScale.SMALL - else (0, 0), + stack_offset=( + (0, -10) if uiscale is bui.UIScale.SMALL else (0, 0) + ), ) ) self._cancel_button = bui.buttonwidget( diff --git a/src/assets/ba_data/python/bauiv1lib/account/v2proxy.py b/src/assets/ba_data/python/bauiv1lib/account/v2proxy.py index 756ea612..52d93ea5 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/v2proxy.py +++ b/src/assets/ba_data/python/bauiv1lib/account/v2proxy.py @@ -34,9 +34,7 @@ class V2ProxySignInWindow(bui.Window): scale=( 1.25 if uiscale is bui.UIScale.SMALL - else 1.05 - if uiscale is bui.UIScale.MEDIUM - else 0.9 + else 1.05 if uiscale is bui.UIScale.MEDIUM else 0.9 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/account/viewer.py b/src/assets/ba_data/python/bauiv1lib/account/viewer.py index 9046a805..cf3c90bf 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/viewer.py +++ b/src/assets/ba_data/python/bauiv1lib/account/viewer.py @@ -43,9 +43,7 @@ class AccountViewerWindow(PopupWindow): scale = ( 2.6 if uiscale is bui.UIScale.SMALL - else 1.8 - if uiscale is bui.UIScale.MEDIUM - else 1.4 + else 1.8 if uiscale is bui.UIScale.MEDIUM else 1.4 ) self._transitioning_out = False @@ -53,9 +51,7 @@ class AccountViewerWindow(PopupWindow): self._height = ( 300 if uiscale is bui.UIScale.SMALL - else 400 - if uiscale is bui.UIScale.MEDIUM - else 450 + else 400 if uiscale is bui.UIScale.MEDIUM else 450 ) self._subcontainer: bui.Widget | None = None @@ -186,9 +182,7 @@ class AccountViewerWindow(PopupWindow): scale=( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ), choices=choices, choices_display=choices_display, diff --git a/src/assets/ba_data/python/bauiv1lib/achievements.py b/src/assets/ba_data/python/bauiv1lib/achievements.py index df2345d5..6a065f1f 100644 --- a/src/assets/ba_data/python/bauiv1lib/achievements.py +++ b/src/assets/ba_data/python/bauiv1lib/achievements.py @@ -23,18 +23,14 @@ class AchievementsWindow(PopupWindow): scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._transitioning_out = False self._width = 450 self._height = ( 300 if uiscale is bui.UIScale.SMALL - else 370 - if uiscale is bui.UIScale.MEDIUM - else 450 + else 370 if uiscale is bui.UIScale.MEDIUM else 450 ) bg_color = (0.5, 0.4, 0.6) @@ -126,9 +122,11 @@ class AchievementsWindow(PopupWindow): bui.imagewidget( parent=self._subcontainer, - position=(sub_width * 0.10 + 1, sub_height - 20 - incr * i - 9) - if complete - else (sub_width * 0.10 - 4, sub_height - 20 - incr * i - 14), + position=( + (sub_width * 0.10 + 1, sub_height - 20 - incr * i - 9) + if complete + else (sub_width * 0.10 - 4, sub_height - 20 - incr * i - 14) + ), size=(18, 18) if complete else (27, 27), opacity=1.0 if complete else 0.3, color=ach.get_icon_color(complete)[:3], @@ -167,9 +165,11 @@ class AchievementsWindow(PopupWindow): flatness=1.0, shadow=0.0, color=(0.83, 0.8, 0.85) if complete else (0.8, 0.8, 0.8, 0.2), - text=ach.description_full_complete - if complete - else ach.description_full, + text=( + ach.description_full_complete + if complete + else ach.description_full + ), size=(0, 0), h_align='left', v_align='center', diff --git a/src/assets/ba_data/python/bauiv1lib/appinvite.py b/src/assets/ba_data/python/bauiv1lib/appinvite.py index 06305e36..4bcbbcb7 100644 --- a/src/assets/ba_data/python/bauiv1lib/appinvite.py +++ b/src/assets/ba_data/python/bauiv1lib/appinvite.py @@ -31,9 +31,7 @@ class ShowFriendCodeWindow(bui.Window): scale=( 1.7 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/characterpicker.py b/src/assets/ba_data/python/bauiv1lib/characterpicker.py index 92194e2b..a5881ae5 100644 --- a/src/assets/ba_data/python/bauiv1lib/characterpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/characterpicker.py @@ -41,9 +41,7 @@ class CharacterPicker(PopupWindow): scale = ( 1.85 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._delegate = delegate diff --git a/src/assets/ba_data/python/bauiv1lib/colorpicker.py b/src/assets/ba_data/python/bauiv1lib/colorpicker.py index 30887432..7a6c281e 100644 --- a/src/assets/ba_data/python/bauiv1lib/colorpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/colorpicker.py @@ -43,9 +43,7 @@ class ColorPicker(PopupWindow): scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._parent = parent self._position = position @@ -206,9 +204,7 @@ class ColorPickerExact(PopupWindow): scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._delegate = delegate self._transitioning_out = False diff --git a/src/assets/ba_data/python/bauiv1lib/config.py b/src/assets/ba_data/python/bauiv1lib/config.py index 763a3704..255dd6d3 100644 --- a/src/assets/ba_data/python/bauiv1lib/config.py +++ b/src/assets/ba_data/python/bauiv1lib/config.py @@ -94,6 +94,8 @@ class ConfigNumberEdit: changesound: bool = True, textscale: float = 1.0, as_percent: bool = False, + fallback_value: float = 0.0, + f: int = 1, ): if displayname is None: displayname = configkey @@ -103,8 +105,12 @@ class ConfigNumberEdit: self._maxval = maxval self._increment = increment self._callback = callback - self._value = bui.app.config.resolve(configkey) + try: + self._value = bui.app.config.resolve(configkey) + except ValueError: + self._value = bui.app.config.get(configkey, fallback_value) self._as_percent = as_percent + self._f = f self.nametext = bui.textwidget( parent=parent, @@ -171,5 +177,5 @@ class ConfigNumberEdit: if self._as_percent: val = f'{round(self._value*100.0)}%' else: - val = f'{self._value:.1f}' + val = f'{self._value:.{self._f}f}' bui.textwidget(edit=self.valuetext, text=val) diff --git a/src/assets/ba_data/python/bauiv1lib/confirm.py b/src/assets/ba_data/python/bauiv1lib/confirm.py index 2882b598..69e3ccd5 100644 --- a/src/assets/ba_data/python/bauiv1lib/confirm.py +++ b/src/assets/ba_data/python/bauiv1lib/confirm.py @@ -61,9 +61,7 @@ class ConfirmWindow: scale=( 2.1 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 ), scale_origin_stack_offset=scale_origin, ) @@ -187,8 +185,10 @@ class QuitWindow: resource=quit_resource, subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], ), - lambda: bui.quit(confirm=False, quit_type=self._quit_type) - if self._quit_type is not None - else bui.quit(confirm=False), + lambda: ( + bui.quit(confirm=False, quit_type=self._quit_type) + if self._quit_type is not None + else bui.quit(confirm=False) + ), origin_widget=origin_widget, ).root_widget diff --git a/src/assets/ba_data/python/bauiv1lib/coop/gamebutton.py b/src/assets/ba_data/python/bauiv1lib/coop/gamebutton.py index c24d3909..5172e3a6 100644 --- a/src/assets/ba_data/python/bauiv1lib/coop/gamebutton.py +++ b/src/assets/ba_data/python/bauiv1lib/coop/gamebutton.py @@ -148,9 +148,11 @@ class GameButton: draw_controller=btn, position=(xach, yach), size=(a_scale, a_scale), - color=tuple(ach.get_icon_color(a_complete)[:3]) - if a_complete - else (1.2, 1.2, 1.2), + color=( + tuple(ach.get_icon_color(a_complete)[:3]) + if a_complete + else (1.2, 1.2, 1.2) + ), texture=ach.get_icon_ui_texture(a_complete), ) imw2 = bui.imagewidget( @@ -307,8 +309,6 @@ class GameButton: opacity=( 1.0 if (a_complete and unlocked) - else 0.2 - if a_complete - else 0.0 + else 0.2 if a_complete else 0.0 ), ) diff --git a/src/assets/ba_data/python/bauiv1lib/coop/level.py b/src/assets/ba_data/python/bauiv1lib/coop/level.py index b3e6d477..e3bfcaa5 100644 --- a/src/assets/ba_data/python/bauiv1lib/coop/level.py +++ b/src/assets/ba_data/python/bauiv1lib/coop/level.py @@ -23,9 +23,7 @@ class CoopLevelLockedWindow(bui.Window): scale=( 1.7 if uiscale is bui.UIScale.SMALL - else 1.3 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/coop/tournamentbutton.py b/src/assets/ba_data/python/bauiv1lib/coop/tournamentbutton.py index 4b766379..0ee8a597 100644 --- a/src/assets/ba_data/python/bauiv1lib/coop/tournamentbutton.py +++ b/src/assets/ba_data/python/bauiv1lib/coop/tournamentbutton.py @@ -417,9 +417,7 @@ class TournamentButton: prize_y_offs = ( 34 if 'prizeRange3' in entry - else 20 - if 'prizeRange2' in entry - else 12 + else 20 if 'prizeRange2' in entry else 12 ) x_offs = 90 @@ -460,9 +458,11 @@ class TournamentButton: bui.textwidget( edit=self.prize_value_1_text, text='-' if pv1 == '' else pv1, - scale=prize_value_scale_large - if ticket_char not in pv1 - else prize_value_scale_small, + scale=( + prize_value_scale_large + if ticket_char not in pv1 + else prize_value_scale_small + ), position=( self.button_x + 380 + x_offs, self.button_y + self.button_scale_y - 93 + prize_y_offs, @@ -480,9 +480,11 @@ class TournamentButton: bui.textwidget( edit=self.prize_value_2_text, text=pv2, - scale=prize_value_scale_large - if ticket_char not in pv2 - else prize_value_scale_small, + scale=( + prize_value_scale_large + if ticket_char not in pv2 + else prize_value_scale_small + ), position=( self.button_x + 380 + x_offs, self.button_y + self.button_scale_y - 93 - 45 + prize_y_offs, @@ -500,9 +502,11 @@ class TournamentButton: bui.textwidget( edit=self.prize_value_3_text, text=pv3, - scale=prize_value_scale_large - if ticket_char not in pv3 - else prize_value_scale_small, + scale=( + prize_value_scale_large + if ticket_char not in pv3 + else prize_value_scale_small + ), position=( self.button_x + 380 + x_offs, self.button_y + self.button_scale_y - 93 - 90 + prize_y_offs, @@ -667,9 +671,11 @@ class TournamentButton: self.button_x + 360, self.button_y + self.button_scale_y - 146, ), - text='' - if ad_tries_remaining in [None, 0] - else ('' + str(ad_tries_remaining)), + text=( + '' + if ad_tries_remaining in [None, 0] + else ('' + str(ad_tries_remaining)) + ), color=(0.6, 0.6, 0.6, 1 if ads_enabled else 0.2), ) else: diff --git a/src/assets/ba_data/python/bauiv1lib/creditslist.py b/src/assets/ba_data/python/bauiv1lib/creditslist.py index c087dfbf..f25449f3 100644 --- a/src/assets/ba_data/python/bauiv1lib/creditslist.py +++ b/src/assets/ba_data/python/bauiv1lib/creditslist.py @@ -51,13 +51,11 @@ class CreditsListWindow(bui.Window): scale=( 2.0 if uiscale is bui.UIScale.SMALL - else 1.3 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -8) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -8) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/debug.py b/src/assets/ba_data/python/bauiv1lib/debug.py index b397610f..5bcf38fb 100644 --- a/src/assets/ba_data/python/bauiv1lib/debug.py +++ b/src/assets/ba_data/python/bauiv1lib/debug.py @@ -25,9 +25,7 @@ class DebugWindow(bui.Window): self._height = height = ( 350 if uiscale is bui.UIScale.SMALL - else 420 - if uiscale is bui.UIScale.MEDIUM - else 520 + else 420 if uiscale is bui.UIScale.MEDIUM else 520 ) self._scroll_width = self._width - 100 @@ -50,13 +48,11 @@ class DebugWindow(bui.Window): scale=( 2.35 if uiscale is bui.UIScale.SMALL - else 1.55 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.55 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -30) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -30) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/discord.py b/src/assets/ba_data/python/bauiv1lib/discord.py index 2e2eb520..de891b29 100644 --- a/src/assets/ba_data/python/bauiv1lib/discord.py +++ b/src/assets/ba_data/python/bauiv1lib/discord.py @@ -45,9 +45,7 @@ class DiscordWindow(bui.Window): scale=( 1.6 if uiscale is bui.UIScale.SMALL - else 1.3 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 ), stack_offset=(0, 5) if uiscale is bui.UIScale.SMALL else (0, 0), ) diff --git a/src/assets/ba_data/python/bauiv1lib/feedback.py b/src/assets/ba_data/python/bauiv1lib/feedback.py index 09568a3f..6767bbee 100644 --- a/src/assets/ba_data/python/bauiv1lib/feedback.py +++ b/src/assets/ba_data/python/bauiv1lib/feedback.py @@ -33,9 +33,7 @@ def ask_for_rating() -> bui.Widget | None: scale=( 1.6 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) v = height - 50 diff --git a/src/assets/ba_data/python/bauiv1lib/fileselector.py b/src/assets/ba_data/python/bauiv1lib/fileselector.py index e9cf0ca6..427df3fb 100644 --- a/src/assets/ba_data/python/bauiv1lib/fileselector.py +++ b/src/assets/ba_data/python/bauiv1lib/fileselector.py @@ -57,13 +57,11 @@ class FileSelectorWindow(bui.Window): scale=( 2.23 if uiscale is bui.UIScale.SMALL - else 1.4 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -35) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -35) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) bui.textwidget( @@ -73,11 +71,15 @@ class FileSelectorWindow(bui.Window): color=bui.app.ui_v1.title_color, h_align='center', v_align='center', - text=bui.Lstr(resource=self._r + '.titleFolderText') - if (allow_folders and not valid_file_extensions) - else bui.Lstr(resource=self._r + '.titleFileText') - if not allow_folders - else bui.Lstr(resource=self._r + '.titleFileFolderText'), + text=( + bui.Lstr(resource=self._r + '.titleFolderText') + if (allow_folders and not valid_file_extensions) + else ( + bui.Lstr(resource=self._r + '.titleFileText') + if not allow_folders + else bui.Lstr(resource=self._r + '.titleFileFolderText') + ) + ), maxwidth=210, ) @@ -444,9 +446,11 @@ class FileSelectorWindow(bui.Window): position=(10 + folder_icon_size * 1.05, entry_height * 0.5), size=(0, 0), maxwidth=self._scroll_width * 0.93 - 50, - color=(1, 1, 1, 1) - if (is_valid_file_path or is_dir) - else (0.5, 0.5, 0.5, 1), + color=( + (1, 1, 1, 1) + if (is_valid_file_path or is_dir) + else (0.5, 0.5, 0.5, 1) + ), ) v -= entry_height diff --git a/src/assets/ba_data/python/bauiv1lib/gather/__init__.py b/src/assets/ba_data/python/bauiv1lib/gather/__init__.py index 61efe323..710e36c1 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/__init__.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/__init__.py @@ -99,9 +99,7 @@ class GatherWindow(bui.Window): self._height = ( 582 if uiscale is bui.UIScale.SMALL - else 680 - if uiscale is bui.UIScale.MEDIUM - else 800 + else 680 if uiscale is bui.UIScale.MEDIUM else 800 ) self._current_tab: GatherWindow.TabID | None = None extra_top = 20 if uiscale is bui.UIScale.SMALL else 0 @@ -116,15 +114,13 @@ class GatherWindow(bui.Window): scale=( 1.3 if uiscale is bui.UIScale.SMALL - else 0.97 - if uiscale is bui.UIScale.MEDIUM - else 0.8 + else 0.97 if uiscale is bui.UIScale.MEDIUM else 0.8 + ), + stack_offset=( + (0, -11) + if uiscale is bui.UIScale.SMALL + else (0, 0) if uiscale is bui.UIScale.MEDIUM else (0, 0) ), - stack_offset=(0, -11) - if uiscale is bui.UIScale.SMALL - else (0, 0) - if uiscale is bui.UIScale.MEDIUM - else (0, 0), ) ) @@ -165,9 +161,7 @@ class GatherWindow(bui.Window): scale=( 1.5 if not condensed - else 1.0 - if uiscale is bui.UIScale.MEDIUM - else 0.6 + else 1.0 if uiscale is bui.UIScale.MEDIUM else 0.6 ), h_align='center', v_align='center', diff --git a/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py b/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py index 1257c4bd..7e0a6caa 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py @@ -44,9 +44,7 @@ class AboutGatherTab(GatherTab): message_height = ( 210 if uiscale is bui.UIScale.SMALL - else 305 - if uiscale is bui.UIScale.MEDIUM - else 370 + else 305 if uiscale is bui.UIScale.MEDIUM else 370 ) # Let's not talk about sharing in vr-mode; its tricky to fit more # than one head in a VR-headset. diff --git a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py index 8b6cf7fb..2b73ec47 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py @@ -837,9 +837,7 @@ class PrivateGatherTab(GatherTab): color=( (0.6, 0.6, 0.6) if disabled - else (0.5, 1.0, 0.5) - if waiting - else None + else (0.5, 1.0, 0.5) if waiting else None ), enable_sound=False, label=btnlabel, diff --git a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py index 83b3b534..a0e1b8ed 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py @@ -204,11 +204,11 @@ class UIRow: bui.textwidget( edit=self._ping_widget, text=str(int(party.ping)), - color=(0, 1, 0) - if party.ping <= ping_good - else (1, 1, 0) - if party.ping <= ping_med - else (1, 0, 0), + color=( + (0, 1, 0) + if party.ping <= ping_good + else (1, 1, 0) if party.ping <= ping_med else (1, 0, 0) + ), ) party.clean_display_index = index @@ -369,8 +369,8 @@ class PublicGatherTab(GatherTab): self._join_status_text: bui.Widget | None = None self._no_servers_found_text: bui.Widget | None = None self._host_max_party_size_value: bui.Widget | None = None - self._host_max_party_size_minus_button: (bui.Widget | None) = None - self._host_max_party_size_plus_button: (bui.Widget | None) = None + self._host_max_party_size_minus_button: bui.Widget | None = None + self._host_max_party_size_plus_button: bui.Widget | None = None self._host_status_text: bui.Widget | None = None self._signed_in = False self._ui_rows: list[UIRow] = [] @@ -800,9 +800,11 @@ class PublicGatherTab(GatherTab): parent=self._container, label=label, size=(400, 80), - on_activate_call=self._on_stop_advertising_press - if is_public_enabled - else self._on_start_advertizing_press, + on_activate_call=( + self._on_stop_advertising_press + if is_public_enabled + else self._on_start_advertizing_press + ), position=(c_width * 0.5 - 200, v), autoselect=True, up_widget=btn2, diff --git a/src/assets/ba_data/python/bauiv1lib/getcurrency.py b/src/assets/ba_data/python/bauiv1lib/getcurrency.py index 6e355d42..e04666b6 100644 --- a/src/assets/ba_data/python/bauiv1lib/getcurrency.py +++ b/src/assets/ba_data/python/bauiv1lib/getcurrency.py @@ -72,13 +72,11 @@ class GetCurrencyWindow(bui.Window): scale=( 1.63 if uiscale is bui.UIScale.SMALL - else 1.2 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.2 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -3) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -3) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) @@ -605,11 +603,11 @@ class GetCurrencyWindow(bui.Window): self._smooth_increase_speed = ( diff / 100.0 if diff >= 5000 - else diff / 50.0 - if diff >= 1500 - else diff / 30.0 - if diff >= 500 - else diff / 15.0 + else ( + diff / 50.0 + if diff >= 1500 + else diff / 30.0 if diff >= 500 else diff / 15.0 + ) ) def _disabled_press(self) -> None: diff --git a/src/assets/ba_data/python/bauiv1lib/getremote.py b/src/assets/ba_data/python/bauiv1lib/getremote.py index 0cea25ae..7f4e2be0 100644 --- a/src/assets/ba_data/python/bauiv1lib/getremote.py +++ b/src/assets/ba_data/python/bauiv1lib/getremote.py @@ -20,9 +20,7 @@ class GetBSRemoteWindow(PopupWindow): scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._transitioning_out = False self._width = 570 diff --git a/src/assets/ba_data/python/bauiv1lib/helpui.py b/src/assets/ba_data/python/bauiv1lib/helpui.py index e1981aad..0a3de5fa 100644 --- a/src/assets/ba_data/python/bauiv1lib/helpui.py +++ b/src/assets/ba_data/python/bauiv1lib/helpui.py @@ -41,9 +41,7 @@ class HelpWindow(bui.Window): height = ( 460 if uiscale is bui.UIScale.SMALL - else 530 - if uiscale is bui.UIScale.MEDIUM - else 600 + else 530 if uiscale is bui.UIScale.MEDIUM else 600 ) super().__init__( @@ -55,15 +53,13 @@ class HelpWindow(bui.Window): scale=( 1.77 if uiscale is bui.UIScale.SMALL - else 1.25 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.25 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -30) + if uiscale is bui.UIScale.SMALL + else (0, 15) if uiscale is bui.UIScale.MEDIUM else (0, 0) ), - stack_offset=(0, -30) - if uiscale is bui.UIScale.SMALL - else (0, 15) - if uiscale is bui.UIScale.MEDIUM - else (0, 0), ) ) @@ -119,9 +115,11 @@ class HelpWindow(bui.Window): ), size=(140, 60), scale=0.7 if uiscale is bui.UIScale.SMALL else 0.8, - label=bui.Lstr(resource='backText') - if self._main_menu - else 'Close', + label=( + bui.Lstr(resource='backText') + if self._main_menu + else 'Close' + ), button_type='back' if self._main_menu else None, extra_touch_border_scale=2.0, autoselect=True, diff --git a/src/assets/ba_data/python/bauiv1lib/iconpicker.py b/src/assets/ba_data/python/bauiv1lib/iconpicker.py index 260bbdec..3abd3f42 100644 --- a/src/assets/ba_data/python/bauiv1lib/iconpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/iconpicker.py @@ -40,9 +40,7 @@ class IconPicker(PopupWindow): scale = ( 1.85 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._delegate = delegate diff --git a/src/assets/ba_data/python/bauiv1lib/kiosk.py b/src/assets/ba_data/python/bauiv1lib/kiosk.py index ab1ca87e..3543e5ce 100644 --- a/src/assets/ba_data/python/bauiv1lib/kiosk.py +++ b/src/assets/ba_data/python/bauiv1lib/kiosk.py @@ -472,9 +472,9 @@ class KioskWindow(bui.Window): 'type': 'bs_hockey.HockeyGame', } ] - appconfig[ - 'Team Tournament Playlist Selection' - ] = 'Just Hockey' + appconfig['Team Tournament Playlist Selection'] = ( + 'Just Hockey' + ) bui.fade_screen( False, endcall=bui.Call( @@ -488,9 +488,11 @@ class KioskWindow(bui.Window): game = ( 'Easy:Onslaught Training' if mode == 'easy' - else 'Easy:Rookie Football' - if mode == 'medium' - else 'Easy:Uber Onslaught' + else ( + 'Easy:Rookie Football' + if mode == 'medium' + else 'Easy:Uber Onslaught' + ) ) cfg = bui.app.config cfg['Selected Coop Game'] = game diff --git a/src/assets/ba_data/python/bauiv1lib/league/rankwindow.py b/src/assets/ba_data/python/bauiv1lib/league/rankwindow.py index 725bb318..7e6d8d1e 100644 --- a/src/assets/ba_data/python/bauiv1lib/league/rankwindow.py +++ b/src/assets/ba_data/python/bauiv1lib/league/rankwindow.py @@ -63,9 +63,7 @@ class LeagueRankWindow(bui.Window): self._height = ( 657 if uiscale is bui.UIScale.SMALL - else 710 - if uiscale is bui.UIScale.MEDIUM - else 800 + else 710 if uiscale is bui.UIScale.MEDIUM else 800 ) self._r = 'coopSelectWindow' self._rdict = bui.app.lang.get_resource(self._r) @@ -79,19 +77,17 @@ class LeagueRankWindow(bui.Window): super().__init__( root_widget=bui.containerwidget( size=(self._width, self._height + top_extra), - stack_offset=(0, -15) - if uiscale is bui.UIScale.SMALL - else (0, 10) - if uiscale is bui.UIScale.MEDIUM - else (0, 0), + stack_offset=( + (0, -15) + if uiscale is bui.UIScale.SMALL + else (0, 10) if uiscale is bui.UIScale.MEDIUM else (0, 0) + ), transition=transition, scale_origin_stack_offset=scale_origin, scale=( 1.2 if uiscale is bui.UIScale.SMALL - else 0.93 - if uiscale is bui.UIScale.MEDIUM - else 0.8 + else 0.93 if uiscale is bui.UIScale.MEDIUM else 0.8 ), ) ) @@ -210,9 +206,11 @@ class LeagueRankWindow(bui.Window): assert plus is not None txt = bui.Lstr( - resource='coopSelectWindow.activenessAllTimeInfoText' - if self._season == 'a' - else 'coopSelectWindow.activenessInfoText', + resource=( + 'coopSelectWindow.activenessAllTimeInfoText' + if self._season == 'a' + else 'coopSelectWindow.activenessInfoText' + ), subs=[ ( '${MAX}', @@ -853,9 +851,11 @@ class LeagueRankWindow(bui.Window): bui.textwidget( edit=self._league_title_text, - text='' - if self._season == 'a' - else bui.Lstr(resource='league.leagueText'), + text=( + '' + if self._season == 'a' + else bui.Lstr(resource='league.leagueText') + ), ) if data is None: @@ -910,9 +910,11 @@ class LeagueRankWindow(bui.Window): bui.textwidget(edit=self._season_ends_text, text=to_end_string) bui.textwidget( edit=self._trophy_counts_reset_text, - text=bui.Lstr(resource='league.trophyCountsResetText') - if self._is_current_season and show_season_end - else '', + text=( + bui.Lstr(resource='league.trophyCountsResetText') + if self._is_current_season and show_season_end + else '' + ), ) bui.textwidget(edit=self._league_text, text=lname, color=lcolor) @@ -932,21 +934,25 @@ class LeagueRankWindow(bui.Window): ) bui.textwidget( edit=self._to_ranked_text, - text=bui.Lstr(resource='coopSelectWindow.toRankedText').evaluate() - + '' - + extra_text - if do_percent - else '', + text=( + bui.Lstr(resource='coopSelectWindow.toRankedText').evaluate() + + '' + + extra_text + if do_percent + else '' + ), ) bui.textwidget( edit=self._your_power_ranking_text, - text=bui.Lstr( - resource='rankText', - fallback_resource='coopSelectWindow.yourPowerRankingText', - ) - if (not do_percent) - else '', + text=( + bui.Lstr( + resource='rankText', + fallback_resource='coopSelectWindow.yourPowerRankingText', + ) + if (not do_percent) + else '' + ), ) bui.textwidget( @@ -954,11 +960,11 @@ class LeagueRankWindow(bui.Window): position=(473, v - 70 - (170 if do_percent else 220)), text=status_text, big=(in_top or do_percent), - scale=3.0 - if (in_top or do_percent) - else 0.7 - if finished_season_unranked - else 1.0, + scale=( + 3.0 + if (in_top or do_percent) + else 0.7 if finished_season_unranked else 1.0 + ), ) if self._activity_mult_button is not None: @@ -992,9 +998,11 @@ class LeagueRankWindow(bui.Window): # pylint: disable=consider-using-f-string bui.textwidget( edit=self._pro_mult_text, - text=' -' - if (data is None or not have_pro) - else 'x ' + ('%.2f' % pro_mult), + text=( + ' -' + if (data is None or not have_pro) + else 'x ' + ('%.2f' % pro_mult) + ), ) bui.buttonwidget( edit=self._pro_mult_button, @@ -1019,9 +1027,11 @@ class LeagueRankWindow(bui.Window): bui.textwidget( edit=self._power_ranking_achievement_total_text, - text='-' - if data is None - else ('+ ' + pts_txt.replace('${NUMBER}', str(total_ach_value))), + text=( + '-' + if data is None + else ('+ ' + pts_txt.replace('${NUMBER}', str(total_ach_value))) + ), ) total_trophies_count = accounts.get_league_rank_points( @@ -1035,19 +1045,24 @@ class LeagueRankWindow(bui.Window): ) bui.textwidget( edit=self._power_ranking_trophies_total_text, - text='-' - if data is None - else ( - '+ ' + pts_txt.replace('${NUMBER}', str(total_trophies_value)) + text=( + '-' + if data is None + else ( + '+ ' + + pts_txt.replace('${NUMBER}', str(total_trophies_value)) + ) ), ) bui.textwidget( edit=self._power_ranking_total_text, - text='-' - if data is None - else eq_text.replace( - '${NUMBER}', str(accounts.get_league_rank_points(data)) + text=( + '-' + if data is None + else eq_text.replace( + '${NUMBER}', str(accounts.get_league_rank_points(data)) + ) ), ) for widget in self._power_ranking_score_widgets: diff --git a/src/assets/ba_data/python/bauiv1lib/mainmenu.py b/src/assets/ba_data/python/bauiv1lib/mainmenu.py index bec93e9c..48242d9c 100644 --- a/src/assets/ba_data/python/bauiv1lib/mainmenu.py +++ b/src/assets/ba_data/python/bauiv1lib/mainmenu.py @@ -43,9 +43,11 @@ class MainMenuWindow(bui.Window): super().__init__( root_widget=bui.containerwidget( transition=transition, - toolbar_visibility='menu_minimal_no_back' - if self._in_game - else 'menu_minimal_no_back', + toolbar_visibility=( + 'menu_minimal_no_back' + if self._in_game + else 'menu_minimal_no_back' + ), ) ) @@ -142,9 +144,11 @@ class MainMenuWindow(bui.Window): return ( 'storeCharacterXmas' if plus.get_v1_account_misc_read_val('xmas', False) - else 'storeCharacterEaster' - if plus.get_v1_account_misc_read_val('easter', False) - else 'storeCharacter' + else ( + 'storeCharacterEaster' + if plus.get_v1_account_misc_read_val('easter', False) + else 'storeCharacter' + ) ) def _check_refresh(self) -> None: @@ -344,9 +348,7 @@ class MainMenuWindow(bui.Window): icon_size = ( 55 if uiscale is bui.UIScale.SMALL - else 55 - if uiscale is bui.UIScale.MEDIUM - else 70 + else 55 if uiscale is bui.UIScale.MEDIUM else 70 ) bui.imagewidget( parent=self._root_widget, @@ -452,7 +454,7 @@ class MainMenuWindow(bui.Window): resource='watchWindow.playbackSpeedText', subs=[('${SPEED}', str(1.23))], ), - position=(h, v + v_offs + 7 * t_scale), + position=(h, v + v_offs + 15 * t_scale), h_align='center', v_align='center', size=(0, 0), @@ -526,6 +528,64 @@ class MainMenuWindow(bui.Window): autoselect=True, on_activate_call=bui.Call(self._pause_or_resume_replay), ) + btn = bui.buttonwidget( + parent=self._root_widget, + position=( + h - b_size * 1.5 - b_buffer_1 * 2, + v - b_size - b_buffer_2 + v_offs, + ), + button_type='square', + size=(b_size, b_size), + label='', + autoselect=True, + on_activate_call=bui.WeakCall(self._rewind_replay), + ) + bui.textwidget( + parent=self._root_widget, + draw_controller=btn, + # text='<<', + text=bui.charstr(bui.SpecialChar.REWIND_BUTTON), + position=( + h - b_size - b_buffer_1 * 2, + v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs, + ), + h_align='center', + v_align='center', + size=(0, 0), + scale=2.0 * t_scale, + ) + btn = bui.buttonwidget( + parent=self._root_widget, + position=( + h + b_size * 0.5 + b_buffer_1 * 2, + v - b_size - b_buffer_2 + v_offs, + ), + button_type='square', + size=(b_size, b_size), + label='', + autoselect=True, + on_activate_call=bui.WeakCall(self._forward_replay), + ) + bui.textwidget( + parent=self._root_widget, + draw_controller=btn, + # text='>>', + text=bui.charstr(bui.SpecialChar.FAST_FORWARD_BUTTON), + position=( + h + b_size + b_buffer_1 * 2, + v - b_size * 0.5 - b_buffer_2 + 5 * t_scale + v_offs, + ), + h_align='center', + v_align='center', + size=(0, 0), + scale=2.0 * t_scale, + ) + + def _rewind_replay(self) -> None: + bs.seek_replay(-2 * pow(2, bs.get_replay_speed_exponent())) + + def _forward_replay(self) -> None: + bs.seek_replay(2 * pow(2, bs.get_replay_speed_exponent())) def _refresh_not_in_game( self, positions: list[tuple[float, float, float]] @@ -646,9 +706,11 @@ class MainMenuWindow(bui.Window): color=(0.45, 0.55, 0.45), textcolor=(0.7, 0.8, 0.7), label=bui.Lstr( - resource='modeArcadeText' - if bui.app.env.arcade - else 'modeDemoText' + resource=( + 'modeArcadeText' + if bui.app.env.arcade + else 'modeDemoText' + ) ), transition_delay=demo_menu_delay, on_activate_call=self._demo_menu_press, @@ -659,9 +721,7 @@ class MainMenuWindow(bui.Window): foof = ( -1 if uiscale is bui.UIScale.SMALL - else 1 - if uiscale is bui.UIScale.MEDIUM - else 3 + else 1 if uiscale is bui.UIScale.MEDIUM else 3 ) h, v, scale = positions[self._p_index] v = v + foof @@ -906,9 +966,7 @@ class MainMenuWindow(bui.Window): scale=( 2.15 if uiscale is bui.UIScale.SMALL - else 1.6 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.6 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) h = 125.0 @@ -1398,8 +1456,9 @@ class MainMenuWindow(bui.Window): def _resume(self) -> None: assert bui.app.classic is not None bui.app.classic.resume() - if self._root_widget: - bui.containerwidget(edit=self._root_widget, transition='out_right') + # if self._root_widget: + # bui.containerwidget(edit=self._root_widget, + # transition='out_right') bui.app.ui_v1.clear_main_menu_window(transition='out_right') # If there's callbacks waiting for this window to go away, call them. diff --git a/src/assets/ba_data/python/bauiv1lib/party.py b/src/assets/ba_data/python/bauiv1lib/party.py index e531b860..3e52fd45 100644 --- a/src/assets/ba_data/python/bauiv1lib/party.py +++ b/src/assets/ba_data/python/bauiv1lib/party.py @@ -36,9 +36,7 @@ class PartyWindow(bui.Window): self._height = ( 365 if uiscale is bui.UIScale.SMALL - else 480 - if uiscale is bui.UIScale.MEDIUM - else 600 + else 480 if uiscale is bui.UIScale.MEDIUM else 600 ) self._display_old_msgs = True super().__init__( @@ -52,15 +50,15 @@ class PartyWindow(bui.Window): scale=( 2.0 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -10) + if uiscale is bui.UIScale.SMALL + else ( + (240, 0) if uiscale is bui.UIScale.MEDIUM else (330, 20) + ) ), - stack_offset=(0, -10) - if uiscale is bui.UIScale.SMALL - else (240, 0) - if uiscale is bui.UIScale.MEDIUM - else (330, 20), ) ) @@ -251,9 +249,7 @@ class PartyWindow(bui.Window): scale=( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ), choices=choices, choices_display=choices_display, @@ -312,9 +308,7 @@ class PartyWindow(bui.Window): columns = ( 1 if len(self._roster) == 1 - else 2 - if len(self._roster) == 2 - else 3 + else 2 if len(self._roster) == 2 else 3 ) rows = int(math.ceil(float(len(self._roster)) / columns)) c_width = (self._width * 0.9) / max(3, columns) @@ -572,9 +566,7 @@ class PartyWindow(bui.Window): scale=( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ), choices=['kick'], choices_display=[kick_str], diff --git a/src/assets/ba_data/python/bauiv1lib/partyqueue.py b/src/assets/ba_data/python/bauiv1lib/partyqueue.py index 26c97bd6..147fabfc 100644 --- a/src/assets/ba_data/python/bauiv1lib/partyqueue.py +++ b/src/assets/ba_data/python/bauiv1lib/partyqueue.py @@ -274,9 +274,7 @@ class PartyQueueWindow(bui.Window): scale=( 1.4 if uiscale is bui.UIScale.SMALL - else 1.2 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.2 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/play.py b/src/assets/ba_data/python/bauiv1lib/play.py index ea52588c..eda60abd 100644 --- a/src/assets/ba_data/python/bauiv1lib/play.py +++ b/src/assets/ba_data/python/bauiv1lib/play.py @@ -57,9 +57,7 @@ class PlayWindow(bui.Window): scale=( 1.6 if uiscale is bui.UIScale.SMALL - else 0.9 - if uiscale is bui.UIScale.MEDIUM - else 0.8 + else 0.9 if uiscale is bui.UIScale.MEDIUM else 0.8 ), stack_offset=(0, 0) if uiscale is bui.UIScale.SMALL else (0, 0), ) @@ -83,9 +81,11 @@ class PlayWindow(bui.Window): # (101 if main_menu else 61)), size=(0, 0), text=bui.Lstr( - resource=(self._r + '.titleText') - if self._is_main_menu - else 'playlistsText' + resource=( + (self._r + '.titleText') + if self._is_main_menu + else 'playlistsText' + ) ), scale=1.7, res_scale=2.0, @@ -494,18 +494,22 @@ class PlayWindow(bui.Window): bui.containerwidget( edit=self._root_widget, on_cancel_call=self._back, - selected_child=self._coop_button - if self._is_main_menu - else self._teams_button, + selected_child=( + self._coop_button + if self._is_main_menu + else self._teams_button + ), ) else: bui.buttonwidget(edit=back_button, on_activate_call=self._back) bui.containerwidget( edit=self._root_widget, cancel_button=back_button, - selected_child=self._coop_button - if self._is_main_menu - else self._teams_button, + selected_child=( + self._coop_button + if self._is_main_menu + else self._teams_button + ), ) self._restore_state() diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py b/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py index c8acdb8a..dce81eec 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/addgame.py @@ -30,9 +30,7 @@ class PlaylistAddGameWindow(bui.Window): self._height = ( 346 if uiscale is bui.UIScale.SMALL - else 380 - if uiscale is bui.UIScale.MEDIUM - else 440 + else 380 if uiscale is bui.UIScale.MEDIUM else 440 ) top_extra = 30 if uiscale is bui.UIScale.SMALL else 20 self._scroll_width = 210 @@ -44,9 +42,7 @@ class PlaylistAddGameWindow(bui.Window): scale=( 2.17 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 ), stack_offset=(0, 1) if uiscale is bui.UIScale.SMALL else (0, 0), ) diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/browser.py b/src/assets/ba_data/python/bauiv1lib/playlist/browser.py index 806ab7aa..f8b1a73f 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/browser.py @@ -67,9 +67,7 @@ class PlaylistBrowserWindow(bui.Window): self._height = ( 480 if uiscale is bui.UIScale.SMALL - else 510 - if uiscale is bui.UIScale.MEDIUM - else 580 + else 510 if uiscale is bui.UIScale.MEDIUM else 580 ) top_extra = 20 if uiscale is bui.UIScale.SMALL else 0 @@ -83,13 +81,11 @@ class PlaylistBrowserWindow(bui.Window): scale=( 1.69 if uiscale is bui.UIScale.SMALL - else 1.05 - if uiscale is bui.UIScale.MEDIUM - else 0.9 + else 1.05 if uiscale is bui.UIScale.MEDIUM else 0.9 + ), + stack_offset=( + (0, -26) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -26) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) @@ -714,9 +710,9 @@ class PlaylistBrowserWindow(bui.Window): ) if self._selected_playlist != prev_sel: cfg = bui.app.config - cfg[ - self._pvars.config_name + ' Playlist Selection' - ] = self._selected_playlist + cfg[self._pvars.config_name + ' Playlist Selection'] = ( + self._selected_playlist + ) cfg.commit() self._save_state() diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/edit.py b/src/assets/ba_data/python/bauiv1lib/playlist/edit.py index 11e00190..d01badba 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/edit.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/edit.py @@ -36,9 +36,7 @@ class PlaylistEditWindow(bui.Window): self._height = ( 400 if uiscale is bui.UIScale.SMALL - else 470 - if uiscale is bui.UIScale.MEDIUM - else 540 + else 470 if uiscale is bui.UIScale.MEDIUM else 540 ) top_extra = 20 if uiscale is bui.UIScale.SMALL else 0 @@ -49,13 +47,11 @@ class PlaylistEditWindow(bui.Window): scale=( 2.0 if uiscale is bui.UIScale.SMALL - else 1.3 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -16) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -16) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) cancel_button = bui.buttonwidget( @@ -149,9 +145,7 @@ class PlaylistEditWindow(bui.Window): scl = ( 1.03 if uiscale is bui.UIScale.SMALL - else 1.36 - if uiscale is bui.UIScale.MEDIUM - else 1.74 + else 1.36 if uiscale is bui.UIScale.MEDIUM else 1.74 ) v -= 63.0 * scl diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/editgame.py b/src/assets/ba_data/python/bauiv1lib/playlist/editgame.py index 491608f9..c7dea649 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/editgame.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/editgame.py @@ -108,9 +108,7 @@ class PlaylistEditGameWindow(bui.Window): height = ( 365 if uiscale is bui.UIScale.SMALL - else 460 - if uiscale is bui.UIScale.MEDIUM - else 550 + else 460 if uiscale is bui.UIScale.MEDIUM else 550 ) spacing = 52 y_extra = 15 @@ -129,13 +127,11 @@ class PlaylistEditGameWindow(bui.Window): scale=( 2.19 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -17) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -17) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) @@ -143,9 +139,11 @@ class PlaylistEditGameWindow(bui.Window): parent=self._root_widget, position=(45 + x_inset, height - 82 + y_extra2), size=(180, 70) if is_add else (180, 65), - label=bui.Lstr(resource='backText') - if is_add - else bui.Lstr(resource='cancelText'), + label=( + bui.Lstr(resource='backText') + if is_add + else bui.Lstr(resource='cancelText') + ), button_type='back' if is_add else None, autoselect=True, scale=0.75, @@ -160,9 +158,11 @@ class PlaylistEditGameWindow(bui.Window): size=(200, 65), scale=0.75, text_scale=1.3, - label=bui.Lstr(resource=self._r + '.addGameText') - if is_add - else bui.Lstr(resource='doneText'), + label=( + bui.Lstr(resource=self._r + '.addGameText') + if is_add + else bui.Lstr(resource='doneText') + ), ) if bui.app.ui_v1.use_toolbars: @@ -447,9 +447,11 @@ class PlaylistEditGameWindow(bui.Window): parent=self._subcontainer, position=(h + 509 - 95, v), size=(0, 28), - text=bui.Lstr(resource='onText') - if value - else bui.Lstr(resource='offText'), + text=( + bui.Lstr(resource='onText') + if value + else bui.Lstr(resource='offText') + ), editable=False, color=(0.6, 1.0, 0.6, 1.0), maxwidth=mw2, @@ -566,9 +568,11 @@ class PlaylistEditGameWindow(bui.Window): ) -> None: bui.textwidget( edit=widget, - text=bui.Lstr(resource='onText') - if value - else bui.Lstr(resource='offText'), + text=( + bui.Lstr(resource='onText') + if value + else bui.Lstr(resource='offText') + ), ) self._settings[setting_name] = value diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py b/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py index 77200bea..8e2cc8ea 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/mapselect.py @@ -49,9 +49,7 @@ class PlaylistMapSelectWindow(bui.Window): height = ( 400 if uiscale is bui.UIScale.SMALL - else 480 - if uiscale is bui.UIScale.MEDIUM - else 600 + else 480 if uiscale is bui.UIScale.MEDIUM else 600 ) top_extra = 20 if uiscale is bui.UIScale.SMALL else 0 @@ -62,13 +60,11 @@ class PlaylistMapSelectWindow(bui.Window): scale=( 2.17 if uiscale is bui.UIScale.SMALL - else 1.3 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -27) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -27) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/share.py b/src/assets/ba_data/python/bauiv1lib/playlist/share.py index 480aba52..cd9af1cb 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/share.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/share.py @@ -93,9 +93,7 @@ class SharePlaylistResultsWindow(bui.Window): scale=( 1.8 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/playoptions.py b/src/assets/ba_data/python/bauiv1lib/playoptions.py index b2d42b21..ace486ac 100644 --- a/src/assets/ba_data/python/bauiv1lib/playoptions.py +++ b/src/assets/ba_data/python/bauiv1lib/playoptions.py @@ -33,6 +33,7 @@ class PlayOptionsWindow(PopupWindow): # pylint: disable=too-many-locals from bascenev1 import filter_playlist, get_map_class from bauiv1lib.playlist import PlaylistTypeVars + from bauiv1lib.config import ConfigNumberEdit self._r = 'gameListWindow' self._delegate = delegate @@ -52,7 +53,7 @@ class PlayOptionsWindow(PopupWindow): self._playlist = playlist self._width = 500.0 - self._height = 330.0 - 50.0 + self._height = 370.0 - 50.0 # In teams games, show the custom names/colors button. if self._sessiontype is bs.DualTeamSession: @@ -145,9 +146,7 @@ class PlayOptionsWindow(PopupWindow): scale = ( 1.69 if uiscale is bui.UIScale.SMALL - else 1.1 - if uiscale is bui.UIScale.MEDIUM - else 0.85 + else 1.1 if uiscale is bui.UIScale.MEDIUM else 0.85 ) # Creates our _root_widget. super().__init__( @@ -275,13 +274,39 @@ class PlayOptionsWindow(PopupWindow): texture=bui.gettexture('lock'), ) + y_offs = 50 if show_shuffle_check_box else 0 + + # Series Length + y_offs2 = 40 if self._sessiontype is bs.DualTeamSession else 0 + self._series_length_numedit = ConfigNumberEdit( + parent=self.root_widget, + position=(100, 200 + y_offs + y_offs2), + configkey=( + 'FFA' if self._sessiontype is bs.FreeForAllSession else 'Teams' + ) + + ' Series Length', + displayname=bui.Lstr( + resource=self._r + + ( + '.pointsToWinText' + if self._sessiontype is bs.FreeForAllSession + else '.seriesLengthText' + ) + ), + minval=1.0, + increment=1.0 if self._sessiontype is bs.FreeForAllSession else 2.0, + fallback_value=( + 24 if self._sessiontype is bs.FreeForAllSession else 7 + ), + f=0, + ) + # Team names/colors. self._custom_colors_names_button: bui.Widget | None if self._sessiontype is bs.DualTeamSession: - y_offs = 50 if show_shuffle_check_box else 0 self._custom_colors_names_button = bui.buttonwidget( parent=self.root_widget, - position=(100, 200 + y_offs), + position=(100, 195 + y_offs), size=(290, 35), on_activate_call=bui.WeakCall(self._custom_colors_names_press), autoselect=True, @@ -304,9 +329,9 @@ class PlayOptionsWindow(PopupWindow): def _cb_callback(val: bool) -> None: self._do_randomize_val = val cfg = bui.app.config - cfg[ - self._pvars.config_name + ' Playlist Randomize' - ] = self._do_randomize_val + cfg[self._pvars.config_name + ' Playlist Randomize'] = ( + self._do_randomize_val + ) cfg.commit() if show_shuffle_check_box: diff --git a/src/assets/ba_data/python/bauiv1lib/popup.py b/src/assets/ba_data/python/bauiv1lib/popup.py index b53cfc93..89e7b4c2 100644 --- a/src/assets/ba_data/python/bauiv1lib/popup.py +++ b/src/assets/ba_data/python/bauiv1lib/popup.py @@ -223,12 +223,14 @@ class PopupMenuWindow(PopupWindow): size=(self._width - 40, 28), on_select_call=bui.Call(self._select, index), click_activate=True, - color=(0.5, 0.5, 0.5, 0.5) - if inactive - else ( - (0.5, 1, 0.5, 1) - if choice == self._current_choice - else (0.8, 0.8, 0.8, 1.0) + color=( + (0.5, 0.5, 0.5, 0.5) + if inactive + else ( + (0.5, 1, 0.5, 1) + if choice == self._current_choice + else (0.8, 0.8, 0.8, 1.0) + ) ), padding=0, maxwidth=maxwidth, @@ -318,9 +320,7 @@ class PopupMenu: scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) if current_choice not in choices: current_choice = None diff --git a/src/assets/ba_data/python/bauiv1lib/profile/browser.py b/src/assets/ba_data/python/bauiv1lib/profile/browser.py index ef9db117..67d816bc 100644 --- a/src/assets/ba_data/python/bauiv1lib/profile/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/profile/browser.py @@ -38,9 +38,7 @@ class ProfileBrowserWindow(bui.Window): self._height = ( 360.0 if uiscale is bui.UIScale.SMALL - else 385.0 - if uiscale is bui.UIScale.MEDIUM - else 410.0 + else 385.0 if uiscale is bui.UIScale.MEDIUM else 410.0 ) # If we're being called up standalone, handle pause/resume ourself. @@ -74,13 +72,11 @@ class ProfileBrowserWindow(bui.Window): scale=( 2.2 if uiscale is bui.UIScale.SMALL - else 1.6 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.6 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -14) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -14) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) @@ -125,9 +121,7 @@ class ProfileBrowserWindow(bui.Window): scl = ( 1.055 if uiscale is bui.UIScale.SMALL - else 1.18 - if uiscale is bui.UIScale.MEDIUM - else 1.3 + else 1.18 if uiscale is bui.UIScale.MEDIUM else 1.3 ) v -= 70.0 * scl self._new_button = bui.buttonwidget( diff --git a/src/assets/ba_data/python/bauiv1lib/profile/edit.py b/src/assets/ba_data/python/bauiv1lib/profile/edit.py index 8456c607..7099e040 100644 --- a/src/assets/ba_data/python/bauiv1lib/profile/edit.py +++ b/src/assets/ba_data/python/bauiv1lib/profile/edit.py @@ -65,17 +65,13 @@ class EditProfileWindow(bui.Window): self._height = height = ( 350.0 if uiscale is bui.UIScale.SMALL - else 400.0 - if uiscale is bui.UIScale.MEDIUM - else 450.0 + else 400.0 if uiscale is bui.UIScale.MEDIUM else 450.0 ) spacing = 40 self._base_scale = ( 2.05 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 ) top_extra = 15 if uiscale is bui.UIScale.SMALL else 15 super().__init__( @@ -83,9 +79,9 @@ class EditProfileWindow(bui.Window): size=(width, height + top_extra), transition=transition, scale=self._base_scale, - stack_offset=(0, 15) - if uiscale is bui.UIScale.SMALL - else (0, 0), + stack_offset=( + (0, 15) if uiscale is bui.UIScale.SMALL else (0, 0) + ), ) ) cancel_button = btn = bui.buttonwidget( @@ -475,9 +471,11 @@ class EditProfileWindow(bui.Window): parent=self._root_widget, autoselect=True, position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50), - up_widget=self._upgrade_button - if self._upgrade_button is not None - else self._account_type_info_button, + up_widget=( + self._upgrade_button + if self._upgrade_button is not None + else self._account_type_info_button + ), size=(b_size, b_size), color=self._highlight, label='', @@ -803,6 +801,15 @@ class EditProfileWindow(bui.Window): bui.getsound('error').play() return False + # Make sure we're not renaming to another existing profile. + profiles: dict = bui.app.config.get('Player Profiles', {}) + if self._existing_profile != new_name and new_name in profiles.keys(): + bui.screenmessage( + bui.Lstr(resource='editProfileWindow.profileAlreadyExistsText') + ) + bui.getsound('error').play() + return False + if transition_out: bui.getsound('gunCocking').play() diff --git a/src/assets/ba_data/python/bauiv1lib/profile/upgrade.py b/src/assets/ba_data/python/bauiv1lib/profile/upgrade.py index b4f0243a..da446d22 100644 --- a/src/assets/ba_data/python/bauiv1lib/profile/upgrade.py +++ b/src/assets/ba_data/python/bauiv1lib/profile/upgrade.py @@ -39,9 +39,7 @@ class ProfileUpgradeWindow(bui.Window): self._base_scale = ( 2.05 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.2 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.2 ) self._upgrade_start_time: float | None = None self._name = edit_profile_window.getname() @@ -54,9 +52,9 @@ class ProfileUpgradeWindow(bui.Window): toolbar_visibility='menu_currency', transition=transition, scale=self._base_scale, - stack_offset=(0, 15) - if uiscale is bui.UIScale.SMALL - else (0, 0), + stack_offset=( + (0, 15) if uiscale is bui.UIScale.SMALL else (0, 0) + ), ) ) cancel_button = bui.buttonwidget( diff --git a/src/assets/ba_data/python/bauiv1lib/promocode.py b/src/assets/ba_data/python/bauiv1lib/promocode.py index 09bcf86a..5dcf3fb6 100644 --- a/src/assets/ba_data/python/bauiv1lib/promocode.py +++ b/src/assets/ba_data/python/bauiv1lib/promocode.py @@ -47,9 +47,7 @@ class PromoCodeWindow(bui.Window): scale=( 2.0 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/purchase.py b/src/assets/ba_data/python/bauiv1lib/purchase.py index 1a9c04f6..56e03cec 100644 --- a/src/assets/ba_data/python/bauiv1lib/purchase.py +++ b/src/assets/ba_data/python/bauiv1lib/purchase.py @@ -48,13 +48,11 @@ class PurchaseWindow(bui.Window): scale=( 1.2 if uiscale is bui.UIScale.SMALL - else 1.1 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.1 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -15) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -15) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) self._is_double = False diff --git a/src/assets/ba_data/python/bauiv1lib/qrcode.py b/src/assets/ba_data/python/bauiv1lib/qrcode.py index 467bab7f..3357de5c 100644 --- a/src/assets/ba_data/python/bauiv1lib/qrcode.py +++ b/src/assets/ba_data/python/bauiv1lib/qrcode.py @@ -19,9 +19,7 @@ class QRCodeWindow(PopupWindow): scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._transitioning_out = False self._width = 450 diff --git a/src/assets/ba_data/python/bauiv1lib/report.py b/src/assets/ba_data/python/bauiv1lib/report.py index 1b00e116..a6256e9b 100644 --- a/src/assets/ba_data/python/bauiv1lib/report.py +++ b/src/assets/ba_data/python/bauiv1lib/report.py @@ -29,9 +29,7 @@ class ReportPlayerWindow(bui.Window): scale=( 1.8 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py b/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py index 6c3fc587..5bcc48cb 100644 --- a/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py +++ b/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py @@ -19,9 +19,7 @@ class ResourceTypeInfoWindow(PopupWindow): scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._transitioning_out = False self._width = 570 diff --git a/src/assets/ba_data/python/bauiv1lib/serverdialog.py b/src/assets/ba_data/python/bauiv1lib/serverdialog.py index acd86938..92ac7d55 100644 --- a/src/assets/ba_data/python/bauiv1lib/serverdialog.py +++ b/src/assets/ba_data/python/bauiv1lib/serverdialog.py @@ -51,9 +51,7 @@ class ServerDialogWindow(bui.Window): scale=( 1.8 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) @@ -114,9 +112,11 @@ class ServerDialogWindow(bui.Window): self._ok_button = bui.buttonwidget( parent=self._root_widget, position=( - (self._width - 182) - if (data.show_cancel or show_copy) - else (self._width * 0.5 - 80), + ( + (self._width - 182) + if (data.show_cancel or show_copy) + else (self._width * 0.5 - 80) + ), 30, ), size=(160, 60), diff --git a/src/assets/ba_data/python/bauiv1lib/settings/advanced.py b/src/assets/ba_data/python/bauiv1lib/settings/advanced.py index 38285375..2585da7d 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/advanced.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/advanced.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """UI functionality for advanced settings.""" +# pylint: disable=too-many-lines from __future__ import annotations @@ -52,9 +53,7 @@ class AdvancedSettingsWindow(bui.Window): self._height = ( 390.0 if uiscale is bui.UIScale.SMALL - else 450.0 - if uiscale is bui.UIScale.MEDIUM - else 520.0 + else 450.0 if uiscale is bui.UIScale.MEDIUM else 520.0 ) self._lang_status_text: bui.Widget | None = None @@ -71,13 +70,11 @@ class AdvancedSettingsWindow(bui.Window): scale=( 2.06 if uiscale is bui.UIScale.SMALL - else 1.4 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -25) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -25) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) @@ -112,6 +109,7 @@ class AdvancedSettingsWindow(bui.Window): if self._do_net_test_button: self._sub_height += self._extra_button_spacing self._sub_height += self._spacing * 2.0 # plugins + self._sub_height += self._spacing * 2.0 # modding tools self._r = 'settingsWindowAdvanced' @@ -196,36 +194,45 @@ class AdvancedSettingsWindow(bui.Window): from bauiv1lib import promocode as _unused7 from bauiv1lib import debug as _unused8 from bauiv1lib.settings import plugins as _unused9 + from bauiv1lib.settings import moddingtools as _unused10 def _update_lang_status(self) -> None: if self._complete_langs_list is not None: up_to_date = bui.app.lang.language in self._complete_langs_list bui.textwidget( edit=self._lang_status_text, - text='' - if bui.app.lang.language == 'Test' - else bui.Lstr( - resource=f'{self._r}.translationNoUpdateNeededText' - ) - if up_to_date - else bui.Lstr( - resource=f'{self._r}.translationUpdateNeededText' + text=( + '' + if bui.app.lang.language == 'Test' + else ( + bui.Lstr( + resource=f'{self._r}.translationNoUpdateNeededText' + ) + if up_to_date + else bui.Lstr( + resource=f'{self._r}.translationUpdateNeededText' + ) + ) + ), + color=( + (0.2, 1.0, 0.2, 0.8) if up_to_date else (1.0, 0.2, 0.2, 0.8) ), - color=(0.2, 1.0, 0.2, 0.8) - if up_to_date - else (1.0, 0.2, 0.2, 0.8), ) else: bui.textwidget( edit=self._lang_status_text, - text=bui.Lstr(resource=f'{self._r}.translationFetchErrorText') - if self._complete_langs_error - else bui.Lstr( - resource=f'{self._r}.translationFetchingStatusText' + text=( + bui.Lstr(resource=f'{self._r}.translationFetchErrorText') + if self._complete_langs_error + else bui.Lstr( + resource=f'{self._r}.translationFetchingStatusText' + ) + ), + color=( + (1.0, 0.5, 0.2) + if self._complete_langs_error + else (0.7, 0.7, 0.7) ), - color=(1.0, 0.5, 0.2) - if self._complete_langs_error - else (0.7, 0.7, 0.7), ) def _rebuild(self) -> None: @@ -575,6 +582,19 @@ class AdvancedSettingsWindow(bui.Window): bui.open_url, 'https://ballistica.net/wiki/modding-guide' ), ) + + v -= self._spacing * 2.0 + + self._modding_tools_button = bui.buttonwidget( + parent=self._subcontainer, + position=(self._sub_width / 2 - this_button_width / 2, v - 10), + size=(this_button_width, 60), + autoselect=True, + label=bui.Lstr(resource=f'{self._r}.moddingToolsText'), + text_scale=1.0, + on_activate_call=self._on_modding_tools_button_press, + ) + if self._show_always_use_internal_keyboard: assert self._always_use_internal_keyboard_check_box is not None bui.widget( @@ -763,6 +783,24 @@ class AdvancedSettingsWindow(bui.Window): from_window=self._root_widget, ) + def _on_modding_tools_button_press(self) -> None: + # pylint: disable=cyclic-import + from bauiv1lib.settings.moddingtools import ModdingToolsWindow + + # no-op if our underlying widget is dead or on its way out. + if not self._root_widget or self._root_widget.transitioning_out: + return + + self._save_state() + bui.containerwidget(edit=self._root_widget, transition='out_left') + assert bui.app.classic is not None + bui.app.ui_v1.set_main_menu_window( + ModdingToolsWindow( + origin_widget=self._modding_tools_button + ).get_root_widget(), + from_window=self._root_widget, + ) + def _on_promo_code_press(self) -> None: from bauiv1lib.promocode import PromoCodeWindow from bauiv1lib.account import show_sign_in_prompt @@ -806,6 +844,7 @@ class AdvancedSettingsWindow(bui.Window): def _save_state(self) -> None: # pylint: disable=too-many-branches + # pylint: disable=too-many-statements try: sel = self._root_widget.get_selected_child() if sel == self._scrollwidget: @@ -848,6 +887,8 @@ class AdvancedSettingsWindow(bui.Window): sel_name = 'ShowUserMods' elif sel == self._plugins_button: sel_name = 'Plugins' + elif sel == self._modding_tools_button: + sel_name = 'ModdingTools' elif sel == self._modding_guide_button: sel_name = 'ModdingGuide' elif sel == self._language_inform_checkbox: @@ -915,6 +956,8 @@ class AdvancedSettingsWindow(bui.Window): sel = self._show_user_mods_button elif sel_name == 'Plugins': sel = self._plugins_button + elif sel_name == 'ModdingTools': + sel = self._modding_tools_button elif sel_name == 'ModdingGuide': sel = self._modding_guide_button elif sel_name == 'LangInform': diff --git a/src/assets/ba_data/python/bauiv1lib/settings/allsettings.py b/src/assets/ba_data/python/bauiv1lib/settings/allsettings.py index 98aedda9..6e6ed9d4 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/allsettings.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/allsettings.py @@ -56,13 +56,11 @@ class AllSettingsWindow(bui.Window): scale=( 1.75 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -8) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -8) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/audio.py b/src/assets/ba_data/python/bauiv1lib/settings/audio.py index fc39b719..27ed2e4b 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/audio.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/audio.py @@ -63,9 +63,7 @@ class AudioSettingsWindow(bui.Window): base_scale = ( 2.05 if uiscale is bui.UIScale.SMALL - else 1.6 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.6 if uiscale is bui.UIScale.MEDIUM else 1.0 ) popup_menu_scale = base_scale * 1.2 @@ -75,9 +73,9 @@ class AudioSettingsWindow(bui.Window): transition=transition, scale=base_scale, scale_origin_stack_offset=scale_origin, - stack_offset=(0, -20) - if uiscale is bui.UIScale.SMALL - else (0, 0), + stack_offset=( + (0, -20) if uiscale is bui.UIScale.SMALL else (0, 0) + ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/controls.py b/src/assets/ba_data/python/bauiv1lib/settings/controls.py index 108657f5..8c28836a 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/controls.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/controls.py @@ -124,9 +124,7 @@ class ControlsSettingsWindow(bui.Window): scale=( smallscale if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py index a4f193a4..0474f32e 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepad.py @@ -56,13 +56,11 @@ class GamepadSettingsWindow(bui.Window): scale=( 1.63 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (-20, -16) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(-20, -16) - if uiscale is bui.UIScale.SMALL - else (0, 0), transition=transition, ) ) @@ -549,16 +547,12 @@ class GamepadSettingsWindow(bui.Window): sval1 = ( self._settings['analogStickLR' + self._ext] if 'analogStickLR' + self._ext in self._settings - else 5 - if self._is_secondary - else None + else 5 if self._is_secondary else None ) sval2 = ( self._settings['analogStickUD' + self._ext] if 'analogStickUD' + self._ext in self._settings - else 6 - if self._is_secondary - else None + else 6 if self._is_secondary else None ) assert isinstance(sval1, (int, type(None))) assert isinstance(sval2, (int, type(None))) @@ -601,9 +595,7 @@ class GamepadSettingsWindow(bui.Window): dpadnum = ( self._settings['dpad' + self._ext] if 'dpad' + self._ext in self._settings - else 2 - if self._is_secondary - else None + else 2 if self._is_secondary else None ) assert isinstance(dpadnum, (int, type(None))) if dpadnum is not None: @@ -971,9 +963,7 @@ class AwaitGamepadInputWindow(bui.Window): scale=( 2.0 if uiscale is bui.UIScale.SMALL - else 1.9 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.9 if uiscale is bui.UIScale.MEDIUM else 1.0 ), size=(width, height), transition='in_scale', diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py index d44300f0..4249cbb1 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepadadvanced.py @@ -42,13 +42,11 @@ class GamepadAdvancedSettingsWindow(bui.Window): * ( 1.85 if uiscale is bui.UIScale.SMALL - else 1.35 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -25) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -25) - if uiscale is bui.UIScale.SMALL - else (0, 0), scale_origin_stack_offset=(advb.get_screen_space_center()), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py b/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py index d0dba0ac..416d48f6 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/gamepadselect.py @@ -45,9 +45,7 @@ def gamepad_configure_callback(event: dict[str, Any]) -> None: scale=( 1.7 if uiscale is bui.UIScale.SMALL - else 1.4 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 ), size=(width, height), transition='in_right', @@ -122,9 +120,7 @@ class GamepadSelectWindow(bui.Window): scale=( 2.3 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 ), size=(width, height), transition='in_right', diff --git a/src/assets/ba_data/python/bauiv1lib/settings/graphics.py b/src/assets/ba_data/python/bauiv1lib/settings/graphics.py index f441826c..3eaf429e 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/graphics.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/graphics.py @@ -75,9 +75,7 @@ class GraphicsSettingsWindow(bui.Window): base_scale = ( 2.0 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 ) popup_menu_scale = base_scale * 1.2 v = height - 50 @@ -88,9 +86,9 @@ class GraphicsSettingsWindow(bui.Window): transition=transition, scale_origin_stack_offset=scale_origin, scale=base_scale, - stack_offset=(0, -30) - if uiscale is bui.UIScale.SMALL - else (0, 0), + stack_offset=( + (0, -30) if uiscale is bui.UIScale.SMALL else (0, 0) + ), ) ) @@ -174,9 +172,11 @@ class GraphicsSettingsWindow(bui.Window): width=150, scale=popup_menu_scale, choices=['Auto', 'Higher', 'High', 'Medium', 'Low'], - choices_disabled=['Higher', 'High'] - if bui.get_max_graphics_quality() == 'Medium' - else [], + choices_disabled=( + ['Higher', 'High'] + if bui.get_max_graphics_quality() == 'Medium' + else [] + ), choices_display=[ bui.Lstr(resource='autoText'), bui.Lstr(resource=self._r + '.higherText'), diff --git a/src/assets/ba_data/python/bauiv1lib/settings/keyboard.py b/src/assets/ba_data/python/bauiv1lib/settings/keyboard.py index 3f445460..2290faf5 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/keyboard.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/keyboard.py @@ -41,9 +41,7 @@ class ConfigKeyboardWindow(bui.Window): scale=( 1.6 if uiscale is bui.UIScale.SMALL - else 1.3 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 ), stack_offset=(0, 5) if uiscale is bui.UIScale.SMALL else (0, 0), transition=transition, @@ -427,9 +425,7 @@ class AwaitKeyboardInputWindow(bui.Window): scale=( 2.0 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/moddingtools.py b/src/assets/ba_data/python/bauiv1lib/settings/moddingtools.py new file mode 100644 index 00000000..a4307360 --- /dev/null +++ b/src/assets/ba_data/python/bauiv1lib/settings/moddingtools.py @@ -0,0 +1,207 @@ +# Released under the MIT License. See LICENSE for details. +# +"""UI functionality for Modding Tools.""" + +from __future__ import annotations + +import babase +import bauiv1 as bui +from bauiv1lib.popup import PopupMenu +from bauiv1lib.confirm import ConfirmWindow + + +class ModdingToolsWindow(bui.Window): + """Window for accessing modding tools.""" + + def __init__( + self, + transition: str = 'in_right', + origin_widget: bui.Widget | None = None, + ): + + app = bui.app + assert app.classic is not None + + # If they provided an origin-widget, scale up from that. + scale_origin: tuple[float, float] | None + if origin_widget is not None: + self._transition_out = 'out_scale' + scale_origin = origin_widget.get_screen_space_center() + transition = 'in_scale' + else: + self._transition_out = 'out_right' + scale_origin = None + + uiscale = app.ui_v1.uiscale + self._width = 970.0 if uiscale is bui.UIScale.SMALL else 670.0 + x_inset = 150 if uiscale is bui.UIScale.SMALL else 0 + self._height = ( + 390.0 + if uiscale is bui.UIScale.SMALL + else 450.0 if uiscale is bui.UIScale.MEDIUM else 520.0 + ) + + self._spacing = 32 + top_extra = 10 if uiscale is bui.UIScale.SMALL else 0 + + self._scroll_width = self._width - (100 + 2 * x_inset) + self._scroll_height = self._height - 115.0 + self._sub_width = self._scroll_width * 0.95 + self._sub_height = 100.0 + + super().__init__( + root_widget=bui.containerwidget( + size=(self._width, self._height + top_extra), + transition=transition, + toolbar_visibility='menu_minimal', + scale_origin_stack_offset=scale_origin, + scale=( + 2.06 + if uiscale is bui.UIScale.SMALL + else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -25) if uiscale is bui.UIScale.SMALL else (0, 0) + ), + ) + ) + + self._r = 'settingsModdingTools' + + if app.ui_v1.use_toolbars and uiscale is bui.UIScale.SMALL: + bui.containerwidget( + edit=self._root_widget, on_cancel_call=self._do_back + ) + self._back_button = None + else: + self._back_button = bui.buttonwidget( + parent=self._root_widget, + position=(53 + x_inset, self._height - 60), + size=(140, 60), + scale=0.8, + autoselect=True, + label=bui.Lstr(resource='backText'), + button_type='back', + on_activate_call=self._do_back, + ) + bui.containerwidget( + edit=self._root_widget, cancel_button=self._back_button + ) + + self._title_text = bui.textwidget( + parent=self._root_widget, + position=(0, self._height - 52), + size=(self._width, 25), + text=bui.Lstr(resource='moddingToolsTitleText'), + color=app.ui_v1.title_color, + h_align='center', + v_align='top', + ) + + if self._back_button is not None: + bui.buttonwidget( + edit=self._back_button, + button_type='backSmall', + size=(60, 60), + label=bui.charstr(bui.SpecialChar.BACK), + ) + + self._scrollwidget = bui.scrollwidget( + parent=self._root_widget, + position=(50 + x_inset, 50), + simple_culling_v=20.0, + highlight=False, + size=(self._scroll_width, self._scroll_height), + selection_loops_to_parent=True, + ) + bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget) + self._subcontainer = bui.containerwidget( + parent=self._scrollwidget, + size=(self._sub_width, self._sub_height), + background=False, + selection_loops_to_parent=True, + ) + + v = self._sub_height - 35 + this_button_width = 410 + + v -= self._spacing * 1.2 + self._create_user_system_scripts_button = bui.buttonwidget( + parent=self._subcontainer, + position=(self._sub_width / 2 - this_button_width / 2, v - 10), + size=(this_button_width, 60), + autoselect=True, + label=bui.Lstr(resource='createUserSystemScriptsText'), + text_scale=1.0, + on_activate_call=babase.modutils.create_user_system_scripts, + ) + + v -= self._spacing * 2.5 + self._delete_user_system_scripts_button = bui.buttonwidget( + parent=self._subcontainer, + position=(self._sub_width / 2 - this_button_width / 2, v - 10), + size=(this_button_width, 60), + autoselect=True, + label=bui.Lstr(resource='deleteUserSystemScriptsText'), + text_scale=1.0, + on_activate_call=lambda: ConfirmWindow( + action=babase.modutils.delete_user_system_scripts, + ), + ) + + v -= self._spacing * 2.5 + bui.textwidget( + parent=self._subcontainer, + position=(170, v + 10), + size=(0, 0), + text=bui.Lstr(value='UI SIZE :'), + color=app.ui_v1.title_color, + h_align='center', + v_align='center', + ) + + PopupMenu( + parent=self._subcontainer, + position=(230, v - 20), + button_size=(200.0, 60.0), + choices=[ + 'auto', + 'small', + 'medium', + 'large', + ], + choices_display=[ + bui.Lstr(resource='autoText'), + bui.Lstr(resource='smallText'), + bui.Lstr(resource='mediumText'), + bui.Lstr(resource='largeText'), + ], + current_choice=app.config.get('UI Scale', 'auto'), + on_value_change_call=self._set_uiscale, + ) + + def _set_uiscale(self, val: str) -> None: + cfg = bui.app.config + cfg['UI Scale'] = val + cfg.apply_and_commit() + if bui.app.ui_v1.uiscale.name != val.upper(): + bui.screenmessage( + bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'), + color=(1.0, 0.5, 0.0), + ) + + def _do_back(self) -> None: + from bauiv1lib.settings.advanced import AdvancedSettingsWindow + + # no-op if our underlying widget is dead or on its way out. + if not self._root_widget or self._root_widget.transitioning_out: + return + + bui.containerwidget( + edit=self._root_widget, transition=self._transition_out + ) + assert bui.app.classic is not None + bui.app.ui_v1.set_main_menu_window( + AdvancedSettingsWindow(transition='in_left').get_root_widget(), + from_window=self._root_widget, + ) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/nettesting.py b/src/assets/ba_data/python/bauiv1lib/settings/nettesting.py index e4e6e996..7cb824c4 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/nettesting.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/nettesting.py @@ -37,9 +37,7 @@ class NetTestingWindow(bui.Window): scale=( 1.56 if uiscale is bui.UIScale.SMALL - else 1.2 - if uiscale is bui.UIScale.MEDIUM - else 0.8 + else 1.2 if uiscale is bui.UIScale.MEDIUM else 0.8 ), stack_offset=(0.0, -7 if uiscale is bui.UIScale.SMALL else 0.0), transition=transition, diff --git a/src/assets/ba_data/python/bauiv1lib/settings/plugins.py b/src/assets/ba_data/python/bauiv1lib/settings/plugins.py index b5f93320..b3f27c69 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/plugins.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/plugins.py @@ -58,9 +58,7 @@ class PluginWindow(bui.Window): self._height = ( 390.0 if uiscale is bui.UIScale.SMALL - else 450.0 - if uiscale is bui.UIScale.MEDIUM - else 520.0 + else 450.0 if uiscale is bui.UIScale.MEDIUM else 520.0 ) top_extra = 10 if uiscale is bui.UIScale.SMALL else 0 super().__init__( @@ -72,13 +70,11 @@ class PluginWindow(bui.Window): scale=( 2.06 if uiscale is bui.UIScale.SMALL - else 1.4 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -25) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -25) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) @@ -252,9 +248,7 @@ class PluginWindow(bui.Window): scale=( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ), choices=[c.value for c in Category], choices_display=[bui.Lstr(resource=c.resource) for c in Category], @@ -365,9 +359,11 @@ class PluginWindow(bui.Window): textcolor=( (0.8, 0.3, 0.3) if (plugspec.attempted_load and plugspec.plugin is None) - else (0.6, 0.6, 0.6) - if plugspec.plugin is None - else (0, 1, 0) + else ( + (0.6, 0.6, 0.6) + if plugspec.plugin is None + else (0, 1, 0) + ) ), ) # noinspection PyUnresolvedReferences diff --git a/src/assets/ba_data/python/bauiv1lib/settings/pluginsettings.py b/src/assets/ba_data/python/bauiv1lib/settings/pluginsettings.py index 1474f5cb..d59554ff 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/pluginsettings.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/pluginsettings.py @@ -22,9 +22,7 @@ class PluginSettingsWindow(bui.Window): height = ( 365.0 if uiscale is bui.UIScale.SMALL - else 300.0 - if uiscale is bui.UIScale.MEDIUM - else 370.0 + else 300.0 if uiscale is bui.UIScale.MEDIUM else 370.0 ) top_extra = 10 if uiscale is bui.UIScale.SMALL else 0 @@ -37,13 +35,11 @@ class PluginSettingsWindow(bui.Window): scale=( 2.06 if uiscale is bui.UIScale.SMALL - else 1.4 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -25) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -25) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/settings/remoteapp.py b/src/assets/ba_data/python/bauiv1lib/settings/remoteapp.py index 3542f992..c38b727a 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/remoteapp.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/remoteapp.py @@ -24,13 +24,11 @@ class RemoteAppSettingsWindow(bui.Window): scale=( 1.85 if uiscale is bui.UIScale.SMALL - else 1.3 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (-10, 0) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(-10, 0) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) btn = bui.buttonwidget( diff --git a/src/assets/ba_data/python/bauiv1lib/settings/testing.py b/src/assets/ba_data/python/bauiv1lib/settings/testing.py index 30f11e28..5af029bb 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/testing.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/testing.py @@ -36,13 +36,11 @@ class TestingWindow(bui.Window): scale=( 2.5 if uiscale is bui.UIScale.SMALL - else 1.2 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.2 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -28) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -28) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) self._back_button = btn = bui.buttonwidget( @@ -114,9 +112,9 @@ class TestingWindow(bui.Window): # If we haven't yet, record the default value for this name so # we can reset if we want.. if entry_name not in bui.app.classic.value_test_defaults: - bui.app.classic.value_test_defaults[ - entry_name - ] = bui.app.classic.value_test(entry_name) + bui.app.classic.value_test_defaults[entry_name] = ( + bui.app.classic.value_test(entry_name) + ) bui.textwidget( parent=self._subcontainer, diff --git a/src/assets/ba_data/python/bauiv1lib/settings/touchscreen.py b/src/assets/ba_data/python/bauiv1lib/settings/touchscreen.py index d77a16a2..b3e1d2bf 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/touchscreen.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/touchscreen.py @@ -35,9 +35,7 @@ class TouchscreenSettingsWindow(bui.Window): scale=( 1.9 if uiscale is bui.UIScale.SMALL - else 1.55 - if uiscale is bui.UIScale.MEDIUM - else 1.2 + else 1.55 if uiscale is bui.UIScale.MEDIUM else 1.2 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/soundtrack/edit.py b/src/assets/ba_data/python/bauiv1lib/soundtrack/edit.py index 8c3887eb..628a599a 100644 --- a/src/assets/ba_data/python/bauiv1lib/soundtrack/edit.py +++ b/src/assets/ba_data/python/bauiv1lib/soundtrack/edit.py @@ -35,9 +35,7 @@ class SoundtrackEditWindow(bui.Window): self._height = ( 395 if uiscale is bui.UIScale.SMALL - else 450 - if uiscale is bui.UIScale.MEDIUM - else 560 + else 450 if uiscale is bui.UIScale.MEDIUM else 560 ) super().__init__( root_widget=bui.containerwidget( @@ -46,15 +44,13 @@ class SoundtrackEditWindow(bui.Window): scale=( 2.08 if uiscale is bui.UIScale.SMALL - else 1.5 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -48) + if uiscale is bui.UIScale.SMALL + else (0, 15) if uiscale is bui.UIScale.MEDIUM else (0, 0) ), - stack_offset=(0, -48) - if uiscale is bui.UIScale.SMALL - else (0, 15) - if uiscale is bui.UIScale.MEDIUM - else (0, 0), ) ) cancel_button = bui.buttonwidget( @@ -266,13 +262,11 @@ class SoundtrackEditWindow(bui.Window): icon=( self._file_tex if icon_type == 'file' - else self._folder_tex - if icon_type == 'folder' - else None + else self._folder_tex if icon_type == 'folder' else None + ), + icon_color=( + (1.1, 0.8, 0.2) if icon_type == 'folder' else (1, 1, 1) ), - icon_color=(1.1, 0.8, 0.2) - if icon_type == 'folder' - else (1, 1, 1), left_widget=self._text_field, iconscale=0.7, autoselect=True, @@ -314,9 +308,11 @@ class SoundtrackEditWindow(bui.Window): label=bui.Lstr(resource=self._r + '.testText'), text_scale=0.6, on_activate_call=bui.Call(self._test, bs.MusicType(song_type)), - up_widget=prev_test_button - if prev_test_button is not None - else self._text_field, + up_widget=( + prev_test_button + if prev_test_button is not None + else self._text_field + ), ) if prev_test_button is not None: bui.widget(edit=prev_test_button, down_widget=btn) diff --git a/src/assets/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py b/src/assets/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py index 583855a8..c1a7d2e2 100644 --- a/src/assets/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py +++ b/src/assets/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py @@ -63,9 +63,7 @@ class SoundtrackEntryTypeSelectWindow(bui.Window): scale=( 1.7 if uiscale is bui.UIScale.SMALL - else 1.4 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 ), ), cleanupcheck=False, diff --git a/src/assets/ba_data/python/bauiv1lib/specialoffer.py b/src/assets/ba_data/python/bauiv1lib/specialoffer.py index 6e4a463b..24ae04db 100644 --- a/src/assets/ba_data/python/bauiv1lib/specialoffer.py +++ b/src/assets/ba_data/python/bauiv1lib/specialoffer.py @@ -86,13 +86,11 @@ class SpecialOfferWindow(bui.Window): scale=( 1.2 if uiscale is bui.UIScale.SMALL - else 1.15 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.15 if uiscale is bui.UIScale.MEDIUM else 1.0 + ), + stack_offset=( + (0, -15) if uiscale is bui.UIScale.SMALL else (0, 0) ), - stack_offset=(0, -15) - if uiscale is bui.UIScale.SMALL - else (0, 0), ) ) self._is_bundle_sale = False @@ -310,9 +308,11 @@ class SpecialOfferWindow(bui.Window): self._cancel_button = bui.buttonwidget( parent=self._root_widget, - position=(50, 40) - if self._is_bundle_sale - else (self._width * 0.5 - 75, 40), + position=( + (50, 40) + if self._is_bundle_sale + else (self._width * 0.5 - 75, 40) + ), size=(150, 60), scale=1.0, on_activate_call=self._cancel, @@ -322,9 +322,11 @@ class SpecialOfferWindow(bui.Window): self._cancel_countdown_text = bui.textwidget( parent=self._root_widget, text='', - position=(50 + 150 + 20, 40 + 27) - if self._is_bundle_sale - else (self._width * 0.5 - 75 + 150 + 20, 40 + 27), + position=( + (50 + 150 + 20, 40 + 27) + if self._is_bundle_sale + else (self._width * 0.5 - 75 + 150 + 20, 40 + 27) + ), scale=1.1, size=(0, 0), h_align='left', @@ -349,12 +351,14 @@ class SpecialOfferWindow(bui.Window): bui.containerwidget( edit=self._root_widget, cancel_button=self._cancel_button, - start_button=self._purchase_button - if self._is_bundle_sale - else None, - selected_child=self._purchase_button - if self._is_bundle_sale - else display['button'], + start_button=( + self._purchase_button if self._is_bundle_sale else None + ), + selected_child=( + self._purchase_button + if self._is_bundle_sale + else display['button'] + ), ) def _stop_flashing(self) -> None: @@ -373,12 +377,12 @@ class SpecialOfferWindow(bui.Window): def _update_cancel_button_graphics(self) -> None: bui.buttonwidget( edit=self._cancel_button, - color=(0.5, 0.5, 0.5) - if self._cancel_delay > 0 - else (0.7, 0.4, 0.34), - textcolor=(0.5, 0.5, 0.5) - if self._cancel_delay > 0 - else (0.9, 0.9, 1.0), + color=( + (0.5, 0.5, 0.5) if self._cancel_delay > 0 else (0.7, 0.4, 0.34) + ), + textcolor=( + (0.5, 0.5, 0.5) if self._cancel_delay > 0 else (0.9, 0.9, 1.0) + ), ) bui.textwidget( edit=self._cancel_countdown_text, diff --git a/src/assets/ba_data/python/bauiv1lib/store/browser.py b/src/assets/ba_data/python/bauiv1lib/store/browser.py index 555e5e1c..1f6df697 100644 --- a/src/assets/ba_data/python/bauiv1lib/store/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/store/browser.py @@ -81,9 +81,7 @@ class StoreBrowserWindow(bui.Window): self._height = ( 578 if uiscale is bui.UIScale.SMALL - else 645 - if uiscale is bui.UIScale.MEDIUM - else 800 + else 645 if uiscale is bui.UIScale.MEDIUM else 800 ) self._current_tab: StoreBrowserWindow.TabID | None = None extra_top = 30 if uiscale is bui.UIScale.SMALL else 0 @@ -100,17 +98,13 @@ class StoreBrowserWindow(bui.Window): scale=( 1.3 if uiscale is bui.UIScale.SMALL - else 0.9 - if uiscale is bui.UIScale.MEDIUM - else 0.8 + else 0.9 if uiscale is bui.UIScale.MEDIUM else 0.8 ), scale_origin_stack_offset=scale_origin, stack_offset=( (0, -5) if uiscale is bui.UIScale.SMALL - else (0, 0) - if uiscale is bui.UIScale.MEDIUM - else (0, 0) + else (0, 0) if uiscale is bui.UIScale.MEDIUM else (0, 0) ), ) ) @@ -905,27 +899,23 @@ class StoreBrowserWindow(bui.Window): dummy_name = 'icons.foo' else: dummy_name = '' - section[ - 'button_size' - ] = cstore.get_store_item_display_size(dummy_name) + section['button_size'] = ( + cstore.get_store_item_display_size(dummy_name) + ) section['v_spacing'] = ( -25 if ( self._tab == 'extras' and uiscale is bui.UIScale.SMALL ) - else -17 - if self._tab == 'characters' - else 0 + else -17 if self._tab == 'characters' else 0 ) if 'title' not in section: section['title'] = '' section['x_offs'] = ( 130 if self._tab == 'extras' - else 270 - if self._tab == 'maps' - else 0 + else 270 if self._tab == 'maps' else 0 ) section['y_offs'] = ( 20 @@ -934,14 +924,14 @@ class StoreBrowserWindow(bui.Window): and uiscale is bui.UIScale.SMALL and bui.app.config.get('Merch Link') ) - else 55 - if ( - self._tab == 'extras' - and uiscale is bui.UIScale.SMALL + else ( + 55 + if ( + self._tab == 'extras' + and uiscale is bui.UIScale.SMALL + ) + else -20 if self._tab == 'icons' else 0 ) - else -20 - if self._tab == 'icons' - else 0 ) def instantiate( diff --git a/src/assets/ba_data/python/bauiv1lib/store/item.py b/src/assets/ba_data/python/bauiv1lib/store/item.py index 3a801466..ee779cb4 100644 --- a/src/assets/ba_data/python/bauiv1lib/store/item.py +++ b/src/assets/ba_data/python/bauiv1lib/store/item.py @@ -83,16 +83,20 @@ def instantiate_store_item_display( tint_color = ( item_info['color'] if 'color' in item_info - else character.default_color - if character.default_color is not None - else (1, 1, 1) + else ( + character.default_color + if character.default_color is not None + else (1, 1, 1) + ) ) tint2_color = ( item_info['highlight'] if 'highlight' in item_info - else character.default_highlight - if character.default_highlight is not None - else (1, 1, 1) + else ( + character.default_highlight + if character.default_highlight is not None + else (1, 1, 1) + ) ) icon_tex = character.icon_texture tint_tex = character.icon_mask_texture diff --git a/src/assets/ba_data/python/bauiv1lib/teamnamescolors.py b/src/assets/ba_data/python/bauiv1lib/teamnamescolors.py index 3fe95459..23bbd0c0 100644 --- a/src/assets/ba_data/python/bauiv1lib/teamnamescolors.py +++ b/src/assets/ba_data/python/bauiv1lib/teamnamescolors.py @@ -33,9 +33,7 @@ class TeamNamesColorsWindow(PopupWindow): scale = ( 1.69 if uiscale is bui.UIScale.SMALL - else 1.1 - if uiscale is bui.UIScale.MEDIUM - else 0.85 + else 1.1 if uiscale is bui.UIScale.MEDIUM else 0.85 ) super().__init__( position=scale_origin, size=(self._width, self._height), scale=scale diff --git a/src/assets/ba_data/python/bauiv1lib/tournamententry.py b/src/assets/ba_data/python/bauiv1lib/tournamententry.py index 90996bc0..34c863c5 100644 --- a/src/assets/ba_data/python/bauiv1lib/tournamententry.py +++ b/src/assets/ba_data/python/bauiv1lib/tournamententry.py @@ -73,9 +73,7 @@ class TournamentEntryWindow(PopupWindow): scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._delegate = delegate self._transitioning_out = False @@ -203,9 +201,11 @@ class TournamentEntryWindow(PopupWindow): self._ad_text = bui.textwidget( parent=self.root_widget, draw_controller=btn, - position=self._ad_text_position_remaining - if have_ad_tries_remaining - else self._ad_text_position, + position=( + self._ad_text_position_remaining + if have_ad_tries_remaining + else self._ad_text_position + ), size=(0, 0), h_align='center', v_align='center', @@ -407,9 +407,11 @@ class TournamentEntryWindow(PopupWindow): ): plus.tournament_query( args={ - 'source': 'entry window' - if self._tournament_activity is None - else 'retry entry window' + 'source': ( + 'entry window' + if self._tournament_activity is None + else 'retry entry window' + ) }, callback=bui.WeakCall(self._on_tournament_query_response), ) @@ -448,35 +450,43 @@ class TournamentEntryWindow(PopupWindow): subs=[ ( '${COUNT}', - str(self._purchase_price) - if self._purchase_price is not None - else '?', + ( + str(self._purchase_price) + if self._purchase_price is not None + else '?' + ), ) ], ) ), - position=self._ticket_cost_text_position_free - if self._purchase_price == 0 - else self._ticket_cost_text_position, + position=( + self._ticket_cost_text_position_free + if self._purchase_price == 0 + else self._ticket_cost_text_position + ), scale=1.0 if self._purchase_price == 0 else 0.6, ) bui.textwidget( edit=self._free_plays_remaining_text, - text='' - if ( - self._tournament_info['freeTriesRemaining'] in [None, 0] - or self._purchase_price != 0 - ) - else '' + str(self._tournament_info['freeTriesRemaining']), + text=( + '' + if ( + self._tournament_info['freeTriesRemaining'] in [None, 0] + or self._purchase_price != 0 + ) + else '' + str(self._tournament_info['freeTriesRemaining']) + ), ) bui.imagewidget( edit=self._ticket_img, opacity=0.2 if self._purchase_price == 0 else 1.0, - position=self._ticket_img_pos_free - if self._purchase_price == 0 - else self._ticket_img_pos, + position=( + self._ticket_img_pos_free + if self._purchase_price == 0 + else self._ticket_img_pos + ), ) if self._do_ad_btn: @@ -487,9 +497,11 @@ class TournamentEntryWindow(PopupWindow): ) bui.textwidget( edit=self._ad_text, - position=self._ad_text_position_remaining - if have_ad_tries_remaining - else self._ad_text_position, + position=( + self._ad_text_position_remaining + if have_ad_tries_remaining + else self._ad_text_position + ), color=(0, 1, 0) if enabled else (0.5, 0.5, 0.5), ) bui.imagewidget( @@ -563,16 +575,18 @@ class TournamentEntryWindow(PopupWindow): bui.apptimer(0.1, bui.getsound('cashRegister').play) bui.apptimer( 1.0, - lambda: bui.app.classic.launch_coop_game( - self._tournament_info['game'], - args={ - 'min_players': self._tournament_info['minPlayers'], - 'max_players': self._tournament_info['maxPlayers'], - 'tournament_id': self._tournament_id, - }, - ) - if bui.app.classic is not None - else None, + lambda: ( + bui.app.classic.launch_coop_game( + self._tournament_info['game'], + args={ + 'min_players': self._tournament_info['minPlayers'], + 'max_players': self._tournament_info['maxPlayers'], + 'tournament_id': self._tournament_id, + }, + ) + if bui.app.classic is not None + else None + ), ) bui.apptimer(0.7, self._transition_out) bui.screenmessage( diff --git a/src/assets/ba_data/python/bauiv1lib/tournamentscores.py b/src/assets/ba_data/python/bauiv1lib/tournamentscores.py index ebd44de7..b7499498 100644 --- a/src/assets/ba_data/python/bauiv1lib/tournamentscores.py +++ b/src/assets/ba_data/python/bauiv1lib/tournamentscores.py @@ -48,9 +48,7 @@ class TournamentScoresWindow(PopupWindow): scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._transitioning_out = False @@ -58,9 +56,7 @@ class TournamentScoresWindow(PopupWindow): self._height = ( 300 if uiscale is bui.UIScale.SMALL - else 370 - if uiscale is bui.UIScale.MEDIUM - else 450 + else 370 if uiscale is bui.UIScale.MEDIUM else 450 ) bg_color = (0.5, 0.4, 0.6) diff --git a/src/assets/ba_data/python/bauiv1lib/trophies.py b/src/assets/ba_data/python/bauiv1lib/trophies.py index e605ad7c..1224ca2b 100644 --- a/src/assets/ba_data/python/bauiv1lib/trophies.py +++ b/src/assets/ba_data/python/bauiv1lib/trophies.py @@ -31,9 +31,7 @@ class TrophiesWindow(popup.PopupWindow): scale = ( 2.3 if uiscale is bui.UIScale.SMALL - else 1.65 - if uiscale is bui.UIScale.MEDIUM - else 1.23 + else 1.65 if uiscale is bui.UIScale.MEDIUM else 1.23 ) self._transitioning_out = False self._width = 300 @@ -179,9 +177,9 @@ class TrophiesWindow(popup.PopupWindow): scale=0.4, flatness=1.0, shadow=0.0, - color=(0.63, 0.6, 0.75) - if (t_count > 0) - else (0.6, 0.6, 0.6, 0.4), + color=( + (0.63, 0.6, 0.75) if (t_count > 0) else (0.6, 0.6, 0.6, 0.4) + ), text=txt, size=(0, 0), h_align='center', @@ -193,9 +191,9 @@ class TrophiesWindow(popup.PopupWindow): parent=self._subcontainer, position=(sub_width * 0.88, sub_height - 20 - incr * i), maxwidth=sub_width * 0.3, - color=(0.7, 0.8, 1.0) - if (t_count > 0) - else (0.9, 0.9, 1.0, 0.3), + color=( + (0.7, 0.8, 1.0) if (t_count > 0) else (0.9, 0.9, 1.0, 0.3) + ), flatness=1.0, shadow=0.0, scale=0.5, diff --git a/src/assets/ba_data/python/bauiv1lib/url.py b/src/assets/ba_data/python/bauiv1lib/url.py index 2e9b8335..bb199123 100644 --- a/src/assets/ba_data/python/bauiv1lib/url.py +++ b/src/assets/ba_data/python/bauiv1lib/url.py @@ -27,9 +27,7 @@ class ShowURLWindow(bui.Window): scale=( 1.25 if uiscale is bui.UIScale.SMALL - else 1.25 - if uiscale is bui.UIScale.MEDIUM - else 1.25 + else 1.25 if uiscale is bui.UIScale.MEDIUM else 1.25 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/v2upgrade.py b/src/assets/ba_data/python/bauiv1lib/v2upgrade.py index de398221..1ce5b3be 100644 --- a/src/assets/ba_data/python/bauiv1lib/v2upgrade.py +++ b/src/assets/ba_data/python/bauiv1lib/v2upgrade.py @@ -28,9 +28,7 @@ class V2UpgradeWindow(bui.Window): scale=( 1.25 if uiscale is bui.UIScale.SMALL - else 1.25 - if uiscale is bui.UIScale.MEDIUM - else 1.25 + else 1.25 if uiscale is bui.UIScale.MEDIUM else 1.25 ), ) ) diff --git a/src/assets/ba_data/python/bauiv1lib/watch.py b/src/assets/ba_data/python/bauiv1lib/watch.py index b9636123..0757c68e 100644 --- a/src/assets/ba_data/python/bauiv1lib/watch.py +++ b/src/assets/ba_data/python/bauiv1lib/watch.py @@ -60,9 +60,7 @@ class WatchWindow(bui.Window): self._height = ( 578 if uiscale is bui.UIScale.SMALL - else 670 - if uiscale is bui.UIScale.MEDIUM - else 800 + else 670 if uiscale is bui.UIScale.MEDIUM else 800 ) self._current_tab: WatchWindow.TabID | None = None extra_top = 20 if uiscale is bui.UIScale.SMALL else 0 @@ -76,15 +74,13 @@ class WatchWindow(bui.Window): scale=( 1.3 if uiscale is bui.UIScale.SMALL - else 0.97 - if uiscale is bui.UIScale.MEDIUM - else 0.8 + else 0.97 if uiscale is bui.UIScale.MEDIUM else 0.8 + ), + stack_offset=( + (0, -10) + if uiscale is bui.UIScale.SMALL + else (0, 15) if uiscale is bui.UIScale.MEDIUM else (0, 0) ), - stack_offset=(0, -10) - if uiscale is bui.UIScale.SMALL - else (0, 15) - if uiscale is bui.UIScale.MEDIUM - else (0, 0), ) ) @@ -249,16 +245,12 @@ class WatchWindow(bui.Window): b_height = ( 107 if uiscale is bui.UIScale.SMALL - else 142 - if uiscale is bui.UIScale.MEDIUM - else 190 + else 142 if uiscale is bui.UIScale.MEDIUM else 190 ) b_space_extra = ( 0 if uiscale is bui.UIScale.SMALL - else -2 - if uiscale is bui.UIScale.MEDIUM - else -5 + else -2 if uiscale is bui.UIScale.MEDIUM else -5 ) b_color = (0.6, 0.53, 0.63) @@ -268,9 +260,7 @@ class WatchWindow(bui.Window): - ( 48 if uiscale is bui.UIScale.SMALL - else 45 - if uiscale is bui.UIScale.MEDIUM - else 40 + else 45 if uiscale is bui.UIScale.MEDIUM else 40 ) - b_height ) @@ -393,9 +383,7 @@ class WatchWindow(bui.Window): scale=( 1.8 if uiscale is bui.UIScale.SMALL - else 1.55 - if uiscale is bui.UIScale.MEDIUM - else 1.0 + else 1.55 if uiscale is bui.UIScale.MEDIUM else 1.0 ), size=(c_width, c_height), transition='in_scale', @@ -581,9 +569,9 @@ class WatchWindow(bui.Window): parent=self._columnwidget, size=(self._my_replays_scroll_width / t_scale, 30), selectable=True, - color=(1.0, 1, 0.4) - if name == '__lastReplay.brp' - else (1, 1, 1), + color=( + (1.0, 1, 0.4) if name == '__lastReplay.brp' else (1, 1, 1) + ), always_highlight=True, on_select_call=bui.Call(self._on_my_replay_select, name), on_activate_call=self._my_replays_watch_replay_button.activate, diff --git a/src/assets/sphinx/template/Makefile b/src/assets/sphinx/template/Makefile new file mode 100644 index 00000000..d4bb2cbb --- /dev/null +++ b/src/assets/sphinx/template/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/src/assets/sphinx/template/conf.py b/src/assets/sphinx/template/conf.py new file mode 100644 index 00000000..b0ff2933 --- /dev/null +++ b/src/assets/sphinx/template/conf.py @@ -0,0 +1,94 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- +import os +import sys + +sphinx_settings = eval(os.getenv('SPHINX_SETTINGS')) # set in tools/batools/docs.py +ballistica_root = os.getenv('BALLISTICA_ROOT') + '/' + +assets_dirs: dict = { + 'ba_data': 'src/assets/ba_data/python/', + 'dummy_modules': 'build/dummymodules/', + 'efro_tools': 'tools/', # for efro and bacommon package +} + +sys.path.append(os.path.abspath(ballistica_root + assets_dirs['ba_data'])) +sys.path.append(os.path.abspath(ballistica_root + assets_dirs['dummy_modules'])) +sys.path.append(os.path.abspath(ballistica_root + assets_dirs['efro_tools'])) + +# -- Options for HTML output ------------------------------------------------- +html_theme = 'furo' # python_docs_theme, groundwork, furo, sphinx_rtd_theme +html_title = sphinx_settings['project_name'] + ' ' + str(sphinx_settings['version']) + ' documentation' +# for more themes visit https://sphinx-themes.org/ + +html_logo = 'https://camo.githubusercontent.com/25021344ceaa7def6fa6523f79115f7ffada8d26b4768bb9a0cf65fc33304f45/68747470733a2f2f66696c65732e62616c6c6973746963612e6e65742f62616c6c6973746963615f6d656469612f62616c6c6973746963615f6c6f676f5f68616c662e706e67' + +if html_theme == 'furo': + html_theme_options = { + 'announcement': 'This is a placeholder announcement', + 'light_css_variables': { + 'color-brand-primary': '#3cda0b', + 'color-brand-content': '#7C4DFF', + }, + 'dark_css_variables': { + 'color-brand-primary': '#3cda0b', + 'color-brand-content': '#7C4DFF', + }, + 'footer_icons': [{ + 'name': 'GitHub', + 'url': 'https://github.com/efroemling/ballistica/', + 'html': """ + + + + """, + 'class': '', + }, + ], + 'top_of_page_button': 'edit', + 'navigation_with_keys': True, + } + + + + +# -- Project information ----------------------------------------------------- + +keep_warnings = True # Supressing warnings + +project = sphinx_settings['project_name'] +copyright = sphinx_settings['copyright'] +author = sphinx_settings['project_author'] +# The full version, including alpha/beta/rc tags +version = str(sphinx_settings['version']) +release = str(sphinx_settings['buildnum']) + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +autosummary_generate = True +extensions = [ + 'sphinx.ext.napoleon', # https://stackoverflow.com/questions/45880348/how-to-remove-the-cause-of-an-unexpected-indentation-warning-when-generating-cod + 'sphinx.ext.autodoc', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] diff --git a/src/assets/sphinx/template/index.rst b/src/assets/sphinx/template/index.rst new file mode 100644 index 00000000..327d5da9 --- /dev/null +++ b/src/assets/sphinx/template/index.rst @@ -0,0 +1,24 @@ +.. Bombsquad documentation master file, created by + sphinx-quickstart on Sat Mar 2 18:31:19 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + + see https://pradyunsg.me/furo/reference/ for formatting help +.. image:: https://camo.githubusercontent.com/25021344ceaa7def6fa6523f79115f7ffada8d26b4768bb9a0cf65fc33304f45/68747470733a2f2f66696c65732e62616c6c6973746963612e6e65742f62616c6c6973746963615f6d656469612f62616c6c6973746963615f6c6f676f5f68616c662e706e67 + +Welcome to ballistica-bombsquad's documentation! +================================================ +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + modules + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` + +.. note:: For customization of this page see https://github.com/efroemling/ballistica/blob/master/src/assets/sphinx/template/index.rst diff --git a/src/assets/sphinx/template/make.bat b/src/assets/sphinx/template/make.bat new file mode 100644 index 00000000..32bb2452 --- /dev/null +++ b/src/assets/sphinx/template/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/src/ballistica/base/assets/assets.cc b/src/ballistica/base/assets/assets.cc index a8b59020..0223e911 100644 --- a/src/ballistica/base/assets/assets.cc +++ b/src/ballistica/base/assets/assets.cc @@ -699,8 +699,8 @@ auto Assets::GetPendingLoadCount() -> int { template auto Assets::GetAssetPendingLoadCount( - std::unordered_map >* t_list, AssetType type) - -> int { + std::unordered_map >* t_list, + AssetType type) -> int { assert(g_base->InLogicThread()); assert(asset_lists_locked_); @@ -1056,8 +1056,8 @@ void Assets::Prune(int level) { } } -auto Assets::FindAssetFile(FileType type, const std::string& name) - -> std::string { +auto Assets::FindAssetFile(FileType type, + const std::string& name) -> std::string { std::string file_out; // We don't protect package-path access so make sure its always from here. diff --git a/src/ballistica/base/assets/assets.h b/src/ballistica/base/assets/assets.h index aa396371..f9cbbe94 100644 --- a/src/ballistica/base/assets/assets.h +++ b/src/ballistica/base/assets/assets.h @@ -38,8 +38,8 @@ class Assets { /// is deleted once the load is completed. void AddPendingLoad(Object::Ref* c); enum class FileType { kMesh, kCollisionMesh, kTexture, kSound, kData }; - auto FindAssetFile(FileType fileType, const std::string& file_in) - -> std::string; + auto FindAssetFile(FileType fileType, + const std::string& file_in) -> std::string; /// Unload renderer-specific bits only (gl display lists, etc) - used when /// recreating/adjusting the renderer. @@ -131,8 +131,8 @@ class Assets { template auto GetAssetPendingLoadCount( - std::unordered_map >* t_list, AssetType type) - -> int; + std::unordered_map >* t_list, + AssetType type) -> int; template auto GetAsset(const std::string& file_name, diff --git a/src/ballistica/base/assets/sound_asset.cc b/src/ballistica/base/assets/sound_asset.cc index 69571ecd..c6e64dcb 100644 --- a/src/ballistica/base/assets/sound_asset.cc +++ b/src/ballistica/base/assets/sound_asset.cc @@ -33,8 +33,8 @@ static auto CallbackRead(void* ptr, size_t size, size_t nmemb, void* data_source) -> size_t { return fread(ptr, size, nmemb, static_cast(data_source)); } -static auto CallbackSeek(void* data_source, ogg_int64_t offset, int whence) - -> int { +static auto CallbackSeek(void* data_source, ogg_int64_t offset, + int whence) -> int { return fseek(static_cast(data_source), static_cast_check_fit(offset), whence); // NOLINT } diff --git a/src/ballistica/base/audio/audio.cc b/src/ballistica/base/audio/audio.cc index f37f4632..7638f032 100644 --- a/src/ballistica/base/audio/audio.cc +++ b/src/ballistica/base/audio/audio.cc @@ -124,8 +124,8 @@ auto Audio::IsSoundPlaying(uint32_t play_id) -> bool { return result; } -auto Audio::SourceBeginExisting(uint32_t play_id, int debug_id) - -> AudioSource* { +auto Audio::SourceBeginExisting(uint32_t play_id, + int debug_id) -> AudioSource* { BA_DEBUG_FUNCTION_TIMER_BEGIN(); uint32_t source_id = AudioServer::SourceIdFromPlayId(play_id); @@ -186,8 +186,8 @@ auto Audio::SafePlaySysSound(SysSoundID sound_id) -> std::optional { return PlaySound(g_base->assets->SysSound(sound_id)); } -auto Audio::PlaySound(SoundAsset* sound, float volume) - -> std::optional { +auto Audio::PlaySound(SoundAsset* sound, + float volume) -> std::optional { assert(g_core); assert(g_base->InLogicThread()); BA_DEBUG_FUNCTION_TIMER_BEGIN(); diff --git a/src/ballistica/base/audio/ogg_stream.cc b/src/ballistica/base/audio/ogg_stream.cc index 5b51d427..c62c4799 100644 --- a/src/ballistica/base/audio/ogg_stream.cc +++ b/src/ballistica/base/audio/ogg_stream.cc @@ -15,8 +15,8 @@ static auto CallbackRead(void* ptr, size_t size, size_t nmemb, return fread(ptr, size, nmemb, static_cast(data_source)); } -static auto CallbackSeek(void* data_source, ogg_int64_t offset, int whence) - -> int { +static auto CallbackSeek(void* data_source, ogg_int64_t offset, + int whence) -> int { return fseek(static_cast(data_source), static_cast_check_fit(offset), whence); // NOLINT } diff --git a/src/ballistica/base/graphics/gl/program/program_blur_gl.h b/src/ballistica/base/graphics/gl/program/program_blur_gl.h index ddd0219a..7d1deb27 100644 --- a/src/ballistica/base/graphics/gl/program/program_blur_gl.h +++ b/src/ballistica/base/graphics/gl/program/program_blur_gl.h @@ -19,9 +19,9 @@ class RendererGL::ProgramBlurGL : public RendererGL::ProgramGL { ProgramBlurGL(RendererGL* renderer, int flags) : RendererGL::ProgramGL( - renderer, Object::New(GetVertexCode(flags)), - Object::New(GetFragmentCode(flags)), GetName(flags), - GetPFlags(flags)), + renderer, Object::New(GetVertexCode(flags)), + Object::New(GetFragmentCode(flags)), + GetName(flags), GetPFlags(flags)), flags_(flags), pixel_size_x_(0.0f), pixel_size_y_(0.0f) { diff --git a/src/ballistica/base/graphics/gl/program/program_object_gl.h b/src/ballistica/base/graphics/gl/program/program_object_gl.h index 0941ea9f..7bb620db 100644 --- a/src/ballistica/base/graphics/gl/program/program_object_gl.h +++ b/src/ballistica/base/graphics/gl/program/program_object_gl.h @@ -23,9 +23,9 @@ class RendererGL::ProgramObjectGL : public RendererGL::ProgramGL { ProgramObjectGL(RendererGL* renderer, int flags) : RendererGL::ProgramGL( - renderer, Object::New(GetVertexCode(flags)), - Object::New(GetFragmentCode(flags)), GetName(flags), - GetPFlags(flags)), + renderer, Object::New(GetVertexCode(flags)), + Object::New(GetFragmentCode(flags)), + GetName(flags), GetPFlags(flags)), flags_(flags), r_(0), g_(0), diff --git a/src/ballistica/base/graphics/gl/program/program_post_process_gl.h b/src/ballistica/base/graphics/gl/program/program_post_process_gl.h index 64e7df99..87c31d78 100644 --- a/src/ballistica/base/graphics/gl/program/program_post_process_gl.h +++ b/src/ballistica/base/graphics/gl/program/program_post_process_gl.h @@ -23,9 +23,9 @@ class RendererGL::ProgramPostProcessGL : public RendererGL::ProgramGL { ProgramPostProcessGL(RendererGL* renderer, int flags) : RendererGL::ProgramGL( - renderer, Object::New(GetVertexCode(flags)), - Object::New(GetFragmentCode(flags)), GetName(flags), - GetPFlags(flags)), + renderer, Object::New(GetVertexCode(flags)), + Object::New(GetFragmentCode(flags)), + GetName(flags), GetPFlags(flags)), flags_(flags), dof_near_min_(0), dof_near_max_(0), diff --git a/src/ballistica/base/graphics/gl/program/program_shield_gl.h b/src/ballistica/base/graphics/gl/program/program_shield_gl.h index 9ecfd8e9..16ad3724 100644 --- a/src/ballistica/base/graphics/gl/program/program_shield_gl.h +++ b/src/ballistica/base/graphics/gl/program/program_shield_gl.h @@ -19,9 +19,9 @@ class RendererGL::ProgramShieldGL : public RendererGL::ProgramGL { ProgramShieldGL(RendererGL* renderer, int flags) : RendererGL::ProgramGL( - renderer, Object::New(GetVertexCode(flags)), - Object::New(GetFragmentCode(flags)), GetName(flags), - GetPFlags(flags)), + renderer, Object::New(GetVertexCode(flags)), + Object::New(GetFragmentCode(flags)), + GetName(flags), GetPFlags(flags)), flags_(flags) { SetTextureUnit("depthTex", kDepthTexUnit); } diff --git a/src/ballistica/base/graphics/gl/program/program_simple_gl.h b/src/ballistica/base/graphics/gl/program/program_simple_gl.h index e2b27d67..23c85f48 100644 --- a/src/ballistica/base/graphics/gl/program/program_simple_gl.h +++ b/src/ballistica/base/graphics/gl/program/program_simple_gl.h @@ -22,9 +22,9 @@ class RendererGL::ProgramSimpleGL : public RendererGL::ProgramGL { ProgramSimpleGL(RendererGL* renderer, int flags) : RendererGL::ProgramGL( - renderer, Object::New(GetVertexCode(flags)), - Object::New(GetFragmentCode(flags)), GetName(flags), - GetPFlags(flags)), + renderer, Object::New(GetVertexCode(flags)), + Object::New(GetFragmentCode(flags)), + GetName(flags), GetPFlags(flags)), flags_(flags) { if (flags & SHD_TEXTURE) { SetTextureUnit("colorTex", kColorTexUnit); diff --git a/src/ballistica/base/graphics/gl/program/program_smoke_gl.h b/src/ballistica/base/graphics/gl/program/program_smoke_gl.h index dc6f2bbc..e5050e1c 100644 --- a/src/ballistica/base/graphics/gl/program/program_smoke_gl.h +++ b/src/ballistica/base/graphics/gl/program/program_smoke_gl.h @@ -17,9 +17,9 @@ class RendererGL::ProgramSmokeGL : public RendererGL::ProgramGL { ProgramSmokeGL(RendererGL* renderer, int flags) : RendererGL::ProgramGL( - renderer, Object::New(GetVertexCode(flags)), - Object::New(GetFragmentCode(flags)), GetName(flags), - GetPFlags(flags)), + renderer, Object::New(GetVertexCode(flags)), + Object::New(GetFragmentCode(flags)), + GetName(flags), GetPFlags(flags)), flags_(flags), r_(0), g_(0), diff --git a/src/ballistica/base/graphics/gl/program/program_sprite_gl.h b/src/ballistica/base/graphics/gl/program/program_sprite_gl.h index 16f34dbd..da8625d0 100644 --- a/src/ballistica/base/graphics/gl/program/program_sprite_gl.h +++ b/src/ballistica/base/graphics/gl/program/program_sprite_gl.h @@ -17,9 +17,9 @@ class RendererGL::ProgramSpriteGL : public RendererGL::ProgramGL { ProgramSpriteGL(RendererGL* renderer, int flags) : RendererGL::ProgramGL( - renderer, Object::New(GetVertexCode(flags)), - Object::New(GetFragmentCode(flags)), GetName(flags), - GetPFlags(flags)), + renderer, Object::New(GetVertexCode(flags)), + Object::New(GetFragmentCode(flags)), + GetName(flags), GetPFlags(flags)), flags_(flags), r_(0), g_(0), diff --git a/src/ballistica/base/graphics/gl/renderer_gl.cc b/src/ballistica/base/graphics/gl/renderer_gl.cc index 26f84d7c..38f8b173 100644 --- a/src/ballistica/base/graphics/gl/renderer_gl.cc +++ b/src/ballistica/base/graphics/gl/renderer_gl.cc @@ -2944,19 +2944,17 @@ auto RendererGL::NewScreenRenderTarget() -> RenderTarget* { return Object::NewDeferred(this); } -auto RendererGL::NewFramebufferRenderTarget(int width, int height, - bool linear_interp, bool depth, - bool texture, bool depth_texture, - bool high_quality, bool msaa, - bool alpha) - -> Object::Ref { +auto RendererGL::NewFramebufferRenderTarget( + int width, int height, bool linear_interp, bool depth, bool texture, + bool depth_texture, bool high_quality, bool msaa, + bool alpha) -> Object::Ref { return Object::New( this, width, height, linear_interp, depth, texture, depth_texture, high_quality, msaa, alpha); } -auto RendererGL::NewMeshData(MeshDataType mesh_type, MeshDrawType draw_type) - -> MeshRendererData* { +auto RendererGL::NewMeshData(MeshDataType mesh_type, + MeshDrawType draw_type) -> MeshRendererData* { switch (mesh_type) { case MeshDataType::kIndexedSimpleSplit: { MeshDataSimpleSplitGL* data; diff --git a/src/ballistica/base/graphics/gl/renderer_gl.h b/src/ballistica/base/graphics/gl/renderer_gl.h index 7793a70e..383bd356 100644 --- a/src/ballistica/base/graphics/gl/renderer_gl.h +++ b/src/ballistica/base/graphics/gl/renderer_gl.h @@ -150,18 +150,17 @@ class RendererGL : public Renderer { void SetDepthTesting(bool enable) override; void SetDrawAtEqualDepth(bool enable) override; auto NewScreenRenderTarget() -> RenderTarget* override; - auto NewFramebufferRenderTarget(int width, int height, bool linear_interp, - bool depth, bool texture, - bool depth_is_texture, bool high_quality, - bool msaa, bool alpha) - -> Object::Ref override; + auto NewFramebufferRenderTarget( + int width, int height, bool linear_interp, bool depth, bool texture, + bool depth_is_texture, bool high_quality, bool msaa, + bool alpha) -> Object::Ref override; auto NewMeshAssetData(const MeshAsset& mesh) -> Object::Ref override; auto NewTextureData(const TextureAsset& texture) -> Object::Ref override; - auto NewMeshData(MeshDataType type, MeshDrawType drawType) - -> MeshRendererData* override; + auto NewMeshData(MeshDataType type, + MeshDrawType drawType) -> MeshRendererData* override; void DeleteMeshData(MeshRendererData* data, MeshDataType type) override; void ProcessRenderCommandBuffer(RenderCommandBuffer* buffer, diff --git a/src/ballistica/base/graphics/graphics.cc b/src/ballistica/base/graphics/graphics.cc index 77f30abf..41adaba9 100644 --- a/src/ballistica/base/graphics/graphics.cc +++ b/src/ballistica/base/graphics/graphics.cc @@ -481,8 +481,8 @@ void Graphics::DrawMiscOverlays(FrameDef* frame_def) { screenmessages->DrawMiscOverlays(frame_def); } -auto Graphics::GetDebugGraph(const std::string& name, bool smoothed) - -> NetGraph* { +auto Graphics::GetDebugGraph(const std::string& name, + bool smoothed) -> NetGraph* { auto out = debug_graphs_.find(name); if (out == debug_graphs_.end()) { debug_graphs_[name] = Object::New(); @@ -1653,9 +1653,8 @@ auto Graphics::GraphicsQualityFromRequest(GraphicsQualityRequest request, } } -auto Graphics::TextureQualityFromRequest(TextureQualityRequest request, - TextureQuality auto_val) - -> TextureQuality { +auto Graphics::TextureQualityFromRequest( + TextureQualityRequest request, TextureQuality auto_val) -> TextureQuality { switch (request) { case TextureQualityRequest::kLow: return TextureQuality::kLow; diff --git a/src/ballistica/base/graphics/graphics.h b/src/ballistica/base/graphics/graphics.h index 93ef8310..687f07ea 100644 --- a/src/ballistica/base/graphics/graphics.h +++ b/src/ballistica/base/graphics/graphics.h @@ -335,9 +335,8 @@ class Graphics { static auto GraphicsQualityFromRequest(GraphicsQualityRequest request, GraphicsQuality auto_val) -> GraphicsQuality; - static auto TextureQualityFromRequest(TextureQualityRequest request, - TextureQuality auto_val) - -> TextureQuality; + static auto TextureQualityFromRequest( + TextureQualityRequest request, TextureQuality auto_val) -> TextureQuality; /// For temporary use from arbitrary threads. This should be removed when /// possible and replaced with proper safe thread-specific access patterns diff --git a/src/ballistica/base/graphics/graphics_vr.cc b/src/ballistica/base/graphics/graphics_vr.cc index 386825e5..3325555b 100644 --- a/src/ballistica/base/graphics/graphics_vr.cc +++ b/src/ballistica/base/graphics/graphics_vr.cc @@ -15,8 +15,8 @@ namespace ballistica::base { -static auto ValueTestFloat(float* storage, double* absval, double* deltaval) - -> double { +static auto ValueTestFloat(float* storage, double* absval, + double* deltaval) -> double { if (absval) { *storage = static_cast(*absval); } @@ -26,8 +26,8 @@ static auto ValueTestFloat(float* storage, double* absval, double* deltaval) return *storage; } -static auto ValueTestBool(bool* storage, double* absval, double* deltaval) - -> double { +static auto ValueTestBool(bool* storage, double* absval, + double* deltaval) -> double { if (absval) { *storage = static_cast(*absval); } @@ -245,9 +245,8 @@ void GraphicsVR::CalcVROverlayMatrices(FrameDef* frame_def) { } } -auto GraphicsVR::CalcVROverlayMatrix(const Vector3f& cam_pt, - const Vector3f& cam_target_pt) const - -> Matrix44f { +auto GraphicsVR::CalcVROverlayMatrix( + const Vector3f& cam_pt, const Vector3f& cam_target_pt) const -> Matrix44f { Matrix44f m = Matrix44fTranslate(cam_target_pt); Vector3f diff = cam_pt - cam_target_pt; diff.Normalize(); diff --git a/src/ballistica/base/graphics/renderer/renderer.h b/src/ballistica/base/graphics/renderer/renderer.h index 3bc6ccc2..4a4a0466 100644 --- a/src/ballistica/base/graphics/renderer/renderer.h +++ b/src/ballistica/base/graphics/renderer/renderer.h @@ -152,8 +152,8 @@ class Renderer { -> Object::Ref = 0; virtual auto NewTextureData(const TextureAsset& texture) -> Object::Ref = 0; - virtual auto NewMeshData(MeshDataType t, MeshDrawType drawType) - -> MeshRendererData* = 0; + virtual auto NewMeshData(MeshDataType t, + MeshDrawType drawType) -> MeshRendererData* = 0; virtual void DeleteMeshData(MeshRendererData* data, MeshDataType t) = 0; virtual void ProcessRenderCommandBuffer(RenderCommandBuffer* buffer, const RenderPass& pass, @@ -176,12 +176,10 @@ class Renderer { virtual void InvalidateFramebuffer(bool color, bool depth, bool target_read_framebuffer) = 0; virtual auto NewScreenRenderTarget() -> RenderTarget* = 0; - virtual auto NewFramebufferRenderTarget(int width, int height, - bool linear_interp, bool depth, - bool texture, bool depth_texture, - bool high_quality, bool msaa, - bool alpha) - -> Object::Ref = 0; + virtual auto NewFramebufferRenderTarget( + int width, int height, bool linear_interp, bool depth, bool texture, + bool depth_texture, bool high_quality, bool msaa, + bool alpha) -> Object::Ref = 0; virtual void PushGroupMarker(const char* label) = 0; virtual void PopGroupMarker() = 0; virtual void BlitBuffer(RenderTarget* src, RenderTarget* dst, bool depth, diff --git a/src/ballistica/base/graphics/support/camera.cc b/src/ballistica/base/graphics/support/camera.cc index c8406c33..483429bc 100644 --- a/src/ballistica/base/graphics/support/camera.cc +++ b/src/ballistica/base/graphics/support/camera.cc @@ -904,18 +904,16 @@ void Camera::ApplyToFrameDef(FrameDef* frame_def) { // for now, though, there's just a single beauty pass // which is us. - RenderPass* passes[] = { - frame_def->beauty_pass(), - frame_def->beauty_pass_bg(), + RenderPass* passes[] = {frame_def->beauty_pass(), + frame_def->beauty_pass_bg(), #if BA_VR_BUILD - frame_def->overlay_pass(), - frame_def->GetOverlayFixedPass(), - frame_def->vr_cover_pass(), + frame_def->overlay_pass(), + frame_def->GetOverlayFixedPass(), + frame_def->vr_cover_pass(), #endif - frame_def->overlay_3d_pass(), - frame_def->blit_pass(), - nullptr - }; + frame_def->overlay_3d_pass(), + frame_def->blit_pass(), + nullptr}; // Currently, our x/y fovs are simply enough to fit everything. // Check the aspect ratio of what we're rendering to and fit them. diff --git a/src/ballistica/base/graphics/text/text_graphics.cc b/src/ballistica/base/graphics/text/text_graphics.cc index fae81787..dd13a924 100644 --- a/src/ballistica/base/graphics/text/text_graphics.cc +++ b/src/ballistica/base/graphics/text/text_graphics.cc @@ -47,6 +47,12 @@ TextGraphics::TextGraphics() { g.pen_offset_y -= 0.1f; } + // Bring Fast Forward & Rewind down and to the left a bit. + if (index == 13 || index == 15) { + g.pen_offset_y -= 0.055; + g.pen_offset_x -= 0.01; + } + // Shrink account logos and move them up a bit. if (index == 29 || index == 32 || index == 33 || index == 38 || index == 40 || index == 48 || index == 49) { diff --git a/src/ballistica/base/graphics/texture/ktx.cc b/src/ballistica/base/graphics/texture/ktx.cc index b532aa92..8b5dd24f 100644 --- a/src/ballistica/base/graphics/texture/ktx.cc +++ b/src/ballistica/base/graphics/texture/ktx.cc @@ -320,7 +320,7 @@ typedef short int16; #define PUTBITS(dest, data, size, startpos) \ dest = ((dest & ~MASK(size, startpos)) \ | ((data << SHIFT(size, startpos)) & MASK(size, startpos))) -#define SHIFTHIGH(size, startpos) (((startpos)-32) - (size) + 1) +#define SHIFTHIGH(size, startpos) (((startpos) - 32) - (size) + 1) #define MASKHIGH(size, startpos) \ (((1 << (size)) - 1) << SHIFTHIGH(size, startpos)) #define PUTBITSHIGH(dest, data, size, startpos) \ @@ -329,7 +329,7 @@ typedef short int16; #define GETBITS(source, size, startpos) \ (((source) >> ((startpos) - (size) + 1)) & ((1 << (size)) - 1)) #define GETBITSHIGH(source, size, startpos) \ - (((source) >> (((startpos)-32) - (size) + 1)) & ((1 << (size)) - 1)) + (((source) >> (((startpos) - 32) - (size) + 1)) & ((1 << (size)) - 1)) #ifndef PGMOUT #define PGMOUT 0 #endif @@ -352,7 +352,7 @@ typedef short int16; // Helper Macros #define CLAMP(ll, x, ul) (((x) < (ll)) ? (ll) : (((x) > (ul)) ? (ul) : (x))) -#define JAS_ROUND(x) (((x) < 0.0) ? ((int)((x)-0.5)) : ((int)((x) + 0.5))) +#define JAS_ROUND(x) (((x) < 0.0) ? ((int)((x) - 0.5)) : ((int)((x) + 0.5))) #define RED_CHANNEL(img, width, x, y, channels) \ img[channels * (y * width + x) + 0] diff --git a/src/ballistica/base/input/device/joystick_input.cc b/src/ballistica/base/input/device/joystick_input.cc index 08f7386c..4e333224 100644 --- a/src/ballistica/base/input/device/joystick_input.cc +++ b/src/ballistica/base/input/device/joystick_input.cc @@ -331,8 +331,8 @@ auto JoystickInput::ShouldBeHiddenFromUser() -> bool { } } -auto JoystickInput::GetCalibratedValue(float raw, float neutral) const - -> int32_t { +auto JoystickInput::GetCalibratedValue(float raw, + float neutral) const -> int32_t { int32_t val; float dead_zone = 0.5f; float mag, target; diff --git a/src/ballistica/base/input/input.h b/src/ballistica/base/input/input.h index 5c23bf33..5d7b0b12 100644 --- a/src/ballistica/base/input/input.h +++ b/src/ballistica/base/input/input.h @@ -43,8 +43,8 @@ class Input { // Given a device name and persistent identifier for it, returns a device or // nullptr. Note that this can return hidden devices (ones the user has // flagged as totally-ignored, etc). - auto GetInputDevice(const std::string& name, const std::string& persistent_id) - -> InputDevice*; + auto GetInputDevice(const std::string& name, + const std::string& persistent_id) -> InputDevice*; // Return a device by id, or nullptr for an invalid id. Note that this can // return hidden devices (ones the user has flagged as totally-ignored, etc). diff --git a/src/ballistica/base/logic/logic.cc b/src/ballistica/base/logic/logic.cc index 12f03435..b6516c57 100644 --- a/src/ballistica/base/logic/logic.cc +++ b/src/ballistica/base/logic/logic.cc @@ -634,8 +634,8 @@ void Logic::NotifyOfPendingAssetLoads() { UpdatePendingWorkTimer_(); } -auto Logic::NewAppTimer(microsecs_t length, bool repeat, Runnable* runnable) - -> int { +auto Logic::NewAppTimer(microsecs_t length, bool repeat, + Runnable* runnable) -> int { // App-Timers simply get injected into our loop and run alongside our own // stuff. assert(g_base->InLogicThread()); @@ -659,8 +659,8 @@ void Logic::SetAppTimerLength(int timer_id, microsecs_t length) { } } -auto Logic::NewDisplayTimer(microsecs_t length, bool repeat, Runnable* runnable) - -> int { +auto Logic::NewDisplayTimer(microsecs_t length, bool repeat, + Runnable* runnable) -> int { // Display-Timers go into a timer-list that we exec explicitly when we // step display-time. assert(g_base->InLogicThread()); diff --git a/src/ballistica/base/logic/logic.h b/src/ballistica/base/logic/logic.h index 2e389214..e2af720e 100644 --- a/src/ballistica/base/logic/logic.h +++ b/src/ballistica/base/logic/logic.h @@ -95,8 +95,8 @@ class Logic { void DeleteAppTimer(int timer_id); void SetAppTimerLength(int timer_id, microsecs_t length); - auto NewDisplayTimer(microsecs_t length, bool repeat, Runnable* runnable) - -> int; + auto NewDisplayTimer(microsecs_t length, bool repeat, + Runnable* runnable) -> int; void DeleteDisplayTimer(int timer_id); void SetDisplayTimerLength(int timer_id, microsecs_t length); diff --git a/src/ballistica/base/python/base_python.cc b/src/ballistica/base/python/base_python.cc index a22c126e..83f53425 100644 --- a/src/ballistica/base/python/base_python.cc +++ b/src/ballistica/base/python/base_python.cc @@ -333,8 +333,8 @@ auto BasePython::GetRawConfigValue(const char* name) -> PyObject* { return PyDict_GetItemString(objs().Get(ObjID::kConfig).Get(), name); } -auto BasePython::GetRawConfigValue(const char* name, const char* default_value) - -> std::string { +auto BasePython::GetRawConfigValue(const char* name, + const char* default_value) -> std::string { assert(g_base->InLogicThread()); assert(objs().Exists(ObjID::kConfig)); PyObject* value = @@ -345,8 +345,8 @@ auto BasePython::GetRawConfigValue(const char* name, const char* default_value) return PyUnicode_AsUTF8(value); } -auto BasePython::GetRawConfigValue(const char* name, float default_value) - -> float { +auto BasePython::GetRawConfigValue(const char* name, + float default_value) -> float { assert(g_base->InLogicThread()); assert(objs().Exists(ObjID::kConfig)); PyObject* value = @@ -402,8 +402,8 @@ auto BasePython::GetRawConfigValue(const char* name, int default_value) -> int { } } -auto BasePython::GetRawConfigValue(const char* name, bool default_value) - -> bool { +auto BasePython::GetRawConfigValue(const char* name, + bool default_value) -> bool { assert(g_base->InLogicThread()); assert(objs().Exists(ObjID::kConfig)); PyObject* value = @@ -545,8 +545,8 @@ auto BasePython::GetResource(const char* key, const char* fallback_resource, return std::string(""; } -auto BasePython::GetTranslation(const char* category, const char* s) - -> std::string { +auto BasePython::GetTranslation(const char* category, + const char* s) -> std::string { assert(Python::HaveGIL()); PythonRef results; PythonRef args(Py_BuildValue("(ss)", category, s), PythonRef::kSteal); diff --git a/src/ballistica/base/python/base_python.h b/src/ballistica/base/python/base_python.h index 3d661f7a..e5cf4d50 100644 --- a/src/ballistica/base/python/base_python.h +++ b/src/ballistica/base/python/base_python.h @@ -145,8 +145,8 @@ class BasePython { // functions (which themselves call these functions) auto GetRawConfigValue(const char* name) -> PyObject*; // (returns a borrowed ref) - auto GetRawConfigValue(const char* name, const char* default_value) - -> std::string; + auto GetRawConfigValue(const char* name, + const char* default_value) -> std::string; auto GetRawConfigValue(const char* name, float default_value) -> float; auto GetRawConfigValue(const char* name, std::optional default_value) -> std::optional; diff --git a/src/ballistica/base/python/class/python_class_app_timer.h b/src/ballistica/base/python/class/python_class_app_timer.h index 7295988a..0c086a2e 100644 --- a/src/ballistica/base/python/class/python_class_app_timer.h +++ b/src/ballistica/base/python/class/python_class_app_timer.h @@ -18,8 +18,8 @@ class PythonClassAppTimer : public PythonClass { static PyTypeObject type_obj; private: - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassAppTimer* self); int timer_id_{}; bool have_timer_{}; diff --git a/src/ballistica/base/python/class/python_class_context_call.cc b/src/ballistica/base/python/class/python_class_context_call.cc index 3dad799a..e50b227e 100644 --- a/src/ballistica/base/python/class/python_class_context_call.cc +++ b/src/ballistica/base/python/class/python_class_context_call.cc @@ -92,8 +92,8 @@ auto PythonClassContextCall::tp_new(PyTypeObject* type, PyObject* args, } auto PythonClassContextCall::tp_call(PythonClassContextCall* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", diff --git a/src/ballistica/base/python/class/python_class_context_call.h b/src/ballistica/base/python/class/python_class_context_call.h index 8d0c3020..349cc289 100644 --- a/src/ballistica/base/python/class/python_class_context_call.h +++ b/src/ballistica/base/python/class/python_class_context_call.h @@ -23,8 +23,8 @@ class PythonClassContextCall : public PythonClass { static auto tp_call(PythonClassContextCall* self, PyObject* args, PyObject* keywds) -> PyObject*; static auto tp_repr(PythonClassContextCall* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassContextCall* self); Object::Ref* context_call_{}; }; diff --git a/src/ballistica/base/python/class/python_class_context_ref.cc b/src/ballistica/base/python/class/python_class_context_ref.cc index e32fb729..90fef920 100644 --- a/src/ballistica/base/python/class/python_class_context_ref.cc +++ b/src/ballistica/base/python/class/python_class_context_ref.cc @@ -151,8 +151,8 @@ auto PythonClassContextRef::Enter(PythonClassContextRef* self) -> PyObject* { BA_PYTHON_CATCH; } -auto PythonClassContextRef::Exit(PythonClassContextRef* self, PyObject* args) - -> PyObject* { +auto PythonClassContextRef::Exit(PythonClassContextRef* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; g_base->SetCurrentContext(*self->context_ref_prev_); Py_RETURN_NONE; diff --git a/src/ballistica/base/python/class/python_class_context_ref.h b/src/ballistica/base/python/class/python_class_context_ref.h index b325dfca..9c3c5edd 100644 --- a/src/ballistica/base/python/class/python_class_context_ref.h +++ b/src/ballistica/base/python/class/python_class_context_ref.h @@ -22,10 +22,10 @@ class PythonClassContextRef : public PythonClass { private: static PyMethodDef tp_methods[]; static auto tp_repr(PythonClassContextRef* self) -> PyObject*; - static auto tp_richcompare(PythonClassContextRef* c1, PyObject* c2, int op) - -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_richcompare(PythonClassContextRef* c1, PyObject* c2, + int op) -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassContextRef* self); static auto Enter(PythonClassContextRef* self) -> PyObject*; static auto Exit(PythonClassContextRef* self, PyObject* args) -> PyObject*; diff --git a/src/ballistica/base/python/class/python_class_display_timer.h b/src/ballistica/base/python/class/python_class_display_timer.h index 61c25888..35b10d3b 100644 --- a/src/ballistica/base/python/class/python_class_display_timer.h +++ b/src/ballistica/base/python/class/python_class_display_timer.h @@ -18,8 +18,8 @@ class PythonClassDisplayTimer : public PythonClass { static PyTypeObject type_obj; private: - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassDisplayTimer* self); int timer_id_; bool have_timer_; diff --git a/src/ballistica/base/python/class/python_class_env.cc b/src/ballistica/base/python/class/python_class_env.cc index 08ac7bef..3079e93c 100644 --- a/src/ballistica/base/python/class/python_class_env.cc +++ b/src/ballistica/base/python/class/python_class_env.cc @@ -214,8 +214,8 @@ void PythonClassEnv::tp_dealloc(PythonClassEnv* self) { Py_TYPE(self)->tp_free(reinterpret_cast(self)); } -auto PythonClassEnv::tp_getattro(PythonClassEnv* self, PyObject* attr) - -> PyObject* { +auto PythonClassEnv::tp_getattro(PythonClassEnv* self, + PyObject* attr) -> PyObject* { BA_PYTHON_TRY; // Do we need to support other attr types? diff --git a/src/ballistica/base/python/class/python_class_env.h b/src/ballistica/base/python/class/python_class_env.h index dcca64c5..dd28f68b 100644 --- a/src/ballistica/base/python/class/python_class_env.h +++ b/src/ballistica/base/python/class/python_class_env.h @@ -34,8 +34,8 @@ class PythonClassEnv : public PythonClass { PythonClassEnv(); ~PythonClassEnv(); static PyMethodDef tp_methods[]; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassEnv* self); static auto Dir(PythonClassEnv* self) -> PyObject*; }; diff --git a/src/ballistica/base/python/class/python_class_feature_set_data.h b/src/ballistica/base/python/class/python_class_feature_set_data.h index f9283d4d..5df100e4 100644 --- a/src/ballistica/base/python/class/python_class_feature_set_data.h +++ b/src/ballistica/base/python/class/python_class_feature_set_data.h @@ -40,8 +40,8 @@ class PythonClassFeatureSetData : public PythonClass { private: static PyMethodDef tp_methods[]; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassFeatureSetData* self); FeatureSetNativeComponent* feature_set_{}; static auto Play(PythonClassFeatureSetData* self, PyObject* args, diff --git a/src/ballistica/base/python/class/python_class_simple_sound.h b/src/ballistica/base/python/class/python_class_simple_sound.h index 6f4e3e69..a0cd3244 100644 --- a/src/ballistica/base/python/class/python_class_simple_sound.h +++ b/src/ballistica/base/python/class/python_class_simple_sound.h @@ -42,8 +42,8 @@ class PythonClassSimpleSound : public PythonClass { private: static PyMethodDef tp_methods[]; static auto tp_repr(PythonClassSimpleSound* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassSimpleSound* self); Object::Ref* sound_; static auto Play(PythonClassSimpleSound* self, PyObject* args, diff --git a/src/ballistica/base/python/class/python_class_vec3.cc b/src/ballistica/base/python/class/python_class_vec3.cc index cbf96e4d..31602fc2 100644 --- a/src/ballistica/base/python/class/python_class_vec3.cc +++ b/src/ballistica/base/python/class/python_class_vec3.cc @@ -138,8 +138,8 @@ auto PythonClassVec3::sq_length(PythonClassVec3* self) -> Py_ssize_t { return kMemberCount; } -auto PythonClassVec3::sq_item(PythonClassVec3* self, Py_ssize_t i) - -> PyObject* { +auto PythonClassVec3::sq_item(PythonClassVec3* self, + Py_ssize_t i) -> PyObject* { if (i < 0 || i >= kMemberCount) { PyErr_SetString(PyExc_IndexError, "Vec3 index out of range"); return nullptr; @@ -159,8 +159,8 @@ auto PythonClassVec3::sq_ass_item(PythonClassVec3* self, Py_ssize_t i, BA_PYTHON_INT_CATCH; } -auto PythonClassVec3::nb_add(PythonClassVec3* l, PythonClassVec3* r) - -> PyObject* { +auto PythonClassVec3::nb_add(PythonClassVec3* l, + PythonClassVec3* r) -> PyObject* { BA_PYTHON_TRY; // We can add if both sides are Vec3. @@ -175,8 +175,8 @@ auto PythonClassVec3::nb_add(PythonClassVec3* l, PythonClassVec3* r) BA_PYTHON_CATCH; } -auto PythonClassVec3::nb_subtract(PythonClassVec3* l, PythonClassVec3* r) - -> PyObject* { +auto PythonClassVec3::nb_subtract(PythonClassVec3* l, + PythonClassVec3* r) -> PyObject* { BA_PYTHON_TRY; // We can subtract if both sides are Vec3. @@ -240,8 +240,8 @@ auto PythonClassVec3::nb_multiply(PyObject* l, PyObject* r) -> PyObject* { BA_PYTHON_CATCH; } -auto PythonClassVec3::tp_richcompare(PythonClassVec3* c1, PyObject* c2, int op) - -> PyObject* { +auto PythonClassVec3::tp_richcompare(PythonClassVec3* c1, PyObject* c2, + int op) -> PyObject* { // Always return false against other types. if (!Check(c2)) { Py_RETURN_FALSE; @@ -283,8 +283,8 @@ auto PythonClassVec3::Dot(PythonClassVec3* self, PyObject* other) -> PyObject* { BA_PYTHON_CATCH; } -auto PythonClassVec3::Cross(PythonClassVec3* self, PyObject* other) - -> PyObject* { +auto PythonClassVec3::Cross(PythonClassVec3* self, + PyObject* other) -> PyObject* { BA_PYTHON_TRY; return Create(Vector3f::Cross(self->value, BasePython::GetPyVector3f(other))); BA_PYTHON_CATCH; @@ -309,8 +309,8 @@ PyMethodDef PythonClassVec3::tp_methods[] = { "Returns the cross product of this vector and another."}, {nullptr}}; -auto PythonClassVec3::tp_getattro(PythonClassVec3* self, PyObject* attr) - -> PyObject* { +auto PythonClassVec3::tp_getattro(PythonClassVec3* self, + PyObject* attr) -> PyObject* { BA_PYTHON_TRY; assert(PyUnicode_Check(attr)); diff --git a/src/ballistica/base/python/class/python_class_vec3.h b/src/ballistica/base/python/class/python_class_vec3.h index 1855a4cd..3290b420 100644 --- a/src/ballistica/base/python/class/python_class_vec3.h +++ b/src/ballistica/base/python/class/python_class_vec3.h @@ -30,19 +30,19 @@ class PythonClassVec3 : public PythonClass { static auto tp_repr(PythonClassVec3* self) -> PyObject*; static auto sq_length(PythonClassVec3* self) -> Py_ssize_t; static auto sq_item(PythonClassVec3* self, Py_ssize_t i) -> PyObject*; - static auto sq_ass_item(PythonClassVec3* self, Py_ssize_t i, PyObject* val) - -> int; + static auto sq_ass_item(PythonClassVec3* self, Py_ssize_t i, + PyObject* val) -> int; static auto nb_add(PythonClassVec3* l, PythonClassVec3* r) -> PyObject*; static auto nb_subtract(PythonClassVec3* l, PythonClassVec3* r) -> PyObject*; static auto nb_multiply(PyObject* l, PyObject* r) -> PyObject*; static auto nb_negative(PythonClassVec3* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static auto tp_getattro(PythonClassVec3* self, PyObject* attr) -> PyObject*; - static auto tp_richcompare(PythonClassVec3* c1, PyObject* c2, int op) - -> PyObject*; - static auto tp_setattro(PythonClassVec3* self, PyObject* attr, PyObject* val) - -> int; + static auto tp_richcompare(PythonClassVec3* c1, PyObject* c2, + int op) -> PyObject*; + static auto tp_setattro(PythonClassVec3* self, PyObject* attr, + PyObject* val) -> int; }; } // namespace ballistica::base diff --git a/src/ballistica/base/python/methods/python_methods_app.cc b/src/ballistica/base/python/methods/python_methods_app.cc index a440f0af..12ddfd05 100644 --- a/src/ballistica/base/python/methods/python_methods_app.cc +++ b/src/ballistica/base/python/methods/python_methods_app.cc @@ -184,8 +184,8 @@ static PyMethodDef PyCanDisplayFullUnicodeDef = { // -------------------------- app_instance_uuid -------------------------------- -static auto PyAppInstanceUUID(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyAppInstanceUUID(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -208,8 +208,8 @@ static PyMethodDef PyAppInstanceUUIDDef = { // --------------------------- user_ran_commands ------------------------------- -static auto PyUserRanCommands(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyUserRanCommands(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -233,8 +233,8 @@ static PyMethodDef PyUserRanCommandsDef = { // -------------------------------- pushcall ---------------------------------- -static auto PyPushCall(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyPushCall(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* call_obj; int from_other_thread{}; @@ -337,8 +337,8 @@ static PyMethodDef PyPushCallDef = { // ------------------------------ apptime -------------------------------------- -static auto PyAppTime(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyAppTime(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -373,8 +373,8 @@ static PyMethodDef PyAppTimeDef = { // ------------------------------ apptimer ------------------------------------- -static auto PyAppTimer(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyAppTimer(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); double length; @@ -431,8 +431,8 @@ static PyMethodDef PyAppTimerDef = { // --------------------------- displaytime ------------------------------------- -static auto PyDisplayTime(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyDisplayTime(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -466,8 +466,8 @@ static PyMethodDef PyDisplayTimeDef = { // ---------------------------- displaytimer ----------------------------------- -static auto PyDisplayTimer(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyDisplayTimer(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); double length; @@ -529,8 +529,8 @@ static PyMethodDef PyDisplayTimerDef = { // ----------------------------------- quit ------------------------------------ -static auto PyQuit(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyQuit(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->IsAppStarted()); @@ -594,8 +594,8 @@ static PyMethodDef PyDoApplyAppConfigDef = { // ----------------------------- commit_config --------------------------------- -static auto PyCommitConfig(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyCommitConfig(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* config_obj; static const char* kwlist[] = {"config", nullptr}; @@ -810,8 +810,8 @@ static PyMethodDef PyEnvDef = { // -------------------------------- emit_log ----------------------------------- -static auto PyEmitLog(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyEmitLog(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {"name", "level", "message", nullptr}; const char* name; @@ -862,8 +862,8 @@ static PyMethodDef PyEmitLogDef = { // ------------------------------ lifecyclelog --------------------------------- -static auto PyLifecycleLog(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyLifecycleLog(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {"message", nullptr}; const char* message; @@ -890,8 +890,8 @@ static PyMethodDef PyLifecycleLogDef = { // ----------------------------- v1_cloud_log ---------------------------------- -static auto PyV1CloudLog(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyV1CloudLog(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* message; static const char* kwlist[] = {"message", nullptr}; @@ -919,8 +919,8 @@ static PyMethodDef PyV1CloudLogDef = { // --------------------------- music_player_stop ------------------------------- -static auto PyMusicPlayerStop(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyMusicPlayerStop(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -945,8 +945,8 @@ static PyMethodDef PyMusicPlayerStopDef = { // ---------------------------- music_player_play ------------------------------ -static auto PyMusicPlayerPlay(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyMusicPlayerPlay(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* files_obj; static const char* kwlist[] = {"files", nullptr}; @@ -1051,8 +1051,8 @@ static PyMethodDef PyReloadMediaDef = { // --------------------------- mac_music_app_init ------------------------------ -static auto PyMacMusicAppInit(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyMacMusicAppInit(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; g_core->platform->MacMusicAppInit(); Py_RETURN_NONE; @@ -1115,8 +1115,8 @@ static PyMethodDef PyMacMusicAppSetVolumeDef = { // --------------------------- mac_music_app_stop ------------------------------ -static auto PyMacMusicAppStop(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyMacMusicAppStop(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; g_core->platform->MacMusicAppStop(); Py_RETURN_NONE; @@ -1193,8 +1193,8 @@ static PyMethodDef PyMacMusicAppGetPlaylistsDef = { // -------------------------- is_os_playing_music ------------------------------ -static auto PyIsOSPlayingMusic(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyIsOSPlayingMusic(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; if (g_core->platform->IsOSPlayingMusic()) { Py_RETURN_TRUE; diff --git a/src/ballistica/base/python/methods/python_methods_graphics.cc b/src/ballistica/base/python/methods/python_methods_graphics.cc index 46215776..68b4b102 100644 --- a/src/ballistica/base/python/methods/python_methods_graphics.cc +++ b/src/ballistica/base/python/methods/python_methods_graphics.cc @@ -26,8 +26,8 @@ namespace ballistica::base { // ---------------------------- screenmessage ---------------------------------- -static auto PyScreenMessage(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyScreenMessage(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* color_obj = Py_None; PyObject* message_obj; @@ -130,8 +130,8 @@ static PyMethodDef PyGetCameraPositionDef = { // --------------------------- get_camera_target ------------------------------- -static auto PyGetCameraTarget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetCameraTarget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; float x = 0.0f; float y = 0.0f; @@ -191,8 +191,8 @@ static PyMethodDef PySetCameraPositionDef = { // ---------------------------- set_camera_target ------------------------------ -static auto PySetCameraTarget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PySetCameraTarget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; float x = 0.0f; float y = 0.0f; @@ -224,8 +224,8 @@ static PyMethodDef PySetCameraTargetDef = { // ---------------------------- set_camera_manual ------------------------------ -static auto PySetCameraManual(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PySetCameraManual(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; bool value = false; static const char* kwlist[] = {"value", nullptr}; @@ -255,8 +255,8 @@ static PyMethodDef PySetCameraManualDef = { // -------------------------------- charstr ------------------------------------ -static auto PyCharStr(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyCharStr(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* name_obj; static const char* kwlist[] = {"name", nullptr}; @@ -291,8 +291,8 @@ static PyMethodDef PyCharStrDef = { // ------------------------------- safecolor ----------------------------------- -static auto PySafeColor(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PySafeColor(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* color_obj; float red, green, blue; @@ -368,8 +368,8 @@ static PyMethodDef PyGetMaxGraphicsQualityDef = { // ------------------------------ evaluate_lstr -------------------------------- -static auto PyEvaluateLstr(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyEvaluateLstr(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* value; static const char* kwlist[] = {"value", nullptr}; @@ -394,8 +394,8 @@ static PyMethodDef PyEvaluateLstrDef = { // --------------------------- get_string_height ------------------------------- -static auto PyGetStringHeight(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetStringHeight(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; std::string s; int suppress_warning = 0; @@ -440,8 +440,8 @@ static PyMethodDef PyGetStringHeightDef = { // ---------------------------- get_string_width ------------------------------- -static auto PyGetStringWidth(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetStringWidth(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; std::string s; PyObject* s_obj; @@ -487,8 +487,8 @@ static PyMethodDef PyGetStringWidthDef = { // ------------------------------ have_chars ----------------------------------- -static auto PyHaveChars(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyHaveChars(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; std::string text; PyObject* text_obj; @@ -518,8 +518,8 @@ static PyMethodDef PyHaveCharsDef = { // ----------------------------- fade_screen ----------------------------------- -static auto PyFadeScreen(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyFadeScreen(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; int fade{}; @@ -765,8 +765,8 @@ static PyMethodDef PySupportsMaxFPSDef = { // --------------------------- show_progress_bar ------------------------------- -static auto PyShowProgressBar(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyShowProgressBar(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; g_base->graphics->EnableProgressBar(false); diff --git a/src/ballistica/base/python/methods/python_methods_misc.cc b/src/ballistica/base/python/methods/python_methods_misc.cc index c1ba7116..798db3de 100644 --- a/src/ballistica/base/python/methods/python_methods_misc.cc +++ b/src/ballistica/base/python/methods/python_methods_misc.cc @@ -26,8 +26,8 @@ namespace ballistica::base { // ---------------------------- getsimplesound -------------------------------- -static auto PyGetSimpleSound(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetSimpleSound(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; @@ -57,8 +57,8 @@ static PyMethodDef PyGetSimpleSoundDef = { // -------------------------- set_ui_input_device ------------------------------ -static auto PySetUIInputDevice(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PySetUIInputDevice(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); static const char* kwlist[] = {"input_device_id", nullptr}; @@ -97,8 +97,8 @@ static PyMethodDef PySetUIInputDeviceDef = { // ----------------------------- hastouchscreen -------------------------------- -static auto PyHasTouchScreen(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyHasTouchScreen(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); static const char* kwlist[] = {nullptr}; @@ -180,8 +180,8 @@ static PyMethodDef PyClipboardHasTextDef = { // --------------------------- clipboard_set_text ------------------------------ -static auto PyClipboardSetText(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyClipboardSetText(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* value; static const char* kwlist[] = {"value", nullptr}; @@ -258,8 +258,8 @@ static PyMethodDef PySetUpSigIntDef = { // ---------------------------- have_permission -------------------------------- -static auto PyHavePermission(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyHavePermission(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); Permission permission; @@ -322,8 +322,8 @@ static PyMethodDef PyRequestPermissionDef = { // ----------------------------- in_logic_thread ------------------------------- -static auto PyInLogicThread(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyInLogicThread(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -351,8 +351,8 @@ static PyMethodDef PyInLogicThreadDef = { // ----------------------------- set_thread_name ------------------------------- -static auto PySetThreadName(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PySetThreadName(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; @@ -381,8 +381,8 @@ static PyMethodDef PySetThreadNameDef = { // ------------------------------ get_thread_name ------------------------------ -static auto PyGetThreadName(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetThreadName(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -411,8 +411,8 @@ static PyMethodDef PyGetThreadNameDef = { // returns an extra hash value that can be incorporated into security checks; // this contains things like whether console commands have been run, etc. -auto PyExtraHashValue(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +auto PyExtraHashValue(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -546,8 +546,8 @@ static PyMethodDef PyDebugPrintPyErrDef = { // ----------------------------- print_context --------------------------------- -static auto PyPrintContext(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyPrintContext(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -573,8 +573,8 @@ static PyMethodDef PyPrintContextDef = { // --------------------------- print_load_info --------------------------------- -static auto PyPrintLoadInfo(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyPrintLoadInfo(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; g_base->assets->PrintLoadInfo(); Py_RETURN_NONE; @@ -595,8 +595,8 @@ static PyMethodDef PyPrintLoadInfoDef = { // -------------------------- get_replays_dir ---------------------------------- -static auto PyGetReplaysDir(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetReplaysDir(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -839,8 +839,8 @@ static PyMethodDef PyGetLogFilePathDef = { // --------------------- get_volatile_data_directory --------------------------- -static auto PyGetVolatileDataDirectory(PyObject* self, PyObject* args) - -> PyObject* { +static auto PyGetVolatileDataDirectory(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; return PyUnicode_FromString( g_core->platform->GetVolatileDataDirectory().c_str()); @@ -883,8 +883,8 @@ static PyMethodDef PyIsLogFullDef = { // -------------------------- get_v1_cloud_log --------------------------------- -static auto PyGetV1CloudLog(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetV1CloudLog(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; std::string log_fin; { @@ -910,8 +910,8 @@ static PyMethodDef PyGetV1CloudLogDef = { // ---------------------------- mark_log_sent ---------------------------------- -static auto PyMarkLogSent(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyMarkLogSent(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; // This way we won't try to send it at shutdown time and whatnot g_core->did_put_v1_cloud_log = true; @@ -931,8 +931,8 @@ static PyMethodDef PyMarkLogSentDef = { // --------------------- increment_analytics_count ----------------------------- -auto PyIncrementAnalyticsCount(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +auto PyIncrementAnalyticsCount(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; int increment = 1; @@ -1123,8 +1123,8 @@ static PyMethodDef PyLoginAdapterBackEndActiveChangeDef = { // ---------------------- set_internal_language_keys --------------------------- -static auto PySetInternalLanguageKeys(PyObject* self, PyObject* args) - -> PyObject* { +static auto PySetInternalLanguageKeys(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; PyObject* list_obj; PyObject* random_names_list_obj; @@ -1221,8 +1221,8 @@ static PyMethodDef PyAndroidGetExternalFilesDirDef = { // ------------------------------- do_once ------------------------------------- -static auto PyDoOnce(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyDoOnce(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; if (g_base->python->DoOnce()) { Py_RETURN_TRUE; @@ -1256,8 +1256,8 @@ static PyMethodDef PyDoOnceDef = { // ------------------------------- getapp -------------------------------------- -static auto PyGetApp(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetApp(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "", @@ -1412,8 +1412,8 @@ static PyMethodDef PyOpenDirExternallyDef = { // ----------------------------- fatal_error ----------------------------------- -static auto PyFatalError(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyFatalError(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* message; static const char* kwlist[] = {"message", nullptr}; @@ -1534,8 +1534,8 @@ static PyMethodDef PyDevConsoleAddTextDef = { // -------------------- dev_console_add_python_terminal ------------------------ -static auto PyDevConsoleAddPythonTerminal(PyObject* self, PyObject* args) - -> PyObject* { +static auto PyDevConsoleAddPythonTerminal(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); auto* dev_console = g_base->ui->dev_console(); diff --git a/src/ballistica/base/support/classic_soft.h b/src/ballistica/base/support/classic_soft.h index 5e388e93..445205b9 100644 --- a/src/ballistica/base/support/classic_soft.h +++ b/src/ballistica/base/support/classic_soft.h @@ -18,9 +18,8 @@ class ClassicSoftInterface { public: virtual auto GetControllerValue(base::InputDevice* device, const std::string& value_name) -> int = 0; - virtual auto GetControllerFloatValue(base::InputDevice* device, - const std::string& value_name) - -> float = 0; + virtual auto GetControllerFloatValue( + base::InputDevice* device, const std::string& value_name) -> float = 0; virtual auto IsV1AccountSignedIn() -> bool = 0; virtual auto HandleSignOutV1() -> bool = 0; virtual void V2SetV1AccountState(const char* statestr, const char* loginid, diff --git a/src/ballistica/base/ui/ui.cc b/src/ballistica/base/ui/ui.cc index cd664879..0b4f6fff 100644 --- a/src/ballistica/base/ui/ui.cc +++ b/src/ballistica/base/ui/ui.cc @@ -209,8 +209,8 @@ auto UI::PartyWindowOpen() -> bool { return false; } -auto UI::HandleMouseDown(int button, float x, float y, bool double_click) - -> bool { +auto UI::HandleMouseDown(int button, float x, float y, + bool double_click) -> bool { assert(g_base->InLogicThread()); bool handled{}; diff --git a/src/ballistica/classic/classic.cc b/src/ballistica/classic/classic.cc index 56a42e41..f78d6acd 100644 --- a/src/ballistica/classic/classic.cc +++ b/src/ballistica/classic/classic.cc @@ -70,15 +70,13 @@ auto ClassicFeatureSet::Import() -> ClassicFeatureSet* { return ImportThroughPythonModule("_baclassic"); } -auto ClassicFeatureSet::GetControllerValue(base::InputDevice* device, - const std::string& value_name) - -> int { +auto ClassicFeatureSet::GetControllerValue( + base::InputDevice* device, const std::string& value_name) -> int { return python->GetControllerValue(device, value_name); } -auto ClassicFeatureSet::GetControllerFloatValue(base::InputDevice* device, - const std::string& value_name) - -> float { +auto ClassicFeatureSet::GetControllerFloatValue( + base::InputDevice* device, const std::string& value_name) -> float { return python->GetControllerFloatValue(device, value_name); } diff --git a/src/ballistica/classic/python/classic_python.cc b/src/ballistica/classic/python/classic_python.cc index 4c3a7f9e..d3c6aa9e 100644 --- a/src/ballistica/classic/python/classic_python.cc +++ b/src/ballistica/classic/python/classic_python.cc @@ -66,9 +66,8 @@ auto ClassicPython::GetControllerValue(base::InputDevice* device, return static_cast(PyLong_AsLong(ret_val.Get())); } -auto ClassicPython::GetControllerFloatValue(base::InputDevice* device, - const std::string& value_name) - -> float { +auto ClassicPython::GetControllerFloatValue( + base::InputDevice* device, const std::string& value_name) -> float { assert(device); assert(objs().Exists(ObjID::kGetInputDeviceMappedValueCall)); diff --git a/src/ballistica/classic/python/methods/python_methods_classic.cc b/src/ballistica/classic/python/methods/python_methods_classic.cc index 5ebda885..482d2565 100644 --- a/src/ballistica/classic/python/methods/python_methods_classic.cc +++ b/src/ballistica/classic/python/methods/python_methods_classic.cc @@ -21,8 +21,8 @@ namespace ballistica::classic { // -------------------------------- value_test --------------------------------- -static auto PyValueTest(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyValueTest(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* arg; double change = 0.0f; diff --git a/src/ballistica/core/platform/apple/core_platform_apple.h b/src/ballistica/core/platform/apple/core_platform_apple.h index 982fb8f9..1d3851a7 100644 --- a/src/ballistica/core/platform/apple/core_platform_apple.h +++ b/src/ballistica/core/platform/apple/core_platform_apple.h @@ -33,14 +33,14 @@ class CorePlatformApple : public CorePlatform { auto CreateTextTexture(int width, int height, const std::vector& strings, const std::vector& positions, - const std::vector& widths, float scale) - -> void* override; + const std::vector& widths, + float scale) -> void* override; auto GetTextTextureData(void* tex) -> uint8_t* override; void SubmitScore(const std::string& game, const std::string& version, int64_t score) override; void ReportAchievement(const std::string& achievement) override; - auto HaveLeaderboard(const std::string& game, const std::string& config) - -> bool override; + auto HaveLeaderboard(const std::string& game, + const std::string& config) -> bool override; void ShowGameServiceUI(const std::string& show, const std::string& game, const std::string& game_version) override; void ResetAchievements() override; diff --git a/src/ballistica/core/platform/core_platform.cc b/src/ballistica/core/platform/core_platform.cc index 0d8bbbdb..a30e03f2 100644 --- a/src/ballistica/core/platform/core_platform.cc +++ b/src/ballistica/core/platform/core_platform.cc @@ -219,8 +219,8 @@ auto CorePlatform::GetConfigFilePath() -> std::string { } // FIXME: should make this unnecessary. -auto CorePlatform::GetLowLevelConfigValue(const char* key, int default_value) - -> int { +auto CorePlatform::GetLowLevelConfigValue(const char* key, + int default_value) -> int { std::string path = g_core->GetConfigDirectory() + BA_DIRSLASH + ".cvar_" + key; int val = default_value; @@ -512,16 +512,14 @@ void CorePlatform::EmitPlatformLog(const std::string& name, LogLevel level, // Do nothing by default. } -auto CorePlatform::ReportFatalError(const std::string& message, - bool in_top_level_exception_handler) - -> bool { +auto CorePlatform::ReportFatalError( + const std::string& message, bool in_top_level_exception_handler) -> bool { // Don't override handling by default. return false; } -auto CorePlatform::HandleFatalError(bool exit_cleanly, - bool in_top_level_exception_handler) - -> bool { +auto CorePlatform::HandleFatalError( + bool exit_cleanly, bool in_top_level_exception_handler) -> bool { // Don't override handling by default. return false; } @@ -853,8 +851,8 @@ void CorePlatform::Unlink(const char* path) { #endif } -auto CorePlatform::AbsPath(const std::string& path, std::string* outpath) - -> bool { +auto CorePlatform::AbsPath(const std::string& path, + std::string* outpath) -> bool { // Ensure all implementations fail if the file does not exist. if (!FilePathExists(path)) { return false; @@ -862,8 +860,8 @@ auto CorePlatform::AbsPath(const std::string& path, std::string* outpath) return DoAbsPath(path, outpath); } -auto CorePlatform::DoAbsPath(const std::string& path, std::string* outpath) - -> bool { +auto CorePlatform::DoAbsPath(const std::string& path, + std::string* outpath) -> bool { // This covers all but windows. #if BA_OSTYPE_WINDOWS throw Exception(); diff --git a/src/ballistica/core/platform/core_platform.h b/src/ballistica/core/platform/core_platform.h index cd84f478..a547faa7 100644 --- a/src/ballistica/core/platform/core_platform.h +++ b/src/ballistica/core/platform/core_platform.h @@ -229,8 +229,8 @@ class CorePlatform { virtual auto CreateTextTexture(int width, int height, const std::vector& strings, const std::vector& positions, - const std::vector& widths, float scale) - -> void*; + const std::vector& widths, + float scale) -> void*; virtual auto GetTextTextureData(void* tex) -> uint8_t*; #pragma mark ACCOUNTS ---------------------------------------------------------- diff --git a/src/ballistica/core/platform/support/min_sdl.h b/src/ballistica/core/platform/support/min_sdl.h index e20e4010..22b95b0d 100644 --- a/src/ballistica/core/platform/support/min_sdl.h +++ b/src/ballistica/core/platform/support/min_sdl.h @@ -748,7 +748,7 @@ typedef struct SDL_MouseButtonEvent { int y; } SDL_MouseButtonEvent; -#define SDL_BUTTON(X) (1 << ((X)-1)) +#define SDL_BUTTON(X) (1 << ((X) - 1)) #define SDL_BUTTON_LEFT 1 #define SDL_BUTTON_MIDDLE 2 #define SDL_BUTTON_RIGHT 3 diff --git a/src/ballistica/core/platform/windows/core_platform_windows.cc b/src/ballistica/core/platform/windows/core_platform_windows.cc index 7bf234c7..b30eddd6 100644 --- a/src/ballistica/core/platform/windows/core_platform_windows.cc +++ b/src/ballistica/core/platform/windows/core_platform_windows.cc @@ -342,13 +342,13 @@ auto CorePlatformWindows::Remove(const char* path) -> int { return _wremove(UTF8Decode(path).c_str()); } -auto CorePlatformWindows::Stat(const char* path, struct BA_STAT* buffer) - -> int { +auto CorePlatformWindows::Stat(const char* path, + struct BA_STAT* buffer) -> int { return _wstat(UTF8Decode(path).c_str(), buffer); } -auto CorePlatformWindows::Rename(const char* oldname, const char* newname) - -> int { +auto CorePlatformWindows::Rename(const char* oldname, + const char* newname) -> int { // Unlike other platforms, windows will error if the target file already // exists instead of simply overwriting it. So let's attempt to blow away // anything there first. diff --git a/src/ballistica/core/platform/windows/core_platform_windows.h b/src/ballistica/core/platform/windows/core_platform_windows.h index 4943e85e..27820814 100644 --- a/src/ballistica/core/platform/windows/core_platform_windows.h +++ b/src/ballistica/core/platform/windows/core_platform_windows.h @@ -31,8 +31,8 @@ class CorePlatformWindows : public CorePlatform { auto Remove(const char* path) -> int; auto Stat(const char* path, struct BA_STAT* buffer) -> int; auto Rename(const char* oldname, const char* newname) -> int; - auto DoAbsPath(const std::string& path, std::string* outpath) - -> bool override; + auto DoAbsPath(const std::string& path, + std::string* outpath) -> bool override; auto FOpen(const char* path, const char* mode) -> FILE* override; auto GetErrnoString() -> std::string override; auto GetSocketErrorString() -> std::string override; diff --git a/src/ballistica/scene_v1/connection/connection_set.cc b/src/ballistica/scene_v1/connection/connection_set.cc index e83c66b2..c487e323 100644 --- a/src/ballistica/scene_v1/connection/connection_set.cc +++ b/src/ballistica/scene_v1/connection/connection_set.cc @@ -700,8 +700,8 @@ void ConnectionSet::HandleIncomingUDPPacket(const std::vector& data_in, } } -auto ConnectionSet::VerifyClientAddr(uint8_t client_id, const SockAddr& addr) - -> bool { +auto ConnectionSet::VerifyClientAddr(uint8_t client_id, + const SockAddr& addr) -> bool { auto connection_to_client = connections_to_clients_.find(client_id); if (connection_to_client != connections_to_clients_.end()) { diff --git a/src/ballistica/scene_v1/connection/connection_to_host.cc b/src/ballistica/scene_v1/connection/connection_to_host.cc index e1093e14..9f9e1339 100644 --- a/src/ballistica/scene_v1/connection/connection_to_host.cc +++ b/src/ballistica/scene_v1/connection/connection_to_host.cc @@ -24,7 +24,7 @@ const int kPingSendInterval = 2000; ConnectionToHost::ConnectionToHost() : protocol_version_{ - SceneV1AppMode::GetSingleton()->host_protocol_version()} {} + SceneV1AppMode::GetSingleton()->host_protocol_version()} {} auto ConnectionToHost::GetAsUDP() -> ConnectionToHostUDP* { return nullptr; } diff --git a/src/ballistica/scene_v1/dynamics/dynamics.cc b/src/ballistica/scene_v1/dynamics/dynamics.cc index ba6e5564..e46543e1 100644 --- a/src/ballistica/scene_v1/dynamics/dynamics.cc +++ b/src/ballistica/scene_v1/dynamics/dynamics.cc @@ -25,8 +25,8 @@ namespace ballistica::scene_v1 { // Given two parts, returns true if part1 is major in // the storage order. -static auto IsInStoreOrder(int64_t node1, int part1, int64_t node2, int part2) - -> bool { +static auto IsInStoreOrder(int64_t node1, int part1, int64_t node2, + int part2) -> bool { assert(node1 >= 0 && part1 >= 0 && node2 >= 0 && part2 >= 0); // Node with smaller id is primary search node. diff --git a/src/ballistica/scene_v1/dynamics/material/material_component.cc b/src/ballistica/scene_v1/dynamics/material/material_component.cc index 55b9963d..80eaf88f 100644 --- a/src/ballistica/scene_v1/dynamics/material/material_component.cc +++ b/src/ballistica/scene_v1/dynamics/material/material_component.cc @@ -28,8 +28,8 @@ MaterialComponent::~MaterialComponent() {} auto MaterialComponent::eval_conditions( const Object::Ref& condition, const Material& c, - const Part* part, const Part* opposing_part, const MaterialContext& s) - -> bool { + const Part* part, const Part* opposing_part, + const MaterialContext& s) -> bool { // If there's no condition, succeed. if (!condition.Exists()) { return true; diff --git a/src/ballistica/scene_v1/dynamics/material/material_component.h b/src/ballistica/scene_v1/dynamics/material/material_component.h index bbd06761..53e7cde4 100644 --- a/src/ballistica/scene_v1/dynamics/material/material_component.h +++ b/src/ballistica/scene_v1/dynamics/material/material_component.h @@ -29,8 +29,8 @@ class MaterialComponent : public Object { Object::Ref conditions; auto eval_conditions(const Object::Ref& condition, const Material& c, const Part* part, - const Part* opposing_part, const MaterialContext& s) - -> bool; + const Part* opposing_part, + const MaterialContext& s) -> bool; // Apply the component to a context. void Apply(MaterialContext* c, const Part* src_part, const Part* dst_part); diff --git a/src/ballistica/scene_v1/node/spaz_node.cc b/src/ballistica/scene_v1/node/spaz_node.cc index 8efa91ea..cfc36364 100644 --- a/src/ballistica/scene_v1/node/spaz_node.cc +++ b/src/ballistica/scene_v1/node/spaz_node.cc @@ -146,8 +146,8 @@ enum SpazBodyType { kHairPonyTailBottomBodyID }; -static auto AngleBetween2DVectors(dReal x1, dReal y1, dReal x2, dReal y2) - -> dReal { +static auto AngleBetween2DVectors(dReal x1, dReal y1, dReal x2, + dReal y2) -> dReal { dReal x1_norm, y1_norm, x2_norm, y2_norm; dReal len1, len2; len1 = sqrtf(x1 * x1 + y1 * y1); diff --git a/src/ballistica/scene_v1/node/spaz_node.h b/src/ballistica/scene_v1/node/spaz_node.h index 3440ef59..dd660902 100644 --- a/src/ballistica/scene_v1/node/spaz_node.h +++ b/src/ballistica/scene_v1/node/spaz_node.h @@ -271,8 +271,8 @@ class SpazNode : public Node { // points line up. auto CreateFixedJoint(RigidBody* b1, RigidBody* b2, float ls, float ld, float as, float ad, float a1x, float a1y, float a1z, - float a2x, float a2y, float a2z, bool reposition = true) - -> JointFixedEF*; + float a2x, float a2y, float a2z, + bool reposition = true) -> JointFixedEF*; void Throw(bool withBombButton); // Reset to a standing, non-moving state at the given point. @@ -285,8 +285,8 @@ class SpazNode : public Node { auto IsBrokenBodyPart(int id) -> bool; static auto StaticCollideCallback(dContact* c, int count, RigidBody* colliding_body, - RigidBody* opposingbody, void* data) - -> bool { + RigidBody* opposingbody, + void* data) -> bool { auto* a = static_cast(data); return a->CollideCallback(c, count, colliding_body, opposingbody); } diff --git a/src/ballistica/scene_v1/python/class/python_class_activity_data.h b/src/ballistica/scene_v1/python/class/python_class_activity_data.h index bb7a7122..f2d8323a 100644 --- a/src/ballistica/scene_v1/python/class/python_class_activity_data.h +++ b/src/ballistica/scene_v1/python/class/python_class_activity_data.h @@ -24,8 +24,8 @@ class PythonClassActivityData : public PythonClass { static PyMethodDef tp_methods[]; static PyNumberMethods as_number_; static auto tp_repr(PythonClassActivityData* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassActivityData* self); static auto nb_bool(PythonClassActivityData* self) -> int; diff --git a/src/ballistica/scene_v1/python/class/python_class_base_timer.h b/src/ballistica/scene_v1/python/class/python_class_base_timer.h index bcd1179e..c061226d 100644 --- a/src/ballistica/scene_v1/python/class/python_class_base_timer.h +++ b/src/ballistica/scene_v1/python/class/python_class_base_timer.h @@ -18,8 +18,8 @@ class PythonClassBaseTimer : public PythonClass { static PyTypeObject type_obj; private: - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassBaseTimer* self); int timer_id_; ContextRefSceneV1* context_ref_; diff --git a/src/ballistica/scene_v1/python/class/python_class_input_device.cc b/src/ballistica/scene_v1/python/class/python_class_input_device.cc index 4d54399b..b4115a04 100644 --- a/src/ballistica/scene_v1/python/class/python_class_input_device.cc +++ b/src/ballistica/scene_v1/python/class/python_class_input_device.cc @@ -344,8 +344,8 @@ auto PythonClassInputDevice::GetPlayerProfiles(PythonClassInputDevice* self) } auto PythonClassInputDevice::GetV1AccountName(PythonClassInputDevice* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; int full; static const char* kwlist[] = {"full", nullptr}; @@ -388,8 +388,8 @@ auto PythonClassInputDevice::Exists(PythonClassInputDevice* self) -> PyObject* { } auto PythonClassInputDevice::GetAxisName(PythonClassInputDevice* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); int id; @@ -409,8 +409,8 @@ auto PythonClassInputDevice::GetAxisName(PythonClassInputDevice* self, } auto PythonClassInputDevice::GetButtonName(PythonClassInputDevice* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); int id{}; diff --git a/src/ballistica/scene_v1/python/class/python_class_input_device.h b/src/ballistica/scene_v1/python/class/python_class_input_device.h index 987b2ece..ab1ab209 100644 --- a/src/ballistica/scene_v1/python/class/python_class_input_device.h +++ b/src/ballistica/scene_v1/python/class/python_class_input_device.h @@ -23,12 +23,12 @@ class PythonClassInputDevice : public PythonClass { private: static PyMethodDef tp_methods[]; static auto tp_repr(PythonClassInputDevice* self) -> PyObject*; - static auto tp_getattro(PythonClassInputDevice* self, PyObject* attr) - -> PyObject*; + static auto tp_getattro(PythonClassInputDevice* self, + PyObject* attr) -> PyObject*; static auto tp_setattro(PythonClassInputDevice* self, PyObject* attr, PyObject* val) -> int; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassInputDevice* self); static auto nb_bool(PythonClassInputDevice* self) -> int; static auto DetachFromPlayer(PythonClassInputDevice* self) -> PyObject*; diff --git a/src/ballistica/scene_v1/python/class/python_class_material.cc b/src/ballistica/scene_v1/python/class/python_class_material.cc index 3ea51b8d..02d7f08a 100644 --- a/src/ballistica/scene_v1/python/class/python_class_material.cc +++ b/src/ballistica/scene_v1/python/class/python_class_material.cc @@ -174,8 +174,8 @@ auto PythonClassMaterial::tp_repr(PythonClassMaterial* self) -> PyObject* { BA_PYTHON_CATCH; } -auto PythonClassMaterial::tp_getattro(PythonClassMaterial* self, PyObject* attr) - -> PyObject* { +auto PythonClassMaterial::tp_getattro(PythonClassMaterial* self, + PyObject* attr) -> PyObject* { BA_PYTHON_TRY; // Assuming this will always be a str? diff --git a/src/ballistica/scene_v1/python/class/python_class_material.h b/src/ballistica/scene_v1/python/class/python_class_material.h index fc452860..c61855ac 100644 --- a/src/ballistica/scene_v1/python/class/python_class_material.h +++ b/src/ballistica/scene_v1/python/class/python_class_material.h @@ -27,12 +27,12 @@ class PythonClassMaterial : public PythonClass { private: static bool s_create_empty_; static PyMethodDef tp_methods[]; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void Delete(Object::Ref* m); static void tp_dealloc(PythonClassMaterial* self); - static auto tp_getattro(PythonClassMaterial* self, PyObject* attr) - -> PyObject*; + static auto tp_getattro(PythonClassMaterial* self, + PyObject* attr) -> PyObject*; static auto tp_setattro(PythonClassMaterial* self, PyObject* attr, PyObject* val) -> int; static auto tp_repr(PythonClassMaterial* self) -> PyObject*; diff --git a/src/ballistica/scene_v1/python/class/python_class_node.cc b/src/ballistica/scene_v1/python/class/python_class_node.cc index fad31158..1636863f 100644 --- a/src/ballistica/scene_v1/python/class/python_class_node.cc +++ b/src/ballistica/scene_v1/python/class/python_class_node.cc @@ -141,8 +141,8 @@ auto PythonClassNode::tp_repr(PythonClassNode* self) -> PyObject* { BA_PYTHON_CATCH; } -auto PythonClassNode::tp_getattro(PythonClassNode* self, PyObject* attr) - -> PyObject* { +auto PythonClassNode::tp_getattro(PythonClassNode* self, + PyObject* attr) -> PyObject* { BA_PYTHON_TRY; // Do we need to support other attr types? @@ -259,8 +259,8 @@ auto PythonClassNode::Delete(PythonClassNode* self, PyObject* args, BA_PYTHON_CATCH; } -auto PythonClassNode::HandleMessage(PythonClassNode* self, PyObject* args) - -> PyObject* { +auto PythonClassNode::HandleMessage(PythonClassNode* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; Py_ssize_t tuple_size = PyTuple_GET_SIZE(args); if (tuple_size < 1) { @@ -294,8 +294,8 @@ auto PythonClassNode::HandleMessage(PythonClassNode* self, PyObject* args) BA_PYTHON_CATCH; } -auto PythonClassNode::AddDeathAction(PythonClassNode* self, PyObject* args) - -> PyObject* { +auto PythonClassNode::AddDeathAction(PythonClassNode* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; PyObject* call_obj; if (!PyArg_ParseTuple(args, "O", &call_obj)) { @@ -317,8 +317,8 @@ auto PythonClassNode::AddDeathAction(PythonClassNode* self, PyObject* args) BA_PYTHON_CATCH; } -auto PythonClassNode::ConnectAttr(PythonClassNode* self, PyObject* args) - -> PyObject* { +auto PythonClassNode::ConnectAttr(PythonClassNode* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; PyObject* dst_node_obj; Node* node = self->node_->Get(); diff --git a/src/ballistica/scene_v1/python/class/python_class_node.h b/src/ballistica/scene_v1/python/class/python_class_node.h index 0765b87e..c3c118ef 100644 --- a/src/ballistica/scene_v1/python/class/python_class_node.h +++ b/src/ballistica/scene_v1/python/class/python_class_node.h @@ -21,23 +21,23 @@ class PythonClassNode : public PythonClass { auto GetNode(bool doraise = true) const -> Node*; private: - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassNode* self); static auto tp_repr(PythonClassNode* self) -> PyObject*; static auto tp_getattro(PythonClassNode* self, PyObject* attr) -> PyObject*; - static auto tp_setattro(PythonClassNode* self, PyObject* attr, PyObject* val) - -> int; + static auto tp_setattro(PythonClassNode* self, PyObject* attr, + PyObject* val) -> int; static auto Exists(PythonClassNode* self) -> PyObject*; static auto GetNodeType(PythonClassNode* self) -> PyObject*; static auto GetName(PythonClassNode* self) -> PyObject*; static auto GetDelegate(PythonClassNode* self, PyObject* args, PyObject* keywds) -> PyObject*; - static auto Delete(PythonClassNode* self, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto Delete(PythonClassNode* self, PyObject* args, + PyObject* keywds) -> PyObject*; static auto HandleMessage(PythonClassNode* self, PyObject* args) -> PyObject*; - static auto AddDeathAction(PythonClassNode* self, PyObject* args) - -> PyObject*; + static auto AddDeathAction(PythonClassNode* self, + PyObject* args) -> PyObject*; static auto ConnectAttr(PythonClassNode* self, PyObject* args) -> PyObject*; static auto Dir(PythonClassNode* self) -> PyObject*; static auto nb_bool(PythonClassNode* self) -> int; diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_collision_mesh.h b/src/ballistica/scene_v1/python/class/python_class_scene_collision_mesh.h index c6ec83a8..89e0a9a6 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_collision_mesh.h +++ b/src/ballistica/scene_v1/python/class/python_class_scene_collision_mesh.h @@ -22,8 +22,8 @@ class PythonClassSceneCollisionMesh : public PythonClass { auto GetCollisionMesh(bool doraise = true) const -> SceneCollisionMesh*; private: - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* kwds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* kwds) -> PyObject*; static void tp_dealloc(PythonClassSceneCollisionMesh* self); static bool s_create_empty_; Object::Ref* collision_mesh_; diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_data_asset.h b/src/ballistica/scene_v1/python/class/python_class_scene_data_asset.h index 58df60e2..da164792 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_data_asset.h +++ b/src/ballistica/scene_v1/python/class/python_class_scene_data_asset.h @@ -24,8 +24,8 @@ class PythonClassSceneDataAsset : public PythonClass { private: static PyMethodDef tp_methods[]; static auto GetValue(PythonClassSceneDataAsset* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* kwds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* kwds) -> PyObject*; static void tp_dealloc(PythonClassSceneDataAsset* self); static bool s_create_empty_; Object::Ref* data_; diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_mesh.h b/src/ballistica/scene_v1/python/class/python_class_scene_mesh.h index b703b5d1..dc55f6b3 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_mesh.h +++ b/src/ballistica/scene_v1/python/class/python_class_scene_mesh.h @@ -23,8 +23,8 @@ class PythonClassSceneMesh : public PythonClass { private: static bool s_create_empty_; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* kwds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* kwds) -> PyObject*; static void tp_dealloc(PythonClassSceneMesh* self); Object::Ref* mesh_; }; diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_sound.h b/src/ballistica/scene_v1/python/class/python_class_scene_sound.h index 9be96fed..b71c2b77 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_sound.h +++ b/src/ballistica/scene_v1/python/class/python_class_scene_sound.h @@ -24,8 +24,8 @@ class PythonClassSceneSound : public PythonClass { private: static auto Play(PythonClassSceneSound* self, PyObject* args, PyObject* keywds) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* kwds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* kwds) -> PyObject*; static void tp_dealloc(PythonClassSceneSound* self); static PyMethodDef tp_methods[]; static bool s_create_empty_; diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_texture.h b/src/ballistica/scene_v1/python/class/python_class_scene_texture.h index 2f78a1da..e198e7cf 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_texture.h +++ b/src/ballistica/scene_v1/python/class/python_class_scene_texture.h @@ -23,8 +23,8 @@ class PythonClassSceneTexture : public PythonClass { private: static bool s_create_empty_; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassSceneTexture* self); Object::Ref* texture_; }; diff --git a/src/ballistica/scene_v1/python/class/python_class_scene_timer.h b/src/ballistica/scene_v1/python/class/python_class_scene_timer.h index 51005bae..d87a475a 100644 --- a/src/ballistica/scene_v1/python/class/python_class_scene_timer.h +++ b/src/ballistica/scene_v1/python/class/python_class_scene_timer.h @@ -18,8 +18,8 @@ class PythonClassSceneTimer : public PythonClass { static PyTypeObject type_obj; private: - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassSceneTimer* self); int timer_id_; ContextRefSceneV1* context_ref_; diff --git a/src/ballistica/scene_v1/python/class/python_class_session_data.h b/src/ballistica/scene_v1/python/class/python_class_session_data.h index a4de57bc..4a75654b 100644 --- a/src/ballistica/scene_v1/python/class/python_class_session_data.h +++ b/src/ballistica/scene_v1/python/class/python_class_session_data.h @@ -24,8 +24,8 @@ class PythonClassSessionData : public PythonClass { static PyMethodDef tp_methods[]; static PyNumberMethods as_number_; static auto tp_repr(PythonClassSessionData* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassSessionData* self); static auto Exists(PythonClassSessionData* self) -> PyObject*; diff --git a/src/ballistica/scene_v1/python/class/python_class_session_player.cc b/src/ballistica/scene_v1/python/class/python_class_session_player.cc index 5431aff9..833e4aab 100644 --- a/src/ballistica/scene_v1/python/class/python_class_session_player.cc +++ b/src/ballistica/scene_v1/python/class/python_class_session_player.cc @@ -324,8 +324,8 @@ auto PythonClassSessionPlayer::tp_getattro(PythonClassSessionPlayer* self, } auto PythonClassSessionPlayer::tp_setattro(PythonClassSessionPlayer* self, - PyObject* attr, PyObject* val) - -> int { + PyObject* attr, + PyObject* val) -> int { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); @@ -351,8 +351,8 @@ auto PythonClassSessionPlayer::tp_setattro(PythonClassSessionPlayer* self, } auto PythonClassSessionPlayer::GetName(PythonClassSessionPlayer* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); int full = false; @@ -383,8 +383,8 @@ auto PythonClassSessionPlayer::Exists(PythonClassSessionPlayer* self) } auto PythonClassSessionPlayer::SetName(PythonClassSessionPlayer* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); PyObject* name_obj; @@ -425,8 +425,8 @@ auto PythonClassSessionPlayer::ResetInput(PythonClassSessionPlayer* self) } auto PythonClassSessionPlayer::AssignInputCall(PythonClassSessionPlayer* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); PyObject* input_type_obj; @@ -518,8 +518,8 @@ auto PythonClassSessionPlayer::GetV1AccountID(PythonClassSessionPlayer* self) } auto PythonClassSessionPlayer::SetData(PythonClassSessionPlayer* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); PyObject* team_obj; @@ -564,8 +564,8 @@ auto PythonClassSessionPlayer::GetIconInfo(PythonClassSessionPlayer* self) } auto PythonClassSessionPlayer::SetIconInfo(PythonClassSessionPlayer* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); PyObject* texture_name_obj; @@ -599,8 +599,8 @@ auto PythonClassSessionPlayer::SetIconInfo(PythonClassSessionPlayer* self, } auto PythonClassSessionPlayer::SetActivity(PythonClassSessionPlayer* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); PyObject* activity_obj; @@ -625,8 +625,8 @@ auto PythonClassSessionPlayer::SetActivity(PythonClassSessionPlayer* self, } auto PythonClassSessionPlayer::SetNode(PythonClassSessionPlayer* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); PyObject* node_obj; diff --git a/src/ballistica/scene_v1/python/class/python_class_session_player.h b/src/ballistica/scene_v1/python/class/python_class_session_player.h index dbe92676..64475655 100644 --- a/src/ballistica/scene_v1/python/class/python_class_session_player.h +++ b/src/ballistica/scene_v1/python/class/python_class_session_player.h @@ -24,11 +24,11 @@ class PythonClassSessionPlayer : public PythonClass { static bool s_create_empty_; static PyMethodDef tp_methods[]; static auto tp_repr(PythonClassSessionPlayer* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassSessionPlayer* self); - static auto tp_getattro(PythonClassSessionPlayer* self, PyObject* attr) - -> PyObject*; + static auto tp_getattro(PythonClassSessionPlayer* self, + PyObject* attr) -> PyObject*; static auto tp_setattro(PythonClassSessionPlayer* self, PyObject* attr, PyObject* val) -> int; static auto GetName(PythonClassSessionPlayer* self, PyObject* args, diff --git a/src/ballistica/scene_v1/python/methods/python_methods_assets.cc b/src/ballistica/scene_v1/python/methods/python_methods_assets.cc index 58f63c19..a99bc200 100644 --- a/src/ballistica/scene_v1/python/methods/python_methods_assets.cc +++ b/src/ballistica/scene_v1/python/methods/python_methods_assets.cc @@ -22,8 +22,8 @@ namespace ballistica::scene_v1 { // ------------------------------- gettexture ---------------------------------- -static auto PyGetTexture(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetTexture(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; @@ -82,8 +82,8 @@ static PyMethodDef PyGetPackageTextureDef = { // ------------------------------- getsound ------------------------------------ -static auto PyGetSound(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetSound(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; @@ -113,8 +113,8 @@ static PyMethodDef PyGetSoundDef = { // --------------------------- get_package_sound ------------------------------- -static auto PyGetPackageSound(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetPackageSound(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; PyObject* package_obj; @@ -142,8 +142,8 @@ static PyMethodDef PyGetPackageSoundDef = { // ------------------------------- getdata ------------------------------------- -static auto PyGetData(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetData(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; @@ -173,8 +173,8 @@ static PyMethodDef PyGetDataDef = { // --------------------------- get_package_data -------------------------------- -static auto PyGetPackageData(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetPackageData(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; PyObject* package_obj; @@ -202,8 +202,8 @@ static PyMethodDef PyGetPackageDataDef = { // -------------------------------- getmesh ------------------------------------ -static auto PyGetMesh(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetMesh(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; @@ -233,8 +233,8 @@ static PyMethodDef PyGetMeshDef = { // ---------------------------- get_package_mesh ------------------------------- -static auto PyGetPackageMesh(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetPackageMesh(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; PyObject* package_obj; @@ -263,8 +263,8 @@ static PyMethodDef PyGetPackageMeshDef = { // ----------------------------- getcollisionmesh ------------------------------ -static auto PyGetCollisionMesh(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetCollisionMesh(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; diff --git a/src/ballistica/scene_v1/python/methods/python_methods_input.cc b/src/ballistica/scene_v1/python/methods/python_methods_input.cc index 55700a64..a41556be 100644 --- a/src/ballistica/scene_v1/python/methods/python_methods_input.cc +++ b/src/ballistica/scene_v1/python/methods/python_methods_input.cc @@ -17,8 +17,8 @@ namespace ballistica::scene_v1 { // ----------------------- get_configurable_game_pads -------------------------- -static auto PyGetConfigurableGamePads(PyObject* self, PyObject* args) - -> PyObject* { +static auto PyGetConfigurableGamePads(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; std::vector gamepads = g_base->input->GetConfigurableGamePads(); @@ -52,8 +52,8 @@ static PyMethodDef PyGetConfigurableGamePadsDef = { // ------------------------ have_touchscreen_input ----------------------------- -static auto PyHaveTouchScreenInput(PyObject* self, PyObject* args) - -> PyObject* { +static auto PyHaveTouchScreenInput(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; if (g_base->touch_input) { Py_RETURN_TRUE; @@ -77,8 +77,8 @@ static PyMethodDef PyHaveTouchScreenInputDef = { // ------------------------- set_touchscreen_editing --------------------------- -static auto PySetTouchscreenEditing(PyObject* self, PyObject* args) - -> PyObject* { +static auto PySetTouchscreenEditing(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; int editing; if (!PyArg_ParseTuple(args, "p", &editing)) { @@ -152,8 +152,8 @@ static PyMethodDef PyReleaseGamePadInputDef = { // ------------------------ capture_keyboard_input ----------------------------- -static auto PyCaptureKeyboardInput(PyObject* self, PyObject* args) - -> PyObject* { +static auto PyCaptureKeyboardInput(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); assert(g_scene_v1); @@ -181,8 +181,8 @@ static PyMethodDef PyCaptureKeyboardInputDef = { // ------------------------- release_keyboard_input ---------------------------- -static auto PyReleaseKeyboardInput(PyObject* self, PyObject* args) - -> PyObject* { +static auto PyReleaseKeyboardInput(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); assert(g_scene_v1); @@ -205,8 +205,8 @@ static PyMethodDef PyReleaseKeyboardInputDef = { // --------------------------- get_ui_input_device ----------------------------- -static auto PyGetUIInputDevice(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetUIInputDevice(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); static const char* kwlist[] = {nullptr}; @@ -252,8 +252,8 @@ static PyMethodDef PyGetUIInputDeviceDef = { // ---------------------------- getinputdevice --------------------------------- -static auto PyGetInputDevice(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetInputDevice(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); const char* name; diff --git a/src/ballistica/scene_v1/python/methods/python_methods_networking.cc b/src/ballistica/scene_v1/python/methods/python_methods_networking.cc index 3343dfde..699d605e 100644 --- a/src/ballistica/scene_v1/python/methods/python_methods_networking.cc +++ b/src/ballistica/scene_v1/python/methods/python_methods_networking.cc @@ -245,8 +245,8 @@ static PyMethodDef PySetAuthenticateClientsDef = { // ------------------------------- set_admins ---------------------------------- -static auto PySetAdmins(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PySetAdmins(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* admins_obj; static const char* kwlist[] = {"admins", nullptr}; @@ -310,8 +310,8 @@ static PyMethodDef PySetEnableDefaultKickVotingDef = { // --------------------------- connect_to_party -------------------------------- -static auto PyConnectToParty(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyConnectToParty(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; std::string address; PyObject* address_obj; @@ -522,8 +522,8 @@ static PyMethodDef PyDisconnectFromHostDef = { // --------------------------- disconnect_client ------------------------------- -static auto PyDisconnectClient(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyDisconnectClient(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; int client_id; int ban_time = 300; // Old default before we exposed this. @@ -633,8 +633,8 @@ static PyMethodDef PyGetGamePortDef = { // ------------------------ set_master_server_source --------------------------- -static auto PySetMasterServerSource(PyObject* self, PyObject* args) - -> PyObject* { +static auto PySetMasterServerSource(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; int source; if (!PyArg_ParseTuple(args, "i", &source)) return nullptr; @@ -660,8 +660,8 @@ static PyMethodDef PySetMasterServerSourceDef = { // ----------------------------- host_scan_cycle ------------------------------- -static auto PyHostScanCycle(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyHostScanCycle(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; auto* appmode = SceneV1AppMode::GetActiveOrThrow(); appmode->HostScanCycle(); @@ -689,8 +689,8 @@ static PyMethodDef PyHostScanCycleDef = { // ---------------------------- end_host_scanning ------------------------------ -static auto PyEndHostScanning(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyEndHostScanning(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; auto* appmode = SceneV1AppMode::GetActiveOrThrow(); appmode->EndHostScanning(); @@ -737,8 +737,8 @@ static PyMethodDef PyHaveConnectedClientsDef = { // ------------------------------ chatmessage ---------------------------------- -static auto PyChatMessage(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyChatMessage(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; std::string message; PyObject* message_obj; @@ -789,8 +789,8 @@ static PyMethodDef PyChatMessageDef = { // --------------------------- get_chat_messages ------------------------------- -static auto PyGetChatMessages(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetChatMessages(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); diff --git a/src/ballistica/scene_v1/python/methods/python_methods_scene.cc b/src/ballistica/scene_v1/python/methods/python_methods_scene.cc index 5e74a112..c684628f 100644 --- a/src/ballistica/scene_v1/python/methods/python_methods_scene.cc +++ b/src/ballistica/scene_v1/python/methods/python_methods_scene.cc @@ -41,8 +41,8 @@ namespace ballistica::scene_v1 { // --------------------------------- time -------------------------------------- -static auto PyTime(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyTime(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; @@ -79,8 +79,8 @@ static PyMethodDef PyTimeDef = { // --------------------------------- timer ------------------------------------- -static auto PyTimer(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyTimer(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); @@ -152,8 +152,8 @@ static PyMethodDef PyTimerDef = { // ----------------------------- basetime ----------------------------------- -static auto PyBaseTime(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyBaseTime(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; @@ -190,8 +190,8 @@ static PyMethodDef PyBaseTimeDef = { // --------------------------------- timer ------------------------------------- -static auto PyBaseTimer(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyBaseTimer(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); @@ -261,8 +261,8 @@ static PyMethodDef PyBaseTimerDef = { // ------------------------------- getsession ---------------------------------- -static auto PyGetSession(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetSession(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; int raise = true; static const char* kwlist[] = {"doraise", nullptr}; @@ -305,8 +305,8 @@ static PyMethodDef PyGetSessionDef = { // --------------------------- new_host_session -------------------------------- -static auto PyNewHostSession(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyNewHostSession(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* benchmark_type_str = nullptr; static const char* kwlist[] = {"sessiontype", "benchmark_type", nullptr}; @@ -347,8 +347,8 @@ static PyMethodDef PyNewHostSessionDef = { // -------------------------- new_replay_session ------------------------------- -static auto PyNewReplaySession(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyNewReplaySession(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; std::string file_name; PyObject* file_name_obj; @@ -377,8 +377,8 @@ static PyMethodDef PyNewReplaySessionDef = { // ------------------------------ is_in_replay --------------------------------- -static auto PyIsInReplay(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyIsInReplay(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); static const char* kwlist[] = {nullptr}; @@ -408,8 +408,8 @@ static PyMethodDef PyIsInReplayDef = { // -------------------------- register_session-------- ------------------------- -static auto PyRegisterSession(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyRegisterSession(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); PyObject* session_obj; @@ -443,8 +443,8 @@ static PyMethodDef PyRegisterSessionDef = { // --------------------------- register_activity ------------------------------- -static auto PyRegisterActivity(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyRegisterActivity(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); PyObject* activity_obj; @@ -516,8 +516,8 @@ static PyMethodDef PyGetForegroundHostSessionDef = { // ----------------------------- newactivity ----------------------------------- -static auto PyNewActivity(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyNewActivity(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {"activity_type", "settings", nullptr}; @@ -575,8 +575,8 @@ static PyMethodDef PyNewActivityDef = { // ----------------------------- getactivity ----------------------------------- -static auto PyGetActivity(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetActivity(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; int raise = true; static const char* kwlist[] = {"doraise", nullptr}; @@ -624,8 +624,8 @@ static PyMethodDef PyGetActivityDef = { // -------------------------- broadcastmessage --------------------------------- -static auto PyBroadcastMessage(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyBroadcastMessage(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* message = nullptr; PyObject* color_obj = Py_None; @@ -800,8 +800,8 @@ static PyMethodDef PyBroadcastMessageDef = { // ------------------------------- newnode ------------------------------------- -static auto PyNewNode(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyNewNode(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; Node* n = SceneV1Python::DoNewNode(args, keywds); if (!n) { @@ -1037,8 +1037,8 @@ static PyMethodDef PyGetCollisionInfoDef = { // ------------------------------ camerashake ---------------------------------- -static auto PyCameraShake(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyCameraShake(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; assert(g_base->InLogicThread()); float intensity = 1.0f; @@ -1087,8 +1087,8 @@ static PyMethodDef PyCameraShakeDef = { // -------------------------------- emitfx ------------------------------------- -static auto PyEmitFx(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyEmitFx(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {"position", "velocity", "count", "scale", "spread", "chunk_type", @@ -1303,8 +1303,8 @@ static PyMethodDef PyGetForegroundHostActivityDef = { // --------------------------- get_game_roster --------------------------------- -static auto PyGetGameRoster(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetGameRoster(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); static const char* kwlist[] = {nullptr}; @@ -1413,8 +1413,8 @@ static PyMethodDef PyGetGameRosterDef = { // ----------------------- set_debug_speed_exponent ---------------------------- -static auto PySetDebugSpeedExponent(PyObject* self, PyObject* args) - -> PyObject* { +static auto PySetDebugSpeedExponent(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; int speed; if (!PyArg_ParseTuple(args, "i", &speed)) { @@ -1452,8 +1452,8 @@ static PyMethodDef PySetDebugSpeedExponentDef = { // ----------------------- get_replay_speed_exponent --------------------------- -static auto PyGetReplaySpeedExponent(PyObject* self, PyObject* args) - -> PyObject* { +static auto PyGetReplaySpeedExponent(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; auto* appmode = SceneV1AppMode::GetActiveOrThrow(); return PyLong_FromLong(appmode->replay_speed_exponent()); @@ -1475,8 +1475,8 @@ static PyMethodDef PyGetReplaySpeedExponentDef = { // ------------------------ set_replay_speed_exponent -------------------------- -static auto PySetReplaySpeedExponent(PyObject* self, PyObject* args) - -> PyObject* { +static auto PySetReplaySpeedExponent(PyObject* self, + PyObject* args) -> PyObject* { BA_PYTHON_TRY; int speed; if (!PyArg_ParseTuple(args, "i", &speed)) { @@ -1568,6 +1568,39 @@ static PyMethodDef PyResumeReplayDef = { "Resumes replay.", }; +// -------------------------- seek_replay -------------------------------------- + +static auto PySeekReplay(PyObject* self, PyObject* args) -> PyObject* { + BA_PYTHON_TRY; + auto* appmode = SceneV1AppMode::GetActiveOrThrow(); + auto* session = + dynamic_cast(appmode->GetForegroundSession()); + if (session == nullptr) { + throw Exception( + "Attempting to seek a replay not in replay session context."); + } + float delta; + if (!PyArg_ParseTuple(args, "f", &delta)) { + return nullptr; + } + session->SeekTo(session->base_time() + + static_cast(delta * 1'000)); + Py_RETURN_NONE; + BA_PYTHON_CATCH; +} + +static PyMethodDef PySeekReplayDef = { + "seek_replay", // name + PySeekReplay, // method + METH_VARARGS, // flags + + "seek_replay(delta: float) -> None\n" + "\n" + "(internal)\n" + "\n" + "Rewind or fast-forward replay.", +}; + // ----------------------- reset_random_player_names --------------------------- static auto PyResetRandomPlayerNames(PyObject* self, PyObject* args, @@ -1618,8 +1651,8 @@ static PyMethodDef PyGetRandomNamesDef = { // -------------------------------- ls_objects --------------------------------- -static auto PyLsObjects(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyLsObjects(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; Object::LsObjects(); Py_RETURN_NONE; @@ -1643,8 +1676,8 @@ static PyMethodDef PyLsObjectsDef = { // --------------------------- ls_input_devices -------------------------------- -static auto PyLsInputDevices(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyLsInputDevices(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; g_base->input->LsInputDevices(); Py_RETURN_NONE; @@ -1668,8 +1701,8 @@ static PyMethodDef PyLsInputDevicesDef = { // -------------------------- set_internal_music ------------------------------- -static auto PySetInternalMusic(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PySetInternalMusic(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); PyObject* music_obj; @@ -1846,6 +1879,7 @@ auto PythonMethodsScene::GetMethods() -> std::vector { PySetReplaySpeedExponentDef, PyGetReplaySpeedExponentDef, PyIsReplayPausedDef, + PySeekReplayDef, PyPauseReplayDef, PyResumeReplayDef, PySetDebugSpeedExponentDef, diff --git a/src/ballistica/scene_v1/python/scene_v1_python.cc b/src/ballistica/scene_v1/python/scene_v1_python.cc index 1c7ed978..f99c9611 100644 --- a/src/ballistica/scene_v1/python/scene_v1_python.cc +++ b/src/ballistica/scene_v1/python/scene_v1_python.cc @@ -422,8 +422,8 @@ auto SceneV1Python::DoNewNode(PyObject* args, PyObject* keywds) -> Node* { // Return the node attr as a PyObject, or nullptr if the node doesn't have that // attr. -auto SceneV1Python::GetNodeAttr(Node* node, const char* attr_name) - -> PyObject* { +auto SceneV1Python::GetNodeAttr(Node* node, + const char* attr_name) -> PyObject* { assert(node); NodeAttribute attr = node->GetAttribute(attr_name); switch (attr.type()) { @@ -972,9 +972,8 @@ auto SceneV1Python::GetPySceneSounds(PyObject* o) -> std::vector { return vals; } -auto SceneV1Python::GetPySceneCollisionMesh(PyObject* o, bool allow_empty_ref, - bool allow_none) - -> SceneCollisionMesh* { +auto SceneV1Python::GetPySceneCollisionMesh( + PyObject* o, bool allow_empty_ref, bool allow_none) -> SceneCollisionMesh* { assert(Python::HaveGIL()); BA_PRECONDITION_FATAL(o != nullptr); @@ -1102,8 +1101,8 @@ auto SceneV1Python::GetPySceneDataAsset(PyObject* o, bool allow_empty_ref, PyExcType::kType); } -auto SceneV1Python::FilterChatMessage(std::string* message, int client_id) - -> bool { +auto SceneV1Python::FilterChatMessage(std::string* message, + int client_id) -> bool { assert(message); base::ScopedSetContext ssc(nullptr); @@ -1424,9 +1423,8 @@ auto SceneV1Python::HandleCapturedKeyRelease(const SDL_Keysym& keysym) -> bool { return true; } -auto SceneV1Python::HandleCapturedJoystickEvent(const SDL_Event& event, - base::InputDevice* input_device) - -> bool { +auto SceneV1Python::HandleCapturedJoystickEvent( + const SDL_Event& event, base::InputDevice* input_device) -> bool { assert(g_base->InLogicThread()); assert(input_device != nullptr); if (!joystick_capture_call_.Exists()) { diff --git a/src/ballistica/scene_v1/python/scene_v1_python.h b/src/ballistica/scene_v1/python/scene_v1_python.h index afa67832..c711ea45 100644 --- a/src/ballistica/scene_v1/python/scene_v1_python.h +++ b/src/ballistica/scene_v1/python/scene_v1_python.h @@ -70,8 +70,8 @@ class SceneV1Python { /// Given an asset-package python object and a media name, verify /// that the asset-package is valid in the current context_ref and return /// its fully qualified name if so. Throw an Exception if not. - auto ValidatedPackageAssetName(PyObject* package, const char* name) - -> std::string; + auto ValidatedPackageAssetName(PyObject* package, + const char* name) -> std::string; /// Specific Python objects we hold in objs_. enum class ObjID { @@ -101,9 +101,8 @@ class SceneV1Python { const auto& objs() { return objs_; } private: - static auto HandleCapturedJoystickEventCall(const SDL_Event& event, - base::InputDevice* input_device) - -> bool; + static auto HandleCapturedJoystickEventCall( + const SDL_Event& event, base::InputDevice* input_device) -> bool; static auto HandleCapturedKeyPressCall(const SDL_Keysym& keysym) -> bool; static auto HandleCapturedKeyReleaseCall(const SDL_Keysym& keysym) -> bool; auto HandleCapturedJoystickEvent(const SDL_Event& event, diff --git a/src/ballistica/scene_v1/support/client_session.h b/src/ballistica/scene_v1/support/client_session.h index f8e2acfb..e9c43d7b 100644 --- a/src/ballistica/scene_v1/support/client_session.h +++ b/src/ballistica/scene_v1/support/client_session.h @@ -96,6 +96,12 @@ class ClientSession : public Session { target_base_time_millisecs_ = base_time_millisecs_; } + protected: + void SetBaseTime(millisecs_t time) { + base_time_millisecs_ = time; + ResetTargetBaseTime(); + } + private: void ClearSessionObjs(); void AddCommand(const std::vector& command); diff --git a/src/ballistica/scene_v1/support/client_session_replay.cc b/src/ballistica/scene_v1/support/client_session_replay.cc index f5c63095..cd60b10b 100644 --- a/src/ballistica/scene_v1/support/client_session_replay.cc +++ b/src/ballistica/scene_v1/support/client_session_replay.cc @@ -2,6 +2,8 @@ #include "ballistica/scene_v1/support/client_session_replay.h" +#include + #include "ballistica/base/assets/assets.h" #include "ballistica/base/networking/networking.h" #include "ballistica/base/support/huffman.h" @@ -14,11 +16,22 @@ namespace ballistica::scene_v1 { +static const millisecs_t kReplayStateDumpIntervalMillisecs = 500; + auto ClientSessionReplay::GetActualTimeAdvanceMillisecs( double base_advance_millisecs) -> double { + if (is_fast_forwarding_) { + if (base_time() < fast_forward_base_time_) { + return std::min( + base_advance_millisecs * 8, + static_cast(fast_forward_base_time_ - base_time())); + } + is_fast_forwarding_ = false; + } auto* appmode = SceneV1AppMode::GetActiveOrFatal(); if (appmode->is_replay_paused()) { - return 0.0; + // FIXME: seeking a replay results in black screen here + return 0; } return base_advance_millisecs * pow(2.0f, appmode->replay_speed_exponent()); } @@ -134,6 +147,23 @@ void ClientSessionReplay::FetchMessages() { // If we have no messages left, read from the file until we get some. while (commands().empty()) { + // Before we read next message, let's save our current state + // if we didn't that for too long. + if (base_time() >= (states_.empty() ? 0 : states_.back().base_time_) + + kReplayStateDumpIntervalMillisecs) { + SessionStream out(nullptr, false); + DumpFullState(&out); + + current_state_.base_time_ = base_time(); + current_state_.correction_messages_.clear(); + GetCorrectionMessages(false, ¤t_state_.correction_messages_); + + fflush(file_); + current_state_.file_position_ = ftell(file_); + current_state_.message_ = out.GetOutMessage(); + states_.push_back(current_state_); + } + std::vector buffer; uint8_t len8; uint32_t len32; @@ -201,7 +231,6 @@ void ClientSessionReplay::FetchMessages() { for (auto&& i : connections_to_clients_) { i->SendReliableMessage(data_decompressed); } - message_fetch_num_++; } } @@ -221,6 +250,10 @@ void ClientSessionReplay::OnReset(bool rewind) { // Handles base resetting. ClientSession::OnReset(rewind); + // Hack or not, but let's reset our fast-forward flag here, in case we were + // asked to seek replay further than it's length. + is_fast_forwarding_ = false; + // If we've got any clients attached to us, tell them to reset as well. for (auto&& i : connections_to_clients_) { i->SendReliableMessage(std::vector(1, BA_MESSAGE_SESSION_RESET)); @@ -265,4 +298,52 @@ void ClientSessionReplay::OnReset(bool rewind) { } } +void ClientSessionReplay::SeekTo(millisecs_t to_base_time) { + is_fast_forwarding_ = false; + if (to_base_time < base_time()) { + auto it = std::lower_bound( + states_.rbegin(), states_.rend(), to_base_time, + [&](const IntermediateState& state, millisecs_t time) -> bool { + return state.base_time_ > time; + }); + if (it == states_.rend()) { + Reset(true); + } else { + current_state_ = *it; + RestoreFromCurrentState(); + } + } else { + auto it = std::lower_bound( + states_.begin(), states_.end(), to_base_time, + [&](const IntermediateState& state, millisecs_t time) -> bool { + return state.base_time_ < time; + }); + if (it == states_.end()) { + if (!states_.empty()) { + current_state_ = states_.back(); + RestoreFromCurrentState(); + } + // Let's speed up replay a bit + // (and we'll collect needed states along). + is_fast_forwarding_ = true; + fast_forward_base_time_ = to_base_time; + } else { + current_state_ = *it; + RestoreFromCurrentState(); + } + } +} + +void ClientSessionReplay::RestoreFromCurrentState() { + // FIXME: calling reset here causes background music to start over + Reset(true); + fseek(file_, current_state_.file_position_, SEEK_SET); + + SetBaseTime(current_state_.base_time_); + HandleSessionMessage(current_state_.message_); + for (const auto& msg : current_state_.correction_messages_) { + HandleSessionMessage(msg); + } +} + } // namespace ballistica::scene_v1 diff --git a/src/ballistica/scene_v1/support/client_session_replay.h b/src/ballistica/scene_v1/support/client_session_replay.h index 4bd82e82..ae5b8f72 100644 --- a/src/ballistica/scene_v1/support/client_session_replay.h +++ b/src/ballistica/scene_v1/support/client_session_replay.h @@ -29,8 +29,29 @@ class ClientSessionReplay : public ClientSession, void Error(const std::string& description) override; void FetchMessages() override; + void SeekTo(millisecs_t to_base_time); + private: - uint32_t message_fetch_num_{}; + struct IntermediateState { + // Message containing full scene state at the moment. + std::vector message_; + std::vector> correction_messages_; + + // A position in replay file where we should continue from. + int64_t file_position_; + + millisecs_t base_time_; + }; + + void RestoreFromCurrentState(); + + // List of passed states which we can rewind to. + std::vector states_; + IntermediateState current_state_; + + bool is_fast_forwarding_{}; + millisecs_t fast_forward_base_time_{}; + bool have_sent_client_message_{}; std::vector connections_to_clients_; std::vector connections_to_clients_ignored_; diff --git a/src/ballistica/scene_v1/support/host_session.h b/src/ballistica/scene_v1/support/host_session.h index cf53cccf..5515a48f 100644 --- a/src/ballistica/scene_v1/support/host_session.h +++ b/src/ballistica/scene_v1/support/host_session.h @@ -58,8 +58,8 @@ class HostSession : public Session { } // Given an activity python type, instantiate a new activity // and return a new reference. - auto NewHostActivity(PyObject* activity_type_obj, PyObject* settings_obj) - -> PyObject*; + auto NewHostActivity(PyObject* activity_type_obj, + PyObject* settings_obj) -> PyObject*; void DestroyHostActivity(HostActivity* a); void RemovePlayer(Player* player); void RequestPlayer(SceneV1InputDeviceDelegate* device); @@ -99,8 +99,8 @@ class HostSession : public Session { // New HostActivities should call this in their constructors. void AddHostActivity(HostActivity* sgc); - auto GetUnusedPlayerName(Player* p, const std::string& base_name) - -> std::string; + auto GetUnusedPlayerName(Player* p, + const std::string& base_name) -> std::string; auto ContextAllowsDefaultTimerTypes() -> bool override; auto TimeToNextEvent() -> std::optional override; diff --git a/src/ballistica/scene_v1/support/session_stream.h b/src/ballistica/scene_v1/support/session_stream.h index 053771f2..1bc3a831 100644 --- a/src/ballistica/scene_v1/support/session_stream.h +++ b/src/ballistica/scene_v1/support/session_stream.h @@ -121,8 +121,8 @@ class SessionStream : public Object, public ClientControllerInterface { template auto GetPointerCount(const std::vector& vec) -> size_t; template - auto GetFreeIndex(std::vector* vec, std::vector* free_indices) - -> size_t; + auto GetFreeIndex(std::vector* vec, + std::vector* free_indices) -> size_t; template void Add(T* val, std::vector* vec, std::vector* free_indices); template diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 19703b87..1e716406 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int { namespace ballistica { // These are set automatically via script; don't modify them here. -const int kEngineBuildNumber = 21770; +const int kEngineBuildNumber = 21778; const char* kEngineVersion = "1.7.33"; const int kEngineApiVersion = 8; diff --git a/src/ballistica/shared/foundation/event_loop.cc b/src/ballistica/shared/foundation/event_loop.cc index 58153d94..a2a714c5 100644 --- a/src/ballistica/shared/foundation/event_loop.cc +++ b/src/ballistica/shared/foundation/event_loop.cc @@ -576,8 +576,8 @@ auto EventLoop::AreEventLoopsSuspended() -> bool { return g_core->event_loops_suspended(); } -auto EventLoop::NewTimer(microsecs_t length, bool repeat, Runnable* runnable) - -> Timer* { +auto EventLoop::NewTimer(microsecs_t length, bool repeat, + Runnable* runnable) -> Timer* { assert(g_core); assert(ThreadIsCurrent()); assert(Object::IsValidManagedObject(runnable)); diff --git a/src/ballistica/shared/foundation/macros.cc b/src/ballistica/shared/foundation/macros.cc index c2ae788d..e1e1791b 100644 --- a/src/ballistica/shared/foundation/macros.cc +++ b/src/ballistica/shared/foundation/macros.cc @@ -138,8 +138,8 @@ void MacroLogPythonTrace(core::CoreFeatureSet* corefs, const std::string& msg) { Log(LogLevel::kError, msg); } -auto MacroPathFilter(core::CoreFeatureSet* corefs, const char* filename) - -> const char* { +auto MacroPathFilter(core::CoreFeatureSet* corefs, + const char* filename) -> const char* { // If we've got a build_src_dir set and filename starts with it, skip past // it. assert(corefs); diff --git a/src/ballistica/shared/foundation/macros.h b/src/ballistica/shared/foundation/macros.h index f8526b8c..3ba372e6 100644 --- a/src/ballistica/shared/foundation/macros.h +++ b/src/ballistica/shared/foundation/macros.h @@ -173,8 +173,8 @@ namespace ballistica { // Support functions used by some of our macros; not intended to be used // directly. -auto MacroPathFilter(core::CoreFeatureSet* corefs, const char* filename) - -> const char*; +auto MacroPathFilter(core::CoreFeatureSet* corefs, + const char* filename) -> const char*; void MacroFunctionTimerEnd(core::CoreFeatureSet* corefs, millisecs_t starttime, millisecs_t time, const char* funcname); void MacroFunctionTimerEndThread(core::CoreFeatureSet* corefs, diff --git a/src/ballistica/shared/generic/base64.cc b/src/ballistica/shared/generic/base64.cc index 77df7e20..cada6c25 100644 --- a/src/ballistica/shared/generic/base64.cc +++ b/src/ballistica/shared/generic/base64.cc @@ -102,8 +102,8 @@ auto base64_encode(const unsigned char* bytes_to_encode, unsigned int in_len, return ret; } -auto base64_decode(const std::string& encoded_string, bool urlsafe) - -> std::string { +auto base64_decode(const std::string& encoded_string, + bool urlsafe) -> std::string { int in_len = static_cast(encoded_string.size()); int i = 0; // int j = 0; diff --git a/src/ballistica/shared/generic/base64.h b/src/ballistica/shared/generic/base64.h index 0df02824..2faab459 100644 --- a/src/ballistica/shared/generic/base64.h +++ b/src/ballistica/shared/generic/base64.h @@ -7,8 +7,8 @@ namespace ballistica { -auto base64_encode(const unsigned char*, unsigned int len, bool urlsafe = false) - -> std::string; +auto base64_encode(const unsigned char*, unsigned int len, + bool urlsafe = false) -> std::string; auto base64_decode(const std::string& s, bool urlsafe = false) -> std::string; } // namespace ballistica diff --git a/src/ballistica/shared/generic/timer_list.h b/src/ballistica/shared/generic/timer_list.h index a954b759..f2ad5408 100644 --- a/src/ballistica/shared/generic/timer_list.h +++ b/src/ballistica/shared/generic/timer_list.h @@ -22,8 +22,8 @@ class TimerList { // Create a timer with provided runnable. auto NewTimer(TimerMedium current_time, TimerMedium length, - TimerMedium offset, int repeat_count, Runnable* runnable) - -> Timer*; + TimerMedium offset, int repeat_count, + Runnable* runnable) -> Timer*; // Return a timer by its id, or nullptr if the timer no longer exists. auto GetTimer(int id) -> Timer*; diff --git a/src/ballistica/shared/generic/utf8.cc b/src/ballistica/shared/generic/utf8.cc index b2cc83b0..b26c76a2 100644 --- a/src/ballistica/shared/generic/utf8.cc +++ b/src/ballistica/shared/generic/utf8.cc @@ -400,8 +400,7 @@ auto u8_is_locale_utf8(const char* locale) -> int { for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++) { if (*cp == '.') { const char* encoding = ++cp; - for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++) - ; + for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++); if ((cp - encoding == 5 && !strncmp(encoding, "UTF-8", 5)) || (cp - encoding == 4 && !strncmp(encoding, "utf8", 4))) return 1; /* it's UTF-8 */ diff --git a/src/ballistica/shared/generic/utils.cc b/src/ballistica/shared/generic/utils.cc index 10025b03..d87a10df 100644 --- a/src/ballistica/shared/generic/utils.cc +++ b/src/ballistica/shared/generic/utils.cc @@ -332,8 +332,8 @@ auto Utils::UTF8FromUnicode(std::vector unichars) -> std::string { return buffer.data(); } -auto Utils::UnicodeFromUTF8(const std::string& s_in, const char* loc) - -> std::vector { +auto Utils::UnicodeFromUTF8(const std::string& s_in, + const char* loc) -> std::vector { std::string s = GetValidUTF8(s_in.c_str(), loc); // worst case every char is a character (plus trailing 0) std::vector vals(s.size() + 1); diff --git a/src/ballistica/shared/generic/utils.h b/src/ballistica/shared/generic/utils.h index db5088ae..1d969586 100644 --- a/src/ballistica/shared/generic/utils.h +++ b/src/ballistica/shared/generic/utils.h @@ -48,8 +48,8 @@ class Utils { /// control characters). static auto StripNonAsciiFromUTF8(const std::string& s) -> std::string; - static auto UnicodeFromUTF8(const std::string& s, const char* loc) - -> std::vector; + static auto UnicodeFromUTF8(const std::string& s, + const char* loc) -> std::vector; static auto UTF8FromUnicode(std::vector unichars) -> std::string; static auto UTF8FromUnicodeChar(uint32_t c) -> std::string; static auto UTF8StringLength(const char* val) -> int; diff --git a/src/ballistica/shared/math/matrix44f.cc b/src/ballistica/shared/math/matrix44f.cc index 46d08c3e..f2e093a4 100644 --- a/src/ballistica/shared/math/matrix44f.cc +++ b/src/ballistica/shared/math/matrix44f.cc @@ -57,8 +57,8 @@ auto Matrix44fRotate(float azimuth, float elevation) -> Matrix44f { return rotate; } -auto Matrix44fOrient(const Vector3f& x, const Vector3f& y, const Vector3f& z) - -> Matrix44f { +auto Matrix44fOrient(const Vector3f& x, const Vector3f& y, + const Vector3f& z) -> Matrix44f { Matrix44f orient{kMatrix44fIdentity}; orient.set(0, 0, x.x); @@ -76,8 +76,8 @@ auto Matrix44fOrient(const Vector3f& x, const Vector3f& y, const Vector3f& z) return orient; } -auto Matrix44fOrient(const Vector3f& direction, const Vector3f& up) - -> Matrix44f { +auto Matrix44fOrient(const Vector3f& direction, + const Vector3f& up) -> Matrix44f { assert(direction.LengthSquared() > 0.0f); assert(up.LengthSquared() > 0.0f); diff --git a/src/ballistica/shared/math/matrix44f.h b/src/ballistica/shared/math/matrix44f.h index e8bcd52c..20b321b0 100644 --- a/src/ballistica/shared/math/matrix44f.h +++ b/src/ballistica/shared/math/matrix44f.h @@ -161,8 +161,8 @@ inline auto Matrix44fTranslate(const Vector3f& trans) -> Matrix44f { return translate; } -inline auto Matrix44fTranslate(const float x, const float y, const float z) - -> Matrix44f { +inline auto Matrix44fTranslate(const float x, const float y, + const float z) -> Matrix44f { Matrix44f translate{kMatrix44fIdentity}; translate.set(3, 0, x); translate.set(3, 1, y); @@ -188,12 +188,12 @@ inline auto Matrix44fScale(const Vector3f& sf) -> Matrix44f { auto Matrix44fRotate(const Vector3f& axis, float angle) -> Matrix44f; auto Matrix44fRotate(float azimuth, float elevation) -> Matrix44f; -auto Matrix44fOrient(const Vector3f& x, const Vector3f& y, const Vector3f& z) - -> Matrix44f; +auto Matrix44fOrient(const Vector3f& x, const Vector3f& y, + const Vector3f& z) -> Matrix44f; // Note: direction and up need to be perpendicular and normalized here. -auto Matrix44fOrient(const Vector3f& direction, const Vector3f& up) - -> Matrix44f; +auto Matrix44fOrient(const Vector3f& direction, + const Vector3f& up) -> Matrix44f; auto Matrix44fFrustum(float left, float right, float bottom, float top, float near, float far) -> Matrix44f; diff --git a/src/ballistica/shared/python/python_class.cc b/src/ballistica/shared/python/python_class.cc index b6530162..1e652df3 100644 --- a/src/ballistica/shared/python/python_class.cc +++ b/src/ballistica/shared/python/python_class.cc @@ -35,8 +35,8 @@ auto PythonClass::TypeIsSetUp(PyTypeObject* cls) -> bool { return Py_REFCNT(cls) > 0; } -auto PythonClass::tp_new(PyTypeObject* type, PyObject* args, PyObject* kwds) - -> PyObject* { +auto PythonClass::tp_new(PyTypeObject* type, PyObject* args, + PyObject* kwds) -> PyObject* { // Simply allocating and returning a zeroed instance of our class here. // If subclasses need to construct/destruct any other values in the object // they can either do it manually here and in tp_dealloc *or* they can get @@ -57,8 +57,8 @@ auto PythonClass::tp_getattro(PythonClass* node, PyObject* attr) -> PyObject* { BA_PYTHON_CATCH; } -auto PythonClass::tp_setattro(PythonClass* node, PyObject* attr, PyObject* val) - -> int { +auto PythonClass::tp_setattro(PythonClass* node, PyObject* attr, + PyObject* val) -> int { BA_PYTHON_TRY; return PyObject_GenericSetAttr(reinterpret_cast(node), attr, val); BA_PYTHON_INT_CATCH; diff --git a/src/ballistica/shared/python/python_class.h b/src/ballistica/shared/python/python_class.h index 572fea36..5036a08e 100644 --- a/src/ballistica/shared/python/python_class.h +++ b/src/ballistica/shared/python/python_class.h @@ -35,12 +35,12 @@ class PythonClass { private: static auto tp_repr(PythonClass* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* kwds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* kwds) -> PyObject*; static void tp_dealloc(PythonClass* self); static auto tp_getattro(PythonClass* node, PyObject* attr) -> PyObject*; - static auto tp_setattro(PythonClass* node, PyObject* attr, PyObject* val) - -> int; + static auto tp_setattro(PythonClass* node, PyObject* attr, + PyObject* val) -> int; }; } // namespace ballistica diff --git a/src/ballistica/shared/python/python_command.cc b/src/ballistica/shared/python/python_command.cc index ab04999f..68cf3275 100644 --- a/src/ballistica/shared/python/python_command.cc +++ b/src/ballistica/shared/python/python_command.cc @@ -97,8 +97,8 @@ auto PythonCommand::CanEval() -> bool { return true; } -auto PythonCommand::Exec(bool print_errors, PyObject* globals, PyObject* locals) - -> bool { +auto PythonCommand::Exec(bool print_errors, PyObject* globals, + PyObject* locals) -> bool { assert(Python::HaveGIL()); // If we're being used before core is up, we need both global and @@ -163,8 +163,8 @@ auto PythonCommand::Exec(bool print_errors, PyObject* globals, PyObject* locals) return false; } -auto PythonCommand::Eval(bool print_errors, PyObject* globals, PyObject* locals) - -> PythonRef { +auto PythonCommand::Eval(bool print_errors, PyObject* globals, + PyObject* locals) -> PythonRef { assert(Python::HaveGIL()); assert(!dead_); diff --git a/src/ballistica/shared/python/python_command.h b/src/ballistica/shared/python/python_command.h index a0a34704..bf712080 100644 --- a/src/ballistica/shared/python/python_command.h +++ b/src/ballistica/shared/python/python_command.h @@ -46,8 +46,8 @@ class PythonCommand { /// Run the command and return the result as a new Python reference. /// Only works for eval-able commands. /// Returns nullptr on errors, but Python error state will be cleared. - auto Eval(bool print_errors, PyObject* globals, PyObject* locals) - -> PythonRef; + auto Eval(bool print_errors, PyObject* globals, + PyObject* locals) -> PythonRef; void PrintContext(); diff --git a/src/ballistica/shared/python/python_ref.cc b/src/ballistica/shared/python/python_ref.cc index eb74d121..b209a561 100644 --- a/src/ballistica/shared/python/python_ref.cc +++ b/src/ballistica/shared/python/python_ref.cc @@ -277,8 +277,8 @@ auto PythonRef::UnicodeCheck() const -> bool { return static_cast(PyUnicode_Check(obj_)); } -static inline auto _HandleCallResults(PyObject* out, bool print_errors) - -> PyObject* { +static inline auto _HandleCallResults(PyObject* out, + bool print_errors) -> PyObject* { if (!out) { if (print_errors) { // Save/restore error or it can mess with context print calls. @@ -297,8 +297,8 @@ static inline auto _HandleCallResults(PyObject* out, bool print_errors) return out; } -auto PythonRef::Call(PyObject* args, PyObject* keywds, bool print_errors) const - -> PythonRef { +auto PythonRef::Call(PyObject* args, PyObject* keywds, + bool print_errors) const -> PythonRef { assert(obj_); assert(Python::HaveGIL()); assert(CallableCheck()); @@ -319,8 +319,8 @@ auto PythonRef::Call(bool print_errors) const -> PythonRef { return out ? PythonRef(out, PythonRef::kSteal) : PythonRef(); } -auto PythonRef::Call(const Vector2f& val, bool print_errors) const - -> PythonRef { +auto PythonRef::Call(const Vector2f& val, + bool print_errors) const -> PythonRef { assert(Python::HaveGIL()); PythonRef args(Py_BuildValue("((ff))", val.x, val.y), PythonRef::kSteal); return Call(args.Get(), nullptr, print_errors); diff --git a/src/ballistica/template_fs/python/class/python_class_hello.h b/src/ballistica/template_fs/python/class/python_class_hello.h index e2e3f28d..d717da9b 100644 --- a/src/ballistica/template_fs/python/class/python_class_hello.h +++ b/src/ballistica/template_fs/python/class/python_class_hello.h @@ -33,8 +33,8 @@ class PythonClassHello : public PythonClass { PythonClassHello(); ~PythonClassHello(); static PyMethodDef tp_methods[]; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassHello* self); static auto TestMethod(PythonClassHello* self, PyObject* args, PyObject* keywds) -> PyObject*; diff --git a/src/ballistica/template_fs/python/methods/python_methods_template_fs.cc b/src/ballistica/template_fs/python/methods/python_methods_template_fs.cc index 2e0015ad..a644e4e9 100644 --- a/src/ballistica/template_fs/python/methods/python_methods_template_fs.cc +++ b/src/ballistica/template_fs/python/methods/python_methods_template_fs.cc @@ -9,8 +9,8 @@ namespace ballistica::template_fs { // -------------------------- hello_again_world -------------------------------- -static auto PyHelloAgainWorld(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyHelloAgainWorld(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {nullptr}; diff --git a/src/ballistica/ui_v1/python/class/python_class_ui_mesh.h b/src/ballistica/ui_v1/python/class/python_class_ui_mesh.h index 09edebc9..49ce22a0 100644 --- a/src/ballistica/ui_v1/python/class/python_class_ui_mesh.h +++ b/src/ballistica/ui_v1/python/class/python_class_ui_mesh.h @@ -39,8 +39,8 @@ class PythonClassUIMesh : public PythonClass { private: static PyMethodDef tp_methods[]; static auto tp_repr(PythonClassUIMesh* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassUIMesh* self); Object::Ref* mesh_; }; diff --git a/src/ballistica/ui_v1/python/class/python_class_ui_sound.h b/src/ballistica/ui_v1/python/class/python_class_ui_sound.h index 50aefb51..1dfcb57e 100644 --- a/src/ballistica/ui_v1/python/class/python_class_ui_sound.h +++ b/src/ballistica/ui_v1/python/class/python_class_ui_sound.h @@ -39,13 +39,13 @@ class PythonClassUISound : public PythonClass { private: static PyMethodDef tp_methods[]; static auto tp_repr(PythonClassUISound* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassUISound* self); - static auto Play(PythonClassUISound* self, PyObject* args, PyObject* keywds) - -> PyObject*; - static auto Stop(PythonClassUISound* self, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto Play(PythonClassUISound* self, PyObject* args, + PyObject* keywds) -> PyObject*; + static auto Stop(PythonClassUISound* self, PyObject* args, + PyObject* keywds) -> PyObject*; Object::Ref* sound_; bool playing_; diff --git a/src/ballistica/ui_v1/python/class/python_class_ui_texture.h b/src/ballistica/ui_v1/python/class/python_class_ui_texture.h index 56e720b6..b50815c9 100644 --- a/src/ballistica/ui_v1/python/class/python_class_ui_texture.h +++ b/src/ballistica/ui_v1/python/class/python_class_ui_texture.h @@ -40,8 +40,8 @@ class PythonClassUITexture : public PythonClass { private: static PyMethodDef tp_methods[]; static auto tp_repr(PythonClassUITexture* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassUITexture* self); Object::Ref* texture_; }; diff --git a/src/ballistica/ui_v1/python/class/python_class_widget.cc b/src/ballistica/ui_v1/python/class/python_class_widget.cc index 62b879be..57978903 100644 --- a/src/ballistica/ui_v1/python/class/python_class_widget.cc +++ b/src/ballistica/ui_v1/python/class/python_class_widget.cc @@ -90,8 +90,8 @@ auto PythonClassWidget::GetWidget() const -> Widget* { return w; } -auto PythonClassWidget::tp_getattro(PythonClassWidget* self, PyObject* attr) - -> PyObject* { +auto PythonClassWidget::tp_getattro(PythonClassWidget* self, + PyObject* attr) -> PyObject* { BA_PYTHON_TRY; BA_PRECONDITION(g_base->InLogicThread()); @@ -312,8 +312,8 @@ auto PythonClassWidget::Delete(PythonClassWidget* self, PyObject* args, } auto PythonClassWidget::AddDeleteCallback(PythonClassWidget* self, - PyObject* args, PyObject* keywds) - -> PyObject* { + PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* call_obj; static const char* kwlist[] = {"call", nullptr}; diff --git a/src/ballistica/ui_v1/python/class/python_class_widget.h b/src/ballistica/ui_v1/python/class/python_class_widget.h index b4e98409..e38fd152 100644 --- a/src/ballistica/ui_v1/python/class/python_class_widget.h +++ b/src/ballistica/ui_v1/python/class/python_class_widget.h @@ -23,8 +23,8 @@ class PythonClassWidget : public PythonClass { private: static PyMethodDef tp_methods[]; static auto tp_repr(PythonClassWidget* self) -> PyObject*; - static auto tp_new(PyTypeObject* type, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto tp_new(PyTypeObject* type, PyObject* args, + PyObject* keywds) -> PyObject*; static void tp_dealloc(PythonClassWidget* self); static auto tp_getattro(PythonClassWidget* self, PyObject* attr) -> PyObject*; static auto tp_setattro(PythonClassWidget* self, PyObject* attr, @@ -35,8 +35,8 @@ class PythonClassWidget : public PythonClass { static auto GetChildren(PythonClassWidget* self) -> PyObject*; static auto GetSelectedChild(PythonClassWidget* self) -> PyObject*; static auto GetScreenSpaceCenter(PythonClassWidget* self) -> PyObject*; - static auto Delete(PythonClassWidget* self, PyObject* args, PyObject* keywds) - -> PyObject*; + static auto Delete(PythonClassWidget* self, PyObject* args, + PyObject* keywds) -> PyObject*; static auto AddDeleteCallback(PythonClassWidget* self, PyObject* args, PyObject* keywds) -> PyObject*; Object::WeakRef* widget_; diff --git a/src/ballistica/ui_v1/python/methods/python_methods_ui_v1.cc b/src/ballistica/ui_v1/python/methods/python_methods_ui_v1.cc index 6937e819..37992377 100644 --- a/src/ballistica/ui_v1/python/methods/python_methods_ui_v1.cc +++ b/src/ballistica/ui_v1/python/methods/python_methods_ui_v1.cc @@ -29,8 +29,8 @@ namespace ballistica::ui_v1 { // ------------------------------ getsound ------------------------------------- -static auto PyGetSound(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetSound(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; @@ -58,8 +58,8 @@ static PyMethodDef PyGetSoundDef = { // ----------------------------- gettexture ------------------------------------ -static auto PyGetTexture(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetTexture(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; @@ -87,8 +87,8 @@ static PyMethodDef PyGetTextureDef = { // -------------------------- get_qrcode_texture ------------------------------- -static auto PyGetQRCodeTexture(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetQRCodeTexture(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* url; static const char* kwlist[] = {"url", nullptr}; @@ -117,8 +117,8 @@ static PyMethodDef PyGetQRCodeTextureDef = { // ------------------------------- getmesh ------------------------------------- -static auto PyGetMesh(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetMesh(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; static const char* kwlist[] = {"name", nullptr}; @@ -146,8 +146,8 @@ static PyMethodDef PyGetMeshDef = { // ----------------------------- buttonwidget ---------------------------------- -static auto PyButtonWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyButtonWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* size_obj = Py_None; PyObject* pos_obj = Py_None; @@ -264,7 +264,7 @@ static auto PyButtonWidget(PyObject* self, PyObject* args, PyObject* keywds) parent_widget = parent_obj == Py_None ? g_ui_v1->screen_root_widget() : dynamic_cast( - UIV1Python::GetPyWidget(parent_obj)); + UIV1Python::GetPyWidget(parent_obj)); if (parent_widget == nullptr) { throw Exception("Parent widget nonexistent or not a container.", PyExcType::kWidgetNotFound); @@ -508,8 +508,8 @@ static PyMethodDef PyButtonWidgetDef = { // --------------------------- checkboxwidget ---------------------------------- -static auto PyCheckBoxWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyCheckBoxWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* size_obj = Py_None; PyObject* pos_obj = Py_None; @@ -573,7 +573,7 @@ static auto PyCheckBoxWidget(PyObject* self, PyObject* args, PyObject* keywds) parent_widget = parent_obj == Py_None ? g_ui_v1->screen_root_widget() : dynamic_cast( - UIV1Python::GetPyWidget(parent_obj)); + UIV1Python::GetPyWidget(parent_obj)); if (parent_widget == nullptr) { throw Exception("Parent widget nonexistent or not a container.", PyExcType::kWidgetNotFound); @@ -682,8 +682,8 @@ static PyMethodDef PyCheckBoxWidgetDef = { // ----------------------------- imagewidget ----------------------------------- -static auto PyImageWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyImageWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* size_obj = Py_None; PyObject* pos_obj = Py_None; @@ -752,7 +752,7 @@ static auto PyImageWidget(PyObject* self, PyObject* args, PyObject* keywds) parent_widget = parent_obj == Py_None ? g_ui_v1->screen_root_widget() : dynamic_cast( - UIV1Python::GetPyWidget(parent_obj)); + UIV1Python::GetPyWidget(parent_obj)); if (parent_widget == nullptr) { throw Exception("Parent widget nonexistent or not a container.", PyExcType::kWidgetNotFound); @@ -880,8 +880,8 @@ static PyMethodDef PyImageWidgetDef = { // ----------------------------- columnwidget ---------------------------------- -static auto PyColumnWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyColumnWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* size_obj{Py_None}; @@ -949,7 +949,7 @@ static auto PyColumnWidget(PyObject* self, PyObject* args, PyObject* keywds) parent_widget = parent_obj == Py_None ? g_ui_v1->screen_root_widget() : dynamic_cast( - UIV1Python::GetPyWidget(parent_obj)); + UIV1Python::GetPyWidget(parent_obj)); if (!parent_widget) { throw Exception("Invalid or nonexistent parent widget.", PyExcType::kWidgetNotFound); @@ -1062,8 +1062,8 @@ static PyMethodDef PyColumnWidgetDef = { // ---------------------------- containerwidget -------------------------------- -static auto PyContainerWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyContainerWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* size_obj = Py_None; PyObject* pos_obj = Py_None; @@ -1170,7 +1170,7 @@ static auto PyContainerWidget(PyObject* self, PyObject* args, PyObject* keywds) parent_widget = parent_obj == Py_None ? g_ui_v1->screen_root_widget() : dynamic_cast( - UIV1Python::GetPyWidget(parent_obj)); + UIV1Python::GetPyWidget(parent_obj)); if (!parent_widget) { throw Exception("Invalid or nonexistent parent widget.", PyExcType::kWidgetNotFound); @@ -1393,8 +1393,8 @@ static PyMethodDef PyContainerWidgetDef = { // ------------------------------ rowwidget ------------------------------------ -static auto PyRowWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyRowWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* size_obj{Py_None}; @@ -1443,7 +1443,7 @@ static auto PyRowWidget(PyObject* self, PyObject* args, PyObject* keywds) parent_widget = parent_obj == Py_None ? g_ui_v1->screen_root_widget() : dynamic_cast( - UIV1Python::GetPyWidget(parent_obj)); + UIV1Python::GetPyWidget(parent_obj)); if (!parent_widget) { throw Exception("invalid or nonexistent parent widget.", PyExcType::kWidgetNotFound); @@ -1522,8 +1522,8 @@ static PyMethodDef PyRowWidgetDef = { // ---------------------------- scrollwidget ----------------------------------- -static auto PyScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyScrollWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* size_obj{Py_None}; PyObject* pos_obj{Py_None}; @@ -1595,7 +1595,7 @@ static auto PyScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) parent_widget = parent_obj == Py_None ? g_ui_v1->screen_root_widget() : dynamic_cast( - UIV1Python::GetPyWidget(parent_obj)); + UIV1Python::GetPyWidget(parent_obj)); if (!parent_widget) { throw Exception("Invalid or nonexistent parent widget.", PyExcType::kWidgetNotFound); @@ -1710,8 +1710,8 @@ static PyMethodDef PyScrollWidgetDef = { // ---------------------------- hscrollwidget ---------------------------------- -static auto PyHScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyHScrollWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* size_obj = Py_None; @@ -1781,7 +1781,7 @@ static auto PyHScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) parent_widget = parent_obj == Py_None ? g_ui_v1->screen_root_widget() : dynamic_cast( - UIV1Python::GetPyWidget(parent_obj)); + UIV1Python::GetPyWidget(parent_obj)); if (!parent_widget) { throw Exception("Invalid or nonexistent parent widget.", PyExcType::kWidgetNotFound); @@ -1889,8 +1889,8 @@ static PyMethodDef PyHScrollWidgetDef = { // ------------------------------ textwidget ----------------------------------- -static auto PyTextWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyTextWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* size_obj = Py_None; PyObject* pos_obj = Py_None; @@ -2039,7 +2039,7 @@ static auto PyTextWidget(PyObject* self, PyObject* args, PyObject* keywds) parent_widget = parent_obj == Py_None ? g_ui_v1->screen_root_widget() : dynamic_cast( - UIV1Python::GetPyWidget(parent_obj)); + UIV1Python::GetPyWidget(parent_obj)); if (!parent_widget) { throw Exception("Invalid or nonexistent parent widget.", PyExcType::kWidgetNotFound); @@ -2280,8 +2280,8 @@ static PyMethodDef PyTextWidgetDef = { // ------------------------------- widget -------------------------------------- -static auto PyWidgetCall(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyWidgetCall(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; PyObject* edit_obj = Py_None; @@ -2510,8 +2510,8 @@ static PyMethodDef PySetPartyWindowOpenDef = { // -------------------------- get_special_widget ------------------------------- -static auto PyGetSpecialWidget(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyGetSpecialWidget(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* name; @@ -2545,8 +2545,8 @@ static PyMethodDef PyGetSpecialWidgetDef = { // ------------------------------ back_press ----------------------------------- -static auto PyBackPress(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyBackPress(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; static const char* kwlist[] = {nullptr}; @@ -2571,8 +2571,8 @@ static PyMethodDef PyBackPressDef = { // ------------------------------- open_url ------------------------------------ -static auto PyOpenURL(PyObject* self, PyObject* args, PyObject* keywds) - -> PyObject* { +static auto PyOpenURL(PyObject* self, PyObject* args, + PyObject* keywds) -> PyObject* { BA_PYTHON_TRY; const char* address{}; int force_internal{0}; diff --git a/src/ballistica/ui_v1/widget/button_widget.cc b/src/ballistica/ui_v1/widget/button_widget.cc index 9b84d87c..a5906567 100644 --- a/src/ballistica/ui_v1/widget/button_widget.cc +++ b/src/ballistica/ui_v1/widget/button_widget.cc @@ -13,7 +13,7 @@ namespace ballistica::ui_v1 { ButtonWidget::ButtonWidget() : birth_time_millisecs_{ - static_cast(g_base->logic->display_time() * 1000.0)} { + static_cast(g_base->logic->display_time() * 1000.0)} { text_ = Object::New(); set_text("Button"); text_->set_valign(TextWidget::VAlign::kCenter); diff --git a/src/ballistica/ui_v1/widget/container_widget.cc b/src/ballistica/ui_v1/widget/container_widget.cc index 37495e0a..aaacb1e2 100644 --- a/src/ballistica/ui_v1/widget/container_widget.cc +++ b/src/ballistica/ui_v1/widget/container_widget.cc @@ -697,8 +697,8 @@ auto ContainerWidget::HandleMessage(const base::WidgetMessage& m) -> bool { return claimed; } -auto ContainerWidget::GetMult(millisecs_t current_time, bool for_glow) const - -> float { +auto ContainerWidget::GetMult(millisecs_t current_time, + bool for_glow) const -> float { if (root_selectable_ && selected()) { float m; diff --git a/src/ballistica/ui_v1/widget/image_widget.cc b/src/ballistica/ui_v1/widget/image_widget.cc index a6d29654..926992f6 100644 --- a/src/ballistica/ui_v1/widget/image_widget.cc +++ b/src/ballistica/ui_v1/widget/image_widget.cc @@ -9,7 +9,7 @@ namespace ballistica::ui_v1 { ImageWidget::ImageWidget() : birth_time_millisecs_{ - static_cast(g_base->logic->display_time() * 1000.0)} {} + static_cast(g_base->logic->display_time() * 1000.0)} {} ImageWidget::~ImageWidget() = default; diff --git a/tests/test_efro/test_dataclassio.py b/tests/test_efro/test_dataclassio.py index 125613e3..e2de4d53 100644 --- a/tests/test_efro/test_dataclassio.py +++ b/tests/test_efro/test_dataclassio.py @@ -644,6 +644,24 @@ def test_dict() -> None: dataclass_to_dict(obj4) +def test_sets() -> None: + """Test bits related to sets.""" + + @ioprepped + @dataclass + class _TestClass: + sval: set[str] + + obj1 = _TestClass({'a', 'b', 'c', 'd', 'e', 'f'}) + obj2 = _TestClass({'c', 'd', 'a', 'e', 'f', 'b'}) + + # Sets get converted to lists; make sure they are getting sorted so + # that output is deterministic and it is meaningful to compare the + # output dicts from two sets for equality. + assert dataclass_to_dict(obj1) == {'sval': ['a', 'b', 'c', 'd', 'e', 'f']} + assert dataclass_to_dict(obj2) == {'sval': ['a', 'b', 'c', 'd', 'e', 'f']} + + def test_name_clashes() -> None: """Make sure we catch name clashes since we can remap attr names.""" diff --git a/tools/bacommon/servermanager.py b/tools/bacommon/servermanager.py index 0fe8e7d8..6cc5cf4b 100644 --- a/tools/bacommon/servermanager.py +++ b/tools/bacommon/servermanager.py @@ -47,10 +47,14 @@ class ServerConfig: # Max devices in the party. Note that this does *NOT* mean max players. # Any device in the party can have more than one player on it if they have # multiple controllers. Also, this number currently includes the server so - # generally make it 1 bigger than you need. Max-players is not currently - # exposed but I'll try to add that soon. + # generally make it 1 bigger than you need. max_party_size: int = 6 + # Max players that can join a session. If present this will override the + # session's preferred max_players. if a value below 0 is given player limit + # will be removed. + session_max_players_override: int | None = None + # Options here are 'ffa' (free-for-all), 'teams' and 'coop' (cooperative) # This value is ignored if you supply a playlist_code (see below). session_type: str = 'ffa' diff --git a/tools/batools/build.py b/tools/batools/build.py index 72caf9e6..69a94a63 100644 --- a/tools/batools/build.py +++ b/tools/batools/build.py @@ -63,6 +63,8 @@ PY_REQUIREMENTS = [ PyRequirement(pipname='pbxproj', minversion=[4, 0, 0]), PyRequirement(pipname='filelock', minversion=[3, 13, 1]), PyRequirement(pipname='python-daemon', minversion=[3, 0, 1]), + PyRequirement(pipname='Sphinx', minversion=[7, 2, 6]), + PyRequirement(pipname='furo', minversion=[2024, 0o1, 29]), ] diff --git a/tools/batools/docs.py b/tools/batools/docs.py index 0c9c05e1..36e0216f 100755 --- a/tools/batools/docs.py +++ b/tools/batools/docs.py @@ -212,3 +212,87 @@ def _run_pdoc() -> None: duration = time.monotonic() - starttime print(f'{Clr.GRN}Generated pdoc documentation in {duration:.1f}s.{Clr.RST}') + + +def generate_sphinxdoc() -> None: + """Generate a set of pdoc documentation.""" + _run_sphinx() + + +def _run_sphinx( + project_name: str = 'ballistica', + project_author: str = 'Efroemling', + copyright_text: str = '2024, Efroemling', + generate_dummymodules_doc: bool = True, + generate_tools_doc: bool = True, +) -> None: + """Do the actual docs generation with sphinx.""" + # pylint: disable=too-many-locals + + import time + import shutil + + from batools.version import get_current_version + + version, buildnum = get_current_version() + + assets_dirs: dict = { + 'ba_data': 'src/assets/ba_data/python/', + 'dummy_modules': 'build/dummymodules/', + 'efro_tools': 'tools/', # for efro and bacommon package + } + + sphinx_src = 'src/assets/sphinx/' + template_dir = Path(sphinx_src + 'template/') + assert template_dir.is_dir() + build_dir = 'build/sphinx/' + os.makedirs(build_dir, exist_ok=True) + sphinx_apidoc_out = '.cache/sphinx/' # might want to use .cache dir + os.makedirs(sphinx_apidoc_out, exist_ok=True) + + os.environ['BALLISTICA_ROOT'] = os.getcwd() # used in sphinx conf.py + os.environ['SPHINX_SETTINGS'] = str( + { + 'project_name': project_name, + 'project_author': project_author, + 'copyright': copyright_text, + 'version': version, + 'buildnum': buildnum, + } + ) + os.environ['BA_RUNNING_WITH_DUMMY_MODULES'] = '1' + + shutil.copytree(template_dir, sphinx_apidoc_out, dirs_exist_ok=True) + + starttime = time.monotonic() + apidoc_cmd = [ + 'sphinx-apidoc', + '-f', # Force overwriting of any existing generated files. + '-H', + project_name, + '-A', + project_author, + '-V', + str(version), # version + '-R', + str(buildnum), # release + # '--templatedir', template_dir, + '-o', + sphinx_apidoc_out, + ] + if generate_dummymodules_doc: + subprocess.run( + apidoc_cmd + [assets_dirs['dummy_modules']] + ['--private'], + check=True, + ) + if generate_tools_doc: + subprocess.run(apidoc_cmd + [assets_dirs['efro_tools']], check=True) + subprocess.run(apidoc_cmd + [assets_dirs['ba_data']], check=True) + + subprocess.run(['make', 'html'], check=True, cwd=sphinx_apidoc_out) + shutil.copytree( + sphinx_apidoc_out + '_build/html/', build_dir, dirs_exist_ok=True + ) + # shutil.rmtree(temp_modules_dir) + duration = time.monotonic() - starttime + print(f'Generated sphinx documentation in {duration:.1f}s.') diff --git a/tools/batools/dummymodule.py b/tools/batools/dummymodule.py index 5a29b870..0b45a489 100755 --- a/tools/batools/dummymodule.py +++ b/tools/batools/dummymodule.py @@ -815,18 +815,24 @@ class Generator: typing_imports = ( 'TYPE_CHECKING, overload, Sequence, TypeVar' if self.mname == '_babase' - else 'TYPE_CHECKING, overload, TypeVar' - if self.mname == '_bascenev1' - else 'TYPE_CHECKING, TypeVar' + else ( + 'TYPE_CHECKING, overload, TypeVar' + if self.mname == '_bascenev1' + else 'TYPE_CHECKING, TypeVar' + ) ) typing_imports_tc = ( 'Any, Callable' if self.mname == '_babase' - else 'Any, Callable, Literal, Sequence' - if self.mname == '_bascenev1' - else 'Any, Callable, Literal, Sequence' - if self.mname == '_bauiv1' - else 'Any, Callable' + else ( + 'Any, Callable, Literal, Sequence' + if self.mname == '_bascenev1' + else ( + 'Any, Callable, Literal, Sequence' + if self.mname == '_bauiv1' + else 'Any, Callable' + ) + ) ) tc_import_lines_extra = '' if self.mname == '_babase': @@ -842,9 +848,7 @@ class Generator: '' if self.mname == '_babase' # else 'from babase._mgen.enums import TimeFormat, TimeType\n\n' - else '' - if self.mname == '_bascenev1' - else '' + else '' if self.mname == '_bascenev1' else '' ) out = ( get_public_license('python') + '\n' diff --git a/tools/batools/pcommands.py b/tools/batools/pcommands.py index 8fa3e42e..eb2be2cb 100644 --- a/tools/batools/pcommands.py +++ b/tools/batools/pcommands.py @@ -562,6 +562,13 @@ def gen_docs_pdoc() -> None: batools.docs.generate_pdoc(projroot=str(pcommand.PROJROOT)) +def gen_docs_sphinx() -> None: + """Generate sphinx documentation.""" + import batools.docs + + batools.docs.generate_sphinxdoc() + + def list_pip_reqs() -> None: """List Python Pip packages needed for this project.""" from batools.build import get_pip_reqs diff --git a/tools/batools/spinoff/_context.py b/tools/batools/spinoff/_context.py index 7efa7dac..b0870822 100644 --- a/tools/batools/spinoff/_context.py +++ b/tools/batools/spinoff/_context.py @@ -1563,7 +1563,11 @@ class SpinoffContext: os.remove(delete_file_name) def _is_project_file(self, path: str) -> bool: - if path.startswith('tools/') or path.startswith('src/external'): + if ( + path.startswith('tools/') + or path.startswith('src/external') + or path.startswith('src/assets/sphinx') + ): return False bname = os.path.basename(path) return ( @@ -1953,9 +1957,9 @@ class SpinoffContext: else: dst_type = self._dst_entities[dst_path].entity_type if dst_type is not EntityType.SYMLINK: - self._src_error_entities[ - src_path - ] = f'expected symlink; found {dst_type}' + self._src_error_entities[src_path] = ( + f'expected symlink; found {dst_type}' + ) else: # Ok; looks like there's a symlink already there. self._dst_entities_claimed.add(dst_path) @@ -1997,9 +2001,9 @@ class SpinoffContext: else: dst_type = self._dst_entities[dst_path].entity_type if dst_type is not EntityType.FILE: - self._src_error_entities[ - src_path - ] = f'expected file; found {dst_type}' + self._src_error_entities[src_path] = ( + f'expected file; found {dst_type}' + ) else: dst_exists = os.path.isfile(dst_path_full) diff --git a/tools/batools/staging.py b/tools/batools/staging.py index 6b97fbba..5a14ea75 100755 --- a/tools/batools/staging.py +++ b/tools/batools/staging.py @@ -645,9 +645,11 @@ class AssetStager: 'ballisticakit_server.py', outfilename=os.path.join( self.serverdst, - 'ballisticakit_server.py' - if self.win_type is not None - else 'ballisticakit_server', + ( + 'ballisticakit_server.py' + if self.win_type is not None + else 'ballisticakit_server' + ), ), ) _stage_server_file( diff --git a/tools/efro/dataclassio/_inputter.py b/tools/efro/dataclassio/_inputter.py index 0e19cba3..b2e28ddb 100644 --- a/tools/efro/dataclassio/_inputter.py +++ b/tools/efro/dataclassio/_inputter.py @@ -534,42 +534,6 @@ class _Inputter: for i in value ) - def _datetime_from_input( - self, cls: type, fieldpath: str, value: Any, ioattrs: IOAttrs | None - ) -> Any: - # For firestore we expect a datetime object. - if self._codec is Codec.FIRESTORE: - # Don't compare exact type here, as firestore can give us - # a subclass with extended precision. - if not isinstance(value, datetime.datetime): - raise TypeError( - f'Invalid input value for "{fieldpath}" on' - f' "{cls.__name__}";' - f' expected a datetime, got a {type(value).__name__}' - ) - check_utc(value) - return value - - assert self._codec is Codec.JSON - - # We expect a list of 7 ints. - if type(value) is not list: - raise TypeError( - f'Invalid input value for "{fieldpath}" on "{cls.__name__}";' - f' expected a list, got a {type(value).__name__}' - ) - if len(value) != 7 or not all(isinstance(x, int) for x in value): - raise ValueError( - f'Invalid input value for "{fieldpath}" on "{cls.__name__}";' - f' expected a list of 7 ints, got {[type(v) for v in value]}.' - ) - out = datetime.datetime( # type: ignore - *value, tzinfo=datetime.timezone.utc - ) - if ioattrs is not None: - ioattrs.validate_datetime(out, fieldpath) - return out - def _tuple_from_input( self, cls: type, @@ -620,3 +584,39 @@ class _Inputter: assert len(out) == len(childanntypes) return tuple(out) + + def _datetime_from_input( + self, cls: type, fieldpath: str, value: Any, ioattrs: IOAttrs | None + ) -> Any: + # For firestore we expect a datetime object. + if self._codec is Codec.FIRESTORE: + # Don't compare exact type here, as firestore can give us + # a subclass with extended precision. + if not isinstance(value, datetime.datetime): + raise TypeError( + f'Invalid input value for "{fieldpath}" on' + f' "{cls.__name__}";' + f' expected a datetime, got a {type(value).__name__}' + ) + check_utc(value) + return value + + assert self._codec is Codec.JSON + + # We expect a list of 7 ints. + if type(value) is not list: + raise TypeError( + f'Invalid input value for "{fieldpath}" on "{cls.__name__}";' + f' expected a list, got a {type(value).__name__}' + ) + if len(value) != 7 or not all(isinstance(x, int) for x in value): + raise ValueError( + f'Invalid input value for "{fieldpath}" on "{cls.__name__}";' + f' expected a list of 7 ints, got {[type(v) for v in value]}.' + ) + out = datetime.datetime( # type: ignore + *value, tzinfo=datetime.timezone.utc + ) + if ioattrs is not None: + ioattrs.validate_datetime(out, fieldpath) + return out diff --git a/tools/efro/dataclassio/_outputter.py b/tools/efro/dataclassio/_outputter.py index 216b11d9..66089eb0 100644 --- a/tools/efro/dataclassio/_outputter.py +++ b/tools/efro/dataclassio/_outputter.py @@ -12,6 +12,7 @@ from enum import Enum import dataclasses import typing import types +import json import datetime from typing import TYPE_CHECKING, cast, Any @@ -330,19 +331,54 @@ class _Outputter: f' data type(s) not supported by the' f' specified codec ({self._codec.name}).' ) - return list(value) if self._create else None + # We output json-friendly values so this becomes a list. + # We need to sort the list so our output is + # deterministic and can be meaningfully compared with + # others, across processes, etc. + # + # Since we don't know what types we've got here, we + # guarantee sortability by dumping each value to a json + # string (itself with keys sorted) and using that as the + # value's sorting key. Not efficient but it works. A + # good reason to avoid set[Any] though. Perhaps we + # should just disallow it altogether. + return ( + sorted(value, key=lambda v: json.dumps(v, sort_keys=True)) + if self._create + else None + ) # We contain elements of some specified type. assert len(childanntypes) == 1 if self._create: - # Note: we output json-friendly values so this becomes - # a list. - return [ - self._process_value( - cls, fieldpath, childanntypes[0], x, ioattrs - ) - for x in value - ] + # We output json-friendly values so this becomes a list. + # We need to sort the list so our output is + # deterministic and can be meaningfully compared with + # others, across processes, etc. + # + # In this case we have a single concrete type, and for + # most incarnations of that (str, int, etc.) we can just + # sort our final output. For more complex cases, + # however, such as optional values or dataclasses, we + # need to convert everything to a json string (itself + # with keys sorted) and sort based on those strings. + # This is probably a good reason to avoid sets + # containing dataclasses or optional values. Perhaps we + # should just disallow those. + return sorted( + ( + self._process_value( + cls, fieldpath, childanntypes[0], x, ioattrs + ) + for x in value + ), + key=( + None + if childanntypes[0] in [str, int, float, bool] + else lambda v: json.dumps(v, sort_keys=True) + ), + ) + for x in value: self._process_value( cls, fieldpath, childanntypes[0], x, ioattrs diff --git a/tools/efro/debug.py b/tools/efro/debug.py index 1f9b8b90..8262a34c 100644 --- a/tools/efro/debug.py +++ b/tools/efro/debug.py @@ -14,12 +14,17 @@ from __future__ import annotations import gc import sys +import time import types +import weakref +import threading from typing import TYPE_CHECKING if TYPE_CHECKING: from typing import Any, TextIO + from logging import Logger + ABS_MAX_LEVEL = 10 # NOTE: In general we want this toolset to allow us to explore @@ -344,3 +349,170 @@ def _printrefs( expand_ids=expand_ids, file=file, ) + + +class DeadlockDumper: + """Dumps thread states if still around after timeout seconds. + + This uses low level Python functionality so should still fire + even in the case of deadlock. + """ + + # faulthandler has a single traceback-dump-later state, so only + # one of us can control it at a time. + lock = threading.Lock() + watch_in_progress = False + + def __init__(self, timeout: float) -> None: + import faulthandler + + cls = type(self) + + with cls.lock: + if cls.watch_in_progress: + print( + 'Existing DeadlockDumper found; new one will be a no-op.', + file=sys.stderr, + ) + self.active = False + return + + # Ok; no watch is in progress; we can be the active one. + cls.watch_in_progress = True + self.active = True + faulthandler.dump_traceback_later(timeout=timeout) + + def __del__(self) -> None: + import faulthandler + + cls = type(self) + + # If we made it to here, call off the dump. But only if we are + # the active dump. + if self.active: + faulthandler.cancel_dump_traceback_later() + cls.watch_in_progress = False + + +class DeadlockWatcher: + """Individual watcher for deadlock conditions. + + Use the enable_deadlock_watchers() to enable this system. + + Next, create these in contexts where they will be torn down after + some operation completes. If any is not torn down within the + timeout period, a traceback of all threads will be dumped. + + Note that the checker thread runs a cycle every ~5 seconds, so + something stuck needs to remain stuck for 5 seconds or so to be + caught for sure. + """ + + watchers_lock: threading.Lock | None = None + watchers: list[weakref.ref[DeadlockWatcher]] | None = None + + def __init__( + self, + timeout: float = 10.0, + logger: Logger | None = None, + logextra: dict | None = None, + ) -> None: + # pylint: disable=not-context-manager + cls = type(self) + if cls.watchers_lock is None or cls.watchers is None: + print( + 'DeadlockWatcher created without watchers enabled.', + file=sys.stderr, + ) + return + + # All we do is record when we were made and how long till we + # expire. + self.create_time = time.monotonic() + self.timeout = timeout + self.noted_expire = False + self.logger = logger + self.logextra = logextra + + with cls.watchers_lock: + cls.watchers.append(weakref.ref(self)) + + @classmethod + def enable_deadlock_watchers(cls) -> None: + """Spins up deadlock-watcher functionality. + + Must be explicitly called before any DeadlockWatchers are + created. + """ + assert cls.watchers_lock is None + cls.watchers_lock = threading.Lock() + assert cls.watchers is None + cls.watchers = [] + + threading.Thread( + target=cls._deadlock_watcher_thread_main, daemon=True + ).start() + + @classmethod + def _deadlock_watcher_thread_main(cls) -> None: + # pylint: disable=not-context-manager + # pylint: disable=not-an-iterable + assert cls.watchers_lock is not None and cls.watchers is not None + + # Spin in a loop checking our watchers periodically and dumping + # state if any have timed out. The trick here is that we don't + # explicitly dump state, but rather we set up a "dead man's + # switch" that does so after some amount of time if we don't + # explicitly cancel it. This way we'll hopefully get state dumps + # even for things like total GIL deadlocks. + while True: + + # Set a dead man's switch for this pass. + dumper = DeadlockDumper(timeout=5.171) + + # Sleep most of the way through it but give ourselves time + # to turn it off if we're still responsive. + time.sleep(4.129) + now = time.monotonic() + + found_fresh_expired = False + + # If any watcher is still alive but expired, sleep past the + # timeout to force the dumper to do its thing. + with cls.watchers_lock: + + for wref in cls.watchers: + w = wref() + if ( + w is not None + and now - w.create_time > w.timeout + and not w.noted_expire + ): + # If they supplied a logger, let them know they + # should check stderr for a dump. + if w.logger is not None: + w.logger.error( + 'DeadlockWatcher with time %.2f expired;' + ' check stderr for stack traces.', + w.timeout, + extra=w.logextra, + ) + found_fresh_expired = True + w.noted_expire = True + + # Important to clear this ref; otherwise we can keep + # a random watcher alive until our next time through. + w = None + + # Prune dead watchers and reset for the next pass. + cls.watchers = [w for w in cls.watchers if w() is not None] + + if found_fresh_expired: + # Push us over the dumper time limit which give us a + # lovely dump. Technically we could just do an immediate + # dump here instead, but that would give us two paths to + # maintain instead of this single one. + time.sleep(2.0) + + # Call off the dump if it hasn't happened yet. + del dumper diff --git a/tools/pcommand b/tools/pcommand index 5cd05df5..0a6eef2a 100755 --- a/tools/pcommand +++ b/tools/pcommand @@ -99,6 +99,7 @@ from batools.pcommands import ( get_modern_make, warm_start_asset_build, gen_docs_pdoc, + gen_docs_sphinx, list_pip_reqs, install_pip_reqs, checkenv,