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

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
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.
@ -82,6 +82,14 @@
- Removed `efro.util.enum_by_value()` which was a workaround for a Python bug
that has been fixed for a few versions now. Instaed of
`enum_by_value(MyEnumType, foo)` you can simply do `MyEnumType(foo)`.
- Removed `bauiv1.is_party_icon_visible()` as it is now always visible.
- 'ui_scale' is no longer available in _babase.env() since it can now change;
use `babase.get_ui_scale()` to get it now.
- Removed the UIScale control from the devtools window, which was only partially
wired up (it did not affect native layer bits). For now the official ways to
test UIScales are by using the UI panel in the dev-console or by setting the
`BA_UI_SCALE` env var. If we can get UIScale switches to feel seamless enough
at some point, it may be worth adding to display settings.
### 1.7.36 (build 21944, api 8, 2024-07-26)
- Wired up Tokens, BombSquad's new purchasable currency. The first thing these

View File

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

View File

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

View File

@ -629,6 +629,35 @@ class App:
self._initial_sign_in_completed = True
self._update_state()
def set_ui_scale(self, scale: babase.UIScale) -> None:
"""Change ui-scale on the fly.
Currently this is mainly for debugging and will not
be called as part of normal app operation.
"""
assert _babase.in_logic_thread()
# Apply to the native layer.
_babase.set_ui_scale(scale.name.lower())
# Inform all subsystems that something screen-related has
# changed. We assume subsystems won't be added at this point so
# we can use the list directly.
assert self._subsystem_registration_ended
for subsystem in self._subsystems:
try:
subsystem.on_screen_change()
except Exception:
logging.exception(
'Error in on_screen_change() for subsystem %s.', subsystem
)
# 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:
from babase._appmode import AppMode
@ -718,7 +747,7 @@ class App:
subsystem.reset()
except Exception:
logging.exception(
'Error in reset for subsystem %s.', subsystem
'Error in reset() for subsystem %s.', subsystem
)
self._mode = mode
@ -805,7 +834,7 @@ class App:
subsystem.on_app_loading()
except Exception:
logging.exception(
'Error in on_app_loading for subsystem %s.', subsystem
'Error in on_app_loading() for subsystem %s.', subsystem
)
# Normally plus tells us when initial sign-in is done. If plus
@ -854,7 +883,7 @@ class App:
subsystem.on_app_running()
except Exception:
logging.exception(
'Error in on_app_running for subsystem %s.', subsystem
'Error in on_app_running() for subsystem %s.', subsystem
)
# Cut off new subsystem additions at this point.
@ -890,7 +919,8 @@ class App:
subsystem.do_apply_app_config()
except Exception:
logging.exception(
'Error in do_apply_app_config for subsystem %s.', subsystem
'Error in do_apply_app_config() for subsystem %s.',
subsystem,
)
# Let the native layer do its thing.
@ -1013,7 +1043,7 @@ class App:
subsystem.on_app_suspend()
except Exception:
logging.exception(
'Error in on_app_suspend for subsystem %s.', subsystem
'Error in on_app_suspend() for subsystem %s.', subsystem
)
def _on_unsuspend(self) -> None:
@ -1027,7 +1057,7 @@ class App:
subsystem.on_app_unsuspend()
except Exception:
logging.exception(
'Error in on_app_unsuspend for subsystem %s.', subsystem
'Error in on_app_unsuspend() for subsystem %s.', subsystem
)
def _on_shutting_down(self) -> None:
@ -1041,7 +1071,7 @@ class App:
subsystem.on_app_shutdown()
except Exception:
logging.exception(
'Error in on_app_shutdown for subsystem %s.', subsystem
'Error in on_app_shutdown() for subsystem %s.', subsystem
)
# Now kick off any async shutdown task(s).
@ -1059,7 +1089,7 @@ class App:
subsystem.on_app_shutdown_complete()
except Exception:
logging.exception(
'Error in on_app_shutdown_complete for subsystem %s.',
'Error in on_app_shutdown_complete() for subsystem %s.',
subsystem,
)

