mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-05 23:13:46 +08:00
Initial 1.6 builds with private party front-end in place
This commit is contained in:
parent
ebaf83c502
commit
2a66b5b93f
@ -420,7 +420,7 @@
|
|||||||
"assets/build/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/a9/71/9286d55c45c37877f3267850f90b",
|
"assets/build/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/a9/71/9286d55c45c37877f3267850f90b",
|
||||||
"assets/build/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/2f/09/36e691de67eb8f155449a7170861",
|
"assets/build/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/2f/09/36e691de67eb8f155449a7170861",
|
||||||
"assets/build/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/fd/a8/ad50785ce206e8dc3dcc7358b173",
|
"assets/build/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/fd/a8/ad50785ce206e8dc3dcc7358b173",
|
||||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/34/93/4989950b5dd035da056a0291dbb2",
|
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/c2/36/59ab3af6b45307c79ba8c296df5b",
|
||||||
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/0d/25/26de912f111de8189f40aeeddee6",
|
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/0d/25/26de912f111de8189f40aeeddee6",
|
||||||
"assets/build/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/44/ed/5b972fa848cffb73723533c2ccb7",
|
"assets/build/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/44/ed/5b972fa848cffb73723533c2ccb7",
|
||||||
"assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/6a/20/57d91c24e0aeb1fe6b7d6dbbcac9",
|
"assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/6a/20/57d91c24e0aeb1fe6b7d6dbbcac9",
|
||||||
@ -429,27 +429,27 @@
|
|||||||
"assets/build/ba_data/data/languages/czech.json": "https://files.ballistica.net/cache/ba1/ce/de/b0f462205cdf687a875abc6f39bd",
|
"assets/build/ba_data/data/languages/czech.json": "https://files.ballistica.net/cache/ba1/ce/de/b0f462205cdf687a875abc6f39bd",
|
||||||
"assets/build/ba_data/data/languages/danish.json": "https://files.ballistica.net/cache/ba1/3f/46/e4da3c1d2b0ebf916df55c608b28",
|
"assets/build/ba_data/data/languages/danish.json": "https://files.ballistica.net/cache/ba1/3f/46/e4da3c1d2b0ebf916df55c608b28",
|
||||||
"assets/build/ba_data/data/languages/dutch.json": "https://files.ballistica.net/cache/ba1/d1/07/37b7adc3dbec7328d26c5325f212",
|
"assets/build/ba_data/data/languages/dutch.json": "https://files.ballistica.net/cache/ba1/d1/07/37b7adc3dbec7328d26c5325f212",
|
||||||
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/3f/ee/72767c1e922d3f2cf668147ef143",
|
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/66/d1/8adfe1479fe6b4c30cd0d0e694d6",
|
||||||
"assets/build/ba_data/data/languages/esperanto.json": "https://files.ballistica.net/cache/ba1/6e/fd/685a4e1da031474d47a1d9eb2731",
|
"assets/build/ba_data/data/languages/esperanto.json": "https://files.ballistica.net/cache/ba1/6e/fd/685a4e1da031474d47a1d9eb2731",
|
||||||
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/18/b2/9c1f6e3ca6e18d6a6fdbdb14e224",
|
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/18/b2/9c1f6e3ca6e18d6a6fdbdb14e224",
|
||||||
"assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/19/ba/b12493cfaa28d27f9bfee0459e20",
|
"assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/19/ba/b12493cfaa28d27f9bfee0459e20",
|
||||||
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/82/9f/bdcff3ac022c125a7232a412568e",
|
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/43/f3/9e88a199337b7913cb5e7961b1c6",
|
||||||
"assets/build/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/51/31/64479524c0ee990b3e97ffdca068",
|
"assets/build/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/51/31/64479524c0ee990b3e97ffdca068",
|
||||||
"assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/ed/98/37d9457755f7e86e2f2875e3b055",
|
"assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/ed/98/37d9457755f7e86e2f2875e3b055",
|
||||||
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/87/2d/027aa239eb66ea8f496562f4fd83",
|
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/87/2d/027aa239eb66ea8f496562f4fd83",
|
||||||
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/a4/01/1fcc28b303858b3d028d26516907",
|
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/a4/01/1fcc28b303858b3d028d26516907",
|
||||||
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/20/ca/d675783cd094030a625e7ce023cf",
|
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/6b/5a/6e8e3692347d9ba01aff607af5a8",
|
||||||
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/0a/84/bbb6ed2abf66509406f534cbbb52",
|
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/0a/84/bbb6ed2abf66509406f534cbbb52",
|
||||||
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/f8/e6/773d3da1cbdb2215956f9d99c348",
|
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/f8/e6/773d3da1cbdb2215956f9d99c348",
|
||||||
"assets/build/ba_data/data/languages/polish.json": "https://files.ballistica.net/cache/ba1/29/72/bcf75316f71373a47739a72ad6da",
|
"assets/build/ba_data/data/languages/polish.json": "https://files.ballistica.net/cache/ba1/29/72/bcf75316f71373a47739a72ad6da",
|
||||||
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/3d/ba/7f4c8846babc5ef59187e87efa3d",
|
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/29/7d/be03fa23b8d80404b1b56c305edc",
|
||||||
"assets/build/ba_data/data/languages/romanian.json": "https://files.ballistica.net/cache/ba1/44/3c/7cc06ca8d5475e1687d0ed05bdbf",
|
"assets/build/ba_data/data/languages/romanian.json": "https://files.ballistica.net/cache/ba1/44/3c/7cc06ca8d5475e1687d0ed05bdbf",
|
||||||
"assets/build/ba_data/data/languages/russian.json": "https://files.ballistica.net/cache/ba1/07/42/382831beefb1f134eed95d18b20b",
|
"assets/build/ba_data/data/languages/russian.json": "https://files.ballistica.net/cache/ba1/07/42/382831beefb1f134eed95d18b20b",
|
||||||
"assets/build/ba_data/data/languages/serbian.json": "https://files.ballistica.net/cache/ba1/05/5b/910b8963f48cd494dc01d5a18a5c",
|
"assets/build/ba_data/data/languages/serbian.json": "https://files.ballistica.net/cache/ba1/05/5b/910b8963f48cd494dc01d5a18a5c",
|
||||||
"assets/build/ba_data/data/languages/slovak.json": "https://files.ballistica.net/cache/ba1/b7/0a/fab820b96e7aa587ee56427ecdc2",
|
"assets/build/ba_data/data/languages/slovak.json": "https://files.ballistica.net/cache/ba1/b7/0a/fab820b96e7aa587ee56427ecdc2",
|
||||||
"assets/build/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/58/3b/2bdbad7748ab0c76b9cf3d65c70e",
|
"assets/build/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/e0/83/32c5bc6544b647dbc599c11123df",
|
||||||
"assets/build/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/50/9f/be006ba19be6a69a57837eb6dca0",
|
"assets/build/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/50/9f/be006ba19be6a69a57837eb6dca0",
|
||||||
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/19/fe/c97df315575d999ad2bb63478b5f",
|
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/2d/a3/114ca23a3fb0f2885bfbbabb9727",
|
||||||
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/66/b0/e1d71e57673a6fc78e0ea181b76b",
|
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/66/b0/e1d71e57673a6fc78e0ea181b76b",
|
||||||
"assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/e4/3e/243eaa0237361b984fc6c56042be",
|
"assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/e4/3e/243eaa0237361b984fc6c56042be",
|
||||||
"assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/04/52/683a27aaf9aa7c63e7e595f80d08",
|
"assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/04/52/683a27aaf9aa7c63e7e595f80d08",
|
||||||
@ -3932,40 +3932,40 @@
|
|||||||
"assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450",
|
"assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450",
|
||||||
"assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e",
|
"assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e",
|
||||||
"assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f",
|
"assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f",
|
||||||
"build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/1c/5f/2e5338ab577aa7dac9942dda3d43",
|
"build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/3c/61/69d59f46d61b3aeee054aa5daab1",
|
||||||
"build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/50/bb/7a9daf22e3a09c6ab40f6b6909f2",
|
"build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d2/41/e8362cfe9f6fd6dc882858021874",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e5/6f/10a4fc55ee08a4f6e1d8f3b87422",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/83/ff/29cf07587f212d5278bb5ed92e75",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f3/fa/ba9a4fd942854e6d330079a5d5b2",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/90/e7/c4834a3b41d8f9d837071dc0800a",
|
||||||
"build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/68/5d/09e80048115eaaa434ffe85a7f8f",
|
"build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ce/3d/0febcd4db42fe5dedb701c60bddf",
|
||||||
"build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/60/0e/804d130b536483882ee3f4299375",
|
"build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/c5/d8/3d7ca6668af72200a6eea00c6d84",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/73/15/f45a3b15110a0cc0493ef17fae4c",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/79/f2/3381ea14e11854a9e8804953bb06",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/55/e7/618d3ecd8072a67d07b1c1098369",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/80/00/a02fdfe67796bc04a78dbd6ed353",
|
||||||
"build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/54/31/bce32b4e1aef2b4bd27dc9336619",
|
"build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/19/36/ebf5f0f1c7a2923f7e3c4ee292ad",
|
||||||
"build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/bf/5a/45640c9cdda02fdffd1c9b3beebe",
|
"build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/fb/4f/fbddddae2d5963a1ec6f97234db3",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ed/ab/1d70d046b60626e74ab6a6d8d733",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/0d/32/8755d570c2e74316497bdd290f0d",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/cb/fb/135c187787329c51b6770a5f5135",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/24/30/863f0c9948669219f66b117502bc",
|
||||||
"build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/1a/1d/fb869851bf6e54e215d1447d1b68",
|
"build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/3c/dc/317d57caa8b27d5b685193cf3de9",
|
||||||
"build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/64/99/58dfc239e6fdac005d583287507f",
|
"build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/cd/8a/3fc0cca1383b6af2a4f8a5ae2cfe",
|
||||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/00/a6/2727ba6b98c46e4ab1414be214a7",
|
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/20/16/c0cf342b1971dcbc757abd29bdc5",
|
||||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a9/47/954ea39895cad0354cd1b39e4436",
|
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1b/06/f81485b10ac37b58a012bc158952",
|
||||||
"build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/ac/62/9c8551a51d8f458e59e856cd4a3a",
|
"build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/85/44/92172591b72302dc4909b0e91108",
|
||||||
"build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/75/e9/9674fac783d2827e5daf33b91afc",
|
"build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d4/e6/8d5a9ffcf32588f8b770a88a80d5",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/f2/46/c17af441ceb12cd41895c8482475",
|
"build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/c7/9c/e55d58caf88ad6bb88f1a5ebfdbf",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/c8/16/000156a1d2728de92b7bcdaa1f22",
|
"build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/f2/6e/981553869590e8367854b5df2802",
|
||||||
"build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/65/e2/82162e0ab11caf2634692d2d7a4e",
|
"build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/34/21/016123d9ec8293ce92ba910dd00a",
|
||||||
"build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6f/4d/baa3f14360c0d379ccb5ae330295",
|
"build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6f/f8/cf46e7c33a0a237e2c6f19ef4f92",
|
||||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c9/4a/167038e8603b915bc6bdebc886a5",
|
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/10/67/5a3d6131d1b1fdf9f629301b68db",
|
||||||
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/fa/a3/3f9a8d8856f9db3340adc5488d9b",
|
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6b/bc/72d32c36d51acb255b2667c4d386",
|
||||||
"build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ef/d0/49b99ce32e5e2b01b056fbac5c67",
|
"build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7c/9b/af5e799cb4d296074598f11a063f",
|
||||||
"build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/83/25/980050d75bbea49a84652209050c",
|
"build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/35/7c/b5f26ca01907df6ea80ff3ae5861",
|
||||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/47/aa/e82233695a50974e7e22db4e7146",
|
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8c/76/9ea770a68773fd4a08fb78855fbb",
|
||||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2b/45/7f9fbae208890455fce2fbc172d3",
|
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1d/b3/329956f15f5cb76a63bd4fd3e0cc",
|
||||||
"build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/fc/75/8ea8b8eeb9a1c47c534bfb9e5d3f",
|
"build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/30/04/7b7c4f847fd992b23719f755981a",
|
||||||
"build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/69/a9/01af1b4a126cf517e9bbbfade412",
|
"build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/bc/20/e13686c62052e3e388431d4859aa",
|
||||||
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d5/f5/7c740da86b84653a3d7b23cb11d7",
|
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a3/a1/1bb8a1926628e34054aeca5a0178",
|
||||||
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/47/64/f4a9fb9a0c338dd0daa0dc0e52a6",
|
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/5a/33/c232d2c633bf70915e1a8eecdf95",
|
||||||
"build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/74/66/c94da5b860d0581b20c9679d183f",
|
"build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/84/8c/2930553d642210c81b6342bffb9f",
|
||||||
"build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0f/c1/90db918c2dce94bd94725b25b2b4",
|
"build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/68/22/cc580cef75b9e452de66095ba62b",
|
||||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0f/49/4269f4e88a55e6712841b7b56f5a",
|
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/93/2d/b6482a7ce6957156fe050f4cc9dc",
|
||||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f7/6c/fe17cf1a3f98cacbe946549631c5"
|
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d1/a2/1d592f5d21dd39d7b16da8f1c8c4"
|
||||||
}
|
}
|
||||||
23
.idea/dictionaries/ericf.xml
generated
23
.idea/dictionaries/ericf.xml
generated
@ -45,6 +45,7 @@
|
|||||||
<w>adbcfaca</w>
|
<w>adbcfaca</w>
|
||||||
<w>adbpath</w>
|
<w>adbpath</w>
|
||||||
<w>addcall</w>
|
<w>addcall</w>
|
||||||
|
<w>addchars</w>
|
||||||
<w>addgame</w>
|
<w>addgame</w>
|
||||||
<w>addlevel</w>
|
<w>addlevel</w>
|
||||||
<w>addr</w>
|
<w>addr</w>
|
||||||
@ -98,6 +99,7 @@
|
|||||||
<w>archs</w>
|
<w>archs</w>
|
||||||
<w>argh</w>
|
<w>argh</w>
|
||||||
<w>argparse</w>
|
<w>argparse</w>
|
||||||
|
<w>argsjoined</w>
|
||||||
<w>argtypes</w>
|
<w>argtypes</w>
|
||||||
<w>argval</w>
|
<w>argval</w>
|
||||||
<w>armeabi</w>
|
<w>armeabi</w>
|
||||||
@ -146,6 +148,7 @@
|
|||||||
<w>autoretain</w>
|
<w>autoretain</w>
|
||||||
<w>autoselect</w>
|
<w>autoselect</w>
|
||||||
<w>autotools</w>
|
<w>autotools</w>
|
||||||
|
<w>availmins</w>
|
||||||
<w>availplug</w>
|
<w>availplug</w>
|
||||||
<w>aval</w>
|
<w>aval</w>
|
||||||
<w>axismotion</w>
|
<w>axismotion</w>
|
||||||
@ -244,6 +247,7 @@
|
|||||||
<w>bsuffix</w>
|
<w>bsuffix</w>
|
||||||
<w>bsui</w>
|
<w>bsui</w>
|
||||||
<w>btnh</w>
|
<w>btnh</w>
|
||||||
|
<w>btnlabel</w>
|
||||||
<w>btnv</w>
|
<w>btnv</w>
|
||||||
<w>btnx</w>
|
<w>btnx</w>
|
||||||
<w>btype</w>
|
<w>btype</w>
|
||||||
@ -279,6 +283,7 @@
|
|||||||
<w>cameraflash</w>
|
<w>cameraflash</w>
|
||||||
<w>camerashake</w>
|
<w>camerashake</w>
|
||||||
<w>campaignname</w>
|
<w>campaignname</w>
|
||||||
|
<w>cancelbtn</w>
|
||||||
<w>capb</w>
|
<w>capb</w>
|
||||||
<w>capturetheflag</w>
|
<w>capturetheflag</w>
|
||||||
<w>carentity</w>
|
<w>carentity</w>
|
||||||
@ -286,6 +291,7 @@
|
|||||||
<w>cbits</w>
|
<w>cbits</w>
|
||||||
<w>cbot</w>
|
<w>cbot</w>
|
||||||
<w>cbtn</w>
|
<w>cbtn</w>
|
||||||
|
<w>cbtnoffs</w>
|
||||||
<w>ccfgs</w>
|
<w>ccfgs</w>
|
||||||
<w>ccode</w>
|
<w>ccode</w>
|
||||||
<w>ccompiler</w>
|
<w>ccompiler</w>
|
||||||
@ -433,6 +439,7 @@
|
|||||||
<w>crashlytics</w>
|
<w>crashlytics</w>
|
||||||
<w>creationflags</w>
|
<w>creationflags</w>
|
||||||
<w>creditslist</w>
|
<w>creditslist</w>
|
||||||
|
<w>cresult</w>
|
||||||
<w>cryptmodule</w>
|
<w>cryptmodule</w>
|
||||||
<w>cspbd</w>
|
<w>cspbd</w>
|
||||||
<w>cspnf</w>
|
<w>cspnf</w>
|
||||||
@ -782,6 +789,7 @@
|
|||||||
<w>freeforallendscreen</w>
|
<w>freeforallendscreen</w>
|
||||||
<w>freeforallsession</w>
|
<w>freeforallsession</w>
|
||||||
<w>freeforallvictory</w>
|
<w>freeforallvictory</w>
|
||||||
|
<w>freemins</w>
|
||||||
<w>freepik</w>
|
<w>freepik</w>
|
||||||
<w>freesound</w>
|
<w>freesound</w>
|
||||||
<w>froemling</w>
|
<w>froemling</w>
|
||||||
@ -966,6 +974,7 @@
|
|||||||
<w>homebrew</w>
|
<w>homebrew</w>
|
||||||
<w>hometest</w>
|
<w>hometest</w>
|
||||||
<w>hostconfig</w>
|
<w>hostconfig</w>
|
||||||
|
<w>hostingstate</w>
|
||||||
<w>hostuser</w>
|
<w>hostuser</w>
|
||||||
<w>hout</w>
|
<w>hout</w>
|
||||||
<w>howtoplay</w>
|
<w>howtoplay</w>
|
||||||
@ -1201,6 +1210,7 @@
|
|||||||
<w>locationlist</w>
|
<w>locationlist</w>
|
||||||
<w>locationsingles</w>
|
<w>locationsingles</w>
|
||||||
<w>locationval</w>
|
<w>locationval</w>
|
||||||
|
<w>lockpath</w>
|
||||||
<w>lockstr</w>
|
<w>lockstr</w>
|
||||||
<w>locktype</w>
|
<w>locktype</w>
|
||||||
<w>locs</w>
|
<w>locs</w>
|
||||||
@ -1417,6 +1427,7 @@
|
|||||||
<w>nosynctool</w>
|
<w>nosynctool</w>
|
||||||
<w>nosynctools</w>
|
<w>nosynctools</w>
|
||||||
<w>notdir</w>
|
<w>notdir</w>
|
||||||
|
<w>nowtickets</w>
|
||||||
<w>npos</w>
|
<w>npos</w>
|
||||||
<w>nprocessors</w>
|
<w>nprocessors</w>
|
||||||
<w>ntpath</w>
|
<w>ntpath</w>
|
||||||
@ -1439,6 +1450,8 @@
|
|||||||
<w>oculus</w>
|
<w>oculus</w>
|
||||||
<w>oenval</w>
|
<w>oenval</w>
|
||||||
<w>offsanchor</w>
|
<w>offsanchor</w>
|
||||||
|
<w>offsx</w>
|
||||||
|
<w>offsy</w>
|
||||||
<w>ofval</w>
|
<w>ofval</w>
|
||||||
<w>oggenc</w>
|
<w>oggenc</w>
|
||||||
<w>oghash</w>
|
<w>oghash</w>
|
||||||
@ -1591,6 +1604,7 @@
|
|||||||
<w>powervr</w>
|
<w>powervr</w>
|
||||||
<w>ppos</w>
|
<w>ppos</w>
|
||||||
<w>pproxy</w>
|
<w>pproxy</w>
|
||||||
|
<w>pptabcom</w>
|
||||||
<w>pragmas</w>
|
<w>pragmas</w>
|
||||||
<w>prch</w>
|
<w>prch</w>
|
||||||
<w>prec</w>
|
<w>prec</w>
|
||||||
@ -1619,6 +1633,7 @@
|
|||||||
<w>printobjects</w>
|
<w>printobjects</w>
|
||||||
<w>printpaths</w>
|
<w>printpaths</w>
|
||||||
<w>priv</w>
|
<w>priv</w>
|
||||||
|
<w>privatetab</w>
|
||||||
<w>proactor</w>
|
<w>proactor</w>
|
||||||
<w>proc</w>
|
<w>proc</w>
|
||||||
<w>procs</w>
|
<w>procs</w>
|
||||||
@ -1628,6 +1643,7 @@
|
|||||||
<w>profilenames</w>
|
<w>profilenames</w>
|
||||||
<w>proj</w>
|
<w>proj</w>
|
||||||
<w>projconfig</w>
|
<w>projconfig</w>
|
||||||
|
<w>projdir</w>
|
||||||
<w>projectpath</w>
|
<w>projectpath</w>
|
||||||
<w>projectroot</w>
|
<w>projectroot</w>
|
||||||
<w>projroot</w>
|
<w>projroot</w>
|
||||||
@ -1751,6 +1767,7 @@
|
|||||||
<w>reqtype</w>
|
<w>reqtype</w>
|
||||||
<w>reqtypes</w>
|
<w>reqtypes</w>
|
||||||
<w>resample</w>
|
<w>resample</w>
|
||||||
|
<w>resetbtn</w>
|
||||||
<w>resetinput</w>
|
<w>resetinput</w>
|
||||||
<w>resourcetypeinfo</w>
|
<w>resourcetypeinfo</w>
|
||||||
<w>respawn</w>
|
<w>respawn</w>
|
||||||
@ -1802,6 +1819,7 @@
|
|||||||
<w>samsung</w>
|
<w>samsung</w>
|
||||||
<w>sandboxing</w>
|
<w>sandboxing</w>
|
||||||
<w>sandyrb</w>
|
<w>sandyrb</w>
|
||||||
|
<w>savebtn</w>
|
||||||
<w>savebutton</w>
|
<w>savebutton</w>
|
||||||
<w>saxutils</w>
|
<w>saxutils</w>
|
||||||
<w>sbblk</w>
|
<w>sbblk</w>
|
||||||
@ -1844,7 +1862,11 @@
|
|||||||
<w>sdkcheck</w>
|
<w>sdkcheck</w>
|
||||||
<w>sdkutils</w>
|
<w>sdkutils</w>
|
||||||
<w>sdtk</w>
|
<w>sdtk</w>
|
||||||
|
<w>selchild</w>
|
||||||
<w>selectmodule</w>
|
<w>selectmodule</w>
|
||||||
|
<w>selindex</w>
|
||||||
|
<w>selwidget</w>
|
||||||
|
<w>selwidgets</w>
|
||||||
<w>senze</w>
|
<w>senze</w>
|
||||||
<w>seqtype</w>
|
<w>seqtype</w>
|
||||||
<w>seqtypestr</w>
|
<w>seqtypestr</w>
|
||||||
@ -2145,6 +2167,7 @@
|
|||||||
<w>this'll</w>
|
<w>this'll</w>
|
||||||
<w>threadtype</w>
|
<w>threadtype</w>
|
||||||
<w>throwiness</w>
|
<w>throwiness</w>
|
||||||
|
<w>ticon</w>
|
||||||
<w>timedisplay</w>
|
<w>timedisplay</w>
|
||||||
<w>timeformat</w>
|
<w>timeformat</w>
|
||||||
<w>timemax</w>
|
<w>timemax</w>
|
||||||
|
|||||||
@ -1,7 +1,14 @@
|
|||||||
### 1.5.30 (20263)
|
### 1.6.0 (20268)
|
||||||
|
- Added private parties functionality (cloud hosted parties with associated codes making it easier to play with friends)
|
||||||
- The meta subsystem now enables new plugins by default in headless builds.
|
- The meta subsystem now enables new plugins by default in headless builds.
|
||||||
- Added option to save party in Manual tab
|
- Added option to save party in Manual tab
|
||||||
- Slight tidying on the tourney entry popup
|
- Slight tidying on the tourney entry popup
|
||||||
|
- Env var to override UI scale is now BA_UI_SCALE instead of BA_FORCE_UI_SCALE.
|
||||||
|
- Fixed an issue where ba.storagename() could prevent objects on the stack from getting released cleanly
|
||||||
|
- Improvements to documentation generation such as link to some external base types.
|
||||||
|
- Added ba.clipboard_* functions for copying and pasting text on supported platforms.
|
||||||
|
- Implemented clipboard functionality on SDL based builds (such as prefab)
|
||||||
|
- Fixed an issue where click locations on scaled text fields could be incorrectly calculated.
|
||||||
|
|
||||||
### 1.5.29 (20246)
|
### 1.5.29 (20246)
|
||||||
- Exposed ba method/class initing in public C++ layer.
|
- Exposed ba method/class initing in public C++ layer.
|
||||||
|
|||||||
@ -364,16 +364,14 @@
|
|||||||
"ba_data/python/bastd/ui/gather/__init__.py",
|
"ba_data/python/bastd/ui/gather/__init__.py",
|
||||||
"ba_data/python/bastd/ui/gather/__pycache__/__init__.cpython-38.opt-1.pyc",
|
"ba_data/python/bastd/ui/gather/__pycache__/__init__.cpython-38.opt-1.pyc",
|
||||||
"ba_data/python/bastd/ui/gather/__pycache__/abouttab.cpython-38.opt-1.pyc",
|
"ba_data/python/bastd/ui/gather/__pycache__/abouttab.cpython-38.opt-1.pyc",
|
||||||
"ba_data/python/bastd/ui/gather/__pycache__/bases.cpython-38.opt-1.pyc",
|
|
||||||
"ba_data/python/bastd/ui/gather/__pycache__/googleplaytab.cpython-38.opt-1.pyc",
|
|
||||||
"ba_data/python/bastd/ui/gather/__pycache__/manualtab.cpython-38.opt-1.pyc",
|
"ba_data/python/bastd/ui/gather/__pycache__/manualtab.cpython-38.opt-1.pyc",
|
||||||
"ba_data/python/bastd/ui/gather/__pycache__/nearbytab.cpython-38.opt-1.pyc",
|
"ba_data/python/bastd/ui/gather/__pycache__/nearbytab.cpython-38.opt-1.pyc",
|
||||||
|
"ba_data/python/bastd/ui/gather/__pycache__/privatetab.cpython-38.opt-1.pyc",
|
||||||
"ba_data/python/bastd/ui/gather/__pycache__/publictab.cpython-38.opt-1.pyc",
|
"ba_data/python/bastd/ui/gather/__pycache__/publictab.cpython-38.opt-1.pyc",
|
||||||
"ba_data/python/bastd/ui/gather/abouttab.py",
|
"ba_data/python/bastd/ui/gather/abouttab.py",
|
||||||
"ba_data/python/bastd/ui/gather/bases.py",
|
|
||||||
"ba_data/python/bastd/ui/gather/googleplaytab.py",
|
|
||||||
"ba_data/python/bastd/ui/gather/manualtab.py",
|
"ba_data/python/bastd/ui/gather/manualtab.py",
|
||||||
"ba_data/python/bastd/ui/gather/nearbytab.py",
|
"ba_data/python/bastd/ui/gather/nearbytab.py",
|
||||||
|
"ba_data/python/bastd/ui/gather/privatetab.py",
|
||||||
"ba_data/python/bastd/ui/gather/publictab.py",
|
"ba_data/python/bastd/ui/gather/publictab.py",
|
||||||
"ba_data/python/bastd/ui/getcurrency.py",
|
"ba_data/python/bastd/ui/getcurrency.py",
|
||||||
"ba_data/python/bastd/ui/getremote.py",
|
"ba_data/python/bastd/ui/getremote.py",
|
||||||
|
|||||||
@ -296,10 +296,9 @@ SCRIPT_TARGETS_PY_PUBLIC = \
|
|||||||
build/ba_data/python/bastd/ui/fileselector.py \
|
build/ba_data/python/bastd/ui/fileselector.py \
|
||||||
build/ba_data/python/bastd/ui/gather/__init__.py \
|
build/ba_data/python/bastd/ui/gather/__init__.py \
|
||||||
build/ba_data/python/bastd/ui/gather/abouttab.py \
|
build/ba_data/python/bastd/ui/gather/abouttab.py \
|
||||||
build/ba_data/python/bastd/ui/gather/bases.py \
|
|
||||||
build/ba_data/python/bastd/ui/gather/googleplaytab.py \
|
|
||||||
build/ba_data/python/bastd/ui/gather/manualtab.py \
|
build/ba_data/python/bastd/ui/gather/manualtab.py \
|
||||||
build/ba_data/python/bastd/ui/gather/nearbytab.py \
|
build/ba_data/python/bastd/ui/gather/nearbytab.py \
|
||||||
|
build/ba_data/python/bastd/ui/gather/privatetab.py \
|
||||||
build/ba_data/python/bastd/ui/gather/publictab.py \
|
build/ba_data/python/bastd/ui/gather/publictab.py \
|
||||||
build/ba_data/python/bastd/ui/getcurrency.py \
|
build/ba_data/python/bastd/ui/getcurrency.py \
|
||||||
build/ba_data/python/bastd/ui/getremote.py \
|
build/ba_data/python/bastd/ui/getremote.py \
|
||||||
@ -541,10 +540,9 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
|
|||||||
build/ba_data/python/bastd/ui/__pycache__/fileselector.cpython-38.opt-1.pyc \
|
build/ba_data/python/bastd/ui/__pycache__/fileselector.cpython-38.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/gather/__pycache__/__init__.cpython-38.opt-1.pyc \
|
build/ba_data/python/bastd/ui/gather/__pycache__/__init__.cpython-38.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/gather/__pycache__/abouttab.cpython-38.opt-1.pyc \
|
build/ba_data/python/bastd/ui/gather/__pycache__/abouttab.cpython-38.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/gather/__pycache__/bases.cpython-38.opt-1.pyc \
|
|
||||||
build/ba_data/python/bastd/ui/gather/__pycache__/googleplaytab.cpython-38.opt-1.pyc \
|
|
||||||
build/ba_data/python/bastd/ui/gather/__pycache__/manualtab.cpython-38.opt-1.pyc \
|
build/ba_data/python/bastd/ui/gather/__pycache__/manualtab.cpython-38.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/gather/__pycache__/nearbytab.cpython-38.opt-1.pyc \
|
build/ba_data/python/bastd/ui/gather/__pycache__/nearbytab.cpython-38.opt-1.pyc \
|
||||||
|
build/ba_data/python/bastd/ui/gather/__pycache__/privatetab.cpython-38.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/gather/__pycache__/publictab.cpython-38.opt-1.pyc \
|
build/ba_data/python/bastd/ui/gather/__pycache__/publictab.cpython-38.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/__pycache__/getcurrency.cpython-38.opt-1.pyc \
|
build/ba_data/python/bastd/ui/__pycache__/getcurrency.cpython-38.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/ui/__pycache__/getremote.cpython-38.opt-1.pyc \
|
build/ba_data/python/bastd/ui/__pycache__/getremote.cpython-38.opt-1.pyc \
|
||||||
|
|||||||
@ -996,7 +996,7 @@ class Timer:
|
|||||||
|
|
||||||
time: length of time (in seconds by default) that the timer will wait
|
time: length of time (in seconds by default) that the timer will wait
|
||||||
before firing. Note that the actual delay experienced may vary
|
before firing. Note that the actual delay experienced may vary
|
||||||
depending on the timetype. (see below)
|
depending on the timetype. (see below)
|
||||||
|
|
||||||
call: A callable Python object. Note that the timer will retain a
|
call: A callable Python object. Note that the timer will retain a
|
||||||
strong reference to the callable for as long as it exists, so you
|
strong reference to the callable for as long as it exists, so you
|
||||||
@ -1006,28 +1006,11 @@ class Timer:
|
|||||||
repeat: if True, the timer will fire repeatedly, with each successive
|
repeat: if True, the timer will fire repeatedly, with each successive
|
||||||
firing having the same delay as the first.
|
firing having the same delay as the first.
|
||||||
|
|
||||||
timetype can be either 'sim', 'base', or 'real'. It defaults to
|
timetype: A ba.TimeType value determining which timeline the timer is
|
||||||
'sim'. Types are explained below:
|
placed onto.
|
||||||
|
|
||||||
'sim' time maps to local simulation time in ba.Activity or ba.Session
|
timeformat: A ba.TimeFormat value determining how the passed time is
|
||||||
Contexts. This means that it may progress slower in slow-motion play
|
interpreted.
|
||||||
modes, stop when the game is paused, etc. This time type is not
|
|
||||||
available in UI contexts.
|
|
||||||
|
|
||||||
'base' time is also linked to gameplay in ba.Activity or ba.Session
|
|
||||||
Contexts, but it progresses at a constant rate regardless of
|
|
||||||
slow-motion states or pausing. It can, however, slow down or stop
|
|
||||||
in certain cases such as network outages or game slowdowns due to
|
|
||||||
cpu load. Like 'sim' time, this is unavailable in UI contexts.
|
|
||||||
|
|
||||||
'real' time always maps to actual clock time with a bit of filtering
|
|
||||||
added, regardless of Context. (the filtering prevents it from going
|
|
||||||
backwards or jumping forward by large amounts due to the app being
|
|
||||||
backgrounded, system time changing, etc.)
|
|
||||||
Real time timers are currently only available in the UI context.
|
|
||||||
|
|
||||||
the 'timeformat' arg defaults to SECONDS but can also be MILLISECONDS
|
|
||||||
if you want to pass time as milliseconds.
|
|
||||||
|
|
||||||
# Example: use a Timer object to print repeatedly for a few seconds:
|
# Example: use a Timer object to print repeatedly for a few seconds:
|
||||||
def say_it():
|
def say_it():
|
||||||
@ -1035,9 +1018,9 @@ class Timer:
|
|||||||
def stop_saying_it():
|
def stop_saying_it():
|
||||||
self.t = None
|
self.t = None
|
||||||
ba.screenmessage('MUSHROOM MUSHROOM!')
|
ba.screenmessage('MUSHROOM MUSHROOM!')
|
||||||
# create our timer; it will run as long as we hold self.t
|
# Create our timer; it will run as long as we have the self.t ref.
|
||||||
self.t = ba.Timer(0.3, say_it, repeat=True)
|
self.t = ba.Timer(0.3, say_it, repeat=True)
|
||||||
# now fire off a one-shot timer to kill it
|
# Now fire off a one-shot timer to kill it.
|
||||||
ba.timer(3.89, stop_saying_it)
|
ba.timer(3.89, stop_saying_it)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -1579,6 +1562,58 @@ def client_info_query_response(token: str, response: Any) -> None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def clipboard_get_text() -> str:
|
||||||
|
"""clipboard_get_text() -> str
|
||||||
|
|
||||||
|
Return text currently on the system clipboard.
|
||||||
|
|
||||||
|
Category: General Utility Functions
|
||||||
|
|
||||||
|
Ensure that ba.clipboard_has_text() returns True before calling
|
||||||
|
this function.
|
||||||
|
"""
|
||||||
|
return str()
|
||||||
|
|
||||||
|
|
||||||
|
def clipboard_has_text() -> bool:
|
||||||
|
"""clipboard_has_text() -> bool
|
||||||
|
|
||||||
|
Return whether there is currently text on the clipboard.
|
||||||
|
|
||||||
|
Category: General Utility Functions
|
||||||
|
|
||||||
|
This will return False if no system clipboard is available; no need
|
||||||
|
to call ba.clipboard_available() separately.
|
||||||
|
"""
|
||||||
|
return bool()
|
||||||
|
|
||||||
|
|
||||||
|
def clipboard_is_supported() -> bool:
|
||||||
|
"""clipboard_is_supported() -> bool
|
||||||
|
|
||||||
|
Return whether this platform supports clipboard operations at all.
|
||||||
|
|
||||||
|
Category: General Utility Functions
|
||||||
|
|
||||||
|
If this returns False, UIs should not show 'copy to clipboard'
|
||||||
|
buttons, etc.
|
||||||
|
"""
|
||||||
|
return bool()
|
||||||
|
|
||||||
|
|
||||||
|
def clipboard_set_text(value: str) -> None:
|
||||||
|
"""clipboard_set_text(value: str) -> None
|
||||||
|
|
||||||
|
Copy a string to the system clipboard.
|
||||||
|
|
||||||
|
Category: General Utility Functions
|
||||||
|
|
||||||
|
Ensure that ba.clipboard_available() returns True before adding
|
||||||
|
buttons/etc. that make use of this functionality.
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def columnwidget(edit: ba.Widget = None,
|
def columnwidget(edit: ba.Widget = None,
|
||||||
parent: ba.Widget = None,
|
parent: ba.Widget = None,
|
||||||
size: Sequence[float] = None,
|
size: Sequence[float] = None,
|
||||||
@ -3293,24 +3328,24 @@ def restore_purchases() -> None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def rowwidget(edit: Widget = None,
|
def rowwidget(edit: ba.Widget = None,
|
||||||
parent: Widget = None,
|
parent: ba.Widget = None,
|
||||||
size: Sequence[float] = None,
|
size: Sequence[float] = None,
|
||||||
position: Sequence[float] = None,
|
position: Sequence[float] = None,
|
||||||
background: bool = None,
|
background: bool = None,
|
||||||
selected_child: Widget = None,
|
selected_child: ba.Widget = None,
|
||||||
visible_child: Widget = None,
|
visible_child: ba.Widget = None,
|
||||||
claims_left_right: bool = None,
|
claims_left_right: bool = None,
|
||||||
claims_tab: bool = None,
|
claims_tab: bool = None,
|
||||||
selection_loops_to_parent: bool = None) -> Widget:
|
selection_loops_to_parent: bool = None) -> ba.Widget:
|
||||||
"""rowwidget(edit: Widget = None, parent: Widget = None,
|
"""rowwidget(edit: ba.Widget = None, parent: ba.Widget = None,
|
||||||
size: Sequence[float] = None,
|
size: Sequence[float] = None,
|
||||||
position: Sequence[float] = None,
|
position: Sequence[float] = None,
|
||||||
background: bool = None, selected_child: Widget = None,
|
background: bool = None, selected_child: ba.Widget = None,
|
||||||
visible_child: Widget = None,
|
visible_child: ba.Widget = None,
|
||||||
claims_left_right: bool = None,
|
claims_left_right: bool = None,
|
||||||
claims_tab: bool = None,
|
claims_tab: bool = None,
|
||||||
selection_loops_to_parent: bool = None) -> Widget
|
selection_loops_to_parent: bool = None) -> ba.Widget
|
||||||
|
|
||||||
Create or edit a row widget.
|
Create or edit a row widget.
|
||||||
|
|
||||||
@ -3320,7 +3355,8 @@ def rowwidget(edit: Widget = None,
|
|||||||
a new one is created and returned. Arguments that are not set to None
|
a new one is created and returned. Arguments that are not set to None
|
||||||
are applied to the Widget.
|
are applied to the Widget.
|
||||||
"""
|
"""
|
||||||
return Widget()
|
import ba # pylint: disable=cyclic-import
|
||||||
|
return ba.Widget()
|
||||||
|
|
||||||
|
|
||||||
def run_transactions() -> None:
|
def run_transactions() -> None:
|
||||||
@ -3775,8 +3811,8 @@ def submit_score(game: str,
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def textwidget(edit: Widget = None,
|
def textwidget(edit: ba.Widget = None,
|
||||||
parent: Widget = None,
|
parent: ba.Widget = None,
|
||||||
size: Sequence[float] = None,
|
size: Sequence[float] = None,
|
||||||
position: Sequence[float] = None,
|
position: Sequence[float] = None,
|
||||||
text: Union[str, ba.Lstr] = None,
|
text: Union[str, ba.Lstr] = None,
|
||||||
@ -3787,13 +3823,13 @@ def textwidget(edit: Widget = None,
|
|||||||
on_return_press_call: Callable[[], None] = None,
|
on_return_press_call: Callable[[], None] = None,
|
||||||
on_activate_call: Callable[[], None] = None,
|
on_activate_call: Callable[[], None] = None,
|
||||||
selectable: bool = None,
|
selectable: bool = None,
|
||||||
query: Widget = None,
|
query: ba.Widget = None,
|
||||||
max_chars: int = None,
|
max_chars: int = None,
|
||||||
color: Sequence[float] = None,
|
color: Sequence[float] = None,
|
||||||
click_activate: bool = None,
|
click_activate: bool = None,
|
||||||
on_select_call: Callable[[], None] = None,
|
on_select_call: Callable[[], None] = None,
|
||||||
always_highlight: bool = None,
|
always_highlight: bool = None,
|
||||||
draw_controller: Widget = None,
|
draw_controller: ba.Widget = None,
|
||||||
scale: float = None,
|
scale: float = None,
|
||||||
corner_scale: float = None,
|
corner_scale: float = None,
|
||||||
description: Union[str, ba.Lstr] = None,
|
description: Union[str, ba.Lstr] = None,
|
||||||
@ -3810,16 +3846,16 @@ def textwidget(edit: Widget = None,
|
|||||||
big: bool = None,
|
big: bool = None,
|
||||||
extra_touch_border_scale: float = None,
|
extra_touch_border_scale: float = None,
|
||||||
res_scale: float = None) -> Widget:
|
res_scale: float = None) -> Widget:
|
||||||
"""textwidget(edit: Widget = None, parent: Widget = None,
|
"""textwidget(edit: ba.Widget = None, parent: ba.Widget = None,
|
||||||
size: Sequence[float] = None, position: Sequence[float] = None,
|
size: Sequence[float] = None, position: Sequence[float] = None,
|
||||||
text: Union[str, ba.Lstr] = None, v_align: str = None,
|
text: Union[str, ba.Lstr] = None, v_align: str = None,
|
||||||
h_align: str = None, editable: bool = None, padding: float = None,
|
h_align: str = None, editable: bool = None, padding: float = None,
|
||||||
on_return_press_call: Callable[[], None] = None,
|
on_return_press_call: Callable[[], None] = None,
|
||||||
on_activate_call: Callable[[], None] = None,
|
on_activate_call: Callable[[], None] = None,
|
||||||
selectable: bool = None, query: Widget = None, max_chars: int = None,
|
selectable: bool = None, query: ba.Widget = None, max_chars: int = None,
|
||||||
color: Sequence[float] = None, click_activate: bool = None,
|
color: Sequence[float] = None, click_activate: bool = None,
|
||||||
on_select_call: Callable[[], None] = None,
|
on_select_call: Callable[[], None] = None,
|
||||||
always_highlight: bool = None, draw_controller: Widget = None,
|
always_highlight: bool = None, draw_controller: ba.Widget = None,
|
||||||
scale: float = None, corner_scale: float = None,
|
scale: float = None, corner_scale: float = None,
|
||||||
description: Union[str, ba.Lstr] = None,
|
description: Union[str, ba.Lstr] = None,
|
||||||
transition_delay: float = None, maxwidth: float = None,
|
transition_delay: float = None, maxwidth: float = None,
|
||||||
|
|||||||
@ -9,16 +9,16 @@ In some specific cases you may need to pull in individual submodules instead.
|
|||||||
# pylint: disable=unused-import
|
# pylint: disable=unused-import
|
||||||
# pylint: disable=redefined-builtin
|
# pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from _ba import (CollideModel, Context, ContextCall, Data, InputDevice,
|
from _ba import (
|
||||||
Material, Model, Node, SessionPlayer, Sound, Texture, Timer,
|
CollideModel, Context, ContextCall, Data, InputDevice, Material, Model,
|
||||||
Vec3, Widget, buttonwidget, camerashake, checkboxwidget,
|
Node, SessionPlayer, Sound, Texture, Timer, Vec3, Widget, buttonwidget,
|
||||||
columnwidget, containerwidget, do_once, emitfx, getactivity,
|
camerashake, checkboxwidget, columnwidget, containerwidget, do_once,
|
||||||
getcollidemodel, getmodel, getnodes, getsession, getsound,
|
emitfx, getactivity, getcollidemodel, getmodel, getnodes, getsession,
|
||||||
gettexture, hscrollwidget, imagewidget, log, newactivity,
|
getsound, gettexture, hscrollwidget, imagewidget, log, newactivity,
|
||||||
newnode, playsound, printnodes, printobjects, pushcall, quit,
|
newnode, playsound, printnodes, printobjects, pushcall, quit, rowwidget,
|
||||||
rowwidget, safecolor, screenmessage, scrollwidget,
|
safecolor, screenmessage, scrollwidget, set_analytics_screen, charstr,
|
||||||
set_analytics_screen, charstr, textwidget, time, timer,
|
textwidget, time, timer, open_url, widget, clipboard_is_supported,
|
||||||
open_url, widget)
|
clipboard_has_text, clipboard_get_text, clipboard_set_text)
|
||||||
from ba._activity import Activity
|
from ba._activity import Activity
|
||||||
from ba._plugin import PotentialPlugin, Plugin, PluginSubsystem
|
from ba._plugin import PotentialPlugin, Plugin, PluginSubsystem
|
||||||
from ba._actor import Actor
|
from ba._actor import Actor
|
||||||
|
|||||||
@ -192,7 +192,7 @@ class Actor:
|
|||||||
"""Return the ba.Activity this Actor is associated with.
|
"""Return the ba.Activity this Actor is associated with.
|
||||||
|
|
||||||
If the Activity no longer exists, raises a ba.ActivityNotFoundError
|
If the Activity no longer exists, raises a ba.ActivityNotFoundError
|
||||||
or returns None depending on whether 'doraise' is set.
|
or returns None depending on whether 'doraise' is True.
|
||||||
"""
|
"""
|
||||||
activity = self._activity()
|
activity = self._activity()
|
||||||
if activity is None and doraise:
|
if activity is None and doraise:
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class AppConfig(dict):
|
|||||||
|
|
||||||
AppConfig data is stored as json on disk on so make sure to only place
|
AppConfig data is stored as json on disk on so make sure to only place
|
||||||
json-friendly values in it (dict, list, str, float, int, bool).
|
json-friendly values in it (dict, list, str, float, int, bool).
|
||||||
Be aware that tuples will be quietly converted to lists.
|
Be aware that tuples will be quietly converted to lists when stored.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def resolve(self, key: str) -> Any:
|
def resolve(self, key: str) -> Any:
|
||||||
|
|||||||
@ -38,16 +38,18 @@ T = TypeVar('T')
|
|||||||
|
|
||||||
|
|
||||||
def existing(obj: Optional[ExistableType]) -> Optional[ExistableType]:
|
def existing(obj: Optional[ExistableType]) -> Optional[ExistableType]:
|
||||||
"""Convert invalid references to None for any ba.Existable type.
|
"""Convert invalid references to None for any ba.Existable object.
|
||||||
|
|
||||||
Category: Gameplay Functions
|
Category: Gameplay Functions
|
||||||
|
|
||||||
To best support type checking, it is important that invalid references
|
To best support type checking, it is important that invalid references
|
||||||
not be passed around and instead get converted to values of None.
|
not be passed around and instead get converted to values of None.
|
||||||
That way the type checker can properly flag attempts to pass dead
|
That way the type checker can properly flag attempts to pass dead
|
||||||
objects into functions expecting only live ones, etc.
|
objects (Optional[FooType]) into functions expecting only live ones
|
||||||
This call can be used on any 'existable' object (one with an exists()
|
(FooType), etc. This call can be used on any 'existable' object
|
||||||
method) and will convert it to a None value if it does not exist.
|
(one with an exists() method) and will convert it to a None value
|
||||||
|
if it does not exist.
|
||||||
|
|
||||||
For more info, see notes on 'existables' here:
|
For more info, see notes on 'existables' here:
|
||||||
https://ballistica.net/wiki/Coding-Style-Guide
|
https://ballistica.net/wiki/Coding-Style-Guide
|
||||||
"""
|
"""
|
||||||
@ -358,15 +360,17 @@ def _verify_object_death(wref: ReferenceType) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def storagename(suffix: str = None) -> str:
|
def storagename(suffix: str = None) -> str:
|
||||||
"""Generate a (hopefully) unique name for storing things in public places.
|
"""Generate a unique name for storing class data in shared places.
|
||||||
|
|
||||||
Category: General Utility Functions
|
Category: General Utility Functions
|
||||||
|
|
||||||
This consists of a leading underscore, the module path at the
|
This consists of a leading underscore, the module path at the
|
||||||
call site with dots replaced by underscores, the class name, and
|
call site with dots replaced by underscores, the containing class's
|
||||||
the provided suffix. When storing data in public places such as
|
qualified name, and the provided suffix. When storing data in public
|
||||||
'customdata' dicts, this minimizes the chance of collisions if a
|
places such as 'customdata' dicts, this minimizes the chance of
|
||||||
module or class is duplicated or renamed.
|
collisions with other similarly named classes.
|
||||||
|
|
||||||
|
Note that this will function even if called in the class definition.
|
||||||
|
|
||||||
# Example: generate a unique name for storage purposes:
|
# Example: generate a unique name for storage purposes:
|
||||||
class MyThingie:
|
class MyThingie:
|
||||||
@ -374,14 +378,21 @@ def storagename(suffix: str = None) -> str:
|
|||||||
# This will give something like '_mymodule_submodule_mythingie_data'.
|
# This will give something like '_mymodule_submodule_mythingie_data'.
|
||||||
_STORENAME = ba.storagename('data')
|
_STORENAME = ba.storagename('data')
|
||||||
|
|
||||||
|
# Use that name to store some data in the Activity we were passed.
|
||||||
def __init__(self, activity):
|
def __init__(self, activity):
|
||||||
# Store some data in the Activity we were passed
|
|
||||||
activity.customdata[self._STORENAME] = {}
|
activity.customdata[self._STORENAME] = {}
|
||||||
"""
|
"""
|
||||||
frame = inspect.currentframe()
|
frame = inspect.currentframe()
|
||||||
if frame is None:
|
if frame is None:
|
||||||
raise RuntimeError('Cannot get current stack frame.')
|
raise RuntimeError('Cannot get current stack frame.')
|
||||||
fback = frame.f_back
|
fback = frame.f_back
|
||||||
|
|
||||||
|
# Note: We need to explicitly clear frame here to avoid a ref-loop
|
||||||
|
# that keeps all function-dicts in the stack alive until the next
|
||||||
|
# full GC cycle (the stack frame refers to this function's dict,
|
||||||
|
# which refers to the stack frame).
|
||||||
|
del frame
|
||||||
|
|
||||||
if fback is None:
|
if fback is None:
|
||||||
raise RuntimeError('Cannot get parent stack frame.')
|
raise RuntimeError('Cannot get parent stack frame.')
|
||||||
modulepath = fback.f_globals.get('__name__')
|
modulepath = fback.f_globals.get('__name__')
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import _ba
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Callable, Any, Optional, Dict, Union, Type
|
from typing import Callable, Any, Optional, Dict, Union, Type
|
||||||
|
import ba
|
||||||
|
|
||||||
|
|
||||||
class MusicType(Enum):
|
class MusicType(Enum):
|
||||||
@ -469,8 +470,9 @@ class MusicPlayer:
|
|||||||
self._actually_playing = False
|
self._actually_playing = False
|
||||||
|
|
||||||
|
|
||||||
def setmusic(musictype: Optional[MusicType], continuous: bool = False) -> None:
|
def setmusic(musictype: Optional[ba.MusicType],
|
||||||
"""Tell the game to play (or stop playing) a certain type of music.
|
continuous: bool = False) -> None:
|
||||||
|
"""Set the app to play (or stop playing) a certain type of music.
|
||||||
|
|
||||||
category: Gameplay Functions
|
category: Gameplay Functions
|
||||||
|
|
||||||
|
|||||||
@ -284,8 +284,8 @@ class EmptyPlayer(Player['ba.EmptyTeam']):
|
|||||||
|
|
||||||
Category: Gameplay Classes
|
Category: Gameplay Classes
|
||||||
|
|
||||||
ba.Player and ba.Team are 'Generic' types, and so passing them as
|
ba.Player and ba.Team are 'Generic' types, and so passing those top level
|
||||||
type arguments when defining a ba.Activity reduces type safety.
|
classes as type arguments when defining a ba.Activity reduces type safety.
|
||||||
For example, activity.teams[0].player will have type 'Any' in that case.
|
For example, activity.teams[0].player will have type 'Any' in that case.
|
||||||
For that reason, it is better to pass EmptyPlayer and EmptyTeam when
|
For that reason, it is better to pass EmptyPlayer and EmptyTeam when
|
||||||
defining a ba.Activity that does not need custom types of its own.
|
defining a ba.Activity that does not need custom types of its own.
|
||||||
|
|||||||
@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
class Session:
|
class Session:
|
||||||
"""Defines a high level series of activities with a common purpose.
|
"""Defines a high level series of ba.Activities with a common purpose.
|
||||||
|
|
||||||
category: Gameplay Classes
|
category: Gameplay Classes
|
||||||
|
|
||||||
|
|||||||
@ -200,8 +200,8 @@ class EmptyTeam(Team['ba.EmptyPlayer']):
|
|||||||
|
|
||||||
Category: Gameplay Classes
|
Category: Gameplay Classes
|
||||||
|
|
||||||
ba.Player and ba.Team are 'Generic' types, and so passing them as
|
ba.Player and ba.Team are 'Generic' types, and so passing those top level
|
||||||
type arguments when defining a ba.Activity reduces type safety.
|
classes as type arguments when defining a ba.Activity reduces type safety.
|
||||||
For example, activity.teams[0].player will have type 'Any' in that case.
|
For example, activity.teams[0].player will have type 'Any' in that case.
|
||||||
For that reason, it is better to pass EmptyPlayer and EmptyTeam when
|
For that reason, it is better to pass EmptyPlayer and EmptyTeam when
|
||||||
defining a ba.Activity that does not need custom types of its own.
|
defining a ba.Activity that does not need custom types of its own.
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import _ba
|
|||||||
from ba._enums import UIScale
|
from ba._enums import UIScale
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Optional, Dict, Any, Callable, List
|
from typing import Optional, Dict, Any, Callable, List, Type
|
||||||
from ba.ui import UICleanupCheck
|
from ba.ui import UICleanupCheck
|
||||||
import ba
|
import ba
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class UISubsystem:
|
|||||||
else:
|
else:
|
||||||
raise RuntimeError(f'Invalid UIScale value: {interfacetype}')
|
raise RuntimeError(f'Invalid UIScale value: {interfacetype}')
|
||||||
|
|
||||||
self.window_states: Dict = {} # FIXME: Kill this.
|
self.window_states: Dict[Type, Any] = {} # FIXME: Kill this.
|
||||||
self.main_menu_selection: Optional[str] = None # FIXME: Kill this.
|
self.main_menu_selection: Optional[str] = None # FIXME: Kill this.
|
||||||
self.have_party_queue_window = False
|
self.have_party_queue_window = False
|
||||||
self.quit_window: Any = None
|
self.quit_window: Any = None
|
||||||
@ -76,7 +76,7 @@ class UISubsystem:
|
|||||||
# this holds true at all aspect ratios.
|
# this holds true at all aspect ratios.
|
||||||
|
|
||||||
# UPDATE: A better way to test this is now by setting the environment
|
# UPDATE: A better way to test this is now by setting the environment
|
||||||
# variable BA_FORCE_UI_SCALE to "small", "medium", or "large".
|
# variable BA_UI_SCALE to "small", "medium", or "large".
|
||||||
# This will affect system UIs not covered by the values below such
|
# This will affect system UIs not covered by the values below such
|
||||||
# as screen-messages. The below values remain functional, however,
|
# as screen-messages. The below values remain functional, however,
|
||||||
# for cases such as Android where environment variables can't be set
|
# for cases such as Android where environment variables can't be set
|
||||||
|
|||||||
@ -118,7 +118,7 @@ class UIEntry:
|
|||||||
|
|
||||||
|
|
||||||
class UIController:
|
class UIController:
|
||||||
"""Wrangles UILocations.
|
"""Wrangles ba.UILocations.
|
||||||
|
|
||||||
Category: User Interface Classes
|
Category: User Interface Classes
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -1088,13 +1088,13 @@ class AccountSettingsWindow(ba.Window):
|
|||||||
sel_name = 'Scroll'
|
sel_name = 'Scroll'
|
||||||
else:
|
else:
|
||||||
raise ValueError('unrecognized selection')
|
raise ValueError('unrecognized selection')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = sel_name
|
ba.app.ui.window_states[type(self)] = sel_name
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self}.')
|
ba.print_exception(f'Error saving state for {self}.')
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
try:
|
try:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__)
|
sel_name = ba.app.ui.window_states.get(type(self))
|
||||||
if sel_name == 'Back':
|
if sel_name == 'Back':
|
||||||
sel = self._back_button
|
sel = self._back_button
|
||||||
elif sel_name == 'Scroll':
|
elif sel_name == 'Scroll':
|
||||||
|
|||||||
@ -1542,7 +1542,7 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
try:
|
try:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__,
|
sel_name = ba.app.ui.window_states.get(type(self),
|
||||||
{}).get('sel_name')
|
{}).get('sel_name')
|
||||||
if sel_name == 'Back':
|
if sel_name == 'Back':
|
||||||
sel = self._back_button
|
sel = self._back_button
|
||||||
@ -1572,9 +1572,7 @@ class CoopBrowserWindow(ba.Window):
|
|||||||
sel_name = 'Scroll'
|
sel_name = 'Scroll'
|
||||||
else:
|
else:
|
||||||
raise ValueError('unrecognized selection')
|
raise ValueError('unrecognized selection')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = {
|
ba.app.ui.window_states[type(self)] = {'sel_name': sel_name}
|
||||||
'sel_name': sel_name
|
|
||||||
}
|
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self}.')
|
ba.print_exception(f'Error saving state for {self}.')
|
||||||
|
|
||||||
|
|||||||
@ -4,22 +4,56 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import weakref
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _ba
|
import _ba
|
||||||
import ba
|
import ba
|
||||||
from bastd.ui.gather.abouttab import AboutGatherTab
|
|
||||||
from bastd.ui.gather.manualtab import ManualGatherTab
|
|
||||||
from bastd.ui.gather.googleplaytab import GooglePlayGatherTab
|
|
||||||
from bastd.ui.gather.publictab import PublicGatherTab
|
|
||||||
from bastd.ui.gather.nearbytab import NearbyGatherTab
|
|
||||||
from bastd.ui.tabs import TabRow
|
from bastd.ui.tabs import TabRow
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import (Any, Optional, Tuple, Dict, List, Union, Callable,
|
from typing import (Any, Optional, Tuple, Dict, List, Union, Callable,
|
||||||
Type)
|
Type)
|
||||||
from bastd.ui.gather.bases import GatherTab
|
|
||||||
|
|
||||||
|
class GatherTab:
|
||||||
|
"""Defines a tab for use in the gather UI."""
|
||||||
|
|
||||||
|
def __init__(self, window: GatherWindow) -> None:
|
||||||
|
self._window = weakref.ref(window)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def window(self) -> GatherWindow:
|
||||||
|
"""The GatherWindow that this tab belongs to."""
|
||||||
|
window = self._window()
|
||||||
|
if window is None:
|
||||||
|
raise ba.NotFoundError("GatherTab's window no longer exists.")
|
||||||
|
return window
|
||||||
|
|
||||||
|
def on_activate(
|
||||||
|
self,
|
||||||
|
parent_widget: ba.Widget,
|
||||||
|
tab_button: ba.Widget,
|
||||||
|
region_width: float,
|
||||||
|
region_height: float,
|
||||||
|
region_left: float,
|
||||||
|
region_bottom: float,
|
||||||
|
) -> ba.Widget:
|
||||||
|
"""Called when the tab becomes the active one.
|
||||||
|
|
||||||
|
The tab should create and return a container widget covering the
|
||||||
|
specified region.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_deactivate(self) -> None:
|
||||||
|
"""Called when the tab will no longer be the active one."""
|
||||||
|
|
||||||
|
def save_state(self) -> None:
|
||||||
|
"""Called when the parent window is saving state."""
|
||||||
|
|
||||||
|
def restore_state(self) -> None:
|
||||||
|
"""Called when the parent window is restoring state."""
|
||||||
|
|
||||||
|
|
||||||
class GatherWindow(ba.Window):
|
class GatherWindow(ba.Window):
|
||||||
@ -29,8 +63,8 @@ class GatherWindow(ba.Window):
|
|||||||
"""Our available tab types."""
|
"""Our available tab types."""
|
||||||
ABOUT = 'about'
|
ABOUT = 'about'
|
||||||
INTERNET = 'internet'
|
INTERNET = 'internet'
|
||||||
GOOGLE_PLAY = 'google_play'
|
PRIVATE = 'private'
|
||||||
LOCAL_NETWORK = 'local_network'
|
NEARBY = 'nearby'
|
||||||
MANUAL = 'manual'
|
MANUAL = 'manual'
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
@ -38,6 +72,13 @@ class GatherWindow(ba.Window):
|
|||||||
origin_widget: ba.Widget = None):
|
origin_widget: ba.Widget = None):
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
from bastd.ui.gather.abouttab import AboutGatherTab
|
||||||
|
from bastd.ui.gather.manualtab import ManualGatherTab
|
||||||
|
from bastd.ui.gather.privatetab import PrivateGatherTab
|
||||||
|
from bastd.ui.gather.publictab import PublicGatherTab
|
||||||
|
from bastd.ui.gather.nearbytab import NearbyGatherTab
|
||||||
|
|
||||||
ba.set_analytics_screen('Gather Window')
|
ba.set_analytics_screen('Gather Window')
|
||||||
scale_origin: Optional[Tuple[float, float]]
|
scale_origin: Optional[Tuple[float, float]]
|
||||||
if origin_widget is not None:
|
if origin_widget is not None:
|
||||||
@ -104,9 +145,6 @@ class GatherWindow(ba.Window):
|
|||||||
text=ba.Lstr(resource=self._r + '.titleText'),
|
text=ba.Lstr(resource=self._r + '.titleText'),
|
||||||
maxwidth=550)
|
maxwidth=550)
|
||||||
|
|
||||||
platform = ba.app.platform
|
|
||||||
subplatform = ba.app.subplatform
|
|
||||||
|
|
||||||
scroll_buffer_h = 130 + 2 * x_offs
|
scroll_buffer_h = 130 + 2 * x_offs
|
||||||
tab_buffer_h = ((320 if condensed else 250) + 2 * x_offs)
|
tab_buffer_h = ((320 if condensed else 250) + 2 * x_offs)
|
||||||
|
|
||||||
@ -117,11 +155,10 @@ class GatherWindow(ba.Window):
|
|||||||
if _ba.get_account_misc_read_val('enablePublicParties', True):
|
if _ba.get_account_misc_read_val('enablePublicParties', True):
|
||||||
tabdefs.append((self.TabID.INTERNET,
|
tabdefs.append((self.TabID.INTERNET,
|
||||||
ba.Lstr(resource=self._r + '.publicText')))
|
ba.Lstr(resource=self._r + '.publicText')))
|
||||||
if platform == 'android' and subplatform == 'google':
|
tabdefs.append(
|
||||||
tabdefs.append((self.TabID.GOOGLE_PLAY,
|
(self.TabID.PRIVATE, ba.Lstr(resource=self._r + '.privateText')))
|
||||||
ba.Lstr(resource=self._r + '.googlePlayText')))
|
tabdefs.append(
|
||||||
tabdefs.append((self.TabID.LOCAL_NETWORK,
|
(self.TabID.NEARBY, ba.Lstr(resource=self._r + '.nearbyText')))
|
||||||
ba.Lstr(resource=self._r + '.nearbyText')))
|
|
||||||
tabdefs.append(
|
tabdefs.append(
|
||||||
(self.TabID.MANUAL, ba.Lstr(resource=self._r + '.manualText')))
|
(self.TabID.MANUAL, ba.Lstr(resource=self._r + '.manualText')))
|
||||||
|
|
||||||
@ -139,9 +176,9 @@ class GatherWindow(ba.Window):
|
|||||||
tabtypes: Dict[GatherWindow.TabID, Type[GatherTab]] = {
|
tabtypes: Dict[GatherWindow.TabID, Type[GatherTab]] = {
|
||||||
self.TabID.ABOUT: AboutGatherTab,
|
self.TabID.ABOUT: AboutGatherTab,
|
||||||
self.TabID.MANUAL: ManualGatherTab,
|
self.TabID.MANUAL: ManualGatherTab,
|
||||||
self.TabID.GOOGLE_PLAY: GooglePlayGatherTab,
|
self.TabID.PRIVATE: PrivateGatherTab,
|
||||||
self.TabID.INTERNET: PublicGatherTab,
|
self.TabID.INTERNET: PublicGatherTab,
|
||||||
self.TabID.LOCAL_NETWORK: NearbyGatherTab
|
self.TabID.NEARBY: NearbyGatherTab
|
||||||
}
|
}
|
||||||
self._tabs: Dict[GatherWindow.TabID, GatherTab] = {}
|
self._tabs: Dict[GatherWindow.TabID, GatherTab] = {}
|
||||||
for tab_id in self._tab_row.tabs:
|
for tab_id in self._tab_row.tabs:
|
||||||
@ -234,7 +271,7 @@ class GatherWindow(ba.Window):
|
|||||||
sel_name = 'TabContainer'
|
sel_name = 'TabContainer'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized selection: \'{sel}\'')
|
raise ValueError(f'unrecognized selection: \'{sel}\'')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = {
|
ba.app.ui.window_states[type(self)] = {
|
||||||
'sel_name': sel_name,
|
'sel_name': sel_name,
|
||||||
}
|
}
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -247,7 +284,7 @@ class GatherWindow(ba.Window):
|
|||||||
tab.restore_state()
|
tab.restore_state()
|
||||||
|
|
||||||
sel: Optional[ba.Widget]
|
sel: Optional[ba.Widget]
|
||||||
winstate = ba.app.ui.window_states.get(self.__class__.__name__, {})
|
winstate = ba.app.ui.window_states.get(type(self), {})
|
||||||
sel_name = winstate.get('sel_name', None)
|
sel_name = winstate.get('sel_name', None)
|
||||||
assert isinstance(sel_name, (str, type(None)))
|
assert isinstance(sel_name, (str, type(None)))
|
||||||
current_tab = self.TabID.ABOUT
|
current_tab = self.TabID.ABOUT
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
import ba
|
import ba
|
||||||
import _ba
|
import _ba
|
||||||
from bastd.ui.gather.bases import GatherTab
|
from bastd.ui.gather import GatherTab
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|||||||
@ -1,52 +0,0 @@
|
|||||||
# Released under the MIT License. See LICENSE for details.
|
|
||||||
#
|
|
||||||
"""Provides UI for inviting/joining friends."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import weakref
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import ba
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from bastd.ui.gather import GatherWindow
|
|
||||||
|
|
||||||
|
|
||||||
class GatherTab:
|
|
||||||
"""Defines a tab for use in the gather UI."""
|
|
||||||
|
|
||||||
def __init__(self, window: GatherWindow) -> None:
|
|
||||||
self._window = weakref.ref(window)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def window(self) -> GatherWindow:
|
|
||||||
"""The GatherWindow that this tab belongs to."""
|
|
||||||
window = self._window()
|
|
||||||
if window is None:
|
|
||||||
raise ba.NotFoundError("GatherTab's window no longer exists.")
|
|
||||||
return window
|
|
||||||
|
|
||||||
def on_activate(
|
|
||||||
self,
|
|
||||||
parent_widget: ba.Widget,
|
|
||||||
tab_button: ba.Widget,
|
|
||||||
region_width: float,
|
|
||||||
region_height: float,
|
|
||||||
region_left: float,
|
|
||||||
region_bottom: float,
|
|
||||||
) -> ba.Widget:
|
|
||||||
"""Called when the tab becomes the active one.
|
|
||||||
|
|
||||||
The tab should create and return a container widget covering the
|
|
||||||
specified region.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def on_deactivate(self) -> None:
|
|
||||||
"""Called when the tab will no longer be the active one."""
|
|
||||||
|
|
||||||
def save_state(self) -> None:
|
|
||||||
"""Called when the parent window is saving state."""
|
|
||||||
|
|
||||||
def restore_state(self) -> None:
|
|
||||||
"""Called when the parent window is restoring state."""
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
# Released under the MIT License. See LICENSE for details.
|
|
||||||
#
|
|
||||||
"""Defines the Google Play tab in the gather UI."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
import _ba
|
|
||||||
import ba
|
|
||||||
from bastd.ui.gather.bases import GatherTab
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from typing import Optional
|
|
||||||
from bastd.ui.gather import GatherWindow
|
|
||||||
|
|
||||||
|
|
||||||
class GooglePlayGatherTab(GatherTab):
|
|
||||||
"""The public tab in the gather UI"""
|
|
||||||
|
|
||||||
def __init__(self, window: GatherWindow) -> None:
|
|
||||||
super().__init__(window)
|
|
||||||
self._container: Optional[ba.Widget] = None
|
|
||||||
|
|
||||||
def on_activate(
|
|
||||||
self,
|
|
||||||
parent_widget: ba.Widget,
|
|
||||||
tab_button: ba.Widget,
|
|
||||||
region_width: float,
|
|
||||||
region_height: float,
|
|
||||||
region_left: float,
|
|
||||||
region_bottom: float,
|
|
||||||
) -> ba.Widget:
|
|
||||||
c_width = region_width
|
|
||||||
c_height = 380.0
|
|
||||||
self._container = ba.containerwidget(
|
|
||||||
parent=parent_widget,
|
|
||||||
position=(region_left,
|
|
||||||
region_bottom + (region_height - c_height) * 0.5),
|
|
||||||
size=(c_width, c_height),
|
|
||||||
background=False,
|
|
||||||
selection_loops_to_parent=True)
|
|
||||||
v = c_height - 30.0
|
|
||||||
ba.textwidget(
|
|
||||||
parent=self._container,
|
|
||||||
position=(c_width * 0.5, v - 140.0),
|
|
||||||
color=(0.6, 1.0, 0.6),
|
|
||||||
scale=1.3,
|
|
||||||
size=(0.0, 0.0),
|
|
||||||
maxwidth=c_width * 0.9,
|
|
||||||
h_align='center',
|
|
||||||
v_align='center',
|
|
||||||
text=ba.Lstr(resource='googleMultiplayerDiscontinuedText'))
|
|
||||||
return self._container
|
|
||||||
|
|
||||||
def _on_google_play_show_invites_press(self) -> None:
|
|
||||||
from bastd.ui import account
|
|
||||||
if (_ba.get_account_state() != 'signed_in'
|
|
||||||
or _ba.get_account_type() != 'Google Play'):
|
|
||||||
account.show_sign_in_prompt('Google Play')
|
|
||||||
else:
|
|
||||||
_ba.show_invites_ui()
|
|
||||||
|
|
||||||
def _on_google_play_invite_press(self) -> None:
|
|
||||||
from bastd.ui.confirm import ConfirmWindow
|
|
||||||
from bastd.ui.account import show_sign_in_prompt
|
|
||||||
if (_ba.get_account_state() != 'signed_in'
|
|
||||||
or _ba.get_account_type() != 'Google Play'):
|
|
||||||
show_sign_in_prompt('Google Play')
|
|
||||||
else:
|
|
||||||
# If there's google play people connected to us, inform the user
|
|
||||||
# that they will get disconnected. Otherwise just go ahead.
|
|
||||||
google_player_count = (_ba.get_google_play_party_client_count())
|
|
||||||
if google_player_count > 0:
|
|
||||||
ConfirmWindow(
|
|
||||||
ba.Lstr(resource='gatherWindow.'
|
|
||||||
'googlePlayReInviteText',
|
|
||||||
subs=[('${COUNT}', str(google_player_count))]),
|
|
||||||
lambda: ba.timer(
|
|
||||||
0.2, _ba.invite_players, timetype=ba.TimeType.REAL),
|
|
||||||
width=500,
|
|
||||||
height=150,
|
|
||||||
ok_text=ba.Lstr(resource='gatherWindow.'
|
|
||||||
'googlePlayInviteText'))
|
|
||||||
else:
|
|
||||||
ba.timer(0.1, _ba.invite_players, timetype=ba.TimeType.REAL)
|
|
||||||
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, cast
|
|||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from bastd.ui.gather.bases import GatherTab
|
from bastd.ui.gather import GatherTab
|
||||||
|
|
||||||
import _ba
|
import _ba
|
||||||
import ba
|
import ba
|
||||||
@ -161,11 +161,10 @@ class ManualGatherTab(GatherTab):
|
|||||||
return self._container
|
return self._container
|
||||||
|
|
||||||
def save_state(self) -> None:
|
def save_state(self) -> None:
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = State(
|
ba.app.ui.window_states[type(self)] = State(sub_tab=self._sub_tab)
|
||||||
sub_tab=self._sub_tab)
|
|
||||||
|
|
||||||
def restore_state(self) -> None:
|
def restore_state(self) -> None:
|
||||||
state = ba.app.ui.window_states.get(self.__class__.__name__)
|
state = ba.app.ui.window_states.get(type(self))
|
||||||
if state is None:
|
if state is None:
|
||||||
state = State()
|
state = State()
|
||||||
assert isinstance(state, State)
|
assert isinstance(state, State)
|
||||||
|
|||||||
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
import ba
|
import ba
|
||||||
import _ba
|
import _ba
|
||||||
from bastd.ui.gather.bases import GatherTab
|
from bastd.ui.gather import GatherTab
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Optional, Dict, Any
|
from typing import Optional, Dict, Any
|
||||||
|
|||||||
755
assets/src/ba_data/python/bastd/ui/gather/privatetab.py
Normal file
755
assets/src/ba_data/python/bastd/ui/gather/privatetab.py
Normal file
@ -0,0 +1,755 @@
|
|||||||
|
# Released under the MIT License. See LICENSE for details.
|
||||||
|
#
|
||||||
|
"""Defines the Private tab in the gather UI."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import copy
|
||||||
|
import time
|
||||||
|
from enum import Enum
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import TYPE_CHECKING, cast
|
||||||
|
|
||||||
|
import ba
|
||||||
|
import _ba
|
||||||
|
from efro.dataclasses import dataclass_from_dict
|
||||||
|
from bastd.ui.gather import GatherTab
|
||||||
|
from bastd.ui import getcurrency
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Optional, Dict, Any, List
|
||||||
|
from bastd.ui.gather import GatherWindow
|
||||||
|
|
||||||
|
# Print a bit of info about queries, etc.
|
||||||
|
DEBUG_SERVER_COMMUNICATION = os.environ.get('BA_DEBUG_PPTABCOM') == '1'
|
||||||
|
|
||||||
|
|
||||||
|
class SubTabType(Enum):
|
||||||
|
"""Available sub-tabs."""
|
||||||
|
JOIN = 'join'
|
||||||
|
HOST = 'host'
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class State:
|
||||||
|
"""Our core state that persists while the app is running."""
|
||||||
|
sub_tab: SubTabType = SubTabType.JOIN
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ConnectResult:
|
||||||
|
"""Info about a server we get back when connecting."""
|
||||||
|
error: Optional[str] = None
|
||||||
|
addr: Optional[str] = None
|
||||||
|
port: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class HostingState:
|
||||||
|
"""Our combined state of whether we're hosting, whether we can, etc."""
|
||||||
|
unavailable_error: Optional[str] = None
|
||||||
|
party_code: Optional[str] = None
|
||||||
|
able_to_host: bool = False
|
||||||
|
tickets_to_host_now: int = 0
|
||||||
|
minutes_until_free_host: Optional[float] = None
|
||||||
|
free_host_minutes_remaining: Optional[float] = None
|
||||||
|
|
||||||
|
|
||||||
|
class PrivateGatherTab(GatherTab):
|
||||||
|
"""The private tab in the gather UI"""
|
||||||
|
|
||||||
|
def __init__(self, window: GatherWindow) -> None:
|
||||||
|
super().__init__(window)
|
||||||
|
self._container: Optional[ba.Widget] = None
|
||||||
|
self._state: State = State()
|
||||||
|
self._hostingstate = HostingState()
|
||||||
|
self._join_sub_tab_text: Optional[ba.Widget] = None
|
||||||
|
self._host_sub_tab_text: Optional[ba.Widget] = None
|
||||||
|
self._update_timer: Optional[ba.Timer] = None
|
||||||
|
self._join_party_code_text: Optional[ba.Widget] = None
|
||||||
|
self._c_width: float = 0.0
|
||||||
|
self._c_height: float = 0.0
|
||||||
|
self._last_hosting_state_query_time: Optional[float] = None
|
||||||
|
self._initial_waiting_for_hosting_state = True
|
||||||
|
self._waiting_for_hosting_state = True
|
||||||
|
self._host_playlist_button: Optional[ba.Widget] = None
|
||||||
|
self._host_copy_button: Optional[ba.Widget] = None
|
||||||
|
self._host_connect_button: Optional[ba.Widget] = None
|
||||||
|
self._host_start_stop_button: Optional[ba.Widget] = None
|
||||||
|
self._get_tickets_button: Optional[ba.Widget] = None
|
||||||
|
self._ticket_count_text: Optional[ba.Widget] = None
|
||||||
|
self._showing_not_signed_in_screen = False
|
||||||
|
self._create_time = time.time()
|
||||||
|
self._last_action_send_time: Optional[float] = None
|
||||||
|
|
||||||
|
def on_activate(
|
||||||
|
self,
|
||||||
|
parent_widget: ba.Widget,
|
||||||
|
tab_button: ba.Widget,
|
||||||
|
region_width: float,
|
||||||
|
region_height: float,
|
||||||
|
region_left: float,
|
||||||
|
region_bottom: float,
|
||||||
|
) -> ba.Widget:
|
||||||
|
self._c_width = region_width
|
||||||
|
self._c_height = region_height - 20
|
||||||
|
self._container = ba.containerwidget(
|
||||||
|
parent=parent_widget,
|
||||||
|
position=(region_left,
|
||||||
|
region_bottom + (region_height - self._c_height) * 0.5),
|
||||||
|
size=(self._c_width, self._c_height),
|
||||||
|
background=False,
|
||||||
|
selection_loops_to_parent=True)
|
||||||
|
v = self._c_height - 30.0
|
||||||
|
self._join_sub_tab_text = ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
position=(self._c_width * 0.5 - 245, v - 13),
|
||||||
|
color=(0.6, 1.0, 0.6),
|
||||||
|
scale=1.3,
|
||||||
|
size=(200, 30),
|
||||||
|
maxwidth=250,
|
||||||
|
h_align='left',
|
||||||
|
v_align='center',
|
||||||
|
click_activate=True,
|
||||||
|
selectable=True,
|
||||||
|
autoselect=True,
|
||||||
|
on_activate_call=lambda: self._set_sub_tab(
|
||||||
|
SubTabType.JOIN,
|
||||||
|
playsound=True,
|
||||||
|
),
|
||||||
|
text=ba.Lstr(resource='gatherWindow.privatePartyJoinText'))
|
||||||
|
self._host_sub_tab_text = ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
position=(self._c_width * 0.5 + 45, v - 13),
|
||||||
|
color=(0.6, 1.0, 0.6),
|
||||||
|
scale=1.3,
|
||||||
|
size=(200, 30),
|
||||||
|
maxwidth=250,
|
||||||
|
h_align='left',
|
||||||
|
v_align='center',
|
||||||
|
click_activate=True,
|
||||||
|
selectable=True,
|
||||||
|
autoselect=True,
|
||||||
|
on_activate_call=lambda: self._set_sub_tab(
|
||||||
|
SubTabType.HOST,
|
||||||
|
playsound=True,
|
||||||
|
),
|
||||||
|
text=ba.Lstr(resource='gatherWindow.privatePartyHostText'))
|
||||||
|
ba.widget(edit=self._join_sub_tab_text, up_widget=tab_button)
|
||||||
|
ba.widget(edit=self._host_sub_tab_text,
|
||||||
|
left_widget=self._join_sub_tab_text,
|
||||||
|
up_widget=tab_button)
|
||||||
|
ba.widget(edit=self._join_sub_tab_text,
|
||||||
|
right_widget=self._host_sub_tab_text)
|
||||||
|
|
||||||
|
self._update_timer = ba.Timer(1.0,
|
||||||
|
ba.WeakCall(self._update),
|
||||||
|
repeat=True,
|
||||||
|
timetype=ba.TimeType.REAL)
|
||||||
|
|
||||||
|
# Get a new state query kicked off immediately and show nothing
|
||||||
|
# until it is back.
|
||||||
|
self._initial_waiting_for_hosting_state = True
|
||||||
|
self._last_hosting_state_query_time = None
|
||||||
|
self._last_action_send_time = None # So we don't ignore response.
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
self._set_sub_tab(self._state.sub_tab)
|
||||||
|
|
||||||
|
return self._container
|
||||||
|
|
||||||
|
def on_deactivate(self) -> None:
|
||||||
|
self._update_timer = None
|
||||||
|
|
||||||
|
def _update_currency_ui(self) -> None:
|
||||||
|
# Keep currency count up to date if applicable.
|
||||||
|
try:
|
||||||
|
t_str = str(_ba.get_account_ticket_count())
|
||||||
|
except Exception:
|
||||||
|
t_str = '?'
|
||||||
|
if self._get_tickets_button:
|
||||||
|
ba.buttonwidget(edit=self._get_tickets_button,
|
||||||
|
label=ba.charstr(ba.SpecialChar.TICKET) + t_str)
|
||||||
|
if self._ticket_count_text:
|
||||||
|
ba.textwidget(edit=self._ticket_count_text,
|
||||||
|
text=ba.charstr(ba.SpecialChar.TICKET) + t_str)
|
||||||
|
|
||||||
|
def _update(self) -> None:
|
||||||
|
"""Periodic updating."""
|
||||||
|
|
||||||
|
now = ba.time(ba.TimeType.REAL)
|
||||||
|
|
||||||
|
self._update_currency_ui()
|
||||||
|
|
||||||
|
if self._state.sub_tab is SubTabType.HOST:
|
||||||
|
|
||||||
|
# If we're not signed in, just refresh to show that.
|
||||||
|
if (_ba.get_account_state() != 'signed_in'
|
||||||
|
and self._showing_not_signed_in_screen):
|
||||||
|
self._refresh_sub_tab()
|
||||||
|
else:
|
||||||
|
|
||||||
|
# Query an updated state periodically.
|
||||||
|
if (self._last_hosting_state_query_time is None
|
||||||
|
or now - self._last_hosting_state_query_time > 15.0):
|
||||||
|
self._debug_server_comm('querying private party state')
|
||||||
|
if _ba.get_account_state() == 'signed_in':
|
||||||
|
_ba.add_transaction(
|
||||||
|
{'type': 'PRIVATE_PARTY_QUERY'},
|
||||||
|
callback=ba.WeakCall(
|
||||||
|
self._hosting_state_idle_response),
|
||||||
|
)
|
||||||
|
_ba.run_transactions()
|
||||||
|
else:
|
||||||
|
self._hosting_state_idle_response(None)
|
||||||
|
self._last_hosting_state_query_time = now
|
||||||
|
|
||||||
|
def _hosting_state_idle_response(self,
|
||||||
|
result: Optional[Dict[str, Any]]) -> None:
|
||||||
|
|
||||||
|
# This simply passes through to our standard response handler.
|
||||||
|
# The one exception is if we've recently sent an action to the
|
||||||
|
# server (start/stop hosting/etc.) In that case we want to ignore
|
||||||
|
# idle background updates and wait for the response to our action.
|
||||||
|
# (this keeps the button showing 'one moment...' until the change
|
||||||
|
# takes effect, etc.)
|
||||||
|
if (self._last_action_send_time is not None
|
||||||
|
and time.time() - self._last_action_send_time < 5.0):
|
||||||
|
self._debug_server_comm('ignoring private party state response'
|
||||||
|
' due to recent action')
|
||||||
|
return
|
||||||
|
self._hosting_state_response(result)
|
||||||
|
|
||||||
|
def _hosting_state_response(self, result: Optional[Dict[str,
|
||||||
|
Any]]) -> None:
|
||||||
|
state: Optional[HostingState] = None
|
||||||
|
if result is not None:
|
||||||
|
self._debug_server_comm('got private party state response')
|
||||||
|
try:
|
||||||
|
state = dataclass_from_dict(HostingState, result)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self._debug_server_comm('private party state response errored')
|
||||||
|
|
||||||
|
# Hmm I guess let's just ignore failed responses?...
|
||||||
|
# Or should we show some sort of error state to the user?...
|
||||||
|
if result is None or state is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._initial_waiting_for_hosting_state = False
|
||||||
|
self._waiting_for_hosting_state = False
|
||||||
|
self._hostingstate = state
|
||||||
|
self._refresh_sub_tab()
|
||||||
|
|
||||||
|
def _set_sub_tab(self, value: SubTabType, playsound: bool = False) -> None:
|
||||||
|
assert self._container
|
||||||
|
if playsound:
|
||||||
|
ba.playsound(ba.getsound('click01'))
|
||||||
|
|
||||||
|
# If switching from join to host, do a fresh state query.
|
||||||
|
if self._state.sub_tab is SubTabType.JOIN and value is SubTabType.HOST:
|
||||||
|
self._last_hosting_state_query_time = None
|
||||||
|
self._initial_waiting_for_hosting_state = True
|
||||||
|
self._last_action_send_time = None # So we don't ignore response.
|
||||||
|
self._update()
|
||||||
|
|
||||||
|
self._state.sub_tab = value
|
||||||
|
active_color = (0.6, 1.0, 0.6)
|
||||||
|
inactive_color = (0.5, 0.4, 0.5)
|
||||||
|
ba.textwidget(
|
||||||
|
edit=self._join_sub_tab_text,
|
||||||
|
color=active_color if value is SubTabType.JOIN else inactive_color)
|
||||||
|
ba.textwidget(
|
||||||
|
edit=self._host_sub_tab_text,
|
||||||
|
color=active_color if value is SubTabType.HOST else inactive_color)
|
||||||
|
|
||||||
|
self._refresh_sub_tab()
|
||||||
|
|
||||||
|
# Kick off an update to get any needed messages sent/etc.
|
||||||
|
ba.pushcall(self._update)
|
||||||
|
|
||||||
|
def _selwidgets(self) -> List[Optional[ba.Widget]]:
|
||||||
|
"""An indexed list of widgets we can use for saving/restoring sel."""
|
||||||
|
return [
|
||||||
|
self._host_playlist_button, self._host_copy_button,
|
||||||
|
self._host_connect_button, self._host_start_stop_button,
|
||||||
|
self._get_tickets_button
|
||||||
|
]
|
||||||
|
|
||||||
|
def _refresh_sub_tab(self) -> None:
|
||||||
|
assert self._container
|
||||||
|
|
||||||
|
# Store an index for our current selection so we can
|
||||||
|
# reselect the equivalent recreated widget if possible.
|
||||||
|
selindex: Optional[int] = None
|
||||||
|
selchild = self._container.get_selected_child()
|
||||||
|
if selchild is not None:
|
||||||
|
try:
|
||||||
|
selindex = self._selwidgets().index(selchild)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Clear anything existing in the old sub-tab.
|
||||||
|
for widget in self._container.get_children():
|
||||||
|
if widget and widget not in {
|
||||||
|
self._host_sub_tab_text,
|
||||||
|
self._join_sub_tab_text,
|
||||||
|
}:
|
||||||
|
widget.delete()
|
||||||
|
|
||||||
|
if self._state.sub_tab is SubTabType.JOIN:
|
||||||
|
self._build_join_tab()
|
||||||
|
elif self._state.sub_tab is SubTabType.HOST:
|
||||||
|
self._build_host_tab()
|
||||||
|
else:
|
||||||
|
raise RuntimeError('Invalid state.')
|
||||||
|
|
||||||
|
# Select the new equivalent widget if there is one.
|
||||||
|
if selindex is not None:
|
||||||
|
selwidget = self._selwidgets()[selindex]
|
||||||
|
if selwidget:
|
||||||
|
ba.containerwidget(edit=self._container,
|
||||||
|
selected_child=selwidget)
|
||||||
|
|
||||||
|
def _build_join_tab(self) -> None:
|
||||||
|
|
||||||
|
ba.textwidget(parent=self._container,
|
||||||
|
position=(self._c_width * 0.5, self._c_height - 140),
|
||||||
|
color=(0.5, 0.46, 0.5),
|
||||||
|
scale=1.5,
|
||||||
|
size=(0, 0),
|
||||||
|
maxwidth=250,
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
text=ba.Lstr(resource='gatherWindow.partyCodeText'))
|
||||||
|
|
||||||
|
self._join_party_code_text = ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
position=(self._c_width * 0.5 - 150, self._c_height - 250),
|
||||||
|
flatness=1.0,
|
||||||
|
scale=1.5,
|
||||||
|
size=(300, 50),
|
||||||
|
editable=True,
|
||||||
|
description=ba.Lstr(resource='gatherWindow.partyCodeText'),
|
||||||
|
autoselect=True,
|
||||||
|
maxwidth=250,
|
||||||
|
h_align='left',
|
||||||
|
v_align='center',
|
||||||
|
text='')
|
||||||
|
btn = ba.buttonwidget(parent=self._container,
|
||||||
|
size=(300, 70),
|
||||||
|
label=ba.Lstr(resource='gatherWindow.'
|
||||||
|
'manualConnectText'),
|
||||||
|
position=(self._c_width * 0.5 - 150,
|
||||||
|
self._c_height - 350),
|
||||||
|
on_activate_call=self._connect_press,
|
||||||
|
autoselect=True)
|
||||||
|
ba.textwidget(edit=self._join_party_code_text,
|
||||||
|
on_return_press_call=btn.activate)
|
||||||
|
|
||||||
|
def _on_get_tickets_press(self) -> None:
|
||||||
|
|
||||||
|
if self._waiting_for_hosting_state:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Bring up get-tickets window and then kill ourself (we're on the
|
||||||
|
# overlay layer so we'd show up above it).
|
||||||
|
getcurrency.GetCurrencyWindow(modal=True,
|
||||||
|
origin_widget=self._get_tickets_button)
|
||||||
|
# self._transition_out()
|
||||||
|
|
||||||
|
def _build_host_tab(self) -> None:
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
|
|
||||||
|
if _ba.get_account_state() != 'signed_in':
|
||||||
|
ba.textwidget(parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=200,
|
||||||
|
scale=0.8,
|
||||||
|
color=(0.6, 0.56, 0.6),
|
||||||
|
position=(self._c_width * 0.5, self._c_height * 0.5),
|
||||||
|
text=ba.Lstr(resource='notSignedInErrorText'))
|
||||||
|
self._showing_not_signed_in_screen = True
|
||||||
|
return
|
||||||
|
self._showing_not_signed_in_screen = False
|
||||||
|
|
||||||
|
# At first we don't want to show anything until we've gotten a state.
|
||||||
|
if self._initial_waiting_for_hosting_state:
|
||||||
|
ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=200,
|
||||||
|
scale=0.8,
|
||||||
|
color=(0.6, 0.56, 0.6),
|
||||||
|
position=(self._c_width * 0.5, self._c_height * 0.5),
|
||||||
|
text=ba.Lstr(
|
||||||
|
value='${A}...',
|
||||||
|
subs=[('${A}', ba.Lstr(resource='store.loadingText'))],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# If we're not currently hosting and hosting requires tickets,
|
||||||
|
# Show our count (possibly with a link to purchase more).
|
||||||
|
if (self._hostingstate.party_code is None
|
||||||
|
and self._hostingstate.tickets_to_host_now != 0):
|
||||||
|
if not ba.app.ui.use_toolbars:
|
||||||
|
if ba.app.allow_ticket_purchases:
|
||||||
|
self._get_tickets_button = ba.buttonwidget(
|
||||||
|
parent=self._container,
|
||||||
|
position=(self._c_width - 210 + 125,
|
||||||
|
self._c_height - 44),
|
||||||
|
autoselect=True,
|
||||||
|
scale=0.6,
|
||||||
|
size=(120, 60),
|
||||||
|
textcolor=(0.2, 1, 0.2),
|
||||||
|
label=ba.charstr(ba.SpecialChar.TICKET),
|
||||||
|
color=(0.65, 0.5, 0.8),
|
||||||
|
on_activate_call=self._on_get_tickets_press)
|
||||||
|
else:
|
||||||
|
self._ticket_count_text = ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
scale=0.6,
|
||||||
|
position=(self._c_width - 210 + 125,
|
||||||
|
self._c_height - 44),
|
||||||
|
color=(0.2, 1, 0.2),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center')
|
||||||
|
# Set initial ticket count.
|
||||||
|
self._update_currency_ui()
|
||||||
|
|
||||||
|
v = self._c_height - 90
|
||||||
|
if self._hostingstate.party_code is None:
|
||||||
|
ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=self._c_width * 0.9,
|
||||||
|
scale=0.7,
|
||||||
|
flatness=1.0,
|
||||||
|
color=(0.5, 0.46, 0.5),
|
||||||
|
position=(self._c_width * 0.5, v),
|
||||||
|
text=ba.Lstr(
|
||||||
|
resource='gatherWindow.privatePartyCloudDescriptionText'))
|
||||||
|
|
||||||
|
v -= 100
|
||||||
|
if self._hostingstate.party_code is None:
|
||||||
|
# We've got no current party running; show options to set one up.
|
||||||
|
ba.textwidget(parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='right',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=200,
|
||||||
|
scale=0.8,
|
||||||
|
color=(0.6, 0.56, 0.6),
|
||||||
|
position=(self._c_width * 0.5 - 210, v),
|
||||||
|
text=ba.Lstr(resource='playlistText'))
|
||||||
|
self._host_playlist_button = ba.buttonwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(400, 70),
|
||||||
|
color=(0.6, 0.5, 0.6),
|
||||||
|
textcolor=(0.8, 0.75, 0.8),
|
||||||
|
label='Default Free-For-All Playlist',
|
||||||
|
on_activate_call=lambda: ba.screenmessage(
|
||||||
|
'TODO: WIRE UP PLAYLIST SELECTION'),
|
||||||
|
position=(self._c_width * 0.5 - 200, v - 35),
|
||||||
|
up_widget=self._host_sub_tab_text,
|
||||||
|
autoselect=True)
|
||||||
|
else:
|
||||||
|
# We've got a current party; show its info.
|
||||||
|
ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=600,
|
||||||
|
scale=0.9,
|
||||||
|
color=(0.7, 0.64, 0.7),
|
||||||
|
position=(self._c_width * 0.5, v + 90),
|
||||||
|
text=ba.Lstr(resource='gatherWindow.partyServerRunningText'))
|
||||||
|
ba.textwidget(parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=600,
|
||||||
|
scale=0.7,
|
||||||
|
color=(0.7, 0.64, 0.7),
|
||||||
|
position=(self._c_width * 0.5, v + 50),
|
||||||
|
text=ba.Lstr(resource='gatherWindow.partyCodeText'))
|
||||||
|
ba.textwidget(parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
scale=2.0,
|
||||||
|
color=(0.0, 1.0, 0.0),
|
||||||
|
position=(self._c_width * 0.5, v + 10),
|
||||||
|
text=self._hostingstate.party_code)
|
||||||
|
|
||||||
|
# Also action buttons to copy it and connect to it.
|
||||||
|
if ba.clipboard_is_supported():
|
||||||
|
cbtnoffs = 10
|
||||||
|
self._host_copy_button = ba.buttonwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(140, 40),
|
||||||
|
color=(0.6, 0.5, 0.6),
|
||||||
|
textcolor=(0.8, 0.75, 0.8),
|
||||||
|
label=ba.Lstr(resource='gatherWindow.copyCodeText'),
|
||||||
|
on_activate_call=self._host_copy_press,
|
||||||
|
position=(self._c_width * 0.5 - 150, v - 70),
|
||||||
|
autoselect=True)
|
||||||
|
else:
|
||||||
|
cbtnoffs = -70
|
||||||
|
self._host_connect_button = ba.buttonwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(140, 40),
|
||||||
|
color=(0.6, 0.5, 0.6),
|
||||||
|
textcolor=(0.8, 0.75, 0.8),
|
||||||
|
label=ba.Lstr(resource='gatherWindow.manualConnectText'),
|
||||||
|
on_activate_call=self._host_connect_press,
|
||||||
|
position=(self._c_width * 0.5 + cbtnoffs, v - 70),
|
||||||
|
autoselect=True)
|
||||||
|
|
||||||
|
v -= 120
|
||||||
|
|
||||||
|
# Line above the main action button:
|
||||||
|
|
||||||
|
# If hosting is unavailable, show the associated reason.
|
||||||
|
if self._hostingstate.unavailable_error is not None:
|
||||||
|
ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=self._c_width * 0.9,
|
||||||
|
scale=0.7,
|
||||||
|
flatness=1.0,
|
||||||
|
color=(1.0, 0.0, 0.0),
|
||||||
|
position=(self._c_width * 0.5, v),
|
||||||
|
text=ba.Lstr(translate=('serverResponses',
|
||||||
|
self._hostingstate.unavailable_error)))
|
||||||
|
elif self._hostingstate.free_host_minutes_remaining is not None:
|
||||||
|
# If we've been pre-approved to start/stop for free, show that.
|
||||||
|
ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=self._c_width * 0.9,
|
||||||
|
scale=0.7,
|
||||||
|
flatness=1.0,
|
||||||
|
color=((0.7, 0.64, 0.7) if self._hostingstate.party_code else
|
||||||
|
(0.0, 1.0, 0.0)),
|
||||||
|
position=(self._c_width * 0.5, v),
|
||||||
|
text=ba.Lstr(
|
||||||
|
resource='gatherWindow.startStopHostingMinutesText',
|
||||||
|
subs=[(
|
||||||
|
'${MINUTES}',
|
||||||
|
f'{self._hostingstate.free_host_minutes_remaining:.0f}'
|
||||||
|
)]))
|
||||||
|
else:
|
||||||
|
# Otherwise tell whether the free cloud server is available
|
||||||
|
# or will be at some point.
|
||||||
|
if self._hostingstate.party_code is None:
|
||||||
|
if self._hostingstate.tickets_to_host_now == 0:
|
||||||
|
ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=self._c_width * 0.9,
|
||||||
|
scale=0.7,
|
||||||
|
flatness=1.0,
|
||||||
|
color=(0.0, 1.0, 0.0),
|
||||||
|
position=(self._c_width * 0.5, v),
|
||||||
|
text=ba.Lstr(
|
||||||
|
resource=
|
||||||
|
'gatherWindow.freeCloudServerAvailableNowText'))
|
||||||
|
else:
|
||||||
|
if self._hostingstate.minutes_until_free_host is None:
|
||||||
|
ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=self._c_width * 0.9,
|
||||||
|
scale=0.7,
|
||||||
|
flatness=1.0,
|
||||||
|
color=(1.0, 0.6, 0.0),
|
||||||
|
position=(self._c_width * 0.5, v),
|
||||||
|
text=ba.Lstr(
|
||||||
|
resource=
|
||||||
|
'gatherWindow.freeCloudServerNotAvailableText')
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
availmins = self._hostingstate.minutes_until_free_host
|
||||||
|
ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=self._c_width * 0.9,
|
||||||
|
scale=0.7,
|
||||||
|
flatness=1.0,
|
||||||
|
color=(1.0, 0.6, 0.0),
|
||||||
|
position=(self._c_width * 0.5, v),
|
||||||
|
text=ba.Lstr(resource='gatherWindow.'
|
||||||
|
'freeCloudServerAvailableMinutesText',
|
||||||
|
subs=[('${MINUTES}',
|
||||||
|
f'{availmins:.0f}')]))
|
||||||
|
|
||||||
|
v -= 100
|
||||||
|
|
||||||
|
if self._waiting_for_hosting_state:
|
||||||
|
btnlabel = ba.Lstr(resource='oneMomentText')
|
||||||
|
else:
|
||||||
|
if self._hostingstate.unavailable_error is not None:
|
||||||
|
btnlabel = ba.Lstr(
|
||||||
|
resource='gatherWindow.hostingUnavailableText')
|
||||||
|
elif self._hostingstate.party_code is None:
|
||||||
|
ticon = _ba.charstr(ba.SpecialChar.TICKET)
|
||||||
|
nowtickets = self._hostingstate.tickets_to_host_now
|
||||||
|
if nowtickets > 0:
|
||||||
|
btnlabel = ba.Lstr(
|
||||||
|
resource='gatherWindow.startHostingPaidText',
|
||||||
|
subs=[('${COST}', f'{ticon}{nowtickets}')])
|
||||||
|
else:
|
||||||
|
btnlabel = ba.Lstr(
|
||||||
|
resource='gatherWindow.startHostingText')
|
||||||
|
else:
|
||||||
|
btnlabel = ba.Lstr(resource='gatherWindow.stopHostingText')
|
||||||
|
|
||||||
|
self._host_start_stop_button = ba.buttonwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(400, 80),
|
||||||
|
color=((0.6, 0.6, 0.6)
|
||||||
|
if self._hostingstate.unavailable_error is not None else
|
||||||
|
(0.5, 1.0,
|
||||||
|
0.5) if self._waiting_for_hosting_state else None),
|
||||||
|
enable_sound=False,
|
||||||
|
label=btnlabel,
|
||||||
|
textcolor=((0.7, 0.7, 0.7)
|
||||||
|
if self._hostingstate.unavailable_error else None),
|
||||||
|
position=(self._c_width * 0.5 - 200, v),
|
||||||
|
on_activate_call=self._host_button_press,
|
||||||
|
autoselect=True)
|
||||||
|
|
||||||
|
def _host_copy_press(self) -> None:
|
||||||
|
assert self._hostingstate.party_code is not None
|
||||||
|
ba.clipboard_set_text(self._hostingstate.party_code)
|
||||||
|
ba.screenmessage(ba.Lstr(resource='gatherWindow.copyCodeConfirmText'))
|
||||||
|
|
||||||
|
def _host_connect_press(self) -> None:
|
||||||
|
assert self._hostingstate.party_code is not None
|
||||||
|
self._connect_to_party_code(self._hostingstate.party_code)
|
||||||
|
|
||||||
|
def _debug_server_comm(self, msg: str) -> None:
|
||||||
|
if DEBUG_SERVER_COMMUNICATION:
|
||||||
|
print(f'PPTABCOM: {msg} at time '
|
||||||
|
f'{time.time()-self._create_time:.2f}')
|
||||||
|
|
||||||
|
def _connect_to_party_code(self, code: str) -> None:
|
||||||
|
self._debug_server_comm('sending private party connect')
|
||||||
|
_ba.add_transaction(
|
||||||
|
{
|
||||||
|
'type': 'PRIVATE_PARTY_CONNECT',
|
||||||
|
'code': code
|
||||||
|
},
|
||||||
|
callback=ba.WeakCall(self._connect_response),
|
||||||
|
)
|
||||||
|
_ba.run_transactions()
|
||||||
|
|
||||||
|
def _host_button_press(self) -> None:
|
||||||
|
if self._waiting_for_hosting_state:
|
||||||
|
return
|
||||||
|
|
||||||
|
if _ba.get_account_state() != 'signed_in':
|
||||||
|
ba.screenmessage(ba.Lstr(resource='notSignedInErrorText'))
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
self._refresh_sub_tab()
|
||||||
|
return
|
||||||
|
|
||||||
|
if self._hostingstate.unavailable_error is not None:
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
|
||||||
|
# If we're not hosting, start.
|
||||||
|
if self._hostingstate.party_code is None:
|
||||||
|
|
||||||
|
# If there's a ticket cost, make sure we have enough tickets.
|
||||||
|
if self._hostingstate.tickets_to_host_now > 0:
|
||||||
|
ticket_count: Optional[int]
|
||||||
|
try:
|
||||||
|
ticket_count = _ba.get_account_ticket_count()
|
||||||
|
except Exception:
|
||||||
|
# FIXME: should add a ba.NotSignedInError we can use here.
|
||||||
|
ticket_count = None
|
||||||
|
ticket_cost = self._hostingstate.tickets_to_host_now
|
||||||
|
if ticket_count is not None and ticket_count < ticket_cost:
|
||||||
|
getcurrency.show_get_tickets_prompt()
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
self._last_action_send_time = time.time()
|
||||||
|
_ba.add_transaction({'type': 'PRIVATE_PARTY_START'},
|
||||||
|
callback=ba.WeakCall(
|
||||||
|
self._hosting_state_response))
|
||||||
|
_ba.run_transactions()
|
||||||
|
|
||||||
|
else:
|
||||||
|
self._last_action_send_time = time.time()
|
||||||
|
_ba.add_transaction({'type': 'PRIVATE_PARTY_STOP'},
|
||||||
|
callback=ba.WeakCall(
|
||||||
|
self._hosting_state_response))
|
||||||
|
_ba.run_transactions()
|
||||||
|
ba.playsound(ba.getsound('click01'))
|
||||||
|
|
||||||
|
self._waiting_for_hosting_state = True
|
||||||
|
self._refresh_sub_tab()
|
||||||
|
|
||||||
|
def _connect_press(self) -> None:
|
||||||
|
code: Optional[str] = None
|
||||||
|
if self._join_party_code_text:
|
||||||
|
code = cast(str, ba.textwidget(query=self._join_party_code_text))
|
||||||
|
if not code:
|
||||||
|
ba.screenmessage(
|
||||||
|
ba.Lstr(resource='internal.invalidAddressErrorText'),
|
||||||
|
color=(1, 0, 0))
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
self._connect_to_party_code(code)
|
||||||
|
|
||||||
|
def _connect_response(self, result: Optional[Dict[str, Any]]) -> None:
|
||||||
|
try:
|
||||||
|
if result is None:
|
||||||
|
raise RuntimeError()
|
||||||
|
cresult = dataclass_from_dict(ConnectResult, result)
|
||||||
|
if cresult.error is not None:
|
||||||
|
self._debug_server_comm('got error connect response')
|
||||||
|
ba.screenmessage(
|
||||||
|
ba.Lstr(translate=('serverResponses', cresult.error)),
|
||||||
|
(1, 0, 0))
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
return
|
||||||
|
self._debug_server_comm('got valid connect response')
|
||||||
|
assert cresult.addr is not None and cresult.port is not None
|
||||||
|
_ba.connect_to_party(cresult.addr, port=cresult.port)
|
||||||
|
except Exception:
|
||||||
|
self._debug_server_comm('got connect response error')
|
||||||
|
ba.playsound(ba.getsound('error'))
|
||||||
|
|
||||||
|
def save_state(self) -> None:
|
||||||
|
ba.app.ui.window_states[type(self)] = copy.deepcopy(self._state)
|
||||||
|
|
||||||
|
def restore_state(self) -> None:
|
||||||
|
state = ba.app.ui.window_states.get(type(self))
|
||||||
|
if state is None:
|
||||||
|
state = State()
|
||||||
|
assert isinstance(state, State)
|
||||||
|
self._state = state
|
||||||
@ -14,7 +14,7 @@ from typing import TYPE_CHECKING, cast
|
|||||||
|
|
||||||
import _ba
|
import _ba
|
||||||
import ba
|
import ba
|
||||||
from bastd.ui.gather.bases import GatherTab
|
from bastd.ui.gather import GatherTab
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Callable, Any, Optional, Dict, Union, Tuple, List
|
from typing import Callable, Any, Optional, Dict, Union, Tuple, List
|
||||||
@ -448,7 +448,7 @@ class PublicGatherTab(GatherTab):
|
|||||||
# display these immediately when our UI comes back up which should
|
# display these immediately when our UI comes back up which should
|
||||||
# be enough to make things feel nice and crisp while we do a full
|
# be enough to make things feel nice and crisp while we do a full
|
||||||
# server re-query or whatnot.
|
# server re-query or whatnot.
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = State(
|
ba.app.ui.window_states[type(self)] = State(
|
||||||
sub_tab=self._sub_tab,
|
sub_tab=self._sub_tab,
|
||||||
parties=[(i, copy.copy(p)) for i, p in self._parties_sorted[:40]],
|
parties=[(i, copy.copy(p)) for i, p in self._parties_sorted[:40]],
|
||||||
next_entry_index=self._next_entry_index,
|
next_entry_index=self._next_entry_index,
|
||||||
@ -457,7 +457,7 @@ class PublicGatherTab(GatherTab):
|
|||||||
have_valid_server_list=self._have_valid_server_list)
|
have_valid_server_list=self._have_valid_server_list)
|
||||||
|
|
||||||
def restore_state(self) -> None:
|
def restore_state(self) -> None:
|
||||||
state = ba.app.ui.window_states.get(self.__class__.__name__)
|
state = ba.app.ui.window_states.get(type(self))
|
||||||
if state is None:
|
if state is None:
|
||||||
state = State()
|
state = State()
|
||||||
assert isinstance(state, State)
|
assert isinstance(state, State)
|
||||||
@ -544,9 +544,8 @@ class PublicGatherTab(GatherTab):
|
|||||||
position=(270, v + 13),
|
position=(270, v + 13),
|
||||||
maxwidth=150,
|
maxwidth=150,
|
||||||
scale=0.8,
|
scale=0.8,
|
||||||
color=(0.5, 0.5, 0.5),
|
color=(0.5, 0.46, 0.5),
|
||||||
flatness=1.0,
|
flatness=1.0,
|
||||||
shadow=0.0,
|
|
||||||
h_align='right',
|
h_align='right',
|
||||||
v_align='center')
|
v_align='center')
|
||||||
|
|
||||||
@ -556,9 +555,8 @@ class PublicGatherTab(GatherTab):
|
|||||||
position=(90, v - 8),
|
position=(90, v - 8),
|
||||||
maxwidth=60,
|
maxwidth=60,
|
||||||
scale=0.6,
|
scale=0.6,
|
||||||
color=(0.5, 0.5, 0.5),
|
color=(0.5, 0.46, 0.5),
|
||||||
flatness=1.0,
|
flatness=1.0,
|
||||||
shadow=0.0,
|
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center')
|
v_align='center')
|
||||||
ba.textwidget(text=ba.Lstr(resource='gatherWindow.partySizeText'),
|
ba.textwidget(text=ba.Lstr(resource='gatherWindow.partySizeText'),
|
||||||
@ -567,9 +565,8 @@ class PublicGatherTab(GatherTab):
|
|||||||
position=(755, v - 8),
|
position=(755, v - 8),
|
||||||
maxwidth=60,
|
maxwidth=60,
|
||||||
scale=0.6,
|
scale=0.6,
|
||||||
color=(0.5, 0.5, 0.5),
|
color=(0.5, 0.46, 0.5),
|
||||||
flatness=1.0,
|
flatness=1.0,
|
||||||
shadow=0.0,
|
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center')
|
v_align='center')
|
||||||
ba.textwidget(text=ba.Lstr(resource='gatherWindow.pingText'),
|
ba.textwidget(text=ba.Lstr(resource='gatherWindow.pingText'),
|
||||||
@ -578,9 +575,8 @@ class PublicGatherTab(GatherTab):
|
|||||||
position=(825, v - 8),
|
position=(825, v - 8),
|
||||||
maxwidth=60,
|
maxwidth=60,
|
||||||
scale=0.6,
|
scale=0.6,
|
||||||
color=(0.5, 0.5, 0.5),
|
color=(0.5, 0.46, 0.5),
|
||||||
flatness=1.0,
|
flatness=1.0,
|
||||||
shadow=0.0,
|
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center')
|
v_align='center')
|
||||||
v -= sub_scroll_height + 23
|
v -= sub_scroll_height + 23
|
||||||
@ -617,6 +613,20 @@ class PublicGatherTab(GatherTab):
|
|||||||
v -= 25
|
v -= 25
|
||||||
is_public_enabled = _ba.get_public_party_enabled()
|
is_public_enabled = _ba.get_public_party_enabled()
|
||||||
v -= 30
|
v -= 30
|
||||||
|
|
||||||
|
ba.textwidget(
|
||||||
|
parent=self._container,
|
||||||
|
size=(0, 0),
|
||||||
|
h_align='center',
|
||||||
|
v_align='center',
|
||||||
|
maxwidth=c_width * 0.9,
|
||||||
|
scale=0.7,
|
||||||
|
flatness=1.0,
|
||||||
|
color=(0.5, 0.46, 0.5),
|
||||||
|
position=(region_width * 0.5, v + 10),
|
||||||
|
text=ba.Lstr(resource='gatherWindow.publicHostRouterConfigText'))
|
||||||
|
v -= 30
|
||||||
|
|
||||||
party_name_text = ba.Lstr(
|
party_name_text = ba.Lstr(
|
||||||
resource='gatherWindow.partyNameText',
|
resource='gatherWindow.partyNameText',
|
||||||
fallback_resource='editGameListWindow.nameText')
|
fallback_resource='editGameListWindow.nameText')
|
||||||
@ -710,11 +720,10 @@ class PublicGatherTab(GatherTab):
|
|||||||
size=(0, 0),
|
size=(0, 0),
|
||||||
scale=0.7,
|
scale=0.7,
|
||||||
flatness=1.0,
|
flatness=1.0,
|
||||||
shadow=0.0,
|
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='top',
|
v_align='top',
|
||||||
maxwidth=c_width,
|
maxwidth=c_width * 0.9,
|
||||||
color=(0.6, 0.6, 0.6),
|
color=(0.6, 0.56, 0.6),
|
||||||
position=(c_width * 0.5, v))
|
position=(c_width * 0.5, v))
|
||||||
v -= 90
|
v -= 90
|
||||||
ba.textwidget(
|
ba.textwidget(
|
||||||
@ -723,11 +732,10 @@ class PublicGatherTab(GatherTab):
|
|||||||
size=(0, 0),
|
size=(0, 0),
|
||||||
scale=0.7,
|
scale=0.7,
|
||||||
flatness=1.0,
|
flatness=1.0,
|
||||||
shadow=0.0,
|
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
maxwidth=c_width * 0.9,
|
maxwidth=c_width * 0.9,
|
||||||
color=ba.app.ui.infotextcolor,
|
color=(0.5, 0.46, 0.5),
|
||||||
position=(c_width * 0.5, v))
|
position=(c_width * 0.5, v))
|
||||||
|
|
||||||
# If public sharing is already on,
|
# If public sharing is already on,
|
||||||
@ -750,8 +758,6 @@ class PublicGatherTab(GatherTab):
|
|||||||
self._have_valid_server_list = True
|
self._have_valid_server_list = True
|
||||||
parties_in = result['l']
|
parties_in = result['l']
|
||||||
|
|
||||||
# parties_in.reverse()
|
|
||||||
|
|
||||||
assert isinstance(parties_in, list)
|
assert isinstance(parties_in, list)
|
||||||
self._pending_party_infos += parties_in
|
self._pending_party_infos += parties_in
|
||||||
|
|
||||||
@ -1060,7 +1066,6 @@ class PublicGatherTab(GatherTab):
|
|||||||
callback=ba.WeakCall(self._on_public_party_query_result))
|
callback=ba.WeakCall(self._on_public_party_query_result))
|
||||||
_ba.run_transactions()
|
_ba.run_transactions()
|
||||||
else:
|
else:
|
||||||
# This will kick us over to a 'not signed in' message.
|
|
||||||
self._on_public_party_query_result(None)
|
self._on_public_party_query_result(None)
|
||||||
|
|
||||||
def _ping_parties_periodically(self) -> None:
|
def _ping_parties_periodically(self) -> None:
|
||||||
|
|||||||
@ -316,7 +316,7 @@ class KioskWindow(ba.Window):
|
|||||||
repeat=True)
|
repeat=True)
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__)
|
sel_name = ba.app.ui.window_states.get(type(self))
|
||||||
sel: Optional[ba.Widget]
|
sel: Optional[ba.Widget]
|
||||||
if sel_name == 'b1':
|
if sel_name == 'b1':
|
||||||
sel = self._b1
|
sel = self._b1
|
||||||
@ -355,7 +355,7 @@ class KioskWindow(ba.Window):
|
|||||||
sel_name = 'b7'
|
sel_name = 'b7'
|
||||||
else:
|
else:
|
||||||
sel_name = 'b1'
|
sel_name = 'b1'
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = sel_name
|
ba.app.ui.window_states[type(self)] = sel_name
|
||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
# Kiosk-mode is designed to be used signed-out... try for force
|
# Kiosk-mode is designed to be used signed-out... try for force
|
||||||
|
|||||||
@ -540,13 +540,13 @@ class PlayWindow(ba.Window):
|
|||||||
sel_name = 'Back'
|
sel_name = 'Back'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized selection {sel}')
|
raise ValueError(f'unrecognized selection {sel}')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = sel_name
|
ba.app.ui.window_states[type(self)] = sel_name
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self}.')
|
ba.print_exception(f'Error saving state for {self}.')
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
try:
|
try:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__)
|
sel_name = ba.app.ui.window_states.get(type(self))
|
||||||
if sel_name == 'Team Games':
|
if sel_name == 'Team Games':
|
||||||
sel = self._teams_button
|
sel = self._teams_button
|
||||||
elif sel_name == 'Co-op Games':
|
elif sel_name == 'Co-op Games':
|
||||||
|
|||||||
@ -628,13 +628,13 @@ class PlaylistBrowserWindow(ba.Window):
|
|||||||
sel_name = 'Scroll'
|
sel_name = 'Scroll'
|
||||||
else:
|
else:
|
||||||
raise Exception('unrecognized selected widget')
|
raise Exception('unrecognized selected widget')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = sel_name
|
ba.app.ui.window_states[type(self)] = sel_name
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self}.')
|
ba.print_exception(f'Error saving state for {self}.')
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
try:
|
try:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__)
|
sel_name = ba.app.ui.window_states.get(type(self))
|
||||||
if sel_name == 'Back':
|
if sel_name == 'Back':
|
||||||
sel = self._back_button
|
sel = self._back_button
|
||||||
elif sel_name == 'Scroll':
|
elif sel_name == 'Scroll':
|
||||||
|
|||||||
@ -347,13 +347,13 @@ class ProfileBrowserWindow(ba.Window):
|
|||||||
sel_name = 'Scroll'
|
sel_name = 'Scroll'
|
||||||
else:
|
else:
|
||||||
sel_name = 'Back'
|
sel_name = 'Back'
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = sel_name
|
ba.app.ui.window_states[type(self)] = sel_name
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self}.')
|
ba.print_exception(f'Error saving state for {self}.')
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
try:
|
try:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__)
|
sel_name = ba.app.ui.window_states.get(type(self))
|
||||||
if sel_name == 'Scroll':
|
if sel_name == 'Scroll':
|
||||||
sel = self._scrollwidget
|
sel = self._scrollwidget
|
||||||
elif sel_name == 'New':
|
elif sel_name == 'New':
|
||||||
|
|||||||
@ -626,16 +626,14 @@ class AdvancedSettingsWindow(ba.Window):
|
|||||||
sel_name = 'Back'
|
sel_name = 'Back'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized selection \'{sel}\'')
|
raise ValueError(f'unrecognized selection \'{sel}\'')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = {
|
ba.app.ui.window_states[type(self)] = {'sel_name': sel_name}
|
||||||
'sel_name': sel_name
|
|
||||||
}
|
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self.__class__}')
|
ba.print_exception(f'Error saving state for {self.__class__}')
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
try:
|
try:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__,
|
sel_name = ba.app.ui.window_states.get(type(self),
|
||||||
{}).get('sel_name')
|
{}).get('sel_name')
|
||||||
if sel_name == 'Back':
|
if sel_name == 'Back':
|
||||||
sel = self._back_button
|
sel = self._back_button
|
||||||
|
|||||||
@ -256,15 +256,13 @@ class AllSettingsWindow(ba.Window):
|
|||||||
sel_name = 'Back'
|
sel_name = 'Back'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized selection \'{sel}\'')
|
raise ValueError(f'unrecognized selection \'{sel}\'')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = {
|
ba.app.ui.window_states[type(self)] = {'sel_name': sel_name}
|
||||||
'sel_name': sel_name
|
|
||||||
}
|
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self}.')
|
ba.print_exception(f'Error saving state for {self}.')
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
try:
|
try:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__,
|
sel_name = ba.app.ui.window_states.get(type(self),
|
||||||
{}).get('sel_name')
|
{}).get('sel_name')
|
||||||
sel: Optional[ba.Widget]
|
sel: Optional[ba.Widget]
|
||||||
if sel_name == 'Controllers':
|
if sel_name == 'Controllers':
|
||||||
|
|||||||
@ -252,13 +252,13 @@ class AudioSettingsWindow(ba.Window):
|
|||||||
sel_name = 'VRHeadRelative'
|
sel_name = 'VRHeadRelative'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized selection \'{sel}\'')
|
raise ValueError(f'unrecognized selection \'{sel}\'')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = sel_name
|
ba.app.ui.window_states[type(self)] = sel_name
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self.__class__}.')
|
ba.print_exception(f'Error saving state for {self.__class__}.')
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
try:
|
try:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__)
|
sel_name = ba.app.ui.window_states.get(type(self))
|
||||||
sel: Optional[ba.Widget]
|
sel: Optional[ba.Widget]
|
||||||
if sel_name == 'SoundMinus':
|
if sel_name == 'SoundMinus':
|
||||||
sel = self._sound_volume_numedit.minusbutton
|
sel = self._sound_volume_numedit.minusbutton
|
||||||
|
|||||||
@ -457,10 +457,10 @@ class ControlsSettingsWindow(ba.Window):
|
|||||||
sel_name = 'Wiimotes'
|
sel_name = 'Wiimotes'
|
||||||
else:
|
else:
|
||||||
sel_name = 'Back'
|
sel_name = 'Back'
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = sel_name
|
ba.app.ui.window_states[type(self)] = sel_name
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__)
|
sel_name = ba.app.ui.window_states.get(type(self))
|
||||||
if sel_name == 'GamePads':
|
if sel_name == 'GamePads':
|
||||||
sel = self._gamepads_button
|
sel = self._gamepads_button
|
||||||
elif sel_name == 'Touch':
|
elif sel_name == 'Touch':
|
||||||
|
|||||||
@ -463,13 +463,13 @@ class SoundtrackBrowserWindow(ba.Window):
|
|||||||
sel_name = 'Back'
|
sel_name = 'Back'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized selection \'{sel}\'')
|
raise ValueError(f'unrecognized selection \'{sel}\'')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = sel_name
|
ba.app.ui.window_states[type(self)] = sel_name
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self}.')
|
ba.print_exception(f'Error saving state for {self}.')
|
||||||
|
|
||||||
def _restore_state(self) -> None:
|
def _restore_state(self) -> None:
|
||||||
try:
|
try:
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__)
|
sel_name = ba.app.ui.window_states.get(type(self))
|
||||||
if sel_name == 'Scroll':
|
if sel_name == 'Scroll':
|
||||||
sel = self._scrollwidget
|
sel = self._scrollwidget
|
||||||
elif sel_name == 'New':
|
elif sel_name == 'New':
|
||||||
|
|||||||
@ -1011,7 +1011,7 @@ class StoreBrowserWindow(ba.Window):
|
|||||||
sel_name = f'Tab:{selected_tab_ids[0].value}'
|
sel_name = f'Tab:{selected_tab_ids[0].value}'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized selection \'{sel}\'')
|
raise ValueError(f'unrecognized selection \'{sel}\'')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = {
|
ba.app.ui.window_states[type(self)] = {
|
||||||
'sel_name': sel_name,
|
'sel_name': sel_name,
|
||||||
}
|
}
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -1021,7 +1021,7 @@ class StoreBrowserWindow(ba.Window):
|
|||||||
from efro.util import enum_by_value
|
from efro.util import enum_by_value
|
||||||
try:
|
try:
|
||||||
sel: Optional[ba.Widget]
|
sel: Optional[ba.Widget]
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__,
|
sel_name = ba.app.ui.window_states.get(type(self),
|
||||||
{}).get('sel_name')
|
{}).get('sel_name')
|
||||||
assert isinstance(sel_name, (str, type(None)))
|
assert isinstance(sel_name, (str, type(None)))
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,7 @@ class TeamNamesColorsWindow(popup.PopupWindow):
|
|||||||
appconfig = ba.app.config
|
appconfig = ba.app.config
|
||||||
self._names = list(
|
self._names = list(
|
||||||
appconfig.get('Custom Team Names', DEFAULT_TEAM_NAMES))
|
appconfig.get('Custom Team Names', DEFAULT_TEAM_NAMES))
|
||||||
|
|
||||||
# We need to flatten the translation since it will be an
|
# We need to flatten the translation since it will be an
|
||||||
# editable string.
|
# editable string.
|
||||||
self._names = [
|
self._names = [
|
||||||
@ -46,7 +47,7 @@ class TeamNamesColorsWindow(popup.PopupWindow):
|
|||||||
self._color_buttons: List[ba.Widget] = []
|
self._color_buttons: List[ba.Widget] = []
|
||||||
self._color_text_fields: List[ba.Widget] = []
|
self._color_text_fields: List[ba.Widget] = []
|
||||||
|
|
||||||
ba.buttonwidget(
|
resetbtn = ba.buttonwidget(
|
||||||
parent=self.root_widget,
|
parent=self.root_widget,
|
||||||
label=ba.Lstr(resource='settingsWindowAdvanced.resetText'),
|
label=ba.Lstr(resource='settingsWindowAdvanced.resetText'),
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
@ -77,20 +78,27 @@ class TeamNamesColorsWindow(popup.PopupWindow):
|
|||||||
description=ba.Lstr(resource='nameText'),
|
description=ba.Lstr(resource='nameText'),
|
||||||
editable=True,
|
editable=True,
|
||||||
padding=4))
|
padding=4))
|
||||||
ba.buttonwidget(parent=self.root_widget,
|
ba.widget(edit=self._color_text_fields[0],
|
||||||
label=ba.Lstr(resource='cancelText'),
|
down_widget=self._color_text_fields[1])
|
||||||
autoselect=True,
|
ba.widget(edit=self._color_text_fields[1],
|
||||||
on_activate_call=self._on_cancel_press,
|
up_widget=self._color_text_fields[0])
|
||||||
size=(150, 50),
|
ba.widget(edit=self._color_text_fields[0], up_widget=resetbtn)
|
||||||
position=(self._width * 0.5 - 200, 20))
|
|
||||||
ba.buttonwidget(parent=self.root_widget,
|
cancelbtn = ba.buttonwidget(parent=self.root_widget,
|
||||||
label=ba.Lstr(resource='saveText'),
|
label=ba.Lstr(resource='cancelText'),
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
on_activate_call=self._save,
|
on_activate_call=self._on_cancel_press,
|
||||||
size=(150, 50),
|
size=(150, 50),
|
||||||
position=(self._width * 0.5 + 50, 20))
|
position=(self._width * 0.5 - 200, 20))
|
||||||
|
savebtn = ba.buttonwidget(parent=self.root_widget,
|
||||||
|
label=ba.Lstr(resource='saveText'),
|
||||||
|
autoselect=True,
|
||||||
|
on_activate_call=self._save,
|
||||||
|
size=(150, 50),
|
||||||
|
position=(self._width * 0.5 + 50, 20))
|
||||||
ba.containerwidget(edit=self.root_widget,
|
ba.containerwidget(edit=self.root_widget,
|
||||||
selected_child=self._color_buttons[0])
|
selected_child=self._color_buttons[0])
|
||||||
|
ba.widget(edit=savebtn, left_widget=cancelbtn)
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
def _color_click(self, i: int) -> None:
|
def _color_click(self, i: int) -> None:
|
||||||
|
|||||||
@ -496,9 +496,7 @@ class WatchWindow(ba.Window):
|
|||||||
sel_name = 'TabContainer'
|
sel_name = 'TabContainer'
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'unrecognized selection {sel}')
|
raise ValueError(f'unrecognized selection {sel}')
|
||||||
ba.app.ui.window_states[self.__class__.__name__] = {
|
ba.app.ui.window_states[type(self)] = {'sel_name': sel_name}
|
||||||
'sel_name': sel_name
|
|
||||||
}
|
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception(f'Error saving state for {self}.')
|
ba.print_exception(f'Error saving state for {self}.')
|
||||||
|
|
||||||
@ -506,7 +504,7 @@ class WatchWindow(ba.Window):
|
|||||||
from efro.util import enum_by_value
|
from efro.util import enum_by_value
|
||||||
try:
|
try:
|
||||||
sel: Optional[ba.Widget]
|
sel: Optional[ba.Widget]
|
||||||
sel_name = ba.app.ui.window_states.get(self.__class__.__name__,
|
sel_name = ba.app.ui.window_states.get(type(self),
|
||||||
{}).get('sel_name')
|
{}).get('sel_name')
|
||||||
assert isinstance(sel_name, (str, type(None)))
|
assert isinstance(sel_name, (str, type(None)))
|
||||||
try:
|
try:
|
||||||
|
|||||||
23
ballisticacore-cmake/.idea/dictionaries/ericf.xml
generated
23
ballisticacore-cmake/.idea/dictionaries/ericf.xml
generated
@ -17,6 +17,7 @@
|
|||||||
<w>aclass's</w>
|
<w>aclass's</w>
|
||||||
<w>activityplayer</w>
|
<w>activityplayer</w>
|
||||||
<w>addcall</w>
|
<w>addcall</w>
|
||||||
|
<w>addchars</w>
|
||||||
<w>addrs</w>
|
<w>addrs</w>
|
||||||
<w>adjoint</w>
|
<w>adjoint</w>
|
||||||
<w>adminset</w>
|
<w>adminset</w>
|
||||||
@ -47,6 +48,7 @@
|
|||||||
<w>appname</w>
|
<w>appname</w>
|
||||||
<w>appnameupper</w>
|
<w>appnameupper</w>
|
||||||
<w>appstate</w>
|
<w>appstate</w>
|
||||||
|
<w>argsjoined</w>
|
||||||
<w>asci</w>
|
<w>asci</w>
|
||||||
<w>assigninput</w>
|
<w>assigninput</w>
|
||||||
<w>athome</w>
|
<w>athome</w>
|
||||||
@ -54,6 +56,7 @@
|
|||||||
<w>audiocache</w>
|
<w>audiocache</w>
|
||||||
<w>automagically</w>
|
<w>automagically</w>
|
||||||
<w>autoselect</w>
|
<w>autoselect</w>
|
||||||
|
<w>availmins</w>
|
||||||
<w>avel</w>
|
<w>avel</w>
|
||||||
<w>avels</w>
|
<w>avels</w>
|
||||||
<w>axismotion</w>
|
<w>axismotion</w>
|
||||||
@ -114,6 +117,7 @@
|
|||||||
<w>bsstd</w>
|
<w>bsstd</w>
|
||||||
<w>bstat</w>
|
<w>bstat</w>
|
||||||
<w>bsuuid</w>
|
<w>bsuuid</w>
|
||||||
|
<w>btnlabel</w>
|
||||||
<w>bufs</w>
|
<w>bufs</w>
|
||||||
<w>buildconfig</w>
|
<w>buildconfig</w>
|
||||||
<w>buildnumber</w>
|
<w>buildnumber</w>
|
||||||
@ -131,8 +135,10 @@
|
|||||||
<w>camalign</w>
|
<w>camalign</w>
|
||||||
<w>camelback</w>
|
<w>camelback</w>
|
||||||
<w>camerashake</w>
|
<w>camerashake</w>
|
||||||
|
<w>cancelbtn</w>
|
||||||
<w>capitan</w>
|
<w>capitan</w>
|
||||||
<w>cargs</w>
|
<w>cargs</w>
|
||||||
|
<w>cbtnoffs</w>
|
||||||
<w>ccdd</w>
|
<w>ccdd</w>
|
||||||
<w>ccontext</w>
|
<w>ccontext</w>
|
||||||
<w>ccylinder</w>
|
<w>ccylinder</w>
|
||||||
@ -177,6 +183,7 @@
|
|||||||
<w>cpuid</w>
|
<w>cpuid</w>
|
||||||
<w>crashenv</w>
|
<w>crashenv</w>
|
||||||
<w>crashlytics</w>
|
<w>crashlytics</w>
|
||||||
|
<w>cresult</w>
|
||||||
<w>crom</w>
|
<w>crom</w>
|
||||||
<w>crosswire</w>
|
<w>crosswire</w>
|
||||||
<w>crvel</w>
|
<w>crvel</w>
|
||||||
@ -329,6 +336,7 @@
|
|||||||
<w>fread</w>
|
<w>fread</w>
|
||||||
<w>freeform</w>
|
<w>freeform</w>
|
||||||
<w>freeifaddrs</w>
|
<w>freeifaddrs</w>
|
||||||
|
<w>freemins</w>
|
||||||
<w>freqs</w>
|
<w>freqs</w>
|
||||||
<w>froemling</w>
|
<w>froemling</w>
|
||||||
<w>fromini</w>
|
<w>fromini</w>
|
||||||
@ -411,6 +419,7 @@
|
|||||||
<w>hostactivity</w>
|
<w>hostactivity</w>
|
||||||
<w>hostcmd</w>
|
<w>hostcmd</w>
|
||||||
<w>hostinfo</w>
|
<w>hostinfo</w>
|
||||||
|
<w>hostingstate</w>
|
||||||
<w>hotkeys</w>
|
<w>hotkeys</w>
|
||||||
<w>hotplug</w>
|
<w>hotplug</w>
|
||||||
<w>hscrollwidget</w>
|
<w>hscrollwidget</w>
|
||||||
@ -491,6 +500,7 @@
|
|||||||
<w>linearsize</w>
|
<w>linearsize</w>
|
||||||
<w>listobj</w>
|
<w>listobj</w>
|
||||||
<w>llock</w>
|
<w>llock</w>
|
||||||
|
<w>lockpath</w>
|
||||||
<w>lockstr</w>
|
<w>lockstr</w>
|
||||||
<w>locktype</w>
|
<w>locktype</w>
|
||||||
<w>logmsg</w>
|
<w>logmsg</w>
|
||||||
@ -596,6 +606,7 @@
|
|||||||
<w>nonlint</w>
|
<w>nonlint</w>
|
||||||
<w>noone</w>
|
<w>noone</w>
|
||||||
<w>nothin</w>
|
<w>nothin</w>
|
||||||
|
<w>nowtickets</w>
|
||||||
<w>nptr</w>
|
<w>nptr</w>
|
||||||
<w>nsize</w>
|
<w>nsize</w>
|
||||||
<w>ntoa</w>
|
<w>ntoa</w>
|
||||||
@ -613,6 +624,8 @@
|
|||||||
<w>obvs</w>
|
<w>obvs</w>
|
||||||
<w>oculus</w>
|
<w>oculus</w>
|
||||||
<w>oenval</w>
|
<w>oenval</w>
|
||||||
|
<w>offsx</w>
|
||||||
|
<w>offsy</w>
|
||||||
<w>oiffsss</w>
|
<w>oiffsss</w>
|
||||||
<w>oldname</w>
|
<w>oldname</w>
|
||||||
<w>oooo</w>
|
<w>oooo</w>
|
||||||
@ -668,6 +681,7 @@
|
|||||||
<w>positivez</w>
|
<w>positivez</w>
|
||||||
<w>postinit</w>
|
<w>postinit</w>
|
||||||
<w>powerup</w>
|
<w>powerup</w>
|
||||||
|
<w>pptabcom</w>
|
||||||
<w>precalc</w>
|
<w>precalc</w>
|
||||||
<w>predeclare</w>
|
<w>predeclare</w>
|
||||||
<w>prefs</w>
|
<w>prefs</w>
|
||||||
@ -679,9 +693,11 @@
|
|||||||
<w>printnodes</w>
|
<w>printnodes</w>
|
||||||
<w>printobjects</w>
|
<w>printobjects</w>
|
||||||
<w>priv</w>
|
<w>priv</w>
|
||||||
|
<w>privatetab</w>
|
||||||
<w>profilers</w>
|
<w>profilers</w>
|
||||||
<w>prog</w>
|
<w>prog</w>
|
||||||
<w>proj</w>
|
<w>proj</w>
|
||||||
|
<w>projdir</w>
|
||||||
<w>prolly</w>
|
<w>prolly</w>
|
||||||
<w>psmx</w>
|
<w>psmx</w>
|
||||||
<w>pspec</w>
|
<w>pspec</w>
|
||||||
@ -739,6 +755,7 @@
|
|||||||
<w>reprfunc</w>
|
<w>reprfunc</w>
|
||||||
<w>rerase</w>
|
<w>rerase</w>
|
||||||
<w>resends</w>
|
<w>resends</w>
|
||||||
|
<w>resetbtn</w>
|
||||||
<w>resetinput</w>
|
<w>resetinput</w>
|
||||||
<w>resync</w>
|
<w>resync</w>
|
||||||
<w>retrysecs</w>
|
<w>retrysecs</w>
|
||||||
@ -759,6 +776,7 @@
|
|||||||
<w>safecolor</w>
|
<w>safecolor</w>
|
||||||
<w>samsung</w>
|
<w>samsung</w>
|
||||||
<w>sapspace</w>
|
<w>sapspace</w>
|
||||||
|
<w>savebtn</w>
|
||||||
<w>savebutton</w>
|
<w>savebutton</w>
|
||||||
<w>scancode</w>
|
<w>scancode</w>
|
||||||
<w>scenetime</w>
|
<w>scenetime</w>
|
||||||
@ -767,6 +785,10 @@
|
|||||||
<w>sdkcheck</w>
|
<w>sdkcheck</w>
|
||||||
<w>sdl's</w>
|
<w>sdl's</w>
|
||||||
<w>sdlk</w>
|
<w>sdlk</w>
|
||||||
|
<w>selchild</w>
|
||||||
|
<w>selindex</w>
|
||||||
|
<w>selwidget</w>
|
||||||
|
<w>selwidgets</w>
|
||||||
<w>seqlen</w>
|
<w>seqlen</w>
|
||||||
<w>seqtype</w>
|
<w>seqtype</w>
|
||||||
<w>seqtypestr</w>
|
<w>seqtypestr</w>
|
||||||
@ -884,6 +906,7 @@
|
|||||||
<w>theres</w>
|
<w>theres</w>
|
||||||
<w>threadname</w>
|
<w>threadname</w>
|
||||||
<w>threadtype</w>
|
<w>threadtype</w>
|
||||||
|
<w>ticon</w>
|
||||||
<w>tiltage</w>
|
<w>tiltage</w>
|
||||||
<w>timedisplay</w>
|
<w>timedisplay</w>
|
||||||
<w>timeformat</w>
|
<w>timeformat</w>
|
||||||
|
|||||||
@ -30,7 +30,8 @@
|
|||||||
"requests",
|
"requests",
|
||||||
"typing_extensions",
|
"typing_extensions",
|
||||||
"cpplint",
|
"cpplint",
|
||||||
"ansiwrap"
|
"ansiwrap",
|
||||||
|
"filelock"
|
||||||
],
|
],
|
||||||
"python_paths": [
|
"python_paths": [
|
||||||
"assets/src/ba_data/python",
|
"assets/src/ba_data/python",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||||
<h4><em>last updated on 2021-01-15 for Ballistica version 1.5.30 build 20267</em></h4>
|
<h4><em>last updated on 2021-01-26 for Ballistica version 1.6.0 build 20278</em></h4>
|
||||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
<p>This page documents the Python classes and functions in the 'ba' module,
|
||||||
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
||||||
<hr>
|
<hr>
|
||||||
@ -85,6 +85,10 @@
|
|||||||
<h4><a name="function_category_General_Utility_Functions">General Utility Functions</a></h4>
|
<h4><a name="function_category_General_Utility_Functions">General Utility Functions</a></h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#function_ba_charstr">ba.charstr()</a></li>
|
<li><a href="#function_ba_charstr">ba.charstr()</a></li>
|
||||||
|
<li><a href="#function_ba_clipboard_get_text">ba.clipboard_get_text()</a></li>
|
||||||
|
<li><a href="#function_ba_clipboard_has_text">ba.clipboard_has_text()</a></li>
|
||||||
|
<li><a href="#function_ba_clipboard_is_supported">ba.clipboard_is_supported()</a></li>
|
||||||
|
<li><a href="#function_ba_clipboard_set_text">ba.clipboard_set_text()</a></li>
|
||||||
<li><a href="#function_ba_do_once">ba.do_once()</a></li>
|
<li><a href="#function_ba_do_once">ba.do_once()</a></li>
|
||||||
<li><a href="#function_ba_garbage_collect">ba.garbage_collect()</a></li>
|
<li><a href="#function_ba_garbage_collect">ba.garbage_collect()</a></li>
|
||||||
<li><a href="#function_ba_getclass">ba.getclass()</a></li>
|
<li><a href="#function_ba_getclass">ba.getclass()</a></li>
|
||||||
@ -395,7 +399,7 @@ actually award achievements.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_Activity">ba.Activity</a></strong></h3>
|
<h2><strong><a name="class_ba_Activity">ba.Activity</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a>, <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a>, <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>Units of execution wrangled by a <a href="#class_ba_Session">ba.Session</a>.</p>
|
<p>Units of execution wrangled by a <a href="#class_ba_Session">ba.Session</a>.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||||
@ -659,7 +663,7 @@ is a convenient way to access this same functionality.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_ActivityNotFoundError">ba.ActivityNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_ActivityNotFoundError">ba.ActivityNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_Activity">ba.Activity</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_Activity">ba.Activity</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -784,7 +788,7 @@ even if myactor is set to None.</p>
|
|||||||
<p>Return the <a href="#class_ba_Activity">ba.Activity</a> this Actor is associated with.</p>
|
<p>Return the <a href="#class_ba_Activity">ba.Activity</a> this Actor is associated with.</p>
|
||||||
|
|
||||||
<p>If the Activity no longer exists, raises a <a href="#class_ba_ActivityNotFoundError">ba.ActivityNotFoundError</a>
|
<p>If the Activity no longer exists, raises a <a href="#class_ba_ActivityNotFoundError">ba.ActivityNotFoundError</a>
|
||||||
or returns None depending on whether 'doraise' is set.</p>
|
or returns None depending on whether 'doraise' is True.</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt><h4><a name="method_ba_Actor__handlemessage">handlemessage()</a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Actor__handlemessage">handlemessage()</a></dt></h4><dd>
|
||||||
@ -823,7 +827,7 @@ likely result in errors.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_ActorNotFoundError">ba.ActorNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_ActorNotFoundError">ba.ActorNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_Actor">ba.Actor</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_Actor">ba.Actor</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -1010,7 +1014,7 @@ to resume.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_AppConfig">ba.AppConfig</a></strong></h3>
|
<h2><strong><a name="class_ba_AppConfig">ba.AppConfig</a></strong></h3>
|
||||||
<p>Inherits from: dict</p>
|
<p>Inherits from: builtins.dict</p>
|
||||||
<p>A special dict that holds the game's persistent configuration values.</p>
|
<p>A special dict that holds the game's persistent configuration values.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_App_Classes">App Classes</a></p>
|
<p>Category: <a href="#class_category_App_Classes">App Classes</a></p>
|
||||||
@ -1023,7 +1027,7 @@ to resume.</p>
|
|||||||
|
|
||||||
<p> AppConfig data is stored as json on disk on so make sure to only place
|
<p> AppConfig data is stored as json on disk on so make sure to only place
|
||||||
json-friendly values in it (dict, list, str, float, int, bool).
|
json-friendly values in it (dict, list, str, float, int, bool).
|
||||||
Be aware that tuples will be quietly converted to lists.
|
Be aware that tuples will be quietly converted to lists when stored.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Methods Defined or Overridden:</h3>
|
<h3>Methods Defined or Overridden:</h3>
|
||||||
@ -1596,7 +1600,7 @@ start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextC
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_ContextError">ba.ContextError</a></strong></h3>
|
<h2><strong><a name="class_ba_ContextError">ba.ContextError</a></strong></h3>
|
||||||
<p>Inherits from: Exception, BaseException</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when a call is made in an invalid context.</p>
|
<p>Exception raised when a call is made in an invalid context.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a></p>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a></p>
|
||||||
@ -1606,10 +1610,10 @@ start_long_action(callback_when_done=<a href="#class_ba_ContextCall">ba.ContextC
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Methods:</h3>
|
<h3>Methods:</h3>
|
||||||
<p><all methods inherited from <a href="#class_builtins_Exception">builtins.Exception</a>></p>
|
<p><all methods inherited from <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>></p>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_CoopGameActivity">ba.CoopGameActivity</a></strong></h3>
|
<h2><strong><a name="class_ba_CoopGameActivity">ba.CoopGameActivity</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_GameActivity">ba.GameActivity</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a>, <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="#class_ba_GameActivity">ba.GameActivity</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a>, <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>Base class for cooperative-mode games.</p>
|
<p>Base class for cooperative-mode games.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a>
|
||||||
@ -1841,7 +1845,7 @@ the data object is requested and when it's value is accessed.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_DeathType">ba.DeathType</a></strong></h3>
|
<h2><strong><a name="class_ba_DeathType">ba.DeathType</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>A reason for a death.</p>
|
<p>A reason for a death.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Enums">Enums</a>
|
<p>Category: <a href="#class_category_Enums">Enums</a>
|
||||||
@ -1858,7 +1862,7 @@ the data object is requested and when it's value is accessed.</p>
|
|||||||
</ul>
|
</ul>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_DelegateNotFoundError">ba.DelegateNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_DelegateNotFoundError">ba.DelegateNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected delegate object does not exist.</p>
|
<p>Exception raised when an expected delegate object does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -1868,7 +1872,7 @@ the data object is requested and when it's value is accessed.</p>
|
|||||||
<p><all methods inherited from <a href="#class_ba_NotFoundError">ba.NotFoundError</a>></p>
|
<p><all methods inherited from <a href="#class_ba_NotFoundError">ba.NotFoundError</a>></p>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_Dependency">ba.Dependency</a></strong></h3>
|
<h2><strong><a name="class_ba_Dependency">ba.Dependency</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>A dependency on a DependencyComponent (with an optional config).</p>
|
<p>A dependency on a DependencyComponent (with an optional config).</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Dependency_Classes">Dependency Classes</a></p>
|
<p>Category: <a href="#class_category_Dependency_Classes">Dependency Classes</a></p>
|
||||||
@ -1941,7 +1945,7 @@ on the dep config value. (for instance a map required by a game type)</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_DependencyError">ba.DependencyError</a></strong></h3>
|
<h2><strong><a name="class_ba_DependencyError">ba.DependencyError</a></strong></h3>
|
||||||
<p>Inherits from: Exception, BaseException</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when one or more <a href="#class_ba_Dependency">ba.Dependency</a> items are missing.</p>
|
<p>Exception raised when one or more <a href="#class_ba_Dependency">ba.Dependency</a> items are missing.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a></p>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a></p>
|
||||||
@ -1968,7 +1972,7 @@ on the dep config value. (for instance a map required by a game type)</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_DependencySet">ba.DependencySet</a></strong></h3>
|
<h2><strong><a name="class_ba_DependencySet">ba.DependencySet</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>Set of resolved dependencies and their associated data.</p>
|
<p>Set of resolved dependencies and their associated data.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Dependency_Classes">Dependency Classes</a></p>
|
<p>Category: <a href="#class_category_Dependency_Classes">Dependency Classes</a></p>
|
||||||
@ -2129,13 +2133,13 @@ its time with lingering corpses, sound effects, etc.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_EmptyPlayer">ba.EmptyPlayer</a></strong></h3>
|
<h2><strong><a name="class_ba_EmptyPlayer">ba.EmptyPlayer</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_Player">ba.Player</a>, <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="#class_ba_Player">ba.Player</a>, <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>An empty player for use by Activities that don't need to define one.</p>
|
<p>An empty player for use by Activities that don't need to define one.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||||
|
|
||||||
<p> <a href="#class_ba_Player">ba.Player</a> and <a href="#class_ba_Team">ba.Team</a> are 'Generic' types, and so passing them as
|
<p> <a href="#class_ba_Player">ba.Player</a> and <a href="#class_ba_Team">ba.Team</a> are 'Generic' types, and so passing those top level
|
||||||
type arguments when defining a <a href="#class_ba_Activity">ba.Activity</a> reduces type safety.
|
classes as type arguments when defining a <a href="#class_ba_Activity">ba.Activity</a> reduces type safety.
|
||||||
For example, activity.teams[0].player will have type 'Any' in that case.
|
For example, activity.teams[0].player will have type 'Any' in that case.
|
||||||
For that reason, it is better to pass EmptyPlayer and EmptyTeam when
|
For that reason, it is better to pass EmptyPlayer and EmptyTeam when
|
||||||
defining a <a href="#class_ba_Activity">ba.Activity</a> that does not need custom types of its own.</p>
|
defining a <a href="#class_ba_Activity">ba.Activity</a> that does not need custom types of its own.</p>
|
||||||
@ -2192,13 +2196,13 @@ its time with lingering corpses, sound effects, etc.</p>
|
|||||||
<p><all methods inherited from <a href="#class_ba_Player">ba.Player</a>></p>
|
<p><all methods inherited from <a href="#class_ba_Player">ba.Player</a>></p>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_EmptyTeam">ba.EmptyTeam</a></strong></h3>
|
<h2><strong><a name="class_ba_EmptyTeam">ba.EmptyTeam</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_Team">ba.Team</a>, <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="#class_ba_Team">ba.Team</a>, <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>An empty player for use by Activities that don't need to define one.</p>
|
<p>An empty player for use by Activities that don't need to define one.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||||
|
|
||||||
<p> <a href="#class_ba_Player">ba.Player</a> and <a href="#class_ba_Team">ba.Team</a> are 'Generic' types, and so passing them as
|
<p> <a href="#class_ba_Player">ba.Player</a> and <a href="#class_ba_Team">ba.Team</a> are 'Generic' types, and so passing those top level
|
||||||
type arguments when defining a <a href="#class_ba_Activity">ba.Activity</a> reduces type safety.
|
classes as type arguments when defining a <a href="#class_ba_Activity">ba.Activity</a> reduces type safety.
|
||||||
For example, activity.teams[0].player will have type 'Any' in that case.
|
For example, activity.teams[0].player will have type 'Any' in that case.
|
||||||
For that reason, it is better to pass EmptyPlayer and EmptyTeam when
|
For that reason, it is better to pass EmptyPlayer and EmptyTeam when
|
||||||
defining a <a href="#class_ba_Activity">ba.Activity</a> that does not need custom types of its own.</p>
|
defining a <a href="#class_ba_Activity">ba.Activity</a> that does not need custom types of its own.</p>
|
||||||
@ -2234,7 +2238,7 @@ its time with lingering corpses, sound effects, etc.</p>
|
|||||||
<p><all methods inherited from <a href="#class_ba_Team">ba.Team</a>></p>
|
<p><all methods inherited from <a href="#class_ba_Team">ba.Team</a>></p>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_Existable">ba.Existable</a></strong></h3>
|
<h2><strong><a name="class_ba_Existable">ba.Existable</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_typing_Protocol">typing.Protocol</a>, <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/typing.html#typing.Protocol">typing.Protocol</a>, <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>A Protocol for objects supporting an exists() method.</p>
|
<p>A Protocol for objects supporting an exists() method.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Protocols">Protocols</a>
|
<p>Category: <a href="#class_category_Protocols">Protocols</a>
|
||||||
@ -2337,8 +2341,8 @@ its time with lingering corpses, sound effects, etc.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_GameActivity">ba.GameActivity</a></strong></h3>
|
<h2><strong><a name="class_ba_GameActivity">ba.GameActivity</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a>, <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a>, <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>Common base class for all game ba.Activities.</p>
|
<p>Common base class for all game <a href="#class_ba_Activity">ba.Activities</a>.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a>
|
||||||
</p>
|
</p>
|
||||||
@ -2990,7 +2994,7 @@ prefs, etc.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_InputDeviceNotFoundError">ba.InputDeviceNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_InputDeviceNotFoundError">ba.InputDeviceNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_InputDevice">ba.InputDevice</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_InputDevice">ba.InputDevice</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -3000,7 +3004,7 @@ prefs, etc.</p>
|
|||||||
<p><all methods inherited from <a href="#class_ba_NotFoundError">ba.NotFoundError</a>></p>
|
<p><all methods inherited from <a href="#class_ba_NotFoundError">ba.NotFoundError</a>></p>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_InputType">ba.InputType</a></strong></h3>
|
<h2><strong><a name="class_ba_InputType">ba.InputType</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>Types of input a controller can send to the game.</p>
|
<p>Types of input a controller can send to the game.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Enums">Enums</a></p>
|
<p>Category: <a href="#class_category_Enums">Enums</a></p>
|
||||||
@ -4053,7 +4057,7 @@ signify that the default soundtrack should be used..</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_MusicPlayMode">ba.MusicPlayMode</a></strong></h3>
|
<h2><strong><a name="class_ba_MusicPlayMode">ba.MusicPlayMode</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>Influences behavior when playing music.</p>
|
<p>Influences behavior when playing music.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Enums">Enums</a>
|
<p>Category: <a href="#class_category_Enums">Enums</a>
|
||||||
@ -4156,7 +4160,7 @@ account what is supported locally.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_MusicType">ba.MusicType</a></strong></h3>
|
<h2><strong><a name="class_ba_MusicType">ba.MusicType</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>Types of music available to play in-game.</p>
|
<p>Types of music available to play in-game.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Enums">Enums</a></p>
|
<p>Category: <a href="#class_category_Enums">Enums</a></p>
|
||||||
@ -4368,7 +4372,7 @@ even if myactor is set to None.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_NodeNotFoundError">ba.NodeNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_NodeNotFoundError">ba.NodeNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_Node">ba.Node</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_Node">ba.Node</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -4378,14 +4382,14 @@ even if myactor is set to None.</p>
|
|||||||
<p><all methods inherited from <a href="#class_ba_NotFoundError">ba.NotFoundError</a>></p>
|
<p><all methods inherited from <a href="#class_ba_NotFoundError">ba.NotFoundError</a>></p>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_NotFoundError">ba.NotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_NotFoundError">ba.NotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: Exception, BaseException</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when a referenced object does not exist.</p>
|
<p>Exception raised when a referenced object does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Methods:</h3>
|
<h3>Methods:</h3>
|
||||||
<p><all methods inherited from <a href="#class_builtins_Exception">builtins.Exception</a>></p>
|
<p><all methods inherited from <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>></p>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_OutOfBoundsMessage">ba.OutOfBoundsMessage</a></strong></h3>
|
<h2><strong><a name="class_ba_OutOfBoundsMessage">ba.OutOfBoundsMessage</a></strong></h3>
|
||||||
<p><em><top level class></em>
|
<p><em><top level class></em>
|
||||||
@ -4404,7 +4408,7 @@ even if myactor is set to None.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_Permission">ba.Permission</a></strong></h3>
|
<h2><strong><a name="class_ba_Permission">ba.Permission</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>Permissions that can be requested from the OS.</p>
|
<p>Permissions that can be requested from the OS.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Enums">Enums</a>
|
<p>Category: <a href="#class_category_Enums">Enums</a>
|
||||||
@ -4462,7 +4466,7 @@ even if myactor is set to None.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_Player">ba.Player</a></strong></h3>
|
<h2><strong><a name="class_ba_Player">ba.Player</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>A player in a specific <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
<p>A player in a specific <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||||
@ -4657,7 +4661,7 @@ the type-checker properly identifies the returned value as one.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_PlayerNotFoundError">ba.PlayerNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_PlayerNotFoundError">ba.PlayerNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_Player">ba.Player</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_Player">ba.Player</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -4944,7 +4948,7 @@ change this. Defaults to an empty string.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_ScoreType">ba.ScoreType</a></strong></h3>
|
<h2><strong><a name="class_ba_ScoreType">ba.ScoreType</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>Type of scores.</p>
|
<p>Type of scores.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Enums">Enums</a>
|
<p>Category: <a href="#class_category_Enums">Enums</a>
|
||||||
@ -5010,7 +5014,7 @@ Pass 0 or a negative number for no ban time.</p>
|
|||||||
<h2><strong><a name="class_ba_Session">ba.Session</a></strong></h3>
|
<h2><strong><a name="class_ba_Session">ba.Session</a></strong></h3>
|
||||||
<p><em><top level class></em>
|
<p><em><top level class></em>
|
||||||
</p>
|
</p>
|
||||||
<p>Defines a high level series of activities with a common purpose.</p>
|
<p>Defines a high level series of <a href="#class_ba_Activity">ba.Activities</a> with a common purpose.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||||
|
|
||||||
@ -5201,7 +5205,7 @@ session.setactivity(foo) and then <a href="#function_ba_newnode">ba.newnode</a>(
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_SessionNotFoundError">ba.SessionNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_SessionNotFoundError">ba.SessionNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_Session">ba.Session</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_Session">ba.Session</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -5345,7 +5349,7 @@ other players.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_SessionPlayerNotFoundError">ba.SessionPlayerNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_SessionPlayerNotFoundError">ba.SessionPlayerNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_SessionPlayer">ba.SessionPlayer</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_SessionPlayer">ba.SessionPlayer</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -5411,7 +5415,7 @@ of the session.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_SessionTeamNotFoundError">ba.SessionTeamNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_SessionTeamNotFoundError">ba.SessionTeamNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_SessionTeam">ba.SessionTeam</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_SessionTeam">ba.SessionTeam</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -5463,7 +5467,7 @@ of the session.</p>
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_SpecialChar">ba.SpecialChar</a></strong></h3>
|
<h2><strong><a name="class_ba_SpecialChar">ba.SpecialChar</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>Special characters the game can print.</p>
|
<p>Special characters the game can print.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Enums">Enums</a>
|
<p>Category: <a href="#class_category_Enums">Enums</a>
|
||||||
@ -5680,7 +5684,7 @@ of the session.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_Team">ba.Team</a></strong></h3>
|
<h2><strong><a name="class_ba_Team">ba.Team</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>A team in a specific <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
<p>A team in a specific <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||||
@ -5729,7 +5733,7 @@ of the session.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_TeamGameActivity">ba.TeamGameActivity</a></strong></h3>
|
<h2><strong><a name="class_ba_TeamGameActivity">ba.TeamGameActivity</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_GameActivity">ba.GameActivity</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a>, <a href="#class_typing_Generic">typing.Generic</a></p>
|
<p>Inherits from: <a href="#class_ba_GameActivity">ba.GameActivity</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_DependencyComponent">ba.DependencyComponent</a>, <a href="https://docs.python.org/3/library/typing.html#typing.Generic">typing.Generic</a></p>
|
||||||
<p>Base class for teams and free-for-all mode games.</p>
|
<p>Base class for teams and free-for-all mode games.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||||
@ -5859,7 +5863,7 @@ False otherwise.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_TeamNotFoundError">ba.TeamNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_TeamNotFoundError">ba.TeamNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_Team">ba.Team</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_Team">ba.Team</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -5895,7 +5899,7 @@ False otherwise.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_TimeFormat">ba.TimeFormat</a></strong></h3>
|
<h2><strong><a name="class_ba_TimeFormat">ba.TimeFormat</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>Specifies the format time values are provided in.</p>
|
<p>Specifies the format time values are provided in.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Enums">Enums</a>
|
<p>Category: <a href="#class_category_Enums">Enums</a>
|
||||||
@ -5927,7 +5931,7 @@ you should use the <a href="#function_ba_timer">ba.timer</a>() function instead.
|
|||||||
|
|
||||||
<p>time: length of time (in seconds by default) that the timer will wait
|
<p>time: length of time (in seconds by default) that the timer will wait
|
||||||
before firing. Note that the actual delay experienced may vary
|
before firing. Note that the actual delay experienced may vary
|
||||||
depending on the timetype. (see below)</p>
|
depending on the timetype. (see below)</p>
|
||||||
|
|
||||||
<p>call: A callable Python object. Note that the timer will retain a
|
<p>call: A callable Python object. Note that the timer will retain a
|
||||||
strong reference to the callable for as long as it exists, so you
|
strong reference to the callable for as long as it exists, so you
|
||||||
@ -5937,28 +5941,11 @@ desired.</p>
|
|||||||
<p>repeat: if True, the timer will fire repeatedly, with each successive
|
<p>repeat: if True, the timer will fire repeatedly, with each successive
|
||||||
firing having the same delay as the first.</p>
|
firing having the same delay as the first.</p>
|
||||||
|
|
||||||
<p>timetype can be either 'sim', 'base', or 'real'. It defaults to
|
<p>timetype: A <a href="#class_ba_TimeType">ba.TimeType</a> value determining which timeline the timer is
|
||||||
'sim'. Types are explained below:</p>
|
placed onto.</p>
|
||||||
|
|
||||||
<p>'sim' time maps to local simulation time in <a href="#class_ba_Activity">ba.Activity</a> or <a href="#class_ba_Session">ba.Session</a>
|
<p>timeformat: A <a href="#class_ba_TimeFormat">ba.TimeFormat</a> value determining how the passed time is
|
||||||
Contexts. This means that it may progress slower in slow-motion play
|
interpreted.</p>
|
||||||
modes, stop when the game is paused, etc. This time type is not
|
|
||||||
available in UI contexts.</p>
|
|
||||||
|
|
||||||
<p>'base' time is also linked to gameplay in <a href="#class_ba_Activity">ba.Activity</a> or <a href="#class_ba_Session">ba.Session</a>
|
|
||||||
Contexts, but it progresses at a constant rate regardless of
|
|
||||||
slow-motion states or pausing. It can, however, slow down or stop
|
|
||||||
in certain cases such as network outages or game slowdowns due to
|
|
||||||
cpu load. Like 'sim' time, this is unavailable in UI contexts.</p>
|
|
||||||
|
|
||||||
<p>'real' time always maps to actual clock time with a bit of filtering
|
|
||||||
added, regardless of Context. (the filtering prevents it from going
|
|
||||||
backwards or jumping forward by large amounts due to the app being
|
|
||||||
backgrounded, system time changing, etc.)
|
|
||||||
Real time timers are currently only available in the UI context.</p>
|
|
||||||
|
|
||||||
<p>the 'timeformat' arg defaults to SECONDS but can also be MILLISECONDS
|
|
||||||
if you want to pass time as milliseconds.</p>
|
|
||||||
|
|
||||||
<pre><span><em><small># Example: use a Timer object to print repeatedly for a few seconds:</small></em></span>
|
<pre><span><em><small># Example: use a Timer object to print repeatedly for a few seconds:</small></em></span>
|
||||||
def say_it():
|
def say_it():
|
||||||
@ -5966,14 +5953,14 @@ def say_it():
|
|||||||
def stop_saying_it():
|
def stop_saying_it():
|
||||||
self.t = None
|
self.t = None
|
||||||
<a href="#function_ba_screenmessage">ba.screenmessage</a>('MUSHROOM MUSHROOM!')
|
<a href="#function_ba_screenmessage">ba.screenmessage</a>('MUSHROOM MUSHROOM!')
|
||||||
<span><em><small># create our timer; it will run as long as we hold self.t</small></em></span>
|
<span><em><small># Create our timer; it will run as long as we have the self.t ref.</small></em></span>
|
||||||
self.t = <a href="#class_ba_Timer">ba.Timer</a>(0.3, say_it, repeat=True)
|
self.t = <a href="#class_ba_Timer">ba.Timer</a>(0.3, say_it, repeat=True)
|
||||||
<span><em><small># now fire off a one-shot timer to kill it</small></em></span>
|
<span><em><small># Now fire off a one-shot timer to kill it.</small></em></span>
|
||||||
<a href="#function_ba_timer">ba.timer</a>(3.89, stop_saying_it)</pre>
|
<a href="#function_ba_timer">ba.timer</a>(3.89, stop_saying_it)</pre>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_TimeType">ba.TimeType</a></strong></h3>
|
<h2><strong><a name="class_ba_TimeType">ba.TimeType</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>Specifies the type of time for various operations to target/use.</p>
|
<p>Specifies the type of time for various operations to target/use.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Enums">Enums</a></p>
|
<p>Category: <a href="#class_category_Enums">Enums</a></p>
|
||||||
@ -6001,7 +5988,7 @@ self.t = <a href="#class_ba_Timer">ba.Timer</a>(0.3, say_it, repeat=True)
|
|||||||
<h2><strong><a name="class_ba_UIController">ba.UIController</a></strong></h3>
|
<h2><strong><a name="class_ba_UIController">ba.UIController</a></strong></h3>
|
||||||
<p><em><top level class></em>
|
<p><em><top level class></em>
|
||||||
</p>
|
</p>
|
||||||
<p>Wrangles UILocations.</p>
|
<p>Wrangles ba.UILocations.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_User_Interface_Classes">User Interface Classes</a>
|
<p>Category: <a href="#class_category_User_Interface_Classes">User Interface Classes</a>
|
||||||
</p>
|
</p>
|
||||||
@ -6022,7 +6009,7 @@ self.t = <a href="#class_ba_Timer">ba.Timer</a>(0.3, say_it, repeat=True)
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_UIScale">ba.UIScale</a></strong></h3>
|
<h2><strong><a name="class_ba_UIScale">ba.UIScale</a></strong></h3>
|
||||||
<p>Inherits from: enum.Enum</p>
|
<p>Inherits from: <a href="https://docs.python.org/3/library/enum.html#enum.Enum">enum.Enum</a></p>
|
||||||
<p>The overall scale the UI is being rendered for. Note that this is
|
<p>The overall scale the UI is being rendered for. Note that this is
|
||||||
independent of pixel resolution. For example, a phone and a desktop PC
|
independent of pixel resolution. For example, a phone and a desktop PC
|
||||||
might render the game at similar pixel resolutions but the size they
|
might render the game at similar pixel resolutions but the size they
|
||||||
@ -6306,7 +6293,7 @@ widgets.</p>
|
|||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="class_ba_WidgetNotFoundError">ba.WidgetNotFoundError</a></strong></h3>
|
<h2><strong><a name="class_ba_WidgetNotFoundError">ba.WidgetNotFoundError</a></strong></h3>
|
||||||
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, Exception, BaseException</p>
|
<p>Inherits from: <a href="#class_ba_NotFoundError">ba.NotFoundError</a>, <a href="https://docs.python.org/3/library/exceptions.html#Exception">Exception</a>, <a href="https://docs.python.org/3/library/exceptions.html#BaseException">BaseException</a></p>
|
||||||
<p>Exception raised when an expected <a href="#class_ba_Widget">ba.Widget</a> does not exist.</p>
|
<p>Exception raised when an expected <a href="#class_ba_Widget">ba.Widget</a> does not exist.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
<p>Category: <a href="#class_category_Exception_Classes">Exception Classes</a>
|
||||||
@ -6473,6 +6460,50 @@ them elsewhere will be meaningless.</p>
|
|||||||
a new one is created and returned. Arguments that are not set to None
|
a new one is created and returned. Arguments that are not set to None
|
||||||
are applied to the Widget.</p>
|
are applied to the Widget.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><strong><a name="function_ba_clipboard_get_text">ba.clipboard_get_text()</a></strong></h3>
|
||||||
|
<p><span>clipboard_get_text() -> str</span></p>
|
||||||
|
|
||||||
|
<p>Return text currently on the system clipboard.</p>
|
||||||
|
|
||||||
|
<p>Category: <a href="#function_category_General_Utility_Functions">General Utility Functions</a></p>
|
||||||
|
|
||||||
|
<p>Ensure that <a href="#function_ba_clipboard_has_text">ba.clipboard_has_text</a>() returns True before calling
|
||||||
|
this function.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><strong><a name="function_ba_clipboard_has_text">ba.clipboard_has_text()</a></strong></h3>
|
||||||
|
<p><span>clipboard_has_text() -> bool</span></p>
|
||||||
|
|
||||||
|
<p>Return whether there is currently text on the clipboard.</p>
|
||||||
|
|
||||||
|
<p>Category: <a href="#function_category_General_Utility_Functions">General Utility Functions</a></p>
|
||||||
|
|
||||||
|
<p>This will return False if no system clipboard is available; no need
|
||||||
|
to call ba.clipboard_available() separately.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><strong><a name="function_ba_clipboard_is_supported">ba.clipboard_is_supported()</a></strong></h3>
|
||||||
|
<p><span>clipboard_is_supported() -> bool</span></p>
|
||||||
|
|
||||||
|
<p>Return whether this platform supports clipboard operations at all.</p>
|
||||||
|
|
||||||
|
<p>Category: <a href="#function_category_General_Utility_Functions">General Utility Functions</a></p>
|
||||||
|
|
||||||
|
<p>If this returns False, UIs should not show 'copy to clipboard'
|
||||||
|
buttons, etc.</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><strong><a name="function_ba_clipboard_set_text">ba.clipboard_set_text()</a></strong></h3>
|
||||||
|
<p><span>clipboard_set_text(value: str) -> None</span></p>
|
||||||
|
|
||||||
|
<p>Copy a string to the system clipboard.</p>
|
||||||
|
|
||||||
|
<p>Category: <a href="#function_category_General_Utility_Functions">General Utility Functions</a></p>
|
||||||
|
|
||||||
|
<p>Ensure that ba.clipboard_available() returns True before adding
|
||||||
|
buttons/etc. that make use of this functionality.</p>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="function_ba_columnwidget">ba.columnwidget()</a></strong></h3>
|
<h2><strong><a name="function_ba_columnwidget">ba.columnwidget()</a></strong></h3>
|
||||||
<p><span>columnwidget(edit: <a href="#class_ba_Widget">ba.Widget</a> = None,
|
<p><span>columnwidget(edit: <a href="#class_ba_Widget">ba.Widget</a> = None,
|
||||||
@ -6582,17 +6613,19 @@ settings, exiting element counts, or other factors.</p>
|
|||||||
<h2><strong><a name="function_ba_existing">ba.existing()</a></strong></h3>
|
<h2><strong><a name="function_ba_existing">ba.existing()</a></strong></h3>
|
||||||
<p><span>existing(obj: Optional[ExistableType]) -> Optional[ExistableType]</span></p>
|
<p><span>existing(obj: Optional[ExistableType]) -> Optional[ExistableType]</span></p>
|
||||||
|
|
||||||
<p>Convert invalid references to None for any <a href="#class_ba_Existable">ba.Existable</a> type.</p>
|
<p>Convert invalid references to None for any <a href="#class_ba_Existable">ba.Existable</a> object.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#function_category_Gameplay_Functions">Gameplay Functions</a></p>
|
<p>Category: <a href="#function_category_Gameplay_Functions">Gameplay Functions</a></p>
|
||||||
|
|
||||||
<p>To best support type checking, it is important that invalid references
|
<p>To best support type checking, it is important that invalid references
|
||||||
not be passed around and instead get converted to values of None.
|
not be passed around and instead get converted to values of None.
|
||||||
That way the type checker can properly flag attempts to pass dead
|
That way the type checker can properly flag attempts to pass dead
|
||||||
objects into functions expecting only live ones, etc.
|
objects (Optional[FooType]) into functions expecting only live ones
|
||||||
This call can be used on any 'existable' object (one with an exists()
|
(FooType), etc. This call can be used on any 'existable' object
|
||||||
method) and will convert it to a None value if it does not exist.
|
(one with an exists() method) and will convert it to a None value
|
||||||
For more info, see notes on 'existables' here:
|
if it does not exist.</p>
|
||||||
|
|
||||||
|
<p>For more info, see notes on 'existables' here:
|
||||||
https://ballistica.net/wiki/Coding-Style-Guide</p>
|
https://ballistica.net/wiki/Coding-Style-Guide</p>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
@ -6989,14 +7022,14 @@ app running.</p>
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="function_ba_rowwidget">ba.rowwidget()</a></strong></h3>
|
<h2><strong><a name="function_ba_rowwidget">ba.rowwidget()</a></strong></h3>
|
||||||
<p><span>rowwidget(edit: Widget = None, parent: Widget = None,
|
<p><span>rowwidget(edit: <a href="#class_ba_Widget">ba.Widget</a> = None, parent: <a href="#class_ba_Widget">ba.Widget</a> = None,
|
||||||
size: Sequence[float] = None,
|
size: Sequence[float] = None,
|
||||||
position: Sequence[float] = None,
|
position: Sequence[float] = None,
|
||||||
background: bool = None, selected_child: Widget = None,
|
background: bool = None, selected_child: <a href="#class_ba_Widget">ba.Widget</a> = None,
|
||||||
visible_child: Widget = None,
|
visible_child: <a href="#class_ba_Widget">ba.Widget</a> = None,
|
||||||
claims_left_right: bool = None,
|
claims_left_right: bool = None,
|
||||||
claims_tab: bool = None,
|
claims_tab: bool = None,
|
||||||
selection_loops_to_parent: bool = None) -> Widget</span></p>
|
selection_loops_to_parent: bool = None) -> <a href="#class_ba_Widget">ba.Widget</a></span></p>
|
||||||
|
|
||||||
<p>Create or edit a row widget.</p>
|
<p>Create or edit a row widget.</p>
|
||||||
|
|
||||||
@ -7076,9 +7109,9 @@ are applied to the Widget.</p>
|
|||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="function_ba_setmusic">ba.setmusic()</a></strong></h3>
|
<h2><strong><a name="function_ba_setmusic">ba.setmusic()</a></strong></h3>
|
||||||
<p><span>setmusic(musictype: Optional[MusicType], continuous: bool = False) -> None</span></p>
|
<p><span>setmusic(musictype: Optional[<a href="#class_ba_MusicType">ba.MusicType</a>], continuous: bool = False) -> None</span></p>
|
||||||
|
|
||||||
<p>Tell the game to play (or stop playing) a certain type of music.</p>
|
<p>Set the app to play (or stop playing) a certain type of music.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#function_category_Gameplay_Functions">Gameplay Functions</a></p>
|
<p>Category: <a href="#function_category_Gameplay_Functions">Gameplay Functions</a></p>
|
||||||
|
|
||||||
@ -7103,15 +7136,17 @@ playing, the playing track will not be restarted.</p>
|
|||||||
<h2><strong><a name="function_ba_storagename">ba.storagename()</a></strong></h3>
|
<h2><strong><a name="function_ba_storagename">ba.storagename()</a></strong></h3>
|
||||||
<p><span>storagename(suffix: str = None) -> str</span></p>
|
<p><span>storagename(suffix: str = None) -> str</span></p>
|
||||||
|
|
||||||
<p>Generate a (hopefully) unique name for storing things in public places.</p>
|
<p>Generate a unique name for storing class data in shared places.</p>
|
||||||
|
|
||||||
<p>Category: <a href="#function_category_General_Utility_Functions">General Utility Functions</a></p>
|
<p>Category: <a href="#function_category_General_Utility_Functions">General Utility Functions</a></p>
|
||||||
|
|
||||||
<p>This consists of a leading underscore, the module path at the
|
<p>This consists of a leading underscore, the module path at the
|
||||||
call site with dots replaced by underscores, the class name, and
|
call site with dots replaced by underscores, the containing class's
|
||||||
the provided suffix. When storing data in public places such as
|
qualified name, and the provided suffix. When storing data in public
|
||||||
'customdata' dicts, this minimizes the chance of collisions if a
|
places such as 'customdata' dicts, this minimizes the chance of
|
||||||
module or class is duplicated or renamed.</p>
|
collisions with other similarly named classes.</p>
|
||||||
|
|
||||||
|
<p>Note that this will function even if called in the class definition.</p>
|
||||||
|
|
||||||
<pre><span><em><small># Example: generate a unique name for storage purposes:</small></em></span>
|
<pre><span><em><small># Example: generate a unique name for storage purposes:</small></em></span>
|
||||||
class MyThingie:</pre>
|
class MyThingie:</pre>
|
||||||
@ -7119,22 +7154,22 @@ class MyThingie:</pre>
|
|||||||
<pre><span><em><small> # This will give something like '_mymodule_submodule_mythingie_data'.</small></em></span>
|
<pre><span><em><small> # This will give something like '_mymodule_submodule_mythingie_data'.</small></em></span>
|
||||||
_STORENAME = <a href="#function_ba_storagename">ba.storagename</a>('data')</pre>
|
_STORENAME = <a href="#function_ba_storagename">ba.storagename</a>('data')</pre>
|
||||||
|
|
||||||
<p> def __init__(self, activity):
|
<pre><span><em><small> # Use that name to store some data in the Activity we were passed.</small></em></span>
|
||||||
# Store some data in the Activity we were passed
|
def __init__(self, activity):
|
||||||
activity.customdata[self._STORENAME] = {}</p>
|
activity.customdata[self._STORENAME] = {}</pre>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="function_ba_textwidget">ba.textwidget()</a></strong></h3>
|
<h2><strong><a name="function_ba_textwidget">ba.textwidget()</a></strong></h3>
|
||||||
<p><span>textwidget(edit: Widget = None, parent: Widget = None,
|
<p><span>textwidget(edit: <a href="#class_ba_Widget">ba.Widget</a> = None, parent: <a href="#class_ba_Widget">ba.Widget</a> = None,
|
||||||
size: Sequence[float] = None, position: Sequence[float] = None,
|
size: Sequence[float] = None, position: Sequence[float] = None,
|
||||||
text: Union[str, <a href="#class_ba_Lstr">ba.Lstr</a>] = None, v_align: str = None,
|
text: Union[str, <a href="#class_ba_Lstr">ba.Lstr</a>] = None, v_align: str = None,
|
||||||
h_align: str = None, editable: bool = None, padding: float = None,
|
h_align: str = None, editable: bool = None, padding: float = None,
|
||||||
on_return_press_call: Callable[[], None] = None,
|
on_return_press_call: Callable[[], None] = None,
|
||||||
on_activate_call: Callable[[], None] = None,
|
on_activate_call: Callable[[], None] = None,
|
||||||
selectable: bool = None, query: Widget = None, max_chars: int = None,
|
selectable: bool = None, query: <a href="#class_ba_Widget">ba.Widget</a> = None, max_chars: int = None,
|
||||||
color: Sequence[float] = None, click_activate: bool = None,
|
color: Sequence[float] = None, click_activate: bool = None,
|
||||||
on_select_call: Callable[[], None] = None,
|
on_select_call: Callable[[], None] = None,
|
||||||
always_highlight: bool = None, draw_controller: Widget = None,
|
always_highlight: bool = None, draw_controller: <a href="#class_ba_Widget">ba.Widget</a> = None,
|
||||||
scale: float = None, corner_scale: float = None,
|
scale: float = None, corner_scale: float = None,
|
||||||
description: Union[str, <a href="#class_ba_Lstr">ba.Lstr</a>] = None,
|
description: Union[str, <a href="#class_ba_Lstr">ba.Lstr</a>] = None,
|
||||||
transition_delay: float = None, maxwidth: float = None,
|
transition_delay: float = None, maxwidth: float = None,
|
||||||
|
|||||||
@ -21,8 +21,8 @@
|
|||||||
namespace ballistica {
|
namespace ballistica {
|
||||||
|
|
||||||
// These are set automatically via script; don't change here.
|
// These are set automatically via script; don't change here.
|
||||||
const int kAppBuildNumber = 20268;
|
const int kAppBuildNumber = 20279;
|
||||||
const char* kAppVersion = "1.5.30";
|
const char* kAppVersion = "1.6.0";
|
||||||
|
|
||||||
// Our standalone globals.
|
// Our standalone globals.
|
||||||
// These are separated out for easy access.
|
// These are separated out for easy access.
|
||||||
|
|||||||
@ -263,9 +263,6 @@ class Graphics {
|
|||||||
internal_components_inited_ = val;
|
internal_components_inited_ = val;
|
||||||
}
|
}
|
||||||
auto set_gyro_vals(const Vector3f& vals) -> void { gyro_vals_ = vals; }
|
auto set_gyro_vals(const Vector3f& vals) -> void { gyro_vals_ = vals; }
|
||||||
// auto draw_overlay_bounds() const -> bool { return draw_overlay_bounds_; }
|
|
||||||
// auto set_draw_overlay_bounds(bool val) -> void { draw_overlay_bounds_ =
|
|
||||||
// val; }
|
|
||||||
auto show_net_info() const -> bool { return show_net_info_; }
|
auto show_net_info() const -> bool { return show_net_info_; }
|
||||||
auto set_show_net_info(bool val) -> void { show_net_info_ = val; }
|
auto set_show_net_info(bool val) -> void { show_net_info_ = val; }
|
||||||
auto debug_graph_1() const -> NetGraph* { return debug_graph_1_.get(); }
|
auto debug_graph_1() const -> NetGraph* { return debug_graph_1_.get(); }
|
||||||
|
|||||||
@ -286,8 +286,8 @@ void GraphicsServer::SetScreen(bool fullscreen, int width, int height,
|
|||||||
// we request fullscreen-windows for full-screen situations and that's it.
|
// we request fullscreen-windows for full-screen situations and that's it.
|
||||||
// (otherwise we may wind up with huge windows due to passing in desktop
|
// (otherwise we may wind up with huge windows due to passing in desktop
|
||||||
// resolutions and retina wonkiness)
|
// resolutions and retina wonkiness)
|
||||||
width = 800;
|
width = static_cast<int>(kBaseVirtualResX * 0.8f);
|
||||||
height = 600;
|
height = static_cast<int>(kBaseVirtualResY * 0.8f);
|
||||||
|
|
||||||
// We should never have to recreate the context after the initial time on
|
// We should never have to recreate the context after the initial time on
|
||||||
// our modern builds.
|
// our modern builds.
|
||||||
|
|||||||
@ -1209,13 +1209,24 @@ void Input::HandleKeyPress(const SDL_Keysym* keysym) {
|
|||||||
if (!repeat_press && keysym->sym == SDLK_q
|
if (!repeat_press && keysym->sym == SDLK_q
|
||||||
&& ((keysym->mod & KMOD_CTRL) || (keysym->mod & KMOD_GUI))) { // NOLINT
|
&& ((keysym->mod & KMOD_CTRL) || (keysym->mod & KMOD_GUI))) { // NOLINT
|
||||||
g_game->PushConfirmQuitCall();
|
g_game->PushConfirmQuitCall();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let the console intercept stuff if it wants at this point.
|
||||||
if (g_app_globals->console != nullptr
|
if (g_app_globals->console != nullptr
|
||||||
&& g_app_globals->console->HandleKeyPress(keysym)) {
|
&& g_app_globals->console->HandleKeyPress(keysym)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ctrl-V or Cmd-V sends paste commands to any interested text fields.
|
||||||
|
// Command-Q or Control-Q quits.
|
||||||
|
if (!repeat_press && keysym->sym == SDLK_v
|
||||||
|
&& ((keysym->mod & KMOD_CTRL) || (keysym->mod & KMOD_GUI))) { // NOLINT
|
||||||
|
g_ui->SendWidgetMessage(WidgetMessage(WidgetMessage::Type::kPaste));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
// None of the following stuff accepts key repeats.
|
// None of the following stuff accepts key repeats.
|
||||||
|
|||||||
@ -1361,4 +1361,88 @@ auto Platform::GetCurrentSeconds() -> int64_t {
|
|||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Platform::ClipboardIsSupported() -> bool {
|
||||||
|
// We only call our actual virtual function once.
|
||||||
|
if (!have_clipboard_is_supported_) {
|
||||||
|
clipboard_is_supported_ = DoClipboardIsSupported();
|
||||||
|
have_clipboard_is_supported_ = true;
|
||||||
|
}
|
||||||
|
return clipboard_is_supported_;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Platform::ClipboardHasText() -> bool {
|
||||||
|
// If subplatform says they don't support clipboards, don't even ask.
|
||||||
|
if (!ClipboardIsSupported()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return DoClipboardHasText();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Platform::ClipboardSetText(const std::string& text) -> void {
|
||||||
|
// If subplatform says they don't support clipboards, this is an error.
|
||||||
|
if (!ClipboardIsSupported()) {
|
||||||
|
throw Exception("ClipboardSetText called with no clipboard support.",
|
||||||
|
PyExcType::kRuntime);
|
||||||
|
}
|
||||||
|
DoClipboardSetText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Platform::ClipboardGetText() -> std::string {
|
||||||
|
// If subplatform says they don't support clipboards, this is an error.
|
||||||
|
if (!ClipboardIsSupported()) {
|
||||||
|
throw Exception("ClipboardGetText called with no clipboard support.",
|
||||||
|
PyExcType::kRuntime);
|
||||||
|
}
|
||||||
|
return DoClipboardGetText();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Platform::DoClipboardIsSupported() -> bool {
|
||||||
|
// Go through SDL functionality on SDL based platforms;
|
||||||
|
// otherwise default to no clipboard.
|
||||||
|
#if BA_SDL2_BUILD && !BA_OSTYPE_IOS_TVOS
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Platform::DoClipboardHasText() -> bool {
|
||||||
|
// Go through SDL functionality on SDL based platforms;
|
||||||
|
// otherwise default to no clipboard.
|
||||||
|
#if BA_SDL2_BUILD && !BA_OSTYPE_IOS_TVOS
|
||||||
|
return SDL_HasClipboardText();
|
||||||
|
#else
|
||||||
|
// Shouldn't get here since we default to no clipboard support.
|
||||||
|
FatalError("Shouldn't get here.");
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Platform::DoClipboardSetText(const std::string& text) -> void {
|
||||||
|
// Go through SDL functionality on SDL based platforms;
|
||||||
|
// otherwise default to no clipboard.
|
||||||
|
#if BA_SDL2_BUILD && !BA_OSTYPE_IOS_TVOS
|
||||||
|
SDL_SetClipboardText(text.c_str());
|
||||||
|
#else
|
||||||
|
// Shouldn't get here since we default to no clipboard support.
|
||||||
|
FatalError("Shouldn't get here.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Platform::DoClipboardGetText() -> std::string {
|
||||||
|
// Go through SDL functionality on SDL based platforms;
|
||||||
|
// otherwise default to no clipboard.
|
||||||
|
#if BA_SDL2_BUILD && !BA_OSTYPE_IOS_TVOS
|
||||||
|
char* out = SDL_GetClipboardText();
|
||||||
|
if (out == nullptr) {
|
||||||
|
throw Exception("Error fetching clipboard contents.", PyExcType::kRuntime);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
#else
|
||||||
|
// Shouldn't get here since we default to no clipboard support.
|
||||||
|
FatalError("Shouldn't get here.");
|
||||||
|
return "";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ballistica
|
} // namespace ballistica
|
||||||
|
|||||||
@ -103,7 +103,25 @@ class Platform {
|
|||||||
virtual auto GetCWD() -> std::string;
|
virtual auto GetCWD() -> std::string;
|
||||||
|
|
||||||
// Unlink a file.
|
// Unlink a file.
|
||||||
virtual void Unlink(const char* path);
|
virtual auto Unlink(const char* path) -> void;
|
||||||
|
|
||||||
|
#pragma mark CLIPBOARD ---------------------------------------------------------
|
||||||
|
|
||||||
|
/// Return whether clipboard operations are supported at all.
|
||||||
|
/// This gets called when determining whether to display clipboard related
|
||||||
|
/// UI elements/etc.
|
||||||
|
auto ClipboardIsSupported() -> bool;
|
||||||
|
|
||||||
|
/// Return whether there is currently text on the clipboard.
|
||||||
|
auto ClipboardHasText() -> bool;
|
||||||
|
|
||||||
|
/// Set current clipboard text. Raises an Exception if clipboard is
|
||||||
|
/// unsupported.
|
||||||
|
auto ClipboardSetText(const std::string& text) -> void;
|
||||||
|
|
||||||
|
/// Return current text from the clipboard. Raises an Exception if
|
||||||
|
/// clipboard is unsupported or if there's no text on the clipboard.
|
||||||
|
auto ClipboardGetText() -> std::string;
|
||||||
|
|
||||||
#pragma mark PRINTING/LOGGING --------------------------------------------------
|
#pragma mark PRINTING/LOGGING --------------------------------------------------
|
||||||
|
|
||||||
@ -493,6 +511,11 @@ class Platform {
|
|||||||
// Generate a random UUID string.
|
// Generate a random UUID string.
|
||||||
virtual auto GenerateUUID() -> std::string;
|
virtual auto GenerateUUID() -> std::string;
|
||||||
|
|
||||||
|
virtual auto DoClipboardIsSupported() -> bool;
|
||||||
|
virtual auto DoClipboardHasText() -> bool;
|
||||||
|
virtual auto DoClipboardSetText(const std::string& text) -> void;
|
||||||
|
virtual auto DoClipboardGetText() -> std::string;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int py_call_num_{};
|
int py_call_num_{};
|
||||||
bool using_custom_app_python_dir_{};
|
bool using_custom_app_python_dir_{};
|
||||||
@ -500,6 +523,8 @@ class Platform {
|
|||||||
bool have_has_touchscreen_value_{};
|
bool have_has_touchscreen_value_{};
|
||||||
bool have_touchscreen_{};
|
bool have_touchscreen_{};
|
||||||
bool is_tegra_k1_{};
|
bool is_tegra_k1_{};
|
||||||
|
bool have_clipboard_is_supported_{};
|
||||||
|
bool clipboard_is_supported_{};
|
||||||
millisecs_t starttime_{};
|
millisecs_t starttime_{};
|
||||||
std::string device_uuid_;
|
std::string device_uuid_;
|
||||||
bool have_device_uuid_{};
|
bool have_device_uuid_{};
|
||||||
|
|||||||
@ -32,7 +32,7 @@ void PythonClassTimer::SetupType(PyTypeObject* obj) {
|
|||||||
"you should use the ba.timer() function instead.\n"
|
"you should use the ba.timer() function instead.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"time: length of time (in seconds by default) that the timer will wait\n"
|
"time: length of time (in seconds by default) that the timer will wait\n"
|
||||||
"before firing. Note that the actual delay experienced may vary\n "
|
"before firing. Note that the actual delay experienced may vary\n"
|
||||||
"depending on the timetype. (see below)\n"
|
"depending on the timetype. (see below)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"call: A callable Python object. Note that the timer will retain a\n"
|
"call: A callable Python object. Note that the timer will retain a\n"
|
||||||
@ -43,28 +43,11 @@ void PythonClassTimer::SetupType(PyTypeObject* obj) {
|
|||||||
"repeat: if True, the timer will fire repeatedly, with each successive\n"
|
"repeat: if True, the timer will fire repeatedly, with each successive\n"
|
||||||
"firing having the same delay as the first.\n"
|
"firing having the same delay as the first.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"timetype can be either 'sim', 'base', or 'real'. It defaults to\n"
|
"timetype: A ba.TimeType value determining which timeline the timer is\n"
|
||||||
"'sim'. Types are explained below:\n"
|
"placed onto.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"'sim' time maps to local simulation time in ba.Activity or ba.Session\n"
|
"timeformat: A ba.TimeFormat value determining how the passed time is\n"
|
||||||
"Contexts. This means that it may progress slower in slow-motion play\n"
|
"interpreted.\n"
|
||||||
"modes, stop when the game is paused, etc. This time type is not\n"
|
|
||||||
"available in UI contexts.\n"
|
|
||||||
"\n"
|
|
||||||
"'base' time is also linked to gameplay in ba.Activity or ba.Session\n"
|
|
||||||
"Contexts, but it progresses at a constant rate regardless of\n "
|
|
||||||
"slow-motion states or pausing. It can, however, slow down or stop\n"
|
|
||||||
"in certain cases such as network outages or game slowdowns due to\n"
|
|
||||||
"cpu load. Like 'sim' time, this is unavailable in UI contexts.\n"
|
|
||||||
"\n"
|
|
||||||
"'real' time always maps to actual clock time with a bit of filtering\n"
|
|
||||||
"added, regardless of Context. (the filtering prevents it from going\n"
|
|
||||||
"backwards or jumping forward by large amounts due to the app being\n"
|
|
||||||
"backgrounded, system time changing, etc.)\n"
|
|
||||||
"Real time timers are currently only available in the UI context.\n"
|
|
||||||
"\n"
|
|
||||||
"the 'timeformat' arg defaults to SECONDS but can also be MILLISECONDS\n"
|
|
||||||
"if you want to pass time as milliseconds.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"# Example: use a Timer object to print repeatedly for a few seconds:\n"
|
"# Example: use a Timer object to print repeatedly for a few seconds:\n"
|
||||||
"def say_it():\n"
|
"def say_it():\n"
|
||||||
@ -72,9 +55,9 @@ void PythonClassTimer::SetupType(PyTypeObject* obj) {
|
|||||||
"def stop_saying_it():\n"
|
"def stop_saying_it():\n"
|
||||||
" self.t = None\n"
|
" self.t = None\n"
|
||||||
" ba.screenmessage('MUSHROOM MUSHROOM!')\n"
|
" ba.screenmessage('MUSHROOM MUSHROOM!')\n"
|
||||||
"# create our timer; it will run as long as we hold self.t\n"
|
"# Create our timer; it will run as long as we have the self.t ref.\n"
|
||||||
"self.t = ba.Timer(0.3, say_it, repeat=True)\n"
|
"self.t = ba.Timer(0.3, say_it, repeat=True)\n"
|
||||||
"# now fire off a one-shot timer to kill it\n"
|
"# Now fire off a one-shot timer to kill it.\n"
|
||||||
"ba.timer(3.89, stop_saying_it)";
|
"ba.timer(3.89, stop_saying_it)";
|
||||||
obj->tp_new = tp_new;
|
obj->tp_new = tp_new;
|
||||||
obj->tp_dealloc = (destructor)tp_dealloc;
|
obj->tp_dealloc = (destructor)tp_dealloc;
|
||||||
|
|||||||
@ -16,4 +16,5 @@ class PythonMethodsApp {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ballistica
|
} // namespace ballistica
|
||||||
|
|
||||||
#endif // BALLISTICA_PYTHON_METHODS_PYTHON_METHODS_APP_H_
|
#endif // BALLISTICA_PYTHON_METHODS_PYTHON_METHODS_APP_H_
|
||||||
|
|||||||
@ -16,4 +16,5 @@ class PythonMethodsGameplay {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ballistica
|
} // namespace ballistica
|
||||||
|
|
||||||
#endif // BALLISTICA_PYTHON_METHODS_PYTHON_METHODS_GAMEPLAY_H_
|
#endif // BALLISTICA_PYTHON_METHODS_PYTHON_METHODS_GAMEPLAY_H_
|
||||||
|
|||||||
@ -16,4 +16,5 @@ class PythonMethodsGraphics {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ballistica
|
} // namespace ballistica
|
||||||
|
|
||||||
#endif // BALLISTICA_PYTHON_METHODS_PYTHON_METHODS_GRAPHICS_H_
|
#endif // BALLISTICA_PYTHON_METHODS_PYTHON_METHODS_GRAPHICS_H_
|
||||||
|
|||||||
@ -32,6 +32,46 @@ namespace ballistica {
|
|||||||
#pragma ide diagnostic ignored "hicpp-signed-bitwise"
|
#pragma ide diagnostic ignored "hicpp-signed-bitwise"
|
||||||
#pragma ide diagnostic ignored "RedundantCast"
|
#pragma ide diagnostic ignored "RedundantCast"
|
||||||
|
|
||||||
|
auto PyClipboardIsSupported(PyObject* self) -> PyObject* {
|
||||||
|
BA_PYTHON_TRY;
|
||||||
|
if (g_platform->ClipboardIsSupported()) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
BA_PYTHON_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PyClipboardHasText(PyObject* self) -> PyObject* {
|
||||||
|
BA_PYTHON_TRY;
|
||||||
|
if (g_platform->ClipboardHasText()) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
BA_PYTHON_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PyClipboardSetText(PyObject* self, PyObject* args, PyObject* keywds)
|
||||||
|
-> PyObject* {
|
||||||
|
BA_PYTHON_TRY;
|
||||||
|
Platform::SetLastPyCall("clipboard_set_text");
|
||||||
|
const char* value;
|
||||||
|
static const char* kwlist[] = {"value", nullptr};
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s",
|
||||||
|
const_cast<char**>(kwlist), &value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
g_platform->ClipboardSetText(value);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
BA_PYTHON_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PyClipboardGetText(PyObject* self) -> PyObject* {
|
||||||
|
BA_PYTHON_TRY;
|
||||||
|
return PyUnicode_FromString(g_platform->ClipboardGetText().c_str());
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
BA_PYTHON_CATCH;
|
||||||
|
}
|
||||||
|
|
||||||
auto PyIsRunningOnOuya(PyObject* self, PyObject* args) -> PyObject* {
|
auto PyIsRunningOnOuya(PyObject* self, PyObject* args) -> PyObject* {
|
||||||
BA_PYTHON_TRY;
|
BA_PYTHON_TRY;
|
||||||
Platform::SetLastPyCall("is_running_on_ouya");
|
Platform::SetLastPyCall("is_running_on_ouya");
|
||||||
@ -743,6 +783,44 @@ auto PyApp(PyObject* self, PyObject* args, PyObject* keywds) -> PyObject* {
|
|||||||
|
|
||||||
auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
|
auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
|
||||||
return {
|
return {
|
||||||
|
{"clipboard_is_supported", (PyCFunction)PyClipboardIsSupported,
|
||||||
|
METH_NOARGS,
|
||||||
|
"clipboard_is_supported() -> bool\n"
|
||||||
|
"\n"
|
||||||
|
"Return whether this platform supports clipboard operations at all.\n"
|
||||||
|
"\n"
|
||||||
|
"Category: General Utility Functions\n"
|
||||||
|
"\n"
|
||||||
|
"If this returns False, UIs should not show 'copy to clipboard'\n"
|
||||||
|
"buttons, etc."},
|
||||||
|
{"clipboard_has_text", (PyCFunction)PyClipboardHasText, METH_NOARGS,
|
||||||
|
"clipboard_has_text() -> bool\n"
|
||||||
|
"\n"
|
||||||
|
"Return whether there is currently text on the clipboard.\n"
|
||||||
|
"\n"
|
||||||
|
"Category: General Utility Functions\n"
|
||||||
|
"\n"
|
||||||
|
"This will return False if no system clipboard is available; no need\n"
|
||||||
|
" to call ba.clipboard_available() separately."},
|
||||||
|
{"clipboard_set_text", (PyCFunction)PyClipboardSetText,
|
||||||
|
METH_VARARGS | METH_KEYWORDS,
|
||||||
|
"clipboard_set_text(value: str) -> None\n"
|
||||||
|
"\n"
|
||||||
|
"Copy a string to the system clipboard.\n"
|
||||||
|
"\n"
|
||||||
|
"Category: General Utility Functions\n"
|
||||||
|
"\n"
|
||||||
|
"Ensure that ba.clipboard_available() returns True before adding\n"
|
||||||
|
" buttons/etc. that make use of this functionality."},
|
||||||
|
{"clipboard_get_text", (PyCFunction)PyClipboardGetText, METH_NOARGS,
|
||||||
|
"clipboard_get_text() -> str\n"
|
||||||
|
"\n"
|
||||||
|
"Return text currently on the system clipboard.\n"
|
||||||
|
"\n"
|
||||||
|
"Category: General Utility Functions\n"
|
||||||
|
"\n"
|
||||||
|
"Ensure that ba.clipboard_has_text() returns True before calling\n"
|
||||||
|
" this function."},
|
||||||
{"printobjects", (PyCFunction)PyPrintObjects,
|
{"printobjects", (PyCFunction)PyPrintObjects,
|
||||||
METH_VARARGS | METH_KEYWORDS,
|
METH_VARARGS | METH_KEYWORDS,
|
||||||
"printobjects() -> None\n"
|
"printobjects() -> None\n"
|
||||||
|
|||||||
@ -2636,14 +2636,14 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
|
|||||||
"are applied to the Widget."},
|
"are applied to the Widget."},
|
||||||
|
|
||||||
{"rowwidget", (PyCFunction)PyRowWidget, METH_VARARGS | METH_KEYWORDS,
|
{"rowwidget", (PyCFunction)PyRowWidget, METH_VARARGS | METH_KEYWORDS,
|
||||||
"rowwidget(edit: Widget = None, parent: Widget = None,\n"
|
"rowwidget(edit: ba.Widget = None, parent: ba.Widget = None,\n"
|
||||||
" size: Sequence[float] = None,\n"
|
" size: Sequence[float] = None,\n"
|
||||||
" position: Sequence[float] = None,\n"
|
" position: Sequence[float] = None,\n"
|
||||||
" background: bool = None, selected_child: Widget = None,\n"
|
" background: bool = None, selected_child: ba.Widget = None,\n"
|
||||||
" visible_child: Widget = None,\n"
|
" visible_child: ba.Widget = None,\n"
|
||||||
" claims_left_right: bool = None,\n"
|
" claims_left_right: bool = None,\n"
|
||||||
" claims_tab: bool = None,\n"
|
" claims_tab: bool = None,\n"
|
||||||
" selection_loops_to_parent: bool = None) -> Widget\n"
|
" selection_loops_to_parent: bool = None) -> ba.Widget\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Create or edit a row widget.\n"
|
"Create or edit a row widget.\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -2699,17 +2699,17 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
|
|||||||
"are applied to the Widget."},
|
"are applied to the Widget."},
|
||||||
|
|
||||||
{"textwidget", (PyCFunction)PyTextWidget, METH_VARARGS | METH_KEYWORDS,
|
{"textwidget", (PyCFunction)PyTextWidget, METH_VARARGS | METH_KEYWORDS,
|
||||||
"textwidget(edit: Widget = None, parent: Widget = None,\n"
|
"textwidget(edit: ba.Widget = None, parent: ba.Widget = None,\n"
|
||||||
" size: Sequence[float] = None, position: Sequence[float] = None,\n"
|
" size: Sequence[float] = None, position: Sequence[float] = None,\n"
|
||||||
" text: Union[str, ba.Lstr] = None, v_align: str = None,\n"
|
" text: Union[str, ba.Lstr] = None, v_align: str = None,\n"
|
||||||
" h_align: str = None, editable: bool = None, padding: float = None,\n"
|
" h_align: str = None, editable: bool = None, padding: float = None,\n"
|
||||||
" on_return_press_call: Callable[[], None] = None,\n"
|
" on_return_press_call: Callable[[], None] = None,\n"
|
||||||
" on_activate_call: Callable[[], None] = None,\n"
|
" on_activate_call: Callable[[], None] = None,\n"
|
||||||
" selectable: bool = None, query: Widget = None, max_chars: int = "
|
" selectable: bool = None, query: ba.Widget = None, max_chars: int = "
|
||||||
"None,\n"
|
"None,\n"
|
||||||
" color: Sequence[float] = None, click_activate: bool = None,\n"
|
" color: Sequence[float] = None, click_activate: bool = None,\n"
|
||||||
" on_select_call: Callable[[], None] = None,\n"
|
" on_select_call: Callable[[], None] = None,\n"
|
||||||
" always_highlight: bool = None, draw_controller: Widget = None,\n"
|
" always_highlight: bool = None, draw_controller: ba.Widget = None,\n"
|
||||||
" scale: float = None, corner_scale: float = None,\n"
|
" scale: float = None, corner_scale: float = None,\n"
|
||||||
" description: Union[str, ba.Lstr] = None,\n"
|
" description: Union[str, ba.Lstr] = None,\n"
|
||||||
" transition_delay: float = None, maxwidth: float = None,\n"
|
" transition_delay: float = None, maxwidth: float = None,\n"
|
||||||
|
|||||||
@ -29,7 +29,7 @@ UI::UI() {
|
|||||||
assert(g_platform);
|
assert(g_platform);
|
||||||
|
|
||||||
// Allow overriding via an environment variable.
|
// Allow overriding via an environment variable.
|
||||||
auto* ui_override = getenv("BA_FORCE_UI_SCALE");
|
auto* ui_override = getenv("BA_UI_SCALE");
|
||||||
bool force_test_small{};
|
bool force_test_small{};
|
||||||
bool force_test_medium{};
|
bool force_test_medium{};
|
||||||
bool force_test_large{};
|
bool force_test_large{};
|
||||||
|
|||||||
@ -296,6 +296,7 @@ auto ContainerWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
|||||||
switch (m.type) {
|
switch (m.type) {
|
||||||
case WidgetMessage::Type::kTextInput:
|
case WidgetMessage::Type::kTextInput:
|
||||||
case WidgetMessage::Type::kKey:
|
case WidgetMessage::Type::kKey:
|
||||||
|
case WidgetMessage::Type::kPaste:
|
||||||
if (selected_widget_) {
|
if (selected_widget_) {
|
||||||
bool val = selected_widget_->HandleMessage(m);
|
bool val = selected_widget_->HandleMessage(m);
|
||||||
if (val != 0) {
|
if (val != 0) {
|
||||||
@ -1218,8 +1219,7 @@ void ContainerWidget::SetTransition(TransitionType t) {
|
|||||||
// stack, update the toolbar for the new topmost input-accepting window
|
// stack, update the toolbar for the new topmost input-accepting window
|
||||||
// *immediately* (otherwise we'd have to wait for our transition to complete
|
// *immediately* (otherwise we'd have to wait for our transition to complete
|
||||||
// before the toolbar switches).
|
// before the toolbar switches).
|
||||||
if (transitioning_ && transitioning_out_ && parent != nullptr
|
if (transitioning_ && transitioning_out_ && parent->is_main_window_stack_) {
|
||||||
&& parent->is_main_window_stack_) {
|
|
||||||
g_ui->root_widget()->UpdateForFocusedWindow();
|
g_ui->root_widget()->UpdateForFocusedWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -116,8 +116,8 @@ void TextWidget::Draw(RenderPass* pass, bool draw_transparent) {
|
|||||||
|
|
||||||
// Center-scale.
|
// Center-scale.
|
||||||
{
|
{
|
||||||
// We should really be scaling our bounds and things, but for now lets just
|
// We should really be scaling our bounds and things,
|
||||||
// do a hacky overall scale.
|
// but for now lets just do a hacky overall scale.
|
||||||
EmptyComponent c(pass);
|
EmptyComponent c(pass);
|
||||||
c.SetTransparent(true);
|
c.SetTransparent(true);
|
||||||
c.PushTransform();
|
c.PushTransform();
|
||||||
@ -178,6 +178,7 @@ void TextWidget::Draw(RenderPass* pass, bool draw_transparent) {
|
|||||||
highlight_center_y_ = b2 - b_border + highlight_height_ * 0.5f;
|
highlight_center_y_ = b2 - b_border + highlight_height_ * 0.5f;
|
||||||
highlight_dirty_ = false;
|
highlight_dirty_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleComponent c(pass);
|
SimpleComponent c(pass);
|
||||||
c.SetTransparent(true);
|
c.SetTransparent(true);
|
||||||
c.SetPremultiplied(true);
|
c.SetPremultiplied(true);
|
||||||
@ -596,6 +597,16 @@ auto TextWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
|||||||
bottom_overlap = 3.0f * extra_touch_border_scale_;
|
bottom_overlap = 3.0f * extra_touch_border_scale_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're doing inline editing, handle clipboard paste.
|
||||||
|
if (editable() && !ShouldUseStringEditDialog()
|
||||||
|
&& m.type == WidgetMessage::Type::kPaste) {
|
||||||
|
if (g_platform->ClipboardIsSupported()) {
|
||||||
|
if (g_platform->ClipboardHasText()) {
|
||||||
|
// Just enter it char by char as if we had typed it...
|
||||||
|
AddCharsToText(g_platform->ClipboardGetText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// If we're doing inline editing, handle some key events.
|
// If we're doing inline editing, handle some key events.
|
||||||
if (m.has_keysym && !ShouldUseStringEditDialog()) {
|
if (m.has_keysym && !ShouldUseStringEditDialog()) {
|
||||||
last_carat_change_time_ = g_game->master_time();
|
last_carat_change_time_ = g_game->master_time();
|
||||||
@ -769,22 +780,7 @@ auto TextWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
|||||||
} else {
|
} else {
|
||||||
// Otherwise apply the text directly.
|
// Otherwise apply the text directly.
|
||||||
if (editable() && m.sval != nullptr) {
|
if (editable() && m.sval != nullptr) {
|
||||||
std::vector<uint32_t> unichars =
|
AddCharsToText(*m.sval);
|
||||||
Utils::UnicodeFromUTF8(text_raw_, "jcjwf8f");
|
|
||||||
int len = static_cast<int>(unichars.size());
|
|
||||||
std::vector<uint32_t> sval =
|
|
||||||
Utils::UnicodeFromUTF8(*m.sval, "j4958fbv");
|
|
||||||
for (unsigned int i : sval) {
|
|
||||||
if (len < max_chars_) {
|
|
||||||
text_group_dirty_ = true;
|
|
||||||
if (carat_position_ > len) carat_position_ = len;
|
|
||||||
unichars.insert(unichars.begin() + carat_position_, i);
|
|
||||||
len++;
|
|
||||||
carat_position_++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text_raw_ = Utils::UTF8FromUnicode(unichars);
|
|
||||||
text_translation_dirty_ = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -794,8 +790,8 @@ auto TextWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
|||||||
if (!IsSelectable()) {
|
if (!IsSelectable()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
float x = m.fval1;
|
float x{ScaleAdjustedX(m.fval1)};
|
||||||
float y = m.fval2;
|
float y{ScaleAdjustedY(m.fval2)};
|
||||||
bool claimed = (m.fval3 > 0.0f);
|
bool claimed = (m.fval3 > 0.0f);
|
||||||
if (claimed) {
|
if (claimed) {
|
||||||
mouse_over_ = clear_mouse_over_ = false;
|
mouse_over_ = clear_mouse_over_ = false;
|
||||||
@ -813,8 +809,9 @@ auto TextWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
|||||||
if (!IsSelectable()) {
|
if (!IsSelectable()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
float x = m.fval1;
|
float x{ScaleAdjustedX(m.fval1)};
|
||||||
float y = m.fval2;
|
float y{ScaleAdjustedY(m.fval2)};
|
||||||
|
|
||||||
auto click_count = static_cast<int>(m.fval3);
|
auto click_count = static_cast<int>(m.fval3);
|
||||||
|
|
||||||
// See if a click is in our clear button.
|
// See if a click is in our clear button.
|
||||||
@ -856,8 +853,8 @@ auto TextWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case WidgetMessage::Type::kMouseUp: {
|
case WidgetMessage::Type::kMouseUp: {
|
||||||
float x = m.fval1;
|
float x{ScaleAdjustedX(m.fval1)};
|
||||||
float y = m.fval2;
|
float y{ScaleAdjustedY(m.fval2)};
|
||||||
bool claimed = (m.fval3 > 0.0f);
|
bool claimed = (m.fval3 > 0.0f);
|
||||||
|
|
||||||
if (clear_pressed_ && !claimed && editable()
|
if (clear_pressed_ && !claimed && editable()
|
||||||
@ -903,6 +900,38 @@ auto TextWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto TextWidget::ScaleAdjustedX(float x) -> float {
|
||||||
|
// Account for our center_scale_ value.
|
||||||
|
float offsx = x - width_ * 0.5f;
|
||||||
|
return width_ * 0.5f + offsx / center_scale_;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto TextWidget::ScaleAdjustedY(float y) -> float {
|
||||||
|
// Account for our center_scale_ value.
|
||||||
|
float offsy = y - height_ * 0.5f;
|
||||||
|
return height_ * 0.5f + offsy / center_scale_;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto TextWidget::AddCharsToText(const std::string& addchars) -> void {
|
||||||
|
assert(editable());
|
||||||
|
std::vector<uint32_t> unichars = Utils::UnicodeFromUTF8(text_raw_, "jcjwf8f");
|
||||||
|
int len = static_cast<int>(unichars.size());
|
||||||
|
std::vector<uint32_t> sval = Utils::UnicodeFromUTF8(addchars, "j4958fbv");
|
||||||
|
for (unsigned int i : sval) {
|
||||||
|
if (len < max_chars_) {
|
||||||
|
text_group_dirty_ = true;
|
||||||
|
if (carat_position_ > len) {
|
||||||
|
carat_position_ = len;
|
||||||
|
}
|
||||||
|
unichars.insert(unichars.begin() + carat_position_, i);
|
||||||
|
len++;
|
||||||
|
carat_position_++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text_raw_ = Utils::UTF8FromUnicode(unichars);
|
||||||
|
text_translation_dirty_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
void TextWidget::UpdateTranslation() {
|
void TextWidget::UpdateTranslation() {
|
||||||
// Apply subs/resources to get our actual text if need be.
|
// Apply subs/resources to get our actual text if need be.
|
||||||
if (text_translation_dirty_) {
|
if (text_translation_dirty_) {
|
||||||
|
|||||||
@ -89,6 +89,9 @@ class TextWidget : public Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
auto ScaleAdjustedX(float x) -> float;
|
||||||
|
auto ScaleAdjustedY(float y) -> float;
|
||||||
|
auto AddCharsToText(const std::string& addchars) -> void;
|
||||||
auto ShouldUseStringEditDialog() const -> bool;
|
auto ShouldUseStringEditDialog() const -> bool;
|
||||||
void BringUpEditDialog();
|
void BringUpEditDialog();
|
||||||
void UpdateTranslation();
|
void UpdateTranslation();
|
||||||
|
|||||||
@ -37,7 +37,8 @@ struct WidgetMessage {
|
|||||||
kMouseWheelVelocityH,
|
kMouseWheelVelocityH,
|
||||||
kMouseMove,
|
kMouseMove,
|
||||||
kScrollMouseDown,
|
kScrollMouseDown,
|
||||||
kTextInput
|
kTextInput,
|
||||||
|
kPaste
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type{};
|
Type type{};
|
||||||
|
|||||||
@ -30,10 +30,10 @@ class PipRequirement:
|
|||||||
|
|
||||||
PIP_REQUIREMENTS = [
|
PIP_REQUIREMENTS = [
|
||||||
PipRequirement(modulename='pylint', minversion=[2, 6, 0]),
|
PipRequirement(modulename='pylint', minversion=[2, 6, 0]),
|
||||||
PipRequirement(modulename='mypy', minversion=[0, 790]),
|
PipRequirement(modulename='mypy', minversion=[0, 800]),
|
||||||
PipRequirement(modulename='yapf', minversion=[0, 30, 0]),
|
PipRequirement(modulename='yapf', minversion=[0, 30, 0]),
|
||||||
PipRequirement(modulename='cpplint', minversion=[1, 5, 4]),
|
PipRequirement(modulename='cpplint', minversion=[1, 5, 4]),
|
||||||
PipRequirement(modulename='pytest', minversion=[6, 1, 2]),
|
PipRequirement(modulename='pytest', minversion=[6, 2, 1]),
|
||||||
PipRequirement(modulename='typing_extensions'),
|
PipRequirement(modulename='typing_extensions'),
|
||||||
PipRequirement(modulename='pytz'),
|
PipRequirement(modulename='pytz'),
|
||||||
PipRequirement(modulename='ansiwrap'),
|
PipRequirement(modulename='ansiwrap'),
|
||||||
|
|||||||
@ -112,7 +112,7 @@ def _windows_enable_color() -> bool:
|
|||||||
# open CONOUT$ instead
|
# open CONOUT$ instead
|
||||||
fdout = os.open('CONOUT$', os.O_RDWR)
|
fdout = os.open('CONOUT$', os.O_RDWR)
|
||||||
try:
|
try:
|
||||||
hout = msvcrt.get_osfhandle(fdout)
|
hout = msvcrt.get_osfhandle(fdout) # type: ignore
|
||||||
old_mode = wintypes.DWORD()
|
old_mode = wintypes.DWORD()
|
||||||
kernel32.GetConsoleMode(hout, ctypes.byref(old_mode))
|
kernel32.GetConsoleMode(hout, ctypes.byref(old_mode))
|
||||||
mode = (new_mode & mask) | (old_mode.value & ~mask)
|
mode = (new_mode & mask) | (old_mode.value & ~mask)
|
||||||
|
|||||||
@ -703,12 +703,10 @@ def _run_idea_inspections(projroot: Path,
|
|||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
# In verbose mode this stuff got printed already.
|
# In verbose mode this stuff got printed already.
|
||||||
if not verbose:
|
if not verbose:
|
||||||
stdout = (
|
stdout = (result.stdout.decode() if isinstance(
|
||||||
result.stdout.decode() if isinstance( # type: ignore
|
result.stdout, bytes) else str(result.stdout))
|
||||||
result.stdout, bytes) else str(result.stdout))
|
stderr = (result.stderr.decode() if isinstance(
|
||||||
stderr = (
|
result.stdout, bytes) else str(result.stdout))
|
||||||
result.stderr.decode() if isinstance( # type: ignore
|
|
||||||
result.stdout, bytes) else str(result.stdout))
|
|
||||||
print(f'{displayname} inspection failure stdout:\n{stdout}' +
|
print(f'{displayname} inspection failure stdout:\n{stdout}' +
|
||||||
f'{displayname} inspection failure stderr:\n{stderr}')
|
f'{displayname} inspection failure stderr:\n{stderr}')
|
||||||
raise RuntimeError(f'{displayname} inspection failed.')
|
raise RuntimeError(f'{displayname} inspection failed.')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user