Example #1
0
def uicleanupcheck(obj: Any, widget: ba.Widget) -> None:
    """Add a check to ensure a widget-owning object gets cleaned up properly.

    Category: User Interface Functions

    This adds a check which will print an error message if the provided
    object still exists ~5 seconds after the provided ba.Widget dies.

    This is a good sanity check for any sort of object that wraps or
    controls a ba.Widget. For instance, a 'Window' class instance has
    no reason to still exist once its root container ba.Widget has fully
    transitioned out and been destroyed. Circular references or careless
    strong referencing can lead to such objects never getting destroyed,
    however, and this helps detect such cases to avoid memory leaks.
    """
    if DEBUG_UI_CLEANUP_CHECKS:
        print(f'adding uicleanup to {obj}')
    if not isinstance(widget, _ba.Widget):
        raise TypeError('widget arg is not a ba.Widget')

    if bool(False):

        def foobar() -> None:
            """Just testing."""
            if DEBUG_UI_CLEANUP_CHECKS:
                print('uicleanupcheck widget dying...')

        widget.add_delete_callback(foobar)

    _ba.app.ui.cleanupchecks.append(
        UICleanupCheck(obj=weakref.ref(obj),
                       widget=widget,
                       widget_death_time=None))
Example #2
0
    def __init__(self, origin_widget: ba.Widget, qr_tex: ba.Texture):

        position = origin_widget.get_screen_space_center()
        uiscale = ba.app.uiscale
        scale = (2.3 if uiscale is ba.UIScale.SMALL else
                 1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
        self._transitioning_out = False
        self._width = 450
        self._height = 400
        bg_color = (0.5, 0.4, 0.6)
        popup.PopupWindow.__init__(self,
                                   position=position,
                                   size=(self._width, self._height),
                                   scale=scale,
                                   bg_color=bg_color)
        self._cancel_button = ba.buttonwidget(
            parent=self.root_widget,
            position=(50, self._height - 30),
            size=(50, 50),
            scale=0.5,
            label='',
            color=bg_color,
            on_activate_call=self._on_cancel_press,
            autoselect=True,
            icon=ba.gettexture('crossOut'),
            iconscale=1.2)
        ba.imagewidget(parent=self.root_widget,
                       position=(self._width * 0.5 - 150,
                                 self._height * 0.5 - 150),
                       size=(300, 300),
                       texture=qr_tex)
Example #3
0
 def _show_account_info(self, account_id: str,
                        textwidget: ba.Widget) -> None:
     from bastd.ui.account import viewer
     ba.playsound(ba.getsound('swish'))
     viewer.AccountViewerWindow(
         account_id=account_id,
         position=textwidget.get_screen_space_center())
Example #4
0
 def __init__(self, origin_widget: ba.Widget):
     uiscale = ba.app.ui.uiscale
     scale = (2.3 if uiscale is ba.UIScale.SMALL else
              1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
     self._transitioning_out = False
     self._width = 570
     self._height = 350
     bg_color = (0.5, 0.4, 0.6)
     popup.PopupWindow.__init__(
         self,
         size=(self._width, self._height),
         toolbar_visibility='inherit',
         scale=scale,
         bg_color=bg_color,
         position=origin_widget.get_screen_space_center())
     self._cancel_button = ba.buttonwidget(
         parent=self.root_widget,
         position=(50, self._height - 30),
         size=(50, 50),
         scale=0.5,
         label='',
         color=bg_color,
         on_activate_call=self._on_cancel_press,
         autoselect=True,
         icon=ba.gettexture('crossOut'),
         iconscale=1.2)
Example #5
0
 def on_account_press(self, account_id: Optional[str],
                      origin_widget: ba.Widget) -> None:
     """A dude was clicked so we should show his account info."""
     from bastd.ui.account import viewer
     if account_id is None:
         ba.playsound(ba.getsound('error'))
         return
     viewer.AccountViewerWindow(
         account_id=account_id,
         position=origin_widget.get_screen_space_center())
Example #6
0
 def _show_player_info(self, entry: Any, textwidget: ba.Widget) -> None:
     from bastd.ui.account.viewer import AccountViewerWindow
     # for the moment we only work if a single player-info is present..
     if len(entry[2]) != 1:
         ba.playsound(ba.getsound('error'))
         return
     ba.playsound(ba.getsound('swish'))
     AccountViewerWindow(account_id=entry[2][0].get('a', None),
                         profile_id=entry[2][0].get('p', None),
                         position=textwidget.get_screen_space_center())
     self._transition_out()
Example #7
0
    def __init__(self, account_id: str, origin_widget: ba.Widget):
        self._width = 550
        self._height = 220
        self._account_id = account_id
        self._transition_out = 'out_scale'
        scale_origin = origin_widget.get_screen_space_center()

        overlay_stack = _ba.get_special_widget('overlay_stack')
        uiscale = ba.app.ui.uiscale
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            parent=overlay_stack,
            transition='in_scale',
            scale_origin_stack_offset=scale_origin,
            scale=(1.8 if uiscale is ba.UIScale.SMALL else
                   1.35 if uiscale is ba.UIScale.MEDIUM else 1.0)))
        self._cancel_button = ba.buttonwidget(parent=self._root_widget,
                                              scale=0.7,
                                              position=(40, self._height - 50),
                                              size=(50, 50),
                                              label='',
                                              on_activate_call=self.close,
                                              autoselect=True,
                                              color=(0.4, 0.4, 0.5),
                                              icon=ba.gettexture('crossOut'),
                                              iconscale=1.2)
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._cancel_button)
        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height * 0.64),
                      size=(0, 0),
                      color=(1, 1, 1, 0.8),
                      scale=1.2,
                      h_align='center',
                      v_align='center',
                      text=ba.Lstr(resource='reportThisPlayerReasonText'),
                      maxwidth=self._width * 0.85)
        ba.buttonwidget(parent=self._root_widget,
                        size=(235, 60),
                        position=(20, 30),
                        label=ba.Lstr(resource='reportThisPlayerLanguageText'),
                        on_activate_call=self._on_language_press,
                        autoselect=True)
        ba.buttonwidget(parent=self._root_widget,
                        size=(235, 60),
                        position=(self._width - 255, 30),
                        label=ba.Lstr(resource='reportThisPlayerCheatingText'),
                        on_activate_call=self._on_cheating_press,
                        autoselect=True)