View File

@ -8,7 +8,7 @@ from typing import TYPE_CHECKING
import _babase
if TYPE_CHECKING:
pass
from babase import UIScale
class AppSubsystem:
@ -54,6 +54,9 @@ class AppSubsystem:
def do_apply_app_config(self) -> None:
"""Called when the app config should be applied."""
def on_screen_change(self) -> None:
"""Called when screen dimensions or ui-scale changes."""
def reset(self) -> None:
"""Reset the subsystem to a default state.

View File

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

View File

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

View File

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

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21988
TARGET_BALLISTICA_BUILD = 21995
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:
offs = -55 if bui.is_party_icon_visible() else 0
offs = -55
assert self._corner_button_offs is not None
pos_x = self._corner_button_offs[0] + offs
pos_y = self._corner_button_offs[1]

View File

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

View File

@ -61,7 +61,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
from bauiv1._uitypes import MainWindow
super().__init__()
env = babase.env()
# We hold only a weak ref to the current main Window; we want it
# to be able to disappear on its own. That being said, we do
@ -72,18 +71,28 @@ class UIV1AppSubsystem(babase.AppSubsystem):
self.quit_window: bauiv1.Widget | None = None
# The following should probably go away or move to classic.
# self._main_menu_location: str | None = None
# For storing arbitrary class-level state data for Windows or
# other UI related classes.
self.window_states: dict[type, Any] = {}
uiscalestr = babase.app.config.get('UI Scale', env['ui_scale'])
if uiscalestr == 'auto':
uiscalestr = env['ui_scale']
self._uiscale: babase.UIScale
self._update_ui_scale()
self.cleanupchecks: list[UICleanupCheck] = []
self.upkeeptimer: babase.AppTimer | None = None
self.title_color = (0.72, 0.7, 0.75)
self.heading_color = (0.72, 0.7, 0.75)
self.infotextcolor = (0.7, 0.9, 0.7)
# Elements in our root UI will call anything here when
# activated.
self.root_ui_calls: dict[
UIV1AppSubsystem.RootUIElement, Callable[[], None]
] = {}
def _update_ui_scale(self) -> None:
uiscalestr = babase.get_ui_scale()
if uiscalestr == 'large':
self._uiscale = babase.UIScale.LARGE
elif uiscalestr == 'medium':
@ -94,18 +103,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
logging.error("Invalid UIScale '%s'.", uiscalestr)
self._uiscale = babase.UIScale.MEDIUM
self.cleanupchecks: list[UICleanupCheck] = []
self.upkeeptimer: babase.AppTimer | None = None
self.title_color = (0.72, 0.7, 0.75)
self.heading_color = (0.72, 0.7, 0.75)
self.infotextcolor = (0.7, 0.9, 0.7)
# Elements in our root UI will call anything here when activated.
self.root_ui_calls: dict[
UIV1AppSubsystem.RootUIElement, Callable[[], None]
] = {}
@property
def available(self) -> bool:
"""Can uiv1 currently be used?
@ -133,20 +130,20 @@ class UIV1AppSubsystem(babase.AppSubsystem):
def on_app_loading(self) -> None:
from bauiv1._uitypes import ui_upkeep
# IMPORTANT: If tweaking UI stuff, make sure it behaves for small,
# medium, and large UI modes. (doesn't run off screen, etc).
# The overrides below can be used to test with different sizes.
# Generally small is used on phones, medium is used on tablets/tvs,
# and large is on desktop computers or perhaps large tablets. When
# possible, run in windowed mode and resize the window to assure
# this holds true at all aspect ratios.
# IMPORTANT: If tweaking UI stuff, make sure it behaves for
# small, medium, and large UI modes. (doesn't run off screen,
# etc). The overrides below can be used to test with different
# sizes. Generally small is used on phones, medium is used on
# tablets/tvs, and large is on desktop computers or perhaps
# large tablets. When possible, run in windowed mode and resize
# the window to assure this holds true at all aspect ratios.
# UPDATE: A better way to test this is now by setting the environment
# variable BA_UI_SCALE to "small", "medium", or "large".
# This will affect system UIs not covered by the values below such
# as screen-messages. The below values remain functional, however,
# for cases such as Android where environment variables can't be set
# easily.
# UPDATE: A better way to test this is now by setting the
# environment variable BA_UI_SCALE to "small", "medium", or
# "large". This will affect system UIs not covered by the values
# below such as screen-messages. The below values remain
# functional, however, for cases such as Android where
# environment variables can't be set easily.
if bool(False): # force-test ui scale
self._uiscale = babase.UIScale.SMALL
@ -160,7 +157,9 @@ class UIV1AppSubsystem(babase.AppSubsystem):
)
# Kick off our periodic UI upkeep.
# FIXME: Can probably kill this if we do immediate UI death checks.
# FIXME: Can probably kill this if we do immediate UI death
# checks.
self.upkeeptimer = babase.AppTimer(2.6543, ui_upkeep, repeat=True)
def auto_set_back_window(self, from_window: MainWindow) -> None:
@ -181,11 +180,12 @@ class UIV1AppSubsystem(babase.AppSubsystem):
f'Main window {main_window} provides no back-state;'
f' cannot use auto-back.'
)
backwin = back_state.create_window(transition='in_left')
# Properly created state should have a value here.
# Valid states should have a value here.
assert back_state.is_top_level is not None
backwin = back_state.create_window(transition='in_left')
self.set_main_window(
backwin,
from_window=from_window,
@ -213,7 +213,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
MainWindow methods main_window_replace() and main_window_back()
should be used when possible for navigation.
"""
# pylint: disable=too-many-locals
# pylint: disable=too-many-branches
# pylint: disable=too-many-statements
from bauiv1._uitypes import MainWindow
@ -275,8 +274,8 @@ class UIV1AppSubsystem(babase.AppSubsystem):
try:
if isinstance(from_window, bool):
# For default val True we warn that the arg wasn't
# passed. False can be explicitly passed to disable this
# check.
# passed. False can be explicitly passed to disable
# this check.
if from_window is True:
caller_frame = inspect.stack()[1]
caller_filename = caller_frame.filename
@ -289,8 +288,8 @@ class UIV1AppSubsystem(babase.AppSubsystem):
caller_line_number,
)
else:
# For everything else, warn if what they passed wasn't
# the previous main menu widget.
# For everything else, warn if what they passed
# wasn't the previous main menu widget.
if from_window is not existing:
caller_frame = inspect.stack()[1]
caller_filename = caller_frame.filename
@ -344,12 +343,9 @@ class UIV1AppSubsystem(babase.AppSubsystem):
)
window.main_window_back_state = None
else:
oldwinstate = oldwin.get_main_window_state()
# Store some common window stuff on its state.
oldwinstate.parent = oldwin.main_window_back_state
oldwinstate.is_top_level = oldwin.main_window_is_top_level
window.main_window_back_state = oldwinstate
window.main_window_back_state = self.save_main_window_state(
oldwin
)
self._main_window = window_weakref
self._main_window_widget = window_widget
@ -376,3 +372,52 @@ class UIV1AppSubsystem(babase.AppSubsystem):
self._main_window = empty_weakref(MainWindow)
self._main_window_widget = None
def save_main_window_state(self, window: MainWindow) -> MainWindowState:
"""Fully initialize a window-state from a window.
Use this to get a state for later restoration purposes.
Calling the window's get_main_window_state() directly is
insufficient.
"""
winstate = window.get_main_window_state()
# Store some common window stuff on its state.
winstate.parent = window.main_window_back_state
winstate.is_top_level = window.main_window_is_top_level
return winstate
def restore_main_window_state(self, state: MainWindowState) -> None:
"""Restore UI to a saved state."""
existing = self.get_main_window()
if existing is not None:
raise RuntimeError('There is already a MainWindow.')
# Valid states should have a value here.
assert state.is_top_level is not None
win = state.create_window(transition=None)
self.set_main_window(
win,
from_window=False, # disable check
is_top_level=state.is_top_level,
back_state=state.parent,
suppress_warning=True,
)
@override
def on_screen_change(self) -> None:
# Update our stored UIScale.
self._update_ui_scale()
# Update native bits (allow root widget to rebuild itself/etc.)
_bauiv1.on_screen_change()
# Lastly, if we have a main window, recreate it to pick up the
# new UIScale/etc.
mainwindow = self.get_main_window()
if mainwindow is not None:
winstate = self.save_main_window_state(mainwindow)
self.clear_main_window(transition='instant')
self.restore_main_window_state(winstate)

View File

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

View File

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

View File

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

View File

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

View File

@ -4,10 +4,12 @@
#include "ballistica/base/app_adapter/app_adapter.h"
#include "ballistica/base/app_mode/empty_app_mode.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/assets/assets_server.h"
#include "ballistica/base/audio/audio.h"
#include "ballistica/base/audio/audio_server.h"
#include "ballistica/base/dynamics/bg/bg_dynamics_server.h"
#include "ballistica/base/graphics/graphics.h"
#include "ballistica/base/graphics/graphics_server.h"
#include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/graphics/text/text_graphics.h"
@ -24,7 +26,6 @@
#include "ballistica/base/support/huffman.h"
#include "ballistica/base/support/plus_soft.h"
#include "ballistica/base/support/stdio_console.h"
#include "ballistica/base/ui/dev_console.h"
#include "ballistica/base/ui/ui_delegate.h"
#include "ballistica/core/python/core_python.h"
#include "ballistica/shared/foundation/event_loop.h"
@ -193,12 +194,6 @@ void BaseFeatureSet::OnAssetsAvailable() {
}
void BaseFeatureSet::StartApp() {
// {
// // TEST - recreate the ID python dumps in its thread tracebacks.
// auto val = PyThread_get_thread_ident();
// printf("MAIN THREAD IS %#018lx\n", val);
// }
BA_PRECONDITION(g_core->InMainThread());
BA_PRECONDITION(g_base);
@ -987,4 +982,14 @@ void BaseFeatureSet::Reset() {
audio->Reset();
}
void BaseFeatureSet::SetUIScale(UIScale scale) {
assert(InLogicThread());
// Store the canonical value in UI.
ui->SetScale(scale);
// Let interested parties know that it has changed.
graphics->OnUIScaleChange();
}
} // namespace ballistica::base

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,12 @@
#include <vector>
#include "ballistica/base/graphics/renderer/renderer.h"
#include "ballistica/base/assets/mesh_asset.h"
#include "ballistica/base/graphics/graphics.h"
#include "ballistica/base/graphics/renderer/render_pass.h"
#include "ballistica/base/graphics/support/frame_def.h"
#include "ballistica/base/graphics/support/render_command_buffer.h"
#include "ballistica/shared/math/rect.h"
namespace ballistica::base {

View File

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

View File

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

View File

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

View File

@ -25,7 +25,7 @@
#include "ballistica/base/graphics/gl/program/program_sprite_gl.h"
#include "ballistica/base/graphics/gl/render_target_gl.h"
#include "ballistica/base/graphics/gl/texture_data_gl.h"
#include "ballistica/base/platform/base_platform.h"
#include "ballistica/shared/math/rect.h"
// Turn this off to see how much blend overdraw is occurring.
#define BA_GL_ENABLE_BLEND 1

View File

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

View File

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

View File

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

View File

@ -3,6 +3,7 @@
#include "ballistica/base/graphics/graphics_vr.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/object_component.h"
#include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/component/special_component.h"

View File

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

View File

@ -5,6 +5,9 @@
#include <list>
#include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/mesh/image_mesh.h"
#include "ballistica/base/graphics/mesh/mesh_indexed_simple_full.h"
#include "ballistica/base/graphics/text/text_group.h"
namespace ballistica::base {

View File

@ -2,9 +2,11 @@
#include "ballistica/base/graphics/support/screen_messages.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
#include "ballistica/base/graphics/text/text_graphics.h"
#include "ballistica/base/graphics/text/text_group.h"
#include "ballistica/base/ui/ui.h"
#include "ballistica/shared/generic/utils.h"

View File

@ -2,6 +2,7 @@
#include "ballistica/base/input/device/touch_input.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/support/camera.h"
#include "ballistica/base/input/input.h"

View File

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

View File

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

View File

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

View File

@ -719,20 +719,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
// Just build this once and recycle it.
if (!g_base->python->objs().Exists(BasePython::ObjID::kEnv)) {
const char* ui_scale;
switch (g_base->ui->scale()) {
case UIScale::kLarge:
ui_scale = "large";
break;
case UIScale::kMedium:
ui_scale = "medium";
break;
case UIScale::kSmall:
ui_scale = "small";
break;
default:
throw Exception();
}
std::optional<std::string> user_py_dir = g_core->GetUserPythonDirectory();
std::optional<std::string> app_py_dir = g_core->GetAppPythonDirectory();
std::optional<std::string> site_py_dir = g_core->GetSitePythonDirectory();
@ -751,7 +737,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
"sO" // python_directory_app
"ss" // platform
"ss" // subplatform
"ss" // ui_scale
"sO" // on_tv
"sO" // vr_mode
"sO" // demo_mode
@ -774,7 +759,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
app_py_dir ? *PythonRef::FromString(*app_py_dir) : Py_None,
"platform", g_core->platform->GetPlatformName().c_str(),
"subplatform", g_core->platform->GetSubplatformName().c_str(),
"ui_scale", ui_scale,
"on_tv", g_core->platform->IsRunningOnTV() ? Py_True : Py_False,
"vr_mode", g_core->vr_mode() ? Py_True : Py_False,
"demo_mode", g_buildconfig.demo_build() ? Py_True : Py_False,

View File

@ -7,7 +7,7 @@
#include "ballistica/base/app_adapter/app_adapter.h"
#include "ballistica/base/app_mode/app_mode.h"
#include "ballistica/base/assets/sound_asset.h"
#include "ballistica/base/assets/sound_asset.h" // IWYU pragma: keep.
#include "ballistica/base/input/input.h"
#include "ballistica/base/platform/base_platform.h"
#include "ballistica/base/python/base_python.h"
@ -62,7 +62,7 @@ static PyMethodDef PyGetSimpleSoundDef = {
static auto PySetUIInputDevice(PyObject* self, PyObject* args,
PyObject* keywds) -> PyObject* {
BA_PYTHON_TRY;
assert(g_base->InLogicThread());
BA_PRECONDITION(g_base->InLogicThread());
static const char* kwlist[] = {"input_device_id", nullptr};
PyObject* input_device_id_obj = Py_None;
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O",
@ -97,6 +97,89 @@ static PyMethodDef PySetUIInputDeviceDef = {
"Sets the input-device that currently owns the user interface.",
};
// ------------------------------ set_ui_scale ---------------------------------
static auto PySetUIScale(PyObject* self, PyObject* args,
PyObject* keywds) -> PyObject* {
BA_PYTHON_TRY;
BA_PRECONDITION(g_base->InLogicThread());
const char* scalestr;
static const char* kwlist[] = {"scale", nullptr};
PyObject* input_device_id_obj = Py_None;
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s",
const_cast<char**>(kwlist), &scalestr)) {
return nullptr;
}
// FIXME: Should have this take an enum directly once we have an easy way
// to share enums between Python/CPP.
UIScale scale;
if (!strcmp(scalestr, "small")) {
scale = UIScale::kSmall;
} else if (!strcmp(scalestr, "medium")) {
scale = UIScale::kMedium;
} else if (!strcmp(scalestr, "large")) {
scale = UIScale::kLarge;
} else {
throw Exception("Invalid scale value.", PyExcType::kValue);
}
g_base->SetUIScale(scale);
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PySetUIScaleDef = {
"set_ui_scale", // name
(PyCFunction)PySetUIScale, // method
METH_VARARGS | METH_KEYWORDS, // flags
"set_ui_scale(scale: str)"
" -> None\n"
"\n"
"(internal)\n",
};
// ------------------------------ set_ui_scale ---------------------------------
static auto PyGetUIScale(PyObject* self) -> PyObject* {
BA_PYTHON_TRY;
BA_PRECONDITION(g_base->InLogicThread());
// FIXME: Should have this return enums directly once we have an easy way
// to share enums between Python/CPP.
auto scale = g_base->ui->scale();
const char* val;
switch (scale) {
case UIScale::kSmall:
val = "small";
break;
case UIScale::kMedium:
val = "medium";
break;
case UIScale::kLarge:
val = "large";
break;
default:
throw Exception("Unhandled scale value.");
}
return PyUnicode_FromString(val);
BA_PYTHON_CATCH;
}
static PyMethodDef PyGetUIScaleDef = {
"get_ui_scale", // name
(PyCFunction)PyGetUIScale, // method
METH_NOARGS, // flags
"get_ui_scale()"
" -> str\n"
"\n"
"(internal)\n",
};
// ----------------------------- hastouchscreen --------------------------------
static auto PyHasTouchScreen(PyObject* self, PyObject* args,
@ -1899,10 +1982,6 @@ static auto PySetDrawUIBounds(PyObject* self, PyObject* args,
return nullptr;
}
// if (g_base->graphics->draw_ui_bounds()) {
// Py_RETURN_TRUE;
// }
// Py_RETURN_FALSE;
g_base->graphics->set_draw_ui_bounds(value);
Py_RETURN_NONE;
@ -1978,6 +2057,8 @@ auto PythonMoethodsBase3::GetMethods() -> std::vector<PyMethodDef> {
PyGetIdleTimeDef,
PyExtraHashValueDef,
PySetUIInputDeviceDef,
PyGetUIScaleDef,
PySetUIScaleDef,
PyGetThreadNameDef,
PySetThreadNameDef,
PyInLogicThreadDef,

View File

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

View File

@ -68,6 +68,8 @@ class DevConsole {
auto BaseScale() const -> float;
void RequestRefresh();
void OnUIScaleChanged();
private:
class ScopedUILock_;
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() {
assert(g_base->InLogicThread());

View File

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

View File

@ -2,6 +2,7 @@
#include "ballistica/scene_v1/node/explosion_node.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/object_component.h"
#include "ballistica/base/graphics/component/post_process_component.h"
#include "ballistica/base/graphics/support/camera.h"

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@
#include "ballistica/scene_v1/node/shield_node.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/object_component.h"
#include "ballistica/base/graphics/component/post_process_component.h"
#include "ballistica/base/graphics/component/shield_component.h"

View File

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

View File

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

View File

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

View File

@ -7,12 +7,13 @@
// This header pulls in the actual Python includes and also defines some handy
// macros and functions for working with Python objects.
// This is the ONE place we actually include Python.
// UPDATE (September 2024): We now include Python.h directly in some places;
// this causes less friction with include-what-you-use checks.
#include <Python.h>
#include <frameobject.h>
#include <weakrefobject.h>
#include <string>
#include <string> // IWYU pragma: keep. (macros below use this)
// Saving/restoring Python error state; useful when function PyObject_Str()
// or other functionality is needed during error reporting; by default it

View File

@ -2,11 +2,9 @@
#include "ballistica/ui_v1/python/methods/python_methods_ui_v1.h"
#include "ballistica/base/app_adapter/app_adapter.h"
#include "ballistica/base/app_mode/app_mode.h"
#include "ballistica/base/assets/sound_asset.h"
#include "ballistica/base/platform/base_platform.h"
#include "ballistica/base/assets/sound_asset.h" // IWYU pragma: keep.
#include "ballistica/base/python/base_python.h"
#include "ballistica/base/support/context.h"
#include "ballistica/shared/foundation/macros.h"
#include "ballistica/ui_v1/python/class/python_class_ui_mesh.h"
#include "ballistica/ui_v1/python/class/python_class_ui_sound.h"
@ -581,7 +579,7 @@ static auto PyCheckBoxWidget(PyObject* self, PyObject* args,
widget = Object::New<CheckBoxWidget>();
}
// set applicable values ----------------------------
// Set applicable values.
if (size_obj != Py_None) {
Point2D p = Python::GetPyPoint2D(size_obj);
widget->SetWidth(p.x);
@ -1022,7 +1020,7 @@ static auto PyColumnWidget(PyObject* self, PyObject* args,
widget->set_claims_tab(Python::GetPyBool(claims_tab_obj));
}
// if making a new widget add it at the end
// If making a new widget, add it at the end.
if (edit_obj == Py_None) {
g_ui_v1->AddWidget(widget.Get(), parent_widget);
}
@ -1628,7 +1626,7 @@ static auto PyScrollWidget(PyObject* self, PyObject* args,
widget = Object::New<ScrollWidget>();
}
// Set applicable values. ----------------------------
// Set applicable values.
if (size_obj != Py_None) {
Point2D p = Python::GetPyPoint2D(size_obj);
widget->SetWidth(p.x);
@ -2586,35 +2584,6 @@ static PyMethodDef PyRootUIBackPressDef = {
"(internal)",
};
// ------------------------ is_party_icon_visible ------------------------------
static auto PyIsPartyIconVisible(PyObject* self) -> PyObject* {
BA_PYTHON_TRY;
BA_PRECONDITION(g_base->InLogicThread());
bool party_button_active = (g_base->app_mode()->HasConnectionToClients()
|| g_base->app_mode()->HasConnectionToHost());
// bool party_button_active = (g_base->app_mode()->HasConnectionToClients()
// || g_base->app_mode()->HasConnectionToHost()
// ||
// g_ui_v1->root_ui()->always_draw_party_icon());
if (party_button_active) {
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
}
BA_PYTHON_CATCH;
}
static PyMethodDef PyIsPartyIconVisibleDef = {
"is_party_icon_visible", // name
(PyCFunction)PyIsPartyIconVisible, // method
METH_NOARGS, // flags
"is_party_icon_visible() -> bool\n"
"\n"
"(internal)",
};
// ----------------------------- is_available ----------------------------------
static auto PyIsAvailable(PyObject* self) -> PyObject* {
@ -2640,31 +2609,37 @@ static PyMethodDef PyIsAvailableDef = {
"(internal)",
};
// --------------------------- on_screen_change --------------------------------
static auto PyOnScreenChange(PyObject* self) -> PyObject* {
BA_PYTHON_TRY;
BA_PRECONDITION(g_base->InLogicThread());
g_ui_v1->OnScreenChange();
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PyOnScreenChangeDef = {
"on_screen_change", // name
(PyCFunction)PyOnScreenChange, // method
METH_NOARGS, // flags
"on_screen_change() -> None\n"
"\n"
"(internal)",
};
// -----------------------------------------------------------------------------
auto PythonMethodsUIV1::GetMethods() -> std::vector<PyMethodDef> {
return {
PyIsPartyIconVisibleDef,
PyRootUIBackPressDef,
PyGetSpecialWidgetDef,
PySetPartyWindowOpenDef,
PyButtonWidgetDef,
PyCheckBoxWidgetDef,
PyImageWidgetDef,
PyColumnWidgetDef,
PyContainerWidgetDef,
PyRowWidgetDef,
PyScrollWidgetDef,
PyHScrollWidgetDef,
PyTextWidgetDef,
PyWidgetDef,
PyUIBoundsDef,
PyGetSoundDef,
PyGetTextureDef,
PyGetQRCodeTextureDef,
PyGetMeshDef,
PyIsAvailableDef,
};
return {PyRootUIBackPressDef, PyGetSpecialWidgetDef, PySetPartyWindowOpenDef,
PyButtonWidgetDef, PyCheckBoxWidgetDef, PyImageWidgetDef,
PyColumnWidgetDef, PyContainerWidgetDef, PyRowWidgetDef,
PyScrollWidgetDef, PyHScrollWidgetDef, PyTextWidgetDef,
PyWidgetDef, PyUIBoundsDef, PyGetSoundDef,
PyGetTextureDef, PyGetQRCodeTextureDef, PyGetMeshDef,
PyIsAvailableDef, PyOnScreenChangeDef};
}
#pragma clang diagnostic pop

View File

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

View File

@ -2,7 +2,7 @@
#include "ballistica/ui_v1/ui_v1.h"
#include "ballistica/base/app_mode/app_mode.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/empty_component.h"
#include "ballistica/base/input/input.h"
#include "ballistica/base/support/app_config.h"
@ -214,12 +214,23 @@ void UIV1FeatureSet::AddWidget(Widget* w, ContainerWidget* parent) {
}
void UIV1FeatureSet::OnScreenSizeChange() {
// This gets called by the native layer as window is resized/etc.
if (root_widget_.Exists()) {
root_widget_->SetWidth(g_base->graphics->screen_virtual_width());
root_widget_->SetHeight(g_base->graphics->screen_virtual_height());
}
}
void UIV1FeatureSet::OnScreenChange() {
// This gets called by the Python layer when UIScale or window size
// changes.
assert(g_base->InLogicThread());
// We allow OnScreenSizeChange() to handle size changes but *do* handle
// UIScale changes here.
root_widget_->OnUIScaleChange();
}
void UIV1FeatureSet::OnLanguageChange() {
// Since switching languages is a bit costly, ignore redundant change
// notifications. These will tend to happen nowadays since change

View File

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

View File

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

View File

@ -2,6 +2,7 @@
#include "ballistica/ui_v1/widget/container_widget.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/audio/audio.h"
#include "ballistica/base/graphics/component/empty_component.h"
#include "ballistica/base/graphics/component/simple_component.h"
@ -349,8 +350,6 @@ auto ContainerWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
// Schedule this to run immediately after any current UI
// traversal.
call->ScheduleInUIOperation();
} else {
OnCancelCustom();
}
}
break;

View File

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

View File

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

View File

@ -2,7 +2,9 @@
#include "ballistica/ui_v1/widget/image_widget.h"
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/component/simple_component.h"
#include "ballistica/base/graphics/mesh/mesh_indexed_simple_full.h"
#include "ballistica/base/logic/logic.h"
namespace ballistica::ui_v1 {

View File

@ -6,6 +6,7 @@
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/graphics/renderer/render_pass.h"
#include "ballistica/base/graphics/support/frame_def.h"
#include "ballistica/base/support/context.h"
#include "ballistica/shared/foundation/inline.h"
#include "ballistica/ui_v1/python/ui_v1_python.h"
#include "ballistica/ui_v1/widget/button_widget.h"
@ -1574,6 +1575,8 @@ void RootWidget::UpdateLayout() {
StepPositions_(0.0f);
}
void RootWidget::OnUIScaleChange() { MarkForUpdate(); }
auto RootWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
// If a cancel message comes through and our back button is enabled, fire
// our back button. In all other cases just do the default.
@ -1607,20 +1610,6 @@ void RootWidget::SetOverlayWidget(StackWidget* w) {
overlay_stack_widget_ = w;
}
void RootWidget::OnCancelCustom() {
// Need to revisit this. If the cancel event it pushes is not handled, it will
// wind up back here where it pushes another back call. This cycle repeats
// forever until something comes along which does handle cancel events and
// then it gets them all. Current repro case is Sign-in-with-BombSquad-Account
// window - press escape a few times while that is up and then click cancel;
// This code is only used for toolbar mode so should be safe to leave it
// disabled for now.
// Is there a reason for this to exist? If so, what is it?
// printf("GOT OnCancelCustom\n");
// g_base->ui->PushBackButtonCall(nullptr);
}
auto RootWidget::GetSpecialWidget(const std::string& s) const -> Widget* {
if (s == "squad_button") {
return squad_button_ ? squad_button_->widget.Get() : nullptr;

View File

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

View File

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

View File

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