gather window is now screen-size-responsive

This commit is contained in:
Eric Froemling 2025-01-22 14:18:55 -08:00
parent b634f4e14f
commit 34ed3be00c
No known key found for this signature in database
10 changed files with 221 additions and 216 deletions

34
.efrocachemap generated
View File

@ -432,7 +432,7 @@
"build/assets/ba_data/audio/zoeOw.ogg": "b2d705c31c9dcc1efdc71394764c3beb",
"build/assets/ba_data/audio/zoePickup01.ogg": "e9366dc2d2b8ab8b0c4e2c14c02d0789",
"build/assets/ba_data/audio/zoeScream01.ogg": "903e0e45ee9b3373e9d9ce20c814374e",
"build/assets/ba_data/data/langdata.json": "637e524f148eedb5a773a5d3529c2f51",
"build/assets/ba_data/data/langdata.json": "bb872f4df766a9cb353677300055066b",
"build/assets/ba_data/data/languages/arabic.json": "32b9849fb8389b8c7798f0b744620318",
"build/assets/ba_data/data/languages/belarussian.json": "009b452aa308bf2b2f7e92d9b78ba5ff",
"build/assets/ba_data/data/languages/chinese.json": "5363a79f843e6be7ef47a840f47cc17d",
@ -462,11 +462,11 @@
"build/assets/ba_data/data/languages/russian.json": "780d1857df77ef59104d5dac75415bd6",
"build/assets/ba_data/data/languages/serbian.json": "623fa4129a1154c2f32ed7867e56ff6a",
"build/assets/ba_data/data/languages/slovak.json": "c11c29708b3742cdc2a92b4fa0d6d29f",
"build/assets/ba_data/data/languages/spanish.json": "5bc22761e8a37cbdf38d4bced753b6ba",
"build/assets/ba_data/data/languages/spanish.json": "ccb08a06f13d56c5d0b752a03c49865e",
"build/assets/ba_data/data/languages/swedish.json": "3b179e7333183c70adb0811246b09959",
"build/assets/ba_data/data/languages/tamil.json": "ead39b864228696a9b0d19344bc4b5ec",
"build/assets/ba_data/data/languages/thai.json": "383540a1e9c7c131ac579f51afc87471",
"build/assets/ba_data/data/languages/turkish.json": "8a406f0fd91b55e3f8e57cd92aea5a52",
"build/assets/ba_data/data/languages/turkish.json": "f4c3e07275180114d951c002be5ef101",
"build/assets/ba_data/data/languages/ukrainian.json": "0db55824759119aca74d2ee8ffe6daae",
"build/assets/ba_data/data/languages/venetian.json": "acea003316bef657925d776dd460e713",
"build/assets/ba_data/data/languages/vietnamese.json": "017d8aa346d0c23a229a8a9acccf79a1",
@ -4182,14 +4182,14 @@
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "af6b01b85380b1a9874f8d7e7db435e4",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "23039996985b4aa93dff5aaf41067ea4",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "56775e7415d62ea2d92ac73c6eb944a4",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "43417f65a4b03d86a0dd149975d79a4f",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "03bf4a2e606ee1fd85b3ba9839da87e6",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "10fc3f2ecef4e957b26d1ec82b441255",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "551815823c8fc7bdb730d23ce32dfac1",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b33d1932f2beb9b3d2769c8f4e35dcad",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "ee6d0760189953307799b7e06858aa87",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "89e6739f26b419ed71548fbba21f476f",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "3ef2b3179c424dfa97f4e50250cccc57",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9b2170e71927e097b3e92a8ad993c81f",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "4bd75394e66b2eba2ec35d1d6119fd7a",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "372d0ad3ef2bcd7f8fa93b9d83e2a300",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "e6f8c4f279931182f28722a33b9e3fc0",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "8e28d37c93494d05479d3132a6525967",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e0db14d2a7df35e29fc4cdfe9c6c42d6",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "4d70703c4eba1a402fbc2d997d84aa93",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "bb64e2182b1a533679f93c5997f14584",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "4d70703c4eba1a402fbc2d997d84aa93",
@ -4202,14 +4202,14 @@
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "116b500c2d57caf06619408b2176e83b",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "e3e9d9c7a94f8cd22939839fd8fbc178",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "116b500c2d57caf06619408b2176e83b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "def3aafdaa027b8311290549d5466a03",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "a168a3ab32ab82e1775d2ac33f4ee859",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "3023cfdf99e6a1af1c5daacd0a5ef93d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "4b2dad34e4edf32a00d6c32e7ed703e2",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "c1d35a57b5c9a84c4da24eaf5bdf210f",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "49080baa202c08e0da85e8562ff7d889",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "04a2c999f64cde37a786fffec1b53e34",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "af531d6fb63cd54cd02dd5a756fd167b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "3f2dddebc7313756f2f6ee83c377f265",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "d4a5d87e4ae724ae5e49cec56cb17a58",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "72d5ac0df3f03d2fceb5f015e9071ca3",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "12b693aea7eb0a3d501bea4ae7de75e1",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "091f0ff2326739346407622d4d8cc449",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "4ad50d22cac50a74f4953abf24016088",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "0be3a0c54d84379972bacc70f0c16887",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "cf56d84fe7f9a4bd8bf93172b561c5c0",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "06042d31df0ff9af96b99477162e2a91",

