Example #1
0
    def __init__(self,
                 position: tuple[float, float],
                 size: tuple[float, float],
                 scale: float = 1.0,
                 offset: tuple[float, float] = (0, 0),
                 bg_color: tuple[float, float, float] = (0.35, 0.55, 0.15),
                 focus_position: tuple[float, float] = (0, 0),
                 focus_size: tuple[float, float] = None,
                 toolbar_visibility: str = 'menu_minimal_no_back'):
        # pylint: disable=too-many-locals
        if focus_size is None:
            focus_size = size

        # In vr mode we can't have windows going outside the screen.
        if ba.app.vr_mode:
            focus_size = size
            focus_position = (0, 0)

        width = focus_size[0]
        height = focus_size[1]

        # Ok, we've been given a desired width, height, and scale;
        # we now need to ensure that we're all onscreen by scaling down if
        # need be and clamping it to the UI bounds.
        bounds = ba.app.ui_bounds
        edge_buffer = 15
        bounds_width = (bounds[1] - bounds[0] - edge_buffer * 2)
        bounds_height = (bounds[3] - bounds[2] - edge_buffer * 2)

        fin_width = width * scale
        fin_height = height * scale
        if fin_width > bounds_width:
            scale /= (fin_width / bounds_width)
            fin_width = width * scale
            fin_height = height * scale
        if fin_height > bounds_height:
            scale /= (fin_height / bounds_height)
            fin_width = width * scale
            fin_height = height * scale

        x_min = bounds[0] + edge_buffer + fin_width * 0.5
        y_min = bounds[2] + edge_buffer + fin_height * 0.5
        x_max = bounds[1] - edge_buffer - fin_width * 0.5
        y_max = bounds[3] - edge_buffer - fin_height * 0.5

        x_fin = min(max(x_min, position[0] + offset[0]), x_max)
        y_fin = min(max(y_min, position[1] + offset[1]), y_max)

        # ok, we've calced a valid x/y position and a scale based on or
        # focus area. ..now calc the difference between the center of our
        # focus area and the center of our window to come up with the
        # offset we'll need to plug in to the window
        x_offs = ((focus_position[0] + focus_size[0] * 0.5) -
                  (size[0] * 0.5)) * scale
        y_offs = ((focus_position[1] + focus_size[1] * 0.5) -
                  (size[1] * 0.5)) * scale

        self.root_widget = ba.containerwidget(
            transition='in_scale',
            scale=scale,
            toolbar_visibility=toolbar_visibility,
            size=size,
            parent=_ba.get_special_widget('overlay_stack'),
            stack_offset=(x_fin - x_offs, y_fin - y_offs),
            scale_origin_stack_offset=(position[0], position[1]),
            on_outside_click_call=self.on_popup_cancel,
            claim_outside_clicks=True,
            color=bg_color,
            on_cancel_call=self.on_popup_cancel)
        # complain if we outlive our root widget
        ba.uicleanupcheck(self, self.root_widget)
Example #2
0
    def __init__(self, textwidget: ba.Widget, label: str, max_chars: int):
        # pylint: disable=too-many-locals
        self._target_text = textwidget
        self._width = 700
        self._height = 400
        top_extra = 20 if ba.app.small_ui else 0
        super().__init__(root_widget=ba.containerwidget(
            parent=_ba.get_special_widget('overlay_stack'),
            size=(self._width, self._height + top_extra),
            transition='in_scale',
            scale_origin_stack_offset=self._target_text.
            get_screen_space_center(),
            scale=(2.0 if ba.app.small_ui else 1.5 if ba.app.med_ui else 1.0),
            stack_offset=(0, 0) if ba.app.small_ui else (
                0, 0) if ba.app.med_ui else (0, 0)))
        self._done_button = ba.buttonwidget(parent=self._root_widget,
                                            position=(self._width - 200, 44),
                                            size=(140, 60),
                                            autoselect=True,
                                            label=ba.Lstr(resource='doneText'),
                                            on_activate_call=self._done)
        ba.containerwidget(edit=self._root_widget,
                           on_cancel_call=self._cancel,
                           start_button=self._done_button)

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 41),
                      size=(0, 0),
                      scale=0.95,
                      text=label,
                      maxwidth=self._width - 140,
                      color=ba.app.title_color,
                      h_align='center',
                      v_align='center')

        self._text_field = ba.textwidget(
            parent=self._root_widget,
            position=(70, self._height - 116),
            max_chars=max_chars,
            text=cast(str, ba.textwidget(query=self._target_text)),
            on_return_press_call=self._done,
            autoselect=True,
            size=(self._width - 140, 55),
            v_align='center',
            editable=True,
            maxwidth=self._width - 175,
            force_internal_editing=True,
            always_show_carat=True)

        self._shift_button = None
        self._num_mode_button = None
        self._char_keys: List[ba.Widget] = []
        self._mode = 'normal'

        v = self._height - 180
        key_width = 46
        key_height = 46
        self._key_color_lit = (1.4, 1.2, 1.4)
        self._key_color = key_color = (0.69, 0.6, 0.74)
        self._key_color_dark = key_color_dark = (0.55, 0.55, 0.71)
        key_textcolor = (1, 1, 1)
        row_starts = (69, 95, 151)

        self._click_sound = ba.getsound('click01')

        # kill prev char keys
        for key in self._char_keys:
            key.delete()
        self._char_keys = []

        # dummy data just used for row/column lengths... we don't actually
        # set things until refresh
        chars: List[Tuple[str, ...]] = [
            ('q', 'u', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'),
            ('a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'),
            ('z', 'x', 'c', 'v', 'b', 'n', 'm')
        ]

        for row_num, row in enumerate(chars):
            h = row_starts[row_num]
            # shift key before row 3
            if row_num == 2:
                self._shift_button = ba.buttonwidget(
                    parent=self._root_widget,
                    position=(h - key_width * 2.0, v),
                    size=(key_width * 1.7, key_height),
                    autoselect=True,
                    textcolor=key_textcolor,
                    color=key_color_dark,
                    label=ba.charstr(ba.SpecialChar.SHIFT),
                    enable_sound=False,
                    extra_touch_border_scale=0.3,
                    button_type='square',
                )

            for _ in row:
                btn = ba.buttonwidget(
                    parent=self._root_widget,
                    position=(h, v),
                    size=(key_width, key_height),
                    autoselect=True,
                    enable_sound=False,
                    textcolor=key_textcolor,
                    color=key_color,
                    label='',
                    button_type='square',
                    extra_touch_border_scale=0.1,
                )
                self._char_keys.append(btn)
                h += key_width + 10

            # Add delete key at end of third row.
            if row_num == 2:
                ba.buttonwidget(parent=self._root_widget,
                                position=(h + 4, v),
                                size=(key_width * 1.8, key_height),
                                autoselect=True,
                                enable_sound=False,
                                repeat=True,
                                textcolor=key_textcolor,
                                color=key_color_dark,
                                label=ba.charstr(ba.SpecialChar.DELETE),
                                button_type='square',
                                on_activate_call=self._del)
            v -= (key_height + 9)
            # Do space bar and stuff.
            if row_num == 2:
                if self._num_mode_button is None:
                    self._num_mode_button = ba.buttonwidget(
                        parent=self._root_widget,
                        position=(112, v - 8),
                        size=(key_width * 2, key_height + 5),
                        enable_sound=False,
                        button_type='square',
                        extra_touch_border_scale=0.3,
                        autoselect=True,
                        textcolor=key_textcolor,
                        color=key_color_dark,
                        label='',
                    )
                btn1 = self._num_mode_button
                btn2 = ba.buttonwidget(parent=self._root_widget,
                                       position=(210, v - 12),
                                       size=(key_width * 6.1, key_height + 15),
                                       extra_touch_border_scale=0.3,
                                       enable_sound=False,
                                       autoselect=True,
                                       textcolor=key_textcolor,
                                       color=key_color_dark,
                                       label=ba.Lstr(resource='spaceKeyText'),
                                       on_activate_call=ba.Call(
                                           self._type_char, ' '))
                ba.widget(edit=btn1, right_widget=btn2)
                ba.widget(edit=btn2,
                          left_widget=btn1,
                          right_widget=self._done_button)
                ba.widget(edit=self._done_button, left_widget=btn2)

        ba.containerwidget(edit=self._root_widget,
                           selected_child=self._char_keys[14])

        self._refresh()
Example #3
0
    def _set_tab(self, tab: str) -> None:
        # pylint: disable=too-many-locals
        from bastd.ui import tabs

        if self._current_tab == tab:
            return
        self._current_tab = tab

        # We wanna preserve our current tab between runs.
        cfg = ba.app.config
        cfg['Watch Tab'] = tab
        cfg.commit()

        # Update tab colors based on which is selected.
        tabs.update_tab_button_colors(self._tab_buttons, tab)

        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

        # A place where tabs can store data to get cleared when
        # switching to a different tab
        self._tab_data = {}

        if tab == 'my_replays':
            c_width = self._scroll_width
            c_height = self._scroll_height - 20
            sub_scroll_height = c_height - 63
            self._my_replays_scroll_width = sub_scroll_width = (
                680 if ba.app.small_ui else 640)

            self._tab_container = cnt = ba.containerwidget(
                parent=self._root_widget,
                position=(scroll_left, scroll_bottom +
                          (self._scroll_height - c_height) * 0.5),
                size=(c_width, c_height),
                background=False,
                selection_loop_to_parent=True)

            v = c_height - 30
            ba.textwidget(parent=cnt,
                          position=(c_width * 0.5, v),
                          color=(0.6, 1.0, 0.6),
                          scale=0.7,
                          size=(0, 0),
                          maxwidth=c_width * 0.9,
                          h_align='center',
                          v_align='center',
                          text=ba.Lstr(
                              resource='replayRenameWarningText',
                              subs=[('${REPLAY}',
                                     ba.Lstr(resource='replayNameDefaultText'))
                                    ]))

            b_width = 140 if ba.app.small_ui else 178
            b_height = (107
                        if ba.app.small_ui else 142 if ba.app.med_ui else 190)
            b_space_extra = (0 if ba.app.small_ui else
                             -2 if ba.app.med_ui else -5)

            b_color = (0.6, 0.53, 0.63)
            b_textcolor = (0.75, 0.7, 0.8)
            btnv = c_height - (48 if ba.app.small_ui else
                               45 if ba.app.med_ui else 40) - b_height
            btnh = 40 if ba.app.small_ui else 40
            smlh = 190 if ba.app.small_ui else 225
            tscl = 1.0 if ba.app.small_ui else 1.2
            self._my_replays_watch_replay_button = btn1 = ba.buttonwidget(
                parent=cnt,
                size=(b_width, b_height),
                position=(btnh, btnv),
                button_type='square',
                color=b_color,
                textcolor=b_textcolor,
                on_activate_call=self._on_my_replay_play_press,
                text_scale=tscl,
                label=ba.Lstr(resource=self._r + '.watchReplayButtonText'),
                autoselect=True)
            ba.widget(edit=btn1, up_widget=self._tab_buttons[tab])
            if ba.app.small_ui and ba.app.toolbars:
                ba.widget(edit=btn1,
                          left_widget=_ba.get_special_widget('back_button'))
            btnv -= b_height + b_space_extra
            ba.buttonwidget(parent=cnt,
                            size=(b_width, b_height),
                            position=(btnh, btnv),
                            button_type='square',
                            color=b_color,
                            textcolor=b_textcolor,
                            on_activate_call=self._on_my_replay_rename_press,
                            text_scale=tscl,
                            label=ba.Lstr(resource=self._r +
                                          '.renameReplayButtonText'),
                            autoselect=True)
            btnv -= b_height + b_space_extra
            ba.buttonwidget(parent=cnt,
                            size=(b_width, b_height),
                            position=(btnh, btnv),
                            button_type='square',
                            color=b_color,
                            textcolor=b_textcolor,
                            on_activate_call=self._on_my_replay_delete_press,
                            text_scale=tscl,
                            label=ba.Lstr(resource=self._r +
                                          '.deleteReplayButtonText'),
                            autoselect=True)

            v -= sub_scroll_height + 23
            self._scrollwidget = scrlw = ba.scrollwidget(
                parent=cnt,
                position=(smlh, v),
                size=(sub_scroll_width, sub_scroll_height))
            ba.containerwidget(edit=cnt, selected_child=scrlw)
            self._columnwidget = ba.columnwidget(parent=scrlw, left_border=10)

            ba.widget(edit=scrlw,
                      autoselect=True,
                      left_widget=btn1,
                      up_widget=self._tab_buttons[tab])
            ba.widget(edit=self._tab_buttons[tab], down_widget=scrlw)

            self._my_replay_selected = None
            self._refresh_my_replays()
def ticket_icon_press() -> None:
    from bastd.ui.resourcetypeinfo import ResourceTypeInfoWindow
    ResourceTypeInfoWindow(
        origin_widget=_ba.get_special_widget('tickets_info_button'))
Example #5
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        # pylint: disable=cyclic-import
        from bastd.ui.popup import PopupMenu
        from bastd.ui.config import ConfigNumberEdit

        music = ba.app.music

        # If they provided an origin-widget, scale up from that.
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        self._r = 'audioSettingsWindow'

        spacing = 50.0
        width = 460.0
        height = 210.0

        # Update: hard-coding head-relative audio to true now,
        # so not showing options.
        # show_vr_head_relative_audio = True if ba.app.vr_mode else False
        show_vr_head_relative_audio = False

        if show_vr_head_relative_audio:
            height += 70

        show_soundtracks = False
        if music.have_music_player():
            show_soundtracks = True
            height += spacing * 2.0

        uiscale = ba.app.uiscale
        base_scale = (2.05 if uiscale is ba.UIScale.SMALL else
                      1.6 if uiscale is ba.UIScale.MEDIUM else 1.0)
        popup_menu_scale = base_scale * 1.2

        super().__init__(root_widget=ba.containerwidget(
            size=(width, height),
            transition=transition,
            scale=base_scale,
            scale_origin_stack_offset=scale_origin,
            stack_offset=(0, -20) if uiscale is ba.UIScale.SMALL else (0, 0)))

        self._back_button = back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(35, height - 55),
            size=(120, 60),
            scale=0.8,
            text_scale=1.2,
            label=ba.Lstr(resource='backText'),
            button_type='back',
            on_activate_call=self._back,
            autoselect=True)
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)
        v = height - 60
        v -= spacing * 1.0
        ba.textwidget(parent=self._root_widget,
                      position=(width * 0.5, height - 32),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      color=ba.app.ui.title_color,
                      maxwidth=180,
                      h_align='center',
                      v_align='center')

        ba.buttonwidget(edit=self._back_button,
                        button_type='backSmall',
                        size=(60, 60),
                        label=ba.charstr(ba.SpecialChar.BACK))

        self._sound_volume_numedit = svne = ConfigNumberEdit(
            parent=self._root_widget,
            position=(40, v),
            xoffset=10,
            configkey='Sound Volume',
            displayname=ba.Lstr(resource=self._r + '.soundVolumeText'),
            minval=0.0,
            maxval=1.0,
            increment=0.1)
        if ba.app.ui.use_toolbars:
            ba.widget(edit=svne.plusbutton,
                      right_widget=_ba.get_special_widget('party_button'))
        v -= spacing
        self._music_volume_numedit = ConfigNumberEdit(
            parent=self._root_widget,
            position=(40, v),
            xoffset=10,
            configkey='Music Volume',
            displayname=ba.Lstr(resource=self._r + '.musicVolumeText'),
            minval=0.0,
            maxval=1.0,
            increment=0.1,
            callback=music.music_volume_changed,
            changesound=False)

        v -= 0.5 * spacing

        self._vr_head_relative_audio_button: Optional[ba.Widget]
        if show_vr_head_relative_audio:
            v -= 40
            ba.textwidget(parent=self._root_widget,
                          position=(40, v + 24),
                          size=(0, 0),
                          text=ba.Lstr(resource=self._r +
                                       '.headRelativeVRAudioText'),
                          color=(0.8, 0.8, 0.8),
                          maxwidth=230,
                          h_align='left',
                          v_align='center')

            popup = PopupMenu(
                parent=self._root_widget,
                position=(290, v),
                width=120,
                button_size=(135, 50),
                scale=popup_menu_scale,
                choices=['Auto', 'On', 'Off'],
                choices_display=[
                    ba.Lstr(resource='autoText'),
                    ba.Lstr(resource='onText'),
                    ba.Lstr(resource='offText')
                ],
                current_choice=ba.app.config.resolve('VR Head Relative Audio'),
                on_value_change_call=self._set_vr_head_relative_audio)
            self._vr_head_relative_audio_button = popup.get_button()
            ba.textwidget(parent=self._root_widget,
                          position=(width * 0.5, v - 11),
                          size=(0, 0),
                          text=ba.Lstr(resource=self._r +
                                       '.headRelativeVRAudioInfoText'),
                          scale=0.5,
                          color=(0.7, 0.8, 0.7),
                          maxwidth=400,
                          flatness=1.0,
                          h_align='center',
                          v_align='center')
            v -= 30
        else:
            self._vr_head_relative_audio_button = None

        self._soundtrack_button: Optional[ba.Widget]
        if show_soundtracks:
            v -= 1.2 * spacing
            self._soundtrack_button = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - 310) / 2, v),
                size=(310, 50),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.soundtrackButtonText'),
                on_activate_call=self._do_soundtracks)
            v -= spacing * 0.5
            ba.textwidget(parent=self._root_widget,
                          position=(0, v),
                          size=(width, 20),
                          text=ba.Lstr(resource=self._r +
                                       '.soundtrackDescriptionText'),
                          flatness=1.0,
                          h_align='center',
                          scale=0.5,
                          color=(0.7, 0.8, 0.7, 1.0),
                          maxwidth=400)
        else:
            self._soundtrack_button = None

        # Tweak a few navigation bits.
        try:
            ba.widget(edit=back_button, down_widget=svne.minusbutton)
        except Exception:
            ba.print_exception('Error wiring AudioSettingsWindow.')

        self._restore_state()
Example #6
0
    def __init__(self,
                 text: Union[str, ba.Lstr] = 'Are you sure?',
                 action: Callable[[], Any] = None,
                 width: float = 360.0,
                 height: float = 100.0,
                 cancel_button: bool = True,
                 cancel_is_selected: bool = False,
                 color: Tuple[float, float, float] = (1, 1, 1),
                 text_scale: float = 1.0,
                 ok_text: Union[str, ba.Lstr] = None,
                 cancel_text: Union[str, ba.Lstr] = None,
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        if ok_text is None:
            ok_text = ba.Lstr(resource='okText')
        if cancel_text is None:
            cancel_text = ba.Lstr(resource='cancelText')
        height += 40
        if width < 360:
            width = 360
        self._action = action

        # if they provided an origin-widget, scale up from that
        self._transition_out: Optional[str]
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = None
            scale_origin = None
            transition = 'in_right'

        uiscale = ba.app.ui.uiscale
        self.root_widget = ba.containerwidget(
            size=(width, height),
            transition=transition,
            toolbar_visibility='menu_minimal_no_back',
            parent=_ba.get_special_widget('overlay_stack'),
            scale=(2.1 if uiscale is ba.UIScale.SMALL else
                   1.5 if uiscale is ba.UIScale.MEDIUM else 1.0),
            scale_origin_stack_offset=scale_origin)

        ba.textwidget(parent=self.root_widget,
                      position=(width * 0.5, height - 5 - (height - 75) * 0.5),
                      size=(0, 0),
                      h_align='center',
                      v_align='center',
                      text=text,
                      scale=text_scale,
                      color=color,
                      maxwidth=width * 0.9,
                      max_height=height - 75)

        cbtn: Optional[ba.Widget]
        if cancel_button:
            cbtn = btn = ba.buttonwidget(parent=self.root_widget,
                                         autoselect=True,
                                         position=(20, 20),
                                         size=(150, 50),
                                         label=cancel_text,
                                         on_activate_call=self._cancel)
            ba.containerwidget(edit=self.root_widget, cancel_button=btn)
            ok_button_h = width - 175
        else:
            # if they don't want a cancel button, we still want back presses to
            # be able to dismiss the window; just wire it up to do the ok
            # button
            ok_button_h = width * 0.5 - 75
            cbtn = None
        btn = ba.buttonwidget(parent=self.root_widget,
                              autoselect=True,
                              position=(ok_button_h, 20),
                              size=(150, 50),
                              label=ok_text,
                              on_activate_call=self._ok)

        # if they didn't want a cancel button, we still want to be able to hit
        # cancel/back/etc to dismiss the window
        if not cancel_button:
            ba.containerwidget(edit=self.root_widget,
                               on_cancel_call=btn.activate)

        ba.containerwidget(edit=self.root_widget,
                           selected_child=(cbtn if cbtn is not None
                                           and cancel_is_selected else btn),
                           start_button=btn)
Example #7
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        ba.set_analytics_screen('Settings Window')
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
        width = 900 if ba.app.small_ui else 580
        x_inset = 75 if ba.app.small_ui else 0
        height = 435
        # button_height = 42
        self._r = 'settingsWindow'
        top_extra = 20 if ba.app.small_ui else 0

        super().__init__(root_widget=ba.containerwidget(
            size=(width, height + top_extra),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(
                1.75 if ba.app.small_ui else 1.35 if ba.app.med_ui else 1.0),
            stack_offset=(0, -8) if ba.app.small_ui else (0, 0)))

        if ba.app.toolbars and ba.app.small_ui:
            self._back_button = None
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._do_back)
        else:
            self._back_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                autoselect=True,
                position=(40 + x_inset, height - 55),
                size=(130, 60),
                scale=0.8,
                text_scale=1.2,
                label=ba.Lstr(resource='backText'),
                button_type='back',
                on_activate_call=self._do_back)
            ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        ba.textwidget(parent=self._root_widget,
                      position=(0, height - 44),
                      size=(width, 25),
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      color=ba.app.title_color,
                      h_align='center',
                      v_align='center',
                      maxwidth=130)

        if self._back_button is not None:
            ba.buttonwidget(edit=self._back_button,
                            button_type='backSmall',
                            size=(60, 60),
                            label=ba.charstr(ba.SpecialChar.BACK))

        v = height - 80
        v -= 145

        basew = 280 if ba.app.small_ui else 230
        baseh = 170
        x_offs = x_inset + (105
                            if ba.app.small_ui else 72) - basew  # now unused
        x_offs2 = x_offs + basew - 7
        x_offs3 = x_offs + 2 * (basew - 7)
        x_offs4 = x_offs2
        x_offs5 = x_offs3

        def _b_title(x: float, y: float, button: ba.Widget,
                     text: Union[str, ba.Lstr]) -> None:
            ba.textwidget(parent=self._root_widget,
                          text=text,
                          position=(x + basew * 0.47, y + baseh * 0.22),
                          maxwidth=basew * 0.7,
                          size=(0, 0),
                          h_align='center',
                          v_align='center',
                          draw_controller=button,
                          color=(0.7, 0.9, 0.7, 1.0))

        ctb = self._controllers_button = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            position=(x_offs2, v),
            size=(basew, baseh),
            button_type='square',
            label='',
            on_activate_call=self._do_controllers)
        if ba.app.toolbars and self._back_button is None:
            bbtn = _ba.get_special_widget('back_button')
            ba.widget(edit=ctb, left_widget=bbtn)
        _b_title(x_offs2, v, ctb,
                 ba.Lstr(resource=self._r + '.controllersText'))
        imgw = imgh = 130
        ba.imagewidget(parent=self._root_widget,
                       position=(x_offs2 + basew * 0.49 - imgw * 0.5, v + 35),
                       size=(imgw, imgh),
                       texture=ba.gettexture('controllerIcon'),
                       draw_controller=ctb)

        gfxb = self._graphics_button = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            position=(x_offs3, v),
            size=(basew, baseh),
            button_type='square',
            label='',
            on_activate_call=self._do_graphics)
        if ba.app.toolbars:
            pbtn = _ba.get_special_widget('party_button')
            ba.widget(edit=gfxb, up_widget=pbtn, right_widget=pbtn)
        _b_title(x_offs3, v, gfxb, ba.Lstr(resource=self._r + '.graphicsText'))
        imgw = imgh = 110
        ba.imagewidget(parent=self._root_widget,
                       position=(x_offs3 + basew * 0.49 - imgw * 0.5, v + 42),
                       size=(imgw, imgh),
                       texture=ba.gettexture('graphicsIcon'),
                       draw_controller=gfxb)

        v -= (baseh - 5)

        abtn = self._audio_button = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            position=(x_offs4, v),
            size=(basew, baseh),
            button_type='square',
            label='',
            on_activate_call=self._do_audio)
        _b_title(x_offs4, v, abtn, ba.Lstr(resource=self._r + '.audioText'))
        imgw = imgh = 120
        ba.imagewidget(parent=self._root_widget,
                       position=(x_offs4 + basew * 0.49 - imgw * 0.5 + 5,
                                 v + 35),
                       size=(imgw, imgh),
                       color=(1, 1, 0),
                       texture=ba.gettexture('audioIcon'),
                       draw_controller=abtn)

        avb = self._advanced_button = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            position=(x_offs5, v),
            size=(basew, baseh),
            button_type='square',
            label='',
            on_activate_call=self._do_advanced)
        _b_title(x_offs5, v, avb, ba.Lstr(resource=self._r + '.advancedText'))
        imgw = imgh = 120
        ba.imagewidget(parent=self._root_widget,
                       position=(x_offs5 + basew * 0.49 - imgw * 0.5 + 5,
                                 v + 35),
                       size=(imgw, imgh),
                       color=(0.8, 0.95, 1),
                       texture=ba.gettexture('advancedIcon'),
                       draw_controller=avb)
