wired up dynamic uiscale changes via dev-console

This commit is contained in:
Eric 2024-09-05 13:47:58 -07:00
parent 1af06d18e6
commit 7122180847
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
66 changed files with 569 additions and 350 deletions

58
.efrocachemap generated
View File

@ -4096,26 +4096,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "e5178f2851b3af9a4e38e3a7d267a240", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "8e1c1a6865e87aa0c5a02e65ac3bb8ec",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "912611f71c3b7d50a7e125ecede0c719", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "25f7b1b98a98bb2a3e7b5e12362808cb",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "d37e2e367d558d8dc2acb0c65297e439", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a8573cbcbe45d27f715c25d4394a23fd",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "9d17cdce4ead349207e33ef2e1797210", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "98b5f12ea27a9af8827b768143e7edb5",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "7e77b7064e3d727c6774dc7b6e4d0484", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "1ced073c261bb7f4cac0a54b6472b508",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "c3c2386a4a8a033eaa1bd2bb30620467", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4621ac4aa53d2babf5c67ee13f417e79",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "ec5ef8638ab507847fe3cc70598f6467", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "587ac9f0678caf5d0b7479bffe50db08",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "6fef8a6f718c2ac6b322affc4fbe5dd2", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "d20e0fa4d8fd8304b91fd8c3270bf499",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d7aceacd58ddb44e8381291ba229d976", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "1b3aee01e605c52a6ddafdc77b701e0e",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "645725e7904049c6d5473e508e5b0a89", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "ed2d598a1de3249179b752b1bf3c75a8",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "69ec81fbfd03210abf87ae39b45282bf", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "99e743acc7b9d8d5d849395e0ee726eb",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "571cce7f35bceb1a2c53ca67e6d2ba66", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "d774b4a8a18083262846d41f2db544ea",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "fbfb6bbbde2ff59ac9279ac2162b2733", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "cf4c11956d06b23583cfad2e946b1502",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "bb2c684f084e2bf3eb87392718b00493", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "38a6b5eaa4ef30f400f72b71f69cdd6e",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5c8cc694aaca54b7d28823a7bbb99f5a", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "982a33f7b34f0a2a95a4fe072c7ad561",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "974e88892bd2ed2ac9a8c9d7cb63e38e", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "dd0468ae96203b6af6529612a18e262a",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "d19acafe6c0b7bf869976ec6b4d47250", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "d9f152f41b712aa9969fad60d54a5dbd",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "98152c4194eaf779c2cda75e5fbd8deb", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d569374c7e05a01fdd1bfb2b8f622b71",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "2bcd3acef687c45602a56b30d2b9541b", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "703229ffb3bd1e0dd025225bad85d90c",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "f7a1726e53ea787e70c57212018487b6", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "3dcf01a911a98b1d01bbd8614e8bef8f",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", "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_gui/release/libballisticaplus.a": "fa659b5d6119acba6570c92ce4d35ae2",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "73ad3303fe1a82005918fbc5dae3446c", "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_gui/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1659535e95e3047fda529543e265ac97", "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/mac_x86_64_server/release/libballisticaplus.a": "3e5c5fd0a09f55ba7b05ce1e2ec7171e",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "70d97e9b1ee3aab626edaaa250ecb161", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "ad1d2ca70c9784c46fd9a079b6bfeacd",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "2cde0bcaa51f05ca76bea9f8fba23de0", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "d239aa7f1abe82ab3920147375b5e714",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "bf044c328cb751d29a96f6f75a9a8034", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "7583533059df43d719c9b0446f282fa3",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "26d6dc203dc2a055b393c1962a2c90e3", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "dac29b15a3eb1294079ea002d93ec3b1",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "957b55aaa06ccea86893d802eda3432d", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "e19618713c795246c4aa64c455235d15",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "7b0dc8b1d2393700ca44a82ba00dad0c", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "7260b697de1753e10a7e8677c787fd16",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "100976691f6e41d024e108f5a14d55c1", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "b18e673dde3c97d97e74b45467fb23b0",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "679aceecd0f8d165553a6ce4f411957f", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "60abcbb58579c047ba673519a5029857",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "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.inc": "efa61468cf098f77cc6a234461d8b86d",
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "97efb93f4bfd8e8b09f2db24398e29fc", "src/ballistica/base/mgen/pyembed/binding_base_app.inc": "97efb93f4bfd8e8b09f2db24398e29fc",
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3", "src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",

View File

