mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-26 17:03:14 +08:00
Merge branch 'efroemling:main' into main
This commit is contained in:
commit
7741c9ca21
92
.efrocachemap
generated
92
.efrocachemap
generated
@ -421,40 +421,40 @@
|
||||
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
|
||||
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
|
||||
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
|
||||
"build/assets/ba_data/data/langdata.json": "65b989c0d893d8981992f66ff81a8a97",
|
||||
"build/assets/ba_data/data/languages/arabic.json": "3be73283cb8009cc2c95e53df36e8b86",
|
||||
"build/assets/ba_data/data/langdata.json": "fa2cb506dd6628e30b775ca44604e4f8",
|
||||
"build/assets/ba_data/data/languages/arabic.json": "609f5d698a488e40e61787b62ee8ea5e",
|
||||
"build/assets/ba_data/data/languages/belarussian.json": "3d5523d0004293aa2df02f3f6f3b84f8",
|
||||
"build/assets/ba_data/data/languages/chinese.json": "fc69790c41e6750d20a7719afc5a7527",
|
||||
"build/assets/ba_data/data/languages/chinesetraditional.json": "86671be47e2b5d0badeb3b90a3db6402",
|
||||
"build/assets/ba_data/data/languages/chinese.json": "d03ed49486d41cfbdf770e5a54f974a1",
|
||||
"build/assets/ba_data/data/languages/chinesetraditional.json": "d85c58cc1e0e4bd0b09b2bc768cb1971",
|
||||
"build/assets/ba_data/data/languages/croatian.json": "b23619cb396ac16640c47458f884b16a",
|
||||
"build/assets/ba_data/data/languages/czech.json": "61bcfce75c0d53d2f2af709cee42187a",
|
||||
"build/assets/ba_data/data/languages/danish.json": "8e57db30c5250df2abff14a822f83ea7",
|
||||
"build/assets/ba_data/data/languages/dutch.json": "b0900d572c9141897d53d6574c471343",
|
||||
"build/assets/ba_data/data/languages/english.json": "5a73dea22df1117d58a79459def62ff5",
|
||||
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
|
||||
"build/assets/ba_data/data/languages/filipino.json": "a291d4d3619adc82c5c4096bbfefe28a",
|
||||
"build/assets/ba_data/data/languages/french.json": "73a01df9b44b3fb030750a1b5f56f07b",
|
||||
"build/assets/ba_data/data/languages/german.json": "198b9860c5b9df7b8e3e30b03d8755cb",
|
||||
"build/assets/ba_data/data/languages/filipino.json": "30f9622136067fe866bebf7e81ee8546",
|
||||
"build/assets/ba_data/data/languages/french.json": "69578cc38349367912659a62ace5a42d",
|
||||
"build/assets/ba_data/data/languages/german.json": "c4b8c4d3c078b7902155af3221cf9cf4",
|
||||
"build/assets/ba_data/data/languages/gibberish.json": "d6810f99fc9055b5203c382a83bc5128",
|
||||
"build/assets/ba_data/data/languages/greek.json": "d28d1092fbb00ed857cbd53124c0dc78",
|
||||
"build/assets/ba_data/data/languages/hindi.json": "54cd56bade6922b40989a8ac5e0c17f6",
|
||||
"build/assets/ba_data/data/languages/hungarian.json": "3a974ea6e6ffccca41aed308ad5a7a26",
|
||||
"build/assets/ba_data/data/languages/indonesian.json": "ed9038bf4b9216f93eb73e753e162706",
|
||||
"build/assets/ba_data/data/languages/italian.json": "ffc58952260b63fdf88805a2d9a68257",
|
||||
"build/assets/ba_data/data/languages/hungarian.json": "9d88004a98f0fbe2ea72edd5e0b3002e",
|
||||
"build/assets/ba_data/data/languages/indonesian.json": "2ccb3fe081ead7706dbebb1008a8bc4e",
|
||||
"build/assets/ba_data/data/languages/italian.json": "d9eb41f6eafb19040f8d5c0608790b62",
|
||||
"build/assets/ba_data/data/languages/korean.json": "4e3524327a0174250aff5e1ef4c0c597",
|
||||
"build/assets/ba_data/data/languages/malay.json": "f6ce0426d03a62612e3e436ed5d1be1f",
|
||||
"build/assets/ba_data/data/languages/persian.json": "ededb9c015afb58b1324a096ea740f72",
|
||||
"build/assets/ba_data/data/languages/polish.json": "62b56ace320191985689bfbcfacd56ea",
|
||||
"build/assets/ba_data/data/languages/portuguese.json": "2be5c25e55946197bd0e0f646d444b2c",
|
||||
"build/assets/ba_data/data/languages/polish.json": "89333fb207f9eb2f22fff5a95b022c35",
|
||||
"build/assets/ba_data/data/languages/portuguese.json": "eb2563e245e1ea00b870264dced3ebd7",
|
||||
"build/assets/ba_data/data/languages/romanian.json": "55a8744e466801013ea131266a856924",
|
||||
"build/assets/ba_data/data/languages/russian.json": "c7c5bfc6f82d74e49ac746d187314ba7",
|
||||
"build/assets/ba_data/data/languages/russian.json": "0fcc60bf1e8e19a74f02b0798728ec68",
|
||||
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
|
||||
"build/assets/ba_data/data/languages/slovak.json": "3c08c748c96c71bd9e1d7291fb8817b6",
|
||||
"build/assets/ba_data/data/languages/spanish.json": "4b262447f703eb4c6683b54af6b7b592",
|
||||
"build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac",
|
||||
"build/assets/ba_data/data/languages/tamil.json": "5ececa2dde2bbe33ad61e580fa5b79ad",
|
||||
"build/assets/ba_data/data/languages/spanish.json": "0a37387183a6634fc8e9ac225fcf20b1",
|
||||
"build/assets/ba_data/data/languages/swedish.json": "039c803fad78f1018ad363d2a0be8582",
|
||||
"build/assets/ba_data/data/languages/tamil.json": "ead39b864228696a9b0d19344bc4b5ec",
|
||||
"build/assets/ba_data/data/languages/thai.json": "1d665629361f302693dead39de8fa945",
|
||||
"build/assets/ba_data/data/languages/turkish.json": "1c0a5c0c0c115107fb0752c92907f584",
|
||||
"build/assets/ba_data/data/languages/turkish.json": "6153ca5248b8e4743e9501ac72378493",
|
||||
"build/assets/ba_data/data/languages/ukrainian.json": "23a98e5722d3e71e809a8a0063daa603",
|
||||
"build/assets/ba_data/data/languages/venetian.json": "a1315f5233ebbee1464683ac55d5d9d5",
|
||||
"build/assets/ba_data/data/languages/vietnamese.json": "5ae84265600b6cfda45c9bed18724e1d",
|
||||
@ -4096,26 +4096,26 @@
|
||||
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
|
||||
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
|
||||
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "fa2f9a37401974a330f6406bfdde195a",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "ec0ca83cb8d63837d86024926a9f5792",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "22e11f5d894e02b521f1c77a3b1d14ad",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "803d4449de9e62bc33d62edaccb3a40c",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "5ee49f99993e6f690c955bf4e22ea232",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "f6882aef1cf0c4ab6a4d71b19e048ea3",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2de6855febbe3fefbd1a696e54ff198c",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "76fff0d53458ff9308ee9050bfe42321",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "4b0f3502089e9a7ea6ea2db0c44ecee9",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "d426ae451363579868ed80e070ee1a7d",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "147e64e814f72846d5f78944df85f879",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0e28cef28d1097cd61c1faa2f18b900d",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "213712de0e2e9c5fcbaf9b2cebd92ff7",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "34122e2302160ce65f4ac624e6b40876",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "09f8466080d70d84c15d697a659c6561",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ad91f8448f3106a7d81f2615ab82d71c",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "6a369680967a22140b9a5d3dd65cfd65",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "eb2ccde783e4e7abaf40a76ed0be4a0c",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "112881e2d4429018dc5487a979d53a80",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "04b1f16241efd35e95ff544de09f3444",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "41a98f2ff00b086a13012b1d41b1b679",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "355efd9eb200adc050f8bf7280bf4ab7",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "99c968cdd2834d4ca0d8cfc1a5a45032",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "d6022d622fe97ca1f53ec82ab7760ba5",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "d940e7a52de205056f514dfb607ae7c2",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "70103854eb9efefbec06170eb180f0b2",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "bce00b851d23d89f79b4fddfdffc450b",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "cd129a1ee5f40d29885b151d7e03c1c9",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "49e4475f1042319638a1ac153179df29",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "82b1318e7502523952b53079298bc8f8",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "1db1588dcd7b6e0f363d136c560c6972",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "24df70b13ce76cb2e7e5a9764c5cbb60",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "5911060f6e9d00c5e2094808892e5498",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "bc46e5358dca0bbf898a3ddb653877e2",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "ceebd7928536a2168e13b2978cbe0f86",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "e42ef061ab1226560cfe85ff211cea73",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "d7aa5a88ad0b480429356b9d864f4cc4",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "ea44279e480430ce8bffbe5ea1c3ac9c",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d4516c60d83688126ae0c525f5860e1c",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "36c639448372b428d361ad1b11b54754",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "fa659b5d6119acba6570c92ce4d35ae2",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c",
|
||||
@ -4132,16 +4132,16 @@
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1659535e95e3047fda529543e265ac97",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "599167b1b452e9a060475c059ebb742e",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "4495e25c4e6e286ebe0ac547c3c785e5",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "ee961522b1a726d982df90d35178f4df",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "de121ab71098df1ff6a9b72b46c30401",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "6319a5f16af08ad8cd396472e623b4e1",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "1464b16e286fc6379aa6e9d8d7b7ddaa",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "64c3bce65d48d16c7b0f5f59105a8856",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "a10c2110bb0155790ddc49a44388ba4c",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "9b192a30bda69790d0b64f91f5e0994f",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "663e75e5c4ef1e7600508bba725c0bc1",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "468ba57dc9006630c0c3c65f660c45cf",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "59e48b3aaca43e98a74c2147a5235c78",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "8219f3131e89ff059d0524d6fbe76e73",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "24254f5fa2d8389a58a86c035a757254",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "cf0bd162dbb597c8f86739547f3cea79",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "85e3392a2b6a05f66eb43efc3045826b",
|
||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
|
||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "cb299985623bbcc86015cb103a424ae6",
|
||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "97efb93f4bfd8e8b09f2db24398e29fc",
|
||||
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",
|
||||
|
||||
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,4 +1,4 @@
|
||||
### 1.7.37 (build 21986, api 9, 2024-09-04)
|
||||
### 1.7.37 (build 22004, api 9, 2024-09-05)
|
||||
- Bumping api version to 9. As you'll see below, there's some UI changes that
|
||||
will require a bit of work for any UI mods to adapt to. If your mods don't
|
||||
touch UI stuff at all you can simply bump your api version and call it a day.
|
||||
@ -36,6 +36,8 @@
|
||||
was to add a higher level layer to the UI to make things like saving/restoring
|
||||
UI states easier, but I now plan to use `WindowState` classes to accomplish
|
||||
much of that in a more backward-compatible way. More on that below.
|
||||
- Removed touch-specific button target-area adjustements. If you find any
|
||||
buttons that are hard to hit accurately on a touchscreen, please holler.
|
||||
- Added a new `bauiv1.Window` subclass called `bauiv1.MainWindow` which handles
|
||||
what was previously called the 'main-menu-window' system which was a bit
|
||||
ad-hoc and messy. MainMenuWindows have a built-in stack system so things like
|
||||
@ -80,6 +82,14 @@
|
||||
- Removed `efro.util.enum_by_value()` which was a workaround for a Python bug
|
||||
that has been fixed for a few versions now. Instaed of
|
||||
`enum_by_value(MyEnumType, foo)` you can simply do `MyEnumType(foo)`.
|
||||
- Removed `bauiv1.is_party_icon_visible()` as it is now always visible.
|
||||
- 'ui_scale' is no longer available in _babase.env() since it can now change;
|
||||
use `babase.get_ui_scale()` to get it now.
|
||||
- Removed the UIScale control from the devtools window, which was only partially
|
||||
wired up (it did not affect native layer bits). For now the official ways to
|
||||
test UIScales are by using the UI panel in the dev-console or by setting the
|
||||
`BA_UI_SCALE` env var. If we can get UIScale switches to feel seamless enough
|
||||
at some point, it may be worth adding to display settings.
|
||||
|
||||
### 1.7.36 (build 21944, api 8, 2024-07-26)
|
||||
- Wired up Tokens, BombSquad's new purchasable currency. The first thing these
|
||||
|
||||
@ -17,6 +17,6 @@ Sphinx==8.0.2
|
||||
tomlkit==0.13.2
|
||||
types-certifi==2021.10.8.3
|
||||
types-filelock==3.2.7
|
||||
types-requests==2.32.0.20240712
|
||||
types-requests==2.32.0.20240905
|
||||
typing_extensions==4.12.2
|
||||
urllib3==2.2.2
|
||||
|
||||
@ -56,6 +56,7 @@ from _babase import (
|
||||
get_replays_dir,
|
||||
get_string_height,
|
||||
get_string_width,
|
||||
get_ui_scale,
|
||||
get_v1_cloud_log_file_path,
|
||||
getsimplesound,
|
||||
has_user_run_commands,
|
||||
@ -99,6 +100,7 @@ from _babase import (
|
||||
set_low_level_config_value,
|
||||
set_thread_name,
|
||||
set_ui_input_device,
|
||||
set_ui_scale,
|
||||
show_progress_bar,
|
||||
shutdown_suppress_begin,
|
||||
shutdown_suppress_end,
|
||||
@ -254,8 +256,9 @@ __all__ = [
|
||||
'get_replays_dir',
|
||||
'get_string_height',
|
||||
'get_string_width',
|
||||
'get_v1_cloud_log_file_path',
|
||||
'get_type_name',
|
||||
'get_ui_scale',
|
||||
'get_v1_cloud_log_file_path',
|
||||
'getclass',
|
||||
'getsimplesound',
|
||||
'handle_leftover_v1_cloud_log_file',
|
||||
@ -325,6 +328,7 @@ __all__ = [
|
||||
'set_low_level_config_value',
|
||||
'set_thread_name',
|
||||
'set_ui_input_device',
|
||||
'set_ui_scale',
|
||||
'show_progress_bar',
|
||||
'shutdown_suppress_begin',
|
||||
'shutdown_suppress_end',
|
||||
|
||||
@ -629,6 +629,29 @@ class App:
|
||||
self._initial_sign_in_completed = True
|
||||
self._update_state()
|
||||
|
||||
def set_ui_scale(self, scale: babase.UIScale) -> None:
|
||||
"""Change ui-scale on the fly.
|
||||
|
||||
Currently this is mainly for debugging and will not
|
||||
be called as part of normal app operation.
|
||||
"""
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
# Apply to the native layer.
|
||||
_babase.set_ui_scale(scale.name.lower())
|
||||
|
||||
# Inform all subsystems that something screen-related has
|
||||
# changed. We assume subsystems won't be added at this point so
|
||||
# we can use the list directly.
|
||||
assert self._subsystem_registration_ended
|
||||
for subsystem in self._subsystems:
|
||||
try:
|
||||
subsystem.on_screen_change()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_screen_change() for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
def _set_intent(self, intent: AppIntent) -> None:
|
||||
from babase._appmode import AppMode
|
||||
|
||||
@ -718,7 +741,7 @@ class App:
|
||||
subsystem.reset()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in reset for subsystem %s.', subsystem
|
||||
'Error in reset() for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
self._mode = mode
|
||||
@ -805,7 +828,7 @@ class App:
|
||||
subsystem.on_app_loading()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_loading for subsystem %s.', subsystem
|
||||
'Error in on_app_loading() for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
# Normally plus tells us when initial sign-in is done. If plus
|
||||
@ -854,7 +877,7 @@ class App:
|
||||
subsystem.on_app_running()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_running for subsystem %s.', subsystem
|
||||
'Error in on_app_running() for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
# Cut off new subsystem additions at this point.
|
||||
@ -890,7 +913,8 @@ class App:
|
||||
subsystem.do_apply_app_config()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in do_apply_app_config for subsystem %s.', subsystem
|
||||
'Error in do_apply_app_config() for subsystem %s.',
|
||||
subsystem,
|
||||
)
|
||||
|
||||
# Let the native layer do its thing.
|
||||
@ -1013,7 +1037,7 @@ class App:
|
||||
subsystem.on_app_suspend()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_suspend for subsystem %s.', subsystem
|
||||
'Error in on_app_suspend() for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
def _on_unsuspend(self) -> None:
|
||||
@ -1027,7 +1051,7 @@ class App:
|
||||
subsystem.on_app_unsuspend()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_unsuspend for subsystem %s.', subsystem
|
||||
'Error in on_app_unsuspend() for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
def _on_shutting_down(self) -> None:
|
||||
@ -1041,7 +1065,7 @@ class App:
|
||||
subsystem.on_app_shutdown()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_shutdown for subsystem %s.', subsystem
|
||||
'Error in on_app_shutdown() for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
# Now kick off any async shutdown task(s).
|
||||
@ -1059,7 +1083,7 @@ class App:
|
||||
subsystem.on_app_shutdown_complete()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_shutdown_complete for subsystem %s.',
|
||||
'Error in on_app_shutdown_complete() for subsystem %s.',
|
||||
subsystem,
|
||||
)
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING
|
||||
import _babase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
from babase import UIScale
|
||||
|
||||
|
||||
class AppSubsystem:
|
||||
@ -54,6 +54,9 @@ class AppSubsystem:
|
||||
def do_apply_app_config(self) -> None:
|
||||
"""Called when the app config should be applied."""
|
||||
|
||||
def on_screen_change(self) -> None:
|
||||
"""Called when screen dimensions or ui-scale changes."""
|
||||
|
||||
def reset(self) -> None:
|
||||
"""Reset the subsystem to a default state.
|
||||
|
||||
|
||||
@ -4,16 +4,17 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import TYPE_CHECKING, override
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
from functools import partial
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
import _babase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable, Any, Literal
|
||||
|
||||
from babase import AppMode
|
||||
from babase import AppMode, UIScale
|
||||
|
||||
|
||||
class DevConsoleTab:
|
||||
@ -35,7 +36,7 @@ class DevConsoleTab:
|
||||
h_anchor: Literal['left', 'center', 'right'] = 'center',
|
||||
label_scale: float = 1.0,
|
||||
corner_radius: float = 8.0,
|
||||
style: Literal['normal', 'dark'] = 'normal',
|
||||
style: Literal['normal', 'light'] = 'normal',
|
||||
) -> None:
|
||||
"""Add a button to the tab being refreshed."""
|
||||
assert _babase.app.devconsole.is_refreshing
|
||||
@ -108,7 +109,6 @@ class DevConsoleTabAppModes(DevConsoleTab):
|
||||
|
||||
@override
|
||||
def refresh(self) -> None:
|
||||
from functools import partial
|
||||
|
||||
modes = _babase.app.mode_selector.testable_app_modes()
|
||||
self.text(
|
||||
@ -150,31 +150,43 @@ class DevConsoleTabUI(DevConsoleTab):
|
||||
|
||||
@override
|
||||
def refresh(self) -> None:
|
||||
from babase._mgen.enums import UIScale
|
||||
|
||||
# self.text(
|
||||
# 'UI Testing',
|
||||
# scale=0.8,
|
||||
# pos=(15, 77),
|
||||
# h_anchor='left',
|
||||
# h_align='left',
|
||||
# v_align='center',
|
||||
# )
|
||||
self.text(
|
||||
'UI Testing: Make sure all static UI fits in the'
|
||||
' virtual screen at all UI scales (not counting things'
|
||||
' that follow screen edges).',
|
||||
scale=0.8,
|
||||
pos=(15, 55),
|
||||
'Make sure all interactive UI fits in the'
|
||||
' virtual bounds at all UI-scales (not counting things'
|
||||
' that follow screen edges).\n'
|
||||
'Note that some elements may not reflect UI-scale changes'
|
||||
' until recreated.',
|
||||
scale=0.6,
|
||||
pos=(15, 70),
|
||||
h_anchor='left',
|
||||
h_align='left',
|
||||
v_align='none',
|
||||
v_align='center',
|
||||
)
|
||||
|
||||
ui_overlay = _babase.get_draw_ui_bounds()
|
||||
self.button(
|
||||
'Hide Virtual Screen' if ui_overlay else 'Show Virtual Screen',
|
||||
'Virtual Bounds ON' if ui_overlay else 'Virtual Bounds OFF',
|
||||
pos=(10, 10),
|
||||
size=(200, 30),
|
||||
h_anchor='left',
|
||||
label_scale=0.6,
|
||||
call=self.toggle_ui_overlay,
|
||||
style='light' if ui_overlay else 'normal',
|
||||
)
|
||||
x = 320
|
||||
x = 300
|
||||
self.text(
|
||||
'UI Scale:',
|
||||
pos=(x - 10, 15),
|
||||
'UI-Scale',
|
||||
pos=(x - 5, 15),
|
||||
h_anchor='left',
|
||||
h_align='right',
|
||||
v_align='none',
|
||||
@ -182,16 +194,21 @@ class DevConsoleTabUI(DevConsoleTab):
|
||||
)
|
||||
|
||||
bwidth = 100
|
||||
for sz in ('small', 'medium', 'large'):
|
||||
for scale in UIScale:
|
||||
self.button(
|
||||
sz,
|
||||
scale.name.capitalize(),
|
||||
pos=(x, 10),
|
||||
size=(bwidth, 30),
|
||||
h_anchor='left',
|
||||
label_scale=0.6,
|
||||
call=lambda: _babase.screenmessage('UNDER CONSTRUCTION.'),
|
||||
call=partial(_babase.app.set_ui_scale, scale),
|
||||
style=(
|
||||
'light'
|
||||
if scale.name.lower() == _babase.get_ui_scale()
|
||||
else 'normal'
|
||||
),
|
||||
)
|
||||
x += bwidth + 10
|
||||
x += bwidth + 2
|
||||
|
||||
def toggle_ui_overlay(self) -> None:
|
||||
"""Toggle UI overlay drawing."""
|
||||
@ -220,7 +237,7 @@ class DevConsoleTabTest(DevConsoleTab):
|
||||
size=(100, 30),
|
||||
h_anchor='left',
|
||||
label_scale=0.6,
|
||||
style='dark',
|
||||
style='light',
|
||||
)
|
||||
self.text(
|
||||
'TestText',
|
||||
|
||||
@ -49,6 +49,8 @@ class ClassicAppMode(AppMode):
|
||||
|
||||
@override
|
||||
def on_activate(self) -> None:
|
||||
print('CLASSIC ACTIVATING')
|
||||
|
||||
# Let the native layer do its thing.
|
||||
_baclassic.classic_app_mode_activate()
|
||||
|
||||
@ -108,6 +110,7 @@ class ClassicAppMode(AppMode):
|
||||
|
||||
@override
|
||||
def on_deactivate(self) -> None:
|
||||
print('CLASSIC DEACTIVATING')
|
||||
# Let the native layer do its thing.
|
||||
_baclassic.classic_app_mode_deactivate()
|
||||
|
||||
|
||||
@ -819,6 +819,8 @@ class ClassicAppSubsystem(babase.AppSubsystem):
|
||||
|
||||
def invoke_main_menu_ui(self) -> None:
|
||||
"""Bring up main menu ui."""
|
||||
print('INVOKING MAIN MENU UI')
|
||||
|
||||
# Bring up the last place we were, or start at the main menu otherwise.
|
||||
app = bauiv1.app
|
||||
env = app.env
|
||||
@ -830,18 +832,15 @@ class ClassicAppSubsystem(babase.AppSubsystem):
|
||||
# UI stuff fails now in headless builds; avoid it.
|
||||
pass
|
||||
else:
|
||||
# main_menu_location = (
|
||||
# bascenev1.app.ui_v1.get_main_menu_location()
|
||||
# )
|
||||
|
||||
# When coming back from a kiosk-mode game, jump to
|
||||
# the kiosk start screen.
|
||||
# When coming back from a kiosk-mode game, jump to the
|
||||
# kiosk start screen.
|
||||
if env.demo or env.arcade:
|
||||
# pylint: disable=cyclic-import
|
||||
from bauiv1lib.kiosk import KioskWindow
|
||||
|
||||
app.ui_v1.set_main_window(
|
||||
KioskWindow(), from_window=False # Disable check here.
|
||||
KioskWindow(), is_top_level=True, suppress_warning=True
|
||||
)
|
||||
# ..or in normal cases go back to the main menu
|
||||
else:
|
||||
@ -912,17 +911,3 @@ class ClassicAppSubsystem(babase.AppSubsystem):
|
||||
is_top_level=True,
|
||||
suppress_warning=True,
|
||||
)
|
||||
|
||||
# attempt to show any pending offers immediately.
|
||||
# If that doesn't work, try again in a few seconds
|
||||
# (we may not have heard back from the server)
|
||||
# ..if that doesn't work they'll just have to wait
|
||||
# until the next opportunity.
|
||||
# if not specialoffer.show_offer():
|
||||
|
||||
# def try_again() -> None:
|
||||
# if not specialoffer.show_offer():
|
||||
# # Try one last time..
|
||||
# bauiv1.apptimer(2.0, specialoffer.show_offer)
|
||||
|
||||
# bauiv1.apptimer(2.0, try_again)
|
||||
|
||||
@ -52,7 +52,7 @@ if TYPE_CHECKING:
|
||||
|
||||
# Build number and version of the ballistica binary we expect to be
|
||||
# using.
|
||||
TARGET_BALLISTICA_BUILD = 21986
|
||||
TARGET_BALLISTICA_BUILD = 22004
|
||||
TARGET_BALLISTICA_VERSION = '1.7.37'
|
||||
|
||||
|
||||
|
||||
@ -64,44 +64,6 @@ class GameActivity(Activity[PlayerT, TeamT]):
|
||||
# (unless overridden by the map).
|
||||
default_music: bascenev1.MusicType | None = None
|
||||
|
||||
# @classmethod
|
||||
# def create_settings_ui(
|
||||
# cls,
|
||||
# sessiontype: type[bascenev1.Session],
|
||||
# settings: dict | None,
|
||||
# completion_call: Callable[[dict | None], None],
|
||||
# ) -> None:
|
||||
# """Launch an in-game UI to configure settings for a game type.
|
||||
|
||||
# 'sessiontype' should be the bascenev1.Session class the game will
|
||||
# be used in.
|
||||
|
||||
# 'settings' should be an existing settings dict (implies 'edit'
|
||||
# ui mode) or None (implies 'add' ui mode).
|
||||
|
||||
# 'completion_call' will be called with a filled-out settings dict on
|
||||
# success or None on cancel.
|
||||
|
||||
# Generally subclasses don't need to override this; if they override
|
||||
# bascenev1.GameActivity.get_available_settings() and
|
||||
# bascenev1.GameActivity.get_supported_maps() they can just rely on
|
||||
# the default implementation here which calls those methods.
|
||||
# """
|
||||
# # pylint: disable=cyclic-import
|
||||
# from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
||||
|
||||
# assert babase.app.classic is not None
|
||||
# babase.app.ui_v1.clear_main_window()
|
||||
# babase.app.ui_v1.set_main_window(
|
||||
# PlaylistEditGameWindow(
|
||||
# cls,
|
||||
# sessiontype,
|
||||
# settings,
|
||||
# completion_call=completion_call,
|
||||
# ),
|
||||
# from_window=False, # Disable check since we don't know.
|
||||
# )
|
||||
|
||||
@classmethod
|
||||
def getscoreconfig(cls) -> bascenev1.ScoreConfig:
|
||||
"""Return info about game scoring setup; can be overridden by games."""
|
||||
|
||||
@ -111,7 +111,6 @@ from _bauiv1 import (
|
||||
gettexture,
|
||||
hscrollwidget,
|
||||
imagewidget,
|
||||
is_party_icon_visible,
|
||||
Mesh,
|
||||
rowwidget,
|
||||
scrollwidget,
|
||||
@ -192,7 +191,6 @@ __all__ = [
|
||||
'in_main_menu',
|
||||
'increment_analytics_count',
|
||||
'is_browser_likely_available',
|
||||
'is_party_icon_visible',
|
||||
'is_xcode_build',
|
||||
'Keyboard',
|
||||
'lock_all_input',
|
||||
|
||||
@ -61,7 +61,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
from bauiv1._uitypes import MainWindow
|
||||
|
||||
super().__init__()
|
||||
env = babase.env()
|
||||
|
||||
# We hold only a weak ref to the current main Window; we want it
|
||||
# to be able to disappear on its own. That being said, we do
|
||||
@ -72,18 +71,28 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
|
||||
self.quit_window: bauiv1.Widget | None = None
|
||||
|
||||
# The following should probably go away or move to classic.
|
||||
# self._main_menu_location: str | None = None
|
||||
|
||||
# For storing arbitrary class-level state data for Windows or
|
||||
# other UI related classes.
|
||||
self.window_states: dict[type, Any] = {}
|
||||
|
||||
uiscalestr = babase.app.config.get('UI Scale', env['ui_scale'])
|
||||
if uiscalestr == 'auto':
|
||||
uiscalestr = env['ui_scale']
|
||||
|
||||
self._uiscale: babase.UIScale
|
||||
self._update_ui_scale()
|
||||
|
||||
self.cleanupchecks: list[UICleanupCheck] = []
|
||||
self.upkeeptimer: babase.AppTimer | None = None
|
||||
|
||||
self.title_color = (0.72, 0.7, 0.75)
|
||||
self.heading_color = (0.72, 0.7, 0.75)
|
||||
self.infotextcolor = (0.7, 0.9, 0.7)
|
||||
|
||||
# Elements in our root UI will call anything here when
|
||||
# activated.
|
||||
self.root_ui_calls: dict[
|
||||
UIV1AppSubsystem.RootUIElement, Callable[[], None]
|
||||
] = {}
|
||||
|
||||
def _update_ui_scale(self) -> None:
|
||||
uiscalestr = babase.get_ui_scale()
|
||||
if uiscalestr == 'large':
|
||||
self._uiscale = babase.UIScale.LARGE
|
||||
elif uiscalestr == 'medium':
|
||||
@ -94,18 +103,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
logging.error("Invalid UIScale '%s'.", uiscalestr)
|
||||
self._uiscale = babase.UIScale.MEDIUM
|
||||
|
||||
self.cleanupchecks: list[UICleanupCheck] = []
|
||||
self.upkeeptimer: babase.AppTimer | None = None
|
||||
|
||||
self.title_color = (0.72, 0.7, 0.75)
|
||||
self.heading_color = (0.72, 0.7, 0.75)
|
||||
self.infotextcolor = (0.7, 0.9, 0.7)
|
||||
|
||||
# Elements in our root UI will call anything here when activated.
|
||||
self.root_ui_calls: dict[
|
||||
UIV1AppSubsystem.RootUIElement, Callable[[], None]
|
||||
] = {}
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Can uiv1 currently be used?
|
||||
@ -133,20 +130,20 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
def on_app_loading(self) -> None:
|
||||
from bauiv1._uitypes import ui_upkeep
|
||||
|
||||
# IMPORTANT: If tweaking UI stuff, make sure it behaves for small,
|
||||
# medium, and large UI modes. (doesn't run off screen, etc).
|
||||
# The overrides below can be used to test with different sizes.
|
||||
# Generally small is used on phones, medium is used on tablets/tvs,
|
||||
# and large is on desktop computers or perhaps large tablets. When
|
||||
# possible, run in windowed mode and resize the window to assure
|
||||
# this holds true at all aspect ratios.
|
||||
# IMPORTANT: If tweaking UI stuff, make sure it behaves for
|
||||
# small, medium, and large UI modes. (doesn't run off screen,
|
||||
# etc). The overrides below can be used to test with different
|
||||
# sizes. Generally small is used on phones, medium is used on
|
||||
# tablets/tvs, and large is on desktop computers or perhaps
|
||||
# large tablets. When possible, run in windowed mode and resize
|
||||
# the window to assure this holds true at all aspect ratios.
|
||||
|
||||
# UPDATE: A better way to test this is now by setting the environment
|
||||
# variable BA_UI_SCALE to "small", "medium", or "large".
|
||||
# This will affect system UIs not covered by the values below such
|
||||
# as screen-messages. The below values remain functional, however,
|
||||
# for cases such as Android where environment variables can't be set
|
||||
# easily.
|
||||
# UPDATE: A better way to test this is now by setting the
|
||||
# environment variable BA_UI_SCALE to "small", "medium", or
|
||||
# "large". This will affect system UIs not covered by the values
|
||||
# below such as screen-messages. The below values remain
|
||||
# functional, however, for cases such as Android where
|
||||
# environment variables can't be set easily.
|
||||
|
||||
if bool(False): # force-test ui scale
|
||||
self._uiscale = babase.UIScale.SMALL
|
||||
@ -160,7 +157,9 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
)
|
||||
|
||||
# Kick off our periodic UI upkeep.
|
||||
# FIXME: Can probably kill this if we do immediate UI death checks.
|
||||
|
||||
# FIXME: Can probably kill this if we do immediate UI death
|
||||
# checks.
|
||||
self.upkeeptimer = babase.AppTimer(2.6543, ui_upkeep, repeat=True)
|
||||
|
||||
def auto_set_back_window(self, from_window: MainWindow) -> None:
|
||||
@ -181,11 +180,12 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
f'Main window {main_window} provides no back-state;'
|
||||
f' cannot use auto-back.'
|
||||
)
|
||||
backwin = back_state.create_window(transition='in_left')
|
||||
|
||||
# Properly created state should have a value here.
|
||||
# Valid states should have a value here.
|
||||
assert back_state.is_top_level is not None
|
||||
|
||||
backwin = back_state.create_window(transition='in_left')
|
||||
|
||||
self.set_main_window(
|
||||
backwin,
|
||||
from_window=from_window,
|
||||
@ -213,7 +213,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
MainWindow methods main_window_replace() and main_window_back()
|
||||
should be used when possible for navigation.
|
||||
"""
|
||||
# pylint: disable=too-many-locals
|
||||
# pylint: disable=too-many-branches
|
||||
# pylint: disable=too-many-statements
|
||||
from bauiv1._uitypes import MainWindow
|
||||
@ -275,8 +274,8 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
try:
|
||||
if isinstance(from_window, bool):
|
||||
# For default val True we warn that the arg wasn't
|
||||
# passed. False can be explicitly passed to disable this
|
||||
# check.
|
||||
# passed. False can be explicitly passed to disable
|
||||
# this check.
|
||||
if from_window is True:
|
||||
caller_frame = inspect.stack()[1]
|
||||
caller_filename = caller_frame.filename
|
||||
@ -289,8 +288,8 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
caller_line_number,
|
||||
)
|
||||
else:
|
||||
# For everything else, warn if what they passed wasn't
|
||||
# the previous main menu widget.
|
||||
# For everything else, warn if what they passed
|
||||
# wasn't the previous main menu widget.
|
||||
if from_window is not existing:
|
||||
caller_frame = inspect.stack()[1]
|
||||
caller_filename = caller_frame.filename
|
||||
@ -344,12 +343,9 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
)
|
||||
window.main_window_back_state = None
|
||||
else:
|
||||
oldwinstate = oldwin.get_main_window_state()
|
||||
|
||||
# Store some common window stuff on its state.
|
||||
oldwinstate.parent = oldwin.main_window_back_state
|
||||
oldwinstate.is_top_level = oldwin.main_window_is_top_level
|
||||
window.main_window_back_state = oldwinstate
|
||||
window.main_window_back_state = self.save_main_window_state(
|
||||
oldwin
|
||||
)
|
||||
|
||||
self._main_window = window_weakref
|
||||
self._main_window_widget = window_widget
|
||||
@ -376,3 +372,52 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
||||
|
||||
self._main_window = empty_weakref(MainWindow)
|
||||
self._main_window_widget = None
|
||||
|
||||
def save_main_window_state(self, window: MainWindow) -> MainWindowState:
|
||||
"""Fully initialize a window-state from a window.
|
||||
|
||||
Use this to get a state for later restoration purposes.
|
||||
Calling the window's get_main_window_state() directly is
|
||||
insufficient.
|
||||
"""
|
||||
winstate = window.get_main_window_state()
|
||||
|
||||
# Store some common window stuff on its state.
|
||||
winstate.parent = window.main_window_back_state
|
||||
winstate.is_top_level = window.main_window_is_top_level
|
||||
|
||||
return winstate
|
||||
|
||||
def restore_main_window_state(self, state: MainWindowState) -> None:
|
||||
"""Restore UI to a saved state."""
|
||||
existing = self.get_main_window()
|
||||
if existing is not None:
|
||||
raise RuntimeError('There is already a MainWindow.')
|
||||
|
||||
# Valid states should have a value here.
|
||||
assert state.is_top_level is not None
|
||||
|
||||
win = state.create_window(transition=None)
|
||||
self.set_main_window(
|
||||
win,
|
||||
from_window=False, # disable check
|
||||
is_top_level=state.is_top_level,
|
||||
back_state=state.parent,
|
||||
suppress_warning=True,
|
||||
)
|
||||
|
||||
@override
|
||||
def on_screen_change(self) -> None:
|
||||
# Update our stored UIScale.
|
||||
self._update_ui_scale()
|
||||
|
||||
# Update native bits (allow root widget to rebuild itself/etc.)
|
||||
_bauiv1.on_screen_change()
|
||||
|
||||
# Lastly, if we have a main window, recreate it to pick up the
|
||||
# new UIScale/etc.
|
||||
mainwindow = self.get_main_window()
|
||||
if mainwindow is not None:
|
||||
winstate = self.save_main_window_state(mainwindow)
|
||||
self.clear_main_window(transition='instant')
|
||||
self.restore_main_window_state(winstate)
|
||||
|
||||
@ -96,14 +96,20 @@ class MainWindow(Window):
|
||||
except Exception:
|
||||
logging.exception('Error in on_main_window_close() for %s.', self)
|
||||
|
||||
_bauiv1.containerwidget(
|
||||
edit=self._root_widget,
|
||||
transition=(
|
||||
self._main_window_transition_out
|
||||
if transition is None
|
||||
else transition
|
||||
),
|
||||
)
|
||||
# Note: normally transition of None means instant, but we use
|
||||
# that to mean 'do the default' so we support a special
|
||||
# 'instant' string..
|
||||
if transition == 'instant':
|
||||
self._root_widget.delete()
|
||||
else:
|
||||
_bauiv1.containerwidget(
|
||||
edit=self._root_widget,
|
||||
transition=(
|
||||
self._main_window_transition_out
|
||||
if transition is None
|
||||
else transition
|
||||
),
|
||||
)
|
||||
|
||||
def main_window_has_control(self) -> bool:
|
||||
"""Is this MainWindow allowed to change the global main window?
|
||||
|
||||
@ -1022,64 +1022,6 @@ class CoopBrowserWindow(bui.MainWindow):
|
||||
def _enable_selectable_callback(self) -> None:
|
||||
self._do_selection_callbacks = True
|
||||
|
||||
# def _switch_to_league_rankings(self) -> None:
|
||||
# # pylint: disable=cyclic-import
|
||||
# from bauiv1lib.account import show_sign_in_prompt
|
||||
# from bauiv1lib.league.rankwindow import LeagueRankWindow
|
||||
|
||||
# # no-op if our underlying widget is dead or on its way out.
|
||||
# if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# return
|
||||
|
||||
# plus = bui.app.plus
|
||||
# assert plus is not None
|
||||
|
||||
# if plus.get_v1_account_state() != 'signed_in':
|
||||
# show_sign_in_prompt()
|
||||
# return
|
||||
# self._save_state()
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
# assert self._league_rank_button is not None
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# LeagueRankWindow(
|
||||
# origin_widget=self._league_rank_button.get_button()
|
||||
# ),
|
||||
# from_window=self,
|
||||
# )
|
||||
|
||||
# def _switch_to_score(
|
||||
# self,
|
||||
# show_tab: (
|
||||
# StoreBrowserWindow.TabID | None
|
||||
# ) = StoreBrowserWindow.TabID.EXTRAS,
|
||||
# ) -> None:
|
||||
# # pylint: disable=cyclic-import
|
||||
# from bauiv1lib.account import show_sign_in_prompt
|
||||
|
||||
# # no-op if our underlying widget is dead or on its way out.
|
||||
# if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# return
|
||||
|
||||
# plus = bui.app.plus
|
||||
# assert plus is not None
|
||||
|
||||
# if plus.get_v1_account_state() != 'signed_in':
|
||||
# show_sign_in_prompt()
|
||||
# return
|
||||
# self._save_state()
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
# assert self._store_button is not None
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# StoreBrowserWindow(
|
||||
# origin_widget=self._store_button.get_button(),
|
||||
# show_tab=show_tab,
|
||||
# back_location='CoopBrowserWindow',
|
||||
# ),
|
||||
# from_window=self,
|
||||
# )
|
||||
|
||||
def is_tourney_data_up_to_date(self) -> bool:
|
||||
"""Return whether our tourney data is up to date."""
|
||||
return self._tourney_data_up_to_date
|
||||
@ -1233,24 +1175,6 @@ class CoopBrowserWindow(bui.MainWindow):
|
||||
position=tournament_button.button.get_screen_space_center(),
|
||||
)
|
||||
|
||||
# def _back(self) -> None:
|
||||
# # pylint: disable=cyclic-import
|
||||
# from bauiv1lib.play import PlayWindow
|
||||
|
||||
# # no-op if our underlying widget is dead or on its way out.
|
||||
# if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# return
|
||||
|
||||
# # If something is selected, store it.
|
||||
# self._save_state()
|
||||
# bui.containerwidget(
|
||||
# edit=self._root_widget, transition=self._transition_out
|
||||
# )
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# PlayWindow(transition='in_left'), from_window=self, is_back=True
|
||||
# )
|
||||
|
||||
def _save_state(self) -> None:
|
||||
cfg = bui.app.config
|
||||
try:
|
||||
|
||||
@ -33,8 +33,8 @@ class FileSelectorWindow(bui.MainWindow):
|
||||
valid_file_extensions = []
|
||||
assert bui.app.classic is not None
|
||||
uiscale = bui.app.ui_v1.uiscale
|
||||
self._width = 700 if uiscale is bui.UIScale.SMALL else 600
|
||||
self._x_inset = x_inset = 50 if uiscale is bui.UIScale.SMALL else 0
|
||||
self._width = 850 if uiscale is bui.UIScale.SMALL else 600
|
||||
self._x_inset = x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
|
||||
self._height = 365 if uiscale is bui.UIScale.SMALL else 418
|
||||
self._callback = callback
|
||||
self._base_path = path
|
||||
@ -54,7 +54,7 @@ class FileSelectorWindow(bui.MainWindow):
|
||||
root_widget=bui.containerwidget(
|
||||
size=(self._width, self._height),
|
||||
scale=(
|
||||
2.23
|
||||
1.93
|
||||
if uiscale is bui.UIScale.SMALL
|
||||
else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
|
||||
),
|
||||
@ -175,7 +175,6 @@ class FileSelectorWindow(bui.MainWindow):
|
||||
bui.getsound('error').play()
|
||||
|
||||
def _on_folder_entry_activated(self) -> None:
|
||||
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
if self._callback is not None:
|
||||
assert self._path is not None
|
||||
self._callback(self._path)
|
||||
@ -204,9 +203,6 @@ class FileSelectorWindow(bui.MainWindow):
|
||||
elif os.path.isfile(test_path):
|
||||
if self._is_valid_file_path(test_path):
|
||||
bui.getsound('swish').play()
|
||||
bui.containerwidget(
|
||||
edit=self._root_widget, transition='out_right'
|
||||
)
|
||||
if self._callback is not None:
|
||||
self._callback(test_path)
|
||||
else:
|
||||
@ -486,7 +482,6 @@ class FileSelectorWindow(bui.MainWindow):
|
||||
)
|
||||
|
||||
def _cancel(self) -> None:
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
self.main_window_back()
|
||||
if self._callback is not None:
|
||||
self._callback(None)
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import override
|
||||
|
||||
import bascenev1 as bs
|
||||
import bauiv1 as bui
|
||||
|
||||
@ -359,6 +361,20 @@ class KioskWindow(bui.MainWindow):
|
||||
1.0, bui.WeakCall(self._update), repeat=True
|
||||
)
|
||||
|
||||
@override
|
||||
def get_main_window_state(self) -> bui.MainWindowState:
|
||||
# Support recreating our window for back/refresh purposes.
|
||||
cls = type(self)
|
||||
return bui.BasicMainWindowState(
|
||||
create_call=lambda transition, origin_widget: cls(
|
||||
transition=transition, origin_widget=origin_widget
|
||||
)
|
||||
)
|
||||
|
||||
@override
|
||||
def on_main_window_close(self) -> None:
|
||||
self._save_state()
|
||||
|
||||
def _restore_state(self) -> None:
|
||||
assert bui.app.classic is not None
|
||||
sel_name = bui.app.ui_v1.window_states.get(type(self))
|
||||
@ -510,13 +526,13 @@ class KioskWindow(bui.MainWindow):
|
||||
# pylint: disable=cyclic-import
|
||||
from bauiv1lib.mainmenu import MainMenuWindow
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
assert bui.app.classic is not None
|
||||
|
||||
self._save_state()
|
||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
bui.app.classic.did_menu_intro = True # prevent delayed transition-in
|
||||
bui.app.ui_v1.set_main_window(MainMenuWindow(), from_window=self)
|
||||
|
||||
self.main_window_replace(MainMenuWindow())
|
||||
|
||||
@ -44,7 +44,8 @@ class PlayWindow(bui.MainWindow):
|
||||
uiscale = bui.app.ui_v1.uiscale
|
||||
width = 1100 if uiscale is bui.UIScale.SMALL else 800
|
||||
x_offs = 150 if uiscale is bui.UIScale.SMALL else 0
|
||||
height = 550
|
||||
y_offs = -60 if uiscale is bui.UIScale.SMALL else 0
|
||||
height = 650 if uiscale is bui.UIScale.SMALL else 550
|
||||
button_width = 400
|
||||
|
||||
if origin_widget is not None:
|
||||
@ -77,21 +78,34 @@ class PlayWindow(bui.MainWindow):
|
||||
transition=transition,
|
||||
origin_widget=origin_widget,
|
||||
)
|
||||
self._back_button = back_button = btn = bui.buttonwidget(
|
||||
parent=self._root_widget,
|
||||
position=(55 + x_offs, height - 132),
|
||||
size=(120, 60),
|
||||
scale=1.1,
|
||||
text_res_scale=1.5,
|
||||
text_scale=1.2,
|
||||
autoselect=True,
|
||||
label=bui.Lstr(resource='backText'),
|
||||
button_type='back',
|
||||
)
|
||||
|
||||
self._back_button: bui.Widget | None
|
||||
if uiscale is bui.UIScale.SMALL:
|
||||
self._back_button = None
|
||||
bui.containerwidget(
|
||||
edit=self._root_widget,
|
||||
on_cancel_call=self.main_window_back,
|
||||
)
|
||||
else:
|
||||
self._back_button = bui.buttonwidget(
|
||||
parent=self._root_widget,
|
||||
position=(55 + x_offs, height - 132 + y_offs),
|
||||
size=(60, 60),
|
||||
scale=1.1,
|
||||
text_res_scale=1.5,
|
||||
text_scale=1.2,
|
||||
autoselect=True,
|
||||
label=bui.charstr(bui.SpecialChar.BACK),
|
||||
button_type='backSmall',
|
||||
on_activate_call=self.main_window_back,
|
||||
)
|
||||
bui.containerwidget(
|
||||
edit=self._root_widget, cancel_button=self._back_button
|
||||
)
|
||||
|
||||
txt = bui.textwidget(
|
||||
parent=self._root_widget,
|
||||
position=(width * 0.5, height - 101),
|
||||
position=(width * 0.5, height - 101 + y_offs),
|
||||
# position=(width * 0.5, height -
|
||||
# (101 if main_menu else 61)),
|
||||
size=(0, 0),
|
||||
@ -110,16 +124,14 @@ class PlayWindow(bui.MainWindow):
|
||||
v_align='center',
|
||||
)
|
||||
|
||||
bui.buttonwidget(
|
||||
edit=btn,
|
||||
button_type='backSmall',
|
||||
size=(60, 60),
|
||||
label=bui.charstr(bui.SpecialChar.BACK),
|
||||
)
|
||||
if uiscale is bui.UIScale.SMALL:
|
||||
bui.textwidget(edit=txt, text='')
|
||||
|
||||
v = height - (110 if self._playlist_select_context is None else 90)
|
||||
v = (
|
||||
height
|
||||
- (110 if self._playlist_select_context is None else 90)
|
||||
+ y_offs
|
||||
)
|
||||
v -= 100
|
||||
clr = (0.6, 0.7, 0.6, 1.0)
|
||||
v -= 280 if self._playlist_select_context is None else 180
|
||||
@ -510,11 +522,8 @@ class PlayWindow(bui.MainWindow):
|
||||
)
|
||||
|
||||
if uiscale is bui.UIScale.SMALL:
|
||||
back_button.delete()
|
||||
bui.containerwidget(
|
||||
edit=self._root_widget,
|
||||
on_cancel_call=self.main_window_back,
|
||||
# cancel_button=bui.get_special_widget('back_button'),
|
||||
selected_child=(
|
||||
self._coop_button
|
||||
if self._playlist_select_context is None
|
||||
@ -522,12 +531,8 @@ class PlayWindow(bui.MainWindow):
|
||||
),
|
||||
)
|
||||
else:
|
||||
bui.buttonwidget(
|
||||
edit=back_button, on_activate_call=self.main_window_back
|
||||
)
|
||||
bui.containerwidget(
|
||||
edit=self._root_widget,
|
||||
cancel_button=back_button,
|
||||
selected_child=(
|
||||
self._coop_button
|
||||
if self._playlist_select_context is None
|
||||
@ -763,7 +768,7 @@ class PlayWindow(bui.MainWindow):
|
||||
sel = self._coop_button
|
||||
elif sel_name == 'Free-for-All Games':
|
||||
sel = self._free_for_all_button
|
||||
elif sel_name == 'Back':
|
||||
elif sel_name == 'Back' and self._back_button is not None:
|
||||
sel = self._back_button
|
||||
else:
|
||||
sel = (
|
||||
|
||||
@ -716,26 +716,23 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
||||
PlaylistCustomizeBrowserWindow,
|
||||
)
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
self._save_state()
|
||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
bui.app.ui_v1.set_main_window(
|
||||
self.main_window_replace(
|
||||
PlaylistCustomizeBrowserWindow(
|
||||
origin_widget=self._customize_button,
|
||||
sessiontype=self._sessiontype,
|
||||
),
|
||||
from_window=self,
|
||||
)
|
||||
)
|
||||
|
||||
def _on_back_press(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
# from bauiv1lib.play import PlayWindow
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
# Store our selected playlist if that's changed.
|
||||
|
||||
@ -545,10 +545,6 @@ class PlaylistEditGameWindow(bui.MainWindow):
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
# if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# return
|
||||
|
||||
self._config = self._getconfig()
|
||||
|
||||
# Replace ourself with the map-select UI.
|
||||
@ -556,26 +552,12 @@ class PlaylistEditGameWindow(bui.MainWindow):
|
||||
PlaylistMapSelectWindow(
|
||||
self._gametype,
|
||||
self._sessiontype,
|
||||
# copy.deepcopy(self._getconfig()),
|
||||
self._config,
|
||||
self._edit_info,
|
||||
self._completion_call,
|
||||
)
|
||||
)
|
||||
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# PlaylistMapSelectWindow(
|
||||
# self._gametype,
|
||||
# self._sessiontype,
|
||||
# copy.deepcopy(self._getconfig()),
|
||||
# self._edit_info,
|
||||
# self._completion_call,
|
||||
# ),
|
||||
# from_window=self,
|
||||
# )
|
||||
|
||||
def _choice_inc(
|
||||
self,
|
||||
setting_name: str,
|
||||
|
||||
@ -61,7 +61,6 @@ class PlaylistMapSelectWindow(bui.MainWindow):
|
||||
super().__init__(
|
||||
root_widget=bui.containerwidget(
|
||||
size=(width, height + top_extra),
|
||||
# transition=transition,
|
||||
scale=(
|
||||
1.95
|
||||
if uiscale is bui.UIScale.SMALL
|
||||
@ -299,66 +298,22 @@ class PlaylistMapSelectWindow(bui.MainWindow):
|
||||
|
||||
self.main_window_replace(
|
||||
StoreBrowserWindow(
|
||||
# modal=True,
|
||||
show_tab=StoreBrowserWindow.TabID.MAPS,
|
||||
# on_close_call=self._on_store_close,
|
||||
origin_widget=self._get_more_maps_button,
|
||||
minimal_toolbars=True,
|
||||
)
|
||||
)
|
||||
|
||||
# def _on_store_close(self) -> None:
|
||||
# pass
|
||||
# self._refresh(select_get_more_maps_button=True)
|
||||
|
||||
def _select(self, map_name: str) -> None:
|
||||
# from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
self._config['settings']['map'] = map_name
|
||||
self.main_window_back()
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# PlaylistEditGameWindow(
|
||||
# self._gametype,
|
||||
# self._sessiontype,
|
||||
# self._config,
|
||||
# self._completion_call,
|
||||
# default_selection='map',
|
||||
# transition='in_left',
|
||||
# edit_info=self._edit_info,
|
||||
# ),
|
||||
# from_window=self,
|
||||
# )
|
||||
|
||||
def _select_with_delay(self, map_name: str) -> None:
|
||||
bui.lock_all_input()
|
||||
bui.apptimer(0.1, bui.unlock_all_input)
|
||||
bui.apptimer(0.1, bui.WeakCall(self._select, map_name))
|
||||
|
||||
# def _cancel(self) -> None:
|
||||
# from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
||||
|
||||
# # no-op if our underlying widget is dead or on its way out.
|
||||
# if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# return
|
||||
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# PlaylistEditGameWindow(
|
||||
# self._gametype,
|
||||
# self._sessiontype,
|
||||
# self._config,
|
||||
# self._completion_call,
|
||||
# default_selection='map',
|
||||
# transition='in_left',
|
||||
# edit_info=self._edit_info,
|
||||
# ),
|
||||
# from_window=self,
|
||||
# is_back=True,
|
||||
# )
|
||||
|
||||
@ -500,8 +500,8 @@ class PlayOptionsWindow(PopupWindow):
|
||||
cfg = bui.app.config
|
||||
cfg[self._pvars.config_name + ' Playlist Selection'] = self._playlist
|
||||
|
||||
# Head back to the gather window in playlist-select mode
|
||||
# or start the game in regular mode.
|
||||
# Head back to the gather window in playlist-select mode or
|
||||
# start the game in regular mode.
|
||||
if self._playlist_select_context is not None:
|
||||
# from bauiv1lib.gather import GatherWindow
|
||||
|
||||
@ -514,14 +514,6 @@ class PlayOptionsWindow(PopupWindow):
|
||||
cfg['Private Party Host Session Type'] = typename
|
||||
bui.getsound('gunCocking').play()
|
||||
|
||||
# assert bui.app.classic is not None
|
||||
# # Note: this is a wonky situation where we aren't actually
|
||||
# # the main window but we set it on behalf of the main window
|
||||
# # that popped us up.
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# GatherWindow(transition='in_right'),
|
||||
# from_window=False, # Disable this test.
|
||||
# )
|
||||
self._transition_out(transition='out_left')
|
||||
if self._delegate is not None:
|
||||
self._delegate.on_play_options_window_run_game()
|
||||
|
||||
@ -268,13 +268,6 @@ class ProfileBrowserWindow(bui.MainWindow):
|
||||
|
||||
self.main_window_replace(EditProfileWindow(existing_profile=None))
|
||||
|
||||
# self._save_state()
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# EditProfileWindow(existing_profile=None),
|
||||
# from_window=self if self._in_main_menu else False,
|
||||
# )
|
||||
|
||||
def _delete_profile(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
from bauiv1lib import confirm
|
||||
|
||||
@ -19,19 +19,16 @@ class EditProfileWindow(bui.MainWindow, CharacterPickerDelegate):
|
||||
def reload_window(self) -> None:
|
||||
"""Transitions out and recreates ourself."""
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
bui.screenmessage('UNDER CONSTRUCTION')
|
||||
return
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# EditProfileWindow(self.getname()),
|
||||
# from_window=self,
|
||||
# is_back=True,
|
||||
# )
|
||||
# Replace ourself with ourself, but keep the same back location.
|
||||
assert self.main_window_back_state is not None
|
||||
self.main_window_replace(
|
||||
EditProfileWindow(self.getname()),
|
||||
back_state=self.main_window_back_state,
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -548,6 +545,15 @@ class EditProfileWindow(bui.MainWindow, CharacterPickerDelegate):
|
||||
from bauiv1lib import account
|
||||
from bauiv1lib.profile import upgrade as pupgrade
|
||||
|
||||
new_name = self.getname().strip()
|
||||
|
||||
if self._existing_profile and self._existing_profile != new_name:
|
||||
bui.screenmessage(
|
||||
'Unsaved changes found; you must save first.', color=(1, 0, 0)
|
||||
)
|
||||
bui.getsound('error').play()
|
||||
return
|
||||
|
||||
plus = bui.app.plus
|
||||
assert plus is not None
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ class DevToolsWindow(bui.MainWindow):
|
||||
self._scroll_width = self._width - (100 + 2 * x_inset)
|
||||
self._scroll_height = self._height - 115.0
|
||||
self._sub_width = self._scroll_width * 0.95
|
||||
self._sub_height = 350.0
|
||||
self._sub_height = 300.0
|
||||
|
||||
super().__init__(
|
||||
root_widget=bui.containerwidget(
|
||||
@ -169,37 +169,41 @@ class DevToolsWindow(bui.MainWindow):
|
||||
),
|
||||
)
|
||||
|
||||
v -= self._spacing * 2.5
|
||||
bui.textwidget(
|
||||
parent=self._subcontainer,
|
||||
position=(170, v + 10),
|
||||
size=(0, 0),
|
||||
text=bui.Lstr(resource='uiScaleText'),
|
||||
color=app.ui_v1.title_color,
|
||||
h_align='center',
|
||||
v_align='center',
|
||||
)
|
||||
# Currently this is not wired up. The current official way to test
|
||||
# UIScales is either to use the switcher in the dev-console or to
|
||||
# set the BA_UI_SCALE env var.
|
||||
if bool(False):
|
||||
v -= self._spacing * 2.5
|
||||
bui.textwidget(
|
||||
parent=self._subcontainer,
|
||||
position=(170, v + 10),
|
||||
size=(0, 0),
|
||||
text=bui.Lstr(resource='uiScaleText'),
|
||||
color=app.ui_v1.title_color,
|
||||
h_align='center',
|
||||
v_align='center',
|
||||
)
|
||||
|
||||
PopupMenu(
|
||||
parent=self._subcontainer,
|
||||
position=(230, v - 20),
|
||||
button_size=(200.0, 60.0),
|
||||
width=100.0,
|
||||
choices=[
|
||||
'auto',
|
||||
'small',
|
||||
'medium',
|
||||
'large',
|
||||
],
|
||||
choices_display=[
|
||||
bui.Lstr(resource='autoText'),
|
||||
bui.Lstr(resource='sizeSmallText'),
|
||||
bui.Lstr(resource='sizeMediumText'),
|
||||
bui.Lstr(resource='sizeLargeText'),
|
||||
],
|
||||
current_choice=app.config.get('UI Scale', 'auto'),
|
||||
on_value_change_call=self._set_uiscale,
|
||||
)
|
||||
PopupMenu(
|
||||
parent=self._subcontainer,
|
||||
position=(230, v - 20),
|
||||
button_size=(200.0, 60.0),
|
||||
width=100.0,
|
||||
choices=[
|
||||
'auto',
|
||||
'small',
|
||||
'medium',
|
||||
'large',
|
||||
],
|
||||
choices_display=[
|
||||
bui.Lstr(resource='autoText'),
|
||||
bui.Lstr(resource='sizeSmallText'),
|
||||
bui.Lstr(resource='sizeMediumText'),
|
||||
bui.Lstr(resource='sizeLargeText'),
|
||||
],
|
||||
current_choice=app.config.get('UI Scale', 'auto'),
|
||||
on_value_change_call=self._set_uiscale,
|
||||
)
|
||||
|
||||
@override
|
||||
def get_main_window_state(self) -> bui.MainWindowState:
|
||||
|
||||
@ -798,22 +798,15 @@ class GamepadSettingsWindow(bui.MainWindow):
|
||||
|
||||
def _cancel(self) -> None:
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
return
|
||||
|
||||
if self._modal:
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
return
|
||||
bui.containerwidget(
|
||||
edit=self._root_widget, transition=self._transition_out
|
||||
)
|
||||
else:
|
||||
self.main_window_back()
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# ControlsSettingsWindow(transition='in_left'),
|
||||
# from_window=self,
|
||||
# is_back=True,
|
||||
# )
|
||||
|
||||
def _reset(self) -> None:
|
||||
from bauiv1lib.confirm import ConfirmWindow
|
||||
|
||||
@ -377,17 +377,16 @@ class ConfigKeyboardWindow(bui.MainWindow):
|
||||
"""Called when the popup is closing."""
|
||||
|
||||
def _save(self) -> None:
|
||||
# from bauiv1lib.settings.controls import ControlsSettingsWindow
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
assert bui.app.classic is not None
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
bui.getsound('gunCocking').play()
|
||||
|
||||
# There's a chance the device disappeared; handle that gracefully.
|
||||
# There's a chance the device disappeared; handle that
|
||||
# gracefully.
|
||||
if not self._input:
|
||||
return
|
||||
|
||||
@ -402,8 +401,8 @@ class ConfigKeyboardWindow(bui.MainWindow):
|
||||
if val != -1:
|
||||
dst2[key] = val
|
||||
|
||||
# Send this config to the master-server so we can generate
|
||||
# more defaults in the future.
|
||||
# Send this config to the master-server so we can generate more
|
||||
# defaults in the future.
|
||||
if bui.app.classic is not None:
|
||||
bui.app.classic.master_server_v1_post(
|
||||
'controllerConfig',
|
||||
@ -418,11 +417,6 @@ class ConfigKeyboardWindow(bui.MainWindow):
|
||||
bui.app.config.apply_and_commit()
|
||||
|
||||
self.main_window_back()
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# ControlsSettingsWindow(transition='in_left'),
|
||||
# from_window=self,
|
||||
# is_back=True,
|
||||
# )
|
||||
|
||||
|
||||
class AwaitKeyboardInputWindow(bui.Window):
|
||||
|
||||
@ -56,10 +56,11 @@ class NetTestingWindow(bui.MainWindow):
|
||||
self._done_button: bui.Widget | None = bui.buttonwidget(
|
||||
parent=self._root_widget,
|
||||
position=(46, self._height - 77),
|
||||
size=(120, 60),
|
||||
scale=0.8,
|
||||
size=(60, 60),
|
||||
scale=0.9,
|
||||
label=bui.charstr(bui.SpecialChar.BACK),
|
||||
button_type='backSmall',
|
||||
autoselect=True,
|
||||
label=bui.Lstr(resource='doneText'),
|
||||
on_activate_call=self.main_window_back,
|
||||
)
|
||||
|
||||
@ -164,28 +165,11 @@ class NetTestingWindow(bui.MainWindow):
|
||||
def _show_val_testing(self) -> None:
|
||||
assert bui.app.classic is not None
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
bui.app.ui_v1.set_main_window(NetValTestingWindow(), from_window=self)
|
||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
|
||||
# def _done(self) -> None:
|
||||
# # pylint: disable=cyclic-import
|
||||
# from bauiv1lib.settings.advanced import AdvancedSettingsWindow
|
||||
|
||||
# # no-op if our underlying widget is dead or on its way out.
|
||||
# if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# return
|
||||
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# AdvancedSettingsWindow(transition='in_left'),
|
||||
# from_window=self,
|
||||
# is_back=True,
|
||||
# )
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
self.main_window_replace(NetValTestingWindow())
|
||||
|
||||
|
||||
def _run_diagnostics(weakwin: weakref.ref[NetTestingWindow]) -> None:
|
||||
|
||||
@ -22,7 +22,6 @@ class TouchscreenSettingsWindow(bui.MainWindow):
|
||||
) -> None:
|
||||
self._width = 780
|
||||
self._height = 380
|
||||
# self._spacing = 40
|
||||
self._r = 'configTouchscreenWindow'
|
||||
|
||||
bs.set_touchscreen_editing(True)
|
||||
@ -302,19 +301,3 @@ class TouchscreenSettingsWindow(bui.MainWindow):
|
||||
del cfg[cfgkey]
|
||||
cfg.apply_and_commit()
|
||||
bui.apptimer(0, self._build_gui)
|
||||
|
||||
# def _back(self) -> None:
|
||||
# from bauiv1lib.settings import controls
|
||||
|
||||
# # no-op if our underlying widget is dead or on its way out.
|
||||
# if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# return
|
||||
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# controls.ControlsSettingsWindow(transition='in_left'),
|
||||
# from_window=self,
|
||||
# is_back=True,
|
||||
# )
|
||||
# bs.set_touchscreen_editing(False)
|
||||
|
||||
@ -15,9 +15,6 @@ if TYPE_CHECKING:
|
||||
|
||||
REQUIRE_PRO = False
|
||||
|
||||
# Temp.
|
||||
UNDER_CONSTRUCTION = True
|
||||
|
||||
|
||||
class SoundtrackBrowserWindow(bui.MainWindow):
|
||||
"""Window for browsing soundtracks."""
|
||||
@ -397,25 +394,6 @@ class SoundtrackBrowserWindow(bui.MainWindow):
|
||||
music.music_types[bui.app.classic.MusicPlayMode.REGULAR]
|
||||
)
|
||||
|
||||
# def _back(self) -> None:
|
||||
# # pylint: disable=cyclic-import
|
||||
# from bauiv1lib.settings.audio import AudioSettingsWindow
|
||||
|
||||
# # no-op if our underlying widget is dead or on its way out.
|
||||
# if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# return
|
||||
|
||||
# self._save_state()
|
||||
# bui.containerwidget(
|
||||
# edit=self._root_widget, transition=self._transition_out
|
||||
# )
|
||||
# assert bui.app.classic is not None
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# AudioSettingsWindow(transition='in_left'),
|
||||
# from_window=self,
|
||||
# is_back=True,
|
||||
# )
|
||||
|
||||
def _edit_soundtrack_with_sound(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
from bauiv1lib.purchase import PurchaseWindow
|
||||
@ -434,12 +412,8 @@ class SoundtrackBrowserWindow(bui.MainWindow):
|
||||
from bauiv1lib.purchase import PurchaseWindow
|
||||
from bauiv1lib.soundtrack.edit import SoundtrackEditWindow
|
||||
|
||||
if UNDER_CONSTRUCTION:
|
||||
bui.screenmessage('UNDER CONSTRUCTION')
|
||||
return
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we don't have control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
if REQUIRE_PRO and (
|
||||
@ -448,8 +422,10 @@ class SoundtrackBrowserWindow(bui.MainWindow):
|
||||
):
|
||||
PurchaseWindow(items=['pro'])
|
||||
return
|
||||
|
||||
if self._selected_soundtrack is None:
|
||||
return
|
||||
|
||||
if self._selected_soundtrack == '__default__':
|
||||
bui.getsound('error').play()
|
||||
bui.screenmessage(
|
||||
@ -458,12 +434,8 @@ class SoundtrackBrowserWindow(bui.MainWindow):
|
||||
)
|
||||
return
|
||||
|
||||
self._save_state()
|
||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
assert bui.app.classic is not None
|
||||
bui.app.ui_v1.set_main_window(
|
||||
SoundtrackEditWindow(existing_soundtrack=self._selected_soundtrack),
|
||||
from_window=self,
|
||||
self.main_window_replace(
|
||||
SoundtrackEditWindow(existing_soundtrack=self._selected_soundtrack)
|
||||
)
|
||||
|
||||
def _get_soundtrack_display_name(self, soundtrack: str) -> bui.Lstr:
|
||||
@ -554,8 +526,8 @@ class SoundtrackBrowserWindow(bui.MainWindow):
|
||||
from bauiv1lib.purchase import PurchaseWindow
|
||||
from bauiv1lib.soundtrack.edit import SoundtrackEditWindow
|
||||
|
||||
if UNDER_CONSTRUCTION:
|
||||
bui.screenmessage('UNDER CONSTRUCTION')
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
if REQUIRE_PRO and (
|
||||
@ -564,11 +536,8 @@ class SoundtrackBrowserWindow(bui.MainWindow):
|
||||
):
|
||||
PurchaseWindow(items=['pro'])
|
||||
return
|
||||
self._save_state()
|
||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
bui.app.ui_v1.set_main_window(
|
||||
SoundtrackEditWindow(existing_soundtrack=None), from_window=self
|
||||
)
|
||||
|
||||
self.main_window_replace(SoundtrackEditWindow(existing_soundtrack=None))
|
||||
|
||||
def _create_done(self, new_soundtrack: str) -> None:
|
||||
if new_soundtrack is not None:
|
||||
|
||||
@ -26,8 +26,6 @@ class SoundtrackEditWindow(bui.MainWindow):
|
||||
):
|
||||
# pylint: disable=too-many-statements
|
||||
|
||||
print('SPAWNING EDIT')
|
||||
|
||||
appconfig = bui.app.config
|
||||
self._r = 'editSoundtrackWindow'
|
||||
self._folder_tex = bui.gettexture('folder')
|
||||
@ -110,7 +108,7 @@ class SoundtrackEditWindow(bui.MainWindow):
|
||||
self._existing_soundtrack_name = existing_soundtrack
|
||||
self._last_edited_song_type = None
|
||||
else:
|
||||
# otherwise they can pass info on an in-progress edit
|
||||
# Otherwise they can pass info on an in-progress edit.
|
||||
self._soundtrack = existing_soundtrack['soundtrack']
|
||||
self._soundtrack_name = existing_soundtrack['name']
|
||||
self._existing_soundtrack_name = existing_soundtrack[
|
||||
@ -202,7 +200,13 @@ class SoundtrackEditWindow(bui.MainWindow):
|
||||
|
||||
# Pull this out of self here; if we do it in the lambda we'll
|
||||
# keep our window alive due to the 'self' reference.
|
||||
existing_soundtrack = self._existing_soundtrack
|
||||
existing_soundtrack = {
|
||||
'name': self._soundtrack_name,
|
||||
'existing_name': self._existing_soundtrack_name,
|
||||
'soundtrack': self._soundtrack,
|
||||
'last_edited_song_type': self._last_edited_song_type,
|
||||
}
|
||||
|
||||
return bui.BasicMainWindowState(
|
||||
create_call=lambda transition, origin_widget: cls(
|
||||
transition=transition,
|
||||
@ -348,8 +352,6 @@ class SoundtrackEditWindow(bui.MainWindow):
|
||||
assert bui.app.classic is not None
|
||||
music = bui.app.classic.music
|
||||
|
||||
print('GoT RESTORE', state, musictype, entry)
|
||||
|
||||
# Apply the change and recreate the window.
|
||||
soundtrack = state['soundtrack']
|
||||
existing_entry = (
|
||||
@ -370,14 +372,20 @@ class SoundtrackEditWindow(bui.MainWindow):
|
||||
else:
|
||||
soundtrack[musictype] = entry
|
||||
|
||||
mainwindow = bui.app.ui_v1.get_main_window()
|
||||
assert mainwindow is not None
|
||||
|
||||
mainwindow.main_window_back_state = state['back_state']
|
||||
mainwindow.main_window_back()
|
||||
|
||||
def _get_entry(
|
||||
self, song_type: str, entry: Any, selection_target_name: str
|
||||
) -> None:
|
||||
assert bui.app.classic is not None
|
||||
music = bui.app.classic.music
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
if selection_target_name != '':
|
||||
@ -388,22 +396,17 @@ class SoundtrackEditWindow(bui.MainWindow):
|
||||
'soundtrack': self._soundtrack,
|
||||
'last_edited_song_type': song_type,
|
||||
}
|
||||
self.main_window_replace(
|
||||
music.get_music_player().select_entry(
|
||||
bui.Call(self._restore_editor, state, song_type),
|
||||
entry,
|
||||
selection_target_name,
|
||||
)
|
||||
new_win = music.get_music_player().select_entry(
|
||||
bui.Call(self._restore_editor, state, song_type),
|
||||
entry,
|
||||
selection_target_name,
|
||||
)
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# music.get_music_player().select_entry(
|
||||
# bui.Call(self._restore_editor, state, song_type),
|
||||
# entry,
|
||||
# selection_target_name,
|
||||
# ),
|
||||
# from_window=self,
|
||||
# )
|
||||
self.main_window_replace(new_win)
|
||||
|
||||
# Once we've set the new window, grab the back-state; we'll use
|
||||
# that to jump back here after selection completes.
|
||||
assert new_win.main_window_back_state is not None
|
||||
state['back_state'] = new_win.main_window_back_state
|
||||
|
||||
def _test(self, song_type: bs.MusicType) -> None:
|
||||
assert bui.app.classic is not None
|
||||
@ -460,15 +463,8 @@ class SoundtrackEditWindow(bui.MainWindow):
|
||||
music.set_music_play_mode(bui.app.classic.MusicPlayMode.REGULAR)
|
||||
|
||||
self.main_window_back()
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# SoundtrackBrowserWindow(transition='in_left'),
|
||||
# from_window=self,
|
||||
# is_back=True,
|
||||
# )
|
||||
|
||||
def _do_it(self) -> None:
|
||||
# from bauiv1lib.soundtrack.browser import SoundtrackBrowserWindow
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
@ -514,7 +510,6 @@ class SoundtrackEditWindow(bui.MainWindow):
|
||||
|
||||
cfg.commit()
|
||||
bui.getsound('gunCocking').play()
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
|
||||
# Resets music back to normal.
|
||||
music.set_music_play_mode(
|
||||
@ -522,11 +517,6 @@ class SoundtrackEditWindow(bui.MainWindow):
|
||||
)
|
||||
|
||||
self.main_window_back()
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# SoundtrackBrowserWindow(transition='in_left'),
|
||||
# from_window=self,
|
||||
# is_back=True,
|
||||
# )
|
||||
|
||||
def _do_it_with_sound(self) -> None:
|
||||
bui.getsound('swish').play()
|
||||
|
||||
@ -189,12 +189,10 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
|
||||
MacMusicAppPlaylistSelectWindow,
|
||||
)
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
|
||||
current_playlist_entry: str | None
|
||||
if (
|
||||
music.get_soundtrack_entry_type(self._current_entry)
|
||||
@ -211,22 +209,16 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
|
||||
self._callback, current_playlist_entry, self._current_entry
|
||||
)
|
||||
)
|
||||
# MacMusicAppPlaylistSelectWindow(
|
||||
# self._callback, current_playlist_entry, self._current_entry
|
||||
# ),
|
||||
# from_window=self,
|
||||
# )
|
||||
|
||||
def _on_music_file_press(self) -> None:
|
||||
from babase import android_get_external_files_dir
|
||||
from baclassic.osmusic import OSMusicPlayer
|
||||
from bauiv1lib.fileselector import FileSelectorWindow
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
base_path = android_get_external_files_dir()
|
||||
assert bui.app.classic is not None
|
||||
|
||||
@ -241,28 +233,15 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
|
||||
allow_folders=False,
|
||||
),
|
||||
)
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# FileSelectorWindow(
|
||||
# base_path,
|
||||
# callback=self._music_file_selector_cb,
|
||||
# show_base_path=False,
|
||||
# valid_file_extensions=(
|
||||
# OSMusicPlayer.get_valid_music_file_extensions()
|
||||
# ),
|
||||
# allow_folders=False,
|
||||
# ),
|
||||
# from_window=self,
|
||||
# )
|
||||
|
||||
def _on_music_folder_press(self) -> None:
|
||||
from bauiv1lib.fileselector import FileSelectorWindow
|
||||
from babase import android_get_external_files_dir
|
||||
|
||||
# no-op if our underlying widget is dead or on its way out.
|
||||
if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# no-op if we're not in control.
|
||||
if not self.main_window_has_control():
|
||||
return
|
||||
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||
base_path = android_get_external_files_dir()
|
||||
assert bui.app.classic is not None
|
||||
|
||||
@ -275,16 +254,6 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
|
||||
allow_folders=True,
|
||||
),
|
||||
)
|
||||
# bui.app.ui_v1.set_main_window(
|
||||
# FileSelectorWindow(
|
||||
# base_path,
|
||||
# callback=self._music_folder_selector_cb,
|
||||
# show_base_path=False,
|
||||
# valid_file_extensions=[],
|
||||
# allow_folders=True,
|
||||
# ),
|
||||
# from_window=self,
|
||||
# )
|
||||
|
||||
def _music_file_selector_cb(self, result: str | None) -> None:
|
||||
if result is None:
|
||||
@ -300,10 +269,8 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
|
||||
|
||||
def _on_default_press(self) -> None:
|
||||
self.main_window_back()
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
self._callback(None)
|
||||
|
||||
def _on_cancel_press(self) -> None:
|
||||
self.main_window_back()
|
||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
||||
self._callback(self._current_entry)
|
||||
|
||||
@ -42,10 +42,7 @@ class StoreBrowserWindow(bui.MainWindow):
|
||||
self,
|
||||
transition: str | None = 'in_right',
|
||||
origin_widget: bui.Widget | None = None,
|
||||
# modal: bool = False,
|
||||
show_tab: StoreBrowserWindow.TabID | None = None,
|
||||
# on_close_call: Callable[[], Any] | None = None,
|
||||
# back_location: str | None = None,
|
||||
minimal_toolbars: bool = False,
|
||||
):
|
||||
# pylint: disable=too-many-statements
|
||||
@ -59,20 +56,11 @@ class StoreBrowserWindow(bui.MainWindow):
|
||||
|
||||
bui.set_analytics_screen('Store Window')
|
||||
|
||||
# Need to store this ourself for modal mode.
|
||||
# if origin_widget is not None:
|
||||
# self._transition_out = 'out_scale'
|
||||
# else:
|
||||
# self._transition_out = 'out_right'
|
||||
|
||||
self.button_infos: dict[str, dict[str, Any]] | None = None
|
||||
self.update_buttons_timer: bui.AppTimer | None = None
|
||||
self._status_textwidget_update_timer = None
|
||||
|
||||
# self._back_location = back_location
|
||||
# self._on_close_call = on_close_call
|
||||
self._show_tab = show_tab
|
||||
# self._modal = modal
|
||||
self._width = 1670 if uiscale is bui.UIScale.SMALL else 1040
|
||||
self._x_inset = x_inset = 310 if uiscale is bui.UIScale.SMALL else 0
|
||||
self._height = (
|
||||
@ -1252,31 +1240,13 @@ class StoreBrowserWindow(bui.MainWindow):
|
||||
except Exception:
|
||||
logging.exception('Error restoring state for %s.', self)
|
||||
|
||||
# def _back(self) -> None:
|
||||
|
||||
# # if self._modal:
|
||||
# # # no-op if our underlying widget is dead or on its way out.
|
||||
# # if not self._root_widget or self._root_widget.transitioning_out:
|
||||
# # return
|
||||
# # self._save_state()
|
||||
# # bui.containerwidget(
|
||||
# # edit=self._root_widget, transition=self._transition_out
|
||||
# # )
|
||||
# # else:
|
||||
# # no-op if we're not currently in control.
|
||||
# if not self.main_window_has_control():
|
||||
# return
|
||||
# self.main_window_back()
|
||||
# # if self._on_close_call is not None:
|
||||
# # self._on_close_call()
|
||||
|
||||
|
||||
def _check_merch_availability_in_bg_thread() -> None:
|
||||
# pylint: disable=cell-var-from-loop
|
||||
|
||||
# Merch is available from some countries only.
|
||||
# Make a reasonable check to ask the master-server about this at
|
||||
# launch and store the results.
|
||||
# Merch is available from some countries only. Make a reasonable
|
||||
# check to ask the master-server about this at launch and store the
|
||||
# results.
|
||||
plus = bui.app.plus
|
||||
assert plus is not None
|
||||
|
||||
|
||||
@ -87,19 +87,13 @@ class WatchWindow(bui.MainWindow):
|
||||
parent=self._root_widget,
|
||||
autoselect=True,
|
||||
position=(70 + x_inset, self._height - 74),
|
||||
size=(140, 60),
|
||||
size=(60, 60),
|
||||
scale=1.1,
|
||||
label=bui.Lstr(resource='backText'),
|
||||
button_type='back',
|
||||
label=bui.charstr(bui.SpecialChar.BACK),
|
||||
button_type='backSmall',
|
||||
on_activate_call=self.main_window_back,
|
||||
)
|
||||
bui.containerwidget(edit=self._root_widget, cancel_button=btn)
|
||||
bui.buttonwidget(
|
||||
edit=btn,
|
||||
button_type='backSmall',
|
||||
size=(60, 60),
|
||||
label=bui.charstr(bui.SpecialChar.BACK),
|
||||
)
|
||||
|
||||
bui.textwidget(
|
||||
parent=self._root_widget,
|
||||
@ -368,7 +362,7 @@ class WatchWindow(bui.MainWindow):
|
||||
bui.fade_screen(True)
|
||||
assert self._my_replay_selected is not None
|
||||
bs.new_replay_session(
|
||||
bui.get_replays_dir() + '/' + self._my_replay_selected
|
||||
f'{bui.get_replays_dir()}/{self._my_replay_selected}'
|
||||
)
|
||||
except Exception:
|
||||
logging.exception('Error running replay session.')
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "ballistica/base/app_mode/empty_app_mode.h"
|
||||
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/text/text_group.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
|
||||
@ -4,10 +4,12 @@
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/app_mode/empty_app_mode.h"
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/assets/assets_server.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/audio/audio_server.h"
|
||||
#include "ballistica/base/dynamics/bg/bg_dynamics_server.h"
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
#include "ballistica/base/graphics/support/screen_messages.h"
|
||||
#include "ballistica/base/graphics/text/text_graphics.h"
|
||||
@ -24,7 +26,6 @@
|
||||
#include "ballistica/base/support/huffman.h"
|
||||
#include "ballistica/base/support/plus_soft.h"
|
||||
#include "ballistica/base/support/stdio_console.h"
|
||||
#include "ballistica/base/ui/dev_console.h"
|
||||
#include "ballistica/base/ui/ui_delegate.h"
|
||||
#include "ballistica/core/python/core_python.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
@ -193,12 +194,6 @@ void BaseFeatureSet::OnAssetsAvailable() {
|
||||
}
|
||||
|
||||
void BaseFeatureSet::StartApp() {
|
||||
// {
|
||||
// // TEST - recreate the ID python dumps in its thread tracebacks.
|
||||
// auto val = PyThread_get_thread_ident();
|
||||
// printf("MAIN THREAD IS %#018lx\n", val);
|
||||
// }
|
||||
|
||||
BA_PRECONDITION(g_core->InMainThread());
|
||||
BA_PRECONDITION(g_base);
|
||||
|
||||
@ -987,4 +982,14 @@ void BaseFeatureSet::Reset() {
|
||||
audio->Reset();
|
||||
}
|
||||
|
||||
void BaseFeatureSet::SetUIScale(UIScale scale) {
|
||||
assert(InLogicThread());
|
||||
|
||||
// Store the canonical value in UI.
|
||||
ui->SetScale(scale);
|
||||
|
||||
// Let interested parties know that it has changed.
|
||||
graphics->OnUIScaleChange();
|
||||
}
|
||||
|
||||
} // namespace ballistica::base
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "ballistica/core/support/base_soft.h"
|
||||
@ -781,6 +780,9 @@ class BaseFeatureSet : public FeatureSetNativeComponent,
|
||||
/// unsupported.
|
||||
void ClipboardSetText(const std::string& text);
|
||||
|
||||
/// Set overall ui scale for the app.
|
||||
void SetUIScale(UIScale scale);
|
||||
|
||||
// Const subsystems.
|
||||
AppAdapter* const app_adapter;
|
||||
AppConfig* const app_config;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/base/dynamics/collision_cache.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ode/ode_collision_kernel.h"
|
||||
#include "ode/ode_collision_space_internal.h"
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include "ballistica/base/graphics/component/object_component.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
void ObjectComponent::WriteConfig() {
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include "ballistica/base/graphics/component/render_component.h"
|
||||
|
||||
#include "ballistica/shared/math/rect.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
void RenderComponent::ScissorPush(const Rect& rect) {
|
||||
|
||||
@ -5,7 +5,12 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ballistica/base/graphics/renderer/renderer.h"
|
||||
#include "ballistica/base/assets/mesh_asset.h"
|
||||
#include "ballistica/base/graphics/graphics.h"
|
||||
#include "ballistica/base/graphics/renderer/render_pass.h"
|
||||
#include "ballistica/base/graphics/support/frame_def.h"
|
||||
#include "ballistica/base/graphics/support/render_command_buffer.h"
|
||||
#include "ballistica/shared/math/rect.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
void SimpleComponent::WriteConfig() {
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include "ballistica/base/graphics/component/smoke_component.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
void SmokeComponent::WriteConfig() {
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include "ballistica/base/graphics/component/sprite_component.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
void SpriteComponent::WriteConfig() {
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#include "ballistica/base/graphics/gl/program/program_sprite_gl.h"
|
||||
#include "ballistica/base/graphics/gl/render_target_gl.h"
|
||||
#include "ballistica/base/graphics/gl/texture_data_gl.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/shared/math/rect.h"
|
||||
|
||||
// Turn this off to see how much blend overdraw is occurring.
|
||||
#define BA_GL_ENABLE_BLEND 1
|
||||
@ -254,42 +254,6 @@ void RendererGL::CheckGLCapabilities_() {
|
||||
// On Android, look at the GL version and try to get gl3 funcs to
|
||||
// determine if we're running ES3 or not.
|
||||
#if BA_OSTYPE_ANDROID
|
||||
// bool have_es3;
|
||||
// #if BA_USE_ES3_INCLUDES
|
||||
// have_es3 = true;
|
||||
// #else
|
||||
// have_es3 = (strstr(version_str, "OpenGL ES 3.") && gl3stubInit());
|
||||
// #endif // BA_OSTYPE_ANDROID
|
||||
|
||||
// if (have_es3) {
|
||||
// g_running_es3 = true;
|
||||
// } else {
|
||||
// #if !BA_USE_ES3_INCLUDES
|
||||
// g_running_es3 = false;
|
||||
|
||||
// // Can still support some stuff like framebuffer-blit with es2
|
||||
// extensions. assert(glBlitFramebuffer == nullptr ||
|
||||
// !first_extension_check_); glBlitFramebuffer =
|
||||
// (decltype(glBlitFramebuffer))eglGetProcAddress("glBlitFramebufferNV");
|
||||
// assert(glRenderbufferStorageMultisample == nullptr
|
||||
// || !first_extension_check_);
|
||||
// glRenderbufferStorageMultisample =
|
||||
// (decltype(glRenderbufferStorageMultisample))eglGetProcAddress(
|
||||
// "glRenderbufferStorageMultisampleNV");
|
||||
|
||||
// assert(glGenVertexArrays == nullptr || !first_extension_check_);
|
||||
// glGenVertexArrays =
|
||||
// (decltype(glGenVertexArrays))eglGetProcAddress("glGenVertexArraysOES");
|
||||
// assert(glDeleteVertexArrays == nullptr || !first_extension_check_);
|
||||
// glDeleteVertexArrays =
|
||||
// (decltype(glDeleteVertexArrays))eglGetProcAddress(
|
||||
// "glDeleteVertexArraysOES");
|
||||
// assert(glBindVertexArray == nullptr || !first_extension_check_);
|
||||
// glBindVertexArray =
|
||||
// (decltype(glBindVertexArray))eglGetProcAddress("glBindVertexArrayOES");
|
||||
|
||||
// #endif // BA_USE_ES3_INCLUDES
|
||||
// }
|
||||
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
|
||||
@ -300,75 +264,7 @@ void RendererGL::CheckGLCapabilities_() {
|
||||
assert(gl_version_major() == 3);
|
||||
is_speedy_android_device_ = gl_version_minor() >= 2;
|
||||
|
||||
// is_extra_speedy_android_device_ = false;
|
||||
is_adreno_ = (strstr(renderer, "Adreno") != nullptr);
|
||||
// draws_shields_funny_ = false; // Start optimistic.
|
||||
|
||||
// Ali tv box.
|
||||
// if (!strcmp(renderer, "Mali-450 MP")) {
|
||||
// is_speedy_android_device_ = true; // this is borderline
|
||||
// speedy/extra-speedy
|
||||
// // draws_shields_funny_ = true;
|
||||
// }
|
||||
|
||||
// Firetv, etc.. lets enable MSAA.
|
||||
// if (!strcmp(renderer, "Adreno (TM) 320")) {
|
||||
// is_recent_adreno_ = true;
|
||||
// }
|
||||
|
||||
// This is right on the borderline, but lets go with extra-speedy I guess.
|
||||
// if (!strcmp(renderer, "Adreno (TM) 330")) {
|
||||
// is_recent_adreno_ = true;
|
||||
// is_extra_speedy_android_device_ = true;
|
||||
// }
|
||||
|
||||
// *any* of the 4xx or 5xx series are extra-speedy.
|
||||
// if (strstr(renderer, "Adreno (TM) 4") || strstr(renderer, "Adreno (TM) 5")
|
||||
// || strstr(renderer, "Adreno (TM) 6")) {
|
||||
// is_extra_speedy_android_device_ = true;
|
||||
// is_recent_adreno_ = true;
|
||||
// }
|
||||
|
||||
// Some speedy malis (Galaxy S6 / Galaxy S7-ish).
|
||||
// if (strstr(renderer, "Mali-T760") || strstr(renderer, "Mali-T860")
|
||||
// || strstr(renderer, "Mali-T880")) {
|
||||
// is_extra_speedy_android_device_ = true;
|
||||
// }
|
||||
|
||||
// Note 8 is speed-tastic
|
||||
// if (!strcmp(renderer, "Mali-G71") || !strcmp(renderer, "Mali-G72")) {
|
||||
// is_extra_speedy_android_device_ = true;
|
||||
// }
|
||||
|
||||
// Covers Nexus player.
|
||||
// HMM Scratch that - this winds up being too slow for phones using this chip.
|
||||
// if (strstr(renderer, "PowerVR Rogue G6430")) {
|
||||
// is_extra_speedy_android_device_ = true;
|
||||
// }
|
||||
|
||||
// Figure out if we're a Tegra 4/K1/etc since we do some special stuff on
|
||||
// those...
|
||||
// if (!strcmp(renderer, "NVIDIA Tegra")) {
|
||||
// // tegra 4 won't have ES3 but will have framebuffer_multisample
|
||||
// if (!g_running_es3 && CheckGLExtension(ex, "framebuffer_multisample")) {
|
||||
// is_tegra_4_ = true;
|
||||
// is_speedy_android_device_ = true;
|
||||
// } else if (g_running_es3) {
|
||||
// // running ES3 - must be a K1 (for now)
|
||||
// is_tegra_k1_ = true;
|
||||
// is_extra_speedy_android_device_ = true;
|
||||
// } else {
|
||||
// // looks like Tegra-2 era stuff was just "NVIDIA Tegra" as well...
|
||||
// }
|
||||
// }
|
||||
|
||||
// Also store this globally for a few other bits of the app to use..
|
||||
// g_core->platform->set_is_tegra_k1(is_tegra_k1_);
|
||||
|
||||
// Extra-speedy implies speedy too..
|
||||
// if (is_extra_speedy_android_device_) {
|
||||
// is_speedy_android_device_ = true;
|
||||
// }
|
||||
|
||||
#endif // BA_OSTYPE_ANDROID
|
||||
|
||||
@ -407,15 +303,11 @@ void RendererGL::CheckGLCapabilities_() {
|
||||
|
||||
g_base->graphics_server->SetTextureCompressionTypes(c_types);
|
||||
|
||||
// Both GL 3 and GL ES 3.0 support depth textures (and thus our high
|
||||
// quality mode) as a core feature.
|
||||
// g_base->graphics->SetSupportsHighQualityGraphics(true);
|
||||
|
||||
// Store the tex-compression type we support.
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
|
||||
// Anisotropic sampling is still an extension as of both GL 3 and ES 3,
|
||||
// so we need to test for it.
|
||||
// Anisotropic sampling is still an extension as of both GL 3 and ES 3, so
|
||||
// we need to test for it.
|
||||
anisotropic_support_ =
|
||||
CheckGLExtension(extensions, "texture_filter_anisotropic");
|
||||
if (anisotropic_support_) {
|
||||
@ -436,8 +328,8 @@ void RendererGL::CheckGLCapabilities_() {
|
||||
combined_texture_image_unit_count_ =
|
||||
GLGetInt(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
|
||||
|
||||
// If we're running ES3, ask about our max multisample counts and whether we
|
||||
// can enable MSAA.
|
||||
// If we're running ES3, ask about our max multisample counts and whether
|
||||
// we can enable MSAA.
|
||||
msaa_max_samples_rgb565_ = msaa_max_samples_rgb8_ = 0; // start pessimistic
|
||||
|
||||
bool have_gl_get_internal_format_iv{};
|
||||
@ -850,12 +742,6 @@ void RendererGL::SyncGLState_() {
|
||||
glFrontFace(GL_CCW);
|
||||
}
|
||||
BA_DEBUG_CHECK_GL_ERROR;
|
||||
|
||||
// if (time(nullptr)%2 == 0) {
|
||||
// glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
// } else {
|
||||
// glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
// }
|
||||
#endif // BA_RIFT_BUILD
|
||||
|
||||
active_tex_unit_ = -1; // force a set next time
|
||||
@ -948,8 +834,8 @@ void RendererGL::SyncGLState_() {
|
||||
assert(VAR&& VAR == dynamic_cast<TYPE*>(buffer->Get())); \
|
||||
buffer++
|
||||
|
||||
// Takes all latest mesh data from the client side and applies it
|
||||
// to our gl implementations.
|
||||
// Takes all latest mesh data from the client side and applies it to our gl
|
||||
// implementations.
|
||||
void RendererGL::UpdateMeshes(
|
||||
const std::vector<Object::Ref<MeshDataClientHandle> >& meshes,
|
||||
const std::vector<int8_t>& index_sizes,
|
||||
@ -1193,7 +1079,8 @@ void RendererGL::ProcessRenderCommandBuffer(RenderCommandBuffer* buffer,
|
||||
const TextureAsset* t = buffer->GetTexture();
|
||||
const TextureAsset* t_mask = buffer->GetTexture();
|
||||
p->SetColorTexture(t);
|
||||
// If this isn't a full-res texture, ramp down the blurring we do.
|
||||
// If this isn't a full-res texture, ramp down the blurring we
|
||||
// do.
|
||||
p->SetShadow(shadow_offset_x, shadow_offset_y,
|
||||
std::max(0.0f, shadow_blur), shadow_opacity);
|
||||
p->SetMaskUV2Texture(t_mask);
|
||||
@ -1215,7 +1102,8 @@ void RendererGL::ProcessRenderCommandBuffer(RenderCommandBuffer* buffer,
|
||||
const TextureAsset* t = buffer->GetTexture();
|
||||
const TextureAsset* t_mask = buffer->GetTexture();
|
||||
p->SetColorTexture(t);
|
||||
// If this isn't a full-res texture, ramp down the blurring we do.
|
||||
// If this isn't a full-res texture, ramp down the blurring we
|
||||
// do.
|
||||
p->SetShadow(shadow_offset_x, shadow_offset_y,
|
||||
std::max(0.0f, shadow_blur), shadow_opacity);
|
||||
p->SetMaskUV2Texture(t_mask);
|
||||
@ -1612,7 +1500,7 @@ void RendererGL::ProcessRenderCommandBuffer(RenderCommandBuffer* buffer,
|
||||
buffer->GetFloats(&r, &g, &b, &reflect_r, &reflect_g, &reflect_b);
|
||||
ProgramObjectGL* p;
|
||||
|
||||
// Testing why reflection is wonky..
|
||||
// Testing why reflection is wonky.
|
||||
if (explicit_bool(false)) {
|
||||
p = world_space ? obj_lightshad_worldspace_prog_
|
||||
: obj_lightshad_prog_;
|
||||
@ -1928,8 +1816,8 @@ void RendererGL::ProcessRenderCommandBuffer(RenderCommandBuffer* buffer,
|
||||
case ShadingType::kSpecial: {
|
||||
SetDoubleSided_(false);
|
||||
|
||||
// if we ever need to use non-blend version
|
||||
// of this in real renders, we should split off a non-blend version
|
||||
// If we ever need to use non-blend version of this in real
|
||||
// renders, we should split off a non-blend version.
|
||||
SetBlend(true);
|
||||
SetBlendPremult(true);
|
||||
auto source = (SpecialComponent::Source)buffer->GetInt();
|
||||
@ -2211,8 +2099,8 @@ void RendererGL::BlitBuffer(RenderTarget* src_in, RenderTarget* dst_in,
|
||||
|
||||
bool do_shader_blit{true};
|
||||
|
||||
// If they want depth we *MUST* use glBlitFramebuffer and can't have linear
|
||||
// interp.
|
||||
// If they want depth we *MUST* use glBlitFramebuffer and can't have
|
||||
// linear interp.
|
||||
if (depth) {
|
||||
assert(!force_shader_mode);
|
||||
linear_interpolation = false;
|
||||
@ -2250,7 +2138,7 @@ void RendererGL::BlitBuffer(RenderTarget* src_in, RenderTarget* dst_in,
|
||||
g_base->graphics_server->ModelViewReset();
|
||||
g_base->graphics_server->SetOrthoProjection(-1, 1, -1, 1, -1, 1);
|
||||
|
||||
// Copied from ShadingType::kSimpleColor
|
||||
// Copied from ShadingType::kSimpleColor.
|
||||
SetDoubleSided_(false);
|
||||
SetBlend(false);
|
||||
ProgramSimpleGL* p = simple_tex_prog_;
|
||||
@ -2554,14 +2442,6 @@ auto RendererGL::GetFunkyDepthIssue_() -> bool {
|
||||
return funky_depth_issue_;
|
||||
}
|
||||
|
||||
// auto RendererGL::GetDrawsShieldsFunny_() -> bool {
|
||||
// if (!draws_shields_funny_set_) {
|
||||
// BA_LOG_ONCE(LogLevel::kError,
|
||||
// "fetching draws-shields-funny value but not set");
|
||||
// }
|
||||
// return draws_shields_funny_;
|
||||
// }
|
||||
|
||||
#if BA_OSTYPE_ANDROID
|
||||
std::string RendererGL::GetAutoAndroidRes() {
|
||||
assert(g_base->app_adapter->InGraphicsContext());
|
||||
@ -2759,9 +2639,9 @@ void RendererGL::Load() {
|
||||
p = shield_prog_ = new ProgramShieldGL(this, 0);
|
||||
RetainShader_(p);
|
||||
|
||||
// Conditional seems to be a *very* slight win on some architectures (A7), a
|
||||
// loss on some (A5) and a wash on some (Adreno 320).
|
||||
// Gonna wait before a clean win before turning it on.
|
||||
// Conditional seems to be a *very* slight win on some architectures (A7),
|
||||
// a loss on some (A5) and a wash on some (Adreno 320). Gonna wait before
|
||||
// a clean win before turning it on.
|
||||
p = postprocess_prog_ = new ProgramPostProcessGL(this, high_qual_pp_flag);
|
||||
RetainShader_(p);
|
||||
if (g_base->graphics_server->quality() >= GraphicsQuality::kHigher) {
|
||||
@ -2805,8 +2685,8 @@ void RendererGL::Load() {
|
||||
UpdateVignetteTex_(true);
|
||||
}
|
||||
|
||||
// Let's pre-fill our recyclable mesh-datas list to reduce the need to make
|
||||
// more which could cause hitches.
|
||||
// Let's pre-fill our recyclable mesh-datas list to reduce the need to
|
||||
// make more which could cause hitches.
|
||||
assert(recycle_mesh_datas_simple_split_.empty());
|
||||
for (int i = 0; i < 10; i++) {
|
||||
recycle_mesh_datas_simple_split_.push_back(new MeshDataSimpleSplitGL(this));
|
||||
@ -2958,7 +2838,7 @@ auto RendererGL::NewMeshData(MeshDataType mesh_type,
|
||||
switch (mesh_type) {
|
||||
case MeshDataType::kIndexedSimpleSplit: {
|
||||
MeshDataSimpleSplitGL* data;
|
||||
// use a recycled one if we've got one.. otherwise create a new one
|
||||
// Use a recycled one if we've got one; otherwise create a new one.
|
||||
auto i = recycle_mesh_datas_simple_split_.rbegin();
|
||||
if (i != recycle_mesh_datas_simple_split_.rend()) {
|
||||
data = *i;
|
||||
@ -2971,7 +2851,7 @@ auto RendererGL::NewMeshData(MeshDataType mesh_type,
|
||||
}
|
||||
case MeshDataType::kIndexedObjectSplit: {
|
||||
MeshDataObjectSplitGL* data;
|
||||
// use a recycled one if we've got one.. otherwise create a new one
|
||||
// Use a recycled one if we've got one; otherwise create a new one.
|
||||
auto i = recycle_mesh_datas_object_split_.rbegin();
|
||||
if (i != recycle_mesh_datas_object_split_.rend()) {
|
||||
data = *i;
|
||||
@ -2984,7 +2864,7 @@ auto RendererGL::NewMeshData(MeshDataType mesh_type,
|
||||
}
|
||||
case MeshDataType::kIndexedSimpleFull: {
|
||||
MeshDataSimpleFullGL* data;
|
||||
// use a recycled one if we've got one.. otherwise create a new one
|
||||
// Use a recycled one if we've got one; otherwise create a new one.
|
||||
auto i = recycle_mesh_datas_simple_full_.rbegin();
|
||||
if (i != recycle_mesh_datas_simple_full_.rend()) {
|
||||
data = *i;
|
||||
@ -2998,7 +2878,7 @@ auto RendererGL::NewMeshData(MeshDataType mesh_type,
|
||||
}
|
||||
case MeshDataType::kIndexedDualTextureFull: {
|
||||
MeshDataDualTextureFullGL* data;
|
||||
// use a recycled one if we've got one.. otherwise create a new one
|
||||
// Use a recycled one if we've got one; otherwise create a new one.
|
||||
auto i = recycle_mesh_datas_dual_texture_full_.rbegin();
|
||||
if (i != recycle_mesh_datas_dual_texture_full_.rend()) {
|
||||
data = *i;
|
||||
@ -3012,7 +2892,7 @@ auto RendererGL::NewMeshData(MeshDataType mesh_type,
|
||||
}
|
||||
case MeshDataType::kIndexedSmokeFull: {
|
||||
MeshDataSmokeFullGL* data;
|
||||
// use a recycled one if we've got one.. otherwise create a new one
|
||||
// Use a recycled one if we've got one; otherwise create a new one.
|
||||
auto i = recycle_mesh_datas_smoke_full_.rbegin();
|
||||
if (i != recycle_mesh_datas_smoke_full_.rend()) {
|
||||
data = *i;
|
||||
@ -3026,7 +2906,7 @@ auto RendererGL::NewMeshData(MeshDataType mesh_type,
|
||||
}
|
||||
case MeshDataType::kSprite: {
|
||||
MeshDataSpriteGL* data;
|
||||
// use a recycled one if we've got one.. otherwise create a new one
|
||||
// Use a recycled one if we've got one; otherwise create a new one.
|
||||
auto i = recycle_mesh_datas_sprite_.rbegin();
|
||||
if (i != recycle_mesh_datas_sprite_.rend()) {
|
||||
data = *i;
|
||||
@ -3046,10 +2926,9 @@ auto RendererGL::NewMeshData(MeshDataType mesh_type,
|
||||
|
||||
void RendererGL::DeleteMeshData(MeshRendererData* source_in,
|
||||
MeshDataType mesh_type) {
|
||||
// When we're done with mesh-data we keep it around for recycling.
|
||||
// It seems that killing off VAO/VBOs can be hitchy (on mac at least).
|
||||
// Hmmm should we have some sort of threshold at which point we kill off
|
||||
// some?
|
||||
// When we're done with mesh-data we keep it around for recycling. It
|
||||
// seems that killing off VAO/VBOs can be hitchy (on mac at least). Hmmm
|
||||
// should we have some sort of threshold at which point we kill off some?
|
||||
|
||||
switch (mesh_type) {
|
||||
case MeshDataType::kIndexedSimpleSplit: {
|
||||
@ -3105,8 +2984,8 @@ void RendererGL::DeleteMeshData(MeshRendererData* source_in,
|
||||
}
|
||||
|
||||
void RendererGL::CheckForErrors() {
|
||||
// lets only check periodically.. i doubt it hurts to run this all the time
|
||||
// but just in case...
|
||||
// Lets only check periodically. I doubt it hurts to run this all the time
|
||||
// but just in case.
|
||||
error_check_counter_++;
|
||||
if (error_check_counter_ > 120) {
|
||||
error_check_counter_ = 0;
|
||||
@ -3201,8 +3080,8 @@ void RendererGL::GenerateCameraBufferBlurPasses() {
|
||||
true, // linear_interp
|
||||
false, // depth
|
||||
true, // tex
|
||||
false, // depthTex
|
||||
high_quality_fbos, // highQuality
|
||||
false, // depth_tex
|
||||
high_quality_fbos, // high_quality
|
||||
false, // msaa
|
||||
false // alpha
|
||||
)); // NOLINT(whitespace/parens)
|
||||
@ -3215,8 +3094,8 @@ void RendererGL::GenerateCameraBufferBlurPasses() {
|
||||
true, // linear_interp
|
||||
false, // depth
|
||||
true, // tex
|
||||
false, // depthTex
|
||||
false, // highQuality
|
||||
false, // depth_tex
|
||||
false, // high_quality
|
||||
false, // msaa
|
||||
false // alpha
|
||||
)); // NOLINT(whitespace/parens)
|
||||
@ -3263,9 +3142,9 @@ void RendererGL::CardboardEnableScissor() { glEnable(GL_SCISSOR_TEST); }
|
||||
void RendererGL::VREyeRenderBegin() {
|
||||
assert(g_core->vr_mode());
|
||||
|
||||
// On rift we need to turn off srgb conversion for each eye render
|
||||
// so we can dump our linear data into oculus' srgb buffer as-is.
|
||||
// (we really should add proper srgb support to the engine at some point)
|
||||
// On rift we need to turn off srgb conversion for each eye render so we
|
||||
// can dump our linear data into oculus' srgb buffer as-is. (we really
|
||||
// should add proper srgb support to the engine at some point).
|
||||
#if BA_RIFT_BUILD
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
#endif // BA_RIFT_BUILD
|
||||
@ -3275,7 +3154,7 @@ void RendererGL::VREyeRenderBegin() {
|
||||
|
||||
#if BA_VR_BUILD
|
||||
void RendererGL::VRSyncRenderStates() {
|
||||
// GL state has been mucked with outside of our code; let's resync stuff..
|
||||
// GL state has been mucked with outside of our code; let's resync stuff.
|
||||
SyncGLState_();
|
||||
}
|
||||
#endif // BA_VR_BUILD
|
||||
|
||||
@ -7,8 +7,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ballistica/shared/ballistica.h"
|
||||
|
||||
#if BA_ENABLE_OPENGL
|
||||
|
||||
#include "ballistica/base/graphics/gl/gl_sys.h"
|
||||
@ -27,13 +25,6 @@
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
// extern int g_msaa_max_samples_rgb565;
|
||||
// extern int g_msaa_max_samples_rgb8;
|
||||
// extern bool g_vao_support;
|
||||
// extern bool g_running_es3;
|
||||
// extern bool g_anisotropic_support;
|
||||
// extern float g_max_anisotropy;
|
||||
|
||||
// For now lets not go above 8 since that's what the iPhone 3gs has. ...haha
|
||||
// perhaps can reconsider that since the 3gs was 15 years ago.
|
||||
constexpr int kMaxGLTexUnitsUsed = 5;
|
||||
@ -227,7 +218,6 @@ class RendererGL : public Renderer {
|
||||
|
||||
private:
|
||||
static auto GetFunkyDepthIssue_() -> bool;
|
||||
// static auto GetDrawsShieldsFunny_()->bool;
|
||||
void CheckFunkyDepthIssue_();
|
||||
auto GetMSAASamplesForFramebuffer_(int width, int height) -> int;
|
||||
void UpdateMSAAEnabled_() override;
|
||||
@ -248,8 +238,8 @@ class RendererGL : public Renderer {
|
||||
void ScissorPop_(RenderTarget* render_target);
|
||||
void BindVertexArray_(GLuint v);
|
||||
|
||||
// Note: This is only for use when VAOs aren't supported.
|
||||
// void SetVertexAttributeArrayEnabled_(GLuint i, bool enabled);
|
||||
// Note: This is only for use when VAOs aren't supported. void
|
||||
// SetVertexAttributeArrayEnabled_(GLuint i, bool enabled);
|
||||
void BindTexture_(GLuint type, const TextureAsset* t, GLuint tex_unit = 0);
|
||||
void BindTexture_(GLuint type, GLuint tex, GLuint tex_unit = 0);
|
||||
void BindTextureUnit(uint32_t tex_unit);
|
||||
@ -276,8 +266,6 @@ class RendererGL : public Renderer {
|
||||
bool double_sided_{};
|
||||
bool invalidate_framebuffer_support_{};
|
||||
bool checked_gl_version_{};
|
||||
GLint gl_version_major_{};
|
||||
GLint gl_version_minor_{};
|
||||
int last_blur_res_count_{};
|
||||
float last_cam_buffer_width_{};
|
||||
float last_cam_buffer_height_{};
|
||||
@ -289,13 +277,15 @@ class RendererGL : public Renderer {
|
||||
float vignette_tex_inner_b_{};
|
||||
float depth_range_min_{};
|
||||
float depth_range_max_{};
|
||||
GLint gl_version_major_{};
|
||||
GLint gl_version_minor_{};
|
||||
GLint screen_framebuffer_{};
|
||||
GLuint random_tex_{};
|
||||
GLuint vignette_tex_{};
|
||||
GLint viewport_x_{};
|
||||
GLint viewport_y_{};
|
||||
GLint viewport_width_{};
|
||||
GLint viewport_height_{};
|
||||
GLuint vignette_tex_{};
|
||||
millisecs_t dof_update_time_{};
|
||||
std::vector<Object::Ref<FramebufferObjectGL> > blur_buffers_;
|
||||
std::vector<std::unique_ptr<ProgramGL> > shaders_;
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#include "ballistica/base/graphics/component/special_component.h"
|
||||
#include "ballistica/base/graphics/component/sprite_component.h"
|
||||
#include "ballistica/base/graphics/graphics_server.h"
|
||||
#include "ballistica/base/graphics/mesh/image_mesh.h"
|
||||
#include "ballistica/base/graphics/renderer/renderer.h"
|
||||
#include "ballistica/base/graphics/support/camera.h"
|
||||
#include "ballistica/base/graphics/support/net_graph.h"
|
||||
#include "ballistica/base/graphics/support/screen_messages.h"
|
||||
@ -1535,12 +1537,23 @@ void Graphics::SetScreenResolution(float x, float y) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We'll need to ship a new settings to the server with this change.
|
||||
graphics_settings_dirty_ = true;
|
||||
|
||||
res_x_ = x;
|
||||
res_y_ = y;
|
||||
|
||||
UpdateScreen_();
|
||||
}
|
||||
|
||||
void Graphics::OnUIScaleChange() {
|
||||
// UIScale affects our virtual res calculations. Redo those.
|
||||
UpdateScreen_();
|
||||
}
|
||||
|
||||
void Graphics::UpdateScreen_() {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// We'll need to ship a new settings to the server with this change.
|
||||
graphics_settings_dirty_ = true;
|
||||
|
||||
// Calc virtual res. In vr mode our virtual res is independent of our
|
||||
// screen size (since it gets drawn to an overlay).
|
||||
if (g_core->vr_mode()) {
|
||||
@ -1555,14 +1568,14 @@ void Graphics::SetScreenResolution(float x, float y) {
|
||||
// Need to rebuild internal components (some are sized to the screen).
|
||||
internal_components_inited_ = false;
|
||||
|
||||
// Inform all our logic thread buddies of this change.
|
||||
g_base->logic->OnScreenSizeChange(res_x_virtual_, res_y_virtual_, res_x_,
|
||||
res_y_);
|
||||
|
||||
// This may trigger us sending initial graphics settings to the
|
||||
// graphics-server to kick off drawing.
|
||||
got_screen_resolution_ = true;
|
||||
UpdateInitialGraphicsSettingsSend_();
|
||||
|
||||
// Inform all our logic thread buddies of virtual/physical res changes.
|
||||
g_base->logic->OnScreenSizeChange(res_x_virtual_, res_y_virtual_, res_x_,
|
||||
res_y_);
|
||||
}
|
||||
|
||||
auto Graphics::CubeMapFromReflectionType(ReflectionType reflection_type)
|
||||
@ -1723,10 +1736,6 @@ void Graphics::DrawUIBounds(RenderPass* pass) {
|
||||
c.SetColor(1, 0, 0);
|
||||
{
|
||||
auto xf = c.ScopedTransform();
|
||||
// float width = pass->virtual_width();
|
||||
// float height = pass->virtual_height();
|
||||
|
||||
// printf("DIMS %.2f %.2f\n", width, height);
|
||||
|
||||
float width, height;
|
||||
if (g_base->ui->scale() == UIScale::kSmall) {
|
||||
|
||||
@ -15,9 +15,8 @@
|
||||
#include "ballistica/shared/foundation/object.h"
|
||||
#include "ballistica/shared/foundation/types.h"
|
||||
#include "ballistica/shared/generic/snapshot.h"
|
||||
#include "ballistica/shared/math/matrix44f.h"
|
||||
#include "ballistica/shared/math/rect.h"
|
||||
#include "ballistica/shared/math/vector2f.h"
|
||||
#include "ballistica/shared/math/vector3f.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
@ -63,10 +62,13 @@ class Graphics {
|
||||
void OnScreenSizeChange();
|
||||
void DoApplyAppConfig();
|
||||
|
||||
/// Should be called by the app-adapter to keep the engine informed
|
||||
/// on the drawable area it has to work with (in pixels).
|
||||
/// Should be called by the app-adapter to keep the engine informed on the
|
||||
/// drawable area it has to work with (in pixels).
|
||||
void SetScreenResolution(float x, float y);
|
||||
|
||||
/// Should be called when UIScale changes.
|
||||
void OnUIScaleChange();
|
||||
|
||||
void StepDisplayTime();
|
||||
|
||||
auto TextureQualityFromAppConfig() -> TextureQualityRequest;
|
||||
@ -364,6 +366,7 @@ class Graphics {
|
||||
ScreenMessages* const screenmessages;
|
||||
|
||||
protected:
|
||||
void UpdateScreen_();
|
||||
virtual ~Graphics();
|
||||
virtual void DoDrawFade(FrameDef* frame_def, float amt);
|
||||
static void CalcVirtualRes_(float* x, float* y);
|
||||
|
||||
@ -50,9 +50,12 @@ void GraphicsServer::ApplySettings(const GraphicsSettings* settings) {
|
||||
if (renderer_) {
|
||||
renderer_->set_pixel_scale(settings->pixel_scale);
|
||||
}
|
||||
// Note: not checking virtual res here; assuming it only changes when
|
||||
// actual res changes.
|
||||
if (res_x_ != settings->resolution.x || res_y_ != settings->resolution.y) {
|
||||
// Note: need to look at both physical and virtual res here; its possible
|
||||
// for physical to stay the same but for virtual to change (ui-scale
|
||||
// changes can do this).
|
||||
if (res_x_ != settings->resolution.x || res_y_ != settings->resolution.y
|
||||
|| res_x_virtual_ != settings->resolution_virtual.x
|
||||
|| res_y_virtual_ != settings->resolution_virtual.y) {
|
||||
res_x_ = settings->resolution.x;
|
||||
res_y_ = settings->resolution.y;
|
||||
res_x_virtual_ = settings->resolution_virtual.x;
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "ballistica/base/graphics/graphics_vr.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/object_component.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/component/special_component.h"
|
||||
|
||||
@ -472,13 +472,13 @@ void RenderPass::SetFrustum(float near_val, float far_val) {
|
||||
} else {
|
||||
// Old angle-based stuff:
|
||||
float x;
|
||||
float angleY = (cam_fov_y_ / 2.0f) * kPi / 180.0f;
|
||||
float y = near_val * tanf(angleY);
|
||||
float angle_y = (cam_fov_y_ / 2.0f) * kPi / 180.0f;
|
||||
float y = near_val * tanf(angle_y);
|
||||
|
||||
// Fov-x < 0 implies to use aspect ratio.
|
||||
if (cam_fov_x_ > 0.0f) {
|
||||
float angleX = (cam_fov_x_ / 2.0f) * kPi / 180.0f;
|
||||
x = near_val * tanf(angleX);
|
||||
float angle_x = (cam_fov_x_ / 2.0f) * kPi / 180.0f;
|
||||
x = near_val * tanf(angle_x);
|
||||
} else {
|
||||
x = y * GetPhysicalAspectRatio();
|
||||
}
|
||||
|
||||
@ -328,10 +328,10 @@ void Camera::UpdatePosition() {
|
||||
x_clamped_focus, y_clamped_focus, z_clamped_focus);
|
||||
}
|
||||
|
||||
// Now, for camera aiming purposes, add some of their velocity and
|
||||
// clamp to the bounds, taking their radius into account. if our AOI
|
||||
// sphere is bigger than a given dimension, center it; otherwise
|
||||
// clamp to the box inset by our radius.
|
||||
// Now, for camera aiming purposes, add some of their velocity
|
||||
// and clamp to the bounds, taking their radius into account. if
|
||||
// our AOI sphere is bigger than a given dimension, center it;
|
||||
// otherwise clamp to the box inset by our radius.
|
||||
float x_clamped, y_clamped, z_clamped, x_mirrored_clamped;
|
||||
float diameter = i.radius() * 2.0f;
|
||||
|
||||
@ -371,9 +371,9 @@ void Camera::UpdatePosition() {
|
||||
i.position().z));
|
||||
}
|
||||
|
||||
// Let's also do a version mirrored across the camera's x coordinate
|
||||
// (adding this to our tracked point set causes us zoom out instead
|
||||
// of rotating generally)
|
||||
// Let's also do a version mirrored across the camera's x
|
||||
// coordinate (adding this to our tracked point set causes us
|
||||
// zoom out instead of rotating generally)
|
||||
float x_mirrored = position_.x - (i.position().x - position_.x);
|
||||
if (diameter
|
||||
> (area_of_interest_bounds_[3] - area_of_interest_bounds_[0])) {
|
||||
@ -395,8 +395,8 @@ void Camera::UpdatePosition() {
|
||||
z_clamped - position_.z};
|
||||
|
||||
// For sample 0, subtract AOI radius in camera-space x and y.
|
||||
// For sample 1, add them.
|
||||
// this way we should get the whole sphere.
|
||||
// For sample 1, add them. this way we should get the whole
|
||||
// sphere.
|
||||
if (sample == 0) {
|
||||
to_point -= corner_offs;
|
||||
} else if (sample == 1) {
|
||||
@ -607,7 +607,6 @@ void Camera::Update(millisecs_t elapsed) {
|
||||
float damping2 = 0.006f;
|
||||
float xy_blend_speed = 0.0002f;
|
||||
time_ += elapsed;
|
||||
// millisecs_t real_time = g_core->GetAppTimeMillisecs();
|
||||
|
||||
// Prevent camera "explosions" if we've been unable to update for a while.
|
||||
elapsed = std::min(millisecs_t{100}, elapsed);
|
||||
@ -676,8 +675,8 @@ void Camera::Update(millisecs_t elapsed) {
|
||||
elapsedf * rand_component * 4.0f * (-0.5f + RandomFloat());
|
||||
}
|
||||
|
||||
// If we have no important areas of interest, keep our camera from moving too
|
||||
// fast.
|
||||
// If we have no important areas of interest, keep our camera from moving
|
||||
// too fast.
|
||||
if (!have_real_areas_of_interest_) {
|
||||
speed *= 0.5f;
|
||||
}
|
||||
@ -952,7 +951,9 @@ void Camera::ApplyToFrameDef(FrameDef* frame_def) {
|
||||
float final_fov_y2 = final_fov_x / render_ratio;
|
||||
|
||||
// If we're not smoothing this frame, snap immediately.
|
||||
if (!smooth_next_frame_) xy_constrain_blend_ = x_constrained_ ? 1.0f : 0.0f;
|
||||
if (!smooth_next_frame_) {
|
||||
xy_constrain_blend_ = x_constrained_ ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
// We smoothly blend between our x-constrained and non-x-constrained y values
|
||||
// so that we don't see a hitch when it switches.
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "ballistica/base/assets/asset.h"
|
||||
#include "ballistica/base/graphics/support/graphics_settings.h"
|
||||
#include "ballistica/shared/generic/snapshot.h"
|
||||
#include "ballistica/shared/math/matrix44f.h"
|
||||
#include "ballistica/shared/math/vector2f.h"
|
||||
|
||||
@ -5,6 +5,9 @@
|
||||
#include <list>
|
||||
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/mesh/image_mesh.h"
|
||||
#include "ballistica/base/graphics/mesh/mesh_indexed_simple_full.h"
|
||||
#include "ballistica/base/graphics/text/text_group.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
|
||||
@ -2,9 +2,11 @@
|
||||
|
||||
#include "ballistica/base/graphics/support/screen_messages.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
|
||||
#include "ballistica/base/graphics/text/text_graphics.h"
|
||||
#include "ballistica/base/graphics/text/text_group.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/base/input/device/touch_input.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/support/camera.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/app_mode/app_mode.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
@ -9,12 +11,12 @@
|
||||
#include "ballistica/base/networking/networking.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/context.h"
|
||||
#include "ballistica/base/support/plus_soft.h"
|
||||
#include "ballistica/base/support/stdio_console.h"
|
||||
#include "ballistica/base/ui/dev_console.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/python/python_sys.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
|
||||
@ -4,9 +4,8 @@
|
||||
#define BALLISTICA_BASE_LOGIC_LOGIC_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "ballistica/shared/foundation/object.h"
|
||||
#include "ballistica/shared/generic/runnable.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
@ -117,9 +116,7 @@ class Logic {
|
||||
auto applied_app_config() const { return applied_app_config_; }
|
||||
auto shutting_down() const { return shutting_down_; }
|
||||
auto shutdown_completed() const { return shutdown_completed_; }
|
||||
|
||||
auto graphics_ready() const { return graphics_ready_; }
|
||||
|
||||
auto app_active() const { return app_active_; }
|
||||
|
||||
private:
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
#ifndef BALLISTICA_BASE_PYTHON_BASE_PYTHON_H_
|
||||
#define BALLISTICA_BASE_PYTHON_BASE_PYTHON_H_
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "ballistica/base/base.h"
|
||||
#include "ballistica/shared/python/python_object_set.h"
|
||||
|
||||
@ -175,7 +177,6 @@ class BasePython {
|
||||
|
||||
void SoftImportPlus();
|
||||
void SoftImportClassic();
|
||||
// void SoftImportUIV1();
|
||||
|
||||
private:
|
||||
std::set<std::string> do_once_locations_;
|
||||
|
||||
@ -719,20 +719,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
|
||||
|
||||
// Just build this once and recycle it.
|
||||
if (!g_base->python->objs().Exists(BasePython::ObjID::kEnv)) {
|
||||
const char* ui_scale;
|
||||
switch (g_base->ui->scale()) {
|
||||
case UIScale::kLarge:
|
||||
ui_scale = "large";
|
||||
break;
|
||||
case UIScale::kMedium:
|
||||
ui_scale = "medium";
|
||||
break;
|
||||
case UIScale::kSmall:
|
||||
ui_scale = "small";
|
||||
break;
|
||||
default:
|
||||
throw Exception();
|
||||
}
|
||||
std::optional<std::string> user_py_dir = g_core->GetUserPythonDirectory();
|
||||
std::optional<std::string> app_py_dir = g_core->GetAppPythonDirectory();
|
||||
std::optional<std::string> site_py_dir = g_core->GetSitePythonDirectory();
|
||||
@ -751,7 +737,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
|
||||
"sO" // python_directory_app
|
||||
"ss" // platform
|
||||
"ss" // subplatform
|
||||
"ss" // ui_scale
|
||||
"sO" // on_tv
|
||||
"sO" // vr_mode
|
||||
"sO" // demo_mode
|
||||
@ -774,7 +759,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
|
||||
app_py_dir ? *PythonRef::FromString(*app_py_dir) : Py_None,
|
||||
"platform", g_core->platform->GetPlatformName().c_str(),
|
||||
"subplatform", g_core->platform->GetSubplatformName().c_str(),
|
||||
"ui_scale", ui_scale,
|
||||
"on_tv", g_core->platform->IsRunningOnTV() ? Py_True : Py_False,
|
||||
"vr_mode", g_core->vr_mode() ? Py_True : Py_False,
|
||||
"demo_mode", g_buildconfig.demo_build() ? Py_True : Py_False,
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/app_mode/app_mode.h"
|
||||
#include "ballistica/base/assets/sound_asset.h"
|
||||
#include "ballistica/base/assets/sound_asset.h" // IWYU pragma: keep.
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
@ -62,7 +62,7 @@ static PyMethodDef PyGetSimpleSoundDef = {
|
||||
static auto PySetUIInputDevice(PyObject* self, PyObject* args,
|
||||
PyObject* keywds) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
assert(g_base->InLogicThread());
|
||||
BA_PRECONDITION(g_base->InLogicThread());
|
||||
static const char* kwlist[] = {"input_device_id", nullptr};
|
||||
PyObject* input_device_id_obj = Py_None;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O",
|
||||
@ -97,6 +97,89 @@ static PyMethodDef PySetUIInputDeviceDef = {
|
||||
"Sets the input-device that currently owns the user interface.",
|
||||
};
|
||||
|
||||
// ------------------------------ set_ui_scale ---------------------------------
|
||||
|
||||
static auto PySetUIScale(PyObject* self, PyObject* args,
|
||||
PyObject* keywds) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
BA_PRECONDITION(g_base->InLogicThread());
|
||||
|
||||
const char* scalestr;
|
||||
|
||||
static const char* kwlist[] = {"scale", nullptr};
|
||||
PyObject* input_device_id_obj = Py_None;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s",
|
||||
const_cast<char**>(kwlist), &scalestr)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// FIXME: Should have this take an enum directly once we have an easy way
|
||||
// to share enums between Python/CPP.
|
||||
UIScale scale;
|
||||
if (!strcmp(scalestr, "small")) {
|
||||
scale = UIScale::kSmall;
|
||||
} else if (!strcmp(scalestr, "medium")) {
|
||||
scale = UIScale::kMedium;
|
||||
} else if (!strcmp(scalestr, "large")) {
|
||||
scale = UIScale::kLarge;
|
||||
} else {
|
||||
throw Exception("Invalid scale value.", PyExcType::kValue);
|
||||
}
|
||||
g_base->SetUIScale(scale);
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
static PyMethodDef PySetUIScaleDef = {
|
||||
"set_ui_scale", // name
|
||||
(PyCFunction)PySetUIScale, // method
|
||||
METH_VARARGS | METH_KEYWORDS, // flags
|
||||
|
||||
"set_ui_scale(scale: str)"
|
||||
" -> None\n"
|
||||
"\n"
|
||||
"(internal)\n",
|
||||
};
|
||||
// ------------------------------ set_ui_scale ---------------------------------
|
||||
|
||||
static auto PyGetUIScale(PyObject* self) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
BA_PRECONDITION(g_base->InLogicThread());
|
||||
|
||||
// FIXME: Should have this return enums directly once we have an easy way
|
||||
// to share enums between Python/CPP.
|
||||
auto scale = g_base->ui->scale();
|
||||
|
||||
const char* val;
|
||||
switch (scale) {
|
||||
case UIScale::kSmall:
|
||||
val = "small";
|
||||
break;
|
||||
case UIScale::kMedium:
|
||||
val = "medium";
|
||||
break;
|
||||
case UIScale::kLarge:
|
||||
val = "large";
|
||||
break;
|
||||
default:
|
||||
throw Exception("Unhandled scale value.");
|
||||
}
|
||||
return PyUnicode_FromString(val);
|
||||
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
static PyMethodDef PyGetUIScaleDef = {
|
||||
"get_ui_scale", // name
|
||||
(PyCFunction)PyGetUIScale, // method
|
||||
METH_NOARGS, // flags
|
||||
|
||||
"get_ui_scale()"
|
||||
" -> str\n"
|
||||
"\n"
|
||||
"(internal)\n",
|
||||
};
|
||||
|
||||
// ----------------------------- hastouchscreen --------------------------------
|
||||
|
||||
static auto PyHasTouchScreen(PyObject* self, PyObject* args,
|
||||
@ -1899,10 +1982,6 @@ static auto PySetDrawUIBounds(PyObject* self, PyObject* args,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// if (g_base->graphics->draw_ui_bounds()) {
|
||||
// Py_RETURN_TRUE;
|
||||
// }
|
||||
// Py_RETURN_FALSE;
|
||||
g_base->graphics->set_draw_ui_bounds(value);
|
||||
Py_RETURN_NONE;
|
||||
|
||||
@ -1978,6 +2057,8 @@ auto PythonMoethodsBase3::GetMethods() -> std::vector<PyMethodDef> {
|
||||
PyGetIdleTimeDef,
|
||||
PyExtraHashValueDef,
|
||||
PySetUIInputDeviceDef,
|
||||
PyGetUIScaleDef,
|
||||
PySetUIScaleDef,
|
||||
PyGetThreadNameDef,
|
||||
PySetThreadNameDef,
|
||||
PyInLogicThreadDef,
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
#include "ballistica/base/ui/dev_console.h"
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/app_mode/app_mode.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
@ -11,12 +13,12 @@
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/context.h"
|
||||
#include "ballistica/base/support/repeater.h"
|
||||
#include "ballistica/base/ui/ui.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/generic/utils.h"
|
||||
#include "ballistica/shared/python/python_command.h"
|
||||
#include "ballistica/shared/python/python_sys.h"
|
||||
|
||||
namespace ballistica::base {
|
||||
|
||||
@ -29,11 +31,11 @@ const float kDevConsoleTabButtonCornerRadius{16.0f};
|
||||
const double kTransitionSeconds{0.15};
|
||||
|
||||
enum class DevConsoleHAnchor_ { kLeft, kCenter, kRight };
|
||||
enum class DevButtonStyle_ { kNormal, kDark };
|
||||
enum class DevButtonStyle_ { kNormal, kLight };
|
||||
|
||||
static auto DevButtonStyleFromStr_(const char* strval) {
|
||||
if (!strcmp(strval, "dark")) {
|
||||
return DevButtonStyle_::kDark;
|
||||
if (!strcmp(strval, "light")) {
|
||||
return DevButtonStyle_::kLight;
|
||||
}
|
||||
assert(!strcmp(strval, "normal"));
|
||||
return DevButtonStyle_::kNormal;
|
||||
@ -245,11 +247,11 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
|
||||
Vector3f fgcolor;
|
||||
Vector3f bgcolor;
|
||||
switch (style) {
|
||||
case DevButtonStyle_::kDark:
|
||||
case DevButtonStyle_::kLight:
|
||||
fgcolor =
|
||||
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.8f, 0.7f, 0.8f};
|
||||
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.9f, 0.8f, 0.9f};
|
||||
bgcolor =
|
||||
pressed ? Vector3f{0.6f, 0.5f, 0.6f} : Vector3f{0.16, 0.07f, 0.18f};
|
||||
pressed ? Vector3f{0.8f, 0.7f, 0.8f} : Vector3f{0.4, 0.33f, 0.5f};
|
||||
break;
|
||||
default:
|
||||
assert(style == DevButtonStyle_::kNormal);
|
||||
@ -454,6 +456,13 @@ DevConsole::DevConsole() {
|
||||
prompt_text_group_.SetText(">");
|
||||
}
|
||||
|
||||
void DevConsole::OnUIScaleChanged() {
|
||||
g_base->logic->event_loop()->PushCall([this] {
|
||||
RefreshTabButtons_();
|
||||
RefreshTabContents_();
|
||||
});
|
||||
}
|
||||
|
||||
void DevConsole::RefreshTabButtons_() {
|
||||
// IMPORTANT: This code should always be run in its own top level call and
|
||||
// never directly from user code. Otherwise we can wind up mucking with
|
||||
|
||||
@ -68,6 +68,8 @@ class DevConsole {
|
||||
auto BaseScale() const -> float;
|
||||
void RequestRefresh();
|
||||
|
||||
void OnUIScaleChanged();
|
||||
|
||||
private:
|
||||
class ScopedUILock_;
|
||||
class Widget_;
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/input/device/keyboard_input.h"
|
||||
#include "ballistica/base/input/device/keyboard_input.h" // IWYU pragma: keep
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
@ -54,11 +54,11 @@ UI::OperationContext::~OperationContext() {
|
||||
assert(runnables_.empty());
|
||||
}
|
||||
|
||||
// Complain if our Finish() call was never run (unless we're being torn
|
||||
// down due to an exception).
|
||||
if (!ran_finish_ && !std::current_exception()) {
|
||||
// Complain if our Finish() call was never run (unless it seems we're being
|
||||
// torn down as part of stack-unwinding due to an exception).
|
||||
if (!ran_finish_ && !std::uncaught_exceptions()) {
|
||||
BA_LOG_ERROR_NATIVE_TRACE_ONCE(
|
||||
"UI::InteractionContext_ being torn down without Complete called.");
|
||||
"UI::InteractionContext_ being torn down without Finish() called.");
|
||||
}
|
||||
|
||||
// Our runnables are raw unmanaged pointers; need to explicitly kill them.
|
||||
@ -140,6 +140,13 @@ UI::UI() {
|
||||
}
|
||||
}
|
||||
}
|
||||
void UI::SetScale(UIScale val) {
|
||||
BA_PRECONDITION(g_base->InLogicThread());
|
||||
scale_ = val;
|
||||
if (dev_console_ != nullptr) {
|
||||
dev_console_->OnUIScaleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void UI::StepDisplayTime() {
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
@ -4,11 +4,9 @@
|
||||
#define BALLISTICA_BASE_UI_UI_H_
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "ballistica/base/support/context.h"
|
||||
#include "ballistica/base/graphics/support/frame_def.h"
|
||||
#include "ballistica/base/ui/widget_message.h"
|
||||
#include "ballistica/shared/generic/timer_list.h"
|
||||
|
||||
// Predeclare a few things from ui_v1.
|
||||
namespace ballistica::ui_v1 {
|
||||
@ -114,9 +112,12 @@ class UI {
|
||||
/// These generally only get shown if a joystick of some form is present.
|
||||
auto ShouldShowButtonShortcuts() const -> bool;
|
||||
|
||||
/// Overall ui scale for the app.
|
||||
/// Get overall ui scale for the app.
|
||||
auto scale() const { return scale_; }
|
||||
|
||||
/// Set overall ui scale for the app.
|
||||
void SetScale(UIScale val);
|
||||
|
||||
/// Push a generic 'menu press' event, optionally associated with an input
|
||||
/// device (nullptr to specify none). Can be called from any thread.
|
||||
void PushMainMenuPressCall(InputDevice* device);
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/scene_v1/node/explosion_node.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/object_component.h"
|
||||
#include "ballistica/base/graphics/component/post_process_component.h"
|
||||
#include "ballistica/base/graphics/support/camera.h"
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/scene_v1/node/flash_node.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/object_component.h"
|
||||
#include "ballistica/scene_v1/node/node_attribute.h"
|
||||
#include "ballistica/scene_v1/node/node_type.h"
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/scene_v1/node/locator_node.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/scene_v1/node/node_attribute.h"
|
||||
#include "ballistica/scene_v1/node/node_type.h"
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/scene_v1/node/scorch_node.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/scene_v1/node/node_attribute.h"
|
||||
#include "ballistica/scene_v1/node/node_type.h"
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/scene_v1/node/shield_node.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/object_component.h"
|
||||
#include "ballistica/base/graphics/component/post_process_component.h"
|
||||
#include "ballistica/base/graphics/component/shield_component.h"
|
||||
|
||||
@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't modify them here.
|
||||
const int kEngineBuildNumber = 21986;
|
||||
const int kEngineBuildNumber = 22004;
|
||||
const char* kEngineVersion = "1.7.37";
|
||||
const int kEngineApiVersion = 9;
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
#define BALLISTICA_SHARED_FOUNDATION_MACROS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
|
||||
@ -142,9 +142,9 @@ typedef int64_t TimerMedium;
|
||||
/// content needs to be presented as large and clear in order to remain
|
||||
/// readable from an average distance.
|
||||
enum class UIScale : uint8_t {
|
||||
kLarge,
|
||||
kMedium,
|
||||
kSmall,
|
||||
kMedium,
|
||||
kLarge,
|
||||
kLast // Sentinel.
|
||||
};
|
||||
|
||||
|
||||
@ -7,12 +7,13 @@
|
||||
// This header pulls in the actual Python includes and also defines some handy
|
||||
// macros and functions for working with Python objects.
|
||||
|
||||
// This is the ONE place we actually include Python.
|
||||
// UPDATE (September 2024): We now include Python.h directly in some places;
|
||||
// this causes less friction with include-what-you-use checks.
|
||||
#include <Python.h>
|
||||
#include <frameobject.h>
|
||||
#include <weakrefobject.h>
|
||||
|
||||
#include <string>
|
||||
#include <string> // IWYU pragma: keep. (macros below use this)
|
||||
|
||||
// Saving/restoring Python error state; useful when function PyObject_Str()
|
||||
// or other functionality is needed during error reporting; by default it
|
||||
|
||||
@ -2,11 +2,9 @@
|
||||
|
||||
#include "ballistica/ui_v1/python/methods/python_methods_ui_v1.h"
|
||||
|
||||
#include "ballistica/base/app_adapter/app_adapter.h"
|
||||
#include "ballistica/base/app_mode/app_mode.h"
|
||||
#include "ballistica/base/assets/sound_asset.h"
|
||||
#include "ballistica/base/platform/base_platform.h"
|
||||
#include "ballistica/base/assets/sound_asset.h" // IWYU pragma: keep.
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/support/context.h"
|
||||
#include "ballistica/shared/foundation/macros.h"
|
||||
#include "ballistica/ui_v1/python/class/python_class_ui_mesh.h"
|
||||
#include "ballistica/ui_v1/python/class/python_class_ui_sound.h"
|
||||
@ -581,7 +579,7 @@ static auto PyCheckBoxWidget(PyObject* self, PyObject* args,
|
||||
widget = Object::New<CheckBoxWidget>();
|
||||
}
|
||||
|
||||
// set applicable values ----------------------------
|
||||
// Set applicable values.
|
||||
if (size_obj != Py_None) {
|
||||
Point2D p = Python::GetPyPoint2D(size_obj);
|
||||
widget->SetWidth(p.x);
|
||||
@ -1022,7 +1020,7 @@ static auto PyColumnWidget(PyObject* self, PyObject* args,
|
||||
widget->set_claims_tab(Python::GetPyBool(claims_tab_obj));
|
||||
}
|
||||
|
||||
// if making a new widget add it at the end
|
||||
// If making a new widget, add it at the end.
|
||||
if (edit_obj == Py_None) {
|
||||
g_ui_v1->AddWidget(widget.Get(), parent_widget);
|
||||
}
|
||||
@ -1357,6 +1355,7 @@ static auto PyContainerWidget(PyObject* self, PyObject* args,
|
||||
ui_op_context.Finish();
|
||||
|
||||
return widget->NewPyRef();
|
||||
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
@ -1628,7 +1627,7 @@ static auto PyScrollWidget(PyObject* self, PyObject* args,
|
||||
widget = Object::New<ScrollWidget>();
|
||||
}
|
||||
|
||||
// Set applicable values. ----------------------------
|
||||
// Set applicable values.
|
||||
if (size_obj != Py_None) {
|
||||
Point2D p = Python::GetPyPoint2D(size_obj);
|
||||
widget->SetWidth(p.x);
|
||||
@ -2587,35 +2586,6 @@ static PyMethodDef PyRootUIBackPressDef = {
|
||||
"(internal)",
|
||||
};
|
||||
|
||||
// ------------------------ is_party_icon_visible ------------------------------
|
||||
|
||||
static auto PyIsPartyIconVisible(PyObject* self) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
BA_PRECONDITION(g_base->InLogicThread());
|
||||
bool party_button_active = (g_base->app_mode()->HasConnectionToClients()
|
||||
|| g_base->app_mode()->HasConnectionToHost());
|
||||
// bool party_button_active = (g_base->app_mode()->HasConnectionToClients()
|
||||
// || g_base->app_mode()->HasConnectionToHost()
|
||||
// ||
|
||||
// g_ui_v1->root_ui()->always_draw_party_icon());
|
||||
if (party_button_active) {
|
||||
Py_RETURN_TRUE;
|
||||
} else {
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
static PyMethodDef PyIsPartyIconVisibleDef = {
|
||||
"is_party_icon_visible", // name
|
||||
(PyCFunction)PyIsPartyIconVisible, // method
|
||||
METH_NOARGS, // flags
|
||||
|
||||
"is_party_icon_visible() -> bool\n"
|
||||
"\n"
|
||||
"(internal)",
|
||||
};
|
||||
|
||||
// ----------------------------- is_available ----------------------------------
|
||||
|
||||
static auto PyIsAvailable(PyObject* self) -> PyObject* {
|
||||
@ -2641,30 +2611,38 @@ static PyMethodDef PyIsAvailableDef = {
|
||||
"(internal)",
|
||||
};
|
||||
|
||||
// --------------------------- on_screen_change --------------------------------
|
||||
|
||||
static auto PyOnScreenChange(PyObject* self) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
BA_PRECONDITION(g_base->InLogicThread());
|
||||
|
||||
g_ui_v1->OnScreenChange();
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
static PyMethodDef PyOnScreenChangeDef = {
|
||||
"on_screen_change", // name
|
||||
(PyCFunction)PyOnScreenChange, // method
|
||||
METH_NOARGS, // flags
|
||||
|
||||
"on_screen_change() -> None\n"
|
||||
"\n"
|
||||
"(internal)",
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
auto PythonMethodsUIV1::GetMethods() -> std::vector<PyMethodDef> {
|
||||
return {
|
||||
PyIsPartyIconVisibleDef,
|
||||
PyRootUIBackPressDef,
|
||||
PyGetSpecialWidgetDef,
|
||||
PySetPartyWindowOpenDef,
|
||||
PyButtonWidgetDef,
|
||||
PyCheckBoxWidgetDef,
|
||||
PyImageWidgetDef,
|
||||
PyColumnWidgetDef,
|
||||
PyContainerWidgetDef,
|
||||
PyRowWidgetDef,
|
||||
PyScrollWidgetDef,
|
||||
PyHScrollWidgetDef,
|
||||
PyTextWidgetDef,
|
||||
PyWidgetDef,
|
||||
PyUIBoundsDef,
|
||||
PyGetSoundDef,
|
||||
PyGetTextureDef,
|
||||
PyGetQRCodeTextureDef,
|
||||
PyGetMeshDef,
|
||||
PyIsAvailableDef,
|
||||
PyRootUIBackPressDef, PyGetSpecialWidgetDef, PySetPartyWindowOpenDef,
|
||||
PyButtonWidgetDef, PyCheckBoxWidgetDef, PyImageWidgetDef,
|
||||
PyColumnWidgetDef, PyContainerWidgetDef, PyRowWidgetDef,
|
||||
PyScrollWidgetDef, PyHScrollWidgetDef, PyTextWidgetDef,
|
||||
PyWidgetDef, PyUIBoundsDef, PyGetSoundDef,
|
||||
PyGetTextureDef, PyGetQRCodeTextureDef, PyGetMeshDef,
|
||||
PyIsAvailableDef, PyOnScreenChangeDef,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -3,14 +3,12 @@
|
||||
#include "ballistica/ui_v1/python/ui_v1_python.h"
|
||||
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/input/device/keyboard_input.h"
|
||||
#include "ballistica/base/input/device/keyboard_input.h" // IWYU pragma: keep.
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
#include "ballistica/base/python/base_python.h"
|
||||
#include "ballistica/base/python/support/python_context_call.h"
|
||||
#include "ballistica/base/ui/dev_console.h"
|
||||
#include "ballistica/shared/foundation/event_loop.h"
|
||||
#include "ballistica/shared/python/python_command.h"
|
||||
#include "ballistica/shared/python/python_command.h" // IWYU pragma: keep.
|
||||
#include "ballistica/shared/python/python_module_builder.h"
|
||||
#include "ballistica/ui_v1/python/class/python_class_ui_mesh.h"
|
||||
#include "ballistica/ui_v1/python/class/python_class_ui_sound.h"
|
||||
@ -22,9 +20,9 @@ namespace ballistica::ui_v1 {
|
||||
|
||||
UIV1Python::UIV1Python() = default;
|
||||
|
||||
// Declare a plain c PyInit_XXX function for our Python module;
|
||||
// this is how Python inits our binary module (and by extension, our
|
||||
// entire feature-set).
|
||||
// Declare a plain C PyInit_XXX function for our Python module; this is how
|
||||
// Python inits our binary module (and by extension, our entire
|
||||
// feature-set).
|
||||
extern "C" auto PyInit__bauiv1() -> PyObject* {
|
||||
auto* builder =
|
||||
new PythonModuleBuilder("_bauiv1",
|
||||
@ -48,8 +46,8 @@ void UIV1Python::AddPythonClasses(PyObject* module) {
|
||||
}
|
||||
|
||||
void UIV1Python::ImportPythonObjs() {
|
||||
// Import and grab all our objs_.
|
||||
// This code blob expects 'ObjID' and 'objs_' to be defined.
|
||||
// Import and grab all our objs_. This code blob expects 'ObjID' and
|
||||
// 'objs_' to be defined.
|
||||
#include "ballistica/ui_v1/mgen/pyembed/binding_ui_v1.inc"
|
||||
}
|
||||
|
||||
@ -113,8 +111,8 @@ void UIV1Python::InvokeStringEditor(PyObject* string_edit_adapter_instance) {
|
||||
auto context_call = Object::New<base::PythonContextCall>(
|
||||
objs().Get(ObjID::kOnScreenKeyboardClass));
|
||||
|
||||
// This is probably getting called from within UI handling, so we
|
||||
// need to schedule things to run post-ui-traversal in that case.
|
||||
// This is probably getting called from within UI handling, so we need to
|
||||
// schedule things to run post-ui-traversal in that case.
|
||||
if (g_base->ui->InUIOperation()) {
|
||||
context_call->ScheduleInUIOperation(args);
|
||||
} else {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include "ballistica/ui_v1/ui_v1.h"
|
||||
|
||||
#include "ballistica/base/app_mode/app_mode.h"
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/support/app_config.h"
|
||||
@ -214,12 +214,23 @@ void UIV1FeatureSet::AddWidget(Widget* w, ContainerWidget* parent) {
|
||||
}
|
||||
|
||||
void UIV1FeatureSet::OnScreenSizeChange() {
|
||||
// This gets called by the native layer as window is resized/etc.
|
||||
if (root_widget_.Exists()) {
|
||||
root_widget_->SetWidth(g_base->graphics->screen_virtual_width());
|
||||
root_widget_->SetHeight(g_base->graphics->screen_virtual_height());
|
||||
}
|
||||
}
|
||||
|
||||
void UIV1FeatureSet::OnScreenChange() {
|
||||
// This gets called by the Python layer when UIScale or window size
|
||||
// changes.
|
||||
assert(g_base->InLogicThread());
|
||||
|
||||
// We allow OnScreenSizeChange() to handle size changes but *do* handle
|
||||
// UIScale changes here.
|
||||
root_widget_->OnUIScaleChange();
|
||||
}
|
||||
|
||||
void UIV1FeatureSet::OnLanguageChange() {
|
||||
// Since switching languages is a bit costly, ignore redundant change
|
||||
// notifications. These will tend to happen nowadays since change
|
||||
|
||||
@ -85,18 +85,10 @@ class UIV1FeatureSet : public FeatureSetNativeComponent,
|
||||
auto MainMenuVisible() -> bool override;
|
||||
auto PartyIconVisible() -> bool override;
|
||||
void ActivatePartyIcon() override;
|
||||
// void HandleLegacyRootUIMouseMotion(float x, float y) override;
|
||||
// auto HandleLegacyRootUIMouseDown(float x, float y) -> bool override;
|
||||
// void HandleLegacyRootUIMouseUp(float x, float y) override;
|
||||
void Draw(base::FrameDef* frame_def) override;
|
||||
|
||||
UIV1Python* const python;
|
||||
|
||||
// auto root_ui() const -> ui_v1::RootUI* {
|
||||
// assert(root_ui_);
|
||||
// return root_ui_;
|
||||
// }
|
||||
// void OnAppStart() override;
|
||||
void OnActivate() override;
|
||||
void OnDeactivate() override;
|
||||
|
||||
@ -123,6 +115,8 @@ class UIV1FeatureSet : public FeatureSetNativeComponent,
|
||||
void DeleteWidget(Widget* widget);
|
||||
|
||||
void OnScreenSizeChange() override;
|
||||
void OnScreenChange();
|
||||
|
||||
void OnLanguageChange() override;
|
||||
auto GetRootWidget() -> ui_v1::Widget* override;
|
||||
auto SendWidgetMessage(const base::WidgetMessage& m) -> int override;
|
||||
@ -140,7 +134,6 @@ class UIV1FeatureSet : public FeatureSetNativeComponent,
|
||||
|
||||
private:
|
||||
UIV1FeatureSet();
|
||||
// RootUI* root_ui_{};
|
||||
Object::Ref<ContainerWidget> screen_root_widget_;
|
||||
Object::Ref<ContainerWidget> overlay_root_widget_;
|
||||
Object::Ref<RootWidget> root_widget_;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/ui_v1/widget/button_widget.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
@ -103,15 +104,11 @@ auto ButtonWidget::GetMult(millisecs_t current_time) const -> float {
|
||||
mult *= 2.0f;
|
||||
}
|
||||
} else {
|
||||
if (!texture_.Exists()) {
|
||||
} else {
|
||||
// In desktop mode we want image buttons to light up when we
|
||||
// mouse over them.
|
||||
if (!g_core->platform->IsRunningOnDesktop()) {
|
||||
if (mouse_over_) {
|
||||
mult = 1.4f;
|
||||
}
|
||||
}
|
||||
// Slightly highlighting all buttons for mouse-over. Once we can
|
||||
// differentiate between touch events and pointer events we should limit
|
||||
// this to pointer events.
|
||||
if (mouse_over_) {
|
||||
mult = 1.2f;
|
||||
}
|
||||
}
|
||||
return mult;
|
||||
@ -459,17 +456,22 @@ void ButtonWidget::Draw(base::RenderPass* pass, bool draw_transparent) {
|
||||
auto ButtonWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
|
||||
// How far outside button touches register.
|
||||
float left_overlap, top_overlap, right_overlap, bottom_overlap;
|
||||
if (g_core->platform->IsRunningOnDesktop()) {
|
||||
left_overlap = 3.0f;
|
||||
top_overlap = 1.0f;
|
||||
right_overlap = 0.0f;
|
||||
bottom_overlap = 0.0f;
|
||||
} else {
|
||||
left_overlap = 3.0f + 9.0f * extra_touch_border_scale_;
|
||||
top_overlap = 1.0f + 5.0f * extra_touch_border_scale_;
|
||||
right_overlap = 7.0f * extra_touch_border_scale_;
|
||||
bottom_overlap = 7.0f * extra_touch_border_scale_;
|
||||
}
|
||||
// if (g_core->platform->IsRunningOnDesktop()) {
|
||||
|
||||
// UPDATE - removing touch-specific boundary adjustments. If it is
|
||||
// necessary to reenable these, should do it on a per-event basis so need
|
||||
// to differentiate between touches and clicks. It is probably sufficient
|
||||
// to simply expose manual boundary tweaks that apply everywhere though.
|
||||
left_overlap = 3.0f;
|
||||
top_overlap = 1.0f;
|
||||
right_overlap = 0.0f;
|
||||
bottom_overlap = 0.0f;
|
||||
// } else {
|
||||
// left_overlap = 3.0f + 9.0f * extra_touch_border_scale_;
|
||||
// top_overlap = 1.0f + 5.0f * extra_touch_border_scale_;
|
||||
// right_overlap = 7.0f * extra_touch_border_scale_;
|
||||
// bottom_overlap = 7.0f * extra_touch_border_scale_;
|
||||
// }
|
||||
|
||||
// Extra overlap that always applies.
|
||||
right_overlap += target_extra_right_;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/ui_v1/widget/container_widget.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
@ -349,8 +350,6 @@ auto ContainerWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
|
||||
// Schedule this to run immediately after any current UI
|
||||
// traversal.
|
||||
call->ScheduleInUIOperation();
|
||||
} else {
|
||||
OnCancelCustom();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1407,7 +1406,7 @@ void ContainerWidget::SelectWidget(Widget* w, SelectionCause c) {
|
||||
}
|
||||
for (auto& widget : widgets_) {
|
||||
if (&(*widget) == w) {
|
||||
Widget* prevSelectedWidget = selected_widget_;
|
||||
Widget* prev_selected_widget = selected_widget_;
|
||||
|
||||
// Deactivate old selected widget.
|
||||
if (selected_widget_) {
|
||||
@ -1421,8 +1420,8 @@ void ContainerWidget::SelectWidget(Widget* w, SelectionCause c) {
|
||||
// Store the old one as prev-selected if its not the one we're
|
||||
// selecting now. (otherwise re-selecting repeatedly kills our prev
|
||||
// mechanism).
|
||||
if (prevSelectedWidget != selected_widget_) {
|
||||
prev_selected_widget_ = prevSelectedWidget;
|
||||
if (prev_selected_widget != selected_widget_) {
|
||||
prev_selected_widget_ = prev_selected_widget;
|
||||
}
|
||||
} else {
|
||||
static bool printed = false;
|
||||
|
||||
@ -36,8 +36,8 @@ class ContainerWidget : public Widget {
|
||||
void SetStartButton(ButtonWidget* button);
|
||||
void SetOnCancelCall(PyObject* call_tuple);
|
||||
|
||||
// Set a widget to selected (must already have been added to dialog)
|
||||
// Pass nullptr to deselect widgets.
|
||||
// Set a widget to selected (must already have been added to dialog). Pass
|
||||
// nullptr to deselect widgets.
|
||||
void SelectWidget(Widget* w, SelectionCause s = SelectionCause::NONE);
|
||||
void ReselectLastSelectedWidget();
|
||||
void ShowWidget(Widget* w);
|
||||
@ -118,12 +118,6 @@ class ContainerWidget : public Widget {
|
||||
// (generally true but list containers may not want)
|
||||
auto selection_loops() const -> bool { return selection_loops_; }
|
||||
|
||||
// If the selection doesn't loop, returns whether a selection loop transfers
|
||||
// the message to the parent instead.
|
||||
auto selection_loops_to_parent() const -> bool {
|
||||
return selection_loops_to_parent_;
|
||||
}
|
||||
|
||||
void SetOnActivateCall(PyObject* c);
|
||||
void SetOnOutsideClickCall(PyObject* c);
|
||||
|
||||
@ -132,13 +126,23 @@ class ContainerWidget : public Widget {
|
||||
}
|
||||
|
||||
void set_draggable(bool d) { draggable_ = d; }
|
||||
void set_claims_tab(bool c) { claims_tab_ = c; }
|
||||
void set_claims_left_right(bool c) { claims_left_right_ = c; }
|
||||
void set_claims_up_down(bool c) { claims_up_down_ = c; }
|
||||
void set_selection_loops_to_parent(bool d) { selection_loops_to_parent_ = d; }
|
||||
|
||||
auto claims_tab() const -> bool { return claims_tab_; }
|
||||
void set_claims_tab(bool c) { claims_tab_ = c; }
|
||||
|
||||
auto claims_left_right() const -> bool { return claims_left_right_; }
|
||||
void set_claims_left_right(bool c) { claims_left_right_ = c; }
|
||||
|
||||
auto claims_up_down() const -> bool { return claims_up_down_; }
|
||||
void set_claims_up_down(bool c) { claims_up_down_ = c; }
|
||||
|
||||
// If the selection doesn't loop, returns whether a selection loop
|
||||
// transfers the message to the parent instead.
|
||||
auto selection_loops_to_parent() const -> bool {
|
||||
return selection_loops_to_parent_;
|
||||
}
|
||||
void set_selection_loops_to_parent(bool d) { selection_loops_to_parent_ = d; }
|
||||
|
||||
void set_single_depth(bool s) { single_depth_ = s; }
|
||||
|
||||
// Translate a point in-place into the space of a given child widget.
|
||||
@ -151,33 +155,33 @@ class ContainerWidget : public Widget {
|
||||
blue_ = b;
|
||||
alpha_ = a;
|
||||
}
|
||||
void set_should_print_list_exit_instructions(bool v) {
|
||||
should_print_list_exit_instructions_ = v;
|
||||
}
|
||||
auto GetDrawBrightness(millisecs_t time) const -> float override;
|
||||
auto IsAcceptingInput() const -> bool override;
|
||||
void OnLanguageChange() override;
|
||||
|
||||
void set_selection_loops(bool loops) { selection_loops_ = loops; }
|
||||
void set_click_activate(bool enabled) { click_activate_ = enabled; }
|
||||
void set_always_highlight(bool enable) { always_highlight_ = enable; }
|
||||
auto GetDrawBrightness(millisecs_t time) const -> float override;
|
||||
auto IsAcceptingInput() const -> bool override;
|
||||
void set_claims_outside_clicks(bool val) { claims_outside_clicks_ = val; }
|
||||
void OnLanguageChange() override;
|
||||
|
||||
void set_is_overlay_window_stack(bool val) { is_overlay_window_stack_ = val; }
|
||||
void set_is_main_window_stack(bool val) { is_main_window_stack_ = val; }
|
||||
void set_should_print_list_exit_instructions(bool v) {
|
||||
should_print_list_exit_instructions_ = v;
|
||||
}
|
||||
|
||||
// Return the topmost widget that is accepting input.
|
||||
// (used for toolbar focusing; may not always equal selected widget
|
||||
// if the topmost one is transitioning out, etc.)
|
||||
// Return the topmost widget that is accepting input. Used for toolbar
|
||||
// focusing; may not always equal selected widget if the topmost one is
|
||||
// transitioning out, etc.
|
||||
auto GetTopmostToolbarInfluencingWidget() -> Widget*;
|
||||
|
||||
auto IsTransitioningOut() const -> bool override;
|
||||
|
||||
protected:
|
||||
virtual void OnCancelCustom() {}
|
||||
void set_single_depth_root(bool s) { single_depth_root_ = s; }
|
||||
|
||||
// Note that the offsets here are purely for visual transitions and things;
|
||||
// the UI itself only knows about the standard widget transform values.
|
||||
// Note that the offsets here are purely for visual transitions and
|
||||
// things; the UI itself only knows about the standard widget transform
|
||||
// values.
|
||||
void DrawChildren(base::RenderPass* pass, bool transparent, float x_offset,
|
||||
float y_offset, float scale);
|
||||
void SetSelected(bool s, SelectionCause cause) override;
|
||||
@ -195,41 +199,36 @@ class ContainerWidget : public Widget {
|
||||
void set_height(float val) { height_ = val; }
|
||||
|
||||
private:
|
||||
// Given a container and a point, returns a selectable widget in the downward
|
||||
// direction or nullptr.
|
||||
// Given a container and a point, returns a selectable widget in the
|
||||
// downward direction or nullptr.
|
||||
auto GetClosestDownWidget(float x, float y, Widget* ignoreWidget) -> Widget*;
|
||||
auto GetClosestUpWidget(float x, float y, Widget* ignoreWidget) -> Widget*;
|
||||
auto GetClosestRightWidget(float x, float y, Widget* ignoreWidget) -> Widget*;
|
||||
auto GetClosestLeftWidget(float x, float y, Widget* ignoreWidget) -> Widget*;
|
||||
auto GetMult(millisecs_t current_time, bool for_glow = false) const -> float;
|
||||
void PrintExitListInstructions(millisecs_t old_last_prev_next_time);
|
||||
|
||||
std::vector<Object::Ref<Widget> > widgets_;
|
||||
Object::Ref<base::TextureAsset> tex_;
|
||||
Object::WeakRef<ButtonWidget> cancel_button_;
|
||||
Object::WeakRef<ButtonWidget> start_button_;
|
||||
Widget* selected_widget_{};
|
||||
Widget* prev_selected_widget_{};
|
||||
base::SysMeshID bg_mesh_transparent_i_d_{};
|
||||
base::SysMeshID bg_mesh_opaque_i_d_{};
|
||||
TransitionType transition_type_{};
|
||||
float width_{};
|
||||
float height_{};
|
||||
bool modal_children_{};
|
||||
bool selection_loops_{true};
|
||||
bool is_main_window_stack_{};
|
||||
bool is_overlay_window_stack_{};
|
||||
float scale_origin_stack_offset_x_{};
|
||||
float scale_origin_stack_offset_y_{};
|
||||
float transition_scale_offset_x_{};
|
||||
float transition_scale_offset_y_{};
|
||||
bool pressed_{};
|
||||
bool mouse_over_{};
|
||||
bool pressed_activate_{};
|
||||
bool always_highlight_{};
|
||||
bool click_activate_{};
|
||||
float red_{0.4f};
|
||||
float green_{0.37f};
|
||||
float blue_{0.49f};
|
||||
float alpha_{1.0f};
|
||||
Object::Ref<base::TextureAsset> tex_;
|
||||
base::SysMeshID bg_mesh_transparent_i_d_{};
|
||||
base::SysMeshID bg_mesh_opaque_i_d_{};
|
||||
float glow_width_{}, glow_height_{}, glow_center_x_{}, glow_center_y_{};
|
||||
float bg_width_{}, bg_height_{}, bg_center_x_{}, bg_center_y_{};
|
||||
millisecs_t last_activate_time_millisecs_{};
|
||||
millisecs_t transition_start_time_{};
|
||||
float transition_target_offset_{};
|
||||
float drag_x_{}, drag_y_{};
|
||||
float transition_offset_x_{};
|
||||
@ -241,11 +240,23 @@ class ContainerWidget : public Widget {
|
||||
float transition_start_offset_{};
|
||||
float transition_scale_{1.0f};
|
||||
float d_transition_scale_{};
|
||||
millisecs_t last_activate_time_millisecs_{};
|
||||
millisecs_t transition_start_time_{};
|
||||
millisecs_t dynamics_update_time_millisecs_{};
|
||||
millisecs_t last_prev_next_time_millisecs_{};
|
||||
millisecs_t last_list_exit_instructions_print_time_{};
|
||||
bool modal_children_{};
|
||||
bool selection_loops_{true};
|
||||
bool is_main_window_stack_{};
|
||||
bool is_overlay_window_stack_{};
|
||||
bool bg_dirty_{true};
|
||||
bool glow_dirty_{true};
|
||||
bool transitioning_{};
|
||||
TransitionType transition_type_{};
|
||||
bool pressed_{};
|
||||
bool mouse_over_{};
|
||||
bool pressed_activate_{};
|
||||
bool always_highlight_{};
|
||||
bool click_activate_{};
|
||||
bool transitioning_out_{};
|
||||
bool draggable_{};
|
||||
bool dragging_{};
|
||||
@ -263,16 +274,10 @@ class ContainerWidget : public Widget {
|
||||
bool single_depth_{true};
|
||||
bool single_depth_root_{};
|
||||
bool should_print_list_exit_instructions_{};
|
||||
millisecs_t last_prev_next_time_millisecs_{};
|
||||
millisecs_t last_list_exit_instructions_print_time_{};
|
||||
Widget* selected_widget_{};
|
||||
Widget* prev_selected_widget_{};
|
||||
Object::WeakRef<ButtonWidget> cancel_button_;
|
||||
Object::WeakRef<ButtonWidget> start_button_;
|
||||
bool claims_outside_clicks_{};
|
||||
|
||||
// Keep these at the bottom so they're torn down first.
|
||||
// ...hmm that seems fragile; should I add explicit code to kill them?
|
||||
// Keep these at the bottom so they're torn down first. ...hmm that seems
|
||||
// fragile; should I add explicit code to kill them?
|
||||
Object::Ref<base::PythonContextCall> on_activate_call_;
|
||||
Object::Ref<base::PythonContextCall> on_outside_click_call_;
|
||||
Object::Ref<base::PythonContextCall> on_cancel_call_;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/ui_v1/widget/h_scroll_widget.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/support/app_timer.h"
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
|
||||
#include "ballistica/ui_v1/widget/image_widget.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/mesh/mesh_indexed_simple_full.h"
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
|
||||
namespace ballistica::ui_v1 {
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/renderer/render_pass.h"
|
||||
#include "ballistica/base/graphics/support/frame_def.h"
|
||||
#include "ballistica/base/support/context.h"
|
||||
#include "ballistica/shared/foundation/inline.h"
|
||||
#include "ballistica/ui_v1/python/ui_v1_python.h"
|
||||
#include "ballistica/ui_v1/widget/button_widget.h"
|
||||
@ -1574,6 +1575,8 @@ void RootWidget::UpdateLayout() {
|
||||
StepPositions_(0.0f);
|
||||
}
|
||||
|
||||
void RootWidget::OnUIScaleChange() { MarkForUpdate(); }
|
||||
|
||||
auto RootWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
|
||||
// If a cancel message comes through and our back button is enabled, fire
|
||||
// our back button. In all other cases just do the default.
|
||||
@ -1607,20 +1610,6 @@ void RootWidget::SetOverlayWidget(StackWidget* w) {
|
||||
overlay_stack_widget_ = w;
|
||||
}
|
||||
|
||||
void RootWidget::OnCancelCustom() {
|
||||
// Need to revisit this. If the cancel event it pushes is not handled, it will
|
||||
// wind up back here where it pushes another back call. This cycle repeats
|
||||
// forever until something comes along which does handle cancel events and
|
||||
// then it gets them all. Current repro case is Sign-in-with-BombSquad-Account
|
||||
// window - press escape a few times while that is up and then click cancel;
|
||||
// This code is only used for toolbar mode so should be safe to leave it
|
||||
// disabled for now.
|
||||
|
||||
// Is there a reason for this to exist? If so, what is it?
|
||||
// printf("GOT OnCancelCustom\n");
|
||||
// g_base->ui->PushBackButtonCall(nullptr);
|
||||
}
|
||||
|
||||
auto RootWidget::GetSpecialWidget(const std::string& s) const -> Widget* {
|
||||
if (s == "squad_button") {
|
||||
return squad_button_ ? squad_button_->widget.Get() : nullptr;
|
||||
|
||||
@ -30,7 +30,9 @@ class RootWidget : public ContainerWidget {
|
||||
return overlay_stack_widget_;
|
||||
}
|
||||
|
||||
void OnCancelCustom() override;
|
||||
/// Called when UIScale or screen dimensions change.
|
||||
void OnUIScaleChange();
|
||||
|
||||
void UpdateLayout() override;
|
||||
|
||||
private:
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ballistica/ui_v1/widget/scroll_widget.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/support/app_timer.h"
|
||||
|
||||
@ -2,11 +2,13 @@
|
||||
|
||||
#include "ballistica/ui_v1/widget/text_widget.h"
|
||||
|
||||
#include "ballistica/base/assets/assets.h"
|
||||
#include "ballistica/base/audio/audio.h"
|
||||
#include "ballistica/base/graphics/component/empty_component.h"
|
||||
#include "ballistica/base/graphics/component/simple_component.h"
|
||||
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
|
||||
#include "ballistica/base/graphics/text/text_graphics.h"
|
||||
#include "ballistica/base/graphics/text/text_group.h"
|
||||
#include "ballistica/base/input/device/keyboard_input.h"
|
||||
#include "ballistica/base/input/input.h"
|
||||
#include "ballistica/base/logic/logic.h"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user