Example #8
0
    def _on_playlist_press(self, button: ba.Widget,
                           playlist_name: str) -> None:
        # pylint: disable=cyclic-import
        from bastd.ui.playoptions import PlayOptionsWindow

        # Make sure the target playlist still exists.
        exists = (playlist_name == '__default__'
                  or playlist_name in ba.app.config.get(
                      self._config_name_full, {}))
        if not exists:
            return

        self._save_state()
        PlayOptionsWindow(sessiontype=self._sessiontype,
                          scale_origin=button.get_screen_space_center(),
                          playlist=playlist_name,
                          delegate=self)
Example #9
0
 def _on_party_member_press(self, client_id: int, is_host: bool,
                            widget: ba.Widget) -> None:
     # if we're the host, pop up 'kick' options for all non-host members
     if _ba.get_foreground_host_session() is not None:
         kick_str = ba.Lstr(resource='kickText')
     else:
         # kick-votes appeared in build 14248
         if (_ba.get_connection_to_host_info().get('build_number', 0) <
                 14248):
             return
         kick_str = ba.Lstr(resource='kickVoteText')
     popup.PopupMenuWindow(
         position=widget.get_screen_space_center(),
         scale=2.3 if ba.app.small_ui else 1.65 if ba.app.med_ui else 1.23,
         choices=['kick'],
         choices_display=[kick_str],
         current_choice='kick',
         delegate=self)
     self._popup_type = 'partyMemberPress'
     self._popup_party_member_client_id = client_id
     self._popup_party_member_is_host = is_host
Example #10
0
    def __init__(self,
                 text: Union[str, ba.Lstr] = 'Are you sure?',
                 action: Callable[[], Any] = None,
                 width: float = 360.0,
                 height: float = 100.0,
                 cancel_button: bool = True,
                 cancel_is_selected: bool = False,
                 color: Tuple[float, float, float] = (1, 1, 1),
                 text_scale: float = 1.0,
                 ok_text: Union[str, ba.Lstr] = None,
                 cancel_text: Union[str, ba.Lstr] = None,
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        if ok_text is None:
            ok_text = ba.Lstr(resource='okText')
        if cancel_text is None:
            cancel_text = ba.Lstr(resource='cancelText')
        height += 40
        if width < 360:
            width = 360
        self._action = action

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

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

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

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

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

        ba.containerwidget(edit=self.root_widget,
                           selected_child=(cbtn if cbtn is not None
                                           and cancel_is_selected else btn),
                           start_button=btn)
Example #11
0
    def __init__(self,
                 transition: str = 'in_right',
                 modal: bool = False,
                 origin_widget: ba.Widget = None):
        from ba.internal import get_cached_league_rank_data
        from ba.deprecated import get_resource
        ba.set_analytics_screen('League Rank Window')

        self._league_rank_data: Optional[Dict[str, Any]] = None
        self._modal = modal

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

        self._width = 1320 if ba.app.small_ui else 1120
        x_inset = 100 if ba.app.small_ui else 0
        self._height = (657
                        if ba.app.small_ui else 710 if ba.app.med_ui else 800)
        self._r = 'coopSelectWindow'
        self._rdict = get_resource(self._r)
        top_extra = 20 if ba.app.small_ui else 0

        self._league_url_arg = ''

        self._is_current_season = False
        self._can_do_more_button = True

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            stack_offset=(0, -15) if ba.app.small_ui else (
                0, 10) if ba.app.med_ui else (0, 0),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            scale=(
                1.2 if ba.app.small_ui else 0.93 if ba.app.med_ui else 0.8)))

        self._back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(75 + x_inset,
                      self._height - 87 - (4 if ba.app.small_ui else 0)),
            size=(120, 60),
            scale=1.2,
            autoselect=True,
            label=ba.Lstr(resource='doneText' if self._modal else 'backText'),
            button_type=None if self._modal else 'back',
            on_activate_call=self._back)

        self._title_text = ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height - 56),
            size=(0, 0),
            text=ba.Lstr(
                resource='league.leagueRankText',
                fallback_resource='coopSelectWindow.powerRankingText'),
            h_align="center",
            color=ba.app.title_color,
            scale=1.4,
            maxwidth=600,
            v_align="center")

        ba.buttonwidget(edit=btn,
                        button_type='backSmall',
                        position=(75 + x_inset, self._height - 87 -
                                  (2 if ba.app.small_ui else 0)),
                        size=(60, 55),
                        label=ba.charstr(ba.SpecialChar.BACK))

        self._scroll_width = self._width - (130 + 2 * x_inset)
        self._scroll_height = self._height - 160
        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                             highlight=False,
                                             position=(65 + x_inset, 70),
                                             size=(self._scroll_width,
                                                   self._scroll_height),
                                             center_small_content=True)
        ba.widget(edit=self._scrollwidget, autoselect=True)
        ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._back_button,
                           selected_child=self._back_button)

        self._last_power_ranking_query_time: Optional[float] = None
        self._doing_power_ranking_query = False

        self._subcontainer: Optional[ba.Widget] = None
        self._subcontainerwidth = 800
        self._subcontainerheight = 483
        self._power_ranking_score_widgets: List[ba.Widget] = []

        self._season_popup_menu: Optional[popup_ui.PopupMenu] = None
        self._requested_season: Optional[str] = None
        self._season: Optional[str] = None

        # take note of our account state; we'll refresh later if this changes
        self._account_state = _ba.get_account_state()

        self._refresh()
        self._restore_state()

        # if we've got cached power-ranking data already, display it
        info = get_cached_league_rank_data()
        if info is not None:
            self._update_for_league_rank_data(info)

        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._update(show=(info is None))