Example #8
0
    def __init__(self, origin: Sequence[float] = (0, 0)):
        _ba.set_party_window_open(True)
        self._r = 'partyWindow'
        self._popup_type: Optional[str] = None
        self._popup_party_member_client_id: Optional[int] = None
        self._popup_party_member_is_host: Optional[bool] = None
        self._width = 500
        uiscale = ba.app.uiscale
        self._height = (365 if uiscale is ba.UIScale.SMALL else
                        480 if uiscale is ba.UIScale.MEDIUM else 600)
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            transition='in_scale',
            color=(0.40, 0.55, 0.20),
            parent=_ba.get_special_widget('overlay_stack'),
            on_outside_click_call=self.close_with_sound,
            scale_origin_stack_offset=origin,
            scale=(2.0 if uiscale is ba.UIScale.SMALL else
                   1.35 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -10) if uiscale is ba.UIScale.SMALL else (
                240, 0) if uiscale is ba.UIScale.MEDIUM else (330, 20)))

        self._cancel_button = ba.buttonwidget(parent=self._root_widget,
                                              scale=0.7,
                                              position=(30, self._height - 47),
                                              size=(50, 50),
                                              label='',
                                              on_activate_call=self.close,
                                              autoselect=True,
                                              color=(0.45, 0.63, 0.15),
                                              icon=ba.gettexture('crossOut'),
                                              iconscale=1.2)
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._cancel_button)

        self._menu_button = ba.buttonwidget(
            parent=self._root_widget,
            scale=0.7,
            position=(self._width - 60, self._height - 47),
            size=(50, 50),
            label='...',
            autoselect=True,
            button_type='square',
            on_activate_call=ba.WeakCall(self._on_menu_button_press),
            color=(0.55, 0.73, 0.25),
            iconscale=1.2)

        info = _ba.get_connection_to_host_info()
        if info.get('name', '') != '':
            title = info['name']
        else:
            title = ba.Lstr(resource=self._r + '.titleText')

        self._title_text = ba.textwidget(parent=self._root_widget,
                                         scale=0.9,
                                         color=(0.5, 0.7, 0.5),
                                         text=title,
                                         size=(0, 0),
                                         position=(self._width * 0.5,
                                                   self._height - 29),
                                         maxwidth=self._width * 0.7,
                                         h_align='center',
                                         v_align='center')

        self._empty_str = ba.textwidget(parent=self._root_widget,
                                        scale=0.75,
                                        size=(0, 0),
                                        position=(self._width * 0.5,
                                                  self._height - 65),
                                        maxwidth=self._width * 0.85,
                                        h_align='center',
                                        v_align='center')

        self._scroll_width = self._width - 50
        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                             size=(self._scroll_width,
                                                   self._height - 200),
                                             position=(30, 80),
                                             color=(0.4, 0.6, 0.3))
        self._columnwidget = ba.columnwidget(parent=self._scrollwidget)
        ba.widget(edit=self._menu_button, down_widget=self._columnwidget)

        self._muted_text = ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height * 0.5),
            size=(0, 0),
            h_align='center',
            v_align='center',
            text=ba.Lstr(resource='chatMutedText'))
        self._chat_texts: List[ba.Widget] = []

        # add all existing messages if chat is not muted
        if not ba.app.config.resolve('Chat Muted'):
            msgs = _ba.get_chat_messages()
            for msg in msgs:
                self._add_msg(msg)

        self._text_field = txt = ba.textwidget(
            parent=self._root_widget,
            editable=True,
            size=(530, 40),
            position=(44, 39),
            text='',
            maxwidth=494,
            shadow=0.3,
            flatness=1.0,
            description=ba.Lstr(resource=self._r + '.chatMessageText'),
            autoselect=True,
            v_align='center',
            corner_scale=0.7)

        ba.widget(edit=self._scrollwidget,
                  autoselect=True,
                  left_widget=self._cancel_button,
                  up_widget=self._cancel_button,
                  down_widget=self._text_field)
        ba.widget(edit=self._columnwidget,
                  autoselect=True,
                  up_widget=self._cancel_button,
                  down_widget=self._text_field)
        ba.containerwidget(edit=self._root_widget, selected_child=txt)
        btn = ba.buttonwidget(parent=self._root_widget,
                              size=(50, 35),
                              label=ba.Lstr(resource=self._r + '.sendText'),
                              button_type='square',
                              autoselect=True,
                              position=(self._width - 70, 35),
                              on_activate_call=self._send_chat_message)
        ba.textwidget(edit=txt, on_return_press_call=btn.activate)
        self._name_widgets: List[ba.Widget] = []
        self._roster: Optional[List[Dict[str, Any]]] = None
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      repeat=True,
                                      timetype=ba.TimeType.REAL)
        self._update()
Example #9
0
    def __init__(self, textwidget: ba.Widget, label: str, max_chars: int):
        self._target_text = textwidget
        self._width = 700
        self._height = 400
        uiscale = ba.app.ui.uiscale
        top_extra = 20 if uiscale is ba.UIScale.SMALL else 0
        super().__init__(root_widget=ba.containerwidget(
            parent=_ba.get_special_widget('overlay_stack'),
            size=(self._width, self._height + top_extra),
            transition='in_scale',
            scale_origin_stack_offset=self._target_text.
            get_screen_space_center(),
            scale=(2.0 if uiscale is ba.UIScale.SMALL else
                   1.5 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, 0) if uiscale is ba.UIScale.SMALL else (
                0, 0) if uiscale is ba.UIScale.MEDIUM else (0, 0)))
        self._done_button = ba.buttonwidget(parent=self._root_widget,
                                            position=(self._width - 200, 44),
                                            size=(140, 60),
                                            autoselect=True,
                                            label=ba.Lstr(resource='doneText'),
                                            on_activate_call=self._done)
        ba.containerwidget(edit=self._root_widget,
                           on_cancel_call=self._cancel,
                           start_button=self._done_button)

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 41),
                      size=(0, 0),
                      scale=0.95,
                      text=label,
                      maxwidth=self._width - 140,
                      color=ba.app.ui.title_color,
                      h_align='center',
                      v_align='center')

        self._text_field = ba.textwidget(
            parent=self._root_widget,
            position=(70, self._height - 116),
            max_chars=max_chars,
            text=cast(str, ba.textwidget(query=self._target_text)),
            on_return_press_call=self._done,
            autoselect=True,
            size=(self._width - 140, 55),
            v_align='center',
            editable=True,
            maxwidth=self._width - 175,
            force_internal_editing=True,
            always_show_carat=True)

        self._key_color_lit = (1.4, 1.2, 1.4)
        self._key_color = (0.69, 0.6, 0.74)
        self._key_color_dark = (0.55, 0.55, 0.71)

        self._shift_button: Optional[ba.Widget] = None
        self._backspace_button: Optional[ba.Widget] = None
        self._space_button: Optional[ba.Widget] = None
        self._double_press_shift = False
        self._num_mode_button: Optional[ba.Widget] = None
        self._emoji_button: Optional[ba.Widget] = None
        self._char_keys: List[ba.Widget] = []
        self._keyboard_index = 0
        self._last_space_press = 0.0
        self._double_space_interval = 0.3

        self._keyboard: ba.Keyboard
        self._chars: List[str]
        self._modes: List[str]
        self._mode: str
        self._mode_index: int
        self._load_keyboard()
Example #10
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # FIXME: should tidy up here.
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=cyclic-import
        from bastd.ui import popup as popup_ui
        self._have_selected_child = False

        scale_origin: Optional[Tuple[float, float]]

        # If they provided an origin-widget, scale up from that.
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        self._r = 'configControllersWindow'
        app = ba.app

        is_fire_tv = _ba.is_running_on_fire_tv()

        spacing = 50.0
        button_width = 350.0
        width = 460.0
        height = 135.0

        space_height = spacing * 0.3

        # FIXME: should create vis settings in platform for these,
        #  not hard code them here..

        show_gamepads = False
        platform = app.platform
        subplatform = app.subplatform
        non_vr_windows = (platform == 'windows'
                          and (subplatform != 'oculus' or not app.vr_mode))
        if platform in ('linux', 'android', 'mac') or non_vr_windows:
            show_gamepads = True
            height += spacing

        show_touch = False
        if _ba.have_touchscreen_input():
            show_touch = True
            height += spacing

        show_space_1 = False
        if show_gamepads or show_touch:
            show_space_1 = True
            height += space_height

        show_keyboard = False
        if _ba.get_input_device('Keyboard', '#1', doraise=False) is not None:
            show_keyboard = True
            height += spacing * 2
        show_keyboard_p2 = False if app.vr_mode else show_keyboard
        if show_keyboard_p2:
            height += spacing

        show_space_2 = False
        if show_keyboard:
            show_space_2 = True
            height += space_height

        if bool(True):
            show_remote = True
            height += spacing
        else:
            show_remote = False

        show_ps3 = False
        if platform == 'mac':
            show_ps3 = True
            height += spacing

        show360 = False
        if platform == 'mac' or is_fire_tv:
            show360 = True
            height += spacing

        show_mac_wiimote = False
        if platform == 'mac':
            show_mac_wiimote = True
            height += spacing

        # on non-oculus-vr windows, show an option to disable xinput
        show_xinput_toggle = False
        if platform == 'windows' and (subplatform != 'oculus'
                                      or not app.vr_mode):
            show_xinput_toggle = True

        # on mac builds, show an option to switch between generic and
        # made-for-iOS/Mac systems
        # (we can run into problems where devices register as one of each
        # type otherwise)..
        show_mac_controller_subsystem = False
        if platform == 'mac':
            show_mac_controller_subsystem = True

        if show_mac_controller_subsystem:
            height += spacing

        if show_xinput_toggle:
            height += spacing

        super().__init__(root_widget=ba.containerwidget(
            size=(width, height),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            scale=(1.7 if show_keyboard else 2.2
                   ) if ba.app.small_ui else 1.5 if ba.app.med_ui else 1.0))
        self._back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(35, height - 60),
            size=(140, 65),
            scale=0.8,
            text_scale=1.2,
            autoselect=True,
            label=ba.Lstr(resource='backText'),
            button_type='back',
            on_activate_call=self._back)
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        # need these vars to exist even if the buttons don't
        self._gamepads_button: Optional[ba.Widget] = None
        self._touch_button: Optional[ba.Widget] = None
        self._keyboard_button: Optional[ba.Widget] = None
        self._keyboard_2_button: Optional[ba.Widget] = None
        self._idevices_button: Optional[ba.Widget] = None
        self._ps3_button: Optional[ba.Widget] = None
        self._xbox_360_button: Optional[ba.Widget] = None
        self._wiimotes_button: Optional[ba.Widget] = None

        ba.textwidget(parent=self._root_widget,
                      position=(0, height - 49),
                      size=(width, 25),
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      color=ba.app.title_color,
                      h_align="center",
                      v_align="top")
        ba.buttonwidget(edit=btn,
                        button_type='backSmall',
                        size=(60, 60),
                        label=ba.charstr(ba.SpecialChar.BACK))

        v = height - 75
        v -= spacing

        if show_touch:
            self._touch_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureTouchText'),
                on_activate_call=self._do_touchscreen)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=self._touch_button)
                ba.widget(edit=self._back_button,
                          down_widget=self._touch_button)
                self._have_selected_child = True
            v -= spacing

        if show_gamepads:
            self._gamepads_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 - 7, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureControllersText'),
                on_activate_call=self._do_gamepads)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=self._gamepads_button)
                ba.widget(edit=self._back_button,
                          down_widget=self._gamepads_button)
                self._have_selected_child = True
            v -= spacing
        else:
            self._gamepads_button = None

        if show_space_1:
            v -= space_height

        if show_keyboard:
            self._keyboard_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 + 5, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureKeyboardText'),
                on_activate_call=self._config_keyboard)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=self._keyboard_button)
                ba.widget(edit=self._back_button,
                          down_widget=self._keyboard_button)
                self._have_selected_child = True
            v -= spacing
        if show_keyboard_p2:
            self._keyboard_2_button = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 - 3, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureKeyboard2Text'),
                on_activate_call=self._config_keyboard2)
            v -= spacing
        if show_space_2:
            v -= space_height
        if show_remote:
            self._idevices_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 - 5, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureMobileText'),
                on_activate_call=self._do_mobile_devices)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=self._idevices_button)
                ba.widget(edit=self._back_button,
                          down_widget=self._idevices_button)
                self._have_selected_child = True
            v -= spacing
        if show_ps3:
            self._ps3_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 + 5, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.ps3Text'),
                on_activate_call=self._do_ps3_controllers)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            v -= spacing
        if show360:
            self._xbox_360_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 - 1, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.xbox360Text'),
                on_activate_call=self._do_360_controllers)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            v -= spacing
        if show_mac_wiimote:
            self._wiimotes_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 + 5, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.wiimotesText'),
                on_activate_call=self._do_wiimotes)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            v -= spacing

        if show_xinput_toggle:

            def do_toggle(value: bool) -> None:
                ba.screenmessage(
                    ba.Lstr(resource='settingsWindowAdvanced.mustRestartText'),
                    color=(1, 1, 0))
                ba.playsound(ba.getsound('gunCocking'))
                _ba.set_low_level_config_value('enablexinput', not value)

            ba.checkboxwidget(
                parent=self._root_widget,
                position=(100, v + 3),
                size=(120, 30),
                value=(not _ba.get_low_level_config_value('enablexinput', 1)),
                maxwidth=200,
                on_value_change_call=do_toggle,
                text=ba.Lstr(resource='disableXInputText'),
                autoselect=True)
            ba.textwidget(
                parent=self._root_widget,
                position=(width * 0.5, v - 5),
                size=(0, 0),
                text=ba.Lstr(resource='disableXInputDescriptionText'),
                scale=0.5,
                h_align='center',
                v_align='center',
                color=ba.app.infotextcolor,
                maxwidth=width * 0.8)
            v -= spacing
        if show_mac_controller_subsystem:
            popup_ui.PopupMenu(
                parent=self._root_widget,
                position=(260, v - 10),
                width=160,
                button_size=(150, 50),
                scale=1.5,
                choices=['Classic', 'MFi', 'Both'],
                choices_display=[
                    ba.Lstr(resource='macControllerSubsystemClassicText'),
                    ba.Lstr(resource='macControllerSubsystemMFiText'),
                    ba.Lstr(resource='macControllerSubsystemBothText')
                ],
                current_choice=ba.app.config.resolve(
                    'Mac Controller Subsystem'),
                on_value_change_call=self._set_mac_controller_subsystem)
            ba.textwidget(
                parent=self._root_widget,
                position=(245, v + 13),
                size=(0, 0),
                text=ba.Lstr(resource='macControllerSubsystemTitleText'),
                scale=1.0,
                h_align='right',
                v_align='center',
                color=ba.app.infotextcolor,
                maxwidth=180)
            ba.textwidget(
                parent=self._root_widget,
                position=(width * 0.5, v - 20),
                size=(0, 0),
                text=ba.Lstr(resource='macControllerSubsystemDescriptionText'),
                scale=0.5,
                h_align='center',
                v_align='center',
                color=ba.app.infotextcolor,
                maxwidth=width * 0.8)
            v -= spacing
        self._restore_state()
Example #11
0
    def __init__(self,
                 transition: Optional[str] = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        from bastd.ui.tabs import TabRow
        ba.set_analytics_screen('Watch Window')
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
        ba.app.ui.set_main_menu_location('Watch')
        self._tab_data: Dict[str, Any] = {}
        self._my_replays_scroll_width: Optional[float] = None
        self._my_replays_watch_replay_button: Optional[ba.Widget] = None
        self._scrollwidget: Optional[ba.Widget] = None
        self._columnwidget: Optional[ba.Widget] = None
        self._my_replay_selected: Optional[str] = None
        self._my_replays_rename_window: Optional[ba.Widget] = None
        self._my_replay_rename_text: Optional[ba.Widget] = None
        self._r = 'watchWindow'
        uiscale = ba.app.ui.uiscale
        self._width = 1240 if uiscale is ba.UIScale.SMALL else 1040
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (578 if uiscale is ba.UIScale.SMALL else
                        670 if uiscale is ba.UIScale.MEDIUM else 800)
        self._current_tab: Optional[WatchWindow.TabID] = None
        extra_top = 20 if uiscale is ba.UIScale.SMALL else 0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + extra_top),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(1.3 if uiscale is ba.UIScale.SMALL else
                   0.97 if uiscale is ba.UIScale.MEDIUM else 0.8),
            stack_offset=(0, -10) if uiscale is ba.UIScale.SMALL else (
                0, 15) if uiscale is ba.UIScale.MEDIUM else (0, 0)))

        if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back)
            self._back_button = None
        else:
            self._back_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                autoselect=True,
                position=(70 + x_inset, self._height - 74),
                size=(140, 60),
                scale=1.1,
                label=ba.Lstr(resource='backText'),
                button_type='back',
                on_activate_call=self._back)
            ba.containerwidget(edit=self._root_widget, cancel_button=btn)
            ba.buttonwidget(edit=btn,
                            button_type='backSmall',
                            size=(60, 60),
                            label=ba.charstr(ba.SpecialChar.BACK))

        title_extra_v = (28 if uiscale is ba.UIScale.SMALL else
                         38 if uiscale is ba.UIScale.MEDIUM else 38)
        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5,
                                self._height - title_extra_v),
                      size=(0, 0),
                      color=ba.app.ui.title_color,
                      scale=0.8 if uiscale is ba.UIScale.SMALL else 1.5,
                      h_align='center',
                      v_align='center',
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      maxwidth=400)

        tabdefs = [
            (self.TabID.MY_REPLAYS,
             ba.Lstr(resource=self._r + '.myReplaysText')),
            # (self.TabID.TEST_TAB, ba.Lstr(value='Testing')),
        ]

        scroll_buffer_h = 130 + 2 * x_inset
        tab_buffer_h = 750 + 2 * x_inset
        tab_buffer_v = (90 if uiscale is ba.UIScale.SMALL else
                        125 if uiscale is ba.UIScale.MEDIUM else 130)

        self._tab_row = TabRow(self._root_widget,
                               tabdefs,
                               pos=(tab_buffer_h * 0.5,
                                    self._height - tab_buffer_v),
                               size=(self._width - tab_buffer_h, 50),
                               on_select_call=self._set_tab)

        if ba.app.ui.use_toolbars:
            first_tab = self._tab_row.tabs[tabdefs[0][0]]
            last_tab = self._tab_row.tabs[tabdefs[-1][0]]
            ba.widget(edit=last_tab.button,
                      right_widget=_ba.get_special_widget('party_button'))
            if uiscale is ba.UIScale.SMALL:
                bbtn = _ba.get_special_widget('back_button')
                ba.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 = 25 if uiscale is ba.UIScale.SMALL else 4
        buffer_extra_v = 19 if uiscale is ba.UIScale.SMALL else 4
        ba.imagewidget(parent=self._root_widget,
                       position=(scroll_left - buffer_h,
                                 scroll_bottom - buffer_v + buffer_extra_v),
                       size=(self._scroll_width + 2 * buffer_h,
                             self._scroll_height + 2 * buffer_v),
                       texture=ba.gettexture('scrollWidget'),
                       model_transparent=ba.getmodel('softEdgeOutside'))
        self._tab_container: Optional[ba.Widget] = None

        self._restore_state()
Example #12
0
    def _set_tab(self, tab_id: TabID) -> None:
        # pylint: disable=too-many-locals

        if self._current_tab == tab_id:
            return
        self._current_tab = tab_id

        # Preserve our current tab between runs.
        cfg = ba.app.config
        cfg['Watch Tab'] = tab_id.value
        cfg.commit()

        # Update tab colors based on which is selected.
        # tabs.update_tab_button_colors(self._tab_buttons, tab)
        self._tab_row.update_appearance(tab_id)

        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

        # A place where tabs can store data to get cleared when
        # switching to a different tab
        self._tab_data = {}

        uiscale = ba.app.ui.uiscale
        if tab_id is self.TabID.MY_REPLAYS:
            c_width = self._scroll_width
            c_extra_height = (-38 if uiscale is ba.UIScale.SMALL else 20)
            c_height = self._scroll_height - c_extra_height
            sub_scroll_height = c_height - 63
            self._my_replays_scroll_width = sub_scroll_width = (
                680 if uiscale is ba.UIScale.SMALL else 640)

            self._tab_container = cnt = ba.containerwidget(
                parent=self._root_widget,
                position=(scroll_left, scroll_bottom +
                          (self._scroll_height - c_height) * 0.5),
                size=(c_width, c_height),
                background=False,
                selection_loops_to_parent=True)

            v = c_height - (9 if uiscale is ba.UIScale.SMALL else 30)
            ba.textwidget(parent=cnt,
                          position=(c_width * 0.5, v),
                          color=(0.6, 1.0, 0.6),
                          scale=0.7,
                          size=(0, 0),
                          maxwidth=c_width * 0.9,
                          h_align='center',
                          v_align='center',
                          text=ba.Lstr(
                              resource='replayRenameWarningText',
                              subs=[('${REPLAY}',
                                     ba.Lstr(resource='replayNameDefaultText'))
                                    ]))

            b_width = 140 if uiscale is ba.UIScale.SMALL else 178
            b_height = (86 if uiscale is ba.UIScale.SMALL else
                        105 if uiscale is ba.UIScale.MEDIUM else 140)
            b_space_extra = (0 if uiscale is ba.UIScale.SMALL else
                             -1 if uiscale is ba.UIScale.MEDIUM else -4)

            b_color = (0.6, 0.53, 0.63)
            b_textcolor = (0.75, 0.7, 0.8)
            btnv = (c_height - (28 if uiscale is ba.UIScale.SMALL else
                                47 if uiscale is ba.UIScale.MEDIUM else 45) -
                    b_height)
            btnh = 40 if uiscale is ba.UIScale.SMALL else 40
            smlh = 190 if uiscale is ba.UIScale.SMALL else 225
            tscl = 1.0 if uiscale is ba.UIScale.SMALL else 1.2
            self._my_replays_watch_replay_button = btn1 = ba.buttonwidget(
                parent=cnt,
                size=(b_width, b_height),
                position=(btnh, btnv),
                button_type='square',
                color=b_color,
                textcolor=b_textcolor,
                on_activate_call=self._on_my_replay_play_press,
                text_scale=tscl,
                label=ba.Lstr(resource=self._r + '.watchReplayButtonText'),
                autoselect=True)
            ba.widget(edit=btn1, up_widget=self._tab_row.tabs[tab_id].button)
            if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
                ba.widget(edit=btn1,
                          left_widget=_ba.get_special_widget('back_button'))
            btnv -= b_height + b_space_extra
            ba.buttonwidget(parent=cnt,
                            size=(b_width, b_height),
                            position=(btnh, btnv),
                            button_type='square',
                            color=b_color,
                            textcolor=b_textcolor,
                            on_activate_call=self._on_my_replay_rename_press,
                            text_scale=tscl,
                            label=ba.Lstr(resource=self._r +
                                          '.renameReplayButtonText'),
                            autoselect=True)
            btnv -= b_height + b_space_extra
            ba.buttonwidget(parent=cnt,
                            size=(b_width, b_height),
                            position=(btnh, btnv),
                            button_type='square',
                            color=b_color,
                            textcolor=b_textcolor,
                            on_activate_call=self._on_my_replay_delete_press,
                            text_scale=tscl,
                            label=ba.Lstr(resource=self._r +
                                          '.deleteReplayButtonText'),
                            autoselect=True)
            if app.platform == 'android':
                btnv -= b_height * 0.7 + b_space_extra
                ba.buttonwidget(parent=cnt,
                                size=(b_width, b_height * 0.67),
                                position=(btnh, btnv),
                                button_type='square',
                                color=b_color,
                                textcolor=b_textcolor,
                                on_activate_call=self._import_replay_press,
                                text_scale=tscl,
                                label=ba.Lstr(resource='importText'),
                                autoselect=True)
                btnv -= b_height * 0.73 + b_space_extra
                ba.buttonwidget(parent=cnt,
                                size=(b_width, b_height * 0.67),
                                position=(btnh, btnv),
                                button_type='square',
                                color=b_color,
                                textcolor=b_textcolor,
                                on_activate_call=self._export_my_replay,
                                text_scale=tscl,
                                label=ba.Lstr(resource='shareText'),
                                autoselect=True)
            else:
                btnv -= b_height + b_space_extra
                ba.buttonwidget(parent=cnt,
                                size=(b_width, b_height),
                                position=(btnh, btnv),
                                button_type='square',
                                color=b_color,
                                textcolor=b_textcolor,
                                on_activate_call=self._show_my_replays,
                                text_scale=tscl,
                                label=ba.Lstr(resource='shareText'),
                                autoselect=True)

            v -= sub_scroll_height + 23
            self._scrollwidget = scrlw = ba.scrollwidget(
                parent=cnt,
                position=(smlh, v),
                size=(sub_scroll_width, sub_scroll_height))
            ba.containerwidget(edit=cnt, selected_child=scrlw)
            self._columnwidget = ba.columnwidget(parent=scrlw,
                                                 left_border=10,
                                                 border=2,
                                                 margin=0)

            ba.widget(edit=scrlw,
                      autoselect=True,
                      left_widget=btn1,
                      up_widget=self._tab_row.tabs[tab_id].button)
            ba.widget(edit=self._tab_row.tabs[tab_id].button,
                      down_widget=scrlw)

            self._my_replay_selected = None
            self._refresh_my_replays()
    def __init__(self,
                 gametype: type[ba.GameActivity],
                 sessiontype: type[ba.Session],
                 config: Optional[dict[str, Any]],
                 completion_call: Callable[[Optional[dict[str, Any]]], Any],
                 default_selection: str = None,
                 transition: str = 'in_right',
                 edit_info: dict[str, Any] = None):
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        from ba.internal import (get_unowned_maps, get_filtered_map_name,
                                 get_map_class, get_map_display_string)
        self._gametype = gametype
        self._sessiontype = sessiontype

        # If we're within an editing session we get passed edit_info
        # (returning from map selection window, etc).
        if edit_info is not None:
            self._edit_info = edit_info

        # ..otherwise determine whether we're adding or editing a game based
        # on whether an existing config was passed to us.
        else:
            if config is None:
                self._edit_info = {'editType': 'add'}
            else:
                self._edit_info = {'editType': 'edit'}

        self._r = 'gameSettingsWindow'

        valid_maps = gametype.get_supported_maps(sessiontype)
        if not valid_maps:
            ba.screenmessage(ba.Lstr(resource='noValidMapsErrorText'))
            raise Exception('No valid maps')

        self._settings_defs = gametype.get_available_settings(sessiontype)
        self._completion_call = completion_call

        # To start with, pick a random map out of the ones we own.
        unowned_maps = get_unowned_maps()
        valid_maps_owned = [m for m in valid_maps if m not in unowned_maps]
        if valid_maps_owned:
            self._map = valid_maps[random.randrange(len(valid_maps_owned))]

        # Hmmm.. we own none of these maps.. just pick a random un-owned one
        # I guess.. should this ever happen?
        else:
            self._map = valid_maps[random.randrange(len(valid_maps))]

        is_add = (self._edit_info['editType'] == 'add')

        # If there's a valid map name in the existing config, use that.
        try:
            if (config is not None and 'settings' in config
                    and 'map' in config['settings']):
                filtered_map_name = get_filtered_map_name(
                    config['settings']['map'])
                if filtered_map_name in valid_maps:
                    self._map = filtered_map_name
        except Exception:
            ba.print_exception('Error getting map for editor.')

        if config is not None and 'settings' in config:
            self._settings = config['settings']
        else:
            self._settings = {}

        self._choice_selections: dict[str, int] = {}

        uiscale = ba.app.ui.uiscale
        width = 720 if uiscale is ba.UIScale.SMALL else 620
        x_inset = 50 if uiscale is ba.UIScale.SMALL else 0
        height = (365 if uiscale is ba.UIScale.SMALL else
                  460 if uiscale is ba.UIScale.MEDIUM else 550)
        spacing = 52
        y_extra = 15
        y_extra2 = 21

        map_tex_name = (get_map_class(self._map).get_preview_texture_name())
        if map_tex_name is None:
            raise Exception('no map preview tex found for' + self._map)
        map_tex = ba.gettexture(map_tex_name)

        top_extra = 20 if uiscale is ba.UIScale.SMALL else 0
        super().__init__(root_widget=ba.containerwidget(
            size=(width, height + top_extra),
            transition=transition,
            scale=(2.19 if uiscale is ba.UIScale.SMALL else
                   1.35 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -17) if uiscale is ba.UIScale.SMALL else (0, 0)))

        btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(45 + x_inset, height - 82 + y_extra2),
            size=(180, 70) if is_add else (180, 65),
            label=ba.Lstr(resource='backText') if is_add else ba.Lstr(
                resource='cancelText'),
            button_type='back' if is_add else None,
            autoselect=True,
            scale=0.75,
            text_scale=1.3,
            on_activate_call=ba.Call(self._cancel))
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        add_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(width - (193 + x_inset), height - 82 + y_extra2),
            size=(200, 65),
            scale=0.75,
            text_scale=1.3,
            label=ba.Lstr(resource=self._r +
                          '.addGameText') if is_add else ba.Lstr(
                              resource='doneText'))

        if ba.app.ui.use_toolbars:
            pbtn = _ba.get_special_widget('party_button')
            ba.widget(edit=add_button, right_widget=pbtn, up_widget=pbtn)

        ba.textwidget(parent=self._root_widget,
                      position=(-8, height - 70 + y_extra2),
                      size=(width, 25),
                      text=gametype.get_display_string(),
                      color=ba.app.ui.title_color,
                      maxwidth=235,
                      scale=1.1,
                      h_align='center',
                      v_align='center')

        map_height = 100

        scroll_height = map_height + 10  # map select and margin

        # Calc our total height we'll need
        scroll_height += spacing * len(self._settings_defs)

        scroll_width = width - (86 + 2 * x_inset)
        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                             position=(44 + x_inset,
                                                       35 + y_extra),
                                             size=(scroll_width, height - 116),
                                             highlight=False,
                                             claims_left_right=True,
                                             claims_tab=True,
                                             selection_loops_to_parent=True)
        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
                                                size=(scroll_width,
                                                      scroll_height),
                                                background=False,
                                                claims_left_right=True,
                                                claims_tab=True,
                                                selection_loops_to_parent=True)

        v = scroll_height - 5
        h = -40

        # Keep track of all the selectable widgets we make so we can wire
        # them up conveniently.
        widget_column: list[list[ba.Widget]] = []

        # Map select button.
        ba.textwidget(parent=self._subcontainer,
                      position=(h + 49, v - 63),
                      size=(100, 30),
                      maxwidth=110,
                      text=ba.Lstr(resource='mapText'),
                      h_align='left',
                      color=(0.8, 0.8, 0.8, 1.0),
                      v_align='center')

        ba.imagewidget(
            parent=self._subcontainer,
            size=(256 * 0.7, 125 * 0.7),
            position=(h + 261 - 128 + 128.0 * 0.56, v - 90),
            texture=map_tex,
            model_opaque=ba.getmodel('level_select_button_opaque'),
            model_transparent=ba.getmodel('level_select_button_transparent'),
            mask_texture=ba.gettexture('mapPreviewMask'))
        map_button = btn = ba.buttonwidget(
            parent=self._subcontainer,
            size=(140, 60),
            position=(h + 448, v - 72),
            on_activate_call=ba.Call(self._select_map),
            scale=0.7,
            label=ba.Lstr(resource='mapSelectText'))
        widget_column.append([btn])

        ba.textwidget(parent=self._subcontainer,
                      position=(h + 363 - 123, v - 114),
                      size=(100, 30),
                      flatness=1.0,
                      shadow=1.0,
                      scale=0.55,
                      maxwidth=256 * 0.7 * 0.8,
                      text=get_map_display_string(self._map),
                      h_align='center',
                      color=(0.6, 1.0, 0.6, 1.0),
                      v_align='center')
        v -= map_height

        for setting in self._settings_defs:
            value = setting.default
            value_type = type(value)

            # Now, if there's an existing value for it in the config,
            # override with that.
            try:
                if (config is not None and 'settings' in config
                        and setting.name in config['settings']):
                    value = value_type(config['settings'][setting.name])
            except Exception:
                ba.print_exception()

            # Shove the starting value in there to start.
            self._settings[setting.name] = value

            name_translated = self._get_localized_setting_name(setting.name)

            mw1 = 280
            mw2 = 70

            # Handle types with choices specially:
            if isinstance(setting, ba.ChoiceSetting):
                for choice in setting.choices:
                    if len(choice) != 2:
                        raise ValueError(
                            "Expected 2-member tuples for 'choices'; got: " +
                            repr(choice))
                    if not isinstance(choice[0], str):
                        raise TypeError(
                            'First value for choice tuple must be a str; got: '
                            + repr(choice))
                    if not isinstance(choice[1], value_type):
                        raise TypeError(
                            'Choice type does not match default value; choice:'
                            + repr(choice) + '; setting:' + repr(setting))
                if value_type not in (int, float):
                    raise TypeError(
                        'Choice type setting must have int or float default; '
                        'got: ' + repr(setting))

                # Start at the choice corresponding to the default if possible.
                self._choice_selections[setting.name] = 0
                for index, choice in enumerate(setting.choices):
                    if choice[1] == value:
                        self._choice_selections[setting.name] = index
                        break

                v -= spacing
                ba.textwidget(parent=self._subcontainer,
                              position=(h + 50, v),
                              size=(100, 30),
                              maxwidth=mw1,
                              text=name_translated,
                              h_align='left',
                              color=(0.8, 0.8, 0.8, 1.0),
                              v_align='center')
                txt = ba.textwidget(
                    parent=self._subcontainer,
                    position=(h + 509 - 95, v),
                    size=(0, 28),
                    text=self._get_localized_setting_name(setting.choices[
                        self._choice_selections[setting.name]][0]),
                    editable=False,
                    color=(0.6, 1.0, 0.6, 1.0),
                    maxwidth=mw2,
                    h_align='right',
                    v_align='center',
                    padding=2)
                btn1 = ba.buttonwidget(parent=self._subcontainer,
                                       position=(h + 509 - 50 - 1, v),
                                       size=(28, 28),
                                       label='<',
                                       autoselect=True,
                                       on_activate_call=ba.Call(
                                           self._choice_inc, setting.name, txt,
                                           setting, -1),
                                       repeat=True)
                btn2 = ba.buttonwidget(parent=self._subcontainer,
                                       position=(h + 509 + 5, v),
                                       size=(28, 28),
                                       label='>',
                                       autoselect=True,
                                       on_activate_call=ba.Call(
                                           self._choice_inc, setting.name, txt,
                                           setting, 1),
                                       repeat=True)
                widget_column.append([btn1, btn2])

            elif isinstance(setting, (ba.IntSetting, ba.FloatSetting)):
                v -= spacing
                min_value = setting.min_value
                max_value = setting.max_value
                increment = setting.increment
                ba.textwidget(parent=self._subcontainer,
                              position=(h + 50, v),
                              size=(100, 30),
                              text=name_translated,
                              h_align='left',
                              color=(0.8, 0.8, 0.8, 1.0),
                              v_align='center',
                              maxwidth=mw1)
                txt = ba.textwidget(parent=self._subcontainer,
                                    position=(h + 509 - 95, v),
                                    size=(0, 28),
                                    text=str(value),
                                    editable=False,
                                    color=(0.6, 1.0, 0.6, 1.0),
                                    maxwidth=mw2,
                                    h_align='right',
                                    v_align='center',
                                    padding=2)
                btn1 = ba.buttonwidget(parent=self._subcontainer,
                                       position=(h + 509 - 50 - 1, v),
                                       size=(28, 28),
                                       label='-',
                                       autoselect=True,
                                       on_activate_call=ba.Call(
                                           self._inc, txt, min_value,
                                           max_value, -increment, value_type,
                                           setting.name),
                                       repeat=True)
                btn2 = ba.buttonwidget(parent=self._subcontainer,
                                       position=(h + 509 + 5, v),
                                       size=(28, 28),
                                       label='+',
                                       autoselect=True,
                                       on_activate_call=ba.Call(
                                           self._inc, txt, min_value,
                                           max_value, increment, value_type,
                                           setting.name),
                                       repeat=True)
                widget_column.append([btn1, btn2])

            elif value_type == bool:
                v -= spacing
                ba.textwidget(parent=self._subcontainer,
                              position=(h + 50, v),
                              size=(100, 30),
                              text=name_translated,
                              h_align='left',
                              color=(0.8, 0.8, 0.8, 1.0),
                              v_align='center',
                              maxwidth=mw1)
                txt = ba.textwidget(
                    parent=self._subcontainer,
                    position=(h + 509 - 95, v),
                    size=(0, 28),
                    text=ba.Lstr(resource='onText') if value else ba.Lstr(
                        resource='offText'),
                    editable=False,
                    color=(0.6, 1.0, 0.6, 1.0),
                    maxwidth=mw2,
                    h_align='right',
                    v_align='center',
                    padding=2)
                cbw = ba.checkboxwidget(parent=self._subcontainer,
                                        text='',
                                        position=(h + 505 - 50 - 5, v - 2),
                                        size=(200, 30),
                                        autoselect=True,
                                        textcolor=(0.8, 0.8, 0.8),
                                        value=value,
                                        on_value_change_call=ba.Call(
                                            self._check_value_change,
                                            setting.name, txt))
                widget_column.append([cbw])

            else:
                raise Exception()

        # Ok now wire up the column.
        try:
            # pylint: disable=unsubscriptable-object
            prev_widgets: Optional[list[ba.Widget]] = None
            for cwdg in widget_column:
                if prev_widgets is not None:
                    # Wire our rightmost to their rightmost.
                    ba.widget(edit=prev_widgets[-1], down_widget=cwdg[-1])
                    ba.widget(cwdg[-1], up_widget=prev_widgets[-1])

                    # Wire our leftmost to their leftmost.
                    ba.widget(edit=prev_widgets[0], down_widget=cwdg[0])
                    ba.widget(cwdg[0], up_widget=prev_widgets[0])
                prev_widgets = cwdg
        except Exception:
            ba.print_exception(
                'Error wiring up game-settings-select widget column.')

        ba.buttonwidget(edit=add_button, on_activate_call=ba.Call(self._add))
        ba.containerwidget(edit=self._root_widget,
                           selected_child=add_button,
                           start_button=add_button)

        if default_selection == 'map':
            ba.containerwidget(edit=self._root_widget,
                               selected_child=self._scrollwidget)
            ba.containerwidget(edit=self._subcontainer,
                               selected_child=map_button)
Example #14
0
    def _refresh(self) -> None:
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=cyclic-import
        from bastd.ui import confirm

        account_state = _ba.get_account_state()
        account_type = (_ba.get_account_type()
                        if account_state == 'signed_in' else 'unknown')

        is_google = account_type == 'Google Play'

        show_local_signed_in_as = False
        local_signed_in_as_space = 50.0

        show_signed_in_as = self._signed_in
        signed_in_as_space = 95.0

        show_sign_in_benefits = not self._signed_in
        sign_in_benefits_space = 80.0

        show_signing_in_text = account_state == 'signing_in'
        signing_in_text_space = 80.0

        show_google_play_sign_in_button = (account_state == 'signed_out'
                                           and 'Google Play'
                                           in self._show_sign_in_buttons)
        show_game_circle_sign_in_button = (account_state == 'signed_out'
                                           and 'Game Circle'
                                           in self._show_sign_in_buttons)
        show_ali_sign_in_button = (account_state == 'signed_out'
                                   and 'Ali' in self._show_sign_in_buttons)
        show_test_sign_in_button = (account_state == 'signed_out'
                                    and 'Test' in self._show_sign_in_buttons)
        show_device_sign_in_button = (account_state == 'signed_out' and 'Local'
                                      in self._show_sign_in_buttons)
        sign_in_button_space = 70.0

        show_game_service_button = (self._signed_in and account_type
                                    in ['Game Center', 'Game Circle'])
        game_service_button_space = 60.0

        show_linked_accounts_text = (self._signed_in
                                     and _ba.get_account_misc_read_val(
                                         'allowAccountLinking2', False))
        linked_accounts_text_space = 60.0

        show_achievements_button = (self._signed_in and account_type
                                    in ('Google Play', 'Alibaba', 'Local',
                                        'OUYA', 'Test'))
        achievements_button_space = 60.0

        show_achievements_text = (self._signed_in
                                  and not show_achievements_button)
        achievements_text_space = 27.0

        show_leaderboards_button = (self._signed_in and is_google)
        leaderboards_button_space = 60.0

        show_campaign_progress = self._signed_in
        campaign_progress_space = 27.0

        show_tickets = self._signed_in
        tickets_space = 27.0

        show_reset_progress_button = False
        reset_progress_button_space = 70.0

        show_player_profiles_button = self._signed_in
        player_profiles_button_space = 100.0

        show_link_accounts_button = (self._signed_in
                                     and _ba.get_account_misc_read_val(
                                         'allowAccountLinking2', False))
        link_accounts_button_space = 70.0

        show_unlink_accounts_button = show_link_accounts_button
        unlink_accounts_button_space = 90.0

        show_sign_out_button = (self._signed_in and account_type
                                in ['Test', 'Local', 'Google Play'])
        sign_out_button_space = 70.0

        if self._subcontainer is not None:
            self._subcontainer.delete()
        self._sub_height = 60.0
        if show_local_signed_in_as:
            self._sub_height += local_signed_in_as_space
        if show_signed_in_as:
            self._sub_height += signed_in_as_space
        if show_signing_in_text:
            self._sub_height += signing_in_text_space
        if show_google_play_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_game_circle_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_ali_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_test_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_device_sign_in_button:
            self._sub_height += sign_in_button_space
        if show_game_service_button:
            self._sub_height += game_service_button_space
        if show_linked_accounts_text:
            self._sub_height += linked_accounts_text_space
        if show_achievements_text:
            self._sub_height += achievements_text_space
        if show_achievements_button:
            self._sub_height += achievements_button_space
        if show_leaderboards_button:
            self._sub_height += leaderboards_button_space
        if show_campaign_progress:
            self._sub_height += campaign_progress_space
        if show_tickets:
            self._sub_height += tickets_space
        if show_sign_in_benefits:
            self._sub_height += sign_in_benefits_space
        if show_reset_progress_button:
            self._sub_height += reset_progress_button_space
        if show_player_profiles_button:
            self._sub_height += player_profiles_button_space
        if show_link_accounts_button:
            self._sub_height += link_accounts_button_space
        if show_unlink_accounts_button:
            self._sub_height += unlink_accounts_button_space
        if show_sign_out_button:
            self._sub_height += sign_out_button_space
        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
                                                size=(self._sub_width,
                                                      self._sub_height),
                                                background=False)
        ba.containerwidget(edit=self._scrollwidget,
                           claims_left_right=True,
                           claims_tab=True,
                           selection_loop_to_parent=True)
        ba.containerwidget(edit=self._subcontainer,
                           claims_left_right=True,
                           claims_tab=True,
                           selection_loop_to_parent=True)

        first_selectable = None
        v = self._sub_height - 10.0

        if show_local_signed_in_as:
            v -= local_signed_in_as_space * 0.6
            ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                text=ba.Lstr(
                    resource='accountSettingsWindow.deviceSpecificAccountText',
                    subs=[('${NAME}', _ba.get_account_display_string())]),
                scale=0.7,
                color=(0.5, 0.5, 0.6),
                maxwidth=self._sub_width * 0.9,
                flatness=1.0,
                h_align='center',
                v_align='center')
            v -= local_signed_in_as_space * 0.4

        self._account_name_text: Optional[ba.Widget]
        if show_signed_in_as:
            v -= signed_in_as_space * 0.2
            txt = ba.Lstr(
                resource='accountSettingsWindow.youAreSignedInAsText',
                fallback_resource='accountSettingsWindow.youAreLoggedInAsText')
            ba.textwidget(parent=self._subcontainer,
                          position=(self._sub_width * 0.5, v),
                          size=(0, 0),
                          text=txt,
                          scale=0.9,
                          color=ba.app.ui.title_color,
                          maxwidth=self._sub_width * 0.9,
                          h_align='center',
                          v_align='center')
            v -= signed_in_as_space * 0.4
            self._account_name_text = ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                scale=1.5,
                maxwidth=self._sub_width * 0.9,
                res_scale=1.5,
                color=(1, 1, 1, 1),
                h_align='center',
                v_align='center')
            self._refresh_account_name_text()
            v -= signed_in_as_space * 0.4
        else:
            self._account_name_text = None

        if self._back_button is None:
            bbtn = _ba.get_special_widget('back_button')
        else:
            bbtn = self._back_button

        if show_sign_in_benefits:
            v -= sign_in_benefits_space
            app = ba.app
            extra: Optional[Union[str, ba.Lstr]]
            if (app.platform in ['mac', 'ios']
                    and app.subplatform == 'appstore'):
                extra = ba.Lstr(
                    value='\n${S}',
                    subs=[('${S}',
                           ba.Lstr(resource='signInWithGameCenterText'))])
            else:
                extra = ''

            ba.textwidget(parent=self._subcontainer,
                          position=(self._sub_width * 0.5,
                                    v + sign_in_benefits_space * 0.4),
                          size=(0, 0),
                          text=ba.Lstr(value='${A}${B}',
                                       subs=[('${A}',
                                              ba.Lstr(resource=self._r +
                                                      '.signInInfoText')),
                                             ('${B}', extra)]),
                          max_height=sign_in_benefits_space * 0.9,
                          scale=0.9,
                          color=(0.75, 0.7, 0.8),
                          maxwidth=self._sub_width * 0.8,
                          h_align='center',
                          v_align='center')

        if show_signing_in_text:
            v -= signing_in_text_space

            ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5,
                          v + signing_in_text_space * 0.5),
                size=(0, 0),
                text=ba.Lstr(resource='accountSettingsWindow.signingInText'),
                scale=0.9,
                color=(0, 1, 0),
                maxwidth=self._sub_width * 0.8,
                h_align='center',
                v_align='center')

        if show_google_play_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_google_play_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v - 20),
                autoselect=True,
                size=(button_width, 60),
                label=ba.Lstr(
                    value='${A}${B}',
                    subs=[('${A}',
                           ba.charstr(ba.SpecialChar.GOOGLE_PLAY_GAMES_LOGO)),
                          ('${B}',
                           ba.Lstr(resource=self._r +
                                   '.signInWithGooglePlayText'))]),
                on_activate_call=lambda: self._sign_in_press('Google Play'))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
            self._sign_in_text = None

        if show_game_circle_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_game_circle_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v - 20),
                autoselect=True,
                size=(button_width, 60),
                label=ba.Lstr(value='${A}${B}',
                              subs=[('${A}',
                                     ba.charstr(
                                         ba.SpecialChar.GAME_CIRCLE_LOGO)),
                                    ('${B}',
                                     ba.Lstr(resource=self._r +
                                             '.signInWithGameCircleText'))]),
                on_activate_call=lambda: self._sign_in_press('Game Circle'))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
            self._sign_in_text = None

        if show_ali_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_ali_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v - 20),
                autoselect=True,
                size=(button_width, 60),
                label=ba.Lstr(value='${A}${B}',
                              subs=[('${A}',
                                     ba.charstr(ba.SpecialChar.ALIBABA_LOGO)),
                                    ('${B}',
                                     ba.Lstr(resource=self._r + '.signInText'))
                                    ]),
                on_activate_call=lambda: self._sign_in_press('Ali'))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
            self._sign_in_text = None

        if show_device_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_device_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v - 20),
                autoselect=True,
                size=(button_width, 60),
                label='',
                on_activate_call=lambda: self._sign_in_press('Local'))
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v + 17),
                          text=ba.Lstr(
                              value='${A}${B}',
                              subs=[('${A}',
                                     ba.charstr(ba.SpecialChar.LOCAL_ACCOUNT)),
                                    ('${B}',
                                     ba.Lstr(resource=self._r +
                                             '.signInWithDeviceText'))]),
                          maxwidth=button_width * 0.8,
                          color=(0.75, 1.0, 0.7))
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v - 4),
                          text=ba.Lstr(resource=self._r +
                                       '.signInWithDeviceInfoText'),
                          flatness=1.0,
                          scale=0.57,
                          maxwidth=button_width * 0.9,
                          color=(0.55, 0.8, 0.5))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
            self._sign_in_text = None

        # Old test-account option.
        if show_test_sign_in_button:
            button_width = 350
            v -= sign_in_button_space
            self._sign_in_test_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v - 20),
                autoselect=True,
                size=(button_width, 60),
                label='',
                on_activate_call=lambda: self._sign_in_press('Test'))
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v + 17),
                          text=ba.Lstr(
                              value='${A}${B}',
                              subs=[('${A}',
                                     ba.charstr(ba.SpecialChar.TEST_ACCOUNT)),
                                    ('${B}',
                                     ba.Lstr(resource=self._r +
                                             '.signInWithTestAccountText'))]),
                          maxwidth=button_width * 0.8,
                          color=(0.75, 1.0, 0.7))
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v - 4),
                          text=ba.Lstr(resource=self._r +
                                       '.signInWithTestAccountInfoText'),
                          flatness=1.0,
                          scale=0.57,
                          maxwidth=button_width * 0.9,
                          color=(0.55, 0.8, 0.5))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100)
            self._sign_in_text = None

        if show_player_profiles_button:
            button_width = 300
            v -= player_profiles_button_space
            self._player_profiles_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v + 30),
                autoselect=True,
                size=(button_width, 60),
                label=ba.Lstr(resource='playerProfilesWindow.titleText'),
                color=(0.55, 0.5, 0.6),
                icon=ba.gettexture('cuteSpaz'),
                textcolor=(0.75, 0.7, 0.8),
                on_activate_call=self._player_profiles_press)
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=0)

        # the button to go to OS-Specific leaderboards/high-score-lists/etc.
        if show_game_service_button:
            button_width = 300
            v -= game_service_button_space * 0.85
            account_type = _ba.get_account_type()
            if account_type == 'Game Center':
                account_type_name = ba.Lstr(resource='gameCenterText')
            elif account_type == 'Game Circle':
                account_type_name = ba.Lstr(resource='gameCircleText')
            else:
                raise ValueError("unknown account type: '" +
                                 str(account_type) + "'")
            self._game_service_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                on_activate_call=_ba.show_online_score_ui,
                size=(button_width, 50),
                label=account_type_name)
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            v -= game_service_button_space * 0.15
        else:
            self.game_service_button = None

        self._achievements_text: Optional[ba.Widget]
        if show_achievements_text:
            v -= achievements_text_space * 0.5
            self._achievements_text = ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                scale=0.9,
                color=(0.75, 0.7, 0.8),
                maxwidth=self._sub_width * 0.8,
                h_align='center',
                v_align='center')
            v -= achievements_text_space * 0.5
        else:
            self._achievements_text = None

        self._achievements_button: Optional[ba.Widget]
        if show_achievements_button:
            button_width = 300
            v -= achievements_button_space * 0.85
            self._achievements_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                icon=ba.gettexture('googlePlayAchievementsIcon'
                                   if is_google else 'achievementsIcon'),
                icon_color=(0.8, 0.95, 0.7) if is_google else (0.85, 0.8, 0.9),
                on_activate_call=self._on_achievements_press,
                size=(button_width, 50),
                label='')
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            v -= achievements_button_space * 0.15
        else:
            self._achievements_button = None

        if show_achievements_text or show_achievements_button:
            self._refresh_achievements()

        self._leaderboards_button: Optional[ba.Widget]
        if show_leaderboards_button:
            button_width = 300
            v -= leaderboards_button_space * 0.85
            self._leaderboards_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                icon=ba.gettexture('googlePlayLeaderboardsIcon'),
                icon_color=(0.8, 0.95, 0.7),
                on_activate_call=self._on_leaderboards_press,
                size=(button_width, 50),
                label=ba.Lstr(resource='leaderboardsText'))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)
            v -= leaderboards_button_space * 0.15
        else:
            self._leaderboards_button = None

        self._campaign_progress_text: Optional[ba.Widget]
        if show_campaign_progress:
            v -= campaign_progress_space * 0.5
            self._campaign_progress_text = ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                scale=0.9,
                color=(0.75, 0.7, 0.8),
                maxwidth=self._sub_width * 0.8,
                h_align='center',
                v_align='center')
            v -= campaign_progress_space * 0.5
            self._refresh_campaign_progress_text()
        else:
            self._campaign_progress_text = None

        self._tickets_text: Optional[ba.Widget]
        if show_tickets:
            v -= tickets_space * 0.5
            self._tickets_text = ba.textwidget(parent=self._subcontainer,
                                               position=(self._sub_width * 0.5,
                                                         v),
                                               size=(0, 0),
                                               scale=0.9,
                                               color=(0.75, 0.7, 0.8),
                                               maxwidth=self._sub_width * 0.8,
                                               flatness=1.0,
                                               h_align='center',
                                               v_align='center')
            v -= tickets_space * 0.5
            self._refresh_tickets_text()

        else:
            self._tickets_text = None

        # bit of spacing before the reset/sign-out section
        v -= 5

        button_width = 250
        if show_reset_progress_button:
            confirm_text = (ba.Lstr(resource=self._r +
                                    '.resetProgressConfirmText')
                            if self._can_reset_achievements else ba.Lstr(
                                resource=self._r +
                                '.resetProgressConfirmNoAchievementsText'))
            v -= reset_progress_button_space
            self._reset_progress_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                size=(button_width, 60),
                label=ba.Lstr(resource=self._r + '.resetProgressText'),
                on_activate_call=lambda: confirm.ConfirmWindow(
                    text=confirm_text,
                    width=500,
                    height=200,
                    action=self._reset_progress))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn)

        self._linked_accounts_text: Optional[ba.Widget]
        if show_linked_accounts_text:
            v -= linked_accounts_text_space * 0.8
            self._linked_accounts_text = ba.textwidget(
                parent=self._subcontainer,
                position=(self._sub_width * 0.5, v),
                size=(0, 0),
                scale=0.9,
                color=(0.75, 0.7, 0.8),
                maxwidth=self._sub_width * 0.95,
                h_align='center',
                v_align='center')
            v -= linked_accounts_text_space * 0.2
            self._update_linked_accounts_text()
        else:
            self._linked_accounts_text = None

        if show_link_accounts_button:
            v -= link_accounts_button_space
            self._link_accounts_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                autoselect=True,
                size=(button_width, 60),
                label='',
                color=(0.55, 0.5, 0.6),
                on_activate_call=self._link_accounts_press)
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v + 17 + 20),
                          text=ba.Lstr(resource=self._r + '.linkAccountsText'),
                          maxwidth=button_width * 0.8,
                          color=(0.75, 0.7, 0.8))
            ba.textwidget(parent=self._subcontainer,
                          draw_controller=btn,
                          h_align='center',
                          v_align='center',
                          size=(0, 0),
                          position=(self._sub_width * 0.5, v - 4 + 20),
                          text=ba.Lstr(resource=self._r +
                                       '.linkAccountsInfoText'),
                          flatness=1.0,
                          scale=0.5,
                          maxwidth=button_width * 0.8,
                          color=(0.75, 0.7, 0.8))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=50)

        self._unlink_accounts_button: Optional[ba.Widget]
        if show_unlink_accounts_button:
            v -= unlink_accounts_button_space
            self._unlink_accounts_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v + 25),
                autoselect=True,
                size=(button_width, 60),
                label='',
                color=(0.55, 0.5, 0.6),
                on_activate_call=self._unlink_accounts_press)
            self._unlink_accounts_button_label = ba.textwidget(
                parent=self._subcontainer,
                draw_controller=btn,
                h_align='center',
                v_align='center',
                size=(0, 0),
                position=(self._sub_width * 0.5, v + 55),
                text=ba.Lstr(resource=self._r + '.unlinkAccountsText'),
                maxwidth=button_width * 0.8,
                color=(0.75, 0.7, 0.8))
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=50)
            self._update_unlink_accounts_button()
        else:
            self._unlink_accounts_button = None

        if show_sign_out_button:
            v -= sign_out_button_space
            self._sign_out_button = btn = ba.buttonwidget(
                parent=self._subcontainer,
                position=((self._sub_width - button_width) * 0.5, v),
                size=(button_width, 60),
                label=ba.Lstr(resource=self._r + '.signOutText'),
                color=(0.55, 0.5, 0.6),
                textcolor=(0.75, 0.7, 0.8),
                autoselect=True,
                on_activate_call=self._sign_out_press)
            if first_selectable is None:
                first_selectable = btn
            if ba.app.ui.use_toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=15)

        # Whatever the topmost selectable thing is, we want it to scroll all
        # the way up when we select it.
        if first_selectable is not None:
            ba.widget(edit=first_selectable,
                      up_widget=bbtn,
                      show_buffer_top=400)
            # (this should re-scroll us to the top..)
            ba.containerwidget(edit=self._subcontainer,
                               visible_child=first_selectable)
        self._needs_refresh = False
Example #15
0
    def _refresh(self, select_get_more_maps_button: bool = False) -> None:
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        from ba.internal import (get_unowned_maps, get_map_class,
                                 get_map_display_string)

        # Kill old.
        if self._subcontainer is not None:
            self._subcontainer.delete()

        model_opaque = ba.getmodel('level_select_button_opaque')
        model_transparent = ba.getmodel('level_select_button_transparent')

        self._maps = []
        map_list = self._gameclass.get_supported_maps(self._sessiontype)
        map_list_sorted = list(map_list)
        map_list_sorted.sort()
        unowned_maps = get_unowned_maps()

        for mapname in map_list_sorted:

            # Disallow ones we don't own.
            if mapname in unowned_maps:
                continue
            map_tex_name = (get_map_class(mapname).get_preview_texture_name())
            if map_tex_name is not None:
                try:
                    map_tex = ba.gettexture(map_tex_name)
                    self._maps.append((mapname, map_tex))
                except Exception:
                    print(f'Invalid map preview texture: "{map_tex_name}".')
            else:
                print('Error: no map preview texture for map:', mapname)

        count = len(self._maps)
        columns = 2
        rows = int(math.ceil(float(count) / columns))
        button_width = 220
        button_height = button_width * 0.5
        button_buffer_h = 16
        button_buffer_v = 19
        self._sub_width = self._scroll_width * 0.95
        self._sub_height = 5 + rows * (button_height +
                                       2 * button_buffer_v) + 100
        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
                                                size=(self._sub_width,
                                                      self._sub_height),
                                                background=False)
        index = 0
        mask_texture = ba.gettexture('mapPreviewMask')
        h_offs = 130 if len(self._maps) == 1 else 0
        for y in range(rows):
            for x in range(columns):
                pos = (x * (button_width + 2 * button_buffer_h) +
                       button_buffer_h + h_offs, self._sub_height - (y + 1) *
                       (button_height + 2 * button_buffer_v) + 12)
                btn = ba.buttonwidget(parent=self._subcontainer,
                                      button_type='square',
                                      size=(button_width, button_height),
                                      autoselect=True,
                                      texture=self._maps[index][1],
                                      mask_texture=mask_texture,
                                      model_opaque=model_opaque,
                                      model_transparent=model_transparent,
                                      label='',
                                      color=(1, 1, 1),
                                      on_activate_call=ba.Call(
                                          self._select_with_delay,
                                          self._maps[index][0]),
                                      position=pos)
                if x == 0:
                    ba.widget(edit=btn, left_widget=self._cancel_button)
                if y == 0:
                    ba.widget(edit=btn, up_widget=self._cancel_button)
                if x == columns - 1 and ba.app.ui.use_toolbars:
                    ba.widget(
                        edit=btn,
                        right_widget=_ba.get_special_widget('party_button'))

                ba.widget(edit=btn, show_buffer_top=60, show_buffer_bottom=60)
                if self._maps[index][0] == self._previous_map:
                    ba.containerwidget(edit=self._subcontainer,
                                       selected_child=btn,
                                       visible_child=btn)
                name = get_map_display_string(self._maps[index][0])
                ba.textwidget(parent=self._subcontainer,
                              text=name,
                              position=(pos[0] + button_width * 0.5,
                                        pos[1] - 12),
                              size=(0, 0),
                              scale=0.5,
                              maxwidth=button_width,
                              draw_controller=btn,
                              h_align='center',
                              v_align='center',
                              color=(0.8, 0.8, 0.8, 0.8))
                index += 1

                if index >= count:
                    break
            if index >= count:
                break
        self._get_more_maps_button = btn = ba.buttonwidget(
            parent=self._subcontainer,
            size=(self._sub_width * 0.8, 60),
            position=(self._sub_width * 0.1, 30),
            label=ba.Lstr(resource='mapSelectGetMoreMapsText'),
            on_activate_call=self._on_store_press,
            color=(0.6, 0.53, 0.63),
            textcolor=(0.75, 0.7, 0.8),
            autoselect=True)
        ba.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30)
        if select_get_more_maps_button:
            ba.containerwidget(edit=self._subcontainer,
                               selected_child=btn,
                               visible_child=btn)
Example #16
0
    def __init__(self,
                 transition: Optional[str] = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        # pylint: disable=cyclic-import
        from bastd.ui.gather.abouttab import AboutGatherTab
        from bastd.ui.gather.manualtab import ManualGatherTab
        from bastd.ui.gather.privatetab import PrivateGatherTab
        from bastd.ui.gather.publictab import PublicGatherTab
        from bastd.ui.gather.nearbytab import NearbyGatherTab

        ba.set_analytics_screen('Gather Window')
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
        ba.app.ui.set_main_menu_location('Gather')
        _ba.set_party_icon_always_visible(True)
        uiscale = ba.app.ui.uiscale
        self._width = 1240 if uiscale is ba.UIScale.SMALL else 1040
        x_offs = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (582 if uiscale is ba.UIScale.SMALL else
                        680 if uiscale is ba.UIScale.MEDIUM else 800)
        self._current_tab: Optional[GatherWindow.TabID] = None
        extra_top = 20 if uiscale is ba.UIScale.SMALL else 0
        self._r = 'gatherWindow'

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + extra_top),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(1.3 if uiscale is ba.UIScale.SMALL else
                   0.97 if uiscale is ba.UIScale.MEDIUM else 0.8),
            stack_offset=(0, -11) if uiscale is ba.UIScale.SMALL else (
                0, 0) if uiscale is ba.UIScale.MEDIUM else (0, 0)))

        if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back)
            self._back_button = None
        else:
            self._back_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=(70 + x_offs, self._height - 74),
                size=(140, 60),
                scale=1.1,
                autoselect=True,
                label=ba.Lstr(resource='backText'),
                button_type='back',
                on_activate_call=self._back)
            ba.containerwidget(edit=self._root_widget, cancel_button=btn)
            ba.buttonwidget(edit=btn,
                            button_type='backSmall',
                            position=(70 + x_offs, self._height - 78),
                            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 + t_offs_y),
                      size=(0, 0),
                      color=ba.app.ui.title_color,
                      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'),
                      maxwidth=550)

        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, ba.Lstr]] = [
            (self.TabID.ABOUT, ba.Lstr(resource=self._r + '.aboutText'))
        ]
        if _ba.get_account_misc_read_val('enablePublicParties', True):
            tabdefs.append((self.TabID.INTERNET,
                            ba.Lstr(resource=self._r + '.publicText')))
        tabdefs.append(
            (self.TabID.PRIVATE, ba.Lstr(resource=self._r + '.privateText')))
        tabdefs.append(
            (self.TabID.NEARBY, ba.Lstr(resource=self._r + '.nearbyText')))
        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 + tabs_top_extra),
                               size=(self._width - tab_buffer_h, 50),
                               on_select_call=ba.WeakCall(self._set_tab))

        # Now instantiate handlers for these tabs.
        tabtypes: Dict[GatherWindow.TabID, Type[GatherTab]] = {
            self.TabID.ABOUT: AboutGatherTab,
            self.TabID.MANUAL: ManualGatherTab,
            self.TabID.PRIVATE: PrivateGatherTab,
            self.TabID.INTERNET: PublicGatherTab,
            self.TabID.NEARBY: NearbyGatherTab
        }
        self._tabs: Dict[GatherWindow.TabID, GatherTab] = {}
        for tab_id in self._tab_row.tabs:
            tabtype = tabtypes.get(tab_id)
            if tabtype is not None:
                self._tabs[tab_id] = tabtype(self)

        if ba.app.ui.use_toolbars:
            ba.widget(edit=self._tab_row.tabs[tabdefs[-1][0]].button,
                      right_widget=_ba.get_special_widget('party_button'))
            if uiscale is ba.UIScale.SMALL:
                ba.widget(edit=self._tab_row.tabs[tabdefs[0][0]].button,
                          left_widget=_ba.get_special_widget('back_button'))

        self._scroll_width = self._width - scroll_buffer_h
        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 +
                               tabs_top_extra)
        buffer_h = 10
        buffer_v = 4

        # Not actually using a scroll widget anymore; just an image.
        ba.imagewidget(parent=self._root_widget,
                       position=(self._scroll_left - buffer_h,
                                 self._scroll_bottom - buffer_v),
                       size=(self._scroll_width + 2 * buffer_h,
                             self._scroll_height + 2 * buffer_v),
                       texture=ba.gettexture('scrollWidget'),
                       model_transparent=ba.getmodel('softEdgeOutside'))
        self._tab_container: Optional[ba.Widget] = None

        self._restore_state()
Example #17
0
    def __init__(self,
                 editcontroller: PlaylistEditController,
                 transition: str = 'in_right'):
        self._editcontroller = editcontroller
        self._r = 'addGameWindow'
        uiscale = ba.app.ui.uiscale
        self._width = 750 if uiscale is ba.UIScale.SMALL else 650
        x_inset = 50 if uiscale is ba.UIScale.SMALL else 0
        self._height = (346 if uiscale is ba.UIScale.SMALL else
                        380 if uiscale is ba.UIScale.MEDIUM else 440)
        top_extra = 30 if uiscale is ba.UIScale.SMALL else 20
        self._scroll_width = 210

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            scale=(2.17 if uiscale is ba.UIScale.SMALL else
                   1.5 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, 1) if uiscale is ba.UIScale.SMALL else (0, 0)))

        self._back_button = ba.buttonwidget(parent=self._root_widget,
                                            position=(58 + x_inset,
                                                      self._height - 53),
                                            size=(165, 70),
                                            scale=0.75,
                                            text_scale=1.2,
                                            label=ba.Lstr(resource='backText'),
                                            autoselect=True,
                                            button_type='back',
                                            on_activate_call=self._back)
        self._select_button = select_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(self._width - (172 + x_inset), self._height - 50),
            autoselect=True,
            size=(160, 60),
            scale=0.75,
            text_scale=1.2,
            label=ba.Lstr(resource='selectText'),
            on_activate_call=self._add)

        if ba.app.ui.use_toolbars:
            ba.widget(edit=select_button,
                      right_widget=_ba.get_special_widget('party_button'))

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 28),
                      size=(0, 0),
                      scale=1.0,
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      h_align='center',
                      color=ba.app.ui.title_color,
                      maxwidth=250,
                      v_align='center')
        v = self._height - 64

        self._selected_title_text = ba.textwidget(
            parent=self._root_widget,
            position=(x_inset + self._scroll_width + 50 + 30, v - 15),
            size=(0, 0),
            scale=1.0,
            color=(0.7, 1.0, 0.7, 1.0),
            maxwidth=self._width - self._scroll_width - 150 - x_inset * 2,
            h_align='left',
            v_align='center')
        v -= 30

        self._selected_description_text = ba.textwidget(
            parent=self._root_widget,
            position=(x_inset + self._scroll_width + 50 + 30, v),
            size=(0, 0),
            scale=0.7,
            color=(0.5, 0.8, 0.5, 1.0),
            maxwidth=self._width - self._scroll_width - 150 - x_inset * 2,
            h_align='left')

        scroll_height = self._height - 100

        v = self._height - 60

        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                             position=(x_inset + 61,
                                                       v - scroll_height),
                                             size=(self._scroll_width,
                                                   scroll_height),
                                             highlight=False)
        ba.widget(edit=self._scrollwidget,
                  up_widget=self._back_button,
                  left_widget=self._back_button,
                  right_widget=select_button)
        self._column: Optional[ba.Widget] = None

        v -= 35
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._back_button,
                           start_button=select_button)
        self._selected_game_type: Optional[Type[ba.GameActivity]] = None

        ba.containerwidget(edit=self._root_widget,
                           selected_child=self._scrollwidget)

        self._refresh()
Example #18
0
    def _rebuild(self) -> None:
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        from bastd.ui.config import ConfigCheckBox
        from ba.internal import show_user_scripts

        # Don't rebuild if the menu is open or if our language and
        # language-list hasn't changed.
        # NOTE - although we now support widgets updating their own
        # translations, we still change the label formatting on the language
        # menu based on the language so still need this. ...however we could
        # make this more limited to it only rebuilds that one menu instead
        # of everything.
        if self._menu_open or (
                self._prev_lang == _ba.app.config.get('Lang', None)
                and self._prev_lang_list == ba.get_valid_languages()):
            return
        self._prev_lang = _ba.app.config.get('Lang', None)
        self._prev_lang_list = ba.get_valid_languages()

        # Clear out our sub-container.
        children = self._subcontainer.get_children()
        for child in children:
            child.delete()

        v = self._sub_height - 35

        v -= self._spacing * 1.2

        # Update our existing back button and title.
        if self._back_button is not None:
            ba.buttonwidget(edit=self._back_button,
                            label=ba.Lstr(resource='backText'))
            ba.buttonwidget(edit=self._back_button,
                            label=ba.charstr(ba.SpecialChar.BACK))

        ba.textwidget(edit=self._title_text,
                      text=ba.Lstr(resource=self._r + '.titleText'))

        this_button_width = 410

        self._promo_code_button = ba.buttonwidget(
            parent=self._subcontainer,
            position=(self._sub_width / 2 - this_button_width / 2, v - 14),
            size=(this_button_width, 60),
            autoselect=True,
            label=ba.Lstr(resource=self._r + '.enterPromoCodeText'),
            text_scale=1.0,
            on_activate_call=self._on_promo_code_press)
        if self._back_button is not None:
            ba.widget(edit=self._promo_code_button,
                      up_widget=self._back_button,
                      left_widget=self._back_button)
        v -= self._extra_button_spacing * 0.8

        ba.textwidget(parent=self._subcontainer,
                      position=(200, v + 10),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r + '.languageText'),
                      maxwidth=150,
                      scale=0.95,
                      color=ba.app.title_color,
                      h_align='right',
                      v_align='center')

        languages = ba.get_valid_languages()
        cur_lang = _ba.app.config.get('Lang', None)
        if cur_lang is None:
            cur_lang = 'Auto'

        # We have a special dict of language names in that language
        # so we don't have to go digging through each full language.
        try:
            import json
            with open('ba_data/data/langdata.json') as infile:
                lang_names_translated = (json.loads(
                    infile.read())['lang_names_translated'])
        except Exception:
            ba.print_exception('error reading lang data')
            lang_names_translated = {}

        langs_translated = {}
        for lang in languages:
            langs_translated[lang] = lang_names_translated.get(lang, lang)

        langs_full = {}
        for lang in languages:
            lang_translated = ba.Lstr(translate=('languages', lang)).evaluate()
            if langs_translated[lang] == lang_translated:
                langs_full[lang] = lang_translated
            else:
                langs_full[lang] = (langs_translated[lang] + ' (' +
                                    lang_translated + ')')

        self._language_popup = popup_ui.PopupMenu(
            parent=self._subcontainer,
            position=(210, v - 19),
            width=150,
            opening_call=ba.WeakCall(self._on_menu_open),
            closing_call=ba.WeakCall(self._on_menu_close),
            autoselect=False,
            on_value_change_call=ba.WeakCall(self._on_menu_choice),
            choices=['Auto'] + languages,
            button_size=(250, 60),
            choices_display=([
                ba.Lstr(value=(ba.Lstr(resource='autoText').evaluate() + ' (' +
                               ba.Lstr(translate=(
                                   'languages',
                                   ba.app.default_language)).evaluate() + ')'))
            ] + [ba.Lstr(value=langs_full[l]) for l in languages]),
            current_choice=cur_lang)

        v -= self._spacing * 1.8

        ba.textwidget(parent=self._subcontainer,
                      position=(self._sub_width * 0.5, v + 10),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r + '.helpTranslateText',
                                   subs=[('${APP_NAME}',
                                          ba.Lstr(resource='titleText'))]),
                      maxwidth=self._sub_width * 0.9,
                      max_height=55,
                      flatness=1.0,
                      scale=0.65,
                      color=(0.4, 0.9, 0.4, 0.8),
                      h_align='center',
                      v_align='center')
        v -= self._spacing * 1.9
        this_button_width = 410
        self._translation_editor_button = ba.buttonwidget(
            parent=self._subcontainer,
            position=(self._sub_width / 2 - this_button_width / 2, v - 24),
            size=(this_button_width, 60),
            label=ba.Lstr(resource=self._r + '.translationEditorButtonText',
                          subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))
                                ]),
            autoselect=True,
            on_activate_call=ba.Call(ba.open_url,
                                     'http://bombsquadgame.com/translate'))

        self._lang_status_text = ba.textwidget(parent=self._subcontainer,
                                               position=(self._sub_width * 0.5,
                                                         v - 40),
                                               size=(0, 0),
                                               text='',
                                               flatness=1.0,
                                               scale=0.63,
                                               h_align='center',
                                               v_align='center',
                                               maxwidth=400.0)
        self._update_lang_status()
        v -= 40

        lang_inform = _ba.get_account_misc_val('langInform', False)

        self._language_inform_checkbox = cbw = ba.checkboxwidget(
            parent=self._subcontainer,
            position=(50, v - 50),
            size=(self._sub_width - 100, 30),
            autoselect=True,
            maxwidth=430,
            textcolor=(0.8, 0.8, 0.8),
            value=lang_inform,
            text=ba.Lstr(resource=self._r + '.translationInformMe'),
            on_value_change_call=ba.WeakCall(
                self._on_lang_inform_value_change))

        ba.widget(edit=self._translation_editor_button,
                  down_widget=cbw,
                  up_widget=self._language_popup.get_button())

        v -= self._spacing * 3.0

        self._kick_idle_players_check_box = ConfigCheckBox(
            parent=self._subcontainer,
            position=(50, v),
            size=(self._sub_width - 100, 30),
            configkey='Kick Idle Players',
            displayname=ba.Lstr(resource=self._r + '.kickIdlePlayersText'),
            scale=1.0,
            maxwidth=430)

        self._always_use_internal_keyboard_check_box: Optional[ConfigCheckBox]
        if self._show_always_use_internal_keyboard:
            v -= 42
            self._always_use_internal_keyboard_check_box = ConfigCheckBox(
                parent=self._subcontainer,
                position=(50, v),
                size=(self._sub_width - 100, 30),
                configkey='Always Use Internal Keyboard',
                autoselect=True,
                displayname=ba.Lstr(resource=self._r +
                                    '.alwaysUseInternalKeyboardText'),
                scale=1.0,
                maxwidth=430)
            ba.textwidget(
                parent=self._subcontainer,
                position=(90, v - 10),
                size=(0, 0),
                text=ba.Lstr(resource=self._r +
                             '.alwaysUseInternalKeyboardDescriptionText'),
                maxwidth=400,
                flatness=1.0,
                scale=0.65,
                color=(0.4, 0.9, 0.4, 0.8),
                h_align='left',
                v_align='center')
            v -= 20
        else:
            self._always_use_internal_keyboard_check_box = None

        v -= self._spacing * 2.1

        this_button_width = 410
        self._show_user_mods_button = ba.buttonwidget(
            parent=self._subcontainer,
            position=(self._sub_width / 2 - this_button_width / 2, v - 10),
            size=(this_button_width, 60),
            autoselect=True,
            label=ba.Lstr(resource=self._r + '.showUserModsText'),
            text_scale=1.0,
            on_activate_call=show_user_scripts)
        if self._show_always_use_internal_keyboard:
            assert self._always_use_internal_keyboard_check_box is not None
            ba.widget(edit=self._always_use_internal_keyboard_check_box.widget,
                      down_widget=self._show_user_mods_button)
            ba.widget(
                edit=self._show_user_mods_button,
                up_widget=self._always_use_internal_keyboard_check_box.widget)
        else:
            ba.widget(edit=self._show_user_mods_button,
                      up_widget=self._kick_idle_players_check_box.widget)
            ba.widget(edit=self._kick_idle_players_check_box.widget,
                      down_widget=self._show_user_mods_button)

        v -= self._spacing * 2.0

        btn = self._modding_guide_button = ba.buttonwidget(
            parent=self._subcontainer,
            position=(self._sub_width / 2 - this_button_width / 2, v - 10),
            size=(this_button_width, 60),
            autoselect=True,
            label=ba.Lstr(resource=self._r + '.moddingGuideText'),
            text_scale=1.0,
            on_activate_call=ba.Call(
                ba.open_url,
                'http://www.froemling.net/docs/bombsquad-modding-guide'))

        v -= self._spacing * 1.8

        self._enable_package_mods_checkbox = ConfigCheckBox(
            parent=self._subcontainer,
            position=(80, v),
            size=(self._sub_width - 100, 30),
            configkey='Enable Package Mods',
            autoselect=True,
            value_change_call=ba.WeakCall(self._show_restart_needed),
            displayname=ba.Lstr(resource=self._r + '.enablePackageModsText'),
            scale=1.0,
            maxwidth=400)
        ccb = self._enable_package_mods_checkbox.widget
        ba.widget(edit=btn, down_widget=ccb)
        ba.widget(edit=ccb, up_widget=btn)
        ba.textwidget(parent=self._subcontainer,
                      position=(90, v - 10),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r +
                                   '.enablePackageModsDescriptionText'),
                      maxwidth=400,
                      flatness=1.0,
                      scale=0.65,
                      color=(0.4, 0.9, 0.4, 0.8),
                      h_align='left',
                      v_align='center')

        v -= self._spacing * 0.6

        self._vr_test_button: Optional[ba.Widget]
        if self._do_vr_test_button:
            v -= self._extra_button_spacing
            self._vr_test_button = ba.buttonwidget(
                parent=self._subcontainer,
                position=(self._sub_width / 2 - this_button_width / 2, v - 14),
                size=(this_button_width, 60),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.vrTestingText'),
                text_scale=1.0,
                on_activate_call=self._on_vr_test_press)
        else:
            self._vr_test_button = None

        self._net_test_button: Optional[ba.Widget]
        if self._do_net_test_button:
            v -= self._extra_button_spacing
            self._net_test_button = ba.buttonwidget(
                parent=self._subcontainer,
                position=(self._sub_width / 2 - this_button_width / 2, v - 14),
                size=(this_button_width, 60),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.netTestingText'),
                text_scale=1.0,
                on_activate_call=self._on_net_test_press)
        else:
            self._net_test_button = None

        v -= 70
        self._benchmarks_button = ba.buttonwidget(
            parent=self._subcontainer,
            position=(self._sub_width / 2 - this_button_width / 2, v - 14),
            size=(this_button_width, 60),
            autoselect=True,
            label=ba.Lstr(resource=self._r + '.benchmarksText'),
            text_scale=1.0,
            on_activate_call=self._on_benchmark_press)

        ba.widget(edit=self._vr_test_button if self._vr_test_button is not None
                  else self._net_test_button if self._net_test_button
                  is not None else self._benchmarks_button,
                  up_widget=cbw)

        for child in self._subcontainer.get_children():
            ba.widget(edit=child, show_buffer_bottom=30, show_buffer_top=20)

        if ba.app.toolbars:
            pbtn = _ba.get_special_widget('party_button')
            ba.widget(edit=self._scrollwidget, right_widget=pbtn)
            if self._back_button is None:
                ba.widget(edit=self._scrollwidget,
                          left_widget=_ba.get_special_widget('back_button'))

        self._restore_state()
    def __init__(self,
                 sessiontype: type[ba.Session],
                 transition: str = 'in_right',
                 select_playlist: str = None,
                 origin_widget: ba.Widget = None):
        # Yes this needs tidying.
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        # pylint: disable=cyclic-import
        from bastd.ui import playlist
        scale_origin: Optional[tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        self._sessiontype = sessiontype
        self._pvars = playlist.PlaylistTypeVars(sessiontype)
        self._max_playlists = 30
        self._r = 'gameListWindow'
        uiscale = ba.app.ui.uiscale
        self._width = 750.0 if uiscale is ba.UIScale.SMALL else 650.0
        x_inset = 50.0 if uiscale is ba.UIScale.SMALL else 0.0
        self._height = (380.0 if uiscale is ba.UIScale.SMALL else
                        420.0 if uiscale is ba.UIScale.MEDIUM else 500.0)
        top_extra = 20.0 if uiscale is ba.UIScale.SMALL else 0.0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            scale=(2.05 if uiscale is ba.UIScale.SMALL else
                   1.5 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -10) if uiscale is ba.UIScale.SMALL else (0, 0)))

        self._back_button = back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(43 + x_inset, self._height - 60),
            size=(160, 68),
            scale=0.77,
            autoselect=True,
            text_scale=1.3,
            label=ba.Lstr(resource='backText'),
            button_type='back')

        ba.textwidget(parent=self._root_widget,
                      position=(0, self._height - 47),
                      size=(self._width, 25),
                      text=ba.Lstr(resource=self._r + '.titleText',
                                   subs=[('${TYPE}',
                                          self._pvars.window_title_name)]),
                      color=ba.app.ui.heading_color,
                      maxwidth=290,
                      h_align='center',
                      v_align='center')

        ba.buttonwidget(edit=btn,
                        button_type='backSmall',
                        size=(60, 60),
                        label=ba.charstr(ba.SpecialChar.BACK))

        v = self._height - 59.0
        h = 41 + x_inset
        b_color = (0.6, 0.53, 0.63)
        b_textcolor = (0.75, 0.7, 0.8)
        self._lock_images: list[ba.Widget] = []
        lock_tex = ba.gettexture('lock')

        scl = (1.1 if uiscale is ba.UIScale.SMALL else
               1.27 if uiscale is ba.UIScale.MEDIUM else 1.57)
        scl *= 0.63
        v -= 65.0 * scl
        new_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._new_playlist,
            color=b_color,
            autoselect=True,
            button_type='square',
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource='newText',
                          fallback_resource=self._r + '.newText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))

        v -= 65.0 * scl
        self._edit_button = edit_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._edit_playlist,
            color=b_color,
            autoselect=True,
            textcolor=b_textcolor,
            button_type='square',
            text_scale=0.7,
            label=ba.Lstr(resource='editText',
                          fallback_resource=self._r + '.editText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))

        v -= 65.0 * scl
        duplicate_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._duplicate_playlist,
            color=b_color,
            autoselect=True,
            textcolor=b_textcolor,
            button_type='square',
            text_scale=0.7,
            label=ba.Lstr(resource='duplicateText',
                          fallback_resource=self._r + '.duplicateText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))

        v -= 65.0 * scl
        delete_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._delete_playlist,
            color=b_color,
            autoselect=True,
            textcolor=b_textcolor,
            button_type='square',
            text_scale=0.7,
            label=ba.Lstr(resource='deleteText',
                          fallback_resource=self._r + '.deleteText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))
        v -= 65.0 * scl
        self._import_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(90, 58.0 * scl),
            on_activate_call=self._import_playlist,
            color=b_color,
            autoselect=True,
            textcolor=b_textcolor,
            button_type='square',
            text_scale=0.7,
            label=ba.Lstr(resource='importText'))
        v -= 65.0 * scl
        btn = ba.buttonwidget(parent=self._root_widget,
                              position=(h, v),
                              size=(90, 58.0 * scl),
                              on_activate_call=self._share_playlist,
                              color=b_color,
                              autoselect=True,
                              textcolor=b_textcolor,
                              button_type='square',
                              text_scale=0.7,
                              label=ba.Lstr(resource='shareText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 58.0 * scl - 28),
                           texture=lock_tex))

        v = self._height - 75
        self._scroll_height = self._height - 119
        scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                       position=(140 + x_inset,
                                                 v - self._scroll_height),
                                       size=(self._width - (180 + 2 * x_inset),
                                             self._scroll_height + 10),
                                       highlight=False)
        ba.widget(edit=back_button, right_widget=scrollwidget)
        self._columnwidget = ba.columnwidget(parent=scrollwidget,
                                             border=2,
                                             margin=0)

        h = 145

        self._do_randomize_val = ba.app.config.get(
            self._pvars.config_name + ' Playlist Randomize', 0)

        h += 210

        for btn in [new_button, delete_button, edit_button, duplicate_button]:
            ba.widget(edit=btn, right_widget=scrollwidget)
        ba.widget(edit=scrollwidget,
                  left_widget=new_button,
                  right_widget=_ba.get_special_widget('party_button')
                  if ba.app.ui.use_toolbars else None)

        # make sure config exists
        self._config_name_full = self._pvars.config_name + ' Playlists'

        if self._config_name_full not in ba.app.config:
            ba.app.config[self._config_name_full] = {}

        self._selected_playlist_name: Optional[str] = None
        self._selected_playlist_index: Optional[int] = None
        self._playlist_widgets: list[ba.Widget] = []

        self._refresh(select_playlist=select_playlist)

        ba.buttonwidget(edit=back_button, on_activate_call=self._back)
        ba.containerwidget(edit=self._root_widget, cancel_button=back_button)

        ba.containerwidget(edit=self._root_widget, selected_child=scrollwidget)

        # Keep our lock images up to date/etc.
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._update()
    def __init__(self,
                 main_menu: bool = False,
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        from ba.internal import get_remote_app_name
        ba.set_analytics_screen('Help Window')

        # If they provided an origin-widget, scale up from that.
        scale_origin: Optional[tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
            transition = 'in_right'

        self._r = 'helpWindow'

        getres = ba.app.lang.get_resource

        self._main_menu = main_menu
        uiscale = ba.app.ui.uiscale
        width = 950 if uiscale is ba.UIScale.SMALL else 750
        x_offs = 100 if uiscale is ba.UIScale.SMALL else 0
        height = (460 if uiscale is ba.UIScale.SMALL else
                  530 if uiscale is ba.UIScale.MEDIUM else 600)

        super().__init__(root_widget=ba.containerwidget(
            size=(width, height),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(1.77 if uiscale is ba.UIScale.SMALL else
                   1.25 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -30) if uiscale is ba.UIScale.SMALL else (
                0, 15) if uiscale is ba.UIScale.MEDIUM else (0, 0)))

        ba.textwidget(parent=self._root_widget,
                      position=(0, height -
                                (50 if uiscale is ba.UIScale.SMALL else 45)),
                      size=(width, 25),
                      text=ba.Lstr(resource=self._r + '.titleText',
                                   subs=[('${APP_NAME}',
                                          ba.Lstr(resource='titleText'))]),
                      color=ba.app.ui.title_color,
                      h_align='center',
                      v_align='top')

        self._scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            position=(44 + x_offs, 55 if uiscale is ba.UIScale.SMALL else 55),
            simple_culling_v=100.0,
            size=(width - (88 + 2 * x_offs),
                  height - 120 + (5 if uiscale is ba.UIScale.SMALL else 0)),
            capture_arrows=True)

        if ba.app.ui.use_toolbars:
            ba.widget(edit=self._scrollwidget,
                      right_widget=_ba.get_special_widget('party_button'))
        ba.containerwidget(edit=self._root_widget,
                           selected_child=self._scrollwidget)

        # ugly: create this last so it gets first dibs at touch events (since
        # we have it close to the scroll widget)
        if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._close)
            ba.widget(edit=self._scrollwidget,
                      left_widget=_ba.get_special_widget('back_button'))
        else:
            btn = ba.buttonwidget(
                parent=self._root_widget,
                position=(x_offs +
                          (40 + 0 if uiscale is ba.UIScale.SMALL else 70),
                          height -
                          (59 if uiscale is ba.UIScale.SMALL else 50)),
                size=(140, 60),
                scale=0.7 if uiscale is ba.UIScale.SMALL else 0.8,
                label=ba.Lstr(
                    resource='backText') if self._main_menu else 'Close',
                button_type='back' if self._main_menu else None,
                extra_touch_border_scale=2.0,
                autoselect=True,
                on_activate_call=self._close)
            ba.containerwidget(edit=self._root_widget, cancel_button=btn)

            if self._main_menu:
                ba.buttonwidget(edit=btn,
                                button_type='backSmall',
                                size=(60, 55),
                                label=ba.charstr(ba.SpecialChar.BACK))

        self._sub_width = 660
        self._sub_height = 1590 + ba.app.lang.get_resource(
            self._r + '.someDaysExtraSpace') + ba.app.lang.get_resource(
                self._r + '.orPunchingSomethingExtraSpace')

        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
                                                size=(self._sub_width,
                                                      self._sub_height),
                                                background=False,
                                                claims_left_right=False,
                                                claims_tab=False)

        spacing = 1.0
        h = self._sub_width * 0.5
        v = self._sub_height - 55
        logo_tex = ba.gettexture('logo')
        icon_buffer = 1.1
        header = (0.7, 1.0, 0.7, 1.0)
        header2 = (0.8, 0.8, 1.0, 1.0)
        paragraph = (0.8, 0.8, 1.0, 1.0)

        txt = ba.Lstr(resource=self._r + '.welcomeText',
                      subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))
                            ]).evaluate()
        txt_scale = 1.4
        txt_maxwidth = 480
        ba.textwidget(parent=self._subcontainer,
                      position=(h, v),
                      size=(0, 0),
                      scale=txt_scale,
                      flatness=0.5,
                      res_scale=1.5,
                      text=txt,
                      h_align='center',
                      color=header,
                      v_align='center',
                      maxwidth=txt_maxwidth)
        txt_width = min(
            txt_maxwidth,
            _ba.get_string_width(txt, suppress_warning=True) * txt_scale)

        icon_size = 70
        hval2 = h - (txt_width * 0.5 + icon_size * 0.5 * icon_buffer)
        ba.imagewidget(parent=self._subcontainer,
                       size=(icon_size, icon_size),
                       position=(hval2 - 0.5 * icon_size,
                                 v - 0.45 * icon_size),
                       texture=logo_tex)

        force_test = False
        app = ba.app
        if (app.platform == 'android'
                and app.subplatform == 'alibaba') or force_test:
            v -= 120.0
            txtv = (
                '\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe5\x8f\xaf'
                '\xe4\xbb\xa5\xe5\x92\x8c\xe5\xae\xb6\xe4\xba\xba\xe6\x9c\x8b'
                '\xe5\x8f\x8b\xe4\xb8\x80\xe8\xb5\xb7\xe7\x8e\xa9\xe7\x9a\x84'
                '\xe6\xb8\xb8\xe6\x88\x8f,\xe5\x90\x8c\xe6\x97\xb6\xe6\x94\xaf'
                '\xe6\x8c\x81\xe8\x81\x94 \xe2\x80\xa8\xe7\xbd\x91\xe5\xaf\xb9'
                '\xe6\x88\x98\xe3\x80\x82\n'
                '\xe5\xa6\x82\xe6\xb2\xa1\xe6\x9c\x89\xe6\xb8\xb8\xe6\x88\x8f'
                '\xe6\x89\x8b\xe6\x9f\x84,\xe5\x8f\xaf\xe4\xbb\xa5\xe4\xbd\xbf'
                '\xe7\x94\xa8\xe7\xa7\xbb\xe5\x8a\xa8\xe8\xae\xbe\xe5\xa4\x87'
                '\xe6\x89\xab\xe7\xa0\x81\xe4\xb8\x8b\xe8\xbd\xbd\xe2\x80\x9c'
                '\xe9\x98\xbf\xe9\x87\x8c\xc2'
                '\xa0TV\xc2\xa0\xe5\x8a\xa9\xe6\x89'
                '\x8b\xe2\x80\x9d\xe7\x94\xa8 \xe6\x9d\xa5\xe4\xbb\xa3\xe6\x9b'
                '\xbf\xe5\xa4\x96\xe8\xae\xbe\xe3\x80\x82\n'
                '\xe6\x9c\x80\xe5\xa4\x9a\xe6\x94\xaf\xe6\x8c\x81\xe6\x8e\xa5'
                '\xe5\x85\xa5\xc2\xa08\xc2\xa0\xe4\xb8\xaa\xe5\xa4\x96\xe8'
                '\xae\xbe')
            ba.textwidget(parent=self._subcontainer,
                          size=(0, 0),
                          h_align='center',
                          v_align='center',
                          maxwidth=self._sub_width * 0.9,
                          position=(self._sub_width * 0.5, v - 180),
                          text=txtv)
            ba.imagewidget(parent=self._subcontainer,
                           position=(self._sub_width - 320, v - 120),
                           size=(200, 200),
                           texture=ba.gettexture('aliControllerQR'))
            ba.imagewidget(parent=self._subcontainer,
                           position=(90, v - 130),
                           size=(210, 210),
                           texture=ba.gettexture('multiplayerExamples'))
            v -= 120.0

        else:
            v -= spacing * 50.0
            txt = ba.Lstr(resource=self._r + '.someDaysText').evaluate()
            ba.textwidget(parent=self._subcontainer,
                          position=(h, v),
                          size=(0, 0),
                          scale=1.2,
                          maxwidth=self._sub_width * 0.9,
                          text=txt,
                          h_align='center',
                          color=paragraph,
                          v_align='center',
                          flatness=1.0)
            v -= (spacing * 25.0 + getres(self._r + '.someDaysExtraSpace'))
            txt_scale = 0.66
            txt = ba.Lstr(resource=self._r +
                          '.orPunchingSomethingText').evaluate()
            ba.textwidget(parent=self._subcontainer,
                          position=(h, v),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=self._sub_width * 0.9,
                          text=txt,
                          h_align='center',
                          color=paragraph,
                          v_align='center',
                          flatness=1.0)
            v -= (spacing * 27.0 +
                  getres(self._r + '.orPunchingSomethingExtraSpace'))
            txt_scale = 1.0
            txt = ba.Lstr(resource=self._r + '.canHelpText',
                          subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))
                                ]).evaluate()
            ba.textwidget(parent=self._subcontainer,
                          position=(h, v),
                          size=(0, 0),
                          scale=txt_scale,
                          flatness=1.0,
                          text=txt,
                          h_align='center',
                          color=paragraph,
                          v_align='center')

            v -= spacing * 70.0
            txt_scale = 1.0
            txt = ba.Lstr(resource=self._r + '.toGetTheMostText').evaluate()
            ba.textwidget(parent=self._subcontainer,
                          position=(h, v),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=self._sub_width * 0.9,
                          text=txt,
                          h_align='center',
                          color=header,
                          v_align='center',
                          flatness=1.0)

            v -= spacing * 40.0
            txt_scale = 0.74
            txt = ba.Lstr(resource=self._r + '.friendsText').evaluate()
            hval2 = h - 220
            ba.textwidget(parent=self._subcontainer,
                          position=(hval2, v),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=100,
                          text=txt,
                          h_align='right',
                          color=header,
                          v_align='center',
                          flatness=1.0)

            txt = ba.Lstr(resource=self._r + '.friendsGoodText',
                          subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))
                                ]).evaluate()
            txt_scale = 0.7
            ba.textwidget(parent=self._subcontainer,
                          position=(hval2 + 10, v + 8),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=500,
                          text=txt,
                          h_align='left',
                          color=paragraph,
                          flatness=1.0)

            app = ba.app

            v -= spacing * 45.0
            txt = (ba.Lstr(resource=self._r + '.devicesText').evaluate()
                   if app.vr_mode else ba.Lstr(resource=self._r +
                                               '.controllersText').evaluate())
            txt_scale = 0.74
            hval2 = h - 220
            ba.textwidget(parent=self._subcontainer,
                          position=(hval2, v),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=100,
                          text=txt,
                          h_align='right',
                          v_align='center',
                          color=header,
                          flatness=1.0)

            txt_scale = 0.7
            if not app.vr_mode:
                infotxt = ('.controllersInfoTextRemoteOnly'
                           if app.iircade_mode else '.controllersInfoText')
                txt = ba.Lstr(
                    resource=self._r + infotxt,
                    fallback_resource=self._r + '.controllersInfoText',
                    subs=[('${APP_NAME}', ba.Lstr(resource='titleText')),
                          ('${REMOTE_APP_NAME}', get_remote_app_name())
                          ]).evaluate()
            else:
                txt = ba.Lstr(resource=self._r + '.devicesInfoText',
                              subs=[('${APP_NAME}',
                                     ba.Lstr(resource='titleText'))
                                    ]).evaluate()

            ba.textwidget(parent=self._subcontainer,
                          position=(hval2 + 10, v + 8),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=500,
                          max_height=105,
                          text=txt,
                          h_align='left',
                          color=paragraph,
                          flatness=1.0)

        v -= spacing * 150.0

        txt = ba.Lstr(resource=self._r + '.controlsText').evaluate()
        txt_scale = 1.4
        txt_maxwidth = 480
        ba.textwidget(parent=self._subcontainer,
                      position=(h, v),
                      size=(0, 0),
                      scale=txt_scale,
                      flatness=0.5,
                      text=txt,
                      h_align='center',
                      color=header,
                      v_align='center',
                      res_scale=1.5,
                      maxwidth=txt_maxwidth)
        txt_width = min(
            txt_maxwidth,
            _ba.get_string_width(txt, suppress_warning=True) * txt_scale)
        icon_size = 70

        hval2 = h - (txt_width * 0.5 + icon_size * 0.5 * icon_buffer)
        ba.imagewidget(parent=self._subcontainer,
                       size=(icon_size, icon_size),
                       position=(hval2 - 0.5 * icon_size,
                                 v - 0.45 * icon_size),
                       texture=logo_tex)

        v -= spacing * 45.0

        txt_scale = 0.7
        txt = ba.Lstr(resource=self._r + '.controlsSubtitleText',
                      subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))
                            ]).evaluate()
        ba.textwidget(parent=self._subcontainer,
                      position=(h, v),
                      size=(0, 0),
                      scale=txt_scale,
                      maxwidth=self._sub_width * 0.9,
                      flatness=1.0,
                      text=txt,
                      h_align='center',
                      color=paragraph,
                      v_align='center')
        v -= spacing * 160.0

        sep = 70
        icon_size = 100
        # icon_size_2 = 30
        hval2 = h - sep
        vval2 = v
        ba.imagewidget(parent=self._subcontainer,
                       size=(icon_size, icon_size),
                       position=(hval2 - 0.5 * icon_size,
                                 vval2 - 0.5 * icon_size),
                       texture=ba.gettexture('buttonPunch'),
                       color=(1, 0.7, 0.3))

        txt_scale = getres(self._r + '.punchInfoTextScale')
        txt = ba.Lstr(resource=self._r + '.punchInfoText').evaluate()
        ba.textwidget(parent=self._subcontainer,
                      position=(h - sep - 185 + 70, v + 120),
                      size=(0, 0),
                      scale=txt_scale,
                      flatness=1.0,
                      text=txt,
                      h_align='center',
                      color=(1, 0.7, 0.3, 1.0),
                      v_align='top')

        hval2 = h + sep
        vval2 = v
        ba.imagewidget(parent=self._subcontainer,
                       size=(icon_size, icon_size),
                       position=(hval2 - 0.5 * icon_size,
                                 vval2 - 0.5 * icon_size),
                       texture=ba.gettexture('buttonBomb'),
                       color=(1, 0.3, 0.3))

        txt = ba.Lstr(resource=self._r + '.bombInfoText').evaluate()
        txt_scale = getres(self._r + '.bombInfoTextScale')
        ba.textwidget(parent=self._subcontainer,
                      position=(h + sep + 50 + 60, v - 35),
                      size=(0, 0),
                      scale=txt_scale,
                      flatness=1.0,
                      maxwidth=270,
                      text=txt,
                      h_align='center',
                      color=(1, 0.3, 0.3, 1.0),
                      v_align='top')

        hval2 = h
        vval2 = v + sep
        ba.imagewidget(parent=self._subcontainer,
                       size=(icon_size, icon_size),
                       position=(hval2 - 0.5 * icon_size,
                                 vval2 - 0.5 * icon_size),
                       texture=ba.gettexture('buttonPickUp'),
                       color=(0.5, 0.5, 1))

        txtl = ba.Lstr(resource=self._r + '.pickUpInfoText')
        txt_scale = getres(self._r + '.pickUpInfoTextScale')
        ba.textwidget(parent=self._subcontainer,
                      position=(h + 60 + 120, v + sep + 50),
                      size=(0, 0),
                      scale=txt_scale,
                      flatness=1.0,
                      text=txtl,
                      h_align='center',
                      color=(0.5, 0.5, 1, 1.0),
                      v_align='top')

        hval2 = h
        vval2 = v - sep
        ba.imagewidget(parent=self._subcontainer,
                       size=(icon_size, icon_size),
                       position=(hval2 - 0.5 * icon_size,
                                 vval2 - 0.5 * icon_size),
                       texture=ba.gettexture('buttonJump'),
                       color=(0.4, 1, 0.4))

        txt = ba.Lstr(resource=self._r + '.jumpInfoText').evaluate()
        txt_scale = getres(self._r + '.jumpInfoTextScale')
        ba.textwidget(parent=self._subcontainer,
                      position=(h - 250 + 75, v - sep - 15 + 30),
                      size=(0, 0),
                      scale=txt_scale,
                      flatness=1.0,
                      text=txt,
                      h_align='center',
                      color=(0.4, 1, 0.4, 1.0),
                      v_align='top')

        txt = ba.Lstr(resource=self._r + '.runInfoText').evaluate()
        txt_scale = getres(self._r + '.runInfoTextScale')
        ba.textwidget(parent=self._subcontainer,
                      position=(h, v - sep - 100),
                      size=(0, 0),
                      scale=txt_scale,
                      maxwidth=self._sub_width * 0.93,
                      flatness=1.0,
                      text=txt,
                      h_align='center',
                      color=(0.7, 0.7, 1.0, 1.0),
                      v_align='center')

        v -= spacing * 280.0

        txt = ba.Lstr(resource=self._r + '.powerupsText').evaluate()
        txt_scale = 1.4
        txt_maxwidth = 480
        ba.textwidget(parent=self._subcontainer,
                      position=(h, v),
                      size=(0, 0),
                      scale=txt_scale,
                      flatness=0.5,
                      text=txt,
                      h_align='center',
                      color=header,
                      v_align='center',
                      maxwidth=txt_maxwidth)
        txt_width = min(
            txt_maxwidth,
            _ba.get_string_width(txt, suppress_warning=True) * txt_scale)
        icon_size = 70
        hval2 = h - (txt_width * 0.5 + icon_size * 0.5 * icon_buffer)
        ba.imagewidget(parent=self._subcontainer,
                       size=(icon_size, icon_size),
                       position=(hval2 - 0.5 * icon_size,
                                 v - 0.45 * icon_size),
                       texture=logo_tex)

        v -= spacing * 50.0
        txt_scale = getres(self._r + '.powerupsSubtitleTextScale')
        txt = ba.Lstr(resource=self._r + '.powerupsSubtitleText').evaluate()
        ba.textwidget(parent=self._subcontainer,
                      position=(h, v),
                      size=(0, 0),
                      scale=txt_scale,
                      maxwidth=self._sub_width * 0.9,
                      text=txt,
                      h_align='center',
                      color=paragraph,
                      v_align='center',
                      flatness=1.0)

        v -= spacing * 1.0

        mm1 = -270
        mm2 = -215
        mm3 = 0
        icon_size = 50
        shadow_size = 80
        shadow_offs_x = 3
        shadow_offs_y = -4
        t_big = 1.1
        t_small = 0.65

        shadow_tex = ba.gettexture('shadowSharp')

        for tex in [
                'powerupPunch', 'powerupShield', 'powerupBomb',
                'powerupHealth', 'powerupIceBombs', 'powerupImpactBombs',
                'powerupStickyBombs', 'powerupLandMines', 'powerupCurse'
        ]:
            name = ba.Lstr(resource=self._r + '.' + tex + 'NameText')
            desc = ba.Lstr(resource=self._r + '.' + tex + 'DescriptionText')

            v -= spacing * 60.0

            ba.imagewidget(
                parent=self._subcontainer,
                size=(shadow_size, shadow_size),
                position=(h + mm1 + shadow_offs_x - 0.5 * shadow_size,
                          v + shadow_offs_y - 0.5 * shadow_size),
                texture=shadow_tex,
                color=(0, 0, 0),
                opacity=0.5)
            ba.imagewidget(parent=self._subcontainer,
                           size=(icon_size, icon_size),
                           position=(h + mm1 - 0.5 * icon_size,
                                     v - 0.5 * icon_size),
                           texture=ba.gettexture(tex))

            txt_scale = t_big
            txtl = name
            ba.textwidget(parent=self._subcontainer,
                          position=(h + mm2, v + 3),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=200,
                          flatness=1.0,
                          text=txtl,
                          h_align='left',
                          color=header2,
                          v_align='center')
            txt_scale = t_small
            txtl = desc
            ba.textwidget(parent=self._subcontainer,
                          position=(h + mm3, v),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=300,
                          flatness=1.0,
                          text=txtl,
                          h_align='left',
                          color=paragraph,
                          v_align='center',
                          res_scale=0.5)
Example #21
0
    def _build_favorites_tab(self, region_height: float) -> None:

        c_height = region_height - 20
        v = c_height - 35 - 25 - 30

        uiscale = ba.app.ui.uiscale
        self._width = 1240 if uiscale is ba.UIScale.SMALL else 1040
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (578 if uiscale is ba.UIScale.SMALL else
                        670 if uiscale is ba.UIScale.MEDIUM else 800)

        self._scroll_width = self._width - 130 + 2 * x_inset
        self._scroll_height = self._height - 180
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0

        c_height = self._scroll_height - 20
        sub_scroll_height = c_height - 63
        self._favorites_scroll_width = sub_scroll_width = (
            680 if uiscale is ba.UIScale.SMALL else 640)

        v = c_height - 30

        b_width = 140 if uiscale is ba.UIScale.SMALL else 178
        b_height = (107 if uiscale is ba.UIScale.SMALL else
                    142 if uiscale is ba.UIScale.MEDIUM else 190)
        b_space_extra = (0 if uiscale is ba.UIScale.SMALL else
                         -2 if uiscale is ba.UIScale.MEDIUM else -5)

        btnv = (c_height - (48 if uiscale is ba.UIScale.SMALL else
                            45 if uiscale is ba.UIScale.MEDIUM else 40) -
                b_height)

        self._favorites_connect_button = btn1 = ba.buttonwidget(
            parent=self._container,
            size=(b_width, b_height),
            position=(40 if uiscale is ba.UIScale.SMALL else 40, btnv),
            button_type='square',
            color=(0.6, 0.53, 0.63),
            textcolor=(0.75, 0.7, 0.8),
            on_activate_call=self._on_favorites_connect_press,
            text_scale=1.0 if uiscale is ba.UIScale.SMALL else 1.2,
            label=ba.Lstr(resource='gatherWindow.manualConnectText'),
            autoselect=True)
        if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
            ba.widget(edit=btn1,
                      left_widget=_ba.get_special_widget('back_button'))
        btnv -= b_height + b_space_extra
        ba.buttonwidget(parent=self._container,
                        size=(b_width, b_height),
                        position=(40 if uiscale is ba.UIScale.SMALL else 40,
                                  btnv),
                        button_type='square',
                        color=(0.6, 0.53, 0.63),
                        textcolor=(0.75, 0.7, 0.8),
                        on_activate_call=self._on_favorites_edit_press,
                        text_scale=1.0 if uiscale is ba.UIScale.SMALL else 1.2,
                        label=ba.Lstr(resource='editText'),
                        autoselect=True)
        btnv -= b_height + b_space_extra
        ba.buttonwidget(parent=self._container,
                        size=(b_width, b_height),
                        position=(40 if uiscale is ba.UIScale.SMALL else 40,
                                  btnv),
                        button_type='square',
                        color=(0.6, 0.53, 0.63),
                        textcolor=(0.75, 0.7, 0.8),
                        on_activate_call=self._on_favorite_delete_press,
                        text_scale=1.0 if uiscale is ba.UIScale.SMALL else 1.2,
                        label=ba.Lstr(resource='deleteText'),
                        autoselect=True)

        v -= sub_scroll_height + 23
        self._scrollwidget = scrlw = ba.scrollwidget(
            parent=self._container,
            position=(190 if uiscale is ba.UIScale.SMALL else 225, v),
            size=(sub_scroll_width, sub_scroll_height),
            claims_left_right=True)
        ba.widget(edit=self._favorites_connect_button,
                  right_widget=self._scrollwidget)
        self._columnwidget = ba.columnwidget(parent=scrlw,
                                             left_border=10,
                                             border=2,
                                             margin=0,
                                             claims_left_right=True)

        self._favorite_selected = None
        self._refresh_favorites()
Example #22
0
    def _refresh(self) -> None:
        # FIXME: Should tidy this up.
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-nested-blocks
        from efro.util import asserttype
        from ba.internal import get_map_class, filter_playlist
        if not self._root_widget:
            return
        if self._subcontainer is not None:
            self._save_state()
            self._subcontainer.delete()

        # Make sure config exists.
        if self._config_name_full not in ba.app.config:
            ba.app.config[self._config_name_full] = {}

        items = list(ba.app.config[self._config_name_full].items())

        # Make sure everything is unicode.
        items = [(i[0].decode(), i[1]) if not isinstance(i[0], str) else i
                 for i in items]

        items.sort(key=lambda x2: asserttype(x2[0], str).lower())
        items = [['__default__', None]] + items  # default is always first

        count = len(items)
        columns = 3
        rows = int(math.ceil(float(count) / columns))
        button_width = 230
        button_height = 230
        button_buffer_h = -3
        button_buffer_v = 0

        self._sub_width = self._scroll_width
        self._sub_height = 40 + rows * (button_height +
                                        2 * button_buffer_v) + 90
        assert self._sub_width is not None
        assert self._sub_height is not None
        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
                                                size=(self._sub_width,
                                                      self._sub_height),
                                                background=False)

        children = self._subcontainer.get_children()
        for child in children:
            child.delete()

        ba.textwidget(parent=self._subcontainer,
                      text=ba.Lstr(resource='playlistsText'),
                      position=(40, self._sub_height - 26),
                      size=(0, 0),
                      scale=1.0,
                      maxwidth=400,
                      color=ba.app.ui.title_color,
                      h_align='left',
                      v_align='center')

        index = 0
        appconfig = ba.app.config

        model_opaque = ba.getmodel('level_select_button_opaque')
        model_transparent = ba.getmodel('level_select_button_transparent')
        mask_tex = ba.gettexture('mapPreviewMask')

        h_offs = 225 if count == 1 else 115 if count == 2 else 0
        h_offs_bottom = 0

        uiscale = ba.app.ui.uiscale
        for y in range(rows):
            for x in range(columns):
                name = items[index][0]
                assert name is not None
                pos = (x * (button_width + 2 * button_buffer_h) +
                       button_buffer_h + 8 + h_offs, self._sub_height - 47 -
                       (y + 1) * (button_height + 2 * button_buffer_v))
                btn = ba.buttonwidget(parent=self._subcontainer,
                                      button_type='square',
                                      size=(button_width, button_height),
                                      autoselect=True,
                                      label='',
                                      position=pos)

                if (x == 0 and ba.app.ui.use_toolbars
                        and uiscale is ba.UIScale.SMALL):
                    ba.widget(
                        edit=btn,
                        left_widget=_ba.get_special_widget('back_button'))
                if (x == columns - 1 and ba.app.ui.use_toolbars
                        and uiscale is ba.UIScale.SMALL):
                    ba.widget(
                        edit=btn,
                        right_widget=_ba.get_special_widget('party_button'))
                ba.buttonwidget(
                    edit=btn,
                    on_activate_call=ba.Call(self._on_playlist_press, btn,
                                             name),
                    on_select_call=ba.Call(self._on_playlist_select, name))
                ba.widget(edit=btn, show_buffer_top=50, show_buffer_bottom=50)

                if self._selected_playlist == name:
                    ba.containerwidget(edit=self._subcontainer,
                                       selected_child=btn,
                                       visible_child=btn)

                if self._back_button is not None:
                    if y == 0:
                        ba.widget(edit=btn, up_widget=self._back_button)
                    if x == 0:
                        ba.widget(edit=btn, left_widget=self._back_button)

                print_name: Optional[Union[str, ba.Lstr]]
                if name == '__default__':
                    print_name = self._pvars.default_list_name
                else:
                    print_name = name
                ba.textwidget(parent=self._subcontainer,
                              text=print_name,
                              position=(pos[0] + button_width * 0.5,
                                        pos[1] + button_height * 0.79),
                              size=(0, 0),
                              scale=button_width * 0.003,
                              maxwidth=button_width * 0.7,
                              draw_controller=btn,
                              h_align='center',
                              v_align='center')

                # Poke into this playlist and see if we can display some of
                # its maps.
                map_images = []
                try:
                    map_textures = []
                    map_texture_entries = []
                    if name == '__default__':
                        playlist = self._pvars.get_default_list_call()
                    else:
                        if name not in appconfig[self._pvars.config_name +
                                                 ' Playlists']:
                            print(
                                'NOT FOUND ERR',
                                appconfig[self._pvars.config_name +
                                          ' Playlists'])
                        playlist = appconfig[self._pvars.config_name +
                                             ' Playlists'][name]
                    playlist = filter_playlist(playlist,
                                               self._sessiontype,
                                               remove_unowned=False,
                                               mark_unowned=True)
                    for entry in playlist:
                        mapname = entry['settings']['map']
                        maptype: Optional[Type[ba.Map]]
                        try:
                            maptype = get_map_class(mapname)
                        except ba.NotFoundError:
                            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)
                        if len(map_textures) >= 6:
                            break

                    if len(map_textures) > 4:
                        img_rows = 3
                        img_columns = 2
                        scl = 0.33
                        h_offs_img = 30
                        v_offs_img = 126
                    elif len(map_textures) > 2:
                        img_rows = 2
                        img_columns = 2
                        scl = 0.35
                        h_offs_img = 24
                        v_offs_img = 110
                    elif len(map_textures) > 1:
                        img_rows = 2
                        img_columns = 1
                        scl = 0.5
                        h_offs_img = 47
                        v_offs_img = 105
                    else:
                        img_rows = 1
                        img_columns = 1
                        scl = 0.75
                        h_offs_img = 20
                        v_offs_img = 65

                    v = None
                    for row in range(img_rows):
                        for col in range(img_columns):
                            tex_index = row * img_columns + col
                            if tex_index < len(map_textures):
                                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']))

                                tex_name = map_textures[tex_index]
                                h = pos[0] + h_offs_img + scl * 250 * col
                                v = pos[1] + v_offs_img - scl * 130 * row
                                map_images.append(
                                    ba.imagewidget(
                                        parent=self._subcontainer,
                                        size=(scl * 250.0, scl * 125.0),
                                        position=(h, v),
                                        texture=ba.gettexture(tex_name),
                                        opacity=1.0 if owned else 0.25,
                                        draw_controller=btn,
                                        model_opaque=model_opaque,
                                        model_transparent=model_transparent,
                                        mask_texture=mask_tex))
                                if not owned:
                                    ba.imagewidget(
                                        parent=self._subcontainer,
                                        size=(scl * 100.0, scl * 100.0),
                                        position=(h + scl * 75, v + scl * 10),
                                        texture=ba.gettexture('lock'),
                                        draw_controller=btn)
                        if v is not None:
                            v -= scl * 130.0

                except Exception:
                    ba.print_exception('Error listing playlist maps.')

                if not map_images:
                    ba.textwidget(parent=self._subcontainer,
                                  text='???',
                                  scale=1.5,
                                  size=(0, 0),
                                  color=(1, 1, 1, 0.5),
                                  h_align='center',
                                  v_align='center',
                                  draw_controller=btn,
                                  position=(pos[0] + button_width * 0.5,
                                            pos[1] + button_height * 0.5))

                index += 1

                if index >= count:
                    break
            if index >= count:
                break
        self._customize_button = btn = ba.buttonwidget(
            parent=self._subcontainer,
            size=(100, 30),
            position=(34 + h_offs_bottom, 50),
            text_scale=0.6,
            label=ba.Lstr(resource='customizeText'),
            on_activate_call=self._on_customize_press,
            color=(0.54, 0.52, 0.67),
            textcolor=(0.7, 0.65, 0.7),
            autoselect=True)
        ba.widget(edit=btn, show_buffer_top=22, show_buffer_bottom=28)
        self._restore_state()
Example #23
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        import threading

        # 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()

        new_style = True
        uiscale = ba.app.ui.uiscale
        width = 1000 if uiscale is ba.UIScale.SMALL else 800
        x_offs = 100 if uiscale is ba.UIScale.SMALL else 0
        height = 550 if new_style else 400
        button_width = 400

        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        self._r = 'playWindow'

        super().__init__(root_widget=ba.containerwidget(
            size=(width, height),
            transition=transition,
            toolbar_visibility='menu_full',
            scale_origin_stack_offset=scale_origin,
            scale=((1.6 if new_style else 1.52) if uiscale is ba.UIScale.SMALL
                   else 0.9 if uiscale is ba.UIScale.MEDIUM else 0.8),
            stack_offset=((0, 0) if new_style else (
                10, 7)) if uiscale is ba.UIScale.SMALL else (0, 0)))
        self._back_button = back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(55 + x_offs, height - 132) if new_style else
            (55, height - 92),
            size=(120, 60),
            scale=1.1,
            text_res_scale=1.5,
            text_scale=1.2,
            autoselect=True,
            label=ba.Lstr(resource='backText'),
            button_type='back')

        txt = ba.textwidget(parent=self._root_widget,
                            position=(width * 0.5,
                                      height - (101 if new_style else 61)),
                            size=(0, 0),
                            text=ba.Lstr(resource=self._r + '.titleText'),
                            scale=1.7,
                            res_scale=2.0,
                            maxwidth=400,
                            color=ba.app.ui.heading_color,
                            h_align='center',
                            v_align='center')

        ba.buttonwidget(edit=btn,
                        button_type='backSmall',
                        size=(60, 60),
                        label=ba.charstr(ba.SpecialChar.BACK))
        if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
            ba.textwidget(edit=txt, text='')

        v = height - (110 if new_style else 60)
        v -= 100
        clr = (0.6, 0.7, 0.6, 1.0)
        v -= 280 if new_style else 180
        v += (30
              if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL else 0)
        hoffs = x_offs + 80 if new_style else 0
        scl = 1.13 if new_style else 0.68

        self._lineup_tex = ba.gettexture('playerLineup')
        angry_computer_transparent_model = ba.getmodel(
            'angryComputerTransparent')
        self._lineup_1_transparent_model = ba.getmodel(
            'playerLineup1Transparent')
        self._lineup_2_transparent_model = ba.getmodel(
            'playerLineup2Transparent')
        self._lineup_3_transparent_model = ba.getmodel(
            'playerLineup3Transparent')
        self._lineup_4_transparent_model = ba.getmodel(
            'playerLineup4Transparent')
        self._eyes_model = ba.getmodel('plasticEyesTransparent')

        self._coop_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(hoffs, v + (scl * 15 if new_style else 0)),
            size=(scl * button_width, scl * (300 if new_style else 360)),
            extra_touch_border_scale=0.1,
            autoselect=True,
            label='',
            button_type='square',
            text_scale=1.13,
            on_activate_call=self._coop)

        if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
            ba.widget(edit=btn,
                      left_widget=_ba.get_special_widget('back_button'))
            ba.widget(edit=btn,
                      up_widget=_ba.get_special_widget('account_button'))
            ba.widget(edit=btn,
                      down_widget=_ba.get_special_widget('settings_button'))

        self._draw_dude(0,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(140, 30),
                        color=(0.72, 0.4, 1.0))
        self._draw_dude(1,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(185, 53),
                        color=(0.71, 0.5, 1.0))
        self._draw_dude(2,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(220, 27),
                        color=(0.67, 0.44, 1.0))
        self._draw_dude(3,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(255, 57),
                        color=(0.7, 0.3, 1.0))
        ba.imagewidget(parent=self._root_widget,
                       draw_controller=btn,
                       position=(hoffs + scl * 230, v + scl * 153),
                       size=(scl * 115, scl * 115),
                       texture=self._lineup_tex,
                       model_transparent=angry_computer_transparent_model)

        ba.textwidget(parent=self._root_widget,
                      draw_controller=btn,
                      position=(hoffs + scl * (-10), v + scl * 95),
                      size=(scl * button_width, scl * 50),
                      text=ba.Lstr(resource='playModes.singlePlayerCoopText',
                                   fallback_resource='playModes.coopText'),
                      maxwidth=scl * button_width * 0.7,
                      res_scale=1.5,
                      h_align='center',
                      v_align='center',
                      color=(0.7, 0.9, 0.7, 1.0),
                      scale=scl * 2.3)

        ba.textwidget(parent=self._root_widget,
                      draw_controller=btn,
                      position=(hoffs + scl * (-10), v + (scl * 54)),
                      size=(scl * button_width, scl * 30),
                      text=ba.Lstr(resource=self._r + '.oneToFourPlayersText'),
                      h_align='center',
                      v_align='center',
                      scale=0.83 * scl,
                      flatness=1.0,
                      maxwidth=scl * button_width * 0.7,
                      color=clr)

        scl = 0.5 if new_style else 0.68
        hoffs += 440 if new_style else 260
        v += 180 if new_style else 0

        self._teams_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(hoffs, v + (scl * 15 if new_style else 0)),
            size=(scl * button_width, scl * (300 if new_style else 360)),
            extra_touch_border_scale=0.1,
            autoselect=True,
            label='',
            button_type='square',
            text_scale=1.13,
            on_activate_call=self._team_tourney)

        if ba.app.ui.use_toolbars:
            ba.widget(edit=btn,
                      up_widget=_ba.get_special_widget('tickets_plus_button'),
                      right_widget=_ba.get_special_widget('party_button'))

        xxx = -14
        self._draw_dude(2,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 148, 30),
                        color=(0.2, 0.4, 1.0))
        self._draw_dude(3,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 181, 53),
                        color=(0.3, 0.4, 1.0))
        self._draw_dude(1,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 216, 33),
                        color=(0.3, 0.5, 1.0))
        self._draw_dude(0,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 245, 57),
                        color=(0.3, 0.5, 1.0))

        xxx = 155
        self._draw_dude(0,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 151, 30),
                        color=(1.0, 0.5, 0.4))
        self._draw_dude(1,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 189, 53),
                        color=(1.0, 0.58, 0.58))
        self._draw_dude(3,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 223, 27),
                        color=(1.0, 0.5, 0.5))
        self._draw_dude(2,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 257, 57),
                        color=(1.0, 0.5, 0.5))

        ba.textwidget(parent=self._root_widget,
                      draw_controller=btn,
                      position=(hoffs + scl * (-10), v + scl * 95),
                      size=(scl * button_width, scl * 50),
                      text=ba.Lstr(resource='playModes.teamsText',
                                   fallback_resource='teamsText'),
                      res_scale=1.5,
                      maxwidth=scl * button_width * 0.7,
                      h_align='center',
                      v_align='center',
                      color=(0.7, 0.9, 0.7, 1.0),
                      scale=scl * 2.3)
        ba.textwidget(parent=self._root_widget,
                      draw_controller=btn,
                      position=(hoffs + scl * (-10), v + (scl * 54)),
                      size=(scl * button_width, scl * 30),
                      text=ba.Lstr(resource=self._r +
                                   '.twoToEightPlayersText'),
                      h_align='center',
                      v_align='center',
                      res_scale=1.5,
                      scale=0.9 * scl,
                      flatness=1.0,
                      maxwidth=scl * button_width * 0.7,
                      color=clr)

        hoffs += 0 if new_style else 260
        v -= 155 if new_style else 0
        self._free_for_all_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(hoffs, v + (scl * 15 if new_style else 0)),
            size=(scl * button_width, scl * (300 if new_style else 360)),
            extra_touch_border_scale=0.1,
            autoselect=True,
            label='',
            button_type='square',
            text_scale=1.13,
            on_activate_call=self._free_for_all)

        xxx = -5
        self._draw_dude(0,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 140, 30),
                        color=(0.4, 1.0, 0.4))
        self._draw_dude(3,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 185, 53),
                        color=(1.0, 0.4, 0.5))
        self._draw_dude(1,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 220, 27),
                        color=(0.4, 0.5, 1.0))
        self._draw_dude(2,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 255, 57),
                        color=(0.5, 1.0, 0.4))
        xxx = 140
        self._draw_dude(2,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 148, 30),
                        color=(1.0, 0.9, 0.4))
        self._draw_dude(0,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 182, 53),
                        color=(0.7, 1.0, 0.5))
        self._draw_dude(3,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 233, 27),
                        color=(0.7, 0.5, 0.9))
        self._draw_dude(1,
                        btn,
                        hoffs,
                        v,
                        scl,
                        position=(xxx + 266, 53),
                        color=(0.4, 0.5, 0.8))
        ba.textwidget(parent=self._root_widget,
                      draw_controller=btn,
                      position=(hoffs + scl * (-10), v + scl * 95),
                      size=(scl * button_width, scl * 50),
                      text=ba.Lstr(resource='playModes.freeForAllText',
                                   fallback_resource='freeForAllText'),
                      maxwidth=scl * button_width * 0.7,
                      h_align='center',
                      v_align='center',
                      color=(0.7, 0.9, 0.7, 1.0),
                      scale=scl * 1.9)
        ba.textwidget(parent=self._root_widget,
                      draw_controller=btn,
                      position=(hoffs + scl * (-10), v + (scl * 54)),
                      size=(scl * button_width, scl * 30),
                      text=ba.Lstr(resource=self._r +
                                   '.twoToEightPlayersText'),
                      h_align='center',
                      v_align='center',
                      scale=0.9 * scl,
                      flatness=1.0,
                      maxwidth=scl * button_width * 0.7,
                      color=clr)

        if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
            back_button.delete()
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back,
                               selected_child=self._coop_button)
        else:
            ba.buttonwidget(edit=back_button, on_activate_call=self._back)
            ba.containerwidget(edit=self._root_widget,
                               cancel_button=back_button,
                               selected_child=self._coop_button)

        self._restore_state()
Example #24
0
    def __init__(self,
                 transition: Optional[str] = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        from bastd.ui import tabs
        ba.set_analytics_screen('Watch Window')
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
        ba.app.main_window = 'Watch'
        self._tab_data: Dict[str, Any] = {}
        self._my_replays_scroll_width: Optional[float] = None
        self._my_replays_watch_replay_button: Optional[ba.Widget] = None
        self._scrollwidget: Optional[ba.Widget] = None
        self._columnwidget: Optional[ba.Widget] = None
        self._my_replay_selected: Optional[str] = None
        self._my_replays_rename_window: Optional[ba.Widget] = None
        self._my_replay_rename_text: Optional[ba.Widget] = None
        self._r = 'watchWindow'
        self._width = 1240 if ba.app.small_ui else 1040
        x_inset = 100 if ba.app.small_ui else 0
        self._height = (578
                        if ba.app.small_ui else 670 if ba.app.med_ui else 800)
        self._current_tab: Optional[str] = None
        extra_top = 20 if ba.app.small_ui else 0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + extra_top),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(1.3 if ba.app.small_ui else 0.97 if ba.app.med_ui else 0.8),
            stack_offset=(0, -10) if ba.app.small_ui else (
                0, 15) if ba.app.med_ui else (0, 0)))

        if ba.app.small_ui and ba.app.toolbars:
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back)
            self._back_button = None
        else:
            self._back_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                autoselect=True,
                position=(70 + x_inset, self._height - 74),
                size=(140, 60),
                scale=1.1,
                label=ba.Lstr(resource='backText'),
                button_type='back',
                on_activate_call=self._back)
            ba.containerwidget(edit=self._root_widget, cancel_button=btn)
            ba.buttonwidget(edit=btn,
                            button_type='backSmall',
                            size=(60, 60),
                            label=ba.charstr(ba.SpecialChar.BACK))

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 38),
                      size=(0, 0),
                      color=ba.app.title_color,
                      scale=1.5,
                      h_align='center',
                      v_align='center',
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      maxwidth=400)

        tabs_def = [('my_replays',
                     ba.Lstr(resource=self._r + '.myReplaysText'))]

        scroll_buffer_h = 130 + 2 * x_inset
        tab_buffer_h = 750 + 2 * x_inset

        self._tab_buttons = tabs.create_tab_buttons(
            self._root_widget,
            tabs_def,
            pos=(tab_buffer_h * 0.5, self._height - 130),
            size=(self._width - tab_buffer_h, 50),
            on_select_call=self._set_tab)

        if ba.app.toolbars:
            ba.widget(edit=self._tab_buttons[tabs_def[-1][0]],
                      right_widget=_ba.get_special_widget('party_button'))
            if ba.app.small_ui:
                bbtn = _ba.get_special_widget('back_button')
                ba.widget(edit=self._tab_buttons[tabs_def[0][0]],
                          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
        ba.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),
                       texture=ba.gettexture('scrollWidget'),
                       model_transparent=ba.getmodel('softEdgeOutside'))
        self._tab_container: Optional[ba.Widget] = None

        self._restore_state()
Example #25
0
    def __init__(self,
                 editcontroller: PlaylistEditController,
                 transition: str = 'in_right'):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        prev_selection: Optional[str]
        self._editcontroller = editcontroller
        self._r = 'editGameListWindow'
        prev_selection = self._editcontroller.get_edit_ui_selection()

        uiscale = ba.app.uiscale
        self._width = 770 if uiscale is ba.UIScale.SMALL else 670
        x_inset = 50 if uiscale is ba.UIScale.SMALL else 0
        self._height = (400 if uiscale is ba.UIScale.SMALL else
                        470 if uiscale is ba.UIScale.MEDIUM else 540)

        top_extra = 20 if uiscale is ba.UIScale.SMALL else 0
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            scale=(2.0 if uiscale is ba.UIScale.SMALL else
                   1.3 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -16) if uiscale is ba.UIScale.SMALL else (0, 0)))
        cancel_button = ba.buttonwidget(parent=self._root_widget,
                                        position=(35 + x_inset,
                                                  self._height - 60),
                                        scale=0.8,
                                        size=(175, 60),
                                        autoselect=True,
                                        label=ba.Lstr(resource='cancelText'),
                                        text_scale=1.2)
        save_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(self._width - (195 + x_inset), self._height - 60),
            scale=0.8,
            size=(190, 60),
            autoselect=True,
            left_widget=cancel_button,
            label=ba.Lstr(resource='saveText'),
            text_scale=1.2)

        if ba.app.ui.use_toolbars:
            ba.widget(edit=btn,
                      right_widget=_ba.get_special_widget('party_button'))

        ba.widget(edit=cancel_button,
                  left_widget=cancel_button,
                  right_widget=save_button)

        ba.textwidget(parent=self._root_widget,
                      position=(-10, self._height - 50),
                      size=(self._width, 25),
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      color=ba.app.ui.title_color,
                      scale=1.05,
                      h_align='center',
                      v_align='center',
                      maxwidth=270)

        v = self._height - 115.0

        self._scroll_width = self._width - (205 + 2 * x_inset)

        ba.textwidget(parent=self._root_widget,
                      text=ba.Lstr(resource=self._r + '.listNameText'),
                      position=(196 + x_inset, v + 31),
                      maxwidth=150,
                      color=(0.8, 0.8, 0.8, 0.5),
                      size=(0, 0),
                      scale=0.75,
                      h_align='right',
                      v_align='center')

        self._text_field = ba.textwidget(
            parent=self._root_widget,
            position=(210 + x_inset, v + 7),
            size=(self._scroll_width - 53, 43),
            text=self._editcontroller.getname(),
            h_align='left',
            v_align='center',
            max_chars=40,
            autoselect=True,
            color=(0.9, 0.9, 0.9, 1.0),
            description=ba.Lstr(resource=self._r + '.listNameText'),
            editable=True,
            padding=4,
            on_return_press_call=self._save_press_with_sound)
        ba.widget(edit=cancel_button, down_widget=self._text_field)

        self._list_widgets: List[ba.Widget] = []

        h = 40 + x_inset
        v = self._height - 172.0

        b_color = (0.6, 0.53, 0.63)
        b_textcolor = (0.75, 0.7, 0.8)

        v -= 2.0
        v += 63

        scl = (1.03 if uiscale is ba.UIScale.SMALL else
               1.36 if uiscale is ba.UIScale.MEDIUM else 1.74)
        v -= 63.0 * scl

        add_game_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(110, 61.0 * scl),
            on_activate_call=self._add,
            on_select_call=ba.Call(self._set_ui_selection, 'add_button'),
            autoselect=True,
            button_type='square',
            color=b_color,
            textcolor=b_textcolor,
            text_scale=0.8,
            label=ba.Lstr(resource=self._r + '.addGameText'))
        ba.widget(edit=add_game_button, up_widget=self._text_field)
        v -= 63.0 * scl

        self._edit_button = edit_game_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(110, 61.0 * scl),
            on_activate_call=self._edit,
            on_select_call=ba.Call(self._set_ui_selection, 'editButton'),
            autoselect=True,
            button_type='square',
            color=b_color,
            textcolor=b_textcolor,
            text_scale=0.8,
            label=ba.Lstr(resource=self._r + '.editGameText'))
        v -= 63.0 * scl

        remove_game_button = ba.buttonwidget(parent=self._root_widget,
                                             position=(h, v),
                                             size=(110, 61.0 * scl),
                                             text_scale=0.8,
                                             on_activate_call=self._remove,
                                             autoselect=True,
                                             button_type='square',
                                             color=b_color,
                                             textcolor=b_textcolor,
                                             label=ba.Lstr(resource=self._r +
                                                           '.removeGameText'))
        v -= 40
        h += 9
        ba.buttonwidget(parent=self._root_widget,
                        position=(h, v),
                        size=(42, 35),
                        on_activate_call=self._move_up,
                        label=ba.charstr(ba.SpecialChar.UP_ARROW),
                        button_type='square',
                        color=b_color,
                        textcolor=b_textcolor,
                        autoselect=True,
                        repeat=True)
        h += 52
        ba.buttonwidget(parent=self._root_widget,
                        position=(h, v),
                        size=(42, 35),
                        on_activate_call=self._move_down,
                        autoselect=True,
                        button_type='square',
                        color=b_color,
                        textcolor=b_textcolor,
                        label=ba.charstr(ba.SpecialChar.DOWN_ARROW),
                        repeat=True)

        v = self._height - 100
        scroll_height = self._height - 155
        scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            position=(160 + x_inset, v - scroll_height),
            highlight=False,
            on_select_call=ba.Call(self._set_ui_selection, 'gameList'),
            size=(self._scroll_width, (scroll_height - 15)))
        ba.widget(edit=scrollwidget,
                  left_widget=add_game_button,
                  right_widget=scrollwidget)
        self._columnwidget = ba.columnwidget(parent=scrollwidget)
        ba.widget(edit=self._columnwidget, up_widget=self._text_field)

        for button in [add_game_button, edit_game_button, remove_game_button]:
            ba.widget(edit=button,
                      left_widget=button,
                      right_widget=scrollwidget)

        self._refresh()

        ba.buttonwidget(edit=cancel_button, on_activate_call=self._cancel)
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=cancel_button,
                           selected_child=scrollwidget)

        ba.buttonwidget(edit=save_button, on_activate_call=self._save_press)
        ba.containerwidget(edit=self._root_widget, start_button=save_button)

        if prev_selection == 'add_button':
            ba.containerwidget(edit=self._root_widget,
                               selected_child=add_game_button)
        elif prev_selection == 'editButton':
            ba.containerwidget(edit=self._root_widget,
                               selected_child=edit_game_button)
        elif prev_selection == 'gameList':
            ba.containerwidget(edit=self._root_widget,
                               selected_child=scrollwidget)
Example #26
0
    def __init__(self, origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        import json
        ba.set_analytics_screen('Credits Window')

        # if they provided an origin-widget, scale up from that
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
            transition = 'in_right'

        uiscale = ba.app.ui.uiscale
        width = 870 if uiscale is ba.UIScale.SMALL else 670
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        height = 398 if uiscale is ba.UIScale.SMALL else 500

        self._r = 'creditsWindow'
        super().__init__(root_widget=ba.containerwidget(
            size=(width, height),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(2.0 if uiscale is ba.UIScale.SMALL else
                   1.3 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -8) if uiscale is ba.UIScale.SMALL else (0, 0)))

        if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back)
        else:
            btn = ba.buttonwidget(
                parent=self._root_widget,
                position=(40 + x_inset, height -
                          (68 if uiscale is ba.UIScale.SMALL else 62)),
                size=(140, 60),
                scale=0.8,
                label=ba.Lstr(resource='backText'),
                button_type='back',
                on_activate_call=self._back,
                autoselect=True)
            ba.containerwidget(edit=self._root_widget, cancel_button=btn)

            ba.buttonwidget(
                edit=btn,
                button_type='backSmall',
                position=(40 + x_inset, height -
                          (68 if uiscale is ba.UIScale.SMALL else 62) + 5),
                size=(60, 48),
                label=ba.charstr(ba.SpecialChar.BACK))

        ba.textwidget(parent=self._root_widget,
                      position=(0, height -
                                (59 if uiscale is ba.UIScale.SMALL else 54)),
                      size=(width, 30),
                      text=ba.Lstr(resource=self._r + '.titleText',
                                   subs=[('${APP_NAME}',
                                          ba.Lstr(resource='titleText'))]),
                      h_align='center',
                      color=ba.app.ui.title_color,
                      maxwidth=330,
                      v_align='center')

        scroll = ba.scrollwidget(parent=self._root_widget,
                                 position=(40 + x_inset, 35),
                                 size=(width - (80 + 2 * x_inset),
                                       height - 100),
                                 capture_arrows=True)

        if ba.app.ui.use_toolbars:
            ba.widget(edit=scroll,
                      right_widget=_ba.get_special_widget('party_button'))
            if uiscale is ba.UIScale.SMALL:
                ba.widget(edit=scroll,
                          left_widget=_ba.get_special_widget('back_button'))

        def _format_names(names2: Sequence[str], inset: float) -> str:
            sval = ''
            # measure a series since there's overlaps and stuff..
            space_width = _ba.get_string_width(' ' * 10,
                                               suppress_warning=True) / 10.0
            spacing = 330.0
            col1 = inset
            col2 = col1 + spacing
            col3 = col2 + spacing
            line_width = 0.0
            nline = ''
            for name in names2:
                # move to the next column (or row) and print
                if line_width > col3:
                    sval += nline + '\n'
                    nline = ''
                    line_width = 0

                if line_width > col2:
                    target = col3
                elif line_width > col1:
                    target = col2
                else:
                    target = col1
                spacingstr = ' ' * int((target - line_width) / space_width)
                nline += spacingstr
                nline += name
                line_width = _ba.get_string_width(nline, suppress_warning=True)
            if nline != '':
                sval += nline + '\n'
            return sval

        sound_and_music = ba.Lstr(resource=self._r +
                                  '.songCreditText').evaluate()
        sound_and_music = sound_and_music.replace(
            '${TITLE}', "'William Tell (Trumpet Entry)'")
        sound_and_music = sound_and_music.replace(
            '${PERFORMER}', 'The Apollo Symphony Orchestra')
        sound_and_music = sound_and_music.replace(
            '${PERFORMER}', 'The Apollo Symphony Orchestra')
        sound_and_music = sound_and_music.replace('${COMPOSER}',
                                                  'Gioacchino Rossini')
        sound_and_music = sound_and_music.replace('${ARRANGER}', 'Chris Worth')
        sound_and_music = sound_and_music.replace('${PUBLISHER}', 'BMI')
        sound_and_music = sound_and_music.replace('${SOURCE}',
                                                  'www.AudioSparx.com')
        spc = '     '
        sound_and_music = spc + sound_and_music.replace('\n', '\n' + spc)
        names = [
            'HubOfTheUniverseProd', 'Jovica', 'LG', 'Leady', 'Percy Duke',
            'PhreaKsAccount', 'Pogotron', 'Rock Savage', 'anamorphosis',
            'benboncan', 'cdrk', 'chipfork', 'guitarguy1985', 'jascha',
            'joedeshon', 'loofa', 'm_O_m', 'mich3d', 'sandyrb', 'shakaharu',
            'sirplus', 'stickman', 'thanvannispen', 'virotic', 'zimbot'
        ]
        names.sort(key=lambda x: x.lower())
        freesound_names = _format_names(names, 90)

        try:
            with open('ba_data/data/langdata.json') as infile:
                translation_contributors = (json.loads(
                    infile.read())['translation_contributors'])
        except Exception:
            ba.print_exception('Error reading translation contributors.')
            translation_contributors = []

        translation_names = _format_names(translation_contributors, 60)

        # Need to bake this out and chop it up since we're passing our
        # 65535 vertex limit for meshes..
        # We can remove that limit once we drop support for GL ES2.. :-/
        # (or add mesh splitting under the hood)
        credits_text = (
            '  ' + ba.Lstr(resource=self._r +
                           '.codingGraphicsAudioText').evaluate().replace(
                               '${NAME}', 'Eric Froemling') + '\n'
            '\n'
            '  ' + ba.Lstr(resource=self._r +
                           '.additionalAudioArtIdeasText').evaluate().replace(
                               '${NAME}', 'Raphael Suter') + '\n'
            '\n'
            '  ' +
            ba.Lstr(resource=self._r + '.soundAndMusicText').evaluate() + '\n'
            '\n' + sound_and_music + '\n'
            '\n'
            '     ' + ba.Lstr(resource=self._r +
                              '.publicDomainMusicViaText').evaluate().replace(
                                  '${NAME}', 'Musopen.com') + '\n'
            '        ' +
            ba.Lstr(resource=self._r +
                    '.thanksEspeciallyToText').evaluate().replace(
                        '${NAME}', 'the US Army, Navy, and Marine Bands') +
            '\n'
            '\n'
            '     ' + ba.Lstr(resource=self._r +
                              '.additionalMusicFromText').evaluate().replace(
                                  '${NAME}', 'The YouTube Audio Library') +
            '\n'
            '\n'
            '     ' +
            ba.Lstr(resource=self._r + '.soundsText').evaluate().replace(
                '${SOURCE}', 'Freesound.org') + '\n'
            '\n' + freesound_names + '\n'
            '\n'
            '  ' + ba.Lstr(resource=self._r +
                           '.languageTranslationsText').evaluate() + '\n'
            '\n' + '\n'.join(translation_names.splitlines()[:146]) +
            '\n'.join(translation_names.splitlines()[146:]) + '\n'
            '\n'
            '  Shout Out to Awesome Mods / Modders:\n\n'
            '     BombDash ModPack\n'
            '     TheMikirog & SoK - BombSquad Joyride Modpack\n'
            '     Mrmaxmeier - BombSquad-Community-Mod-Manager\n'
            '\n'
            '  Holiday theme vector art designed by Freepik\n'
            '\n'
            '  ' +
            ba.Lstr(resource=self._r + '.specialThanksText').evaluate() + '\n'
            '\n'
            '     Todd, Laura, and Robert Froemling\n'
            '     ' +
            ba.Lstr(resource=self._r + '.allMyFamilyText').evaluate().replace(
                '\n', '\n     ') + '\n'
            '     ' + ba.Lstr(resource=self._r +
                              '.whoeverInventedCoffeeText').evaluate() + '\n'
            '\n'
            '  ' + ba.Lstr(resource=self._r + '.legalText').evaluate() + '\n'
            '\n'
            '     ' + ba.Lstr(resource=self._r +
                              '.softwareBasedOnText').evaluate().replace(
                                  '${NAME}', 'the Khronos Group') + '\n'
            '\n'
            '                                       '
            '                      www.froemling.net\n')

        txt = credits_text
        lines = txt.splitlines()
        line_height = 20

        scale = 0.55
        self._sub_width = width - 80
        self._sub_height = line_height * len(lines) + 40

        container = self._subcontainer = ba.containerwidget(
            parent=scroll,
            size=(self._sub_width, self._sub_height),
            background=False,
            claims_left_right=False,
            claims_tab=False)

        voffs = 0
        for line in lines:
            ba.textwidget(parent=container,
                          padding=4,
                          color=(0.7, 0.9, 0.7, 1.0),
                          scale=scale,
                          flatness=1.0,
                          size=(0, 0),
                          position=(0, self._sub_height - 20 + voffs),
                          h_align='left',
                          v_align='top',
                          text=ba.Lstr(value=line))
            voffs -= line_height
Example #27
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-statements
        from bastd.ui import popup
        from bastd.ui.config import ConfigCheckBox, ConfigNumberEdit
        # if they provided an origin-widget, scale up from that
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        self._r = 'graphicsSettingsWindow'
        app = ba.app

        spacing = 32
        self._have_selected_child = False
        uiscale = app.ui.uiscale
        width = 450.0
        height = 302.0

        self._show_fullscreen = False
        fullscreen_spacing_top = spacing * 0.2
        fullscreen_spacing = spacing * 1.2
        if uiscale == ba.UIScale.LARGE and app.platform != 'android':
            self._show_fullscreen = True
            height += fullscreen_spacing + fullscreen_spacing_top

        show_gamma = False
        gamma_spacing = spacing * 1.3
        if _ba.has_gamma_control():
            show_gamma = True
            height += gamma_spacing

        show_vsync = False
        if app.platform == 'mac':
            show_vsync = True

        show_resolution = True
        if app.vr_mode:
            show_resolution = (app.platform == 'android'
                               and app.subplatform == 'cardboard')

        uiscale = ba.app.ui.uiscale
        base_scale = (2.4 if uiscale is ba.UIScale.SMALL else
                      1.5 if uiscale is ba.UIScale.MEDIUM else 1.0)
        popup_menu_scale = base_scale * 1.2
        v = height - 50
        v -= spacing * 1.15
        super().__init__(root_widget=ba.containerwidget(
            size=(width, height),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            scale=base_scale,
            stack_offset=(0, -30) if uiscale is ba.UIScale.SMALL else (0, 0)))

        btn = ba.buttonwidget(parent=self._root_widget,
                              position=(35, height - 50),
                              size=(120, 60),
                              scale=0.8,
                              text_scale=1.2,
                              autoselect=True,
                              label=ba.Lstr(resource='backText'),
                              button_type='back',
                              on_activate_call=self._back)

        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        ba.textwidget(parent=self._root_widget,
                      position=(0, height - 44),
                      size=(width, 25),
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      color=ba.app.ui.title_color,
                      h_align='center',
                      v_align='top')

        ba.buttonwidget(edit=btn,
                        button_type='backSmall',
                        size=(60, 60),
                        label=ba.charstr(ba.SpecialChar.BACK))

        self._fullscreen_checkbox: Optional[ba.Widget]
        if self._show_fullscreen:
            v -= fullscreen_spacing_top
            self._fullscreen_checkbox = ConfigCheckBox(
                parent=self._root_widget,
                position=(100, v),
                maxwidth=200,
                size=(300, 30),
                configkey='Fullscreen',
                displayname=ba.Lstr(resource=self._r +
                                    ('.fullScreenCmdText' if app.platform ==
                                     'mac' else '.fullScreenCtrlText'))).widget
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=self._fullscreen_checkbox)
                self._have_selected_child = True
            v -= fullscreen_spacing
        else:
            self._fullscreen_checkbox = None

        self._gamma_controls: Optional[ConfigNumberEdit]
        if show_gamma:
            self._gamma_controls = gmc = ConfigNumberEdit(
                parent=self._root_widget,
                position=(90, v),
                configkey='Screen Gamma',
                displayname=ba.Lstr(resource=self._r + '.gammaText'),
                minval=0.1,
                maxval=2.0,
                increment=0.1,
                xoffset=-70,
                textscale=0.85)
            if ba.app.ui.use_toolbars:
                ba.widget(edit=gmc.plusbutton,
                          right_widget=_ba.get_special_widget('party_button'))
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=gmc.minusbutton)
                self._have_selected_child = True
            v -= gamma_spacing
        else:
            self._gamma_controls = None

        self._selected_color = (0.5, 1, 0.5, 1)
        self._unselected_color = (0.7, 0.7, 0.7, 1)

        # quality
        ba.textwidget(parent=self._root_widget,
                      position=(60, v),
                      size=(160, 25),
                      text=ba.Lstr(resource=self._r + '.visualsText'),
                      color=ba.app.ui.heading_color,
                      scale=0.65,
                      maxwidth=150,
                      h_align='center',
                      v_align='center')
        popup.PopupMenu(
            parent=self._root_widget,
            position=(60, v - 50),
            width=150,
            scale=popup_menu_scale,
            choices=['Auto', 'Higher', 'High', 'Medium', 'Low'],
            choices_disabled=['Higher', 'High']
            if _ba.get_max_graphics_quality() == 'Medium' else [],
            choices_display=[
                ba.Lstr(resource='autoText'),
                ba.Lstr(resource=self._r + '.higherText'),
                ba.Lstr(resource=self._r + '.highText'),
                ba.Lstr(resource=self._r + '.mediumText'),
                ba.Lstr(resource=self._r + '.lowText')
            ],
            current_choice=ba.app.config.resolve('Graphics Quality'),
            on_value_change_call=self._set_quality)

        # texture controls
        ba.textwidget(parent=self._root_widget,
                      position=(230, v),
                      size=(160, 25),
                      text=ba.Lstr(resource=self._r + '.texturesText'),
                      color=ba.app.ui.heading_color,
                      scale=0.65,
                      maxwidth=150,
                      h_align='center',
                      v_align='center')
        textures_popup = popup.PopupMenu(
            parent=self._root_widget,
            position=(230, v - 50),
            width=150,
            scale=popup_menu_scale,
            choices=['Auto', 'High', 'Medium', 'Low'],
            choices_display=[
                ba.Lstr(resource='autoText'),
                ba.Lstr(resource=self._r + '.highText'),
                ba.Lstr(resource=self._r + '.mediumText'),
                ba.Lstr(resource=self._r + '.lowText')
            ],
            current_choice=ba.app.config.resolve('Texture Quality'),
            on_value_change_call=self._set_textures)
        if ba.app.ui.use_toolbars:
            ba.widget(edit=textures_popup.get_button(),
                      right_widget=_ba.get_special_widget('party_button'))
        v -= 80

        h_offs = 0

        if show_resolution:
            # resolution
            ba.textwidget(parent=self._root_widget,
                          position=(h_offs + 60, v),
                          size=(160, 25),
                          text=ba.Lstr(resource=self._r + '.resolutionText'),
                          color=ba.app.ui.heading_color,
                          scale=0.65,
                          maxwidth=150,
                          h_align='center',
                          v_align='center')

            # on standard android we have 'Auto', 'Native', and a few
            # HD standards
            if app.platform == 'android':
                # on cardboard/daydream android we have a few
                # render-target-scale options
                if app.subplatform == 'cardboard':
                    current_res_cardboard = (str(min(100, max(10, int(round(
                        ba.app.config.resolve('GVR Render Target Scale')
                        * 100.0))))) + '%')  # yapf: disable
                    popup.PopupMenu(
                        parent=self._root_widget,
                        position=(h_offs + 60, v - 50),
                        width=120,
                        scale=popup_menu_scale,
                        choices=['100%', '75%', '50%', '35%'],
                        current_choice=current_res_cardboard,
                        on_value_change_call=self._set_gvr_render_target_scale)
                else:
                    native_res = _ba.get_display_resolution()
                    assert native_res is not None
                    choices = ['Auto', 'Native']
                    choices_display = [
                        ba.Lstr(resource='autoText'),
                        ba.Lstr(resource='nativeText')
                    ]
                    for res in [1440, 1080, 960, 720, 480]:
                        # nav bar is 72px so lets allow for that in what
                        # choices we show
                        if native_res[1] >= res - 72:
                            res_str = str(res) + 'p'
                            choices.append(res_str)
                            choices_display.append(ba.Lstr(value=res_str))
                    current_res_android = ba.app.config.resolve(
                        'Resolution (Android)')
                    popup.PopupMenu(parent=self._root_widget,
                                    position=(h_offs + 60, v - 50),
                                    width=120,
                                    scale=popup_menu_scale,
                                    choices=choices,
                                    choices_display=choices_display,
                                    current_choice=current_res_android,
                                    on_value_change_call=self._set_android_res)
            else:
                # if we're on a system that doesn't allow setting resolution,
                # set pixel-scale instead
                current_res = _ba.get_display_resolution()
                if current_res is None:
                    current_res2 = (str(min(100, max(10, int(round(
                        ba.app.config.resolve('Screen Pixel Scale')
                        * 100.0))))) + '%')  # yapf: disable
                    popup.PopupMenu(
                        parent=self._root_widget,
                        position=(h_offs + 60, v - 50),
                        width=120,
                        scale=popup_menu_scale,
                        choices=['100%', '88%', '75%', '63%', '50%'],
                        current_choice=current_res2,
                        on_value_change_call=self._set_pixel_scale)
                else:
                    raise Exception('obsolete path; discrete resolutions'
                                    ' no longer supported')

        # vsync
        if show_vsync:
            ba.textwidget(parent=self._root_widget,
                          position=(230, v),
                          size=(160, 25),
                          text=ba.Lstr(resource=self._r + '.verticalSyncText'),
                          color=ba.app.ui.heading_color,
                          scale=0.65,
                          maxwidth=150,
                          h_align='center',
                          v_align='center')

            popup.PopupMenu(
                parent=self._root_widget,
                position=(230, v - 50),
                width=150,
                scale=popup_menu_scale,
                choices=['Auto', 'Always', 'Never'],
                choices_display=[
                    ba.Lstr(resource='autoText'),
                    ba.Lstr(resource=self._r + '.alwaysText'),
                    ba.Lstr(resource=self._r + '.neverText')
                ],
                current_choice=ba.app.config.resolve('Vertical Sync'),
                on_value_change_call=self._set_vsync)

        v -= 90
        fpsc = ConfigCheckBox(parent=self._root_widget,
                              position=(69, v - 6),
                              size=(210, 30),
                              scale=0.86,
                              configkey='Show FPS',
                              displayname=ba.Lstr(resource=self._r +
                                                  '.showFPSText'),
                              maxwidth=130)

        # (tv mode doesnt apply to vr)
        if not ba.app.vr_mode:
            tvc = ConfigCheckBox(parent=self._root_widget,
                                 position=(240, v - 6),
                                 size=(210, 30),
                                 scale=0.86,
                                 configkey='TV Border',
                                 displayname=ba.Lstr(resource=self._r +
                                                     '.tvBorderText'),
                                 maxwidth=130)
            # grumble..
            ba.widget(edit=fpsc.widget, right_widget=tvc.widget)
        try:
            pass

        except Exception:
            ba.print_exception('Exception wiring up graphics settings UI:')

        v -= spacing

        # make a timer to update our controls in case the config changes
        # under us
        self._update_timer = ba.Timer(0.25,
                                      ba.WeakCall(self._update_controls),
                                      repeat=True,
                                      timetype=ba.TimeType.REAL)
Example #28
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements

        # If they provided an origin-widget, scale up from that.
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        self._r = 'editSoundtrackWindow'
        uiscale = ba.app.ui.uiscale
        self._width = 800 if uiscale is ba.UIScale.SMALL else 600
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (340 if uiscale is ba.UIScale.SMALL else
                        370 if uiscale is ba.UIScale.MEDIUM else 440)
        spacing = 40.0
        v = self._height - 40.0
        v -= spacing * 1.0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(2.3 if uiscale is ba.UIScale.SMALL else
                   1.6 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -18) if uiscale is ba.UIScale.SMALL else (0, 0)))

        if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
            self._back_button = None
        else:
            self._back_button = ba.buttonwidget(
                parent=self._root_widget,
                position=(45 + x_inset, self._height - 60),
                size=(120, 60),
                scale=0.8,
                label=ba.Lstr(resource='backText'),
                button_type='back',
                autoselect=True)
            ba.buttonwidget(edit=self._back_button,
                            button_type='backSmall',
                            size=(60, 60),
                            label=ba.charstr(ba.SpecialChar.BACK))
        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 35),
                      size=(0, 0),
                      maxwidth=300,
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      color=ba.app.ui.title_color,
                      h_align='center',
                      v_align='center')

        h = 43 + x_inset
        v = self._height - 60
        b_color = (0.6, 0.53, 0.63)
        b_textcolor = (0.75, 0.7, 0.8)
        lock_tex = ba.gettexture('lock')
        self._lock_images: List[ba.Widget] = []

        scl = (1.0 if uiscale is ba.UIScale.SMALL else
               1.13 if uiscale is ba.UIScale.MEDIUM else 1.4)
        v -= 60.0 * scl
        self._new_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(100, 55.0 * scl),
            on_activate_call=self._new_soundtrack,
            color=b_color,
            button_type='square',
            autoselect=True,
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.newText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 55.0 * scl - 28),
                           texture=lock_tex))

        if self._back_button is None:
            ba.widget(edit=btn,
                      left_widget=_ba.get_special_widget('back_button'))
        v -= 60.0 * scl

        self._edit_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(100, 55.0 * scl),
            on_activate_call=self._edit_soundtrack,
            color=b_color,
            button_type='square',
            autoselect=True,
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.editText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 55.0 * scl - 28),
                           texture=lock_tex))
        if self._back_button is None:
            ba.widget(edit=btn,
                      left_widget=_ba.get_special_widget('back_button'))
        v -= 60.0 * scl

        self._duplicate_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(100, 55.0 * scl),
            on_activate_call=self._duplicate_soundtrack,
            button_type='square',
            autoselect=True,
            color=b_color,
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.duplicateText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 55.0 * scl - 28),
                           texture=lock_tex))
        if self._back_button is None:
            ba.widget(edit=btn,
                      left_widget=_ba.get_special_widget('back_button'))
        v -= 60.0 * scl

        self._delete_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(100, 55.0 * scl),
            on_activate_call=self._delete_soundtrack,
            color=b_color,
            button_type='square',
            autoselect=True,
            textcolor=b_textcolor,
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.deleteText'))
        self._lock_images.append(
            ba.imagewidget(parent=self._root_widget,
                           size=(30, 30),
                           draw_controller=btn,
                           position=(h - 10, v + 55.0 * scl - 28),
                           texture=lock_tex))
        if self._back_button is None:
            ba.widget(edit=btn,
                      left_widget=_ba.get_special_widget('back_button'))

        # Keep our lock images up to date/etc.
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._update()

        v = self._height - 65
        scroll_height = self._height - 105
        v -= scroll_height
        self._scrollwidget = scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            position=(152 + x_inset, v),
            highlight=False,
            size=(self._width - (205 + 2 * x_inset), scroll_height))
        ba.widget(edit=self._scrollwidget,
                  left_widget=self._new_button,
                  right_widget=_ba.get_special_widget('party_button')
                  if ba.app.ui.use_toolbars else self._scrollwidget)
        self._col = ba.columnwidget(parent=scrollwidget, border=2, margin=0)

        self._soundtracks: Optional[Dict[str, Any]] = None
        self._selected_soundtrack: Optional[str] = None
        self._selected_soundtrack_index: Optional[int] = None
        self._soundtrack_widgets: List[ba.Widget] = []
        self._allow_changing_soundtracks = False
        self._refresh()
        if self._back_button is not None:
            ba.buttonwidget(edit=self._back_button,
                            on_activate_call=self._back)
            ba.containerwidget(edit=self._root_widget,
                               cancel_button=self._back_button)
        else:
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back)
    def _build_saved_party_tab(self, region_width: float,
                        region_height: float) -> None:
        c_width = region_width
        c_height = region_height - 20
        v = c_height - 35
        v -= 25
        is_public_enabled = _ba.get_public_party_enabled()
        v -= 30
        uiscale = ba.app.ui.uiscale
        self._width = 1240 if uiscale is ba.UIScale.SMALL else 1040
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (578 if uiscale is ba.UIScale.SMALL else
                        670 if uiscale is ba.UIScale.MEDIUM else 800)
        scroll_buffer_h = 130 + 2 * x_inset
        tab_buffer_h = 750 + 2 * x_inset
        self._scroll_width = self._width - scroll_buffer_h
        self._scroll_height = self._height - 180
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        
        if True:
            c_width = self._scroll_width
            c_height = self._scroll_height - 20
            sub_scroll_height = c_height - 63
            self._my_parties_scroll_width = sub_scroll_width = (
                680 if uiscale is ba.UIScale.SMALL else 640)

           

            v = c_height - 30
            
            b_width = 140 if uiscale is ba.UIScale.SMALL else 178
            b_height = (107 if uiscale is ba.UIScale.SMALL else
                        142 if uiscale is ba.UIScale.MEDIUM else 190)
            b_space_extra = (0 if uiscale is ba.UIScale.SMALL else
                             -2 if uiscale is ba.UIScale.MEDIUM else -5)

            b_color = (0.6, 0.53, 0.63)
            b_textcolor = (0.75, 0.7, 0.8)
            btnv = (c_height - (48 if uiscale is ba.UIScale.SMALL else
                                45 if uiscale is ba.UIScale.MEDIUM else 40) -
                    b_height)
            btnh = 40 if uiscale is ba.UIScale.SMALL else 40
            smlh = 190 if uiscale is ba.UIScale.SMALL else 225
            tscl = 1.0 if uiscale is ba.UIScale.SMALL else 1.2
            self._my_saved_party_connect_button = btn1 = ba.buttonwidget(
                parent=self._container,
                size=(b_width, b_height),
                position=(btnh, btnv),
                button_type='square',
                color=b_color,
                textcolor=b_textcolor,
                on_activate_call=self._on_my_saved_party_press,
                text_scale=tscl,
                label="Connect",
                autoselect=True)
            # ba.widget(edit=btn1, up_widget=self._tab_row.tabs[tab_id].button)
            if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
                ba.widget(edit=btn1,
                          left_widget=_ba.get_special_widget('back_button'))
            btnv -= b_height + b_space_extra
            ba.buttonwidget(parent=self._container,
                            size=(b_width, b_height),
                            position=(btnh, btnv),
                            button_type='square',
                            color=b_color,
                            textcolor=b_textcolor,
                            on_activate_call=self._on_my_saved_party_rename_press,
                            text_scale=tscl,
                            label="Rename",
                            autoselect=True)
            btnv -= b_height + b_space_extra
            ba.buttonwidget(parent=self._container,
                            size=(b_width, b_height),
                            position=(btnh, btnv),
                            button_type='square',
                            color=b_color,
                            textcolor=b_textcolor,
                            on_activate_call=self._on_my_saved_party_delete_press,
                            text_scale=tscl,
                            label="Delete",
                            autoselect=True)

            v -= sub_scroll_height + 23
            self._scrollwidget = scrlw = ba.scrollwidget(
                parent=self._container,
                position=(smlh, v),
                size=(sub_scroll_width, sub_scroll_height))
            ba.containerwidget(edit=self._container, selected_child=scrlw)
            self._columnwidget = ba.columnwidget(parent=scrlw,
                                                 left_border=10,
                                                 border=2,
                                                 margin=0)

            
            self._my_saved_party_selected = None
            self._refresh_my_saved_parties()