mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-08 00:30:22 +08:00
Merge branch 'efroemling:master' into master
This commit is contained in:
commit
eac3418972
216
.efrocachemap
generated
216
.efrocachemap
generated
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ballisticakit-windows/Generic/BallisticaKit.ico": "be1b956dcd7f7a261b1afe5bce2a0336",
|
"ballisticakit-windows/Generic/BallisticaKit.ico": "6f33e74cb282f070871413f092983fcd",
|
||||||
"build/assets/ba_data/audio/achievement.ogg": "079a366ce183b25a63550ef7072af605",
|
"build/assets/ba_data/audio/achievement.ogg": "079a366ce183b25a63550ef7072af605",
|
||||||
"build/assets/ba_data/audio/actionHero1.ogg": "f0f986f268f036a5ac2f940e07f2f27e",
|
"build/assets/ba_data/audio/actionHero1.ogg": "f0f986f268f036a5ac2f940e07f2f27e",
|
||||||
"build/assets/ba_data/audio/actionHero2.ogg": "204a6735dc655f0975cf8308b585f2fd",
|
"build/assets/ba_data/audio/actionHero2.ogg": "204a6735dc655f0975cf8308b585f2fd",
|
||||||
@ -421,42 +421,42 @@
|
|||||||
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
|
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
|
||||||
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
|
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
|
||||||
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
|
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
|
||||||
"build/assets/ba_data/data/langdata.json": "992c5c5ce292132c4f011f39e0d13de8",
|
"build/assets/ba_data/data/langdata.json": "fae88cbb2a5b9c24096f2e43452114a2",
|
||||||
"build/assets/ba_data/data/languages/arabic.json": "d1f900ab5aa2433d402bd46ed1149cc7",
|
"build/assets/ba_data/data/languages/arabic.json": "0db32e21b6d5337ccca478381744aa88",
|
||||||
"build/assets/ba_data/data/languages/belarussian.json": "e151808b6b4f6dc159cf55ee62adad3c",
|
"build/assets/ba_data/data/languages/belarussian.json": "a112dfca3e188387516788bd8229c5b0",
|
||||||
"build/assets/ba_data/data/languages/chinese.json": "8d889accdd49334591209bdaf6eaf02f",
|
"build/assets/ba_data/data/languages/chinese.json": "ff9a595726f0aff42a39be576d0ff037",
|
||||||
"build/assets/ba_data/data/languages/chinesetraditional.json": "f858da49be0a5374157c627857751078",
|
"build/assets/ba_data/data/languages/chinesetraditional.json": "f858da49be0a5374157c627857751078",
|
||||||
"build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa",
|
"build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa",
|
||||||
"build/assets/ba_data/data/languages/czech.json": "93c5fe0d884d95435da6c675f64e30e0",
|
"build/assets/ba_data/data/languages/czech.json": "c9d518a324870066b987b8f412881dd3",
|
||||||
"build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e",
|
"build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e",
|
||||||
"build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e",
|
"build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e",
|
||||||
"build/assets/ba_data/data/languages/english.json": "b38d54aecf3ac47b8d8ca97d8bab3006",
|
"build/assets/ba_data/data/languages/english.json": "2434e127b6788e3128d3523fcb1b8994",
|
||||||
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
|
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
|
||||||
"build/assets/ba_data/data/languages/filipino.json": "347f38524816691170d266708fe25894",
|
"build/assets/ba_data/data/languages/filipino.json": "e750fb1a95e4c5611115f9ece9ecab53",
|
||||||
"build/assets/ba_data/data/languages/french.json": "d8527da977a563185de25ef02bacf826",
|
"build/assets/ba_data/data/languages/french.json": "163362f7b33866ef069cae62d0387551",
|
||||||
"build/assets/ba_data/data/languages/german.json": "549754d2a530d825200c6126be56df5c",
|
"build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad",
|
||||||
"build/assets/ba_data/data/languages/gibberish.json": "837423db378b3e7679683805826aa26e",
|
"build/assets/ba_data/data/languages/gibberish.json": "e24d391c9fd12f9afa92f7ff65a06d23",
|
||||||
"build/assets/ba_data/data/languages/greek.json": "a65d78f912e9a89f98de004405167a6a",
|
"build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3",
|
||||||
"build/assets/ba_data/data/languages/hindi.json": "88ee0cda537bab9ac827def5e236fe1a",
|
"build/assets/ba_data/data/languages/hindi.json": "8848f6b0caec0fcf9d85bc6e683809ec",
|
||||||
"build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e",
|
"build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e",
|
||||||
"build/assets/ba_data/data/languages/indonesian.json": "bff88ce57744a639810b93a1d1dd79f4",
|
"build/assets/ba_data/data/languages/indonesian.json": "408fb026e84c24a8dd7a43cb2b794541",
|
||||||
"build/assets/ba_data/data/languages/italian.json": "338e7a03dff47f4eefc0ca3a995cd4f4",
|
"build/assets/ba_data/data/languages/italian.json": "61c5308638bed44194f0ec24f19bf3cb",
|
||||||
"build/assets/ba_data/data/languages/korean.json": "ca1122a9ee551da3f75ae632012bd0e2",
|
"build/assets/ba_data/data/languages/korean.json": "03fd99d5e1155e81053fc028f69df982",
|
||||||
"build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38",
|
"build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38",
|
||||||
"build/assets/ba_data/data/languages/persian.json": "71cc5b33abda0f285b970b8cc4a014a8",
|
"build/assets/ba_data/data/languages/persian.json": "4c3394f6662bb6dcf55728cfe213d750",
|
||||||
"build/assets/ba_data/data/languages/polish.json": "e1a1a801851924748ad38fa68216439a",
|
"build/assets/ba_data/data/languages/polish.json": "3a90b2d9e2c59305580c96f8098fc839",
|
||||||
"build/assets/ba_data/data/languages/portuguese.json": "9fcd6b4da9e5d0dc0e337ab00b5debe2",
|
"build/assets/ba_data/data/languages/portuguese.json": "0274cb9a4b7d2bd49c8eb8120144a1bf",
|
||||||
"build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826",
|
"build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826",
|
||||||
"build/assets/ba_data/data/languages/russian.json": "910cf653497654a16d5c4f067d6def22",
|
"build/assets/ba_data/data/languages/russian.json": "9d0b40586301a82e532c4a250d5f6d58",
|
||||||
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
|
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
|
||||||
"build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef",
|
"build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef",
|
||||||
"build/assets/ba_data/data/languages/spanish.json": "0122b0b24aa111ab259af02bbae9b7b6",
|
"build/assets/ba_data/data/languages/spanish.json": "42f857c40dbd4b637e3866849489f7d1",
|
||||||
"build/assets/ba_data/data/languages/swedish.json": "77d671f10613291ebf9c71da66f18a18",
|
"build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac",
|
||||||
"build/assets/ba_data/data/languages/tamil.json": "b9d4b4e107456ea6420ee0f9d9d7a03e",
|
"build/assets/ba_data/data/languages/tamil.json": "b4de1a2851afe4869c82e9acd94cd89c",
|
||||||
"build/assets/ba_data/data/languages/thai.json": "33f63753c9af9a5b238d229a0bf23fbc",
|
"build/assets/ba_data/data/languages/thai.json": "77755219bbf5fb7eea0d6b226684f403",
|
||||||
"build/assets/ba_data/data/languages/turkish.json": "9d7e58c9062dc517c3779c255a9b3142",
|
"build/assets/ba_data/data/languages/turkish.json": "ab149ebbd57cf4daa3cf8f310d91519a",
|
||||||
"build/assets/ba_data/data/languages/ukrainian.json": "f72eb51abfbbb56e27866895d7e947d2",
|
"build/assets/ba_data/data/languages/ukrainian.json": "e5c861187c4c6db37d1a033f4ef3dd5a",
|
||||||
"build/assets/ba_data/data/languages/venetian.json": "88595b7ee696b4094d7874c3c4188852",
|
"build/assets/ba_data/data/languages/venetian.json": "a559a5608d2e0b4708f7a4dee42ff354",
|
||||||
"build/assets/ba_data/data/languages/vietnamese.json": "921cd1e50f60fe3e101f246e172750ba",
|
"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/big_g.json": "1dd301d490643088a435ce75df971054",
|
||||||
"build/assets/ba_data/data/maps/bridgit.json": "6aea74805f4880cc11237c5734a24422",
|
"build/assets/ba_data/data/maps/bridgit.json": "6aea74805f4880cc11237c5734a24422",
|
||||||
@ -946,11 +946,11 @@
|
|||||||
"build/assets/ba_data/meshes/zoeUpperArm.bob": "a8a881010ac1ee9ec5ca872d5c5e853a",
|
"build/assets/ba_data/meshes/zoeUpperArm.bob": "a8a881010ac1ee9ec5ca872d5c5e853a",
|
||||||
"build/assets/ba_data/meshes/zoeUpperLeg.bob": "95b2502f74c70f934927f67cd505c3ad",
|
"build/assets/ba_data/meshes/zoeUpperLeg.bob": "95b2502f74c70f934927f67cd505c3ad",
|
||||||
"build/assets/ba_data/python-site-packages/_yaml/__init__.py": "b09d1968d73a04d6cf20e4e79657a6e7",
|
"build/assets/ba_data/python-site-packages/_yaml/__init__.py": "b09d1968d73a04d6cf20e4e79657a6e7",
|
||||||
"build/assets/ba_data/python-site-packages/certifi/__init__.py": "6337efa17f5b457b793332df33904162",
|
"build/assets/ba_data/python-site-packages/certifi/__init__.py": "b1fb6436db400125ecbb288262d00f0f",
|
||||||
"build/assets/ba_data/python-site-packages/certifi/__main__.py": "ef02e73f8581609df189a9f61aca365b",
|
"build/assets/ba_data/python-site-packages/certifi/__main__.py": "ef02e73f8581609df189a9f61aca365b",
|
||||||
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "6ac29a6bccca11cd2ed7e16e27dfccec",
|
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "4422aed09ab445f7290df7d72a301a47",
|
||||||
"build/assets/ba_data/python-site-packages/certifi/core.py": "1b505388f1475fabd1b60031f985271c",
|
"build/assets/ba_data/python-site-packages/certifi/core.py": "1b505388f1475fabd1b60031f985271c",
|
||||||
"build/assets/ba_data/python-site-packages/typing_extensions.py": "084d93bb609d798a3930dfb5e25eba59",
|
"build/assets/ba_data/python-site-packages/typing_extensions.py": "2d974cad17a71505d86513d1322976a5",
|
||||||
"build/assets/ba_data/python-site-packages/yaml/__init__.py": "2b747e5772c203377222afc888ac6b71",
|
"build/assets/ba_data/python-site-packages/yaml/__init__.py": "2b747e5772c203377222afc888ac6b71",
|
||||||
"build/assets/ba_data/python-site-packages/yaml/composer.py": "cef871e1f5f99ba2a7c44941b70afb06",
|
"build/assets/ba_data/python-site-packages/yaml/composer.py": "cef871e1f5f99ba2a7c44941b70afb06",
|
||||||
"build/assets/ba_data/python-site-packages/yaml/constructor.py": "8a15e361e34b79491c81553bb3534062",
|
"build/assets/ba_data/python-site-packages/yaml/constructor.py": "8a15e361e34b79491c81553bb3534062",
|
||||||
@ -1444,6 +1444,10 @@
|
|||||||
"build/assets/ba_data/textures/discordLogo.ktx": "d56ab6389e2770e0601d87f99375d7a5",
|
"build/assets/ba_data/textures/discordLogo.ktx": "d56ab6389e2770e0601d87f99375d7a5",
|
||||||
"build/assets/ba_data/textures/discordLogo.pvr": "bd39785cf2cbf9bc41fdde8b86ab3310",
|
"build/assets/ba_data/textures/discordLogo.pvr": "bd39785cf2cbf9bc41fdde8b86ab3310",
|
||||||
"build/assets/ba_data/textures/discordLogo_preview.png": "90efd54d3abd371c0150a363f3f673e7",
|
"build/assets/ba_data/textures/discordLogo_preview.png": "90efd54d3abd371c0150a363f3f673e7",
|
||||||
|
"build/assets/ba_data/textures/discordServer.dds": "782f63ce8bcf0de2c338ee1fbfb5df2e",
|
||||||
|
"build/assets/ba_data/textures/discordServer.ktx": "09c969fd0a278b5c426344845ef07c43",
|
||||||
|
"build/assets/ba_data/textures/discordServer.pvr": "54216467f9527c3fc2d8c777811e97a7",
|
||||||
|
"build/assets/ba_data/textures/discordServer_preview.png": "99cf0a7f77b909e9079d423a687e399f",
|
||||||
"build/assets/ba_data/textures/doomShroomBGColor.dds": "628100f564789f57e22f2ce0dcf53b76",
|
"build/assets/ba_data/textures/doomShroomBGColor.dds": "628100f564789f57e22f2ce0dcf53b76",
|
||||||
"build/assets/ba_data/textures/doomShroomBGColor.ktx": "ffbb38af60ab59e6030b01cd129bfaf9",
|
"build/assets/ba_data/textures/doomShroomBGColor.ktx": "ffbb38af60ab59e6030b01cd129bfaf9",
|
||||||
"build/assets/ba_data/textures/doomShroomBGColor.pvr": "77d103392813e302cdaf631cef88ba36",
|
"build/assets/ba_data/textures/doomShroomBGColor.pvr": "77d103392813e302cdaf631cef88ba36",
|
||||||
@ -1524,9 +1528,9 @@
|
|||||||
"build/assets/ba_data/textures/fontBig.ktx": "94b56c2488d6c9ebabfbbb740eca07dd",
|
"build/assets/ba_data/textures/fontBig.ktx": "94b56c2488d6c9ebabfbbb740eca07dd",
|
||||||
"build/assets/ba_data/textures/fontBig.pvr": "dff3f6c04a8c7b0bb937001640b42c8d",
|
"build/assets/ba_data/textures/fontBig.pvr": "dff3f6c04a8c7b0bb937001640b42c8d",
|
||||||
"build/assets/ba_data/textures/fontBig_preview.png": "f8b15cb04f0deca7774def335a72f053",
|
"build/assets/ba_data/textures/fontBig_preview.png": "f8b15cb04f0deca7774def335a72f053",
|
||||||
"build/assets/ba_data/textures/fontExtras.dds": "7ab11df1b3a3daa651dfad34219b89f5",
|
"build/assets/ba_data/textures/fontExtras.dds": "0a5a39028853c443cd88bc2492cb6ad9",
|
||||||
"build/assets/ba_data/textures/fontExtras.ktx": "30c3c8ca2cdf1209ff177017bb10f0a8",
|
"build/assets/ba_data/textures/fontExtras.ktx": "5b14075ce3d1d29c6d5635602e2176d8",
|
||||||
"build/assets/ba_data/textures/fontExtras.pvr": "fd3b0bd902c30e4b7aa5fe00e1eec4be",
|
"build/assets/ba_data/textures/fontExtras.pvr": "8cc68ca85ba327c20c45bad73b000d8c",
|
||||||
"build/assets/ba_data/textures/fontExtras2.dds": "18063a12912dadc9528afd90d1cf2369",
|
"build/assets/ba_data/textures/fontExtras2.dds": "18063a12912dadc9528afd90d1cf2369",
|
||||||
"build/assets/ba_data/textures/fontExtras2.ktx": "36da7f6cfbfb8d32fb14371de0a8f660",
|
"build/assets/ba_data/textures/fontExtras2.ktx": "36da7f6cfbfb8d32fb14371de0a8f660",
|
||||||
"build/assets/ba_data/textures/fontExtras2.pvr": "7a4e8e64ac05313b1782fb5b958150d0",
|
"build/assets/ba_data/textures/fontExtras2.pvr": "7a4e8e64ac05313b1782fb5b958150d0",
|
||||||
@ -1539,7 +1543,7 @@
|
|||||||
"build/assets/ba_data/textures/fontExtras4.ktx": "6d872ac15e2e874c1252f63b4584722b",
|
"build/assets/ba_data/textures/fontExtras4.ktx": "6d872ac15e2e874c1252f63b4584722b",
|
||||||
"build/assets/ba_data/textures/fontExtras4.pvr": "6a0a0a1a8bbbc3ee9d6b8b914e7aa697",
|
"build/assets/ba_data/textures/fontExtras4.pvr": "6a0a0a1a8bbbc3ee9d6b8b914e7aa697",
|
||||||
"build/assets/ba_data/textures/fontExtras4_preview.png": "363e2647621917b3821c9068267d2516",
|
"build/assets/ba_data/textures/fontExtras4_preview.png": "363e2647621917b3821c9068267d2516",
|
||||||
"build/assets/ba_data/textures/fontExtras_preview.png": "9c9c58aff612e7b6386f3522c0b4f1f6",
|
"build/assets/ba_data/textures/fontExtras_preview.png": "b6503267cc15e9e2524f41fabd94e773",
|
||||||
"build/assets/ba_data/textures/fontSmall0.dds": "b30bfe5f9e436be7be8b5eae6e8490c3",
|
"build/assets/ba_data/textures/fontSmall0.dds": "b30bfe5f9e436be7be8b5eae6e8490c3",
|
||||||
"build/assets/ba_data/textures/fontSmall0.ktx": "7e6058f37e6c5a4ea628f35b5f92c227",
|
"build/assets/ba_data/textures/fontSmall0.ktx": "7e6058f37e6c5a4ea628f35b5f92c227",
|
||||||
"build/assets/ba_data/textures/fontSmall0.pvr": "c66e3d6aa1f7def83aaacd8a6c9185e5",
|
"build/assets/ba_data/textures/fontSmall0.pvr": "c66e3d6aa1f7def83aaacd8a6c9185e5",
|
||||||
@ -2586,21 +2590,21 @@
|
|||||||
"build/assets/pylib-android/_pyio.py": "a6e88d66fbca88b13213cdd2177390b8",
|
"build/assets/pylib-android/_pyio.py": "a6e88d66fbca88b13213cdd2177390b8",
|
||||||
"build/assets/pylib-android/_sitebuiltins.py": "8b5e3f6e73917962fa014ad2c4a55e61",
|
"build/assets/pylib-android/_sitebuiltins.py": "8b5e3f6e73917962fa014ad2c4a55e61",
|
||||||
"build/assets/pylib-android/_strptime.py": "ff699c3f7647db7621bb88c43cc282d3",
|
"build/assets/pylib-android/_strptime.py": "ff699c3f7647db7621bb88c43cc282d3",
|
||||||
"build/assets/pylib-android/_sysconfigdata__linux_aarch64-linux-android.py": "cb9a77b04173c8776365999b57186e36",
|
"build/assets/pylib-android/_sysconfigdata__linux_aarch64-linux-android.py": "b1a9ca985ff6a159aa5ef94abd287f46",
|
||||||
"build/assets/pylib-android/_sysconfigdata__linux_arm-linux-androideabi.py": "6d50596ec7f4858a0c6a5edefde21f7a",
|
"build/assets/pylib-android/_sysconfigdata__linux_arm-linux-androideabi.py": "21a5842f39c86fccaaa0a30e0e4ab347",
|
||||||
"build/assets/pylib-android/_sysconfigdata__linux_i686-linux-android.py": "bf9358a2243aa7884b8e80d85c969fa5",
|
"build/assets/pylib-android/_sysconfigdata__linux_i686-linux-android.py": "9349023049d7599da61456b3f9a9687b",
|
||||||
"build/assets/pylib-android/_sysconfigdata__linux_x86_64-linux-android.py": "45eee0efbc2441535b94a8ad5acf4d2e",
|
"build/assets/pylib-android/_sysconfigdata__linux_x86_64-linux-android.py": "4151fa62c11c32cddf538e5cc7647160",
|
||||||
"build/assets/pylib-android/_sysconfigdata_d_linux_aarch64-linux-android.py": "f8ff271cf6df0b5b4d46d9c548abb84e",
|
"build/assets/pylib-android/_sysconfigdata_d_linux_aarch64-linux-android.py": "d9f7f1d3f5b89b08150dfa00cf243901",
|
||||||
"build/assets/pylib-android/_sysconfigdata_d_linux_arm-linux-androideabi.py": "da171b290c06a34d6a5cfbb296c22c34",
|
"build/assets/pylib-android/_sysconfigdata_d_linux_arm-linux-androideabi.py": "f4b99d4501a1cf1eb20fbc8973fa0040",
|
||||||
"build/assets/pylib-android/_sysconfigdata_d_linux_i686-linux-android.py": "dde2516b5ac29412dfbebaa7b3de0d0d",
|
"build/assets/pylib-android/_sysconfigdata_d_linux_i686-linux-android.py": "454094da5fe52a969b53bb46d360da84",
|
||||||
"build/assets/pylib-android/_sysconfigdata_d_linux_x86_64-linux-android.py": "7df452144c6630afb96951487c1257a0",
|
"build/assets/pylib-android/_sysconfigdata_d_linux_x86_64-linux-android.py": "1e23f45f4243c1aacc83f23ad5852390",
|
||||||
"build/assets/pylib-android/_threading_local.py": "4a9688e3987d7d692db46feb9214945e",
|
"build/assets/pylib-android/_threading_local.py": "4a9688e3987d7d692db46feb9214945e",
|
||||||
"build/assets/pylib-android/_weakrefset.py": "e4fa8532ace46dfbc35149c41ea497f7",
|
"build/assets/pylib-android/_weakrefset.py": "e4fa8532ace46dfbc35149c41ea497f7",
|
||||||
"build/assets/pylib-android/abc.py": "a0daa1ed187eee8690c1e8438b97da90",
|
"build/assets/pylib-android/abc.py": "a0daa1ed187eee8690c1e8438b97da90",
|
||||||
"build/assets/pylib-android/aifc.py": "1b9134c72b1e542417bee5bf345a1d0a",
|
"build/assets/pylib-android/aifc.py": "1b9134c72b1e542417bee5bf345a1d0a",
|
||||||
"build/assets/pylib-android/antigravity.py": "6d56bedf73be574cb6d7117caf5d334c",
|
"build/assets/pylib-android/antigravity.py": "6d56bedf73be574cb6d7117caf5d334c",
|
||||||
"build/assets/pylib-android/argparse.py": "e22cac9b12c09592929d57eb982fc554",
|
"build/assets/pylib-android/argparse.py": "e22cac9b12c09592929d57eb982fc554",
|
||||||
"build/assets/pylib-android/ast.py": "3aaa1b0e56b21b28155707c54bc225a8",
|
"build/assets/pylib-android/ast.py": "f287ccaa1cd7cb0ea256e3984fd4ce4d",
|
||||||
"build/assets/pylib-android/asynchat.py": "2ef3a0ce322332fabbf8fad4e133c6a3",
|
"build/assets/pylib-android/asynchat.py": "2ef3a0ce322332fabbf8fad4e133c6a3",
|
||||||
"build/assets/pylib-android/asyncio/__init__.py": "edf0e79e2b8b85c08f09fd14668e4822",
|
"build/assets/pylib-android/asyncio/__init__.py": "edf0e79e2b8b85c08f09fd14668e4822",
|
||||||
"build/assets/pylib-android/asyncio/__main__.py": "8e391b47f448ad922dc2614dbd93011e",
|
"build/assets/pylib-android/asyncio/__main__.py": "8e391b47f448ad922dc2614dbd93011e",
|
||||||
@ -2624,10 +2628,10 @@
|
|||||||
"build/assets/pylib-android/asyncio/selector_events.py": "a108fbd3a49f967da245f39cebf7694e",
|
"build/assets/pylib-android/asyncio/selector_events.py": "a108fbd3a49f967da245f39cebf7694e",
|
||||||
"build/assets/pylib-android/asyncio/sslproto.py": "2ec1b21e523055147d94c8c634154aab",
|
"build/assets/pylib-android/asyncio/sslproto.py": "2ec1b21e523055147d94c8c634154aab",
|
||||||
"build/assets/pylib-android/asyncio/staggered.py": "f5056f0a56b73b477a9fa65e71145366",
|
"build/assets/pylib-android/asyncio/staggered.py": "f5056f0a56b73b477a9fa65e71145366",
|
||||||
"build/assets/pylib-android/asyncio/streams.py": "f00ddd2b2fd74554ae1d3088bd9d2bfd",
|
"build/assets/pylib-android/asyncio/streams.py": "8cc026c067fc9245568199ea659167df",
|
||||||
"build/assets/pylib-android/asyncio/subprocess.py": "edb8d98278300b6c99f36cd08643c743",
|
"build/assets/pylib-android/asyncio/subprocess.py": "46e8b0ba32b4ac7bb5f840c49c89c85a",
|
||||||
"build/assets/pylib-android/asyncio/taskgroups.py": "5162e5b1806d9b647383d34ba1b21b56",
|
"build/assets/pylib-android/asyncio/taskgroups.py": "5162e5b1806d9b647383d34ba1b21b56",
|
||||||
"build/assets/pylib-android/asyncio/tasks.py": "234550593cd4928e6ee2c9591b6928ca",
|
"build/assets/pylib-android/asyncio/tasks.py": "c1bc59c01792bac43b79b425bb61e10e",
|
||||||
"build/assets/pylib-android/asyncio/threads.py": "7bbf81d424901524510e07b5d20e4a50",
|
"build/assets/pylib-android/asyncio/threads.py": "7bbf81d424901524510e07b5d20e4a50",
|
||||||
"build/assets/pylib-android/asyncio/timeouts.py": "c7cb81c7ee938bc47ff75342befc872a",
|
"build/assets/pylib-android/asyncio/timeouts.py": "c7cb81c7ee938bc47ff75342befc872a",
|
||||||
"build/assets/pylib-android/asyncio/transports.py": "04598090d813bb363cea9bf714b97c3f",
|
"build/assets/pylib-android/asyncio/transports.py": "04598090d813bb363cea9bf714b97c3f",
|
||||||
@ -2641,13 +2645,13 @@
|
|||||||
"build/assets/pylib-android/bisect.py": "9b70437e327d5176da41192567ad0064",
|
"build/assets/pylib-android/bisect.py": "9b70437e327d5176da41192567ad0064",
|
||||||
"build/assets/pylib-android/bz2.py": "cd6a5f2491bc52afd8fc180097371473",
|
"build/assets/pylib-android/bz2.py": "cd6a5f2491bc52afd8fc180097371473",
|
||||||
"build/assets/pylib-android/cProfile.py": "9e9c07ac3b9e4195a62b74e4f2b9489f",
|
"build/assets/pylib-android/cProfile.py": "9e9c07ac3b9e4195a62b74e4f2b9489f",
|
||||||
"build/assets/pylib-android/calendar.py": "4ef3d6d85d44e36212e5d784051c80b6",
|
"build/assets/pylib-android/calendar.py": "18df862e8e3c3fcbe4ab8a0b0348e339",
|
||||||
"build/assets/pylib-android/cgi.py": "090c5cfc8b4b92a730beec975159bd2a",
|
"build/assets/pylib-android/cgi.py": "090c5cfc8b4b92a730beec975159bd2a",
|
||||||
"build/assets/pylib-android/cgitb.py": "2bcff1cec7f3a3a9c96de7a55ebb4ea3",
|
"build/assets/pylib-android/cgitb.py": "2bcff1cec7f3a3a9c96de7a55ebb4ea3",
|
||||||
"build/assets/pylib-android/chunk.py": "13d7633b1ff28f5aed4eb043c65c99c5",
|
"build/assets/pylib-android/chunk.py": "13d7633b1ff28f5aed4eb043c65c99c5",
|
||||||
"build/assets/pylib-android/cmd.py": "8befee2654b0954af7886e24e2e7871f",
|
"build/assets/pylib-android/cmd.py": "8befee2654b0954af7886e24e2e7871f",
|
||||||
"build/assets/pylib-android/code.py": "5d47099984013b933c96b02ef16981b8",
|
"build/assets/pylib-android/code.py": "5d47099984013b933c96b02ef16981b8",
|
||||||
"build/assets/pylib-android/codecs.py": "6fac5e2969e98ceaba92d3b8e42cb2ec",
|
"build/assets/pylib-android/codecs.py": "e11eabe4824899dea4b26a89a568a361",
|
||||||
"build/assets/pylib-android/codeop.py": "d375467fb29fccd43ab94d15a2e63085",
|
"build/assets/pylib-android/codeop.py": "d375467fb29fccd43ab94d15a2e63085",
|
||||||
"build/assets/pylib-android/collections/__init__.py": "dcffbb6ee2cadd0c05ad22f2ef41f89b",
|
"build/assets/pylib-android/collections/__init__.py": "dcffbb6ee2cadd0c05ad22f2ef41f89b",
|
||||||
"build/assets/pylib-android/collections/abc.py": "15f410d3821352033a90a04539c99060",
|
"build/assets/pylib-android/collections/abc.py": "15f410d3821352033a90a04539c99060",
|
||||||
@ -2656,7 +2660,7 @@
|
|||||||
"build/assets/pylib-android/concurrent/__init__.py": "aa990702e8f3a7af205efb5ae23a7c85",
|
"build/assets/pylib-android/concurrent/__init__.py": "aa990702e8f3a7af205efb5ae23a7c85",
|
||||||
"build/assets/pylib-android/concurrent/futures/__init__.py": "3e46fadb9de9c995c37dca4311641d6a",
|
"build/assets/pylib-android/concurrent/futures/__init__.py": "3e46fadb9de9c995c37dca4311641d6a",
|
||||||
"build/assets/pylib-android/concurrent/futures/_base.py": "a1cd37aea6fe0efff1bc00a39543609e",
|
"build/assets/pylib-android/concurrent/futures/_base.py": "a1cd37aea6fe0efff1bc00a39543609e",
|
||||||
"build/assets/pylib-android/concurrent/futures/process.py": "a44e8618e158f8f351dafcb566a02544",
|
"build/assets/pylib-android/concurrent/futures/process.py": "1d1bb7b14e3999b383ba8bd11aa8951c",
|
||||||
"build/assets/pylib-android/concurrent/futures/thread.py": "e63753b8201f1392dbebc84a15054a13",
|
"build/assets/pylib-android/concurrent/futures/thread.py": "e63753b8201f1392dbebc84a15054a13",
|
||||||
"build/assets/pylib-android/configparser.py": "914afd2b2cec90bbca0b94fd176b5176",
|
"build/assets/pylib-android/configparser.py": "914afd2b2cec90bbca0b94fd176b5176",
|
||||||
"build/assets/pylib-android/contextlib.py": "6f52eac914e438ef54407760def8305f",
|
"build/assets/pylib-android/contextlib.py": "6f52eac914e438ef54407760def8305f",
|
||||||
@ -2680,7 +2684,7 @@
|
|||||||
"build/assets/pylib-android/curses/panel.py": "8f36fdade9588f8a4362d2cc057a6eff",
|
"build/assets/pylib-android/curses/panel.py": "8f36fdade9588f8a4362d2cc057a6eff",
|
||||||
"build/assets/pylib-android/curses/textpad.py": "94aa9ebc47a6068d4461652346646dbb",
|
"build/assets/pylib-android/curses/textpad.py": "94aa9ebc47a6068d4461652346646dbb",
|
||||||
"build/assets/pylib-android/dataclasses.py": "febeea138bff21dbed88762be772514e",
|
"build/assets/pylib-android/dataclasses.py": "febeea138bff21dbed88762be772514e",
|
||||||
"build/assets/pylib-android/datetime.py": "5dcfd7f3b1a4db8214c1442164ac999c",
|
"build/assets/pylib-android/datetime.py": "521d6767afcfef887ac4c3719386b8fd",
|
||||||
"build/assets/pylib-android/decimal.py": "f57d255d45b5d1d7d8e13c41a283c3e4",
|
"build/assets/pylib-android/decimal.py": "f57d255d45b5d1d7d8e13c41a283c3e4",
|
||||||
"build/assets/pylib-android/difflib.py": "6b3c8fd541b2b8d0320727025cd25275",
|
"build/assets/pylib-android/difflib.py": "6b3c8fd541b2b8d0320727025cd25275",
|
||||||
"build/assets/pylib-android/dis.py": "cecdc0c02aa3d70a7f550e60ebc9b3ba",
|
"build/assets/pylib-android/dis.py": "cecdc0c02aa3d70a7f550e60ebc9b3ba",
|
||||||
@ -2836,7 +2840,7 @@
|
|||||||
"build/assets/pylib-android/encodings/utf_8_sig.py": "8f3542863ef311d8b970a37c0d66b0de",
|
"build/assets/pylib-android/encodings/utf_8_sig.py": "8f3542863ef311d8b970a37c0d66b0de",
|
||||||
"build/assets/pylib-android/encodings/uu_codec.py": "4ef8a65413574c017a96b97fc1638ba6",
|
"build/assets/pylib-android/encodings/uu_codec.py": "4ef8a65413574c017a96b97fc1638ba6",
|
||||||
"build/assets/pylib-android/encodings/zlib_codec.py": "1388fb103fdf395451bfc8a2d60933a9",
|
"build/assets/pylib-android/encodings/zlib_codec.py": "1388fb103fdf395451bfc8a2d60933a9",
|
||||||
"build/assets/pylib-android/enum.py": "73b214a43ceef88aff7098b83623ed09",
|
"build/assets/pylib-android/enum.py": "e2a5734675e418870d7b379b5dba1ed3",
|
||||||
"build/assets/pylib-android/filecmp.py": "7648fdc6d0fc8bae7429d5e4081cf353",
|
"build/assets/pylib-android/filecmp.py": "7648fdc6d0fc8bae7429d5e4081cf353",
|
||||||
"build/assets/pylib-android/fileinput.py": "c3def1041e6b12dd5f1906c9dbbd1101",
|
"build/assets/pylib-android/fileinput.py": "c3def1041e6b12dd5f1906c9dbbd1101",
|
||||||
"build/assets/pylib-android/fnmatch.py": "a1bc67633695d4defd4c0886428c5363",
|
"build/assets/pylib-android/fnmatch.py": "a1bc67633695d4defd4c0886428c5363",
|
||||||
@ -2916,7 +2920,7 @@
|
|||||||
"build/assets/pylib-android/optparse.py": "5f65f891612b68c71a2846da86254285",
|
"build/assets/pylib-android/optparse.py": "5f65f891612b68c71a2846da86254285",
|
||||||
"build/assets/pylib-android/os.py": "36f9692131ffb9ba4db510de31afc651",
|
"build/assets/pylib-android/os.py": "36f9692131ffb9ba4db510de31afc651",
|
||||||
"build/assets/pylib-android/pathlib.py": "095ec821fec243124d0a286b4de3848a",
|
"build/assets/pylib-android/pathlib.py": "095ec821fec243124d0a286b4de3848a",
|
||||||
"build/assets/pylib-android/pdb.py": "117b0d24ccb89edc5f183c94f6722f70",
|
"build/assets/pylib-android/pdb.py": "c44527d9e905ca3b1b45d3c158df730a",
|
||||||
"build/assets/pylib-android/pickle.py": "e6f9f53d29988454690ccde3279c7c38",
|
"build/assets/pylib-android/pickle.py": "e6f9f53d29988454690ccde3279c7c38",
|
||||||
"build/assets/pylib-android/pickletools.py": "85b30fba86d32dfc4a588300dedf5f01",
|
"build/assets/pylib-android/pickletools.py": "85b30fba86d32dfc4a588300dedf5f01",
|
||||||
"build/assets/pylib-android/pipes.py": "2dd796bdbb87982034234fec50d4526c",
|
"build/assets/pylib-android/pipes.py": "2dd796bdbb87982034234fec50d4526c",
|
||||||
@ -2945,10 +2949,10 @@
|
|||||||
"build/assets/pylib-android/runpy.py": "3a2dd98314791c7e36b6bd3585f6ad82",
|
"build/assets/pylib-android/runpy.py": "3a2dd98314791c7e36b6bd3585f6ad82",
|
||||||
"build/assets/pylib-android/sched.py": "f5579c8c711dd3e89da70ec9e1788c9c",
|
"build/assets/pylib-android/sched.py": "f5579c8c711dd3e89da70ec9e1788c9c",
|
||||||
"build/assets/pylib-android/secrets.py": "bbf9ed672044ef3ab4b83ca2aea1644e",
|
"build/assets/pylib-android/secrets.py": "bbf9ed672044ef3ab4b83ca2aea1644e",
|
||||||
"build/assets/pylib-android/selectors.py": "98e0d83849452cbc2cc1381555bd5024",
|
"build/assets/pylib-android/selectors.py": "3c94b3b678c473543cdc7f1d2b20a6f6",
|
||||||
"build/assets/pylib-android/shelve.py": "3e569c07c863ecbd7f35a6c382d1785a",
|
"build/assets/pylib-android/shelve.py": "3e569c07c863ecbd7f35a6c382d1785a",
|
||||||
"build/assets/pylib-android/shlex.py": "0873fac90a491702950816ead0e59dd0",
|
"build/assets/pylib-android/shlex.py": "0873fac90a491702950816ead0e59dd0",
|
||||||
"build/assets/pylib-android/shutil.py": "a5d0ee9f28244b42a06e682312d0e3fa",
|
"build/assets/pylib-android/shutil.py": "aa636d67785c2e92d34c7c5c81f9e8c5",
|
||||||
"build/assets/pylib-android/signal.py": "114ef47b1798fca6f56ac8a250974b3e",
|
"build/assets/pylib-android/signal.py": "114ef47b1798fca6f56ac8a250974b3e",
|
||||||
"build/assets/pylib-android/site.py": "2a99f7de2702aa8411d35acbb91fe926",
|
"build/assets/pylib-android/site.py": "2a99f7de2702aa8411d35acbb91fe926",
|
||||||
"build/assets/pylib-android/smtpd.py": "0602b6a39c4e37133303bee16c3e28a4",
|
"build/assets/pylib-android/smtpd.py": "0602b6a39c4e37133303bee16c3e28a4",
|
||||||
@ -2958,7 +2962,7 @@
|
|||||||
"build/assets/pylib-android/socketserver.py": "98e33643181a54765e6d0b9e01b03d53",
|
"build/assets/pylib-android/socketserver.py": "98e33643181a54765e6d0b9e01b03d53",
|
||||||
"build/assets/pylib-android/sqlite3/__init__.py": "8838d75ad0e465e25bb0c8dfeab7a9ab",
|
"build/assets/pylib-android/sqlite3/__init__.py": "8838d75ad0e465e25bb0c8dfeab7a9ab",
|
||||||
"build/assets/pylib-android/sqlite3/dbapi2.py": "c85f3ff9ddbd56683a8c801885dc5e53",
|
"build/assets/pylib-android/sqlite3/dbapi2.py": "c85f3ff9ddbd56683a8c801885dc5e53",
|
||||||
"build/assets/pylib-android/sqlite3/dump.py": "8364bd18be01acf7e56e168db98c0e6f",
|
"build/assets/pylib-android/sqlite3/dump.py": "8d2085ec40031d544694759608e53178",
|
||||||
"build/assets/pylib-android/sre_compile.py": "a1784e9ccbea7d9963cab75b536b40c8",
|
"build/assets/pylib-android/sre_compile.py": "a1784e9ccbea7d9963cab75b536b40c8",
|
||||||
"build/assets/pylib-android/sre_constants.py": "5c5be32a5334d9b0a848dad520746a63",
|
"build/assets/pylib-android/sre_constants.py": "5c5be32a5334d9b0a848dad520746a63",
|
||||||
"build/assets/pylib-android/sre_parse.py": "cca15b9ab31509e6642f9d2fd4fb9d91",
|
"build/assets/pylib-android/sre_parse.py": "cca15b9ab31509e6642f9d2fd4fb9d91",
|
||||||
@ -2978,8 +2982,8 @@
|
|||||||
"build/assets/pylib-android/tempfile.py": "436007fbe6821c864a53861bd73b4d43",
|
"build/assets/pylib-android/tempfile.py": "436007fbe6821c864a53861bd73b4d43",
|
||||||
"build/assets/pylib-android/textwrap.py": "3eb16a40553205dc96be5cb9039f3c8c",
|
"build/assets/pylib-android/textwrap.py": "3eb16a40553205dc96be5cb9039f3c8c",
|
||||||
"build/assets/pylib-android/this.py": "8b0a9a1fa0a45a37e6c656eca1922277",
|
"build/assets/pylib-android/this.py": "8b0a9a1fa0a45a37e6c656eca1922277",
|
||||||
"build/assets/pylib-android/threading.py": "dda98a9e1169adb496655300454ecc09",
|
"build/assets/pylib-android/threading.py": "3354bf0cad72286a0532b0754de78704",
|
||||||
"build/assets/pylib-android/timeit.py": "8dc6f4245abf1d44814745e22a2f78b1",
|
"build/assets/pylib-android/timeit.py": "c918c7dee7538ff6e5a92288f55b4327",
|
||||||
"build/assets/pylib-android/token.py": "d8ff4e6c8eb59896891d01148f481e27",
|
"build/assets/pylib-android/token.py": "d8ff4e6c8eb59896891d01148f481e27",
|
||||||
"build/assets/pylib-android/tokenize.py": "3056f048c07e6c5a6442a5ef4f38e54c",
|
"build/assets/pylib-android/tokenize.py": "3056f048c07e6c5a6442a5ef4f38e54c",
|
||||||
"build/assets/pylib-android/tomllib/__init__.py": "253ecf9dd67cb81a3e19911a4a39f930",
|
"build/assets/pylib-android/tomllib/__init__.py": "253ecf9dd67cb81a3e19911a4a39f930",
|
||||||
@ -2987,7 +2991,7 @@
|
|||||||
"build/assets/pylib-android/tomllib/_re.py": "0e509117e16c41c491615e06bb98861d",
|
"build/assets/pylib-android/tomllib/_re.py": "0e509117e16c41c491615e06bb98861d",
|
||||||
"build/assets/pylib-android/tomllib/_types.py": "07be9616d6f5e401fd31fbeea619fc97",
|
"build/assets/pylib-android/tomllib/_types.py": "07be9616d6f5e401fd31fbeea619fc97",
|
||||||
"build/assets/pylib-android/trace.py": "3d8698a2c3ec03dc0f394a2f48c2ffbc",
|
"build/assets/pylib-android/trace.py": "3d8698a2c3ec03dc0f394a2f48c2ffbc",
|
||||||
"build/assets/pylib-android/traceback.py": "91f67818e621e3b2f5bf583ed6863ef8",
|
"build/assets/pylib-android/traceback.py": "668bd36fc103a89554d2f9202a07f56d",
|
||||||
"build/assets/pylib-android/tracemalloc.py": "e4d10d2bee7773566e46797a939e5cbf",
|
"build/assets/pylib-android/tracemalloc.py": "e4d10d2bee7773566e46797a939e5cbf",
|
||||||
"build/assets/pylib-android/tty.py": "271c7d61005a0a3c2c0952efc60dcb6d",
|
"build/assets/pylib-android/tty.py": "271c7d61005a0a3c2c0952efc60dcb6d",
|
||||||
"build/assets/pylib-android/types.py": "78f8942c08dbfc9c582f1bb8d5206639",
|
"build/assets/pylib-android/types.py": "78f8942c08dbfc9c582f1bb8d5206639",
|
||||||
@ -4056,59 +4060,59 @@
|
|||||||
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
||||||
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
||||||
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
||||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "43a2b924e39a8ec1c1c4dc29c4dd82a1",
|
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "5f7e668a6a904ba8c0fe391654a8211b",
|
||||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "870c3973e3f84ca977496f79706ceab1",
|
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "77cd63dbc1760a3d1bb55753794701b0",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "49251d9bf7583a51e7e28cf6b62ff357",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9f674a5b767f798b350ef30d84968d44",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "23068b129ac54e4f24c96aa154f0bb4d",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "84546f0452561d3f6519d296a9e9b2ca",
|
||||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "045814b1c6e365ca5ac73883bbd9f22d",
|
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "3122dbce63fb248c9ebe66d545be8480",
|
||||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "52d8664a3ed40b0715fa5097005f58da",
|
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4004c01a3ea1a7b62544f08f14e76f9e",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "4f364467c2f636a83a04f4f2930b34ee",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "cd9b5b9ae925cef7417d2b86fd0f0489",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "9b2afa754ae00d687750b243ee977312",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "35c2b307e5d228b105315b8d022d31d2",
|
||||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "182c54fa13364049339aedfa67cbfcba",
|
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "90993c873a2d1ca7b593992e52b1865a",
|
||||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "341976d8d665a94bf20a685aace37be5",
|
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "46119cb9ff99629ca16471f51032bac7",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b60fe7cb522e9aa3969c7e92af06d14e",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "8cac6eff8eb4f9e453a669b6f239b8a5",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "e03943051877ae0105c7526b5094c67f",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "3e20c91bf8948354a0e167faa5c184e9",
|
||||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "bfc7e631e7319b0749912e40b4bdbe88",
|
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "52ff216e1b0394a07bf178b8eea8c269",
|
||||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "d30e8266191cfd80f108129086f83b87",
|
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "32d85cc58ade8e7a63dfb604ef175553",
|
||||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "bcf27351436cb58df186612b82be983b",
|
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "fdf3da5251bc0d3b8f4e5a5b2e0d4b94",
|
||||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "39f8ce569f1faed09bd4189e291a91bd",
|
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "c03afc18b7aa72ab065381be985f48ae",
|
||||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "71b1c542f48d5abae5fb790b521a156a",
|
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "67a58d483ac028f9fc59112b59463a99",
|
||||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "553f71787d119cb01046f247711424b5",
|
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "0800d71a41320664bacba49822e8b442",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "12cd08021ae0ed1ce4238c1adead61dc",
|
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9019d9b48cefa45a7a16bae6bd696896",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "b7e08e6b9f76def9b61e4839b2682497",
|
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "90eca6cc81b0a2c39fd1d41d0d029f04",
|
||||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "58946f3534363d88f713c54d3d643d6d",
|
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "db535f0ca1e01af825f75f204fbc8928",
|
||||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "be356d05ecccd68043258d87b1892805",
|
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "97d51afca996ae15b61fd9f409a00459",
|
||||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "58946f3534363d88f713c54d3d643d6d",
|
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "db535f0ca1e01af825f75f204fbc8928",
|
||||||
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "be356d05ecccd68043258d87b1892805",
|
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "97d51afca996ae15b61fd9f409a00459",
|
||||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "bf7d793d62416db7273590a796001cb6",
|
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "43794f4973b09588367261faf46b652a",
|
||||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "b309e0cc3ec04024712c4ca938efdb92",
|
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "9bc71c9874596dd708841d84dff69b55",
|
||||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "bf7d793d62416db7273590a796001cb6",
|
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "43794f4973b09588367261faf46b652a",
|
||||||
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "b309e0cc3ec04024712c4ca938efdb92",
|
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "9bc71c9874596dd708841d84dff69b55",
|
||||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "a86b09c31abf0b5ec934ef28c8bd9fa3",
|
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "87f6bf3ea1196d91cd6486785702a5b2",
|
||||||
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "87be7a2f6e83c495f99024bb68660e17",
|
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "60336f9d664825ca08236dda311276ca",
|
||||||
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "a86b09c31abf0b5ec934ef28c8bd9fa3",
|
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "87f6bf3ea1196d91cd6486785702a5b2",
|
||||||
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "87be7a2f6e83c495f99024bb68660e17",
|
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "60336f9d664825ca08236dda311276ca",
|
||||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "9fb5d3cb36dd53bd18c7ca831e7c73ee",
|
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "4399c87b58fbe58fa67096cfa878f86a",
|
||||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "88332859e6e9ee70848f5252e5ee6ce0",
|
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "452623f0495dd4375e5b5d9b80d643d5",
|
||||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "55b6db8700acfc573cc3db31c6b210f7",
|
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "ca49b32ed573feea11613d62cd89840c",
|
||||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "88332859e6e9ee70848f5252e5ee6ce0",
|
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "452623f0495dd4375e5b5d9b80d643d5",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "cf40ba3bce2391e82978b08785405a5e",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "ff81e6eeea861f59e71db628bc64918b",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "a8a74156e04932a2a5cc6d2d4b202acf",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "ba89e5949d1cdf2b857089feb901285c",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "a135f9210a1c3be6b5d5d8228c8f6184",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "5e063f8acc0e0e9f35f82480d7dbf143",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "e412e20e4a0ac33b9f83c7750cde7109",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "1f0d14fcc16dd0d4896d91c75e32be25",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "cfcae11dab1c6752f821f0816706fa47",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "251d3dd0bc9a6418eb1cb5176bb5509c",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "16daa37287a6d9d3404461da8565aadb",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "96c003edb87b3f506d1b15af461487c3",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "b3faf8b8925145f121b09e67d6114fb8",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "274ebd634f05b23653719ef973119cf5",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "ed7ec02978df94f92168c5990cb6c78c",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "796edace73f874ebf46054b2a1ff0ba1",
|
||||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
||||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
|
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
|
||||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "ba8ce3ca3858b4c2d20db68f99b788b2",
|
"src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f",
|
||||||
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "00f81f9bd92386ec12a6e60170678a98",
|
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "97efb93f4bfd8e8b09f2db24398e29fc",
|
||||||
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",
|
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",
|
||||||
"src/ballistica/core/mgen/pyembed/binding_core.inc": "9d0a3c9636138e35284923e0c8311c69",
|
"src/ballistica/core/mgen/pyembed/binding_core.inc": "9d0a3c9636138e35284923e0c8311c69",
|
||||||
"src/ballistica/core/mgen/pyembed/env.inc": "8be46e5818f360d10b7b0224a9e91d07",
|
"src/ballistica/core/mgen/pyembed/env.inc": "8be46e5818f360d10b7b0224a9e91d07",
|
||||||
"src/ballistica/core/mgen/python_modules_monolithic.h": "fb967ed1c7db0c77d8deb4f00a7103c5",
|
"src/ballistica/core/mgen/python_modules_monolithic.h": "fb967ed1c7db0c77d8deb4f00a7103c5",
|
||||||
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "d80f970053099b3044204bfe29ddefce",
|
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "c25b263f2a31fb5ebe057db07d144879",
|
||||||
"src/ballistica/template_fs/mgen/pyembed/binding_template_fs.inc": "44a45492db057bf7f7158c3b0fa11f0f",
|
"src/ballistica/template_fs/mgen/pyembed/binding_template_fs.inc": "44a45492db057bf7f7158c3b0fa11f0f",
|
||||||
"src/ballistica/ui_v1/mgen/pyembed/binding_ui_v1.inc": "8f4c2070174bdc2fbf735180394d7b3a"
|
"src/ballistica/ui_v1/mgen/pyembed/binding_ui_v1.inc": "f5f054050d2b2fcd3763a4833fb32269"
|
||||||
}
|
}
|
||||||
178
.github/workflows/cd.yml
vendored
Normal file
178
.github/workflows/cd.yml
vendored
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
name: CD
|
||||||
|
|
||||||
|
on:
|
||||||
|
# Run on pushes and pull-requests
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
make_linux_x86_64_gui_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-gui-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: linux_x86_64_gui_(debug)
|
||||||
|
path: build/prefab/full/linux_x86_64_gui
|
||||||
|
make_linux_x86_64_server_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-server-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: linux_x86_64_server_(debug)
|
||||||
|
path: build/prefab/full/linux_x86_64_server
|
||||||
|
make_linux_arm64_gui_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-linux-arm64-gui-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: linux_arm64_gui_(debug)
|
||||||
|
path: build/prefab/full/linux_arm64_gui
|
||||||
|
make_linux_arm64_server_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-linux-arm64-server-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: linux_arm64_server_(debug)
|
||||||
|
path: build/prefab/full/linux_arm64_server
|
||||||
|
make_mac_x86_64_gui_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-mac-x86-64-gui-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: mac_x86_64_gui_(debug)
|
||||||
|
path: build/prefab/full/mac_x86_64_gui
|
||||||
|
make_mac_x86_64_server_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-mac-x86-64-server-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: mac_x86_64_server_(debug)
|
||||||
|
path: build/prefab/full/mac_x86_64_server
|
||||||
|
make_mac_arm64_gui_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-mac-arm64-gui-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: mac_arm64_gui_(debug)
|
||||||
|
path: build/prefab/full/mac_arm64_gui
|
||||||
|
make_mac_arm64_server_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-mac-arm64-server-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: mac_arm64_server_(debug)
|
||||||
|
path: build/prefab/full/mac_arm64_server
|
||||||
|
make_windows_x86_gui_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-windows-x86-gui-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: windows_x86_gui_(debug)
|
||||||
|
path: build/prefab/full/windows_x86_gui
|
||||||
|
make_windows_x86_server_debug_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install pip requirements
|
||||||
|
run: tools/pcommand install_pip_reqs
|
||||||
|
- name: Make the build
|
||||||
|
run: make prefab-windows-x86-server-debug-build
|
||||||
|
- name: Upload the build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: windows_x86_server_(debug)
|
||||||
|
path: build/prefab/full/windows_x86_server
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -120,10 +120,10 @@ xcuserdata/
|
|||||||
/ballisticakit-android/BallisticaKit/src/main/res/mipmap-*/ic_launcher*.png
|
/ballisticakit-android/BallisticaKit/src/main/res/mipmap-*/ic_launcher*.png
|
||||||
/ballisticakit-android/BallisticaKit/src/cardboard/res/mipmap-*/ic_launcher*.png
|
/ballisticakit-android/BallisticaKit/src/cardboard/res/mipmap-*/ic_launcher*.png
|
||||||
BallisticaKit.ico
|
BallisticaKit.ico
|
||||||
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/Cursor macOS.appiconset/cursor_*.png
|
|
||||||
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/AppIcon iOS.appiconset/icon_*.png
|
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/AppIcon iOS.appiconset/icon_*.png
|
||||||
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/AppIcon macOS.appiconset/icon_*.png
|
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/AppIcon macOS.appiconset/icon_*.png
|
||||||
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/tvOS App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Layer*.imagestacklayer/Content.imageset/*.png
|
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/tvOS App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Layer*.imagestacklayer/Content.imageset/*.png
|
||||||
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/tvOS App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Layer*.imagestacklayer/Content.imageset/*.png
|
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/tvOS App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Layer*.imagestacklayer/Content.imageset/*.png
|
||||||
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/tvOS App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/*.png
|
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/tvOS App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/*.png
|
||||||
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/tvOS App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/*.png
|
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/tvOS App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/*.png
|
||||||
|
/ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/Cursor macOS.imageset/cursor_*.png
|
||||||
|
|||||||
3
.idea/ballisticakit.iml
generated
3
.idea/ballisticakit.iml
generated
@ -21,7 +21,6 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-android" />
|
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-android" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-cmake" />
|
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-cmake" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-ios.xcodeproj" />
|
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-ios.xcodeproj" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-mac.xcodeproj" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-windows" />
|
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-windows" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-windows-oculus" />
|
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-windows-oculus" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-xcode" />
|
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-xcode" />
|
||||||
@ -74,4 +73,4 @@
|
|||||||
<component name="PyDocumentationSettings">
|
<component name="PyDocumentationSettings">
|
||||||
<option name="analyzeDoctest" value="false" />
|
<option name="analyzeDoctest" value="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|||||||
4
.idea/misc.xml
generated
4
.idea/misc.xml
generated
@ -4,10 +4,10 @@
|
|||||||
<option name="cmdArguments" value="--line-length 80 --skip-string-normalization" />
|
<option name="cmdArguments" value="--line-length 80 --skip-string-normalization" />
|
||||||
<option name="enabledOnReformat" value="true" />
|
<option name="enabledOnReformat" value="true" />
|
||||||
<option name="pathToExecutable" value="/opt/homebrew/bin/black" />
|
<option name="pathToExecutable" value="/opt/homebrew/bin/black" />
|
||||||
<option name="sdkUUID" value="1b270adb-5261-4492-85e8-d79b3894255d" />
|
<option name="sdkName" value="Python 3.11" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
|
||||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||||
<option name="version" value="3" />
|
<option name="version" value="3" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
201
CHANGELOG.md
201
CHANGELOG.md
@ -1,19 +1,128 @@
|
|||||||
### 1.7.28 (build 21445, api 8, 2023-10-11)
|
### 1.7.33 (build 21743, api 8, 2023-12-21)
|
||||||
|
|
||||||
|
### 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!)
|
||||||
|
- Old messages are now displayed as soon as you press 'Unmute Chat' (Thanks vishal332008!)
|
||||||
|
- Added an 'Add to Favorites' entry to the party menu (Thanks vishal332008!)
|
||||||
|
- Now displays 'No Parties Added' in favorites tab if no favorites are present (Thanks vishal332008!)
|
||||||
|
- Now shows character icons in the profiles list window (Thanks vishal332008!)
|
||||||
|
- Added a Random button for names in the Player Profiles window (Thanks vishal332008!)
|
||||||
|
- Fixed a bug where no server is selected by default in the favorites tab (Thanks vishal332008!)
|
||||||
|
- Fixed a bug where no replay is selected by default in the watch tab (Thanks vishal332008!)
|
||||||
|
- Fixed a bug where no profile is selected by default in the profile tab (Thanks vishal332008!)
|
||||||
|
- Fixed a number of UI screens so that ugly window edges are no longer visible
|
||||||
|
in corners on modern ultra wide phone displays.
|
||||||
|
- Added a `player_rejoin_cooldown` server config option. This defaults to 10
|
||||||
|
seconds for servers but 0 for normal gui clients. This mechanism had been
|
||||||
|
introduced recently to combat multiplayer fast-rejoin exploits and was set to
|
||||||
|
10 seconds everywhere, but it could tend to be annoying for local single
|
||||||
|
player play, dev testing, etc. Hopefully this strikes a good balance now.
|
||||||
|
- Removed the player-rejoin-cooldown mechanism from the C++ layer since it was
|
||||||
|
redundant with the Python level one and didn't cover as many cases.
|
||||||
|
- Restored the behavior from before 1.7.28 where backgrounding the app would
|
||||||
|
bring up the main menu and pause the action. Now it is implemented more
|
||||||
|
cleanly however (an `on_app_active_changed()` call in the `AppMode` class).
|
||||||
|
This means that it also applies to other platforms when the app reaches the
|
||||||
|
'inactive' state; for instance when minimizing the window on the SDL build.
|
||||||
|
|
||||||
|
### 1.7.31 (build 21727, api 8, 2023-12-17)
|
||||||
|
- Added `bascenev1.get_connection_to_host_info_2()` which is an improved
|
||||||
|
type-safe version of `bascenev1.get_connection_to_host_info()`.
|
||||||
|
- There is now a link to the official Discord server in the About section
|
||||||
|
(thanks EraOSBeta!).
|
||||||
|
- Native stack traces now work on Android; woohoo! Should be very helpful for
|
||||||
|
debugging.
|
||||||
|
- Added the concept of 'ui-operations' in the native layer to hopefully clear
|
||||||
|
out the remaining double-window bugs. Basically, widgets used to schedule
|
||||||
|
their payload commands to a future cycle of the event loop, meaning it was
|
||||||
|
possible for commands that switched the main window to get scheduled twice
|
||||||
|
before the first one ran (due to 2 key presses, etc), which could lead to all
|
||||||
|
sorts of weirdness happening such as multiple windows popping up when one was
|
||||||
|
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
|
||||||
|
simplification on the Android layer, cleaning out years of cruft. This should
|
||||||
|
put things in a better more maintainable place, but there will probably be
|
||||||
|
some bugs to iron out, so please holler if you run into any.
|
||||||
|
- Minimum supported Android version has been bumped from 5.0 to 6.0. Some
|
||||||
|
upcoming tech such as ASTC textures will likely not be well supported on such
|
||||||
|
old devices, so I think it is better to leave them running an older version
|
||||||
|
that performs decently instead of a newer version that performs poorly. And
|
||||||
|
letting go of old Android versions lets us better support new ones.
|
||||||
|
- Android version now uses the 'Oboe' library as an audio back-end instead of
|
||||||
|
OpenSL. This should result in better behaving audio in general. Please holler
|
||||||
|
if you experience otherwise.
|
||||||
|
- Bundled Android Python has been bumped to version 3.11.6.
|
||||||
|
- Android app suspend behavior has been revamped. The app should stay running
|
||||||
|
more often and be quicker to respond when dialogs or other activities
|
||||||
|
temporarily pop up in front of it. This also allows it to continue playing
|
||||||
|
music over other activities such as Google Play Games
|
||||||
|
Achievements/Leaderboards screens. Please holler if you run into strange side
|
||||||
|
effects such as the app continuing to play audio when it should not be.
|
||||||
|
- Modernized the Android fullscreen setup code when running in Android 11 or
|
||||||
|
newer. The game should now use the whole screen area, including the area
|
||||||
|
around notches or camera cutouts. Please holler if you are seeing any problems
|
||||||
|
related to this.
|
||||||
|
- (build 21626) Fixed a bug where click/tap locations were incorrect on some
|
||||||
|
builds when tv-border was on (Thanks for the heads-up Loup(Dliwk's fan)!).
|
||||||
|
- (build 21631) Fixes an issue where '^^^^^^^^^^^^^' lines in stack traces could
|
||||||
|
get chopped into tiny bits each on their own line in the dev console.
|
||||||
|
- Hopefully finally fixed a longstanding issue where obscure cases such as
|
||||||
|
multiple key presses simultaneously could cause multiple main menu windows to
|
||||||
|
pop up. Please holler if you still see this problem happening anywhere. Also
|
||||||
|
added a few related safety checks and warnings to help ensure UI code is free
|
||||||
|
from such problems going forward. To make sure your custom UIs are behaving
|
||||||
|
well in this system, do the following two things: 1) any time you call
|
||||||
|
`set_main_menu_window()`, pass your existing main menu window root widget as
|
||||||
|
`from_window`. 2) In any call that can lead to you switching the main menu
|
||||||
|
window, check if your root widget is dead or transitioning out first and abort
|
||||||
|
if it is. See any window in `ui_v1_lib` for examples.
|
||||||
|
- (build 21691) Fixed a bug causing touches to not register in some cases on
|
||||||
|
newer Android devices. (Huge thanks to JESWIN A J for helping me track that
|
||||||
|
down!).
|
||||||
|
- Temporarily removed the pause-the-game-when-backgrounded behavior for locally
|
||||||
|
hosted games, mainly due to the code being hacky. Will try to restore this
|
||||||
|
functionality in a cleaner way soon.
|
||||||
|
|
||||||
|
### 1.7.29 (build 21619, api 8, 2023-11-21)
|
||||||
|
|
||||||
|
- Simply continued work on the big 1.7.28 update. I was able to finally start
|
||||||
|
updating the Mac App Store version of the game again (it had been stuck at
|
||||||
|
1.4!), and it turns out that Apple AppStore submissions require the version
|
||||||
|
number to increase each time and not just the build number, so we may start
|
||||||
|
seeing more minor version number bumps for that reason.
|
||||||
|
- Windows builds should now die with a clear error when the OpenGL version is
|
||||||
|
too old (OpenGL 3.0 or newer is required). Previously they could die with more
|
||||||
|
cryptic error messages such as "OpenGL function 'glActiveTexture2D' not
|
||||||
|
found".
|
||||||
|
|
||||||
|
### 1.7.28 (build 21599, api 8, 2023-11-16)
|
||||||
|
|
||||||
|
- Turning off ticket continues on all platforms. I'll be moving the game towards
|
||||||
|
a new monetization scheme mostly based on cosmetics and this has always felt a
|
||||||
|
bit ugly pay-to-win to me, so it's time for it to go. Note that the
|
||||||
|
functionality is still in there if anyone wants to support it in mods.
|
||||||
- Massively cleaned up code related to rendering and window systems (OpenGL,
|
- Massively cleaned up code related to rendering and window systems (OpenGL,
|
||||||
SDL, etc). This code had been growing into a nasty tangle for 15 years
|
SDL, etc). This code had been growing into a nasty tangle for 15 years
|
||||||
attempting to support various old/hacked versions of SDL, etc. I ripped out
|
attempting to support various old/hacked versions of SDL, etc. I ripped out
|
||||||
huge chunks of it and put back still-relevant pieces in a much more cleanly
|
huge chunks of it and put back still-relevant pieces in a much more cleanly
|
||||||
designed way. This should put us in a much better place for supporting various
|
designed way. This should put us in a much better place for supporting various
|
||||||
platforms and making graphical improvements going forward. See
|
platforms and making graphical improvements going forward.
|
||||||
`ballistica/base/app_adapter/app_adapter_sdl.cc` for an example of the now
|
`ballistica/base/app_adapter/app_adapter_sdl.cc` is an example of the now
|
||||||
nicely implemented system.
|
nicely implemented system.
|
||||||
- The engine now requires OpenGL 3.0 or newer on desktop and OpenGL ES 3.0 or
|
- The engine now requires OpenGL 3.0 or newer on desktop and OpenGL ES 3.0 or
|
||||||
newer on mobile. This means we're cutting off a few percent of old devices on
|
newer on mobile. This means we're cutting off a few percent of old devices on
|
||||||
Android that only support ES 2, but ES 3 has been out for 10 years now so I
|
Android that only support ES 2, but ES 3 has been out for 10 years now so I
|
||||||
feel it is time. As mentioned above, this allows massively cleaning up the
|
feel it is time. As mentioned above, this allows massively cleaning up the
|
||||||
graphics code which means we can start to improve it.
|
graphics code which means we can start to improve it. Ideally now the GL
|
||||||
- Removed gamma controls. These were only active on the old Mac version anyway
|
renderer can be abstracted a bit more which will make the process of writing
|
||||||
|
other renderers easier.
|
||||||
|
- Removed gamma controls. These were only active on the old Mac builds anyway
|
||||||
and are being removed from the upcoming SDL3, so if we want this sort of thing
|
and are being removed from the upcoming SDL3, so if we want this sort of thing
|
||||||
we should do it through shading in the renderer now.
|
we should do it through shading in the renderer now.
|
||||||
- Implemented both vsync and max-fps for the SDL build of the game. This means
|
- Implemented both vsync and max-fps for the SDL build of the game. This means
|
||||||
@ -129,7 +238,87 @@
|
|||||||
before. It also takes a `confirm` bool arg which allows it to be used to bring
|
before. It also takes a `confirm` bool arg which allows it to be used to bring
|
||||||
up a confirm dialog.
|
up a confirm dialog.
|
||||||
- Clicking on a window close button to quit no longer brings up a confirm dialog
|
- Clicking on a window close button to quit no longer brings up a confirm dialog
|
||||||
and instead quits immediately (though with a proper graceful shutdown).
|
and instead quits immediately (though with a proper graceful shutdown and a
|
||||||
|
lovely little fade).
|
||||||
|
- Camera shake is now supported in network games and replays. Somehow I didn't
|
||||||
|
notice that was missing for years. The downside is this requires a server to
|
||||||
|
be hosting protocol 35, which cuts off support for 1.4 clients. So for now I
|
||||||
|
am keeping the default at 33. Once there a fewer 1.4 clients around we can
|
||||||
|
consider changing this (if everything hasn't moved to SceneV2 by then).
|
||||||
|
- Added a server option to set the hosting protocol for servers who might want
|
||||||
|
to allow camera shake (or other minor features/fixes) that don't work in the
|
||||||
|
default protocol 33. See `protocol_version` in `config.yaml`. Just remember
|
||||||
|
that you will be cutting off support for older clients if you use 35.
|
||||||
|
- Fixed a bug with screen-messages animating off screen too fast when frame
|
||||||
|
rates are high.
|
||||||
|
- Added a proper graceful shutdown process for the audio server. This should
|
||||||
|
result in fewer ugly pops and warning messages when the app is quit.
|
||||||
|
- Tidied up some keyboard shortcuts to be more platform-appropriate. For
|
||||||
|
example, toggling fullscreen on Windows is now Alt+Enter or F11.
|
||||||
|
- Fancy rebuilt Mac build should now automatically sync its frame rate to the
|
||||||
|
display its running on (using CVDisplayLinks, not VSync).
|
||||||
|
- Mac build is now relying solely on Apple's Game Controller Framework, which
|
||||||
|
seems pretty awesome these days. It should support most stuff SDL does and
|
||||||
|
with less configuring involved. Please holler if you come across something
|
||||||
|
that doesn't work.
|
||||||
|
- Mac build is also now using the Game Controller Framework to handle keyboard
|
||||||
|
events. This should better handle things like modifier keys and also will
|
||||||
|
allow us to use that exact same code on the iPad/iPhone version.
|
||||||
|
- OS key repeat events are no longer passed through the engine. This means that
|
||||||
|
any time we want repeating behavior, such as holding an arrow key to move
|
||||||
|
through UI elements, we will need to wire it up ourselves. We already do this
|
||||||
|
for things like game controllers however, so this is more consistent in a way.
|
||||||
|
- Dev console no longer claims key events unless the Python tab is showing and
|
||||||
|
there is a hardware keyboard attached. This allows showing dev console tabs
|
||||||
|
above gameplay without interfering with it.
|
||||||
|
- Added clipboard paste support to the dev console python terminal.
|
||||||
|
- Added various text editing functionality to the dev console python terminal
|
||||||
|
(cursor movement, deleting chars and words, etc.)
|
||||||
|
- Internal on-screen-keyboard now has a cancel button (thanks vishal332008!)
|
||||||
|
- Public servers list now shows 'No servers found' if there are no servers to
|
||||||
|
show instead of just remaining mysteriously blank (thanks vishal332008!)
|
||||||
|
- Players are now prevented from rejoining a session for 10 seconds after they
|
||||||
|
leave to prevent game exploits. Note this is different than the existing
|
||||||
|
system that prevents joining a *party* for 10 seconds; this covers people
|
||||||
|
who never leave the party (Thanks EraOSBeta!).
|
||||||
|
- Fixes an issue where servers could be crashed by flooding them with join
|
||||||
|
requests (Thanks for the heads-up Era!).
|
||||||
|
- The engine will now ignore empty device config dicts and fall back to
|
||||||
|
defaults; these could theoretically happen if device config code fails
|
||||||
|
somewhere and it previously would leave the device mysteriously inoperable.
|
||||||
|
- The game will now show <unset> for controls with no bindings in the in-game
|
||||||
|
guide and controller/keyboard config screens.
|
||||||
|
- Fixed a crash that could occur if SDL couldn't find a name for connected
|
||||||
|
joystick.
|
||||||
|
- Simplified the app's handling of broken config files. Previously it would do
|
||||||
|
various complex things such as offering to edit the broken config on desktop
|
||||||
|
builds, avoiding overwriting broken configs, and automatically loading
|
||||||
|
previous configs. Now, if it finds a broken config, it will simply back it up
|
||||||
|
to a .broken file, log an error message, and then start up normally with a
|
||||||
|
default config. This way, things are more consistent across platforms, and
|
||||||
|
technical users can still fix and restore their old configs. Note that the app
|
||||||
|
still also writes .prev configs for extra security, though it no longer uses
|
||||||
|
them for anything itself.
|
||||||
|
- Converted more internal engine time values from milliseconds to microseconds,
|
||||||
|
including things like the internal EventLoop timeline. Please holler if you
|
||||||
|
notice anything running 1000x too fast or slow. In general my strategy going
|
||||||
|
forward is to use microseconds for exact internal time values but to mostly
|
||||||
|
expose float seconds to the user, especially on the Python layer. There were
|
||||||
|
starting to be a few cases were integer milliseconds was not enough precision
|
||||||
|
for internal values. For instance, if we run with unclamped framerates and hit
|
||||||
|
several hundred FPS, milliseconds per frame would drop to 0 which caused some
|
||||||
|
problems. Note that scenev1 will be remaining on milliseconds internally for
|
||||||
|
compatibility reasons. Scenev2 should move to microseconds though.
|
||||||
|
- The V2 account id for the signed in account is now available at
|
||||||
|
`ba*.app.plus.accounts.primary.accountid` (alongside some other existing
|
||||||
|
account info).
|
||||||
|
- (build 21585) Fixed an issue where some navigation key presses were getting
|
||||||
|
incorrectly absorbed by text widgets. (Thanks for the heads-up Temp!)
|
||||||
|
- (build 21585) Fixed an issue where texture quality changes would not take
|
||||||
|
effect until next launch.
|
||||||
|
- 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)
|
### 1.7.27 (build 21282, api 8, 2023-08-30)
|
||||||
|
|
||||||
|
|||||||
@ -41,8 +41,12 @@
|
|||||||
- Modder
|
- Modder
|
||||||
|
|
||||||
### Era0S
|
### Era0S
|
||||||
|
- Community Suggestions Implementer
|
||||||
- Bug Fixer
|
- Bug Fixer
|
||||||
- Modder
|
- Modder
|
||||||
|
|
||||||
### VinniTR
|
### VinniTR
|
||||||
- Fixes
|
- Fixes
|
||||||
|
|
||||||
|
### Rikko
|
||||||
|
- Created the original "reject_recently_left_players" plugin
|
||||||
|
|||||||
9
Makefile
9
Makefile
@ -779,13 +779,12 @@ check-full: py_check_prereqs
|
|||||||
|
|
||||||
# Same as 'check' plus optional/slow extra checks.
|
# Same as 'check' plus optional/slow extra checks.
|
||||||
check2: py_check_prereqs
|
check2: py_check_prereqs
|
||||||
@$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy pycharm
|
@$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy
|
||||||
@$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
|
@$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
|
||||||
|
|
||||||
# Same as check2 but no caching (all files are checked).
|
# Same as check2 but no caching (all files are checked).
|
||||||
check2-full: py_check_prereqs
|
check2-full: py_check_prereqs
|
||||||
@$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full \
|
@$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full
|
||||||
pycharm-full
|
|
||||||
@$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
|
@$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
|
||||||
|
|
||||||
# Run Cpplint checks on all C/C++ code.
|
# Run Cpplint checks on all C/C++ code.
|
||||||
@ -924,14 +923,14 @@ preflight-full:
|
|||||||
preflight2:
|
preflight2:
|
||||||
@$(MAKE) format
|
@$(MAKE) format
|
||||||
@$(MAKE) update
|
@$(MAKE) update
|
||||||
@$(MAKE) -j$(CPUS) cpplint pylint mypy pycharm test
|
@$(MAKE) -j$(CPUS) cpplint pylint mypy test
|
||||||
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
|
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
|
||||||
|
|
||||||
# Same as 'preflight2' but without caching (all files visited).
|
# Same as 'preflight2' but without caching (all files visited).
|
||||||
preflight2-full:
|
preflight2-full:
|
||||||
@$(MAKE) format-full
|
@$(MAKE) format-full
|
||||||
@$(MAKE) update
|
@$(MAKE) update
|
||||||
@$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full pycharm-full test-full
|
@$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full test-full
|
||||||
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
|
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
|
||||||
|
|
||||||
# Tell make which of these targets don't represent files.
|
# Tell make which of these targets don't represent files.
|
||||||
|
|||||||
@ -6,7 +6,7 @@ height="50" alt="logo">
|
|||||||
|
|
||||||
***-ica***: collection of things relating to a specific theme.
|
***-ica***: collection of things relating to a specific theme.
|
||||||
|
|
||||||
[](https://github.com/efroemling/ballistica/actions/workflows/ci.yml)
|
[](https://github.com/efroemling/ballistica/actions/workflows/ci.yml) [](https://github.com/efroemling/ballistica/actions/workflows/cd.yml)
|
||||||
|
|
||||||
The Ballistica project is the foundation for
|
The Ballistica project is the foundation for
|
||||||
[BombSquad](https://www.froemling.net/apps/bombsquad) and potentially other
|
[BombSquad](https://www.froemling.net/apps/bombsquad) and potentially other
|
||||||
@ -52,7 +52,7 @@ want to keep that spirit alive as the Ballistica project moves forward. Whether
|
|||||||
this means making it easier to share mods, organize tournaments, join up with
|
this means making it easier to share mods, organize tournaments, join up with
|
||||||
friends, teach each other some Python, or whatever else. Life is short; let's
|
friends, teach each other some Python, or whatever else. Life is short; let's
|
||||||
play some games. Or make them. Maybe both.
|
play some games. Or make them. Maybe both.
|
||||||
|
|
||||||
### Frequently Asked Questions
|
### Frequently Asked Questions
|
||||||
|
|
||||||
* **Q: What's with this name? Is it BombSquad or Ballistica?**
|
* **Q: What's with this name? Is it BombSquad or Ballistica?**
|
||||||
@ -86,4 +86,4 @@ Playstation / My Toaster??**
|
|||||||
for more details or the [Ballistica
|
for more details or the [Ballistica
|
||||||
Downloads](https://ballistica.net/downloads) page for early test builds on
|
Downloads](https://ballistica.net/downloads) page for early test builds on
|
||||||
some platforms.
|
some platforms.
|
||||||
|
|
||||||
|
|||||||
1
ballisticakit-cmake/.idea/misc.xml
generated
1
ballisticakit-cmake/.idea/misc.xml
generated
@ -14,7 +14,6 @@
|
|||||||
<file path="$PROJECT_DIR$/../ballisticakit-android" />
|
<file path="$PROJECT_DIR$/../ballisticakit-android" />
|
||||||
<file path="$PROJECT_DIR$/.idea" />
|
<file path="$PROJECT_DIR$/.idea" />
|
||||||
<file path="$PROJECT_DIR$/../ballisticakit-ios.xcodeproj" />
|
<file path="$PROJECT_DIR$/../ballisticakit-ios.xcodeproj" />
|
||||||
<file path="$PROJECT_DIR$/../ballisticakit-mac.xcodeproj" />
|
|
||||||
<file path="$PROJECT_DIR$/../ballisticakit-windows" />
|
<file path="$PROJECT_DIR$/../ballisticakit-windows" />
|
||||||
<file path="$PROJECT_DIR$/../ballisticakit-xcode" />
|
<file path="$PROJECT_DIR$/../ballisticakit-xcode" />
|
||||||
<file path="$PROJECT_DIR$/../build" />
|
<file path="$PROJECT_DIR$/../build" />
|
||||||
|
|||||||
@ -353,9 +353,15 @@ set(BALLISTICA_SOURCES
|
|||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/camera.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/camera.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.cc
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/frame_def.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_client_context.cc
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_client_context.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_settings.cc
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/graphics_settings.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.cc
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/net_graph.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/support/render_command_buffer.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/render_command_buffer.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/screen_messages.cc
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/graphics/support/screen_messages.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/text/font_page_map_data.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/text/font_page_map_data.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/text/text_graphics.cc
|
${BA_SRC_ROOT}/ballistica/base/graphics/text/text_graphics.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/graphics/text/text_graphics.h
|
${BA_SRC_ROOT}/ballistica/base/graphics/text/text_graphics.h
|
||||||
@ -432,16 +438,19 @@ set(BALLISTICA_SOURCES
|
|||||||
${BA_SRC_ROOT}/ballistica/base/support/app_config.cc
|
${BA_SRC_ROOT}/ballistica/base/support/app_config.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/app_config.h
|
${BA_SRC_ROOT}/ballistica/base/support/app_config.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/app_timer.h
|
${BA_SRC_ROOT}/ballistica/base/support/app_timer.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/support/base_build_switches.cc
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/support/base_build_switches.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/classic_soft.h
|
${BA_SRC_ROOT}/ballistica/base/support/classic_soft.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/context.cc
|
${BA_SRC_ROOT}/ballistica/base/support/context.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/context.h
|
${BA_SRC_ROOT}/ballistica/base/support/context.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/support/display_timer.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/huffman.cc
|
${BA_SRC_ROOT}/ballistica/base/support/huffman.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/huffman.h
|
${BA_SRC_ROOT}/ballistica/base/support/huffman.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/plus_soft.h
|
${BA_SRC_ROOT}/ballistica/base/support/plus_soft.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/support/repeater.cc
|
||||||
|
${BA_SRC_ROOT}/ballistica/base/support/repeater.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/stdio_console.cc
|
${BA_SRC_ROOT}/ballistica/base/support/stdio_console.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/stdio_console.h
|
${BA_SRC_ROOT}/ballistica/base/support/stdio_console.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/stress_test.cc
|
|
||||||
${BA_SRC_ROOT}/ballistica/base/support/stress_test.h
|
|
||||||
${BA_SRC_ROOT}/ballistica/base/ui/dev_console.cc
|
${BA_SRC_ROOT}/ballistica/base/ui/dev_console.cc
|
||||||
${BA_SRC_ROOT}/ballistica/base/ui/dev_console.h
|
${BA_SRC_ROOT}/ballistica/base/ui/dev_console.h
|
||||||
${BA_SRC_ROOT}/ballistica/base/ui/ui.cc
|
${BA_SRC_ROOT}/ballistica/base/ui/ui.cc
|
||||||
@ -454,6 +463,8 @@ set(BALLISTICA_SOURCES
|
|||||||
${BA_SRC_ROOT}/ballistica/classic/python/classic_python.h
|
${BA_SRC_ROOT}/ballistica/classic/python/classic_python.h
|
||||||
${BA_SRC_ROOT}/ballistica/classic/python/methods/python_methods_classic.cc
|
${BA_SRC_ROOT}/ballistica/classic/python/methods/python_methods_classic.cc
|
||||||
${BA_SRC_ROOT}/ballistica/classic/python/methods/python_methods_classic.h
|
${BA_SRC_ROOT}/ballistica/classic/python/methods/python_methods_classic.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/classic/support/stress_test.cc
|
||||||
|
${BA_SRC_ROOT}/ballistica/classic/support/stress_test.h
|
||||||
${BA_SRC_ROOT}/ballistica/classic/support/v1_account.cc
|
${BA_SRC_ROOT}/ballistica/classic/support/v1_account.cc
|
||||||
${BA_SRC_ROOT}/ballistica/classic/support/v1_account.h
|
${BA_SRC_ROOT}/ballistica/classic/support/v1_account.h
|
||||||
${BA_SRC_ROOT}/ballistica/core/core.cc
|
${BA_SRC_ROOT}/ballistica/core/core.cc
|
||||||
@ -686,8 +697,10 @@ set(BALLISTICA_SOURCES
|
|||||||
${BA_SRC_ROOT}/ballistica/shared/generic/json.cc
|
${BA_SRC_ROOT}/ballistica/shared/generic/json.cc
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/json.h
|
${BA_SRC_ROOT}/ballistica/shared/generic/json.h
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/lambda_runnable.h
|
${BA_SRC_ROOT}/ballistica/shared/generic/lambda_runnable.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/shared/generic/native_stack_trace.h
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/runnable.cc
|
${BA_SRC_ROOT}/ballistica/shared/generic/runnable.cc
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/runnable.h
|
${BA_SRC_ROOT}/ballistica/shared/generic/runnable.h
|
||||||
|
${BA_SRC_ROOT}/ballistica/shared/generic/snapshot.h
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.cc
|
${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.cc
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.h
|
${BA_SRC_ROOT}/ballistica/shared/generic/timer_list.h
|
||||||
${BA_SRC_ROOT}/ballistica/shared/generic/utf8.cc
|
${BA_SRC_ROOT}/ballistica/shared/generic/utf8.cc
|
||||||
|
|||||||
@ -345,9 +345,15 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\camera.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\camera.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\frame_def.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\frame_def.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_settings.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_settings.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\screen_messages.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\screen_messages.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\text\text_graphics.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\text\text_graphics.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\text\text_graphics.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\text\text_graphics.h" />
|
||||||
@ -424,16 +430,19 @@
|
|||||||
<ClCompile Include="..\..\src\ballistica\base\support\app_config.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\support\app_config.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\app_config.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\app_config.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\support\base_build_switches.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\base_build_switches.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\context.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\support\context.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\context.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\context.h" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\display_timer.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\huffman.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\support\huffman.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\huffman.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\huffman.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\plus_soft.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\plus_soft.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\support\repeater.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\repeater.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\stress_test.cc" />
|
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\stress_test.h" />
|
|
||||||
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\ui\dev_console.h" />
|
<ClInclude Include="..\..\src\ballistica\base\ui\dev_console.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\ui\ui.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\ui\ui.cc" />
|
||||||
@ -446,6 +455,8 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\classic\python\classic_python.h" />
|
<ClInclude Include="..\..\src\ballistica\classic\python\classic_python.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.cc" />
|
<ClCompile Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h" />
|
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\classic\support\stress_test.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\classic\support\stress_test.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc" />
|
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\classic\support\v1_account.h" />
|
<ClInclude Include="..\..\src\ballistica\classic\support\v1_account.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\core\core.cc" />
|
<ClCompile Include="..\..\src\ballistica\core\core.cc" />
|
||||||
@ -678,8 +689,10 @@
|
|||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\json.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\json.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\json.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\json.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\native_stack_trace.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\snapshot.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\timer_list.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\timer_list.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\utf8.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\utf8.cc" />
|
||||||
|
|||||||
@ -469,6 +469,18 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h">
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_settings.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_settings.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc">
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -478,6 +490,12 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h">
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\screen_messages.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\screen_messages.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h">
|
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h">
|
||||||
<Filter>ballistica\base\graphics\text</Filter>
|
<Filter>ballistica\base\graphics\text</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -706,6 +724,12 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\support\base_build_switches.cc">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\base_build_switches.h">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -715,6 +739,9 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\support\context.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\context.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\display_timer.h">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\huffman.cc">
|
<ClCompile Include="..\..\src\ballistica\base\support\huffman.cc">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -724,18 +751,18 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\support\plus_soft.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\plus_soft.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\support\repeater.cc">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\repeater.h">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc">
|
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\stress_test.cc">
|
|
||||||
<Filter>ballistica\base\support</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\stress_test.h">
|
|
||||||
<Filter>ballistica\base\support</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc">
|
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc">
|
||||||
<Filter>ballistica\base\ui</Filter>
|
<Filter>ballistica\base\ui</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -772,6 +799,12 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h">
|
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h">
|
||||||
<Filter>ballistica\classic\python\methods</Filter>
|
<Filter>ballistica\classic\python\methods</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\classic\support\stress_test.cc">
|
||||||
|
<Filter>ballistica\classic\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\classic\support\stress_test.h">
|
||||||
|
<Filter>ballistica\classic\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc">
|
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc">
|
||||||
<Filter>ballistica\classic\support</Filter>
|
<Filter>ballistica\classic\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1468,12 +1501,18 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h">
|
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\native_stack_trace.h">
|
||||||
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc">
|
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h">
|
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\snapshot.h">
|
||||||
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc">
|
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@ -340,9 +340,15 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\camera.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\camera.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\frame_def.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\frame_def.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_settings.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_settings.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\net_graph.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\screen_messages.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\screen_messages.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\text\text_graphics.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\graphics\text\text_graphics.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\text\text_graphics.h" />
|
<ClInclude Include="..\..\src\ballistica\base\graphics\text\text_graphics.h" />
|
||||||
@ -419,16 +425,19 @@
|
|||||||
<ClCompile Include="..\..\src\ballistica\base\support\app_config.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\support\app_config.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\app_config.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\app_config.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\support\base_build_switches.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\base_build_switches.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\context.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\support\context.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\context.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\context.h" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\display_timer.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\huffman.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\support\huffman.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\huffman.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\huffman.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\plus_soft.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\plus_soft.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\support\repeater.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\repeater.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h" />
|
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\stress_test.cc" />
|
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\stress_test.h" />
|
|
||||||
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\base\ui\dev_console.h" />
|
<ClInclude Include="..\..\src\ballistica\base\ui\dev_console.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\base\ui\ui.cc" />
|
<ClCompile Include="..\..\src\ballistica\base\ui\ui.cc" />
|
||||||
@ -441,6 +450,8 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\classic\python\classic_python.h" />
|
<ClInclude Include="..\..\src\ballistica\classic\python\classic_python.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.cc" />
|
<ClCompile Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h" />
|
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h" />
|
||||||
|
<ClCompile Include="..\..\src\ballistica\classic\support\stress_test.cc" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\classic\support\stress_test.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc" />
|
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\classic\support\v1_account.h" />
|
<ClInclude Include="..\..\src\ballistica\classic\support\v1_account.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\core\core.cc" />
|
<ClCompile Include="..\..\src\ballistica\core\core.cc" />
|
||||||
@ -673,8 +684,10 @@
|
|||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\json.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\json.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\json.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\json.h" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\native_stack_trace.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h" />
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\snapshot.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc" />
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\timer_list.h" />
|
<ClInclude Include="..\..\src\ballistica\shared\generic\timer_list.h" />
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\utf8.cc" />
|
<ClCompile Include="..\..\src\ballistica\shared\generic\utf8.cc" />
|
||||||
|
|||||||
@ -469,6 +469,18 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h">
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\frame_def.h">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_client_context.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\graphics_settings.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\graphics_settings.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc">
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\net_graph.cc">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -478,6 +490,12 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h">
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\render_command_buffer.h">
|
||||||
<Filter>ballistica\base\graphics\support</Filter>
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\graphics\support\screen_messages.cc">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\graphics\support\screen_messages.h">
|
||||||
|
<Filter>ballistica\base\graphics\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h">
|
<ClInclude Include="..\..\src\ballistica\base\graphics\text\font_page_map_data.h">
|
||||||
<Filter>ballistica\base\graphics\text</Filter>
|
<Filter>ballistica\base\graphics\text</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -706,6 +724,12 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\app_timer.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\support\base_build_switches.cc">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\base_build_switches.h">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\classic_soft.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -715,6 +739,9 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\support\context.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\context.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\display_timer.h">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\huffman.cc">
|
<ClCompile Include="..\..\src\ballistica\base\support\huffman.cc">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -724,18 +751,18 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\base\support\plus_soft.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\plus_soft.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\base\support\repeater.cc">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\base\support\repeater.h">
|
||||||
|
<Filter>ballistica\base\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc">
|
<ClCompile Include="..\..\src\ballistica\base\support\stdio_console.cc">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h">
|
<ClInclude Include="..\..\src\ballistica\base\support\stdio_console.h">
|
||||||
<Filter>ballistica\base\support</Filter>
|
<Filter>ballistica\base\support</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\base\support\stress_test.cc">
|
|
||||||
<Filter>ballistica\base\support</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClInclude Include="..\..\src\ballistica\base\support\stress_test.h">
|
|
||||||
<Filter>ballistica\base\support</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc">
|
<ClCompile Include="..\..\src\ballistica\base\ui\dev_console.cc">
|
||||||
<Filter>ballistica\base\ui</Filter>
|
<Filter>ballistica\base\ui</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -772,6 +799,12 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h">
|
<ClInclude Include="..\..\src\ballistica\classic\python\methods\python_methods_classic.h">
|
||||||
<Filter>ballistica\classic\python\methods</Filter>
|
<Filter>ballistica\classic\python\methods</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ballistica\classic\support\stress_test.cc">
|
||||||
|
<Filter>ballistica\classic\support</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\classic\support\stress_test.h">
|
||||||
|
<Filter>ballistica\classic\support</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc">
|
<ClCompile Include="..\..\src\ballistica\classic\support\v1_account.cc">
|
||||||
<Filter>ballistica\classic\support</Filter>
|
<Filter>ballistica\classic\support</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1468,12 +1501,18 @@
|
|||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h">
|
<ClInclude Include="..\..\src\ballistica\shared\generic\lambda_runnable.h">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\native_stack_trace.h">
|
||||||
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc">
|
<ClCompile Include="..\..\src\ballistica\shared\generic\runnable.cc">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h">
|
<ClInclude Include="..\..\src\ballistica\shared\generic\runnable.h">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ballistica\shared\generic\snapshot.h">
|
||||||
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc">
|
<ClCompile Include="..\..\src\ballistica\shared\generic\timer_list.cc">
|
||||||
<Filter>ballistica\shared\generic</Filter>
|
<Filter>ballistica\shared\generic</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@ -10,11 +10,11 @@
|
|||||||
"src/ballistica/base/graphics/texture/ktx.cc",
|
"src/ballistica/base/graphics/texture/ktx.cc",
|
||||||
"src/ballistica/core/platform/android/android_gl3.h",
|
"src/ballistica/core/platform/android/android_gl3.h",
|
||||||
"src/ballistica/base/platform/apple/app_delegate.h",
|
"src/ballistica/base/platform/apple/app_delegate.h",
|
||||||
"src/ballistica/base/platform/apple/scripting_bridge_music.h",
|
"src/ballistica/base/platform/apple/MacMusicApp.h",
|
||||||
|
"src/ballistica/base/platform/apple/MacMusicAppScriptingBridge.h",
|
||||||
"src/ballistica/core/platform/android/utf8/checked.h",
|
"src/ballistica/core/platform/android/utf8/checked.h",
|
||||||
"src/ballistica/core/platform/android/utf8/unchecked.h",
|
"src/ballistica/core/platform/android/utf8/unchecked.h",
|
||||||
"src/ballistica/core/platform/android/utf8/core.h",
|
"src/ballistica/core/platform/android/utf8/core.h",
|
||||||
"src/ballistica/base/platform/apple/sdl_main_mac.h",
|
|
||||||
"src/ballistica/base/platform/oculus/main_rift.cc",
|
"src/ballistica/base/platform/oculus/main_rift.cc",
|
||||||
"src/ballistica/core/platform/android/android_gl3.c"
|
"src/ballistica/core/platform/android/android_gl3.c"
|
||||||
],
|
],
|
||||||
|
|||||||
@ -53,47 +53,60 @@ ctx.src_omit_paths = {
|
|||||||
'src/assets/workspace',
|
'src/assets/workspace',
|
||||||
}
|
}
|
||||||
|
|
||||||
# Use this to 'carve out' directories or exact file paths which will be
|
# Use this to 'carve out' files or directories which will be git-managed
|
||||||
# git-managed on dst. By default, spinoff will consider dirs containing
|
# on dst.
|
||||||
# the files it syncs from src as 'spinoff-managed'; it will set them as
|
#
|
||||||
# git-ignored and will complain if any files appear in them that it does
|
# By default, spinoff will consider dirs containing the files it syncs
|
||||||
# not manage itself (to prevent accidentally doing work in such places).
|
# from src as 'spinoff-managed'; it will set them as git-ignored and
|
||||||
# Note that adding a dir to src_write_paths does not prevent files
|
# will complain if any files appear in them that it does not manage
|
||||||
# within it from being synced by spinoff; it just means that each of
|
# itself (to prevent accidentally doing work in such places). Note that
|
||||||
# those individual spinoff-managed files will have their own gitignore
|
# adding a dir to src_write_paths does not prevent files within it from
|
||||||
# entry since there is no longer one covering the whole dir. So to keep
|
# being synced by spinoff; it just means that each of those individual
|
||||||
# things tidy, carve out the minimal set of exact file/dir paths that
|
# spinoff-managed files will have their own gitignore entry since there
|
||||||
# you need.
|
# can't be a single one covering the whole dir. So to keep things tidy,
|
||||||
|
# carve out the minimal set of exact file/dir paths that you need.
|
||||||
ctx.src_write_paths = {
|
ctx.src_write_paths = {
|
||||||
'tools/spinoff',
|
'tools/spinoff',
|
||||||
'config/spinoffconfig.py',
|
'config/spinoffconfig.py',
|
||||||
}
|
}
|
||||||
|
|
||||||
# Normally spinoff errors if it finds any files in its managed dirs that
|
# Use this to 'carve out' files or directories under spinoff managed
|
||||||
# it did not put there. This is to prevent accidentally working in these
|
# dirs which will be completely ignored by spinoff (but *not* placed
|
||||||
# parts of a dst project; since these sections are git-ignored, git
|
# under git control).
|
||||||
# itself won't raise any warnings in such cases and it would be easy to
|
|
||||||
# accidentally lose work otherwise.
|
|
||||||
#
|
#
|
||||||
# This list can be used to suppress spinoff's errors for specific
|
# Normally spinoff will error if it finds any files under its managed
|
||||||
# locations. This is generally used to allow build output or other
|
# dirs that it did not put there. This is to prevent accidentally
|
||||||
# dynamically generated files to exist within spinoff-managed
|
# working in these parts of a dst project; since spinoff-controlled
|
||||||
# directories. It is possible to use src_write_paths for such purposes,
|
# stuff is git-ignored, git itself won't raise any warnings in such
|
||||||
# but this has the side-effect of greatly complicating the dst project's
|
# cases and it would be easy to accidentally blow away changes if
|
||||||
# gitignore list; selectively marking a few dirs as unchecked makes for
|
# spinoff didn't raise a stink.
|
||||||
# a cleaner setup. Just be careful to not set excessively broad regions
|
#
|
||||||
# as unchecked; you don't want to mask actual useful error messages.
|
# This list is used to suppress raising of said stink for specific
|
||||||
|
# locations. This allows build output or other dynamically generated
|
||||||
|
# files to exist under spinoff-managed directories. It is also possible
|
||||||
|
# to use src_write_paths for such carve-outs, but that can have the
|
||||||
|
# negative side-effect of greatly complicating the dst project's
|
||||||
|
# .gitignore file. Selectively marking a few specific files or dirs as
|
||||||
|
# unchecked instead can keep things tidier and more understandable.
|
||||||
|
#
|
||||||
|
# Note that files and paths marked as unchecked cannot be the
|
||||||
|
# destination for synced files, as that would be ambiguous (We can
|
||||||
|
# either sync the file ourself or expect someone else to write it, but
|
||||||
|
# not both).
|
||||||
ctx.src_unchecked_paths = {
|
ctx.src_unchecked_paths = {
|
||||||
'src/ballistica/mgen',
|
'src/ballistica/mgen',
|
||||||
'src/ballistica/*/mgen',
|
'src/ballistica/*/mgen',
|
||||||
'src/assets/ba_data/python/*/_mgen',
|
'src/assets/ba_data/python/*/_mgen',
|
||||||
'src/meta/*/mgen',
|
'src/meta/*/mgen',
|
||||||
'ballisticakit-cmake/.clang-format',
|
'ballisticakit-cmake/.clang-format',
|
||||||
'ballisticakit-android/BallisticaKit/src/cardboard/res',
|
|
||||||
'ballisticakit-windows/*/BallisticaKit.ico',
|
'ballisticakit-windows/*/BallisticaKit.ico',
|
||||||
'ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets',
|
'ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/*/*.png',
|
||||||
'ballisticakit-android/BallisticaKit/src/*/res',
|
'ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/*/*/*.png',
|
||||||
'ballisticakit-android/BallisticaKit/src/*/assets',
|
'ballisticakit-xcode/BallisticaKit Shared/Assets.xcassets/*/*/*/*/*.png',
|
||||||
|
'ballisticakit-xcode/BallisticaKit.xcodeproj/'
|
||||||
|
'project.xcworkspace/xcuserdata',
|
||||||
|
'ballisticakit-android/BallisticaKit/src/*/res/*/*.png',
|
||||||
|
'ballisticakit-android/BallisticaKit/src/*/assets/ballistica_files',
|
||||||
'ballisticakit-android/local.properties',
|
'ballisticakit-android/local.properties',
|
||||||
'ballisticakit-android/.gradle',
|
'ballisticakit-android/.gradle',
|
||||||
'ballisticakit-android/build',
|
'ballisticakit-android/build',
|
||||||
@ -139,7 +152,6 @@ ctx.filter_dirs = {
|
|||||||
'ballisticakit-cmake',
|
'ballisticakit-cmake',
|
||||||
'ballisticakit-xcode/BallisticaKit.xcodeproj',
|
'ballisticakit-xcode/BallisticaKit.xcodeproj',
|
||||||
'ballisticakit-ios.xcodeproj',
|
'ballisticakit-ios.xcodeproj',
|
||||||
'ballisticakit-mac.xcodeproj',
|
|
||||||
'config',
|
'config',
|
||||||
'src/assets/pdoc',
|
'src/assets/pdoc',
|
||||||
}
|
}
|
||||||
@ -182,6 +194,7 @@ ctx.filter_file_names = {
|
|||||||
'.projectile',
|
'.projectile',
|
||||||
'.editorconfig',
|
'.editorconfig',
|
||||||
'ci.yml',
|
'ci.yml',
|
||||||
|
'cd.yml',
|
||||||
'LICENSE',
|
'LICENSE',
|
||||||
'cloudtool',
|
'cloudtool',
|
||||||
'bacloud',
|
'bacloud',
|
||||||
@ -263,6 +276,7 @@ ctx.filter_file_extensions = {
|
|||||||
'.frag',
|
'.frag',
|
||||||
'.vert',
|
'.vert',
|
||||||
'.xcsettings',
|
'.xcsettings',
|
||||||
|
'.xcstrings',
|
||||||
'.filters',
|
'.filters',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1465,6 +1465,10 @@
|
|||||||
"ba_data/textures/discordLogo.ktx",
|
"ba_data/textures/discordLogo.ktx",
|
||||||
"ba_data/textures/discordLogo.pvr",
|
"ba_data/textures/discordLogo.pvr",
|
||||||
"ba_data/textures/discordLogo_preview.png",
|
"ba_data/textures/discordLogo_preview.png",
|
||||||
|
"ba_data/textures/discordServer.dds",
|
||||||
|
"ba_data/textures/discordServer.ktx",
|
||||||
|
"ba_data/textures/discordServer.pvr",
|
||||||
|
"ba_data/textures/discordServer_preview.png",
|
||||||
"ba_data/textures/doomShroomBGColor.dds",
|
"ba_data/textures/doomShroomBGColor.dds",
|
||||||
"ba_data/textures/doomShroomBGColor.ktx",
|
"ba_data/textures/doomShroomBGColor.ktx",
|
||||||
"ba_data/textures/doomShroomBGColor.pvr",
|
"ba_data/textures/doomShroomBGColor.pvr",
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
"ba_data/python/babase/__pycache__/_error.cpython-311.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_error.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_general.cpython-311.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_general.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_hooks.cpython-311.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_hooks.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_keyboard.cpython-311.opt-1.pyc",
|
|
||||||
"ba_data/python/babase/__pycache__/_language.cpython-311.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_language.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_login.cpython-311.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_login.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/babase/__pycache__/_math.cpython-311.opt-1.pyc",
|
"ba_data/python/babase/__pycache__/_math.cpython-311.opt-1.pyc",
|
||||||
@ -50,7 +49,6 @@
|
|||||||
"ba_data/python/babase/_error.py",
|
"ba_data/python/babase/_error.py",
|
||||||
"ba_data/python/babase/_general.py",
|
"ba_data/python/babase/_general.py",
|
||||||
"ba_data/python/babase/_hooks.py",
|
"ba_data/python/babase/_hooks.py",
|
||||||
"ba_data/python/babase/_keyboard.py",
|
|
||||||
"ba_data/python/babase/_language.py",
|
"ba_data/python/babase/_language.py",
|
||||||
"ba_data/python/babase/_login.py",
|
"ba_data/python/babase/_login.py",
|
||||||
"ba_data/python/babase/_math.py",
|
"ba_data/python/babase/_math.py",
|
||||||
@ -152,6 +150,7 @@
|
|||||||
"ba_data/python/bascenev1/__pycache__/_messages.cpython-311.opt-1.pyc",
|
"ba_data/python/bascenev1/__pycache__/_messages.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bascenev1/__pycache__/_multiteamsession.cpython-311.opt-1.pyc",
|
"ba_data/python/bascenev1/__pycache__/_multiteamsession.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bascenev1/__pycache__/_music.cpython-311.opt-1.pyc",
|
"ba_data/python/bascenev1/__pycache__/_music.cpython-311.opt-1.pyc",
|
||||||
|
"ba_data/python/bascenev1/__pycache__/_net.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bascenev1/__pycache__/_nodeactor.cpython-311.opt-1.pyc",
|
"ba_data/python/bascenev1/__pycache__/_nodeactor.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bascenev1/__pycache__/_player.cpython-311.opt-1.pyc",
|
"ba_data/python/bascenev1/__pycache__/_player.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bascenev1/__pycache__/_playlist.cpython-311.opt-1.pyc",
|
"ba_data/python/bascenev1/__pycache__/_playlist.cpython-311.opt-1.pyc",
|
||||||
@ -186,6 +185,7 @@
|
|||||||
"ba_data/python/bascenev1/_messages.py",
|
"ba_data/python/bascenev1/_messages.py",
|
||||||
"ba_data/python/bascenev1/_multiteamsession.py",
|
"ba_data/python/bascenev1/_multiteamsession.py",
|
||||||
"ba_data/python/bascenev1/_music.py",
|
"ba_data/python/bascenev1/_music.py",
|
||||||
|
"ba_data/python/bascenev1/_net.py",
|
||||||
"ba_data/python/bascenev1/_nodeactor.py",
|
"ba_data/python/bascenev1/_nodeactor.py",
|
||||||
"ba_data/python/bascenev1/_player.py",
|
"ba_data/python/bascenev1/_player.py",
|
||||||
"ba_data/python/bascenev1/_playlist.py",
|
"ba_data/python/bascenev1/_playlist.py",
|
||||||
@ -352,10 +352,12 @@
|
|||||||
"ba_data/python/bauiv1/__init__.py",
|
"ba_data/python/bauiv1/__init__.py",
|
||||||
"ba_data/python/bauiv1/__pycache__/__init__.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1/__pycache__/__init__.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1/__pycache__/_hooks.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1/__pycache__/_hooks.cpython-311.opt-1.pyc",
|
||||||
|
"ba_data/python/bauiv1/__pycache__/_keyboard.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1/__pycache__/_subsystem.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1/__pycache__/_subsystem.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1/__pycache__/_uitypes.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1/__pycache__/_uitypes.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1/__pycache__/onscreenkeyboard.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1/__pycache__/onscreenkeyboard.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1/_hooks.py",
|
"ba_data/python/bauiv1/_hooks.py",
|
||||||
|
"ba_data/python/bauiv1/_keyboard.py",
|
||||||
"ba_data/python/bauiv1/_subsystem.py",
|
"ba_data/python/bauiv1/_subsystem.py",
|
||||||
"ba_data/python/bauiv1/_uitypes.py",
|
"ba_data/python/bauiv1/_uitypes.py",
|
||||||
"ba_data/python/bauiv1/onscreenkeyboard.py",
|
"ba_data/python/bauiv1/onscreenkeyboard.py",
|
||||||
@ -366,11 +368,11 @@
|
|||||||
"ba_data/python/bauiv1lib/__pycache__/characterpicker.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/characterpicker.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1lib/__pycache__/colorpicker.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/colorpicker.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1lib/__pycache__/config.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/config.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1lib/__pycache__/configerror.cpython-311.opt-1.pyc",
|
|
||||||
"ba_data/python/bauiv1lib/__pycache__/confirm.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/confirm.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1lib/__pycache__/continues.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/continues.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1lib/__pycache__/creditslist.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/creditslist.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1lib/__pycache__/debug.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/debug.cpython-311.opt-1.pyc",
|
||||||
|
"ba_data/python/bauiv1lib/__pycache__/discord.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1lib/__pycache__/feedback.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/feedback.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1lib/__pycache__/fileselector.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/fileselector.cpython-311.opt-1.pyc",
|
||||||
"ba_data/python/bauiv1lib/__pycache__/getcurrency.cpython-311.opt-1.pyc",
|
"ba_data/python/bauiv1lib/__pycache__/getcurrency.cpython-311.opt-1.pyc",
|
||||||
@ -417,7 +419,6 @@
|
|||||||
"ba_data/python/bauiv1lib/characterpicker.py",
|
"ba_data/python/bauiv1lib/characterpicker.py",
|
||||||
"ba_data/python/bauiv1lib/colorpicker.py",
|
"ba_data/python/bauiv1lib/colorpicker.py",
|
||||||
"ba_data/python/bauiv1lib/config.py",
|
"ba_data/python/bauiv1lib/config.py",
|
||||||
"ba_data/python/bauiv1lib/configerror.py",
|
|
||||||
"ba_data/python/bauiv1lib/confirm.py",
|
"ba_data/python/bauiv1lib/confirm.py",
|
||||||
"ba_data/python/bauiv1lib/continues.py",
|
"ba_data/python/bauiv1lib/continues.py",
|
||||||
"ba_data/python/bauiv1lib/coop/__init__.py",
|
"ba_data/python/bauiv1lib/coop/__init__.py",
|
||||||
@ -432,6 +433,7 @@
|
|||||||
"ba_data/python/bauiv1lib/coop/tournamentbutton.py",
|
"ba_data/python/bauiv1lib/coop/tournamentbutton.py",
|
||||||
"ba_data/python/bauiv1lib/creditslist.py",
|
"ba_data/python/bauiv1lib/creditslist.py",
|
||||||
"ba_data/python/bauiv1lib/debug.py",
|
"ba_data/python/bauiv1lib/debug.py",
|
||||||
|
"ba_data/python/bauiv1lib/discord.py",
|
||||||
"ba_data/python/bauiv1lib/feedback.py",
|
"ba_data/python/bauiv1lib/feedback.py",
|
||||||
"ba_data/python/bauiv1lib/fileselector.py",
|
"ba_data/python/bauiv1lib/fileselector.py",
|
||||||
"ba_data/python/bauiv1lib/gather/__init__.py",
|
"ba_data/python/bauiv1lib/gather/__init__.py",
|
||||||
|
|||||||
@ -178,7 +178,6 @@ SCRIPT_TARGETS_PY_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/babase/_error.py \
|
$(BUILD_DIR)/ba_data/python/babase/_error.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_general.py \
|
$(BUILD_DIR)/ba_data/python/babase/_general.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_hooks.py \
|
$(BUILD_DIR)/ba_data/python/babase/_hooks.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_keyboard.py \
|
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_language.py \
|
$(BUILD_DIR)/ba_data/python/babase/_language.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_login.py \
|
$(BUILD_DIR)/ba_data/python/babase/_login.py \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/_math.py \
|
$(BUILD_DIR)/ba_data/python/babase/_math.py \
|
||||||
@ -237,6 +236,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/bascenev1/_messages.py \
|
$(BUILD_DIR)/ba_data/python/bascenev1/_messages.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/_multiteamsession.py \
|
$(BUILD_DIR)/ba_data/python/bascenev1/_multiteamsession.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/_music.py \
|
$(BUILD_DIR)/ba_data/python/bascenev1/_music.py \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bascenev1/_net.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/_nodeactor.py \
|
$(BUILD_DIR)/ba_data/python/bascenev1/_nodeactor.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/_player.py \
|
$(BUILD_DIR)/ba_data/python/bascenev1/_player.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/_playlist.py \
|
$(BUILD_DIR)/ba_data/python/bascenev1/_playlist.py \
|
||||||
@ -326,6 +326,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/batemplatefs/_subsystem.py \
|
$(BUILD_DIR)/ba_data/python/batemplatefs/_subsystem.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/__init__.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1/__init__.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/_hooks.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1/_hooks.py \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bauiv1/_keyboard.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/_subsystem.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1/_subsystem.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/_uitypes.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1/_uitypes.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/onscreenkeyboard.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1/onscreenkeyboard.py \
|
||||||
@ -341,7 +342,6 @@ SCRIPT_TARGETS_PY_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/characterpicker.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/characterpicker.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/colorpicker.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/colorpicker.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/config.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/config.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/configerror.py \
|
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/confirm.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/confirm.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/continues.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/continues.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/coop/__init__.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/coop/__init__.py \
|
||||||
@ -351,6 +351,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/coop/tournamentbutton.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/coop/tournamentbutton.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/creditslist.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/creditslist.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/debug.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/debug.py \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/discord.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/feedback.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/feedback.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/fileselector.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/fileselector.py \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/gather/__init__.py \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/gather/__init__.py \
|
||||||
@ -452,7 +453,6 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_error.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_error.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_general.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_general.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_hooks.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_hooks.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_keyboard.cpython-311.opt-1.pyc \
|
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_language.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_language.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_login.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_login.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_math.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_math.cpython-311.opt-1.pyc \
|
||||||
@ -511,6 +511,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_messages.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_messages.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_multiteamsession.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_multiteamsession.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_music.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_music.cpython-311.opt-1.pyc \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_net.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_nodeactor.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_nodeactor.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_player.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_player.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_playlist.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_playlist.cpython-311.opt-1.pyc \
|
||||||
@ -600,6 +601,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/batemplatefs/__pycache__/_subsystem.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/batemplatefs/__pycache__/_subsystem.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/__init__.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/__init__.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_hooks.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_hooks.cpython-311.opt-1.pyc \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_keyboard.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_subsystem.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_subsystem.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_uitypes.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_uitypes.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/onscreenkeyboard.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/onscreenkeyboard.cpython-311.opt-1.pyc \
|
||||||
@ -615,7 +617,6 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/characterpicker.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/characterpicker.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/colorpicker.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/colorpicker.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/config.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/config.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/configerror.cpython-311.opt-1.pyc \
|
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/confirm.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/confirm.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/continues.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/continues.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/coop/__pycache__/__init__.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/coop/__pycache__/__init__.cpython-311.opt-1.pyc \
|
||||||
@ -625,6 +626,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
|
|||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/coop/__pycache__/tournamentbutton.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/coop/__pycache__/tournamentbutton.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/creditslist.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/creditslist.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/debug.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/debug.cpython-311.opt-1.pyc \
|
||||||
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/discord.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/feedback.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/feedback.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/fileselector.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/__pycache__/fileselector.cpython-311.opt-1.pyc \
|
||||||
$(BUILD_DIR)/ba_data/python/bauiv1lib/gather/__pycache__/__init__.cpython-311.opt-1.pyc \
|
$(BUILD_DIR)/ba_data/python/bauiv1lib/gather/__pycache__/__init__.cpython-311.opt-1.pyc \
|
||||||
@ -5710,6 +5712,7 @@ TEX2D_DDS_TARGETS = \
|
|||||||
$(BUILD_DIR)/ba_data/textures/cyborgIcon.dds \
|
$(BUILD_DIR)/ba_data/textures/cyborgIcon.dds \
|
||||||
$(BUILD_DIR)/ba_data/textures/cyborgIconColorMask.dds \
|
$(BUILD_DIR)/ba_data/textures/cyborgIconColorMask.dds \
|
||||||
$(BUILD_DIR)/ba_data/textures/discordLogo.dds \
|
$(BUILD_DIR)/ba_data/textures/discordLogo.dds \
|
||||||
|
$(BUILD_DIR)/ba_data/textures/discordServer.dds \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomBGColor.dds \
|
$(BUILD_DIR)/ba_data/textures/doomShroomBGColor.dds \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomLevelColor.dds \
|
$(BUILD_DIR)/ba_data/textures/doomShroomLevelColor.dds \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomPreview.dds \
|
$(BUILD_DIR)/ba_data/textures/doomShroomPreview.dds \
|
||||||
@ -6113,6 +6116,7 @@ TEX2D_PVR_TARGETS = \
|
|||||||
$(BUILD_DIR)/ba_data/textures/cyborgIcon.pvr \
|
$(BUILD_DIR)/ba_data/textures/cyborgIcon.pvr \
|
||||||
$(BUILD_DIR)/ba_data/textures/cyborgIconColorMask.pvr \
|
$(BUILD_DIR)/ba_data/textures/cyborgIconColorMask.pvr \
|
||||||
$(BUILD_DIR)/ba_data/textures/discordLogo.pvr \
|
$(BUILD_DIR)/ba_data/textures/discordLogo.pvr \
|
||||||
|
$(BUILD_DIR)/ba_data/textures/discordServer.pvr \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomBGColor.pvr \
|
$(BUILD_DIR)/ba_data/textures/doomShroomBGColor.pvr \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomLevelColor.pvr \
|
$(BUILD_DIR)/ba_data/textures/doomShroomLevelColor.pvr \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomPreview.pvr \
|
$(BUILD_DIR)/ba_data/textures/doomShroomPreview.pvr \
|
||||||
@ -6516,6 +6520,7 @@ TEX2D_KTX_TARGETS = \
|
|||||||
$(BUILD_DIR)/ba_data/textures/cyborgIcon.ktx \
|
$(BUILD_DIR)/ba_data/textures/cyborgIcon.ktx \
|
||||||
$(BUILD_DIR)/ba_data/textures/cyborgIconColorMask.ktx \
|
$(BUILD_DIR)/ba_data/textures/cyborgIconColorMask.ktx \
|
||||||
$(BUILD_DIR)/ba_data/textures/discordLogo.ktx \
|
$(BUILD_DIR)/ba_data/textures/discordLogo.ktx \
|
||||||
|
$(BUILD_DIR)/ba_data/textures/discordServer.ktx \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomBGColor.ktx \
|
$(BUILD_DIR)/ba_data/textures/doomShroomBGColor.ktx \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomLevelColor.ktx \
|
$(BUILD_DIR)/ba_data/textures/doomShroomLevelColor.ktx \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomPreview.ktx \
|
$(BUILD_DIR)/ba_data/textures/doomShroomPreview.ktx \
|
||||||
@ -6919,6 +6924,7 @@ TEX2D_PREVIEW_PNG_TARGETS = \
|
|||||||
$(BUILD_DIR)/ba_data/textures/cyborgIconColorMask_preview.png \
|
$(BUILD_DIR)/ba_data/textures/cyborgIconColorMask_preview.png \
|
||||||
$(BUILD_DIR)/ba_data/textures/cyborgIcon_preview.png \
|
$(BUILD_DIR)/ba_data/textures/cyborgIcon_preview.png \
|
||||||
$(BUILD_DIR)/ba_data/textures/discordLogo_preview.png \
|
$(BUILD_DIR)/ba_data/textures/discordLogo_preview.png \
|
||||||
|
$(BUILD_DIR)/ba_data/textures/discordServer_preview.png \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomBGColor_preview.png \
|
$(BUILD_DIR)/ba_data/textures/doomShroomBGColor_preview.png \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomLevelColor_preview.png \
|
$(BUILD_DIR)/ba_data/textures/doomShroomLevelColor_preview.png \
|
||||||
$(BUILD_DIR)/ba_data/textures/doomShroomPreview_preview.png \
|
$(BUILD_DIR)/ba_data/textures/doomShroomPreview_preview.png \
|
||||||
|
|||||||
@ -27,7 +27,10 @@ from _babase import (
|
|||||||
apptime,
|
apptime,
|
||||||
apptimer,
|
apptimer,
|
||||||
AppTimer,
|
AppTimer,
|
||||||
can_toggle_fullscreen,
|
fullscreen_control_available,
|
||||||
|
fullscreen_control_get,
|
||||||
|
fullscreen_control_key_shortcut,
|
||||||
|
fullscreen_control_set,
|
||||||
charstr,
|
charstr,
|
||||||
clipboard_get_text,
|
clipboard_get_text,
|
||||||
clipboard_has_text,
|
clipboard_has_text,
|
||||||
@ -57,11 +60,10 @@ from _babase import (
|
|||||||
have_permission,
|
have_permission,
|
||||||
in_logic_thread,
|
in_logic_thread,
|
||||||
increment_analytics_count,
|
increment_analytics_count,
|
||||||
|
invoke_main_menu,
|
||||||
is_os_playing_music,
|
is_os_playing_music,
|
||||||
is_running_on_fire_tv,
|
|
||||||
is_xcode_build,
|
is_xcode_build,
|
||||||
lock_all_input,
|
lock_all_input,
|
||||||
mac_music_app_get_library_source,
|
|
||||||
mac_music_app_get_playlists,
|
mac_music_app_get_playlists,
|
||||||
mac_music_app_get_volume,
|
mac_music_app_get_volume,
|
||||||
mac_music_app_init,
|
mac_music_app_init,
|
||||||
@ -72,7 +74,10 @@ from _babase import (
|
|||||||
music_player_set_volume,
|
music_player_set_volume,
|
||||||
music_player_shutdown,
|
music_player_shutdown,
|
||||||
music_player_stop,
|
music_player_stop,
|
||||||
|
native_review_request,
|
||||||
|
native_review_request_supported,
|
||||||
native_stack_trace,
|
native_stack_trace,
|
||||||
|
open_file_externally,
|
||||||
print_load_info,
|
print_load_info,
|
||||||
pushcall,
|
pushcall,
|
||||||
quit,
|
quit,
|
||||||
@ -82,7 +87,6 @@ from _babase import (
|
|||||||
screenmessage,
|
screenmessage,
|
||||||
set_analytics_screen,
|
set_analytics_screen,
|
||||||
set_low_level_config_value,
|
set_low_level_config_value,
|
||||||
set_stress_testing,
|
|
||||||
set_thread_name,
|
set_thread_name,
|
||||||
set_ui_input_device,
|
set_ui_input_device,
|
||||||
show_progress_bar,
|
show_progress_bar,
|
||||||
@ -151,9 +155,8 @@ from babase._general import (
|
|||||||
getclass,
|
getclass,
|
||||||
get_type_name,
|
get_type_name,
|
||||||
)
|
)
|
||||||
from babase._keyboard import Keyboard
|
|
||||||
from babase._language import Lstr, LanguageSubsystem
|
from babase._language import Lstr, LanguageSubsystem
|
||||||
from babase._login import LoginAdapter
|
from babase._login import LoginAdapter, LoginInfo
|
||||||
|
|
||||||
# noinspection PyProtectedMember
|
# noinspection PyProtectedMember
|
||||||
# (PyCharm inspection bug?)
|
# (PyCharm inspection bug?)
|
||||||
@ -200,7 +203,10 @@ __all__ = [
|
|||||||
'apptimer',
|
'apptimer',
|
||||||
'AppTimer',
|
'AppTimer',
|
||||||
'Call',
|
'Call',
|
||||||
'can_toggle_fullscreen',
|
'fullscreen_control_available',
|
||||||
|
'fullscreen_control_get',
|
||||||
|
'fullscreen_control_key_shortcut',
|
||||||
|
'fullscreen_control_set',
|
||||||
'charstr',
|
'charstr',
|
||||||
'clipboard_get_text',
|
'clipboard_get_text',
|
||||||
'clipboard_has_text',
|
'clipboard_has_text',
|
||||||
@ -249,18 +255,17 @@ __all__ = [
|
|||||||
'increment_analytics_count',
|
'increment_analytics_count',
|
||||||
'InputDeviceNotFoundError',
|
'InputDeviceNotFoundError',
|
||||||
'InputType',
|
'InputType',
|
||||||
|
'invoke_main_menu',
|
||||||
'is_browser_likely_available',
|
'is_browser_likely_available',
|
||||||
'is_browser_likely_available',
|
'is_browser_likely_available',
|
||||||
'is_os_playing_music',
|
'is_os_playing_music',
|
||||||
'is_point_in_box',
|
'is_point_in_box',
|
||||||
'is_running_on_fire_tv',
|
|
||||||
'is_xcode_build',
|
'is_xcode_build',
|
||||||
'Keyboard',
|
|
||||||
'LanguageSubsystem',
|
'LanguageSubsystem',
|
||||||
'lock_all_input',
|
'lock_all_input',
|
||||||
'LoginAdapter',
|
'LoginAdapter',
|
||||||
|
'LoginInfo',
|
||||||
'Lstr',
|
'Lstr',
|
||||||
'mac_music_app_get_library_source',
|
|
||||||
'mac_music_app_get_playlists',
|
'mac_music_app_get_playlists',
|
||||||
'mac_music_app_get_volume',
|
'mac_music_app_get_volume',
|
||||||
'mac_music_app_init',
|
'mac_music_app_init',
|
||||||
@ -273,10 +278,13 @@ __all__ = [
|
|||||||
'music_player_set_volume',
|
'music_player_set_volume',
|
||||||
'music_player_shutdown',
|
'music_player_shutdown',
|
||||||
'music_player_stop',
|
'music_player_stop',
|
||||||
|
'native_review_request',
|
||||||
|
'native_review_request_supported',
|
||||||
'native_stack_trace',
|
'native_stack_trace',
|
||||||
'NodeNotFoundError',
|
'NodeNotFoundError',
|
||||||
'normalized_color',
|
'normalized_color',
|
||||||
'NotFoundError',
|
'NotFoundError',
|
||||||
|
'open_file_externally',
|
||||||
'Permission',
|
'Permission',
|
||||||
'PlayerNotFoundError',
|
'PlayerNotFoundError',
|
||||||
'Plugin',
|
'Plugin',
|
||||||
@ -297,7 +305,6 @@ __all__ = [
|
|||||||
'SessionTeamNotFoundError',
|
'SessionTeamNotFoundError',
|
||||||
'set_analytics_screen',
|
'set_analytics_screen',
|
||||||
'set_low_level_config_value',
|
'set_low_level_config_value',
|
||||||
'set_stress_testing',
|
|
||||||
'set_thread_name',
|
'set_thread_name',
|
||||||
'set_ui_input_device',
|
'set_ui_input_device',
|
||||||
'show_progress_bar',
|
'show_progress_bar',
|
||||||
|
|||||||
@ -6,7 +6,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING, assert_never
|
||||||
|
|
||||||
from efro.call import tpartial
|
from efro.call import tpartial
|
||||||
from efro.error import CommunicationError
|
from efro.error import CommunicationError
|
||||||
@ -16,7 +16,7 @@ import _babase
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from babase._login import LoginAdapter
|
from babase._login import LoginAdapter, LoginInfo
|
||||||
|
|
||||||
|
|
||||||
DEBUG_LOG = False
|
DEBUG_LOG = False
|
||||||
@ -27,10 +27,12 @@ class AccountV2Subsystem:
|
|||||||
|
|
||||||
Category: **App Classes**
|
Category: **App Classes**
|
||||||
|
|
||||||
Access the single shared instance of this class at 'ba.app.accounts'.
|
Access the single shared instance of this class at 'ba.app.plus.accounts'.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
from babase._login import LoginAdapterGPGS, LoginAdapterGameCenter
|
||||||
|
|
||||||
# Whether or not everything related to an initial login
|
# Whether or not everything related to an initial login
|
||||||
# (or lack thereof) has completed. This includes things like
|
# (or lack thereof) has completed. This includes things like
|
||||||
# workspace syncing. Completion of this is what flips the app
|
# workspace syncing. Completion of this is what flips the app
|
||||||
@ -45,16 +47,13 @@ class AccountV2Subsystem:
|
|||||||
self._implicit_state_changed = False
|
self._implicit_state_changed = False
|
||||||
self._can_do_auto_sign_in = True
|
self._can_do_auto_sign_in = True
|
||||||
|
|
||||||
if _babase.app.classic is None:
|
adapter: LoginAdapter
|
||||||
raise RuntimeError('Needs updating for no-classic case.')
|
if _babase.using_google_play_game_services():
|
||||||
|
adapter = LoginAdapterGPGS()
|
||||||
if (
|
self.login_adapters[adapter.login_type] = adapter
|
||||||
_babase.app.classic.platform == 'android'
|
if _babase.using_game_center():
|
||||||
and _babase.app.classic.subplatform == 'google'
|
adapter = LoginAdapterGameCenter()
|
||||||
):
|
self.login_adapters[adapter.login_type] = adapter
|
||||||
from babase._login import LoginAdapterGPGS
|
|
||||||
|
|
||||||
self.login_adapters[LoginType.GPGS] = LoginAdapterGPGS()
|
|
||||||
|
|
||||||
def on_app_loading(self) -> None:
|
def on_app_loading(self) -> None:
|
||||||
"""Should be called at standard on_app_loading time."""
|
"""Should be called at standard on_app_loading time."""
|
||||||
@ -62,10 +61,6 @@ class AccountV2Subsystem:
|
|||||||
for adapter in self.login_adapters.values():
|
for adapter in self.login_adapters.values():
|
||||||
adapter.on_app_loading()
|
adapter.on_app_loading()
|
||||||
|
|
||||||
def set_primary_credentials(self, credentials: str | None) -> None:
|
|
||||||
"""Set credentials for the primary app account."""
|
|
||||||
raise NotImplementedError('This should be overridden.')
|
|
||||||
|
|
||||||
def have_primary_credentials(self) -> bool:
|
def have_primary_credentials(self) -> bool:
|
||||||
"""Are credentials currently set for the primary app account?
|
"""Are credentials currently set for the primary app account?
|
||||||
|
|
||||||
@ -80,10 +75,6 @@ class AccountV2Subsystem:
|
|||||||
"""The primary account for the app, or None if not logged in."""
|
"""The primary account for the app, or None if not logged in."""
|
||||||
return self.do_get_primary()
|
return self.do_get_primary()
|
||||||
|
|
||||||
def do_get_primary(self) -> AccountV2Handle | None:
|
|
||||||
"""Internal - should be overridden by subclass."""
|
|
||||||
return None
|
|
||||||
|
|
||||||
def on_primary_account_changed(
|
def on_primary_account_changed(
|
||||||
self, account: AccountV2Handle | None
|
self, account: AccountV2Handle | None
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -142,6 +133,8 @@ class AccountV2Subsystem:
|
|||||||
"""An implicit sign-in happened (called by native layer)."""
|
"""An implicit sign-in happened (called by native layer)."""
|
||||||
from babase._login import LoginAdapter
|
from babase._login import LoginAdapter
|
||||||
|
|
||||||
|
assert _babase.in_logic_thread()
|
||||||
|
|
||||||
with _babase.ContextRef.empty():
|
with _babase.ContextRef.empty():
|
||||||
self.login_adapters[login_type].set_implicit_login_state(
|
self.login_adapters[login_type].set_implicit_login_state(
|
||||||
LoginAdapter.ImplicitLoginState(
|
LoginAdapter.ImplicitLoginState(
|
||||||
@ -151,6 +144,7 @@ class AccountV2Subsystem:
|
|||||||
|
|
||||||
def on_implicit_sign_out(self, login_type: LoginType) -> None:
|
def on_implicit_sign_out(self, login_type: LoginType) -> None:
|
||||||
"""An implicit sign-out happened (called by native layer)."""
|
"""An implicit sign-out happened (called by native layer)."""
|
||||||
|
assert _babase.in_logic_thread()
|
||||||
with _babase.ContextRef.empty():
|
with _babase.ContextRef.empty():
|
||||||
self.login_adapters[login_type].set_implicit_login_state(None)
|
self.login_adapters[login_type].set_implicit_login_state(None)
|
||||||
|
|
||||||
@ -192,9 +186,10 @@ class AccountV2Subsystem:
|
|||||||
cfgkey = 'ImplicitLoginStates'
|
cfgkey = 'ImplicitLoginStates'
|
||||||
cfgdict = _babase.app.config.setdefault(cfgkey, {})
|
cfgdict = _babase.app.config.setdefault(cfgkey, {})
|
||||||
|
|
||||||
# Store which (if any) adapter is currently implicitly signed in.
|
# Store which (if any) adapter is currently implicitly signed
|
||||||
# Making the assumption there will only ever be one implicit
|
# in. Making the assumption there will only ever be one implicit
|
||||||
# adapter at a time; may need to update this if that changes.
|
# adapter at a time; may need to revisit this logic if that
|
||||||
|
# changes.
|
||||||
prev_state = cfgdict.get(login_type.value)
|
prev_state = cfgdict.get(login_type.value)
|
||||||
if state is None:
|
if state is None:
|
||||||
self._implicit_signed_in_adapter = None
|
self._implicit_signed_in_adapter = None
|
||||||
@ -205,18 +200,26 @@ class AccountV2Subsystem:
|
|||||||
state.login_id
|
state.login_id
|
||||||
)
|
)
|
||||||
|
|
||||||
# Special case: if the user is already signed in but not with
|
# Special case: if the user is already signed in but not
|
||||||
# this implicit login, we may want to let them know that the
|
# with this implicit login, let them know that the 'Welcome
|
||||||
# 'Welcome back FOO' they likely just saw is not actually
|
# back FOO' they likely just saw is not actually accurate.
|
||||||
# accurate.
|
|
||||||
if (
|
if (
|
||||||
self.primary is not None
|
self.primary is not None
|
||||||
and not self.login_adapters[login_type].is_back_end_active()
|
and not self.login_adapters[login_type].is_back_end_active()
|
||||||
):
|
):
|
||||||
|
service_str: Lstr | None
|
||||||
if login_type is LoginType.GPGS:
|
if login_type is LoginType.GPGS:
|
||||||
service_str = Lstr(resource='googlePlayText')
|
service_str = Lstr(resource='googlePlayText')
|
||||||
else:
|
elif login_type is LoginType.GAME_CENTER:
|
||||||
|
# Note: Apparently Game Center is just called 'Game
|
||||||
|
# Center' in all languages. Can revisit if not true.
|
||||||
|
# https://developer.apple.com/forums/thread/725779
|
||||||
|
service_str = Lstr(value='Game Center')
|
||||||
|
elif login_type is LoginType.EMAIL:
|
||||||
|
# Not possible; just here for exhaustive coverage.
|
||||||
service_str = None
|
service_str = None
|
||||||
|
else:
|
||||||
|
assert_never(login_type)
|
||||||
if service_str is not None:
|
if service_str is not None:
|
||||||
_babase.apptimer(
|
_babase.apptimer(
|
||||||
2.0,
|
2.0,
|
||||||
@ -259,6 +262,14 @@ class AccountV2Subsystem:
|
|||||||
# We may want to auto-sign-in based on this new state.
|
# We may want to auto-sign-in based on this new state.
|
||||||
self._update_auto_sign_in()
|
self._update_auto_sign_in()
|
||||||
|
|
||||||
|
def do_get_primary(self) -> AccountV2Handle | None:
|
||||||
|
"""Internal - should be overridden by subclass."""
|
||||||
|
raise NotImplementedError('This should be overridden.')
|
||||||
|
|
||||||
|
def set_primary_credentials(self, credentials: str | None) -> None:
|
||||||
|
"""Set credentials for the primary app account."""
|
||||||
|
raise NotImplementedError('This should be overridden.')
|
||||||
|
|
||||||
def _update_auto_sign_in(self) -> None:
|
def _update_auto_sign_in(self) -> None:
|
||||||
plus = _babase.app.plus
|
plus = _babase.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
@ -266,7 +277,7 @@ class AccountV2Subsystem:
|
|||||||
# If implicit state has changed, try to respond.
|
# If implicit state has changed, try to respond.
|
||||||
if self._implicit_state_changed:
|
if self._implicit_state_changed:
|
||||||
if self._implicit_signed_in_adapter is None:
|
if self._implicit_signed_in_adapter is None:
|
||||||
# If implicit back-end is signed out, follow suit
|
# If implicit back-end has signed out, we follow suit
|
||||||
# immediately; no need to wait for network connectivity.
|
# immediately; no need to wait for network connectivity.
|
||||||
if DEBUG_LOG:
|
if DEBUG_LOG:
|
||||||
logging.debug(
|
logging.debug(
|
||||||
@ -286,9 +297,8 @@ class AccountV2Subsystem:
|
|||||||
# Consider this an 'explicit' sign in because the
|
# Consider this an 'explicit' sign in because the
|
||||||
# implicit-login state change presumably was triggered
|
# implicit-login state change presumably was triggered
|
||||||
# by some user action (signing in, signing out, or
|
# by some user action (signing in, signing out, or
|
||||||
# switching accounts via the back-end).
|
# switching accounts via the back-end). NOTE: should
|
||||||
# NOTE: should test case where we don't have
|
# test case where we don't have connectivity here.
|
||||||
# connectivity here.
|
|
||||||
if plus.cloud.is_connected():
|
if plus.cloud.is_connected():
|
||||||
if DEBUG_LOG:
|
if DEBUG_LOG:
|
||||||
logging.debug(
|
logging.debug(
|
||||||
@ -419,14 +429,11 @@ class AccountV2Handle:
|
|||||||
used with some operations such as cloud messaging.
|
used with some operations such as cloud messaging.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
accountid: str
|
||||||
self.tag = '?'
|
tag: str
|
||||||
|
workspacename: str | None
|
||||||
self.workspacename: str | None = None
|
workspaceid: str | None
|
||||||
self.workspaceid: str | None = None
|
logins: dict[LoginType, LoginInfo]
|
||||||
|
|
||||||
# Login types and their display-names associated with this account.
|
|
||||||
self.logins: dict[LoginType, str] = {}
|
|
||||||
|
|
||||||
def __enter__(self) -> None:
|
def __enter__(self) -> None:
|
||||||
"""Support for "with" statement.
|
"""Support for "with" statement.
|
||||||
|
|||||||
@ -56,6 +56,8 @@ class App:
|
|||||||
|
|
||||||
# pylint: disable=too-many-public-methods
|
# pylint: disable=too-many-public-methods
|
||||||
|
|
||||||
|
# A few things defined as non-optional values but not actually
|
||||||
|
# available until the app starts.
|
||||||
plugins: PluginSubsystem
|
plugins: PluginSubsystem
|
||||||
lang: LanguageSubsystem
|
lang: LanguageSubsystem
|
||||||
health_monitor: AppHealthMonitor
|
health_monitor: AppHealthMonitor
|
||||||
@ -92,7 +94,7 @@ class App:
|
|||||||
|
|
||||||
# Used on platforms such as mobile where the app basically needs
|
# Used on platforms such as mobile where the app basically needs
|
||||||
# to shut down while backgrounded. In this state, all event
|
# to shut down while backgrounded. In this state, all event
|
||||||
# loops are suspended and all graphics and audio should cease
|
# loops are suspended and all graphics and audio must cease
|
||||||
# completely. Be aware that the suspended state can be entered
|
# completely. Be aware that the suspended state can be entered
|
||||||
# from any other state including NATIVE_BOOTSTRAPPING and
|
# from any other state including NATIVE_BOOTSTRAPPING and
|
||||||
# SHUTTING_DOWN.
|
# SHUTTING_DOWN.
|
||||||
@ -149,9 +151,9 @@ class App:
|
|||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
"""(internal)
|
"""(internal)
|
||||||
|
|
||||||
Do not instantiate this class; access the single shared instance
|
Do not instantiate this class. You can access the single shared
|
||||||
of it as 'app' which is available in various Ballistica
|
instance of it through various high level packages: 'babase.app',
|
||||||
feature-set modules such as babase.
|
'bascenev1.app', 'bauiv1.app', etc.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Hack for docs-generation: we can be imported with dummy modules
|
# Hack for docs-generation: we can be imported with dummy modules
|
||||||
@ -182,7 +184,6 @@ class App:
|
|||||||
# foregrounded; can be a simple way to determine if network data
|
# foregrounded; can be a simple way to determine if network data
|
||||||
# should be refreshed/etc.
|
# should be refreshed/etc.
|
||||||
self.fg_state = 0
|
self.fg_state = 0
|
||||||
self.config_file_healthy: bool = False
|
|
||||||
|
|
||||||
self._subsystems: list[AppSubsystem] = []
|
self._subsystems: list[AppSubsystem] = []
|
||||||
self._native_bootstrapping_completed = False
|
self._native_bootstrapping_completed = False
|
||||||
@ -208,7 +209,8 @@ class App:
|
|||||||
self._shutdown_task: asyncio.Task[None] | None = None
|
self._shutdown_task: asyncio.Task[None] | None = None
|
||||||
self._shutdown_tasks: list[Coroutine[None, None, None]] = [
|
self._shutdown_tasks: list[Coroutine[None, None, None]] = [
|
||||||
self._wait_for_shutdown_suppressions(),
|
self._wait_for_shutdown_suppressions(),
|
||||||
self._fade_for_shutdown(),
|
self._fade_and_shutdown_graphics(),
|
||||||
|
self._fade_and_shutdown_audio(),
|
||||||
]
|
]
|
||||||
self._pool_thread_count = 0
|
self._pool_thread_count = 0
|
||||||
|
|
||||||
@ -227,6 +229,15 @@ class App:
|
|||||||
self.lang = LanguageSubsystem()
|
self.lang = LanguageSubsystem()
|
||||||
self.plugins = PluginSubsystem()
|
self.plugins = PluginSubsystem()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def active(self) -> bool:
|
||||||
|
"""Whether the app is currently front and center.
|
||||||
|
|
||||||
|
This will be False when the app is hidden, other activities
|
||||||
|
are covering it, etc. (depending on the platform).
|
||||||
|
"""
|
||||||
|
return _babase.app_is_active()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def aioloop(self) -> asyncio.AbstractEventLoop:
|
def aioloop(self) -> asyncio.AbstractEventLoop:
|
||||||
"""The logic thread's asyncio event loop.
|
"""The logic thread's asyncio event loop.
|
||||||
@ -426,11 +437,17 @@ class App:
|
|||||||
self._native_shutdown_complete_called = True
|
self._native_shutdown_complete_called = True
|
||||||
self._update_state()
|
self._update_state()
|
||||||
|
|
||||||
|
def on_native_active_changed(self) -> None:
|
||||||
|
"""Called by the native layer when the app active state changes."""
|
||||||
|
assert _babase.in_logic_thread()
|
||||||
|
if self._mode is not None:
|
||||||
|
self._mode.on_app_active_changed()
|
||||||
|
|
||||||
def read_config(self) -> None:
|
def read_config(self) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
from babase._appconfig import read_app_config
|
from babase._appconfig import read_app_config
|
||||||
|
|
||||||
self._config, self.config_file_healthy = read_app_config()
|
self._config = read_app_config()
|
||||||
|
|
||||||
def handle_deep_link(self, url: str) -> None:
|
def handle_deep_link(self, url: str) -> None:
|
||||||
"""Handle a deep link URL."""
|
"""Handle a deep link URL."""
|
||||||
@ -508,7 +525,7 @@ class App:
|
|||||||
except Exception:
|
except Exception:
|
||||||
logging.exception('Error setting app intent to %s.', intent)
|
logging.exception('Error setting app intent to %s.', intent)
|
||||||
_babase.pushcall(
|
_babase.pushcall(
|
||||||
tpartial(self._apply_intent_error, intent),
|
tpartial(self._display_set_intent_error, intent),
|
||||||
from_other_thread=True,
|
from_other_thread=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -553,10 +570,11 @@ class App:
|
|||||||
'Error handling intent %s in app-mode %s.', intent, mode
|
'Error handling intent %s in app-mode %s.', intent, mode
|
||||||
)
|
)
|
||||||
|
|
||||||
def _apply_intent_error(self, intent: AppIntent) -> None:
|
def _display_set_intent_error(self, intent: AppIntent) -> None:
|
||||||
|
"""Show the *user* something went wrong setting an intent."""
|
||||||
from babase._language import Lstr
|
from babase._language import Lstr
|
||||||
|
|
||||||
del intent # Unused.
|
del intent
|
||||||
_babase.screenmessage(Lstr(resource='errorText'), color=(1, 0, 0))
|
_babase.screenmessage(Lstr(resource='errorText'), color=(1, 0, 0))
|
||||||
_babase.getsimplesound('error').play()
|
_babase.getsimplesound('error').play()
|
||||||
|
|
||||||
@ -579,19 +597,6 @@ class App:
|
|||||||
self._aioloop = _asyncio.setup_asyncio()
|
self._aioloop = _asyncio.setup_asyncio()
|
||||||
self.health_monitor = AppHealthMonitor()
|
self.health_monitor = AppHealthMonitor()
|
||||||
|
|
||||||
# Only proceed if our config file is healthy so we don't
|
|
||||||
# overwrite a broken one or whatnot and wipe out data.
|
|
||||||
if not self.config_file_healthy:
|
|
||||||
if self.classic is not None:
|
|
||||||
handled = self.classic.show_config_error_window()
|
|
||||||
if handled:
|
|
||||||
return
|
|
||||||
|
|
||||||
# For now on other systems we just overwrite the bum config.
|
|
||||||
# At this point settings are already set; lets just commit
|
|
||||||
# them to disk.
|
|
||||||
_appconfig.commit_app_config(force=True)
|
|
||||||
|
|
||||||
# __FEATURESET_APP_SUBSYSTEM_CREATE_BEGIN__
|
# __FEATURESET_APP_SUBSYSTEM_CREATE_BEGIN__
|
||||||
# This section generated by batools.appmodule; do not edit.
|
# This section generated by batools.appmodule; do not edit.
|
||||||
|
|
||||||
@ -795,6 +800,7 @@ class App:
|
|||||||
async def _shutdown(self) -> None:
|
async def _shutdown(self) -> None:
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
_babase.lock_all_input()
|
||||||
try:
|
try:
|
||||||
async with asyncio.TaskGroup() as task_group:
|
async with asyncio.TaskGroup() as task_group:
|
||||||
for task_coro in self._shutdown_tasks:
|
for task_coro in self._shutdown_tasks:
|
||||||
@ -890,23 +896,45 @@ class App:
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
# Spin and wait for anything blocking shutdown to complete.
|
# Spin and wait for anything blocking shutdown to complete.
|
||||||
|
starttime = _babase.apptime()
|
||||||
_babase.lifecyclelog('shutdown-suppress wait begin')
|
_babase.lifecyclelog('shutdown-suppress wait begin')
|
||||||
while _babase.shutdown_suppress_count() > 0:
|
while _babase.shutdown_suppress_count() > 0:
|
||||||
await asyncio.sleep(0.001)
|
await asyncio.sleep(0.001)
|
||||||
_babase.lifecyclelog('shutdown-suppress wait end')
|
_babase.lifecyclelog('shutdown-suppress wait end')
|
||||||
|
duration = _babase.apptime() - starttime
|
||||||
|
if duration > 1.0:
|
||||||
|
logging.warning(
|
||||||
|
'Shutdown-suppressions lasted longer than ideal '
|
||||||
|
'(%.2f seconds).',
|
||||||
|
duration,
|
||||||
|
)
|
||||||
|
|
||||||
async def _fade_for_shutdown(self) -> None:
|
async def _fade_and_shutdown_graphics(self) -> None:
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
# Kick off a fade, block input, and wait for a short bit.
|
# Kick off a short fade and give it time to complete.
|
||||||
# Ideally most shutdown activity completes during the fade so
|
_babase.lifecyclelog('fade-and-shutdown-graphics begin')
|
||||||
# there's no tangible wait.
|
|
||||||
_babase.lifecyclelog('fade-for-shutdown begin')
|
|
||||||
_babase.fade_screen(False, time=0.15)
|
_babase.fade_screen(False, time=0.15)
|
||||||
_babase.lock_all_input()
|
|
||||||
# _babase.getsimplesound('swish2').play()
|
|
||||||
await asyncio.sleep(0.15)
|
await asyncio.sleep(0.15)
|
||||||
_babase.lifecyclelog('fade-for-shutdown end')
|
|
||||||
|
# Now tell the graphics system to go down and wait until
|
||||||
|
# it has done so.
|
||||||
|
_babase.graphics_shutdown_begin()
|
||||||
|
while not _babase.graphics_shutdown_is_complete():
|
||||||
|
await asyncio.sleep(0.01)
|
||||||
|
_babase.lifecyclelog('fade-and-shutdown-graphics end')
|
||||||
|
|
||||||
|
async def _fade_and_shutdown_audio(self) -> None:
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
# Tell the audio system to go down and give it a bit of
|
||||||
|
# time to do so gracefully.
|
||||||
|
_babase.lifecyclelog('fade-and-shutdown-audio begin')
|
||||||
|
_babase.audio_shutdown_begin()
|
||||||
|
await asyncio.sleep(0.15)
|
||||||
|
while not _babase.audio_shutdown_is_complete():
|
||||||
|
await asyncio.sleep(0.01)
|
||||||
|
_babase.lifecyclelog('fade-and-shutdown-audio end')
|
||||||
|
|
||||||
def _threadpool_no_wait_done(self, fut: Future) -> None:
|
def _threadpool_no_wait_done(self, fut: Future) -> None:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -101,15 +101,13 @@ class AppConfig(dict):
|
|||||||
self.commit()
|
self.commit()
|
||||||
|
|
||||||
|
|
||||||
def read_app_config() -> tuple[AppConfig, bool]:
|
def read_app_config() -> AppConfig:
|
||||||
"""Read the app config."""
|
"""Read the app config."""
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
|
||||||
config_file_healthy = False
|
# NOTE: it is assumed that this only gets called once and the config
|
||||||
|
# object will not change from here on out
|
||||||
# NOTE: it is assumed that this only gets called once and the
|
|
||||||
# config object will not change from here on out
|
|
||||||
config_file_path = _babase.app.env.config_file_path
|
config_file_path = _babase.app.env.config_file_path
|
||||||
config_contents = ''
|
config_contents = ''
|
||||||
try:
|
try:
|
||||||
@ -119,20 +117,16 @@ def read_app_config() -> tuple[AppConfig, bool]:
|
|||||||
config = AppConfig(json.loads(config_contents))
|
config = AppConfig(json.loads(config_contents))
|
||||||
else:
|
else:
|
||||||
config = AppConfig()
|
config = AppConfig()
|
||||||
config_file_healthy = True
|
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception(
|
logging.exception(
|
||||||
"Error reading config file at time %.3f: '%s'.",
|
"Error reading config file '%s' at time %.3f.\n"
|
||||||
|
"Backing up broken config to'%s.broken'.",
|
||||||
|
config_file_path,
|
||||||
_babase.apptime(),
|
_babase.apptime(),
|
||||||
config_file_path,
|
config_file_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Whenever this happens lets back up the broken one just in case it
|
|
||||||
# gets overwritten accidentally.
|
|
||||||
logging.info(
|
|
||||||
"Backing up current config file to '%s.broken'", config_file_path
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
@ -141,23 +135,10 @@ def read_app_config() -> tuple[AppConfig, bool]:
|
|||||||
logging.exception('Error copying broken config.')
|
logging.exception('Error copying broken config.')
|
||||||
config = AppConfig()
|
config = AppConfig()
|
||||||
|
|
||||||
# Now attempt to read one of our 'prev' backup copies.
|
return config
|
||||||
prev_path = config_file_path + '.prev'
|
|
||||||
try:
|
|
||||||
if os.path.exists(prev_path):
|
|
||||||
with open(prev_path, encoding='utf-8') as infile:
|
|
||||||
config_contents = infile.read()
|
|
||||||
config = AppConfig(json.loads(config_contents))
|
|
||||||
else:
|
|
||||||
config = AppConfig()
|
|
||||||
config_file_healthy = True
|
|
||||||
logging.info('Successfully read backup config.')
|
|
||||||
except Exception:
|
|
||||||
logging.exception('Error reading prev backup config.')
|
|
||||||
return config, config_file_healthy
|
|
||||||
|
|
||||||
|
|
||||||
def commit_app_config(force: bool = False) -> None:
|
def commit_app_config() -> None:
|
||||||
"""Commit the config to persistent storage.
|
"""Commit the config to persistent storage.
|
||||||
|
|
||||||
Category: **General Utility Functions**
|
Category: **General Utility Functions**
|
||||||
@ -167,10 +148,4 @@ def commit_app_config(force: bool = False) -> None:
|
|||||||
plus = _babase.app.plus
|
plus = _babase.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
if not _babase.app.config_file_healthy and not force:
|
|
||||||
logging.warning(
|
|
||||||
'Current config file is broken; '
|
|
||||||
'skipping write to avoid losing settings.'
|
|
||||||
)
|
|
||||||
return
|
|
||||||
plus.mark_config_dirty()
|
plus.mark_config_dirty()
|
||||||
|
|||||||
@ -31,6 +31,7 @@ class AppMode:
|
|||||||
AppExperience associated with the AppMode must be supported by
|
AppExperience associated with the AppMode must be supported by
|
||||||
the current app and runtime environment.
|
the current app and runtime environment.
|
||||||
"""
|
"""
|
||||||
|
# FIXME: check AppExperience.
|
||||||
return cls._supports_intent(intent)
|
return cls._supports_intent(intent)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -51,3 +52,10 @@ class AppMode:
|
|||||||
|
|
||||||
def on_deactivate(self) -> None:
|
def on_deactivate(self) -> None:
|
||||||
"""Called when the mode is being deactivated."""
|
"""Called when the mode is being deactivated."""
|
||||||
|
|
||||||
|
def on_app_active_changed(self) -> None:
|
||||||
|
"""Called when babase.app.active changes.
|
||||||
|
|
||||||
|
The app-mode may want to take action such as pausing a running
|
||||||
|
game in such cases.
|
||||||
|
"""
|
||||||
|
|||||||
@ -325,7 +325,7 @@ def dump_app_state(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def log_dumped_app_state() -> None:
|
def log_dumped_app_state(from_previous_run: bool = False) -> None:
|
||||||
"""If an app-state dump exists, log it and clear it. No-op otherwise."""
|
"""If an app-state dump exists, log it and clear it. No-op otherwise."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -352,8 +352,13 @@ def log_dumped_app_state() -> None:
|
|||||||
|
|
||||||
metadata = dataclass_from_json(DumpedAppStateMetadata, appstatedata)
|
metadata = dataclass_from_json(DumpedAppStateMetadata, appstatedata)
|
||||||
|
|
||||||
|
header = (
|
||||||
|
'Found app state dump from previous app run'
|
||||||
|
if from_previous_run
|
||||||
|
else 'App state dump'
|
||||||
|
)
|
||||||
out += (
|
out += (
|
||||||
f'App state dump:\nReason: {metadata.reason}\n'
|
f'{header}:\nReason: {metadata.reason}\n'
|
||||||
f'Time: {metadata.app_time:.2f}'
|
f'Time: {metadata.app_time:.2f}'
|
||||||
)
|
)
|
||||||
tbpath = os.path.join(
|
tbpath = os.path.join(
|
||||||
@ -383,7 +388,7 @@ class AppHealthMonitor(AppSubsystem):
|
|||||||
|
|
||||||
def on_app_loading(self) -> None:
|
def on_app_loading(self) -> None:
|
||||||
# If any traceback dumps happened last run, log and clear them.
|
# If any traceback dumps happened last run, log and clear them.
|
||||||
log_dumped_app_state()
|
log_dumped_app_state(from_previous_run=True)
|
||||||
|
|
||||||
def _app_monitor_thread_main(self) -> None:
|
def _app_monitor_thread_main(self) -> None:
|
||||||
_babase.set_thread_name('ballistica app-monitor')
|
_babase.set_thread_name('ballistica app-monitor')
|
||||||
|
|||||||
@ -26,6 +26,11 @@ DEBUG_LOG = False
|
|||||||
class CloudSubsystem(AppSubsystem):
|
class CloudSubsystem(AppSubsystem):
|
||||||
"""Manages communication with cloud components."""
|
"""Manages communication with cloud components."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def connected(self) -> bool:
|
||||||
|
"""Property equivalent of CloudSubsystem.is_connected()."""
|
||||||
|
return self.is_connected()
|
||||||
|
|
||||||
def is_connected(self) -> bool:
|
def is_connected(self) -> bool:
|
||||||
"""Return whether a connection to the cloud is present.
|
"""Return whether a connection to the cloud is present.
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
"""Dev-Console functionality."""
|
"""Dev-Console functionality."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import logging
|
import logging
|
||||||
@ -154,9 +155,10 @@ class DevConsoleSubsystem:
|
|||||||
# All tabs in the dev-console. Add your own stuff here via
|
# All tabs in the dev-console. Add your own stuff here via
|
||||||
# plugins or whatnot.
|
# plugins or whatnot.
|
||||||
self.tabs: list[DevConsoleTabEntry] = [
|
self.tabs: list[DevConsoleTabEntry] = [
|
||||||
DevConsoleTabEntry('Python', DevConsoleTabPython),
|
DevConsoleTabEntry('Python', DevConsoleTabPython)
|
||||||
DevConsoleTabEntry('Test', DevConsoleTabTest),
|
|
||||||
]
|
]
|
||||||
|
if os.environ.get('BA_DEV_CONSOLE_TEST_TAB', '0') == '1':
|
||||||
|
self.tabs.append(DevConsoleTabEntry('Test', DevConsoleTabTest))
|
||||||
self.is_refreshing = False
|
self.is_refreshing = False
|
||||||
|
|
||||||
def do_refresh_tab(self, tabname: str) -> None:
|
def do_refresh_tab(self, tabname: str) -> None:
|
||||||
|
|||||||
@ -185,10 +185,8 @@ def _feed_logs_to_babase(log_handler: LogHandler) -> None:
|
|||||||
def _on_log(entry: LogEntry) -> None:
|
def _on_log(entry: LogEntry) -> None:
|
||||||
# Forward this along to the engine to display in the in-app
|
# Forward this along to the engine to display in the in-app
|
||||||
# console, in the Android log, etc.
|
# console, in the Android log, etc.
|
||||||
_babase.display_log(
|
_babase.emit_log(
|
||||||
name=entry.name,
|
name=entry.name, level=entry.level.name, message=entry.message
|
||||||
level=entry.level.name,
|
|
||||||
message=entry.message,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We also want to feed some logs to the old v1-cloud-log system.
|
# We also want to feed some logs to the old v1-cloud-log system.
|
||||||
|
|||||||
@ -33,18 +33,47 @@ def reset_to_main_menu() -> None:
|
|||||||
logging.warning('reset_to_main_menu: no-op due to classic not present.')
|
logging.warning('reset_to_main_menu: no-op due to classic not present.')
|
||||||
|
|
||||||
|
|
||||||
def set_config_fullscreen_on() -> None:
|
def get_v2_account_id() -> str | None:
|
||||||
|
"""Return the current V2 account id if signed in, or None if not."""
|
||||||
|
try:
|
||||||
|
plus = _babase.app.plus
|
||||||
|
if plus is not None:
|
||||||
|
account = plus.accounts.primary
|
||||||
|
if account is not None:
|
||||||
|
accountid = account.accountid
|
||||||
|
# (Avoids mypy complaints when plus is not present)
|
||||||
|
assert isinstance(accountid, (str, type(None)))
|
||||||
|
return accountid
|
||||||
|
return None
|
||||||
|
except Exception:
|
||||||
|
logging.exception('Error fetching v2 account id.')
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def store_config_fullscreen_on() -> None:
|
||||||
"""The OS has changed our fullscreen state and we should take note."""
|
"""The OS has changed our fullscreen state and we should take note."""
|
||||||
_babase.app.config['Fullscreen'] = True
|
_babase.app.config['Fullscreen'] = True
|
||||||
_babase.app.config.commit()
|
_babase.app.config.commit()
|
||||||
|
|
||||||
|
|
||||||
def set_config_fullscreen_off() -> None:
|
def store_config_fullscreen_off() -> None:
|
||||||
"""The OS has changed our fullscreen state and we should take note."""
|
"""The OS has changed our fullscreen state and we should take note."""
|
||||||
_babase.app.config['Fullscreen'] = False
|
_babase.app.config['Fullscreen'] = False
|
||||||
_babase.app.config.commit()
|
_babase.app.config.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def set_config_fullscreen_on() -> None:
|
||||||
|
"""Set and store fullscreen state"""
|
||||||
|
_babase.app.config['Fullscreen'] = True
|
||||||
|
_babase.app.config.apply_and_commit()
|
||||||
|
|
||||||
|
|
||||||
|
def set_config_fullscreen_off() -> None:
|
||||||
|
"""The OS has changed our fullscreen state and we should take note."""
|
||||||
|
_babase.app.config['Fullscreen'] = False
|
||||||
|
_babase.app.config.apply_and_commit()
|
||||||
|
|
||||||
|
|
||||||
def not_signed_in_screen_message() -> None:
|
def not_signed_in_screen_message() -> None:
|
||||||
from babase._language import Lstr
|
from babase._language import Lstr
|
||||||
|
|
||||||
@ -111,6 +140,14 @@ def error_message() -> None:
|
|||||||
_babase.screenmessage(Lstr(resource='errorText'), color=(1, 0, 0))
|
_babase.screenmessage(Lstr(resource='errorText'), color=(1, 0, 0))
|
||||||
|
|
||||||
|
|
||||||
|
def success_message() -> None:
|
||||||
|
from babase._language import Lstr
|
||||||
|
|
||||||
|
if _babase.app.env.gui:
|
||||||
|
_babase.getsimplesound('dingSmall').play()
|
||||||
|
_babase.screenmessage(Lstr(resource='successText'), color=(0, 1, 0))
|
||||||
|
|
||||||
|
|
||||||
def purchase_not_valid_error() -> None:
|
def purchase_not_valid_error() -> None:
|
||||||
from babase._language import Lstr
|
from babase._language import Lstr
|
||||||
|
|
||||||
@ -300,6 +337,7 @@ def implicit_sign_in(
|
|||||||
from bacommon.login import LoginType
|
from bacommon.login import LoginType
|
||||||
|
|
||||||
assert _babase.app.plus is not None
|
assert _babase.app.plus is not None
|
||||||
|
|
||||||
_babase.app.plus.accounts.on_implicit_sign_in(
|
_babase.app.plus.accounts.on_implicit_sign_in(
|
||||||
login_type=LoginType(login_type_str),
|
login_type=LoginType(login_type_str),
|
||||||
login_id=login_id,
|
login_id=login_id,
|
||||||
@ -377,3 +415,17 @@ def string_edit_adapter_can_be_replaced(adapter: StringEditAdapter) -> bool:
|
|||||||
def get_dev_console_tab_names() -> list[str]:
|
def get_dev_console_tab_names() -> list[str]:
|
||||||
"""Return the current set of dev-console tab names."""
|
"""Return the current set of dev-console tab names."""
|
||||||
return [t.name for t in _babase.app.devconsole.tabs]
|
return [t.name for t in _babase.app.devconsole.tabs]
|
||||||
|
|
||||||
|
|
||||||
|
def unsupported_controller_message(name: str) -> None:
|
||||||
|
"""Print a message when an unsupported controller is connected."""
|
||||||
|
from babase._language import Lstr
|
||||||
|
|
||||||
|
# Ick; this can get called early in the bootstrapping process
|
||||||
|
# before we're allowed to load assets. Guard against that.
|
||||||
|
if _babase.asset_loads_allowed():
|
||||||
|
_babase.getsimplesound('error').play()
|
||||||
|
_babase.screenmessage(
|
||||||
|
Lstr(resource='unsupportedControllerText', subs=[('${NAME}', name)]),
|
||||||
|
color=(1, 0, 0),
|
||||||
|
)
|
||||||
|
|||||||
@ -20,6 +20,13 @@ if TYPE_CHECKING:
|
|||||||
DEBUG_LOG = False
|
DEBUG_LOG = False
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LoginInfo:
|
||||||
|
"""Basic info about a login available in the app.plus.accounts section."""
|
||||||
|
|
||||||
|
name: str
|
||||||
|
|
||||||
|
|
||||||
class LoginAdapter:
|
class LoginAdapter:
|
||||||
"""Allows using implicit login types in an explicit way.
|
"""Allows using implicit login types in an explicit way.
|
||||||
|
|
||||||
@ -138,7 +145,7 @@ class LoginAdapter:
|
|||||||
is actually being used by the app. It should therefore register
|
is actually being used by the app. It should therefore register
|
||||||
unlocked achievements, leaderboard scores, allow viewing native
|
unlocked achievements, leaderboard scores, allow viewing native
|
||||||
UIs, etc. When not active it should ignore everything and behave
|
UIs, etc. When not active it should ignore everything and behave
|
||||||
as if logged out, even if it technically is still logged in.
|
as if signed out, even if it technically is still signed in.
|
||||||
"""
|
"""
|
||||||
assert _babase.in_logic_thread()
|
assert _babase.in_logic_thread()
|
||||||
del active # Unused.
|
del active # Unused.
|
||||||
@ -149,7 +156,7 @@ class LoginAdapter:
|
|||||||
result_cb: Callable[[LoginAdapter, SignInResult | Exception], None],
|
result_cb: Callable[[LoginAdapter, SignInResult | Exception], None],
|
||||||
description: str,
|
description: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Attempt an explicit sign in via this adapter.
|
"""Attempt to sign in via this adapter.
|
||||||
|
|
||||||
This can be called even if the back-end is not implicitly signed in;
|
This can be called even if the back-end is not implicitly signed in;
|
||||||
the adapter will attempt to sign in if possible. An exception will
|
the adapter will attempt to sign in if possible. An exception will
|
||||||
@ -161,7 +168,7 @@ class LoginAdapter:
|
|||||||
# Have been seeing multiple sign-in attempts come through
|
# Have been seeing multiple sign-in attempts come through
|
||||||
# nearly simultaneously which can be problematic server-side.
|
# nearly simultaneously which can be problematic server-side.
|
||||||
# Let's error if a sign-in attempt is made within a few seconds
|
# Let's error if a sign-in attempt is made within a few seconds
|
||||||
# of the last one to address this.
|
# of the last one to try and address this.
|
||||||
now = time.monotonic()
|
now = time.monotonic()
|
||||||
appnow = _babase.apptime()
|
appnow = _babase.apptime()
|
||||||
if self._last_sign_in_time is not None:
|
if self._last_sign_in_time is not None:
|
||||||
@ -229,6 +236,7 @@ class LoginAdapter:
|
|||||||
def _got_sign_in_response(
|
def _got_sign_in_response(
|
||||||
response: bacommon.cloud.SignInResponse | Exception,
|
response: bacommon.cloud.SignInResponse | Exception,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
# This likely means we couldn't communicate with the server.
|
||||||
if isinstance(response, Exception):
|
if isinstance(response, Exception):
|
||||||
if DEBUG_LOG:
|
if DEBUG_LOG:
|
||||||
logging.debug(
|
logging.debug(
|
||||||
@ -239,20 +247,18 @@ class LoginAdapter:
|
|||||||
)
|
)
|
||||||
_babase.pushcall(Call(result_cb, self, response))
|
_babase.pushcall(Call(result_cb, self, response))
|
||||||
else:
|
else:
|
||||||
if DEBUG_LOG:
|
# This means our credentials were explicitly rejected.
|
||||||
logging.debug(
|
|
||||||
'LoginAdapter: %s adapter got successful'
|
|
||||||
' sign-in response',
|
|
||||||
self.login_type.name,
|
|
||||||
)
|
|
||||||
if response.credentials is None:
|
if response.credentials is None:
|
||||||
result2: LoginAdapter.SignInResult | Exception = (
|
result2: LoginAdapter.SignInResult | Exception = (
|
||||||
RuntimeError(
|
RuntimeError('Sign-in-token was rejected.')
|
||||||
'No credentials returned after'
|
|
||||||
' submitting sign-in-token.'
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
if DEBUG_LOG:
|
||||||
|
logging.debug(
|
||||||
|
'LoginAdapter: %s adapter got successful'
|
||||||
|
' sign-in response',
|
||||||
|
self.login_type.name,
|
||||||
|
)
|
||||||
result2 = self.SignInResult(
|
result2 = self.SignInResult(
|
||||||
credentials=response.credentials
|
credentials=response.credentials
|
||||||
)
|
)
|
||||||
@ -269,7 +275,7 @@ class LoginAdapter:
|
|||||||
on_response=_got_sign_in_response,
|
on_response=_got_sign_in_response,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Kick off the process by fetching a sign-in token.
|
# Kick off the sign-in process by fetching a sign-in token.
|
||||||
self.get_sign_in_token(completion_cb=_got_sign_in_token_result)
|
self.get_sign_in_token(completion_cb=_got_sign_in_token_result)
|
||||||
|
|
||||||
def is_back_end_active(self) -> bool:
|
def is_back_end_active(self) -> bool:
|
||||||
@ -282,11 +288,10 @@ class LoginAdapter:
|
|||||||
"""Get a sign-in token from the adapter back end.
|
"""Get a sign-in token from the adapter back end.
|
||||||
|
|
||||||
This token is then passed to the master-server to complete the
|
This token is then passed to the master-server to complete the
|
||||||
login process.
|
sign-in process. The adapter can use this opportunity to bring
|
||||||
The adapter can use this opportunity to bring up account creation
|
up account creation UI, call its internal sign_in function, etc.
|
||||||
UI, call its internal sign_in function, etc. as needed.
|
as needed. The provided completion_cb should then be called with
|
||||||
The provided completion_cb should then be called with either a token
|
either a token or None if sign in failed or was cancelled.
|
||||||
or None if sign in failed or was cancelled.
|
|
||||||
"""
|
"""
|
||||||
from babase._general import Call
|
from babase._general import Call
|
||||||
|
|
||||||
@ -295,7 +300,7 @@ class LoginAdapter:
|
|||||||
|
|
||||||
def _update_implicit_login_state(self) -> None:
|
def _update_implicit_login_state(self) -> None:
|
||||||
# If we've received an implicit login state, schedule it to be
|
# If we've received an implicit login state, schedule it to be
|
||||||
# sent along to the app. We wait until on-app-launch has been
|
# sent along to the app. We wait until on-app-loading has been
|
||||||
# called so that account-client-v2 has had a chance to load
|
# called so that account-client-v2 has had a chance to load
|
||||||
# any existing state so it can properly respond to this.
|
# any existing state so it can properly respond to this.
|
||||||
if self._implicit_login_state_dirty and self._on_app_loading_called:
|
if self._implicit_login_state_dirty and self._on_app_loading_called:
|
||||||
@ -340,8 +345,8 @@ class LoginAdapter:
|
|||||||
class LoginAdapterNative(LoginAdapter):
|
class LoginAdapterNative(LoginAdapter):
|
||||||
"""A login adapter that does its work in the native layer."""
|
"""A login adapter that does its work in the native layer."""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self, login_type: LoginType) -> None:
|
||||||
super().__init__(LoginType.GPGS)
|
super().__init__(login_type)
|
||||||
|
|
||||||
# Store int ids for in-flight attempts since they may go through
|
# Store int ids for in-flight attempts since they may go through
|
||||||
# various platform layers and back.
|
# various platform layers and back.
|
||||||
@ -375,3 +380,13 @@ class LoginAdapterNative(LoginAdapter):
|
|||||||
|
|
||||||
class LoginAdapterGPGS(LoginAdapterNative):
|
class LoginAdapterGPGS(LoginAdapterNative):
|
||||||
"""Google Play Game Services adapter."""
|
"""Google Play Game Services adapter."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__(LoginType.GPGS)
|
||||||
|
|
||||||
|
|
||||||
|
class LoginAdapterGameCenter(LoginAdapterNative):
|
||||||
|
"""Apple Game Center adapter."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__(LoginType.GAME_CENTER)
|
||||||
|
|||||||
@ -24,6 +24,8 @@ if TYPE_CHECKING:
|
|||||||
# instead of these or to make the meta system aware of arbitrary classes.
|
# instead of these or to make the meta system aware of arbitrary classes.
|
||||||
EXPORT_CLASS_NAME_SHORTCUTS: dict[str, str] = {
|
EXPORT_CLASS_NAME_SHORTCUTS: dict[str, str] = {
|
||||||
'plugin': 'babase.Plugin',
|
'plugin': 'babase.Plugin',
|
||||||
|
# DEPRECATED as of 12/2023. Currently am warning if finding these
|
||||||
|
# but should take this out eventually.
|
||||||
'keyboard': 'babase.Keyboard',
|
'keyboard': 'babase.Keyboard',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,30 +416,27 @@ class DirectoryScan:
|
|||||||
if export_class_name is not None:
|
if export_class_name is not None:
|
||||||
classname = modulename + '.' + export_class_name
|
classname = modulename + '.' + export_class_name
|
||||||
|
|
||||||
# Since we'll soon have multiple versions of 'game'
|
# Migrating away from the 'keyboard' name shortcut
|
||||||
# classes we need to migrate people to using base
|
# since it's specific to bauiv1; warn if we find it.
|
||||||
# class names for them.
|
if exporttypestr == 'keyboard':
|
||||||
if exporttypestr == 'game':
|
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"metascan: %s:%d: '# ba_meta export"
|
"metascan: %s:%d: '# ba_meta export"
|
||||||
" game' tag should be replaced by '# ba_meta"
|
" keyboard' tag should be replaced by '# ba_meta"
|
||||||
" export bascenev1.GameActivity'.",
|
" export bauiv1.Keyboard'.",
|
||||||
subpath,
|
subpath,
|
||||||
lindex + 1,
|
lindex + 1,
|
||||||
)
|
)
|
||||||
self.results.announce_errors_occurred = True
|
self.results.announce_errors_occurred = True
|
||||||
else:
|
|
||||||
# If export type is one of our shortcuts, sub in the
|
# If export type is one of our shortcuts, sub in the
|
||||||
# actual class path. Otherwise assume its a classpath
|
# actual class path. Otherwise assume its a classpath
|
||||||
# itself.
|
# itself.
|
||||||
exporttype = EXPORT_CLASS_NAME_SHORTCUTS.get(
|
exporttype = EXPORT_CLASS_NAME_SHORTCUTS.get(exporttypestr)
|
||||||
exporttypestr
|
if exporttype is None:
|
||||||
)
|
exporttype = exporttypestr
|
||||||
if exporttype is None:
|
self.results.exports.setdefault(exporttype, []).append(
|
||||||
exporttype = exporttypestr
|
classname
|
||||||
self.results.exports.setdefault(exporttype, []).append(
|
)
|
||||||
classname
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_export_class_name(
|
def _get_export_class_name(
|
||||||
self, subpath: Path, lines: list[str], lindex: int
|
self, subpath: Path, lines: list[str], lindex: int
|
||||||
|
|||||||
@ -104,8 +104,8 @@ def show_user_scripts() -> None:
|
|||||||
|
|
||||||
_error.print_exception('error writing about_this_folder stuff')
|
_error.print_exception('error writing about_this_folder stuff')
|
||||||
|
|
||||||
# On a few platforms we try to open the dir in the UI.
|
# On platforms that support it, open the dir in the UI.
|
||||||
if app.classic is not None and app.classic.platform in ['mac', 'windows']:
|
if _babase.supports_open_dir_externally():
|
||||||
_babase.open_dir_externally(env.python_directory_user)
|
_babase.open_dir_externally(env.python_directory_user)
|
||||||
|
|
||||||
# Otherwise we just print a pretty version of it.
|
# Otherwise we just print a pretty version of it.
|
||||||
|
|||||||
@ -302,6 +302,11 @@ class AccountV1Subsystem:
|
|||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
plus = babase.app.plus
|
plus = babase.app.plus
|
||||||
if plus is None:
|
if plus is None:
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logging.warning(
|
||||||
|
'Error adding pending promo code; plus not present.'
|
||||||
|
)
|
||||||
babase.screenmessage(
|
babase.screenmessage(
|
||||||
babase.Lstr(resource='errorText'), color=(1, 0, 0)
|
babase.Lstr(resource='errorText'), color=(1, 0, 0)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -4,10 +4,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import babase
|
import babase
|
||||||
import bauiv1
|
|
||||||
import bascenev1
|
import bascenev1
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -31,6 +32,7 @@ class AdsSubsystem:
|
|||||||
self.last_in_game_ad_remove_message_show_time: float | None = None
|
self.last_in_game_ad_remove_message_show_time: float | None = None
|
||||||
self.last_ad_completion_time: float | None = None
|
self.last_ad_completion_time: float | None = None
|
||||||
self.last_ad_was_short = False
|
self.last_ad_was_short = False
|
||||||
|
self._fallback_task: asyncio.Task | None = None
|
||||||
|
|
||||||
def do_remove_in_game_ads_message(self) -> None:
|
def do_remove_in_game_ads_message(self) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
@ -69,7 +71,8 @@ class AdsSubsystem:
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
self.last_ad_purpose = purpose
|
self.last_ad_purpose = purpose
|
||||||
bauiv1.show_ad(purpose, on_completion_call)
|
assert babase.app.plus is not None
|
||||||
|
babase.app.plus.show_ad(purpose, on_completion_call)
|
||||||
|
|
||||||
def show_ad_2(
|
def show_ad_2(
|
||||||
self,
|
self,
|
||||||
@ -78,7 +81,8 @@ class AdsSubsystem:
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
self.last_ad_purpose = purpose
|
self.last_ad_purpose = purpose
|
||||||
bauiv1.show_ad_2(purpose, on_completion_call)
|
assert babase.app.plus is not None
|
||||||
|
babase.app.plus.show_ad_2(purpose, on_completion_call)
|
||||||
|
|
||||||
def call_after_ad(self, call: Callable[[], Any]) -> None:
|
def call_after_ad(self, call: Callable[[], Any]) -> None:
|
||||||
"""Run a call after potentially showing an ad."""
|
"""Run a call after potentially showing an ad."""
|
||||||
@ -94,7 +98,7 @@ class AdsSubsystem:
|
|||||||
show = True
|
show = True
|
||||||
|
|
||||||
# No ads without net-connections, etc.
|
# No ads without net-connections, etc.
|
||||||
if not bauiv1.can_show_ad():
|
if not plus.can_show_ad():
|
||||||
show = False
|
show = False
|
||||||
if classic.accounts.have_pro():
|
if classic.accounts.have_pro():
|
||||||
show = False # Pro disables interstitials.
|
show = False # Pro disables interstitials.
|
||||||
@ -132,7 +136,7 @@ class AdsSubsystem:
|
|||||||
# ad-show-threshold and see if we should *actually* show
|
# ad-show-threshold and see if we should *actually* show
|
||||||
# (we reach our threshold faster the longer we've been
|
# (we reach our threshold faster the longer we've been
|
||||||
# playing).
|
# playing).
|
||||||
base = 'ads' if bauiv1.has_video_ads() else 'ads2'
|
base = 'ads' if plus.has_video_ads() else 'ads2'
|
||||||
min_lc = plus.get_v1_account_misc_read_val(base + '.minLC', 0.0)
|
min_lc = plus.get_v1_account_misc_read_val(base + '.minLC', 0.0)
|
||||||
max_lc = plus.get_v1_account_misc_read_val(base + '.maxLC', 5.0)
|
max_lc = plus.get_v1_account_misc_read_val(base + '.maxLC', 5.0)
|
||||||
min_lc_scale = plus.get_v1_account_misc_read_val(
|
min_lc_scale = plus.get_v1_account_misc_read_val(
|
||||||
@ -181,36 +185,53 @@ class AdsSubsystem:
|
|||||||
|
|
||||||
# If we're *still* cleared to show, actually tell the system to show.
|
# If we're *still* cleared to show, actually tell the system to show.
|
||||||
if show:
|
if show:
|
||||||
# As a safety-check, set up an object that will run
|
# As a safety-check, we set up an object that will run the
|
||||||
# the completion callback if we've returned and sat for 10 seconds
|
# completion callback if we've returned and sat for several
|
||||||
# (in case some random ad network doesn't properly deliver its
|
# seconds (in case some random ad network doesn't properly
|
||||||
# completion callback).
|
# deliver its completion callback).
|
||||||
class _Payload:
|
class _Payload:
|
||||||
def __init__(self, pcall: Callable[[], Any]):
|
def __init__(self, pcall: Callable[[], Any]):
|
||||||
self._call = pcall
|
self._call = pcall
|
||||||
self._ran = False
|
self._ran = False
|
||||||
|
|
||||||
def run(self, fallback: bool = False) -> None:
|
def run(self, fallback: bool = False) -> None:
|
||||||
"""Run fallback call (and issue a warning about it)."""
|
"""Run the payload."""
|
||||||
assert app.classic is not None
|
assert app.classic is not None
|
||||||
if not self._ran:
|
if not self._ran:
|
||||||
if fallback:
|
if fallback:
|
||||||
lanst = app.classic.ads.last_ad_network_set_time
|
lanst = app.classic.ads.last_ad_network_set_time
|
||||||
print(
|
logging.error(
|
||||||
'ERROR: relying on fallback ad-callback! '
|
'Relying on fallback ad-callback! '
|
||||||
'last network: '
|
'last network: %s (set %s seconds ago);'
|
||||||
+ app.classic.ads.last_ad_network
|
' purpose=%s.',
|
||||||
+ ' (set '
|
app.classic.ads.last_ad_network,
|
||||||
+ str(int(time.time() - lanst))
|
time.time() - lanst,
|
||||||
+ 's ago); purpose='
|
app.classic.ads.last_ad_purpose,
|
||||||
+ app.classic.ads.last_ad_purpose
|
|
||||||
)
|
)
|
||||||
babase.pushcall(self._call)
|
babase.pushcall(self._call)
|
||||||
self._ran = True
|
self._ran = True
|
||||||
|
|
||||||
payload = _Payload(call)
|
payload = _Payload(call)
|
||||||
|
|
||||||
|
# Set up our backup.
|
||||||
with babase.ContextRef.empty():
|
with babase.ContextRef.empty():
|
||||||
babase.apptimer(5.0, lambda: payload.run(fallback=True))
|
# Note to self: Previously this was a simple 5 second
|
||||||
|
# timer because the app got totally suspended while ads
|
||||||
|
# were showing (which delayed the timer), but these days
|
||||||
|
# the app may continue to run, so we need to be more
|
||||||
|
# careful and only fire the fallback after we see that
|
||||||
|
# the app has been front-and-center for several seconds.
|
||||||
|
async def add_fallback_task() -> None:
|
||||||
|
activesecs = 5
|
||||||
|
while activesecs > 0:
|
||||||
|
if babase.app.active:
|
||||||
|
activesecs -= 1
|
||||||
|
await asyncio.sleep(1.0)
|
||||||
|
payload.run(fallback=True)
|
||||||
|
|
||||||
|
_fallback_task = babase.app.aioloop.create_task(
|
||||||
|
add_fallback_task()
|
||||||
|
)
|
||||||
self.show_ad('between_game', on_completion_call=payload.run)
|
self.show_ad('between_game', on_completion_call=payload.run)
|
||||||
else:
|
else:
|
||||||
babase.pushcall(call) # Just run the callback without the ad.
|
babase.pushcall(call) # Just run the callback without the ad.
|
||||||
|
|||||||
@ -41,5 +41,6 @@ class AppDelegate:
|
|||||||
sessiontype,
|
sessiontype,
|
||||||
settings,
|
settings,
|
||||||
completion_call=completion_call,
|
completion_call=completion_call,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=False, # Disable check since we don't know.
|
||||||
)
|
)
|
||||||
|
|||||||
@ -8,6 +8,7 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
import babase
|
import babase
|
||||||
import bascenev1
|
import bascenev1
|
||||||
|
import _baclassic
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Sequence
|
from typing import Any, Sequence
|
||||||
@ -54,7 +55,6 @@ def run_stress_test(
|
|||||||
round_duration: int = 30,
|
round_duration: int = 30,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Run a stress test."""
|
"""Run a stress test."""
|
||||||
from babase import modutils
|
|
||||||
|
|
||||||
babase.screenmessage(
|
babase.screenmessage(
|
||||||
"Beginning stress test.. use 'End Test' to stop testing.",
|
"Beginning stress test.. use 'End Test' to stop testing.",
|
||||||
@ -69,22 +69,12 @@ def run_stress_test(
|
|||||||
'round_duration': round_duration,
|
'round_duration': round_duration,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
babase.apptimer(
|
|
||||||
7.0,
|
|
||||||
babase.Call(
|
|
||||||
babase.screenmessage,
|
|
||||||
(
|
|
||||||
'stats will be written to '
|
|
||||||
+ modutils.get_human_readable_user_scripts_path()
|
|
||||||
+ '/stress_test_stats.csv'
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def stop_stress_test() -> None:
|
def stop_stress_test() -> None:
|
||||||
"""End a running stress test."""
|
"""End a running stress test."""
|
||||||
babase.set_stress_testing(False, 0)
|
|
||||||
|
_baclassic.set_stress_testing(False, 0)
|
||||||
assert babase.app.classic is not None
|
assert babase.app.classic is not None
|
||||||
try:
|
try:
|
||||||
if babase.app.classic.stress_test_reset_timer is not None:
|
if babase.app.classic.stress_test_reset_timer is not None:
|
||||||
@ -134,14 +124,14 @@ def start_stress_test(args: dict[str, Any]) -> None:
|
|||||||
babase.Call(bascenev1.new_host_session, FreeForAllSession),
|
babase.Call(bascenev1.new_host_session, FreeForAllSession),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
babase.set_stress_testing(True, args['player_count'])
|
_baclassic.set_stress_testing(True, args['player_count'])
|
||||||
babase.app.classic.stress_test_reset_timer = babase.AppTimer(
|
babase.app.classic.stress_test_reset_timer = babase.AppTimer(
|
||||||
args['round_duration'], babase.Call(_reset_stress_test, args)
|
args['round_duration'], babase.Call(_reset_stress_test, args)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _reset_stress_test(args: dict[str, Any]) -> None:
|
def _reset_stress_test(args: dict[str, Any]) -> None:
|
||||||
babase.set_stress_testing(False, args['player_count'])
|
_baclassic.set_stress_testing(False, args['player_count'])
|
||||||
babase.screenmessage('Resetting stress test...')
|
babase.screenmessage('Resetting stress test...')
|
||||||
session = bascenev1.get_foreground_host_session()
|
session = bascenev1.get_foreground_host_session()
|
||||||
assert session is not None
|
assert session is not None
|
||||||
|
|||||||
@ -20,7 +20,6 @@ def get_input_device_mapped_value(
|
|||||||
This checks the user config and falls back to default values
|
This checks the user config and falls back to default values
|
||||||
where available.
|
where available.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-statements
|
|
||||||
# pylint: disable=too-many-return-statements
|
# pylint: disable=too-many-return-statements
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
|
|
||||||
@ -40,7 +39,14 @@ def get_input_device_mapped_value(
|
|||||||
mapping = ccfgs[devicename][unique_id]
|
mapping = ccfgs[devicename][unique_id]
|
||||||
elif 'default' in ccfgs[devicename]:
|
elif 'default' in ccfgs[devicename]:
|
||||||
mapping = ccfgs[devicename]['default']
|
mapping = ccfgs[devicename]['default']
|
||||||
if mapping is not None:
|
|
||||||
|
# We now use the config mapping *only* if it is not empty.
|
||||||
|
# There have been cases of config writing code messing up
|
||||||
|
# and leaving empty dicts in the app config, which currently
|
||||||
|
# leaves the device unusable. Alternatively, we'd perhaps
|
||||||
|
# want to fall back to defaults for individual missing
|
||||||
|
# values, but that is a bigger change we can make later.
|
||||||
|
if isinstance(mapping, dict) and mapping:
|
||||||
return mapping.get(name, -1)
|
return mapping.get(name, -1)
|
||||||
|
|
||||||
if platform == 'windows':
|
if platform == 'windows':
|
||||||
@ -76,91 +82,6 @@ def get_input_device_mapped_value(
|
|||||||
'triggerRun1': 5,
|
'triggerRun1': 5,
|
||||||
}.get(name, -1)
|
}.get(name, -1)
|
||||||
|
|
||||||
# Look for some exact types.
|
|
||||||
if babase.is_running_on_fire_tv():
|
|
||||||
if devicename in ['Thunder', 'Amazon Fire Game Controller']:
|
|
||||||
return {
|
|
||||||
'triggerRun2': 23,
|
|
||||||
'unassignedButtonsRun': False,
|
|
||||||
'buttonPickUp': 101,
|
|
||||||
'buttonBomb': 98,
|
|
||||||
'buttonJump': 97,
|
|
||||||
'analogStickDeadZone': 0.0,
|
|
||||||
'startButtonActivatesDefaultWidget': False,
|
|
||||||
'buttonStart': 83,
|
|
||||||
'buttonPunch': 100,
|
|
||||||
'buttonRun2': 103,
|
|
||||||
'buttonRun1': 104,
|
|
||||||
'triggerRun1': 24,
|
|
||||||
}.get(name, -1)
|
|
||||||
if devicename == 'NYKO PLAYPAD PRO':
|
|
||||||
return {
|
|
||||||
'triggerRun2': 23,
|
|
||||||
'triggerRun1': 24,
|
|
||||||
'buttonPickUp': 101,
|
|
||||||
'buttonBomb': 98,
|
|
||||||
'buttonJump': 97,
|
|
||||||
'buttonUp': 20,
|
|
||||||
'buttonLeft': 22,
|
|
||||||
'buttonRight': 23,
|
|
||||||
'buttonStart': 83,
|
|
||||||
'buttonPunch': 100,
|
|
||||||
'buttonDown': 21,
|
|
||||||
}.get(name, -1)
|
|
||||||
if devicename == 'Logitech Dual Action':
|
|
||||||
return {
|
|
||||||
'triggerRun2': 23,
|
|
||||||
'triggerRun1': 24,
|
|
||||||
'buttonPickUp': 98,
|
|
||||||
'buttonBomb': 101,
|
|
||||||
'buttonJump': 100,
|
|
||||||
'buttonStart': 109,
|
|
||||||
'buttonPunch': 97,
|
|
||||||
}.get(name, -1)
|
|
||||||
if devicename == 'Xbox 360 Wireless Receiver':
|
|
||||||
return {
|
|
||||||
'triggerRun2': 23,
|
|
||||||
'triggerRun1': 24,
|
|
||||||
'buttonPickUp': 101,
|
|
||||||
'buttonBomb': 98,
|
|
||||||
'buttonJump': 97,
|
|
||||||
'buttonUp': 20,
|
|
||||||
'buttonLeft': 22,
|
|
||||||
'buttonRight': 23,
|
|
||||||
'buttonStart': 83,
|
|
||||||
'buttonPunch': 100,
|
|
||||||
'buttonDown': 21,
|
|
||||||
}.get(name, -1)
|
|
||||||
if devicename == 'Microsoft X-Box 360 pad':
|
|
||||||
return {
|
|
||||||
'triggerRun2': 23,
|
|
||||||
'triggerRun1': 24,
|
|
||||||
'buttonPickUp': 101,
|
|
||||||
'buttonBomb': 98,
|
|
||||||
'buttonJump': 97,
|
|
||||||
'buttonStart': 83,
|
|
||||||
'buttonPunch': 100,
|
|
||||||
}.get(name, -1)
|
|
||||||
if devicename in [
|
|
||||||
'Amazon Remote',
|
|
||||||
'Amazon Bluetooth Dev',
|
|
||||||
'Amazon Fire TV Remote',
|
|
||||||
]:
|
|
||||||
return {
|
|
||||||
'triggerRun2': 23,
|
|
||||||
'triggerRun1': 24,
|
|
||||||
'buttonPickUp': 24,
|
|
||||||
'buttonBomb': 91,
|
|
||||||
'buttonJump': 86,
|
|
||||||
'buttonUp': 20,
|
|
||||||
'buttonLeft': 22,
|
|
||||||
'startButtonActivatesDefaultWidget': False,
|
|
||||||
'buttonRight': 23,
|
|
||||||
'buttonStart': 83,
|
|
||||||
'buttonPunch': 90,
|
|
||||||
'buttonDown': 21,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
elif 'NVIDIA SHIELD;' in useragentstring:
|
elif 'NVIDIA SHIELD;' in useragentstring:
|
||||||
if 'NVIDIA Controller' in devicename:
|
if 'NVIDIA Controller' in devicename:
|
||||||
return {
|
return {
|
||||||
@ -175,112 +96,6 @@ def get_input_device_mapped_value(
|
|||||||
'buttonIgnored': 184,
|
'buttonIgnored': 184,
|
||||||
'buttonIgnored2': 86,
|
'buttonIgnored2': 86,
|
||||||
}.get(name, -1)
|
}.get(name, -1)
|
||||||
elif platform == 'mac':
|
|
||||||
if devicename == 'PLAYSTATION(R)3 Controller':
|
|
||||||
return {
|
|
||||||
'buttonLeft': 8,
|
|
||||||
'buttonUp': 5,
|
|
||||||
'buttonRight': 6,
|
|
||||||
'buttonDown': 7,
|
|
||||||
'buttonJump': 15,
|
|
||||||
'buttonPunch': 16,
|
|
||||||
'buttonBomb': 14,
|
|
||||||
'buttonPickUp': 13,
|
|
||||||
'buttonStart': 4,
|
|
||||||
'buttonIgnored': 17,
|
|
||||||
}.get(name, -1)
|
|
||||||
if devicename in ['Wireless 360 Controller', 'Controller']:
|
|
||||||
# Xbox360 gamepads
|
|
||||||
return {
|
|
||||||
'analogStickDeadZone': 1.2,
|
|
||||||
'buttonBomb': 13,
|
|
||||||
'buttonDown': 2,
|
|
||||||
'buttonJump': 12,
|
|
||||||
'buttonLeft': 3,
|
|
||||||
'buttonPickUp': 15,
|
|
||||||
'buttonPunch': 14,
|
|
||||||
'buttonRight': 4,
|
|
||||||
'buttonStart': 5,
|
|
||||||
'buttonUp': 1,
|
|
||||||
'triggerRun1': 5,
|
|
||||||
'triggerRun2': 6,
|
|
||||||
'buttonIgnored': 11,
|
|
||||||
}.get(name, -1)
|
|
||||||
if devicename in [
|
|
||||||
'Logitech Dual Action',
|
|
||||||
'Logitech Cordless RumblePad 2',
|
|
||||||
]:
|
|
||||||
return {
|
|
||||||
'buttonJump': 2,
|
|
||||||
'buttonPunch': 1,
|
|
||||||
'buttonBomb': 3,
|
|
||||||
'buttonPickUp': 4,
|
|
||||||
'buttonStart': 10,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
# Old gravis gamepad.
|
|
||||||
if devicename == 'GamePad Pro USB ':
|
|
||||||
return {
|
|
||||||
'buttonJump': 2,
|
|
||||||
'buttonPunch': 1,
|
|
||||||
'buttonBomb': 3,
|
|
||||||
'buttonPickUp': 4,
|
|
||||||
'buttonStart': 10,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
if devicename == 'Microsoft SideWinder Plug & Play Game Pad':
|
|
||||||
return {
|
|
||||||
'buttonJump': 1,
|
|
||||||
'buttonPunch': 3,
|
|
||||||
'buttonBomb': 2,
|
|
||||||
'buttonPickUp': 4,
|
|
||||||
'buttonStart': 6,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
# Saitek P2500 Rumble Force Pad.. (hopefully works for others too?..)
|
|
||||||
if devicename == 'Saitek P2500 Rumble Force Pad':
|
|
||||||
return {
|
|
||||||
'buttonJump': 3,
|
|
||||||
'buttonPunch': 1,
|
|
||||||
'buttonBomb': 4,
|
|
||||||
'buttonPickUp': 2,
|
|
||||||
'buttonStart': 11,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
# Some crazy 'Senze' dual gamepad.
|
|
||||||
if devicename == 'Twin USB Joystick':
|
|
||||||
return {
|
|
||||||
'analogStickLR': 3,
|
|
||||||
'analogStickLR_B': 7,
|
|
||||||
'analogStickUD': 4,
|
|
||||||
'analogStickUD_B': 8,
|
|
||||||
'buttonBomb': 2,
|
|
||||||
'buttonBomb_B': 14,
|
|
||||||
'buttonJump': 3,
|
|
||||||
'buttonJump_B': 15,
|
|
||||||
'buttonPickUp': 1,
|
|
||||||
'buttonPickUp_B': 13,
|
|
||||||
'buttonPunch': 4,
|
|
||||||
'buttonPunch_B': 16,
|
|
||||||
'buttonRun1': 7,
|
|
||||||
'buttonRun1_B': 19,
|
|
||||||
'buttonRun2': 8,
|
|
||||||
'buttonRun2_B': 20,
|
|
||||||
'buttonStart': 10,
|
|
||||||
'buttonStart_B': 22,
|
|
||||||
'enableSecondary': 1,
|
|
||||||
'unassignedButtonsRun': False,
|
|
||||||
}.get(name, -1)
|
|
||||||
if devicename == 'USB Gamepad ': # some weird 'JITE' gamepad
|
|
||||||
return {
|
|
||||||
'analogStickLR': 4,
|
|
||||||
'analogStickUD': 5,
|
|
||||||
'buttonJump': 3,
|
|
||||||
'buttonPunch': 4,
|
|
||||||
'buttonBomb': 2,
|
|
||||||
'buttonPickUp': 1,
|
|
||||||
'buttonStart': 10,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
default_android_mapping = {
|
default_android_mapping = {
|
||||||
'triggerRun2': 19,
|
'triggerRun2': 19,
|
||||||
@ -303,6 +118,41 @@ def get_input_device_mapped_value(
|
|||||||
|
|
||||||
# Generic android...
|
# Generic android...
|
||||||
if platform == 'android':
|
if platform == 'android':
|
||||||
|
if devicename in ['Amazon Fire Game Controller']:
|
||||||
|
return {
|
||||||
|
'triggerRun2': 23,
|
||||||
|
'unassignedButtonsRun': False,
|
||||||
|
'buttonPickUp': 101,
|
||||||
|
'buttonBomb': 98,
|
||||||
|
'buttonJump': 97,
|
||||||
|
'analogStickDeadZone': 0.0,
|
||||||
|
'startButtonActivatesDefaultWidget': False,
|
||||||
|
'buttonStart': 83,
|
||||||
|
'buttonPunch': 100,
|
||||||
|
'buttonRun2': 103,
|
||||||
|
'buttonRun1': 104,
|
||||||
|
'triggerRun1': 24,
|
||||||
|
}.get(name, -1)
|
||||||
|
if devicename in [
|
||||||
|
'Amazon Remote',
|
||||||
|
'Amazon Bluetooth Dev',
|
||||||
|
'Amazon Fire TV Remote',
|
||||||
|
]:
|
||||||
|
return {
|
||||||
|
'triggerRun2': 23,
|
||||||
|
'triggerRun1': 24,
|
||||||
|
'buttonPickUp': 24,
|
||||||
|
'buttonBomb': 91,
|
||||||
|
'buttonJump': 86,
|
||||||
|
'buttonUp': 20,
|
||||||
|
'buttonLeft': 22,
|
||||||
|
'startButtonActivatesDefaultWidget': False,
|
||||||
|
'buttonRight': 23,
|
||||||
|
'buttonStart': 83,
|
||||||
|
'buttonPunch': 90,
|
||||||
|
'buttonDown': 21,
|
||||||
|
}.get(name, -1)
|
||||||
|
|
||||||
# Steelseries stratus xl.
|
# Steelseries stratus xl.
|
||||||
if devicename == 'SteelSeries Stratus XL':
|
if devicename == 'SteelSeries Stratus XL':
|
||||||
return {
|
return {
|
||||||
@ -380,14 +230,6 @@ def get_input_device_mapped_value(
|
|||||||
'uiOnly': True,
|
'uiOnly': True,
|
||||||
}.get(name, -1)
|
}.get(name, -1)
|
||||||
|
|
||||||
# flag particular gamepads to use exact android defaults..
|
|
||||||
# (so they don't even ask to configure themselves)
|
|
||||||
if devicename in [
|
|
||||||
'Samsung Game Pad EI-GP20',
|
|
||||||
'ASUS Gamepad',
|
|
||||||
] or devicename.startswith('Freefly VR Glide'):
|
|
||||||
return default_android_mapping.get(name, -1)
|
|
||||||
|
|
||||||
# Nvidia controller is default, but gets some strange
|
# Nvidia controller is default, but gets some strange
|
||||||
# keypresses we want to ignore.. touching the touchpad,
|
# keypresses we want to ignore.. touching the touchpad,
|
||||||
# so lets ignore those.
|
# so lets ignore those.
|
||||||
@ -445,76 +287,11 @@ def get_input_device_mapped_value(
|
|||||||
'buttonRight': 100,
|
'buttonRight': 100,
|
||||||
}.get(name, -1)
|
}.get(name, -1)
|
||||||
|
|
||||||
# Ok, this gamepad's not in our specific preset list;
|
# Ok, this gamepad's not in our specific preset list; fall back to
|
||||||
# fall back to some (hopefully) reasonable defaults.
|
# some (hopefully) reasonable defaults.
|
||||||
|
|
||||||
# Leaving these in here for now but not gonna add any more now that we have
|
|
||||||
# fancy-pants config sharing across the internet.
|
|
||||||
if platform == 'mac':
|
|
||||||
if 'PLAYSTATION' in devicename: # ps3 gamepad?..
|
|
||||||
return {
|
|
||||||
'buttonLeft': 8,
|
|
||||||
'buttonUp': 5,
|
|
||||||
'buttonRight': 6,
|
|
||||||
'buttonDown': 7,
|
|
||||||
'buttonJump': 15,
|
|
||||||
'buttonPunch': 16,
|
|
||||||
'buttonBomb': 14,
|
|
||||||
'buttonPickUp': 13,
|
|
||||||
'buttonStart': 4,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
# Dual Action Config - hopefully applies to more...
|
|
||||||
if 'Logitech' in devicename:
|
|
||||||
return {
|
|
||||||
'buttonJump': 2,
|
|
||||||
'buttonPunch': 1,
|
|
||||||
'buttonBomb': 3,
|
|
||||||
'buttonPickUp': 4,
|
|
||||||
'buttonStart': 10,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
# Saitek P2500 Rumble Force Pad.. (hopefully works for others too?..)
|
|
||||||
if 'Saitek' in devicename:
|
|
||||||
return {
|
|
||||||
'buttonJump': 3,
|
|
||||||
'buttonPunch': 1,
|
|
||||||
'buttonBomb': 4,
|
|
||||||
'buttonPickUp': 2,
|
|
||||||
'buttonStart': 11,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
# Gravis stuff?...
|
|
||||||
if 'GamePad' in devicename:
|
|
||||||
return {
|
|
||||||
'buttonJump': 2,
|
|
||||||
'buttonPunch': 1,
|
|
||||||
'buttonBomb': 3,
|
|
||||||
'buttonPickUp': 4,
|
|
||||||
'buttonStart': 10,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
# Reasonable defaults.
|
# Reasonable defaults.
|
||||||
if platform == 'android':
|
if platform == 'android':
|
||||||
if babase.is_running_on_fire_tv():
|
|
||||||
# Mostly same as default firetv controller.
|
|
||||||
return {
|
|
||||||
'triggerRun2': 23,
|
|
||||||
'triggerRun1': 24,
|
|
||||||
'buttonPickUp': 101,
|
|
||||||
'buttonBomb': 98,
|
|
||||||
'buttonJump': 97,
|
|
||||||
'buttonStart': 83,
|
|
||||||
'buttonPunch': 100,
|
|
||||||
'buttonDown': 21,
|
|
||||||
'buttonUp': 20,
|
|
||||||
'buttonLeft': 22,
|
|
||||||
'buttonRight': 23,
|
|
||||||
'startButtonActivatesDefaultWidget': False,
|
|
||||||
}.get(name, -1)
|
|
||||||
|
|
||||||
# Mostly same as 'Gamepad' except with 'menu' for default start
|
|
||||||
# button instead of 'mode'.
|
|
||||||
return default_android_mapping.get(name, -1)
|
return default_android_mapping.get(name, -1)
|
||||||
|
|
||||||
# Is there a point to any sort of fallbacks here?.. should check.
|
# Is there a point to any sort of fallbacks here?.. should check.
|
||||||
@ -533,9 +310,9 @@ def _gen_android_input_hash() -> str:
|
|||||||
|
|
||||||
md5 = hashlib.md5()
|
md5 = hashlib.md5()
|
||||||
|
|
||||||
# Currently we just do a single hash of *all* inputs on android
|
# Currently we just do a single hash of *all* inputs on android and
|
||||||
# and that's it.. good enough.
|
# that's it. Good enough. (grabbing mappings for a specific device
|
||||||
# (grabbing mappings for a specific device looks to be non-trivial)
|
# looks to be non-trivial)
|
||||||
for dirname in [
|
for dirname in [
|
||||||
'/system/usr/keylayout',
|
'/system/usr/keylayout',
|
||||||
'/data/usr/keylayout',
|
'/data/usr/keylayout',
|
||||||
@ -544,9 +321,9 @@ def _gen_android_input_hash() -> str:
|
|||||||
try:
|
try:
|
||||||
if os.path.isdir(dirname):
|
if os.path.isdir(dirname):
|
||||||
for f_name in os.listdir(dirname):
|
for f_name in os.listdir(dirname):
|
||||||
# This is usually volume keys and stuff;
|
# This is usually volume keys and stuff; assume we
|
||||||
# assume we can skip it?..
|
# can skip it?.. (since it'll vary a lot across
|
||||||
# (since it'll vary a lot across devices)
|
# devices)
|
||||||
if f_name == 'gpio-keys.kl':
|
if f_name == 'gpio-keys.kl':
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
@ -569,8 +346,8 @@ def get_input_device_map_hash() -> str:
|
|||||||
"""
|
"""
|
||||||
app = babase.app
|
app = babase.app
|
||||||
|
|
||||||
# Currently only using this when classic is present.
|
# Currently only using this when classic is present. Need to replace
|
||||||
# Need to replace with a modern equivalent.
|
# with a modern equivalent.
|
||||||
if app.classic is not None:
|
if app.classic is not None:
|
||||||
try:
|
try:
|
||||||
if app.classic.input_map_hash is None:
|
if app.classic.input_map_hash is None:
|
||||||
|
|||||||
@ -165,15 +165,16 @@ class MusicSubsystem:
|
|||||||
|
|
||||||
def supports_soundtrack_entry_type(self, entry_type: str) -> bool:
|
def supports_soundtrack_entry_type(self, entry_type: str) -> bool:
|
||||||
"""Return whether provided soundtrack entry type is supported here."""
|
"""Return whether provided soundtrack entry type is supported here."""
|
||||||
uas = babase.env()['legacy_user_agent_string']
|
# Note to self; can't access babase.app.classic here because
|
||||||
assert isinstance(uas, str)
|
# we are called during its construction.
|
||||||
|
env = babase.env()
|
||||||
# FIXME: Generalize this.
|
platform = env.get('platform')
|
||||||
|
assert isinstance(platform, str)
|
||||||
if entry_type == 'iTunesPlaylist':
|
if entry_type == 'iTunesPlaylist':
|
||||||
return 'Mac' in uas
|
return platform == 'mac' and babase.is_xcode_build()
|
||||||
if entry_type in ('musicFile', 'musicFolder'):
|
if entry_type in ('musicFile', 'musicFolder'):
|
||||||
return (
|
return (
|
||||||
'android' in uas
|
platform == 'android'
|
||||||
and babase.android_get_external_files_dir() is not None
|
and babase.android_get_external_files_dir() is not None
|
||||||
)
|
)
|
||||||
if entry_type == 'default':
|
if entry_type == 'default':
|
||||||
|
|||||||
@ -423,6 +423,10 @@ class ServerController:
|
|||||||
bascenev1.set_public_party_stats_url(self._config.stats_url)
|
bascenev1.set_public_party_stats_url(self._config.stats_url)
|
||||||
bascenev1.set_public_party_enabled(self._config.party_is_public)
|
bascenev1.set_public_party_enabled(self._config.party_is_public)
|
||||||
|
|
||||||
|
bascenev1.set_player_rejoin_cooldown(
|
||||||
|
self._config.player_rejoin_cooldown
|
||||||
|
)
|
||||||
|
|
||||||
# And here.. we.. go.
|
# And here.. we.. go.
|
||||||
if self._config.stress_test_players is not None:
|
if self._config.stress_test_players is not None:
|
||||||
# Special case: run a stress test.
|
# Special case: run a stress test.
|
||||||
|
|||||||
@ -451,15 +451,6 @@ class ClassicSubsystem(babase.AppSubsystem):
|
|||||||
if playtype in val.get_play_types()
|
if playtype in val.get_play_types()
|
||||||
)
|
)
|
||||||
|
|
||||||
def show_online_score_ui(
|
|
||||||
self,
|
|
||||||
show: str = 'general',
|
|
||||||
game: str | None = None,
|
|
||||||
game_version: str | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""(internal)"""
|
|
||||||
bauiv1.show_online_score_ui(show, game, game_version)
|
|
||||||
|
|
||||||
def game_begin_analytics(self) -> None:
|
def game_begin_analytics(self) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
from baclassic import _analytics
|
from baclassic import _analytics
|
||||||
@ -627,15 +618,6 @@ class ClassicSubsystem(babase.AppSubsystem):
|
|||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
return bascenev1.get_foreground_host_activity()
|
return bascenev1.get_foreground_host_activity()
|
||||||
|
|
||||||
def show_config_error_window(self) -> bool:
|
|
||||||
"""(internal)"""
|
|
||||||
if self.platform in ('mac', 'linux', 'windows'):
|
|
||||||
from bauiv1lib.configerror import ConfigErrorWindow
|
|
||||||
|
|
||||||
babase.pushcall(ConfigErrorWindow)
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def value_test(
|
def value_test(
|
||||||
self,
|
self,
|
||||||
arg: str,
|
arg: str,
|
||||||
@ -809,5 +791,6 @@ class ClassicSubsystem(babase.AppSubsystem):
|
|||||||
bauiv1.getsound('swish').play()
|
bauiv1.getsound('swish').play()
|
||||||
|
|
||||||
babase.app.ui_v1.set_main_menu_window(
|
babase.app.ui_v1.set_main_menu_window(
|
||||||
MainMenuWindow().get_root_widget()
|
MainMenuWindow().get_root_widget(),
|
||||||
|
from_window=False, # Disable check here.
|
||||||
)
|
)
|
||||||
|
|||||||
@ -80,14 +80,13 @@ class _MacMusicAppThread(threading.Thread):
|
|||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
"""Run the Music.app thread."""
|
"""Run the Music.app thread."""
|
||||||
babase.set_thread_name('BA_MacMusicAppThread')
|
babase.set_thread_name('BA_MacMusicAppThread')
|
||||||
babase.mac_music_app_init()
|
|
||||||
|
|
||||||
# Let's mention to the user we're launching Music.app in case
|
# Let's mention to the user we're launching Music.app in case
|
||||||
# it causes any funny business (this used to background the app
|
# it causes any funny business (this used to background the app
|
||||||
# sometimes, though I think that is fixed now)
|
# sometimes, though I think that is fixed now)
|
||||||
def do_print() -> None:
|
def do_print() -> None:
|
||||||
babase.apptimer(
|
babase.apptimer(
|
||||||
1.0,
|
0.5,
|
||||||
babase.Call(
|
babase.Call(
|
||||||
babase.screenmessage,
|
babase.screenmessage,
|
||||||
babase.Lstr(resource='usingItunesText'),
|
babase.Lstr(resource='usingItunesText'),
|
||||||
@ -97,9 +96,8 @@ class _MacMusicAppThread(threading.Thread):
|
|||||||
|
|
||||||
babase.pushcall(do_print, from_other_thread=True)
|
babase.pushcall(do_print, from_other_thread=True)
|
||||||
|
|
||||||
# Here we grab this to force the actual launch.
|
babase.mac_music_app_init()
|
||||||
babase.mac_music_app_get_volume()
|
|
||||||
babase.mac_music_app_get_library_source()
|
|
||||||
done = False
|
done = False
|
||||||
while not done:
|
while not done:
|
||||||
self._commands_available.wait()
|
self._commands_available.wait()
|
||||||
|
|||||||
@ -40,7 +40,7 @@ if TYPE_CHECKING:
|
|||||||
# the last load. Either way, however, multiple execs will happen in some
|
# the last load. Either way, however, multiple execs will happen in some
|
||||||
# form.
|
# form.
|
||||||
#
|
#
|
||||||
# So we need to do a few things to handle that situation gracefully.
|
# To handle that situation gracefully, we need to do a few things:
|
||||||
#
|
#
|
||||||
# - First, we need to store any mutable global state in the __main__
|
# - First, we need to store any mutable global state in the __main__
|
||||||
# module; not in ourself. This way, alternate versions of ourself will
|
# module; not in ourself. This way, alternate versions of ourself will
|
||||||
@ -48,12 +48,12 @@ if TYPE_CHECKING:
|
|||||||
#
|
#
|
||||||
# - Second, we should avoid the use of isinstance and similar calls for
|
# - Second, we should avoid the use of isinstance and similar calls for
|
||||||
# our types. An EnvConfig we create would technically be a different
|
# our types. An EnvConfig we create would technically be a different
|
||||||
# type than that created by an alternate baenv.
|
# type than an EnvConfig created by an alternate baenv.
|
||||||
|
|
||||||
# Build number and version of the ballistica binary we expect to be
|
# Build number and version of the ballistica binary we expect to be
|
||||||
# using.
|
# using.
|
||||||
TARGET_BALLISTICA_BUILD = 21445
|
TARGET_BALLISTICA_BUILD = 21743
|
||||||
TARGET_BALLISTICA_VERSION = '1.7.28'
|
TARGET_BALLISTICA_VERSION = '1.7.33'
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Released under the MIT License. See LICENSE for details.
|
# Released under the MIT License. See LICENSE for details.
|
||||||
#
|
#
|
||||||
"""Provides classic app subsystem."""
|
"""Provides plus app subsystem."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
@ -249,3 +249,41 @@ class PlusSubsystem(AppSubsystem):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
return _baplus.tournament_query(callback, args)
|
return _baplus.tournament_query(callback, args)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def have_incentivized_ad() -> bool:
|
||||||
|
"""Is an incentivized ad available?"""
|
||||||
|
return _baplus.have_incentivized_ad()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def has_video_ads() -> bool:
|
||||||
|
"""Are video ads available?"""
|
||||||
|
return _baplus.has_video_ads()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def can_show_ad() -> bool:
|
||||||
|
"""Can we show an ad?"""
|
||||||
|
return _baplus.can_show_ad()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def show_ad(
|
||||||
|
purpose: str, on_completion_call: Callable[[], None] | None = None
|
||||||
|
) -> None:
|
||||||
|
"""Show an ad."""
|
||||||
|
_baplus.show_ad(purpose, on_completion_call)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def show_ad_2(
|
||||||
|
purpose: str, on_completion_call: Callable[[bool], None] | None = None
|
||||||
|
) -> None:
|
||||||
|
"""Show an ad."""
|
||||||
|
_baplus.show_ad_2(purpose, on_completion_call)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def show_game_service_ui(
|
||||||
|
show: str = 'general',
|
||||||
|
game: str | None = None,
|
||||||
|
game_version: str | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Show game-service provided UI."""
|
||||||
|
_baplus.show_game_service_ui(show, game, game_version)
|
||||||
|
|||||||
@ -78,6 +78,7 @@ from _bascenev1 import (
|
|||||||
end_host_scanning,
|
end_host_scanning,
|
||||||
get_chat_messages,
|
get_chat_messages,
|
||||||
get_connection_to_host_info,
|
get_connection_to_host_info,
|
||||||
|
get_connection_to_host_info_2,
|
||||||
get_foreground_host_activity,
|
get_foreground_host_activity,
|
||||||
get_foreground_host_session,
|
get_foreground_host_session,
|
||||||
get_game_port,
|
get_game_port,
|
||||||
@ -202,6 +203,7 @@ from bascenev1._multiteamsession import (
|
|||||||
DEFAULT_TEAM_NAMES,
|
DEFAULT_TEAM_NAMES,
|
||||||
)
|
)
|
||||||
from bascenev1._music import MusicType, setmusic
|
from bascenev1._music import MusicType, setmusic
|
||||||
|
from bascenev1._net import HostInfo
|
||||||
from bascenev1._nodeactor import NodeActor
|
from bascenev1._nodeactor import NodeActor
|
||||||
from bascenev1._powerup import get_default_powerup_distribution
|
from bascenev1._powerup import get_default_powerup_distribution
|
||||||
from bascenev1._profile import (
|
from bascenev1._profile import (
|
||||||
@ -226,7 +228,7 @@ from bascenev1._settings import (
|
|||||||
IntSetting,
|
IntSetting,
|
||||||
Setting,
|
Setting,
|
||||||
)
|
)
|
||||||
from bascenev1._session import Session
|
from bascenev1._session import Session, set_player_rejoin_cooldown
|
||||||
from bascenev1._stats import PlayerScoredMessage, PlayerRecord, Stats
|
from bascenev1._stats import PlayerScoredMessage, PlayerRecord, Stats
|
||||||
from bascenev1._team import SessionTeam, Team, EmptyTeam
|
from bascenev1._team import SessionTeam, Team, EmptyTeam
|
||||||
from bascenev1._teamgame import TeamGameActivity
|
from bascenev1._teamgame import TeamGameActivity
|
||||||
@ -303,6 +305,7 @@ __all__ = [
|
|||||||
'GameTip',
|
'GameTip',
|
||||||
'get_chat_messages',
|
'get_chat_messages',
|
||||||
'get_connection_to_host_info',
|
'get_connection_to_host_info',
|
||||||
|
'get_connection_to_host_info_2',
|
||||||
'get_default_free_for_all_playlist',
|
'get_default_free_for_all_playlist',
|
||||||
'get_default_teams_playlist',
|
'get_default_teams_playlist',
|
||||||
'get_default_powerup_distribution',
|
'get_default_powerup_distribution',
|
||||||
@ -338,6 +341,7 @@ __all__ = [
|
|||||||
'have_connected_clients',
|
'have_connected_clients',
|
||||||
'have_touchscreen_input',
|
'have_touchscreen_input',
|
||||||
'HitMessage',
|
'HitMessage',
|
||||||
|
'HostInfo',
|
||||||
'host_scan_cycle',
|
'host_scan_cycle',
|
||||||
'ImpactDamageMessage',
|
'ImpactDamageMessage',
|
||||||
'increment_analytics_count',
|
'increment_analytics_count',
|
||||||
@ -415,6 +419,7 @@ __all__ = [
|
|||||||
'set_public_party_name',
|
'set_public_party_name',
|
||||||
'set_public_party_queue_enabled',
|
'set_public_party_queue_enabled',
|
||||||
'set_public_party_stats_url',
|
'set_public_party_stats_url',
|
||||||
|
'set_player_rejoin_cooldown',
|
||||||
'set_replay_speed_exponent',
|
'set_replay_speed_exponent',
|
||||||
'set_touchscreen_editing',
|
'set_touchscreen_editing',
|
||||||
'setmusic',
|
'setmusic',
|
||||||
|
|||||||
@ -6,7 +6,13 @@ from __future__ import annotations
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from bacommon.app import AppExperience
|
from bacommon.app import AppExperience
|
||||||
from babase import AppMode, AppIntentExec, AppIntentDefault
|
from babase import (
|
||||||
|
app,
|
||||||
|
AppMode,
|
||||||
|
AppIntentExec,
|
||||||
|
AppIntentDefault,
|
||||||
|
invoke_main_menu,
|
||||||
|
)
|
||||||
|
|
||||||
import _bascenev1
|
import _bascenev1
|
||||||
|
|
||||||
@ -40,3 +46,9 @@ class SceneV1AppMode(AppMode):
|
|||||||
def on_deactivate(self) -> None:
|
def on_deactivate(self) -> None:
|
||||||
# Let the native layer do its thing.
|
# Let the native layer do its thing.
|
||||||
_bascenev1.on_app_mode_deactivate()
|
_bascenev1.on_app_mode_deactivate()
|
||||||
|
|
||||||
|
def on_app_active_changed(self) -> None:
|
||||||
|
# If we've gone inactive, bring up the main menu, which has the
|
||||||
|
# side effect of pausing the action (when possible).
|
||||||
|
if not app.active:
|
||||||
|
invoke_main_menu()
|
||||||
|
|||||||
@ -438,10 +438,16 @@ class GameActivity(Activity[PlayerT, TeamT]):
|
|||||||
assert classic is not None
|
assert classic is not None
|
||||||
continues_window = classic.continues_window
|
continues_window = classic.continues_window
|
||||||
|
|
||||||
|
# Turning these off. I want to migrate towards monetization that
|
||||||
|
# feels less pay-to-win-ish.
|
||||||
|
allow_continues = False
|
||||||
|
|
||||||
plus = babase.app.plus
|
plus = babase.app.plus
|
||||||
try:
|
try:
|
||||||
if plus is not None and plus.get_v1_account_misc_read_val(
|
if (
|
||||||
'enableContinues', False
|
plus is not None
|
||||||
|
and plus.get_v1_account_misc_read_val('enableContinues', False)
|
||||||
|
and allow_continues
|
||||||
):
|
):
|
||||||
session = self.session
|
session = self.session
|
||||||
|
|
||||||
|
|||||||
24
src/assets/ba_data/python/bascenev1/_net.py
Normal file
24
src/assets/ba_data/python/bascenev1/_net.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Released under the MIT License. See LICENSE for details.
|
||||||
|
#
|
||||||
|
"""Functionality related to net play."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class HostInfo:
|
||||||
|
"""Info about a host."""
|
||||||
|
|
||||||
|
name: str
|
||||||
|
build_number: int
|
||||||
|
|
||||||
|
# Note this can be None for non-ip hosts such as bluetooth.
|
||||||
|
address: str | None
|
||||||
|
|
||||||
|
# Note this can be None for non-ip hosts such as bluetooth.
|
||||||
|
port: int | None
|
||||||
@ -3,6 +3,7 @@
|
|||||||
"""Defines base session class."""
|
"""Defines base session class."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
import weakref
|
import weakref
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
@ -17,6 +18,17 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
import bascenev1
|
import bascenev1
|
||||||
|
|
||||||
|
# How many seconds someone who left the session (but not the party) must
|
||||||
|
# wait to rejoin the session again. Intended to prevent game exploits
|
||||||
|
# such as skipping respawn waits.
|
||||||
|
_g_player_rejoin_cooldown: float = 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def set_player_rejoin_cooldown(cooldown: float) -> None:
|
||||||
|
"""Set the cooldown for individual players rejoining after leaving."""
|
||||||
|
global _g_player_rejoin_cooldown # pylint: disable=global-statement
|
||||||
|
_g_player_rejoin_cooldown = max(0.0, cooldown)
|
||||||
|
|
||||||
|
|
||||||
class Session:
|
class Session:
|
||||||
"""Defines a high level series of bascenev1.Activity-es.
|
"""Defines a high level series of bascenev1.Activity-es.
|
||||||
@ -203,6 +215,11 @@ class Session:
|
|||||||
# Instantiate our session globals node which will apply its settings.
|
# Instantiate our session globals node which will apply its settings.
|
||||||
self._sessionglobalsnode = _bascenev1.newnode('sessionglobals')
|
self._sessionglobalsnode = _bascenev1.newnode('sessionglobals')
|
||||||
|
|
||||||
|
# Rejoin cooldown stuff.
|
||||||
|
self._players_on_wait: dict = {}
|
||||||
|
self._player_requested_identifiers: dict = {}
|
||||||
|
self._waitlist_timers: dict = {}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def context(self) -> bascenev1.ContextRef:
|
def context(self) -> bascenev1.ContextRef:
|
||||||
"""A context-ref pointing at this activity."""
|
"""A context-ref pointing at this activity."""
|
||||||
@ -253,6 +270,33 @@ class Session:
|
|||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Rejoin cooldown.
|
||||||
|
identifier = player.get_v1_account_id()
|
||||||
|
if identifier:
|
||||||
|
leave_time = self._players_on_wait.get(identifier)
|
||||||
|
if leave_time:
|
||||||
|
diff = str(
|
||||||
|
math.ceil(
|
||||||
|
_g_player_rejoin_cooldown
|
||||||
|
- babase.apptime()
|
||||||
|
+ leave_time
|
||||||
|
)
|
||||||
|
)
|
||||||
|
_bascenev1.broadcastmessage(
|
||||||
|
babase.Lstr(
|
||||||
|
translate=(
|
||||||
|
'serverResponses',
|
||||||
|
'You can join in ${COUNT} seconds.',
|
||||||
|
),
|
||||||
|
subs=[('${COUNT}', diff)],
|
||||||
|
),
|
||||||
|
color=(1, 1, 0),
|
||||||
|
clients=[player.inputdevice.client_id],
|
||||||
|
transient=True,
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
self._player_requested_identifiers[player.id] = identifier
|
||||||
|
|
||||||
_bascenev1.getsound('dripity').play()
|
_bascenev1.getsound('dripity').play()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -270,6 +314,16 @@ class Session:
|
|||||||
|
|
||||||
activity = self._activity_weak()
|
activity = self._activity_weak()
|
||||||
|
|
||||||
|
# Rejoin cooldown.
|
||||||
|
identifier = self._player_requested_identifiers.get(sessionplayer.id)
|
||||||
|
if identifier:
|
||||||
|
self._players_on_wait[identifier] = babase.apptime()
|
||||||
|
with babase.ContextRef.empty():
|
||||||
|
self._waitlist_timers[identifier] = babase.AppTimer(
|
||||||
|
_g_player_rejoin_cooldown,
|
||||||
|
babase.Call(self._remove_player_from_waitlist, identifier),
|
||||||
|
)
|
||||||
|
|
||||||
if not sessionplayer.in_game:
|
if not sessionplayer.in_game:
|
||||||
# Ok, the player is still in the lobby; simply remove them.
|
# Ok, the player is still in the lobby; simply remove them.
|
||||||
with self.context:
|
with self.context:
|
||||||
@ -770,3 +824,9 @@ class Session:
|
|||||||
if pass_to_activity:
|
if pass_to_activity:
|
||||||
activity.add_player(sessionplayer)
|
activity.add_player(sessionplayer)
|
||||||
return sessionplayer
|
return sessionplayer
|
||||||
|
|
||||||
|
def _remove_player_from_waitlist(self, identifier: str) -> None:
|
||||||
|
try:
|
||||||
|
self._players_on_wait.pop(identifier)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import random
|
|||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from bacommon.login import LoginType
|
||||||
import bascenev1 as bs
|
import bascenev1 as bs
|
||||||
import bauiv1 as bui
|
import bauiv1 as bui
|
||||||
|
|
||||||
@ -59,29 +60,25 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self._account_type = (
|
|
||||||
plus.get_v1_account_type()
|
|
||||||
if plus.get_v1_account_state() == 'signed_in'
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
|
|
||||||
self._game_service_icon_color: Sequence[float] | None
|
self._game_service_icon_color: Sequence[float] | None
|
||||||
self._game_service_achievements_texture: bui.Texture | None
|
self._game_service_achievements_texture: bui.Texture | None
|
||||||
self._game_service_leaderboards_texture: bui.Texture | None
|
self._game_service_leaderboards_texture: bui.Texture | None
|
||||||
|
|
||||||
if self._account_type == 'Game Center':
|
# Tie in to specific game services if they are active.
|
||||||
|
adapter = plus.accounts.login_adapters.get(LoginType.GPGS)
|
||||||
|
gpgs_active = adapter is not None and adapter.is_back_end_active()
|
||||||
|
adapter = plus.accounts.login_adapters.get(LoginType.GAME_CENTER)
|
||||||
|
game_center_active = (
|
||||||
|
adapter is not None and adapter.is_back_end_active()
|
||||||
|
)
|
||||||
|
|
||||||
|
if game_center_active:
|
||||||
self._game_service_icon_color = (1.0, 1.0, 1.0)
|
self._game_service_icon_color = (1.0, 1.0, 1.0)
|
||||||
icon = bui.gettexture('gameCenterIcon')
|
icon = bui.gettexture('gameCenterIcon')
|
||||||
self._game_service_achievements_texture = icon
|
self._game_service_achievements_texture = icon
|
||||||
self._game_service_leaderboards_texture = icon
|
self._game_service_leaderboards_texture = icon
|
||||||
self._account_has_achievements = True
|
self._account_has_achievements = True
|
||||||
elif self._account_type == 'Game Circle':
|
elif gpgs_active:
|
||||||
icon = bui.gettexture('gameCircleIcon')
|
|
||||||
self._game_service_icon_color = (1, 1, 1)
|
|
||||||
self._game_service_achievements_texture = icon
|
|
||||||
self._game_service_leaderboards_texture = icon
|
|
||||||
self._account_has_achievements = True
|
|
||||||
elif self._account_type == 'Google Play':
|
|
||||||
self._game_service_icon_color = (0.8, 1.0, 0.6)
|
self._game_service_icon_color = (0.8, 1.0, 0.6)
|
||||||
self._game_service_achievements_texture = bui.gettexture(
|
self._game_service_achievements_texture = bui.gettexture(
|
||||||
'googlePlayAchievementsIcon'
|
'googlePlayAchievementsIcon'
|
||||||
@ -193,7 +190,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
|||||||
super().__del__()
|
super().__del__()
|
||||||
|
|
||||||
# If our UI is still up, kill it.
|
# If our UI is still up, kill it.
|
||||||
if self._root_ui:
|
if self._root_ui and not self._root_ui.transitioning_out:
|
||||||
with bui.ContextRef.empty():
|
with bui.ContextRef.empty():
|
||||||
bui.containerwidget(edit=self._root_ui, transition='out_left')
|
bui.containerwidget(edit=self._root_ui, transition='out_left')
|
||||||
|
|
||||||
@ -287,20 +284,20 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
|
|||||||
self.end({'outcome': 'next_level'})
|
self.end({'outcome': 'next_level'})
|
||||||
|
|
||||||
def _ui_gc(self) -> None:
|
def _ui_gc(self) -> None:
|
||||||
if bs.app.classic is not None:
|
if bs.app.plus is not None:
|
||||||
bs.app.classic.show_online_score_ui(
|
bs.app.plus.show_game_service_ui(
|
||||||
'leaderboard',
|
'leaderboard',
|
||||||
game=self._game_name_str,
|
game=self._game_name_str,
|
||||||
game_version=self._game_config_str,
|
game_version=self._game_config_str,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logging.warning('show_online_score_ui requires classic')
|
logging.warning('show_game_service_ui requires plus feature-set')
|
||||||
|
|
||||||
def _ui_show_achievements(self) -> None:
|
def _ui_show_achievements(self) -> None:
|
||||||
if bs.app.classic is not None:
|
if bs.app.plus is not None:
|
||||||
bs.app.classic.show_online_score_ui('achievements')
|
bs.app.plus.show_game_service_ui('achievements')
|
||||||
else:
|
else:
|
||||||
logging.warning('show_online_score_ui requires classic')
|
logging.warning('show_game_service_ui requires plus feature-set')
|
||||||
|
|
||||||
def _ui_worlds_best(self) -> None:
|
def _ui_worlds_best(self) -> None:
|
||||||
if self._score_link is None:
|
if self._score_link is None:
|
||||||
|
|||||||
@ -35,7 +35,7 @@ class ControlsGuide(bs.Actor):
|
|||||||
delay: is the time in seconds before the overlay fades in.
|
delay: is the time in seconds before the overlay fades in.
|
||||||
|
|
||||||
lifespan: if not None, the overlay will fade back out and die after
|
lifespan: if not None, the overlay will fade back out and die after
|
||||||
that long (in milliseconds).
|
that long (in seconds).
|
||||||
|
|
||||||
bright: if True, brighter colors will be used; handy when showing
|
bright: if True, brighter colors will be used; handy when showing
|
||||||
over gameplay but may be too bright for join-screens, etc.
|
over gameplay but may be too bright for join-screens, etc.
|
||||||
@ -50,6 +50,7 @@ class ControlsGuide(bs.Actor):
|
|||||||
offs5 = 43.0 * scale
|
offs5 = 43.0 * scale
|
||||||
ouya = False
|
ouya = False
|
||||||
maxw = 50
|
maxw = 50
|
||||||
|
xtweak = -2.8 * scale
|
||||||
self._lifespan = lifespan
|
self._lifespan = lifespan
|
||||||
self._dead = False
|
self._dead = False
|
||||||
self._bright = bright
|
self._bright = bright
|
||||||
@ -117,7 +118,7 @@ class ControlsGuide(bs.Actor):
|
|||||||
'host_only': True,
|
'host_only': True,
|
||||||
'shadow': 1.0,
|
'shadow': 1.0,
|
||||||
'maxwidth': maxw,
|
'maxwidth': maxw,
|
||||||
'position': (pos[0], pos[1] - offs5),
|
'position': (pos[0] + xtweak, pos[1] - offs5),
|
||||||
'color': clr,
|
'color': clr,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -145,7 +146,7 @@ class ControlsGuide(bs.Actor):
|
|||||||
'host_only': True,
|
'host_only': True,
|
||||||
'shadow': 1.0,
|
'shadow': 1.0,
|
||||||
'maxwidth': maxw,
|
'maxwidth': maxw,
|
||||||
'position': (pos[0], pos[1] - offs5),
|
'position': (pos[0] + xtweak, pos[1] - offs5),
|
||||||
'color': clr,
|
'color': clr,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -173,7 +174,7 @@ class ControlsGuide(bs.Actor):
|
|||||||
'host_only': True,
|
'host_only': True,
|
||||||
'shadow': 1.0,
|
'shadow': 1.0,
|
||||||
'maxwidth': maxw,
|
'maxwidth': maxw,
|
||||||
'position': (pos[0], pos[1] - offs5),
|
'position': (pos[0] + xtweak, pos[1] - offs5),
|
||||||
'color': clr,
|
'color': clr,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -201,7 +202,7 @@ class ControlsGuide(bs.Actor):
|
|||||||
'host_only': True,
|
'host_only': True,
|
||||||
'shadow': 1.0,
|
'shadow': 1.0,
|
||||||
'maxwidth': maxw,
|
'maxwidth': maxw,
|
||||||
'position': (pos[0], pos[1] - offs5),
|
'position': (pos[0] + xtweak, pos[1] - offs5),
|
||||||
'color': clr,
|
'color': clr,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -264,10 +265,19 @@ class ControlsGuide(bs.Actor):
|
|||||||
bs.timer(delay, bs.WeakCall(self._start_updating))
|
bs.timer(delay, bs.WeakCall(self._start_updating))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _meaningful_button_name(device: bs.InputDevice, button: int) -> str:
|
def _meaningful_button_name(
|
||||||
|
device: bs.InputDevice, button_name: str
|
||||||
|
) -> str:
|
||||||
"""Return a flattened string button name; empty for non-meaningful."""
|
"""Return a flattened string button name; empty for non-meaningful."""
|
||||||
if not device.has_meaningful_button_names:
|
if not device.has_meaningful_button_names:
|
||||||
return ''
|
return ''
|
||||||
|
assert bs.app.classic is not None
|
||||||
|
button = bs.app.classic.get_input_device_mapped_value(
|
||||||
|
device, button_name
|
||||||
|
)
|
||||||
|
# -1 means unset; let's show that.
|
||||||
|
if button == -1:
|
||||||
|
return bs.Lstr(resource='configGamepadWindow.unsetText').evaluate()
|
||||||
return device.get_button_name(button).evaluate()
|
return device.get_button_name(button).evaluate()
|
||||||
|
|
||||||
def _start_updating(self) -> None:
|
def _start_updating(self) -> None:
|
||||||
@ -289,10 +299,10 @@ class ControlsGuide(bs.Actor):
|
|||||||
def _check_fade_in(self) -> None:
|
def _check_fade_in(self) -> None:
|
||||||
assert bs.app.classic is not None
|
assert bs.app.classic is not None
|
||||||
|
|
||||||
# If we have a touchscreen, we only fade in if we have a player with
|
# If we have a touchscreen, we only fade in if we have a player
|
||||||
# an input device that is *not* the touchscreen.
|
# with an input device that is *not* the touchscreen. Otherwise
|
||||||
# (otherwise it is confusing to see the touchscreen buttons right
|
# it is confusing to see the touchscreen buttons right next to
|
||||||
# next to our display buttons)
|
# our display buttons.
|
||||||
touchscreen: bs.InputDevice | None = bs.getinputdevice(
|
touchscreen: bs.InputDevice | None = bs.getinputdevice(
|
||||||
'TouchScreen', '#1', doraise=False
|
'TouchScreen', '#1', doraise=False
|
||||||
)
|
)
|
||||||
@ -318,15 +328,7 @@ class ControlsGuide(bs.Actor):
|
|||||||
'buttonBomb',
|
'buttonBomb',
|
||||||
'buttonPickUp',
|
'buttonPickUp',
|
||||||
):
|
):
|
||||||
if (
|
if self._meaningful_button_name(device, name) != '':
|
||||||
self._meaningful_button_name(
|
|
||||||
device,
|
|
||||||
bs.app.classic.get_input_device_mapped_value(
|
|
||||||
device, name
|
|
||||||
),
|
|
||||||
)
|
|
||||||
!= ''
|
|
||||||
):
|
|
||||||
fade_in = True
|
fade_in = True
|
||||||
break
|
break
|
||||||
if fade_in:
|
if fade_in:
|
||||||
@ -401,58 +403,30 @@ class ControlsGuide(bs.Actor):
|
|||||||
# We only care about movement buttons in the case of keyboards.
|
# We only care about movement buttons in the case of keyboards.
|
||||||
if all_keyboards:
|
if all_keyboards:
|
||||||
right_button_names.add(
|
right_button_names.add(
|
||||||
device.get_button_name(
|
self._meaningful_button_name(device, 'buttonRight')
|
||||||
classic.get_input_device_mapped_value(
|
|
||||||
device, 'buttonRight'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
left_button_names.add(
|
left_button_names.add(
|
||||||
device.get_button_name(
|
self._meaningful_button_name(device, 'buttonLeft')
|
||||||
classic.get_input_device_mapped_value(
|
|
||||||
device, 'buttonLeft'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
down_button_names.add(
|
down_button_names.add(
|
||||||
device.get_button_name(
|
self._meaningful_button_name(device, 'buttonDown')
|
||||||
classic.get_input_device_mapped_value(
|
|
||||||
device, 'buttonDown'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
up_button_names.add(
|
up_button_names.add(
|
||||||
device.get_button_name(
|
self._meaningful_button_name(device, 'buttonUp')
|
||||||
classic.get_input_device_mapped_value(
|
|
||||||
device, 'buttonUp'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Ignore empty values; things like the remote app or
|
# Ignore empty values; things like the remote app or
|
||||||
# wiimotes can return these.
|
# wiimotes can return these.
|
||||||
bname = self._meaningful_button_name(
|
bname = self._meaningful_button_name(device, 'buttonPunch')
|
||||||
device,
|
|
||||||
classic.get_input_device_mapped_value(device, 'buttonPunch'),
|
|
||||||
)
|
|
||||||
if bname != '':
|
if bname != '':
|
||||||
punch_button_names.add(bname)
|
punch_button_names.add(bname)
|
||||||
bname = self._meaningful_button_name(
|
bname = self._meaningful_button_name(device, 'buttonJump')
|
||||||
device,
|
|
||||||
classic.get_input_device_mapped_value(device, 'buttonJump'),
|
|
||||||
)
|
|
||||||
if bname != '':
|
if bname != '':
|
||||||
jump_button_names.add(bname)
|
jump_button_names.add(bname)
|
||||||
bname = self._meaningful_button_name(
|
bname = self._meaningful_button_name(device, 'buttonBomb')
|
||||||
device,
|
|
||||||
classic.get_input_device_mapped_value(device, 'buttonBomb'),
|
|
||||||
)
|
|
||||||
if bname != '':
|
if bname != '':
|
||||||
bomb_button_names.add(bname)
|
bomb_button_names.add(bname)
|
||||||
bname = self._meaningful_button_name(
|
bname = self._meaningful_button_name(device, 'buttonPickUp')
|
||||||
device,
|
|
||||||
classic.get_input_device_mapped_value(device, 'buttonPickUp'),
|
|
||||||
)
|
|
||||||
if bname != '':
|
if bname != '':
|
||||||
pickup_button_names.add(bname)
|
pickup_button_names.add(bname)
|
||||||
|
|
||||||
@ -582,8 +556,8 @@ class ControlsGuide(bs.Actor):
|
|||||||
if msg.immediate:
|
if msg.immediate:
|
||||||
self._die()
|
self._die()
|
||||||
else:
|
else:
|
||||||
# If they don't need immediate,
|
# If they don't need immediate, fade out our nodes and
|
||||||
# fade out our nodes and die later.
|
# die later.
|
||||||
for node in self._nodes:
|
for node in self._nodes:
|
||||||
bs.animate(node, 'opacity', {0: node.opacity, 3.0: 0.0})
|
bs.animate(node, 'opacity', {0: node.opacity, 3.0: 0.0})
|
||||||
bs.timer(3.1, bs.WeakCall(self._die))
|
bs.timer(3.1, bs.WeakCall(self._die))
|
||||||
|
|||||||
@ -624,7 +624,7 @@ class Spaz(bs.Actor):
|
|||||||
1000.0 * (tval + self.curse_time)
|
1000.0 * (tval + self.curse_time)
|
||||||
)
|
)
|
||||||
self._curse_timer = bs.Timer(
|
self._curse_timer = bs.Timer(
|
||||||
5.0, bs.WeakCall(self.curse_explode)
|
5.0, bs.WeakCall(self.handlemessage, CurseExplodeMessage())
|
||||||
)
|
)
|
||||||
|
|
||||||
def equip_boxing_gloves(self) -> None:
|
def equip_boxing_gloves(self) -> None:
|
||||||
|
|||||||
@ -317,7 +317,8 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
|||||||
from bauiv1lib.kiosk import KioskWindow
|
from bauiv1lib.kiosk import KioskWindow
|
||||||
|
|
||||||
bs.app.ui_v1.set_main_menu_window(
|
bs.app.ui_v1.set_main_menu_window(
|
||||||
KioskWindow().get_root_widget()
|
KioskWindow().get_root_widget(),
|
||||||
|
from_window=False, # Disable check here.
|
||||||
)
|
)
|
||||||
# ..or in normal cases go back to the main menu
|
# ..or in normal cases go back to the main menu
|
||||||
else:
|
else:
|
||||||
@ -326,14 +327,16 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
|||||||
from bauiv1lib.gather import GatherWindow
|
from bauiv1lib.gather import GatherWindow
|
||||||
|
|
||||||
bs.app.ui_v1.set_main_menu_window(
|
bs.app.ui_v1.set_main_menu_window(
|
||||||
GatherWindow(transition=None).get_root_widget()
|
GatherWindow(transition=None).get_root_widget(),
|
||||||
|
from_window=False, # Disable check here.
|
||||||
)
|
)
|
||||||
elif main_menu_location == 'Watch':
|
elif main_menu_location == 'Watch':
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.watch import WatchWindow
|
from bauiv1lib.watch import WatchWindow
|
||||||
|
|
||||||
bs.app.ui_v1.set_main_menu_window(
|
bs.app.ui_v1.set_main_menu_window(
|
||||||
WatchWindow(transition=None).get_root_widget()
|
WatchWindow(transition=None).get_root_widget(),
|
||||||
|
from_window=False, # Disable check here.
|
||||||
)
|
)
|
||||||
elif main_menu_location == 'Team Game Select':
|
elif main_menu_location == 'Team Game Select':
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
@ -344,7 +347,8 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
|||||||
bs.app.ui_v1.set_main_menu_window(
|
bs.app.ui_v1.set_main_menu_window(
|
||||||
PlaylistBrowserWindow(
|
PlaylistBrowserWindow(
|
||||||
sessiontype=bs.DualTeamSession, transition=None
|
sessiontype=bs.DualTeamSession, transition=None
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=False, # Disable check here.
|
||||||
)
|
)
|
||||||
elif main_menu_location == 'Free-for-All Game Select':
|
elif main_menu_location == 'Free-for-All Game Select':
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
@ -356,28 +360,34 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]):
|
|||||||
PlaylistBrowserWindow(
|
PlaylistBrowserWindow(
|
||||||
sessiontype=bs.FreeForAllSession,
|
sessiontype=bs.FreeForAllSession,
|
||||||
transition=None,
|
transition=None,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=False, # Disable check here.
|
||||||
)
|
)
|
||||||
elif main_menu_location == 'Coop Select':
|
elif main_menu_location == 'Coop Select':
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.coop.browser import CoopBrowserWindow
|
from bauiv1lib.coop.browser import CoopBrowserWindow
|
||||||
|
|
||||||
bs.app.ui_v1.set_main_menu_window(
|
bs.app.ui_v1.set_main_menu_window(
|
||||||
CoopBrowserWindow(transition=None).get_root_widget()
|
CoopBrowserWindow(
|
||||||
|
transition=None
|
||||||
|
).get_root_widget(),
|
||||||
|
from_window=False, # Disable check here.
|
||||||
)
|
)
|
||||||
elif main_menu_location == 'Benchmarks & Stress Tests':
|
elif main_menu_location == 'Benchmarks & Stress Tests':
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.debug import DebugWindow
|
from bauiv1lib.debug import DebugWindow
|
||||||
|
|
||||||
bs.app.ui_v1.set_main_menu_window(
|
bs.app.ui_v1.set_main_menu_window(
|
||||||
DebugWindow(transition=None).get_root_widget()
|
DebugWindow(transition=None).get_root_widget(),
|
||||||
|
from_window=False, # Disable check here.
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.mainmenu import MainMenuWindow
|
from bauiv1lib.mainmenu import MainMenuWindow
|
||||||
|
|
||||||
bs.app.ui_v1.set_main_menu_window(
|
bs.app.ui_v1.set_main_menu_window(
|
||||||
MainMenuWindow(transition=None).get_root_widget()
|
MainMenuWindow(transition=None).get_root_widget(),
|
||||||
|
from_window=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
# attempt to show any pending offers immediately.
|
# attempt to show any pending offers immediately.
|
||||||
|
|||||||
@ -31,7 +31,10 @@ from babase import (
|
|||||||
apptimer,
|
apptimer,
|
||||||
AppTimer,
|
AppTimer,
|
||||||
Call,
|
Call,
|
||||||
can_toggle_fullscreen,
|
fullscreen_control_available,
|
||||||
|
fullscreen_control_get,
|
||||||
|
fullscreen_control_key_shortcut,
|
||||||
|
fullscreen_control_set,
|
||||||
charstr,
|
charstr,
|
||||||
clipboard_is_supported,
|
clipboard_is_supported,
|
||||||
clipboard_set_text,
|
clipboard_set_text,
|
||||||
@ -57,13 +60,15 @@ from babase import (
|
|||||||
in_logic_thread,
|
in_logic_thread,
|
||||||
increment_analytics_count,
|
increment_analytics_count,
|
||||||
is_browser_likely_available,
|
is_browser_likely_available,
|
||||||
is_running_on_fire_tv,
|
|
||||||
is_xcode_build,
|
is_xcode_build,
|
||||||
Keyboard,
|
|
||||||
lock_all_input,
|
lock_all_input,
|
||||||
LoginAdapter,
|
LoginAdapter,
|
||||||
|
LoginInfo,
|
||||||
Lstr,
|
Lstr,
|
||||||
|
native_review_request,
|
||||||
|
native_review_request_supported,
|
||||||
NotFoundError,
|
NotFoundError,
|
||||||
|
open_file_externally,
|
||||||
Permission,
|
Permission,
|
||||||
Plugin,
|
Plugin,
|
||||||
PluginSpec,
|
PluginSpec,
|
||||||
@ -88,7 +93,6 @@ from babase import (
|
|||||||
|
|
||||||
from _bauiv1 import (
|
from _bauiv1 import (
|
||||||
buttonwidget,
|
buttonwidget,
|
||||||
can_show_ad,
|
|
||||||
checkboxwidget,
|
checkboxwidget,
|
||||||
columnwidget,
|
columnwidget,
|
||||||
containerwidget,
|
containerwidget,
|
||||||
@ -97,21 +101,15 @@ from _bauiv1 import (
|
|||||||
getmesh,
|
getmesh,
|
||||||
getsound,
|
getsound,
|
||||||
gettexture,
|
gettexture,
|
||||||
has_video_ads,
|
|
||||||
have_incentivized_ad,
|
|
||||||
hscrollwidget,
|
hscrollwidget,
|
||||||
imagewidget,
|
imagewidget,
|
||||||
is_party_icon_visible,
|
is_party_icon_visible,
|
||||||
Mesh,
|
Mesh,
|
||||||
open_file_externally,
|
|
||||||
open_url,
|
open_url,
|
||||||
rowwidget,
|
rowwidget,
|
||||||
scrollwidget,
|
scrollwidget,
|
||||||
set_party_icon_always_visible,
|
set_party_icon_always_visible,
|
||||||
set_party_window_open,
|
set_party_window_open,
|
||||||
show_ad,
|
|
||||||
show_ad_2,
|
|
||||||
show_online_score_ui,
|
|
||||||
Sound,
|
Sound,
|
||||||
Texture,
|
Texture,
|
||||||
textwidget,
|
textwidget,
|
||||||
@ -119,6 +117,7 @@ from _bauiv1 import (
|
|||||||
Widget,
|
Widget,
|
||||||
widget,
|
widget,
|
||||||
)
|
)
|
||||||
|
from bauiv1._keyboard import Keyboard
|
||||||
from bauiv1._uitypes import Window, uicleanupcheck
|
from bauiv1._uitypes import Window, uicleanupcheck
|
||||||
from bauiv1._subsystem import UIV1Subsystem
|
from bauiv1._subsystem import UIV1Subsystem
|
||||||
|
|
||||||
@ -138,8 +137,10 @@ __all__ = [
|
|||||||
'AppTimer',
|
'AppTimer',
|
||||||
'buttonwidget',
|
'buttonwidget',
|
||||||
'Call',
|
'Call',
|
||||||
'can_show_ad',
|
'fullscreen_control_available',
|
||||||
'can_toggle_fullscreen',
|
'fullscreen_control_get',
|
||||||
|
'fullscreen_control_key_shortcut',
|
||||||
|
'fullscreen_control_set',
|
||||||
'charstr',
|
'charstr',
|
||||||
'checkboxwidget',
|
'checkboxwidget',
|
||||||
'clipboard_is_supported',
|
'clipboard_is_supported',
|
||||||
@ -169,8 +170,6 @@ __all__ = [
|
|||||||
'getmesh',
|
'getmesh',
|
||||||
'getsound',
|
'getsound',
|
||||||
'gettexture',
|
'gettexture',
|
||||||
'has_video_ads',
|
|
||||||
'have_incentivized_ad',
|
|
||||||
'have_permission',
|
'have_permission',
|
||||||
'hscrollwidget',
|
'hscrollwidget',
|
||||||
'imagewidget',
|
'imagewidget',
|
||||||
@ -178,13 +177,15 @@ __all__ = [
|
|||||||
'increment_analytics_count',
|
'increment_analytics_count',
|
||||||
'is_browser_likely_available',
|
'is_browser_likely_available',
|
||||||
'is_party_icon_visible',
|
'is_party_icon_visible',
|
||||||
'is_running_on_fire_tv',
|
|
||||||
'is_xcode_build',
|
'is_xcode_build',
|
||||||
'Keyboard',
|
'Keyboard',
|
||||||
'lock_all_input',
|
'lock_all_input',
|
||||||
'LoginAdapter',
|
'LoginAdapter',
|
||||||
|
'LoginInfo',
|
||||||
'Lstr',
|
'Lstr',
|
||||||
'Mesh',
|
'Mesh',
|
||||||
|
'native_review_request',
|
||||||
|
'native_review_request_supported',
|
||||||
'NotFoundError',
|
'NotFoundError',
|
||||||
'open_file_externally',
|
'open_file_externally',
|
||||||
'open_url',
|
'open_url',
|
||||||
@ -204,9 +205,6 @@ __all__ = [
|
|||||||
'set_party_icon_always_visible',
|
'set_party_icon_always_visible',
|
||||||
'set_party_window_open',
|
'set_party_window_open',
|
||||||
'set_ui_input_device',
|
'set_ui_input_device',
|
||||||
'show_ad',
|
|
||||||
'show_ad_2',
|
|
||||||
'show_online_score_ui',
|
|
||||||
'Sound',
|
'Sound',
|
||||||
'SpecialChar',
|
'SpecialChar',
|
||||||
'supports_max_fps',
|
'supports_max_fps',
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import inspect
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _bauiv1
|
import _bauiv1
|
||||||
@ -87,3 +88,19 @@ def show_url_window(address: str) -> None:
|
|||||||
return
|
return
|
||||||
|
|
||||||
app.classic.show_url_window(address)
|
app.classic.show_url_window(address)
|
||||||
|
|
||||||
|
|
||||||
|
def double_transition_out_warning() -> None:
|
||||||
|
"""Called if a widget is set to transition out twice."""
|
||||||
|
caller_frame = inspect.stack()[1]
|
||||||
|
caller_filename = caller_frame.filename
|
||||||
|
caller_line_number = caller_frame.lineno
|
||||||
|
logging.warning(
|
||||||
|
'ContainerWidget was set to transition out twice;'
|
||||||
|
' this often implies buggy code (%s line %s).\n'
|
||||||
|
' Generally you should check the value of'
|
||||||
|
' _root_widget.transitioning_out and perform no actions if that'
|
||||||
|
' is True.',
|
||||||
|
caller_filename,
|
||||||
|
caller_line_number,
|
||||||
|
)
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import inspect
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import babase
|
import babase
|
||||||
@ -66,6 +67,16 @@ class UIV1Subsystem(babase.AppSubsystem):
|
|||||||
# a more elegant way once we revamp high level UI stuff a bit.
|
# a more elegant way once we revamp high level UI stuff a bit.
|
||||||
self.selecting_private_party_playlist: bool = False
|
self.selecting_private_party_playlist: bool = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Can uiv1 currently be used?
|
||||||
|
|
||||||
|
Code that may run in headless mode, before the UI has been spun up,
|
||||||
|
while other ui systems are active, etc. can check this to avoid
|
||||||
|
likely erroring.
|
||||||
|
"""
|
||||||
|
return _bauiv1.is_available()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def uiscale(self) -> babase.UIScale:
|
def uiscale(self) -> babase.UIScale:
|
||||||
"""Current ui scale for the app."""
|
"""Current ui scale for the app."""
|
||||||
@ -106,21 +117,69 @@ class UIV1Subsystem(babase.AppSubsystem):
|
|||||||
# FIXME: Can probably kill this if we do immediate UI death checks.
|
# FIXME: Can probably kill this if we do immediate UI death checks.
|
||||||
self.upkeeptimer = babase.AppTimer(2.6543, ui_upkeep, repeat=True)
|
self.upkeeptimer = babase.AppTimer(2.6543, ui_upkeep, repeat=True)
|
||||||
|
|
||||||
def set_main_menu_window(self, window: bauiv1.Widget) -> None:
|
def set_main_menu_window(
|
||||||
"""Set the current 'main' window, replacing any existing."""
|
self,
|
||||||
|
window: bauiv1.Widget,
|
||||||
|
from_window: bauiv1.Widget | None | bool = True,
|
||||||
|
) -> None:
|
||||||
|
"""Set the current 'main' window, replacing any existing.
|
||||||
|
|
||||||
|
If 'from_window' is passed as a bauiv1.Widget or None, a warning
|
||||||
|
will be issued if it that value does not match the current main
|
||||||
|
window. This can help clean up flawed code that can lead to bad
|
||||||
|
UI states. A value of False will disable the check.
|
||||||
|
"""
|
||||||
|
|
||||||
existing = self._main_menu_window
|
existing = self._main_menu_window
|
||||||
from inspect import currentframe, getframeinfo
|
|
||||||
|
try:
|
||||||
|
if isinstance(from_window, bool):
|
||||||
|
# For default val True we warn that the arg wasn't
|
||||||
|
# passed. False can be explicitly passed to disable this
|
||||||
|
# check.
|
||||||
|
if from_window is True:
|
||||||
|
caller_frame = inspect.stack()[1]
|
||||||
|
caller_filename = caller_frame.filename
|
||||||
|
caller_line_number = caller_frame.lineno
|
||||||
|
logging.warning(
|
||||||
|
'set_main_menu_window() should be passed a'
|
||||||
|
" 'from_window' value to help ensure proper UI behavior"
|
||||||
|
' (%s line %i).',
|
||||||
|
caller_filename,
|
||||||
|
caller_line_number,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# For everything else, warn if what they passed wasn't
|
||||||
|
# the previous main menu widget.
|
||||||
|
if from_window is not existing:
|
||||||
|
caller_frame = inspect.stack()[1]
|
||||||
|
caller_filename = caller_frame.filename
|
||||||
|
caller_line_number = caller_frame.lineno
|
||||||
|
logging.warning(
|
||||||
|
"set_main_menu_window() was passed 'from_window' %s"
|
||||||
|
' but existing main-menu-window is %s. (%s line %i).',
|
||||||
|
from_window,
|
||||||
|
existing,
|
||||||
|
caller_filename,
|
||||||
|
caller_line_number,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
# Prevent any bugs in these checks from causing problems.
|
||||||
|
logging.exception('Error checking from_window')
|
||||||
|
|
||||||
|
# Once the above code leads to us fixing all leftover window bugs
|
||||||
|
# at the source, we can kill the code below.
|
||||||
|
|
||||||
# Let's grab the location where we were called from to report
|
# Let's grab the location where we were called from to report
|
||||||
# if we have to force-kill the existing window (which normally
|
# if we have to force-kill the existing window (which normally
|
||||||
# should not happen).
|
# should not happen).
|
||||||
frameline = None
|
frameline = None
|
||||||
try:
|
try:
|
||||||
frame = currentframe()
|
frame = inspect.currentframe()
|
||||||
if frame is not None:
|
if frame is not None:
|
||||||
frame = frame.f_back
|
frame = frame.f_back
|
||||||
if frame is not None:
|
if frame is not None:
|
||||||
frameinfo = getframeinfo(frame)
|
frameinfo = inspect.getframeinfo(frame)
|
||||||
frameline = f'{frameinfo.filename} {frameinfo.lineno}'
|
frameline = f'{frameinfo.filename} {frameinfo.lineno}'
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception('Error calcing line for set_main_menu_window')
|
logging.exception('Error calcing line for set_main_menu_window')
|
||||||
@ -150,13 +209,18 @@ class UIV1Subsystem(babase.AppSubsystem):
|
|||||||
|
|
||||||
def clear_main_menu_window(self, transition: str | None = None) -> None:
|
def clear_main_menu_window(self, transition: str | None = None) -> None:
|
||||||
"""Clear any existing 'main' window with the provided transition."""
|
"""Clear any existing 'main' window with the provided transition."""
|
||||||
|
assert transition is None or not transition.endswith('_in')
|
||||||
if self._main_menu_window:
|
if self._main_menu_window:
|
||||||
if transition is not None:
|
if (
|
||||||
|
transition is not None
|
||||||
|
and not self._main_menu_window.transitioning_out
|
||||||
|
):
|
||||||
_bauiv1.containerwidget(
|
_bauiv1.containerwidget(
|
||||||
edit=self._main_menu_window, transition=transition
|
edit=self._main_menu_window, transition=transition
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self._main_menu_window.delete()
|
self._main_menu_window.delete()
|
||||||
|
self._main_menu_window = None
|
||||||
|
|
||||||
def add_main_menu_close_callback(self, call: Callable[[], Any]) -> None:
|
def add_main_menu_close_callback(self, call: Callable[[], Any]) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
|
|||||||
@ -12,6 +12,7 @@ from typing import TYPE_CHECKING
|
|||||||
import babase
|
import babase
|
||||||
|
|
||||||
import _bauiv1
|
import _bauiv1
|
||||||
|
from bauiv1._keyboard import Keyboard
|
||||||
from bauiv1._uitypes import Window
|
from bauiv1._uitypes import Window
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -51,6 +52,19 @@ class OnScreenKeyboardWindow(Window):
|
|||||||
else (0, 0),
|
else (0, 0),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
self._cancel_button = _bauiv1.buttonwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
scale=0.5,
|
||||||
|
position=(30, self._height - 55),
|
||||||
|
size=(60, 60),
|
||||||
|
label='',
|
||||||
|
enable_sound=False,
|
||||||
|
on_activate_call=self._cancel,
|
||||||
|
autoselect=True,
|
||||||
|
color=(0.55, 0.5, 0.6),
|
||||||
|
icon=_bauiv1.gettexture('crossOut'),
|
||||||
|
iconscale=1.2,
|
||||||
|
)
|
||||||
self._done_button = _bauiv1.buttonwidget(
|
self._done_button = _bauiv1.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(self._width - 200, 44),
|
position=(self._width - 200, 44),
|
||||||
@ -240,9 +254,7 @@ class OnScreenKeyboardWindow(Window):
|
|||||||
# Show change instructions only if we have more than one
|
# Show change instructions only if we have more than one
|
||||||
# keyboard option.
|
# keyboard option.
|
||||||
keyboards = (
|
keyboards = (
|
||||||
babase.app.meta.scanresults.exports_of_class(
|
babase.app.meta.scanresults.exports_of_class(Keyboard)
|
||||||
babase.Keyboard
|
|
||||||
)
|
|
||||||
if babase.app.meta.scanresults is not None
|
if babase.app.meta.scanresults is not None
|
||||||
else []
|
else []
|
||||||
)
|
)
|
||||||
@ -274,10 +286,10 @@ class OnScreenKeyboardWindow(Window):
|
|||||||
|
|
||||||
def _get_keyboard(self) -> bui.Keyboard:
|
def _get_keyboard(self) -> bui.Keyboard:
|
||||||
assert babase.app.meta.scanresults is not None
|
assert babase.app.meta.scanresults is not None
|
||||||
classname = babase.app.meta.scanresults.exports_of_class(
|
classname = babase.app.meta.scanresults.exports_of_class(Keyboard)[
|
||||||
babase.Keyboard
|
self._keyboard_index
|
||||||
)[self._keyboard_index]
|
]
|
||||||
kbclass = babase.getclass(classname, babase.Keyboard)
|
kbclass = babase.getclass(classname, Keyboard)
|
||||||
return kbclass()
|
return kbclass()
|
||||||
|
|
||||||
def _refresh(self) -> None:
|
def _refresh(self) -> None:
|
||||||
@ -372,9 +384,7 @@ class OnScreenKeyboardWindow(Window):
|
|||||||
|
|
||||||
def _next_keyboard(self) -> None:
|
def _next_keyboard(self) -> None:
|
||||||
assert babase.app.meta.scanresults is not None
|
assert babase.app.meta.scanresults is not None
|
||||||
kbexports = babase.app.meta.scanresults.exports_of_class(
|
kbexports = babase.app.meta.scanresults.exports_of_class(Keyboard)
|
||||||
babase.Keyboard
|
|
||||||
)
|
|
||||||
self._keyboard_index = (self._keyboard_index + 1) % len(kbexports)
|
self._keyboard_index = (self._keyboard_index + 1) % len(kbexports)
|
||||||
|
|
||||||
self._load_keyboard()
|
self._load_keyboard()
|
||||||
|
|||||||
@ -63,20 +63,14 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
1.0, bui.WeakCall(self._update), repeat=True
|
1.0, bui.WeakCall(self._update), repeat=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# Currently we can only reset achievements on game-center.
|
self._can_reset_achievements = False
|
||||||
v1_account_type: str | None
|
|
||||||
if self._v1_signed_in:
|
|
||||||
v1_account_type = plus.get_v1_account_type()
|
|
||||||
else:
|
|
||||||
v1_account_type = None
|
|
||||||
self._can_reset_achievements = v1_account_type == 'Game Center'
|
|
||||||
|
|
||||||
app = bui.app
|
app = bui.app
|
||||||
assert app.classic is not None
|
assert app.classic is not None
|
||||||
uiscale = app.ui_v1.uiscale
|
uiscale = app.ui_v1.uiscale
|
||||||
|
|
||||||
self._width = 760 if uiscale is bui.UIScale.SMALL else 660
|
self._width = 860 if uiscale is bui.UIScale.SMALL else 660
|
||||||
x_offs = 50 if uiscale is bui.UIScale.SMALL else 0
|
x_offs = 100 if uiscale is bui.UIScale.SMALL else 0
|
||||||
self._height = (
|
self._height = (
|
||||||
390
|
390
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -98,6 +92,9 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
if LoginType.GPGS in plus.accounts.login_adapters:
|
if LoginType.GPGS in plus.accounts.login_adapters:
|
||||||
self._show_sign_in_buttons.append('Google Play')
|
self._show_sign_in_buttons.append('Google Play')
|
||||||
|
|
||||||
|
if LoginType.GAME_CENTER in plus.accounts.login_adapters:
|
||||||
|
self._show_sign_in_buttons.append('Game Center')
|
||||||
|
|
||||||
# Always want to show our web-based v2 login option.
|
# Always want to show our web-based v2 login option.
|
||||||
self._show_sign_in_buttons.append('V2Proxy')
|
self._show_sign_in_buttons.append('V2Proxy')
|
||||||
|
|
||||||
@ -227,6 +224,8 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
|
via_lines: list[str] = []
|
||||||
|
|
||||||
primary_v2_account = plus.accounts.primary
|
primary_v2_account = plus.accounts.primary
|
||||||
|
|
||||||
v1_state = plus.get_v1_account_state()
|
v1_state = plus.get_v1_account_state()
|
||||||
@ -237,14 +236,55 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
# We expose GPGS-specific functionality only if it is 'active'
|
# We expose GPGS-specific functionality only if it is 'active'
|
||||||
# (meaning the current GPGS player matches one of our account's
|
# (meaning the current GPGS player matches one of our account's
|
||||||
# logins).
|
# logins).
|
||||||
gpgs_adapter = plus.accounts.login_adapters.get(LoginType.GPGS)
|
adapter = plus.accounts.login_adapters.get(LoginType.GPGS)
|
||||||
is_gpgs = (
|
gpgs_active = adapter is not None and adapter.is_back_end_active()
|
||||||
False if gpgs_adapter is None else gpgs_adapter.is_back_end_active()
|
|
||||||
|
# Ditto for Game Center.
|
||||||
|
adapter = plus.accounts.login_adapters.get(LoginType.GAME_CENTER)
|
||||||
|
game_center_active = (
|
||||||
|
adapter is not None and adapter.is_back_end_active()
|
||||||
)
|
)
|
||||||
|
|
||||||
show_signed_in_as = self._v1_signed_in
|
show_signed_in_as = self._v1_signed_in
|
||||||
signed_in_as_space = 95.0
|
signed_in_as_space = 95.0
|
||||||
|
|
||||||
|
# To reduce confusion about the whole V2 account situation for
|
||||||
|
# people used to seeing their Google Play Games or Game Center
|
||||||
|
# account name and icon and whatnot, let's show those underneath
|
||||||
|
# the V2 tag to help communicate that they are in fact logged in
|
||||||
|
# through that account.
|
||||||
|
via_space = 25.0
|
||||||
|
if show_signed_in_as and bui.app.plus is not None:
|
||||||
|
accounts = bui.app.plus.accounts
|
||||||
|
if accounts.primary is not None:
|
||||||
|
# For these login types, we show 'via' IF there is a
|
||||||
|
# login of that type attached to our account AND it is
|
||||||
|
# currently active (We don't want to show 'via Game
|
||||||
|
# Center' if we're signed out of Game Center or
|
||||||
|
# currently running on Steam, even if there is a Game
|
||||||
|
# Center login attached to our account).
|
||||||
|
for ltype, lchar in [
|
||||||
|
(LoginType.GPGS, bui.SpecialChar.GOOGLE_PLAY_GAMES_LOGO),
|
||||||
|
(LoginType.GAME_CENTER, bui.SpecialChar.GAME_CENTER_LOGO),
|
||||||
|
]:
|
||||||
|
linfo = accounts.primary.logins.get(ltype)
|
||||||
|
ladapter = accounts.login_adapters.get(ltype)
|
||||||
|
if (
|
||||||
|
linfo is not None
|
||||||
|
and ladapter is not None
|
||||||
|
and ladapter.is_back_end_active()
|
||||||
|
):
|
||||||
|
via_lines.append(f'{bui.charstr(lchar)}{linfo.name}')
|
||||||
|
|
||||||
|
# TEMP TESTING
|
||||||
|
if bool(False):
|
||||||
|
icontxt = bui.charstr(bui.SpecialChar.GAME_CENTER_LOGO)
|
||||||
|
via_lines.append(f'{icontxt}FloofDibble')
|
||||||
|
icontxt = bui.charstr(
|
||||||
|
bui.SpecialChar.GOOGLE_PLAY_GAMES_LOGO
|
||||||
|
)
|
||||||
|
via_lines.append(f'{icontxt}StinkBobble')
|
||||||
|
|
||||||
show_sign_in_benefits = not self._v1_signed_in
|
show_sign_in_benefits = not self._v1_signed_in
|
||||||
sign_in_benefits_space = 80.0
|
sign_in_benefits_space = 80.0
|
||||||
|
|
||||||
@ -258,6 +298,11 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
and self._signing_in_adapter is None
|
and self._signing_in_adapter is None
|
||||||
and 'Google Play' in self._show_sign_in_buttons
|
and 'Google Play' in self._show_sign_in_buttons
|
||||||
)
|
)
|
||||||
|
show_game_center_sign_in_button = (
|
||||||
|
v1_state == 'signed_out'
|
||||||
|
and self._signing_in_adapter is None
|
||||||
|
and 'Game Center' in self._show_sign_in_buttons
|
||||||
|
)
|
||||||
show_v2_proxy_sign_in_button = (
|
show_v2_proxy_sign_in_button = (
|
||||||
v1_state == 'signed_out'
|
v1_state == 'signed_out'
|
||||||
and self._signing_in_adapter is None
|
and self._signing_in_adapter is None
|
||||||
@ -271,9 +316,8 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
sign_in_button_space = 70.0
|
sign_in_button_space = 70.0
|
||||||
deprecated_space = 60
|
deprecated_space = 60
|
||||||
|
|
||||||
show_game_service_button = self._v1_signed_in and v1_account_type in [
|
# Game Center currently has a single UI for everything.
|
||||||
'Game Center'
|
show_game_service_button = game_center_active
|
||||||
]
|
|
||||||
game_service_button_space = 60.0
|
game_service_button_space = 60.0
|
||||||
|
|
||||||
show_what_is_v2 = self._v1_signed_in and v1_account_type == 'V2'
|
show_what_is_v2 = self._v1_signed_in and v1_account_type == 'V2'
|
||||||
@ -281,11 +325,9 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
show_linked_accounts_text = self._v1_signed_in
|
show_linked_accounts_text = self._v1_signed_in
|
||||||
linked_accounts_text_space = 60.0
|
linked_accounts_text_space = 60.0
|
||||||
|
|
||||||
show_achievements_button = self._v1_signed_in and v1_account_type in (
|
# Always show achievements except in the game-center case where
|
||||||
'Google Play',
|
# its unified UI covers them.
|
||||||
'Local',
|
show_achievements_button = self._v1_signed_in and not game_center_active
|
||||||
'V2',
|
|
||||||
)
|
|
||||||
achievements_button_space = 60.0
|
achievements_button_space = 60.0
|
||||||
|
|
||||||
show_achievements_text = (
|
show_achievements_text = (
|
||||||
@ -293,7 +335,7 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
achievements_text_space = 27.0
|
achievements_text_space = 27.0
|
||||||
|
|
||||||
show_leaderboards_button = self._v1_signed_in and is_gpgs
|
show_leaderboards_button = self._v1_signed_in and gpgs_active
|
||||||
leaderboards_button_space = 60.0
|
leaderboards_button_space = 60.0
|
||||||
|
|
||||||
show_campaign_progress = self._v1_signed_in
|
show_campaign_progress = self._v1_signed_in
|
||||||
@ -330,7 +372,6 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
|
|
||||||
show_sign_out_button = self._v1_signed_in and v1_account_type in [
|
show_sign_out_button = self._v1_signed_in and v1_account_type in [
|
||||||
'Local',
|
'Local',
|
||||||
'Google Play',
|
|
||||||
'V2',
|
'V2',
|
||||||
]
|
]
|
||||||
sign_out_button_space = 70.0
|
sign_out_button_space = 70.0
|
||||||
@ -349,10 +390,13 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
self._sub_height = 60.0
|
self._sub_height = 60.0
|
||||||
if show_signed_in_as:
|
if show_signed_in_as:
|
||||||
self._sub_height += signed_in_as_space
|
self._sub_height += signed_in_as_space
|
||||||
|
self._sub_height += via_space * len(via_lines)
|
||||||
if show_signing_in_text:
|
if show_signing_in_text:
|
||||||
self._sub_height += signing_in_text_space
|
self._sub_height += signing_in_text_space
|
||||||
if show_google_play_sign_in_button:
|
if show_google_play_sign_in_button:
|
||||||
self._sub_height += sign_in_button_space
|
self._sub_height += sign_in_button_space
|
||||||
|
if show_game_center_sign_in_button:
|
||||||
|
self._sub_height += sign_in_button_space
|
||||||
if show_v2_proxy_sign_in_button:
|
if show_v2_proxy_sign_in_button:
|
||||||
self._sub_height += sign_in_button_space
|
self._sub_height += sign_in_button_space
|
||||||
if show_device_sign_in_button:
|
if show_device_sign_in_button:
|
||||||
@ -442,20 +486,21 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
self._account_name_what_is_text = bui.textwidget(
|
self._account_name_what_is_text = bui.textwidget(
|
||||||
parent=self._subcontainer,
|
parent=self._subcontainer,
|
||||||
position=(0.0, self._account_name_what_is_y),
|
position=(0.0, self._account_name_what_is_y),
|
||||||
size=(200.0, 60),
|
size=(220.0, 60),
|
||||||
text=bui.Lstr(
|
text=bui.Lstr(
|
||||||
value='${WHAT} -->',
|
value='${WHAT} -->',
|
||||||
subs=[('${WHAT}', bui.Lstr(resource='whatIsThisText'))],
|
subs=[('${WHAT}', bui.Lstr(resource='whatIsThisText'))],
|
||||||
),
|
),
|
||||||
scale=0.6,
|
scale=0.6,
|
||||||
color=(0.3, 0.7, 0.05),
|
color=(0.3, 0.7, 0.05),
|
||||||
maxwidth=200.0,
|
maxwidth=130.0,
|
||||||
h_align='right',
|
h_align='right',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
selectable=True,
|
selectable=True,
|
||||||
on_activate_call=show_what_is_v2_page,
|
on_activate_call=show_what_is_v2_page,
|
||||||
click_activate=True,
|
click_activate=True,
|
||||||
|
glow_type='uniform',
|
||||||
)
|
)
|
||||||
if first_selectable is None:
|
if first_selectable is None:
|
||||||
first_selectable = self._account_name_what_is_text
|
first_selectable = self._account_name_what_is_text
|
||||||
@ -466,6 +511,54 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
|
|
||||||
v -= signed_in_as_space * 0.4
|
v -= signed_in_as_space * 0.4
|
||||||
|
|
||||||
|
for via in via_lines:
|
||||||
|
v -= via_space * 0.1
|
||||||
|
sscale = 0.7
|
||||||
|
swidth = (
|
||||||
|
bui.get_string_width(via, suppress_warning=True) * sscale
|
||||||
|
)
|
||||||
|
bui.textwidget(
|
||||||
|
parent=self._subcontainer,
|
||||||
|
position=(self._sub_width * 0.5, v),
|
||||||
|
size=(0, 0),
|
||||||
|
text=via,
|
||||||
|
scale=sscale,
|
||||||
|
color=(0.6, 0.6, 0.6),
|
||||||
|
flatness=1.0,
|
||||||
|
shadow=0.0,
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
)
|
||||||
|
bui.textwidget(
|
||||||
|
parent=self._subcontainer,
|
||||||
|
position=(self._sub_width * 0.5 - swidth * 0.5 - 5, v),
|
||||||
|
size=(0, 0),
|
||||||
|
text=bui.Lstr(
|
||||||
|
value='(${VIA}',
|
||||||
|
subs=[('${VIA}', bui.Lstr(resource='viaText'))],
|
||||||
|
),
|
||||||
|
scale=0.5,
|
||||||
|
color=(0.4, 0.6, 0.4, 0.5),
|
||||||
|
flatness=1.0,
|
||||||
|
shadow=0.0,
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
)
|
||||||
|
bui.textwidget(
|
||||||
|
parent=self._subcontainer,
|
||||||
|
position=(self._sub_width * 0.5 + swidth * 0.5 + 10, v),
|
||||||
|
size=(0, 0),
|
||||||
|
text=')',
|
||||||
|
scale=0.5,
|
||||||
|
color=(0.4, 0.6, 0.4, 0.5),
|
||||||
|
flatness=1.0,
|
||||||
|
shadow=0.0,
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
)
|
||||||
|
|
||||||
|
v -= via_space * 0.9
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self._account_name_text = None
|
self._account_name_text = None
|
||||||
self._account_name_what_is_text = None
|
self._account_name_what_is_text = None
|
||||||
@ -477,22 +570,6 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
|
|
||||||
if show_sign_in_benefits:
|
if show_sign_in_benefits:
|
||||||
v -= sign_in_benefits_space
|
v -= sign_in_benefits_space
|
||||||
app = bui.app
|
|
||||||
assert app.classic is not None
|
|
||||||
extra: str | bui.Lstr | None
|
|
||||||
if (
|
|
||||||
app.classic.platform in ['mac', 'ios']
|
|
||||||
and app.classic.subplatform == 'appstore'
|
|
||||||
):
|
|
||||||
extra = bui.Lstr(
|
|
||||||
value='\n${S}',
|
|
||||||
subs=[
|
|
||||||
('${S}', bui.Lstr(resource='signInWithGameCenterText'))
|
|
||||||
],
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
extra = ''
|
|
||||||
|
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
parent=self._subcontainer,
|
parent=self._subcontainer,
|
||||||
position=(
|
position=(
|
||||||
@ -500,16 +577,7 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
v + sign_in_benefits_space * 0.4,
|
v + sign_in_benefits_space * 0.4,
|
||||||
),
|
),
|
||||||
size=(0, 0),
|
size=(0, 0),
|
||||||
text=bui.Lstr(
|
text=bui.Lstr(resource=self._r + '.signInInfoText'),
|
||||||
value='${A}${B}',
|
|
||||||
subs=[
|
|
||||||
(
|
|
||||||
'${A}',
|
|
||||||
bui.Lstr(resource=self._r + '.signInInfoText'),
|
|
||||||
),
|
|
||||||
('${B}', extra),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
max_height=sign_in_benefits_space * 0.9,
|
max_height=sign_in_benefits_space * 0.9,
|
||||||
scale=0.9,
|
scale=0.9,
|
||||||
color=(0.75, 0.7, 0.8),
|
color=(0.75, 0.7, 0.8),
|
||||||
@ -554,7 +622,13 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
(
|
(
|
||||||
'${B}',
|
'${B}',
|
||||||
bui.Lstr(
|
bui.Lstr(
|
||||||
resource=self._r + '.signInWithGooglePlayText'
|
resource=self._r + '.signInWithText',
|
||||||
|
subs=[
|
||||||
|
(
|
||||||
|
'${SERVICE}',
|
||||||
|
bui.Lstr(resource='googlePlayText'),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -572,6 +646,48 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
bui.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
|
bui.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
|
||||||
self._sign_in_text = None
|
self._sign_in_text = None
|
||||||
|
|
||||||
|
if show_game_center_sign_in_button:
|
||||||
|
button_width = 350
|
||||||
|
v -= sign_in_button_space
|
||||||
|
self._sign_in_google_play_button = btn = bui.buttonwidget(
|
||||||
|
parent=self._subcontainer,
|
||||||
|
position=((self._sub_width - button_width) * 0.5, v - 20),
|
||||||
|
autoselect=True,
|
||||||
|
size=(button_width, 60),
|
||||||
|
# Note: Apparently Game Center is just called 'Game Center'
|
||||||
|
# in all languages. Can revisit if not true.
|
||||||
|
# https://developer.apple.com/forums/thread/725779
|
||||||
|
label=bui.Lstr(
|
||||||
|
value='${A}${B}',
|
||||||
|
subs=[
|
||||||
|
(
|
||||||
|
'${A}',
|
||||||
|
bui.charstr(bui.SpecialChar.GAME_CENTER_LOGO),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'${B}',
|
||||||
|
bui.Lstr(
|
||||||
|
resource=self._r + '.signInWithText',
|
||||||
|
subs=[('${SERVICE}', 'Game Center')],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
on_activate_call=lambda: self._sign_in_press(
|
||||||
|
LoginType.GAME_CENTER
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if first_selectable is None:
|
||||||
|
first_selectable = btn
|
||||||
|
if bui.app.ui_v1.use_toolbars:
|
||||||
|
bui.widget(
|
||||||
|
edit=btn,
|
||||||
|
right_widget=bui.get_special_widget('party_button'),
|
||||||
|
)
|
||||||
|
bui.widget(edit=btn, left_widget=bbtn)
|
||||||
|
bui.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
|
||||||
|
self._sign_in_text = None
|
||||||
|
|
||||||
if show_v2_proxy_sign_in_button:
|
if show_v2_proxy_sign_in_button:
|
||||||
button_width = 350
|
button_width = 350
|
||||||
v -= sign_in_button_space
|
v -= sign_in_button_space
|
||||||
@ -704,7 +820,7 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
position=((self._sub_width - button_width) * 0.5, v + 30),
|
position=((self._sub_width - button_width) * 0.5, v + 30),
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
size=(button_width, 60),
|
size=(button_width, 60),
|
||||||
label=bui.Lstr(resource=self._r + '.manageAccountText'),
|
label=bui.Lstr(resource=f'{self._r}.manageAccountText'),
|
||||||
color=(0.55, 0.5, 0.6),
|
color=(0.55, 0.5, 0.6),
|
||||||
icon=bui.gettexture('settingsIcon'),
|
icon=bui.gettexture('settingsIcon'),
|
||||||
textcolor=(0.75, 0.7, 0.8),
|
textcolor=(0.75, 0.7, 0.8),
|
||||||
@ -745,10 +861,15 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
# the button to go to OS-Specific leaderboards/high-score-lists/etc.
|
# the button to go to OS-Specific leaderboards/high-score-lists/etc.
|
||||||
if show_game_service_button:
|
if show_game_service_button:
|
||||||
button_width = 300
|
button_width = 300
|
||||||
v -= game_service_button_space * 0.85
|
v -= game_service_button_space * 0.6
|
||||||
v1_account_type = plus.get_v1_account_type()
|
if game_center_active:
|
||||||
if v1_account_type == 'Game Center':
|
# Note: Apparently Game Center is just called 'Game Center'
|
||||||
v1_account_type_name = bui.Lstr(resource='gameCenterText')
|
# in all languages. Can revisit if not true.
|
||||||
|
# https://developer.apple.com/forums/thread/725779
|
||||||
|
game_service_button_label = bui.Lstr(
|
||||||
|
value=bui.charstr(bui.SpecialChar.GAME_CENTER_LOGO)
|
||||||
|
+ 'Game Center'
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"unknown account type: '" + str(v1_account_type) + "'"
|
"unknown account type: '" + str(v1_account_type) + "'"
|
||||||
@ -761,7 +882,7 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
autoselect=True,
|
autoselect=True,
|
||||||
on_activate_call=self._on_game_service_button_press,
|
on_activate_call=self._on_game_service_button_press,
|
||||||
size=(button_width, 50),
|
size=(button_width, 50),
|
||||||
label=v1_account_type_name,
|
label=game_service_button_label,
|
||||||
)
|
)
|
||||||
if first_selectable is None:
|
if first_selectable is None:
|
||||||
first_selectable = btn
|
first_selectable = btn
|
||||||
@ -771,7 +892,7 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
right_widget=bui.get_special_widget('party_button'),
|
right_widget=bui.get_special_widget('party_button'),
|
||||||
)
|
)
|
||||||
bui.widget(edit=btn, left_widget=bbtn)
|
bui.widget(edit=btn, left_widget=bbtn)
|
||||||
v -= game_service_button_space * 0.15
|
v -= game_service_button_space * 0.4
|
||||||
else:
|
else:
|
||||||
self.game_service_button = None
|
self.game_service_button = None
|
||||||
|
|
||||||
@ -804,13 +925,15 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
autoselect=True,
|
autoselect=True,
|
||||||
icon=bui.gettexture(
|
icon=bui.gettexture(
|
||||||
'googlePlayAchievementsIcon'
|
'googlePlayAchievementsIcon'
|
||||||
if is_gpgs
|
if gpgs_active
|
||||||
else 'achievementsIcon'
|
else 'achievementsIcon'
|
||||||
),
|
),
|
||||||
icon_color=(0.8, 0.95, 0.7) if is_gpgs 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=(
|
on_activate_call=(
|
||||||
self._on_custom_achievements_press
|
self._on_custom_achievements_press
|
||||||
if is_gpgs
|
if gpgs_active
|
||||||
else self._on_achievements_press
|
else self._on_achievements_press
|
||||||
),
|
),
|
||||||
size=(button_width, 50),
|
size=(button_width, 50),
|
||||||
@ -1135,19 +1258,21 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
self._needs_refresh = False
|
self._needs_refresh = False
|
||||||
|
|
||||||
def _on_game_service_button_press(self) -> None:
|
def _on_game_service_button_press(self) -> None:
|
||||||
if bui.app.classic is not None:
|
if bui.app.plus is not None:
|
||||||
bui.app.classic.show_online_score_ui()
|
bui.app.plus.show_game_service_ui()
|
||||||
else:
|
else:
|
||||||
logging.warning('game service ui not available without classic.')
|
logging.warning(
|
||||||
|
'game-service-ui not available without plus feature-set.'
|
||||||
|
)
|
||||||
|
|
||||||
def _on_custom_achievements_press(self) -> None:
|
def _on_custom_achievements_press(self) -> None:
|
||||||
if bui.app.classic is not None:
|
if bui.app.plus is not None:
|
||||||
bui.apptimer(
|
bui.apptimer(
|
||||||
0.15,
|
0.15,
|
||||||
bui.Call(bui.app.classic.show_online_score_ui, 'achievements'),
|
bui.Call(bui.app.plus.show_game_service_ui, 'achievements'),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logging.warning('show_online_score_ui requires classic')
|
logging.warning('show_game_service_ui requires plus feature-set.')
|
||||||
|
|
||||||
def _on_achievements_press(self) -> None:
|
def _on_achievements_press(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
@ -1162,11 +1287,21 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
show_what_is_v2_page()
|
show_what_is_v2_page()
|
||||||
|
|
||||||
def _on_manage_account_press(self) -> None:
|
def _on_manage_account_press(self) -> None:
|
||||||
bui.screenmessage(bui.Lstr(resource='oneMomentText'))
|
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
|
# Preemptively fail if it looks like we won't be able to talk to
|
||||||
|
# the server anyway.
|
||||||
|
if not plus.cloud.connected:
|
||||||
|
bui.screenmessage(
|
||||||
|
bui.Lstr(resource='internal.unavailableNoConnectionText'),
|
||||||
|
color=(1, 0, 0),
|
||||||
|
)
|
||||||
|
bui.getsound('error').play()
|
||||||
|
return
|
||||||
|
|
||||||
|
bui.screenmessage(bui.Lstr(resource='oneMomentText'))
|
||||||
|
|
||||||
# We expect to have a v2 account signed in if we get here.
|
# We expect to have a v2 account signed in if we get here.
|
||||||
if plus.accounts.primary is None:
|
if plus.accounts.primary is None:
|
||||||
logging.exception(
|
logging.exception(
|
||||||
@ -1184,6 +1319,9 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
self, response: bacommon.cloud.ManageAccountResponse | Exception
|
self, response: bacommon.cloud.ManageAccountResponse | Exception
|
||||||
) -> None:
|
) -> None:
|
||||||
if isinstance(response, Exception) or response.url is None:
|
if isinstance(response, Exception) or response.url is None:
|
||||||
|
logging.warning(
|
||||||
|
'Got error in manage-account-response: %s.', response
|
||||||
|
)
|
||||||
bui.screenmessage(bui.Lstr(resource='errorText'), color=(1, 0, 0))
|
bui.screenmessage(bui.Lstr(resource='errorText'), color=(1, 0, 0))
|
||||||
bui.getsound('error').play()
|
bui.getsound('error').play()
|
||||||
return
|
return
|
||||||
@ -1191,13 +1329,13 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
bui.open_url(response.url)
|
bui.open_url(response.url)
|
||||||
|
|
||||||
def _on_leaderboards_press(self) -> None:
|
def _on_leaderboards_press(self) -> None:
|
||||||
if bui.app.classic is not None:
|
if bui.app.plus is not None:
|
||||||
bui.apptimer(
|
bui.apptimer(
|
||||||
0.15,
|
0.15,
|
||||||
bui.Call(bui.app.classic.show_online_score_ui, 'leaderboards'),
|
bui.Call(bui.app.plus.show_game_service_ui, 'leaderboards'),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logging.warning('show_online_score_ui requires classic')
|
logging.warning('show_game_service_ui requires classic')
|
||||||
|
|
||||||
def _have_unlinkable_v1_accounts(self) -> bool:
|
def _have_unlinkable_v1_accounts(self) -> bool:
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
@ -1323,7 +1461,7 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
swidth = bui.get_string_width(name_str, suppress_warning=True)
|
swidth = bui.get_string_width(name_str, suppress_warning=True)
|
||||||
# Eww; number-fudging. Need to recalibrate this if
|
# Eww; number-fudging. Need to recalibrate this if
|
||||||
# account name scaling changes.
|
# account name scaling changes.
|
||||||
x = self._sub_width * 0.5 - swidth * 0.75 - 170
|
x = self._sub_width * 0.5 - swidth * 0.75 - 190
|
||||||
|
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
edit=self._account_name_what_is_text,
|
edit=self._account_name_what_is_text,
|
||||||
@ -1371,9 +1509,18 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.profile.browser import ProfileBrowserWindow
|
from bauiv1lib.profile.browser import ProfileBrowserWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
ProfileBrowserWindow(origin_widget=self._player_profiles_button)
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
|
ProfileBrowserWindow(
|
||||||
|
origin_widget=self._player_profiles_button
|
||||||
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
|
)
|
||||||
|
|
||||||
def _cancel_sign_in_press(self) -> None:
|
def _cancel_sign_in_press(self) -> None:
|
||||||
# If we're waiting on an adapter to give us credentials, abort.
|
# If we're waiting on an adapter to give us credentials, abort.
|
||||||
@ -1466,7 +1613,11 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
if isinstance(result, Exception):
|
if isinstance(result, Exception):
|
||||||
# For now just make a bit of noise if anything went wrong;
|
# For now just make a bit of noise if anything went wrong;
|
||||||
# can get more specific as needed later.
|
# can get more specific as needed later.
|
||||||
bui.screenmessage(bui.Lstr(resource='errorText'), color=(1, 0, 0))
|
logging.warning('Got error in v2 sign-in result: %s', result)
|
||||||
|
bui.screenmessage(
|
||||||
|
bui.Lstr(resource='internal.signInNoConnectionText'),
|
||||||
|
color=(1, 0, 0),
|
||||||
|
)
|
||||||
bui.getsound('error').play()
|
bui.getsound('error').play()
|
||||||
else:
|
else:
|
||||||
# Success! Plug in these credentials which will begin
|
# Success! Plug in these credentials which will begin
|
||||||
@ -1530,6 +1681,10 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.mainmenu import MainMenuWindow
|
from bauiv1lib.mainmenu import MainMenuWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
@ -1538,7 +1693,8 @@ class AccountSettingsWindow(bui.Window):
|
|||||||
if not self._modal:
|
if not self._modal:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
MainMenuWindow(transition='in_left').get_root_widget()
|
MainMenuWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
|
|||||||
@ -62,14 +62,11 @@ class V2ProxySignInWindow(bui.Window):
|
|||||||
label=bui.Lstr(resource='cancelText'),
|
label=bui.Lstr(resource='cancelText'),
|
||||||
on_activate_call=self._done,
|
on_activate_call=self._done,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
color=(0.55, 0.5, 0.6),
|
|
||||||
textcolor=(0.75, 0.7, 0.8),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if bool(False):
|
bui.containerwidget(
|
||||||
bui.containerwidget(
|
edit=self._root_widget, cancel_button=self._cancel_button
|
||||||
edit=self._root_widget, cancel_button=self._cancel_button
|
)
|
||||||
)
|
|
||||||
|
|
||||||
self._update_timer: bui.AppTimer | None = None
|
self._update_timer: bui.AppTimer | None = None
|
||||||
|
|
||||||
@ -242,4 +239,7 @@ class V2ProxySignInWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _done(self) -> None:
|
def _done(self) -> None:
|
||||||
|
# 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='out_scale')
|
bui.containerwidget(edit=self._root_widget, transition='out_scale')
|
||||||
|
|||||||
@ -93,6 +93,7 @@ class ConfigNumberEdit:
|
|||||||
displayname: str | bui.Lstr | None = None,
|
displayname: str | bui.Lstr | None = None,
|
||||||
changesound: bool = True,
|
changesound: bool = True,
|
||||||
textscale: float = 1.0,
|
textscale: float = 1.0,
|
||||||
|
as_percent: bool = False,
|
||||||
):
|
):
|
||||||
if displayname is None:
|
if displayname is None:
|
||||||
displayname = configkey
|
displayname = configkey
|
||||||
@ -103,6 +104,7 @@ class ConfigNumberEdit:
|
|||||||
self._increment = increment
|
self._increment = increment
|
||||||
self._callback = callback
|
self._callback = callback
|
||||||
self._value = bui.app.config.resolve(configkey)
|
self._value = bui.app.config.resolve(configkey)
|
||||||
|
self._as_percent = as_percent
|
||||||
|
|
||||||
self.nametext = bui.textwidget(
|
self.nametext = bui.textwidget(
|
||||||
parent=parent,
|
parent=parent,
|
||||||
@ -166,4 +168,8 @@ class ConfigNumberEdit:
|
|||||||
bui.app.config.apply_and_commit()
|
bui.app.config.apply_and_commit()
|
||||||
|
|
||||||
def _update_display(self) -> None:
|
def _update_display(self) -> None:
|
||||||
bui.textwidget(edit=self.valuetext, text=f'{self._value:.1f}')
|
if self._as_percent:
|
||||||
|
val = f'{round(self._value*100.0)}%'
|
||||||
|
else:
|
||||||
|
val = f'{self._value:.1f}'
|
||||||
|
bui.textwidget(edit=self.valuetext, text=val)
|
||||||
|
|||||||
@ -1,80 +0,0 @@
|
|||||||
# Released under the MIT License. See LICENSE for details.
|
|
||||||
#
|
|
||||||
"""UI for dealing with broken config files."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import bauiv1 as bui
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigErrorWindow(bui.Window):
|
|
||||||
"""Window for dealing with a broken config."""
|
|
||||||
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self._config_file_path = bui.app.env.config_file_path
|
|
||||||
width = 800
|
|
||||||
super().__init__(
|
|
||||||
bui.containerwidget(size=(width, 400), transition='in_right')
|
|
||||||
)
|
|
||||||
padding = 20
|
|
||||||
bui.textwidget(
|
|
||||||
parent=self._root_widget,
|
|
||||||
position=(padding, 220 + 60),
|
|
||||||
size=(width - 2 * padding, 100 - 2 * padding),
|
|
||||||
h_align='center',
|
|
||||||
v_align='top',
|
|
||||||
scale=0.73,
|
|
||||||
text=(
|
|
||||||
f'Error reading {bui.appnameupper()} config file'
|
|
||||||
':\n\n\nCheck the console'
|
|
||||||
' (press ~ twice) for details.\n\nWould you like to quit and'
|
|
||||||
' try to fix it by hand\nor overwrite it with defaults?\n\n'
|
|
||||||
'(high scores, player profiles, etc will be lost if you'
|
|
||||||
' overwrite)'
|
|
||||||
),
|
|
||||||
)
|
|
||||||
bui.textwidget(
|
|
||||||
parent=self._root_widget,
|
|
||||||
position=(padding, 198 + 60),
|
|
||||||
size=(width - 2 * padding, 100 - 2 * padding),
|
|
||||||
h_align='center',
|
|
||||||
v_align='top',
|
|
||||||
scale=0.5,
|
|
||||||
text=self._config_file_path,
|
|
||||||
)
|
|
||||||
quit_button = bui.buttonwidget(
|
|
||||||
parent=self._root_widget,
|
|
||||||
position=(35, 30),
|
|
||||||
size=(240, 54),
|
|
||||||
label='Quit and Edit',
|
|
||||||
on_activate_call=self._quit,
|
|
||||||
)
|
|
||||||
bui.buttonwidget(
|
|
||||||
parent=self._root_widget,
|
|
||||||
position=(width - 370, 30),
|
|
||||||
size=(330, 54),
|
|
||||||
label='Overwrite with Defaults',
|
|
||||||
on_activate_call=self._defaults,
|
|
||||||
)
|
|
||||||
bui.containerwidget(
|
|
||||||
edit=self._root_widget,
|
|
||||||
cancel_button=quit_button,
|
|
||||||
selected_child=quit_button,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _quit(self) -> None:
|
|
||||||
bui.apptimer(0.001, self._edit_and_quit)
|
|
||||||
bui.lock_all_input()
|
|
||||||
|
|
||||||
def _edit_and_quit(self) -> None:
|
|
||||||
bui.open_file_externally(self._config_file_path)
|
|
||||||
bui.apptimer(0.1, bui.quit)
|
|
||||||
|
|
||||||
def _defaults(self) -> None:
|
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
||||||
bui.getsound('gunCocking').play()
|
|
||||||
bui.screenmessage('settings reset.', color=(1, 1, 0))
|
|
||||||
|
|
||||||
# At this point settings are already set; lets just commit them
|
|
||||||
# to disk.
|
|
||||||
bui.commit_app_config(force=True)
|
|
||||||
@ -85,8 +85,8 @@ class CoopBrowserWindow(bui.Window):
|
|||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
self._width = 1320 if uiscale is bui.UIScale.SMALL else 1120
|
self._width = 1520 if uiscale is bui.UIScale.SMALL else 1120
|
||||||
self._x_inset = x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
|
self._x_inset = x_inset = 200 if uiscale is bui.UIScale.SMALL else 0
|
||||||
self._height = (
|
self._height = (
|
||||||
657
|
657
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -415,7 +415,7 @@ class CoopBrowserWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Decrement time on our tournament buttons.
|
# Decrement time on our tournament buttons.
|
||||||
ads_enabled = bui.have_incentivized_ad()
|
ads_enabled = plus.have_incentivized_ad()
|
||||||
for tbtn in self._tournament_buttons:
|
for tbtn in self._tournament_buttons:
|
||||||
tbtn.time_remaining = max(0, tbtn.time_remaining - 1)
|
tbtn.time_remaining = max(0, tbtn.time_remaining - 1)
|
||||||
if tbtn.time_remaining_value_text is not None:
|
if tbtn.time_remaining_value_text is not None:
|
||||||
@ -430,7 +430,7 @@ class CoopBrowserWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Also adjust the ad icon visibility.
|
# Also adjust the ad icon visibility.
|
||||||
if tbtn.allow_ads and bui.has_video_ads():
|
if tbtn.allow_ads and plus.has_video_ads():
|
||||||
bui.imagewidget(
|
bui.imagewidget(
|
||||||
edit=tbtn.entry_fee_ad_image,
|
edit=tbtn.entry_fee_ad_image,
|
||||||
opacity=1.0 if ads_enabled else 0.25,
|
opacity=1.0 if ads_enabled else 0.25,
|
||||||
@ -1019,6 +1019,10 @@ class CoopBrowserWindow(bui.Window):
|
|||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
from bauiv1lib.league.rankwindow import LeagueRankWindow
|
from bauiv1lib.league.rankwindow import LeagueRankWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
@ -1032,7 +1036,8 @@ class CoopBrowserWindow(bui.Window):
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
LeagueRankWindow(
|
LeagueRankWindow(
|
||||||
origin_widget=self._league_rank_button.get_button()
|
origin_widget=self._league_rank_button.get_button()
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _switch_to_score(
|
def _switch_to_score(
|
||||||
@ -1043,6 +1048,10 @@ class CoopBrowserWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
@ -1058,7 +1067,8 @@ class CoopBrowserWindow(bui.Window):
|
|||||||
origin_widget=self._store_button.get_button(),
|
origin_widget=self._store_button.get_button(),
|
||||||
show_tab=show_tab,
|
show_tab=show_tab,
|
||||||
back_location='CoopBrowserWindow',
|
back_location='CoopBrowserWindow',
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_tourney_data_up_to_date(self) -> bool:
|
def is_tourney_data_up_to_date(self) -> bool:
|
||||||
@ -1218,6 +1228,10 @@ class CoopBrowserWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.play import PlayWindow
|
from bauiv1lib.play import PlayWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# If something is selected, store it.
|
# If something is selected, store it.
|
||||||
self._save_state()
|
self._save_state()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
@ -1225,7 +1239,8 @@ class CoopBrowserWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlayWindow(transition='in_left').get_root_widget()
|
PlayWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
|
|||||||
@ -638,8 +638,8 @@ class TournamentButton:
|
|||||||
|
|
||||||
# Now, if this fee allows ads and we support video ads, show
|
# Now, if this fee allows ads and we support video ads, show
|
||||||
# the 'or ad' version.
|
# the 'or ad' version.
|
||||||
if allow_ads and bui.has_video_ads():
|
if allow_ads and plus.has_video_ads():
|
||||||
ads_enabled = bui.have_incentivized_ad()
|
ads_enabled = plus.have_incentivized_ad()
|
||||||
bui.imagewidget(
|
bui.imagewidget(
|
||||||
edit=self.entry_fee_ad_image,
|
edit=self.entry_fee_ad_image,
|
||||||
opacity=1.0 if ads_enabled else 0.25,
|
opacity=1.0 if ads_enabled else 0.25,
|
||||||
|
|||||||
@ -359,10 +359,15 @@ class CreditsListWindow(bui.Window):
|
|||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
from bauiv1lib.mainmenu import MainMenuWindow
|
from bauiv1lib.mainmenu import MainMenuWindow
|
||||||
|
|
||||||
|
# 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(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
MainMenuWindow(transition='in_left').get_root_widget()
|
MainMenuWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -379,8 +379,13 @@ class DebugWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.advanced import AdvancedSettingsWindow
|
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='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AdvancedSettingsWindow(transition='in_left').get_root_widget()
|
AdvancedSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|||||||
133
src/assets/ba_data/python/bauiv1lib/discord.py
Normal file
133
src/assets/ba_data/python/bauiv1lib/discord.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
# Released under the MIT License. See LICENSE for details.
|
||||||
|
#
|
||||||
|
"""UI functionality for the Discord window."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import bauiv1 as bui
|
||||||
|
|
||||||
|
|
||||||
|
class DiscordWindow(bui.Window):
|
||||||
|
"""Window for joining the Discord."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
transition: str = 'in_right',
|
||||||
|
origin_widget: bui.Widget | None = None,
|
||||||
|
):
|
||||||
|
if bui.app.classic is None:
|
||||||
|
raise RuntimeError('This requires classic support.')
|
||||||
|
|
||||||
|
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 = bui.app.ui_v1.uiscale
|
||||||
|
self._width = 800
|
||||||
|
x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
|
||||||
|
self._height = 320
|
||||||
|
top_extra = 10 if uiscale is bui.UIScale.SMALL else 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=(
|
||||||
|
1.6
|
||||||
|
if uiscale is bui.UIScale.SMALL
|
||||||
|
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),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
# Do we need to translate 'Discord'? Or is that always the name?
|
||||||
|
self._title_text = bui.textwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
position=(0, self._height - 52),
|
||||||
|
size=(self._width, 25),
|
||||||
|
text='Discord',
|
||||||
|
color=app.ui_v1.title_color,
|
||||||
|
h_align='center',
|
||||||
|
v_align='top',
|
||||||
|
)
|
||||||
|
|
||||||
|
min_size = min(self._width - 25, self._height - 25)
|
||||||
|
bui.imagewidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
position=(40, -15),
|
||||||
|
size=(min_size, min_size),
|
||||||
|
texture=bui.gettexture('discordServer'),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Hmm should we translate this? The discord server is mostly
|
||||||
|
# English so being able to read this might be a good screening
|
||||||
|
# process?..
|
||||||
|
bui.textwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
position=(self._width / 2 - 60, self._height - 100),
|
||||||
|
text='We have our own Discord server where you can:\n- Find new'
|
||||||
|
' friends and people to play with\n- Participate in Office'
|
||||||
|
' Hours/Coffee with Eric\n- Share mods, plugins, art, and'
|
||||||
|
' memes\n- Report bugs and make feature suggestions\n'
|
||||||
|
'- Troubleshoot issues',
|
||||||
|
maxwidth=(self._width - 10) / 2,
|
||||||
|
color=(1, 1, 1, 1),
|
||||||
|
h_align='left',
|
||||||
|
v_align='top',
|
||||||
|
)
|
||||||
|
|
||||||
|
bui.buttonwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
position=(self._width / 2 - 30, 20),
|
||||||
|
size=(self._width / 2 - 60, 60),
|
||||||
|
autoselect=True,
|
||||||
|
label=bui.Lstr(resource='discordJoinText'),
|
||||||
|
text_scale=1.0,
|
||||||
|
on_activate_call=bui.Call(
|
||||||
|
bui.open_url, 'https://ballistica.net/discord'
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
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),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _do_back(self) -> None:
|
||||||
|
bui.containerwidget(edit=self._root_widget, transition='out_scale')
|
||||||
@ -94,8 +94,8 @@ class GatherWindow(bui.Window):
|
|||||||
bui.app.ui_v1.set_main_menu_location('Gather')
|
bui.app.ui_v1.set_main_menu_location('Gather')
|
||||||
bui.set_party_icon_always_visible(True)
|
bui.set_party_icon_always_visible(True)
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
self._width = 1240 if uiscale is bui.UIScale.SMALL else 1040
|
self._width = 1440 if uiscale is bui.UIScale.SMALL else 1040
|
||||||
x_offs = 100 if uiscale is bui.UIScale.SMALL else 0
|
x_offs = 200 if uiscale is bui.UIScale.SMALL else 0
|
||||||
self._height = (
|
self._height = (
|
||||||
582
|
582
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -270,12 +270,17 @@ class GatherWindow(bui.Window):
|
|||||||
"""Called by the private-hosting tab to select a playlist."""
|
"""Called by the private-hosting tab to select a playlist."""
|
||||||
from bauiv1lib.play import PlayWindow
|
from bauiv1lib.play import PlayWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.selecting_private_party_playlist = True
|
bui.app.ui_v1.selecting_private_party_playlist = True
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlayWindow(origin_widget=origin_widget).get_root_widget()
|
PlayWindow(origin_widget=origin_widget).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _set_tab(self, tab_id: TabID) -> None:
|
def _set_tab(self, tab_id: TabID) -> None:
|
||||||
@ -383,11 +388,16 @@ class GatherWindow(bui.Window):
|
|||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
from bauiv1lib.mainmenu import MainMenuWindow
|
from bauiv1lib.mainmenu import MainMenuWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
MainMenuWindow(transition='in_left').get_root_widget()
|
MainMenuWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -16,10 +16,6 @@ if TYPE_CHECKING:
|
|||||||
class AboutGatherTab(GatherTab):
|
class AboutGatherTab(GatherTab):
|
||||||
"""The about tab in the gather UI"""
|
"""The about tab in the gather UI"""
|
||||||
|
|
||||||
def __init__(self, window: GatherWindow) -> None:
|
|
||||||
super().__init__(window)
|
|
||||||
self._container: bui.Widget | None = None
|
|
||||||
|
|
||||||
def on_activate(
|
def on_activate(
|
||||||
self,
|
self,
|
||||||
parent_widget: bui.Widget,
|
parent_widget: bui.Widget,
|
||||||
@ -29,9 +25,45 @@ class AboutGatherTab(GatherTab):
|
|||||||
region_left: float,
|
region_left: float,
|
||||||
region_bottom: float,
|
region_bottom: float,
|
||||||
) -> bui.Widget:
|
) -> bui.Widget:
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
|
try_tickets = plus.get_v1_account_misc_read_val(
|
||||||
|
'friendTryTickets', None
|
||||||
|
)
|
||||||
|
|
||||||
|
show_message = True
|
||||||
|
# Squish message as needed to get things to fit nicely at
|
||||||
|
# various scales.
|
||||||
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
|
message_height = (
|
||||||
|
210
|
||||||
|
if uiscale is bui.UIScale.SMALL
|
||||||
|
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.
|
||||||
|
show_message_extra = not bui.app.env.vr
|
||||||
|
message_extra_height = 60
|
||||||
|
show_invite = try_tickets is not None
|
||||||
|
invite_height = 80
|
||||||
|
show_discord = True
|
||||||
|
discord_height = 80
|
||||||
|
|
||||||
|
c_height = 0
|
||||||
|
if show_message:
|
||||||
|
c_height += message_height
|
||||||
|
if show_message_extra:
|
||||||
|
c_height += message_extra_height
|
||||||
|
if show_invite:
|
||||||
|
c_height += invite_height
|
||||||
|
if show_discord:
|
||||||
|
c_height += discord_height
|
||||||
|
|
||||||
party_button_label = bui.charstr(bui.SpecialChar.TOP_BUTTON)
|
party_button_label = bui.charstr(bui.SpecialChar.TOP_BUTTON)
|
||||||
message = bui.Lstr(
|
message = bui.Lstr(
|
||||||
resource='gatherWindow.aboutDescriptionText',
|
resource='gatherWindow.aboutDescriptionText',
|
||||||
@ -41,9 +73,7 @@ class AboutGatherTab(GatherTab):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Let's not talk about sharing in vr-mode; its tricky to fit more
|
if show_message_extra:
|
||||||
# than one head in a VR-headset ;-)
|
|
||||||
if not bui.app.env.vr:
|
|
||||||
message = bui.Lstr(
|
message = bui.Lstr(
|
||||||
value='${A}\n\n${B}',
|
value='${A}\n\n${B}',
|
||||||
subs=[
|
subs=[
|
||||||
@ -57,47 +87,52 @@ class AboutGatherTab(GatherTab):
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
string_height = 400
|
|
||||||
include_invite = True
|
scroll_widget = bui.scrollwidget(
|
||||||
msc_scale = 1.1
|
|
||||||
c_height_2 = min(region_height, string_height * msc_scale + 100)
|
|
||||||
try_tickets = plus.get_v1_account_misc_read_val(
|
|
||||||
'friendTryTickets', None
|
|
||||||
)
|
|
||||||
if try_tickets is None:
|
|
||||||
include_invite = False
|
|
||||||
self._container = bui.containerwidget(
|
|
||||||
parent=parent_widget,
|
parent=parent_widget,
|
||||||
|
position=(region_left, region_bottom),
|
||||||
|
size=(region_width, region_height),
|
||||||
|
highlight=False,
|
||||||
|
border_opacity=0,
|
||||||
|
)
|
||||||
|
msc_scale = 1.1
|
||||||
|
|
||||||
|
container = bui.containerwidget(
|
||||||
|
parent=scroll_widget,
|
||||||
position=(
|
position=(
|
||||||
region_left,
|
region_left,
|
||||||
region_bottom + (region_height - c_height_2) * 0.5,
|
region_bottom + (region_height - c_height) * 0.5,
|
||||||
),
|
),
|
||||||
size=(region_width, c_height_2),
|
size=(region_width, c_height),
|
||||||
background=False,
|
background=False,
|
||||||
selectable=include_invite,
|
selectable=show_invite or show_discord,
|
||||||
)
|
)
|
||||||
bui.widget(edit=self._container, up_widget=tab_button)
|
# Allows escaping if we select the container somehow (though
|
||||||
|
# shouldn't be possible when buttons are present).
|
||||||
|
bui.widget(edit=container, up_widget=tab_button)
|
||||||
|
|
||||||
bui.textwidget(
|
y = c_height - 30
|
||||||
parent=self._container,
|
if show_message:
|
||||||
position=(
|
|
||||||
region_width * 0.5,
|
|
||||||
c_height_2 * (0.58 if include_invite else 0.5),
|
|
||||||
),
|
|
||||||
color=(0.6, 1.0, 0.6),
|
|
||||||
scale=msc_scale,
|
|
||||||
size=(0, 0),
|
|
||||||
maxwidth=region_width * 0.9,
|
|
||||||
max_height=c_height_2 * (0.7 if include_invite else 0.9),
|
|
||||||
h_align='center',
|
|
||||||
v_align='center',
|
|
||||||
text=message,
|
|
||||||
)
|
|
||||||
|
|
||||||
if include_invite:
|
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
parent=self._container,
|
parent=container,
|
||||||
position=(region_width * 0.57, 35),
|
position=(region_width * 0.5, y),
|
||||||
|
color=(0.6, 1.0, 0.6),
|
||||||
|
scale=msc_scale,
|
||||||
|
size=(0, 0),
|
||||||
|
maxwidth=region_width * 0.9,
|
||||||
|
max_height=message_height,
|
||||||
|
h_align='center',
|
||||||
|
v_align='top',
|
||||||
|
text=message,
|
||||||
|
)
|
||||||
|
y -= message_height
|
||||||
|
if show_message_extra:
|
||||||
|
y -= message_extra_height
|
||||||
|
|
||||||
|
if show_invite:
|
||||||
|
bui.textwidget(
|
||||||
|
parent=container,
|
||||||
|
position=(region_width * 0.57, y),
|
||||||
color=(0, 1, 0),
|
color=(0, 1, 0),
|
||||||
scale=0.6,
|
scale=0.6,
|
||||||
size=(0, 0),
|
size=(0, 0),
|
||||||
@ -110,9 +145,9 @@ class AboutGatherTab(GatherTab):
|
|||||||
subs=[('${COUNT}', str(try_tickets))],
|
subs=[('${COUNT}', str(try_tickets))],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
bui.buttonwidget(
|
invite_button = bui.buttonwidget(
|
||||||
parent=self._container,
|
parent=container,
|
||||||
position=(region_width * 0.59, 10),
|
position=(region_width * 0.59, y - 25),
|
||||||
size=(230, 50),
|
size=(230, 50),
|
||||||
color=(0.54, 0.42, 0.56),
|
color=(0.54, 0.42, 0.56),
|
||||||
textcolor=(0, 1, 0),
|
textcolor=(0, 1, 0),
|
||||||
@ -124,7 +159,44 @@ class AboutGatherTab(GatherTab):
|
|||||||
on_activate_call=bui.WeakCall(self._invite_to_try_press),
|
on_activate_call=bui.WeakCall(self._invite_to_try_press),
|
||||||
up_widget=tab_button,
|
up_widget=tab_button,
|
||||||
)
|
)
|
||||||
return self._container
|
y -= invite_height
|
||||||
|
else:
|
||||||
|
invite_button = None
|
||||||
|
|
||||||
|
if show_discord:
|
||||||
|
bui.textwidget(
|
||||||
|
parent=container,
|
||||||
|
position=(region_width * 0.57, y),
|
||||||
|
color=(0.6, 0.6, 1),
|
||||||
|
scale=0.6,
|
||||||
|
size=(0, 0),
|
||||||
|
maxwidth=region_width * 0.5,
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
flatness=1.0,
|
||||||
|
text=bui.Lstr(resource='discordFriendsText'),
|
||||||
|
)
|
||||||
|
discord_button = bui.buttonwidget(
|
||||||
|
parent=container,
|
||||||
|
position=(region_width * 0.59, y - 25),
|
||||||
|
size=(230, 50),
|
||||||
|
color=(0.54, 0.42, 0.56),
|
||||||
|
textcolor=(0.6, 0.6, 1),
|
||||||
|
label=bui.Lstr(resource='discordJoinText'),
|
||||||
|
autoselect=True,
|
||||||
|
on_activate_call=bui.WeakCall(self._join_the_discord_press),
|
||||||
|
up_widget=(
|
||||||
|
invite_button if invite_button is not None else tab_button
|
||||||
|
),
|
||||||
|
)
|
||||||
|
y -= discord_height
|
||||||
|
else:
|
||||||
|
discord_button = None
|
||||||
|
|
||||||
|
if discord_button is not None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return scroll_widget
|
||||||
|
|
||||||
def _invite_to_try_press(self) -> None:
|
def _invite_to_try_press(self) -> None:
|
||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
@ -137,3 +209,10 @@ class AboutGatherTab(GatherTab):
|
|||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
return
|
return
|
||||||
handle_app_invites_press()
|
handle_app_invites_press()
|
||||||
|
|
||||||
|
def _join_the_discord_press(self) -> None:
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
from bauiv1lib.discord import DiscordWindow
|
||||||
|
|
||||||
|
assert bui.app.classic is not None
|
||||||
|
DiscordWindow().get_root_widget()
|
||||||
|
|||||||
@ -99,6 +99,7 @@ class ManualGatherTab(GatherTab):
|
|||||||
self._party_edit_name_text: bui.Widget | None = None
|
self._party_edit_name_text: bui.Widget | None = None
|
||||||
self._party_edit_addr_text: bui.Widget | None = None
|
self._party_edit_addr_text: bui.Widget | None = None
|
||||||
self._party_edit_port_text: bui.Widget | None = None
|
self._party_edit_port_text: bui.Widget | None = None
|
||||||
|
self._no_parties_added_text: bui.Widget | None = None
|
||||||
|
|
||||||
def on_activate(
|
def on_activate(
|
||||||
self,
|
self,
|
||||||
@ -142,6 +143,7 @@ class ManualGatherTab(GatherTab):
|
|||||||
playsound=True,
|
playsound=True,
|
||||||
),
|
),
|
||||||
text=bui.Lstr(resource='gatherWindow.manualJoinSectionText'),
|
text=bui.Lstr(resource='gatherWindow.manualJoinSectionText'),
|
||||||
|
glow_type='uniform',
|
||||||
)
|
)
|
||||||
self._favorites_text = bui.textwidget(
|
self._favorites_text = bui.textwidget(
|
||||||
parent=self._container,
|
parent=self._container,
|
||||||
@ -162,6 +164,7 @@ class ManualGatherTab(GatherTab):
|
|||||||
playsound=True,
|
playsound=True,
|
||||||
),
|
),
|
||||||
text=bui.Lstr(resource='gatherWindow.favoritesText'),
|
text=bui.Lstr(resource='gatherWindow.favoritesText'),
|
||||||
|
glow_type='uniform',
|
||||||
)
|
)
|
||||||
bui.widget(edit=self._join_by_address_text, up_widget=tab_button)
|
bui.widget(edit=self._join_by_address_text, up_widget=tab_button)
|
||||||
bui.widget(
|
bui.widget(
|
||||||
@ -316,7 +319,7 @@ class ManualGatherTab(GatherTab):
|
|||||||
self._check_button = bui.textwidget(
|
self._check_button = bui.textwidget(
|
||||||
parent=self._container,
|
parent=self._container,
|
||||||
size=(250, 60),
|
size=(250, 60),
|
||||||
text=bui.Lstr(resource='gatherWindow.' 'showMyAddressText'),
|
text=bui.Lstr(resource='gatherWindow.showMyAddressText'),
|
||||||
v_align='center',
|
v_align='center',
|
||||||
h_align='center',
|
h_align='center',
|
||||||
click_activate=True,
|
click_activate=True,
|
||||||
@ -331,6 +334,7 @@ class ManualGatherTab(GatherTab):
|
|||||||
self._container,
|
self._container,
|
||||||
c_width,
|
c_width,
|
||||||
),
|
),
|
||||||
|
glow_type='uniform',
|
||||||
)
|
)
|
||||||
bui.widget(edit=self._check_button, up_widget=btn)
|
bui.widget(edit=self._check_button, up_widget=btn)
|
||||||
|
|
||||||
@ -453,6 +457,24 @@ class ManualGatherTab(GatherTab):
|
|||||||
claims_left_right=True,
|
claims_left_right=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._no_parties_added_text = bui.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
text='',
|
||||||
|
color=(0.6, 0.6, 0.6),
|
||||||
|
scale=1.2,
|
||||||
|
position=(
|
||||||
|
(
|
||||||
|
(190 if uiscale is bui.UIScale.SMALL else 225)
|
||||||
|
+ sub_scroll_width * 0.5
|
||||||
|
),
|
||||||
|
v + sub_scroll_height * 0.5,
|
||||||
|
),
|
||||||
|
glow_type='uniform',
|
||||||
|
)
|
||||||
|
|
||||||
self._favorite_selected = None
|
self._favorite_selected = None
|
||||||
self._refresh_favorites()
|
self._refresh_favorites()
|
||||||
|
|
||||||
@ -695,6 +717,12 @@ class ManualGatherTab(GatherTab):
|
|||||||
|
|
||||||
assert self._favorites_scroll_width is not None
|
assert self._favorites_scroll_width is not None
|
||||||
assert self._favorites_connect_button is not None
|
assert self._favorites_connect_button is not None
|
||||||
|
|
||||||
|
bui.textwidget(
|
||||||
|
edit=self._no_parties_added_text,
|
||||||
|
text='',
|
||||||
|
)
|
||||||
|
num_of_fav = 0
|
||||||
for i, server in enumerate(servers):
|
for i, server in enumerate(servers):
|
||||||
txt = bui.textwidget(
|
txt = bui.textwidget(
|
||||||
parent=self._columnwidget,
|
parent=self._columnwidget,
|
||||||
@ -718,11 +746,13 @@ class ManualGatherTab(GatherTab):
|
|||||||
)
|
)
|
||||||
if i == 0:
|
if i == 0:
|
||||||
bui.widget(edit=txt, up_widget=self._favorites_text)
|
bui.widget(edit=txt, up_widget=self._favorites_text)
|
||||||
|
self._favorite_selected = server
|
||||||
bui.widget(
|
bui.widget(
|
||||||
edit=txt,
|
edit=txt,
|
||||||
left_widget=self._favorites_connect_button,
|
left_widget=self._favorites_connect_button,
|
||||||
right_widget=txt,
|
right_widget=txt,
|
||||||
)
|
)
|
||||||
|
num_of_fav = num_of_fav + 1
|
||||||
|
|
||||||
# If there's no servers, allow selecting out of the scroll area
|
# If there's no servers, allow selecting out of the scroll area
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
@ -735,6 +765,11 @@ class ManualGatherTab(GatherTab):
|
|||||||
up_widget=self._favorites_text,
|
up_widget=self._favorites_text,
|
||||||
left_widget=self._favorites_connect_button,
|
left_widget=self._favorites_connect_button,
|
||||||
)
|
)
|
||||||
|
if num_of_fav == 0:
|
||||||
|
bui.textwidget(
|
||||||
|
edit=self._no_parties_added_text,
|
||||||
|
text=bui.Lstr(resource='gatherWindow.noPartiesAddedText'),
|
||||||
|
)
|
||||||
|
|
||||||
def on_deactivate(self) -> None:
|
def on_deactivate(self) -> None:
|
||||||
self._access_check_timer = None
|
self._access_check_timer = None
|
||||||
@ -800,8 +835,17 @@ class ManualGatherTab(GatherTab):
|
|||||||
}
|
}
|
||||||
config.commit()
|
config.commit()
|
||||||
bui.getsound('gunCocking').play()
|
bui.getsound('gunCocking').play()
|
||||||
|
bui.screenmessage(
|
||||||
|
bui.Lstr(
|
||||||
|
resource='addedToFavoritesText', subs=[('${NAME}', addr)]
|
||||||
|
),
|
||||||
|
color=(0, 1, 0),
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
bui.screenmessage('Invalid Address', color=(1, 0, 0))
|
bui.screenmessage(
|
||||||
|
bui.Lstr(resource='internal.invalidAddressErrorText'),
|
||||||
|
color=(1, 0, 0),
|
||||||
|
)
|
||||||
bui.getsound('error').play()
|
bui.getsound('error').play()
|
||||||
|
|
||||||
def _host_lookup_result(
|
def _host_lookup_result(
|
||||||
|
|||||||
@ -120,6 +120,7 @@ class PrivateGatherTab(GatherTab):
|
|||||||
playsound=True,
|
playsound=True,
|
||||||
),
|
),
|
||||||
text=bui.Lstr(resource='gatherWindow.privatePartyJoinText'),
|
text=bui.Lstr(resource='gatherWindow.privatePartyJoinText'),
|
||||||
|
glow_type='uniform',
|
||||||
)
|
)
|
||||||
self._host_sub_tab_text = bui.textwidget(
|
self._host_sub_tab_text = bui.textwidget(
|
||||||
parent=self._container,
|
parent=self._container,
|
||||||
@ -138,6 +139,7 @@ class PrivateGatherTab(GatherTab):
|
|||||||
playsound=True,
|
playsound=True,
|
||||||
),
|
),
|
||||||
text=bui.Lstr(resource='gatherWindow.privatePartyHostText'),
|
text=bui.Lstr(resource='gatherWindow.privatePartyHostText'),
|
||||||
|
glow_type='uniform',
|
||||||
)
|
)
|
||||||
bui.widget(edit=self._join_sub_tab_text, up_widget=tab_button)
|
bui.widget(edit=self._join_sub_tab_text, up_widget=tab_button)
|
||||||
bui.widget(
|
bui.widget(
|
||||||
@ -458,9 +460,9 @@ class PrivateGatherTab(GatherTab):
|
|||||||
scale=1.5,
|
scale=1.5,
|
||||||
size=(300, 50),
|
size=(300, 50),
|
||||||
editable=True,
|
editable=True,
|
||||||
|
max_chars=20,
|
||||||
description=bui.Lstr(resource='gatherWindow.partyCodeText'),
|
description=bui.Lstr(resource='gatherWindow.partyCodeText'),
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
maxwidth=250,
|
|
||||||
h_align='left',
|
h_align='left',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
text='',
|
text='',
|
||||||
@ -962,7 +964,7 @@ class PrivateGatherTab(GatherTab):
|
|||||||
code = cast(str, bui.textwidget(query=self._join_party_code_text))
|
code = cast(str, bui.textwidget(query=self._join_party_code_text))
|
||||||
if not code:
|
if not code:
|
||||||
bui.screenmessage(
|
bui.screenmessage(
|
||||||
bui.Lstr(resource='internal.invalidAddressErrorText'),
|
bui.Lstr(translate=('serverResponses', 'Invalid code.')),
|
||||||
color=(1, 0, 0),
|
color=(1, 0, 0),
|
||||||
)
|
)
|
||||||
bui.getsound('error').play()
|
bui.getsound('error').play()
|
||||||
|
|||||||
@ -114,7 +114,7 @@ class UIRow:
|
|||||||
self._name_widget = bui.textwidget(
|
self._name_widget = bui.textwidget(
|
||||||
text=bui.Lstr(value=party.name),
|
text=bui.Lstr(value=party.name),
|
||||||
parent=columnwidget,
|
parent=columnwidget,
|
||||||
size=(sub_scroll_width * 0.63, 20),
|
size=(sub_scroll_width * 0.46, 20),
|
||||||
position=(0 + hpos, 4 + vpos),
|
position=(0 + hpos, 4 + vpos),
|
||||||
selectable=True,
|
selectable=True,
|
||||||
on_select_call=bui.WeakCall(
|
on_select_call=bui.WeakCall(
|
||||||
@ -248,6 +248,7 @@ class AddrFetchThread(Thread):
|
|||||||
self._call = call
|
self._call = call
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
|
sock: socket.socket | None = None
|
||||||
try:
|
try:
|
||||||
# FIXME: Update this to work with IPv6 at some point.
|
# FIXME: Update this to work with IPv6 at some point.
|
||||||
import socket
|
import socket
|
||||||
@ -255,7 +256,6 @@ class AddrFetchThread(Thread):
|
|||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
sock.connect(('8.8.8.8', 80))
|
sock.connect(('8.8.8.8', 80))
|
||||||
val = sock.getsockname()[0]
|
val = sock.getsockname()[0]
|
||||||
sock.close()
|
|
||||||
bui.pushcall(bui.Call(self._call, val), from_other_thread=True)
|
bui.pushcall(bui.Call(self._call, val), from_other_thread=True)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
from efro.error import is_udp_communication_error
|
from efro.error import is_udp_communication_error
|
||||||
@ -265,6 +265,9 @@ class AddrFetchThread(Thread):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
logging.exception('Error in addr-fetch-thread')
|
logging.exception('Error in addr-fetch-thread')
|
||||||
|
finally:
|
||||||
|
if sock is not None:
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
|
||||||
class PingThread(Thread):
|
class PingThread(Thread):
|
||||||
@ -361,6 +364,7 @@ class PublicGatherTab(GatherTab):
|
|||||||
self._last_server_list_query_time: float | None = None
|
self._last_server_list_query_time: float | None = None
|
||||||
self._join_list_column: bui.Widget | None = None
|
self._join_list_column: bui.Widget | None = None
|
||||||
self._join_status_text: bui.Widget | None = None
|
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_value: bui.Widget | None = None
|
||||||
self._host_max_party_size_minus_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_max_party_size_plus_button: (bui.Widget | None) = None
|
||||||
@ -431,6 +435,7 @@ class PublicGatherTab(GatherTab):
|
|||||||
text=bui.Lstr(
|
text=bui.Lstr(
|
||||||
resource='gatherWindow.' 'joinPublicPartyDescriptionText'
|
resource='gatherWindow.' 'joinPublicPartyDescriptionText'
|
||||||
),
|
),
|
||||||
|
glow_type='uniform',
|
||||||
)
|
)
|
||||||
self._host_text = bui.textwidget(
|
self._host_text = bui.textwidget(
|
||||||
parent=self._container,
|
parent=self._container,
|
||||||
@ -453,6 +458,7 @@ class PublicGatherTab(GatherTab):
|
|||||||
text=bui.Lstr(
|
text=bui.Lstr(
|
||||||
resource='gatherWindow.' 'hostPublicPartyDescriptionText'
|
resource='gatherWindow.' 'hostPublicPartyDescriptionText'
|
||||||
),
|
),
|
||||||
|
glow_type='uniform',
|
||||||
)
|
)
|
||||||
bui.widget(edit=self._join_text, up_widget=tab_button)
|
bui.widget(edit=self._join_text, up_widget=tab_button)
|
||||||
bui.widget(
|
bui.widget(
|
||||||
@ -658,6 +664,18 @@ class PublicGatherTab(GatherTab):
|
|||||||
color=(0.6, 0.6, 0.6),
|
color=(0.6, 0.6, 0.6),
|
||||||
position=(c_width * 0.5, c_height * 0.5),
|
position=(c_width * 0.5, c_height * 0.5),
|
||||||
)
|
)
|
||||||
|
self._no_servers_found_text = bui.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
text='',
|
||||||
|
size=(0, 0),
|
||||||
|
scale=0.9,
|
||||||
|
flatness=1.0,
|
||||||
|
shadow=0.0,
|
||||||
|
h_align='center',
|
||||||
|
v_align='top',
|
||||||
|
color=(0.6, 0.6, 0.6),
|
||||||
|
position=(c_width * 0.5, c_height * 0.5),
|
||||||
|
)
|
||||||
|
|
||||||
def _build_host_tab(
|
def _build_host_tab(
|
||||||
self, region_width: float, region_height: float
|
self, region_width: float, region_height: float
|
||||||
@ -950,6 +968,9 @@ class PublicGatherTab(GatherTab):
|
|||||||
self._update_party_rows()
|
self._update_party_rows()
|
||||||
|
|
||||||
def _update_party_rows(self) -> None:
|
def _update_party_rows(self) -> None:
|
||||||
|
plus = bui.app.plus
|
||||||
|
assert plus is not None
|
||||||
|
|
||||||
columnwidget = self._join_list_column
|
columnwidget = self._join_list_column
|
||||||
if not columnwidget:
|
if not columnwidget:
|
||||||
return
|
return
|
||||||
@ -963,6 +984,7 @@ class PublicGatherTab(GatherTab):
|
|||||||
edit=self._host_scrollwidget,
|
edit=self._host_scrollwidget,
|
||||||
claims_up_down=(len(self._parties_displayed) > 0),
|
claims_up_down=(len(self._parties_displayed) > 0),
|
||||||
)
|
)
|
||||||
|
bui.textwidget(edit=self._no_servers_found_text, text='')
|
||||||
|
|
||||||
# Clip if we have more UI rows than parties to show.
|
# Clip if we have more UI rows than parties to show.
|
||||||
clipcount = len(self._ui_rows) - len(self._parties_displayed)
|
clipcount = len(self._ui_rows) - len(self._parties_displayed)
|
||||||
@ -972,6 +994,15 @@ class PublicGatherTab(GatherTab):
|
|||||||
|
|
||||||
# If we have no parties to show, we're done.
|
# If we have no parties to show, we're done.
|
||||||
if not self._parties_displayed:
|
if not self._parties_displayed:
|
||||||
|
text = self._join_status_text
|
||||||
|
if (
|
||||||
|
plus.get_v1_account_state() == 'signed_in'
|
||||||
|
and cast(str, bui.textwidget(query=text)) == ''
|
||||||
|
):
|
||||||
|
bui.textwidget(
|
||||||
|
edit=self._no_servers_found_text,
|
||||||
|
text=bui.Lstr(resource='noServersFoundText'),
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
sub_scroll_width = 830
|
sub_scroll_width = 830
|
||||||
|
|||||||
@ -334,7 +334,7 @@ class GetCurrencyWindow(bui.Window):
|
|||||||
tex_scale=1.2,
|
tex_scale=1.2,
|
||||||
) # 19.99-ish
|
) # 19.99-ish
|
||||||
|
|
||||||
self._enable_ad_button = bui.has_video_ads()
|
self._enable_ad_button = plus.has_video_ads()
|
||||||
h = self._width * 0.5 + 110.0
|
h = self._width * 0.5 + 110.0
|
||||||
v = self._height - b_size[1] - 115.0
|
v = self._height - b_size[1] - 115.0
|
||||||
|
|
||||||
@ -561,7 +561,7 @@ class GetCurrencyWindow(bui.Window):
|
|||||||
next_reward_ad_time
|
next_reward_ad_time
|
||||||
)
|
)
|
||||||
now = datetime.datetime.utcnow()
|
now = datetime.datetime.utcnow()
|
||||||
if bui.have_incentivized_ad() and (
|
if plus.have_incentivized_ad() and (
|
||||||
next_reward_ad_time is None or next_reward_ad_time <= now
|
next_reward_ad_time is None or next_reward_ad_time <= now
|
||||||
):
|
):
|
||||||
self._ad_button_greyed = False
|
self._ad_button_greyed = False
|
||||||
@ -732,8 +732,13 @@ class GetCurrencyWindow(bui.Window):
|
|||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
from bauiv1lib.store import browser
|
from bauiv1lib.store import browser
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
if self._transitioning_out:
|
if self._transitioning_out:
|
||||||
return
|
return
|
||||||
|
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
@ -745,7 +750,9 @@ class GetCurrencyWindow(bui.Window):
|
|||||||
).get_root_widget()
|
).get_root_widget()
|
||||||
if not self._from_modal_store:
|
if not self._from_modal_store:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(window)
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
|
window, from_window=self._root_widget
|
||||||
|
)
|
||||||
self._transitioning_out = True
|
self._transitioning_out = True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -36,8 +36,8 @@ class HelpWindow(bui.Window):
|
|||||||
self._main_menu = main_menu
|
self._main_menu = main_menu
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
width = 950 if uiscale is bui.UIScale.SMALL else 750
|
width = 1050 if uiscale is bui.UIScale.SMALL else 750
|
||||||
x_offs = 100 if uiscale is bui.UIScale.SMALL else 0
|
x_offs = 150 if uiscale is bui.UIScale.SMALL else 0
|
||||||
height = (
|
height = (
|
||||||
460
|
460
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -645,11 +645,16 @@ class HelpWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.mainmenu import MainMenuWindow
|
from bauiv1lib.mainmenu import MainMenuWindow
|
||||||
|
|
||||||
|
# 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(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
if self._main_menu:
|
if self._main_menu:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
MainMenuWindow(transition='in_left').get_root_widget()
|
MainMenuWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import babase
|
import bauiv1 as bui
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
@ -33,15 +33,15 @@ def split(chars: Iterable[str], maxlen: int) -> list[list[str]]:
|
|||||||
|
|
||||||
|
|
||||||
def generate_emojis(maxlen: int) -> list[list[str]]:
|
def generate_emojis(maxlen: int) -> list[list[str]]:
|
||||||
"""Generates a lot of UTF8 emojis prepared for babase.Keyboard pages"""
|
"""Generates a lot of UTF8 emojis prepared for bui.Keyboard pages"""
|
||||||
all_emojis = split([chr(i) for i in range(0x1F601, 0x1F650)], maxlen)
|
all_emojis = split([chr(i) for i in range(0x1F601, 0x1F650)], maxlen)
|
||||||
all_emojis += split([chr(i) for i in range(0x2702, 0x27B1)], maxlen)
|
all_emojis += split([chr(i) for i in range(0x2702, 0x27B1)], maxlen)
|
||||||
all_emojis += split([chr(i) for i in range(0x1F680, 0x1F6C1)], maxlen)
|
all_emojis += split([chr(i) for i in range(0x1F680, 0x1F6C1)], maxlen)
|
||||||
return all_emojis
|
return all_emojis
|
||||||
|
|
||||||
|
|
||||||
# ba_meta export keyboard
|
# ba_meta export bauiv1.Keyboard
|
||||||
class EnglishKeyboard(babase.Keyboard):
|
class EnglishKeyboard(bui.Keyboard):
|
||||||
"""Default English keyboard."""
|
"""Default English keyboard."""
|
||||||
|
|
||||||
name = 'English'
|
name = 'English'
|
||||||
|
|||||||
@ -501,9 +501,15 @@ class KioskWindow(bui.Window):
|
|||||||
def _do_full_menu(self) -> None:
|
def _do_full_menu(self) -> None:
|
||||||
from bauiv1lib.mainmenu import MainMenuWindow
|
from bauiv1lib.mainmenu import MainMenuWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
|
|
||||||
self._save_state()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
bui.app.classic.did_menu_intro = True # prevent delayed transition-in
|
bui.app.classic.did_menu_intro = True # prevent delayed transition-in
|
||||||
bui.app.ui_v1.set_main_menu_window(MainMenuWindow().get_root_widget())
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
|
MainMenuWindow().get_root_widget(), from_window=self._root_widget
|
||||||
|
)
|
||||||
|
|||||||
@ -1142,6 +1142,10 @@ class LeagueRankWindow(bui.Window):
|
|||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
from bauiv1lib.coop.browser import CoopBrowserWindow
|
from bauiv1lib.coop.browser import CoopBrowserWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
@ -1149,5 +1153,6 @@ class LeagueRankWindow(bui.Window):
|
|||||||
if not self._modal:
|
if not self._modal:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
CoopBrowserWindow(transition='in_left').get_root_widget()
|
CoopBrowserWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -311,8 +311,8 @@ class MainMenuWindow(bui.Window):
|
|||||||
else self._confirm_end_game
|
else self._confirm_end_game
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
# Assume we're in a client-session.
|
|
||||||
else:
|
else:
|
||||||
|
# Assume we're in a client-session.
|
||||||
bui.buttonwidget(
|
bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(h - self._button_width * 0.5 * scale, v),
|
position=(h - self._button_width * 0.5 * scale, v),
|
||||||
@ -360,7 +360,6 @@ class MainMenuWindow(bui.Window):
|
|||||||
tilt_scale=0.0,
|
tilt_scale=0.0,
|
||||||
draw_controller=store_button,
|
draw_controller=store_button,
|
||||||
)
|
)
|
||||||
|
|
||||||
self._tdelay += self._t_delay_inc
|
self._tdelay += self._t_delay_inc
|
||||||
else:
|
else:
|
||||||
self._store_button = None
|
self._store_button = None
|
||||||
@ -1039,6 +1038,10 @@ class MainMenuWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.confirm import QuitWindow
|
from bauiv1lib.confirm import QuitWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# Note: Normally we should go through bui.quit(confirm=True) but
|
# Note: Normally we should go through bui.quit(confirm=True) but
|
||||||
# invoking the window directly lets us scale it up from the
|
# invoking the window directly lets us scale it up from the
|
||||||
# button.
|
# button.
|
||||||
@ -1048,24 +1051,34 @@ class MainMenuWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.kiosk import KioskWindow
|
from bauiv1lib.kiosk import KioskWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
KioskWindow(transition='in_left').get_root_widget()
|
KioskWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _show_account_window(self) -> None:
|
def _show_account_window(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.account.settings import AccountSettingsWindow
|
from bauiv1lib.account.settings import AccountSettingsWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AccountSettingsWindow(
|
AccountSettingsWindow(
|
||||||
origin_widget=self._account_button
|
origin_widget=self._account_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_store_pressed(self) -> None:
|
def _on_store_pressed(self) -> None:
|
||||||
@ -1073,6 +1086,10 @@ class MainMenuWindow(bui.Window):
|
|||||||
from bauiv1lib.store.browser import StoreBrowserWindow
|
from bauiv1lib.store.browser import StoreBrowserWindow
|
||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
@ -1085,7 +1102,8 @@ class MainMenuWindow(bui.Window):
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
StoreBrowserWindow(
|
StoreBrowserWindow(
|
||||||
origin_widget=self._store_button
|
origin_widget=self._store_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _is_benchmark(self) -> bool:
|
def _is_benchmark(self) -> bool:
|
||||||
@ -1150,8 +1168,11 @@ class MainMenuWindow(bui.Window):
|
|||||||
|
|
||||||
def _end_game(self) -> None:
|
def _end_game(self) -> None:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
if not self._root_widget:
|
|
||||||
|
# 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
|
return
|
||||||
|
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
bui.app.classic.return_to_main_menu_session_gracefully(reset_ui=False)
|
bui.app.classic.return_to_main_menu_session_gracefully(reset_ui=False)
|
||||||
|
|
||||||
@ -1167,39 +1188,54 @@ class MainMenuWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.creditslist import CreditsListWindow
|
from bauiv1lib.creditslist import CreditsListWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
CreditsListWindow(
|
CreditsListWindow(
|
||||||
origin_widget=self._credits_button
|
origin_widget=self._credits_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _howtoplay(self) -> None:
|
def _howtoplay(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.helpui import HelpWindow
|
from bauiv1lib.helpui import HelpWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
HelpWindow(
|
HelpWindow(
|
||||||
main_menu=True, origin_widget=self._how_to_play_button
|
main_menu=True, origin_widget=self._how_to_play_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _settings(self) -> None:
|
def _settings(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.allsettings import AllSettingsWindow
|
from bauiv1lib.settings.allsettings import AllSettingsWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AllSettingsWindow(
|
AllSettingsWindow(
|
||||||
origin_widget=self._settings_button
|
origin_widget=self._settings_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _resume_and_call(self, call: Callable[[], Any]) -> None:
|
def _resume_and_call(self, call: Callable[[], Any]) -> None:
|
||||||
@ -1208,10 +1244,12 @@ class MainMenuWindow(bui.Window):
|
|||||||
|
|
||||||
def _do_game_service_press(self) -> None:
|
def _do_game_service_press(self) -> None:
|
||||||
self._save_state()
|
self._save_state()
|
||||||
if bui.app.classic is not None:
|
if bui.app.plus is not None:
|
||||||
bui.app.classic.show_online_score_ui()
|
bui.app.plus.show_game_service_ui()
|
||||||
else:
|
else:
|
||||||
logging.warning('classic is required to show game service ui')
|
logging.warning(
|
||||||
|
'plus feature-set is required to show game service ui'
|
||||||
|
)
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
# Don't do this for the in-game menu.
|
# Don't do this for the in-game menu.
|
||||||
@ -1282,35 +1320,50 @@ class MainMenuWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.gather import GatherWindow
|
from bauiv1lib.gather import GatherWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
GatherWindow(origin_widget=self._gather_button).get_root_widget()
|
GatherWindow(origin_widget=self._gather_button).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _watch_press(self) -> None:
|
def _watch_press(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.watch import WatchWindow
|
from bauiv1lib.watch import WatchWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
WatchWindow(origin_widget=self._watch_button).get_root_widget()
|
WatchWindow(origin_widget=self._watch_button).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _play_press(self) -> None:
|
def _play_press(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.play import PlayWindow
|
from bauiv1lib.play import PlayWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.selecting_private_party_playlist = False
|
bui.app.ui_v1.selecting_private_party_playlist = False
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlayWindow(origin_widget=self._start_button).get_root_widget()
|
PlayWindow(origin_widget=self._start_button).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _resume(self) -> None:
|
def _resume(self) -> None:
|
||||||
@ -1318,7 +1371,7 @@ class MainMenuWindow(bui.Window):
|
|||||||
bui.app.classic.resume()
|
bui.app.classic.resume()
|
||||||
if self._root_widget:
|
if self._root_widget:
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
bui.app.ui_v1.clear_main_menu_window()
|
bui.app.ui_v1.clear_main_menu_window(transition='out_right')
|
||||||
|
|
||||||
# If there's callbacks waiting for this window to go away, call them.
|
# If there's callbacks waiting for this window to go away, call them.
|
||||||
for call in bui.app.ui_v1.main_menu_resume_callbacks:
|
for call in bui.app.ui_v1.main_menu_resume_callbacks:
|
||||||
|
|||||||
@ -40,6 +40,7 @@ class PartyWindow(bui.Window):
|
|||||||
if uiscale is bui.UIScale.MEDIUM
|
if uiscale is bui.UIScale.MEDIUM
|
||||||
else 600
|
else 600
|
||||||
)
|
)
|
||||||
|
self._display_old_msgs = True
|
||||||
super().__init__(
|
super().__init__(
|
||||||
root_widget=bui.containerwidget(
|
root_widget=bui.containerwidget(
|
||||||
size=(self._width, self._height),
|
size=(self._width, self._height),
|
||||||
@ -92,9 +93,10 @@ class PartyWindow(bui.Window):
|
|||||||
iconscale=1.2,
|
iconscale=1.2,
|
||||||
)
|
)
|
||||||
|
|
||||||
info = bs.get_connection_to_host_info()
|
info = bs.get_connection_to_host_info_2()
|
||||||
if info.get('name', '') != '':
|
|
||||||
title = bui.Lstr(value=info['name'])
|
if info is not None and info.name != '':
|
||||||
|
title = bui.Lstr(value=info.name)
|
||||||
else:
|
else:
|
||||||
title = bui.Lstr(resource=self._r + '.titleText')
|
title = bui.Lstr(resource=self._r + '.titleText')
|
||||||
|
|
||||||
@ -142,12 +144,6 @@ class PartyWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
self._chat_texts: list[bui.Widget] = []
|
self._chat_texts: list[bui.Widget] = []
|
||||||
|
|
||||||
# add all existing messages if chat is not muted
|
|
||||||
if not bui.app.config.resolve('Chat Muted'):
|
|
||||||
msgs = bs.get_chat_messages()
|
|
||||||
for msg in msgs:
|
|
||||||
self._add_msg(msg)
|
|
||||||
|
|
||||||
self._text_field = txt = bui.textwidget(
|
self._text_field = txt = bui.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
editable=True,
|
editable=True,
|
||||||
@ -233,6 +229,23 @@ class PartyWindow(bui.Window):
|
|||||||
is_muted = bui.app.config.resolve('Chat Muted')
|
is_muted = bui.app.config.resolve('Chat Muted')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
|
|
||||||
|
choices: list[str] = ['unmute' if is_muted else 'mute']
|
||||||
|
choices_display: list[bui.Lstr] = [
|
||||||
|
bui.Lstr(resource='chatUnMuteText' if is_muted else 'chatMuteText')
|
||||||
|
]
|
||||||
|
|
||||||
|
# Allow the 'Add to Favorites' option only if we're actually
|
||||||
|
# connected to a party and if it doesn't seem to be a private
|
||||||
|
# party (those are dynamically assigned addresses and ports so
|
||||||
|
# it makes no sense to save them).
|
||||||
|
server_info = bs.get_connection_to_host_info_2()
|
||||||
|
if server_info is not None and not server_info.name.startswith(
|
||||||
|
'Private Party '
|
||||||
|
):
|
||||||
|
choices.append('add_to_favorites')
|
||||||
|
choices_display.append(bui.Lstr(resource='addToFavoritesText'))
|
||||||
|
|
||||||
PopupMenuWindow(
|
PopupMenuWindow(
|
||||||
position=self._menu_button.get_screen_space_center(),
|
position=self._menu_button.get_screen_space_center(),
|
||||||
scale=(
|
scale=(
|
||||||
@ -242,12 +255,8 @@ class PartyWindow(bui.Window):
|
|||||||
if uiscale is bui.UIScale.MEDIUM
|
if uiscale is bui.UIScale.MEDIUM
|
||||||
else 1.23
|
else 1.23
|
||||||
),
|
),
|
||||||
choices=['unmute' if is_muted else 'mute'],
|
choices=choices,
|
||||||
choices_display=[
|
choices_display=choices_display,
|
||||||
bui.Lstr(
|
|
||||||
resource='chatUnMuteText' if is_muted else 'chatMuteText'
|
|
||||||
)
|
|
||||||
],
|
|
||||||
current_choice='unmute' if is_muted else 'mute',
|
current_choice='unmute' if is_muted else 'mute',
|
||||||
delegate=self,
|
delegate=self,
|
||||||
)
|
)
|
||||||
@ -269,6 +278,12 @@ class PartyWindow(bui.Window):
|
|||||||
first.delete()
|
first.delete()
|
||||||
else:
|
else:
|
||||||
bui.textwidget(edit=self._muted_text, color=(1, 1, 1, 0.0))
|
bui.textwidget(edit=self._muted_text, color=(1, 1, 1, 0.0))
|
||||||
|
# add all existing messages if chat is not muted
|
||||||
|
if self._display_old_msgs:
|
||||||
|
msgs = bs.get_chat_messages()
|
||||||
|
for msg in msgs:
|
||||||
|
self._add_msg(msg)
|
||||||
|
self._display_old_msgs = False
|
||||||
|
|
||||||
# update roster section
|
# update roster section
|
||||||
roster = bs.get_game_roster()
|
roster = bs.get_game_roster()
|
||||||
@ -466,10 +481,75 @@ class PartyWindow(bui.Window):
|
|||||||
cfg = bui.app.config
|
cfg = bui.app.config
|
||||||
cfg['Chat Muted'] = choice == 'mute'
|
cfg['Chat Muted'] = choice == 'mute'
|
||||||
cfg.apply_and_commit()
|
cfg.apply_and_commit()
|
||||||
|
self._display_old_msgs = True
|
||||||
self._update()
|
self._update()
|
||||||
|
if choice == 'add_to_favorites':
|
||||||
|
info = bs.get_connection_to_host_info_2()
|
||||||
|
if info is not None:
|
||||||
|
self._add_to_favorites(
|
||||||
|
name=info.name,
|
||||||
|
address=info.address,
|
||||||
|
port_num=info.port,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# We should not allow the user to see this option
|
||||||
|
# if they aren't in a server; this is our bad.
|
||||||
|
bui.screenmessage(
|
||||||
|
bui.Lstr(resource='errorText'), color=(1, 0, 0)
|
||||||
|
)
|
||||||
|
bui.getsound('error').play()
|
||||||
else:
|
else:
|
||||||
print(f'unhandled popup type: {self._popup_type}')
|
print(f'unhandled popup type: {self._popup_type}')
|
||||||
|
|
||||||
|
def _add_to_favorites(
|
||||||
|
self, name: str, address: str | None, port_num: int | None
|
||||||
|
) -> None:
|
||||||
|
addr = address
|
||||||
|
if addr == '':
|
||||||
|
bui.screenmessage(
|
||||||
|
bui.Lstr(resource='internal.invalidAddressErrorText'),
|
||||||
|
color=(1, 0, 0),
|
||||||
|
)
|
||||||
|
bui.getsound('error').play()
|
||||||
|
return
|
||||||
|
port = port_num if port_num is not None else -1
|
||||||
|
if port > 65535 or port < 0:
|
||||||
|
bui.screenmessage(
|
||||||
|
bui.Lstr(resource='internal.invalidPortErrorText'),
|
||||||
|
color=(1, 0, 0),
|
||||||
|
)
|
||||||
|
bui.getsound('error').play()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Avoid empty names.
|
||||||
|
if not name:
|
||||||
|
name = f'{addr}@{port}'
|
||||||
|
|
||||||
|
config = bui.app.config
|
||||||
|
|
||||||
|
if addr:
|
||||||
|
if not isinstance(config.get('Saved Servers'), dict):
|
||||||
|
config['Saved Servers'] = {}
|
||||||
|
config['Saved Servers'][f'{addr}@{port}'] = {
|
||||||
|
'addr': addr,
|
||||||
|
'port': port,
|
||||||
|
'name': name,
|
||||||
|
}
|
||||||
|
config.commit()
|
||||||
|
bui.getsound('gunCocking').play()
|
||||||
|
bui.screenmessage(
|
||||||
|
bui.Lstr(
|
||||||
|
resource='addedToFavoritesText', subs=[('${NAME}', name)]
|
||||||
|
),
|
||||||
|
color=(0, 1, 0),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
bui.screenmessage(
|
||||||
|
bui.Lstr(resource='internal.invalidAddressErrorText'),
|
||||||
|
color=(1, 0, 0),
|
||||||
|
)
|
||||||
|
bui.getsound('error').play()
|
||||||
|
|
||||||
def popup_menu_closing(self, popup_window: PopupWindow) -> None:
|
def popup_menu_closing(self, popup_window: PopupWindow) -> None:
|
||||||
"""Called when the popup is closing."""
|
"""Called when the popup is closing."""
|
||||||
|
|
||||||
@ -481,7 +561,8 @@ class PartyWindow(bui.Window):
|
|||||||
kick_str = bui.Lstr(resource='kickText')
|
kick_str = bui.Lstr(resource='kickText')
|
||||||
else:
|
else:
|
||||||
# kick-votes appeared in build 14248
|
# kick-votes appeared in build 14248
|
||||||
if bs.get_connection_to_host_info().get('build_number', 0) < 14248:
|
info = bs.get_connection_to_host_info_2()
|
||||||
|
if info is None or info.build_number < 14248:
|
||||||
return
|
return
|
||||||
kick_str = bui.Lstr(resource='kickVoteText')
|
kick_str = bui.Lstr(resource='kickVoteText')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
@ -510,9 +591,17 @@ class PartyWindow(bui.Window):
|
|||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
"""Close the window."""
|
"""Close the window."""
|
||||||
|
# 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='out_scale')
|
bui.containerwidget(edit=self._root_widget, transition='out_scale')
|
||||||
|
|
||||||
def close_with_sound(self) -> None:
|
def close_with_sound(self) -> None:
|
||||||
"""Close the window and make a lovely sound."""
|
"""Close the window and make a lovely sound."""
|
||||||
|
# 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.getsound('swish').play()
|
bui.getsound('swish').play()
|
||||||
self.close()
|
self.close()
|
||||||
|
|||||||
@ -32,8 +32,8 @@ class PlayWindow(bui.Window):
|
|||||||
self._is_main_menu = not bui.app.ui_v1.selecting_private_party_playlist
|
self._is_main_menu = not bui.app.ui_v1.selecting_private_party_playlist
|
||||||
|
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
width = 1000 if uiscale is bui.UIScale.SMALL else 800
|
width = 1100 if uiscale is bui.UIScale.SMALL else 800
|
||||||
x_offs = 100 if uiscale is bui.UIScale.SMALL else 0
|
x_offs = 150 if uiscale is bui.UIScale.SMALL else 0
|
||||||
height = 550
|
height = 550
|
||||||
button_width = 400
|
button_width = 400
|
||||||
|
|
||||||
@ -521,13 +521,19 @@ class PlayWindow(bui.Window):
|
|||||||
|
|
||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
if self._is_main_menu:
|
if self._is_main_menu:
|
||||||
from bauiv1lib.mainmenu import MainMenuWindow
|
from bauiv1lib.mainmenu import MainMenuWindow
|
||||||
|
|
||||||
self._save_state()
|
self._save_state()
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
MainMenuWindow(transition='in_left').get_root_widget()
|
MainMenuWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
@ -538,7 +544,8 @@ class PlayWindow(bui.Window):
|
|||||||
self._save_state()
|
self._save_state()
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
GatherWindow(transition='in_left').get_root_widget()
|
GatherWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
@ -549,6 +556,10 @@ class PlayWindow(bui.Window):
|
|||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
from bauiv1lib.coop.browser import CoopBrowserWindow
|
from bauiv1lib.coop.browser import CoopBrowserWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
@ -559,26 +570,38 @@ class PlayWindow(bui.Window):
|
|||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
CoopBrowserWindow(origin_widget=self._coop_button).get_root_widget()
|
CoopBrowserWindow(
|
||||||
|
origin_widget=self._coop_button
|
||||||
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _team_tourney(self) -> None:
|
def _team_tourney(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.playlist.browser import PlaylistBrowserWindow
|
from bauiv1lib.playlist.browser import PlaylistBrowserWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlaylistBrowserWindow(
|
PlaylistBrowserWindow(
|
||||||
origin_widget=self._teams_button, sessiontype=bs.DualTeamSession
|
origin_widget=self._teams_button, sessiontype=bs.DualTeamSession
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _free_for_all(self) -> None:
|
def _free_for_all(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.playlist.browser import PlaylistBrowserWindow
|
from bauiv1lib.playlist.browser import PlaylistBrowserWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
@ -586,7 +609,8 @@ class PlayWindow(bui.Window):
|
|||||||
PlaylistBrowserWindow(
|
PlaylistBrowserWindow(
|
||||||
origin_widget=self._free_for_all_button,
|
origin_widget=self._free_for_all_button,
|
||||||
sessiontype=bs.FreeForAllSession,
|
sessiontype=bs.FreeForAllSession,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _draw_dude(
|
def _draw_dude(
|
||||||
|
|||||||
@ -198,7 +198,7 @@ class PlaylistAddGameWindow(bui.Window):
|
|||||||
txt = bui.textwidget(
|
txt = bui.textwidget(
|
||||||
parent=self._column,
|
parent=self._column,
|
||||||
position=(0, 0),
|
position=(0, 0),
|
||||||
size=(self._width - 88, 24),
|
size=(self._scroll_width * 1.1, 24),
|
||||||
text=gametype.get_display_string(),
|
text=gametype.get_display_string(),
|
||||||
h_align='left',
|
h_align='left',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
|
|||||||
@ -62,8 +62,8 @@ class PlaylistBrowserWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
|
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
self._width = 900.0 if uiscale is bui.UIScale.SMALL else 800.0
|
self._width = 1100.0 if uiscale is bui.UIScale.SMALL else 800.0
|
||||||
x_inset = 50 if uiscale is bui.UIScale.SMALL else 0
|
x_inset = 150 if uiscale is bui.UIScale.SMALL else 0
|
||||||
self._height = (
|
self._height = (
|
||||||
480
|
480
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -684,6 +684,10 @@ class PlaylistBrowserWindow(bui.Window):
|
|||||||
PlaylistCustomizeBrowserWindow,
|
PlaylistCustomizeBrowserWindow,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
@ -691,13 +695,18 @@ class PlaylistBrowserWindow(bui.Window):
|
|||||||
PlaylistCustomizeBrowserWindow(
|
PlaylistCustomizeBrowserWindow(
|
||||||
origin_widget=self._customize_button,
|
origin_widget=self._customize_button,
|
||||||
sessiontype=self._sessiontype,
|
sessiontype=self._sessiontype,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_back_press(self) -> None:
|
def _on_back_press(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.play import PlayWindow
|
from bauiv1lib.play import PlayWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# Store our selected playlist if that's changed.
|
# Store our selected playlist if that's changed.
|
||||||
if self._selected_playlist is not None:
|
if self._selected_playlist is not None:
|
||||||
prev_sel = bui.app.config.get(
|
prev_sel = bui.app.config.get(
|
||||||
@ -716,7 +725,8 @@ class PlaylistBrowserWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlayWindow(transition='in_left').get_root_widget()
|
PlayWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
|
|||||||
@ -47,8 +47,8 @@ class PlaylistCustomizeBrowserWindow(bui.Window):
|
|||||||
self._r = 'gameListWindow'
|
self._r = 'gameListWindow'
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
self._width = 750.0 if uiscale is bui.UIScale.SMALL else 650.0
|
self._width = 850.0 if uiscale is bui.UIScale.SMALL else 650.0
|
||||||
x_inset = 50.0 if uiscale is bui.UIScale.SMALL else 0.0
|
x_inset = 100.0 if uiscale is bui.UIScale.SMALL else 0.0
|
||||||
self._height = (
|
self._height = (
|
||||||
380.0
|
380.0
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -323,6 +323,10 @@ class PlaylistCustomizeBrowserWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.playlist import browser
|
from bauiv1lib.playlist import browser
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
if self._selected_playlist_name is not None:
|
if self._selected_playlist_name is not None:
|
||||||
cfg = bui.app.config
|
cfg = bui.app.config
|
||||||
cfg[
|
cfg[
|
||||||
@ -337,7 +341,8 @@ class PlaylistCustomizeBrowserWindow(bui.Window):
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
browser.PlaylistBrowserWindow(
|
browser.PlaylistBrowserWindow(
|
||||||
transition='in_left', sessiontype=self._sessiontype
|
transition='in_left', sessiontype=self._sessiontype
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _select(self, name: str, index: int) -> None:
|
def _select(self, name: str, index: int) -> None:
|
||||||
|
|||||||
@ -31,8 +31,8 @@ class PlaylistEditWindow(bui.Window):
|
|||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
self._width = 770 if uiscale is bui.UIScale.SMALL else 670
|
self._width = 870 if uiscale is bui.UIScale.SMALL else 670
|
||||||
x_inset = 50 if uiscale is bui.UIScale.SMALL else 0
|
x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
|
||||||
self._height = (
|
self._height = (
|
||||||
400
|
400
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -283,6 +283,10 @@ class PlaylistEditWindow(bui.Window):
|
|||||||
PlaylistCustomizeBrowserWindow,
|
PlaylistCustomizeBrowserWindow,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 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.getsound('powerdown01').play()
|
bui.getsound('powerdown01').play()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
@ -293,7 +297,8 @@ class PlaylistEditWindow(bui.Window):
|
|||||||
select_playlist=(
|
select_playlist=(
|
||||||
self._editcontroller.get_existing_playlist_name()
|
self._editcontroller.get_existing_playlist_name()
|
||||||
),
|
),
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _add(self) -> None:
|
def _add(self) -> None:
|
||||||
@ -315,6 +320,10 @@ class PlaylistEditWindow(bui.Window):
|
|||||||
PlaylistCustomizeBrowserWindow,
|
PlaylistCustomizeBrowserWindow,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
@ -380,7 +389,8 @@ class PlaylistEditWindow(bui.Window):
|
|||||||
transition='in_left',
|
transition='in_left',
|
||||||
sessiontype=self._editcontroller.get_session_type(),
|
sessiontype=self._editcontroller.get_session_type(),
|
||||||
select_playlist=new_name,
|
select_playlist=new_name,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save_press_with_sound(self) -> None:
|
def _save_press_with_sound(self) -> None:
|
||||||
|
|||||||
@ -92,7 +92,8 @@ class PlaylistEditController:
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlaylistEditWindow(
|
PlaylistEditWindow(
|
||||||
editcontroller=self, transition=transition
|
editcontroller=self, transition=transition
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=False, # Disable this check.
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_config_name(self) -> str:
|
def get_config_name(self) -> str:
|
||||||
@ -150,7 +151,8 @@ class PlaylistEditController:
|
|||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.clear_main_menu_window(transition='out_left')
|
bui.app.ui_v1.clear_main_menu_window(transition='out_left')
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlaylistAddGameWindow(editcontroller=self).get_root_widget()
|
PlaylistAddGameWindow(editcontroller=self).get_root_widget(),
|
||||||
|
from_window=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
def edit_game_pressed(self) -> None:
|
def edit_game_pressed(self) -> None:
|
||||||
@ -175,7 +177,8 @@ class PlaylistEditController:
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlaylistEditWindow(
|
PlaylistEditWindow(
|
||||||
editcontroller=self, transition='in_left'
|
editcontroller=self, transition='in_left'
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _show_edit_ui(
|
def _show_edit_ui(
|
||||||
@ -205,7 +208,8 @@ class PlaylistEditController:
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlaylistEditWindow(
|
PlaylistEditWindow(
|
||||||
editcontroller=self, transition='in_left'
|
editcontroller=self, transition='in_left'
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Otherwise we were adding; go back to the add type choice list.
|
# Otherwise we were adding; go back to the add type choice list.
|
||||||
@ -214,7 +218,8 @@ class PlaylistEditController:
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlaylistAddGameWindow(
|
PlaylistAddGameWindow(
|
||||||
editcontroller=self, transition='in_left'
|
editcontroller=self, transition='in_left'
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=None,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Make sure type is in there.
|
# Make sure type is in there.
|
||||||
@ -236,5 +241,6 @@ class PlaylistEditController:
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PlaylistEditWindow(
|
PlaylistEditWindow(
|
||||||
editcontroller=self, transition='in_left'
|
editcontroller=self, transition='in_left'
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=None,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -103,8 +103,8 @@ class PlaylistEditGameWindow(bui.Window):
|
|||||||
self._choice_selections: dict[str, int] = {}
|
self._choice_selections: dict[str, int] = {}
|
||||||
|
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
width = 720 if uiscale is bui.UIScale.SMALL else 620
|
width = 820 if uiscale is bui.UIScale.SMALL else 620
|
||||||
x_inset = 50 if uiscale is bui.UIScale.SMALL else 0
|
x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
|
||||||
height = (
|
height = (
|
||||||
365
|
365
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -514,6 +514,10 @@ class PlaylistEditGameWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.playlist.mapselect import PlaylistMapSelectWindow
|
from bauiv1lib.playlist.mapselect import PlaylistMapSelectWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# Replace ourself with the map-select UI.
|
# Replace ourself with the map-select UI.
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
@ -524,7 +528,8 @@ class PlaylistEditGameWindow(bui.Window):
|
|||||||
copy.deepcopy(self._getconfig()),
|
copy.deepcopy(self._getconfig()),
|
||||||
self._edit_info,
|
self._edit_info,
|
||||||
self._completion_call,
|
self._completion_call,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _choice_inc(
|
def _choice_inc(
|
||||||
|
|||||||
@ -44,8 +44,8 @@ class PlaylistMapSelectWindow(bui.Window):
|
|||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
width = 715 if uiscale is bui.UIScale.SMALL else 615
|
width = 815 if uiscale is bui.UIScale.SMALL else 615
|
||||||
x_inset = 50 if uiscale is bui.UIScale.SMALL else 0
|
x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
|
||||||
height = (
|
height = (
|
||||||
400
|
400
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -273,6 +273,10 @@ class PlaylistMapSelectWindow(bui.Window):
|
|||||||
def _select(self, map_name: str) -> None:
|
def _select(self, map_name: str) -> None:
|
||||||
from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
||||||
|
|
||||||
|
# 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._config['settings']['map'] = map_name
|
self._config['settings']['map'] = map_name
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
@ -285,7 +289,8 @@ class PlaylistMapSelectWindow(bui.Window):
|
|||||||
default_selection='map',
|
default_selection='map',
|
||||||
transition='in_left',
|
transition='in_left',
|
||||||
edit_info=self._edit_info,
|
edit_info=self._edit_info,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _select_with_delay(self, map_name: str) -> None:
|
def _select_with_delay(self, map_name: str) -> None:
|
||||||
@ -296,6 +301,10 @@ class PlaylistMapSelectWindow(bui.Window):
|
|||||||
def _cancel(self) -> None:
|
def _cancel(self) -> None:
|
||||||
from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
||||||
|
|
||||||
|
# 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='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
@ -307,5 +316,6 @@ class PlaylistMapSelectWindow(bui.Window):
|
|||||||
default_selection='map',
|
default_selection='map',
|
||||||
transition='in_left',
|
transition='in_left',
|
||||||
edit_info=self._edit_info,
|
edit_info=self._edit_info,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -140,7 +140,6 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
if show_shuffle_check_box:
|
if show_shuffle_check_box:
|
||||||
self._height += 40
|
self._height += 40
|
||||||
|
|
||||||
# Creates our _root_widget.
|
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
scale = (
|
scale = (
|
||||||
1.69
|
1.69
|
||||||
@ -149,6 +148,7 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
if uiscale is bui.UIScale.MEDIUM
|
if uiscale is bui.UIScale.MEDIUM
|
||||||
else 0.85
|
else 0.85
|
||||||
)
|
)
|
||||||
|
# Creates our _root_widget.
|
||||||
super().__init__(
|
super().__init__(
|
||||||
position=scale_origin, size=(self._width, self._height), scale=scale
|
position=scale_origin, size=(self._width, self._height), scale=scale
|
||||||
)
|
)
|
||||||
@ -448,6 +448,10 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
self._transition_out()
|
self._transition_out()
|
||||||
|
|
||||||
def _on_ok_press(self) -> None:
|
def _on_ok_press(self) -> None:
|
||||||
|
# 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
|
||||||
|
|
||||||
# Disallow if our playlist has disappeared.
|
# Disallow if our playlist has disappeared.
|
||||||
if not self._does_target_playlist_exist():
|
if not self._does_target_playlist_exist():
|
||||||
return
|
return
|
||||||
@ -478,8 +482,12 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
cfg['Private Party Host Session Type'] = typename
|
cfg['Private Party Host Session Type'] = typename
|
||||||
bui.getsound('gunCocking').play()
|
bui.getsound('gunCocking').play()
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
|
# Note: this is a wonky situation where we aren't actually
|
||||||
|
# the main window but we set it on behalf of the main window
|
||||||
|
# that popped us up.
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
GatherWindow(transition='in_right').get_root_widget()
|
GatherWindow(transition='in_right').get_root_widget(),
|
||||||
|
from_window=False, # Disable this test.
|
||||||
)
|
)
|
||||||
self._transition_out(transition='out_left')
|
self._transition_out(transition='out_left')
|
||||||
if self._delegate is not None:
|
if self._delegate is not None:
|
||||||
|
|||||||
@ -33,8 +33,8 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
back_label = bui.Lstr(resource='doneText')
|
back_label = bui.Lstr(resource='doneText')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
self._width = 700.0 if uiscale is bui.UIScale.SMALL else 600.0
|
self._width = 800.0 if uiscale is bui.UIScale.SMALL else 600.0
|
||||||
x_inset = 50.0 if uiscale is bui.UIScale.SMALL else 0.0
|
x_inset = 100.0 if uiscale is bui.UIScale.SMALL else 0.0
|
||||||
self._height = (
|
self._height = (
|
||||||
360.0
|
360.0
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -197,8 +197,10 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, selected_child=self._scrollwidget
|
edit=self._root_widget, selected_child=self._scrollwidget
|
||||||
)
|
)
|
||||||
self._columnwidget = bui.columnwidget(
|
self._subcontainer = bui.containerwidget(
|
||||||
parent=self._scrollwidget, border=2, margin=0
|
parent=self._scrollwidget,
|
||||||
|
size=(self._scroll_width, 32),
|
||||||
|
background=False,
|
||||||
)
|
)
|
||||||
v -= 255
|
v -= 255
|
||||||
self._profiles: dict[str, dict[str, Any]] | None = None
|
self._profiles: dict[str, dict[str, Any]] | None = None
|
||||||
@ -212,6 +214,10 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
from bauiv1lib.profile.edit import EditProfileWindow
|
from bauiv1lib.profile.edit import EditProfileWindow
|
||||||
from bauiv1lib.purchase import PurchaseWindow
|
from bauiv1lib.purchase import PurchaseWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
@ -252,7 +258,8 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
EditProfileWindow(
|
EditProfileWindow(
|
||||||
existing_profile=None, in_main_menu=self._in_main_menu
|
existing_profile=None, in_main_menu=self._in_main_menu
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget if self._in_main_menu else False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _delete_profile(self) -> None:
|
def _delete_profile(self) -> None:
|
||||||
@ -301,6 +308,10 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.profile.edit import EditProfileWindow
|
from bauiv1lib.profile.edit import EditProfileWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
if self._selected_profile is None:
|
if self._selected_profile is None:
|
||||||
bui.getsound('error').play()
|
bui.getsound('error').play()
|
||||||
bui.screenmessage(
|
bui.screenmessage(
|
||||||
@ -313,7 +324,8 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
EditProfileWindow(
|
EditProfileWindow(
|
||||||
self._selected_profile, in_main_menu=self._in_main_menu
|
self._selected_profile, in_main_menu=self._in_main_menu
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget if self._in_main_menu else False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _select(self, name: str, index: int) -> None:
|
def _select(self, name: str, index: int) -> None:
|
||||||
@ -324,6 +336,10 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.account.settings import AccountSettingsWindow
|
from bauiv1lib.account.settings import AccountSettingsWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
|
|
||||||
self._save_state()
|
self._save_state()
|
||||||
@ -333,7 +349,8 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
if self._in_main_menu:
|
if self._in_main_menu:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AccountSettingsWindow(transition='in_left').get_root_widget()
|
AccountSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
# If we're being called up standalone, handle pause/resume ourself.
|
# If we're being called up standalone, handle pause/resume ourself.
|
||||||
@ -342,8 +359,10 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
|
|
||||||
def _refresh(self) -> None:
|
def _refresh(self) -> None:
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
from efro.util import asserttype
|
from efro.util import asserttype
|
||||||
from bascenev1 import PlayerProfilesChangedMessage
|
from bascenev1 import PlayerProfilesChangedMessage
|
||||||
|
from bascenev1lib.actor import spazappearance
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
|
|
||||||
@ -359,14 +378,27 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
assert self._profiles is not None
|
assert self._profiles is not None
|
||||||
items = list(self._profiles.items())
|
items = list(self._profiles.items())
|
||||||
items.sort(key=lambda x: asserttype(x[0], str).lower())
|
items.sort(key=lambda x: asserttype(x[0], str).lower())
|
||||||
|
spazzes = spazappearance.get_appearances()
|
||||||
|
spazzes.sort()
|
||||||
|
icon_textures = [
|
||||||
|
bui.gettexture(bui.app.classic.spaz_appearances[s].icon_texture)
|
||||||
|
for s in spazzes
|
||||||
|
]
|
||||||
|
icon_tint_textures = [
|
||||||
|
bui.gettexture(
|
||||||
|
bui.app.classic.spaz_appearances[s].icon_mask_texture
|
||||||
|
)
|
||||||
|
for s in spazzes
|
||||||
|
]
|
||||||
index = 0
|
index = 0
|
||||||
|
y_val = 35 * (len(self._profiles) - 1)
|
||||||
account_name: str | None
|
account_name: str | None
|
||||||
if plus.get_v1_account_state() == 'signed_in':
|
if plus.get_v1_account_state() == 'signed_in':
|
||||||
account_name = plus.get_v1_account_display_string()
|
account_name = plus.get_v1_account_display_string()
|
||||||
else:
|
else:
|
||||||
account_name = None
|
account_name = None
|
||||||
widget_to_select = None
|
widget_to_select = None
|
||||||
for p_name, _ in items:
|
for p_name, p_info in items:
|
||||||
if p_name == '__account__' and account_name is None:
|
if p_name == '__account__' and account_name is None:
|
||||||
continue
|
continue
|
||||||
color, _highlight = bui.app.classic.get_player_profile_colors(
|
color, _highlight = bui.app.classic.get_player_profile_colors(
|
||||||
@ -378,16 +410,35 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
if p_name == '__account__'
|
if p_name == '__account__'
|
||||||
else bui.app.classic.get_player_profile_icon(p_name) + p_name
|
else bui.app.classic.get_player_profile_icon(p_name) + p_name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
char_index = spazzes.index(p_info['character'])
|
||||||
|
except Exception:
|
||||||
|
char_index = spazzes.index('Spaz')
|
||||||
|
|
||||||
assert isinstance(tval, str)
|
assert isinstance(tval, str)
|
||||||
|
character = bui.buttonwidget(
|
||||||
|
parent=self._subcontainer,
|
||||||
|
position=(0, y_val),
|
||||||
|
size=(28, 28),
|
||||||
|
label='',
|
||||||
|
color=(1, 1, 1),
|
||||||
|
mask_texture=bui.gettexture('characterIconMask'),
|
||||||
|
tint_color=color,
|
||||||
|
tint2_color=_highlight,
|
||||||
|
texture=icon_textures[char_index],
|
||||||
|
tint_texture=icon_tint_textures[char_index],
|
||||||
|
selectable=False,
|
||||||
|
)
|
||||||
txtw = bui.textwidget(
|
txtw = bui.textwidget(
|
||||||
parent=self._columnwidget,
|
parent=self._subcontainer,
|
||||||
position=(0, 32),
|
position=(35, y_val),
|
||||||
size=((self._width - 40) / scl, 28),
|
size=((self._width - 210) / scl, 28),
|
||||||
text=bui.Lstr(value=tval),
|
text=bui.Lstr(value=tval),
|
||||||
h_align='left',
|
h_align='left',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
on_select_call=bui.WeakCall(self._select, p_name, index),
|
on_select_call=bui.WeakCall(self._select, p_name, index),
|
||||||
maxwidth=self._scroll_width * 0.92,
|
maxwidth=self._scroll_width * 0.86,
|
||||||
corner_scale=scl,
|
corner_scale=scl,
|
||||||
color=bui.safecolor(color, 0.4),
|
color=bui.safecolor(color, 0.4),
|
||||||
always_highlight=True,
|
always_highlight=True,
|
||||||
@ -396,8 +447,11 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
if index == 0:
|
if index == 0:
|
||||||
bui.widget(edit=txtw, up_widget=self._back_button)
|
bui.widget(edit=txtw, up_widget=self._back_button)
|
||||||
|
if self._selected_profile is None:
|
||||||
|
self._selected_profile = p_name
|
||||||
bui.widget(edit=txtw, show_buffer_top=40, show_buffer_bottom=40)
|
bui.widget(edit=txtw, show_buffer_top=40, show_buffer_bottom=40)
|
||||||
self._profile_widgets.append(txtw)
|
self._profile_widgets.append(txtw)
|
||||||
|
self._profile_widgets.append(character)
|
||||||
|
|
||||||
# Select/show this one if it was previously selected
|
# Select/show this one if it was previously selected
|
||||||
# (but defer till after this loop since our height is
|
# (but defer till after this loop since our height is
|
||||||
@ -406,10 +460,15 @@ class ProfileBrowserWindow(bui.Window):
|
|||||||
widget_to_select = txtw
|
widget_to_select = txtw
|
||||||
|
|
||||||
index += 1
|
index += 1
|
||||||
|
y_val -= 35
|
||||||
|
|
||||||
|
bui.containerwidget(
|
||||||
|
edit=self._subcontainer,
|
||||||
|
size=(self._scroll_width, index * 35),
|
||||||
|
)
|
||||||
if widget_to_select is not None:
|
if widget_to_select is not None:
|
||||||
bui.columnwidget(
|
bui.containerwidget(
|
||||||
edit=self._columnwidget,
|
edit=self._subcontainer,
|
||||||
selected_child=widget_to_select,
|
selected_child=widget_to_select,
|
||||||
visible_child=widget_to_select,
|
visible_child=widget_to_select,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -18,12 +18,18 @@ class EditProfileWindow(bui.Window):
|
|||||||
# FIXME: WILL NEED TO CHANGE THIS FOR UILOCATION.
|
# FIXME: WILL NEED TO CHANGE THIS FOR UILOCATION.
|
||||||
def reload_window(self) -> None:
|
def reload_window(self) -> None:
|
||||||
"""Transitions out and recreates ourself."""
|
"""Transitions out and recreates ourself."""
|
||||||
|
|
||||||
|
# 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='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
EditProfileWindow(
|
EditProfileWindow(
|
||||||
self.getname(), self._in_main_menu
|
self.getname(), self._in_main_menu
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -54,8 +60,8 @@ class EditProfileWindow(bui.Window):
|
|||||||
self._highlight,
|
self._highlight,
|
||||||
) = bui.app.classic.get_player_profile_colors(existing_profile)
|
) = bui.app.classic.get_player_profile_colors(existing_profile)
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
self._width = width = 780.0 if uiscale is bui.UIScale.SMALL else 680.0
|
self._width = width = 880.0 if uiscale is bui.UIScale.SMALL else 680.0
|
||||||
self._x_inset = x_inset = 50.0 if uiscale is bui.UIScale.SMALL else 0.0
|
self._x_inset = x_inset = 100.0 if uiscale is bui.UIScale.SMALL else 0.0
|
||||||
self._height = height = (
|
self._height = height = (
|
||||||
350.0
|
350.0
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -184,7 +190,7 @@ class EditProfileWindow(bui.Window):
|
|||||||
self._clipped_name_text = bui.textwidget(
|
self._clipped_name_text = bui.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
text='',
|
text='',
|
||||||
position=(540 + x_inset, v - 8),
|
position=(580 + x_inset, v - 8),
|
||||||
flatness=1.0,
|
flatness=1.0,
|
||||||
shadow=0.0,
|
shadow=0.0,
|
||||||
scale=0.55,
|
scale=0.55,
|
||||||
@ -390,6 +396,16 @@ class EditProfileWindow(bui.Window):
|
|||||||
autoselect=True,
|
autoselect=True,
|
||||||
on_activate_call=self.upgrade_profile,
|
on_activate_call=self.upgrade_profile,
|
||||||
)
|
)
|
||||||
|
self._random_name_button = bui.buttonwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
label=bui.Lstr(resource='randomText'),
|
||||||
|
size=(30, 20),
|
||||||
|
position=(495 + x_inset, v - 20),
|
||||||
|
button_type='square',
|
||||||
|
color=(0.6, 0.5, 0.65),
|
||||||
|
autoselect=True,
|
||||||
|
on_activate_call=self.assign_random_name,
|
||||||
|
)
|
||||||
|
|
||||||
self._update_clipped_name()
|
self._update_clipped_name()
|
||||||
self._clipped_name_timer = bui.AppTimer(
|
self._clipped_name_timer = bui.AppTimer(
|
||||||
@ -498,8 +514,17 @@ class EditProfileWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
self._update_character()
|
self._update_character()
|
||||||
|
|
||||||
|
def assign_random_name(self) -> None:
|
||||||
|
"""Assigning a random name to the player."""
|
||||||
|
names = bs.get_random_names()
|
||||||
|
name = names[random.randrange(len(names))]
|
||||||
|
bui.textwidget(
|
||||||
|
edit=self._text_field,
|
||||||
|
text=name,
|
||||||
|
)
|
||||||
|
|
||||||
def upgrade_profile(self) -> None:
|
def upgrade_profile(self) -> None:
|
||||||
"""Attempt to ugrade the profile to global."""
|
"""Attempt to upgrade the profile to global."""
|
||||||
from bauiv1lib import account
|
from bauiv1lib import account
|
||||||
from bauiv1lib.profile import upgrade as pupgrade
|
from bauiv1lib.profile import upgrade as pupgrade
|
||||||
|
|
||||||
@ -653,6 +678,10 @@ class EditProfileWindow(bui.Window):
|
|||||||
def _cancel(self) -> None:
|
def _cancel(self) -> None:
|
||||||
from bauiv1lib.profile.browser import ProfileBrowserWindow
|
from bauiv1lib.profile.browser import ProfileBrowserWindow
|
||||||
|
|
||||||
|
# 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='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
@ -660,7 +689,8 @@ class EditProfileWindow(bui.Window):
|
|||||||
'in_left',
|
'in_left',
|
||||||
selected_profile=self._existing_profile,
|
selected_profile=self._existing_profile,
|
||||||
in_main_menu=self._in_main_menu,
|
in_main_menu=self._in_main_menu,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _set_color(self, color: tuple[float, float, float]) -> None:
|
def _set_color(self, color: tuple[float, float, float]) -> None:
|
||||||
@ -759,6 +789,10 @@ class EditProfileWindow(bui.Window):
|
|||||||
"""Save has been selected."""
|
"""Save has been selected."""
|
||||||
from bauiv1lib.profile.browser import ProfileBrowserWindow
|
from bauiv1lib.profile.browser import ProfileBrowserWindow
|
||||||
|
|
||||||
|
# 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 False
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
@ -808,6 +842,7 @@ class EditProfileWindow(bui.Window):
|
|||||||
'in_left',
|
'in_left',
|
||||||
selected_profile=new_name,
|
selected_profile=new_name,
|
||||||
in_main_menu=self._in_main_menu,
|
in_main_menu=self._in_main_menu,
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|||||||
@ -26,7 +26,7 @@ class PromoCodeWindow(bui.Window):
|
|||||||
transition = 'in_right'
|
transition = 'in_right'
|
||||||
|
|
||||||
width = 450
|
width = 450
|
||||||
height = 230
|
height = 330
|
||||||
|
|
||||||
self._modal = modal
|
self._modal = modal
|
||||||
self._r = 'promoCodeWindow'
|
self._r = 'promoCodeWindow'
|
||||||
@ -62,17 +62,50 @@ class PromoCodeWindow(bui.Window):
|
|||||||
iconscale=1.2,
|
iconscale=1.2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
v = height - 74
|
||||||
|
bui.textwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
text=bui.Lstr(resource='codesExplainText'),
|
||||||
|
maxwidth=width * 0.9,
|
||||||
|
position=(width * 0.5, v),
|
||||||
|
color=(0.7, 0.7, 0.7, 1.0),
|
||||||
|
size=(0, 0),
|
||||||
|
scale=0.8,
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
)
|
||||||
|
v -= 60
|
||||||
|
|
||||||
|
bui.textwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
text=bui.Lstr(
|
||||||
|
resource='supportEmailText',
|
||||||
|
subs=[('${EMAIL}', 'support@froemling.net')],
|
||||||
|
),
|
||||||
|
maxwidth=width * 0.9,
|
||||||
|
position=(width * 0.5, v),
|
||||||
|
color=(0.7, 0.7, 0.7, 1.0),
|
||||||
|
size=(0, 0),
|
||||||
|
scale=0.65,
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
)
|
||||||
|
|
||||||
|
v -= 80
|
||||||
|
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
text=bui.Lstr(resource=self._r + '.codeText'),
|
text=bui.Lstr(resource=self._r + '.codeText'),
|
||||||
position=(22, height - 113),
|
position=(22, v),
|
||||||
color=(0.8, 0.8, 0.8, 1.0),
|
color=(0.8, 0.8, 0.8, 1.0),
|
||||||
size=(90, 30),
|
size=(90, 30),
|
||||||
h_align='right',
|
h_align='right',
|
||||||
)
|
)
|
||||||
|
v -= 8
|
||||||
|
|
||||||
self._text_field = bui.textwidget(
|
self._text_field = bui.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(125, height - 121),
|
position=(125, v),
|
||||||
size=(280, 46),
|
size=(280, 46),
|
||||||
text='',
|
text='',
|
||||||
h_align='left',
|
h_align='left',
|
||||||
@ -86,10 +119,11 @@ class PromoCodeWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
bui.widget(edit=btn, down_widget=self._text_field)
|
bui.widget(edit=btn, down_widget=self._text_field)
|
||||||
|
|
||||||
|
v -= 79
|
||||||
b_width = 200
|
b_width = 200
|
||||||
self._enter_button = btn2 = bui.buttonwidget(
|
self._enter_button = btn2 = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(width * 0.5 - b_width * 0.5, height - 200),
|
position=(width * 0.5 - b_width * 0.5, v),
|
||||||
size=(b_width, 60),
|
size=(b_width, 60),
|
||||||
scale=1.0,
|
scale=1.0,
|
||||||
label=bui.Lstr(
|
label=bui.Lstr(
|
||||||
@ -108,13 +142,18 @@ class PromoCodeWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.advanced import AdvancedSettingsWindow
|
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(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
if not self._modal:
|
if not self._modal:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AdvancedSettingsWindow(transition='in_left').get_root_widget()
|
AdvancedSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _activate_enter_button(self) -> None:
|
def _activate_enter_button(self) -> None:
|
||||||
@ -124,6 +163,10 @@ class PromoCodeWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.advanced import AdvancedSettingsWindow
|
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
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
@ -133,7 +176,8 @@ class PromoCodeWindow(bui.Window):
|
|||||||
if not self._modal:
|
if not self._modal:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AdvancedSettingsWindow(transition='in_left').get_root_widget()
|
AdvancedSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
plus.add_v1_account_transaction(
|
plus.add_v1_account_transaction(
|
||||||
{
|
{
|
||||||
|
|||||||
@ -47,8 +47,8 @@ class AdvancedSettingsWindow(bui.Window):
|
|||||||
scale_origin = None
|
scale_origin = None
|
||||||
|
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
self._width = 870.0 if uiscale is bui.UIScale.SMALL else 670.0
|
self._width = 970.0 if uiscale is bui.UIScale.SMALL else 670.0
|
||||||
x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
|
x_inset = 150 if uiscale is bui.UIScale.SMALL else 0
|
||||||
self._height = (
|
self._height = (
|
||||||
390.0
|
390.0
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -682,11 +682,16 @@ class AdvancedSettingsWindow(bui.Window):
|
|||||||
def _on_vr_test_press(self) -> None:
|
def _on_vr_test_press(self) -> None:
|
||||||
from bauiv1lib.settings.vrtesting import VRTestingWindow
|
from bauiv1lib.settings.vrtesting import VRTestingWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
VRTestingWindow(transition='in_right').get_root_widget()
|
VRTestingWindow(transition='in_right').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_net_test_press(self) -> None:
|
def _on_net_test_press(self) -> None:
|
||||||
@ -694,6 +699,10 @@ class AdvancedSettingsWindow(bui.Window):
|
|||||||
assert plus is not None
|
assert plus is not None
|
||||||
from bauiv1lib.settings.nettesting import NetTestingWindow
|
from bauiv1lib.settings.nettesting import NetTestingWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# Net-testing requires a signed in v1 account.
|
# Net-testing requires a signed in v1 account.
|
||||||
if plus.get_v1_account_state() != 'signed_in':
|
if plus.get_v1_account_state() != 'signed_in':
|
||||||
bui.screenmessage(
|
bui.screenmessage(
|
||||||
@ -706,7 +715,8 @@ class AdvancedSettingsWindow(bui.Window):
|
|||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
NetTestingWindow(transition='in_right').get_root_widget()
|
NetTestingWindow(transition='in_right').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_friend_promo_code_press(self) -> None:
|
def _on_friend_promo_code_press(self) -> None:
|
||||||
@ -724,17 +734,26 @@ class AdvancedSettingsWindow(bui.Window):
|
|||||||
def _on_plugins_button_press(self) -> None:
|
def _on_plugins_button_press(self) -> None:
|
||||||
from bauiv1lib.settings.plugins import PluginWindow
|
from bauiv1lib.settings.plugins import PluginWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PluginWindow(origin_widget=self._plugins_button).get_root_widget()
|
PluginWindow(origin_widget=self._plugins_button).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_promo_code_press(self) -> None:
|
def _on_promo_code_press(self) -> None:
|
||||||
from bauiv1lib.promocode import PromoCodeWindow
|
from bauiv1lib.promocode import PromoCodeWindow
|
||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
@ -742,23 +761,30 @@ class AdvancedSettingsWindow(bui.Window):
|
|||||||
if plus.get_v1_account_state() != 'signed_in':
|
if plus.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
return
|
return
|
||||||
|
|
||||||
self._save_state()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
PromoCodeWindow(
|
PromoCodeWindow(
|
||||||
origin_widget=self._promo_code_button
|
origin_widget=self._promo_code_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_benchmark_press(self) -> None:
|
def _on_benchmark_press(self) -> None:
|
||||||
from bauiv1lib.debug import DebugWindow
|
from bauiv1lib.debug import DebugWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
DebugWindow(transition='in_right').get_root_widget()
|
DebugWindow(transition='in_right').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
@ -807,6 +833,8 @@ class AdvancedSettingsWindow(bui.Window):
|
|||||||
sel_name = 'ModdingGuide'
|
sel_name = 'ModdingGuide'
|
||||||
elif sel == self._language_inform_checkbox:
|
elif sel == self._language_inform_checkbox:
|
||||||
sel_name = 'LangInform'
|
sel_name = 'LangInform'
|
||||||
|
elif sel == self._show_dev_console_button_check_box.widget:
|
||||||
|
sel_name = 'ShowDevConsole'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized selection \'{sel}\'')
|
raise ValueError(f'unrecognized selection \'{sel}\'')
|
||||||
elif sel == self._back_button:
|
elif sel == self._back_button:
|
||||||
@ -870,6 +898,8 @@ class AdvancedSettingsWindow(bui.Window):
|
|||||||
sel = self._modding_guide_button
|
sel = self._modding_guide_button
|
||||||
elif sel_name == 'LangInform':
|
elif sel_name == 'LangInform':
|
||||||
sel = self._language_inform_checkbox
|
sel = self._language_inform_checkbox
|
||||||
|
elif sel_name == 'ShowDevConsole':
|
||||||
|
sel = self._show_dev_console_button_check_box.widget
|
||||||
else:
|
else:
|
||||||
sel = None
|
sel = None
|
||||||
if sel is not None:
|
if sel is not None:
|
||||||
@ -904,11 +934,16 @@ class AdvancedSettingsWindow(bui.Window):
|
|||||||
def _do_back(self) -> None:
|
def _do_back(self) -> None:
|
||||||
from bauiv1lib.settings.allsettings import AllSettingsWindow
|
from bauiv1lib.settings.allsettings import AllSettingsWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AllSettingsWindow(transition='in_left').get_root_widget()
|
AllSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -40,8 +40,8 @@ class AllSettingsWindow(bui.Window):
|
|||||||
scale_origin = None
|
scale_origin = None
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
width = 900 if uiscale is bui.UIScale.SMALL else 580
|
width = 1000 if uiscale is bui.UIScale.SMALL else 580
|
||||||
x_inset = 75 if uiscale is bui.UIScale.SMALL else 0
|
x_inset = 125 if uiscale is bui.UIScale.SMALL else 0
|
||||||
height = 435
|
height = 435
|
||||||
self._r = 'settingsWindow'
|
self._r = 'settingsWindow'
|
||||||
top_extra = 20 if uiscale is bui.UIScale.SMALL else 0
|
top_extra = 20 if uiscale is bui.UIScale.SMALL else 0
|
||||||
@ -235,65 +235,90 @@ class AllSettingsWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.mainmenu import MainMenuWindow
|
from bauiv1lib.mainmenu import MainMenuWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
MainMenuWindow(transition='in_left').get_root_widget()
|
MainMenuWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _do_controllers(self) -> None:
|
def _do_controllers(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
ControlsSettingsWindow(
|
ControlsSettingsWindow(
|
||||||
origin_widget=self._controllers_button
|
origin_widget=self._controllers_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _do_graphics(self) -> None:
|
def _do_graphics(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.graphics import GraphicsSettingsWindow
|
from bauiv1lib.settings.graphics import GraphicsSettingsWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
GraphicsSettingsWindow(
|
GraphicsSettingsWindow(
|
||||||
origin_widget=self._graphics_button
|
origin_widget=self._graphics_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _do_audio(self) -> None:
|
def _do_audio(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.audio import AudioSettingsWindow
|
from bauiv1lib.settings.audio import AudioSettingsWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AudioSettingsWindow(
|
AudioSettingsWindow(
|
||||||
origin_widget=self._audio_button
|
origin_widget=self._audio_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _do_advanced(self) -> None:
|
def _do_advanced(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.advanced import AdvancedSettingsWindow
|
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
|
||||||
|
|
||||||
self._save_state()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AdvancedSettingsWindow(
|
AdvancedSettingsWindow(
|
||||||
origin_widget=self._advanced_button
|
origin_widget=self._advanced_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
|
|||||||
@ -121,7 +121,8 @@ class AudioSettingsWindow(bui.Window):
|
|||||||
displayname=bui.Lstr(resource=self._r + '.soundVolumeText'),
|
displayname=bui.Lstr(resource=self._r + '.soundVolumeText'),
|
||||||
minval=0.0,
|
minval=0.0,
|
||||||
maxval=1.0,
|
maxval=1.0,
|
||||||
increment=0.1,
|
increment=0.05,
|
||||||
|
as_percent=True,
|
||||||
)
|
)
|
||||||
if bui.app.ui_v1.use_toolbars:
|
if bui.app.ui_v1.use_toolbars:
|
||||||
bui.widget(
|
bui.widget(
|
||||||
@ -137,9 +138,10 @@ class AudioSettingsWindow(bui.Window):
|
|||||||
displayname=bui.Lstr(resource=self._r + '.musicVolumeText'),
|
displayname=bui.Lstr(resource=self._r + '.musicVolumeText'),
|
||||||
minval=0.0,
|
minval=0.0,
|
||||||
maxval=1.0,
|
maxval=1.0,
|
||||||
increment=0.1,
|
increment=0.05,
|
||||||
callback=music.music_volume_changed,
|
callback=music.music_volume_changed,
|
||||||
changesound=False,
|
changesound=False,
|
||||||
|
as_percent=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
v -= 0.5 * spacing
|
v -= 0.5 * spacing
|
||||||
@ -235,6 +237,10 @@ class AudioSettingsWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.soundtrack import browser as stb
|
from bauiv1lib.soundtrack import browser as stb
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# We require disk access for soundtracks;
|
# We require disk access for soundtracks;
|
||||||
# if we don't have it, request it.
|
# if we don't have it, request it.
|
||||||
if not bui.have_permission(bui.Permission.STORAGE):
|
if not bui.have_permission(bui.Permission.STORAGE):
|
||||||
@ -254,13 +260,18 @@ class AudioSettingsWindow(bui.Window):
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
stb.SoundtrackBrowserWindow(
|
stb.SoundtrackBrowserWindow(
|
||||||
origin_widget=self._soundtrack_button
|
origin_widget=self._soundtrack_button
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings import allsettings
|
from bauiv1lib.settings import allsettings
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
@ -269,7 +280,8 @@ class AudioSettingsWindow(bui.Window):
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
allsettings.AllSettingsWindow(
|
allsettings.AllSettingsWindow(
|
||||||
transition='in_left'
|
transition='in_left'
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
|
|||||||
@ -98,9 +98,11 @@ class ControlsSettingsWindow(bui.Window):
|
|||||||
# made-for-iOS/Mac systems
|
# made-for-iOS/Mac systems
|
||||||
# (we can run into problems where devices register as one of each
|
# (we can run into problems where devices register as one of each
|
||||||
# type otherwise)..
|
# type otherwise)..
|
||||||
|
# UPDATE: We always use the apple system these days (which should
|
||||||
|
# support older controllers). So no need for a switch.
|
||||||
show_mac_controller_subsystem = False
|
show_mac_controller_subsystem = False
|
||||||
if platform == 'mac' and bui.is_xcode_build():
|
# if platform == 'mac' and bui.is_xcode_build():
|
||||||
show_mac_controller_subsystem = True
|
# show_mac_controller_subsystem = True
|
||||||
|
|
||||||
if show_mac_controller_subsystem:
|
if show_mac_controller_subsystem:
|
||||||
height += spacing * 1.5
|
height += spacing * 1.5
|
||||||
@ -311,6 +313,7 @@ class ControlsSettingsWindow(bui.Window):
|
|||||||
maxwidth=width * 0.8,
|
maxwidth=width * 0.8,
|
||||||
)
|
)
|
||||||
v -= spacing
|
v -= spacing
|
||||||
|
|
||||||
if show_mac_controller_subsystem:
|
if show_mac_controller_subsystem:
|
||||||
PopupMenu(
|
PopupMenu(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
@ -364,59 +367,84 @@ class ControlsSettingsWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.keyboard import ConfigKeyboardWindow
|
from bauiv1lib.settings.keyboard import ConfigKeyboardWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
ConfigKeyboardWindow(
|
ConfigKeyboardWindow(
|
||||||
bs.getinputdevice('Keyboard', '#1')
|
bs.getinputdevice('Keyboard', '#1')
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _config_keyboard2(self) -> None:
|
def _config_keyboard2(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.keyboard import ConfigKeyboardWindow
|
from bauiv1lib.settings.keyboard import ConfigKeyboardWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
ConfigKeyboardWindow(
|
ConfigKeyboardWindow(
|
||||||
bs.getinputdevice('Keyboard', '#2')
|
bs.getinputdevice('Keyboard', '#2')
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _do_mobile_devices(self) -> None:
|
def _do_mobile_devices(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.remoteapp import RemoteAppSettingsWindow
|
from bauiv1lib.settings.remoteapp import RemoteAppSettingsWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
RemoteAppSettingsWindow().get_root_widget()
|
RemoteAppSettingsWindow().get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _do_gamepads(self) -> None:
|
def _do_gamepads(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.gamepadselect import GamepadSelectWindow
|
from bauiv1lib.settings.gamepadselect import GamepadSelectWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
GamepadSelectWindow().get_root_widget()
|
GamepadSelectWindow().get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _do_touchscreen(self) -> None:
|
def _do_touchscreen(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.touchscreen import TouchscreenSettingsWindow
|
from bauiv1lib.settings.touchscreen import TouchscreenSettingsWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
TouchscreenSettingsWindow().get_root_widget()
|
TouchscreenSettingsWindow().get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
@ -463,11 +491,16 @@ class ControlsSettingsWindow(bui.Window):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.settings.allsettings import AllSettingsWindow
|
from bauiv1lib.settings.allsettings import AllSettingsWindow
|
||||||
|
|
||||||
|
# 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()
|
self._save_state()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
AllSettingsWindow(transition='in_left').get_root_widget()
|
AllSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -545,20 +545,24 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
if 'analogStickLR' + self._ext in self._settings
|
if 'analogStickLR' + self._ext in self._settings
|
||||||
else 5
|
else 5
|
||||||
if self._is_secondary
|
if self._is_secondary
|
||||||
else 1
|
else None
|
||||||
)
|
)
|
||||||
sval2 = (
|
sval2 = (
|
||||||
self._settings['analogStickUD' + self._ext]
|
self._settings['analogStickUD' + self._ext]
|
||||||
if 'analogStickUD' + self._ext in self._settings
|
if 'analogStickUD' + self._ext in self._settings
|
||||||
else 6
|
else 6
|
||||||
if self._is_secondary
|
if self._is_secondary
|
||||||
else 2
|
else None
|
||||||
)
|
|
||||||
return (
|
|
||||||
self._input.get_axis_name(sval1)
|
|
||||||
+ ' / '
|
|
||||||
+ self._input.get_axis_name(sval2)
|
|
||||||
)
|
)
|
||||||
|
assert isinstance(sval1, (int, type(None)))
|
||||||
|
assert isinstance(sval2, (int, type(None)))
|
||||||
|
if sval1 is not None and sval2 is not None:
|
||||||
|
return (
|
||||||
|
self._input.get_axis_name(sval1)
|
||||||
|
+ ' / '
|
||||||
|
+ self._input.get_axis_name(sval2)
|
||||||
|
)
|
||||||
|
return bui.Lstr(resource=self._r + '.unsetText')
|
||||||
|
|
||||||
# If they're looking for triggers.
|
# If they're looking for triggers.
|
||||||
if control in ['triggerRun1' + self._ext, 'triggerRun2' + self._ext]:
|
if control in ['triggerRun1' + self._ext, 'triggerRun2' + self._ext]:
|
||||||
@ -573,7 +577,7 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
return str(1.0)
|
return str(1.0)
|
||||||
|
|
||||||
# For dpad buttons: show individual buttons if any are set.
|
# For dpad buttons: show individual buttons if any are set.
|
||||||
# Otherwise show whichever dpad is set (defaulting to 1).
|
# Otherwise show whichever dpad is set.
|
||||||
dpad_buttons = [
|
dpad_buttons = [
|
||||||
'buttonLeft' + self._ext,
|
'buttonLeft' + self._ext,
|
||||||
'buttonRight' + self._ext,
|
'buttonRight' + self._ext,
|
||||||
@ -588,24 +592,28 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
return bui.Lstr(resource=self._r + '.unsetText')
|
return bui.Lstr(resource=self._r + '.unsetText')
|
||||||
|
|
||||||
# No dpad buttons - show the dpad number for all 4.
|
# No dpad buttons - show the dpad number for all 4.
|
||||||
return bui.Lstr(
|
dpadnum = (
|
||||||
value='${A} ${B}',
|
self._settings['dpad' + self._ext]
|
||||||
subs=[
|
if 'dpad' + self._ext in self._settings
|
||||||
('${A}', bui.Lstr(resource=self._r + '.dpadText')),
|
else 2
|
||||||
(
|
if self._is_secondary
|
||||||
'${B}',
|
else None
|
||||||
str(
|
|
||||||
self._settings['dpad' + self._ext]
|
|
||||||
if 'dpad' + self._ext in self._settings
|
|
||||||
else 2
|
|
||||||
if self._is_secondary
|
|
||||||
else 1
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
assert isinstance(dpadnum, (int, type(None)))
|
||||||
|
if dpadnum is not None:
|
||||||
|
return bui.Lstr(
|
||||||
|
value='${A} ${B}',
|
||||||
|
subs=[
|
||||||
|
('${A}', bui.Lstr(resource=self._r + '.dpadText')),
|
||||||
|
(
|
||||||
|
'${B}',
|
||||||
|
str(dpadnum),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
return bui.Lstr(resource=self._r + '.unsetText')
|
||||||
|
|
||||||
# other buttons..
|
# Other buttons.
|
||||||
if control in self._settings:
|
if control in self._settings:
|
||||||
return self._input.get_button_name(self._settings[control])
|
return self._input.get_button_name(self._settings[control])
|
||||||
return bui.Lstr(resource=self._r + '.unsetText')
|
return bui.Lstr(resource=self._r + '.unsetText')
|
||||||
@ -616,9 +624,7 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
event: dict[str, Any],
|
event: dict[str, Any],
|
||||||
dialog: AwaitGamepadInputWindow,
|
dialog: AwaitGamepadInputWindow,
|
||||||
) -> None:
|
) -> None:
|
||||||
# pylint: disable=too-many-nested-blocks
|
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
# pylint: disable=too-many-statements
|
|
||||||
assert self._settings is not None
|
assert self._settings is not None
|
||||||
ext = self._ext
|
ext = self._ext
|
||||||
|
|
||||||
@ -648,10 +654,6 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
if btn in self._settings:
|
if btn in self._settings:
|
||||||
del self._settings[btn]
|
del self._settings[btn]
|
||||||
if event['hat'] == (2 if self._is_secondary else 1):
|
if event['hat'] == (2 if self._is_secondary else 1):
|
||||||
# Exclude value in default case.
|
|
||||||
if 'dpad' + ext in self._settings:
|
|
||||||
del self._settings['dpad' + ext]
|
|
||||||
else:
|
|
||||||
self._settings['dpad' + ext] = event['hat']
|
self._settings['dpad' + ext] = event['hat']
|
||||||
|
|
||||||
# Update the 4 dpad button txt widgets.
|
# Update the 4 dpad button txt widgets.
|
||||||
@ -680,10 +682,6 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
if abs(event['value']) > 0.5:
|
if abs(event['value']) > 0.5:
|
||||||
axis = event['axis']
|
axis = event['axis']
|
||||||
if axis == (5 if self._is_secondary else 1):
|
if axis == (5 if self._is_secondary else 1):
|
||||||
# Exclude value in default case.
|
|
||||||
if 'analogStickLR' + ext in self._settings:
|
|
||||||
del self._settings['analogStickLR' + ext]
|
|
||||||
else:
|
|
||||||
self._settings['analogStickLR' + ext] = axis
|
self._settings['analogStickLR' + ext] = axis
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
edit=self._textwidgets['analogStickLR' + ext],
|
edit=self._textwidgets['analogStickLR' + ext],
|
||||||
@ -713,10 +711,6 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
lr_axis = 5 if self._is_secondary else 1
|
lr_axis = 5 if self._is_secondary else 1
|
||||||
if axis != lr_axis:
|
if axis != lr_axis:
|
||||||
if axis == (6 if self._is_secondary else 2):
|
if axis == (6 if self._is_secondary else 2):
|
||||||
# Exclude value in default case.
|
|
||||||
if 'analogStickUD' + ext in self._settings:
|
|
||||||
del self._settings['analogStickUD' + ext]
|
|
||||||
else:
|
|
||||||
self._settings['analogStickUD' + ext] = axis
|
self._settings['analogStickUD' + ext] = axis
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
edit=self._textwidgets['analogStickLR' + ext],
|
edit=self._textwidgets['analogStickLR' + ext],
|
||||||
@ -795,25 +789,34 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
bui.apptimer(0, doit)
|
bui.pushcall(doit)
|
||||||
return btn
|
return btn
|
||||||
|
|
||||||
def _cancel(self) -> None:
|
def _cancel(self) -> None:
|
||||||
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
||||||
|
|
||||||
|
# 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(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
if self._is_main_menu:
|
if self._is_main_menu:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
ControlsSettingsWindow(transition='in_left').get_root_widget()
|
ControlsSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save(self) -> None:
|
def _save(self) -> None:
|
||||||
classic = bui.app.classic
|
classic = bui.app.classic
|
||||||
assert classic is not None
|
assert classic is not None
|
||||||
|
|
||||||
|
# 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(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
)
|
||||||
@ -858,7 +861,8 @@ class GamepadSettingsWindow(bui.Window):
|
|||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
ControlsSettingsWindow(transition='in_left').get_root_widget()
|
ControlsSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -452,7 +452,7 @@ class GamepadAdvancedSettingsWindow(bui.Window):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
bui.apptimer(0, doit)
|
bui.pushcall(doit)
|
||||||
return btn, btn2
|
return btn, btn2
|
||||||
|
|
||||||
def _inc(
|
def _inc(
|
||||||
|
|||||||
@ -29,16 +29,17 @@ def gamepad_configure_callback(event: dict[str, Any]) -> None:
|
|||||||
logging.exception('Error transitioning out main_menu_window.')
|
logging.exception('Error transitioning out main_menu_window.')
|
||||||
bui.getsound('activateBeep').play()
|
bui.getsound('activateBeep').play()
|
||||||
bui.getsound('swish').play()
|
bui.getsound('swish').play()
|
||||||
inputdevice = event['input_device']
|
device = event['input_device']
|
||||||
assert isinstance(inputdevice, bs.InputDevice)
|
assert isinstance(device, bs.InputDevice)
|
||||||
if inputdevice.allows_configuring:
|
if device.allows_configuring:
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
gamepad.GamepadSettingsWindow(inputdevice).get_root_widget()
|
gamepad.GamepadSettingsWindow(device).get_root_widget(),
|
||||||
|
from_window=None,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
width = 700
|
width = 700
|
||||||
height = 200
|
height = 200
|
||||||
button_width = 100
|
button_width = 80
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
dlg = bui.containerwidget(
|
dlg = bui.containerwidget(
|
||||||
scale=(
|
scale=(
|
||||||
@ -51,9 +52,14 @@ def gamepad_configure_callback(event: dict[str, Any]) -> None:
|
|||||||
size=(width, height),
|
size=(width, height),
|
||||||
transition='in_right',
|
transition='in_right',
|
||||||
)
|
)
|
||||||
bui.app.ui_v1.set_main_menu_window(dlg)
|
bui.app.ui_v1.set_main_menu_window(dlg, from_window=None)
|
||||||
device_name = inputdevice.name
|
|
||||||
if device_name == 'iDevice':
|
if device.allows_configuring_in_system_settings:
|
||||||
|
msg = bui.Lstr(
|
||||||
|
resource='configureDeviceInSystemSettingsText',
|
||||||
|
subs=[('${DEVICE}', device.name)],
|
||||||
|
)
|
||||||
|
elif device.is_controller_app:
|
||||||
msg = bui.Lstr(
|
msg = bui.Lstr(
|
||||||
resource='bsRemoteConfigureInAppText',
|
resource='bsRemoteConfigureInAppText',
|
||||||
subs=[('${REMOTE_APP_NAME}', bui.get_remote_app_name())],
|
subs=[('${REMOTE_APP_NAME}', bui.get_remote_app_name())],
|
||||||
@ -61,7 +67,7 @@ def gamepad_configure_callback(event: dict[str, Any]) -> None:
|
|||||||
else:
|
else:
|
||||||
msg = bui.Lstr(
|
msg = bui.Lstr(
|
||||||
resource='cantConfigureDeviceText',
|
resource='cantConfigureDeviceText',
|
||||||
subs=[('${DEVICE}', device_name)],
|
subs=[('${DEVICE}', device.name)],
|
||||||
)
|
)
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
parent=dlg,
|
parent=dlg,
|
||||||
@ -76,12 +82,17 @@ def gamepad_configure_callback(event: dict[str, Any]) -> None:
|
|||||||
def _ok() -> None:
|
def _ok() -> None:
|
||||||
from bauiv1lib.settings import controls
|
from bauiv1lib.settings import controls
|
||||||
|
|
||||||
|
# no-op if our underlying widget is dead or on its way out.
|
||||||
|
if not dlg or dlg.transitioning_out:
|
||||||
|
return
|
||||||
|
|
||||||
bui.containerwidget(edit=dlg, transition='out_right')
|
bui.containerwidget(edit=dlg, transition='out_right')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
controls.ControlsSettingsWindow(
|
controls.ControlsSettingsWindow(
|
||||||
transition='in_left'
|
transition='in_left'
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=dlg,
|
||||||
)
|
)
|
||||||
|
|
||||||
bui.buttonwidget(
|
bui.buttonwidget(
|
||||||
@ -186,11 +197,16 @@ class GamepadSelectWindow(bui.Window):
|
|||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
from bauiv1lib.settings import controls
|
from bauiv1lib.settings import controls
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
bs.release_gamepad_input()
|
bs.release_gamepad_input()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
controls.ControlsSettingsWindow(
|
controls.ControlsSettingsWindow(
|
||||||
transition='in_left'
|
transition='in_left'
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -52,7 +52,7 @@ class GraphicsSettingsWindow(bui.Window):
|
|||||||
self._show_fullscreen = False
|
self._show_fullscreen = False
|
||||||
fullscreen_spacing_top = spacing * 0.2
|
fullscreen_spacing_top = spacing * 0.2
|
||||||
fullscreen_spacing = spacing * 1.2
|
fullscreen_spacing = spacing * 1.2
|
||||||
if bui.can_toggle_fullscreen():
|
if bui.fullscreen_control_available():
|
||||||
self._show_fullscreen = True
|
self._show_fullscreen = True
|
||||||
height += fullscreen_spacing + fullscreen_spacing_top
|
height += fullscreen_spacing + fullscreen_spacing_top
|
||||||
|
|
||||||
@ -122,21 +122,29 @@ class GraphicsSettingsWindow(bui.Window):
|
|||||||
self._fullscreen_checkbox: bui.Widget | None = None
|
self._fullscreen_checkbox: bui.Widget | None = None
|
||||||
if self._show_fullscreen:
|
if self._show_fullscreen:
|
||||||
v -= fullscreen_spacing_top
|
v -= fullscreen_spacing_top
|
||||||
self._fullscreen_checkbox = ConfigCheckBox(
|
# Fullscreen control does not necessarily talk to the
|
||||||
|
# app config so we have to wrangle it manually instead of
|
||||||
|
# using a config-checkbox.
|
||||||
|
label = bui.Lstr(resource=f'{self._r}.fullScreenText')
|
||||||
|
|
||||||
|
# Show keyboard shortcut alongside the control if they
|
||||||
|
# provide one.
|
||||||
|
shortcut = bui.fullscreen_control_key_shortcut()
|
||||||
|
if shortcut is not None:
|
||||||
|
label = bui.Lstr(
|
||||||
|
value='$(NAME) [$(SHORTCUT)]',
|
||||||
|
subs=[('$(NAME)', label), ('$(SHORTCUT)', shortcut)],
|
||||||
|
)
|
||||||
|
self._fullscreen_checkbox = bui.checkboxwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(100, v),
|
position=(100, v),
|
||||||
maxwidth=200,
|
value=bui.fullscreen_control_get(),
|
||||||
|
on_value_change_call=bui.fullscreen_control_set,
|
||||||
|
maxwidth=250,
|
||||||
size=(300, 30),
|
size=(300, 30),
|
||||||
configkey='Fullscreen',
|
text=label,
|
||||||
displayname=bui.Lstr(
|
)
|
||||||
resource=self._r
|
|
||||||
+ (
|
|
||||||
'.fullScreenCmdText'
|
|
||||||
if app.classic.platform == 'mac'
|
|
||||||
else '.fullScreenCtrlText'
|
|
||||||
)
|
|
||||||
),
|
|
||||||
).widget
|
|
||||||
if not self._have_selected_child:
|
if not self._have_selected_child:
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget,
|
edit=self._root_widget,
|
||||||
@ -259,9 +267,7 @@ class GraphicsSettingsWindow(bui.Window):
|
|||||||
bui.Lstr(resource='nativeText'),
|
bui.Lstr(resource='nativeText'),
|
||||||
]
|
]
|
||||||
for res in [1440, 1080, 960, 720, 480]:
|
for res in [1440, 1080, 960, 720, 480]:
|
||||||
# Nav bar is 72px so lets allow for that in what
|
if native_res[1] >= res:
|
||||||
# choices we show.
|
|
||||||
if native_res[1] >= res - 72:
|
|
||||||
res_str = f'{res}p'
|
res_str = f'{res}p'
|
||||||
choices.append(res_str)
|
choices.append(res_str)
|
||||||
choices_display.append(bui.Lstr(value=res_str))
|
choices_display.append(bui.Lstr(value=res_str))
|
||||||
@ -430,6 +436,10 @@ class GraphicsSettingsWindow(bui.Window):
|
|||||||
def _back(self) -> None:
|
def _back(self) -> None:
|
||||||
from bauiv1lib.settings import allsettings
|
from bauiv1lib.settings import allsettings
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
# Applying max-fps takes a few moments. Apply if it hasn't been
|
# Applying max-fps takes a few moments. Apply if it hasn't been
|
||||||
# yet.
|
# yet.
|
||||||
self._apply_max_fps()
|
self._apply_max_fps()
|
||||||
@ -441,7 +451,8 @@ class GraphicsSettingsWindow(bui.Window):
|
|||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
allsettings.AllSettingsWindow(
|
allsettings.AllSettingsWindow(
|
||||||
transition='in_left'
|
transition='in_left'
|
||||||
).get_root_widget()
|
).get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _set_quality(self, quality: str) -> None:
|
def _set_quality(self, quality: str) -> None:
|
||||||
@ -528,8 +539,10 @@ class GraphicsSettingsWindow(bui.Window):
|
|||||||
and bui.apptime() - self._last_max_fps_set_time > 1.0
|
and bui.apptime() - self._last_max_fps_set_time > 1.0
|
||||||
):
|
):
|
||||||
self._apply_max_fps()
|
self._apply_max_fps()
|
||||||
|
|
||||||
if self._show_fullscreen:
|
if self._show_fullscreen:
|
||||||
|
# Keep the fullscreen checkbox up to date with the current value.
|
||||||
bui.checkboxwidget(
|
bui.checkboxwidget(
|
||||||
edit=self._fullscreen_checkbox,
|
edit=self._fullscreen_checkbox,
|
||||||
value=bui.app.config.resolve('Fullscreen'),
|
value=bui.fullscreen_control_get(),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -213,6 +213,12 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
scale=1.0,
|
scale=1.0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _pretty_button_name(self, button_name: str) -> bui.Lstr:
|
||||||
|
button_id = self._settings[button_name]
|
||||||
|
if button_id == -1:
|
||||||
|
return bs.Lstr(resource='configGamepadWindow.unsetText')
|
||||||
|
return self._input.get_button_name(button_id)
|
||||||
|
|
||||||
def _capture_button(
|
def _capture_button(
|
||||||
self,
|
self,
|
||||||
pos: tuple[float, float],
|
pos: tuple[float, float],
|
||||||
@ -250,7 +256,7 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
v_align='top',
|
v_align='top',
|
||||||
scale=uiscale,
|
scale=uiscale,
|
||||||
maxwidth=maxwidth,
|
maxwidth=maxwidth,
|
||||||
text=self._input.get_button_name(self._settings[button]),
|
text=self._pretty_button_name(button),
|
||||||
)
|
)
|
||||||
bui.buttonwidget(
|
bui.buttonwidget(
|
||||||
edit=btn,
|
edit=btn,
|
||||||
@ -265,15 +271,24 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
def _cancel(self) -> None:
|
def _cancel(self) -> None:
|
||||||
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
||||||
|
|
||||||
|
# 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='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
ControlsSettingsWindow(transition='in_left').get_root_widget()
|
ControlsSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _save(self) -> None:
|
def _save(self) -> None:
|
||||||
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||||
bui.getsound('gunCocking').play()
|
bui.getsound('gunCocking').play()
|
||||||
@ -308,7 +323,8 @@ class ConfigKeyboardWindow(bui.Window):
|
|||||||
)
|
)
|
||||||
bui.app.config.apply_and_commit()
|
bui.app.config.apply_and_commit()
|
||||||
bui.app.ui_v1.set_main_menu_window(
|
bui.app.ui_v1.set_main_menu_window(
|
||||||
ControlsSettingsWindow(transition='in_left').get_root_widget()
|
ControlsSettingsWindow(transition='in_left').get_root_widget(),
|
||||||
|
from_window=self._root_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user