Example #12
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements

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

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

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

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

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

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

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

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

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

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

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

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

        self._soundtracks: Optional[Dict[str, Any]] = None
        self._selected_soundtrack: Optional[str] = None
        self._selected_soundtrack_index: Optional[int] = None
        self._soundtrack_widgets: List[ba.Widget] = []
        self._allow_changing_soundtracks = False
        self._refresh()
        if self._back_button is not None:
            ba.buttonwidget(edit=self._back_button,
                            on_activate_call=self._back)
            ba.containerwidget(edit=self._root_widget,
                               cancel_button=self._back_button)
        else:
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back)
Example #13
0
    def __init__(self,
                 transition: Optional[str] = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        from bastd.ui.tabs import TabRow
        ba.set_analytics_screen('Watch Window')
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
        ba.app.ui.set_main_menu_location('Watch')
        self._tab_data: Dict[str, Any] = {}
        self._my_replays_scroll_width: Optional[float] = None
        self._my_replays_watch_replay_button: Optional[ba.Widget] = None
        self._scrollwidget: Optional[ba.Widget] = None
        self._columnwidget: Optional[ba.Widget] = None
        self._my_replay_selected: Optional[str] = None
        self._my_replays_rename_window: Optional[ba.Widget] = None
        self._my_replay_rename_text: Optional[ba.Widget] = None
        self._r = 'watchWindow'
        uiscale = ba.app.ui.uiscale
        self._width = 1240 if uiscale is ba.UIScale.SMALL else 1040
        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (578 if uiscale is ba.UIScale.SMALL else
                        670 if uiscale is ba.UIScale.MEDIUM else 800)
        self._current_tab: Optional[WatchWindow.TabID] = None
        extra_top = 20 if uiscale is ba.UIScale.SMALL else 0

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

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

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

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

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

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

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

        self._scroll_width = self._width - scroll_buffer_h
        self._scroll_height = self._height - 180

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

        self._restore_state()
    def __init__(self, origin_widget: ba.Widget = None):
        scale_origin: Optional[tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
            transition = 'in_right'
        bg_color = (0.4, 0.4, 0.5)
        self._width = 540
        self._height = 350
        self._scroll_width = 400
        self._scroll_height = 200
        uiscale = ba.app.ui.uiscale
        base_scale = (2.0 if uiscale is ba.UIScale.SMALL else
                      1.6 if uiscale is ba.UIScale.MEDIUM else 1.1)
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            transition=transition,
            scale=base_scale,
            scale_origin_stack_offset=scale_origin,
            stack_offset=(0, -10) if uiscale is ba.UIScale.SMALL else (0, 0)))
        self._cancel_button = ba.buttonwidget(parent=self._root_widget,
                                              position=(30, self._height - 50),
                                              size=(50, 50),
                                              scale=0.7,
                                              label='',
                                              color=bg_color,
                                              on_activate_call=self._cancel,
                                              autoselect=True,
                                              icon=ba.gettexture('crossOut'),
                                              iconscale=1.2)
        ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height * 0.88),
            size=(0, 0),
            text=ba.Lstr(
                resource='accountSettingsWindow.unlinkAccountsInstructionsText'
            ),
            maxwidth=self._width * 0.7,
            color=ba.app.ui.infotextcolor,
            h_align='center',
            v_align='center')
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._cancel_button)

        self._scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            highlight=False,
            position=((self._width - self._scroll_width) * 0.5,
                      self._height - 85 - self._scroll_height),
            size=(self._scroll_width, self._scroll_height))
        ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
        self._columnwidget = ba.columnwidget(parent=self._scrollwidget,
                                             border=2,
                                             margin=0,
                                             left_border=10)

        our_login_id = _ba.get_public_login_id()
        if our_login_id is None:
            entries = []
        else:
            account_infos = _ba.get_account_misc_read_val_2(
                'linkedAccounts2', [])
            entries = [{
                'name': ai['d'],
                'id': ai['id']
            } for ai in account_infos if ai['id'] != our_login_id]

        # (avoid getting our selection stuck on an empty column widget)
        if not entries:
            ba.containerwidget(edit=self._scrollwidget, selectable=False)
        for i, entry in enumerate(entries):
            txt = ba.textwidget(parent=self._columnwidget,
                                selectable=True,
                                text=entry['name'],
                                size=(self._scroll_width - 30, 30),
                                autoselect=True,
                                click_activate=True,
                                on_activate_call=ba.Call(
                                    self._on_entry_selected, entry))
            ba.widget(edit=txt, left_widget=self._cancel_button)
            if i == 0:
                ba.widget(edit=txt, up_widget=self._cancel_button)
Example #15
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        # pylint: disable=cyclic-import
        from bastd.ui.popup import PopupMenu
        from bastd.ui.config import ConfigNumberEdit

        music = ba.app.music

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

        self._r = 'audioSettingsWindow'

        spacing = 50.0
        width = 460.0
        height = 210.0

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

        if show_vr_head_relative_audio:
            height += 70

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

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

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

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

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

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

        v -= 0.5 * spacing

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

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

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

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

        self._restore_state()
