def edit_game_pressed(self) -> None: """Should be called by supplemental UIs when a game is to be edited.""" from ba.internal import getclass if not self._playlist: return self._show_edit_ui(gametype=getclass( self._playlist[self._selected_index]['type'], subclassof=ba.GameActivity), settings=self._playlist[self._selected_index])
def _refresh(self) -> None: from ba.internal import getclass # Need to grab this here as rebuilding the list will # change it otherwise. old_selection_index = self._editcontroller.get_selected_index() while self._list_widgets: self._list_widgets.pop().delete() for index, pentry in enumerate(self._editcontroller.get_playlist()): try: cls = getclass(pentry['type'], subclassof=ba.GameActivity) desc = cls.get_settings_display_string(pentry) except Exception: ba.print_exception() desc = "(invalid: '" + pentry['type'] + "')" txtw = ba.textwidget(parent=self._columnwidget, size=(self._width - 80, 30), on_select_call=ba.Call(self._select, index), always_highlight=True, color=(0.8, 0.8, 0.8, 1.0), padding=0, maxwidth=self._scroll_width * 0.93, text=desc, on_activate_call=self._edit_button.activate, v_align='center', selectable=True) ba.widget(edit=txtw, show_buffer_top=50, show_buffer_bottom=50) # Wanna be able to jump up to the text field from the top one. if index == 0: ba.widget(edit=txtw, up_widget=self._text_field) self._list_widgets.append(txtw) if old_selection_index == index: ba.columnwidget(edit=self._columnwidget, selected_child=txtw, visible_child=txtw)
def __init__(self, sessiontype: Type[ba.Session], playlist: str, scale_origin: Tuple[float, float], delegate: Any = None): # FIXME: Tidy this up. # pylint: disable=too-many-branches # pylint: disable=too-many-statements # pylint: disable=too-many-locals from ba.internal import (getclass, have_pro, get_default_teams_playlist, get_default_free_for_all_playlist, filter_playlist) from ba.internal import get_map_class from bastd.ui.playlist import PlaylistTypeVars self._r = 'gameListWindow' self._delegate = delegate self._pvars = PlaylistTypeVars(sessiontype) self._transitioning_out = False self._do_randomize_val = (ba.app.config.get( self._pvars.config_name + ' Playlist Randomize', 0)) self._sessiontype = sessiontype self._playlist = playlist self._width = 500.0 self._height = 330.0 - 50.0 # In teams games, show the custom names/colors button. if self._sessiontype is ba.DualTeamSession: self._height += 50.0 self._row_height = 45.0 # Grab our maps to display. model_opaque = ba.getmodel('level_select_button_opaque') model_transparent = ba.getmodel('level_select_button_transparent') mask_tex = ba.gettexture('mapPreviewMask') # Poke into this playlist and see if we can display some of its maps. map_textures = [] map_texture_entries = [] rows = 0 columns = 0 game_count = 0 scl = 0.35 c_width_total = 0.0 try: max_columns = 5 name = playlist if name == '__default__': if self._sessiontype is ba.FreeForAllSession: plst = get_default_free_for_all_playlist() elif self._sessiontype is ba.DualTeamSession: plst = get_default_teams_playlist() else: raise Exception('unrecognized session-type: ' + str(self._sessiontype)) else: try: plst = ba.app.config[self._pvars.config_name + ' Playlists'][name] except Exception: print('ERROR INFO: self._config_name is:', self._pvars.config_name) print( 'ERROR INFO: playlist names are:', list(ba.app.config[self._pvars.config_name + ' Playlists'].keys())) raise plst = filter_playlist(plst, self._sessiontype, remove_unowned=False, mark_unowned=True) game_count = len(plst) for entry in plst: mapname = entry['settings']['map'] maptype: Optional[Type[ba.Map]] try: maptype = get_map_class(mapname) except Exception: maptype = None if maptype is not None: tex_name = maptype.get_preview_texture_name() if tex_name is not None: map_textures.append(tex_name) map_texture_entries.append(entry) rows = (max(0, len(map_textures) - 1) // max_columns) + 1 columns = min(max_columns, len(map_textures)) if len(map_textures) == 1: scl = 1.1 elif len(map_textures) == 2: scl = 0.7 elif len(map_textures) == 3: scl = 0.55 else: scl = 0.35 self._row_height = 128.0 * scl c_width_total = scl * 250.0 * columns if map_textures: self._height += self._row_height * rows except Exception: ba.print_exception('error listing playlist maps') show_shuffle_check_box = game_count > 1 if show_shuffle_check_box: self._height += 40 # Creates our _root_widget. scale = (1.69 if ba.app.small_ui else 1.1 if ba.app.med_ui else 0.85) super().__init__(position=scale_origin, size=(self._width, self._height), scale=scale) playlist_name: Union[str, ba.Lstr] = (self._pvars.default_list_name if playlist == '__default__' else playlist) self._title_text = ba.textwidget(parent=self.root_widget, position=(self._width * 0.5, self._height - 89 + 51), size=(0, 0), text=playlist_name, scale=1.4, color=(1, 1, 1), maxwidth=self._width * 0.7, h_align='center', v_align='center') self._cancel_button = ba.buttonwidget( parent=self.root_widget, position=(25, self._height - 53), size=(50, 50), scale=0.7, label='', color=(0.42, 0.73, 0.2), on_activate_call=self._on_cancel_press, autoselect=True, icon=ba.gettexture('crossOut'), iconscale=1.2) h_offs_img = self._width * 0.5 - c_width_total * 0.5 v_offs_img = self._height - 118 - scl * 125.0 + 50 bottom_row_buttons = [] self._have_at_least_one_owned = False for row in range(rows): for col in range(columns): tex_index = row * columns + col if tex_index < len(map_textures): tex_name = map_textures[tex_index] h = h_offs_img + scl * 250 * col v = v_offs_img - self._row_height * row entry = map_texture_entries[tex_index] owned = not (('is_unowned_map' in entry and entry['is_unowned_map']) or ('is_unowned_game' in entry and entry['is_unowned_game'])) if owned: self._have_at_least_one_owned = True try: desc = getclass(entry['type'], subclassof=ba.GameActivity ).get_config_display_string(entry) if not owned: desc = ba.Lstr( value='${DESC}\n${UNLOCK}', subs=[ ('${DESC}', desc), ('${UNLOCK}', ba.Lstr( resource='unlockThisInTheStoreText')) ]) desc_color = (0, 1, 0) if owned else (1, 0, 0) except Exception: desc = ba.Lstr(value='(invalid)') desc_color = (1, 0, 0) btn = ba.buttonwidget( parent=self.root_widget, size=(scl * 240.0, scl * 120.0), position=(h, v), texture=ba.gettexture(tex_name if owned else 'empty'), model_opaque=model_opaque if owned else None, on_activate_call=ba.Call(ba.screenmessage, desc, desc_color), label='', color=(1, 1, 1), autoselect=True, extra_touch_border_scale=0.0, model_transparent=model_transparent if owned else None, mask_texture=mask_tex if owned else None) if row == 0 and col == 0: ba.widget(edit=self._cancel_button, down_widget=btn) if row == rows - 1: bottom_row_buttons.append(btn) if not owned: # Ewww; buttons don't currently have alpha so in this # case we draw an image over our button with an empty # texture on it. ba.imagewidget(parent=self.root_widget, size=(scl * 260.0, scl * 130.0), position=(h - 10.0 * scl, v - 4.0 * scl), draw_controller=btn, color=(1, 1, 1), texture=ba.gettexture(tex_name), model_opaque=model_opaque, opacity=0.25, model_transparent=model_transparent, mask_texture=mask_tex) ba.imagewidget(parent=self.root_widget, size=(scl * 100, scl * 100), draw_controller=btn, position=(h + scl * 70, v + scl * 10), texture=ba.gettexture('lock')) # Team names/colors. self._custom_colors_names_button: Optional[ba.Widget] if self._sessiontype is ba.DualTeamSession: y_offs = 50 if show_shuffle_check_box else 0 self._custom_colors_names_button = ba.buttonwidget( parent=self.root_widget, position=(100, 200 + y_offs), size=(290, 35), on_activate_call=ba.WeakCall(self._custom_colors_names_press), autoselect=True, textcolor=(0.8, 0.8, 0.8), label=ba.Lstr(resource='teamNamesColorText')) if not have_pro(): ba.imagewidget( parent=self.root_widget, size=(30, 30), position=(95, 202 + y_offs), texture=ba.gettexture('lock'), draw_controller=self._custom_colors_names_button) else: self._custom_colors_names_button = None # Shuffle. def _cb_callback(val: bool) -> None: self._do_randomize_val = val cfg = ba.app.config cfg[self._pvars.config_name + ' Playlist Randomize'] = self._do_randomize_val cfg.commit() if show_shuffle_check_box: self._shuffle_check_box = ba.checkboxwidget( parent=self.root_widget, position=(110, 200), scale=1.0, size=(250, 30), autoselect=True, text=ba.Lstr(resource=self._r + '.shuffleGameOrderText'), maxwidth=300, textcolor=(0.8, 0.8, 0.8), value=self._do_randomize_val, on_value_change_call=_cb_callback) # Show tutorial. try: show_tutorial = ba.app.config['Show Tutorial'] except Exception: show_tutorial = True def _cb_callback_2(val: bool) -> None: cfg = ba.app.config cfg['Show Tutorial'] = val cfg.commit() self._show_tutorial_check_box = ba.checkboxwidget( parent=self.root_widget, position=(110, 151), scale=1.0, size=(250, 30), autoselect=True, text=ba.Lstr(resource=self._r + '.showTutorialText'), maxwidth=300, textcolor=(0.8, 0.8, 0.8), value=show_tutorial, on_value_change_call=_cb_callback_2) # Grumble: current autoselect doesn't do a very good job # with checkboxes. if self._custom_colors_names_button is not None: for btn in bottom_row_buttons: ba.widget(edit=btn, down_widget=self._custom_colors_names_button) if show_shuffle_check_box: ba.widget(edit=self._custom_colors_names_button, down_widget=self._shuffle_check_box) ba.widget(edit=self._shuffle_check_box, up_widget=self._custom_colors_names_button) else: ba.widget(edit=self._custom_colors_names_button, down_widget=self._show_tutorial_check_box) ba.widget(edit=self._show_tutorial_check_box, up_widget=self._custom_colors_names_button) self._play_button = ba.buttonwidget( parent=self.root_widget, position=(70, 44), size=(200, 45), scale=1.8, text_res_scale=1.5, on_activate_call=self._on_play_press, autoselect=True, label=ba.Lstr(resource='playText')) ba.widget(edit=self._play_button, up_widget=self._show_tutorial_check_box) ba.containerwidget(edit=self.root_widget, start_button=self._play_button, cancel_button=self._cancel_button, selected_child=self._play_button) # Update now and once per second. self._update_timer = ba.Timer(1.0, ba.WeakCall(self._update), timetype=ba.TimeType.REAL, repeat=True) self._update()