Esempio n. 1
0
 def __init__(self,
              parent: ba.Widget,
              configkey: str,
              position: Tuple[float, float],
              size: Tuple[float, float],
              displayname: Union[str, ba.Lstr] = None,
              scale: float = None,
              maxwidth: float = None,
              autoselect: bool = True,
              value_change_call: Callable[[Any], Any] = None):
     if displayname is None:
         displayname = configkey
     self._value_change_call = value_change_call
     self._configkey = configkey
     self.widget = ba.checkboxwidget(
         parent=parent,
         autoselect=autoselect,
         position=position,
         size=size,
         text=displayname,
         textcolor=(0.8, 0.8, 0.8),
         value=ba.app.config.resolve(configkey),
         on_value_change_call=self._value_changed,
         scale=scale,
         maxwidth=maxwidth)
     # complain if we outlive our checkbox
     ba.uicleanupcheck(self, self.widget)
Esempio n. 2
0
def make_radio_group(check_boxes: Sequence[ba.Widget],
                     value_names: Sequence[str], value: str,
                     value_change_call: Callable[[str], Any]) -> None:
    """Link the provided check_boxes together into a radio group."""
    def _radio_press(check_string: str, other_check_boxes: List[ba.Widget],
                     val: int) -> None:
        if val == 1:
            value_change_call(check_string)
            for cbx in other_check_boxes:
                ba.checkboxwidget(edit=cbx, value=False)

    for i, check_box in enumerate(check_boxes):
        ba.checkboxwidget(edit=check_box,
                          value=(value == value_names[i]),
                          is_radio_button=True,
                          on_value_change_call=ba.Call(
                              _radio_press, value_names[i],
                              [c for c in check_boxes if c != check_box]))
Esempio n. 3
0
    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)
Esempio n. 4
0
    def __init__(self) -> None:
        from ba.internal import get_remote_app_name
        self._r = 'connectMobileDevicesWindow'
        width = 700
        height = 390
        spacing = 40
        super().__init__(root_widget=ba.containerwidget(
            size=(width, height),
            transition='in_right',
            scale=(1.85 if ba.app.small_ui else 1.3 if ba.app.med_ui else 1.0),
            stack_offset=(-10, 0) if ba.app.small_ui else (0, 0)))
        btn = ba.buttonwidget(parent=self._root_widget,
                              position=(40, height - 67),
                              size=(140, 65),
                              scale=0.8,
                              label=ba.Lstr(resource='backText'),
                              button_type='back',
                              text_scale=1.1,
                              autoselect=True,
                              on_activate_call=self._back)
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        ba.textwidget(parent=self._root_widget,
                      position=(width * 0.5, height - 42),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      maxwidth=370,
                      color=ba.app.title_color,
                      scale=0.8,
                      h_align='center',
                      v_align='center')

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

        v = height - 70.0
        v -= spacing * 1.2
        ba.textwidget(parent=self._root_widget,
                      position=(15, v - 26),
                      size=(width - 30, 30),
                      maxwidth=width * 0.95,
                      color=(0.7, 0.9, 0.7, 1.0),
                      scale=0.8,
                      text=ba.Lstr(resource=self._r + '.explanationText',
                                   subs=[('${APP_NAME}',
                                          ba.Lstr(resource='titleText')),
                                         ('${REMOTE_APP_NAME}',
                                          get_remote_app_name())]),
                      max_height=100,
                      h_align='center',
                      v_align='center')
        v -= 90

        # hmm the itms:// version doesnt bounce through safari but is kinda
        # apple-specific-ish

        # Update: now we just show link to the remote webpage.
        ba.textwidget(parent=self._root_widget,
                      position=(width * 0.5, v + 5),
                      size=(0, 0),
                      color=(0.7, 0.9, 0.7, 1.0),
                      scale=1.4,
                      text='bombsquadgame.com/remote',
                      maxwidth=width * 0.95,
                      max_height=60,
                      h_align='center',
                      v_align='center')
        v -= 30

        ba.textwidget(parent=self._root_widget,
                      position=(width * 0.5, v - 35),
                      size=(0, 0),
                      color=(0.7, 0.9, 0.7, 0.8),
                      scale=0.65,
                      text=ba.Lstr(resource=self._r + '.bestResultsText'),
                      maxwidth=width * 0.95,
                      max_height=height * 0.19,
                      h_align='center',
                      v_align='center')

        ba.checkboxwidget(
            parent=self._root_widget,
            position=(width * 0.5 - 150, v - 116),
            size=(300, 30),
            maxwidth=300,
            scale=0.8,
            value=not ba.app.config.resolve('Enable Remote App'),
            autoselect=True,
            text=ba.Lstr(resource='disableRemoteAppConnectionsText'),
            on_value_change_call=self._on_check_changed)
Esempio n. 5
0
    def __init__(self,
                 sessiontype: Type[ba.Session],
                 playlist: str,
                 scale_origin: Tuple[float, float],
                 delegate: Any = None):
        # FIXME: Tidy this up.
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        from ba.internal import (getclass, have_pro,
                                 get_default_teams_playlist,
                                 get_default_free_for_all_playlist,
                                 filter_playlist)
        from ba.internal import get_map_class
        from bastd.ui.playlist import PlaylistTypeVars

        self._r = 'gameListWindow'
        self._delegate = delegate
        self._pvars = PlaylistTypeVars(sessiontype)
        self._transitioning_out = False

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

        self._sessiontype = sessiontype
        self._playlist = playlist

        self._width = 500.0
        self._height = 330.0 - 50.0

        # In teams games, show the custom names/colors button.
        if self._sessiontype is ba.DualTeamSession:
            self._height += 50.0

        self._row_height = 45.0

        # Grab our maps to display.
        model_opaque = ba.getmodel('level_select_button_opaque')
        model_transparent = ba.getmodel('level_select_button_transparent')
        mask_tex = ba.gettexture('mapPreviewMask')

        # Poke into this playlist and see if we can display some of its maps.
        map_textures = []
        map_texture_entries = []
        rows = 0
        columns = 0
        game_count = 0
        scl = 0.35
        c_width_total = 0.0
        try:
            max_columns = 5
            name = playlist
            if name == '__default__':
                if self._sessiontype is ba.FreeForAllSession:
                    plst = get_default_free_for_all_playlist()
                elif self._sessiontype is ba.DualTeamSession:
                    plst = get_default_teams_playlist()
                else:
                    raise Exception('unrecognized session-type: ' +
                                    str(self._sessiontype))
            else:
                try:
                    plst = ba.app.config[self._pvars.config_name +
                                         ' Playlists'][name]
                except Exception:
                    print('ERROR INFO: self._config_name is:',
                          self._pvars.config_name)
                    print(
                        'ERROR INFO: playlist names are:',
                        list(ba.app.config[self._pvars.config_name +
                                           ' Playlists'].keys()))
                    raise
            plst = filter_playlist(plst,
                                   self._sessiontype,
                                   remove_unowned=False,
                                   mark_unowned=True)
            game_count = len(plst)
            for entry in plst:
                mapname = entry['settings']['map']
                maptype: Optional[Type[ba.Map]]
                try:
                    maptype = get_map_class(mapname)
                except Exception:
                    maptype = None
                if maptype is not None:
                    tex_name = maptype.get_preview_texture_name()
                    if tex_name is not None:
                        map_textures.append(tex_name)
                        map_texture_entries.append(entry)
            rows = (max(0, len(map_textures) - 1) // max_columns) + 1
            columns = min(max_columns, len(map_textures))

            if len(map_textures) == 1:
                scl = 1.1
            elif len(map_textures) == 2:
                scl = 0.7
            elif len(map_textures) == 3:
                scl = 0.55
            else:
                scl = 0.35
            self._row_height = 128.0 * scl
            c_width_total = scl * 250.0 * columns
            if map_textures:
                self._height += self._row_height * rows

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

        show_shuffle_check_box = game_count > 1

        if show_shuffle_check_box:
            self._height += 40

        # Creates our _root_widget.
        scale = (1.69 if ba.app.small_ui else 1.1 if ba.app.med_ui else 0.85)
        super().__init__(position=scale_origin,
                         size=(self._width, self._height),
                         scale=scale)

        playlist_name: Union[str, ba.Lstr] = (self._pvars.default_list_name
                                              if playlist == '__default__' else
                                              playlist)
        self._title_text = ba.textwidget(parent=self.root_widget,
                                         position=(self._width * 0.5,
                                                   self._height - 89 + 51),
                                         size=(0, 0),
                                         text=playlist_name,
                                         scale=1.4,
                                         color=(1, 1, 1),
                                         maxwidth=self._width * 0.7,
                                         h_align='center',
                                         v_align='center')

        self._cancel_button = ba.buttonwidget(
            parent=self.root_widget,
            position=(25, self._height - 53),
            size=(50, 50),
            scale=0.7,
            label='',
            color=(0.42, 0.73, 0.2),
            on_activate_call=self._on_cancel_press,
            autoselect=True,
            icon=ba.gettexture('crossOut'),
            iconscale=1.2)

        h_offs_img = self._width * 0.5 - c_width_total * 0.5
        v_offs_img = self._height - 118 - scl * 125.0 + 50
        bottom_row_buttons = []
        self._have_at_least_one_owned = False

        for row in range(rows):
            for col in range(columns):
                tex_index = row * columns + col
                if tex_index < len(map_textures):
                    tex_name = map_textures[tex_index]
                    h = h_offs_img + scl * 250 * col
                    v = v_offs_img - self._row_height * row
                    entry = map_texture_entries[tex_index]
                    owned = not (('is_unowned_map' in entry
                                  and entry['is_unowned_map']) or
                                 ('is_unowned_game' in entry
                                  and entry['is_unowned_game']))

                    if owned:
                        self._have_at_least_one_owned = True

                    try:
                        desc = getclass(entry['type'],
                                        subclassof=ba.GameActivity
                                        ).get_config_display_string(entry)
                        if not owned:
                            desc = ba.Lstr(
                                value='${DESC}\n${UNLOCK}',
                                subs=[
                                    ('${DESC}', desc),
                                    ('${UNLOCK}',
                                     ba.Lstr(
                                         resource='unlockThisInTheStoreText'))
                                ])
                        desc_color = (0, 1, 0) if owned else (1, 0, 0)
                    except Exception:
                        desc = ba.Lstr(value='(invalid)')
                        desc_color = (1, 0, 0)

                    btn = ba.buttonwidget(
                        parent=self.root_widget,
                        size=(scl * 240.0, scl * 120.0),
                        position=(h, v),
                        texture=ba.gettexture(tex_name if owned else 'empty'),
                        model_opaque=model_opaque if owned else None,
                        on_activate_call=ba.Call(ba.screenmessage, desc,
                                                 desc_color),
                        label='',
                        color=(1, 1, 1),
                        autoselect=True,
                        extra_touch_border_scale=0.0,
                        model_transparent=model_transparent if owned else None,
                        mask_texture=mask_tex if owned else None)
                    if row == 0 and col == 0:
                        ba.widget(edit=self._cancel_button, down_widget=btn)
                    if row == rows - 1:
                        bottom_row_buttons.append(btn)
                    if not owned:

                        # Ewww; buttons don't currently have alpha so in this
                        # case we draw an image over our button with an empty
                        # texture on it.
                        ba.imagewidget(parent=self.root_widget,
                                       size=(scl * 260.0, scl * 130.0),
                                       position=(h - 10.0 * scl,
                                                 v - 4.0 * scl),
                                       draw_controller=btn,
                                       color=(1, 1, 1),
                                       texture=ba.gettexture(tex_name),
                                       model_opaque=model_opaque,
                                       opacity=0.25,
                                       model_transparent=model_transparent,
                                       mask_texture=mask_tex)

                        ba.imagewidget(parent=self.root_widget,
                                       size=(scl * 100, scl * 100),
                                       draw_controller=btn,
                                       position=(h + scl * 70, v + scl * 10),
                                       texture=ba.gettexture('lock'))

        # Team names/colors.
        self._custom_colors_names_button: Optional[ba.Widget]
        if self._sessiontype is ba.DualTeamSession:
            y_offs = 50 if show_shuffle_check_box else 0
            self._custom_colors_names_button = ba.buttonwidget(
                parent=self.root_widget,
                position=(100, 200 + y_offs),
                size=(290, 35),
                on_activate_call=ba.WeakCall(self._custom_colors_names_press),
                autoselect=True,
                textcolor=(0.8, 0.8, 0.8),
                label=ba.Lstr(resource='teamNamesColorText'))
            if not have_pro():
                ba.imagewidget(
                    parent=self.root_widget,
                    size=(30, 30),
                    position=(95, 202 + y_offs),
                    texture=ba.gettexture('lock'),
                    draw_controller=self._custom_colors_names_button)
        else:
            self._custom_colors_names_button = None

        # Shuffle.
        def _cb_callback(val: bool) -> None:
            self._do_randomize_val = val
            cfg = ba.app.config
            cfg[self._pvars.config_name +
                ' Playlist Randomize'] = self._do_randomize_val
            cfg.commit()

        if show_shuffle_check_box:
            self._shuffle_check_box = ba.checkboxwidget(
                parent=self.root_widget,
                position=(110, 200),
                scale=1.0,
                size=(250, 30),
                autoselect=True,
                text=ba.Lstr(resource=self._r + '.shuffleGameOrderText'),
                maxwidth=300,
                textcolor=(0.8, 0.8, 0.8),
                value=self._do_randomize_val,
                on_value_change_call=_cb_callback)

        # Show tutorial.
        try:
            show_tutorial = ba.app.config['Show Tutorial']
        except Exception:
            show_tutorial = True

        def _cb_callback_2(val: bool) -> None:
            cfg = ba.app.config
            cfg['Show Tutorial'] = val
            cfg.commit()

        self._show_tutorial_check_box = ba.checkboxwidget(
            parent=self.root_widget,
            position=(110, 151),
            scale=1.0,
            size=(250, 30),
            autoselect=True,
            text=ba.Lstr(resource=self._r + '.showTutorialText'),
            maxwidth=300,
            textcolor=(0.8, 0.8, 0.8),
            value=show_tutorial,
            on_value_change_call=_cb_callback_2)

        # Grumble: current autoselect doesn't do a very good job
        # with checkboxes.
        if self._custom_colors_names_button is not None:
            for btn in bottom_row_buttons:
                ba.widget(edit=btn,
                          down_widget=self._custom_colors_names_button)
            if show_shuffle_check_box:
                ba.widget(edit=self._custom_colors_names_button,
                          down_widget=self._shuffle_check_box)
                ba.widget(edit=self._shuffle_check_box,
                          up_widget=self._custom_colors_names_button)
            else:
                ba.widget(edit=self._custom_colors_names_button,
                          down_widget=self._show_tutorial_check_box)
                ba.widget(edit=self._show_tutorial_check_box,
                          up_widget=self._custom_colors_names_button)

        self._play_button = ba.buttonwidget(
            parent=self.root_widget,
            position=(70, 44),
            size=(200, 45),
            scale=1.8,
            text_res_scale=1.5,
            on_activate_call=self._on_play_press,
            autoselect=True,
            label=ba.Lstr(resource='playText'))

        ba.widget(edit=self._play_button,
                  up_widget=self._show_tutorial_check_box)

        ba.containerwidget(edit=self.root_widget,
                           start_button=self._play_button,
                           cancel_button=self._cancel_button,
                           selected_child=self._play_button)

        # Update now and once per second.
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._update()
Esempio n. 6
0
    def _rebuild_ui(self) -> None:
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        from ba.internal import get_device_value

        # Clear existing UI.
        for widget in self._root_widget.get_children():
            widget.delete()

        self._textwidgets: Dict[str, ba.Widget] = {}

        # If we were supplied with settings, we're a secondary joystick and
        # just operate on that. in the other (normal) case we make our own.
        if not self._is_secondary:

            # Fill our temp config with present values (for our primary and
            # secondary controls).
            self._settings = {}
            for skey in [
                    'buttonJump',
                    'buttonJump_B',
                    'buttonPunch',
                    'buttonPunch_B',
                    'buttonBomb',
                    'buttonBomb_B',
                    'buttonPickUp',
                    'buttonPickUp_B',
                    'buttonStart',
                    'buttonStart_B',
                    'buttonStart2',
                    'buttonStart2_B',
                    'buttonUp',
                    'buttonUp_B',
                    'buttonDown',
                    'buttonDown_B',
                    'buttonLeft',
                    'buttonLeft_B',
                    'buttonRight',
                    'buttonRight_B',
                    'buttonRun1',
                    'buttonRun1_B',
                    'buttonRun2',
                    'buttonRun2_B',
                    'triggerRun1',
                    'triggerRun1_B',
                    'triggerRun2',
                    'triggerRun2_B',
                    'buttonIgnored',
                    'buttonIgnored_B',
                    'buttonIgnored2',
                    'buttonIgnored2_B',
                    'buttonIgnored3',
                    'buttonIgnored3_B',
                    'buttonIgnored4',
                    'buttonIgnored4_B',
                    'buttonVRReorient',
                    'buttonVRReorient_B',
                    'analogStickDeadZone',
                    'analogStickDeadZone_B',
                    'dpad',
                    'dpad_B',
                    'unassignedButtonsRun',
                    'unassignedButtonsRun_B',
                    'startButtonActivatesDefaultWidget',
                    'startButtonActivatesDefaultWidget_B',
                    'uiOnly',
                    'uiOnly_B',
                    'ignoreCompletely',
                    'ignoreCompletely_B',
                    'autoRecalibrateAnalogStick',
                    'autoRecalibrateAnalogStick_B',
                    'analogStickLR',
                    'analogStickLR_B',
                    'analogStickUD',
                    'analogStickUD_B',
                    'enableSecondary',
            ]:
                val = get_device_value(self._input, skey)
                if val != -1:
                    self._settings[skey] = val

        back_button: Optional[ba.Widget]

        if self._is_secondary:
            back_button = ba.buttonwidget(parent=self._root_widget,
                                          position=(self._width - 180,
                                                    self._height - 65),
                                          autoselect=True,
                                          size=(160, 60),
                                          label=ba.Lstr(resource='doneText'),
                                          scale=0.9,
                                          on_activate_call=self._save)
            ba.containerwidget(edit=self._root_widget,
                               start_button=back_button,
                               on_cancel_call=back_button.activate)
            cancel_button = None
        else:
            cancel_button = ba.buttonwidget(
                parent=self._root_widget,
                position=(51, self._height - 65),
                autoselect=True,
                size=(160, 60),
                label=ba.Lstr(resource='cancelText'),
                scale=0.9,
                on_activate_call=self._cancel)
            ba.containerwidget(edit=self._root_widget,
                               cancel_button=cancel_button)

        save_button: Optional[ba.Widget]
        if not self._is_secondary:
            save_button = ba.buttonwidget(
                parent=self._root_widget,
                position=(self._width - (165 if self._is_secondary else 195),
                          self._height - 65),
                size=((160 if self._is_secondary else 180), 60),
                autoselect=True,
                label=ba.Lstr(resource='doneText')
                if self._is_secondary else ba.Lstr(resource='saveText'),
                scale=0.9,
                on_activate_call=self._save)
            ba.containerwidget(edit=self._root_widget,
                               start_button=save_button)
        else:
            save_button = None

        if not self._is_secondary:
            v = self._height - 59
            ba.textwidget(parent=self._root_widget,
                          position=(0, v + 5),
                          size=(self._width, 25),
                          text=ba.Lstr(resource=self._r + '.titleText'),
                          color=ba.app.ui.title_color,
                          maxwidth=310,
                          h_align='center',
                          v_align='center')
            v -= 48

            ba.textwidget(parent=self._root_widget,
                          position=(0, v + 3),
                          size=(self._width, 25),
                          text=self._name,
                          color=ba.app.ui.infotextcolor,
                          maxwidth=self._width * 0.9,
                          h_align='center',
                          v_align='center')
            v -= self._spacing * 1

            ba.textwidget(parent=self._root_widget,
                          position=(50, v + 10),
                          size=(self._width - 100, 30),
                          text=ba.Lstr(resource=self._r + '.appliesToAllText'),
                          maxwidth=330,
                          scale=0.65,
                          color=(0.5, 0.6, 0.5, 1.0),
                          h_align='center',
                          v_align='center')
            v -= 70
            self._enable_check_box = None
        else:
            v = self._height - 49
            ba.textwidget(parent=self._root_widget,
                          position=(0, v + 5),
                          size=(self._width, 25),
                          text=ba.Lstr(resource=self._r + '.secondaryText'),
                          color=ba.app.ui.title_color,
                          maxwidth=300,
                          h_align='center',
                          v_align='center')
            v -= self._spacing * 1

            ba.textwidget(parent=self._root_widget,
                          position=(50, v + 10),
                          size=(self._width - 100, 30),
                          text=ba.Lstr(resource=self._r + '.secondHalfText'),
                          maxwidth=300,
                          scale=0.65,
                          color=(0.6, 0.8, 0.6, 1.0),
                          h_align='center')
            self._enable_check_box = ba.checkboxwidget(
                parent=self._root_widget,
                position=(self._width * 0.5 - 80, v - 73),
                value=self.get_enable_secondary_value(),
                autoselect=True,
                on_value_change_call=self._enable_check_box_changed,
                size=(200, 30),
                text=ba.Lstr(resource=self._r + '.secondaryEnableText'),
                scale=1.2)
            v = self._height - 205

        h_offs = 160
        dist = 70
        d_color = (0.4, 0.4, 0.8)
        sclx = 1.2
        scly = 0.98
        dpm = ba.Lstr(resource=self._r + '.pressAnyButtonOrDpadText')
        dpm2 = ba.Lstr(resource=self._r + '.ifNothingHappensTryAnalogText')
        self._capture_button(pos=(h_offs, v + scly * dist),
                             color=d_color,
                             button='buttonUp' + self._ext,
                             texture=ba.gettexture('upButton'),
                             scale=1.0,
                             message=dpm,
                             message2=dpm2)
        self._capture_button(pos=(h_offs - sclx * dist, v),
                             color=d_color,
                             button='buttonLeft' + self._ext,
                             texture=ba.gettexture('leftButton'),
                             scale=1.0,
                             message=dpm,
                             message2=dpm2)
        self._capture_button(pos=(h_offs + sclx * dist, v),
                             color=d_color,
                             button='buttonRight' + self._ext,
                             texture=ba.gettexture('rightButton'),
                             scale=1.0,
                             message=dpm,
                             message2=dpm2)
        self._capture_button(pos=(h_offs, v - scly * dist),
                             color=d_color,
                             button='buttonDown' + self._ext,
                             texture=ba.gettexture('downButton'),
                             scale=1.0,
                             message=dpm,
                             message2=dpm2)

        dpm3 = ba.Lstr(resource=self._r + '.ifNothingHappensTryDpadText')
        self._capture_button(pos=(h_offs + 130, v - 125),
                             color=(0.4, 0.4, 0.6),
                             button='analogStickLR' + self._ext,
                             maxwidth=140,
                             texture=ba.gettexture('analogStick'),
                             scale=1.2,
                             message=ba.Lstr(resource=self._r +
                                             '.pressLeftRightText'),
                             message2=dpm3)

        self._capture_button(pos=(self._width * 0.5, v),
                             color=(0.4, 0.4, 0.6),
                             button='buttonStart' + self._ext,
                             texture=ba.gettexture('startButton'),
                             scale=0.7)

        h_offs = self._width - 160

        self._capture_button(pos=(h_offs, v + scly * dist),
                             color=(0.6, 0.4, 0.8),
                             button='buttonPickUp' + self._ext,
                             texture=ba.gettexture('buttonPickUp'),
                             scale=1.0)
        self._capture_button(pos=(h_offs - sclx * dist, v),
                             color=(0.7, 0.5, 0.1),
                             button='buttonPunch' + self._ext,
                             texture=ba.gettexture('buttonPunch'),
                             scale=1.0)
        self._capture_button(pos=(h_offs + sclx * dist, v),
                             color=(0.5, 0.2, 0.1),
                             button='buttonBomb' + self._ext,
                             texture=ba.gettexture('buttonBomb'),
                             scale=1.0)
        self._capture_button(pos=(h_offs, v - scly * dist),
                             color=(0.2, 0.5, 0.2),
                             button='buttonJump' + self._ext,
                             texture=ba.gettexture('buttonJump'),
                             scale=1.0)

        self._advanced_button = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            label=ba.Lstr(resource=self._r + '.advancedText'),
            text_scale=0.9,
            color=(0.45, 0.4, 0.5),
            textcolor=(0.65, 0.6, 0.7),
            position=(self._width - 300, 30),
            size=(130, 40),
            on_activate_call=self._do_advanced)

        try:
            if cancel_button is not None and save_button is not None:
                ba.widget(edit=cancel_button, right_widget=save_button)
                ba.widget(edit=save_button, left_widget=cancel_button)
        except Exception:
            ba.print_exception('Error wiring up gamepad config window.')
Esempio n. 7
0
 def _update_controls(self) -> None:
     if self._show_fullscreen:
         ba.checkboxwidget(edit=self._fullscreen_checkbox,
                           value=ba.app.config.resolve('Fullscreen'))
Esempio n. 8
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        app = ba.app

        # 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

        uiscale = ba.app.ui.uiscale
        self._width = 870.0 if uiscale is ba.UIScale.SMALL else 670.0
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (390.0 if uiscale is ba.UIScale.SMALL else
                        450.0 if uiscale is ba.UIScale.MEDIUM else 520.0)
        top_extra = 10 if uiscale is ba.UIScale.SMALL else 0
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(2.06 if uiscale is ba.UIScale.SMALL else
                   1.4 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -25) if uiscale is ba.UIScale.SMALL else (0, 0)))

        self._scroll_width = self._width - (100 + 2 * x_inset)
        self._scroll_height = self._height - 115.0
        self._sub_width = self._scroll_width * 0.95
        self._sub_height = 724.0

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

        self._title_text = ba.textwidget(parent=self._root_widget,
                                         position=(0, self._height - 52),
                                         size=(self._width, 25),
                                         text=ba.Lstr(resource='pluginsText'),
                                         color=app.ui.title_color,
                                         h_align='center',
                                         v_align='top')

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

        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                             position=(50 + x_inset, 50),
                                             simple_culling_v=20.0,
                                             highlight=False,
                                             size=(self._scroll_width,
                                                   self._scroll_height),
                                             selection_loops_to_parent=True)
        ba.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)
        self._subcontainer = ba.columnwidget(parent=self._scrollwidget,
                                             selection_loops_to_parent=True)

        if ba.app.metascan is None:
            ba.screenmessage('Still scanning plugins; please try again.',
                             color=(1, 0, 0))
            ba.playsound(ba.getsound('error'))
        pluglist = ba.app.potential_plugins
        plugstates: Dict[str, Dict] = ba.app.config.setdefault('Plugins', {})
        assert isinstance(plugstates, dict)
        for i, availplug in enumerate(pluglist):
            active = availplug.class_path in ba.app.active_plugins

            plugstate = plugstates.setdefault(availplug.class_path, {})
            checked = plugstate.get('enabled', False)
            assert isinstance(checked, bool)
            check = ba.checkboxwidget(
                parent=self._subcontainer,
                text=availplug.display_name,
                value=checked,
                maxwidth=self._scroll_width - 100,
                size=(self._scroll_width - 40, 50),
                on_value_change_call=ba.Call(self._check_value_changed,
                                             availplug),
                textcolor=((0.8, 0.3, 0.3) if not availplug.available else
                           (0, 1, 0) if active else (0.6, 0.6, 0.6)))

            # Make sure we scroll all the way to the end when using
            # keyboard/button nav.
            ba.widget(edit=check, show_buffer_top=40, show_buffer_bottom=40)

            # Keep last from looping to back button when down is pressed.
            if i == len(pluglist) - 1:
                ba.widget(edit=check, down_widget=check)
        ba.containerwidget(edit=self._root_widget,
                           selected_child=self._scrollwidget)

        self._restore_state()
    def __init__(self, parent_window: gpsui.GamepadSettingsWindow):
        # pylint: disable=too-many-statements
        self._parent_window = parent_window

        app = ba.app

        self._r = parent_window.get_r()
        uiscale = ba.app.ui.uiscale
        self._width = 900 if uiscale is ba.UIScale.SMALL else 700
        self._x_inset = x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = 402 if uiscale is ba.UIScale.SMALL else 512
        self._textwidgets: dict[str, ba.Widget] = {}
        super().__init__(root_widget=ba.containerwidget(
            transition='in_scale',
            size=(self._width, self._height),
            scale=1.06 * (1.85 if uiscale is ba.UIScale.SMALL else
                          1.35 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -25) if uiscale is ba.UIScale.SMALL else (0, 0),
            scale_origin_stack_offset=(parent_window.get_advanced_button().
                                       get_screen_space_center())))

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height -
                                (40 if uiscale is ba.UIScale.SMALL else 34)),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r + '.advancedTitleText'),
                      maxwidth=320,
                      color=ba.app.ui.title_color,
                      h_align='center',
                      v_align='center')

        back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            position=(self._width - (176 + x_inset), self._height -
                      (60 if uiscale is ba.UIScale.SMALL else 55)),
            size=(120, 48),
            text_scale=0.8,
            label=ba.Lstr(resource='doneText'),
            on_activate_call=self._done)
        ba.containerwidget(edit=self._root_widget,
                           start_button=btn,
                           on_cancel_call=btn.activate)

        self._scroll_width = self._width - (100 + 2 * x_inset)
        self._scroll_height = self._height - 110
        self._sub_width = self._scroll_width - 20
        self._sub_height = (940 if self._parent_window.get_is_secondary() else
                            1040)
        if app.vr_mode:
            self._sub_height += 50
        self._scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            position=((self._width - self._scroll_width) * 0.5,
                      self._height - 65 - self._scroll_height),
            size=(self._scroll_width, self._scroll_height),
            claims_left_right=True,
            claims_tab=True,
            selection_loops_to_parent=True)
        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
                                                size=(self._sub_width,
                                                      self._sub_height),
                                                background=False,
                                                claims_left_right=True,
                                                claims_tab=True,
                                                selection_loops_to_parent=True)
        ba.containerwidget(edit=self._root_widget,
                           selected_child=self._scrollwidget)

        h = 30
        v = self._sub_height - 10

        h2 = h + 12

        # don't allow secondary joysticks to handle unassigned buttons
        if not self._parent_window.get_is_secondary():
            v -= 40
            cb1 = ba.checkboxwidget(
                parent=self._subcontainer,
                position=(h + 70, v),
                size=(500, 30),
                text=ba.Lstr(resource=self._r + '.unassignedButtonsRunText'),
                textcolor=(0.8, 0.8, 0.8),
                maxwidth=330,
                scale=1.0,
                on_value_change_call=self._parent_window.
                set_unassigned_buttons_run_value,
                autoselect=True,
                value=self._parent_window.get_unassigned_buttons_run_value())
            ba.widget(edit=cb1, up_widget=back_button)
        v -= 60
        capb = self._capture_button(
            pos=(h2, v),
            name=ba.Lstr(resource=self._r + '.runButton1Text'),
            control='buttonRun1' + self._parent_window.get_ext())
        if self._parent_window.get_is_secondary():
            for widget in capb:
                ba.widget(edit=widget, up_widget=back_button)
        v -= 42
        self._capture_button(
            pos=(h2, v),
            name=ba.Lstr(resource=self._r + '.runButton2Text'),
            control='buttonRun2' + self._parent_window.get_ext())
        ba.textwidget(parent=self._subcontainer,
                      position=(self._sub_width * 0.5, v - 24),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r +
                                   '.runTriggerDescriptionText'),
                      color=(0.7, 1, 0.7, 0.6),
                      maxwidth=self._sub_width * 0.8,
                      scale=0.7,
                      h_align='center',
                      v_align='center')

        v -= 85

        self._capture_button(
            pos=(h2, v),
            name=ba.Lstr(resource=self._r + '.runTrigger1Text'),
            control='triggerRun1' + self._parent_window.get_ext(),
            message=ba.Lstr(resource=self._r + '.pressAnyAnalogTriggerText'))
        v -= 42
        self._capture_button(
            pos=(h2, v),
            name=ba.Lstr(resource=self._r + '.runTrigger2Text'),
            control='triggerRun2' + self._parent_window.get_ext(),
            message=ba.Lstr(resource=self._r + '.pressAnyAnalogTriggerText'))

        # in vr mode, allow assigning a reset-view button
        if app.vr_mode:
            v -= 50
            self._capture_button(
                pos=(h2, v),
                name=ba.Lstr(resource=self._r + '.vrReorientButtonText'),
                control='buttonVRReorient' + self._parent_window.get_ext())

        v -= 60
        self._capture_button(
            pos=(h2, v),
            name=ba.Lstr(resource=self._r + '.extraStartButtonText'),
            control='buttonStart2' + self._parent_window.get_ext())
        v -= 60
        self._capture_button(
            pos=(h2, v),
            name=ba.Lstr(resource=self._r + '.ignoredButton1Text'),
            control='buttonIgnored' + self._parent_window.get_ext())
        v -= 42
        self._capture_button(
            pos=(h2, v),
            name=ba.Lstr(resource=self._r + '.ignoredButton2Text'),
            control='buttonIgnored2' + self._parent_window.get_ext())
        v -= 42
        self._capture_button(
            pos=(h2, v),
            name=ba.Lstr(resource=self._r + '.ignoredButton3Text'),
            control='buttonIgnored3' + self._parent_window.get_ext())
        v -= 42
        self._capture_button(
            pos=(h2, v),
            name=ba.Lstr(resource=self._r + '.ignoredButton4Text'),
            control='buttonIgnored4' + self._parent_window.get_ext())
        ba.textwidget(parent=self._subcontainer,
                      position=(self._sub_width * 0.5, v - 14),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r +
                                   '.ignoredButtonDescriptionText'),
                      color=(0.7, 1, 0.7, 0.6),
                      scale=0.8,
                      maxwidth=self._sub_width * 0.8,
                      h_align='center',
                      v_align='center')

        v -= 80
        ba.checkboxwidget(parent=self._subcontainer,
                          autoselect=True,
                          position=(h + 50, v),
                          size=(400, 30),
                          text=ba.Lstr(resource=self._r +
                                       '.startButtonActivatesDefaultText'),
                          textcolor=(0.8, 0.8, 0.8),
                          maxwidth=450,
                          scale=0.9,
                          on_value_change_call=self._parent_window.
                          set_start_button_activates_default_widget_value,
                          value=self._parent_window.
                          get_start_button_activates_default_widget_value())
        ba.textwidget(
            parent=self._subcontainer,
            position=(self._sub_width * 0.5, v - 12),
            size=(0, 0),
            text=ba.Lstr(resource=self._r +
                         '.startButtonActivatesDefaultDescriptionText'),
            color=(0.7, 1, 0.7, 0.6),
            maxwidth=self._sub_width * 0.8,
            scale=0.7,
            h_align='center',
            v_align='center')

        v -= 80
        ba.checkboxwidget(
            parent=self._subcontainer,
            autoselect=True,
            position=(h + 50, v),
            size=(400, 30),
            text=ba.Lstr(resource=self._r + '.uiOnlyText'),
            textcolor=(0.8, 0.8, 0.8),
            maxwidth=450,
            scale=0.9,
            on_value_change_call=self._parent_window.set_ui_only_value,
            value=self._parent_window.get_ui_only_value())
        ba.textwidget(parent=self._subcontainer,
                      position=(self._sub_width * 0.5, v - 12),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r +
                                   '.uiOnlyDescriptionText'),
                      color=(0.7, 1, 0.7, 0.6),
                      maxwidth=self._sub_width * 0.8,
                      scale=0.7,
                      h_align='center',
                      v_align='center')

        v -= 80
        ba.checkboxwidget(
            parent=self._subcontainer,
            autoselect=True,
            position=(h + 50, v),
            size=(400, 30),
            text=ba.Lstr(resource=self._r + '.ignoreCompletelyText'),
            textcolor=(0.8, 0.8, 0.8),
            maxwidth=450,
            scale=0.9,
            on_value_change_call=self._parent_window.
            set_ignore_completely_value,
            value=self._parent_window.get_ignore_completely_value())
        ba.textwidget(parent=self._subcontainer,
                      position=(self._sub_width * 0.5, v - 12),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r +
                                   '.ignoreCompletelyDescriptionText'),
                      color=(0.7, 1, 0.7, 0.6),
                      maxwidth=self._sub_width * 0.8,
                      scale=0.7,
                      h_align='center',
                      v_align='center')

        v -= 80

        cb1 = ba.checkboxwidget(
            parent=self._subcontainer,
            autoselect=True,
            position=(h + 50, v),
            size=(400, 30),
            text=ba.Lstr(resource=self._r + '.autoRecalibrateText'),
            textcolor=(0.8, 0.8, 0.8),
            maxwidth=450,
            scale=0.9,
            on_value_change_call=self._parent_window.
            set_auto_recalibrate_analog_stick_value,
            value=self._parent_window.get_auto_recalibrate_analog_stick_value(
            ))
        ba.textwidget(parent=self._subcontainer,
                      position=(self._sub_width * 0.5, v - 12),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r +
                                   '.autoRecalibrateDescriptionText'),
                      color=(0.7, 1, 0.7, 0.6),
                      maxwidth=self._sub_width * 0.8,
                      scale=0.7,
                      h_align='center',
                      v_align='center')
        v -= 80

        buttons = self._config_value_editor(
            ba.Lstr(resource=self._r + '.analogStickDeadZoneText'),
            control=('analogStickDeadZone' + self._parent_window.get_ext()),
            position=(h + 40, v),
            min_val=0,
            max_val=10.0,
            increment=0.1,
            x_offset=100)
        ba.widget(edit=buttons[0], left_widget=cb1, up_widget=cb1)
        ba.widget(edit=cb1, right_widget=buttons[0], down_widget=buttons[0])

        ba.textwidget(parent=self._subcontainer,
                      position=(self._sub_width * 0.5, v - 12),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r +
                                   '.analogStickDeadZoneDescriptionText'),
                      color=(0.7, 1, 0.7, 0.6),
                      maxwidth=self._sub_width * 0.8,
                      scale=0.7,
                      h_align='center',
                      v_align='center')
        v -= 100

        # child joysticks cant have child joysticks.. that's just
        # crazy talk
        if not self._parent_window.get_is_secondary():
            ba.buttonwidget(
                parent=self._subcontainer,
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.twoInOneSetupText'),
                position=(40, v),
                size=(self._sub_width - 80, 50),
                on_activate_call=self._parent_window.show_secondary_editor,
                up_widget=buttons[0])

        # set a bigger bottom show-buffer for the widgets we just made
        # so we can see the text below them when navigating with
        # a gamepad
        for child in self._subcontainer.get_children():
            ba.widget(edit=child, show_buffer_bottom=30, show_buffer_top=30)
Esempio n. 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.getinputdevice('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()
Esempio n. 11
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.modutils import show_user_scripts

        available_languages = ba.app.lang.available_languages

        # 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 == available_languages):
            return
        self._prev_lang = _ba.app.config.get('Lang', None)
        self._prev_lang_list = available_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.ui.title_color,
                      h_align='right',
                      v_align='center')

        languages = _ba.app.lang.available_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',
                      encoding='utf-8') 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.lang.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, 'https://legacy.ballistica.net/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_v1_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)

        v -= 42
        self._disable_camera_shake_check_box = ConfigCheckBox(
            parent=self._subcontainer,
            position=(50, v),
            size=(self._sub_width - 100, 30),
            configkey='Disable Camera Shake',
            displayname=ba.Lstr(resource=self._r + '.disableCameraShakeText'),
            scale=1.0,
            maxwidth=430)

        self._disable_gyro_check_box: Optional[ConfigCheckBox] = None
        if self._show_disable_gyro:
            v -= 42
            self._disable_gyro_check_box = ConfigCheckBox(
                parent=self._subcontainer,
                position=(50, v),
                size=(self._sub_width - 100, 30),
                configkey='Disable Camera Gyro',
                displayname=ba.Lstr(resource=self._r +
                                    '.disableCameraGyroscopeMotionText'),
                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

        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 * 2.0

        self._plugins_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='pluginsText'),
            text_scale=1.0,
            on_activate_call=self._on_plugins_button_press)

        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)

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

        if ba.app.ui.use_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()
Esempio n. 12
0
 def _radio_press(check_string: str, other_check_boxes: List[ba.Widget],
                  val: int) -> None:
     if val == 1:
         value_change_call(check_string)
         for cbx in other_check_boxes:
             ba.checkboxwidget(edit=cbx, value=False)
Esempio n. 13
0
    def _build_gui(self) -> None:
        from bastd.ui import config as cfgui
        from bastd.ui import radiogroup
        # clear anything already there
        children = self._subcontainer.get_children()
        for child in children:
            child.delete()
        h = 30
        v = self._sub_height - 85
        clr = (0.8, 0.8, 0.8, 1.0)
        clr2 = (0.8, 0.8, 0.8)
        ba.textwidget(parent=self._subcontainer,
                      position=(-10, v + 43),
                      size=(self._sub_width, 25),
                      text=ba.Lstr(resource=self._r + '.swipeInfoText'),
                      flatness=1.0,
                      color=(0, 0.9, 0.1, 0.7),
                      maxwidth=self._sub_width * 0.9,
                      scale=0.55,
                      h_align='center',
                      v_align='center')
        cur_val = ba.app.config.get('Touch Movement Control Type', 'swipe')
        ba.textwidget(parent=self._subcontainer,
                      position=(h, v - 2),
                      size=(0, 30),
                      text=ba.Lstr(resource=self._r + '.movementText'),
                      maxwidth=190,
                      color=clr,
                      v_align='center')
        cb1 = ba.checkboxwidget(parent=self._subcontainer,
                                position=(h + 220, v),
                                size=(170, 30),
                                text=ba.Lstr(resource=self._r +
                                             '.joystickText'),
                                maxwidth=100,
                                textcolor=clr2,
                                scale=0.9)
        cb2 = ba.checkboxwidget(parent=self._subcontainer,
                                position=(h + 357, v),
                                size=(170, 30),
                                text=ba.Lstr(resource=self._r + '.swipeText'),
                                maxwidth=100,
                                textcolor=clr2,
                                value=False,
                                scale=0.9)
        radiogroup.make_radio_group((cb1, cb2), ('joystick', 'swipe'), cur_val,
                                    self._movement_changed)
        v -= 50
        cfgui.ConfigNumberEdit(
            parent=self._subcontainer,
            position=(h, v),
            xoffset=65,
            configkey='Touch Controls Scale Movement',
            displayname=ba.Lstr(resource=self._r +
                                '.movementControlScaleText'),
            changesound=False,
            minval=0.1,
            maxval=4.0,
            increment=0.1)
        v -= 50
        cur_val = ba.app.config.get('Touch Action Control Type', 'buttons')
        ba.textwidget(parent=self._subcontainer,
                      position=(h, v - 2),
                      size=(0, 30),
                      text=ba.Lstr(resource=self._r + '.actionsText'),
                      maxwidth=190,
                      color=clr,
                      v_align='center')
        cb1 = ba.checkboxwidget(parent=self._subcontainer,
                                position=(h + 220, v),
                                size=(170, 30),
                                text=ba.Lstr(resource=self._r +
                                             '.buttonsText'),
                                maxwidth=100,
                                textcolor=clr2,
                                scale=0.9)
        cb2 = ba.checkboxwidget(parent=self._subcontainer,
                                position=(h + 357, v),
                                size=(170, 30),
                                text=ba.Lstr(resource=self._r + '.swipeText'),
                                maxwidth=100,
                                textcolor=clr2,
                                scale=0.9)
        radiogroup.make_radio_group((cb1, cb2), ('buttons', 'swipe'), cur_val,
                                    self._actions_changed)
        v -= 50
        cfgui.ConfigNumberEdit(parent=self._subcontainer,
                               position=(h, v),
                               xoffset=65,
                               configkey='Touch Controls Scale Actions',
                               displayname=ba.Lstr(resource=self._r +
                                                   '.actionControlScaleText'),
                               changesound=False,
                               minval=0.1,
                               maxval=4.0,
                               increment=0.1)

        v -= 50
        cfgui.ConfigCheckBox(parent=self._subcontainer,
                             position=(h, v),
                             size=(400, 30),
                             maxwidth=400,
                             configkey='Touch Controls Swipe Hidden',
                             displayname=ba.Lstr(resource=self._r +
                                                 '.swipeControlsHiddenText'))
        v -= 65

        ba.buttonwidget(parent=self._subcontainer,
                        position=(self._sub_width * 0.5 - 70, v),
                        size=(170, 60),
                        label=ba.Lstr(resource=self._r + '.resetText'),
                        scale=0.75,
                        on_activate_call=self._reset)

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, 38),
                      size=(0, 0),
                      h_align='center',
                      text=ba.Lstr(resource=self._r + '.dragControlsText'),
                      maxwidth=self._width * 0.8,
                      scale=0.65,
                      color=(1, 1, 1, 0.4))
    def _update_internet_tab(self) -> None:
        global searchText, textModified

        def updatepartylist():
            self._internet_join_last_refresh_time = now
            self._first_public_party_list_rebuild_time = ba.time(
                ba.TimeType.REAL) + 1
            app = ba.app
            _ba.add_transaction(
                {
                    'type': 'PUBLIC_PARTY_QUERY',
                    'proto': app.protocol_version,
                    'lang': app.language
                },
                callback=ba.WeakCall(self._on_public_party_query_result))
            _ba.run_transactions()

        def checkBox(val):
            global checkBoxBool
            checkBoxBool = bool(val)
            updatepartylist()

        if not searchText:
            widgetInstalled = True
            c_width = self._scroll_width
            c_height = self._scroll_height - 20
            v = c_height - 30

            searchText = txt = ba.textwidget(
                parent=self._tab_container,
                position=(c_width * 0.5 + 250, v + 105),
                color=ba.app.ui.title_color,
                scale=1.3,
                size=(150, 30),
                maxwidth=145,
                h_align='left',
                v_align='center',
                click_activate=True,
                selectable=True,
                autoselect=True,
                on_activate_call=lambda: self._set_internet_tab(
                    'host', playsound=True),
                editable=True,
                text='')
            ba.textwidget(parent=self._tab_container,
                          position=(c_width * 0.5 + 125, v + 122),
                          color=ba.app.ui.title_color,
                          scale=1.1,
                          size=(0, 0),
                          h_align='left',
                          v_align='center',
                          on_activate_call=lambda: self._set_internet_tab(
                              'host', playsound=True),
                          text='Search:')
            ba.checkboxwidget(parent=self._tab_container,
                              text="Case-Sensitive",
                              position=(c_width * 0.5 + 125, v + 135),
                              color=ba.app.ui.title_color,
                              textcolor=ba.app.ui.title_color,
                              size=(50, 50),
                              scale=1,
                              value=False,
                              on_value_change_call=checkBox)

        # pylint: disable=too-many-statements

        # Special case: if a party-queue window is up, don't do any of this
        # (keeps things smoother).
        if ba.app.ui.have_party_queue_window:
            return
        # If we've got a party-name text widget, keep its value plugged
        # into our public host name.
        text = self._internet_host_name_text
        if text:
            name = cast(str,
                        ba.textwidget(query=self._internet_host_name_text))
            _ba.set_public_party_name(name)

        # Show/hide the lock icon depending on if we've got pro.
        icon = self._internet_lock_icon
        if icon:
            if self._is_internet_locked():
                ba.imagewidget(edit=icon, opacity=0.5)
            else:
                ba.imagewidget(edit=icon, opacity=0.0)

        if self._internet_tab == 'join':
            now = ba.time(ba.TimeType.REAL)
            if (now - self._internet_join_last_refresh_time > 0.001 *
                    _ba.get_account_misc_read_val('pubPartyRefreshMS', 10000)):
                updatepartylist()
            search_text = cast(str, ba.textwidget(query=searchText))

            if search_text != '':

                textModified = True
                x = []
                if not checkBoxBool:
                    search_text = search_text.lower()
                    for i in self._public_parties:
                        if not search_text in self._public_parties[i][
                                'name'].lower():
                            x.append(i)
                else:
                    for i in self._public_parties:
                        if not search_text in self._public_parties[i]['name']:
                            x.append(i)

                for i in x:
                    del self._public_parties[i]
                self._first_public_party_list_rebuild_time = ba.time(
                    ba.TimeType.REAL) + 1
                self._rebuild_public_party_list()

            else:
                if textModified:
                    updatepartylist()

                    textModified = False
            # Go through our existing public party entries firing off pings
            # for any that have timed out.
            for party in list(self._public_parties.values()):
                if (party['next_ping_time'] <= now
                        and ba.app.ping_thread_count < 15):

                    # Make sure to fully catch up and not to multi-ping if
                    # we're way behind somehow.
                    while party['next_ping_time'] <= now:
                        # Crank the interval up for high-latency parties to
                        # save us some work.
                        mult = 1
                        if party['ping'] is not None:
                            mult = (10 if party['ping'] > 300 else
                                    5 if party['ping'] > 150 else 2)
                        party[
                            'next_ping_time'] += party['ping_interval'] * mult

                    class PingThread(threading.Thread):
                        """Thread for sending out pings."""
                        def __init__(self, address: str, port: int,
                                     call: Callable[[str, int, Optional[int]],
                                                    Optional[int]]):
                            super().__init__()
                            self._address = address
                            self._port = port
                            self._call = call

                        def run(self) -> None:
                            # pylint: disable=too-many-branches
                            ba.app.ping_thread_count += 1
                            try:
                                import socket
                                from ba.internal import get_ip_address_type
                                socket_type = get_ip_address_type(
                                    self._address)
                                sock = socket.socket(socket_type,
                                                     socket.SOCK_DGRAM)
                                sock.connect((self._address, self._port))

                                accessible = False
                                starttime = time.time()

                                # Send a few pings and wait a second for
                                # a response.
                                sock.settimeout(1)
                                for _i in range(3):
                                    sock.send(b'\x0b')
                                    result: Optional[bytes]
                                    try:
                                        # 11: BA_PACKET_SIMPLE_PING
                                        result = sock.recv(10)
                                    except Exception:
                                        result = None
                                    if result == b'\x0c':
                                        # 12: BA_PACKET_SIMPLE_PONG
                                        accessible = True
                                        break
                                    time.sleep(1)
                                sock.close()
                                ping = int((time.time() - starttime) * 1000.0)
                                ba.pushcall(ba.Call(
                                    self._call, self._address, self._port,
                                    ping if accessible else None),
                                            from_other_thread=True)
                            except ConnectionRefusedError:
                                # Fine, server; sorry we pinged you. Hmph.
                                pass
                            except OSError as exc:
                                import errno

                                # Ignore harmless errors.
                                if exc.errno in {
                                        errno.EHOSTUNREACH,
                                        errno.ENETUNREACH,
                                }:
                                    pass
                                elif exc.errno == 10022:
                                    # Windows 'invalid argument' error.
                                    pass
                                elif exc.errno == 10051:
                                    # Windows 'a socket operation was attempted
                                    # to an unreachable network' error.
                                    pass
                                elif exc.errno == errno.EADDRNOTAVAIL:
                                    if self._port == 0:
                                        # This has happened. Ignore.
                                        pass
                                    elif ba.do_once():
                                        print(
                                            f'Got EADDRNOTAVAIL on gather ping'
                                            f' for addr {self._address}'
                                            f' port {self._port}.')
                                else:
                                    ba.print_exception(
                                        f'Error on gather ping '
                                        f'(errno={exc.errno})',
                                        once=True)
                            except Exception:
                                ba.print_exception('Error on gather ping',
                                                   once=True)
                            ba.app.ping_thread_count -= 1

                    PingThread(party['address'], party['port'],
                               ba.WeakCall(self._ping_callback)).start()