Example #16
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()
Example #17
0
    def __init__(self, origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        import json
        ba.set_analytics_screen('Credits Window')

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

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

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

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

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

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

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

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

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

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

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

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

        translation_names = _format_names(translation_contributors, 60)

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

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

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

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

        voffs = 0
        for line in lines:
            ba.textwidget(parent=container,
                          padding=4,
                          color=(0.7, 0.9, 0.7, 1.0),
                          scale=scale,
                          flatness=1.0,
                          size=(0, 0),
                          position=(0, self._sub_height - 20 + voffs),
                          h_align='left',
                          v_align='top',
                          text=ba.Lstr(value=line))
            voffs -= line_height
Example #18
0
    def __init__(self,
                 main_menu: bool = False,
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        from ba.internal import get_remote_app_name
        from ba.deprecated import get_resource
        ba.set_analytics_screen('Help Window')

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

        self._r = 'helpWindow'

        self._main_menu = main_menu
        width = 950 if ba.app.small_ui else 750
        x_offs = 100 if ba.app.small_ui else 0
        height = 460 if ba.app.small_ui else 530 if ba.app.med_ui else 600

        super().__init__(root_widget=ba.containerwidget(
            size=(width, height),
            transition=transition,
            toolbar_visibility='menu_minimal',
            scale_origin_stack_offset=scale_origin,
            scale=(
                1.77 if ba.app.small_ui else 1.25 if ba.app.med_ui else 1.0),
            stack_offset=(0, -30) if ba.app.small_ui else (
                0, 15) if ba.app.med_ui else (0, 0)))

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

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

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

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

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

        # interface_type = ba.app.interface_type

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

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

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

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

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

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

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

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

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

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

            app = ba.app

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

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

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

        v -= spacing * 150.0

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

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

        v -= spacing * 45.0

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

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

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

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

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

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

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

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

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

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

        v -= spacing * 280.0

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

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

        v -= spacing * 1.0

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

        shadow_tex = ba.gettexture('shadowSharp')

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

            v -= spacing * 60.0

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

            txt_scale = t_big
            txtl = name
            ba.textwidget(parent=self._subcontainer,
                          position=(h + mm2, v + 3),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=200,
                          flatness=1.0,
                          text=txtl,
                          h_align='left',
                          color=header2,
                          v_align='center')
            txt_scale = t_small
            txtl = desc
            ba.textwidget(parent=self._subcontainer,
                          position=(h + mm3, v),
                          size=(0, 0),
                          scale=txt_scale,
                          maxwidth=300,
                          flatness=1.0,
                          text=txtl,
                          h_align='left',
                          color=paragraph,
                          v_align='center',
                          res_scale=0.5)
Example #19
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()
Example #20
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)
Example #21
0
    def __init__(self,
                 transition: str = 'in_right',
                 modal: bool = False,
                 origin_widget: ba.Widget = None,
                 close_once_signed_in: bool = False):
        # pylint: disable=too-many-statements

        self._sign_in_game_circle_button: Optional[ba.Widget] = None
        self._sign_in_v2_button: Optional[ba.Widget] = None
        self._sign_in_device_button: Optional[ba.Widget] = None

        self._close_once_signed_in = close_once_signed_in
        ba.set_analytics_screen('Account Window')

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

        self._r = 'accountSettingsWindow'
        self._modal = modal
        self._needs_refresh = False
        self._signed_in = (_ba.get_v1_account_state() == 'signed_in')
        self._account_state_num = _ba.get_v1_account_state_num()
        self._show_linked = (self._signed_in
                             and _ba.get_v1_account_misc_read_val(
                                 'allowAccountLinking2', False))
        self._check_sign_in_timer = ba.Timer(1.0,
                                             ba.WeakCall(self._update),
                                             timetype=ba.TimeType.REAL,
                                             repeat=True)

        # Currently we can only reset achievements on game-center.
        account_type: Optional[str]
        if self._signed_in:
            account_type = _ba.get_v1_account_type()
        else:
            account_type = None
        self._can_reset_achievements = (account_type == 'Game Center')

        app = ba.app
        uiscale = app.ui.uiscale

        self._width = 760 if uiscale is ba.UIScale.SMALL else 660
        x_offs = 50 if uiscale is ba.UIScale.SMALL else 0
        self._height = (390 if uiscale is ba.UIScale.SMALL else
                        430 if uiscale is ba.UIScale.MEDIUM else 490)

        self._sign_in_button = None
        self._sign_in_text = None

        self._scroll_width = self._width - (100 + x_offs * 2)
        self._scroll_height = self._height - 120
        self._sub_width = self._scroll_width - 20

        # Determine which sign-in/sign-out buttons we should show.
        self._show_sign_in_buttons: list[str] = []

        if app.platform == 'android' and app.subplatform == 'google':
            self._show_sign_in_buttons.append('Google Play')

        elif app.platform == 'android' and app.subplatform == 'amazon':
            self._show_sign_in_buttons.append('Game Circle')

        # Local accounts are generally always available with a few key
        # exceptions.
        self._show_sign_in_buttons.append('Local')

        # Ditto with shiny new V2 ones.
        if bool(True):
            self._show_sign_in_buttons.append('V2')

        top_extra = 15 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.09 if uiscale is ba.UIScale.SMALL else
                   1.4 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -19) if uiscale is ba.UIScale.SMALL else (0, 0)))
        if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars:
            self._back_button = None
            ba.containerwidget(edit=self._root_widget,
                               on_cancel_call=self._back)
        else:
            self._back_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=(51 + x_offs, self._height - 62),
                size=(120, 60),
                scale=0.8,
                text_scale=1.2,
                autoselect=True,
                label=ba.Lstr(
                    resource='doneText' if self._modal else 'backText'),
                button_type='regular' if self._modal else 'back',
                on_activate_call=self._back)
            ba.containerwidget(edit=self._root_widget, cancel_button=btn)
            if not self._modal:
                ba.buttonwidget(edit=btn,
                                button_type='backSmall',
                                size=(60, 56),
                                label=ba.charstr(ba.SpecialChar.BACK))

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

        self._scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            highlight=False,
            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: Optional[ba.Widget] = None
        self._refresh()
        self._restore_state()
Example #22
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-statements
        from bastd.ui import popup
        from bastd.ui.config import ConfigCheckBox, ConfigNumberEdit
        # if they provided an origin-widget, scale up from that
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        h_offs = 0

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

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

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

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

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

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

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

        v -= spacing

        # make a timer to update our controls in case the config changes
        # under us
        self._update_timer = ba.Timer(0.25,
                                      ba.WeakCall(self._update_controls),
                                      repeat=True,
                                      timetype=ba.TimeType.REAL)
Example #23
0
    def __init__(self,
                 sessiontype: Type[ba.Session],
                 transition: str = 'in_right',
                 select_playlist: str = None,
                 origin_widget: ba.Widget = None):
        # Yes this needs tidying.
        # pylint: disable=too-many-locals
        # pylint: disable=too-many-statements
        # pylint: disable=cyclic-import
        from bastd.ui import playlist
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        self._sessiontype = sessiontype
        self._pvars = playlist.PlaylistTypeVars(sessiontype)
        self._max_playlists = 30
        self._r = 'gameListWindow'
        self._width = 750.0 if ba.app.small_ui else 650.0
        x_inset = 50.0 if ba.app.small_ui else 0.0
        self._height = (380.0 if ba.app.small_ui else
                        420.0 if ba.app.med_ui else 500.0)
        top_extra = 20.0 if ba.app.small_ui else 0.0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            scale=(2.05 if ba.app.small_ui else 1.5 if ba.app.med_ui else 1.0),
            stack_offset=(0, -10) if ba.app.small_ui else (0, 0)))

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

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

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

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

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

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

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

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

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

        h = 145

        try:
            self._do_randomize_val = ba.app.config[self._pvars.config_name +
                                                   ' Playlist Randomize']
        except Exception:
            self._do_randomize_val = 0

        h += 210

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

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

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

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

        self._refresh(select_playlist=select_playlist)

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

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

        # Keep our lock images up to date/etc.
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._update()
Example #24
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        import threading

        # Preload some modules we use in a background thread so we won't
        # have a visual hitch when the user taps them.
        threading.Thread(target=self._preload_modules).start()

        # We can currently be used either for main menu duty or for selecting
        # playlists (should make this more elegant/general).
        self._is_main_menu = not ba.app.ui.selecting_private_party_playlist

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

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

        self._r = 'playWindow'

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

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

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

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

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

        self._coop_button: Optional[ba.Widget] = None

        # Only show coop button in main-menu variant.
        if self._is_main_menu:
            self._coop_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=(hoffs, v + (scl * 15 if self._is_main_menu else 0)),
                size=(scl * button_width,
                      scl * (300 if self._is_main_menu else 360)),
                extra_touch_border_scale=0.1,
                autoselect=True,
                label='',
                button_type='square',
                text_scale=1.13,
                on_activate_call=self._coop)

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

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

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

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

        scl = 0.5 if self._is_main_menu else 0.68
        hoffs += 440 if self._is_main_menu else 216
        v += 180 if self._is_main_menu else -68

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

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

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

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

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

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

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

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

        self._restore_state()
Example #25
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        import threading

        # Preload some modules we use in a background thread so we won't
        # have a visual hitch when the user taps them.
        threading.Thread(target=self._preload_modules).start()

        ba.set_analytics_screen('Settings Window')
        scale_origin: Optional[Tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
        uiscale = ba.app.uiscale
        width = 900 if uiscale is ba.UIScale.SMALL else 580
        x_inset = 75 if uiscale is ba.UIScale.SMALL else 0
        height = 435
        # button_height = 42
        self._r = 'settingsWindow'
        top_extra = 20 if uiscale is ba.UIScale.SMALL else 0

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

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

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

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

        v = height - 80
        v -= 145

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

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

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

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

        v -= (baseh - 5)

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

        avb = self._advanced_button = ba.buttonwidget(
            parent=self._root_widget,
            autoselect=True,
            position=(x_offs5, v),
            size=(basew, baseh),
            button_type='square',
            label='',
            on_activate_call=self._do_advanced)
        _b_title(x_offs5, v, avb, ba.Lstr(resource=self._r + '.advancedText'))
        imgw = imgh = 120
        ba.imagewidget(parent=self._root_widget,
                       position=(x_offs5 + basew * 0.49 - imgw * 0.5 + 5,
                                 v + 35),
                       size=(imgw, imgh),
                       color=(0.8, 0.95, 1),
                       texture=ba.gettexture('advancedIcon'),
                       draw_controller=avb)
Example #26
0
 def safe_delete(widget: ba.Widget) -> None:
     if widget:
         widget.delete()
Example #27
0
 def __init__(self, origin_widget: ba.Widget = None):
     scale_origin: Optional[Tuple[float, float]]
     if origin_widget is not None:
         self._transition_out = 'out_scale'
         scale_origin = origin_widget.get_screen_space_center()
         transition = 'in_scale'
     else:
         self._transition_out = 'out_right'
         scale_origin = None
         transition = 'in_right'
     bg_color = (0.4, 0.4, 0.5)
     self._width = 560
     self._height = 420
     uiscale = ba.app.uiscale
     base_scale = (1.65 if uiscale is ba.UIScale.SMALL else
                   1.5 if uiscale is ba.UIScale.MEDIUM else 1.1)
     super().__init__(root_widget=ba.containerwidget(
         size=(self._width, self._height),
         transition=transition,
         scale=base_scale,
         scale_origin_stack_offset=scale_origin,
         stack_offset=(0, -10) if uiscale is ba.UIScale.SMALL else (0, 0)))
     self._cancel_button = ba.buttonwidget(parent=self._root_widget,
                                           position=(40, self._height - 45),
                                           size=(50, 50),
                                           scale=0.7,
                                           label='',
                                           color=bg_color,
                                           on_activate_call=self._cancel,
                                           autoselect=True,
                                           icon=ba.gettexture('crossOut'),
                                           iconscale=1.2)
     maxlinks = _ba.get_account_misc_read_val('maxLinkAccounts', 5)
     ba.textwidget(
         parent=self._root_widget,
         position=(self._width * 0.5, self._height * 0.56),
         size=(0, 0),
         text=ba.Lstr(resource=(
             'accountSettingsWindow.linkAccountsInstructionsNewText'),
                      subs=[('${COUNT}', str(maxlinks))]),
         maxwidth=self._width * 0.9,
         color=ba.app.infotextcolor,
         max_height=self._height * 0.6,
         h_align='center',
         v_align='center')
     ba.containerwidget(edit=self._root_widget,
                        cancel_button=self._cancel_button)
     ba.buttonwidget(
         parent=self._root_widget,
         position=(40, 30),
         size=(200, 60),
         label=ba.Lstr(
             resource='accountSettingsWindow.linkAccountsGenerateCodeText'),
         autoselect=True,
         on_activate_call=self._generate_press)
     self._enter_code_button = ba.buttonwidget(
         parent=self._root_widget,
         position=(self._width - 240, 30),
         size=(200, 60),
         label=ba.Lstr(
             resource='accountSettingsWindow.linkAccountsEnterCodeText'),
         autoselect=True,
         on_activate_call=self._enter_code_press)
Example #28
0
    def __init__(self,
                 transition: str = 'in_right',
                 from_modal_store: bool = False,
                 modal: bool = False,
                 origin_widget: ba.Widget = None,
                 store_back_location: str = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals

        ba.set_analytics_screen('Get Tickets Window')

        self._transitioning_out = False
        self._store_back_location = store_back_location  # ew.

        self._ad_button_greyed = False
        self._smooth_update_timer: Optional[ba.Timer] = None
        self._ad_button = None
        self._ad_label = None
        self._ad_image = None
        self._ad_time_text = None

        # 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.uiscale
        self._width = 1000.0 if uiscale is ba.UIScale.SMALL else 800.0
        x_inset = 100.0 if uiscale is ba.UIScale.SMALL else 0.0
        self._height = 480.0

        self._modal = modal
        self._from_modal_store = from_modal_store
        self._r = 'getTicketsWindow'

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

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            color=(0.4, 0.37, 0.55),
            scale=(1.63 if uiscale is ba.UIScale.SMALL else
                   1.2 if uiscale is ba.UIScale.MEDIUM else 1.0),
            stack_offset=(0, -3) if uiscale is ba.UIScale.SMALL else (0, 0)))

        btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(55 + x_inset, self._height - 79),
            size=(140, 60),
            scale=1.0,
            autoselect=True,
            label=ba.Lstr(resource='doneText' if modal else 'backText'),
            button_type='regular' if modal else 'back',
            on_activate_call=self._back)

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

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

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

        b_size = (220.0, 180.0)
        v = self._height - b_size[1] - 80
        spacing = 1

        self._ad_button = None

        def _add_button(item: str,
                        position: Tuple[float, float],
                        size: Tuple[float, float],
                        label: ba.Lstr,
                        price: str = None,
                        tex_name: str = None,
                        tex_opacity: float = 1.0,
                        tex_scale: float = 1.0,
                        enabled: bool = True,
                        text_scale: float = 1.0) -> ba.Widget:
            btn2 = ba.buttonwidget(
                parent=self._root_widget,
                position=position,
                button_type='square',
                size=size,
                label='',
                autoselect=True,
                color=None if enabled else (0.5, 0.5, 0.5),
                on_activate_call=(ba.Call(self._purchase, item)
                                  if enabled else self._disabled_press))
            txt = ba.textwidget(parent=self._root_widget,
                                text=label,
                                position=(position[0] + size[0] * 0.5,
                                          position[1] + size[1] * 0.3),
                                scale=text_scale,
                                maxwidth=size[0] * 0.75,
                                size=(0, 0),
                                h_align='center',
                                v_align='center',
                                draw_controller=btn2,
                                color=(0.7, 0.9, 0.7, 1.0 if enabled else 0.2))
            if price is not None and enabled:
                ba.textwidget(parent=self._root_widget,
                              text=price,
                              position=(position[0] + size[0] * 0.5,
                                        position[1] + size[1] * 0.17),
                              scale=0.7,
                              maxwidth=size[0] * 0.75,
                              size=(0, 0),
                              h_align='center',
                              v_align='center',
                              draw_controller=btn2,
                              color=(0.4, 0.9, 0.4, 1.0))
            i = None
            if tex_name is not None:
                tex_size = 90.0 * tex_scale
                i = ba.imagewidget(
                    parent=self._root_widget,
                    texture=ba.gettexture(tex_name),
                    position=(position[0] + size[0] * 0.5 - tex_size * 0.5,
                              position[1] + size[1] * 0.66 - tex_size * 0.5),
                    size=(tex_size, tex_size),
                    draw_controller=btn2,
                    opacity=tex_opacity * (1.0 if enabled else 0.25))
            if item == 'ad':
                self._ad_button = btn2
                self._ad_label = txt
                assert i is not None
                self._ad_image = i
                self._ad_time_text = ba.textwidget(
                    parent=self._root_widget,
                    text='1m 10s',
                    position=(position[0] + size[0] * 0.5,
                              position[1] + size[1] * 0.5),
                    scale=text_scale * 1.2,
                    maxwidth=size[0] * 0.85,
                    size=(0, 0),
                    h_align='center',
                    v_align='center',
                    draw_controller=btn2,
                    color=(0.4, 0.9, 0.4, 1.0))
            return btn2

        rsrc = self._r + '.ticketsText'

        c2txt = ba.Lstr(
            resource=rsrc,
            subs=[('${COUNT}',
                   str(_ba.get_account_misc_read_val('tickets2Amount', 500)))])
        c3txt = ba.Lstr(
            resource=rsrc,
            subs=[('${COUNT}',
                   str(_ba.get_account_misc_read_val('tickets3Amount',
                                                     1500)))])
        c4txt = ba.Lstr(
            resource=rsrc,
            subs=[('${COUNT}',
                   str(_ba.get_account_misc_read_val('tickets4Amount',
                                                     5000)))])
        c5txt = ba.Lstr(
            resource=rsrc,
            subs=[('${COUNT}',
                   str(_ba.get_account_misc_read_val('tickets5Amount',
                                                     15000)))])

        h = 110.0

        # enable buttons if we have prices..
        tickets2_price = _ba.get_price('tickets2')
        tickets3_price = _ba.get_price('tickets3')
        tickets4_price = _ba.get_price('tickets4')
        tickets5_price = _ba.get_price('tickets5')

        # TEMP
        # tickets1_price = '$0.99'
        # tickets2_price = '$4.99'
        # tickets3_price = '$9.99'
        # tickets4_price = '$19.99'
        # tickets5_price = '$49.99'

        _add_button('tickets2',
                    enabled=(tickets2_price is not None),
                    position=(self._width * 0.5 - spacing * 1.5 -
                              b_size[0] * 2.0 + h, v),
                    size=b_size,
                    label=c2txt,
                    price=tickets2_price,
                    tex_name='ticketsMore')  # 0.99-ish
        _add_button('tickets3',
                    enabled=(tickets3_price is not None),
                    position=(self._width * 0.5 - spacing * 0.5 -
                              b_size[0] * 1.0 + h, v),
                    size=b_size,
                    label=c3txt,
                    price=tickets3_price,
                    tex_name='ticketRoll')  # 4.99-ish
        v -= b_size[1] - 5
        _add_button('tickets4',
                    enabled=(tickets4_price is not None),
                    position=(self._width * 0.5 - spacing * 1.5 -
                              b_size[0] * 2.0 + h, v),
                    size=b_size,
                    label=c4txt,
                    price=tickets4_price,
                    tex_name='ticketRollBig',
                    tex_scale=1.2)  # 9.99-ish
        _add_button('tickets5',
                    enabled=(tickets5_price is not None),
                    position=(self._width * 0.5 - spacing * 0.5 -
                              b_size[0] * 1.0 + h, v),
                    size=b_size,
                    label=c5txt,
                    price=tickets5_price,
                    tex_name='ticketRolls',
                    tex_scale=1.2)  # 19.99-ish

        self._enable_ad_button = _ba.has_video_ads()
        h = self._width * 0.5 + 110.0
        v = self._height - b_size[1] - 115.0

        if self._enable_ad_button:
            h_offs = 35
            b_size_3 = (150, 120)
            cdb = _add_button(
                'ad',
                position=(h + h_offs, v),
                size=b_size_3,
                label=ba.Lstr(resource=self._r + '.ticketsFromASponsorText',
                              subs=[('${COUNT}',
                                     str(
                                         _ba.get_account_misc_read_val(
                                             'sponsorTickets', 5)))]),
                tex_name='ticketsMore',
                enabled=self._enable_ad_button,
                tex_opacity=0.6,
                tex_scale=0.7,
                text_scale=0.7)
            ba.buttonwidget(edit=cdb,
                            color=(0.65, 0.5,
                                   0.7) if self._enable_ad_button else
                            (0.5, 0.5, 0.5))

            self._ad_free_text = ba.textwidget(
                parent=self._root_widget,
                text=ba.Lstr(resource=self._r + '.freeText'),
                position=(h + h_offs + b_size_3[0] * 0.5,
                          v + b_size_3[1] * 0.5 + 25),
                size=(0, 0),
                color=(1, 1, 0, 1.0) if self._enable_ad_button else
                (1, 1, 1, 0.2),
                draw_controller=cdb,
                rotate=15,
                shadow=1.0,
                maxwidth=150,
                h_align='center',
                v_align='center',
                scale=1.0)
            v -= 125
        else:
            v -= 20

        if True:  # pylint: disable=using-constant-test
            h_offs = 35
            b_size_3 = (150, 120)
            cdb = _add_button(
                'app_invite',
                position=(h + h_offs, v),
                size=b_size_3,
                label=ba.Lstr(
                    resource='gatherWindow.earnTicketsForRecommendingText',
                    subs=[
                        ('${COUNT}',
                         str(_ba.get_account_misc_read_val(
                             'sponsorTickets', 5)))
                    ]),
                tex_name='ticketsMore',
                enabled=True,
                tex_opacity=0.6,
                tex_scale=0.7,
                text_scale=0.7)
            ba.buttonwidget(edit=cdb, color=(0.65, 0.5, 0.7))

            ba.textwidget(parent=self._root_widget,
                          text=ba.Lstr(resource=self._r + '.freeText'),
                          position=(h + h_offs + b_size_3[0] * 0.5,
                                    v + b_size_3[1] * 0.5 + 25),
                          size=(0, 0),
                          color=(1, 1, 0, 1.0),
                          draw_controller=cdb,
                          rotate=15,
                          shadow=1.0,
                          maxwidth=150,
                          h_align='center',
                          v_align='center',
                          scale=1.0)
            tc_y_offs = 0

        h = self._width - (185 + x_inset)
        v = self._height - 95 + tc_y_offs

        txt1 = (ba.Lstr(
            resource=self._r +
            '.youHaveText').evaluate().split('${COUNT}')[0].strip())
        txt2 = (ba.Lstr(
            resource=self._r +
            '.youHaveText').evaluate().split('${COUNT}')[-1].strip())

        ba.textwidget(parent=self._root_widget,
                      text=txt1,
                      position=(h, v),
                      size=(0, 0),
                      color=(0.5, 0.5, 0.6),
                      maxwidth=200,
                      h_align='center',
                      v_align='center',
                      scale=0.8)
        v -= 30
        self._ticket_count_text = ba.textwidget(parent=self._root_widget,
                                                position=(h, v),
                                                size=(0, 0),
                                                color=(0.2, 1.0, 0.2),
                                                maxwidth=200,
                                                h_align='center',
                                                v_align='center',
                                                scale=1.6)
        v -= 30
        ba.textwidget(parent=self._root_widget,
                      text=txt2,
                      position=(h, v),
                      size=(0, 0),
                      color=(0.5, 0.5, 0.6),
                      maxwidth=200,
                      h_align='center',
                      v_align='center',
                      scale=0.8)

        # update count now and once per second going forward..
        self._ticking_node: Optional[ba.Node] = None
        self._smooth_ticket_count: Optional[float] = None
        self._ticket_count = 0
        self._update()
        self._update_timer = ba.Timer(1.0,
                                      ba.WeakCall(self._update),
                                      timetype=ba.TimeType.REAL,
                                      repeat=True)
        self._smooth_increase_speed = 1.0
Example #29
0
    def __init__(self,
                 transition: str = 'in_right',
                 modal: bool = False,
                 show_tab: str = None,
                 on_close_call: Callable[[], Any] = None,
                 back_location: str = None,
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        from bastd.ui import tabs
        from ba import SpecialChar

        app = ba.app
        uiscale = app.uiscale

        ba.set_analytics_screen('Store Window')

        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.button_infos: Optional[Dict[str, Dict[str, Any]]] = None
        self.update_buttons_timer: Optional[ba.Timer] = None
        self._status_textwidget_update_timer = None

        self._back_location = back_location
        self._on_close_call = on_close_call
        self._show_tab = show_tab
        self._modal = modal
        self._width = 1240 if uiscale is ba.UIScale.SMALL else 1040
        self._x_inset = x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
        self._height = (578 if uiscale is ba.UIScale.SMALL else
                        645 if uiscale is ba.UIScale.MEDIUM else 800)
        self._current_tab: Optional[str] = None
        extra_top = 30 if uiscale is ba.UIScale.SMALL else 0

        self._request: Any = None
        self._r = 'store'
        self._last_buy_time: Optional[float] = None

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

        self._back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(70 + x_inset, self._height - 74),
            size=(140, 60),
            scale=1.1,
            autoselect=True,
            label=ba.Lstr(resource='doneText' if self._modal else 'backText'),
            button_type=None if self._modal else 'back',
            on_activate_call=self._back)
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        self._get_tickets_button = ba.buttonwidget(
            parent=self._root_widget,
            size=(210, 65),
            on_activate_call=self._on_get_more_tickets_press,
            autoselect=True,
            scale=0.9,
            text_scale=1.4,
            left_widget=self._back_button,
            color=(0.7, 0.5, 0.85),
            textcolor=(0.2, 1.0, 0.2),
            label=ba.Lstr(resource='getTicketsWindow.titleText'))

        # Move this dynamically to keep it out of the way of the party icon.
        self._update_get_tickets_button_pos()
        self._get_ticket_pos_update_timer = ba.Timer(
            1.0,
            ba.WeakCall(self._update_get_tickets_button_pos),
            repeat=True,
            timetype=ba.TimeType.REAL)
        ba.widget(edit=self._back_button,
                  right_widget=self._get_tickets_button)
        self._ticket_text_update_timer = ba.Timer(
            1.0,
            ba.WeakCall(self._update_tickets_text),
            timetype=ba.TimeType.REAL,
            repeat=True)
        self._update_tickets_text()

        app = ba.app
        if app.platform in ['mac', 'ios'] and app.subplatform == 'appstore':
            ba.buttonwidget(
                parent=self._root_widget,
                position=(self._width * 0.5 - 70, 16),
                size=(230, 50),
                scale=0.65,
                on_activate_call=ba.WeakCall(self._restore_purchases),
                color=(0.35, 0.3, 0.4),
                selectable=False,
                textcolor=(0.55, 0.5, 0.6),
                label=ba.Lstr(
                    resource='getTicketsWindow.restorePurchasesText'))

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 44),
                      size=(0, 0),
                      color=app.title_color,
                      scale=1.5,
                      h_align='center',
                      v_align='center',
                      text=ba.Lstr(resource='storeText'),
                      maxwidth=420)

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

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

        tabs_def = [
            ('extras', ba.Lstr(resource=self._r + '.extrasText')),
            ('maps', ba.Lstr(resource=self._r + '.mapsText')),
            ('minigames', ba.Lstr(resource=self._r + '.miniGamesText')),
            ('characters', ba.Lstr(resource=self._r + '.charactersText')),
            ('icons', ba.Lstr(resource=self._r + '.iconsText')),
        ]

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

        self._purchasable_count_widgets: Dict[str, Dict[str, Any]] = {}

        # Create our purchasable-items tags and have them update over time.
        for i, tab in enumerate(tabs_def):
            pos = tab_results['positions'][i]
            size = tab_results['sizes'][i]
            button = tab_results['buttons_indexed'][i]
            rad = 10
            center = (pos[0] + 0.1 * size[0], pos[1] + 0.9 * size[1])
            img = ba.imagewidget(parent=self._root_widget,
                                 position=(center[0] - rad * 1.04,
                                           center[1] - rad * 1.15),
                                 size=(rad * 2.2, rad * 2.2),
                                 texture=ba.gettexture('circleShadow'),
                                 color=(1, 0, 0))
            txt = ba.textwidget(parent=self._root_widget,
                                position=center,
                                size=(0, 0),
                                h_align='center',
                                v_align='center',
                                maxwidth=1.4 * rad,
                                scale=0.6,
                                shadow=1.0,
                                flatness=1.0)
            rad = 20
            sale_img = ba.imagewidget(parent=self._root_widget,
                                      position=(center[0] - rad,
                                                center[1] - rad),
                                      size=(rad * 2, rad * 2),
                                      draw_controller=button,
                                      texture=ba.gettexture('circleZigZag'),
                                      color=(0.5, 0, 1.0))
            sale_title_text = ba.textwidget(parent=self._root_widget,
                                            position=(center[0],
                                                      center[1] + 0.24 * rad),
                                            size=(0, 0),
                                            h_align='center',
                                            v_align='center',
                                            draw_controller=button,
                                            maxwidth=1.4 * rad,
                                            scale=0.6,
                                            shadow=0.0,
                                            flatness=1.0,
                                            color=(0, 1, 0))
            sale_time_text = ba.textwidget(parent=self._root_widget,
                                           position=(center[0],
                                                     center[1] - 0.29 * rad),
                                           size=(0, 0),
                                           h_align='center',
                                           v_align='center',
                                           draw_controller=button,
                                           maxwidth=1.4 * rad,
                                           scale=0.4,
                                           shadow=0.0,
                                           flatness=1.0,
                                           color=(0, 1, 0))
            self._purchasable_count_widgets[tab[0]] = {
                'img': img,
                'text': txt,
                'sale_img': sale_img,
                'sale_title_text': sale_title_text,
                'sale_time_text': sale_time_text
            }
        self._tab_update_timer = ba.Timer(1.0,
                                          ba.WeakCall(self._update_tabs),
                                          timetype=ba.TimeType.REAL,
                                          repeat=True)
        self._update_tabs()

        self._tab_buttons = tab_results['buttons']

        if self._get_tickets_button is not None:
            last_tab_button = self._tab_buttons[tabs_def[-1][0]]
            ba.widget(edit=self._get_tickets_button,
                      down_widget=last_tab_button)
            ba.widget(edit=last_tab_button,
                      up_widget=self._get_tickets_button,
                      right_widget=self._get_tickets_button)

        self._scroll_width = self._width - scroll_buffer_h
        self._scroll_height = self._height - 180

        self._scrollwidget: Optional[ba.Widget] = None
        self._status_textwidget: Optional[ba.Widget] = None
        self._restore_state()
Example #30
0
    def __init__(self,
                 transition: str = 'in_right',
                 in_main_menu: bool = True,
                 selected_profile: str = None,
                 origin_widget: ba.Widget = None):
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-locals
        from ba.internal import ensure_have_account_player_profile
        self._in_main_menu = in_main_menu
        if self._in_main_menu:
            back_label = ba.Lstr(resource='backText')
        else:
            back_label = ba.Lstr(resource='doneText')
        self._width = 700.0 if ba.app.small_ui else 600.0
        x_inset = 50.0 if ba.app.small_ui else 0.0
        self._height = (360.0 if ba.app.small_ui else
                        385.0 if ba.app.med_ui else 410.0)

        # If we're being called up standalone, handle pause/resume ourself.
        if not self._in_main_menu:
            ba.app.pause()

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

        self._r = 'playerProfilesWindow'

        # Ensure we've got an account-profile in cases where we're signed in.
        ensure_have_account_player_profile()

        top_extra = 20 if ba.app.small_ui else 0

        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height + top_extra),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            scale=(2.2 if ba.app.small_ui else 1.6 if ba.app.med_ui else 1.0),
            stack_offset=(0, -14) if ba.app.small_ui else (0, 0)))

        self._back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(40 + x_inset, self._height - 59),
            size=(120, 60),
            scale=0.8,
            label=back_label,
            button_type='back' if self._in_main_menu else None,
            autoselect=True,
            on_activate_call=self._back)
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

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

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

        scroll_height = self._height - 140.0
        self._scroll_width = self._width - (188 + x_inset * 2)
        v = self._height - 84.0
        h = 50 + x_inset
        b_color = (0.6, 0.53, 0.63)

        scl = (1.055 if ba.app.small_ui else 1.18 if ba.app.med_ui else 1.3)
        v -= 70.0 * scl
        self._new_button = ba.buttonwidget(parent=self._root_widget,
                                           position=(h, v),
                                           size=(80, 66.0 * scl),
                                           on_activate_call=self._new_profile,
                                           color=b_color,
                                           button_type='square',
                                           autoselect=True,
                                           textcolor=(0.75, 0.7, 0.8),
                                           text_scale=0.7,
                                           label=ba.Lstr(resource=self._r +
                                                         '.newButtonText'))
        v -= 70.0 * scl
        self._edit_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(80, 66.0 * scl),
            on_activate_call=self._edit_profile,
            color=b_color,
            button_type='square',
            autoselect=True,
            textcolor=(0.75, 0.7, 0.8),
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.editButtonText'))
        v -= 70.0 * scl
        self._delete_button = ba.buttonwidget(
            parent=self._root_widget,
            position=(h, v),
            size=(80, 66.0 * scl),
            on_activate_call=self._delete_profile,
            color=b_color,
            button_type='square',
            autoselect=True,
            textcolor=(0.75, 0.7, 0.8),
            text_scale=0.7,
            label=ba.Lstr(resource=self._r + '.deleteButtonText'))

        v = self._height - 87

        ba.textwidget(parent=self._root_widget,
                      position=(self._width * 0.5, self._height - 71),
                      size=(0, 0),
                      text=ba.Lstr(resource=self._r + '.explanationText'),
                      color=ba.app.infotextcolor,
                      maxwidth=self._width * 0.83,
                      scale=0.6,
                      h_align="center",
                      v_align="center")

        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
                                             highlight=False,
                                             position=(140 + x_inset,
                                                       v - scroll_height),
                                             size=(self._scroll_width,
                                                   scroll_height))
        ba.widget(edit=self._scrollwidget,
                  autoselect=True,
                  left_widget=self._new_button)
        ba.containerwidget(edit=self._root_widget,
                           selected_child=self._scrollwidget)
        self._columnwidget = ba.columnwidget(parent=self._scrollwidget)
        v -= 255
        self._profiles: Optional[Dict[str, Dict[str, Any]]] = None
        self._selected_profile = selected_profile
        self._profile_widgets: List[ba.Widget] = []
        self._refresh()
        self._restore_state()