diff --git a/src/assets/ba_data/python/bauiv1lib/gather/manualtab.py b/src/assets/ba_data/python/bauiv1lib/gather/manualtab.py index b75f14c99..ce8bb81d0 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/manualtab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/manualtab.py @@ -99,6 +99,7 @@ def __init__(self, window: GatherWindow) -> None: self._party_edit_name_text: bui.Widget | None = None self._party_edit_addr_text: bui.Widget | None = None self._party_edit_port_text: bui.Widget | None = None + self._no_parties_added_text: bui.Widget | None = None def on_activate( self, @@ -456,6 +457,24 @@ def _build_favorites_tab(self, region_height: float) -> None: claims_left_right=True, ) + self._no_parties_added_text = bui.textwidget( + parent=self._container, + size=(0, 0), + h_align='center', + v_align='center', + text='', + color=(0.6, 0.6, 0.6), + scale=1.2, + position=( + ( + (190 if uiscale is bui.UIScale.SMALL else 225) + + sub_scroll_width * 0.5 + ), + v + sub_scroll_height * 0.5 + ), + glow_type='uniform', + ) + self._favorite_selected = None self._refresh_favorites() @@ -698,6 +717,12 @@ def _refresh_favorites(self) -> None: assert self._favorites_scroll_width is not None assert self._favorites_connect_button is not None + + bui.textwidget( + edit=self._no_parties_added_text, + text='', + ) + num_of_fav = 0 for i, server in enumerate(servers): txt = bui.textwidget( parent=self._columnwidget, @@ -721,11 +746,13 @@ def _refresh_favorites(self) -> None: ) if i == 0: bui.widget(edit=txt, up_widget=self._favorites_text) + self._favorite_selected = server bui.widget( edit=txt, left_widget=self._favorites_connect_button, right_widget=txt, ) + num_of_fav = num_of_fav + 1 # If there's no servers, allow selecting out of the scroll area bui.containerwidget( @@ -738,6 +765,11 @@ def _refresh_favorites(self) -> None: up_widget=self._favorites_text, left_widget=self._favorites_connect_button, ) + if num_of_fav == 0: + bui.textwidget( + edit=self._no_parties_added_text, + text=bui.Lstr(resource='noPartiesAddedText'), + ) def on_deactivate(self) -> None: self._access_check_timer = None @@ -803,8 +835,15 @@ def _save_server( } config.commit() bui.getsound('gunCocking').play() + bui.screenmessage( + bui.Lstr(resource='addedToFavoritesText'), + color=(0, 1, 0), + ) else: - bui.screenmessage('Invalid Address', color=(1, 0, 0)) + bui.screenmessage( + bui.Lstr(resource='internal.invalidAddressErrorText'), + color=(1, 0, 0), + ) bui.getsound('error').play() def _host_lookup_result( diff --git a/src/assets/ba_data/python/bauiv1lib/party.py b/src/assets/ba_data/python/bauiv1lib/party.py index f9250334e..98323f857 100644 --- a/src/assets/ba_data/python/bauiv1lib/party.py +++ b/src/assets/ba_data/python/bauiv1lib/party.py @@ -40,6 +40,7 @@ def __init__(self, origin: Sequence[float] = (0, 0)): if uiscale is bui.UIScale.MEDIUM else 600 ) + self._display_old_msgs = True super().__init__( root_widget=bui.containerwidget( size=(self._width, self._height), @@ -143,12 +144,6 @@ def __init__(self, origin: Sequence[float] = (0, 0)): ) self._chat_texts: list[bui.Widget] = [] - # add all existing messages if chat is not muted - if not bui.app.config.resolve('Chat Muted'): - msgs = bs.get_chat_messages() - for msg in msgs: - self._add_msg(msg) - self._text_field = txt = bui.textwidget( parent=self._root_widget, editable=True, @@ -243,10 +238,13 @@ def _on_menu_button_press(self) -> None: if uiscale is bui.UIScale.MEDIUM else 1.23 ), - choices=['unmute' if is_muted else 'mute'], + choices=['unmute' if is_muted else 'mute', 'add_to_favorites'], choices_display=[ bui.Lstr( resource='chatUnMuteText' if is_muted else 'chatMuteText' + ), + bui.Lstr( + resource='AddToFavoritesText' ) ], current_choice='unmute' if is_muted else 'mute', @@ -270,6 +268,12 @@ def _update(self) -> None: first.delete() else: bui.textwidget(edit=self._muted_text, color=(1, 1, 1, 0.0)) + # add all existing messages if chat is not muted + if self._display_old_msgs: + msgs = bs.get_chat_messages() + for msg in msgs: + self._add_msg(msg) + self._display_old_msgs = False # update roster section roster = bs.get_game_roster() @@ -467,10 +471,70 @@ def popup_menu_selected_choice( cfg = bui.app.config cfg['Chat Muted'] = choice == 'mute' cfg.apply_and_commit() + self._display_old_msgs = True self._update() + if choice == 'add_to_favorites': + info = bs.get_connection_to_host_info_2() + if info is not None: + self._add_to_favorites( + name=info.name, + address=info.address, + port_num=info.port, + ) + else: + bui.screenmessage( + bui.Lstr( + resource='NotConnectedToServerText' + ) + ) else: print(f'unhandled popup type: {self._popup_type}') + def _add_to_favorites( + self, + name: str, + address: str | None, + port_num: int | None + ) -> None: + addr = address + if addr == '': + bui.screenmessage( + bui.Lstr(resource='internal.invalidAddressErrorText'), + color=(1, 0, 0), + ) + bui.getsound('error').play() + return + port = port_num if port_num is not None else -1 + if port > 65535 or port < 0: + bui.screenmessage( + bui.Lstr(resource='internal.invalidPortErrorText'), + color=(1, 0, 0), + ) + bui.getsound('error').play() + return + config = bui.app.config + + if addr: + if not isinstance(config.get('Saved Servers'), dict): + config['Saved Servers'] = {} + config['Saved Servers'][f'{addr}@{port}'] = { + 'addr': addr, + 'port': port, + 'name': name, + } + config.commit() + bui.getsound('gunCocking').play() + bui.screenmessage( + bui.Lstr(value='Added To Favorites'), + color=(0, 1, 0), + ) + else: + bui.screenmessage( + bui.Lstr(resource='internal.invalidAddressErrorText'), + color=(1, 0, 0), + ) + bui.getsound('error').play() + def popup_menu_closing(self, popup_window: PopupWindow) -> None: """Called when the popup is closing.""" diff --git a/src/assets/ba_data/python/bauiv1lib/profile/browser.py b/src/assets/ba_data/python/bauiv1lib/profile/browser.py index 38cbbd3c6..2d79765b0 100644 --- a/src/assets/ba_data/python/bauiv1lib/profile/browser.py +++ b/src/assets/ba_data/python/bauiv1lib/profile/browser.py @@ -197,9 +197,11 @@ def __init__( bui.containerwidget( edit=self._root_widget, selected_child=self._scrollwidget ) - self._columnwidget = bui.columnwidget( - parent=self._scrollwidget, border=2, margin=0 - ) + self._subcontainer = bui.containerwidget( + parent=self._scrollwidget, + size=(self._scroll_width, 32), + background=False, + ) v -= 255 self._profiles: dict[str, dict[str, Any]] | None = None self._selected_profile = selected_profile @@ -357,8 +359,10 @@ def _back(self) -> None: def _refresh(self) -> None: # pylint: disable=too-many-locals + # pylint: disable=too-many-statements from efro.util import asserttype from bascenev1 import PlayerProfilesChangedMessage + from bascenev1lib.actor import spazappearance assert bui.app.classic is not None @@ -374,14 +378,27 @@ def _refresh(self) -> None: assert self._profiles is not None items = list(self._profiles.items()) items.sort(key=lambda x: asserttype(x[0], str).lower()) + spazzes = spazappearance.get_appearances() + spazzes.sort() + icon_textures = [ + bui.gettexture(bui.app.classic.spaz_appearances[s].icon_texture) + for s in spazzes + ] + icon_tint_textures = [ + bui.gettexture( + bui.app.classic.spaz_appearances[s].icon_mask_texture + ) + for s in spazzes + ] index = 0 + y_val = 35 * (len(self._profiles) - 1) account_name: str | None if plus.get_v1_account_state() == 'signed_in': account_name = plus.get_v1_account_display_string() else: account_name = None widget_to_select = None - for p_name, _ in items: + for p_name, p_info in items: if p_name == '__account__' and account_name is None: continue color, _highlight = bui.app.classic.get_player_profile_colors( @@ -393,10 +410,29 @@ def _refresh(self) -> None: if p_name == '__account__' else bui.app.classic.get_player_profile_icon(p_name) + p_name ) + + try: + char_index = spazzes.index(p_info['character']) + except Exception: + char_index = spazzes.index('Spaz') + assert isinstance(tval, str) + character = bui.buttonwidget( + parent=self._subcontainer, + position=(0, y_val), + size=(28, 28), + label='', + color=(1, 1, 1), + mask_texture=bui.gettexture('characterIconMask'), + tint_color=color, + tint2_color=_highlight, + texture=icon_textures[char_index], + tint_texture=icon_tint_textures[char_index], + selectable=False, + ) txtw = bui.textwidget( - parent=self._columnwidget, - position=(0, 32), + parent=self._subcontainer, + position=(35, y_val), size=((self._width - 210) / scl, 28), text=bui.Lstr(value=tval), h_align='left', @@ -411,8 +447,11 @@ def _refresh(self) -> None: ) if index == 0: bui.widget(edit=txtw, up_widget=self._back_button) + if self._selected_profile is None: + self._selected_profile = p_name bui.widget(edit=txtw, show_buffer_top=40, show_buffer_bottom=40) self._profile_widgets.append(txtw) + self._profile_widgets.append(character) # Select/show this one if it was previously selected # (but defer till after this loop since our height is @@ -421,10 +460,15 @@ def _refresh(self) -> None: widget_to_select = txtw index += 1 + y_val -= 35 + bui.containerwidget( + edit=self._subcontainer, + size=(self._scroll_width, index * 35), + ) if widget_to_select is not None: - bui.columnwidget( - edit=self._columnwidget, + bui.containerwidget( + edit=self._subcontainer, selected_child=widget_to_select, visible_child=widget_to_select, ) diff --git a/src/assets/ba_data/python/bauiv1lib/profile/edit.py b/src/assets/ba_data/python/bauiv1lib/profile/edit.py index b216d1f97..0c27d78c7 100644 --- a/src/assets/ba_data/python/bauiv1lib/profile/edit.py +++ b/src/assets/ba_data/python/bauiv1lib/profile/edit.py @@ -190,7 +190,7 @@ def __init__( self._clipped_name_text = bui.textwidget( parent=self._root_widget, text='', - position=(540 + x_inset, v - 8), + position=(580 + x_inset, v - 8), flatness=1.0, shadow=0.0, scale=0.55, @@ -396,6 +396,16 @@ def __init__( autoselect=True, on_activate_call=self.upgrade_profile, ) + self._random_name_button = bui.buttonwidget( + parent=self._root_widget, + label=bui.Lstr(resource='randomText'), + size=(30, 20), + position=(495 + x_inset, v - 20), + button_type='square', + color=(0.6, 0.5, 0.65), + autoselect=True, + on_activate_call=self.assign_random_name, + ) self._update_clipped_name() self._clipped_name_timer = bui.AppTimer( @@ -504,8 +514,17 @@ def __init__( ) self._update_character() + def assign_random_name(self) -> None: + """Assigning a random name to the player.""" + names = bs.get_random_names() + name = names[random.randrange(len(names))] + bui.textwidget( + edit=self._text_field, + text=name, + ) + def upgrade_profile(self) -> None: - """Attempt to ugrade the profile to global.""" + """Attempt to upgrade the profile to global.""" from bauiv1lib import account from bauiv1lib.profile import upgrade as pupgrade diff --git a/src/assets/ba_data/python/bauiv1lib/settings/plugins.py b/src/assets/ba_data/python/bauiv1lib/settings/plugins.py index c2327bbea..f5c106b54 100644 --- a/src/assets/ba_data/python/bauiv1lib/settings/plugins.py +++ b/src/assets/ba_data/python/bauiv1lib/settings/plugins.py @@ -129,6 +129,15 @@ def __init__( settings_button_x = 670 if uiscale is bui.UIScale.SMALL else 570 + self._num_plugins_text = bui.textwidget( + parent=self._root_widget, + position=(settings_button_x - 130, self._height - 38), + size=(0, 0), + text='', + h_align='center', + v_align='center', + ) + self._category_button = bui.buttonwidget( parent=self._root_widget, scale=0.7, @@ -174,6 +183,17 @@ def __init__( ) bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget) + self._no_plugins_installed_text = bui.textwidget( + parent=self._root_widget, + position=(self._width * 0.5, self._height * 0.5), + size=(0, 0), + text='', + color=(0.6, 0.6, 0.6), + scale=0.8, + h_align='center', + v_align='center', + ) + if bui.app.meta.scanresults is None: bui.screenmessage( 'Still scanning plugins; please try again.', color=(1, 0, 0) @@ -268,6 +288,7 @@ def _clear_scroll_widget(self) -> None: def _show_plugins(self) -> None: # pylint: disable=too-many-locals # pylint: disable=too-many-branches + # pylint: disable=too-many-statements plugspecs = bui.app.plugins.plugin_specs plugstates: dict[str, dict] = bui.app.config.setdefault('Plugins', {}) assert isinstance(plugstates, dict) @@ -279,6 +300,11 @@ def _show_plugins(self) -> None: plugspecs_sorted = sorted(plugspecs.items()) + bui.textwidget( + edit=self._no_plugins_installed_text, + text='', + ) + for _classpath, plugspec in plugspecs_sorted: # counting number of enabled and disabled plugins # plugstate = plugstates.setdefault(plugspec[0], {}) @@ -377,6 +403,17 @@ def _show_plugins(self) -> None: bui.widget(edit=check, show_buffer_top=40, show_buffer_bottom=40) num_shown += 1 + bui.textwidget( + edit=self._num_plugins_text, + text=str(num_shown), + ) + + if num_shown == 0: + bui.textwidget( + edit=self._no_plugins_installed_text, + text=bui.Lstr(resource='noPluginsInstalledText'), + ) + def _save_state(self) -> None: try: sel = self._root_widget.get_selected_child() diff --git a/src/assets/ba_data/python/bauiv1lib/watch.py b/src/assets/ba_data/python/bauiv1lib/watch.py index c2e50e4ce..b43b93210 100644 --- a/src/assets/ba_data/python/bauiv1lib/watch.py +++ b/src/assets/ba_data/python/bauiv1lib/watch.py @@ -598,6 +598,7 @@ def _refresh_my_replays(self) -> None: edit=txt, up_widget=self._tab_row.tabs[self.TabID.MY_REPLAYS].button, ) + self._my_replay_selected = name def _save_state(self) -> None: try: