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

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

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

        v = self._sub_height - 35

        v -= self._spacing * 1.2

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

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

        this_button_width = 410

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

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

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

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

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

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

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

        v -= self._spacing * 1.8

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

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

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

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

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

        v -= self._spacing * 3.0

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

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

        v -= self._spacing * 2.1

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

        v -= self._spacing * 2.0

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

        v -= self._spacing * 1.8

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

        v -= self._spacing * 0.6

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

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

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

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

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

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

        self._restore_state()
Esempio n. 2
0
    def __init__(self,
                 sessiontype: Type[ba.Session],
                 transition: Optional[str] = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=cyclic-import
        from bastd.ui.playlist import PlaylistTypeVars

        # 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

        # Store state for when we exit the next game.
        if issubclass(sessiontype, ba.DualTeamSession):
            ba.app.main_window = 'Team Game Select'
            ba.set_analytics_screen('Teams Window')
        elif issubclass(sessiontype, ba.FreeForAllSession):
            ba.app.main_window = 'Free-for-All Game Select'
            ba.set_analytics_screen('FreeForAll Window')
        else:
            raise TypeError(f'Invalid sessiontype: {sessiontype}.')
        self._pvars = PlaylistTypeVars(sessiontype)

        self._sessiontype = sessiontype

        self._customize_button: Optional[ba.Widget] = None
        self._sub_width: Optional[float] = None
        self._sub_height: Optional[float] = None

        # On new installations, go ahead and create a few playlists
        # besides the hard-coded default one:
        if not _ba.get_account_misc_val('madeStandardPlaylists', False):
            _ba.add_transaction({
                'type':
                'ADD_PLAYLIST',
                'playlistType':
                'Free-for-All',
                'playlistName':
                ba.Lstr(
                    resource='singleGamePlaylistNameText').evaluate().replace(
                        '${GAME}',
                        ba.Lstr(translate=('gameNames',
                                           'Death Match')).evaluate()),
                'playlist': [
                    {
                        'type': 'bs_death_match.DeathMatchGame',
                        'settings': {
                            'Epic Mode': False,
                            'Kills to Win Per Player': 10,
                            'Respawn Times': 1.0,
                            'Time Limit': 300,
                            'map': 'Doom Shroom'
                        }
                    },
                    {
                        'type': 'bs_death_match.DeathMatchGame',
                        'settings': {
                            'Epic Mode': False,
                            'Kills to Win Per Player': 10,
                            'Respawn Times': 1.0,
                            'Time Limit': 300,
                            'map': 'Crag Castle'
                        }
                    },
                ]
            })
            _ba.add_transaction({
                'type':
                'ADD_PLAYLIST',
                'playlistType':
                'Team Tournament',
                'playlistName':
                ba.Lstr(
                    resource='singleGamePlaylistNameText').evaluate().replace(
                        '${GAME}',
                        ba.Lstr(translate=('gameNames',
                                           'Capture the Flag')).evaluate()),
                'playlist': [
                    {
                        'type': 'bs_capture_the_flag.CTFGame',
                        'settings': {
                            'map': 'Bridgit',
                            'Score to Win': 3,
                            'Flag Idle Return Time': 30,
                            'Flag Touch Return Time': 0,
                            'Respawn Times': 1.0,
                            'Time Limit': 600,
                            'Epic Mode': False
                        }
                    },
                    {
                        'type': 'bs_capture_the_flag.CTFGame',
                        'settings': {
                            'map': 'Roundabout',
                            'Score to Win': 2,
                            'Flag Idle Return Time': 30,
                            'Flag Touch Return Time': 0,
                            'Respawn Times': 1.0,
                            'Time Limit': 600,
                            'Epic Mode': False
                        }
                    },
                    {
                        'type': 'bs_capture_the_flag.CTFGame',
                        'settings': {
                            'map': 'Tip Top',
                            'Score to Win': 2,
                            'Flag Idle Return Time': 30,
                            'Flag Touch Return Time': 3,
                            'Respawn Times': 1.0,
                            'Time Limit': 300,
                            'Epic Mode': False
                        }
                    },
                ]
            })
            _ba.add_transaction({
                'type':
                'ADD_PLAYLIST',
                'playlistType':
                'Team Tournament',
                'playlistName':
                ba.Lstr(translate=('playlistNames', 'Just Sports')).evaluate(),
                'playlist': [
                    {
                        'type': 'bs_hockey.HockeyGame',
                        'settings': {
                            'Time Limit': 0,
                            'map': 'Hockey Stadium',
                            'Score to Win': 1,
                            'Respawn Times': 1.0
                        }
                    },
                    {
                        'type': 'bs_football.FootballTeamGame',
                        'settings': {
                            'Time Limit': 0,
                            'map': 'Football Stadium',
                            'Score to Win': 21,
                            'Respawn Times': 1.0
                        }
                    },
                ]
            })
            _ba.add_transaction({
                'type':
                'ADD_PLAYLIST',
                'playlistType':
                'Free-for-All',
                'playlistName':
                ba.Lstr(translate=('playlistNames', 'Just Epic')).evaluate(),
                'playlist': [{
                    'type': 'bs_elimination.EliminationGame',
                    'settings': {
                        'Time Limit': 120,
                        'map': 'Tip Top',
                        'Respawn Times': 1.0,
                        'Lives Per Player': 1,
                        'Epic Mode': 1
                    }
                }]
            })
            _ba.add_transaction({
                'type': 'SET_MISC_VAL',
                'name': 'madeStandardPlaylists',
                'value': True
            })
            _ba.run_transactions()

        # Get the current selection (if any).
        self._selected_playlist = ba.app.config.get(self._pvars.config_name +
                                                    ' Playlist Selection')

        uiscale = ba.app.uiscale
        self._width = 900 if uiscale is ba.UIScale.SMALL else 800
        x_inset = 50 if uiscale is ba.UIScale.SMALL else 0
        self._height = (480 if uiscale is ba.UIScale.SMALL else
                        510 if uiscale is ba.UIScale.MEDIUM else 580)

        top_extra = 20 if uiscale is ba.UIScale.SMALL else 0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            toolbar_visibility='menu_full',
            scale_origin_stack_offset=scale_origin,
            scale=(1.69 if uiscale is ba.UIScale.SMALL else
                   1.05 if uiscale is ba.UIScale.MEDIUM else 0.9),
            stack_offset=(0, -26) if uiscale is ba.UIScale.SMALL else (0, 0)))

        self._back_button: Optional[ba.Widget] = ba.buttonwidget(
            parent=self._root_widget,
            position=(59 + x_inset, self._height - 70),
            size=(120, 60),
            scale=1.0,
            on_activate_call=self._on_back_press,
            autoselect=True,
            label=ba.Lstr(resource='backText'),
            button_type='back')
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._back_button)
        txt = self._title_text = ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height - 41),
            size=(0, 0),
            text=self._pvars.window_title_name,
            scale=1.3,
            res_scale=1.5,
            color=ba.app.heading_color,
            h_align='center',
            v_align='center')
        if uiscale is ba.UIScale.SMALL and ba.app.toolbars:
            ba.textwidget(edit=txt, text='')

        ba.buttonwidget(edit=self._back_button,
                        button_type='backSmall',
                        size=(60, 54),
                        position=(59 + x_inset, self._height - 67),
                        label=ba.charstr(ba.SpecialChar.BACK))

        if uiscale is ba.UIScale.SMALL and ba.app.toolbars:
            self._back_button.delete()
            self._back_button = None
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._on_back_press)
            scroll_offs = 33
        else:
            scroll_offs = 0
        self._scroll_width = self._width - (100 + 2 * x_inset)
        self._scroll_height = self._height - (
            146 if uiscale is ba.UIScale.SMALL and ba.app.toolbars else 136)
        self._scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            highlight=False,
            size=(self._scroll_width, self._scroll_height),
            position=((self._width - self._scroll_width) * 0.5,
                      65 + scroll_offs))
        ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
        self._subcontainer: Optional[ba.Widget] = None
        self._config_name_full = self._pvars.config_name + ' Playlists'
        self._last_config = None

        # Update now and once per second.
        # (this should do our initial refresh)
        self._update()
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
Esempio n. 3
0
 def _ensure_standard_playlists_exist(self) -> None:
     # On new installations, go ahead and create a few playlists
     # besides the hard-coded default one:
     if not _ba.get_account_misc_val('madeStandardPlaylists', False):
         _ba.add_transaction({
             'type':
             'ADD_PLAYLIST',
             'playlistType':
             'Free-for-All',
             'playlistName':
             ba.Lstr(
                 resource='singleGamePlaylistNameText').evaluate().replace(
                     '${GAME}',
                     ba.Lstr(translate=('gameNames',
                                        'Death Match')).evaluate()),
             'playlist': [
                 {
                     'type': 'bs_death_match.DeathMatchGame',
                     'settings': {
                         'Epic Mode': False,
                         'Kills to Win Per Player': 10,
                         'Respawn Times': 1.0,
                         'Time Limit': 300,
                         'map': 'Doom Shroom'
                     }
                 },
                 {
                     'type': 'bs_death_match.DeathMatchGame',
                     'settings': {
                         'Epic Mode': False,
                         'Kills to Win Per Player': 10,
                         'Respawn Times': 1.0,
                         'Time Limit': 300,
                         'map': 'Crag Castle'
                     }
                 },
             ]
         })
         _ba.add_transaction({
             'type':
             'ADD_PLAYLIST',
             'playlistType':
             'Team Tournament',
             'playlistName':
             ba.Lstr(
                 resource='singleGamePlaylistNameText').evaluate().replace(
                     '${GAME}',
                     ba.Lstr(translate=('gameNames',
                                        'Capture the Flag')).evaluate()),
             'playlist': [
                 {
                     'type': 'bs_capture_the_flag.CTFGame',
                     'settings': {
                         'map': 'Bridgit',
                         'Score to Win': 3,
                         'Flag Idle Return Time': 30,
                         'Flag Touch Return Time': 0,
                         'Respawn Times': 1.0,
                         'Time Limit': 600,
                         'Epic Mode': False
                     }
                 },
                 {
                     'type': 'bs_capture_the_flag.CTFGame',
                     'settings': {
                         'map': 'Roundabout',
                         'Score to Win': 2,
                         'Flag Idle Return Time': 30,
                         'Flag Touch Return Time': 0,
                         'Respawn Times': 1.0,
                         'Time Limit': 600,
                         'Epic Mode': False
                     }
                 },
                 {
                     'type': 'bs_capture_the_flag.CTFGame',
                     'settings': {
                         'map': 'Tip Top',
                         'Score to Win': 2,
                         'Flag Idle Return Time': 30,
                         'Flag Touch Return Time': 3,
                         'Respawn Times': 1.0,
                         'Time Limit': 300,
                         'Epic Mode': False
                     }
                 },
             ]
         })
         _ba.add_transaction({
             'type':
             'ADD_PLAYLIST',
             'playlistType':
             'Team Tournament',
             'playlistName':
             ba.Lstr(translate=('playlistNames', 'Just Sports')).evaluate(),
             'playlist': [
                 {
                     'type': 'bs_hockey.HockeyGame',
                     'settings': {
                         'Time Limit': 0,
                         'map': 'Hockey Stadium',
                         'Score to Win': 1,
                         'Respawn Times': 1.0
                     }
                 },
                 {
                     'type': 'bs_football.FootballTeamGame',
                     'settings': {
                         'Time Limit': 0,
                         'map': 'Football Stadium',
                         'Score to Win': 21,
                         'Respawn Times': 1.0
                     }
                 },
             ]
         })
         _ba.add_transaction({
             'type':
             'ADD_PLAYLIST',
             'playlistType':
             'Free-for-All',
             'playlistName':
             ba.Lstr(translate=('playlistNames', 'Just Epic')).evaluate(),
             'playlist': [{
                 'type': 'bs_elimination.EliminationGame',
                 'settings': {
                     'Time Limit': 120,
                     'map': 'Tip Top',
                     'Respawn Times': 1.0,
                     'Lives Per Player': 1,
                     'Epic Mode': 1
                 }
             }]
         })
         _ba.add_transaction({
             'type': 'SET_MISC_VAL',
             'name': 'madeStandardPlaylists',
             'value': True
         })
         _ba.run_transactions()