mirror of
https://github.com/imayushsaini/Bombsquad-Ballistica-Modded-Server.git
synced 2025-10-20 00:00:39 +00:00
1324 lines
48 KiB
Python
1324 lines
48 KiB
Python
# Released under the MIT License. See LICENSE for details.
|
|
#
|
|
"""Implements the main menu window."""
|
|
# pylint: disable=too-many-lines
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
import logging
|
|
|
|
import bauiv1 as bui
|
|
import bascenev1 as bs
|
|
|
|
if TYPE_CHECKING:
|
|
from typing import Any, Callable
|
|
|
|
|
|
class MainMenuWindow(bui.Window):
|
|
"""The main menu window, both in-game and in the main menu session."""
|
|
|
|
def __init__(self, transition: str | None = 'in_right'):
|
|
# pylint: disable=cyclic-import
|
|
import threading
|
|
from bascenev1lib.mainmenu import MainMenuSession
|
|
|
|
plus = bui.app.plus
|
|
assert plus is not None
|
|
|
|
self._in_game = not isinstance(
|
|
bs.get_foreground_host_session(),
|
|
MainMenuSession,
|
|
)
|
|
|
|
# Preload some modules we use in a background thread so we won't
|
|
# have a visual hitch when the user taps them.
|
|
threading.Thread(target=self._preload_modules).start()
|
|
|
|
if not self._in_game:
|
|
bui.set_analytics_screen('Main Menu')
|
|
self._show_remote_app_info_on_first_launch()
|
|
|
|
# Make a vanilla container; we'll modify it to our needs in refresh.
|
|
super().__init__(
|
|
root_widget=bui.containerwidget(
|
|
transition=transition,
|
|
toolbar_visibility='menu_minimal_no_back'
|
|
if self._in_game
|
|
else 'menu_minimal_no_back',
|
|
)
|
|
)
|
|
|
|
# Grab this stuff in case it changes.
|
|
self._is_demo = bui.app.env.demo
|
|
self._is_arcade = bui.app.env.arcade
|
|
|
|
self._tdelay = 0.0
|
|
self._t_delay_inc = 0.02
|
|
self._t_delay_play = 1.7
|
|
self._p_index = 0
|
|
self._use_autoselect = True
|
|
self._button_width = 200.0
|
|
self._button_height = 45.0
|
|
self._width = 100.0
|
|
self._height = 100.0
|
|
self._demo_menu_button: bui.Widget | None = None
|
|
self._gather_button: bui.Widget | None = None
|
|
self._start_button: bui.Widget | None = None
|
|
self._watch_button: bui.Widget | None = None
|
|
self._account_button: bui.Widget | None = None
|
|
self._how_to_play_button: bui.Widget | None = None
|
|
self._credits_button: bui.Widget | None = None
|
|
self._settings_button: bui.Widget | None = None
|
|
self._next_refresh_allow_time = 0.0
|
|
|
|
self._store_char_tex = self._get_store_char_tex()
|
|
|
|
self._refresh()
|
|
self._restore_state()
|
|
|
|
# Keep an eye on a few things and refresh if they change.
|
|
self._account_state = plus.get_v1_account_state()
|
|
self._account_state_num = plus.get_v1_account_state_num()
|
|
self._account_type = (
|
|
plus.get_v1_account_type()
|
|
if self._account_state == 'signed_in'
|
|
else None
|
|
)
|
|
self._refresh_timer = bui.AppTimer(
|
|
0.27, bui.WeakCall(self._check_refresh), repeat=True
|
|
)
|
|
|
|
# noinspection PyUnresolvedReferences
|
|
@staticmethod
|
|
def _preload_modules() -> None:
|
|
"""Preload modules we use; avoids hitches (called in bg thread)."""
|
|
import bauiv1lib.getremote as _unused
|
|
import bauiv1lib.confirm as _unused2
|
|
import bauiv1lib.store.button as _unused3
|
|
import bauiv1lib.kiosk as _unused4
|
|
import bauiv1lib.account.settings as _unused5
|
|
import bauiv1lib.store.browser as _unused6
|
|
import bauiv1lib.creditslist as _unused7
|
|
import bauiv1lib.helpui as _unused8
|
|
import bauiv1lib.settings.allsettings as _unused9
|
|
import bauiv1lib.gather as _unused10
|
|
import bauiv1lib.watch as _unused11
|
|
import bauiv1lib.play as _unused12
|
|
|
|
def _show_remote_app_info_on_first_launch(self) -> None:
|
|
app = bui.app
|
|
assert app.classic is not None
|
|
# The first time the non-in-game menu pops up, we might wanna show
|
|
# a 'get-remote-app' dialog in front of it.
|
|
if app.classic.first_main_menu:
|
|
app.classic.first_main_menu = False
|
|
try:
|
|
force_test = False
|
|
bs.get_local_active_input_devices_count()
|
|
if (
|
|
(app.env.tv or app.classic.platform == 'mac')
|
|
and bui.app.config.get('launchCount', 0) <= 1
|
|
) or force_test:
|
|
|
|
def _check_show_bs_remote_window() -> None:
|
|
try:
|
|
from bauiv1lib.getremote import GetBSRemoteWindow
|
|
|
|
bui.getsound('swish').play()
|
|
GetBSRemoteWindow()
|
|
except Exception:
|
|
logging.exception(
|
|
'Error showing get-remote window.'
|
|
)
|
|
|
|
bui.apptimer(2.5, _check_show_bs_remote_window)
|
|
except Exception:
|
|
logging.exception('Error showing get-remote-app info.')
|
|
|
|
def _get_store_char_tex(self) -> str:
|
|
plus = bui.app.plus
|
|
assert plus is not None
|
|
return (
|
|
'storeCharacterXmas'
|
|
if plus.get_v1_account_misc_read_val('xmas', False)
|
|
else 'storeCharacterEaster'
|
|
if plus.get_v1_account_misc_read_val('easter', False)
|
|
else 'storeCharacter'
|
|
)
|
|
|
|
def _check_refresh(self) -> None:
|
|
plus = bui.app.plus
|
|
assert plus is not None
|
|
|
|
if not self._root_widget:
|
|
return
|
|
|
|
now = bui.apptime()
|
|
if now < self._next_refresh_allow_time:
|
|
return
|
|
|
|
# Don't refresh for the first few seconds the game is up so we don't
|
|
# interrupt the transition in.
|
|
# bui.app.main_menu_window_refresh_check_count += 1
|
|
# if bui.app.main_menu_window_refresh_check_count < 4:
|
|
# return
|
|
|
|
store_char_tex = self._get_store_char_tex()
|
|
account_state_num = plus.get_v1_account_state_num()
|
|
if (
|
|
account_state_num != self._account_state_num
|
|
or store_char_tex != self._store_char_tex
|
|
):
|
|
self._store_char_tex = store_char_tex
|
|
self._account_state_num = account_state_num
|
|
account_state = self._account_state = plus.get_v1_account_state()
|
|
self._account_type = (
|
|
plus.get_v1_account_type()
|
|
if account_state == 'signed_in'
|
|
else None
|
|
)
|
|
self._save_state()
|
|
self._refresh()
|
|
self._restore_state()
|
|
|
|
def get_play_button(self) -> bui.Widget | None:
|
|
"""Return the play button."""
|
|
return self._start_button
|
|
|
|
def _refresh(self) -> None:
|
|
# pylint: disable=too-many-branches
|
|
# pylint: disable=too-many-locals
|
|
# pylint: disable=too-many-statements
|
|
from bauiv1lib.confirm import QuitWindow
|
|
from bauiv1lib.store.button import StoreButton
|
|
|
|
plus = bui.app.plus
|
|
assert plus is not None
|
|
|
|
# Clear everything that was there.
|
|
children = self._root_widget.get_children()
|
|
for child in children:
|
|
child.delete()
|
|
|
|
self._tdelay = 0.0
|
|
self._t_delay_inc = 0.0
|
|
self._t_delay_play = 0.0
|
|
self._button_width = 200.0
|
|
self._button_height = 45.0
|
|
|
|
self._r = 'mainMenu'
|
|
|
|
app = bui.app
|
|
assert app.classic is not None
|
|
self._have_quit_button = app.ui_v1.uiscale is bui.UIScale.LARGE or (
|
|
app.classic.platform == 'windows'
|
|
and app.classic.subplatform == 'oculus'
|
|
)
|
|
|
|
self._have_store_button = not self._in_game
|
|
|
|
self._have_settings_button = (
|
|
not self._in_game or not app.ui_v1.use_toolbars
|
|
) and not (self._is_demo or self._is_arcade)
|
|
|
|
self._input_device = input_device = bs.get_ui_input_device()
|
|
|
|
# Are we connected to a local player?
|
|
self._input_player = input_device.player if input_device else None
|
|
|
|
# Are we connected to a remote player?.
|
|
self._connected_to_remote_player = (
|
|
input_device.is_attached_to_player()
|
|
if (input_device and self._input_player is None)
|
|
else False
|
|
)
|
|
|
|
positions: list[tuple[float, float, float]] = []
|
|
self._p_index = 0
|
|
|
|
if self._in_game:
|
|
h, v, scale = self._refresh_in_game(positions)
|
|
else:
|
|
h, v, scale = self._refresh_not_in_game(positions)
|
|
|
|
if self._have_settings_button:
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
self._settings_button = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width * 0.5 * scale, v),
|
|
size=(self._button_width, self._button_height),
|
|
scale=scale,
|
|
autoselect=self._use_autoselect,
|
|
label=bui.Lstr(resource=self._r + '.settingsText'),
|
|
transition_delay=self._tdelay,
|
|
on_activate_call=self._settings,
|
|
)
|
|
|
|
# Scattered eggs on easter.
|
|
if (
|
|
plus.get_v1_account_misc_read_val('easter', False)
|
|
and not self._in_game
|
|
):
|
|
icon_size = 34
|
|
bui.imagewidget(
|
|
parent=self._root_widget,
|
|
position=(
|
|
h - icon_size * 0.5 - 15,
|
|
v + self._button_height * scale - icon_size * 0.24 + 1.5,
|
|
),
|
|
transition_delay=self._tdelay,
|
|
size=(icon_size, icon_size),
|
|
texture=bui.gettexture('egg3'),
|
|
tilt_scale=0.0,
|
|
)
|
|
|
|
self._tdelay += self._t_delay_inc
|
|
|
|
if self._in_game:
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
|
|
# If we're in a replay, we have a 'Leave Replay' button.
|
|
if bs.is_in_replay():
|
|
bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width * 0.5 * scale, v),
|
|
scale=scale,
|
|
size=(self._button_width, self._button_height),
|
|
autoselect=self._use_autoselect,
|
|
label=bui.Lstr(resource='replayEndText'),
|
|
on_activate_call=self._confirm_end_replay,
|
|
)
|
|
elif bs.get_foreground_host_session() is not None:
|
|
bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width * 0.5 * scale, v),
|
|
scale=scale,
|
|
size=(self._button_width, self._button_height),
|
|
autoselect=self._use_autoselect,
|
|
label=bui.Lstr(
|
|
resource=self._r
|
|
+ (
|
|
'.endTestText'
|
|
if self._is_benchmark()
|
|
else '.endGameText'
|
|
)
|
|
),
|
|
on_activate_call=(
|
|
self._confirm_end_test
|
|
if self._is_benchmark()
|
|
else self._confirm_end_game
|
|
),
|
|
)
|
|
# Assume we're in a client-session.
|
|
else:
|
|
bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width * 0.5 * scale, v),
|
|
scale=scale,
|
|
size=(self._button_width, self._button_height),
|
|
autoselect=self._use_autoselect,
|
|
label=bui.Lstr(resource=self._r + '.leavePartyText'),
|
|
on_activate_call=self._confirm_leave_party,
|
|
)
|
|
|
|
self._store_button: bui.Widget | None
|
|
if self._have_store_button:
|
|
this_b_width = self._button_width
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
|
|
sbtn = self._store_button_instance = StoreButton(
|
|
parent=self._root_widget,
|
|
position=(h - this_b_width * 0.5 * scale, v),
|
|
size=(this_b_width, self._button_height),
|
|
scale=scale,
|
|
on_activate_call=bui.WeakCall(self._on_store_pressed),
|
|
sale_scale=1.3,
|
|
transition_delay=self._tdelay,
|
|
)
|
|
self._store_button = store_button = sbtn.get_button()
|
|
assert bui.app.classic is not None
|
|
uiscale = bui.app.ui_v1.uiscale
|
|
icon_size = (
|
|
55
|
|
if uiscale is bui.UIScale.SMALL
|
|
else 55
|
|
if uiscale is bui.UIScale.MEDIUM
|
|
else 70
|
|
)
|
|
bui.imagewidget(
|
|
parent=self._root_widget,
|
|
position=(
|
|
h - icon_size * 0.5,
|
|
v + self._button_height * scale - icon_size * 0.23,
|
|
),
|
|
transition_delay=self._tdelay,
|
|
size=(icon_size, icon_size),
|
|
texture=bui.gettexture(self._store_char_tex),
|
|
tilt_scale=0.0,
|
|
draw_controller=store_button,
|
|
)
|
|
|
|
self._tdelay += self._t_delay_inc
|
|
else:
|
|
self._store_button = None
|
|
|
|
self._quit_button: bui.Widget | None
|
|
if not self._in_game and self._have_quit_button:
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
self._quit_button = quit_button = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
autoselect=self._use_autoselect,
|
|
position=(h - self._button_width * 0.5 * scale, v),
|
|
size=(self._button_width, self._button_height),
|
|
scale=scale,
|
|
label=bui.Lstr(
|
|
resource=self._r
|
|
+ (
|
|
'.quitText'
|
|
if 'Mac' in app.classic.legacy_user_agent_string
|
|
else '.exitGameText'
|
|
)
|
|
),
|
|
on_activate_call=self._quit,
|
|
transition_delay=self._tdelay,
|
|
)
|
|
|
|
# Scattered eggs on easter.
|
|
if plus.get_v1_account_misc_read_val('easter', False):
|
|
icon_size = 30
|
|
bui.imagewidget(
|
|
parent=self._root_widget,
|
|
position=(
|
|
h - icon_size * 0.5 + 25,
|
|
v
|
|
+ self._button_height * scale
|
|
- icon_size * 0.24
|
|
+ 1.5,
|
|
),
|
|
transition_delay=self._tdelay,
|
|
size=(icon_size, icon_size),
|
|
texture=bui.gettexture('egg1'),
|
|
tilt_scale=0.0,
|
|
)
|
|
|
|
bui.containerwidget(
|
|
edit=self._root_widget, cancel_button=quit_button
|
|
)
|
|
self._tdelay += self._t_delay_inc
|
|
else:
|
|
self._quit_button = None
|
|
|
|
# If we're not in-game, have no quit button, and this is android,
|
|
# we want back presses to quit our activity.
|
|
if (
|
|
not self._in_game
|
|
and not self._have_quit_button
|
|
and app.classic.platform == 'android'
|
|
):
|
|
|
|
def _do_quit() -> None:
|
|
QuitWindow(swish=True, back=True)
|
|
|
|
bui.containerwidget(
|
|
edit=self._root_widget, on_cancel_call=_do_quit
|
|
)
|
|
|
|
# Add speed-up/slow-down buttons for replays.
|
|
# (ideally this should be part of a fading-out playback bar like most
|
|
# media players but this works for now).
|
|
if bs.is_in_replay():
|
|
b_size = 50.0
|
|
b_buffer = 10.0
|
|
t_scale = 0.75
|
|
assert bui.app.classic is not None
|
|
uiscale = bui.app.ui_v1.uiscale
|
|
if uiscale is bui.UIScale.SMALL:
|
|
b_size *= 0.6
|
|
b_buffer *= 1.0
|
|
v_offs = -40
|
|
t_scale = 0.5
|
|
elif uiscale is bui.UIScale.MEDIUM:
|
|
v_offs = -70
|
|
else:
|
|
v_offs = -100
|
|
self._replay_speed_text = bui.textwidget(
|
|
parent=self._root_widget,
|
|
text=bui.Lstr(
|
|
resource='watchWindow.playbackSpeedText',
|
|
subs=[('${SPEED}', str(1.23))],
|
|
),
|
|
position=(h, v + v_offs + 7 * t_scale),
|
|
h_align='center',
|
|
v_align='center',
|
|
size=(0, 0),
|
|
scale=t_scale,
|
|
)
|
|
|
|
# Update to current value.
|
|
self._change_replay_speed(0)
|
|
|
|
# Keep updating in a timer in case it gets changed elsewhere.
|
|
self._change_replay_speed_timer = bui.AppTimer(
|
|
0.25, bui.WeakCall(self._change_replay_speed, 0), repeat=True
|
|
)
|
|
btn = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(
|
|
h - b_size - b_buffer,
|
|
v - b_size - b_buffer + v_offs,
|
|
),
|
|
button_type='square',
|
|
size=(b_size, b_size),
|
|
label='',
|
|
autoselect=True,
|
|
on_activate_call=bui.Call(self._change_replay_speed, -1),
|
|
)
|
|
bui.textwidget(
|
|
parent=self._root_widget,
|
|
draw_controller=btn,
|
|
text='-',
|
|
position=(
|
|
h - b_size * 0.5 - b_buffer,
|
|
v - b_size * 0.5 - b_buffer + 5 * t_scale + v_offs,
|
|
),
|
|
h_align='center',
|
|
v_align='center',
|
|
size=(0, 0),
|
|
scale=3.0 * t_scale,
|
|
)
|
|
btn = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h + b_buffer, v - b_size - b_buffer + v_offs),
|
|
button_type='square',
|
|
size=(b_size, b_size),
|
|
label='',
|
|
autoselect=True,
|
|
on_activate_call=bui.Call(self._change_replay_speed, 1),
|
|
)
|
|
bui.textwidget(
|
|
parent=self._root_widget,
|
|
draw_controller=btn,
|
|
text='+',
|
|
position=(
|
|
h + b_size * 0.5 + b_buffer,
|
|
v - b_size * 0.5 - b_buffer + 5 * t_scale + v_offs,
|
|
),
|
|
h_align='center',
|
|
v_align='center',
|
|
size=(0, 0),
|
|
scale=3.0 * t_scale,
|
|
)
|
|
|
|
def _refresh_not_in_game(
|
|
self, positions: list[tuple[float, float, float]]
|
|
) -> tuple[float, float, float]:
|
|
# pylint: disable=too-many-branches
|
|
# pylint: disable=too-many-locals
|
|
# pylint: disable=too-many-statements
|
|
plus = bui.app.plus
|
|
assert plus is not None
|
|
|
|
assert bui.app.classic is not None
|
|
if not bui.app.classic.did_menu_intro:
|
|
self._tdelay = 2.0
|
|
self._t_delay_inc = 0.02
|
|
self._t_delay_play = 1.7
|
|
|
|
def _set_allow_time() -> None:
|
|
self._next_refresh_allow_time = bui.apptime() + 2.5
|
|
|
|
# Slight hack: widget transitions currently only progress when
|
|
# frames are being drawn, but this tends to get called before
|
|
# frame drawing even starts, meaning we don't know exactly how
|
|
# long we should wait before refreshing to avoid interrupting
|
|
# the transition. To make things a bit better, let's do a
|
|
# redundant set of the time in a deferred call which hopefully
|
|
# happens closer to actual frame draw times.
|
|
_set_allow_time()
|
|
bui.pushcall(_set_allow_time)
|
|
|
|
bui.app.classic.did_menu_intro = True
|
|
self._width = 400.0
|
|
self._height = 200.0
|
|
enable_account_button = True
|
|
account_type_name: str | bui.Lstr
|
|
if plus.get_v1_account_state() == 'signed_in':
|
|
account_type_name = plus.get_v1_account_display_string()
|
|
account_type_icon = None
|
|
account_textcolor = (1.0, 1.0, 1.0)
|
|
else:
|
|
account_type_name = bui.Lstr(
|
|
resource='notSignedInText',
|
|
fallback_resource='accountSettingsWindow.titleText',
|
|
)
|
|
account_type_icon = None
|
|
account_textcolor = (1.0, 0.2, 0.2)
|
|
account_type_icon_color = (1.0, 1.0, 1.0)
|
|
account_type_call = self._show_account_window
|
|
account_type_enable_button_sound = True
|
|
b_count = 3 # play, help, credits
|
|
if self._have_settings_button:
|
|
b_count += 1
|
|
if enable_account_button:
|
|
b_count += 1
|
|
if self._have_quit_button:
|
|
b_count += 1
|
|
if self._have_store_button:
|
|
b_count += 1
|
|
uiscale = bui.app.ui_v1.uiscale
|
|
if uiscale is bui.UIScale.SMALL:
|
|
root_widget_scale = 1.6
|
|
play_button_width = self._button_width * 0.65
|
|
play_button_height = self._button_height * 1.1
|
|
small_button_scale = 0.51 if b_count > 6 else 0.63
|
|
button_y_offs = -20.0
|
|
button_y_offs2 = -60.0
|
|
self._button_height *= 1.3
|
|
button_spacing = 1.04
|
|
elif uiscale is bui.UIScale.MEDIUM:
|
|
root_widget_scale = 1.3
|
|
play_button_width = self._button_width * 0.65
|
|
play_button_height = self._button_height * 1.1
|
|
small_button_scale = 0.6
|
|
button_y_offs = -55.0
|
|
button_y_offs2 = -75.0
|
|
self._button_height *= 1.25
|
|
button_spacing = 1.1
|
|
else:
|
|
root_widget_scale = 1.0
|
|
play_button_width = self._button_width * 0.65
|
|
play_button_height = self._button_height * 1.1
|
|
small_button_scale = 0.75
|
|
button_y_offs = -80.0
|
|
button_y_offs2 = -100.0
|
|
self._button_height *= 1.2
|
|
button_spacing = 1.1
|
|
spc = self._button_width * small_button_scale * button_spacing
|
|
bui.containerwidget(
|
|
edit=self._root_widget,
|
|
size=(self._width, self._height),
|
|
background=False,
|
|
scale=root_widget_scale,
|
|
)
|
|
assert not positions
|
|
positions.append((self._width * 0.5, button_y_offs, 1.7))
|
|
x_offs = self._width * 0.5 - (spc * (b_count - 1) * 0.5) + (spc * 0.5)
|
|
for i in range(b_count - 1):
|
|
positions.append(
|
|
(
|
|
x_offs + spc * i - 1.0,
|
|
button_y_offs + button_y_offs2,
|
|
small_button_scale,
|
|
)
|
|
)
|
|
# In kiosk mode, provide a button to get back to the kiosk menu.
|
|
if bui.app.env.demo or bui.app.env.arcade:
|
|
h, v, scale = positions[self._p_index]
|
|
this_b_width = self._button_width * 0.4 * scale
|
|
demo_menu_delay = (
|
|
0.0
|
|
if self._t_delay_play == 0.0
|
|
else max(0, self._t_delay_play + 0.1)
|
|
)
|
|
self._demo_menu_button = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(self._width * 0.5 - this_b_width * 0.5, v + 90),
|
|
size=(this_b_width, 45),
|
|
autoselect=True,
|
|
color=(0.45, 0.55, 0.45),
|
|
textcolor=(0.7, 0.8, 0.7),
|
|
label=bui.Lstr(
|
|
resource='modeArcadeText'
|
|
if bui.app.env.arcade
|
|
else 'modeDemoText'
|
|
),
|
|
transition_delay=demo_menu_delay,
|
|
on_activate_call=self._demo_menu_press,
|
|
)
|
|
else:
|
|
self._demo_menu_button = None
|
|
uiscale = bui.app.ui_v1.uiscale
|
|
foof = (
|
|
-1
|
|
if uiscale is bui.UIScale.SMALL
|
|
else 1
|
|
if uiscale is bui.UIScale.MEDIUM
|
|
else 3
|
|
)
|
|
h, v, scale = positions[self._p_index]
|
|
v = v + foof
|
|
gather_delay = (
|
|
0.0
|
|
if self._t_delay_play == 0.0
|
|
else max(0.0, self._t_delay_play + 0.1)
|
|
)
|
|
assert play_button_width is not None
|
|
assert play_button_height is not None
|
|
this_h = h - play_button_width * 0.5 * scale - 40 * scale
|
|
this_b_width = self._button_width * 0.25 * scale
|
|
this_b_height = self._button_height * 0.82 * scale
|
|
self._gather_button = btn = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(this_h - this_b_width * 0.5, v),
|
|
size=(this_b_width, this_b_height),
|
|
autoselect=self._use_autoselect,
|
|
button_type='square',
|
|
label='',
|
|
transition_delay=gather_delay,
|
|
on_activate_call=self._gather_press,
|
|
)
|
|
bui.textwidget(
|
|
parent=self._root_widget,
|
|
position=(this_h, v + self._button_height * 0.33),
|
|
size=(0, 0),
|
|
scale=0.75,
|
|
transition_delay=gather_delay,
|
|
draw_controller=btn,
|
|
color=(0.75, 1.0, 0.7),
|
|
maxwidth=self._button_width * 0.33,
|
|
text=bui.Lstr(resource='gatherWindow.titleText'),
|
|
h_align='center',
|
|
v_align='center',
|
|
)
|
|
icon_size = this_b_width * 0.6
|
|
bui.imagewidget(
|
|
parent=self._root_widget,
|
|
size=(icon_size, icon_size),
|
|
draw_controller=btn,
|
|
transition_delay=gather_delay,
|
|
position=(this_h - 0.5 * icon_size, v + 0.31 * this_b_height),
|
|
texture=bui.gettexture('usersButton'),
|
|
)
|
|
|
|
# Play button.
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
self._start_button = start_button = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - play_button_width * 0.5 * scale, v),
|
|
size=(play_button_width, play_button_height),
|
|
autoselect=self._use_autoselect,
|
|
scale=scale,
|
|
text_res_scale=2.0,
|
|
label=bui.Lstr(resource='playText'),
|
|
transition_delay=self._t_delay_play,
|
|
on_activate_call=self._play_press,
|
|
)
|
|
bui.containerwidget(
|
|
edit=self._root_widget,
|
|
start_button=start_button,
|
|
selected_child=start_button,
|
|
)
|
|
v = v + foof
|
|
watch_delay = (
|
|
0.0
|
|
if self._t_delay_play == 0.0
|
|
else max(0.0, self._t_delay_play - 0.1)
|
|
)
|
|
this_h = h + play_button_width * 0.5 * scale + 40 * scale
|
|
this_b_width = self._button_width * 0.25 * scale
|
|
this_b_height = self._button_height * 0.82 * scale
|
|
self._watch_button = btn = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(this_h - this_b_width * 0.5, v),
|
|
size=(this_b_width, this_b_height),
|
|
autoselect=self._use_autoselect,
|
|
button_type='square',
|
|
label='',
|
|
transition_delay=watch_delay,
|
|
on_activate_call=self._watch_press,
|
|
)
|
|
bui.textwidget(
|
|
parent=self._root_widget,
|
|
position=(this_h, v + self._button_height * 0.33),
|
|
size=(0, 0),
|
|
scale=0.75,
|
|
transition_delay=watch_delay,
|
|
color=(0.75, 1.0, 0.7),
|
|
draw_controller=btn,
|
|
maxwidth=self._button_width * 0.33,
|
|
text=bui.Lstr(resource='watchWindow.titleText'),
|
|
h_align='center',
|
|
v_align='center',
|
|
)
|
|
icon_size = this_b_width * 0.55
|
|
bui.imagewidget(
|
|
parent=self._root_widget,
|
|
size=(icon_size, icon_size),
|
|
draw_controller=btn,
|
|
transition_delay=watch_delay,
|
|
position=(this_h - 0.5 * icon_size, v + 0.33 * this_b_height),
|
|
texture=bui.gettexture('tv'),
|
|
)
|
|
if not self._in_game and enable_account_button:
|
|
this_b_width = self._button_width
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
self._account_button = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - this_b_width * 0.5 * scale, v),
|
|
size=(this_b_width, self._button_height),
|
|
scale=scale,
|
|
label=account_type_name,
|
|
autoselect=self._use_autoselect,
|
|
on_activate_call=account_type_call,
|
|
textcolor=account_textcolor,
|
|
icon=account_type_icon,
|
|
icon_color=account_type_icon_color,
|
|
transition_delay=self._tdelay,
|
|
enable_sound=account_type_enable_button_sound,
|
|
)
|
|
|
|
# Scattered eggs on easter.
|
|
if (
|
|
plus.get_v1_account_misc_read_val('easter', False)
|
|
and not self._in_game
|
|
):
|
|
icon_size = 32
|
|
bui.imagewidget(
|
|
parent=self._root_widget,
|
|
position=(
|
|
h - icon_size * 0.5 + 35,
|
|
v
|
|
+ self._button_height * scale
|
|
- icon_size * 0.24
|
|
+ 1.5,
|
|
),
|
|
transition_delay=self._tdelay,
|
|
size=(icon_size, icon_size),
|
|
texture=bui.gettexture('egg2'),
|
|
tilt_scale=0.0,
|
|
)
|
|
self._tdelay += self._t_delay_inc
|
|
else:
|
|
self._account_button = None
|
|
|
|
# How-to-play button.
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
btn = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width * 0.5 * scale, v),
|
|
scale=scale,
|
|
autoselect=self._use_autoselect,
|
|
size=(self._button_width, self._button_height),
|
|
label=bui.Lstr(resource=self._r + '.howToPlayText'),
|
|
transition_delay=self._tdelay,
|
|
on_activate_call=self._howtoplay,
|
|
)
|
|
self._how_to_play_button = btn
|
|
|
|
# Scattered eggs on easter.
|
|
if (
|
|
plus.get_v1_account_misc_read_val('easter', False)
|
|
and not self._in_game
|
|
):
|
|
icon_size = 28
|
|
bui.imagewidget(
|
|
parent=self._root_widget,
|
|
position=(
|
|
h - icon_size * 0.5 + 30,
|
|
v + self._button_height * scale - icon_size * 0.24 + 1.5,
|
|
),
|
|
transition_delay=self._tdelay,
|
|
size=(icon_size, icon_size),
|
|
texture=bui.gettexture('egg4'),
|
|
tilt_scale=0.0,
|
|
)
|
|
# Credits button.
|
|
self._tdelay += self._t_delay_inc
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
self._credits_button = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width * 0.5 * scale, v),
|
|
size=(self._button_width, self._button_height),
|
|
autoselect=self._use_autoselect,
|
|
label=bui.Lstr(resource=self._r + '.creditsText'),
|
|
scale=scale,
|
|
transition_delay=self._tdelay,
|
|
on_activate_call=self._credits,
|
|
)
|
|
self._tdelay += self._t_delay_inc
|
|
return h, v, scale
|
|
|
|
def _refresh_in_game(
|
|
self, positions: list[tuple[float, float, float]]
|
|
) -> tuple[float, float, float]:
|
|
# pylint: disable=too-many-branches
|
|
# pylint: disable=too-many-locals
|
|
# pylint: disable=too-many-statements
|
|
assert bui.app.classic is not None
|
|
custom_menu_entries: list[dict[str, Any]] = []
|
|
session = bs.get_foreground_host_session()
|
|
if session is not None:
|
|
try:
|
|
custom_menu_entries = session.get_custom_menu_entries()
|
|
for cme in custom_menu_entries:
|
|
cme_any: Any = cme # Type check may not hold true.
|
|
if (
|
|
not isinstance(cme_any, dict)
|
|
or 'label' not in cme
|
|
or not isinstance(cme['label'], (str, bui.Lstr))
|
|
or 'call' not in cme
|
|
or not callable(cme['call'])
|
|
):
|
|
raise ValueError(
|
|
'invalid custom menu entry: ' + str(cme)
|
|
)
|
|
except Exception:
|
|
custom_menu_entries = []
|
|
logging.exception(
|
|
'Error getting custom menu entries for %s.', session
|
|
)
|
|
self._width = 250.0
|
|
self._height = 250.0 if self._input_player else 180.0
|
|
if (self._is_demo or self._is_arcade) and self._input_player:
|
|
self._height -= 40
|
|
if not self._have_settings_button:
|
|
self._height -= 50
|
|
if self._connected_to_remote_player:
|
|
# In this case we have a leave *and* a disconnect button.
|
|
self._height += 50
|
|
self._height += 50 * (len(custom_menu_entries))
|
|
uiscale = bui.app.ui_v1.uiscale
|
|
bui.containerwidget(
|
|
edit=self._root_widget,
|
|
size=(self._width, self._height),
|
|
scale=(
|
|
2.15
|
|
if uiscale is bui.UIScale.SMALL
|
|
else 1.6
|
|
if uiscale is bui.UIScale.MEDIUM
|
|
else 1.0
|
|
),
|
|
)
|
|
h = 125.0
|
|
v = self._height - 80.0 if self._input_player else self._height - 60
|
|
h_offset = 0
|
|
d_h_offset = 0
|
|
v_offset = -50
|
|
for _i in range(6 + len(custom_menu_entries)):
|
|
positions.append((h, v, 1.0))
|
|
v += v_offset
|
|
h += h_offset
|
|
h_offset += d_h_offset
|
|
self._start_button = None
|
|
bui.app.classic.pause()
|
|
|
|
# Player name if applicable.
|
|
if self._input_player:
|
|
player_name = self._input_player.getname()
|
|
h, v, scale = positions[self._p_index]
|
|
v += 35
|
|
bui.textwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width / 2, v),
|
|
size=(self._button_width, self._button_height),
|
|
color=(1, 1, 1, 0.5),
|
|
scale=0.7,
|
|
h_align='center',
|
|
text=bui.Lstr(value=player_name),
|
|
)
|
|
else:
|
|
player_name = ''
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
btn = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width / 2, v),
|
|
size=(self._button_width, self._button_height),
|
|
scale=scale,
|
|
label=bui.Lstr(resource=self._r + '.resumeText'),
|
|
autoselect=self._use_autoselect,
|
|
on_activate_call=self._resume,
|
|
)
|
|
bui.containerwidget(edit=self._root_widget, cancel_button=btn)
|
|
|
|
# Add any custom options defined by the current game.
|
|
for entry in custom_menu_entries:
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
|
|
# Ask the entry whether we should resume when we call
|
|
# it (defaults to true).
|
|
resume = bool(entry.get('resume_on_call', True))
|
|
|
|
if resume:
|
|
call = bui.Call(self._resume_and_call, entry['call'])
|
|
else:
|
|
call = bui.Call(entry['call'], bui.WeakCall(self._resume))
|
|
|
|
bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width / 2, v),
|
|
size=(self._button_width, self._button_height),
|
|
scale=scale,
|
|
on_activate_call=call,
|
|
label=entry['label'],
|
|
autoselect=self._use_autoselect,
|
|
)
|
|
# Add a 'leave' button if the menu-owner has a player.
|
|
if (self._input_player or self._connected_to_remote_player) and not (
|
|
self._is_demo or self._is_arcade
|
|
):
|
|
h, v, scale = positions[self._p_index]
|
|
self._p_index += 1
|
|
btn = bui.buttonwidget(
|
|
parent=self._root_widget,
|
|
position=(h - self._button_width / 2, v),
|
|
size=(self._button_width, self._button_height),
|
|
scale=scale,
|
|
on_activate_call=self._leave,
|
|
label='',
|
|
autoselect=self._use_autoselect,
|
|
)
|
|
|
|
if (
|
|
player_name != ''
|
|
and player_name[0] != '<'
|
|
and player_name[-1] != '>'
|
|
):
|
|
txt = bui.Lstr(
|
|
resource=self._r + '.justPlayerText',
|
|
subs=[('${NAME}', player_name)],
|
|
)
|
|
else:
|
|
txt = bui.Lstr(value=player_name)
|
|
bui.textwidget(
|
|
parent=self._root_widget,
|
|
position=(
|
|
h,
|
|
v
|
|
+ self._button_height
|
|
* (0.64 if player_name != '' else 0.5),
|
|
),
|
|
size=(0, 0),
|
|
text=bui.Lstr(resource=self._r + '.leaveGameText'),
|
|
scale=(0.83 if player_name != '' else 1.0),
|
|
color=(0.75, 1.0, 0.7),
|
|
h_align='center',
|
|
v_align='center',
|
|
draw_controller=btn,
|
|
maxwidth=self._button_width * 0.9,
|
|
)
|
|
bui.textwidget(
|
|
parent=self._root_widget,
|
|
position=(h, v + self._button_height * 0.27),
|
|
size=(0, 0),
|
|
text=txt,
|
|
color=(0.75, 1.0, 0.7),
|
|
h_align='center',
|
|
v_align='center',
|
|
draw_controller=btn,
|
|
scale=0.45,
|
|
maxwidth=self._button_width * 0.9,
|
|
)
|
|
return h, v, scale
|
|
|
|
def _change_replay_speed(self, offs: int) -> None:
|
|
if not self._replay_speed_text:
|
|
if bui.do_once():
|
|
print('_change_replay_speed called without widget')
|
|
return
|
|
bs.set_replay_speed_exponent(bs.get_replay_speed_exponent() + offs)
|
|
actual_speed = pow(2.0, bs.get_replay_speed_exponent())
|
|
bui.textwidget(
|
|
edit=self._replay_speed_text,
|
|
text=bui.Lstr(
|
|
resource='watchWindow.playbackSpeedText',
|
|
subs=[('${SPEED}', str(actual_speed))],
|
|
),
|
|
)
|
|
|
|
def _quit(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.confirm import QuitWindow
|
|
|
|
QuitWindow(origin_widget=self._quit_button)
|
|
|
|
def _demo_menu_press(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.kiosk import KioskWindow
|
|
|
|
self._save_state()
|
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
|
assert bui.app.classic is not None
|
|
bui.app.ui_v1.set_main_menu_window(
|
|
KioskWindow(transition='in_left').get_root_widget()
|
|
)
|
|
|
|
def _show_account_window(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.account.settings import AccountSettingsWindow
|
|
|
|
self._save_state()
|
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
assert bui.app.classic is not None
|
|
bui.app.ui_v1.set_main_menu_window(
|
|
AccountSettingsWindow(
|
|
origin_widget=self._account_button
|
|
).get_root_widget()
|
|
)
|
|
|
|
def _on_store_pressed(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.store.browser import StoreBrowserWindow
|
|
from bauiv1lib.account import show_sign_in_prompt
|
|
|
|
plus = bui.app.plus
|
|
assert plus is not None
|
|
|
|
if plus.get_v1_account_state() != 'signed_in':
|
|
show_sign_in_prompt()
|
|
return
|
|
self._save_state()
|
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
assert bui.app.classic is not None
|
|
bui.app.ui_v1.set_main_menu_window(
|
|
StoreBrowserWindow(
|
|
origin_widget=self._store_button
|
|
).get_root_widget()
|
|
)
|
|
|
|
def _is_benchmark(self) -> bool:
|
|
session = bs.get_foreground_host_session()
|
|
return getattr(session, 'benchmark_type', None) == 'cpu' or (
|
|
bui.app.classic is not None
|
|
and bui.app.classic.stress_test_reset_timer is not None
|
|
)
|
|
|
|
def _confirm_end_game(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.confirm import ConfirmWindow
|
|
|
|
# FIXME: Currently we crash calling this on client-sessions.
|
|
|
|
# Select cancel by default; this occasionally gets called by accident
|
|
# in a fit of button mashing and this will help reduce damage.
|
|
ConfirmWindow(
|
|
bui.Lstr(resource=self._r + '.exitToMenuText'),
|
|
self._end_game,
|
|
cancel_is_selected=True,
|
|
)
|
|
|
|
def _confirm_end_test(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.confirm import ConfirmWindow
|
|
|
|
# Select cancel by default; this occasionally gets called by accident
|
|
# in a fit of button mashing and this will help reduce damage.
|
|
ConfirmWindow(
|
|
bui.Lstr(resource=self._r + '.exitToMenuText'),
|
|
self._end_game,
|
|
cancel_is_selected=True,
|
|
)
|
|
|
|
def _confirm_end_replay(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.confirm import ConfirmWindow
|
|
|
|
# Select cancel by default; this occasionally gets called by accident
|
|
# in a fit of button mashing and this will help reduce damage.
|
|
ConfirmWindow(
|
|
bui.Lstr(resource=self._r + '.exitToMenuText'),
|
|
self._end_game,
|
|
cancel_is_selected=True,
|
|
)
|
|
|
|
def _confirm_leave_party(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.confirm import ConfirmWindow
|
|
|
|
# Select cancel by default; this occasionally gets called by accident
|
|
# in a fit of button mashing and this will help reduce damage.
|
|
ConfirmWindow(
|
|
bui.Lstr(resource=self._r + '.leavePartyConfirmText'),
|
|
self._leave_party,
|
|
cancel_is_selected=True,
|
|
)
|
|
|
|
def _leave_party(self) -> None:
|
|
bs.disconnect_from_host()
|
|
|
|
def _end_game(self) -> None:
|
|
assert bui.app.classic is not None
|
|
if not self._root_widget:
|
|
return
|
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
bui.app.classic.return_to_main_menu_session_gracefully(reset_ui=False)
|
|
|
|
def _leave(self) -> None:
|
|
if self._input_player:
|
|
self._input_player.remove_from_game()
|
|
elif self._connected_to_remote_player:
|
|
if self._input_device:
|
|
self._input_device.detach_from_player()
|
|
self._resume()
|
|
|
|
def _credits(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.creditslist import CreditsListWindow
|
|
|
|
self._save_state()
|
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
assert bui.app.classic is not None
|
|
bui.app.ui_v1.set_main_menu_window(
|
|
CreditsListWindow(
|
|
origin_widget=self._credits_button
|
|
).get_root_widget()
|
|
)
|
|
|
|
def _howtoplay(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.helpui import HelpWindow
|
|
|
|
self._save_state()
|
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
assert bui.app.classic is not None
|
|
bui.app.ui_v1.set_main_menu_window(
|
|
HelpWindow(
|
|
main_menu=True, origin_widget=self._how_to_play_button
|
|
).get_root_widget()
|
|
)
|
|
|
|
def _settings(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.settings.allsettings import AllSettingsWindow
|
|
|
|
self._save_state()
|
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
assert bui.app.classic is not None
|
|
bui.app.ui_v1.set_main_menu_window(
|
|
AllSettingsWindow(
|
|
origin_widget=self._settings_button
|
|
).get_root_widget()
|
|
)
|
|
|
|
def _resume_and_call(self, call: Callable[[], Any]) -> None:
|
|
self._resume()
|
|
call()
|
|
|
|
def _do_game_service_press(self) -> None:
|
|
self._save_state()
|
|
if bui.app.classic is not None:
|
|
bui.app.classic.show_online_score_ui()
|
|
else:
|
|
logging.warning('classic is required to show game service ui')
|
|
|
|
def _save_state(self) -> None:
|
|
# Don't do this for the in-game menu.
|
|
if self._in_game:
|
|
return
|
|
assert bui.app.classic is not None
|
|
ui = bui.app.ui_v1
|
|
sel = self._root_widget.get_selected_child()
|
|
if sel == self._start_button:
|
|
ui.main_menu_selection = 'Start'
|
|
elif sel == self._gather_button:
|
|
ui.main_menu_selection = 'Gather'
|
|
elif sel == self._watch_button:
|
|
ui.main_menu_selection = 'Watch'
|
|
elif sel == self._how_to_play_button:
|
|
ui.main_menu_selection = 'HowToPlay'
|
|
elif sel == self._credits_button:
|
|
ui.main_menu_selection = 'Credits'
|
|
elif sel == self._settings_button:
|
|
ui.main_menu_selection = 'Settings'
|
|
elif sel == self._account_button:
|
|
ui.main_menu_selection = 'Account'
|
|
elif sel == self._store_button:
|
|
ui.main_menu_selection = 'Store'
|
|
elif sel == self._quit_button:
|
|
ui.main_menu_selection = 'Quit'
|
|
elif sel == self._demo_menu_button:
|
|
ui.main_menu_selection = 'DemoMenu'
|
|
else:
|
|
print('unknown widget in main menu store selection:', sel)
|
|
ui.main_menu_selection = 'Start'
|
|
|
|
def _restore_state(self) -> None:
|
|
# pylint: disable=too-many-branches
|
|
|
|
# Don't do this for the in-game menu.
|
|
if self._in_game:
|
|
return
|
|
assert bui.app.classic is not None
|
|
sel_name = bui.app.ui_v1.main_menu_selection
|
|
sel: bui.Widget | None
|
|
if sel_name is None:
|
|
sel_name = 'Start'
|
|
if sel_name == 'HowToPlay':
|
|
sel = self._how_to_play_button
|
|
elif sel_name == 'Gather':
|
|
sel = self._gather_button
|
|
elif sel_name == 'Watch':
|
|
sel = self._watch_button
|
|
elif sel_name == 'Credits':
|
|
sel = self._credits_button
|
|
elif sel_name == 'Settings':
|
|
sel = self._settings_button
|
|
elif sel_name == 'Account':
|
|
sel = self._account_button
|
|
elif sel_name == 'Store':
|
|
sel = self._store_button
|
|
elif sel_name == 'Quit':
|
|
sel = self._quit_button
|
|
elif sel_name == 'DemoMenu':
|
|
sel = self._demo_menu_button
|
|
else:
|
|
sel = self._start_button
|
|
if sel is not None:
|
|
bui.containerwidget(edit=self._root_widget, selected_child=sel)
|
|
|
|
def _gather_press(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.gather import GatherWindow
|
|
|
|
self._save_state()
|
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
assert bui.app.classic is not None
|
|
bui.app.ui_v1.set_main_menu_window(
|
|
GatherWindow(origin_widget=self._gather_button).get_root_widget()
|
|
)
|
|
|
|
def _watch_press(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.watch import WatchWindow
|
|
|
|
self._save_state()
|
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
assert bui.app.classic is not None
|
|
bui.app.ui_v1.set_main_menu_window(
|
|
WatchWindow(origin_widget=self._watch_button).get_root_widget()
|
|
)
|
|
|
|
def _play_press(self) -> None:
|
|
# pylint: disable=cyclic-import
|
|
from bauiv1lib.play import PlayWindow
|
|
|
|
self._save_state()
|
|
bui.containerwidget(edit=self._root_widget, transition='out_left')
|
|
|
|
assert bui.app.classic is not None
|
|
bui.app.ui_v1.selecting_private_party_playlist = False
|
|
bui.app.ui_v1.set_main_menu_window(
|
|
PlayWindow(origin_widget=self._start_button).get_root_widget()
|
|
)
|
|
|
|
def _resume(self) -> None:
|
|
assert bui.app.classic is not None
|
|
bui.app.classic.resume()
|
|
if self._root_widget:
|
|
bui.containerwidget(edit=self._root_widget, transition='out_right')
|
|
bui.app.ui_v1.clear_main_menu_window()
|
|
|
|
# If there's callbacks waiting for this window to go away, call them.
|
|
for call in bui.app.ui_v1.main_menu_resume_callbacks:
|
|
call()
|
|
del bui.app.ui_v1.main_menu_resume_callbacks[:]
|