View File

@ -89,7 +89,7 @@ class AccountSettingsWindow(bui.MainWindow):
self._scroll_width = target_width
self._scroll_height = target_height - 33
scroll_y = yoffs - 61 - self._scroll_height
scroll_bottom = yoffs - 61 - self._scroll_height
self._sign_in_button = None
self._sign_in_text = None
@ -174,7 +174,10 @@ class AccountSettingsWindow(bui.MainWindow):
parent=self._root_widget,
highlight=False,
size=(self._scroll_width, self._scroll_height),
position=(self._width * 0.5 - self._scroll_width * 0.5, scroll_y),
position=(
self._width * 0.5 - self._scroll_width * 0.5,
scroll_bottom,
),
claims_left_right=True,
selection_loops_to_parent=True,
border_opacity=0.4,

View File

@ -55,7 +55,7 @@ class AchievementsWindow(bui.MainWindow):
scroll_width = target_width
scroll_height = target_height - 25
scroll_y = yoffs - 54 - scroll_height
scroll_bottom = yoffs - 54 - scroll_height
super().__init__(
root_widget=bui.containerwidget(
@ -121,7 +121,7 @@ class AchievementsWindow(bui.MainWindow):
self._scrollwidget = bui.scrollwidget(
parent=self._root_widget,
size=(scroll_width, scroll_height),
position=(self._width * 0.5 - scroll_width * 0.5, scroll_y),
position=(self._width * 0.5 - scroll_width * 0.5, scroll_bottom),
capture_arrows=True,
simple_culling_v=10,
border_opacity=0.4,

View File

@ -88,39 +88,56 @@ class GatherWindow(bui.MainWindow):
bui.set_analytics_screen('Gather Window')
uiscale = bui.app.ui_v1.uiscale
self._width = 1640 if uiscale is bui.UIScale.SMALL else 1040
x_offs = 200 if uiscale is bui.UIScale.SMALL else 0
y_offs = -65 if uiscale is bui.UIScale.SMALL else 0
self._height = (
650
self._width = (
1640
if uiscale is bui.UIScale.SMALL
else 680 if uiscale is bui.UIScale.MEDIUM else 800
else 1100 if uiscale is bui.UIScale.MEDIUM else 1200
)
self._height = (
1000
if uiscale is bui.UIScale.SMALL
else 730 if uiscale is bui.UIScale.MEDIUM else 900
)
self._current_tab: GatherWindow.TabID | None = None
extra_top = 20 if uiscale is bui.UIScale.SMALL else 0
self._r = 'gatherWindow'
# Do some fancy math to fill all available screen area up to the
# size of our backing container. This lets us fit to the exact
# screen shape at small ui scale.
screensize = bui.get_virtual_screen_size()
scale = (
1.15
if uiscale is bui.UIScale.SMALL
else 0.88 if uiscale is bui.UIScale.MEDIUM else 0.66
)
# Calc screen size in our local container space and clamp to a
# bit smaller than our container size.
target_width = min(self._width - 130, screensize[0] / scale)
target_height = min(self._height - 130, screensize[1] / scale)
# To get top/left coords, go to the center of our window and
# offset by half the width/height of our target area.
yoffs = 0.5 * self._height + 0.5 * target_height + 30.0
self._scroll_width = target_width
self._scroll_height = target_height - 57
self._scroll_bottom = yoffs - 90 - self._scroll_height
self._scroll_left = (self._width - self._scroll_width) * 0.5
super().__init__(
root_widget=bui.containerwidget(
size=(self._width, self._height + extra_top),
size=(self._width, self._height),
toolbar_visibility=(
'menu_tokens'
if uiscale is bui.UIScale.SMALL
else 'menu_full'
),
scale=(
1.15
if uiscale is bui.UIScale.SMALL
else 0.95 if uiscale is bui.UIScale.MEDIUM else 0.7
),
stack_offset=(
(0, 0)
if uiscale is bui.UIScale.SMALL
else (0, 0) if uiscale is bui.UIScale.MEDIUM else (0, 0)
),
scale=scale,
),
transition=transition,
origin_widget=origin_widget,
# We're affected by screen size only at small ui-scale.
refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL,
)
if uiscale is bui.UIScale.SMALL:
@ -131,46 +148,35 @@ class GatherWindow(bui.MainWindow):
else:
self._back_button = btn = bui.buttonwidget(
parent=self._root_widget,
position=(70 + x_offs, self._height - 74 + y_offs),
size=(140, 60),
position=(70, yoffs - 43),
size=(60, 60),
scale=1.1,
autoselect=True,
label=bui.Lstr(resource='backText'),
button_type='back',
label=bui.charstr(bui.SpecialChar.BACK),
button_type='backSmall',
on_activate_call=self.main_window_back,
)
bui.containerwidget(edit=self._root_widget, cancel_button=btn)
bui.buttonwidget(
edit=btn,
button_type='backSmall',
position=(70 + x_offs, self._height - 78),
size=(60, 60),
label=bui.charstr(bui.SpecialChar.BACK),
)
condensed = uiscale is not bui.UIScale.LARGE
t_offs_y = (
0 if not condensed else 25 if uiscale is bui.UIScale.MEDIUM else 33
)
bui.textwidget(
parent=self._root_widget,
position=(self._width * 0.5, self._height - 42 + t_offs_y + y_offs),
position=(
self._width * 0.5,
yoffs - (53 if uiscale is bui.UIScale.SMALL else 4),
),
size=(0, 0),
color=bui.app.ui_v1.title_color,
scale=(
1.5
if not condensed
else 1.0 if uiscale is bui.UIScale.MEDIUM else 1.0
),
scale=1.0,
h_align='center',
v_align='center',
text=bui.Lstr(resource=f'{self._r}.titleText'),
text=(
''
if uiscale is bui.UIScale.SMALL
else bui.Lstr(resource=f'{self._r}.titleText')
),
maxwidth=320,
)
scroll_buffer_h = 130 + 2 * x_offs
tab_buffer_h = (320 if condensed else 250) + 2 * x_offs
# Build up the set of tabs we want.
tabdefs: list[tuple[GatherWindow.TabID, bui.Lstr]] = [
(self.TabID.ABOUT, bui.Lstr(resource=f'{self._r}.aboutText'))
@ -192,17 +198,16 @@ class GatherWindow(bui.MainWindow):
(self.TabID.MANUAL, bui.Lstr(resource=f'{self._r}.manualText'))
)
# On small UI, push our tabs up closer to the top of the screen to
# save a bit of space.
tabs_top_extra = 42 if condensed else 0
tab_inset = 100.0
tab_inset_extra_r = 150 if uiscale is bui.UIScale.SMALL else 0
self._tab_row = TabRow(
self._root_widget,
tabdefs,
size=(self._scroll_width - 2.0 * tab_inset - tab_inset_extra_r, 50),
pos=(
tab_buffer_h * 0.5,
self._height - 130 + tabs_top_extra + y_offs,
self._scroll_left + tab_inset,
self._scroll_bottom + self._scroll_height,
),
size=(self._width - tab_buffer_h, 50),
on_select_call=bui.WeakCall(self._set_tab),
)
@ -220,45 +225,26 @@ class GatherWindow(bui.MainWindow):
if tabtype is not None:
self._tabs[tab_id] = tabtype(self)
# Eww; tokens meter may or may not be here; should be smarter
# about this.
bui.widget(
edit=self._tab_row.tabs[tabdefs[-1][0]].button,
right_widget=bui.get_special_widget('squad_button'),
right_widget=bui.get_special_widget('tokens_meter'),
)
if uiscale is bui.UIScale.SMALL:
bui.widget(
edit=self._tab_row.tabs[tabdefs[0][0]].button,
left_widget=bui.get_special_widget('back_button'),
up_widget=bui.get_special_widget('back_button'),
)
self._scroll_width = self._width - scroll_buffer_h
self._scroll_height = (
self._height
- (270.0 if uiscale is bui.UIScale.SMALL else 180.0)
+ tabs_top_extra
)
self._scroll_left = (self._width - self._scroll_width) * 0.5
self._scroll_bottom = (
self._height
- self._scroll_height
- 79
- 48
+ tabs_top_extra
+ y_offs
)
buffer_h = 10
buffer_v = 4
# Not actually using a scroll widget anymore; just an image.
bui.imagewidget(
parent=self._root_widget,
size=(self._scroll_width, self._scroll_height),
position=(
self._scroll_left - buffer_h,
self._scroll_bottom - buffer_v,
),
size=(
self._scroll_width + 2 * buffer_h,
self._scroll_height + 2 * buffer_v,
self._width * 0.5 - self._scroll_width * 0.5,
self._scroll_bottom,
),
texture=bui.gettexture('scrollWidget'),
mesh_transparent=bui.getmesh('softEdgeOutside'),

View File

@ -162,7 +162,8 @@ class UIRow:
Selection(party.get_key(), SelectionComponent.STATS_BUTTON),
),
size=(120, 40),
position=(sub_scroll_width * 0.66 + hpos, 1 + vpos),
# position=(sub_scroll_width * 0.66 + hpos, 1 + vpos),
position=(sub_scroll_width - 270.0, 1 + vpos),
scale=0.9,
)
if existing_selection == Selection(
@ -176,7 +177,8 @@ class UIRow:
text=str(party.size) + '/' + str(party.size_max),
parent=columnwidget,
size=(0, 0),
position=(sub_scroll_width * 0.86 + hpos, 20 + vpos),
# position=(sub_scroll_width * 0.86 + hpos, 20 + vpos),
position=(sub_scroll_width - 100, 20 + vpos),
scale=0.7,
color=(0.8, 0.8, 0.8),
h_align='right',
@ -191,7 +193,8 @@ class UIRow:
self._ping_widget = bui.textwidget(
parent=columnwidget,
size=(0, 0),
position=(sub_scroll_width * 0.94 + hpos, 20 + vpos),
# position=(sub_scroll_width * 0.94 + hpos, 20 + vpos),
position=(sub_scroll_width - 30.0, 20 + vpos),
scale=0.7,
h_align='right',
v_align='center',
@ -372,6 +375,7 @@ class PublicGatherTab(GatherTab):
self._host_max_party_size_value: bui.Widget | None = None
self._host_max_party_size_minus_button: bui.Widget | None = None
self._host_max_party_size_plus_button: bui.Widget | None = None
self._join_sub_scroll_width: float | None = None
self._host_status_text: bui.Widget | None = None
self._signed_in = False
self._ui_rows: list[UIRow] = []
@ -474,7 +478,8 @@ class PublicGatherTab(GatherTab):
)
bui.widget(edit=self._join_text, right_widget=self._host_text)
# Attempt to fetch our local address so we have it for error messages.
# Attempt to fetch our local address so we have it for error
# messages.
if self._local_address is None:
AddrFetchThread(bui.WeakCall(self._fetch_local_addr_cb)).start()
@ -491,9 +496,9 @@ class PublicGatherTab(GatherTab):
@override
def save_state(self) -> None:
# Save off a small number of parties with the lowest ping; we'll
# display these immediately when our UI comes back up which should
# be enough to make things feel nice and crisp while we do a full
# server re-query or whatnot.
# display these immediately when our UI comes back up which
# should be enough to make things feel nice and crisp while we
# do a full server re-query or whatnot.
assert bui.app.classic is not None
bui.app.ui_v1.window_states[type(self)] = State(
sub_tab=self._sub_tab,
@ -523,7 +528,7 @@ class PublicGatherTab(GatherTab):
self._next_entry_index = state.next_entry_index
# FIXME: should save/restore these too?..
# FIXME: should save/restore these too?
self._have_server_list_response = state.have_server_list_response
self._have_valid_server_list = state.have_valid_server_list
self._filter_value = state.filter_value
@ -539,9 +544,8 @@ class PublicGatherTab(GatherTab):
if playsound:
bui.getsound('click01').play()
# Reset our selection.
# (prevents selecting something way down the list if we switched away
# and came back)
# Reset our selection (prevents selecting something way down the
# list if we switched away and came back).
self._selection = None
self._have_user_selected_row = False
@ -579,7 +583,9 @@ class PublicGatherTab(GatherTab):
c_width = region_width
c_height = region_height - 20
sub_scroll_height = c_height - 125
sub_scroll_width = 830
self._join_sub_scroll_width = sub_scroll_width = min(
1200, region_width - 80
)
v = c_height - 35
v -= 60
filter_txt = bui.Lstr(resource='filterText')
@ -726,6 +732,9 @@ class PublicGatherTab(GatherTab):
)
v -= 30
# Nudge party name and size values to be mostly centered.
xoffs = region_width * 0.5 - 500
party_name_text = bui.Lstr(
resource='gatherWindow.partyNameText',
fallback_resource='editGameListWindow.nameText',
@ -739,14 +748,14 @@ class PublicGatherTab(GatherTab):
maxwidth=200,
scale=0.8,
color=bui.app.ui_v1.infotextcolor,
position=(210, v - 9),
position=(210 + xoffs, v - 9),
text=party_name_text,
)
self._host_name_text = bui.textwidget(
parent=self._container,
editable=True,
size=(535, 40),
position=(230, v - 30),
position=(230 + xoffs, v - 30),
text=bui.app.config.get('Public Party Name', ''),
maxwidth=494,
shadow=0.3,
@ -766,7 +775,7 @@ class PublicGatherTab(GatherTab):
maxwidth=200,
scale=0.8,
color=bui.app.ui_v1.infotextcolor,
position=(210, v - 9),
position=(210 + xoffs, v - 9),
text=bui.Lstr(
resource='maxPartySizeText',
fallback_resource='maxConnectionsText',
@ -779,7 +788,7 @@ class PublicGatherTab(GatherTab):
v_align='center',
scale=1.2,
color=(1, 1, 1),
position=(240, v - 9),
position=(240 + xoffs, v - 9),
text=str(bs.get_public_party_max_size()),
)
btn1 = self._host_max_party_size_minus_button = bui.buttonwidget(
@ -788,7 +797,7 @@ class PublicGatherTab(GatherTab):
on_activate_call=bui.WeakCall(
self._on_max_public_party_size_minus_press
),
position=(280, v - 26),
position=(280 + xoffs, v - 26),
label='-',
autoselect=True,
)
@ -798,7 +807,7 @@ class PublicGatherTab(GatherTab):
on_activate_call=bui.WeakCall(
self._on_max_public_party_size_plus_press
),
position=(350, v - 26),
position=(350 + xoffs, v - 26),
label='+',
autoselect=True,
)
@ -859,8 +868,8 @@ class PublicGatherTab(GatherTab):
position=(c_width * 0.5, v),
)
# If public sharing is already on,
# launch a status-check immediately.
# If public sharing is already on, launch a status-check
# immediately.
if bs.get_public_party_enabled():
self._do_status_check()
@ -884,9 +893,9 @@ class PublicGatherTab(GatherTab):
self._pending_party_infos += parties_in
# To avoid causing a stutter here, we do most processing of
# these entries incrementally in our _update() method.
# The one thing we do here is prune parties not contained in
# this result.
# these entries incrementally in our _update() method. The one
# thing we do here is prune parties not contained in this
# result.
for partyval in list(self._parties.values()):
partyval.claimed = False
for party_in in parties_in:
@ -904,7 +913,6 @@ class PublicGatherTab(GatherTab):
self._parties_sorted = [p for p in self._parties_sorted if p[1].claimed]
self._party_lists_dirty = True
# self._update_server_list()
if DEBUG_PROCESSING:
print(
f'Handled public party query results in '
@ -926,10 +934,10 @@ class PublicGatherTab(GatherTab):
self._filter_value = filter_value
self._party_lists_dirty = True
# Also wipe out party clean-row states.
# (otherwise if a party disappears from a row due to
# filtering and then reappears on that same row when
# the filter is removed it may not update)
# Also wipe out party clean-row states (otherwise if
# a party disappears from a row due to filtering and
# then reappears on that same row when the filter is
# removed it may not update).
for party in self._parties.values():
party.clean_display_index = None
@ -965,9 +973,9 @@ class PublicGatherTab(GatherTab):
)
bui.spinnerwidget(edit=self._join_status_spinner, visible=False)
else:
# If we have a valid list, show no status; just the list.
# Otherwise show either 'loading...' or 'error' depending
# on whether this is our first go-round.
# If we have a valid list, show no status; just the
# list. Otherwise show either 'loading...' or 'error'
# depending on whether this is our first go-round.
if self._have_valid_server_list:
bui.textwidget(edit=self._join_status_text, text='')
bui.spinnerwidget(
@ -985,19 +993,6 @@ class PublicGatherTab(GatherTab):
else:
# Show our loading spinner.
bui.textwidget(edit=self._join_status_text, text='')
# bui.textwidget(
# edit=self._join_status_text,
# text=bui.Lstr(
# value='${A}...',
# subs=[
# (
# '${A}',
#
# bui.Lstr(resource='store.loadingText'),
# )
# ],
# ),
# )
bui.spinnerwidget(
edit=self._join_status_spinner, visible=True
)
@ -1037,7 +1032,8 @@ class PublicGatherTab(GatherTab):
)
return
sub_scroll_width = 830
assert self._join_sub_scroll_width is not None
sub_scroll_width = self._join_sub_scroll_width
lineheight = 42
sub_scroll_height = lineheight * len(self._parties_displayed) + 50
bui.containerwidget(
@ -1045,27 +1041,27 @@ class PublicGatherTab(GatherTab):
)
# Any time our height changes, reset the refresh back to the top
# so we don't see ugly empty spaces appearing during initial list
# filling.
# so we don't see ugly empty spaces appearing during initial
# list filling.
if sub_scroll_height != self._last_sub_scroll_height:
self._refresh_ui_row = 0
self._last_sub_scroll_height = sub_scroll_height
# Also note that we need to redisplay everything since its pos
# will have changed.. :(
# Also note that we need to redisplay everything since its
# pos will have changed.. :(
for party in self._parties.values():
party.clean_display_index = None
# Ew; this rebuilding generates deferred selection callbacks
# so we need to push deferred notices so we know to ignore them.
# Ew; this rebuilding generates deferred selection callbacks so
# we need to push deferred notices so we know to ignore them.
def refresh_on() -> None:
self._refreshing_list = True
bui.pushcall(refresh_on)
# Ok, now here's the deal: we want to avoid creating/updating this
# entire list at one time because it will lead to hitches. So we
# refresh individual rows quickly in a loop.
# Ok, now here's the deal: we want to avoid creating/updating
# this entire list at one time because it will lead to hitches.
# So we refresh individual rows quickly in a loop.
rowcount = min(12, len(self._parties_displayed))
party_vals_displayed = list(self._parties_displayed.values())
@ -1075,9 +1071,10 @@ class PublicGatherTab(GatherTab):
self._ui_rows.append(UIRow())
refresh_row = len(self._ui_rows) - 1
# For the first few seconds after getting our first server-list,
# refresh only the top section of the list; this allows the lowest
# ping servers to show up more quickly.
# For the first few seconds after getting our first
# server-list, refresh only the top section of the list;
# this allows the lowest ping servers to show up more
# quickly.
if self._first_valid_server_list_time is not None:
if time.time() - self._first_valid_server_list_time < 4.0:
if refresh_row > 40:
@ -1107,7 +1104,8 @@ class PublicGatherTab(GatherTab):
def _process_pending_party_infos(self) -> None:
starttime = time.time()
# We want to do this in small enough pieces to not cause UI hitches.
# We want to do this in small enough pieces to not cause UI
# hitches.
chunksize = 30
parties_in = self._pending_party_infos[:chunksize]
self._pending_party_infos = self._pending_party_infos[chunksize:]
@ -1191,16 +1189,16 @@ class PublicGatherTab(GatherTab):
else:
self._parties_displayed = dict(self._parties_sorted)
# Any time our selection disappears from the displayed list, go back to
# auto-selecting the top entry.
# Any time our selection disappears from the displayed list, go
# back to auto-selecting the top entry.
if (
self._selection is not None
and self._selection.entry_key not in self._parties_displayed
):
self._have_user_selected_row = False
# Whenever the user hasn't selected something, keep the first visible
# row selected.
# Whenever the user hasn't selected something, keep the first
# visible row selected.
if not self._have_user_selected_row and self._parties_displayed:
firstpartykey = next(iter(self._parties_displayed))
self._selection = Selection(firstpartykey, SelectionComponent.NAME)
@ -1252,8 +1250,8 @@ class PublicGatherTab(GatherTab):
party.next_ping_time <= now
and bui.app.classic.ping_thread_count < 15
):
# Crank the interval up for high-latency or non-responding
# parties to save us some useless work.
# Crank the interval up for high-latency or
# non-responding parties to save us some useless work.
mult = 1
if party.ping_responses == 0:
if party.ping_attempts > 4:
@ -1283,16 +1281,16 @@ class PublicGatherTab(GatherTab):
def _ping_callback(
self, address: str, port: int | None, result: float | None
) -> None:
# Look for a widget corresponding to this target.
# If we find one, update our list.
# Look for a widget corresponding to this target. If we find
# one, update our list.
party_key = f'{address}_{port}'
party = self._parties.get(party_key)
if party is not None:
if result is not None:
party.ping_responses += 1
# We now smooth ping a bit to reduce jumping around in the list
# (only where pings are relatively good).
# We now smooth ping a bit to reduce jumping around in the
# list (only where pings are relatively good).
current_ping = party.ping
if current_ping is not None and result is not None and result < 150:
smoothing = 0.7
@ -1419,8 +1417,8 @@ class PublicGatherTab(GatherTab):
bui.getsound('shieldUp').play()
bs.set_public_party_enabled(True)
# In GUI builds we want to authenticate clients only when hosting
# public parties.
# In GUI builds we want to authenticate clients only when
# hosting public parties.
bs.set_authenticate_clients(True)
self._do_status_check()
@ -1436,8 +1434,8 @@ class PublicGatherTab(GatherTab):
def _on_stop_advertising_press(self) -> None:
bs.set_public_party_enabled(False)
# In GUI builds we want to authenticate clients only when hosting
# public parties.
# In GUI builds we want to authenticate clients only when
# hosting public parties.
bs.set_authenticate_clients(False)
bui.getsound('shieldDown').play()
text = self._host_status_text

View File

@ -58,7 +58,7 @@ class HelpWindow(bui.MainWindow):
scroll_width = target_width
scroll_height = target_height - 36
scroll_y = yoffs - 64 - scroll_height
scroll_bottom = yoffs - 64 - scroll_height
super().__init__(
root_widget=bui.containerwidget(
@ -114,7 +114,7 @@ class HelpWindow(bui.MainWindow):
self._scrollwidget = bui.scrollwidget(
parent=self._root_widget,
size=(scroll_width, scroll_height),
position=(width * 0.5 - scroll_width * 0.5, scroll_y),
position=(width * 0.5 - scroll_width * 0.5, scroll_bottom),
simple_culling_v=100.0,
capture_arrows=True,
border_opacity=0.4,

View File

@ -346,7 +346,7 @@ class InboxWindow(bui.MainWindow):
scroll_width = target_width
scroll_height = target_height - 31
scroll_y = yoffs - 59 - scroll_height
scroll_bottom = yoffs - 59 - scroll_height
super().__init__(
root_widget=bui.containerwidget(
@ -420,7 +420,7 @@ class InboxWindow(bui.MainWindow):
self._scrollwidget = bui.scrollwidget(
parent=self._root_widget,
size=(scroll_width, scroll_height),
position=(self._width * 0.5 - scroll_width * 0.5, scroll_y),
position=(self._width * 0.5 - scroll_width * 0.5, scroll_bottom),
capture_arrows=True,
simple_culling_v=200,
claims_left_right=True,

View File

@ -84,7 +84,7 @@ class PlaylistBrowserWindow(bui.MainWindow):
self._scroll_width = target_width
self._scroll_height = target_height - 31
scroll_y = yoffs - 60 - self._scroll_height
scroll_bottom = yoffs - 60 - self._scroll_height
super().__init__(
root_widget=bui.containerwidget(
@ -145,7 +145,10 @@ class PlaylistBrowserWindow(bui.MainWindow):
parent=self._root_widget,
highlight=False,
size=(self._scroll_width, self._scroll_height),
position=(self._width * 0.5 - self._scroll_width * 0.5, scroll_y),
position=(
self._width * 0.5 - self._scroll_width * 0.5,
scroll_bottom,
),
border_opacity=0.4,
center_small_content_horizontally=True,
)

View File

@ -70,7 +70,7 @@ class AdvancedSettingsWindow(bui.MainWindow):
self._scroll_width = target_width
self._scroll_height = target_height - 25
scroll_y = yoffs - 56 - self._scroll_height
scroll_bottom = yoffs - 56 - self._scroll_height
super().__init__(
root_widget=bui.containerwidget(
@ -162,7 +162,10 @@ class AdvancedSettingsWindow(bui.MainWindow):
self._scrollwidget = bui.scrollwidget(
parent=self._root_widget,
size=(self._scroll_width, self._scroll_height),
position=(self._width * 0.5 - self._scroll_width * 0.5, scroll_y),
position=(
self._width * 0.5 - self._scroll_width * 0.5,
scroll_bottom,
),
simple_culling_v=20.0,
highlight=False,
center_small_content_horizontally=True,

View File

@ -45,36 +45,49 @@ class WatchWindow(bui.MainWindow):
self._r = 'watchWindow'
uiscale = bui.app.ui_v1.uiscale
self._width = 1440 if uiscale is bui.UIScale.SMALL else 1040
x_inset = 200 if uiscale is bui.UIScale.SMALL else 0
self._height = (
570
900
if uiscale is bui.UIScale.SMALL
else 670 if uiscale is bui.UIScale.MEDIUM else 800
)
self._current_tab: WatchWindow.TabID | None = None
extra_top = 20 if uiscale is bui.UIScale.SMALL else 0
# Do some fancy math to fill all available screen area up to the
# size of our backing container. This lets us fit to the exact
# screen shape at small ui scale.
screensize = bui.get_virtual_screen_size()
scale = (
1.32
if uiscale is bui.UIScale.SMALL
else 0.85 if uiscale is bui.UIScale.MEDIUM else 0.65
)
# Calc screen size in our local container space and clamp to a
# bit smaller than our container size.
target_width = min(self._width - 120, screensize[0] / scale)
target_height = min(self._height - 120, screensize[1] / scale)
# To get top/left coords, go to the center of our window and
# offset by half the width/height of our target area.
self.yoffs = 0.5 * self._height + 0.5 * target_height + 30.0
self._scroll_width = target_width
self._scroll_height = target_height - 60
self._scroll_y = self.yoffs - 90 - self._scroll_height
super().__init__(
root_widget=bui.containerwidget(
size=(self._width, self._height + extra_top),
size=(self._width, self._height),
toolbar_visibility=(
'menu_minimal'
if uiscale is bui.UIScale.SMALL
else 'menu_full'
),
scale=(
1.32
if uiscale is bui.UIScale.SMALL
else 0.85 if uiscale is bui.UIScale.MEDIUM else 0.65
),
stack_offset=(
(0, 30)
if uiscale is bui.UIScale.SMALL
else (0, 0) if uiscale is bui.UIScale.MEDIUM else (0, 0)
),
scale=scale,
),
transition=transition,
origin_widget=origin_widget,
# We're affected by screen size only at small ui-scale.
refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL,
)
if uiscale is bui.UIScale.SMALL:
@ -86,7 +99,7 @@ class WatchWindow(bui.MainWindow):
self._back_button = btn = bui.buttonwidget(
parent=self._root_widget,
autoselect=True,
position=(70 + x_inset, self._height - 74),
position=(70, self.yoffs - 50),
size=(60, 60),
scale=1.1,
label=bui.charstr(bui.SpecialChar.BACK),
@ -99,11 +112,11 @@ class WatchWindow(bui.MainWindow):
parent=self._root_widget,
position=(
self._width * 0.5,
self._height - (65 if uiscale is bui.UIScale.SMALL else 38),
self.yoffs - (44 if uiscale is bui.UIScale.SMALL else 10),
),
size=(0, 0),
color=bui.app.ui_v1.title_color,
scale=0.7 if uiscale is bui.UIScale.SMALL else 1.5,
scale=0.6 if uiscale is bui.UIScale.SMALL else 1.5,
h_align='center',
v_align='center',
text=(
@ -119,17 +132,19 @@ class WatchWindow(bui.MainWindow):
self.TabID.MY_REPLAYS,
bui.Lstr(resource=f'{self._r}.myReplaysText'),
),
# (self.TabID.TEST_TAB, bui.Lstr(value='Testing')),
]
scroll_buffer_h = 130 + 2 * x_inset
tab_buffer_h = 750 + 2 * x_inset
tab_bar_width = 200.0 * len(tabdefs)
tab_bar_inset = (self._scroll_width - tab_bar_width) * 0.5
self._tab_row = TabRow(
self._root_widget,
tabdefs,
pos=(tab_buffer_h * 0.5, self._height - 130),
size=(self._width - tab_buffer_h, 50),
pos=(
self._width * 0.5 - self._scroll_width * 0.5 + tab_bar_inset,
self._scroll_y + self._scroll_height,
),
size=(self._scroll_width - 2.0 * tab_bar_inset, 50),
on_select_call=self._set_tab,
)
@ -143,20 +158,13 @@ class WatchWindow(bui.MainWindow):
bbtn = bui.get_special_widget('back_button')
bui.widget(edit=first_tab.button, up_widget=bbtn, left_widget=bbtn)
self._scroll_width = self._width - scroll_buffer_h
self._scroll_height = self._height - 180
# Not actually using a scroll widget anymore; just an image.
scroll_left = (self._width - self._scroll_width) * 0.5
scroll_bottom = self._height - self._scroll_height - 79 - 48
buffer_h = 10
buffer_v = 4
bui.imagewidget(
parent=self._root_widget,
position=(scroll_left - buffer_h, scroll_bottom - buffer_v),
size=(
self._scroll_width + 2 * buffer_h,
self._scroll_height + 2 * buffer_v,
size=(self._scroll_width, self._scroll_height),
position=(
self._width * 0.5 - self._scroll_width * 0.5,
self._scroll_y,
),
texture=bui.gettexture('scrollWidget'),
mesh_transparent=bui.getmesh('softEdgeOutside'),
@ -199,7 +207,7 @@ class WatchWindow(bui.MainWindow):
if self._tab_container:
self._tab_container.delete()
scroll_left = (self._width - self._scroll_width) * 0.5
scroll_bottom = self._height - self._scroll_height - 79 - 48
scroll_bottom = self._scroll_y
# A place where tabs can store data to get cleared when
# switching to a different tab
@ -249,9 +257,9 @@ class WatchWindow(bui.MainWindow):
b_width = 140 if uiscale is bui.UIScale.SMALL else 178
b_height = (
107
110
if uiscale is bui.UIScale.SMALL
else 142 if uiscale is bui.UIScale.MEDIUM else 190
else 142 if uiscale is bui.UIScale.MEDIUM else 180
)
b_space_extra = (
0
@ -264,14 +272,18 @@ class WatchWindow(bui.MainWindow):
btnv = (
c_height
- (
48
40
if uiscale is bui.UIScale.SMALL
else 45 if uiscale is bui.UIScale.MEDIUM else 40
else 40 if uiscale is bui.UIScale.MEDIUM else 40
)
- b_height
)
btnh = 40 if uiscale is bui.UIScale.SMALL else 40
smlh = 190 if uiscale is bui.UIScale.SMALL else 225
# Roughly center buttons and scroll-widget in the middle.
xextra = (
self._scroll_width - (sub_scroll_width + b_width)
) * 0.5 - 50.0
btnh = (40 if uiscale is bui.UIScale.SMALL else 40) + xextra
smlh = (190 if uiscale is bui.UIScale.SMALL else 225) + xextra
tscl = 1.0 if uiscale is bui.UIScale.SMALL else 1.2
self._my_replays_watch_replay_button = btn1 = bui.buttonwidget(
parent=cnt,