From 752999da85639f00e9bfa97a096dc21850763928 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Mon, 26 Oct 2020 21:00:40 -0500 Subject: [PATCH] Made the Gather UI a bit more compact on small/medium screens --- .efrocachemap | 32 +++++------ assets/src/ba_data/python/_ba.py | 6 +- .../python/bastd/ui/gather/__init__.py | 22 ++++++-- .../python/bastd/ui/gather/abouttab.py | 10 ++-- .../python/bastd/ui/gather/publictab.py | 56 +++++++++---------- docs/ba_module.md | 5 +- src/ballistica/ballistica.cc | 2 +- .../python/methods/python_methods_ui.cc | 21 +++++-- 8 files changed, 89 insertions(+), 65 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 527065e0..ada7d9de 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -3932,24 +3932,24 @@ "assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450", "assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e", "assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f", - "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/5a/0e/c0d740728ec6a91c4058db0de580", - "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/b2/5e/fd7b9b92e62dd673b3f0b8bde257", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1c/cf/0bcbafccaf1e7cc3e7f2e0fb1a51", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/39/82/ed8272b0ef178a7d625227729b93", - "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/1b/34/79ba915806f7984d2821c16e61aa", - "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/0d/80/f7277f55432bb4685f0605169d16", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9c/d2/f2d25f1ede5d806a553ce1da129a", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1b/42/b968b868eedd97b7be64a1728bfe", - "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/79/99/e8fa8f51f33ca94705a4eca05673", - "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/2d/dd/3deb44f89955ba8ffdd9ff1fec30", - "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/cb/57/dd199c247cbd2a9651da09eaafcf", - "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/85/a7/968e92f45eb512b0a6546fe64157", + "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/5d/5f/7e353ad61a992fd31b1c27918e89", + "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/61/77/65d2fd041d9f8fea8d7e4733a5ec", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/70/6c/a1111ede41bda66b5c4dda4162cb", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f6/24/3d45f90a537c7f19496b8dd8101c", + "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/01/b9/a4862fd7ac4b9bc46109bf0f3fb5", + "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/70/58/4b5840cd26a0853197fa63c39f26", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/93/de/4dc052ed052de5353044adaf3b56", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f9/5c/69ff3f14bb37bd82956088c16872", + "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/5c/4d/acecaaafada62747b7beb884348b", + "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/08/81/f3cfc8bb76bc05b0ee53ccd47b67", + "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/45/9b/635f9392ba5c0561949e519ec8c3", + "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/5f/f2/4136816295eca8ffefabc60a8b6e", "build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/80/d2/d1c6766cf07f4c4828bbd5899f79", "build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/de/49/2cfc34ac856737d903954db5571b", "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/17/9a/fa66aafdf31fc9bdd92ce382c619", "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/86/de/7d9c9a2b7bba34c630130ed759c9", - "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/de/16/c12809a8a4754329e6da3c1586ec", - "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/71/51/edcfb82938dcd3410f2d31547db6", - "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/73/77/b5c1338380f41d341a799921fe69", - "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0d/5c/c180e7a4d28600125e8dc2b1fbcc" + "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/43/1d/ee9ee9bf897787f0b469853bb426", + "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/98/d2/7a106e580aa03db5c9f91ccd8bc8", + "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/38/28/2cbd3a1eeec91e71ff8f4a048d73", + "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/25/4d/c9b30b84774de5ee5eed1927d6b1" } \ No newline at end of file diff --git a/assets/src/ba_data/python/_ba.py b/assets/src/ba_data/python/_ba.py index cb7afb6b..0640f6fe 100644 --- a/assets/src/ba_data/python/_ba.py +++ b/assets/src/ba_data/python/_ba.py @@ -3388,7 +3388,8 @@ def scrollwidget(edit: ba.Widget = None, simple_culling_v: float = None, selection_loops_to_parent: bool = None, claims_left_right: bool = None, - claims_tab: bool = None) -> ba.Widget: + claims_tab: bool = None, + autoselect: bool = None) -> ba.Widget: """scrollwidget(edit: ba.Widget = None, parent: ba.Widget = None, size: Sequence[float] = None, position: Sequence[float] = None, background: bool = None, selected_child: ba.Widget = None, @@ -3398,7 +3399,8 @@ def scrollwidget(edit: ba.Widget = None, simple_culling_v: float = None, selection_loops_to_parent: bool = None, claims_left_right: bool = None, - claims_tab: bool = None) -> ba.Widget + claims_tab: bool = None, + autoselect: bool = None) -> ba.Widget Create or edit a scroll widget. diff --git a/assets/src/ba_data/python/bastd/ui/gather/__init__.py b/assets/src/ba_data/python/bastd/ui/gather/__init__.py index 46e0b0ca..253c0629 100644 --- a/assets/src/ba_data/python/bastd/ui/gather/__init__.py +++ b/assets/src/ba_data/python/bastd/ui/gather/__init__.py @@ -89,11 +89,16 @@ class GatherWindow(ba.Window): size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) + condensed = uiscale is not ba.UIScale.LARGE + t_offs_y = (0 if not condensed else + 25 if uiscale is ba.UIScale.MEDIUM else 17) ba.textwidget(parent=self._root_widget, - position=(self._width * 0.5, self._height - 42), + position=(self._width * 0.5, + self._height - 42 + t_offs_y), size=(0, 0), color=ba.app.ui.title_color, - scale=1.5, + scale=(1.5 if not condensed else + 1.0 if uiscale is ba.UIScale.MEDIUM else 0.6), h_align='center', v_align='center', text=ba.Lstr(resource=self._r + '.titleText'), @@ -103,7 +108,7 @@ class GatherWindow(ba.Window): subplatform = ba.app.subplatform scroll_buffer_h = 130 + 2 * x_offs - tab_buffer_h = 250 + 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, ba.Lstr]] = [ @@ -120,9 +125,13 @@ class GatherWindow(ba.Window): tabdefs.append( (self.TabID.MANUAL, ba.Lstr(resource=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 self._tab_row = TabRow(self._root_widget, tabdefs, - pos=(tab_buffer_h * 0.5, self._height - 130), + pos=(tab_buffer_h * 0.5, + self._height - 130 + tabs_top_extra), size=(self._width - tab_buffer_h, 50), on_select_call=self._set_tab) @@ -148,10 +157,11 @@ class GatherWindow(ba.Window): left_widget=_ba.get_special_widget('back_button')) self._scroll_width = self._width - scroll_buffer_h - self._scroll_height = self._height - 180.0 + self._scroll_height = self._height - 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 + self._scroll_bottom = (self._height - self._scroll_height - 79 - 48 + + tabs_top_extra) buffer_h = 10 buffer_v = 4 diff --git a/assets/src/ba_data/python/bastd/ui/gather/abouttab.py b/assets/src/ba_data/python/bastd/ui/gather/abouttab.py index 7fd1975b..de0a16b6 100644 --- a/assets/src/ba_data/python/bastd/ui/gather/abouttab.py +++ b/assets/src/ba_data/python/bastd/ui/gather/abouttab.py @@ -31,11 +31,11 @@ class AboutGatherTab(GatherTab): region_left: float, region_bottom: float, ) -> ba.Widget: - message = ba.Lstr(resource='gatherWindow.aboutDescriptionText', - subs=[('${PARTY}', - ba.charstr(ba.SpecialChar.PARTY_ICON)), - ('${BUTTON}', - ba.charstr(ba.SpecialChar.TOP_BUTTON))]) + message = ba.Lstr( + resource='gatherWindow.aboutDescriptionText', + subs=[('${PARTY}', ba.charstr(ba.SpecialChar.PARTY_ICON)), + ('${BUTTON}', ba.charstr(ba.SpecialChar.TOP_BUTTON))], + ) # Let's not talk about sharing in vr-mode; its tricky to fit more # than one head in a VR-headset ;-) diff --git a/assets/src/ba_data/python/bastd/ui/gather/publictab.py b/assets/src/ba_data/python/bastd/ui/gather/publictab.py index da07f0e9..94e7bd19 100644 --- a/assets/src/ba_data/python/bastd/ui/gather/publictab.py +++ b/assets/src/ba_data/python/bastd/ui/gather/publictab.py @@ -179,10 +179,10 @@ class PublicGatherTab(GatherTab): self._join_text: Optional[ba.Widget] = None self._host_text: Optional[ba.Widget] = None self._local_address: Optional[str] = None - self._last_public_party_connect_attempt_time: Optional[float] = None + self._last_connect_attempt_time: Optional[float] = None self._sub_tab: SubTabType = SubTabType.JOIN self._selection: Optional[Selection] = None - self._refreshing_public_party_list = False + self._refreshing_list = False self._update_timer: Optional[ba.Timer] = None self._host_scrollwidget: Optional[ba.Widget] = None self._host_name_text: Optional[ba.Widget] = None @@ -195,9 +195,9 @@ class PublicGatherTab(GatherTab): self._host_max_party_size_plus_button: (Optional[ba.Widget]) = None self._host_status_text: Optional[ba.Widget] = None self._public_parties: Dict[str, PartyEntry] = {} - self._last_public_party_list_rebuild_time: Optional[float] = None - self._first_public_party_list_rebuild_time: Optional[float] = None - self._next_public_party_entry_index = 0 + self._last_list_rebuild_time: Optional[float] = None + self._first_list_rebuild_time: Optional[float] = None + self._next_entry_index = 0 def on_activate( self, @@ -329,7 +329,7 @@ class PublicGatherTab(GatherTab): edit=self._host_text, color=active_color if value is SubTabType.HOST else inactive_color) - # Clear anything in existence in our sub-tabs. + # Clear anything existing in the old sub-tab. for widget in self._container.get_children(): if widget and widget not in {self._host_text, self._join_text}: widget.delete() @@ -356,8 +356,8 @@ class PublicGatherTab(GatherTab): # Reset our list of public parties. self._public_parties = {} - self._last_public_party_list_rebuild_time = 0 - self._first_public_party_list_rebuild_time = None + self._last_list_rebuild_time = 0 + self._first_list_rebuild_time = None ba.textwidget(text=ba.Lstr(resource='nameText'), parent=self._container, size=(0, 0), @@ -397,13 +397,13 @@ class PublicGatherTab(GatherTab): parent=self._container, simple_culling_v=10, position=((c_width - sub_scroll_width) * 0.5, v), - size=(sub_scroll_width, sub_scroll_height)) - ba.widget(edit=scrollw, autoselect=True) - colw = self._host_columnwidget = ba.containerwidget(parent=scrollw, - background=False, - size=(400, 400)) - ba.containerwidget(edit=scrollw, claims_left_right=True) - ba.containerwidget(edit=colw, claims_left_right=True) + size=(sub_scroll_width, sub_scroll_height), + claims_left_right=True, + autoselect=True) + self._host_columnwidget = ba.containerwidget(parent=scrollw, + background=False, + size=(400, 400), + claims_left_right=True) self._join_status_text = ba.textwidget( parent=self._container, @@ -550,18 +550,18 @@ class PublicGatherTab(GatherTab): # pylint: disable=too-many-locals # pylint: disable=too-many-statements cur_time = ba.time(ba.TimeType.REAL) - if self._first_public_party_list_rebuild_time is None: - self._first_public_party_list_rebuild_time = cur_time + if self._first_list_rebuild_time is None: + self._first_list_rebuild_time = cur_time # Update faster for the first few seconds; # then ease off to keep the list from jumping around. - since_first = cur_time - self._first_public_party_list_rebuild_time + since_first = cur_time - self._first_list_rebuild_time wait_time = (1.0 if since_first < 2.0 else 2.5 if since_first < 10.0 else 5.0) - assert self._last_public_party_list_rebuild_time is not None - if cur_time - self._last_public_party_list_rebuild_time < wait_time: + assert self._last_list_rebuild_time is not None + if cur_time - self._last_list_rebuild_time < wait_time: return - self._last_public_party_list_rebuild_time = cur_time + self._last_list_rebuild_time = cur_time # First off, check for the existence of our column widget; # if we don't have this, we're done. @@ -594,7 +594,7 @@ class PublicGatherTab(GatherTab): # Ew; this rebuilding generates deferred selection callbacks # so we need to generated deferred ignore notices for ourself. def refresh_on() -> None: - self._refreshing_public_party_list = True + self._refreshing_list = True ba.pushcall(refresh_on) @@ -701,7 +701,7 @@ class PublicGatherTab(GatherTab): # So our selection callbacks can start firing.. def refresh_off() -> None: - self._refreshing_public_party_list = False + self._refreshing_list = False ba.pushcall(refresh_off) @@ -745,8 +745,8 @@ class PublicGatherTab(GatherTab): next_ping_time=ba.time(ba.TimeType.REAL) + 0.001 * party_in['pd'], ping=None, - index=self._next_public_party_entry_index) - self._next_public_party_entry_index += 1 + index=self._next_entry_index) + self._next_entry_index += 1 assert isinstance(party.address, str) assert isinstance(party.next_ping_time, float) @@ -968,13 +968,13 @@ class PublicGatherTab(GatherTab): # Rate limit this a bit. now = time.time() - last_connect_time = self._last_public_party_connect_attempt_time + last_connect_time = self._last_connect_attempt_time if last_connect_time is None or now - last_connect_time > 2.0: _ba.connect_to_party(address, port=port) - self._last_public_party_connect_attempt_time = now + self._last_connect_attempt_time = now def _set_public_party_selection(self, sel: Selection) -> None: - if self._refreshing_public_party_list: + if self._refreshing_list: return self._selection = sel diff --git a/docs/ba_module.md b/docs/ba_module.md index c47b585d..b9bf5a21 100644 --- a/docs/ba_module.md +++ b/docs/ba_module.md @@ -1,5 +1,5 @@ -

last updated on 2020-10-25 for Ballistica version 1.5.27 build 20224

+

last updated on 2020-10-26 for Ballistica version 1.5.27 build 20227

This page documents the Python classes and functions in the 'ba' module, which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please let me know. Happy modding!


@@ -7036,7 +7036,8 @@ Currently the 'clients' option only works for transient messages.

simple_culling_v: float = None, selection_loops_to_parent: bool = None, claims_left_right: bool = None, - claims_tab: bool = None) -> ba.Widget

+ claims_tab: bool = None, + autoselect: bool = None) -> ba.Widget

Create or edit a scroll widget.

diff --git a/src/ballistica/ballistica.cc b/src/ballistica/ballistica.cc index 9fa746e4..65f019ce 100644 --- a/src/ballistica/ballistica.cc +++ b/src/ballistica/ballistica.cc @@ -21,7 +21,7 @@ namespace ballistica { // These are set automatically via script; don't change here. -const int kAppBuildNumber = 20227; +const int kAppBuildNumber = 20228; const char* kAppVersion = "1.5.27"; // Our standalone globals. diff --git a/src/ballistica/python/methods/python_methods_ui.cc b/src/ballistica/python/methods/python_methods_ui.cc index 02686359..b1f032de 100644 --- a/src/ballistica/python/methods/python_methods_ui.cc +++ b/src/ballistica/python/methods/python_methods_ui.cc @@ -1180,6 +1180,7 @@ auto PyScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) PyObject* selection_loops_to_parent_obj{Py_None}; PyObject* claims_left_right_obj{Py_None}; PyObject* claims_tab_obj{Py_None}; + PyObject* autoselect_obj{Py_None}; static const char* kwlist[] = {"edit", "parent", @@ -1197,16 +1198,17 @@ auto PyScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) "selection_loops_to_parent", "claims_left_right", "claims_tab", + "autoselect", nullptr}; if (!PyArg_ParseTupleAndKeywords( - args, keywds, "|OOOOOOOOOOOOOOOO", const_cast(kwlist), + args, keywds, "|OOOOOOOOOOOOOOOOO", const_cast(kwlist), &edit_obj, &parent_obj, &size_obj, &pos_obj, &background_obj, &selected_child_obj, &capture_arrows_obj, &on_select_call_obj, ¢er_small_content_obj, &color_obj, &highlight_obj, &border_opacity_obj, &simple_culling_v_obj, &selection_loops_to_parent_obj, &claims_left_right_obj, - &claims_tab_obj)) + &claims_tab_obj, &autoselect_obj)) return nullptr; if (!g_game->IsInUIContext()) { @@ -1288,6 +1290,9 @@ auto PyScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) if (claims_tab_obj != Py_None) { widget->set_claims_tab(Python::GetPyBool(claims_tab_obj)); } + if (autoselect_obj != Py_None) { + widget->set_auto_select(Python::GetPyBool(autoselect_obj)); + } // If making a new widget add it at the end. if (edit_obj == Py_None) { @@ -1320,6 +1325,7 @@ auto PyHScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) PyObject* simple_culling_h_obj = Py_None; PyObject* claims_left_right_obj = Py_None; PyObject* claims_tab_obj = Py_None; + PyObject* autoselect_obj = Py_None; static const char* kwlist[] = {"edit", "parent", @@ -1336,15 +1342,16 @@ auto PyHScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) "simple_culling_h", "claims_left_right", "claims_tab", + "autoselect", nullptr}; if (!PyArg_ParseTupleAndKeywords( - args, keywds, "|OOOOOOOOOOOOOOO", const_cast(kwlist), + args, keywds, "|OOOOOOOOOOOOOOOO", const_cast(kwlist), &edit_obj, &parent_obj, &size_obj, &pos_obj, &background_obj, &selected_child_obj, &capture_arrows_obj, &on_select_call_obj, ¢er_small_content_obj, &color_obj, &highlight_obj, &border_opacity_obj, &simple_culling_h_obj, &claims_left_right_obj, - &claims_tab_obj)) + &claims_tab_obj, &autoselect_obj)) return nullptr; if (!g_game->IsInUIContext()) { @@ -1421,6 +1428,9 @@ auto PyHScrollWidget(PyObject* self, PyObject* args, PyObject* keywds) if (claims_tab_obj != Py_None) { widget->set_claims_tab(Python::GetPyBool(claims_tab_obj)); } + if (autoselect_obj != Py_None) { + widget->set_auto_select(Python::GetPyBool(autoselect_obj)); + } // if making a new widget add it at the end if (edit_obj == Py_None) { @@ -2633,7 +2643,8 @@ PyMethodDef PythonMethodsUI::methods_def[] = { " simple_culling_v: float = None,\n" " selection_loops_to_parent: bool = None,\n" " claims_left_right: bool = None,\n" - " claims_tab: bool = None) -> ba.Widget\n" + " claims_tab: bool = None,\n" + " autoselect: bool = None) -> ba.Widget\n" "\n" "Create or edit a scroll widget.\n" "\n"