mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-05 23:13:46 +08:00
Merge branch 'efroemling:main' into main
This commit is contained in:
commit
a9efb4a0ca
56
.efrocachemap
generated
56
.efrocachemap
generated
@ -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": "d6246c930e7e2d2d9a6aff6788f33b69",
|
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "a0e1890fc3d156a1d480e7cbba7295bd",
|
||||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "001c67c4d4d33e20755399e0b2ed1593",
|
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "2ea3ddfd5280b5fa721a82286767208a",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "6f6bfaf19daf6e866f4fecbc889b8854",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "f9860dbec27801cf8b24c3b42e0b62bd",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ebc7449903d7868c631c504aed10f371",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "a53de05a4a3c3c2e766f488b0b53230d",
|
||||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "91f03e7dbfc0d7eb75568704f681fba5",
|
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "43485a1c27605267ee83d27961b61017",
|
||||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "0b32b6eb05df0a7e23e55ff2e7235a8f",
|
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "65fe6d346dfd844925a07278a73bbb39",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "4ed4b63cc506815f759412a295bfe088",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "bc277e964bc08d0bd086f836732901f8",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "1890731fb8a2fb43c4cde72af9d7a4e6",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "738e76cf0dc643a016f16f94503767db",
|
||||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "1a4764a504dcb20591ac3472c48db8d9",
|
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "949fd54340bc597c19ada580f59c30a9",
|
||||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "9bfd6234aac4ffd7d7601a40017a73be",
|
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "f0f1037044f841e6817e970ba67f3c02",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "941f8fb79d54522ca5df97a735c3babe",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "3990893e788968fe74e98aa419f28397",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "290a3d9840efc5e88532e13b76b3ae6b",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0c5fbd4cd45f944f02d7482e08d4b5d5",
|
||||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "621a6684b54b0a9101f808209bcca1ee",
|
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "c39bcf72ef41865429f3df1d3ad586d0",
|
||||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "43c8b0b29e5fb257e4cde0f7fce1c680",
|
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "37cb193fec5c61443fafa24d3ae96447",
|
||||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "9a30c6b88ffc11bdf6765780616d8ba1",
|
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "e454f30500a3ef2c0e4248388338db89",
|
||||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "8a8f63850fc296b060a994f4e001d74f",
|
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "ddb81916ad653ccb38be9ffc9f98e7f3",
|
||||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "2864e9ae1d2d566def85f1cdf6e863fe",
|
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "18766baaa9e1a23e785aceb9f6be0d3a",
|
||||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "dc0db7ca99661a896634fc05187a5c75",
|
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "b687f66795a831f0dfd7e15aa7a908b2",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "f56bb0fafe0a45cecdcd06a10a6924c9",
|
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "146168838c8e9cdbd5c016772b68e91a",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e3a58b09fea193d78187f97cf922717d",
|
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "f0ee92768afe3211aeab356539d58876",
|
||||||
"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,14 +4132,14 @@
|
|||||||
"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": "6b6aae30362b1e9aaf3f1a8daae0b0b4",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "07c51c6015b17d6ad2e32ac6bad9aaee",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "25db08ee2b4c79ca631e517b622c741d",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "d9dc89c65a1f5ae3a0a4e25636129bb7",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "2ea419644782c4c52d1fa784d0ced86d",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "8afac2e5edb1586137c60ce1d4829d0a",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "c40627a46ee127997153df041e47eda5",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "c9bfc854e52b6d2270d748ce80f45342",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "fff81b29e2d86031ec25c4a672a243e7",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "ec65affda58721c395d5188810195443",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "2a87e2f53c658d0be3918476cd8a04ee",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e16447cfaffecc545ae970aff2f09d16",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1e91536979b318b9a8325ab0e871ecec",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1f5ba81d75d56eb680bb7f3aefaae5b6",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "c6506399a93ef93e8322425f78e2e6b0",
|
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "44bc0d1aab93081db335ebd837f44632",
|
||||||
"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": "cb299985623bbcc86015cb103a424ae6",
|
||||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d",
|
"src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
### 1.7.37 (build 21977, api 9, 2024-08-30)
|
### 1.7.37 (build 21985, api 9, 2024-09-03)
|
||||||
- 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.
|
||||||
|
|||||||
@ -6,8 +6,8 @@ mypy==1.11.2
|
|||||||
pbxproj==4.2.1
|
pbxproj==4.2.1
|
||||||
pdoc==14.6.1
|
pdoc==14.6.1
|
||||||
pur==7.3.2
|
pur==7.3.2
|
||||||
pylint==3.2.6
|
pylint==3.2.7
|
||||||
pylsp-mypy==0.6.8
|
pylsp-mypy==0.6.9
|
||||||
pytest==8.3.2
|
pytest==8.3.2
|
||||||
python-daemon==3.0.1
|
python-daemon==3.0.1
|
||||||
python-lsp-black==2.0.0
|
python-lsp-black==2.0.0
|
||||||
|
|||||||
@ -112,10 +112,6 @@ class ClassicAppSubsystem(babase.AppSubsystem):
|
|||||||
self.invite_confirm_windows: list[Any] = [] # FIXME: Don't use Any.
|
self.invite_confirm_windows: list[Any] = [] # FIXME: Don't use Any.
|
||||||
self.party_window: weakref.ref[PartyWindow] | None = None
|
self.party_window: weakref.ref[PartyWindow] | None = None
|
||||||
self.main_menu_resume_callbacks: list = []
|
self.main_menu_resume_callbacks: list = []
|
||||||
# Switch our overall game selection UI flow between Play and
|
|
||||||
# Private-party playlist selection modes; should do this in
|
|
||||||
# a more elegant way once we revamp high level UI stuff a bit.
|
|
||||||
self.selecting_private_party_playlist: bool = False
|
|
||||||
|
|
||||||
# Store.
|
# Store.
|
||||||
self.store_layout: dict[str, list[dict[str, Any]]] | None = None
|
self.store_layout: dict[str, list[dict[str, Any]]] | None = None
|
||||||
|
|||||||
@ -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 = 21977
|
TARGET_BALLISTICA_BUILD = 21985
|
||||||
TARGET_BALLISTICA_VERSION = '1.7.37'
|
TARGET_BALLISTICA_VERSION = '1.7.37'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -64,43 +64,43 @@ class GameActivity(Activity[PlayerT, TeamT]):
|
|||||||
# (unless overridden by the map).
|
# (unless overridden by the map).
|
||||||
default_music: bascenev1.MusicType | None = None
|
default_music: bascenev1.MusicType | None = None
|
||||||
|
|
||||||
@classmethod
|
# @classmethod
|
||||||
def create_settings_ui(
|
# def create_settings_ui(
|
||||||
cls,
|
# cls,
|
||||||
sessiontype: type[bascenev1.Session],
|
# sessiontype: type[bascenev1.Session],
|
||||||
settings: dict | None,
|
# settings: dict | None,
|
||||||
completion_call: Callable[[dict | None], None],
|
# completion_call: Callable[[dict | None], None],
|
||||||
) -> None:
|
# ) -> None:
|
||||||
"""Launch an in-game UI to configure settings for a game type.
|
# """Launch an in-game UI to configure settings for a game type.
|
||||||
|
|
||||||
'sessiontype' should be the bascenev1.Session class the game will
|
# 'sessiontype' should be the bascenev1.Session class the game will
|
||||||
be used in.
|
# be used in.
|
||||||
|
|
||||||
'settings' should be an existing settings dict (implies 'edit'
|
# 'settings' should be an existing settings dict (implies 'edit'
|
||||||
ui mode) or None (implies 'add' ui mode).
|
# ui mode) or None (implies 'add' ui mode).
|
||||||
|
|
||||||
'completion_call' will be called with a filled-out settings dict on
|
# 'completion_call' will be called with a filled-out settings dict on
|
||||||
success or None on cancel.
|
# success or None on cancel.
|
||||||
|
|
||||||
Generally subclasses don't need to override this; if they override
|
# Generally subclasses don't need to override this; if they override
|
||||||
bascenev1.GameActivity.get_available_settings() and
|
# bascenev1.GameActivity.get_available_settings() and
|
||||||
bascenev1.GameActivity.get_supported_maps() they can just rely on
|
# bascenev1.GameActivity.get_supported_maps() they can just rely on
|
||||||
the default implementation here which calls those methods.
|
# the default implementation here which calls those methods.
|
||||||
"""
|
# """
|
||||||
# pylint: disable=cyclic-import
|
# # pylint: disable=cyclic-import
|
||||||
from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
# from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
||||||
|
|
||||||
assert babase.app.classic is not None
|
# assert babase.app.classic is not None
|
||||||
babase.app.ui_v1.clear_main_window()
|
# babase.app.ui_v1.clear_main_window()
|
||||||
babase.app.ui_v1.set_main_window(
|
# babase.app.ui_v1.set_main_window(
|
||||||
PlaylistEditGameWindow(
|
# PlaylistEditGameWindow(
|
||||||
cls,
|
# cls,
|
||||||
sessiontype,
|
# sessiontype,
|
||||||
settings,
|
# settings,
|
||||||
completion_call=completion_call,
|
# completion_call=completion_call,
|
||||||
),
|
# ),
|
||||||
from_window=False, # Disable check since we don't know.
|
# from_window=False, # Disable check since we don't know.
|
||||||
)
|
# )
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getscoreconfig(cls) -> bascenev1.ScoreConfig:
|
def getscoreconfig(cls) -> bascenev1.ScoreConfig:
|
||||||
|
|||||||
@ -68,7 +68,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
|||||||
# another MainWindow and we complain if they don't.
|
# another MainWindow and we complain if they don't.
|
||||||
self._main_window = empty_weakref(MainWindow)
|
self._main_window = empty_weakref(MainWindow)
|
||||||
self._main_window_widget: bauiv1.Widget | None = None
|
self._main_window_widget: bauiv1.Widget | None = None
|
||||||
self.main_window_group_id: str | None = None
|
|
||||||
|
|
||||||
self.quit_window: bauiv1.Widget | None = None
|
self.quit_window: bauiv1.Widget | None = None
|
||||||
|
|
||||||
@ -123,7 +122,6 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
|||||||
self.root_ui_calls.clear()
|
self.root_ui_calls.clear()
|
||||||
self._main_window = empty_weakref(MainWindow)
|
self._main_window = empty_weakref(MainWindow)
|
||||||
self._main_window_widget = None
|
self._main_window_widget = None
|
||||||
self.main_window_group_id = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def uiscale(self) -> babase.UIScale:
|
def uiscale(self) -> babase.UIScale:
|
||||||
@ -164,7 +162,7 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
|||||||
# FIXME: Can probably kill this if we do immediate UI death checks.
|
# FIXME: Can probably kill this if we do immediate UI death checks.
|
||||||
self.upkeeptimer = babase.AppTimer(2.6543, ui_upkeep, repeat=True)
|
self.upkeeptimer = babase.AppTimer(2.6543, ui_upkeep, repeat=True)
|
||||||
|
|
||||||
def do_main_window_back(self, window: MainWindow) -> None:
|
def do_main_window_back(self, from_window: MainWindow) -> None:
|
||||||
"""Sets the main menu window automatically from a parent WindowState."""
|
"""Sets the main menu window automatically from a parent WindowState."""
|
||||||
|
|
||||||
main_window = self._main_window()
|
main_window = self._main_window()
|
||||||
@ -178,7 +176,7 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
|||||||
)
|
)
|
||||||
backwin = back_state.create_window(transition='in_left')
|
backwin = back_state.create_window(transition='in_left')
|
||||||
backwin.main_window_back_state = back_state.parent
|
backwin.main_window_back_state = back_state.parent
|
||||||
self.set_main_window(backwin, from_window=window, is_back=True)
|
self.set_main_window(backwin, from_window=from_window, is_back=True)
|
||||||
|
|
||||||
def get_main_window(self) -> bauiv1.MainWindow | None:
|
def get_main_window(self) -> bauiv1.MainWindow | None:
|
||||||
"""Return main window, if any."""
|
"""Return main window, if any."""
|
||||||
@ -189,30 +187,14 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
|||||||
window: bauiv1.MainWindow,
|
window: bauiv1.MainWindow,
|
||||||
from_window: bauiv1.MainWindow | None | bool = True,
|
from_window: bauiv1.MainWindow | None | bool = True,
|
||||||
is_back: bool = False,
|
is_back: bool = False,
|
||||||
group_id: str | None = None,
|
|
||||||
is_top_level: bool = False,
|
is_top_level: bool = False,
|
||||||
back_state: MainWindowState | None = None,
|
back_state: MainWindowState | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set the current 'main' window, replacing any existing.
|
"""Set the current 'main' window, replacing any existing.
|
||||||
|
|
||||||
If 'from_window' is passed as a bauiv1.Widget or bauiv1.Window
|
Generally this should not be called directly; The high level
|
||||||
or None, a warning will be issued if it that value does not
|
MainWindow methods main_window_replace() and main_window_back()
|
||||||
match the current main window. This can help identify flawed
|
should be used when possible for navigation.
|
||||||
code that can lead to bad UI states. A value of False will
|
|
||||||
disable the check, which is necessary in some cases when the
|
|
||||||
current main window is not known.
|
|
||||||
|
|
||||||
When navigating somewhere from a cancel or back-button, pass
|
|
||||||
is_back=True; this will prevent the new main window from itself
|
|
||||||
being registered as a new location on the stack that can be
|
|
||||||
returned to.
|
|
||||||
|
|
||||||
If a 'group_id' string is provided and the window being replaced
|
|
||||||
has the same group-id, the WindowState stack is left unchanged,
|
|
||||||
effectively replacing the previous window with the new one in
|
|
||||||
the stack. This can be useful in cases where tab-bar-like UIs
|
|
||||||
allow flipping between sibling windows with the back button
|
|
||||||
always leading to a shared parent.
|
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
@ -222,13 +204,24 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
|||||||
from_window_widget: bauiv1.Widget | None
|
from_window_widget: bauiv1.Widget | None
|
||||||
|
|
||||||
# We used to accept Widgets but now want MainWindows.
|
# We used to accept Widgets but now want MainWindows.
|
||||||
assert isinstance(window, MainWindow)
|
if not isinstance(window, MainWindow):
|
||||||
|
raise RuntimeError(
|
||||||
|
f'set_main_window() now takes a MainWindow as its "window" arg.'
|
||||||
|
f' You passed a {type(window)}.',
|
||||||
|
)
|
||||||
window_weakref = weakref.ref(window)
|
window_weakref = weakref.ref(window)
|
||||||
window_widget = window.get_root_widget()
|
window_widget = window.get_root_widget()
|
||||||
|
|
||||||
if isinstance(from_window, MainWindow):
|
if isinstance(from_window, MainWindow):
|
||||||
from_window_widget = from_window.get_root_widget()
|
from_window_widget = from_window.get_root_widget()
|
||||||
else:
|
else:
|
||||||
|
if from_window is not None and not isinstance(from_window, bool):
|
||||||
|
raise RuntimeError(
|
||||||
|
f'set_main_window() now takes a MainWindow or bool or None'
|
||||||
|
f'as its "from_window" arg.'
|
||||||
|
f' You passed a {type(from_window)}.',
|
||||||
|
)
|
||||||
|
|
||||||
from_window_widget = None
|
from_window_widget = None
|
||||||
|
|
||||||
existing = self._main_window_widget
|
existing = self._main_window_widget
|
||||||
@ -317,13 +310,15 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
|||||||
else:
|
else:
|
||||||
# When navigating forward, generate a back-window-state from
|
# When navigating forward, generate a back-window-state from
|
||||||
# the outgoing window.
|
# the outgoing window.
|
||||||
|
if is_top_level:
|
||||||
# Exception is when we were passed a group and it matches
|
# Top level windows don't have or expect anywhere to
|
||||||
# the existing group; in that case we just keep the existing
|
# go back to.
|
||||||
# back-state.
|
#
|
||||||
if group_id is not None and group_id == self.main_window_group_id:
|
# self._main_window_back_state = None
|
||||||
assert not is_top_level
|
window.main_window_back_state = None
|
||||||
print(f'GOT GROUP ID MATCH {group_id}; KEEPING BACK STATE.')
|
elif back_state is not None:
|
||||||
|
window.main_window_back_state = back_state
|
||||||
|
else:
|
||||||
oldwin = self._main_window()
|
oldwin = self._main_window()
|
||||||
if oldwin is None:
|
if oldwin is None:
|
||||||
# We currenty only hold weak refs to windows so
|
# We currenty only hold weak refs to windows so
|
||||||
@ -332,60 +327,32 @@ class UIV1AppSubsystem(babase.AppSubsystem):
|
|||||||
# alive as long as its the main one. Holler if
|
# alive as long as its the main one. Holler if
|
||||||
# that seems to not be happening.
|
# that seems to not be happening.
|
||||||
logging.warning(
|
logging.warning(
|
||||||
'set_main_window: no existing MainWindow found'
|
'set_main_window: No old MainWindow found'
|
||||||
' (and is_top_level is False); should not happen.'
|
' and is_top_level is False;'
|
||||||
' a MainWindow should keep itself alive as long'
|
' this should not happen.'
|
||||||
' as it is main.'
|
|
||||||
)
|
)
|
||||||
window.main_window_back_state = None
|
window.main_window_back_state = None
|
||||||
else:
|
else:
|
||||||
window.main_window_back_state = (
|
oldwinstate = oldwin.get_main_window_state()
|
||||||
oldwin.main_window_back_state
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
if is_top_level:
|
|
||||||
# Top level windows don't have or expect anywhere to go
|
|
||||||
# back to.
|
|
||||||
# self._main_window_back_state = None
|
|
||||||
window.main_window_back_state = None
|
|
||||||
elif back_state is not None:
|
|
||||||
window.main_window_back_state = back_state
|
|
||||||
else:
|
|
||||||
oldwin = self._main_window()
|
|
||||||
if oldwin is None:
|
|
||||||
# We currenty only hold weak refs to windows so
|
|
||||||
# that they are free to die on their own, but we
|
|
||||||
# expect the main menu window to keep itself
|
|
||||||
# alive as long as its the main one. Holler if
|
|
||||||
# that seems to not be happening.
|
|
||||||
logging.warning(
|
|
||||||
'set_main_window: No old MainWindow found'
|
|
||||||
' and is_top_level is False;'
|
|
||||||
' this should not happen.'
|
|
||||||
)
|
|
||||||
window.main_window_back_state = None
|
|
||||||
else:
|
|
||||||
oldwinstate = oldwin.get_main_window_state()
|
|
||||||
|
|
||||||
# Store our previous back state on this new one.
|
# Store our previous back state on this new one.
|
||||||
oldwinstate.parent = oldwin.main_window_back_state
|
oldwinstate.parent = oldwin.main_window_back_state
|
||||||
window.main_window_back_state = oldwinstate
|
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
|
||||||
self.main_window_group_id = group_id
|
|
||||||
|
|
||||||
def has_main_window(self) -> bool:
|
def has_main_window(self) -> bool:
|
||||||
"""Return whether a main menu window is present."""
|
"""Return whether a main menu window is present."""
|
||||||
return bool(self._main_window_widget)
|
return bool(self._main_window_widget)
|
||||||
|
|
||||||
def clear_main_window(self) -> None:
|
def clear_main_window(self, transition: str | None = None) -> None:
|
||||||
"""Clear any existing main window."""
|
"""Clear any existing main window."""
|
||||||
from bauiv1._uitypes import MainWindow
|
from bauiv1._uitypes import MainWindow
|
||||||
|
|
||||||
main_window = self._main_window()
|
main_window = self._main_window()
|
||||||
if main_window:
|
if main_window:
|
||||||
main_window.main_window_close()
|
main_window.main_window_close(transition=transition)
|
||||||
else:
|
else:
|
||||||
# Fallback; if we have a widget but no window, nuke the widget.
|
# Fallback; if we have a widget but no window, nuke the widget.
|
||||||
if self._main_window_widget:
|
if self._main_window_widget:
|
||||||
@ -397,4 +364,3 @@ 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
|
||||||
self.main_window_group_id = None
|
|
||||||
|
|||||||
@ -60,7 +60,6 @@ class MainWindow(Window):
|
|||||||
Automatically handles in and out transitions on the provided widget,
|
Automatically handles in and out transitions on the provided widget,
|
||||||
so there is no need to set transitions when creating it.
|
so there is no need to set transitions when creating it.
|
||||||
"""
|
"""
|
||||||
# TODO - move to MainWindow
|
|
||||||
# A back-state supplied by the ui system.
|
# A back-state supplied by the ui system.
|
||||||
self.main_window_back_state: MainWindowState | None = None
|
self.main_window_back_state: MainWindowState | None = None
|
||||||
|
|
||||||
@ -82,7 +81,7 @@ class MainWindow(Window):
|
|||||||
scale_origin_stack_offset=scale_origin,
|
scale_origin_stack_offset=scale_origin,
|
||||||
)
|
)
|
||||||
|
|
||||||
def main_window_close(self) -> None:
|
def main_window_close(self, transition: str | None = None) -> None:
|
||||||
"""Get window transitioning out if still alive."""
|
"""Get window transitioning out if still alive."""
|
||||||
|
|
||||||
# no-op if our underlying widget is dead or on its way out.
|
# no-op if our underlying widget is dead or on its way out.
|
||||||
@ -96,16 +95,21 @@ class MainWindow(Window):
|
|||||||
logging.exception('Error in on_main_window_close() for %s.', self)
|
logging.exception('Error in on_main_window_close() for %s.', self)
|
||||||
|
|
||||||
_bauiv1.containerwidget(
|
_bauiv1.containerwidget(
|
||||||
edit=self._root_widget, transition=self._main_window_transition_out
|
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?
|
||||||
|
|
||||||
It is a good idea to make sure this is True before calling
|
It is a good idea to make sure this is True before calling
|
||||||
either main_window_back() or main_window_replace(). This
|
main_window_replace(). This prevents fluke UI breakage such as
|
||||||
prevents fluke UI breakage such as multiple simultaneous events
|
multiple simultaneous events causing a MainWindow to spawn
|
||||||
causing a MainWindow to spawn multiple replacements for itself.
|
multiple replacements for itself.
|
||||||
"""
|
"""
|
||||||
# We are allowed to change main windows if we are the current one
|
# We are allowed to change main windows if we are the current one
|
||||||
# AND our underlying widget is still alive and not transitioning out.
|
# AND our underlying widget is still alive and not transitioning out.
|
||||||
@ -116,16 +120,16 @@ class MainWindow(Window):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def main_window_back(self) -> None:
|
def main_window_back(self) -> None:
|
||||||
"""Move back in the main window stack."""
|
"""Move back in the main window stack.
|
||||||
|
|
||||||
|
Is a no-op if the main window does not have control;
|
||||||
|
no need to check main_window_has_control() first.
|
||||||
|
"""
|
||||||
|
|
||||||
# Users should always check main_window_has_control() before
|
# Users should always check main_window_has_control() before
|
||||||
# calling us. Error if it seems they did not.
|
# calling us. Error if it seems they did not.
|
||||||
if not self.main_window_has_control():
|
if not self.main_window_has_control():
|
||||||
raise RuntimeError(
|
return
|
||||||
'main_window_back() should only be called'
|
|
||||||
' if main_window_has_control() returns True'
|
|
||||||
' (it currently is False).'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get the 'back' window coming in.
|
# Get the 'back' window coming in.
|
||||||
babase.app.ui_v1.do_main_window_back(self)
|
babase.app.ui_v1.do_main_window_back(self)
|
||||||
@ -133,31 +137,24 @@ class MainWindow(Window):
|
|||||||
self.main_window_close()
|
self.main_window_close()
|
||||||
|
|
||||||
def main_window_replace(
|
def main_window_replace(
|
||||||
self, new_window: MainWindow, group_id: str | None = None
|
self, new_window: MainWindow, back_state: MainWindowState | None = None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Replace ourself with a new MainWindow."""
|
"""Replace ourself with a new MainWindow."""
|
||||||
|
|
||||||
# Users should always check main_window_has_control() before
|
# Users should always check main_window_has_control() *before*
|
||||||
# creating new MainWindows and passing them in here. Error if it
|
# creating new MainWindows and passing them in here. Kill the
|
||||||
# seems they did not.
|
# passed window and Error if it seems they did not.
|
||||||
if not self.main_window_has_control():
|
if not self.main_window_has_control():
|
||||||
|
new_window.get_root_widget().delete()
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
'main_window_replace() should only be called'
|
f'main_window_replace() called on a not-in-control window'
|
||||||
' if main_window_has_control() returns True'
|
f' ({self}); always check main_window_has_control() before'
|
||||||
' (it currently is False).'
|
f' calling main_window_replace().'
|
||||||
)
|
)
|
||||||
|
|
||||||
# If we're navigating within a group, we want it to look like we're
|
# Just shove the old out the left to give the feel that we're
|
||||||
# backing out of the old one and going into the new one.
|
# adding to the nav stack.
|
||||||
if (
|
transition = 'out_left'
|
||||||
group_id is not None
|
|
||||||
and babase.app.ui_v1.main_window_group_id == group_id
|
|
||||||
):
|
|
||||||
transition = self._main_window_transition_out
|
|
||||||
else:
|
|
||||||
# Otherwise just shove the old out the left to give the feel
|
|
||||||
# that we're adding to the nav stack.
|
|
||||||
transition = 'out_left'
|
|
||||||
|
|
||||||
# Transition ourself out.
|
# Transition ourself out.
|
||||||
try:
|
try:
|
||||||
@ -167,7 +164,7 @@ class MainWindow(Window):
|
|||||||
|
|
||||||
_bauiv1.containerwidget(edit=self._root_widget, transition=transition)
|
_bauiv1.containerwidget(edit=self._root_widget, transition=transition)
|
||||||
babase.app.ui_v1.set_main_window(
|
babase.app.ui_v1.set_main_window(
|
||||||
new_window, from_window=self, group_id=group_id
|
new_window, from_window=self, back_state=back_state
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_main_window_close(self) -> None:
|
def on_main_window_close(self) -> None:
|
||||||
|
|||||||
@ -181,7 +181,8 @@ class CharacterPicker(PopupWindow):
|
|||||||
|
|
||||||
def _on_store_press(self) -> None:
|
def _on_store_press(self) -> None:
|
||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
from bauiv1lib.store.browser import StoreBrowserWindow
|
|
||||||
|
# from bauiv1lib.store.browser import StoreBrowserWindow
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
@ -189,12 +190,16 @@ class CharacterPicker(PopupWindow):
|
|||||||
if plus.get_v1_account_state() != 'signed_in':
|
if plus.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
return
|
return
|
||||||
self._transition_out()
|
|
||||||
StoreBrowserWindow(
|
bui.screenmessage('UNDER CONSTRUCTION')
|
||||||
modal=True,
|
return
|
||||||
show_tab=StoreBrowserWindow.TabID.CHARACTERS,
|
|
||||||
origin_widget=self._get_more_characters_button,
|
# self._transition_out()
|
||||||
)
|
# StoreBrowserWindow(
|
||||||
|
# modal=True,
|
||||||
|
# show_tab=StoreBrowserWindow.TabID.CHARACTERS,
|
||||||
|
# origin_widget=self._get_more_characters_button,
|
||||||
|
# )
|
||||||
|
|
||||||
def _select_character(self, character: str) -> None:
|
def _select_character(self, character: str) -> None:
|
||||||
if self._delegate is not None:
|
if self._delegate is not None:
|
||||||
|
|||||||
@ -7,11 +7,14 @@ from __future__ import annotations
|
|||||||
import weakref
|
import weakref
|
||||||
import logging
|
import logging
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import override
|
from typing import override, TYPE_CHECKING
|
||||||
|
|
||||||
from bauiv1lib.tabs import TabRow
|
from bauiv1lib.tabs import TabRow
|
||||||
import bauiv1 as bui
|
import bauiv1 as bui
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from bauiv1lib.play import PlaylistSelectContext
|
||||||
|
|
||||||
|
|
||||||
class GatherTab:
|
class GatherTab:
|
||||||
"""Defines a tab for use in the gather UI."""
|
"""Defines a tab for use in the gather UI."""
|
||||||
@ -264,23 +267,27 @@ class GatherWindow(bui.MainWindow):
|
|||||||
def on_main_window_close(self) -> None:
|
def on_main_window_close(self) -> None:
|
||||||
self._save_state()
|
self._save_state()
|
||||||
|
|
||||||
def playlist_select(self, origin_widget: bui.Widget) -> None:
|
def playlist_select(
|
||||||
|
self,
|
||||||
|
origin_widget: bui.Widget,
|
||||||
|
context: PlaylistSelectContext,
|
||||||
|
) -> None:
|
||||||
"""Called by the private-hosting tab to select a playlist."""
|
"""Called by the private-hosting tab to select a playlist."""
|
||||||
from bauiv1lib.play import PlayWindow
|
from bauiv1lib.play import PlayWindow
|
||||||
|
|
||||||
classic = bui.app.classic
|
# Avoid redundant window spawns.
|
||||||
assert classic is not None
|
if not self.main_window_has_control():
|
||||||
|
|
||||||
# no-op if our underlying widget is dead or on its way out.
|
|
||||||
if not self._root_widget or self._root_widget.transitioning_out:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self._save_state()
|
playwindow = PlayWindow(
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
origin_widget=origin_widget, playlist_select_context=context
|
||||||
classic.selecting_private_party_playlist = True
|
|
||||||
bui.app.ui_v1.set_main_window(
|
|
||||||
PlayWindow(origin_widget=origin_widget), from_window=self
|
|
||||||
)
|
)
|
||||||
|
self.main_window_replace(playwindow)
|
||||||
|
|
||||||
|
# Grab the newly-set main-window's back-state; that will lead us
|
||||||
|
# back here once we're done going down our main-window
|
||||||
|
# rabbit-hole for playlist selection.
|
||||||
|
context.back_state = playwindow.main_window_back_state
|
||||||
|
|
||||||
def _set_tab(self, tab_id: TabID) -> None:
|
def _set_tab(self, tab_id: TabID) -> None:
|
||||||
if self._current_tab is tab_id:
|
if self._current_tab is tab_id:
|
||||||
|
|||||||
@ -22,6 +22,7 @@ from bacommon.net import (
|
|||||||
PrivatePartyConnectResult,
|
PrivatePartyConnectResult,
|
||||||
)
|
)
|
||||||
from bauiv1lib.gather import GatherTab
|
from bauiv1lib.gather import GatherTab
|
||||||
|
from bauiv1lib.play import PlaylistSelectContext
|
||||||
|
|
||||||
from bauiv1lib.gettokens import GetTokensWindow, show_get_tokens_prompt
|
from bauiv1lib.gettokens import GetTokensWindow, show_get_tokens_prompt
|
||||||
import bascenev1 as bs
|
import bascenev1 as bs
|
||||||
@ -49,6 +50,7 @@ class State:
|
|||||||
"""Our core state that persists while the app is running."""
|
"""Our core state that persists while the app is running."""
|
||||||
|
|
||||||
sub_tab: SubTabType = SubTabType.JOIN
|
sub_tab: SubTabType = SubTabType.JOIN
|
||||||
|
playlist_select_context: PlaylistSelectContext | None = None
|
||||||
|
|
||||||
|
|
||||||
class PrivateGatherTab(GatherTab):
|
class PrivateGatherTab(GatherTab):
|
||||||
@ -685,12 +687,13 @@ class PrivateGatherTab(GatherTab):
|
|||||||
|
|
||||||
# If it appears we're coming back from playlist selection,
|
# If it appears we're coming back from playlist selection,
|
||||||
# re-select our playlist button.
|
# re-select our playlist button.
|
||||||
if classic.selecting_private_party_playlist:
|
if self._state.playlist_select_context is not None:
|
||||||
|
self._state.playlist_select_context = None
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._container,
|
edit=self._container,
|
||||||
selected_child=self._host_playlist_button,
|
selected_child=self._host_playlist_button,
|
||||||
)
|
)
|
||||||
classic.selecting_private_party_playlist = False
|
|
||||||
else:
|
else:
|
||||||
# We've got a current party; show its info.
|
# We've got a current party; show its info.
|
||||||
bui.textwidget(
|
bui.textwidget(
|
||||||
@ -918,11 +921,14 @@ class PrivateGatherTab(GatherTab):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _playlist_press(self) -> None:
|
def _playlist_press(self) -> None:
|
||||||
if bool(True):
|
|
||||||
bui.screenmessage('UNDER CONSTRUCTION')
|
|
||||||
return
|
|
||||||
assert self._host_playlist_button is not None
|
assert self._host_playlist_button is not None
|
||||||
self.window.playlist_select(origin_widget=self._host_playlist_button)
|
|
||||||
|
self._state.playlist_select_context = PlaylistSelectContext()
|
||||||
|
|
||||||
|
self.window.playlist_select(
|
||||||
|
origin_widget=self._host_playlist_button,
|
||||||
|
context=self._state.playlist_select_context,
|
||||||
|
)
|
||||||
|
|
||||||
def _host_copy_press(self) -> None:
|
def _host_copy_press(self) -> None:
|
||||||
assert self._hostingstate.party_code is not None
|
assert self._hostingstate.party_code is not None
|
||||||
|
|||||||
@ -159,7 +159,8 @@ class IconPicker(PopupWindow):
|
|||||||
|
|
||||||
def _on_store_press(self) -> None:
|
def _on_store_press(self) -> None:
|
||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
from bauiv1lib.store.browser import StoreBrowserWindow
|
|
||||||
|
# from bauiv1lib.store.browser import StoreBrowserWindow
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
@ -167,12 +168,16 @@ class IconPicker(PopupWindow):
|
|||||||
if plus.get_v1_account_state() != 'signed_in':
|
if plus.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
return
|
return
|
||||||
self._transition_out()
|
# self._transition_out()
|
||||||
StoreBrowserWindow(
|
|
||||||
modal=True,
|
bui.screenmessage('UNDER CONSTRUCTION')
|
||||||
show_tab=StoreBrowserWindow.TabID.ICONS,
|
return
|
||||||
origin_widget=self._get_more_icons_button,
|
|
||||||
)
|
# StoreBrowserWindow(
|
||||||
|
# modal=True,
|
||||||
|
# show_tab=StoreBrowserWindow.TabID.ICONS,
|
||||||
|
# origin_widget=self._get_more_icons_button,
|
||||||
|
# )
|
||||||
|
|
||||||
def _select_icon(self, icon: str) -> None:
|
def _select_icon(self, icon: str) -> None:
|
||||||
if self._delegate is not None:
|
if self._delegate is not None:
|
||||||
|
|||||||
@ -505,7 +505,6 @@ class MainMenuWindow(bui.MainWindow):
|
|||||||
|
|
||||||
self.main_window_replace(
|
self.main_window_replace(
|
||||||
CreditsWindow(origin_widget=self._credits_button),
|
CreditsWindow(origin_widget=self._credits_button),
|
||||||
# group_id='mainmenutop',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def _howtoplay(self) -> None:
|
def _howtoplay(self) -> None:
|
||||||
@ -607,8 +606,4 @@ class MainMenuWindow(bui.MainWindow):
|
|||||||
if not self.main_window_has_control():
|
if not self.main_window_has_control():
|
||||||
return
|
return
|
||||||
|
|
||||||
classic = bui.app.classic
|
|
||||||
if classic is not None:
|
|
||||||
classic.selecting_private_party_playlist = False
|
|
||||||
|
|
||||||
self.main_window_replace(PlayWindow(origin_widget=self._play_button))
|
self.main_window_replace(PlayWindow(origin_widget=self._play_button))
|
||||||
|
|||||||
@ -5,11 +5,20 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import override
|
from typing import override, TYPE_CHECKING
|
||||||
|
|
||||||
import bascenev1 as bs
|
import bascenev1 as bs
|
||||||
import bauiv1 as bui
|
import bauiv1 as bui
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from bauiv1 import MainWindowState
|
||||||
|
|
||||||
|
|
||||||
|
class PlaylistSelectContext:
|
||||||
|
"""For using PlayWindow to select a playlist instead of running game."""
|
||||||
|
|
||||||
|
back_state: MainWindowState | None = None
|
||||||
|
|
||||||
|
|
||||||
class PlayWindow(bui.MainWindow):
|
class PlayWindow(bui.MainWindow):
|
||||||
"""Window for selecting overall play type."""
|
"""Window for selecting overall play type."""
|
||||||
@ -18,6 +27,7 @@ class PlayWindow(bui.MainWindow):
|
|||||||
self,
|
self,
|
||||||
transition: str | None = 'in_right',
|
transition: str | None = 'in_right',
|
||||||
origin_widget: bui.Widget | None = None,
|
origin_widget: bui.Widget | None = None,
|
||||||
|
playlist_select_context: PlaylistSelectContext | None = None,
|
||||||
):
|
):
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
@ -29,11 +39,7 @@ class PlayWindow(bui.MainWindow):
|
|||||||
classic = bui.app.classic
|
classic = bui.app.classic
|
||||||
assert classic is not None
|
assert classic is not None
|
||||||
|
|
||||||
# We can currently be used either for main window duty or
|
self._playlist_select_context = playlist_select_context
|
||||||
# modally for selecting playlists. Ideally we should clean
|
|
||||||
# things up and make playlist selection go through the
|
|
||||||
# main-window mechanism.
|
|
||||||
self._is_main_menu = not classic.selecting_private_party_playlist
|
|
||||||
|
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
width = 1100 if uiscale is bui.UIScale.SMALL else 800
|
width = 1100 if uiscale is bui.UIScale.SMALL else 800
|
||||||
@ -54,7 +60,11 @@ class PlayWindow(bui.MainWindow):
|
|||||||
super().__init__(
|
super().__init__(
|
||||||
root_widget=bui.containerwidget(
|
root_widget=bui.containerwidget(
|
||||||
size=(width, height),
|
size=(width, height),
|
||||||
toolbar_visibility='menu_full',
|
toolbar_visibility=(
|
||||||
|
'menu_full'
|
||||||
|
if playlist_select_context is None
|
||||||
|
else 'menu_minimal'
|
||||||
|
),
|
||||||
scale=(
|
scale=(
|
||||||
1.35
|
1.35
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
@ -88,7 +98,7 @@ class PlayWindow(bui.MainWindow):
|
|||||||
text=bui.Lstr(
|
text=bui.Lstr(
|
||||||
resource=(
|
resource=(
|
||||||
(f'{self._r}.titleText')
|
(f'{self._r}.titleText')
|
||||||
if self._is_main_menu
|
if self._playlist_select_context is None
|
||||||
else 'playlistsText'
|
else 'playlistsText'
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -109,13 +119,17 @@ class PlayWindow(bui.MainWindow):
|
|||||||
if uiscale is bui.UIScale.SMALL:
|
if uiscale is bui.UIScale.SMALL:
|
||||||
bui.textwidget(edit=txt, text='')
|
bui.textwidget(edit=txt, text='')
|
||||||
|
|
||||||
v = height - (110 if self._is_main_menu else 90)
|
v = height - (110 if self._playlist_select_context is None else 90)
|
||||||
v -= 100
|
v -= 100
|
||||||
clr = (0.6, 0.7, 0.6, 1.0)
|
clr = (0.6, 0.7, 0.6, 1.0)
|
||||||
v -= 280 if self._is_main_menu else 180
|
v -= 280 if self._playlist_select_context is None else 180
|
||||||
v += 30 if uiscale is bui.UIScale.SMALL else 0
|
v += 30 if uiscale is bui.UIScale.SMALL else 0
|
||||||
hoffs = x_offs + 80 if self._is_main_menu else x_offs - 100
|
hoffs = (
|
||||||
scl = 1.13 if self._is_main_menu else 0.68
|
x_offs + 80
|
||||||
|
if self._playlist_select_context is None
|
||||||
|
else x_offs - 100
|
||||||
|
)
|
||||||
|
scl = 1.13 if self._playlist_select_context is None else 0.68
|
||||||
|
|
||||||
self._lineup_tex = bui.gettexture('playerLineup')
|
self._lineup_tex = bui.gettexture('playerLineup')
|
||||||
angry_computer_transparent_mesh = bui.getmesh(
|
angry_computer_transparent_mesh = bui.getmesh(
|
||||||
@ -137,8 +151,8 @@ class PlayWindow(bui.MainWindow):
|
|||||||
|
|
||||||
self._coop_button: bui.Widget | None = None
|
self._coop_button: bui.Widget | None = None
|
||||||
|
|
||||||
# Only show coop button in main-menu variant.
|
# Only show coop button in regular variant.
|
||||||
if self._is_main_menu:
|
if self._playlist_select_context is None:
|
||||||
self._coop_button = btn = bui.buttonwidget(
|
self._coop_button = btn = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(hoffs, v + (scl * 15)),
|
position=(hoffs, v + (scl * 15)),
|
||||||
@ -238,16 +252,19 @@ class PlayWindow(bui.MainWindow):
|
|||||||
color=clr,
|
color=clr,
|
||||||
)
|
)
|
||||||
|
|
||||||
scl = 0.5 if self._is_main_menu else 0.68
|
scl = 0.5 if self._playlist_select_context is None else 0.68
|
||||||
hoffs += 440 if self._is_main_menu else 216
|
hoffs += 440 if self._playlist_select_context is None else 216
|
||||||
v += 180 if self._is_main_menu else -68
|
v += 180 if self._playlist_select_context is None else -68
|
||||||
|
|
||||||
self._teams_button = btn = bui.buttonwidget(
|
self._teams_button = btn = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(hoffs, v + (scl * 15 if self._is_main_menu else 0)),
|
position=(
|
||||||
|
hoffs,
|
||||||
|
v + (scl * 15 if self._playlist_select_context is None else 0),
|
||||||
|
),
|
||||||
size=(
|
size=(
|
||||||
scl * button_width,
|
scl * button_width,
|
||||||
scl * (300 if self._is_main_menu else 360),
|
scl * (300 if self._playlist_select_context is None else 360),
|
||||||
),
|
),
|
||||||
extra_touch_border_scale=0.1,
|
extra_touch_border_scale=0.1,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
@ -369,14 +386,17 @@ class PlayWindow(bui.MainWindow):
|
|||||||
color=clr,
|
color=clr,
|
||||||
)
|
)
|
||||||
|
|
||||||
hoffs += 0 if self._is_main_menu else 300
|
hoffs += 0 if self._playlist_select_context is None else 300
|
||||||
v -= 155 if self._is_main_menu else 0
|
v -= 155 if self._playlist_select_context is None else 0
|
||||||
self._free_for_all_button = btn = bui.buttonwidget(
|
self._free_for_all_button = btn = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(hoffs, v + (scl * 15 if self._is_main_menu else 0)),
|
position=(
|
||||||
|
hoffs,
|
||||||
|
v + (scl * 15 if self._playlist_select_context is None else 0),
|
||||||
|
),
|
||||||
size=(
|
size=(
|
||||||
scl * button_width,
|
scl * button_width,
|
||||||
scl * (300 if self._is_main_menu else 360),
|
scl * (300 if self._playlist_select_context is None else 360),
|
||||||
),
|
),
|
||||||
extra_touch_border_scale=0.1,
|
extra_touch_border_scale=0.1,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
@ -493,22 +513,24 @@ class PlayWindow(bui.MainWindow):
|
|||||||
back_button.delete()
|
back_button.delete()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget,
|
edit=self._root_widget,
|
||||||
on_cancel_call=self._back,
|
on_cancel_call=self.main_window_back,
|
||||||
# cancel_button=bui.get_special_widget('back_button'),
|
# cancel_button=bui.get_special_widget('back_button'),
|
||||||
selected_child=(
|
selected_child=(
|
||||||
self._coop_button
|
self._coop_button
|
||||||
if self._is_main_menu
|
if self._playlist_select_context is None
|
||||||
else self._teams_button
|
else self._teams_button
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
bui.buttonwidget(edit=back_button, on_activate_call=self._back)
|
bui.buttonwidget(
|
||||||
|
edit=back_button, on_activate_call=self.main_window_back
|
||||||
|
)
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget,
|
edit=self._root_widget,
|
||||||
cancel_button=back_button,
|
cancel_button=back_button,
|
||||||
selected_child=(
|
selected_child=(
|
||||||
self._coop_button
|
self._coop_button
|
||||||
if self._is_main_menu
|
if self._playlist_select_context is None
|
||||||
else self._teams_button
|
else self._teams_button
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -519,9 +541,15 @@ class PlayWindow(bui.MainWindow):
|
|||||||
def get_main_window_state(self) -> bui.MainWindowState:
|
def get_main_window_state(self) -> bui.MainWindowState:
|
||||||
# Support recreating our window for back/refresh purposes.
|
# Support recreating our window for back/refresh purposes.
|
||||||
cls = type(self)
|
cls = type(self)
|
||||||
|
|
||||||
|
# Pull any values out of self here; if we do it in the lambda
|
||||||
|
# we'll keep our window alive inadvertantly.
|
||||||
|
playlist_select_context = self._playlist_select_context
|
||||||
return bui.BasicMainWindowState(
|
return bui.BasicMainWindowState(
|
||||||
create_call=lambda transition, origin_widget: cls(
|
create_call=lambda transition, origin_widget: cls(
|
||||||
transition=transition, origin_widget=origin_widget
|
transition=transition,
|
||||||
|
origin_widget=origin_widget,
|
||||||
|
playlist_select_context=playlist_select_context,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -537,30 +565,6 @@ class PlayWindow(bui.MainWindow):
|
|||||||
import bauiv1lib.coop.browser as _unused3
|
import bauiv1lib.coop.browser as _unused3
|
||||||
import bauiv1lib.playlist.browser as _unused4
|
import bauiv1lib.playlist.browser as _unused4
|
||||||
|
|
||||||
def _back(self) -> None:
|
|
||||||
# pylint: disable=cyclic-import
|
|
||||||
|
|
||||||
# no-op if we're not currently in control.
|
|
||||||
if not self.main_window_has_control():
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._is_main_menu:
|
|
||||||
self.main_window_back()
|
|
||||||
else:
|
|
||||||
from bauiv1lib.gather import GatherWindow
|
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
|
||||||
|
|
||||||
self._save_state()
|
|
||||||
bui.app.ui_v1.set_main_window(
|
|
||||||
GatherWindow(transition='in_left'),
|
|
||||||
from_window=self,
|
|
||||||
is_back=True,
|
|
||||||
)
|
|
||||||
bui.containerwidget(
|
|
||||||
edit=self._root_widget, transition=self._transition_out
|
|
||||||
)
|
|
||||||
|
|
||||||
def _coop(self) -> None:
|
def _coop(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
@ -595,7 +599,9 @@ class PlayWindow(bui.MainWindow):
|
|||||||
|
|
||||||
self.main_window_replace(
|
self.main_window_replace(
|
||||||
PlaylistBrowserWindow(
|
PlaylistBrowserWindow(
|
||||||
origin_widget=self._teams_button, sessiontype=bs.DualTeamSession
|
origin_widget=self._teams_button,
|
||||||
|
sessiontype=bs.DualTeamSession,
|
||||||
|
playlist_select_context=self._playlist_select_context,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -614,6 +620,7 @@ class PlayWindow(bui.MainWindow):
|
|||||||
PlaylistBrowserWindow(
|
PlaylistBrowserWindow(
|
||||||
origin_widget=self._free_for_all_button,
|
origin_widget=self._free_for_all_button,
|
||||||
sessiontype=bs.FreeForAllSession,
|
sessiontype=bs.FreeForAllSession,
|
||||||
|
playlist_select_context=self._playlist_select_context,
|
||||||
),
|
),
|
||||||
from_window=self,
|
from_window=self,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -57,12 +57,10 @@ class PlaylistAddGameWindow(bui.MainWindow):
|
|||||||
self._back_button = bui.buttonwidget(
|
self._back_button = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(58 + x_inset, self._height - 53),
|
position=(58 + x_inset, self._height - 53),
|
||||||
size=(165, 70),
|
size=(60, 48),
|
||||||
scale=0.75,
|
label=bui.charstr(bui.SpecialChar.BACK),
|
||||||
text_scale=1.2,
|
|
||||||
label=bui.Lstr(resource='backText'),
|
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
button_type='back',
|
button_type='backSmall',
|
||||||
on_activate_call=self.main_window_back,
|
on_activate_call=self.main_window_back,
|
||||||
)
|
)
|
||||||
self._select_button = select_button = bui.buttonwidget(
|
self._select_button = select_button = bui.buttonwidget(
|
||||||
@ -257,27 +255,37 @@ class PlaylistAddGameWindow(bui.MainWindow):
|
|||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
from bauiv1lib.store.browser import StoreBrowserWindow
|
from bauiv1lib.store.browser import StoreBrowserWindow
|
||||||
|
|
||||||
|
# No-op if we're not in control.
|
||||||
|
if self.main_window_has_control():
|
||||||
|
return
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
if plus.get_v1_account_state() != 'signed_in':
|
if plus.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
return
|
return
|
||||||
StoreBrowserWindow(
|
|
||||||
modal=True,
|
self.main_window_replace(
|
||||||
show_tab=StoreBrowserWindow.TabID.MINIGAMES,
|
StoreBrowserWindow(
|
||||||
on_close_call=self._on_store_close,
|
# modal=True,
|
||||||
origin_widget=self._get_more_games_button,
|
show_tab=StoreBrowserWindow.TabID.MINIGAMES,
|
||||||
|
# on_close_call=self._on_store_close,
|
||||||
|
origin_widget=self._get_more_games_button,
|
||||||
|
minimal_toolbars=True,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_store_close(self) -> None:
|
# def _on_store_close(self) -> None:
|
||||||
self._refresh(select_get_more_games_button=True)
|
# self._refresh(select_get_more_games_button=True)
|
||||||
|
|
||||||
def _add(self) -> None:
|
def _add(self) -> None:
|
||||||
bui.lock_all_input() # Make sure no more commands happen.
|
bui.lock_all_input() # Make sure no more commands happen.
|
||||||
bui.apptimer(0.1, bui.unlock_all_input)
|
bui.apptimer(0.1, bui.unlock_all_input)
|
||||||
assert self._selected_game_type is not None
|
assert self._selected_game_type is not None
|
||||||
self._editcontroller.add_game_type_selected(self._selected_game_type)
|
self._editcontroller.add_game_type_selected(
|
||||||
|
self._selected_game_type, from_window=self
|
||||||
|
)
|
||||||
|
|
||||||
def _set_selected_game_type(self, gametype: type[bs.GameActivity]) -> None:
|
def _set_selected_game_type(self, gametype: type[bs.GameActivity]) -> None:
|
||||||
self._selected_game_type = gametype
|
self._selected_game_type = gametype
|
||||||
@ -290,6 +298,3 @@ class PlaylistAddGameWindow(bui.MainWindow):
|
|||||||
self._editcontroller.get_session_type()
|
self._editcontroller.get_session_type()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# def _back(self) -> None:
|
|
||||||
# self._editcontroller.add_game_cancelled()
|
|
||||||
|
|||||||
@ -7,11 +7,14 @@ from __future__ import annotations
|
|||||||
import copy
|
import copy
|
||||||
import math
|
import math
|
||||||
import logging
|
import logging
|
||||||
from typing import override
|
from typing import override, TYPE_CHECKING
|
||||||
|
|
||||||
import bascenev1 as bs
|
import bascenev1 as bs
|
||||||
import bauiv1 as bui
|
import bauiv1 as bui
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from bauiv1lib.play import PlaylistSelectContext
|
||||||
|
|
||||||
|
|
||||||
class PlaylistBrowserWindow(bui.MainWindow):
|
class PlaylistBrowserWindow(bui.MainWindow):
|
||||||
"""Window for starting teams games."""
|
"""Window for starting teams games."""
|
||||||
@ -21,6 +24,7 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
sessiontype: type[bs.Session],
|
sessiontype: type[bs.Session],
|
||||||
transition: str | None = 'in_right',
|
transition: str | None = 'in_right',
|
||||||
origin_widget: bui.Widget | None = None,
|
origin_widget: bui.Widget | None = None,
|
||||||
|
playlist_select_context: PlaylistSelectContext | None = None,
|
||||||
):
|
):
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.playlist import PlaylistTypeVars
|
from bauiv1lib.playlist import PlaylistTypeVars
|
||||||
@ -39,6 +43,7 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
self._customize_button: bui.Widget | None = None
|
self._customize_button: bui.Widget | None = None
|
||||||
self._sub_width: float | None = None
|
self._sub_width: float | None = None
|
||||||
self._sub_height: float | None = None
|
self._sub_height: float | None = None
|
||||||
|
self._playlist_select_context = playlist_select_context
|
||||||
|
|
||||||
self._ensure_standard_playlists_exist()
|
self._ensure_standard_playlists_exist()
|
||||||
|
|
||||||
@ -63,7 +68,10 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
size=(self._width, self._height + top_extra),
|
size=(self._width, self._height + top_extra),
|
||||||
toolbar_visibility=(
|
toolbar_visibility=(
|
||||||
'menu_minimal'
|
'menu_minimal'
|
||||||
if uiscale is bui.UIScale.SMALL
|
if (
|
||||||
|
uiscale is bui.UIScale.SMALL
|
||||||
|
or playlist_select_context is not None
|
||||||
|
)
|
||||||
else 'menu_full'
|
else 'menu_full'
|
||||||
),
|
),
|
||||||
scale=(
|
scale=(
|
||||||
@ -106,8 +114,6 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center',
|
v_align='center',
|
||||||
)
|
)
|
||||||
# if uiscale is bui.UIScale.SMALL and bui.app.ui_v1.use_toolbars:
|
|
||||||
# bui.textwidget(edit=txt, text='')
|
|
||||||
|
|
||||||
bui.buttonwidget(
|
bui.buttonwidget(
|
||||||
edit=self._back_button,
|
edit=self._back_button,
|
||||||
@ -144,8 +150,8 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
self._config_name_full = self._pvars.config_name + ' Playlists'
|
self._config_name_full = self._pvars.config_name + ' Playlists'
|
||||||
self._last_config = None
|
self._last_config = None
|
||||||
|
|
||||||
# Update now and once per second.
|
# Update now and once per second (this should do our initial
|
||||||
# (this should do our initial refresh)
|
# refresh).
|
||||||
self._update()
|
self._update()
|
||||||
self._update_timer = bui.AppTimer(
|
self._update_timer = bui.AppTimer(
|
||||||
1.0, bui.WeakCall(self._update), repeat=True
|
1.0, bui.WeakCall(self._update), repeat=True
|
||||||
@ -160,11 +166,16 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
# then we keep self alive.
|
# then we keep self alive.
|
||||||
sessiontype = self._sessiontype
|
sessiontype = self._sessiontype
|
||||||
|
|
||||||
|
# Pull anything out of self here; if we do it in the lambda
|
||||||
|
# we'll inadvertanly keep self alive.
|
||||||
|
playlist_select_context = self._playlist_select_context
|
||||||
|
|
||||||
return bui.BasicMainWindowState(
|
return bui.BasicMainWindowState(
|
||||||
create_call=lambda transition, origin_widget: cls(
|
create_call=lambda transition, origin_widget: cls(
|
||||||
transition=transition,
|
transition=transition,
|
||||||
origin_widget=origin_widget,
|
origin_widget=origin_widget,
|
||||||
sessiontype=sessiontype,
|
sessiontype=sessiontype,
|
||||||
|
playlist_select_context=playlist_select_context,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -639,15 +650,35 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
|
|
||||||
def on_play_options_window_run_game(self) -> None:
|
def on_play_options_window_run_game(self) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
if not self._root_widget:
|
|
||||||
|
# No-op if we're not in control.
|
||||||
|
if not self.main_window_has_control():
|
||||||
|
# if not self._root_widget:
|
||||||
return
|
return
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
||||||
|
if self._playlist_select_context is not None:
|
||||||
|
# Done doing a playlist selection; now back all the way out
|
||||||
|
# of our selection windows to our stored starting point.
|
||||||
|
if self._playlist_select_context.back_state is None:
|
||||||
|
logging.error(
|
||||||
|
'No back state found'
|
||||||
|
' after playlist select context completion.'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.main_window_back_state = (
|
||||||
|
self._playlist_select_context.back_state
|
||||||
|
)
|
||||||
|
self.main_window_back()
|
||||||
|
else:
|
||||||
|
# Launching a regular game session; simply get our window
|
||||||
|
# transitioning out.
|
||||||
|
self.main_window_close(transition='out_left')
|
||||||
|
|
||||||
def _on_playlist_select(self, playlist_name: str) -> None:
|
def _on_playlist_select(self, playlist_name: str) -> None:
|
||||||
self._selected_playlist = playlist_name
|
self._selected_playlist = playlist_name
|
||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
# make sure config exists
|
# Make sure config exists.
|
||||||
if self._config_name_full not in bui.app.config:
|
if self._config_name_full not in bui.app.config:
|
||||||
bui.app.config[self._config_name_full] = {}
|
bui.app.config[self._config_name_full] = {}
|
||||||
|
|
||||||
@ -676,6 +707,7 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
scale_origin=button.get_screen_space_center(),
|
scale_origin=button.get_screen_space_center(),
|
||||||
playlist=playlist_name,
|
playlist=playlist_name,
|
||||||
delegate=self,
|
delegate=self,
|
||||||
|
playlist_select_context=self._playlist_select_context,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_customize_press(self) -> None:
|
def _on_customize_press(self) -> None:
|
||||||
@ -690,7 +722,6 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
|
|
||||||
self._save_state()
|
self._save_state()
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
assert bui.app.classic is not None
|
|
||||||
bui.app.ui_v1.set_main_window(
|
bui.app.ui_v1.set_main_window(
|
||||||
PlaylistCustomizeBrowserWindow(
|
PlaylistCustomizeBrowserWindow(
|
||||||
origin_widget=self._customize_button,
|
origin_widget=self._customize_button,
|
||||||
@ -721,15 +752,6 @@ class PlaylistBrowserWindow(bui.MainWindow):
|
|||||||
|
|
||||||
self.main_window_back()
|
self.main_window_back()
|
||||||
|
|
||||||
# self._save_state()
|
|
||||||
# bui.containerwidget(
|
|
||||||
# edit=self._root_widget, transition=self._transition_out
|
|
||||||
# )
|
|
||||||
# assert bui.app.classic is not None
|
|
||||||
# bui.app.ui_v1.set_main_window(
|
|
||||||
# PlayWindow(transition='in_left'), from_window=self, is_back=True
|
|
||||||
# )
|
|
||||||
|
|
||||||
def _save_state(self) -> None:
|
def _save_state(self) -> None:
|
||||||
try:
|
try:
|
||||||
sel = self._root_widget.get_selected_child()
|
sel = self._root_widget.get_selected_child()
|
||||||
|
|||||||
@ -6,19 +6,19 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
import time
|
import time
|
||||||
import logging
|
|
||||||
|
# import logging
|
||||||
from typing import TYPE_CHECKING, override
|
from typing import TYPE_CHECKING, override
|
||||||
|
|
||||||
import bascenev1 as bs
|
# import bascenev1 as bs
|
||||||
import bauiv1 as bui
|
import bauiv1 as bui
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
REQUIRE_PRO = False
|
import bascenev1 as bs
|
||||||
|
|
||||||
# TEMP
|
REQUIRE_PRO = False
|
||||||
UNDER_CONSTRUCTION = True
|
|
||||||
|
|
||||||
|
|
||||||
class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
||||||
@ -77,7 +77,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
if uiscale is bui.UIScale.SMALL:
|
if uiscale is bui.UIScale.SMALL:
|
||||||
self._back_button = None
|
self._back_button = None
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, on_cancel_call=self._back
|
edit=self._root_widget, on_cancel_call=self.main_window_back
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self._back_button = bui.buttonwidget(
|
self._back_button = bui.buttonwidget(
|
||||||
@ -291,8 +291,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
right_widget=bui.get_special_widget('squad_button'),
|
right_widget=bui.get_special_widget('squad_button'),
|
||||||
)
|
)
|
||||||
|
|
||||||
# make sure config exists
|
# Make sure config exists.
|
||||||
self._config_name_full = self._pvars.config_name + ' Playlists'
|
self._config_name_full = f'{self._pvars.config_name} Playlists'
|
||||||
|
|
||||||
if self._config_name_full not in bui.app.config:
|
if self._config_name_full not in bui.app.config:
|
||||||
bui.app.config[self._config_name_full] = {}
|
bui.app.config[self._config_name_full] = {}
|
||||||
@ -305,7 +305,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
|
|
||||||
if self._back_button is not None:
|
if self._back_button is not None:
|
||||||
bui.buttonwidget(
|
bui.buttonwidget(
|
||||||
edit=self._back_button, on_activate_call=self._back
|
edit=self._back_button, on_activate_call=self.main_window_back
|
||||||
)
|
)
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, cancel_button=self._back_button
|
edit=self._root_widget, cancel_button=self._back_button
|
||||||
@ -336,9 +336,14 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# @override
|
@override
|
||||||
# def on_main_window_close(self) -> None:
|
def on_main_window_close(self) -> None:
|
||||||
# self._save_state()
|
if self._selected_playlist_name is not None:
|
||||||
|
cfg = bui.app.config
|
||||||
|
cfg[f'{self._pvars.config_name} Playlist Selection'] = (
|
||||||
|
self._selected_playlist_name
|
||||||
|
)
|
||||||
|
cfg.commit()
|
||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
@ -348,59 +353,10 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
edit=lock, opacity=0.0 if (have or not REQUIRE_PRO) else 1.0
|
edit=lock, opacity=0.0 if (have or not REQUIRE_PRO) else 1.0
|
||||||
)
|
)
|
||||||
|
|
||||||
def _back(self) -> None:
|
|
||||||
# pylint: disable=cyclic-import
|
|
||||||
# from bauiv1lib.playlist import browser
|
|
||||||
|
|
||||||
# no-op if our underlying widget is dead or on its way out.
|
|
||||||
if not self._root_widget or self._root_widget.transitioning_out:
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._selected_playlist_name is not None:
|
|
||||||
cfg = bui.app.config
|
|
||||||
cfg[self._pvars.config_name + ' Playlist Selection'] = (
|
|
||||||
self._selected_playlist_name
|
|
||||||
)
|
|
||||||
cfg.commit()
|
|
||||||
|
|
||||||
self.main_window_back()
|
|
||||||
# bui.containerwidget(
|
|
||||||
# edit=self._root_widget, transition=self._transition_out
|
|
||||||
# )
|
|
||||||
# assert bui.app.classic is not None
|
|
||||||
# bui.app.ui_v1.set_main_window(
|
|
||||||
# browser.PlaylistBrowserWindow(
|
|
||||||
# transition='in_left', sessiontype=self._sessiontype
|
|
||||||
# ),
|
|
||||||
# from_window=self,
|
|
||||||
# is_back=True,
|
|
||||||
# )
|
|
||||||
|
|
||||||
def _select(self, name: str, index: int) -> None:
|
def _select(self, name: str, index: int) -> None:
|
||||||
self._selected_playlist_name = name
|
self._selected_playlist_name = name
|
||||||
self._selected_playlist_index = index
|
self._selected_playlist_index = index
|
||||||
|
|
||||||
def _run_selected_playlist(self) -> None:
|
|
||||||
# pylint: disable=cyclic-import
|
|
||||||
bui.unlock_all_input()
|
|
||||||
try:
|
|
||||||
bs.new_host_session(self._sessiontype)
|
|
||||||
except Exception:
|
|
||||||
from bascenev1lib import mainmenu
|
|
||||||
|
|
||||||
logging.exception('Error running session %s.', self._sessiontype)
|
|
||||||
|
|
||||||
# Drop back into a main menu session.
|
|
||||||
bs.new_host_session(mainmenu.MainMenuSession)
|
|
||||||
|
|
||||||
def _choose_playlist(self) -> None:
|
|
||||||
if self._selected_playlist_name is None:
|
|
||||||
return
|
|
||||||
self._save_playlist_selection()
|
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
||||||
bui.fade_screen(False, endcall=self._run_selected_playlist)
|
|
||||||
bui.lock_all_input()
|
|
||||||
|
|
||||||
def _refresh(self, select_playlist: str | None = None) -> None:
|
def _refresh(self, select_playlist: str | None = None) -> None:
|
||||||
from efro.util import asserttype
|
from efro.util import asserttype
|
||||||
|
|
||||||
@ -451,7 +407,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
)
|
)
|
||||||
bui.widget(edit=txtw, show_buffer_top=50, show_buffer_bottom=50)
|
bui.widget(edit=txtw, show_buffer_top=50, show_buffer_bottom=50)
|
||||||
|
|
||||||
# Hitting up from top widget should jump to 'back'
|
# Hitting up from top widget should jump to 'back'.
|
||||||
if index == 0:
|
if index == 0:
|
||||||
bui.widget(
|
bui.widget(
|
||||||
edit=txtw,
|
edit=txtw,
|
||||||
@ -473,8 +429,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
visible_child=txtw,
|
visible_child=txtw,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Select this one if it was previously selected.
|
# Select this one if it was previously selected. Go by
|
||||||
# Go by index if there's one.
|
# index if there's one.
|
||||||
if old_selection_index is not None:
|
if old_selection_index is not None:
|
||||||
if index == old_selection_index:
|
if index == old_selection_index:
|
||||||
bui.columnwidget(
|
bui.columnwidget(
|
||||||
@ -493,10 +449,10 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
def _save_playlist_selection(self) -> None:
|
def _save_playlist_selection(self) -> None:
|
||||||
# Store the selected playlist in prefs.
|
# Store the selected playlist in prefs. This serves dual
|
||||||
# This serves dual purposes of letting us re-select it next time
|
# purposes of letting us re-select it next time if we want and
|
||||||
# if we want and also lets us pass it to the game (since we reset
|
# also lets us pass it to the game (since we reset the whole
|
||||||
# the whole python environment that's not actually easy).
|
# python environment that's not actually easy).
|
||||||
cfg = bui.app.config
|
cfg = bui.app.config
|
||||||
cfg[self._pvars.config_name + ' Playlist Selection'] = (
|
cfg[self._pvars.config_name + ' Playlist Selection'] = (
|
||||||
self._selected_playlist_name
|
self._selected_playlist_name
|
||||||
@ -511,8 +467,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
from bauiv1lib.playlist.editcontroller import PlaylistEditController
|
from bauiv1lib.playlist.editcontroller import PlaylistEditController
|
||||||
from bauiv1lib.purchase import PurchaseWindow
|
from bauiv1lib.purchase import PurchaseWindow
|
||||||
|
|
||||||
if UNDER_CONSTRUCTION:
|
# No-op if we're not in control.
|
||||||
bui.screenmessage('UNDER CONSTRUCTION')
|
if not self.main_window_has_control():
|
||||||
return
|
return
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
@ -538,18 +494,13 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
self._save_playlist_selection()
|
self._save_playlist_selection()
|
||||||
|
|
||||||
# Kick off the edit UI.
|
# Kick off the edit UI.
|
||||||
PlaylistEditController(sessiontype=self._sessiontype)
|
PlaylistEditController(sessiontype=self._sessiontype, from_window=self)
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
||||||
|
|
||||||
def _edit_playlist(self) -> None:
|
def _edit_playlist(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.playlist.editcontroller import PlaylistEditController
|
from bauiv1lib.playlist.editcontroller import PlaylistEditController
|
||||||
from bauiv1lib.purchase import PurchaseWindow
|
from bauiv1lib.purchase import PurchaseWindow
|
||||||
|
|
||||||
if UNDER_CONSTRUCTION:
|
|
||||||
bui.screenmessage('UNDER CONSTRUCTION')
|
|
||||||
return
|
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
if REQUIRE_PRO and not bui.app.classic.accounts.have_pro_options():
|
if REQUIRE_PRO and not bui.app.classic.accounts.have_pro_options():
|
||||||
PurchaseWindow(items=['pro'])
|
PurchaseWindow(items=['pro'])
|
||||||
@ -566,8 +517,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
PlaylistEditController(
|
PlaylistEditController(
|
||||||
existing_playlist_name=self._selected_playlist_name,
|
existing_playlist_name=self._selected_playlist_name,
|
||||||
sessiontype=self._sessiontype,
|
sessiontype=self._sessiontype,
|
||||||
|
from_window=self,
|
||||||
)
|
)
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
||||||
|
|
||||||
def _do_delete_playlist(self) -> None:
|
def _do_delete_playlist(self) -> None:
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
@ -732,7 +683,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
bui.getsound('error').play()
|
bui.getsound('error').play()
|
||||||
return
|
return
|
||||||
|
|
||||||
# clamp at our max playlist number
|
# Clamp at our max playlist number.
|
||||||
if len(bui.app.config[self._config_name_full]) > self._max_playlists:
|
if len(bui.app.config[self._config_name_full]) > self._max_playlists:
|
||||||
bui.screenmessage(
|
bui.screenmessage(
|
||||||
bui.Lstr(
|
bui.Lstr(
|
||||||
@ -747,10 +698,11 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
copy_text = bui.Lstr(resource='copyOfText').evaluate()
|
copy_text = bui.Lstr(resource='copyOfText').evaluate()
|
||||||
# get just 'Copy' or whatnot
|
|
||||||
copy_word = copy_text.replace('${NAME}', '').strip()
|
|
||||||
# find a valid dup name that doesn't exist
|
|
||||||
|
|
||||||
|
# Get just 'Copy' or whatnot.
|
||||||
|
copy_word = copy_text.replace('${NAME}', '').strip()
|
||||||
|
|
||||||
|
# Find a valid dup name that doesn't exist.
|
||||||
test_index = 1
|
test_index = 1
|
||||||
base_name = self._get_playlist_display_name(
|
base_name = self._get_playlist_display_name(
|
||||||
self._selected_playlist_name
|
self._selected_playlist_name
|
||||||
|
|||||||
@ -290,9 +290,6 @@ class PlaylistEditWindow(bui.MainWindow):
|
|||||||
self._editcontroller.set_edit_ui_selection(selection)
|
self._editcontroller.set_edit_ui_selection(selection)
|
||||||
|
|
||||||
def _cancel(self) -> None:
|
def _cancel(self) -> None:
|
||||||
# from bauiv1lib.playlist.customizebrowser import (
|
|
||||||
# PlaylistCustomizeBrowserWindow,
|
|
||||||
# )
|
|
||||||
|
|
||||||
# no-op if our underlying widget is dead or on its way out.
|
# no-op if our underlying widget is dead or on its way out.
|
||||||
if not self._root_widget or self._root_widget.transitioning_out:
|
if not self._root_widget or self._root_widget.transitioning_out:
|
||||||
@ -301,38 +298,25 @@ class PlaylistEditWindow(bui.MainWindow):
|
|||||||
bui.getsound('powerdown01').play()
|
bui.getsound('powerdown01').play()
|
||||||
self.main_window_back()
|
self.main_window_back()
|
||||||
|
|
||||||
# bui.containerwidget(edit=self._root_widget, transition='out_right')
|
|
||||||
# assert bui.app.classic is not None
|
|
||||||
# bui.app.ui_v1.set_main_window(
|
|
||||||
# PlaylistCustomizeBrowserWindow(
|
|
||||||
# transition='in_left',
|
|
||||||
# sessiontype=self._editcontroller.get_session_type(),
|
|
||||||
# select_playlist=(
|
|
||||||
# self._editcontroller.get_existing_playlist_name()
|
|
||||||
# ),
|
|
||||||
# ),
|
|
||||||
# from_window=self,
|
|
||||||
# is_back=True,
|
|
||||||
# )
|
|
||||||
|
|
||||||
def _add(self) -> None:
|
def _add(self) -> None:
|
||||||
# Store list name then tell the session to perform an add.
|
# Store list name then tell the session to perform an add.
|
||||||
self._editcontroller.setname(
|
self._editcontroller.setname(
|
||||||
cast(str, bui.textwidget(query=self._text_field))
|
cast(str, bui.textwidget(query=self._text_field))
|
||||||
)
|
)
|
||||||
self._editcontroller.add_game_pressed()
|
self._editcontroller.add_game_pressed(from_window=self)
|
||||||
|
|
||||||
def _edit(self) -> None:
|
def _edit(self) -> None:
|
||||||
# Store list name then tell the session to perform an add.
|
# Store list name then tell the session to perform an add.
|
||||||
self._editcontroller.setname(
|
self._editcontroller.setname(
|
||||||
cast(str, bui.textwidget(query=self._text_field))
|
cast(str, bui.textwidget(query=self._text_field))
|
||||||
)
|
)
|
||||||
self._editcontroller.edit_game_pressed()
|
self._editcontroller.edit_game_pressed(from_window=self)
|
||||||
|
|
||||||
def _save_press(self) -> None:
|
def _save_press(self) -> None:
|
||||||
from bauiv1lib.playlist.customizebrowser import (
|
|
||||||
PlaylistCustomizeBrowserWindow,
|
# No-op if we're not in control.
|
||||||
)
|
if not self.main_window_has_control():
|
||||||
|
return
|
||||||
|
|
||||||
# no-op if our underlying widget is dead or on its way out.
|
# no-op if our underlying widget is dead or on its way out.
|
||||||
if not self._root_widget or self._root_widget.transitioning_out:
|
if not self._root_widget or self._root_widget.transitioning_out:
|
||||||
@ -395,18 +379,9 @@ class PlaylistEditWindow(bui.MainWindow):
|
|||||||
)
|
)
|
||||||
plus.run_v1_account_transactions()
|
plus.run_v1_account_transactions()
|
||||||
|
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
|
||||||
bui.getsound('gunCocking').play()
|
bui.getsound('gunCocking').play()
|
||||||
assert bui.app.classic is not None
|
|
||||||
bui.app.ui_v1.set_main_window(
|
self.main_window_back()
|
||||||
PlaylistCustomizeBrowserWindow(
|
|
||||||
transition='in_left',
|
|
||||||
sessiontype=self._editcontroller.get_session_type(),
|
|
||||||
select_playlist=new_name,
|
|
||||||
),
|
|
||||||
from_window=self,
|
|
||||||
is_back=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _save_press_with_sound(self) -> None:
|
def _save_press_with_sound(self) -> None:
|
||||||
bui.getsound('swish').play()
|
bui.getsound('swish').play()
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import bascenev1 as bs
|
|||||||
import bauiv1 as bui
|
import bauiv1 as bui
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
|
||||||
class PlaylistEditController:
|
class PlaylistEditController:
|
||||||
@ -20,8 +20,8 @@ class PlaylistEditController:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
sessiontype: type[bs.Session],
|
sessiontype: type[bs.Session],
|
||||||
|
from_window: bui.MainWindow,
|
||||||
existing_playlist_name: str | None = None,
|
existing_playlist_name: str | None = None,
|
||||||
transition: str = 'in_right',
|
|
||||||
playlist: list[dict[str, Any]] | None = None,
|
playlist: list[dict[str, Any]] | None = None,
|
||||||
playlist_name: str | None = None,
|
playlist_name: str | None = None,
|
||||||
):
|
):
|
||||||
@ -44,6 +44,9 @@ class PlaylistEditController:
|
|||||||
self._existing_playlist_name = existing_playlist_name
|
self._existing_playlist_name = existing_playlist_name
|
||||||
self._config_name_full = self._pvars.config_name + ' Playlists'
|
self._config_name_full = self._pvars.config_name + ' Playlists'
|
||||||
|
|
||||||
|
self._pre_game_add_state: bui.MainWindowState | None = None
|
||||||
|
self._pre_game_edit_state: bui.MainWindowState | None = None
|
||||||
|
|
||||||
# Make sure config exists.
|
# Make sure config exists.
|
||||||
if self._config_name_full not in appconfig:
|
if self._config_name_full not in appconfig:
|
||||||
appconfig[self._config_name_full] = {}
|
appconfig[self._config_name_full] = {}
|
||||||
@ -88,11 +91,12 @@ class PlaylistEditController:
|
|||||||
# and that's all they can do.
|
# and that's all they can do.
|
||||||
self._edit_ui_selection = 'add_button'
|
self._edit_ui_selection = 'add_button'
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
editwindow = PlaylistEditWindow(editcontroller=self)
|
||||||
bui.app.ui_v1.set_main_window(
|
from_window.main_window_replace(editwindow)
|
||||||
PlaylistEditWindow(editcontroller=self, transition=transition),
|
|
||||||
from_window=False, # Disable this check.
|
# Once we've set our start window, store the back state. We'll
|
||||||
)
|
# skip back to there once we're fully done.
|
||||||
|
self._back_state = editwindow.main_window_back_state
|
||||||
|
|
||||||
def get_config_name(self) -> str:
|
def get_config_name(self) -> str:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
@ -142,83 +146,88 @@ class PlaylistEditController:
|
|||||||
"""Sets the selected playlist index."""
|
"""Sets the selected playlist index."""
|
||||||
self._selected_index = index
|
self._selected_index = index
|
||||||
|
|
||||||
def add_game_pressed(self) -> None:
|
def add_game_pressed(self, from_window: bui.MainWindow) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
|
from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
# assert bui.app.classic is not None
|
||||||
bui.app.ui_v1.clear_main_window()
|
|
||||||
bui.app.ui_v1.set_main_window(
|
|
||||||
PlaylistAddGameWindow(editcontroller=self), from_window=None
|
|
||||||
)
|
|
||||||
|
|
||||||
def edit_game_pressed(self) -> None:
|
# No op if we're not in control.
|
||||||
|
if not from_window.main_window_has_control():
|
||||||
|
return
|
||||||
|
|
||||||
|
addwindow = PlaylistAddGameWindow(editcontroller=self)
|
||||||
|
from_window.main_window_replace(addwindow)
|
||||||
|
|
||||||
|
# Once we're there, store the back state. We'll use that to jump
|
||||||
|
# back to our current location once the edit is done.
|
||||||
|
assert self._pre_game_add_state is None
|
||||||
|
self._pre_game_add_state = addwindow.main_window_back_state
|
||||||
|
|
||||||
|
def edit_game_pressed(self, from_window: bui.MainWindow) -> None:
|
||||||
"""Should be called by supplemental UIs when a game is to be edited."""
|
"""Should be called by supplemental UIs when a game is to be edited."""
|
||||||
|
|
||||||
if not self._playlist:
|
if not self._playlist:
|
||||||
return
|
return
|
||||||
|
|
||||||
self._show_edit_ui(
|
self._show_edit_ui(
|
||||||
gametype=bui.getclass(
|
gametype=bui.getclass(
|
||||||
self._playlist[self._selected_index]['type'],
|
self._playlist[self._selected_index]['type'],
|
||||||
subclassof=bs.GameActivity,
|
subclassof=bs.GameActivity,
|
||||||
),
|
),
|
||||||
settings=self._playlist[self._selected_index],
|
settings=self._playlist[self._selected_index],
|
||||||
|
from_window=from_window,
|
||||||
)
|
)
|
||||||
|
|
||||||
# def add_game_cancelled(self) -> None:
|
|
||||||
# """(internal)"""
|
|
||||||
# from bauiv1lib.playlist.edit import PlaylistEditWindow
|
|
||||||
|
|
||||||
# assert bui.app.classic is not None
|
|
||||||
# bui.app.ui_v1.clear_main_window(transition='out_right')
|
|
||||||
# bui.app.ui_v1.set_main_window(
|
|
||||||
# PlaylistEditWindow(editcontroller=self, transition='in_left'),
|
|
||||||
# from_window=None,
|
|
||||||
# is_back=True,
|
|
||||||
# )
|
|
||||||
|
|
||||||
def _show_edit_ui(
|
def _show_edit_ui(
|
||||||
self, gametype: type[bs.GameActivity], settings: dict[str, Any] | None
|
self,
|
||||||
|
gametype: type[bs.GameActivity],
|
||||||
|
settings: dict[str, Any] | None,
|
||||||
|
from_window: bui.MainWindow,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
# pylint: disable=cyclic-import
|
||||||
|
from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
||||||
|
|
||||||
|
if not from_window.main_window_has_control():
|
||||||
|
return
|
||||||
|
|
||||||
self._editing_game = settings is not None
|
self._editing_game = settings is not None
|
||||||
self._editing_game_type = gametype
|
self._editing_game_type = gametype
|
||||||
assert self._sessiontype is not None
|
assert self._sessiontype is not None
|
||||||
gametype.create_settings_ui(
|
|
||||||
self._sessiontype, copy.deepcopy(settings), self._edit_game_done
|
# Jump into an edit window.
|
||||||
|
editwindow = PlaylistEditGameWindow(
|
||||||
|
gametype,
|
||||||
|
self._sessiontype,
|
||||||
|
copy.deepcopy(settings),
|
||||||
|
completion_call=self._edit_game_done,
|
||||||
|
)
|
||||||
|
from_window.main_window_replace(editwindow)
|
||||||
|
|
||||||
|
# Once we're there, store the back state. We'll use that to jump
|
||||||
|
# back to our current location once the edit is done.
|
||||||
|
assert self._pre_game_edit_state is None
|
||||||
|
self._pre_game_edit_state = editwindow.main_window_back_state
|
||||||
|
|
||||||
|
def add_game_type_selected(
|
||||||
|
self, gametype: type[bs.GameActivity], from_window: bui.MainWindow
|
||||||
|
) -> None:
|
||||||
|
"""(internal)"""
|
||||||
|
self._show_edit_ui(
|
||||||
|
gametype=gametype, settings=None, from_window=from_window
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_game_type_selected(self, gametype: type[bs.GameActivity]) -> None:
|
def _edit_game_done(
|
||||||
"""(internal)"""
|
self, config: dict[str, Any] | None, from_window: bui.MainWindow
|
||||||
self._show_edit_ui(gametype=gametype, settings=None)
|
) -> None:
|
||||||
|
|
||||||
def _edit_game_done(self, config: dict[str, Any] | None) -> None:
|
# No-op if provided window isn't in charge.
|
||||||
from bauiv1lib.playlist.edit import PlaylistEditWindow
|
if not from_window.main_window_has_control():
|
||||||
from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
|
return
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
if config is None:
|
if config is None:
|
||||||
# If we were editing, go back to our list.
|
bui.getsound('powerdown01').play()
|
||||||
if self._editing_game:
|
|
||||||
bui.getsound('powerdown01').play()
|
|
||||||
bui.app.ui_v1.clear_main_window()
|
|
||||||
bui.app.ui_v1.set_main_window(
|
|
||||||
PlaylistEditWindow(
|
|
||||||
editcontroller=self, transition='in_left'
|
|
||||||
),
|
|
||||||
from_window=None,
|
|
||||||
is_back=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Otherwise we were adding; go back to the add type choice list.
|
|
||||||
else:
|
|
||||||
bui.app.ui_v1.clear_main_window()
|
|
||||||
bui.app.ui_v1.set_main_window(
|
|
||||||
PlaylistAddGameWindow(
|
|
||||||
editcontroller=self, transition='in_left'
|
|
||||||
),
|
|
||||||
from_window=None,
|
|
||||||
is_back=True,
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# Make sure type is in there.
|
# Make sure type is in there.
|
||||||
assert self._editing_game_type is not None
|
assert self._editing_game_type is not None
|
||||||
@ -235,9 +244,17 @@ class PlaylistEditController:
|
|||||||
self._selected_index = insert_index
|
self._selected_index = insert_index
|
||||||
|
|
||||||
bui.getsound('gunCocking').play()
|
bui.getsound('gunCocking').play()
|
||||||
bui.app.ui_v1.clear_main_window()
|
|
||||||
bui.app.ui_v1.set_main_window(
|
# If we're adding, jump to before the add started.
|
||||||
PlaylistEditWindow(editcontroller=self, transition='in_left'),
|
# Otherwise jump to before the edit started.
|
||||||
from_window=None,
|
assert (
|
||||||
is_back=True,
|
self._pre_game_edit_state is not None
|
||||||
)
|
or self._pre_game_add_state is not None
|
||||||
|
)
|
||||||
|
if self._pre_game_add_state is not None:
|
||||||
|
from_window.main_window_back_state = self._pre_game_add_state
|
||||||
|
elif self._pre_game_edit_state is not None:
|
||||||
|
from_window.main_window_back_state = self._pre_game_edit_state
|
||||||
|
from_window.main_window_back()
|
||||||
|
self._pre_game_edit_state = None
|
||||||
|
self._pre_game_add_state = None
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class PlaylistEditGameWindow(bui.MainWindow):
|
|||||||
gametype: type[bs.GameActivity],
|
gametype: type[bs.GameActivity],
|
||||||
sessiontype: type[bs.Session],
|
sessiontype: type[bs.Session],
|
||||||
config: dict[str, Any] | None,
|
config: dict[str, Any] | None,
|
||||||
completion_call: Callable[[dict[str, Any] | None], Any],
|
completion_call: Callable[[dict[str, Any] | None, bui.MainWindow], Any],
|
||||||
default_selection: str | None = None,
|
default_selection: str | None = None,
|
||||||
transition: str | None = 'in_right',
|
transition: str | None = 'in_right',
|
||||||
origin_widget: bui.Widget | None = None,
|
origin_widget: bui.Widget | None = None,
|
||||||
@ -141,15 +141,15 @@ class PlaylistEditGameWindow(bui.MainWindow):
|
|||||||
btn = bui.buttonwidget(
|
btn = bui.buttonwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(45 + x_inset, height - 82 + y_extra2),
|
position=(45 + x_inset, height - 82 + y_extra2),
|
||||||
size=(180, 70) if is_add else (180, 65),
|
size=(60, 48) if is_add else (180, 65),
|
||||||
label=(
|
label=(
|
||||||
bui.Lstr(resource='backText')
|
bui.charstr(bui.SpecialChar.BACK)
|
||||||
if is_add
|
if is_add
|
||||||
else bui.Lstr(resource='cancelText')
|
else bui.Lstr(resource='cancelText')
|
||||||
),
|
),
|
||||||
button_type='back' if is_add else None,
|
button_type='backSmall' if is_add else None,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
scale=0.75,
|
scale=1.0 if is_add else 0.75,
|
||||||
text_scale=1.3,
|
text_scale=1.3,
|
||||||
on_activate_call=bui.Call(self._cancel),
|
on_activate_call=bui.Call(self._cancel),
|
||||||
)
|
)
|
||||||
@ -541,24 +541,41 @@ class PlaylistEditGameWindow(bui.MainWindow):
|
|||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.playlist.mapselect import PlaylistMapSelectWindow
|
from bauiv1lib.playlist.mapselect import PlaylistMapSelectWindow
|
||||||
|
|
||||||
# no-op if our underlying widget is dead or on its way out.
|
# No-op if we're not in control.
|
||||||
if not self._root_widget or self._root_widget.transitioning_out:
|
if not self.main_window_has_control():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# no-op if our underlying widget is dead or on its way out.
|
||||||
|
# if not self._root_widget or self._root_widget.transitioning_out:
|
||||||
|
# return
|
||||||
|
|
||||||
|
self._config = self._getconfig()
|
||||||
|
|
||||||
# Replace ourself with the map-select UI.
|
# Replace ourself with the map-select UI.
|
||||||
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
self.main_window_replace(
|
||||||
assert bui.app.classic is not None
|
|
||||||
bui.app.ui_v1.set_main_window(
|
|
||||||
PlaylistMapSelectWindow(
|
PlaylistMapSelectWindow(
|
||||||
self._gametype,
|
self._gametype,
|
||||||
self._sessiontype,
|
self._sessiontype,
|
||||||
copy.deepcopy(self._getconfig()),
|
# copy.deepcopy(self._getconfig()),
|
||||||
|
self._config,
|
||||||
self._edit_info,
|
self._edit_info,
|
||||||
self._completion_call,
|
self._completion_call,
|
||||||
),
|
)
|
||||||
from_window=self,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
|
# assert bui.app.classic is not None
|
||||||
|
# bui.app.ui_v1.set_main_window(
|
||||||
|
# PlaylistMapSelectWindow(
|
||||||
|
# self._gametype,
|
||||||
|
# self._sessiontype,
|
||||||
|
# copy.deepcopy(self._getconfig()),
|
||||||
|
# self._edit_info,
|
||||||
|
# self._completion_call,
|
||||||
|
# ),
|
||||||
|
# from_window=self,
|
||||||
|
# )
|
||||||
|
|
||||||
def _choice_inc(
|
def _choice_inc(
|
||||||
self,
|
self,
|
||||||
setting_name: str,
|
setting_name: str,
|
||||||
@ -586,7 +603,7 @@ class PlaylistEditGameWindow(bui.MainWindow):
|
|||||||
][1]
|
][1]
|
||||||
|
|
||||||
def _cancel(self) -> None:
|
def _cancel(self) -> None:
|
||||||
self._completion_call(None)
|
self._completion_call(None, self)
|
||||||
|
|
||||||
def _check_value_change(
|
def _check_value_change(
|
||||||
self, setting_name: str, widget: bui.Widget, value: int
|
self, setting_name: str, widget: bui.Widget, value: int
|
||||||
@ -607,7 +624,7 @@ class PlaylistEditGameWindow(bui.MainWindow):
|
|||||||
return {'settings': settings}
|
return {'settings': settings}
|
||||||
|
|
||||||
def _add(self) -> None:
|
def _add(self) -> None:
|
||||||
self._completion_call(copy.deepcopy(self._getconfig()))
|
self._completion_call(self._getconfig(), self)
|
||||||
|
|
||||||
def _inc(
|
def _inc(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import math
|
import math
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING, override
|
||||||
|
|
||||||
import bauiv1 as bui
|
import bauiv1 as bui
|
||||||
|
|
||||||
@ -24,9 +24,10 @@ class PlaylistMapSelectWindow(bui.MainWindow):
|
|||||||
sessiontype: type[bs.Session],
|
sessiontype: type[bs.Session],
|
||||||
config: dict[str, Any],
|
config: dict[str, Any],
|
||||||
edit_info: dict[str, Any],
|
edit_info: dict[str, Any],
|
||||||
completion_call: Callable[[dict[str, Any] | None], Any],
|
completion_call: Callable[[dict[str, Any] | None, bui.MainWindow], Any],
|
||||||
transition: str | None = 'in_right',
|
transition: str | None = 'in_right',
|
||||||
origin_widget: bui.Widget | None = None,
|
origin_widget: bui.Widget | None = None,
|
||||||
|
select_get_more_maps_button: bool = False,
|
||||||
):
|
):
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ class PlaylistMapSelectWindow(bui.MainWindow):
|
|||||||
self._completion_call = completion_call
|
self._completion_call = completion_call
|
||||||
self._edit_info = edit_info
|
self._edit_info = edit_info
|
||||||
self._maps: list[tuple[str, bui.Texture]] = []
|
self._maps: list[tuple[str, bui.Texture]] = []
|
||||||
|
self._selected_get_more_maps = False
|
||||||
try:
|
try:
|
||||||
self._previous_map = get_filtered_map_name(
|
self._previous_map = get_filtered_map_name(
|
||||||
config['settings']['map']
|
config['settings']['map']
|
||||||
@ -114,7 +116,34 @@ class PlaylistMapSelectWindow(bui.MainWindow):
|
|||||||
bui.containerwidget(edit=self._scrollwidget, claims_left_right=True)
|
bui.containerwidget(edit=self._scrollwidget, claims_left_right=True)
|
||||||
|
|
||||||
self._subcontainer: bui.Widget | None = None
|
self._subcontainer: bui.Widget | None = None
|
||||||
self._refresh()
|
self._refresh(select_get_more_maps_button=select_get_more_maps_button)
|
||||||
|
|
||||||
|
@override
|
||||||
|
def get_main_window_state(self) -> bui.MainWindowState:
|
||||||
|
# Support recreating our window for back/refresh purposes.
|
||||||
|
cls = type(self)
|
||||||
|
|
||||||
|
# Pull things out of self here; if we do it in the lambda we'll
|
||||||
|
# keep ourself alive.
|
||||||
|
gametype = self._gametype
|
||||||
|
sessiontype = self._sessiontype
|
||||||
|
config = self._config
|
||||||
|
edit_info = self._edit_info
|
||||||
|
completion_call = self._completion_call
|
||||||
|
select_get_more_maps = self._selected_get_more_maps
|
||||||
|
|
||||||
|
return bui.BasicMainWindowState(
|
||||||
|
create_call=lambda transition, origin_widget: cls(
|
||||||
|
transition=transition,
|
||||||
|
origin_widget=origin_widget,
|
||||||
|
gametype=gametype,
|
||||||
|
sessiontype=sessiontype,
|
||||||
|
config=config,
|
||||||
|
edit_info=edit_info,
|
||||||
|
completion_call=completion_call,
|
||||||
|
select_get_more_maps_button=select_get_more_maps,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def _refresh(self, select_get_more_maps_button: bool = False) -> None:
|
def _refresh(self, select_get_more_maps_button: bool = False) -> None:
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
@ -255,21 +284,32 @@ class PlaylistMapSelectWindow(bui.MainWindow):
|
|||||||
from bauiv1lib import account
|
from bauiv1lib import account
|
||||||
from bauiv1lib.store.browser import StoreBrowserWindow
|
from bauiv1lib.store.browser import StoreBrowserWindow
|
||||||
|
|
||||||
|
# No-op if we're not in control.
|
||||||
|
if not self.main_window_has_control():
|
||||||
|
return
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
|
|
||||||
if plus.get_v1_account_state() != 'signed_in':
|
if plus.get_v1_account_state() != 'signed_in':
|
||||||
account.show_sign_in_prompt()
|
account.show_sign_in_prompt()
|
||||||
return
|
return
|
||||||
StoreBrowserWindow(
|
|
||||||
modal=True,
|
self._selected_get_more_maps = True
|
||||||
show_tab=StoreBrowserWindow.TabID.MAPS,
|
|
||||||
on_close_call=self._on_store_close,
|
self.main_window_replace(
|
||||||
origin_widget=self._get_more_maps_button,
|
StoreBrowserWindow(
|
||||||
|
# modal=True,
|
||||||
|
show_tab=StoreBrowserWindow.TabID.MAPS,
|
||||||
|
# on_close_call=self._on_store_close,
|
||||||
|
origin_widget=self._get_more_maps_button,
|
||||||
|
minimal_toolbars=True,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_store_close(self) -> None:
|
# def _on_store_close(self) -> None:
|
||||||
self._refresh(select_get_more_maps_button=True)
|
# pass
|
||||||
|
# self._refresh(select_get_more_maps_button=True)
|
||||||
|
|
||||||
def _select(self, map_name: str) -> None:
|
def _select(self, map_name: str) -> None:
|
||||||
# from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
# from bauiv1lib.playlist.editgame import PlaylistEditGameWindow
|
||||||
|
|||||||
@ -15,6 +15,8 @@ from bauiv1lib.popup import PopupWindow
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from bauiv1lib.play import PlaylistSelectContext
|
||||||
|
|
||||||
|
|
||||||
class PlayOptionsWindow(PopupWindow):
|
class PlayOptionsWindow(PopupWindow):
|
||||||
"""A popup window for configuring play options."""
|
"""A popup window for configuring play options."""
|
||||||
@ -25,6 +27,7 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
playlist: str,
|
playlist: str,
|
||||||
scale_origin: tuple[float, float],
|
scale_origin: tuple[float, float],
|
||||||
delegate: Any = None,
|
delegate: Any = None,
|
||||||
|
playlist_select_context: PlaylistSelectContext | None = None,
|
||||||
):
|
):
|
||||||
# FIXME: Tidy this up.
|
# FIXME: Tidy this up.
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
@ -39,11 +42,7 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
self._pvars = PlaylistTypeVars(sessiontype)
|
self._pvars = PlaylistTypeVars(sessiontype)
|
||||||
self._transitioning_out = False
|
self._transitioning_out = False
|
||||||
|
|
||||||
# We behave differently if we're being used for playlist selection
|
self._playlist_select_context = playlist_select_context
|
||||||
# vs starting a game directly (should make this more elegant).
|
|
||||||
classic = bui.app.classic
|
|
||||||
assert classic is not None
|
|
||||||
self._selecting_mode = classic.selecting_private_party_playlist
|
|
||||||
|
|
||||||
self._do_randomize_val = bui.app.config.get(
|
self._do_randomize_val = bui.app.config.get(
|
||||||
self._pvars.config_name + ' Playlist Randomize', 0
|
self._pvars.config_name + ' Playlist Randomize', 0
|
||||||
@ -66,7 +65,8 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
mesh_transparent = bui.getmesh('level_select_button_transparent')
|
mesh_transparent = bui.getmesh('level_select_button_transparent')
|
||||||
mask_tex = bui.gettexture('mapPreviewMask')
|
mask_tex = bui.gettexture('mapPreviewMask')
|
||||||
|
|
||||||
# Poke into this playlist and see if we can display some of its maps.
|
# Poke into this playlist and see if we can display some of its
|
||||||
|
# maps.
|
||||||
map_textures = []
|
map_textures = []
|
||||||
map_texture_entries = []
|
map_texture_entries = []
|
||||||
rows = 0
|
rows = 0
|
||||||
@ -405,7 +405,11 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
on_activate_call=self._on_ok_press,
|
on_activate_call=self._on_ok_press,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
label=bui.Lstr(
|
label=bui.Lstr(
|
||||||
resource='okText' if self._selecting_mode else 'playText'
|
resource=(
|
||||||
|
'okText'
|
||||||
|
if self._playlist_select_context is not None
|
||||||
|
else 'playText'
|
||||||
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -498,8 +502,8 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
|
|
||||||
# Head back to the gather window in playlist-select mode
|
# Head back to the gather window in playlist-select mode
|
||||||
# or start the game in regular mode.
|
# or start the game in regular mode.
|
||||||
if self._selecting_mode:
|
if self._playlist_select_context is not None:
|
||||||
from bauiv1lib.gather import GatherWindow
|
# from bauiv1lib.gather import GatherWindow
|
||||||
|
|
||||||
if self._sessiontype is bs.FreeForAllSession:
|
if self._sessiontype is bs.FreeForAllSession:
|
||||||
typename = 'ffa'
|
typename = 'ffa'
|
||||||
@ -509,14 +513,15 @@ class PlayOptionsWindow(PopupWindow):
|
|||||||
raise RuntimeError('Only teams and ffa currently supported')
|
raise RuntimeError('Only teams and ffa currently supported')
|
||||||
cfg['Private Party Host Session Type'] = typename
|
cfg['Private Party Host Session Type'] = typename
|
||||||
bui.getsound('gunCocking').play()
|
bui.getsound('gunCocking').play()
|
||||||
assert bui.app.classic is not None
|
|
||||||
# Note: this is a wonky situation where we aren't actually
|
# assert bui.app.classic is not None
|
||||||
# the main window but we set it on behalf of the main window
|
# # Note: this is a wonky situation where we aren't actually
|
||||||
# that popped us up.
|
# # the main window but we set it on behalf of the main window
|
||||||
bui.app.ui_v1.set_main_window(
|
# # that popped us up.
|
||||||
GatherWindow(transition='in_right'),
|
# bui.app.ui_v1.set_main_window(
|
||||||
from_window=False, # Disable this test.
|
# GatherWindow(transition='in_right'),
|
||||||
)
|
# from_window=False, # Disable this test.
|
||||||
|
# )
|
||||||
self._transition_out(transition='out_left')
|
self._transition_out(transition='out_left')
|
||||||
if self._delegate is not None:
|
if self._delegate is not None:
|
||||||
self._delegate.on_play_options_window_run_game()
|
self._delegate.on_play_options_window_run_game()
|
||||||
|
|||||||
@ -105,7 +105,7 @@ class ControlsSettingsWindow(bui.MainWindow):
|
|||||||
height += spacing
|
height += spacing
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
smallscale = 1.7 if show_keyboard else 2.2
|
smallscale = 1.7
|
||||||
super().__init__(
|
super().__init__(
|
||||||
root_widget=bui.containerwidget(
|
root_widget=bui.containerwidget(
|
||||||
size=(width, height),
|
size=(width, height),
|
||||||
|
|||||||
@ -24,20 +24,20 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
gamepad: bs.InputDevice,
|
inputdevice: bs.InputDevice,
|
||||||
is_main_menu: bool = True,
|
modal: bool = False,
|
||||||
transition: str = 'in_right',
|
transition: str = 'in_right',
|
||||||
transition_out: str = 'out_right',
|
transition_out: str = 'out_right',
|
||||||
origin_widget: bui.Widget | None = None,
|
origin_widget: bui.Widget | None = None,
|
||||||
settings: dict | None = None,
|
settings: dict | None = None,
|
||||||
):
|
):
|
||||||
self._input = gamepad
|
self._inputdevice = inputdevice
|
||||||
|
|
||||||
# If our input-device went away, just return an empty zombie.
|
# If our input-device went away, just return an empty zombie.
|
||||||
if not self._input:
|
if not self._inputdevice:
|
||||||
return
|
return
|
||||||
|
|
||||||
self._name = self._input.name
|
self._name = self._inputdevice.name
|
||||||
|
|
||||||
self._r = 'configGamepadWindow'
|
self._r = 'configGamepadWindow'
|
||||||
self._transition_out = transition_out
|
self._transition_out = transition_out
|
||||||
@ -45,7 +45,7 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
# We're a secondary gamepad if supplied with settings.
|
# We're a secondary gamepad if supplied with settings.
|
||||||
self._is_secondary = settings is not None
|
self._is_secondary = settings is not None
|
||||||
self._ext = '_B' if self._is_secondary else ''
|
self._ext = '_B' if self._is_secondary else ''
|
||||||
self._is_main_menu = is_main_menu
|
self._modal = modal
|
||||||
self._displayname = self._name
|
self._displayname = self._name
|
||||||
self._width = 700 if self._is_secondary else 730
|
self._width = 700 if self._is_secondary else 730
|
||||||
self._height = 440 if self._is_secondary else 450
|
self._height = 440 if self._is_secondary else 450
|
||||||
@ -56,14 +56,13 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
root_widget=bui.containerwidget(
|
root_widget=bui.containerwidget(
|
||||||
size=(self._width, self._height),
|
size=(self._width, self._height),
|
||||||
scale=(
|
scale=(
|
||||||
1.63
|
1.4
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0
|
else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0
|
||||||
),
|
),
|
||||||
stack_offset=(
|
stack_offset=(
|
||||||
(-20, -16) if uiscale is bui.UIScale.SMALL else (0, 0)
|
(0, -10) if uiscale is bui.UIScale.SMALL else (0, 0)
|
||||||
),
|
),
|
||||||
transition=transition,
|
|
||||||
),
|
),
|
||||||
transition=transition,
|
transition=transition,
|
||||||
origin_widget=origin_widget,
|
origin_widget=origin_widget,
|
||||||
@ -72,6 +71,7 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
self._settings: dict[str, int] = {}
|
self._settings: dict[str, int] = {}
|
||||||
if not self._is_secondary:
|
if not self._is_secondary:
|
||||||
self._get_config_mapping()
|
self._get_config_mapping()
|
||||||
|
|
||||||
# Don't ask to config joysticks while we're in here.
|
# Don't ask to config joysticks while we're in here.
|
||||||
self._rebuild_ui()
|
self._rebuild_ui()
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
]:
|
]:
|
||||||
assert bui.app.classic is not None
|
assert bui.app.classic is not None
|
||||||
val = bui.app.classic.get_input_device_mapped_value(
|
val = bui.app.classic.get_input_device_mapped_value(
|
||||||
self._input, button, default
|
self._inputdevice, button, default
|
||||||
)
|
)
|
||||||
if val != -1:
|
if val != -1:
|
||||||
self._settings[button] = val
|
self._settings[button] = val
|
||||||
@ -419,7 +419,7 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
|
|
||||||
def get_input(self) -> bs.InputDevice:
|
def get_input(self) -> bs.InputDevice:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
return self._input
|
return self._inputdevice
|
||||||
|
|
||||||
def _do_advanced(self) -> None:
|
def _do_advanced(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
@ -535,8 +535,8 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
def show_secondary_editor(self) -> None:
|
def show_secondary_editor(self) -> None:
|
||||||
"""(internal)"""
|
"""(internal)"""
|
||||||
GamepadSettingsWindow(
|
GamepadSettingsWindow(
|
||||||
self._input,
|
self._inputdevice,
|
||||||
is_main_menu=False,
|
modal=True,
|
||||||
settings=self._settings,
|
settings=self._settings,
|
||||||
transition='in_scale',
|
transition='in_scale',
|
||||||
transition_out='out_scale',
|
transition_out='out_scale',
|
||||||
@ -562,16 +562,16 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
assert isinstance(sval2, (int, type(None)))
|
assert isinstance(sval2, (int, type(None)))
|
||||||
if sval1 is not None and sval2 is not None:
|
if sval1 is not None and sval2 is not None:
|
||||||
return (
|
return (
|
||||||
self._input.get_axis_name(sval1)
|
self._inputdevice.get_axis_name(sval1)
|
||||||
+ ' / '
|
+ ' / '
|
||||||
+ self._input.get_axis_name(sval2)
|
+ self._inputdevice.get_axis_name(sval2)
|
||||||
)
|
)
|
||||||
return bui.Lstr(resource=f'{self._r}.unsetText')
|
return bui.Lstr(resource=f'{self._r}.unsetText')
|
||||||
|
|
||||||
# If they're looking for triggers.
|
# If they're looking for triggers.
|
||||||
if control in ['triggerRun1' + self._ext, 'triggerRun2' + self._ext]:
|
if control in ['triggerRun1' + self._ext, 'triggerRun2' + self._ext]:
|
||||||
if control in self._settings:
|
if control in self._settings:
|
||||||
return self._input.get_axis_name(self._settings[control])
|
return self._inputdevice.get_axis_name(self._settings[control])
|
||||||
return bui.Lstr(resource=f'{self._r}.unsetText')
|
return bui.Lstr(resource=f'{self._r}.unsetText')
|
||||||
|
|
||||||
# Dead-zone.
|
# Dead-zone.
|
||||||
@ -592,7 +592,9 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
# If *any* dpad buttons are assigned, show only button assignments.
|
# If *any* dpad buttons are assigned, show only button assignments.
|
||||||
if any(b in self._settings for b in dpad_buttons):
|
if any(b in self._settings for b in dpad_buttons):
|
||||||
if control in self._settings:
|
if control in self._settings:
|
||||||
return self._input.get_button_name(self._settings[control])
|
return self._inputdevice.get_button_name(
|
||||||
|
self._settings[control]
|
||||||
|
)
|
||||||
return bui.Lstr(resource=f'{self._r}.unsetText')
|
return bui.Lstr(resource=f'{self._r}.unsetText')
|
||||||
|
|
||||||
# No dpad buttons - show the dpad number for all 4.
|
# No dpad buttons - show the dpad number for all 4.
|
||||||
@ -617,7 +619,7 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
|
|
||||||
# Other buttons.
|
# Other buttons.
|
||||||
if control in self._settings:
|
if control in self._settings:
|
||||||
return self._input.get_button_name(self._settings[control])
|
return self._inputdevice.get_button_name(self._settings[control])
|
||||||
return bui.Lstr(resource=f'{self._r}.unsetText')
|
return bui.Lstr(resource=f'{self._r}.unsetText')
|
||||||
|
|
||||||
def _gamepad_event(
|
def _gamepad_event(
|
||||||
@ -694,7 +696,7 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
|
|
||||||
# Now launch the up/down listener.
|
# Now launch the up/down listener.
|
||||||
AwaitGamepadInputWindow(
|
AwaitGamepadInputWindow(
|
||||||
self._input,
|
self._inputdevice,
|
||||||
'analogStickUD' + ext,
|
'analogStickUD' + ext,
|
||||||
self._gamepad_event,
|
self._gamepad_event,
|
||||||
bui.Lstr(resource=f'{self._r}.pressUpDownText'),
|
bui.Lstr(resource=f'{self._r}.pressUpDownText'),
|
||||||
@ -783,7 +785,7 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
edit=btn,
|
edit=btn,
|
||||||
on_activate_call=bui.Call(
|
on_activate_call=bui.Call(
|
||||||
AwaitGamepadInputWindow,
|
AwaitGamepadInputWindow,
|
||||||
self._input,
|
self._inputdevice,
|
||||||
button,
|
button,
|
||||||
self._gamepad_event,
|
self._gamepad_event,
|
||||||
message,
|
message,
|
||||||
@ -795,16 +797,16 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
return btn
|
return btn
|
||||||
|
|
||||||
def _cancel(self) -> None:
|
def _cancel(self) -> None:
|
||||||
# from bauiv1lib.settings.controls import ControlsSettingsWindow
|
|
||||||
|
|
||||||
# no-op if our underlying widget is dead or on its way out.
|
# no-op if our underlying widget is dead or on its way out.
|
||||||
if not self._root_widget or self._root_widget.transitioning_out:
|
if not self._root_widget or self._root_widget.transitioning_out:
|
||||||
return
|
return
|
||||||
|
|
||||||
bui.containerwidget(
|
if self._modal:
|
||||||
edit=self._root_widget, transition=self._transition_out
|
bui.containerwidget(
|
||||||
)
|
edit=self._root_widget, transition=self._transition_out
|
||||||
if self._is_main_menu:
|
)
|
||||||
|
else:
|
||||||
self.main_window_back()
|
self.main_window_back()
|
||||||
# assert bui.app.classic is not None
|
# assert bui.app.classic is not None
|
||||||
# bui.app.ui_v1.set_main_window(
|
# bui.app.ui_v1.set_main_window(
|
||||||
@ -899,18 +901,20 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
if not self._root_widget or self._root_widget.transitioning_out:
|
if not self._root_widget or self._root_widget.transitioning_out:
|
||||||
return
|
return
|
||||||
|
|
||||||
bui.containerwidget(
|
|
||||||
edit=self._root_widget, transition=self._transition_out
|
|
||||||
)
|
|
||||||
|
|
||||||
# If we're a secondary editor we just go away (we were editing our
|
# If we're a secondary editor we just go away (we were editing our
|
||||||
# parent's settings dict).
|
# parent's settings dict).
|
||||||
if self._is_secondary:
|
if self._is_secondary:
|
||||||
|
assert self._modal
|
||||||
|
bui.containerwidget(
|
||||||
|
edit=self._root_widget, transition=self._transition_out
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
assert self._settings is not None
|
assert self._settings is not None
|
||||||
if self._input:
|
if self._inputdevice:
|
||||||
dst = classic.get_input_device_config(self._input, default=True)
|
dst = classic.get_input_device_config(
|
||||||
|
self._inputdevice, default=True
|
||||||
|
)
|
||||||
dst2: dict[str, Any] = dst[0][dst[1]]
|
dst2: dict[str, Any] = dst[0][dst[1]]
|
||||||
dst2.clear()
|
dst2.clear()
|
||||||
|
|
||||||
@ -921,7 +925,7 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
|
|
||||||
# If we're allowed to phone home, send this config so we can
|
# If we're allowed to phone home, send this config so we can
|
||||||
# generate more defaults in the future.
|
# generate more defaults in the future.
|
||||||
inputhash = classic.get_input_device_map_hash(self._input)
|
inputhash = classic.get_input_device_map_hash(self._inputdevice)
|
||||||
classic.master_server_v1_post(
|
classic.master_server_v1_post(
|
||||||
'controllerConfig',
|
'controllerConfig',
|
||||||
{
|
{
|
||||||
@ -938,15 +942,13 @@ class GamepadSettingsWindow(bui.MainWindow):
|
|||||||
else:
|
else:
|
||||||
bui.getsound('error').play()
|
bui.getsound('error').play()
|
||||||
|
|
||||||
if self._is_main_menu:
|
if self._modal:
|
||||||
from bauiv1lib.settings.controls import ControlsSettingsWindow
|
bui.containerwidget(
|
||||||
|
edit=self._root_widget, transition=self._transition_out
|
||||||
assert bui.app.classic is not None
|
|
||||||
bui.app.ui_v1.set_main_window(
|
|
||||||
ControlsSettingsWindow(transition='in_left'),
|
|
||||||
from_window=self,
|
|
||||||
is_back=True,
|
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
assert self.main_window_has_control()
|
||||||
|
self.main_window_back()
|
||||||
|
|
||||||
|
|
||||||
class AwaitGamepadInputWindow(bui.Window):
|
class AwaitGamepadInputWindow(bui.Window):
|
||||||
|
|||||||
@ -40,7 +40,7 @@ class GamepadAdvancedSettingsWindow(bui.Window):
|
|||||||
size=(self._width, self._height),
|
size=(self._width, self._height),
|
||||||
scale=1.06
|
scale=1.06
|
||||||
* (
|
* (
|
||||||
1.85
|
1.6
|
||||||
if uiscale is bui.UIScale.SMALL
|
if uiscale is bui.UIScale.SMALL
|
||||||
else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0
|
else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0
|
||||||
),
|
),
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
from typing import TYPE_CHECKING, override
|
from typing import TYPE_CHECKING, override
|
||||||
|
|
||||||
import bascenev1 as bs
|
import bascenev1 as bs
|
||||||
@ -14,107 +13,6 @@ if TYPE_CHECKING:
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
def gamepad_configure_callback(event: dict[str, Any]) -> None:
|
|
||||||
"""Respond to a gamepad button press during config selection."""
|
|
||||||
from bauiv1lib.settings.gamepad import GamepadSettingsWindow
|
|
||||||
|
|
||||||
# Ignore all but button-presses.
|
|
||||||
if event['type'] not in ['BUTTONDOWN', 'HATMOTION']:
|
|
||||||
return
|
|
||||||
bs.release_gamepad_input()
|
|
||||||
|
|
||||||
if bool(True):
|
|
||||||
bui.screenmessage('UNDER CONSTRUCTION')
|
|
||||||
return
|
|
||||||
|
|
||||||
assert bui.app.classic is not None
|
|
||||||
try:
|
|
||||||
bui.app.ui_v1.clear_main_window()
|
|
||||||
except Exception:
|
|
||||||
logging.exception('Error transitioning out main_menu_window.')
|
|
||||||
bui.getsound('activateBeep').play()
|
|
||||||
bui.getsound('swish').play()
|
|
||||||
device = event['input_device']
|
|
||||||
assert isinstance(device, bs.InputDevice)
|
|
||||||
if device.allows_configuring:
|
|
||||||
bui.app.ui_v1.set_main_window(
|
|
||||||
GamepadSettingsWindow(device), from_window=None
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
width = 700
|
|
||||||
height = 200
|
|
||||||
button_width = 80
|
|
||||||
uiscale = bui.app.ui_v1.uiscale
|
|
||||||
|
|
||||||
class _Window(bui.MainWindow):
|
|
||||||
def __init__(self) -> None:
|
|
||||||
super().__init__(
|
|
||||||
root_widget=bui.containerwidget(
|
|
||||||
scale=(
|
|
||||||
1.7
|
|
||||||
if uiscale is bui.UIScale.SMALL
|
|
||||||
else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
|
|
||||||
),
|
|
||||||
size=(width, height),
|
|
||||||
),
|
|
||||||
transition='in_right',
|
|
||||||
origin_widget=None,
|
|
||||||
)
|
|
||||||
|
|
||||||
win = _Window()
|
|
||||||
dlg = win.get_root_widget()
|
|
||||||
|
|
||||||
bui.app.ui_v1.set_main_window(win, from_window=None)
|
|
||||||
|
|
||||||
if device.allows_configuring_in_system_settings:
|
|
||||||
msg = bui.Lstr(
|
|
||||||
resource='configureDeviceInSystemSettingsText',
|
|
||||||
subs=[('${DEVICE}', device.name)],
|
|
||||||
)
|
|
||||||
elif device.is_controller_app:
|
|
||||||
msg = bui.Lstr(
|
|
||||||
resource='bsRemoteConfigureInAppText',
|
|
||||||
subs=[('${REMOTE_APP_NAME}', bui.get_remote_app_name())],
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
msg = bui.Lstr(
|
|
||||||
resource='cantConfigureDeviceText',
|
|
||||||
subs=[('${DEVICE}', device.name)],
|
|
||||||
)
|
|
||||||
bui.textwidget(
|
|
||||||
parent=dlg,
|
|
||||||
position=(0, height - 80),
|
|
||||||
size=(width, 25),
|
|
||||||
text=msg,
|
|
||||||
scale=0.8,
|
|
||||||
h_align='center',
|
|
||||||
v_align='top',
|
|
||||||
)
|
|
||||||
|
|
||||||
def _ok() -> None:
|
|
||||||
from bauiv1lib.settings import controls
|
|
||||||
|
|
||||||
# no-op if our underlying widget is dead or on its way out.
|
|
||||||
if not dlg or dlg.transitioning_out:
|
|
||||||
return
|
|
||||||
|
|
||||||
bui.containerwidget(edit=dlg, transition='out_right')
|
|
||||||
assert bui.app.classic is not None
|
|
||||||
bui.app.ui_v1.set_main_window(
|
|
||||||
controls.ControlsSettingsWindow(transition='in_left'),
|
|
||||||
from_window=win,
|
|
||||||
is_back=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
bui.buttonwidget(
|
|
||||||
parent=dlg,
|
|
||||||
position=((width - button_width) / 2, 20),
|
|
||||||
size=(button_width, 60),
|
|
||||||
label=bui.Lstr(resource='okText'),
|
|
||||||
on_activate_call=_ok,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class GamepadSelectWindow(bui.MainWindow):
|
class GamepadSelectWindow(bui.MainWindow):
|
||||||
"""Window for selecting a gamepad to configure."""
|
"""Window for selecting a gamepad to configure."""
|
||||||
|
|
||||||
@ -155,8 +53,8 @@ class GamepadSelectWindow(bui.MainWindow):
|
|||||||
on_activate_call=self.main_window_back,
|
on_activate_call=self.main_window_back,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Let's not have anything selected by default; its misleading looking
|
# Let's not have anything selected by default; its misleading
|
||||||
# for the controller getting configured.
|
# looking for the controller getting configured.
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget,
|
edit=self._root_widget,
|
||||||
cancel_button=btn,
|
cancel_button=btn,
|
||||||
@ -207,7 +105,10 @@ class GamepadSelectWindow(bui.MainWindow):
|
|||||||
v_align='top',
|
v_align='top',
|
||||||
)
|
)
|
||||||
|
|
||||||
bs.capture_gamepad_input(gamepad_configure_callback)
|
bs.capture_gamepad_input(bui.WeakCall(self.gamepad_configure_callback))
|
||||||
|
|
||||||
|
def __del__(self) -> None:
|
||||||
|
bs.release_gamepad_input()
|
||||||
|
|
||||||
@override
|
@override
|
||||||
def get_main_window_state(self) -> bui.MainWindowState:
|
def get_main_window_state(self) -> bui.MainWindowState:
|
||||||
@ -219,6 +120,102 @@ class GamepadSelectWindow(bui.MainWindow):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@override
|
def gamepad_configure_callback(self, event: dict[str, Any]) -> None:
|
||||||
def on_main_window_close(self) -> None:
|
"""Respond to a gamepad button press during config selection."""
|
||||||
|
from bauiv1lib.settings.gamepad import GamepadSettingsWindow
|
||||||
|
|
||||||
|
if not self.main_window_has_control():
|
||||||
|
return
|
||||||
|
|
||||||
|
# Ignore all but button-presses.
|
||||||
|
if event['type'] not in ['BUTTONDOWN', 'HATMOTION']:
|
||||||
|
return
|
||||||
bs.release_gamepad_input()
|
bs.release_gamepad_input()
|
||||||
|
|
||||||
|
assert bui.app.classic is not None
|
||||||
|
|
||||||
|
bui.getsound('activateBeep').play()
|
||||||
|
bui.getsound('swish').play()
|
||||||
|
device = event['input_device']
|
||||||
|
assert isinstance(device, bs.InputDevice)
|
||||||
|
|
||||||
|
# No matter where we redirect to, we want their back
|
||||||
|
# functionality to skip over us and go to our parent.
|
||||||
|
assert self.main_window_back_state is not None
|
||||||
|
back_state = self.main_window_back_state
|
||||||
|
|
||||||
|
if device.allows_configuring:
|
||||||
|
self.main_window_replace(
|
||||||
|
GamepadSettingsWindow(device), back_state=back_state
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.main_window_replace(
|
||||||
|
_NotConfigurableWindow(device), back_state=back_state
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class _NotConfigurableWindow(bui.MainWindow):
|
||||||
|
|
||||||
|
def __init__(self, device: bs.InputDevice) -> None:
|
||||||
|
width = 700
|
||||||
|
height = 200
|
||||||
|
button_width = 80
|
||||||
|
uiscale = bui.app.ui_v1.uiscale
|
||||||
|
super().__init__(
|
||||||
|
root_widget=bui.containerwidget(
|
||||||
|
scale=(
|
||||||
|
1.7
|
||||||
|
if uiscale is bui.UIScale.SMALL
|
||||||
|
else (1.4 if uiscale is bui.UIScale.MEDIUM else 1.0)
|
||||||
|
),
|
||||||
|
size=(width, height),
|
||||||
|
),
|
||||||
|
transition='in_right',
|
||||||
|
origin_widget=None,
|
||||||
|
)
|
||||||
|
if device.allows_configuring_in_system_settings:
|
||||||
|
msg = bui.Lstr(
|
||||||
|
resource='configureDeviceInSystemSettingsText',
|
||||||
|
subs=[('${DEVICE}', device.name)],
|
||||||
|
)
|
||||||
|
elif device.is_controller_app:
|
||||||
|
msg = bui.Lstr(
|
||||||
|
resource='bsRemoteConfigureInAppText',
|
||||||
|
subs=[
|
||||||
|
(
|
||||||
|
'${REMOTE_APP_NAME}',
|
||||||
|
bui.get_remote_app_name(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
msg = bui.Lstr(
|
||||||
|
resource='cantConfigureDeviceText',
|
||||||
|
subs=[('${DEVICE}', device.name)],
|
||||||
|
)
|
||||||
|
bui.textwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
position=(0, height - 80),
|
||||||
|
size=(width, 25),
|
||||||
|
text=msg,
|
||||||
|
scale=0.8,
|
||||||
|
h_align='center',
|
||||||
|
v_align='top',
|
||||||
|
)
|
||||||
|
|
||||||
|
btn = bui.buttonwidget(
|
||||||
|
parent=self._root_widget,
|
||||||
|
position=((width - button_width) / 2, 20),
|
||||||
|
size=(button_width, 60),
|
||||||
|
label=bui.Lstr(resource='okText'),
|
||||||
|
on_activate_call=self.main_window_back,
|
||||||
|
)
|
||||||
|
bui.containerwidget(edit=self._root_widget, cancel_button=btn)
|
||||||
|
|
||||||
|
# def _ok(self) -> None:
|
||||||
|
|
||||||
|
# # Back would take us to the gamepad-select window. We want to go
|
||||||
|
# # past that.
|
||||||
|
# assert self.main_window_back_state is not None
|
||||||
|
# self.main_window_back_state = self.main_window_back_state.parent
|
||||||
|
# self.main_window_back()
|
||||||
|
|||||||
@ -393,8 +393,7 @@ class SoundtrackEditWindow(bui.MainWindow):
|
|||||||
bui.Call(self._restore_editor, state, song_type),
|
bui.Call(self._restore_editor, state, song_type),
|
||||||
entry,
|
entry,
|
||||||
selection_target_name,
|
selection_target_name,
|
||||||
),
|
)
|
||||||
group_id='soundtrackentryselect',
|
|
||||||
)
|
)
|
||||||
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
# bui.containerwidget(edit=self._root_widget, transition='out_left')
|
||||||
# bui.app.ui_v1.set_main_window(
|
# bui.app.ui_v1.set_main_window(
|
||||||
|
|||||||
@ -209,8 +209,7 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
|
|||||||
self.main_window_replace(
|
self.main_window_replace(
|
||||||
MacMusicAppPlaylistSelectWindow(
|
MacMusicAppPlaylistSelectWindow(
|
||||||
self._callback, current_playlist_entry, self._current_entry
|
self._callback, current_playlist_entry, self._current_entry
|
||||||
),
|
)
|
||||||
group_id='soundtrackentryselect',
|
|
||||||
)
|
)
|
||||||
# MacMusicAppPlaylistSelectWindow(
|
# MacMusicAppPlaylistSelectWindow(
|
||||||
# self._callback, current_playlist_entry, self._current_entry
|
# self._callback, current_playlist_entry, self._current_entry
|
||||||
@ -241,7 +240,6 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
|
|||||||
),
|
),
|
||||||
allow_folders=False,
|
allow_folders=False,
|
||||||
),
|
),
|
||||||
group_id='soundtrackentryselect',
|
|
||||||
)
|
)
|
||||||
# bui.app.ui_v1.set_main_window(
|
# bui.app.ui_v1.set_main_window(
|
||||||
# FileSelectorWindow(
|
# FileSelectorWindow(
|
||||||
@ -276,7 +274,6 @@ class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
|
|||||||
valid_file_extensions=[],
|
valid_file_extensions=[],
|
||||||
allow_folders=True,
|
allow_folders=True,
|
||||||
),
|
),
|
||||||
group_id='soundtrackentryselect',
|
|
||||||
)
|
)
|
||||||
# bui.app.ui_v1.set_main_window(
|
# bui.app.ui_v1.set_main_window(
|
||||||
# FileSelectorWindow(
|
# FileSelectorWindow(
|
||||||
|
|||||||
@ -41,11 +41,12 @@ class StoreBrowserWindow(bui.MainWindow):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
transition: str | None = 'in_right',
|
transition: str | None = 'in_right',
|
||||||
modal: bool = False,
|
# modal: bool = False,
|
||||||
show_tab: StoreBrowserWindow.TabID | None = None,
|
show_tab: StoreBrowserWindow.TabID | None = None,
|
||||||
on_close_call: Callable[[], Any] | None = None,
|
# on_close_call: Callable[[], Any] | None = None,
|
||||||
back_location: str | None = None,
|
# back_location: str | None = None,
|
||||||
origin_widget: bui.Widget | None = None,
|
origin_widget: bui.Widget | None = None,
|
||||||
|
minimal_toolbars: bool = False,
|
||||||
):
|
):
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
@ -59,19 +60,19 @@ class StoreBrowserWindow(bui.MainWindow):
|
|||||||
bui.set_analytics_screen('Store Window')
|
bui.set_analytics_screen('Store Window')
|
||||||
|
|
||||||
# Need to store this ourself for modal mode.
|
# Need to store this ourself for modal mode.
|
||||||
if origin_widget is not None:
|
# if origin_widget is not None:
|
||||||
self._transition_out = 'out_scale'
|
# self._transition_out = 'out_scale'
|
||||||
else:
|
# else:
|
||||||
self._transition_out = 'out_right'
|
# self._transition_out = 'out_right'
|
||||||
|
|
||||||
self.button_infos: dict[str, dict[str, Any]] | None = None
|
self.button_infos: dict[str, dict[str, Any]] | None = None
|
||||||
self.update_buttons_timer: bui.AppTimer | None = None
|
self.update_buttons_timer: bui.AppTimer | None = None
|
||||||
self._status_textwidget_update_timer = None
|
self._status_textwidget_update_timer = None
|
||||||
|
|
||||||
self._back_location = back_location
|
# self._back_location = back_location
|
||||||
self._on_close_call = on_close_call
|
# self._on_close_call = on_close_call
|
||||||
self._show_tab = show_tab
|
self._show_tab = show_tab
|
||||||
self._modal = modal
|
# self._modal = modal
|
||||||
self._width = 1670 if uiscale is bui.UIScale.SMALL else 1040
|
self._width = 1670 if uiscale is bui.UIScale.SMALL else 1040
|
||||||
self._x_inset = x_inset = 310 if uiscale is bui.UIScale.SMALL else 0
|
self._x_inset = x_inset = 310 if uiscale is bui.UIScale.SMALL else 0
|
||||||
self._height = (
|
self._height = (
|
||||||
@ -91,7 +92,7 @@ class StoreBrowserWindow(bui.MainWindow):
|
|||||||
size=(self._width, self._height + extra_top),
|
size=(self._width, self._height + extra_top),
|
||||||
toolbar_visibility=(
|
toolbar_visibility=(
|
||||||
'menu_store'
|
'menu_store'
|
||||||
if uiscale is bui.UIScale.SMALL
|
if (uiscale is bui.UIScale.SMALL or minimal_toolbars)
|
||||||
else 'menu_full'
|
else 'menu_full'
|
||||||
),
|
),
|
||||||
scale=(
|
scale=(
|
||||||
@ -115,15 +116,15 @@ class StoreBrowserWindow(bui.MainWindow):
|
|||||||
size=(140, 60),
|
size=(140, 60),
|
||||||
scale=1.1,
|
scale=1.1,
|
||||||
autoselect=True,
|
autoselect=True,
|
||||||
label=bui.Lstr(resource='doneText' if self._modal else 'backText'),
|
label=bui.Lstr(resource='backText'),
|
||||||
button_type=None if self._modal else 'back',
|
button_type='back',
|
||||||
on_activate_call=self._back,
|
on_activate_call=self.main_window_back,
|
||||||
)
|
)
|
||||||
|
|
||||||
if uiscale is bui.UIScale.SMALL:
|
if uiscale is bui.UIScale.SMALL:
|
||||||
self._back_button.delete()
|
self._back_button.delete()
|
||||||
bui.containerwidget(
|
bui.containerwidget(
|
||||||
edit=self._root_widget, on_cancel_call=self._back
|
edit=self._root_widget, on_cancel_call=self.main_window_back
|
||||||
)
|
)
|
||||||
backbuttonspecial = True
|
backbuttonspecial = True
|
||||||
else:
|
else:
|
||||||
@ -163,7 +164,7 @@ class StoreBrowserWindow(bui.MainWindow):
|
|||||||
maxwidth=290,
|
maxwidth=290,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not self._modal and not backbuttonspecial:
|
if not backbuttonspecial:
|
||||||
bui.buttonwidget(
|
bui.buttonwidget(
|
||||||
edit=self._back_button,
|
edit=self._back_button,
|
||||||
button_type='backSmall',
|
button_type='backSmall',
|
||||||
@ -1251,23 +1252,23 @@ class StoreBrowserWindow(bui.MainWindow):
|
|||||||
except Exception:
|
except Exception:
|
||||||
logging.exception('Error restoring state for %s.', self)
|
logging.exception('Error restoring state for %s.', self)
|
||||||
|
|
||||||
def _back(self) -> None:
|
# def _back(self) -> None:
|
||||||
|
|
||||||
if self._modal:
|
# # if self._modal:
|
||||||
# no-op if our underlying widget is dead or on its way out.
|
# # # no-op if our underlying widget is dead or on its way out.
|
||||||
if not self._root_widget or self._root_widget.transitioning_out:
|
# # if not self._root_widget or self._root_widget.transitioning_out:
|
||||||
return
|
# # return
|
||||||
self._save_state()
|
# # self._save_state()
|
||||||
bui.containerwidget(
|
# # bui.containerwidget(
|
||||||
edit=self._root_widget, transition=self._transition_out
|
# # edit=self._root_widget, transition=self._transition_out
|
||||||
)
|
# # )
|
||||||
else:
|
# # else:
|
||||||
# no-op if we're not currently in control.
|
# # no-op if we're not currently in control.
|
||||||
if not self.main_window_has_control():
|
# if not self.main_window_has_control():
|
||||||
return
|
# return
|
||||||
self.main_window_back()
|
# self.main_window_back()
|
||||||
if self._on_close_call is not None:
|
# # if self._on_close_call is not None:
|
||||||
self._on_close_call()
|
# # self._on_close_call()
|
||||||
|
|
||||||
|
|
||||||
def _check_merch_availability_in_bg_thread() -> None:
|
def _check_merch_availability_in_bg_thread() -> None:
|
||||||
|
|||||||
@ -229,14 +229,18 @@ class StoreButton:
|
|||||||
def _default_on_activate_call(self) -> None:
|
def _default_on_activate_call(self) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bauiv1lib.account import show_sign_in_prompt
|
from bauiv1lib.account import show_sign_in_prompt
|
||||||
from bauiv1lib.store.browser import StoreBrowserWindow
|
|
||||||
|
# from bauiv1lib.store.browser import StoreBrowserWindow
|
||||||
|
|
||||||
plus = bui.app.plus
|
plus = bui.app.plus
|
||||||
assert plus is not None
|
assert plus is not None
|
||||||
if plus.get_v1_account_state() != 'signed_in':
|
if plus.get_v1_account_state() != 'signed_in':
|
||||||
show_sign_in_prompt()
|
show_sign_in_prompt()
|
||||||
return
|
return
|
||||||
StoreBrowserWindow(modal=True, origin_widget=self._button)
|
|
||||||
|
raise RuntimeError('no longer wired up')
|
||||||
|
|
||||||
|
# StoreBrowserWindow(modal=True, origin_widget=self._button)
|
||||||
|
|
||||||
def get_button(self) -> bui.Widget:
|
def get_button(self) -> bui.Widget:
|
||||||
"""Return the underlying button widget."""
|
"""Return the underlying button widget."""
|
||||||
|
|||||||
@ -585,6 +585,17 @@ void AppAdapterSDL::RemoveSDLInputDevice_(int index) {
|
|||||||
assert(g_core->InMainThread());
|
assert(g_core->InMainThread());
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
JoystickInput* j = GetSDLJoystickInput_(index);
|
JoystickInput* j = GetSDLJoystickInput_(index);
|
||||||
|
|
||||||
|
// Note: am running into this with a PS5 controller on macOS Sequoia beta.
|
||||||
|
if (!j) {
|
||||||
|
Log(LogLevel::kError,
|
||||||
|
"GetSDLJoystickInput_() returned nullptr on RemoveSDLInputDevice_();"
|
||||||
|
" joysticks size is "
|
||||||
|
+ std::to_string(sdl_joysticks_.size()) + "; index is "
|
||||||
|
+ std::to_string(index));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(j);
|
assert(j);
|
||||||
if (static_cast_check_fit<int>(sdl_joysticks_.size()) > index) {
|
if (static_cast_check_fit<int>(sdl_joysticks_.size()) > index) {
|
||||||
sdl_joysticks_[index] = nullptr;
|
sdl_joysticks_[index] = nullptr;
|
||||||
|
|||||||
@ -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 = 21977;
|
const int kEngineBuildNumber = 21985;
|
||||||
const char* kEngineVersion = "1.7.37";
|
const char* kEngineVersion = "1.7.37";
|
||||||
const int kEngineApiVersion = 9;
|
const int kEngineApiVersion = 9;
|
||||||
|
|
||||||
|
|||||||
@ -967,28 +967,31 @@ void RootWidget::Setup() {
|
|||||||
// AddCover(0.5f, VAlign::kBottom, 0.0f, -180.0f, 600.0f, 550.0f,
|
// AddCover(0.5f, VAlign::kBottom, 0.0f, -180.0f, 600.0f, 550.0f,
|
||||||
// 0.35f);
|
// 0.35f);
|
||||||
|
|
||||||
float backingR = 0.44f;
|
float backing_r = 0.43f;
|
||||||
float backingG = 0.41f;
|
float backing_g = 0.40f;
|
||||||
float backingB = 0.56f;
|
float backing_b = 0.53f;
|
||||||
float backingCoverR = backingR;
|
// float backingR = 0.44f;
|
||||||
float backingCoverG = backingG;
|
// float backingG = 0.41f;
|
||||||
float backingCoverB = backingB;
|
// float backingB = 0.56f;
|
||||||
|
float backing_cover_r = backing_r;
|
||||||
|
float backing_cover_g = backing_g;
|
||||||
|
float backing_cover_b = backing_b;
|
||||||
float backingA = 1.0f;
|
float backingA = 1.0f;
|
||||||
if (g_base->ui->scale() != UIScale::kSmall) {
|
if (g_base->ui->scale() != UIScale::kSmall) {
|
||||||
backingR *= TOOLBAR_COLOR_R * TOOLBAR_BACK_COLOR_R;
|
backing_r *= TOOLBAR_COLOR_R * TOOLBAR_BACK_COLOR_R;
|
||||||
backingG *= TOOLBAR_COLOR_G * TOOLBAR_BACK_COLOR_G;
|
backing_g *= TOOLBAR_COLOR_G * TOOLBAR_BACK_COLOR_G;
|
||||||
backingB *= TOOLBAR_COLOR_B * TOOLBAR_BACK_COLOR_B;
|
backing_b *= TOOLBAR_COLOR_B * TOOLBAR_BACK_COLOR_B;
|
||||||
backingCoverR *= TOOLBAR_COLOR_R;
|
backing_cover_r *= TOOLBAR_COLOR_R;
|
||||||
backingCoverG *= TOOLBAR_COLOR_G;
|
backing_cover_g *= TOOLBAR_COLOR_G;
|
||||||
backingCoverB *= TOOLBAR_COLOR_B;
|
backing_cover_b *= TOOLBAR_COLOR_B;
|
||||||
backingA *= TOOLBAR_OPACITY;
|
backingA *= TOOLBAR_OPACITY;
|
||||||
} else {
|
} else {
|
||||||
backingR *= 1.1f;
|
backing_r *= 1.1f;
|
||||||
backingG *= 1.1f;
|
backing_g *= 1.1f;
|
||||||
backingB *= 1.1f;
|
backing_b *= 1.1f;
|
||||||
backingCoverR *= 1.1f;
|
backing_cover_r *= 1.1f;
|
||||||
backingCoverG *= 1.1f;
|
backing_cover_g *= 1.1f;
|
||||||
backingCoverB *= 1.1f;
|
backing_cover_b *= 1.1f;
|
||||||
backingA *= TOOLBAR_OPACITY_2;
|
backingA *= TOOLBAR_OPACITY_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -997,16 +1000,16 @@ void RootWidget::Setup() {
|
|||||||
ButtonDef bd;
|
ButtonDef bd;
|
||||||
bd.h_align = 0.5f;
|
bd.h_align = 0.5f;
|
||||||
bd.v_align = VAlign::kBottom;
|
bd.v_align = VAlign::kBottom;
|
||||||
bd.width = 550.0f;
|
bd.width = 500.0f;
|
||||||
bd.height = 110.0f;
|
bd.height = 100.0f;
|
||||||
bd.x = 0.0f;
|
bd.x = 0.0f;
|
||||||
bd.y = 41.0f;
|
bd.y = 41.0f;
|
||||||
bd.img = "uiAtlas2";
|
bd.img = "uiAtlas2";
|
||||||
bd.mesh_transparent = "toolbarBackingBottom2";
|
bd.mesh_transparent = "toolbarBackingBottom2";
|
||||||
bd.selectable = false;
|
bd.selectable = false;
|
||||||
bd.color_r = backingR;
|
bd.color_r = backing_r;
|
||||||
bd.color_g = backingG;
|
bd.color_g = backing_g;
|
||||||
bd.color_b = backingB;
|
bd.color_b = backing_b;
|
||||||
bd.opacity = backingA;
|
bd.opacity = backingA;
|
||||||
|
|
||||||
bd.depth_min = 0.2f;
|
bd.depth_min = 0.2f;
|
||||||
@ -1023,7 +1026,7 @@ void RootWidget::Setup() {
|
|||||||
ButtonDef b;
|
ButtonDef b;
|
||||||
b.h_align = 0.5f;
|
b.h_align = 0.5f;
|
||||||
b.v_align = VAlign::kBottom;
|
b.v_align = VAlign::kBottom;
|
||||||
b.width = b.height = 120.0f;
|
b.width = b.height = 110.0f;
|
||||||
b.x = 0.0f;
|
b.x = 0.0f;
|
||||||
b.y = b.height * 0.4f;
|
b.y = b.height * 0.4f;
|
||||||
b.img = "chestIcon";
|
b.img = "chestIcon";
|
||||||
@ -1032,28 +1035,31 @@ void RootWidget::Setup() {
|
|||||||
(static_cast<uint32_t>(Widget::ToolbarVisibility::kMenuFull)
|
(static_cast<uint32_t>(Widget::ToolbarVisibility::kMenuFull)
|
||||||
| static_cast<uint32_t>(Widget::ToolbarVisibility::kMenuFullNoBack)
|
| static_cast<uint32_t>(Widget::ToolbarVisibility::kMenuFullNoBack)
|
||||||
| static_cast<uint32_t>(Widget::ToolbarVisibility::kMenuFullRoot));
|
| static_cast<uint32_t>(Widget::ToolbarVisibility::kMenuFullRoot));
|
||||||
float spacing = 130.0f;
|
float spacing = 120.0f;
|
||||||
b.x = -1.5f * spacing;
|
b.x = -1.5f * spacing;
|
||||||
b.call = UIV1Python::ObjID::kRootUIChestSlot1PressCall;
|
b.call = UIV1Python::ObjID::kRootUIChestSlot1PressCall;
|
||||||
b.allow_in_game = false;
|
b.allow_in_game = false;
|
||||||
AddButton_(b);
|
AddButton_(b);
|
||||||
|
|
||||||
b.x = -0.5f * spacing;
|
// b.x = -0.5f * spacing;
|
||||||
b.img = "chestOpenIcon";
|
// b.img = "chestOpenIcon";
|
||||||
b.y = b.height * 0.5f;
|
// b.y = b.height * 0.5f;
|
||||||
b.call = UIV1Python::ObjID::kRootUIChestSlot2PressCall;
|
// b.call = UIV1Python::ObjID::kRootUIChestSlot2PressCall;
|
||||||
AddButton_(b);
|
// AddButton_(b);
|
||||||
|
|
||||||
// test - empty icons
|
// test - empty icons
|
||||||
b.y = b.height * 0.4f;
|
b.y = b.height * 0.4f;
|
||||||
b.x = 0.5f * spacing;
|
b.x = 0.5f * spacing;
|
||||||
b.img = "chestIconEmpty";
|
b.img = "chestIconEmpty";
|
||||||
b.width = b.height = 80.0f;
|
b.width = b.height = 80.0f;
|
||||||
b.color_r = backingCoverR;
|
b.color_r = backing_cover_r;
|
||||||
b.color_g = backingCoverG;
|
b.color_g = backing_cover_g;
|
||||||
b.color_b = backingCoverB;
|
b.color_b = backing_cover_b;
|
||||||
b.opacity = 1.0f;
|
b.opacity = 1.0f;
|
||||||
b.call = UIV1Python::ObjID::kRootUIChestSlot3PressCall;
|
b.call = UIV1Python::ObjID::kRootUIChestSlot3PressCall;
|
||||||
|
b.x = -0.5f * spacing;
|
||||||
|
AddButton_(b);
|
||||||
|
b.x = 0.5f * spacing;
|
||||||
AddButton_(b);
|
AddButton_(b);
|
||||||
b.x = 1.5f * spacing;
|
b.x = 1.5f * spacing;
|
||||||
b.call = UIV1Python::ObjID::kRootUIChestSlot4PressCall;
|
b.call = UIV1Python::ObjID::kRootUIChestSlot4PressCall;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user