@ -1,4 +1,4 @@
### 1.7.37 (build 21988, api 9, 2024-09-04) ### 1.7.37 (build 21995, api 9, 2024-09-05)
- Bumping api version to 9. As you'll see below, there's some UI changes that - 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 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. touch UI stuff at all you can simply bump your api version and call it a day.
@ -82,6 +82,14 @@
- Removed `efro.util.enum_by_value()` which was a workaround for a Python bug - 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 that has been fixed for a few versions now. Instaed of
`enum_by_value(MyEnumType, foo)` you can simply do `MyEnumType(foo)`. `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) ### 1.7.36 (build 21944, api 8, 2024-07-26)
- Wired up Tokens, BombSquad's new purchasable currency. The first thing these - Wired up Tokens, BombSquad's new purchasable currency. The first thing these

View File

@ -17,6 +17,6 @@ Sphinx==8.0.2
tomlkit==0.13.2 tomlkit==0.13.2
types-certifi==2021.10.8.3 types-certifi==2021.10.8.3
types-filelock==3.2.7 types-filelock==3.2.7
types-requests==2.32.0.20240712 types-requests==2.32.0.20240905
typing_extensions==4.12.2 typing_extensions==4.12.2
urllib3==2.2.2 urllib3==2.2.2

View File

@ -56,6 +56,7 @@ from _babase import (
get_replays_dir, get_replays_dir,
get_string_height, get_string_height,
get_string_width, get_string_width,
get_ui_scale,
get_v1_cloud_log_file_path, get_v1_cloud_log_file_path,
getsimplesound, getsimplesound,
has_user_run_commands, has_user_run_commands,
@ -99,6 +100,7 @@ from _babase import (
set_low_level_config_value, set_low_level_config_value,
set_thread_name, set_thread_name,
set_ui_input_device, set_ui_input_device,
set_ui_scale,
show_progress_bar, show_progress_bar,
shutdown_suppress_begin, shutdown_suppress_begin,
shutdown_suppress_end, shutdown_suppress_end,
@ -254,8 +256,9 @@ __all__ = [
'get_replays_dir', 'get_replays_dir',
'get_string_height', 'get_string_height',
'get_string_width', 'get_string_width',
'get_v1_cloud_log_file_path',
'get_type_name', 'get_type_name',
'get_ui_scale',
'get_v1_cloud_log_file_path',
'getclass', 'getclass',
'getsimplesound', 'getsimplesound',
'handle_leftover_v1_cloud_log_file', 'handle_leftover_v1_cloud_log_file',
@ -325,6 +328,7 @@ __all__ = [
'set_low_level_config_value', 'set_low_level_config_value',
'set_thread_name', 'set_thread_name',
'set_ui_input_device', 'set_ui_input_device',
'set_ui_scale',
'show_progress_bar', 'show_progress_bar',
'shutdown_suppress_begin', 'shutdown_suppress_begin',
'shutdown_suppress_end', 'shutdown_suppress_end',

View File

@ -629,6 +629,35 @@ class App:
self._initial_sign_in_completed = True self._initial_sign_in_completed = True
self._update_state() 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
)
# Note to the user that this is currently an imperfect system.
_babase.screenmessage(
f'UI Scale is now {scale.name}.\n'
f' NOTE: some UI elements may not respond to this currently.'
)
def _set_intent(self, intent: AppIntent) -> None: def _set_intent(self, intent: AppIntent) -> None:
from babase._appmode import AppMode from babase._appmode import AppMode
@ -718,7 +747,7 @@ class App:
subsystem.reset() subsystem.reset()
except Exception: except Exception:
logging.exception( logging.exception(
'Error in reset for subsystem %s.', subsystem 'Error in reset() for subsystem %s.', subsystem
) )
self._mode = mode self._mode = mode
@ -805,7 +834,7 @@ class App:
subsystem.on_app_loading() subsystem.on_app_loading()
except Exception: except Exception:
logging.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 # Normally plus tells us when initial sign-in is done. If plus
@ -854,7 +883,7 @@ class App:
subsystem.on_app_running() subsystem.on_app_running()
except Exception: except Exception:
logging.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. # Cut off new subsystem additions at this point.
@ -890,7 +919,8 @@ class App:
subsystem.do_apply_app_config() subsystem.do_apply_app_config()
except Exception: except Exception:
logging.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. # Let the native layer do its thing.
@ -1013,7 +1043,7 @@ class App:
subsystem.on_app_suspend() subsystem.on_app_suspend()
except Exception: except Exception:
logging.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: def _on_unsuspend(self) -> None:
@ -1027,7 +1057,7 @@ class App:
subsystem.on_app_unsuspend() subsystem.on_app_unsuspend()
except Exception: except Exception:
logging.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: def _on_shutting_down(self) -> None:
@ -1041,7 +1071,7 @@ class App:
subsystem.on_app_shutdown() subsystem.on_app_shutdown()
except Exception: except Exception:
logging.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). # Now kick off any async shutdown task(s).
@ -1059,7 +1089,7 @@ class App:
subsystem.on_app_shutdown_complete() subsystem.on_app_shutdown_complete()
except Exception: except Exception:
logging.exception( logging.exception(
'Error in on_app_shutdown_complete for subsystem %s.', 'Error in on_app_shutdown_complete() for subsystem %s.',
subsystem, subsystem,
) )

View File

@ -8,7 +8,7 @@ from typing import TYPE_CHECKING
import _babase import _babase
if TYPE_CHECKING: if TYPE_CHECKING:
pass from babase import UIScale
class AppSubsystem: class AppSubsystem:
@ -54,6 +54,9 @@ class AppSubsystem:
def do_apply_app_config(self) -> None: def do_apply_app_config(self) -> None:
"""Called when the app config should be applied.""" """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: def reset(self) -> None:
"""Reset the subsystem to a default state. """Reset the subsystem to a default state.

View File

@ -4,16 +4,17 @@
from __future__ import annotations from __future__ import annotations
import os import os
from typing import TYPE_CHECKING, override
from dataclasses import dataclass
import logging import logging
from functools import partial
from dataclasses import dataclass
from typing import TYPE_CHECKING, override
import _babase import _babase
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Callable, Any, Literal from typing import Callable, Any, Literal
from babase import AppMode from babase import AppMode, UIScale
class DevConsoleTab: class DevConsoleTab:
@ -108,7 +109,6 @@ class DevConsoleTabAppModes(DevConsoleTab):
@override @override
def refresh(self) -> None: def refresh(self) -> None:
from functools import partial
modes = _babase.app.mode_selector.testable_app_modes() modes = _babase.app.mode_selector.testable_app_modes()
self.text( self.text(
@ -150,6 +150,7 @@ class DevConsoleTabUI(DevConsoleTab):
@override @override
def refresh(self) -> None: def refresh(self) -> None:
from babase._mgen.enums import UIScale
self.text( self.text(
'UI Testing: Make sure all static UI fits in the' 'UI Testing: Make sure all static UI fits in the'
@ -182,14 +183,14 @@ class DevConsoleTabUI(DevConsoleTab):
) )
bwidth = 100 bwidth = 100
for sz in ('small', 'medium', 'large'): for scale in UIScale:
self.button( self.button(
sz, scale.name,
pos=(x, 10), pos=(x, 10),
size=(bwidth, 30), size=(bwidth, 30),
h_anchor='left', h_anchor='left',
label_scale=0.6, label_scale=0.6,
call=lambda: _babase.screenmessage('UNDER CONSTRUCTION.'), call=partial(_babase.app.set_ui_scale, scale),
) )
x += bwidth + 10 x += bwidth + 10

View File

@ -49,6 +49,8 @@ class ClassicAppMode(AppMode):
@override @override
def on_activate(self) -> None: def on_activate(self) -> None:
print('CLASSIC ACTIVATING')
# Let the native layer do its thing. # Let the native layer do its thing.
_baclassic.classic_app_mode_activate() _baclassic.classic_app_mode_activate()
@ -108,6 +110,7 @@ class ClassicAppMode(AppMode):
@override @override
def on_deactivate(self) -> None: def on_deactivate(self) -> None:
print('CLASSIC DEACTIVATING')
# Let the native layer do its thing. # Let the native layer do its thing.
_baclassic.classic_app_mode_deactivate() _baclassic.classic_app_mode_deactivate()

View File

@ -819,6 +819,8 @@ class ClassicAppSubsystem(babase.AppSubsystem):
def invoke_main_menu_ui(self) -> None: def invoke_main_menu_ui(self) -> None:
"""Bring up main menu ui.""" """Bring up main menu ui."""
print('INVOKING MAIN MENU UI')
# Bring up the last place we were, or start at the main menu otherwise. # Bring up the last place we were, or start at the main menu otherwise.
app = bauiv1.app app = bauiv1.app
env = app.env env = app.env

View File

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

View File

@ -536,7 +536,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]):
) )
def _update_corner_button_positions(self) -> None: def _update_corner_button_positions(self) -> None:
offs = -55 if bui.is_party_icon_visible() else 0 offs = -55
assert self._corner_button_offs is not None assert self._corner_button_offs is not None
pos_x = self._corner_button_offs[0] + offs pos_x = self._corner_button_offs[0] + offs
pos_y = self._corner_button_offs[1] pos_y = self._corner_button_offs[1]

View File

@ -111,7 +111,6 @@ from _bauiv1 import (
gettexture, gettexture,
hscrollwidget, hscrollwidget,
imagewidget, imagewidget,
is_party_icon_visible,
Mesh, Mesh,
rowwidget, rowwidget,
scrollwidget, scrollwidget,
@ -192,7 +191,6 @@ __all__ = [
'in_main_menu', 'in_main_menu',
'increment_analytics_count', 'increment_analytics_count',
'is_browser_likely_available', 'is_browser_likely_available',
'is_party_icon_visible',
'is_xcode_build', 'is_xcode_build',
'Keyboard', 'Keyboard',
'lock_all_input', 'lock_all_input',

View File

@ -61,7 +61,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
from bauiv1._uitypes import MainWindow from bauiv1._uitypes import MainWindow
super().__init__() super().__init__()
env = babase.env()
# We hold only a weak ref to the current main Window; we want it # 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 # 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 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 # For storing arbitrary class-level state data for Windows or
# other UI related classes. # other UI related classes.
self.window_states: dict[type, Any] = {} 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._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': if uiscalestr == 'large':
self._uiscale = babase.UIScale.LARGE self._uiscale = babase.UIScale.LARGE
elif uiscalestr == 'medium': elif uiscalestr == 'medium':
@ -94,18 +103,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
logging.error("Invalid UIScale '%s'.", uiscalestr) logging.error("Invalid UIScale '%s'.", uiscalestr)
self._uiscale = babase.UIScale.MEDIUM 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 @property
def available(self) -> bool: def available(self) -> bool:
"""Can uiv1 currently be used? """Can uiv1 currently be used?
@ -133,20 +130,20 @@ class UIV1AppSubsystem(babase.AppSubsystem):
def on_app_loading(self) -> None: def on_app_loading(self) -> None:
from bauiv1._uitypes import ui_upkeep from bauiv1._uitypes import ui_upkeep
# IMPORTANT: If tweaking UI stuff, make sure it behaves for small, # IMPORTANT: If tweaking UI stuff, make sure it behaves for
# medium, and large UI modes. (doesn't run off screen, etc). # small, medium, and large UI modes. (doesn't run off screen,
# The overrides below can be used to test with different sizes. # etc). The overrides below can be used to test with different
# Generally small is used on phones, medium is used on tablets/tvs, # sizes. Generally small is used on phones, medium is used on
# and large is on desktop computers or perhaps large tablets. When # tablets/tvs, and large is on desktop computers or perhaps
# possible, run in windowed mode and resize the window to assure # large tablets. When possible, run in windowed mode and resize
# this holds true at all aspect ratios. # the window to assure this holds true at all aspect ratios.
# UPDATE: A better way to test this is now by setting the environment # UPDATE: A better way to test this is now by setting the
# variable BA_UI_SCALE to "small", "medium", or "large". # environment variable BA_UI_SCALE to "small", "medium", or
# This will affect system UIs not covered by the values below such # "large". This will affect system UIs not covered by the values
# as screen-messages. The below values remain functional, however, # below such as screen-messages. The below values remain
# for cases such as Android where environment variables can't be set # functional, however, for cases such as Android where
# easily. # environment variables can't be set easily.
if bool(False): # force-test ui scale if bool(False): # force-test ui scale
self._uiscale = babase.UIScale.SMALL self._uiscale = babase.UIScale.SMALL
@ -160,7 +157,9 @@ class UIV1AppSubsystem(babase.AppSubsystem):
) )
# Kick off our periodic UI upkeep. # 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) self.upkeeptimer = babase.AppTimer(2.6543, ui_upkeep, repeat=True)
def auto_set_back_window(self, from_window: MainWindow) -> None: 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'Main window {main_window} provides no back-state;'
f' cannot use auto-back.' 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 assert back_state.is_top_level is not None
backwin = back_state.create_window(transition='in_left')
self.set_main_window( self.set_main_window(
backwin, backwin,
from_window=from_window, from_window=from_window,
@ -213,7 +213,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
MainWindow methods main_window_replace() and main_window_back() MainWindow methods main_window_replace() and main_window_back()
should be used when possible for navigation. should be used when possible for navigation.
""" """
# pylint: disable=too-many-locals
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
from bauiv1._uitypes import MainWindow from bauiv1._uitypes import MainWindow
@ -275,8 +274,8 @@ class UIV1AppSubsystem(babase.AppSubsystem):
try: try:
if isinstance(from_window, bool): if isinstance(from_window, bool):
# For default val True we warn that the arg wasn't # For default val True we warn that the arg wasn't
# passed. False can be explicitly passed to disable this # passed. False can be explicitly passed to disable
# check. # this check.
if from_window is True: if from_window is True:
caller_frame = inspect.stack()[1] caller_frame = inspect.stack()[1]
caller_filename = caller_frame.filename caller_filename = caller_frame.filename
@ -289,8 +288,8 @@ class UIV1AppSubsystem(babase.AppSubsystem):
caller_line_number, caller_line_number,
) )
else: else:
# For everything else, warn if what they passed wasn't # For everything else, warn if what they passed
# the previous main menu widget. # wasn't the previous main menu widget.
if from_window is not existing: if from_window is not existing:
caller_frame = inspect.stack()[1] caller_frame = inspect.stack()[1]
caller_filename = caller_frame.filename caller_filename = caller_frame.filename
@ -344,12 +343,9 @@ class UIV1AppSubsystem(babase.AppSubsystem):
) )
window.main_window_back_state = None window.main_window_back_state = None
else: else:
oldwinstate = oldwin.get_main_window_state() window.main_window_back_state = self.save_main_window_state(
oldwin
# 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
self._main_window = window_weakref self._main_window = window_weakref
self._main_window_widget = window_widget self._main_window_widget = window_widget
@ -376,3 +372,52 @@ class UIV1AppSubsystem(babase.AppSubsystem):
self._main_window = empty_weakref(MainWindow) self._main_window = empty_weakref(MainWindow)
self._main_window_widget = None 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)

View File

@ -96,14 +96,20 @@ class MainWindow(Window):
except Exception: except Exception:
logging.exception('Error in on_main_window_close() for %s.', self) logging.exception('Error in on_main_window_close() for %s.', self)
_bauiv1.containerwidget( # Note: normally transition of None means instant, but we use
edit=self._root_widget, # that to mean 'do the default' so we support a special
transition=( # 'instant' string..
self._main_window_transition_out if transition == 'instant':
if transition is None self._root_widget.delete()
else transition 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: def main_window_has_control(self) -> bool:
"""Is this MainWindow allowed to change the global main window? """Is this MainWindow allowed to change the global main window?

View File

@ -40,7 +40,7 @@ class DevToolsWindow(bui.MainWindow):
self._scroll_width = self._width - (100 + 2 * x_inset) self._scroll_width = self._width - (100 + 2 * x_inset)
self._scroll_height = self._height - 115.0 self._scroll_height = self._height - 115.0
self._sub_width = self._scroll_width * 0.95 self._sub_width = self._scroll_width * 0.95
self._sub_height = 350.0 self._sub_height = 300.0
super().__init__( super().__init__(
root_widget=bui.containerwidget( root_widget=bui.containerwidget(
@ -169,37 +169,41 @@ class DevToolsWindow(bui.MainWindow):
), ),
) )
v -= self._spacing * 2.5 # Currently this is not wired up. The current official way to test
bui.textwidget( # UIScales is either to use the switcher in the dev-console or to
parent=self._subcontainer, # set the BA_UI_SCALE env var.
position=(170, v + 10), if bool(False):
size=(0, 0), v -= self._spacing * 2.5
text=bui.Lstr(resource='uiScaleText'), bui.textwidget(
color=app.ui_v1.title_color, parent=self._subcontainer,
h_align='center', position=(170, v + 10),
v_align='center', size=(0, 0),
) text=bui.Lstr(resource='uiScaleText'),
color=app.ui_v1.title_color,
h_align='center',
v_align='center',
)
PopupMenu( PopupMenu(
parent=self._subcontainer, parent=self._subcontainer,
position=(230, v - 20), position=(230, v - 20),
button_size=(200.0, 60.0), button_size=(200.0, 60.0),
width=100.0, width=100.0,
choices=[ choices=[
'auto', 'auto',
'small', 'small',
'medium', 'medium',
'large', 'large',
], ],
choices_display=[ choices_display=[
bui.Lstr(resource='autoText'), bui.Lstr(resource='autoText'),
bui.Lstr(resource='sizeSmallText'), bui.Lstr(resource='sizeSmallText'),
bui.Lstr(resource='sizeMediumText'), bui.Lstr(resource='sizeMediumText'),
bui.Lstr(resource='sizeLargeText'), bui.Lstr(resource='sizeLargeText'),
], ],
current_choice=app.config.get('UI Scale', 'auto'), current_choice=app.config.get('UI Scale', 'auto'),
on_value_change_call=self._set_uiscale, on_value_change_call=self._set_uiscale,
) )
@override @override
def get_main_window_state(self) -> bui.MainWindowState: def get_main_window_state(self) -> bui.MainWindowState:

View File

@ -362,7 +362,7 @@ class WatchWindow(bui.MainWindow):
bui.fade_screen(True) bui.fade_screen(True)
assert self._my_replay_selected is not None assert self._my_replay_selected is not None
bs.new_replay_session( bs.new_replay_session(
bui.get_replays_dir() + '/' + self._my_replay_selected f'{bui.get_replays_dir()}/{self._my_replay_selected}'
) )
except Exception: except Exception:
logging.exception('Error running replay session.') logging.exception('Error running replay session.')

View File

@ -3,6 +3,7 @@
#include "ballistica/base/app_mode/empty_app_mode.h" #include "ballistica/base/app_mode/empty_app_mode.h"
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/text/text_group.h"
namespace ballistica::base { namespace ballistica::base {

View File

@ -4,10 +4,12 @@
#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/app_adapter/app_adapter.h"
#include "ballistica/base/app_mode/empty_app_mode.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/assets/assets_server.h"
#include "ballistica/base/audio/audio.h" #include "ballistica/base/audio/audio.h"
#include "ballistica/base/audio/audio_server.h" #include "ballistica/base/audio/audio_server.h"
#include "ballistica/base/dynamics/bg/bg_dynamics_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/graphics_server.h"
#include "ballistica/base/graphics/support/screen_messages.h" #include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/graphics/text/text_graphics.h" #include "ballistica/base/graphics/text/text_graphics.h"
@ -24,7 +26,6 @@
#include "ballistica/base/support/huffman.h" #include "ballistica/base/support/huffman.h"
#include "ballistica/base/support/plus_soft.h" #include "ballistica/base/support/plus_soft.h"
#include "ballistica/base/support/stdio_console.h" #include "ballistica/base/support/stdio_console.h"
#include "ballistica/base/ui/dev_console.h"
#include "ballistica/base/ui/ui_delegate.h" #include "ballistica/base/ui/ui_delegate.h"
#include "ballistica/core/python/core_python.h" #include "ballistica/core/python/core_python.h"
#include "ballistica/shared/foundation/event_loop.h" #include "ballistica/shared/foundation/event_loop.h"
@ -193,12 +194,6 @@ void BaseFeatureSet::OnAssetsAvailable() {
} }
void BaseFeatureSet::StartApp() { 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_core->InMainThread());
BA_PRECONDITION(g_base); BA_PRECONDITION(g_base);
@ -987,4 +982,14 @@ void BaseFeatureSet::Reset() {
audio->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 } // namespace ballistica::base

View File

@ -5,7 +5,6 @@
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
#include <set>
#include <string> #include <string>
#include "ballistica/core/support/base_soft.h" #include "ballistica/core/support/base_soft.h"
@ -781,6 +780,9 @@ class BaseFeatureSet : public FeatureSetNativeComponent,
/// unsupported. /// unsupported.
void ClipboardSetText(const std::string& text); void ClipboardSetText(const std::string& text);
/// Set overall ui scale for the app.
void SetUIScale(UIScale scale);
// Const subsystems. // Const subsystems.
AppAdapter* const app_adapter; AppAdapter* const app_adapter;
AppConfig* const app_config; AppConfig* const app_config;

View File

@ -2,6 +2,7 @@
#include "ballistica/base/dynamics/collision_cache.h" #include "ballistica/base/dynamics/collision_cache.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"
#include "ode/ode_collision_kernel.h" #include "ode/ode_collision_kernel.h"
#include "ode/ode_collision_space_internal.h" #include "ode/ode_collision_space_internal.h"

View File

@ -2,6 +2,8 @@
#include "ballistica/base/graphics/component/object_component.h" #include "ballistica/base/graphics/component/object_component.h"
#include "ballistica/base/assets/assets.h"
namespace ballistica::base { namespace ballistica::base {
void ObjectComponent::WriteConfig() { void ObjectComponent::WriteConfig() {

View File

@ -2,6 +2,8 @@
#include "ballistica/base/graphics/component/render_component.h" #include "ballistica/base/graphics/component/render_component.h"
#include "ballistica/shared/math/rect.h"
namespace ballistica::base { namespace ballistica::base {
void RenderComponent::ScissorPush(const Rect& rect) { void RenderComponent::ScissorPush(const Rect& rect) {

View File

@ -5,7 +5,12 @@
#include <vector> #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 { namespace ballistica::base {

View File

@ -2,6 +2,8 @@
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/assets/assets.h"
namespace ballistica::base { namespace ballistica::base {
void SimpleComponent::WriteConfig() { void SimpleComponent::WriteConfig() {

View File

@ -2,6 +2,8 @@
#include "ballistica/base/graphics/component/smoke_component.h" #include "ballistica/base/graphics/component/smoke_component.h"
#include "ballistica/base/assets/assets.h"
namespace ballistica::base { namespace ballistica::base {
void SmokeComponent::WriteConfig() { void SmokeComponent::WriteConfig() {

View File

@ -2,6 +2,8 @@
#include "ballistica/base/graphics/component/sprite_component.h" #include "ballistica/base/graphics/component/sprite_component.h"
#include "ballistica/base/assets/assets.h"
namespace ballistica::base { namespace ballistica::base {
void SpriteComponent::WriteConfig() { void SpriteComponent::WriteConfig() {

View File

@ -25,7 +25,7 @@
#include "ballistica/base/graphics/gl/program/program_sprite_gl.h" #include "ballistica/base/graphics/gl/program/program_sprite_gl.h"
#include "ballistica/base/graphics/gl/render_target_gl.h" #include "ballistica/base/graphics/gl/render_target_gl.h"
#include "ballistica/base/graphics/gl/texture_data_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. // Turn this off to see how much blend overdraw is occurring.
#define BA_GL_ENABLE_BLEND 1 #define BA_GL_ENABLE_BLEND 1

View File

@ -11,6 +11,8 @@
#include "ballistica/base/graphics/component/special_component.h" #include "ballistica/base/graphics/component/special_component.h"
#include "ballistica/base/graphics/component/sprite_component.h" #include "ballistica/base/graphics/component/sprite_component.h"
#include "ballistica/base/graphics/graphics_server.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/camera.h"
#include "ballistica/base/graphics/support/net_graph.h" #include "ballistica/base/graphics/support/net_graph.h"
#include "ballistica/base/graphics/support/screen_messages.h" #include "ballistica/base/graphics/support/screen_messages.h"
@ -1535,12 +1537,23 @@ void Graphics::SetScreenResolution(float x, float y) {
return; return;
} }
// We'll need to ship a new settings to the server with this change.
graphics_settings_dirty_ = true;
res_x_ = x; res_x_ = x;
res_y_ = y; 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 // Calc virtual res. In vr mode our virtual res is independent of our
// screen size (since it gets drawn to an overlay). // screen size (since it gets drawn to an overlay).
if (g_core->vr_mode()) { 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). // Need to rebuild internal components (some are sized to the screen).
internal_components_inited_ = false; 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 // This may trigger us sending initial graphics settings to the
// graphics-server to kick off drawing. // graphics-server to kick off drawing.
got_screen_resolution_ = true; got_screen_resolution_ = true;
UpdateInitialGraphicsSettingsSend_(); 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) auto Graphics::CubeMapFromReflectionType(ReflectionType reflection_type)
@ -1723,10 +1736,6 @@ void Graphics::DrawUIBounds(RenderPass* pass) {
c.SetColor(1, 0, 0); c.SetColor(1, 0, 0);
{ {
auto xf = c.ScopedTransform(); auto xf = c.ScopedTransform();
// float width = pass->virtual_width();
// float height = pass->virtual_height();
// printf("DIMS %.2f %.2f\n", width, height);
float width, height; float width, height;
if (g_base->ui->scale() == UIScale::kSmall) { if (g_base->ui->scale() == UIScale::kSmall) {

View File

@ -15,9 +15,8 @@
#include "ballistica/shared/foundation/object.h" #include "ballistica/shared/foundation/object.h"
#include "ballistica/shared/foundation/types.h" #include "ballistica/shared/foundation/types.h"
#include "ballistica/shared/generic/snapshot.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/vector2f.h"
#include "ballistica/shared/math/vector3f.h"
namespace ballistica::base { namespace ballistica::base {
@ -63,10 +62,13 @@ class Graphics {
void OnScreenSizeChange(); void OnScreenSizeChange();
void DoApplyAppConfig(); void DoApplyAppConfig();
/// Should be called by the app-adapter to keep the engine informed /// Should be called by the app-adapter to keep the engine informed on the
/// on the drawable area it has to work with (in pixels). /// drawable area it has to work with (in pixels).
void SetScreenResolution(float x, float y); void SetScreenResolution(float x, float y);
/// Should be called when UIScale changes.
void OnUIScaleChange();
void StepDisplayTime(); void StepDisplayTime();
auto TextureQualityFromAppConfig() -> TextureQualityRequest; auto TextureQualityFromAppConfig() -> TextureQualityRequest;
@ -364,6 +366,7 @@ class Graphics {
ScreenMessages* const screenmessages; ScreenMessages* const screenmessages;
protected: protected:
void UpdateScreen_();
virtual ~Graphics(); virtual ~Graphics();
virtual void DoDrawFade(FrameDef* frame_def, float amt); virtual void DoDrawFade(FrameDef* frame_def, float amt);
static void CalcVirtualRes_(float* x, float* y); static void CalcVirtualRes_(float* x, float* y);

View File

@ -50,9 +50,12 @@ void GraphicsServer::ApplySettings(const GraphicsSettings* settings) {
if (renderer_) { if (renderer_) {
renderer_->set_pixel_scale(settings->pixel_scale); renderer_->set_pixel_scale(settings->pixel_scale);
} }
// Note: not checking virtual res here; assuming it only changes when // Note: need to look at both physical and virtual res here; its possible
// actual res changes. // for physical to stay the same but for virtual to change (ui-scale
if (res_x_ != settings->resolution.x || res_y_ != settings->resolution.y) { // 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_x_ = settings->resolution.x;
res_y_ = settings->resolution.y; res_y_ = settings->resolution.y;
res_x_virtual_ = settings->resolution_virtual.x; res_x_virtual_ = settings->resolution_virtual.x;

View File

@ -3,6 +3,7 @@
#include "ballistica/base/graphics/graphics_vr.h" #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/object_component.h"
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/component/special_component.h" #include "ballistica/base/graphics/component/special_component.h"

View File

@ -7,6 +7,7 @@
#include <vector> #include <vector>
#include "ballistica/base/assets/asset.h" #include "ballistica/base/assets/asset.h"
#include "ballistica/base/graphics/support/graphics_settings.h"
#include "ballistica/shared/generic/snapshot.h" #include "ballistica/shared/generic/snapshot.h"
#include "ballistica/shared/math/matrix44f.h" #include "ballistica/shared/math/matrix44f.h"
#include "ballistica/shared/math/vector2f.h" #include "ballistica/shared/math/vector2f.h"

View File

@ -5,6 +5,9 @@
#include <list> #include <list>
#include "ballistica/base/graphics/component/simple_component.h" #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 { namespace ballistica::base {

View File

@ -2,9 +2,11 @@
#include "ballistica/base/graphics/support/screen_messages.h" #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/component/simple_component.h"
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h" #include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
#include "ballistica/base/graphics/text/text_graphics.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/base/ui/ui.h"
#include "ballistica/shared/generic/utils.h" #include "ballistica/shared/generic/utils.h"

View File

@ -2,6 +2,7 @@
#include "ballistica/base/input/device/touch_input.h" #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/component/simple_component.h"
#include "ballistica/base/graphics/support/camera.h" #include "ballistica/base/graphics/support/camera.h"
#include "ballistica/base/input/input.h" #include "ballistica/base/input/input.h"

View File

@ -2,6 +2,8 @@
#include "ballistica/base/logic/logic.h" #include "ballistica/base/logic/logic.h"
#include <Python.h>
#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/app_adapter/app_adapter.h"
#include "ballistica/base/app_mode/app_mode.h" #include "ballistica/base/app_mode/app_mode.h"
#include "ballistica/base/audio/audio.h" #include "ballistica/base/audio/audio.h"
@ -9,12 +11,12 @@
#include "ballistica/base/networking/networking.h" #include "ballistica/base/networking/networking.h"
#include "ballistica/base/platform/base_platform.h" #include "ballistica/base/platform/base_platform.h"
#include "ballistica/base/python/base_python.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/plus_soft.h"
#include "ballistica/base/support/stdio_console.h" #include "ballistica/base/support/stdio_console.h"
#include "ballistica/base/ui/dev_console.h" #include "ballistica/base/ui/dev_console.h"
#include "ballistica/base/ui/ui.h" #include "ballistica/base/ui/ui.h"
#include "ballistica/shared/foundation/event_loop.h" #include "ballistica/shared/foundation/event_loop.h"
#include "ballistica/shared/python/python_sys.h"
namespace ballistica::base { namespace ballistica::base {

View File

@ -4,9 +4,8 @@
#define BALLISTICA_BASE_LOGIC_LOGIC_H_ #define BALLISTICA_BASE_LOGIC_LOGIC_H_
#include <memory> #include <memory>
#include <string>
#include "ballistica/shared/foundation/object.h" #include "ballistica/shared/generic/runnable.h"
namespace ballistica::base { namespace ballistica::base {
@ -117,9 +116,7 @@ class Logic {
auto applied_app_config() const { return applied_app_config_; } auto applied_app_config() const { return applied_app_config_; }
auto shutting_down() const { return shutting_down_; } auto shutting_down() const { return shutting_down_; }
auto shutdown_completed() const { return shutdown_completed_; } auto shutdown_completed() const { return shutdown_completed_; }
auto graphics_ready() const { return graphics_ready_; } auto graphics_ready() const { return graphics_ready_; }
auto app_active() const { return app_active_; } auto app_active() const { return app_active_; }
private: private:

View File

@ -3,6 +3,8 @@
#ifndef BALLISTICA_BASE_PYTHON_BASE_PYTHON_H_ #ifndef BALLISTICA_BASE_PYTHON_BASE_PYTHON_H_
#define BALLISTICA_BASE_PYTHON_BASE_PYTHON_H_ #define BALLISTICA_BASE_PYTHON_BASE_PYTHON_H_
#include <set>
#include "ballistica/base/base.h" #include "ballistica/base/base.h"
#include "ballistica/shared/python/python_object_set.h" #include "ballistica/shared/python/python_object_set.h"
@ -175,7 +177,6 @@ class BasePython {
void SoftImportPlus(); void SoftImportPlus();
void SoftImportClassic(); void SoftImportClassic();
// void SoftImportUIV1();
private: private:
std::set<std::string> do_once_locations_; std::set<std::string> do_once_locations_;

View File

@ -719,20 +719,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
// Just build this once and recycle it. // Just build this once and recycle it.
if (!g_base->python->objs().Exists(BasePython::ObjID::kEnv)) { 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> user_py_dir = g_core->GetUserPythonDirectory();
std::optional<std::string> app_py_dir = g_core->GetAppPythonDirectory(); std::optional<std::string> app_py_dir = g_core->GetAppPythonDirectory();
std::optional<std::string> site_py_dir = g_core->GetSitePythonDirectory(); std::optional<std::string> site_py_dir = g_core->GetSitePythonDirectory();
@ -751,7 +737,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
"sO" // python_directory_app "sO" // python_directory_app
"ss" // platform "ss" // platform
"ss" // subplatform "ss" // subplatform
"ss" // ui_scale
"sO" // on_tv "sO" // on_tv
"sO" // vr_mode "sO" // vr_mode
"sO" // demo_mode "sO" // demo_mode
@ -774,7 +759,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
app_py_dir ? *PythonRef::FromString(*app_py_dir) : Py_None, app_py_dir ? *PythonRef::FromString(*app_py_dir) : Py_None,
"platform", g_core->platform->GetPlatformName().c_str(), "platform", g_core->platform->GetPlatformName().c_str(),
"subplatform", g_core->platform->GetSubplatformName().c_str(), "subplatform", g_core->platform->GetSubplatformName().c_str(),
"ui_scale", ui_scale,
"on_tv", g_core->platform->IsRunningOnTV() ? Py_True : Py_False, "on_tv", g_core->platform->IsRunningOnTV() ? Py_True : Py_False,
"vr_mode", g_core->vr_mode() ? Py_True : Py_False, "vr_mode", g_core->vr_mode() ? Py_True : Py_False,
"demo_mode", g_buildconfig.demo_build() ? Py_True : Py_False, "demo_mode", g_buildconfig.demo_build() ? Py_True : Py_False,

View File

@ -7,7 +7,7 @@
#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/app_adapter/app_adapter.h"
#include "ballistica/base/app_mode/app_mode.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/input/input.h"
#include "ballistica/base/platform/base_platform.h" #include "ballistica/base/platform/base_platform.h"
#include "ballistica/base/python/base_python.h" #include "ballistica/base/python/base_python.h"
@ -62,7 +62,7 @@ static PyMethodDef PyGetSimpleSoundDef = {
static auto PySetUIInputDevice(PyObject* self, PyObject* args, static auto PySetUIInputDevice(PyObject* self, PyObject* args,
PyObject* keywds) -> PyObject* { PyObject* keywds) -> PyObject* {
BA_PYTHON_TRY; BA_PYTHON_TRY;
assert(g_base->InLogicThread()); BA_PRECONDITION(g_base->InLogicThread());
static const char* kwlist[] = {"input_device_id", nullptr}; static const char* kwlist[] = {"input_device_id", nullptr};
PyObject* input_device_id_obj = Py_None; PyObject* input_device_id_obj = Py_None;
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O", if (!PyArg_ParseTupleAndKeywords(args, keywds, "O",
@ -97,6 +97,89 @@ static PyMethodDef PySetUIInputDeviceDef = {
"Sets the input-device that currently owns the user interface.", "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 -------------------------------- // ----------------------------- hastouchscreen --------------------------------
static auto PyHasTouchScreen(PyObject* self, PyObject* args, static auto PyHasTouchScreen(PyObject* self, PyObject* args,
@ -1899,10 +1982,6 @@ static auto PySetDrawUIBounds(PyObject* self, PyObject* args,
return nullptr; return nullptr;
} }
// if (g_base->graphics->draw_ui_bounds()) {
// Py_RETURN_TRUE;
// }
// Py_RETURN_FALSE;
g_base->graphics->set_draw_ui_bounds(value); g_base->graphics->set_draw_ui_bounds(value);
Py_RETURN_NONE; Py_RETURN_NONE;
@ -1978,6 +2057,8 @@ auto PythonMoethodsBase3::GetMethods() -> std::vector<PyMethodDef> {
PyGetIdleTimeDef, PyGetIdleTimeDef,
PyExtraHashValueDef, PyExtraHashValueDef,
PySetUIInputDeviceDef, PySetUIInputDeviceDef,
PyGetUIScaleDef,
PySetUIScaleDef,
PyGetThreadNameDef, PyGetThreadNameDef,
PySetThreadNameDef, PySetThreadNameDef,
PyInLogicThreadDef, PyInLogicThreadDef,

View File

@ -2,6 +2,8 @@
#include "ballistica/base/ui/dev_console.h" #include "ballistica/base/ui/dev_console.h"
#include <Python.h>
#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/app_adapter/app_adapter.h"
#include "ballistica/base/app_mode/app_mode.h" #include "ballistica/base/app_mode/app_mode.h"
#include "ballistica/base/audio/audio.h" #include "ballistica/base/audio/audio.h"
@ -11,12 +13,12 @@
#include "ballistica/base/logic/logic.h" #include "ballistica/base/logic/logic.h"
#include "ballistica/base/platform/base_platform.h" #include "ballistica/base/platform/base_platform.h"
#include "ballistica/base/python/base_python.h" #include "ballistica/base/python/base_python.h"
#include "ballistica/base/support/context.h"
#include "ballistica/base/support/repeater.h" #include "ballistica/base/support/repeater.h"
#include "ballistica/base/ui/ui.h" #include "ballistica/base/ui/ui.h"
#include "ballistica/shared/foundation/event_loop.h" #include "ballistica/shared/foundation/event_loop.h"
#include "ballistica/shared/generic/utils.h" #include "ballistica/shared/generic/utils.h"
#include "ballistica/shared/python/python_command.h" #include "ballistica/shared/python/python_command.h"
#include "ballistica/shared/python/python_sys.h"
namespace ballistica::base { namespace ballistica::base {
@ -454,6 +456,13 @@ DevConsole::DevConsole() {
prompt_text_group_.SetText(">"); prompt_text_group_.SetText(">");
} }
void DevConsole::OnUIScaleChanged() {
g_base->logic->event_loop()->PushCall([this] {
RefreshTabButtons_();
RefreshTabContents_();
});
}
void DevConsole::RefreshTabButtons_() { void DevConsole::RefreshTabButtons_() {
// IMPORTANT: This code should always be run in its own top level call and // 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 // never directly from user code. Otherwise we can wind up mucking with

View File

@ -68,6 +68,8 @@ class DevConsole {
auto BaseScale() const -> float; auto BaseScale() const -> float;
void RequestRefresh(); void RequestRefresh();
void OnUIScaleChanged();
private: private:
class ScopedUILock_; class ScopedUILock_;
class Widget_; class Widget_;

View File

@ -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() { void UI::StepDisplayTime() {
assert(g_base->InLogicThread()); assert(g_base->InLogicThread());

View File

@ -4,11 +4,9 @@
#define BALLISTICA_BASE_UI_UI_H_ #define BALLISTICA_BASE_UI_UI_H_
#include <string> #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/base/ui/widget_message.h"
#include "ballistica/shared/generic/timer_list.h"
// Predeclare a few things from ui_v1. // Predeclare a few things from ui_v1.
namespace ballistica::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. /// These generally only get shown if a joystick of some form is present.
auto ShouldShowButtonShortcuts() const -> bool; auto ShouldShowButtonShortcuts() const -> bool;
/// Overall ui scale for the app. /// Get overall ui scale for the app.
auto scale() const { return scale_; } 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 /// Push a generic 'menu press' event, optionally associated with an input
/// device (nullptr to specify none). Can be called from any thread. /// device (nullptr to specify none). Can be called from any thread.
void PushMainMenuPressCall(InputDevice* device); void PushMainMenuPressCall(InputDevice* device);

View File

@ -2,6 +2,7 @@
#include "ballistica/scene_v1/node/explosion_node.h" #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/object_component.h"
#include "ballistica/base/graphics/component/post_process_component.h" #include "ballistica/base/graphics/component/post_process_component.h"
#include "ballistica/base/graphics/support/camera.h" #include "ballistica/base/graphics/support/camera.h"

View File

@ -2,6 +2,7 @@
#include "ballistica/scene_v1/node/flash_node.h" #include "ballistica/scene_v1/node/flash_node.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/object_component.h" #include "ballistica/base/graphics/component/object_component.h"
#include "ballistica/scene_v1/node/node_attribute.h" #include "ballistica/scene_v1/node/node_attribute.h"
#include "ballistica/scene_v1/node/node_type.h" #include "ballistica/scene_v1/node/node_type.h"

View File

@ -2,6 +2,7 @@
#include "ballistica/scene_v1/node/locator_node.h" #include "ballistica/scene_v1/node/locator_node.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/scene_v1/node/node_attribute.h" #include "ballistica/scene_v1/node/node_attribute.h"
#include "ballistica/scene_v1/node/node_type.h" #include "ballistica/scene_v1/node/node_type.h"

View File

@ -2,6 +2,7 @@
#include "ballistica/scene_v1/node/scorch_node.h" #include "ballistica/scene_v1/node/scorch_node.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/scene_v1/node/node_attribute.h" #include "ballistica/scene_v1/node/node_attribute.h"
#include "ballistica/scene_v1/node/node_type.h" #include "ballistica/scene_v1/node/node_type.h"

View File

@ -2,6 +2,7 @@
#include "ballistica/scene_v1/node/shield_node.h" #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/object_component.h"
#include "ballistica/base/graphics/component/post_process_component.h" #include "ballistica/base/graphics/component/post_process_component.h"
#include "ballistica/base/graphics/component/shield_component.h" #include "ballistica/base/graphics/component/shield_component.h"

View File

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

View File

@ -4,7 +4,6 @@
#define BALLISTICA_SHARED_FOUNDATION_MACROS_H_ #define BALLISTICA_SHARED_FOUNDATION_MACROS_H_
#ifdef __cplusplus #ifdef __cplusplus
#include <cassert>
#include <string> #include <string>
#endif #endif

View File

@ -142,9 +142,9 @@ typedef int64_t TimerMedium;
/// content needs to be presented as large and clear in order to remain /// content needs to be presented as large and clear in order to remain
/// readable from an average distance. /// readable from an average distance.
enum class UIScale : uint8_t { enum class UIScale : uint8_t {
kLarge,
kMedium,
kSmall, kSmall,
kMedium,
kLarge,
kLast // Sentinel. kLast // Sentinel.
}; };

View File

@ -7,12 +7,13 @@
// This header pulls in the actual Python includes and also defines some handy // This header pulls in the actual Python includes and also defines some handy
// macros and functions for working with Python objects. // 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 <Python.h>
#include <frameobject.h> #include <frameobject.h>
#include <weakrefobject.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() // Saving/restoring Python error state; useful when function PyObject_Str()
// or other functionality is needed during error reporting; by default it // or other functionality is needed during error reporting; by default it

View File

@ -2,11 +2,9 @@
#include "ballistica/ui_v1/python/methods/python_methods_ui_v1.h" #include "ballistica/ui_v1/python/methods/python_methods_ui_v1.h"
#include "ballistica/base/app_adapter/app_adapter.h" #include "ballistica/base/assets/sound_asset.h" // IWYU pragma: keep.
#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/python/base_python.h" #include "ballistica/base/python/base_python.h"
#include "ballistica/base/support/context.h"
#include "ballistica/shared/foundation/macros.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_mesh.h"
#include "ballistica/ui_v1/python/class/python_class_ui_sound.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>(); widget = Object::New<CheckBoxWidget>();
} }
// set applicable values ---------------------------- // Set applicable values.
if (size_obj != Py_None) { if (size_obj != Py_None) {
Point2D p = Python::GetPyPoint2D(size_obj); Point2D p = Python::GetPyPoint2D(size_obj);
widget->SetWidth(p.x); widget->SetWidth(p.x);
@ -1022,7 +1020,7 @@ static auto PyColumnWidget(PyObject* self, PyObject* args,
widget->set_claims_tab(Python::GetPyBool(claims_tab_obj)); 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) { if (edit_obj == Py_None) {
g_ui_v1->AddWidget(widget.Get(), parent_widget); g_ui_v1->AddWidget(widget.Get(), parent_widget);
} }
@ -1628,7 +1626,7 @@ static auto PyScrollWidget(PyObject* self, PyObject* args,
widget = Object::New<ScrollWidget>(); widget = Object::New<ScrollWidget>();
} }
// Set applicable values. ---------------------------- // Set applicable values.
if (size_obj != Py_None) { if (size_obj != Py_None) {
Point2D p = Python::GetPyPoint2D(size_obj); Point2D p = Python::GetPyPoint2D(size_obj);
widget->SetWidth(p.x); widget->SetWidth(p.x);
@ -2586,35 +2584,6 @@ static PyMethodDef PyRootUIBackPressDef = {
"(internal)", "(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 ---------------------------------- // ----------------------------- is_available ----------------------------------
static auto PyIsAvailable(PyObject* self) -> PyObject* { static auto PyIsAvailable(PyObject* self) -> PyObject* {
@ -2640,31 +2609,37 @@ static PyMethodDef PyIsAvailableDef = {
"(internal)", "(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> { auto PythonMethodsUIV1::GetMethods() -> std::vector<PyMethodDef> {
return { return {PyRootUIBackPressDef, PyGetSpecialWidgetDef, PySetPartyWindowOpenDef,
PyIsPartyIconVisibleDef, PyButtonWidgetDef, PyCheckBoxWidgetDef, PyImageWidgetDef,
PyRootUIBackPressDef, PyColumnWidgetDef, PyContainerWidgetDef, PyRowWidgetDef,
PyGetSpecialWidgetDef, PyScrollWidgetDef, PyHScrollWidgetDef, PyTextWidgetDef,
PySetPartyWindowOpenDef, PyWidgetDef, PyUIBoundsDef, PyGetSoundDef,
PyButtonWidgetDef, PyGetTextureDef, PyGetQRCodeTextureDef, PyGetMeshDef,
PyCheckBoxWidgetDef, PyIsAvailableDef, PyOnScreenChangeDef};
PyImageWidgetDef,
PyColumnWidgetDef,
PyContainerWidgetDef,
PyRowWidgetDef,
PyScrollWidgetDef,
PyHScrollWidgetDef,
PyTextWidgetDef,
PyWidgetDef,
PyUIBoundsDef,
PyGetSoundDef,
PyGetTextureDef,
PyGetQRCodeTextureDef,
PyGetMeshDef,
PyIsAvailableDef,
};
} }
#pragma clang diagnostic pop #pragma clang diagnostic pop

View File

@ -3,14 +3,12 @@
#include "ballistica/ui_v1/python/ui_v1_python.h" #include "ballistica/ui_v1/python/ui_v1_python.h"
#include "ballistica/base/audio/audio.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/input/input.h"
#include "ballistica/base/logic/logic.h"
#include "ballistica/base/python/base_python.h" #include "ballistica/base/python/base_python.h"
#include "ballistica/base/python/support/python_context_call.h" #include "ballistica/base/python/support/python_context_call.h"
#include "ballistica/base/ui/dev_console.h" #include "ballistica/base/ui/dev_console.h"
#include "ballistica/shared/foundation/event_loop.h" #include "ballistica/shared/python/python_command.h" // IWYU pragma: keep.
#include "ballistica/shared/python/python_command.h"
#include "ballistica/shared/python/python_module_builder.h" #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_mesh.h"
#include "ballistica/ui_v1/python/class/python_class_ui_sound.h" #include "ballistica/ui_v1/python/class/python_class_ui_sound.h"
@ -22,9 +20,9 @@ namespace ballistica::ui_v1 {
UIV1Python::UIV1Python() = default; UIV1Python::UIV1Python() = default;
// Declare a plain c PyInit_XXX function for our Python module; // Declare a plain C PyInit_XXX function for our Python module; this is how
// this is how Python inits our binary module (and by extension, our // Python inits our binary module (and by extension, our entire
// entire feature-set). // feature-set).
extern "C" auto PyInit__bauiv1() -> PyObject* { extern "C" auto PyInit__bauiv1() -> PyObject* {
auto* builder = auto* builder =
new PythonModuleBuilder("_bauiv1", new PythonModuleBuilder("_bauiv1",
@ -48,8 +46,8 @@ void UIV1Python::AddPythonClasses(PyObject* module) {
} }
void UIV1Python::ImportPythonObjs() { void UIV1Python::ImportPythonObjs() {
// Import and grab all our objs_. // Import and grab all our objs_. This code blob expects 'ObjID' and
// This code blob expects 'ObjID' and 'objs_' to be defined. // 'objs_' to be defined.
#include "ballistica/ui_v1/mgen/pyembed/binding_ui_v1.inc" #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>( auto context_call = Object::New<base::PythonContextCall>(
objs().Get(ObjID::kOnScreenKeyboardClass)); objs().Get(ObjID::kOnScreenKeyboardClass));
// This is probably getting called from within UI handling, so we // This is probably getting called from within UI handling, so we need to
// need to schedule things to run post-ui-traversal in that case. // schedule things to run post-ui-traversal in that case.
if (g_base->ui->InUIOperation()) { if (g_base->ui->InUIOperation()) {
context_call->ScheduleInUIOperation(args); context_call->ScheduleInUIOperation(args);
} else { } else {

View File

@ -2,7 +2,7 @@
#include "ballistica/ui_v1/ui_v1.h" #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/graphics/component/empty_component.h"
#include "ballistica/base/input/input.h" #include "ballistica/base/input/input.h"
#include "ballistica/base/support/app_config.h" #include "ballistica/base/support/app_config.h"
@ -214,12 +214,23 @@ void UIV1FeatureSet::AddWidget(Widget* w, ContainerWidget* parent) {
} }
void UIV1FeatureSet::OnScreenSizeChange() { void UIV1FeatureSet::OnScreenSizeChange() {
// This gets called by the native layer as window is resized/etc.
if (root_widget_.Exists()) { if (root_widget_.Exists()) {
root_widget_->SetWidth(g_base->graphics->screen_virtual_width()); root_widget_->SetWidth(g_base->graphics->screen_virtual_width());
root_widget_->SetHeight(g_base->graphics->screen_virtual_height()); 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() { void UIV1FeatureSet::OnLanguageChange() {
// Since switching languages is a bit costly, ignore redundant change // Since switching languages is a bit costly, ignore redundant change
// notifications. These will tend to happen nowadays since change // notifications. These will tend to happen nowadays since change

View File

@ -85,18 +85,10 @@ class UIV1FeatureSet : public FeatureSetNativeComponent,
auto MainMenuVisible() -> bool override; auto MainMenuVisible() -> bool override;
auto PartyIconVisible() -> bool override; auto PartyIconVisible() -> bool override;
void ActivatePartyIcon() 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; void Draw(base::FrameDef* frame_def) override;
UIV1Python* const python; UIV1Python* const python;
// auto root_ui() const -> ui_v1::RootUI* {
// assert(root_ui_);
// return root_ui_;
// }
// void OnAppStart() override;
void OnActivate() override; void OnActivate() override;
void OnDeactivate() override; void OnDeactivate() override;
@ -123,6 +115,8 @@ class UIV1FeatureSet : public FeatureSetNativeComponent,
void DeleteWidget(Widget* widget); void DeleteWidget(Widget* widget);
void OnScreenSizeChange() override; void OnScreenSizeChange() override;
void OnScreenChange();
void OnLanguageChange() override; void OnLanguageChange() override;
auto GetRootWidget() -> ui_v1::Widget* override; auto GetRootWidget() -> ui_v1::Widget* override;
auto SendWidgetMessage(const base::WidgetMessage& m) -> int override; auto SendWidgetMessage(const base::WidgetMessage& m) -> int override;
@ -137,7 +131,6 @@ class UIV1FeatureSet : public FeatureSetNativeComponent,
private: private:
UIV1FeatureSet(); UIV1FeatureSet();
// RootUI* root_ui_{};
Object::Ref<ContainerWidget> screen_root_widget_; Object::Ref<ContainerWidget> screen_root_widget_;
Object::Ref<ContainerWidget> overlay_root_widget_; Object::Ref<ContainerWidget> overlay_root_widget_;
Object::Ref<RootWidget> root_widget_; Object::Ref<RootWidget> root_widget_;

View File

@ -2,6 +2,7 @@
#include "ballistica/ui_v1/widget/button_widget.h" #include "ballistica/ui_v1/widget/button_widget.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/audio/audio.h" #include "ballistica/base/audio/audio.h"
#include "ballistica/base/graphics/component/empty_component.h" #include "ballistica/base/graphics/component/empty_component.h"
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"

View File

@ -2,6 +2,7 @@
#include "ballistica/ui_v1/widget/container_widget.h" #include "ballistica/ui_v1/widget/container_widget.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/audio/audio.h" #include "ballistica/base/audio/audio.h"
#include "ballistica/base/graphics/component/empty_component.h" #include "ballistica/base/graphics/component/empty_component.h"
#include "ballistica/base/graphics/component/simple_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 // Schedule this to run immediately after any current UI
// traversal. // traversal.
call->ScheduleInUIOperation(); call->ScheduleInUIOperation();
} else {
OnCancelCustom();
} }
} }
break; break;

View File

@ -118,12 +118,6 @@ class ContainerWidget : public Widget {
// (generally true but list containers may not want) // (generally true but list containers may not want)
auto selection_loops() const -> bool { return selection_loops_; } 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 SetOnActivateCall(PyObject* c);
void SetOnOutsideClickCall(PyObject* c); void SetOnOutsideClickCall(PyObject* c);
@ -132,13 +126,23 @@ class ContainerWidget : public Widget {
} }
void set_draggable(bool d) { draggable_ = d; } 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_; } 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_; } 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_; } 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; } void set_single_depth(bool s) { single_depth_ = s; }
// Translate a point in-place into the space of a given child widget. // Translate a point in-place into the space of a given child widget.
@ -151,33 +155,33 @@ class ContainerWidget : public Widget {
blue_ = b; blue_ = b;
alpha_ = a; alpha_ = a;
} }
void set_should_print_list_exit_instructions(bool v) { auto GetDrawBrightness(millisecs_t time) const -> float override;
should_print_list_exit_instructions_ = v; auto IsAcceptingInput() const -> bool override;
} void OnLanguageChange() override;
void set_selection_loops(bool loops) { selection_loops_ = loops; } void set_selection_loops(bool loops) { selection_loops_ = loops; }
void set_click_activate(bool enabled) { click_activate_ = enabled; } void set_click_activate(bool enabled) { click_activate_ = enabled; }
void set_always_highlight(bool enable) { always_highlight_ = enable; } 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 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_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_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. // Return the topmost widget that is accepting input. Used for toolbar
// (used for toolbar focusing; may not always equal selected widget // focusing; may not always equal selected widget if the topmost one is
// if the topmost one is transitioning out, etc.) // transitioning out, etc.
auto GetTopmostToolbarInfluencingWidget() -> Widget*; auto GetTopmostToolbarInfluencingWidget() -> Widget*;
auto IsTransitioningOut() const -> bool override; auto IsTransitioningOut() const -> bool override;
protected: protected:
virtual void OnCancelCustom() {}
void set_single_depth_root(bool s) { single_depth_root_ = s; } void set_single_depth_root(bool s) { single_depth_root_ = s; }
// Note that the offsets here are purely for visual transitions and things; // Note that the offsets here are purely for visual transitions and
// the UI itself only knows about the standard widget transform values. // things; the UI itself only knows about the standard widget transform
// values.
void DrawChildren(base::RenderPass* pass, bool transparent, float x_offset, void DrawChildren(base::RenderPass* pass, bool transparent, float x_offset,
float y_offset, float scale); float y_offset, float scale);
void SetSelected(bool s, SelectionCause cause) override; void SetSelected(bool s, SelectionCause cause) override;
@ -195,41 +199,36 @@ class ContainerWidget : public Widget {
void set_height(float val) { height_ = val; } void set_height(float val) { height_ = val; }
private: private:
// Given a container and a point, returns a selectable widget in the downward // Given a container and a point, returns a selectable widget in the
// direction or nullptr. // downward direction or nullptr.
auto GetClosestDownWidget(float x, float y, Widget* ignoreWidget) -> Widget*; auto GetClosestDownWidget(float x, float y, Widget* ignoreWidget) -> Widget*;
auto GetClosestUpWidget(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 GetClosestRightWidget(float x, float y, Widget* ignoreWidget) -> Widget*;
auto GetClosestLeftWidget(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; auto GetMult(millisecs_t current_time, bool for_glow = false) const -> float;
void PrintExitListInstructions(millisecs_t old_last_prev_next_time); void PrintExitListInstructions(millisecs_t old_last_prev_next_time);
std::vector<Object::Ref<Widget> > widgets_; 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 width_{};
float height_{}; 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_x_{};
float scale_origin_stack_offset_y_{}; float scale_origin_stack_offset_y_{};
float transition_scale_offset_x_{}; float transition_scale_offset_x_{};
float transition_scale_offset_y_{}; float transition_scale_offset_y_{};
bool pressed_{};
bool mouse_over_{};
bool pressed_activate_{};
bool always_highlight_{};
bool click_activate_{};
float red_{0.4f}; float red_{0.4f};
float green_{0.37f}; float green_{0.37f};
float blue_{0.49f}; float blue_{0.49f};
float alpha_{1.0f}; 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 glow_width_{}, glow_height_{}, glow_center_x_{}, glow_center_y_{};
float bg_width_{}, bg_height_{}, bg_center_x_{}, bg_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 transition_target_offset_{};
float drag_x_{}, drag_y_{}; float drag_x_{}, drag_y_{};
float transition_offset_x_{}; float transition_offset_x_{};
@ -241,11 +240,23 @@ class ContainerWidget : public Widget {
float transition_start_offset_{}; float transition_start_offset_{};
float transition_scale_{1.0f}; float transition_scale_{1.0f};
float d_transition_scale_{}; float d_transition_scale_{};
millisecs_t last_activate_time_millisecs_{};
millisecs_t transition_start_time_{};
millisecs_t dynamics_update_time_millisecs_{}; 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 bg_dirty_{true};
bool glow_dirty_{true}; bool glow_dirty_{true};
bool transitioning_{}; bool transitioning_{};
TransitionType transition_type_{}; bool pressed_{};
bool mouse_over_{};
bool pressed_activate_{};
bool always_highlight_{};
bool click_activate_{};
bool transitioning_out_{}; bool transitioning_out_{};
bool draggable_{}; bool draggable_{};
bool dragging_{}; bool dragging_{};
@ -263,16 +274,10 @@ class ContainerWidget : public Widget {
bool single_depth_{true}; bool single_depth_{true};
bool single_depth_root_{}; bool single_depth_root_{};
bool should_print_list_exit_instructions_{}; 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_{}; bool claims_outside_clicks_{};
// Keep these at the bottom so they're torn down first. // Keep these at the bottom so they're torn down first. ...hmm that seems
// ...hmm that seems fragile; should I add explicit code to kill them? // fragile; should I add explicit code to kill them?
Object::Ref<base::PythonContextCall> on_activate_call_; Object::Ref<base::PythonContextCall> on_activate_call_;
Object::Ref<base::PythonContextCall> on_outside_click_call_; Object::Ref<base::PythonContextCall> on_outside_click_call_;
Object::Ref<base::PythonContextCall> on_cancel_call_; Object::Ref<base::PythonContextCall> on_cancel_call_;

View File

@ -2,6 +2,7 @@
#include "ballistica/ui_v1/widget/h_scroll_widget.h" #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/empty_component.h"
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/support/app_timer.h" #include "ballistica/base/support/app_timer.h"

View File

@ -2,7 +2,9 @@
#include "ballistica/ui_v1/widget/image_widget.h" #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/component/simple_component.h"
#include "ballistica/base/graphics/mesh/mesh_indexed_simple_full.h"
#include "ballistica/base/logic/logic.h" #include "ballistica/base/logic/logic.h"
namespace ballistica::ui_v1 { namespace ballistica::ui_v1 {

View File

@ -6,6 +6,7 @@
#include "ballistica/base/assets/assets.h" #include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/renderer/render_pass.h" #include "ballistica/base/graphics/renderer/render_pass.h"
#include "ballistica/base/graphics/support/frame_def.h" #include "ballistica/base/graphics/support/frame_def.h"
#include "ballistica/base/support/context.h"
#include "ballistica/shared/foundation/inline.h" #include "ballistica/shared/foundation/inline.h"
#include "ballistica/ui_v1/python/ui_v1_python.h" #include "ballistica/ui_v1/python/ui_v1_python.h"
#include "ballistica/ui_v1/widget/button_widget.h" #include "ballistica/ui_v1/widget/button_widget.h"
@ -1574,6 +1575,8 @@ void RootWidget::UpdateLayout() {
StepPositions_(0.0f); StepPositions_(0.0f);
} }
void RootWidget::OnUIScaleChange() { MarkForUpdate(); }
auto RootWidget::HandleMessage(const base::WidgetMessage& m) -> bool { auto RootWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
// If a cancel message comes through and our back button is enabled, fire // If a cancel message comes through and our back button is enabled, fire
// our back button. In all other cases just do the default. // our back button. In all other cases just do the default.
@ -1607,20 +1610,6 @@ void RootWidget::SetOverlayWidget(StackWidget* w) {
overlay_stack_widget_ = 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* { auto RootWidget::GetSpecialWidget(const std::string& s) const -> Widget* {
if (s == "squad_button") { if (s == "squad_button") {
return squad_button_ ? squad_button_->widget.Get() : nullptr; return squad_button_ ? squad_button_->widget.Get() : nullptr;

View File

@ -30,7 +30,9 @@ class RootWidget : public ContainerWidget {
return overlay_stack_widget_; return overlay_stack_widget_;
} }
void OnCancelCustom() override; /// Called when UIScale or screen dimensions change.
void OnUIScaleChange();
void UpdateLayout() override; void UpdateLayout() override;
private: private:

View File

@ -2,6 +2,7 @@
#include "ballistica/ui_v1/widget/scroll_widget.h" #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/empty_component.h"
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/support/app_timer.h" #include "ballistica/base/support/app_timer.h"

View File

@ -2,11 +2,13 @@
#include "ballistica/ui_v1/widget/text_widget.h" #include "ballistica/ui_v1/widget/text_widget.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/audio/audio.h" #include "ballistica/base/audio/audio.h"
#include "ballistica/base/graphics/component/empty_component.h" #include "ballistica/base/graphics/component/empty_component.h"
#include "ballistica/base/graphics/component/simple_component.h" #include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h" #include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
#include "ballistica/base/graphics/text/text_graphics.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/device/keyboard_input.h"
#include "ballistica/base/input/input.h" #include "ballistica/base/input/input.h"
#include "ballistica/base/logic/logic.h" #include "ballistica/base/logic/logic.h"