def __init__(self, transition: str = 'in_right', origin_widget: ba.Widget = None): # pylint: disable=too-many-statements # pylint: disable=too-many-locals new_style = True width = 1000 if ba.app.small_ui else 800 x_offs = 100 if ba.app.small_ui else 0 height = 550 if new_style else 400 button_width = 400 scale_origin: Optional[Tuple[float, float]] if origin_widget is not None: self._transition_out = 'out_scale' scale_origin = origin_widget.get_screen_space_center() transition = 'in_scale' else: self._transition_out = 'out_right' scale_origin = None self._r = 'playWindow' super().__init__(root_widget=ba.containerwidget( size=(width, height), transition=transition, toolbar_visibility='menu_full', scale_origin_stack_offset=scale_origin, scale=(1.6 if new_style else 1.52 ) if ba.app.small_ui else 0.9 if ba.app.med_ui else 0.8, stack_offset=((0, 0) if new_style else ( 10, 7)) if ba.app.small_ui else (0, 0))) self._back_button = back_button = btn = ba.buttonwidget( parent=self._root_widget, position=(55 + x_offs, height - 132) if new_style else (55, height - 92), size=(120, 60), scale=1.1, text_res_scale=1.5, text_scale=1.2, autoselect=True, label=ba.Lstr(resource='backText'), button_type='back') txt = ba.textwidget(parent=self._root_widget, position=(width * 0.5, height - (101 if new_style else 61)), size=(0, 0), text=ba.Lstr(resource=self._r + '.titleText'), scale=1.7, res_scale=2.0, maxwidth=400, color=ba.app.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.toolbars and ba.app.small_ui: ba.textwidget(edit=txt, text='') v = height - (110 if new_style else 60) v -= 100 clr = (0.6, 0.7, 0.6, 1.0) v -= 280 if new_style else 180 v += 30 if ba.app.toolbars and ba.app.small_ui else 0 hoffs = x_offs + 80 if new_style else 0 scl = 1.13 if new_style else 0.68 self._lineup_tex = ba.gettexture('playerLineup') angry_computer_transparent_model = ba.getmodel( 'angryComputerTransparent') self._lineup_1_transparent_model = ba.getmodel( 'playerLineup1Transparent') self._lineup_2_transparent_model = ba.getmodel( 'playerLineup2Transparent') self._lineup_3_transparent_model = ba.getmodel( 'playerLineup3Transparent') self._lineup_4_transparent_model = ba.getmodel( 'playerLineup4Transparent') self._eyes_model = ba.getmodel('plasticEyesTransparent') self._coop_button = btn = ba.buttonwidget( parent=self._root_widget, position=(hoffs, v + (scl * 15 if new_style else 0)), size=(scl * button_width, scl * (300 if new_style else 360)), extra_touch_border_scale=0.1, autoselect=True, label='', button_type='square', text_scale=1.13, on_activate_call=self._coop) if ba.app.toolbars and ba.app.small_ui: ba.widget(edit=btn, left_widget=_ba.get_special_widget('back_button')) ba.widget(edit=btn, up_widget=_ba.get_special_widget('account_button')) ba.widget(edit=btn, down_widget=_ba.get_special_widget('settings_button')) self._draw_dude(0, btn, hoffs, v, scl, position=(140, 30), color=(0.72, 0.4, 1.0)) self._draw_dude(1, btn, hoffs, v, scl, position=(185, 53), color=(0.71, 0.5, 1.0)) self._draw_dude(2, btn, hoffs, v, scl, position=(220, 27), color=(0.67, 0.44, 1.0)) self._draw_dude(3, btn, hoffs, v, scl, position=(255, 57), color=(0.7, 0.3, 1.0)) ba.imagewidget(parent=self._root_widget, draw_controller=btn, position=(hoffs + scl * 230, v + scl * 153), size=(scl * 115, scl * 115), texture=self._lineup_tex, model_transparent=angry_computer_transparent_model) ba.textwidget(parent=self._root_widget, draw_controller=btn, position=(hoffs + scl * (-10), v + scl * 95), size=(scl * button_width, scl * 50), text=ba.Lstr(resource='playModes.singlePlayerCoopText', fallback_resource='playModes.coopText'), maxwidth=scl * button_width * 0.7, res_scale=1.5, h_align='center', v_align='center', color=(0.7, 0.9, 0.7, 1.0), scale=scl * 2.3) ba.textwidget(parent=self._root_widget, draw_controller=btn, position=(hoffs + scl * (-10), v + (scl * 54)), size=(scl * button_width, scl * 30), text=ba.Lstr(resource=self._r + '.oneToFourPlayersText'), h_align='center', v_align='center', scale=0.83 * scl, flatness=1.0, maxwidth=scl * button_width * 0.7, color=clr) scl = 0.5 if new_style else 0.68 hoffs += 440 if new_style else 260 v += 180 if new_style else 0 self._teams_button = btn = ba.buttonwidget( parent=self._root_widget, position=(hoffs, v + (scl * 15 if new_style else 0)), size=(scl * button_width, scl * (300 if new_style else 360)), extra_touch_border_scale=0.1, autoselect=True, label='', button_type='square', text_scale=1.13, on_activate_call=self._team_tourney) if ba.app.toolbars: ba.widget(edit=btn, up_widget=_ba.get_special_widget('tickets_plus_button'), right_widget=_ba.get_special_widget('party_button')) xxx = -14 self._draw_dude(2, btn, hoffs, v, scl, position=(xxx + 148, 30), color=(0.2, 0.4, 1.0)) self._draw_dude(3, btn, hoffs, v, scl, position=(xxx + 181, 53), color=(0.3, 0.4, 1.0)) self._draw_dude(1, btn, hoffs, v, scl, position=(xxx + 216, 33), color=(0.3, 0.5, 1.0)) self._draw_dude(0, btn, hoffs, v, scl, position=(xxx + 245, 57), color=(0.3, 0.5, 1.0)) xxx = 155 self._draw_dude(0, btn, hoffs, v, scl, position=(xxx + 151, 30), color=(1.0, 0.5, 0.4)) self._draw_dude(1, btn, hoffs, v, scl, position=(xxx + 189, 53), color=(1.0, 0.58, 0.58)) self._draw_dude(3, btn, hoffs, v, scl, position=(xxx + 223, 27), color=(1.0, 0.5, 0.5)) self._draw_dude(2, btn, hoffs, v, scl, position=(xxx + 257, 57), color=(1.0, 0.5, 0.5)) ba.textwidget(parent=self._root_widget, draw_controller=btn, position=(hoffs + scl * (-10), v + scl * 95), size=(scl * button_width, scl * 50), text=ba.Lstr(resource='playModes.teamsText', fallback_resource='teamsText'), res_scale=1.5, maxwidth=scl * button_width * 0.7, h_align='center', v_align='center', color=(0.7, 0.9, 0.7, 1.0), scale=scl * 2.3) ba.textwidget(parent=self._root_widget, draw_controller=btn, position=(hoffs + scl * (-10), v + (scl * 54)), size=(scl * button_width, scl * 30), text=ba.Lstr(resource=self._r + '.twoToEightPlayersText'), h_align='center', v_align='center', res_scale=1.5, scale=0.9 * scl, flatness=1.0, maxwidth=scl * button_width * 0.7, color=clr) hoffs += 0 if new_style else 260 v -= 155 if new_style else 0 self._free_for_all_button = btn = ba.buttonwidget( parent=self._root_widget, position=(hoffs, v + (scl * 15 if new_style else 0)), size=(scl * button_width, scl * (300 if new_style else 360)), extra_touch_border_scale=0.1, autoselect=True, label='', button_type='square', text_scale=1.13, on_activate_call=self._free_for_all) xxx = -5 self._draw_dude(0, btn, hoffs, v, scl, position=(xxx + 140, 30), color=(0.4, 1.0, 0.4)) self._draw_dude(3, btn, hoffs, v, scl, position=(xxx + 185, 53), color=(1.0, 0.4, 0.5)) self._draw_dude(1, btn, hoffs, v, scl, position=(xxx + 220, 27), color=(0.4, 0.5, 1.0)) self._draw_dude(2, btn, hoffs, v, scl, position=(xxx + 255, 57), color=(0.5, 1.0, 0.4)) xxx = 140 self._draw_dude(2, btn, hoffs, v, scl, position=(xxx + 148, 30), color=(1.0, 0.9, 0.4)) self._draw_dude(0, btn, hoffs, v, scl, position=(xxx + 182, 53), color=(0.7, 1.0, 0.5)) self._draw_dude(3, btn, hoffs, v, scl, position=(xxx + 233, 27), color=(0.7, 0.5, 0.9)) self._draw_dude(1, btn, hoffs, v, scl, position=(xxx + 266, 53), color=(0.4, 0.5, 0.8)) ba.textwidget(parent=self._root_widget, draw_controller=btn, position=(hoffs + scl * (-10), v + scl * 95), size=(scl * button_width, scl * 50), text=ba.Lstr(resource='playModes.freeForAllText', fallback_resource='freeForAllText'), maxwidth=scl * button_width * 0.7, h_align='center', v_align='center', color=(0.7, 0.9, 0.7, 1.0), scale=scl * 1.9) ba.textwidget(parent=self._root_widget, draw_controller=btn, position=(hoffs + scl * (-10), v + (scl * 54)), size=(scl * button_width, scl * 30), text=ba.Lstr(resource=self._r + '.twoToEightPlayersText'), h_align='center', v_align='center', scale=0.9 * scl, flatness=1.0, maxwidth=scl * button_width * 0.7, color=clr) if ba.app.toolbars and ba.app.small_ui: back_button.delete() ba.containerwidget(edit=self._root_widget, on_cancel_call=self._back, selected_child=self._coop_button) else: ba.buttonwidget(edit=back_button, on_activate_call=self._back) ba.containerwidget(edit=self._root_widget, cancel_button=back_button, selected_child=self._coop_button) self._restore_state()
def __init__(self, tournament_id: str, tournament_activity: ba.Activity = None, position: Tuple[float, float] = (0.0, 0.0), delegate: Any = None, scale: float = None, offset: Tuple[float, float] = (0.0, 0.0), on_close_call: Callable[[], Any] = None): # needs some tidying # pylint: disable=too-many-branches # pylint: disable=too-many-statements ba.set_analytics_screen('Tournament Entry Window') self._tournament_id = tournament_id self._tournament_info = (ba.app.tournament_info[self._tournament_id]) # Set a few vars depending on the tourney fee. self._fee = self._tournament_info['fee'] self._allow_ads = self._tournament_info['allowAds'] if self._fee == 4: self._purchase_name = 'tournament_entry_4' self._purchase_price_name = 'price.tournament_entry_4' elif self._fee == 3: self._purchase_name = 'tournament_entry_3' self._purchase_price_name = 'price.tournament_entry_3' elif self._fee == 2: self._purchase_name = 'tournament_entry_2' self._purchase_price_name = 'price.tournament_entry_2' elif self._fee == 1: self._purchase_name = 'tournament_entry_1' self._purchase_price_name = 'price.tournament_entry_1' else: if self._fee != 0: raise Exception("invalid fee: " + str(self._fee)) self._purchase_name = 'tournament_entry_0' self._purchase_price_name = 'price.tournament_entry_0' self._purchase_price: Optional[int] = None self._on_close_call = on_close_call if scale is None: scale = (2.3 if ba.app.small_ui else 1.65 if ba.app.med_ui else 1.23) self._delegate = delegate self._transitioning_out = False self._tournament_activity = tournament_activity self._width = 340 self._height = 220 bg_color = (0.5, 0.4, 0.6) # Creates our root_widget. popup.PopupWindow.__init__(self, position=position, size=(self._width, self._height), scale=scale, bg_color=bg_color, offset=offset, toolbar_visibility='menu_currency') self._last_ad_press_time = -9999.0 self._last_ticket_press_time = -9999.0 self._entering = False self._launched = False # Show the ad button only if we support ads *and* it has a level 1 fee. self._do_ad_btn = (_ba.has_video_ads() and self._allow_ads) x_offs = 0 if self._do_ad_btn else 85 self._cancel_button = ba.buttonwidget(parent=self.root_widget, position=(20, self._height - 30), size=(50, 50), scale=0.5, label='', color=bg_color, on_activate_call=self._on_cancel, autoselect=True, icon=ba.gettexture('crossOut'), iconscale=1.2) self._title_text = ba.textwidget( parent=self.root_widget, position=(self._width * 0.5, self._height - 20), size=(0, 0), h_align='center', v_align='center', scale=0.6, text=ba.Lstr(resource='tournamentEntryText'), maxwidth=200, color=(1, 1, 1, 0.4)) btn = self._pay_with_tickets_button = ba.buttonwidget( parent=self.root_widget, position=(30 + x_offs, 60), autoselect=True, button_type='square', size=(120, 120), label='', on_activate_call=self._on_pay_with_tickets_press) self._ticket_img_pos = (50 + x_offs, 94) self._ticket_img_pos_free = (50 + x_offs, 80) self._ticket_img = ba.imagewidget(parent=self.root_widget, draw_controller=btn, size=(80, 80), position=self._ticket_img_pos, texture=ba.gettexture('tickets')) self._ticket_cost_text_position = (87 + x_offs, 88) self._ticket_cost_text_position_free = (87 + x_offs, 120) self._ticket_cost_text = ba.textwidget( parent=self.root_widget, draw_controller=btn, position=self._ticket_cost_text_position, size=(0, 0), h_align='center', v_align='center', scale=0.6, text='', maxwidth=95, color=(0, 1, 0)) self._free_plays_remaining_text = ba.textwidget( parent=self.root_widget, draw_controller=btn, position=(87 + x_offs, 78), size=(0, 0), h_align='center', v_align='center', scale=0.33, text='', maxwidth=95, color=(0, 0.8, 0)) self._pay_with_ad_btn: Optional[ba.Widget] if self._do_ad_btn: btn = self._pay_with_ad_btn = ba.buttonwidget( parent=self.root_widget, position=(190, 60), autoselect=True, button_type='square', size=(120, 120), label='', on_activate_call=self._on_pay_with_ad_press) self._pay_with_ad_img = ba.imagewidget(parent=self.root_widget, draw_controller=btn, size=(80, 80), position=(210, 94), texture=ba.gettexture('tv')) self._ad_text_position = (251, 88) self._ad_text_position_remaining = (251, 92) have_ad_tries_remaining = ( self._tournament_info['adTriesRemaining'] is not None) self._ad_text = ba.textwidget( parent=self.root_widget, draw_controller=btn, position=self._ad_text_position_remaining if have_ad_tries_remaining else self._ad_text_position, size=(0, 0), h_align='center', v_align='center', scale=0.6, text=ba.Lstr(resource='watchAVideoText', fallback_resource='watchAnAdText'), maxwidth=95, color=(0, 1, 0)) ad_plays_remaining_text = ( '' if not have_ad_tries_remaining else '' + str(self._tournament_info['adTriesRemaining'])) self._ad_plays_remaining_text = ba.textwidget( parent=self.root_widget, draw_controller=btn, position=(251, 78), size=(0, 0), h_align='center', v_align='center', scale=0.33, text=ad_plays_remaining_text, maxwidth=95, color=(0, 0.8, 0)) ba.textwidget(parent=self.root_widget, position=(self._width * 0.5, 120), size=(0, 0), h_align='center', v_align='center', scale=0.6, text=ba.Lstr(resource='orText', subs=[('${A}', ''), ('${B}', '')]), maxwidth=35, color=(1, 1, 1, 0.5)) else: self._pay_with_ad_btn = None self._get_tickets_button: Optional[ba.Widget] if not ba.app.toolbars: self._get_tickets_button = ba.buttonwidget( parent=self.root_widget, position=(self._width - 190 + 110, 15), autoselect=True, scale=0.6, size=(120, 60), textcolor=(0.2, 1, 0.2), label=ba.charstr(ba.SpecialChar.TICKET), color=(0.6, 0.4, 0.7), on_activate_call=self._on_get_tickets_press) else: self._get_tickets_button = None self._seconds_remaining = None ba.containerwidget(edit=self.root_widget, cancel_button=self._cancel_button) # Let's also ask the server for info about this tournament # (time remaining, etc) so we can show the user time remaining, # disallow entry if time has run out, etc. xoffs = 104 if ba.app.toolbars else 0 self._time_remaining_text = ba.textwidget(parent=self.root_widget, position=(70 + xoffs, 23), size=(0, 0), h_align='center', v_align='center', text='-', scale=0.65, maxwidth=100, flatness=1.0, color=(0.7, 0.7, 0.7)) self._time_remaining_label_text = ba.textwidget( parent=self.root_widget, position=(70 + xoffs, 40), size=(0, 0), h_align='center', v_align='center', text=ba.Lstr(resource='coopSelectWindow.timeRemainingText'), scale=0.45, flatness=1.0, maxwidth=100, color=(0.7, 0.7, 0.7)) self._last_query_time: Optional[float] = None # If there seems to be a relatively-recent valid cached info for this # tournament, use it. Otherwise we'll kick off a query ourselves. if (self._tournament_id in ba.app.tournament_info and ba.app.tournament_info[self._tournament_id]['valid'] and (ba.time(ba.TimeType.REAL, ba.TimeFormat.MILLISECONDS) - ba.app.tournament_info[self._tournament_id]['timeReceived'] < 1000 * 60 * 5)): try: info = ba.app.tournament_info[self._tournament_id] self._seconds_remaining = max( 0, info['timeRemaining'] - int( (ba.time(ba.TimeType.REAL, ba.TimeFormat.MILLISECONDS) - info['timeReceived']) / 1000)) self._have_valid_data = True self._last_query_time = ba.time(ba.TimeType.REAL) except Exception: ba.print_exception("error using valid tourney data") self._have_valid_data = False else: self._have_valid_data = False self._fg_state = ba.app.fg_state self._running_query = False self._update_timer = ba.Timer(1.0, ba.WeakCall(self._update), repeat=True, timetype=ba.TimeType.REAL) self._update() self._restore_state()
def __init__(self, title: ba.Lstr, entries: List[Dict[str, Any]], transition: str = 'in_right'): self._width = 600 self._height = 324 if ba.app.small_ui else 400 self._entries = copy.deepcopy(entries) super().__init__(root_widget=ba.containerwidget( size=(self._width, self._height), transition=transition, scale=(2.5 if ba.app.small_ui else 1.2 if ba.app.med_ui else 1.0), stack_offset=(0, -28) if ba.app.small_ui else (0, 0))) self._back_button = btn = ba.buttonwidget( parent=self._root_widget, autoselect=True, position=(65, self._height - 59), 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.textwidget(parent=self._root_widget, position=(self._width * 0.5, self._height - 35), size=(0, 0), color=ba.app.title_color, h_align='center', v_align='center', maxwidth=245, text=title) 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 - 75), size=(0, 0), color=ba.app.infotextcolor, h_align='center', v_align='center', maxwidth=self._width * 0.75, text=ba.Lstr(resource='settingsWindowAdvanced.forTestingText')) ba.containerwidget(edit=self._root_widget, cancel_button=btn) self._scroll_width = self._width - 130 self._scroll_height = self._height - 140 self._scrollwidget = ba.scrollwidget( parent=self._root_widget, size=(self._scroll_width, self._scroll_height), highlight=False, position=((self._width - self._scroll_width) * 0.5, 40)) ba.containerwidget(edit=self._scrollwidget, claims_left_right=True) self._spacing = 50 self._sub_width = self._scroll_width * 0.95 self._sub_height = 50 + len(self._entries) * self._spacing + 60 self._subcontainer = ba.containerwidget(parent=self._scrollwidget, size=(self._sub_width, self._sub_height), background=False) h = 230 v = self._sub_height - 48 for i, entry in enumerate(self._entries): entry_name = entry['name'] # if we haven't yet, record the default value for this name so # we can reset if we want.. if entry_name not in ba.app.value_test_defaults: ba.app.value_test_defaults[entry_name] = ( _ba.value_test(entry_name)) ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), h_align='right', v_align='center', maxwidth=200, text=entry['label']) btn = ba.buttonwidget(parent=self._subcontainer, position=(h + 20, v - 19), size=(40, 40), autoselect=True, repeat=True, left_widget=self._back_button, button_type='square', label='-', on_activate_call=ba.Call( self._on_minus_press, entry['name'])) if i == 0: ba.widget(edit=btn, up_widget=self._back_button) ba.widget(edit=btn, show_buffer_top=20, show_buffer_bottom=20) entry['widget'] = ba.textwidget( parent=self._subcontainer, position=(h + 100, v), size=(0, 0), h_align='center', v_align='center', maxwidth=60, text=str(round(_ba.value_test(entry_name), 4))) btn = ba.buttonwidget(parent=self._subcontainer, position=(h + 140, v - 19), size=(40, 40), autoselect=True, repeat=True, button_type='square', label='+', on_activate_call=ba.Call( self._on_plus_press, entry['name'])) if i == 0: ba.widget(edit=btn, up_widget=self._back_button) v -= self._spacing v -= 35 b_reset = ba.buttonwidget( parent=self._subcontainer, autoselect=True, size=(200, 50), position=(self._sub_width * 0.5 - 100, v), label=ba.Lstr(resource='settingsWindowAdvanced.resetText'), right_widget=btn, on_activate_call=self._on_reset_press) ba.widget(edit=b_reset, show_buffer_top=20, show_buffer_bottom=20)
def __init__(self, existing_profile: Optional[str], in_main_menu: bool, transition: str = 'in_right'): # FIXME: Tidy this up a bit. # pylint: disable=too-many-branches # pylint: disable=too-many-statements # pylint: disable=too-many-locals from ba.internal import get_player_profile_colors self._in_main_menu = in_main_menu self._existing_profile = existing_profile self._r = 'editProfileWindow' self._spazzes: List[str] = [] self._icon_textures: List[ba.Texture] = [] self._icon_tint_textures: List[ba.Texture] = [] # Grab profile colors or pick random ones. self._color, self._highlight = get_player_profile_colors( existing_profile) self._width = width = 780.0 if ba.app.small_ui else 680.0 self._x_inset = x_inset = 50.0 if ba.app.small_ui else 0.0 self._height = height = (350.0 if ba.app.small_ui else 400.0 if ba.app.med_ui else 450.0) spacing = 40 self._base_scale = (2.05 if ba.app.small_ui else 1.5 if ba.app.med_ui else 1.0) top_extra = 15 if ba.app.small_ui else 15 super().__init__(root_widget=ba.containerwidget( size=(width, height + top_extra), transition=transition, scale=self._base_scale, stack_offset=(0, 15) if ba.app.small_ui else (0, 0))) cancel_button = btn = ba.buttonwidget( parent=self._root_widget, position=(52 + x_inset, height - 60), size=(155, 60), scale=0.8, autoselect=True, label=ba.Lstr(resource='cancelText'), on_activate_call=self._cancel) ba.containerwidget(edit=self._root_widget, cancel_button=btn) save_button = btn = ba.buttonwidget(parent=self._root_widget, position=(width - (177 + x_inset), height - 60), size=(155, 60), autoselect=True, scale=0.8, label=ba.Lstr(resource='saveText')) ba.widget(edit=save_button, left_widget=cancel_button) ba.widget(edit=cancel_button, right_widget=save_button) ba.containerwidget(edit=self._root_widget, start_button=btn) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, height - 38), size=(0, 0), text=(ba.Lstr(resource=self._r + '.titleNewText') if existing_profile is None else ba.Lstr( resource=self._r + '.titleEditText')), color=ba.app.title_color, maxwidth=290, scale=1.0, h_align='center', v_align='center') # Make a list of spaz icons. self.refresh_characters() profile = ba.app.config.get('Player Profiles', {}).get(self._existing_profile, {}) if 'global' in profile: self._global = profile['global'] else: self._global = False if 'icon' in profile: self._icon = profile['icon'] else: self._icon = ba.charstr(ba.SpecialChar.LOGO) assigned_random_char = False # Look for existing character choice or pick random one otherwise. try: icon_index = self._spazzes.index(profile['character']) except Exception: # Let's set the default icon to spaz for our first profile; after # that we go random. # (SCRATCH THAT.. we now hard-code account-profiles to start with # spaz which has a similar effect) # try: p_len = len(ba.app.config['Player Profiles']) # except Exception: p_len = 0 # if p_len == 0: icon_index = self._spazzes.index('Spaz') # else: random.seed() icon_index = random.randrange(len(self._spazzes)) assigned_random_char = True self._icon_index = icon_index ba.buttonwidget(edit=save_button, on_activate_call=self.save) v = height - 115.0 self._name = ('' if self._existing_profile is None else self._existing_profile) self._is_account_profile = (self._name == '__account__') # If we just picked a random character, see if it has specific # colors/highlights associated with it and assign them if so. if assigned_random_char: clr = ba.app.spaz_appearances[ self._spazzes[icon_index]].default_color if clr is not None: self._color = clr highlight = ba.app.spaz_appearances[ self._spazzes[icon_index]].default_highlight if highlight is not None: self._highlight = highlight # Assign a random name if they had none. if self._name == '': names = _ba.get_random_names() self._name = names[random.randrange(len(names))] self._clipped_name_text = ba.textwidget(parent=self._root_widget, text='', position=(540 + x_inset, v - 8), flatness=1.0, shadow=0.0, scale=0.55, size=(0, 0), maxwidth=100, h_align='center', v_align='center', color=(1, 1, 0, 0.5)) if not self._is_account_profile and not self._global: ba.textwidget(parent=self._root_widget, text=ba.Lstr(resource=self._r + '.nameText'), position=(200 + x_inset, v - 6), size=(0, 0), h_align='right', v_align='center', color=(1, 1, 1, 0.5), scale=0.9) self._upgrade_button = None if self._is_account_profile: if _ba.get_account_state() == 'signed_in': sval = _ba.get_account_display_string() else: sval = '??' ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, v - 7), size=(0, 0), scale=1.2, text=sval, maxwidth=270, h_align='center', v_align='center') txtl = ba.Lstr( resource='editProfileWindow.accountProfileText').evaluate() b_width = min( 270.0, _ba.get_string_width(txtl, suppress_warning=True) * 0.6) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, v - 39), size=(0, 0), scale=0.6, color=ba.app.infotextcolor, text=txtl, maxwidth=270, h_align='center', v_align='center') self._account_type_info_button = ba.buttonwidget( parent=self._root_widget, label='?', size=(15, 15), text_scale=0.6, position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47), button_type='square', color=(0.6, 0.5, 0.65), autoselect=True, on_activate_call=self.show_account_profile_info) elif self._global: b_size = 60 self._icon_button = btn = ba.buttonwidget( parent=self._root_widget, autoselect=True, position=(self._width * 0.5 - 160 - b_size * 0.5, v - 38 - 15), size=(b_size, b_size), color=(0.6, 0.5, 0.6), label='', button_type='square', text_scale=1.2, on_activate_call=self._on_icon_press) self._icon_button_label = ba.textwidget( parent=self._root_widget, position=(self._width * 0.5 - 160, v - 35), draw_controller=btn, h_align='center', v_align='center', size=(0, 0), color=(1, 1, 1), text='', scale=2.0) ba.textwidget(parent=self._root_widget, h_align='center', v_align='center', position=(self._width * 0.5 - 160, v - 55 - 15), size=(0, 0), draw_controller=btn, text=ba.Lstr(resource=self._r + '.iconText'), scale=0.7, color=ba.app.title_color, maxwidth=120) self._update_icon() ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, v - 7), size=(0, 0), scale=1.2, text=self._name, maxwidth=240, h_align='center', v_align='center') # FIXME hard coded strings are bad txtl = ba.Lstr( resource='editProfileWindow.globalProfileText').evaluate() b_width = min( 240.0, _ba.get_string_width(txtl, suppress_warning=True) * 0.6) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, v - 39), size=(0, 0), scale=0.6, color=ba.app.infotextcolor, text=txtl, maxwidth=240, h_align='center', v_align='center') self._account_type_info_button = ba.buttonwidget( parent=self._root_widget, label='?', size=(15, 15), text_scale=0.6, position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47), button_type='square', color=(0.6, 0.5, 0.65), autoselect=True, on_activate_call=self.show_global_profile_info) else: self._text_field = ba.textwidget( parent=self._root_widget, position=(220 + x_inset, v - 30), size=(265, 40), text=self._name, h_align='left', v_align='center', max_chars=16, description=ba.Lstr(resource=self._r + '.nameDescriptionText'), autoselect=True, editable=True, padding=4, color=(0.9, 0.9, 0.9, 1.0), on_return_press_call=ba.Call(save_button.activate)) # FIXME hard coded strings are bad txtl = ba.Lstr( resource='editProfileWindow.localProfileText').evaluate() b_width = min( 270.0, _ba.get_string_width(txtl, suppress_warning=True) * 0.6) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, v - 43), size=(0, 0), scale=0.6, color=ba.app.infotextcolor, text=txtl, maxwidth=270, h_align='center', v_align='center') self._account_type_info_button = ba.buttonwidget( parent=self._root_widget, label='?', size=(15, 15), text_scale=0.6, position=(self._width * 0.5 + b_width * 0.5 + 13, v - 50), button_type='square', color=(0.6, 0.5, 0.65), autoselect=True, on_activate_call=self.show_local_profile_info) self._upgrade_button = ba.buttonwidget( parent=self._root_widget, label=ba.Lstr(resource='upgradeText'), size=(40, 17), text_scale=1.0, button_type='square', position=(self._width * 0.5 + b_width * 0.5 + 13 + 43, v - 51), color=(0.6, 0.5, 0.65), autoselect=True, on_activate_call=self.upgrade_profile) self._update_clipped_name() self._clipped_name_timer = ba.Timer(0.333, ba.WeakCall( self._update_clipped_name), timetype=ba.TimeType.REAL, repeat=True) v -= spacing * 3.0 b_size = 80 b_size_2 = 100 b_offs = 150 self._color_button = btn = ba.buttonwidget( parent=self._root_widget, autoselect=True, position=(self._width * 0.5 - b_offs - b_size * 0.5, v - 50), size=(b_size, b_size), color=self._color, label='', button_type='square') origin = self._color_button.get_screen_space_center() ba.buttonwidget(edit=self._color_button, on_activate_call=ba.WeakCall(self._make_picker, 'color', origin)) ba.textwidget(parent=self._root_widget, h_align='center', v_align='center', position=(self._width * 0.5 - b_offs, v - 65), size=(0, 0), draw_controller=btn, text=ba.Lstr(resource=self._r + '.colorText'), scale=0.7, color=ba.app.title_color, maxwidth=120) self._character_button = btn = ba.buttonwidget( parent=self._root_widget, autoselect=True, position=(self._width * 0.5 - b_size_2 * 0.5, v - 60), up_widget=self._account_type_info_button, on_activate_call=self._on_character_press, size=(b_size_2, b_size_2), label='', color=(1, 1, 1), mask_texture=ba.gettexture('characterIconMask')) if not self._is_account_profile and not self._global: ba.containerwidget(edit=self._root_widget, selected_child=self._text_field) ba.textwidget(parent=self._root_widget, h_align='center', v_align='center', position=(self._width * 0.5, v - 80), size=(0, 0), draw_controller=btn, text=ba.Lstr(resource=self._r + '.characterText'), scale=0.7, color=ba.app.title_color, maxwidth=130) self._highlight_button = btn = ba.buttonwidget( parent=self._root_widget, autoselect=True, position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50), up_widget=self._upgrade_button if self._upgrade_button is not None else self._account_type_info_button, size=(b_size, b_size), color=self._highlight, label='', button_type='square') if not self._is_account_profile and not self._global: ba.widget(edit=cancel_button, down_widget=self._text_field) ba.widget(edit=save_button, down_widget=self._text_field) ba.widget(edit=self._color_button, up_widget=self._text_field) ba.widget(edit=self._account_type_info_button, down_widget=self._character_button) origin = self._highlight_button.get_screen_space_center() ba.buttonwidget(edit=self._highlight_button, on_activate_call=ba.WeakCall(self._make_picker, 'highlight', origin)) ba.textwidget(parent=self._root_widget, h_align='center', v_align='center', position=(self._width * 0.5 + b_offs, v - 65), size=(0, 0), draw_controller=btn, text=ba.Lstr(resource=self._r + '.highlightText'), scale=0.7, color=ba.app.title_color, maxwidth=120) self._update_character()
def _build_host_tab(self) -> None: # pylint: disable=too-many-branches # pylint: disable=too-many-statements if _ba.get_account_state() != 'signed_in': ba.textwidget(parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=200, scale=0.8, color=(0.6, 0.56, 0.6), position=(self._c_width * 0.5, self._c_height * 0.5), text=ba.Lstr(resource='notSignedInErrorText')) self._showing_not_signed_in_screen = True return self._showing_not_signed_in_screen = False # At first we don't want to show anything until we've gotten a state. # Update: In this situation we now simply show our existing state # but give the start/stop button a loading message and disallow its # use. This keeps things a lot less jumpy looking and allows selecting # playlists/etc without having to wait for the server each time # back to the ui. if self._waiting_for_initial_state and bool(False): ba.textwidget( parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=200, scale=0.8, color=(0.6, 0.56, 0.6), position=(self._c_width * 0.5, self._c_height * 0.5), text=ba.Lstr( value='${A}...', subs=[('${A}', ba.Lstr(resource='store.loadingText'))], ), ) return # If we're not currently hosting and hosting requires tickets, # Show our count (possibly with a link to purchase more). if (not self._waiting_for_initial_state and self._hostingstate.party_code is None and self._hostingstate.tickets_to_host_now != 0): if not ba.app.ui.use_toolbars: if ba.app.allow_ticket_purchases: self._get_tickets_button = ba.buttonwidget( parent=self._container, position=(self._c_width - 210 + 125, self._c_height - 44), autoselect=True, scale=0.6, size=(120, 60), textcolor=(0.2, 1, 0.2), label=ba.charstr(ba.SpecialChar.TICKET), color=(0.65, 0.5, 0.8), on_activate_call=self._on_get_tickets_press) else: self._ticket_count_text = ba.textwidget( parent=self._container, scale=0.6, position=(self._c_width - 210 + 125, self._c_height - 44), color=(0.2, 1, 0.2), h_align='center', v_align='center') # Set initial ticket count. self._update_currency_ui() v = self._c_height - 90 if self._hostingstate.party_code is None: ba.textwidget( parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=self._c_width * 0.9, scale=0.7, flatness=1.0, color=(0.5, 0.46, 0.5), position=(self._c_width * 0.5, v), text=ba.Lstr( resource='gatherWindow.privatePartyCloudDescriptionText')) v -= 100 if self._hostingstate.party_code is None: # We've got no current party running; show options to set one up. ba.textwidget(parent=self._container, size=(0, 0), h_align='right', v_align='center', maxwidth=200, scale=0.8, color=(0.6, 0.56, 0.6), position=(self._c_width * 0.5 - 210, v), text=ba.Lstr(resource='playlistText')) self._host_playlist_button = ba.buttonwidget( parent=self._container, size=(400, 70), color=(0.6, 0.5, 0.6), textcolor=(0.8, 0.75, 0.8), label=self._hostingconfig.playlist_name, on_activate_call=self._playlist_press, position=(self._c_width * 0.5 - 200, v - 35), up_widget=self._host_sub_tab_text, autoselect=True) # If it appears we're coming back from playlist selection, # re-select our playlist button. if ba.app.ui.selecting_private_party_playlist: ba.containerwidget(edit=self._container, selected_child=self._host_playlist_button) ba.app.ui.selecting_private_party_playlist = False else: # We've got a current party; show its info. ba.textwidget( parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=600, scale=0.9, color=(0.7, 0.64, 0.7), position=(self._c_width * 0.5, v + 90), text=ba.Lstr(resource='gatherWindow.partyServerRunningText')) ba.textwidget(parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=600, scale=0.7, color=(0.7, 0.64, 0.7), position=(self._c_width * 0.5, v + 50), text=ba.Lstr(resource='gatherWindow.partyCodeText')) ba.textwidget(parent=self._container, size=(0, 0), h_align='center', v_align='center', scale=2.0, color=(0.0, 1.0, 0.0), position=(self._c_width * 0.5, v + 10), text=self._hostingstate.party_code) # Also action buttons to copy it and connect to it. if ba.clipboard_is_supported(): cbtnoffs = 10 self._host_copy_button = ba.buttonwidget( parent=self._container, size=(140, 40), color=(0.6, 0.5, 0.6), textcolor=(0.8, 0.75, 0.8), label=ba.Lstr(resource='gatherWindow.copyCodeText'), on_activate_call=self._host_copy_press, position=(self._c_width * 0.5 - 150, v - 70), autoselect=True) else: cbtnoffs = -70 self._host_connect_button = ba.buttonwidget( parent=self._container, size=(140, 40), color=(0.6, 0.5, 0.6), textcolor=(0.8, 0.75, 0.8), label=ba.Lstr(resource='gatherWindow.manualConnectText'), on_activate_call=self._host_connect_press, position=(self._c_width * 0.5 + cbtnoffs, v - 70), autoselect=True) v -= 120 # Line above the main action button: # If we don't want to show anything until we get a state: if self._waiting_for_initial_state: pass elif self._hostingstate.unavailable_error is not None: # If hosting is unavailable, show the associated reason. ba.textwidget( parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=self._c_width * 0.9, scale=0.7, flatness=1.0, color=(1.0, 0.0, 0.0), position=(self._c_width * 0.5, v), text=ba.Lstr(translate=('serverResponses', self._hostingstate.unavailable_error))) elif self._hostingstate.free_host_minutes_remaining is not None: # If we've been pre-approved to start/stop for free, show that. ba.textwidget( parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=self._c_width * 0.9, scale=0.7, flatness=1.0, color=((0.7, 0.64, 0.7) if self._hostingstate.party_code else (0.0, 1.0, 0.0)), position=(self._c_width * 0.5, v), text=ba.Lstr( resource='gatherWindow.startStopHostingMinutesText', subs=[( '${MINUTES}', f'{self._hostingstate.free_host_minutes_remaining:.0f}' )])) else: # Otherwise tell whether the free cloud server is available # or will be at some point. if self._hostingstate.party_code is None: if self._hostingstate.tickets_to_host_now == 0: ba.textwidget( parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=self._c_width * 0.9, scale=0.7, flatness=1.0, color=(0.0, 1.0, 0.0), position=(self._c_width * 0.5, v), text=ba.Lstr( resource= 'gatherWindow.freeCloudServerAvailableNowText')) else: if self._hostingstate.minutes_until_free_host is None: ba.textwidget( parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=self._c_width * 0.9, scale=0.7, flatness=1.0, color=(1.0, 0.6, 0.0), position=(self._c_width * 0.5, v), text=ba.Lstr( resource= 'gatherWindow.freeCloudServerNotAvailableText') ) else: availmins = self._hostingstate.minutes_until_free_host ba.textwidget( parent=self._container, size=(0, 0), h_align='center', v_align='center', maxwidth=self._c_width * 0.9, scale=0.7, flatness=1.0, color=(1.0, 0.6, 0.0), position=(self._c_width * 0.5, v), text=ba.Lstr(resource='gatherWindow.' 'freeCloudServerAvailableMinutesText', subs=[('${MINUTES}', f'{availmins:.0f}')])) v -= 100 if (self._waiting_for_start_stop_response or self._waiting_for_initial_state): btnlabel = ba.Lstr(resource='oneMomentText') else: if self._hostingstate.unavailable_error is not None: btnlabel = ba.Lstr( resource='gatherWindow.hostingUnavailableText') elif self._hostingstate.party_code is None: ticon = _ba.charstr(ba.SpecialChar.TICKET) nowtickets = self._hostingstate.tickets_to_host_now if nowtickets > 0: btnlabel = ba.Lstr( resource='gatherWindow.startHostingPaidText', subs=[('${COST}', f'{ticon}{nowtickets}')]) else: btnlabel = ba.Lstr( resource='gatherWindow.startHostingText') else: btnlabel = ba.Lstr(resource='gatherWindow.stopHostingText') disabled = (self._hostingstate.unavailable_error is not None or self._waiting_for_initial_state) waiting = self._waiting_for_start_stop_response self._host_start_stop_button = ba.buttonwidget( parent=self._container, size=(400, 80), color=((0.6, 0.6, 0.6) if disabled else (0.5, 1.0, 0.5) if waiting else None), enable_sound=False, label=btnlabel, textcolor=((0.7, 0.7, 0.7) if disabled else None), position=(self._c_width * 0.5 - 200, v), on_activate_call=self._start_stop_button_press, autoselect=True)
def update_buttons(self) -> None: """Update our buttons.""" # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals from ba.internal import have_pro, get_available_sale_time from ba import SpecialChar if not self._root_widget: return import datetime sales_raw = _ba.get_account_misc_read_val('sales', {}) sales = {} try: # Look at the current set of sales; filter any with time remaining. for sale_item, sale_info in list(sales_raw.items()): to_end = (datetime.datetime.utcfromtimestamp(sale_info['e']) - datetime.datetime.utcnow()).total_seconds() if to_end > 0: sales[sale_item] = { 'to_end': to_end, 'original_price': sale_info['op'] } except Exception: ba.print_exception('Error parsing sales.') assert self.button_infos is not None for b_type, b_info in self.button_infos.items(): if b_type in ['upgrades.pro', 'pro']: purchased = have_pro() else: purchased = _ba.get_purchased(b_type) sale_opacity = 0.0 sale_title_text: Union[str, ba.Lstr] = '' sale_time_text: Union[str, ba.Lstr] = '' if purchased: title_color = (0.8, 0.7, 0.9, 1.0) color = (0.63, 0.55, 0.78) extra_image_opacity = 0.5 call = ba.WeakCall(self._print_already_own, b_info['name']) price_text = '' price_text_left = '' price_text_right = '' show_purchase_check = True description_color: Sequence[float] = (0.4, 1.0, 0.4, 0.4) description_color2: Sequence[float] = (0.0, 0.0, 0.0, 0.0) price_color = (0.5, 1, 0.5, 0.3) else: title_color = (0.7, 0.9, 0.7, 1.0) color = (0.4, 0.8, 0.1) extra_image_opacity = 1.0 call = b_info['call'] if 'call' in b_info else None if b_type in ['upgrades.pro', 'pro']: sale_time = get_available_sale_time('extras') if sale_time is not None: priceraw = _ba.get_price('pro') price_text_left = (priceraw if priceraw is not None else '?') priceraw = _ba.get_price('pro_sale') price_text_right = (priceraw if priceraw is not None else '?') sale_opacity = 1.0 price_text = '' sale_title_text = ba.Lstr(resource='store.saleText') sale_time_text = ba.timestring( sale_time, centi=False, timeformat=ba.TimeFormat.MILLISECONDS) else: priceraw = _ba.get_price('pro') price_text = priceraw if priceraw is not None else '?' price_text_left = '' price_text_right = '' else: price = _ba.get_account_misc_read_val('price.' + b_type, 0) # Color the button differently if we cant afford this. if _ba.get_account_state() == 'signed_in': if _ba.get_account_ticket_count() < price: color = (0.6, 0.61, 0.6) price_text = ba.charstr(ba.SpecialChar.TICKET) + str( _ba.get_account_misc_read_val('price.' + b_type, '?')) price_text_left = '' price_text_right = '' # TESTING: if b_type in sales: sale_opacity = 1.0 price_text_left = ba.charstr(SpecialChar.TICKET) + str( sales[b_type]['original_price']) price_text_right = price_text price_text = '' sale_title_text = ba.Lstr(resource='store.saleText') sale_time_text = ba.timestring( int(sales[b_type]['to_end'] * 1000), centi=False, timeformat=ba.TimeFormat.MILLISECONDS) description_color = (0.5, 1.0, 0.5) description_color2 = (0.3, 1.0, 1.0) price_color = (0.2, 1, 0.2, 1.0) show_purchase_check = False if 'title_text' in b_info: ba.textwidget(edit=b_info['title_text'], color=title_color) if 'purchase_check' in b_info: ba.imagewidget(edit=b_info['purchase_check'], opacity=1.0 if show_purchase_check else 0.0) if 'price_widget' in b_info: ba.textwidget(edit=b_info['price_widget'], text=price_text, color=price_color) if 'price_widget_left' in b_info: ba.textwidget(edit=b_info['price_widget_left'], text=price_text_left) if 'price_widget_right' in b_info: ba.textwidget(edit=b_info['price_widget_right'], text=price_text_right) if 'price_slash_widget' in b_info: ba.imagewidget(edit=b_info['price_slash_widget'], opacity=sale_opacity) if 'sale_bg_widget' in b_info: ba.imagewidget(edit=b_info['sale_bg_widget'], opacity=sale_opacity) if 'sale_title_widget' in b_info: ba.textwidget(edit=b_info['sale_title_widget'], text=sale_title_text) if 'sale_time_widget' in b_info: ba.textwidget(edit=b_info['sale_time_widget'], text=sale_time_text) if 'button' in b_info: ba.buttonwidget(edit=b_info['button'], color=color, on_activate_call=call) if 'extra_backings' in b_info: for bck in b_info['extra_backings']: ba.imagewidget(edit=bck, color=color, opacity=extra_image_opacity) if 'extra_images' in b_info: for img in b_info['extra_images']: ba.imagewidget(edit=img, opacity=extra_image_opacity) if 'extra_texts' in b_info: for etxt in b_info['extra_texts']: ba.textwidget(edit=etxt, color=description_color) if 'extra_texts_2' in b_info: for etxt in b_info['extra_texts_2']: ba.textwidget(edit=etxt, color=description_color2) if 'descriptionText' in b_info: ba.textwidget(edit=b_info['descriptionText'], color=description_color)
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.ui.set_main_menu_location('Team Game Select') ba.set_analytics_screen('Teams Window') elif issubclass(sessiontype, ba.FreeForAllSession): ba.app.ui.set_main_menu_location('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.ui.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.ui.heading_color, h_align='center', v_align='center') if uiscale is ba.UIScale.SMALL and ba.app.ui.use_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.ui.use_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.ui.use_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)
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._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_account_state() == 'signed_in') self._account_state_num = _ba.get_account_state_num() self._show_linked = (self._signed_in and _ba.get_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_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') 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()
def __init__(self, transition: str = 'in_right', modal: bool = False, origin_widget: ba.Widget = None): 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 uiscale = ba.app.ui.uiscale self._width = 1320 if uiscale is ba.UIScale.SMALL else 1120 x_inset = 100 if uiscale is ba.UIScale.SMALL else 0 self._height = (657 if uiscale is ba.UIScale.SMALL else 710 if uiscale is ba.UIScale.MEDIUM else 800) self._r = 'coopSelectWindow' self._rdict = ba.app.lang.get_resource(self._r) top_extra = 20 if uiscale is ba.UIScale.SMALL 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 uiscale is ba.UIScale.SMALL else ( 0, 10) if uiscale is ba.UIScale.MEDIUM else (0, 0), transition=transition, scale_origin_stack_offset=scale_origin, scale=(1.2 if uiscale is ba.UIScale.SMALL else 0.93 if uiscale is ba.UIScale.MEDIUM else 0.8))) self._back_button = btn = ba.buttonwidget( parent=self._root_widget, position=(75 + x_inset, self._height - 87 - (4 if uiscale is ba.UIScale.SMALL 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.ui.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 uiscale is ba.UIScale.SMALL 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 = ba.app.accounts.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))
def __init__(self, transition: str = 'in_right', origin_widget: ba.Widget = None): # pylint: disable=too-many-statements # pylint: disable=too-many-locals # pylint: disable=cyclic-import from bastd.ui.popup import PopupMenu from bastd.ui.config import ConfigNumberEdit music = ba.app.music # If they provided an origin-widget, scale up from that. scale_origin: Optional[Tuple[float, float]] if origin_widget is not None: self._transition_out = 'out_scale' scale_origin = origin_widget.get_screen_space_center() transition = 'in_scale' else: self._transition_out = 'out_right' scale_origin = None self._r = 'audioSettingsWindow' spacing = 50.0 width = 460.0 height = 210.0 # Update: hard-coding head-relative audio to true now, # so not showing options. # show_vr_head_relative_audio = True if ba.app.vr_mode else False show_vr_head_relative_audio = False if show_vr_head_relative_audio: height += 70 show_soundtracks = False if music.have_music_player(): show_soundtracks = True height += spacing * 2.0 uiscale = ba.app.uiscale base_scale = (2.05 if uiscale is ba.UIScale.SMALL else 1.6 if uiscale is ba.UIScale.MEDIUM else 1.0) popup_menu_scale = base_scale * 1.2 super().__init__(root_widget=ba.containerwidget( size=(width, height), transition=transition, scale=base_scale, scale_origin_stack_offset=scale_origin, stack_offset=(0, -20) if uiscale is ba.UIScale.SMALL else (0, 0))) self._back_button = back_button = btn = ba.buttonwidget( parent=self._root_widget, position=(35, height - 55), size=(120, 60), scale=0.8, text_scale=1.2, label=ba.Lstr(resource='backText'), button_type='back', on_activate_call=self._back, autoselect=True) ba.containerwidget(edit=self._root_widget, cancel_button=btn) v = height - 60 v -= spacing * 1.0 ba.textwidget(parent=self._root_widget, position=(width * 0.5, height - 32), size=(0, 0), text=ba.Lstr(resource=self._r + '.titleText'), color=ba.app.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.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()
def _refresh(self) -> None: # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals # pylint: disable=cyclic-import from bastd.ui import confirm account_state = _ba.get_account_state() account_type = (_ba.get_account_type() if account_state == 'signed_in' else 'unknown') is_google = account_type == 'Google Play' show_local_signed_in_as = False local_signed_in_as_space = 50.0 show_signed_in_as = self._signed_in signed_in_as_space = 95.0 show_sign_in_benefits = not self._signed_in sign_in_benefits_space = 80.0 show_signing_in_text = account_state == 'signing_in' signing_in_text_space = 80.0 show_google_play_sign_in_button = (account_state == 'signed_out' and 'Google Play' in self._show_sign_in_buttons) show_game_circle_sign_in_button = (account_state == 'signed_out' and 'Game Circle' in self._show_sign_in_buttons) show_ali_sign_in_button = (account_state == 'signed_out' and 'Ali' in self._show_sign_in_buttons) show_test_sign_in_button = (account_state == 'signed_out' and 'Test' in self._show_sign_in_buttons) show_device_sign_in_button = (account_state == 'signed_out' and 'Local' in self._show_sign_in_buttons) sign_in_button_space = 70.0 show_game_service_button = (self._signed_in and account_type in ['Game Center', 'Game Circle']) game_service_button_space = 60.0 show_linked_accounts_text = (self._signed_in and _ba.get_account_misc_read_val( 'allowAccountLinking2', False)) linked_accounts_text_space = 60.0 show_achievements_button = (self._signed_in and account_type in ('Google Play', 'Alibaba', 'Local', 'OUYA', 'Test')) achievements_button_space = 60.0 show_achievements_text = (self._signed_in and not show_achievements_button) achievements_text_space = 27.0 show_leaderboards_button = (self._signed_in and is_google) leaderboards_button_space = 60.0 show_campaign_progress = self._signed_in campaign_progress_space = 27.0 show_tickets = self._signed_in tickets_space = 27.0 show_reset_progress_button = False reset_progress_button_space = 70.0 show_player_profiles_button = self._signed_in player_profiles_button_space = 100.0 show_link_accounts_button = (self._signed_in and _ba.get_account_misc_read_val( 'allowAccountLinking2', False)) link_accounts_button_space = 70.0 show_unlink_accounts_button = show_link_accounts_button unlink_accounts_button_space = 90.0 show_sign_out_button = (self._signed_in and account_type in ['Test', 'Local', 'Google Play']) sign_out_button_space = 70.0 if self._subcontainer is not None: self._subcontainer.delete() self._sub_height = 60.0 if show_local_signed_in_as: self._sub_height += local_signed_in_as_space if show_signed_in_as: self._sub_height += signed_in_as_space if show_signing_in_text: self._sub_height += signing_in_text_space if show_google_play_sign_in_button: self._sub_height += sign_in_button_space if show_game_circle_sign_in_button: self._sub_height += sign_in_button_space if show_ali_sign_in_button: self._sub_height += sign_in_button_space if show_test_sign_in_button: self._sub_height += sign_in_button_space if show_device_sign_in_button: self._sub_height += sign_in_button_space if show_game_service_button: self._sub_height += game_service_button_space if show_linked_accounts_text: self._sub_height += linked_accounts_text_space if show_achievements_text: self._sub_height += achievements_text_space if show_achievements_button: self._sub_height += achievements_button_space if show_leaderboards_button: self._sub_height += leaderboards_button_space if show_campaign_progress: self._sub_height += campaign_progress_space if show_tickets: self._sub_height += tickets_space if show_sign_in_benefits: self._sub_height += sign_in_benefits_space if show_reset_progress_button: self._sub_height += reset_progress_button_space if show_player_profiles_button: self._sub_height += player_profiles_button_space if show_link_accounts_button: self._sub_height += link_accounts_button_space if show_unlink_accounts_button: self._sub_height += unlink_accounts_button_space if show_sign_out_button: self._sub_height += sign_out_button_space self._subcontainer = ba.containerwidget(parent=self._scrollwidget, size=(self._sub_width, self._sub_height), background=False, claims_left_right=True, claims_tab=True, selection_loops_to_parent=True) first_selectable = None v = self._sub_height - 10.0 if show_local_signed_in_as: v -= local_signed_in_as_space * 0.6 ba.textwidget( parent=self._subcontainer, position=(self._sub_width * 0.5, v), size=(0, 0), text=ba.Lstr( resource='accountSettingsWindow.deviceSpecificAccountText', subs=[('${NAME}', _ba.get_account_display_string())]), scale=0.7, color=(0.5, 0.5, 0.6), maxwidth=self._sub_width * 0.9, flatness=1.0, h_align='center', v_align='center') v -= local_signed_in_as_space * 0.4 self._account_name_text: Optional[ba.Widget] if show_signed_in_as: v -= signed_in_as_space * 0.2 txt = ba.Lstr( resource='accountSettingsWindow.youAreSignedInAsText', fallback_resource='accountSettingsWindow.youAreLoggedInAsText') ba.textwidget(parent=self._subcontainer, position=(self._sub_width * 0.5, v), size=(0, 0), text=txt, scale=0.9, color=ba.app.ui.title_color, maxwidth=self._sub_width * 0.9, h_align='center', v_align='center') v -= signed_in_as_space * 0.4 self._account_name_text = ba.textwidget( parent=self._subcontainer, position=(self._sub_width * 0.5, v), size=(0, 0), scale=1.5, maxwidth=self._sub_width * 0.9, res_scale=1.5, color=(1, 1, 1, 1), h_align='center', v_align='center') self._refresh_account_name_text() v -= signed_in_as_space * 0.4 else: self._account_name_text = None if self._back_button is None: bbtn = _ba.get_special_widget('back_button') else: bbtn = self._back_button if show_sign_in_benefits: v -= sign_in_benefits_space app = ba.app extra: Optional[Union[str, ba.Lstr]] if (app.platform in ['mac', 'ios'] and app.subplatform == 'appstore'): extra = ba.Lstr( value='\n${S}', subs=[('${S}', ba.Lstr(resource='signInWithGameCenterText'))]) else: extra = '' ba.textwidget(parent=self._subcontainer, position=(self._sub_width * 0.5, v + sign_in_benefits_space * 0.4), size=(0, 0), text=ba.Lstr(value='${A}${B}', subs=[('${A}', ba.Lstr(resource=self._r + '.signInInfoText')), ('${B}', extra)]), max_height=sign_in_benefits_space * 0.9, scale=0.9, color=(0.75, 0.7, 0.8), maxwidth=self._sub_width * 0.8, h_align='center', v_align='center') if show_signing_in_text: v -= signing_in_text_space ba.textwidget( parent=self._subcontainer, position=(self._sub_width * 0.5, v + signing_in_text_space * 0.5), size=(0, 0), text=ba.Lstr(resource='accountSettingsWindow.signingInText'), scale=0.9, color=(0, 1, 0), maxwidth=self._sub_width * 0.8, h_align='center', v_align='center') if show_google_play_sign_in_button: button_width = 350 v -= sign_in_button_space self._sign_in_google_play_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v - 20), autoselect=True, size=(button_width, 60), label=ba.Lstr( value='${A}${B}', subs=[('${A}', ba.charstr(ba.SpecialChar.GOOGLE_PLAY_GAMES_LOGO)), ('${B}', ba.Lstr(resource=self._r + '.signInWithGooglePlayText'))]), on_activate_call=lambda: self._sign_in_press('Google Play')) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn) ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100) self._sign_in_text = None if show_game_circle_sign_in_button: button_width = 350 v -= sign_in_button_space self._sign_in_game_circle_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v - 20), autoselect=True, size=(button_width, 60), label=ba.Lstr(value='${A}${B}', subs=[('${A}', ba.charstr( ba.SpecialChar.GAME_CIRCLE_LOGO)), ('${B}', ba.Lstr(resource=self._r + '.signInWithGameCircleText'))]), on_activate_call=lambda: self._sign_in_press('Game Circle')) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn) ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100) self._sign_in_text = None if show_ali_sign_in_button: button_width = 350 v -= sign_in_button_space self._sign_in_ali_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v - 20), autoselect=True, size=(button_width, 60), label=ba.Lstr(value='${A}${B}', subs=[('${A}', ba.charstr(ba.SpecialChar.ALIBABA_LOGO)), ('${B}', ba.Lstr(resource=self._r + '.signInText')) ]), on_activate_call=lambda: self._sign_in_press('Ali')) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn) ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100) self._sign_in_text = None if show_device_sign_in_button: button_width = 350 v -= sign_in_button_space self._sign_in_device_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v - 20), autoselect=True, size=(button_width, 60), label='', on_activate_call=lambda: self._sign_in_press('Local')) ba.textwidget(parent=self._subcontainer, draw_controller=btn, h_align='center', v_align='center', size=(0, 0), position=(self._sub_width * 0.5, v + 17), text=ba.Lstr( value='${A}${B}', subs=[('${A}', ba.charstr(ba.SpecialChar.LOCAL_ACCOUNT)), ('${B}', ba.Lstr(resource=self._r + '.signInWithDeviceText'))]), maxwidth=button_width * 0.8, color=(0.75, 1.0, 0.7)) ba.textwidget(parent=self._subcontainer, draw_controller=btn, h_align='center', v_align='center', size=(0, 0), position=(self._sub_width * 0.5, v - 4), text=ba.Lstr(resource=self._r + '.signInWithDeviceInfoText'), flatness=1.0, scale=0.57, maxwidth=button_width * 0.9, color=(0.55, 0.8, 0.5)) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn) ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100) self._sign_in_text = None # Old test-account option. if show_test_sign_in_button: button_width = 350 v -= sign_in_button_space self._sign_in_test_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v - 20), autoselect=True, size=(button_width, 60), label='', on_activate_call=lambda: self._sign_in_press('Test')) ba.textwidget(parent=self._subcontainer, draw_controller=btn, h_align='center', v_align='center', size=(0, 0), position=(self._sub_width * 0.5, v + 17), text=ba.Lstr( value='${A}${B}', subs=[('${A}', ba.charstr(ba.SpecialChar.TEST_ACCOUNT)), ('${B}', ba.Lstr(resource=self._r + '.signInWithTestAccountText'))]), maxwidth=button_width * 0.8, color=(0.75, 1.0, 0.7)) ba.textwidget(parent=self._subcontainer, draw_controller=btn, h_align='center', v_align='center', size=(0, 0), position=(self._sub_width * 0.5, v - 4), text=ba.Lstr(resource=self._r + '.signInWithTestAccountInfoText'), flatness=1.0, scale=0.57, maxwidth=button_width * 0.9, color=(0.55, 0.8, 0.5)) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn) ba.widget(edit=btn, show_buffer_bottom=40, show_buffer_top=100) self._sign_in_text = None if show_player_profiles_button: button_width = 300 v -= player_profiles_button_space self._player_profiles_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v + 30), autoselect=True, size=(button_width, 60), label=ba.Lstr(resource='playerProfilesWindow.titleText'), color=(0.55, 0.5, 0.6), icon=ba.gettexture('cuteSpaz'), textcolor=(0.75, 0.7, 0.8), on_activate_call=self._player_profiles_press) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=0) # the button to go to OS-Specific leaderboards/high-score-lists/etc. if show_game_service_button: button_width = 300 v -= game_service_button_space * 0.85 account_type = _ba.get_account_type() if account_type == 'Game Center': account_type_name = ba.Lstr(resource='gameCenterText') elif account_type == 'Game Circle': account_type_name = ba.Lstr(resource='gameCircleText') else: raise ValueError("unknown account type: '" + str(account_type) + "'") self._game_service_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v), color=(0.55, 0.5, 0.6), textcolor=(0.75, 0.7, 0.8), autoselect=True, on_activate_call=_ba.show_online_score_ui, size=(button_width, 50), label=account_type_name) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn) v -= game_service_button_space * 0.15 else: self.game_service_button = None self._achievements_text: Optional[ba.Widget] if show_achievements_text: v -= achievements_text_space * 0.5 self._achievements_text = ba.textwidget( parent=self._subcontainer, position=(self._sub_width * 0.5, v), size=(0, 0), scale=0.9, color=(0.75, 0.7, 0.8), maxwidth=self._sub_width * 0.8, h_align='center', v_align='center') v -= achievements_text_space * 0.5 else: self._achievements_text = None self._achievements_button: Optional[ba.Widget] if show_achievements_button: button_width = 300 v -= achievements_button_space * 0.85 self._achievements_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v), color=(0.55, 0.5, 0.6), textcolor=(0.75, 0.7, 0.8), autoselect=True, icon=ba.gettexture('googlePlayAchievementsIcon' if is_google else 'achievementsIcon'), icon_color=(0.8, 0.95, 0.7) if is_google else (0.85, 0.8, 0.9), on_activate_call=self._on_achievements_press, size=(button_width, 50), label='') if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn) v -= achievements_button_space * 0.15 else: self._achievements_button = None if show_achievements_text or show_achievements_button: self._refresh_achievements() self._leaderboards_button: Optional[ba.Widget] if show_leaderboards_button: button_width = 300 v -= leaderboards_button_space * 0.85 self._leaderboards_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v), color=(0.55, 0.5, 0.6), textcolor=(0.75, 0.7, 0.8), autoselect=True, icon=ba.gettexture('googlePlayLeaderboardsIcon'), icon_color=(0.8, 0.95, 0.7), on_activate_call=self._on_leaderboards_press, size=(button_width, 50), label=ba.Lstr(resource='leaderboardsText')) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn) v -= leaderboards_button_space * 0.15 else: self._leaderboards_button = None self._campaign_progress_text: Optional[ba.Widget] if show_campaign_progress: v -= campaign_progress_space * 0.5 self._campaign_progress_text = ba.textwidget( parent=self._subcontainer, position=(self._sub_width * 0.5, v), size=(0, 0), scale=0.9, color=(0.75, 0.7, 0.8), maxwidth=self._sub_width * 0.8, h_align='center', v_align='center') v -= campaign_progress_space * 0.5 self._refresh_campaign_progress_text() else: self._campaign_progress_text = None self._tickets_text: Optional[ba.Widget] if show_tickets: v -= tickets_space * 0.5 self._tickets_text = ba.textwidget(parent=self._subcontainer, position=(self._sub_width * 0.5, v), size=(0, 0), scale=0.9, color=(0.75, 0.7, 0.8), maxwidth=self._sub_width * 0.8, flatness=1.0, h_align='center', v_align='center') v -= tickets_space * 0.5 self._refresh_tickets_text() else: self._tickets_text = None # bit of spacing before the reset/sign-out section v -= 5 button_width = 250 if show_reset_progress_button: confirm_text = (ba.Lstr(resource=self._r + '.resetProgressConfirmText') if self._can_reset_achievements else ba.Lstr( resource=self._r + '.resetProgressConfirmNoAchievementsText')) v -= reset_progress_button_space self._reset_progress_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v), color=(0.55, 0.5, 0.6), textcolor=(0.75, 0.7, 0.8), autoselect=True, size=(button_width, 60), label=ba.Lstr(resource=self._r + '.resetProgressText'), on_activate_call=lambda: confirm.ConfirmWindow( text=confirm_text, width=500, height=200, action=self._reset_progress)) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn) self._linked_accounts_text: Optional[ba.Widget] if show_linked_accounts_text: v -= linked_accounts_text_space * 0.8 self._linked_accounts_text = ba.textwidget( parent=self._subcontainer, position=(self._sub_width * 0.5, v), size=(0, 0), scale=0.9, color=(0.75, 0.7, 0.8), maxwidth=self._sub_width * 0.95, h_align='center', v_align='center') v -= linked_accounts_text_space * 0.2 self._update_linked_accounts_text() else: self._linked_accounts_text = None if show_link_accounts_button: v -= link_accounts_button_space self._link_accounts_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v), autoselect=True, size=(button_width, 60), label='', color=(0.55, 0.5, 0.6), on_activate_call=self._link_accounts_press) ba.textwidget(parent=self._subcontainer, draw_controller=btn, h_align='center', v_align='center', size=(0, 0), position=(self._sub_width * 0.5, v + 17 + 20), text=ba.Lstr(resource=self._r + '.linkAccountsText'), maxwidth=button_width * 0.8, color=(0.75, 0.7, 0.8)) ba.textwidget(parent=self._subcontainer, draw_controller=btn, h_align='center', v_align='center', size=(0, 0), position=(self._sub_width * 0.5, v - 4 + 20), text=ba.Lstr(resource=self._r + '.linkAccountsInfoText'), flatness=1.0, scale=0.5, maxwidth=button_width * 0.8, color=(0.75, 0.7, 0.8)) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=50) self._unlink_accounts_button: Optional[ba.Widget] if show_unlink_accounts_button: v -= unlink_accounts_button_space self._unlink_accounts_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v + 25), autoselect=True, size=(button_width, 60), label='', color=(0.55, 0.5, 0.6), on_activate_call=self._unlink_accounts_press) self._unlink_accounts_button_label = ba.textwidget( parent=self._subcontainer, draw_controller=btn, h_align='center', v_align='center', size=(0, 0), position=(self._sub_width * 0.5, v + 55), text=ba.Lstr(resource=self._r + '.unlinkAccountsText'), maxwidth=button_width * 0.8, color=(0.75, 0.7, 0.8)) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=50) self._update_unlink_accounts_button() else: self._unlink_accounts_button = None if show_sign_out_button: v -= sign_out_button_space self._sign_out_button = btn = ba.buttonwidget( parent=self._subcontainer, position=((self._sub_width - button_width) * 0.5, v), size=(button_width, 60), label=ba.Lstr(resource=self._r + '.signOutText'), color=(0.55, 0.5, 0.6), textcolor=(0.75, 0.7, 0.8), autoselect=True, on_activate_call=self._sign_out_press) if first_selectable is None: first_selectable = btn if ba.app.ui.use_toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=15) # Whatever the topmost selectable thing is, we want it to scroll all # the way up when we select it. if first_selectable is not None: ba.widget(edit=first_selectable, up_widget=bbtn, show_buffer_top=400) # (this should re-scroll us to the top..) ba.containerwidget(edit=self._subcontainer, visible_child=first_selectable) self._needs_refresh = False
def __init__(self, transition: str = 'in_right', origin_widget: ba.Widget = None): # pylint: disable=too-many-statements from ba.internal import master_server_get 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() 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) self._spacing = 32 self._menu_open = False 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._prev_lang = '' self._prev_lang_list: list[str] = [] self._complete_langs_list: Optional[list] = None self._complete_langs_error = False self._language_popup: Optional[popup_ui.PopupMenu] = None # In vr-mode, the internal keyboard is currently the *only* option, # so no need to show this. self._show_always_use_internal_keyboard = (not app.vr_mode and not app.iircade_mode) 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 self._show_always_use_internal_keyboard: self._sub_height += 62 self._show_disable_gyro = app.platform in {'ios', 'android'} if self._show_disable_gyro: self._sub_height += 42 self._do_vr_test_button = app.vr_mode self._do_net_test_button = True self._extra_button_spacing = self._spacing * 2.5 if self._do_vr_test_button: self._sub_height += self._extra_button_spacing if self._do_net_test_button: self._sub_height += self._extra_button_spacing self._sub_height += self._spacing * 2.0 # plugins self._r = 'settingsWindowAdvanced' 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=self._r + '.titleText'), 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.containerwidget(parent=self._scrollwidget, size=(self._sub_width, self._sub_height), background=False, selection_loops_to_parent=True) self._rebuild() # Rebuild periodically to pick up language changes/additions/etc. self._rebuild_timer = ba.Timer(1.0, ba.WeakCall(self._rebuild), repeat=True, timetype=ba.TimeType.REAL) # Fetch the list of completed languages. master_server_get('bsLangGetCompleted', {'b': app.build_number}, callback=ba.WeakCall(self._completed_langs_cb))
def __init__(self) -> None: self._r = 'xbox360ControllersWindow' width = 700 height = 300 if _ba.is_running_on_fire_tv() else 485 spacing = 40 uiscale = ba.app.uiscale super().__init__(root_widget=ba.containerwidget( size=(width, height), transition='in_right', scale=(1.4 if uiscale is ba.UIScale.SMALL else 1.4 if uiscale is ba.UIScale.MEDIUM else 1.0))) btn = ba.buttonwidget(parent=self._root_widget, position=(35, height - 65), size=(120, 60), scale=0.84, label=ba.Lstr(resource='backText'), button_type='back', autoselect=True, on_activate_call=self._back) ba.containerwidget(edit=self._root_widget, cancel_button=btn) ba.textwidget(parent=self._root_widget, position=(width * 0.5, height - 42), size=(0, 0), scale=0.85, text=ba.Lstr(resource=self._r + '.titleText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))]), color=ba.app.title_color, maxwidth=400, h_align='center', v_align='center') ba.buttonwidget(edit=btn, button_type='backSmall', size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) v = height - 70 v -= spacing if _ba.is_running_on_fire_tv(): ba.textwidget(parent=self._root_widget, position=(width * 0.5, height * 0.47), size=(0, 0), color=(0.7, 0.9, 0.7, 1.0), maxwidth=width * 0.95, max_height=height * 0.75, scale=0.7, text=ba.Lstr(resource=self._r + '.ouyaInstructionsText'), h_align='center', v_align='center') else: ba.textwidget(parent=self._root_widget, position=(width * 0.5, v - 1), size=(0, 0), color=(0.7, 0.9, 0.7, 1.0), maxwidth=width * 0.95, max_height=height * 0.22, text=ba.Lstr(resource=self._r + '.macInstructionsText'), scale=0.7, h_align='center', v_align='center') v -= 90 b_width = 300 btn = ba.buttonwidget( parent=self._root_widget, position=((width - b_width) * 0.5, v - 10), size=(b_width, 50), label=ba.Lstr(resource=self._r + '.getDriverText'), autoselect=True, on_activate_call=ba.Call( ba.open_url, 'https://github.com/360Controller/360Controller/releases')) ba.containerwidget(edit=self._root_widget, start_button=btn) v -= 60 ba.textwidget(parent=self._root_widget, position=(width * 0.5, v - 85), size=(0, 0), color=(0.7, 0.9, 0.7, 1.0), maxwidth=width * 0.95, max_height=height * 0.46, scale=0.7, text=ba.Lstr(resource=self._r + '.macInstructions2Text'), h_align='center', v_align='center')
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 uiscale = ba.app.uiscale width = 950 if uiscale is ba.UIScale.SMALL else 750 x_offs = 100 if uiscale is ba.UIScale.SMALL else 0 height = (460 if uiscale is ba.UIScale.SMALL else 530 if uiscale is ba.UIScale.MEDIUM else 600) super().__init__(root_widget=ba.containerwidget( size=(width, height), transition=transition, toolbar_visibility='menu_minimal', scale_origin_stack_offset=scale_origin, scale=(1.77 if uiscale is ba.UIScale.SMALL else 1.25 if uiscale is ba.UIScale.MEDIUM else 1.0), stack_offset=(0, -30) if uiscale is ba.UIScale.SMALL else ( 0, 15) if uiscale is ba.UIScale.MEDIUM else (0, 0))) ba.textwidget(parent=self._root_widget, position=(0, height - (50 if uiscale is ba.UIScale.SMALL else 45)), size=(width, 25), text=ba.Lstr(resource=self._r + '.titleText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))]), color=ba.app.ui.title_color, h_align='center', v_align='top') self._scrollwidget = ba.scrollwidget( parent=self._root_widget, position=(44 + x_offs, 55 if uiscale is ba.UIScale.SMALL else 55), simple_culling_v=100.0, size=(width - (88 + 2 * x_offs), height - 120 + (5 if uiscale is ba.UIScale.SMALL else 0)), capture_arrows=True) if ba.app.ui.use_toolbars: ba.widget(edit=self._scrollwidget, right_widget=_ba.get_special_widget('party_button')) ba.containerwidget(edit=self._root_widget, selected_child=self._scrollwidget) # ugly: create this last so it gets first dibs at touch events (since # we have it close to the scroll widget) if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars: ba.containerwidget(edit=self._root_widget, on_cancel_call=self._close) ba.widget(edit=self._scrollwidget, left_widget=_ba.get_special_widget('back_button')) else: btn = ba.buttonwidget( parent=self._root_widget, position=(x_offs + (40 + 0 if uiscale is ba.UIScale.SMALL else 70), height - (59 if uiscale is ba.UIScale.SMALL else 50)), size=(140, 60), scale=0.7 if uiscale is ba.UIScale.SMALL else 0.8, label=ba.Lstr( resource='backText') if self._main_menu else 'Close', button_type='back' if self._main_menu else None, extra_touch_border_scale=2.0, autoselect=True, on_activate_call=self._close) ba.containerwidget(edit=self._root_widget, cancel_button=btn) if self._main_menu: ba.buttonwidget(edit=btn, button_type='backSmall', size=(60, 55), label=ba.charstr(ba.SpecialChar.BACK)) self._sub_width = 660 self._sub_height = 1590 + 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)
def __init__(self, sessiontype: Type[ba.Session], transition: str = 'in_right', select_playlist: str = None, origin_widget: ba.Widget = None): # Yes this needs tidying. # pylint: disable=too-many-locals # pylint: disable=too-many-statements # pylint: disable=cyclic-import from bastd.ui import playlist scale_origin: Optional[Tuple[float, float]] if origin_widget is not None: self._transition_out = 'out_scale' scale_origin = origin_widget.get_screen_space_center() transition = 'in_scale' else: self._transition_out = 'out_right' scale_origin = None self._sessiontype = sessiontype self._pvars = playlist.PlaylistTypeVars(sessiontype) self._max_playlists = 30 self._r = 'gameListWindow' uiscale = ba.app.ui.uiscale self._width = 750.0 if uiscale is ba.UIScale.SMALL else 650.0 x_inset = 50.0 if uiscale is ba.UIScale.SMALL else 0.0 self._height = (380.0 if uiscale is ba.UIScale.SMALL else 420.0 if uiscale is ba.UIScale.MEDIUM else 500.0) top_extra = 20.0 if uiscale is ba.UIScale.SMALL else 0.0 super().__init__(root_widget=ba.containerwidget( size=(self._width, self._height + top_extra), transition=transition, scale_origin_stack_offset=scale_origin, scale=(2.05 if uiscale is ba.UIScale.SMALL else 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0), stack_offset=(0, -10) if uiscale is ba.UIScale.SMALL else (0, 0))) self._back_button = back_button = btn = ba.buttonwidget( parent=self._root_widget, position=(43 + x_inset, self._height - 60), size=(160, 68), scale=0.77, autoselect=True, text_scale=1.3, label=ba.Lstr(resource='backText'), button_type='back') ba.textwidget(parent=self._root_widget, position=(0, self._height - 47), size=(self._width, 25), text=ba.Lstr(resource=self._r + '.titleText', subs=[('${TYPE}', self._pvars.window_title_name)]), color=ba.app.ui.heading_color, maxwidth=290, h_align='center', v_align='center') ba.buttonwidget(edit=btn, button_type='backSmall', size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) v = self._height - 59.0 h = 41 + x_inset b_color = (0.6, 0.53, 0.63) b_textcolor = (0.75, 0.7, 0.8) self._lock_images: List[ba.Widget] = [] lock_tex = ba.gettexture('lock') scl = (1.1 if uiscale is ba.UIScale.SMALL else 1.27 if uiscale is ba.UIScale.MEDIUM else 1.57) scl *= 0.63 v -= 65.0 * scl new_button = btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(90, 58.0 * scl), on_activate_call=self._new_playlist, color=b_color, autoselect=True, button_type='square', textcolor=b_textcolor, text_scale=0.7, label=ba.Lstr(resource='newText', fallback_resource=self._r + '.newText')) self._lock_images.append( ba.imagewidget(parent=self._root_widget, size=(30, 30), draw_controller=btn, position=(h - 10, v + 58.0 * scl - 28), texture=lock_tex)) v -= 65.0 * scl self._edit_button = edit_button = btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(90, 58.0 * scl), on_activate_call=self._edit_playlist, color=b_color, autoselect=True, textcolor=b_textcolor, button_type='square', text_scale=0.7, label=ba.Lstr(resource='editText', fallback_resource=self._r + '.editText')) self._lock_images.append( ba.imagewidget(parent=self._root_widget, size=(30, 30), draw_controller=btn, position=(h - 10, v + 58.0 * scl - 28), texture=lock_tex)) v -= 65.0 * scl duplicate_button = btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(90, 58.0 * scl), on_activate_call=self._duplicate_playlist, color=b_color, autoselect=True, textcolor=b_textcolor, button_type='square', text_scale=0.7, label=ba.Lstr(resource='duplicateText', fallback_resource=self._r + '.duplicateText')) self._lock_images.append( ba.imagewidget(parent=self._root_widget, size=(30, 30), draw_controller=btn, position=(h - 10, v + 58.0 * scl - 28), texture=lock_tex)) v -= 65.0 * scl delete_button = btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(90, 58.0 * scl), on_activate_call=self._delete_playlist, color=b_color, autoselect=True, textcolor=b_textcolor, button_type='square', text_scale=0.7, label=ba.Lstr(resource='deleteText', fallback_resource=self._r + '.deleteText')) self._lock_images.append( ba.imagewidget(parent=self._root_widget, size=(30, 30), draw_controller=btn, position=(h - 10, v + 58.0 * scl - 28), texture=lock_tex)) v -= 65.0 * scl self._import_button = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(90, 58.0 * scl), on_activate_call=self._import_playlist, color=b_color, autoselect=True, textcolor=b_textcolor, button_type='square', text_scale=0.7, label=ba.Lstr(resource='importText')) v -= 65.0 * scl btn = ba.buttonwidget(parent=self._root_widget, position=(h, v), size=(90, 58.0 * scl), on_activate_call=self._share_playlist, color=b_color, autoselect=True, textcolor=b_textcolor, button_type='square', text_scale=0.7, label=ba.Lstr(resource='shareText')) self._lock_images.append( ba.imagewidget(parent=self._root_widget, size=(30, 30), draw_controller=btn, position=(h - 10, v + 58.0 * scl - 28), texture=lock_tex)) v = self._height - 75 self._scroll_height = self._height - 119 scrollwidget = ba.scrollwidget(parent=self._root_widget, position=(140 + x_inset, v - self._scroll_height), size=(self._width - (180 + 2 * x_inset), self._scroll_height + 10), highlight=False) ba.widget(edit=back_button, right_widget=scrollwidget) self._columnwidget = ba.columnwidget(parent=scrollwidget, border=2, margin=0) h = 145 self._do_randomize_val = ba.app.config.get( self._pvars.config_name + ' Playlist Randomize', 0) h += 210 for btn in [new_button, delete_button, edit_button, duplicate_button]: ba.widget(edit=btn, right_widget=scrollwidget) ba.widget(edit=scrollwidget, left_widget=new_button, right_widget=_ba.get_special_widget('party_button') if ba.app.ui.use_toolbars else None) # make sure config exists self._config_name_full = self._pvars.config_name + ' Playlists' if self._config_name_full not in ba.app.config: ba.app.config[self._config_name_full] = {} self._selected_playlist_name: Optional[str] = None self._selected_playlist_index: Optional[int] = None self._playlist_widgets: List[ba.Widget] = [] self._refresh(select_playlist=select_playlist) ba.buttonwidget(edit=back_button, on_activate_call=self._back) ba.containerwidget(edit=self._root_widget, cancel_button=back_button) ba.containerwidget(edit=self._root_widget, selected_child=scrollwidget) # Keep our lock images up to date/etc. self._update_timer = ba.Timer(1.0, ba.WeakCall(self._update), timetype=ba.TimeType.REAL, repeat=True) self._update()
def _rebuild(self) -> None: # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals from bastd.ui.config import ConfigCheckBox from ba.internal import show_user_scripts # Don't rebuild if the menu is open or if our language and # language-list hasn't changed. # NOTE - although we now support widgets updating their own # translations, we still change the label formatting on the language # menu based on the language so still need this. ...however we could # make this more limited to it only rebuilds that one menu instead # of everything. if self._menu_open or ( self._prev_lang == _ba.app.config.get('Lang', None) and self._prev_lang_list == ba.get_valid_languages()): return self._prev_lang = _ba.app.config.get('Lang', None) self._prev_lang_list = ba.get_valid_languages() # Clear out our sub-container. children = self._subcontainer.get_children() for child in children: child.delete() v = self._sub_height - 35 v -= self._spacing * 1.2 # Update our existing back button and title. if self._back_button is not None: ba.buttonwidget(edit=self._back_button, label=ba.Lstr(resource='backText')) ba.buttonwidget(edit=self._back_button, label=ba.charstr(ba.SpecialChar.BACK)) ba.textwidget(edit=self._title_text, text=ba.Lstr(resource=self._r + '.titleText')) this_button_width = 410 self._promo_code_button = ba.buttonwidget( parent=self._subcontainer, position=(self._sub_width / 2 - this_button_width / 2, v - 14), size=(this_button_width, 60), autoselect=True, label=ba.Lstr(resource=self._r + '.enterPromoCodeText'), text_scale=1.0, on_activate_call=self._on_promo_code_press) if self._back_button is not None: ba.widget(edit=self._promo_code_button, up_widget=self._back_button, left_widget=self._back_button) v -= self._extra_button_spacing * 0.8 ba.textwidget(parent=self._subcontainer, position=(200, v + 10), size=(0, 0), text=ba.Lstr(resource=self._r + '.languageText'), maxwidth=150, scale=0.95, color=ba.app.title_color, h_align='right', v_align='center') languages = ba.get_valid_languages() cur_lang = _ba.app.config.get('Lang', None) if cur_lang is None: cur_lang = 'Auto' # We have a special dict of language names in that language # so we don't have to go digging through each full language. try: import json with open('ba_data/data/langdata.json') as infile: lang_names_translated = (json.loads( infile.read())['lang_names_translated']) except Exception: ba.print_exception('error reading lang data') lang_names_translated = {} langs_translated = {} for lang in languages: langs_translated[lang] = lang_names_translated.get(lang, lang) langs_full = {} for lang in languages: lang_translated = ba.Lstr(translate=('languages', lang)).evaluate() if langs_translated[lang] == lang_translated: langs_full[lang] = lang_translated else: langs_full[lang] = (langs_translated[lang] + ' (' + lang_translated + ')') self._language_popup = popup_ui.PopupMenu( parent=self._subcontainer, position=(210, v - 19), width=150, opening_call=ba.WeakCall(self._on_menu_open), closing_call=ba.WeakCall(self._on_menu_close), autoselect=False, on_value_change_call=ba.WeakCall(self._on_menu_choice), choices=['Auto'] + languages, button_size=(250, 60), choices_display=([ ba.Lstr(value=(ba.Lstr(resource='autoText').evaluate() + ' (' + ba.Lstr(translate=( 'languages', ba.app.default_language)).evaluate() + ')')) ] + [ba.Lstr(value=langs_full[l]) for l in languages]), current_choice=cur_lang) v -= self._spacing * 1.8 ba.textwidget(parent=self._subcontainer, position=(self._sub_width * 0.5, v + 10), size=(0, 0), text=ba.Lstr(resource=self._r + '.helpTranslateText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))]), maxwidth=self._sub_width * 0.9, max_height=55, flatness=1.0, scale=0.65, color=(0.4, 0.9, 0.4, 0.8), h_align='center', v_align='center') v -= self._spacing * 1.9 this_button_width = 410 self._translation_editor_button = ba.buttonwidget( parent=self._subcontainer, position=(self._sub_width / 2 - this_button_width / 2, v - 24), size=(this_button_width, 60), label=ba.Lstr(resource=self._r + '.translationEditorButtonText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText')) ]), autoselect=True, on_activate_call=ba.Call(ba.open_url, 'http://bombsquadgame.com/translate')) self._lang_status_text = ba.textwidget(parent=self._subcontainer, position=(self._sub_width * 0.5, v - 40), size=(0, 0), text='', flatness=1.0, scale=0.63, h_align='center', v_align='center', maxwidth=400.0) self._update_lang_status() v -= 40 lang_inform = _ba.get_account_misc_val('langInform', False) self._language_inform_checkbox = cbw = ba.checkboxwidget( parent=self._subcontainer, position=(50, v - 50), size=(self._sub_width - 100, 30), autoselect=True, maxwidth=430, textcolor=(0.8, 0.8, 0.8), value=lang_inform, text=ba.Lstr(resource=self._r + '.translationInformMe'), on_value_change_call=ba.WeakCall( self._on_lang_inform_value_change)) ba.widget(edit=self._translation_editor_button, down_widget=cbw, up_widget=self._language_popup.get_button()) v -= self._spacing * 3.0 self._kick_idle_players_check_box = ConfigCheckBox( parent=self._subcontainer, position=(50, v), size=(self._sub_width - 100, 30), configkey="Kick Idle Players", displayname=ba.Lstr(resource=self._r + '.kickIdlePlayersText'), scale=1.0, maxwidth=430) self._always_use_internal_keyboard_check_box: Optional[ConfigCheckBox] if self._show_always_use_internal_keyboard: v -= 42 self._always_use_internal_keyboard_check_box = ConfigCheckBox( parent=self._subcontainer, position=(50, v), size=(self._sub_width - 100, 30), configkey="Always Use Internal Keyboard", autoselect=True, displayname=ba.Lstr(resource=self._r + '.alwaysUseInternalKeyboardText'), scale=1.0, maxwidth=430) ba.textwidget( parent=self._subcontainer, position=(90, v - 10), size=(0, 0), text=ba.Lstr(resource=self._r + '.alwaysUseInternalKeyboardDescriptionText'), maxwidth=400, flatness=1.0, scale=0.65, color=(0.4, 0.9, 0.4, 0.8), h_align='left', v_align='center') v -= 20 else: self._always_use_internal_keyboard_check_box = None v -= self._spacing * 2.1 this_button_width = 410 self._show_user_mods_button = ba.buttonwidget( parent=self._subcontainer, position=(self._sub_width / 2 - this_button_width / 2, v - 10), size=(this_button_width, 60), autoselect=True, label=ba.Lstr(resource=self._r + '.showUserModsText'), text_scale=1.0, on_activate_call=show_user_scripts) if self._show_always_use_internal_keyboard: assert self._always_use_internal_keyboard_check_box is not None ba.widget(edit=self._always_use_internal_keyboard_check_box.widget, down_widget=self._show_user_mods_button) ba.widget( edit=self._show_user_mods_button, up_widget=self._always_use_internal_keyboard_check_box.widget) else: ba.widget(edit=self._show_user_mods_button, up_widget=self._kick_idle_players_check_box.widget) ba.widget(edit=self._kick_idle_players_check_box.widget, down_widget=self._show_user_mods_button) v -= self._spacing * 2.0 btn = self._modding_guide_button = ba.buttonwidget( parent=self._subcontainer, position=(self._sub_width / 2 - this_button_width / 2, v - 10), size=(this_button_width, 60), autoselect=True, label=ba.Lstr(resource=self._r + '.moddingGuideText'), text_scale=1.0, on_activate_call=ba.Call( ba.open_url, 'http://www.froemling.net/docs/bombsquad-modding-guide')) v -= self._spacing * 1.8 self._enable_package_mods_checkbox = ConfigCheckBox( parent=self._subcontainer, position=(80, v), size=(self._sub_width - 100, 30), configkey="Enable Package Mods", autoselect=True, value_change_call=ba.WeakCall(self._show_restart_needed), displayname=ba.Lstr(resource=self._r + '.enablePackageModsText'), scale=1.0, maxwidth=400) ccb = self._enable_package_mods_checkbox.widget ba.widget(edit=btn, down_widget=ccb) ba.widget(edit=ccb, up_widget=btn) ba.textwidget(parent=self._subcontainer, position=(90, v - 10), size=(0, 0), text=ba.Lstr(resource=self._r + '.enablePackageModsDescriptionText'), maxwidth=400, flatness=1.0, scale=0.65, color=(0.4, 0.9, 0.4, 0.8), h_align='left', v_align='center') v -= self._spacing * 0.6 self._vr_test_button: Optional[ba.Widget] if self._do_vr_test_button: v -= self._extra_button_spacing self._vr_test_button = ba.buttonwidget( parent=self._subcontainer, position=(self._sub_width / 2 - this_button_width / 2, v - 14), size=(this_button_width, 60), autoselect=True, label=ba.Lstr(resource=self._r + '.vrTestingText'), text_scale=1.0, on_activate_call=self._on_vr_test_press) else: self._vr_test_button = None self._net_test_button: Optional[ba.Widget] if self._do_net_test_button: v -= self._extra_button_spacing self._net_test_button = ba.buttonwidget( parent=self._subcontainer, position=(self._sub_width / 2 - this_button_width / 2, v - 14), size=(this_button_width, 60), autoselect=True, label=ba.Lstr(resource=self._r + '.netTestingText'), text_scale=1.0, on_activate_call=self._on_net_test_press) else: self._net_test_button = None v -= 70 self._benchmarks_button = ba.buttonwidget( parent=self._subcontainer, position=(self._sub_width / 2 - this_button_width / 2, v - 14), size=(this_button_width, 60), autoselect=True, label=ba.Lstr(resource=self._r + '.benchmarksText'), text_scale=1.0, on_activate_call=self._on_benchmark_press) ba.widget(edit=self._vr_test_button if self._vr_test_button is not None else self._net_test_button if self._net_test_button is not None else self._benchmarks_button, up_widget=cbw) for child in self._subcontainer.get_children(): ba.widget(edit=child, show_buffer_bottom=30, show_buffer_top=20) if ba.app.toolbars: pbtn = _ba.get_special_widget('party_button') ba.widget(edit=self._scrollwidget, right_widget=pbtn) if self._back_button is None: ba.widget(edit=self._scrollwidget, left_widget=_ba.get_special_widget('back_button')) self._restore_state()
def __init__(self, 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.ui.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.ui.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()
def __init__(self, transition: str = 'in_right', origin_widget: ba.Widget = None): # pylint: disable=too-many-statements from ba.internal import serverget 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 self._width = 870.0 if app.small_ui else 670.0 x_inset = 100 if app.small_ui else 0 self._height = (390.0 if app.small_ui else 450.0 if app.med_ui else 520.0) self._spacing = 32 self._menu_open = False top_extra = 10 if app.small_ui 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 app.small_ui else 1.4 if app.med_ui else 1.0, stack_offset=(0, -25) if app.small_ui else (0, 0))) self._prev_lang = "" self._prev_lang_list: List[str] = [] self._complete_langs_list: Optional[List] = None self._complete_langs_error = False self._language_popup: Optional[popup_ui.PopupMenu] = None # In vr-mode, the internal keyboard is currently the *only* option, # so no need to show this. self._show_always_use_internal_keyboard = (not app.vr_mode) 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 = 740.0 if self._show_always_use_internal_keyboard: self._sub_height += 62 self._do_vr_test_button = app.vr_mode self._do_net_test_button = True self._extra_button_spacing = self._spacing * 2.5 if self._do_vr_test_button: self._sub_height += self._extra_button_spacing if self._do_net_test_button: self._sub_height += self._extra_button_spacing self._r = 'settingsWindowAdvanced' if app.toolbars and app.small_ui: 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=self._r + '.titleText'), color=app.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)) ba.containerwidget(edit=self._scrollwidget, selection_loop_to_parent=True) self._subcontainer = ba.containerwidget(parent=self._scrollwidget, size=(self._sub_width, self._sub_height), background=False, selection_loop_to_parent=True) self._rebuild() # Rebuild periodically to pick up language changes/additions/etc. self._rebuild_timer = ba.Timer(1.0, ba.WeakCall(self._rebuild), repeat=True, timetype=ba.TimeType.REAL) # Fetch the list of completed languages. serverget('bsLangGetCompleted', {'b': app.build_number}, callback=ba.WeakCall(self._completed_langs_cb))
def __init__(self) -> None: from ba.internal import get_remote_app_name self._r = 'connectMobileDevicesWindow' width = 700 height = 390 spacing = 40 uiscale = ba.app.ui.uiscale super().__init__(root_widget=ba.containerwidget( size=(width, height), transition='in_right', scale=(1.85 if uiscale is ba.UIScale.SMALL else 1.3 if uiscale is ba.UIScale.MEDIUM else 1.0), stack_offset=(-10, 0) if uiscale is ba.UIScale.SMALL else (0, 0))) btn = ba.buttonwidget(parent=self._root_widget, position=(40, height - 67), size=(140, 65), scale=0.8, label=ba.Lstr(resource='backText'), button_type='back', text_scale=1.1, autoselect=True, on_activate_call=self._back) ba.containerwidget(edit=self._root_widget, cancel_button=btn) ba.textwidget(parent=self._root_widget, position=(width * 0.5, height - 42), size=(0, 0), text=ba.Lstr(resource=self._r + '.titleText'), maxwidth=370, color=ba.app.ui.title_color, scale=0.8, h_align='center', v_align='center') ba.buttonwidget(edit=btn, button_type='backSmall', size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) v = height - 70.0 v -= spacing * 1.2 ba.textwidget(parent=self._root_widget, position=(15, v - 26), size=(width - 30, 30), maxwidth=width * 0.95, color=(0.7, 0.9, 0.7, 1.0), scale=0.8, text=ba.Lstr(resource=self._r + '.explanationText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText')), ('${REMOTE_APP_NAME}', get_remote_app_name())]), max_height=100, h_align='center', v_align='center') v -= 90 # hmm the itms:// version doesnt bounce through safari but is kinda # apple-specific-ish # Update: now we just show link to the remote webpage. ba.textwidget(parent=self._root_widget, position=(width * 0.5, v + 5), size=(0, 0), color=(0.7, 0.9, 0.7, 1.0), scale=1.4, text='bombsquadgame.com/remote', maxwidth=width * 0.95, max_height=60, h_align='center', v_align='center') v -= 30 ba.textwidget(parent=self._root_widget, position=(width * 0.5, v - 35), size=(0, 0), color=(0.7, 0.9, 0.7, 0.8), scale=0.65, text=ba.Lstr(resource=self._r + '.bestResultsText'), maxwidth=width * 0.95, max_height=height * 0.19, h_align='center', v_align='center') ba.checkboxwidget( parent=self._root_widget, position=(width * 0.5 - 150, v - 116), size=(300, 30), maxwidth=300, scale=0.8, value=not ba.app.config.resolve('Enable Remote App'), autoselect=True, text=ba.Lstr(resource='disableRemoteAppConnectionsText'), on_value_change_call=self._on_check_changed)
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.ui.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
def __init__(self, transition: str = 'in_right', origin_widget: ba.Widget = None): # FIXME: should tidy up here. # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals # pylint: disable=cyclic-import from bastd.ui import popup as popup_ui self._have_selected_child = False scale_origin: Optional[Tuple[float, float]] # If they provided an origin-widget, scale up from that. if origin_widget is not None: self._transition_out = 'out_scale' scale_origin = origin_widget.get_screen_space_center() transition = 'in_scale' else: self._transition_out = 'out_right' scale_origin = None self._r = 'configControllersWindow' app = ba.app is_fire_tv = _ba.is_running_on_fire_tv() spacing = 50.0 button_width = 350.0 width = 460.0 height = 135.0 space_height = spacing * 0.3 # FIXME: should create vis settings in platform for these, # not hard code them here.. show_gamepads = False platform = app.platform subplatform = app.subplatform non_vr_windows = (platform == 'windows' and (subplatform != 'oculus' or not app.vr_mode)) if platform in ('linux', 'android', 'mac') or non_vr_windows: show_gamepads = True height += spacing show_touch = False if _ba.have_touchscreen_input(): show_touch = True height += spacing show_space_1 = False if show_gamepads or show_touch: show_space_1 = True height += space_height show_keyboard = False if _ba.get_input_device('Keyboard', '#1', doraise=False) is not None: show_keyboard = True height += spacing * 2 show_keyboard_p2 = False if app.vr_mode else show_keyboard if show_keyboard_p2: height += spacing show_space_2 = False if show_keyboard: show_space_2 = True height += space_height if bool(True): show_remote = True height += spacing else: show_remote = False show_ps3 = False if platform == 'mac': show_ps3 = True height += spacing show360 = False if platform == 'mac' or is_fire_tv: show360 = True height += spacing show_mac_wiimote = False if platform == 'mac': show_mac_wiimote = True height += spacing # on non-oculus-vr windows, show an option to disable xinput show_xinput_toggle = False if platform == 'windows' and (subplatform != 'oculus' or not app.vr_mode): show_xinput_toggle = True # on mac builds, show an option to switch between generic and # made-for-iOS/Mac systems # (we can run into problems where devices register as one of each # type otherwise).. show_mac_controller_subsystem = False if platform == 'mac': show_mac_controller_subsystem = True if show_mac_controller_subsystem: height += spacing if show_xinput_toggle: height += spacing super().__init__(root_widget=ba.containerwidget( size=(width, height), transition=transition, scale_origin_stack_offset=scale_origin, scale=(1.7 if show_keyboard else 2.2 ) if ba.app.small_ui else 1.5 if ba.app.med_ui else 1.0)) self._back_button = btn = ba.buttonwidget( parent=self._root_widget, position=(35, height - 60), size=(140, 65), scale=0.8, text_scale=1.2, autoselect=True, label=ba.Lstr(resource='backText'), button_type='back', on_activate_call=self._back) ba.containerwidget(edit=self._root_widget, cancel_button=btn) # need these vars to exist even if the buttons don't self._gamepads_button: Optional[ba.Widget] = None self._touch_button: Optional[ba.Widget] = None self._keyboard_button: Optional[ba.Widget] = None self._keyboard_2_button: Optional[ba.Widget] = None self._idevices_button: Optional[ba.Widget] = None self._ps3_button: Optional[ba.Widget] = None self._xbox_360_button: Optional[ba.Widget] = None self._wiimotes_button: Optional[ba.Widget] = None ba.textwidget(parent=self._root_widget, position=(0, height - 49), size=(width, 25), text=ba.Lstr(resource=self._r + '.titleText'), color=ba.app.title_color, h_align='center', v_align='top') ba.buttonwidget(edit=btn, button_type='backSmall', size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) v = height - 75 v -= spacing if show_touch: self._touch_button = btn = ba.buttonwidget( parent=self._root_widget, position=((width - button_width) / 2, v), size=(button_width, 43), autoselect=True, label=ba.Lstr(resource=self._r + '.configureTouchText'), on_activate_call=self._do_touchscreen) if ba.app.toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) if not self._have_selected_child: ba.containerwidget(edit=self._root_widget, selected_child=self._touch_button) ba.widget(edit=self._back_button, down_widget=self._touch_button) self._have_selected_child = True v -= spacing if show_gamepads: self._gamepads_button = btn = ba.buttonwidget( parent=self._root_widget, position=((width - button_width) / 2 - 7, v), size=(button_width, 43), autoselect=True, label=ba.Lstr(resource=self._r + '.configureControllersText'), on_activate_call=self._do_gamepads) if ba.app.toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) if not self._have_selected_child: ba.containerwidget(edit=self._root_widget, selected_child=self._gamepads_button) ba.widget(edit=self._back_button, down_widget=self._gamepads_button) self._have_selected_child = True v -= spacing else: self._gamepads_button = None if show_space_1: v -= space_height if show_keyboard: self._keyboard_button = btn = ba.buttonwidget( parent=self._root_widget, position=((width - button_width) / 2 + 5, v), size=(button_width, 43), autoselect=True, label=ba.Lstr(resource=self._r + '.configureKeyboardText'), on_activate_call=self._config_keyboard) if ba.app.toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) if not self._have_selected_child: ba.containerwidget(edit=self._root_widget, selected_child=self._keyboard_button) ba.widget(edit=self._back_button, down_widget=self._keyboard_button) self._have_selected_child = True v -= spacing if show_keyboard_p2: self._keyboard_2_button = ba.buttonwidget( parent=self._root_widget, position=((width - button_width) / 2 - 3, v), size=(button_width, 43), autoselect=True, label=ba.Lstr(resource=self._r + '.configureKeyboard2Text'), on_activate_call=self._config_keyboard2) v -= spacing if show_space_2: v -= space_height if show_remote: self._idevices_button = btn = ba.buttonwidget( parent=self._root_widget, position=((width - button_width) / 2 - 5, v), size=(button_width, 43), autoselect=True, label=ba.Lstr(resource=self._r + '.configureMobileText'), on_activate_call=self._do_mobile_devices) if ba.app.toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) if not self._have_selected_child: ba.containerwidget(edit=self._root_widget, selected_child=self._idevices_button) ba.widget(edit=self._back_button, down_widget=self._idevices_button) self._have_selected_child = True v -= spacing if show_ps3: self._ps3_button = btn = ba.buttonwidget( parent=self._root_widget, position=((width - button_width) / 2 + 5, v), size=(button_width, 43), autoselect=True, label=ba.Lstr(resource=self._r + '.ps3Text'), on_activate_call=self._do_ps3_controllers) if ba.app.toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) v -= spacing if show360: self._xbox_360_button = btn = ba.buttonwidget( parent=self._root_widget, position=((width - button_width) / 2 - 1, v), size=(button_width, 43), autoselect=True, label=ba.Lstr(resource=self._r + '.xbox360Text'), on_activate_call=self._do_360_controllers) if ba.app.toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) v -= spacing if show_mac_wiimote: self._wiimotes_button = btn = ba.buttonwidget( parent=self._root_widget, position=((width - button_width) / 2 + 5, v), size=(button_width, 43), autoselect=True, label=ba.Lstr(resource=self._r + '.wiimotesText'), on_activate_call=self._do_wiimotes) if ba.app.toolbars: ba.widget(edit=btn, right_widget=_ba.get_special_widget('party_button')) v -= spacing if show_xinput_toggle: def do_toggle(value: bool) -> None: ba.screenmessage( ba.Lstr(resource='settingsWindowAdvanced.mustRestartText'), color=(1, 1, 0)) ba.playsound(ba.getsound('gunCocking')) _ba.set_low_level_config_value('enablexinput', not value) ba.checkboxwidget( parent=self._root_widget, position=(100, v + 3), size=(120, 30), value=(not _ba.get_low_level_config_value('enablexinput', 1)), maxwidth=200, on_value_change_call=do_toggle, text=ba.Lstr(resource='disableXInputText'), autoselect=True) ba.textwidget( parent=self._root_widget, position=(width * 0.5, v - 5), size=(0, 0), text=ba.Lstr(resource='disableXInputDescriptionText'), scale=0.5, h_align='center', v_align='center', color=ba.app.infotextcolor, maxwidth=width * 0.8) v -= spacing if show_mac_controller_subsystem: popup_ui.PopupMenu( parent=self._root_widget, position=(260, v - 10), width=160, button_size=(150, 50), scale=1.5, choices=['Classic', 'MFi', 'Both'], choices_display=[ ba.Lstr(resource='macControllerSubsystemClassicText'), ba.Lstr(resource='macControllerSubsystemMFiText'), ba.Lstr(resource='macControllerSubsystemBothText') ], current_choice=ba.app.config.resolve( 'Mac Controller Subsystem'), on_value_change_call=self._set_mac_controller_subsystem) ba.textwidget( parent=self._root_widget, position=(245, v + 13), size=(0, 0), text=ba.Lstr(resource='macControllerSubsystemTitleText'), scale=1.0, h_align='right', v_align='center', color=ba.app.infotextcolor, maxwidth=180) ba.textwidget( parent=self._root_widget, position=(width * 0.5, v - 20), size=(0, 0), text=ba.Lstr(resource='macControllerSubsystemDescriptionText'), scale=0.5, h_align='center', v_align='center', color=ba.app.infotextcolor, maxwidth=width * 0.8) v -= spacing self._restore_state()
def __init__(self, transition: Optional[str] = 'in_right', origin_widget: ba.Widget = None): # pylint: disable=too-many-statements # pylint: disable=too-many-locals # pylint: disable=cyclic-import from bastd.ui.gather.abouttab import AboutGatherTab from bastd.ui.gather.manualtab import ManualGatherTab from bastd.ui.gather.privatetab import PrivateGatherTab from bastd.ui.gather.publictab import PublicGatherTab from bastd.ui.gather.nearbytab import NearbyGatherTab ba.set_analytics_screen('Gather Window') scale_origin: Optional[tuple[float, float]] if origin_widget is not None: self._transition_out = 'out_scale' scale_origin = origin_widget.get_screen_space_center() transition = 'in_scale' else: self._transition_out = 'out_right' scale_origin = None ba.app.ui.set_main_menu_location('Gather') _ba.set_party_icon_always_visible(True) uiscale = ba.app.ui.uiscale self._width = 1240 if uiscale is ba.UIScale.SMALL else 1040 x_offs = 100 if uiscale is ba.UIScale.SMALL else 0 self._height = (582 if uiscale is ba.UIScale.SMALL else 680 if uiscale is ba.UIScale.MEDIUM else 800) self._current_tab: Optional[GatherWindow.TabID] = None extra_top = 20 if uiscale is ba.UIScale.SMALL else 0 self._r = 'gatherWindow' super().__init__(root_widget=ba.containerwidget( size=(self._width, self._height + extra_top), transition=transition, toolbar_visibility='menu_minimal', scale_origin_stack_offset=scale_origin, scale=(1.3 if uiscale is ba.UIScale.SMALL else 0.97 if uiscale is ba.UIScale.MEDIUM else 0.8), stack_offset=(0, -11) if uiscale is ba.UIScale.SMALL else ( 0, 0) if uiscale is ba.UIScale.MEDIUM else (0, 0))) if uiscale is ba.UIScale.SMALL and ba.app.ui.use_toolbars: ba.containerwidget(edit=self._root_widget, on_cancel_call=self._back) self._back_button = None else: self._back_button = btn = ba.buttonwidget( parent=self._root_widget, position=(70 + x_offs, self._height - 74), size=(140, 60), scale=1.1, autoselect=True, label=ba.Lstr(resource='backText'), button_type='back', on_activate_call=self._back) ba.containerwidget(edit=self._root_widget, cancel_button=btn) ba.buttonwidget(edit=btn, button_type='backSmall', position=(70 + x_offs, self._height - 78), size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) condensed = uiscale is not ba.UIScale.LARGE t_offs_y = (0 if not condensed else 25 if uiscale is ba.UIScale.MEDIUM else 17) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, self._height - 42 + t_offs_y), size=(0, 0), color=ba.app.ui.title_color, scale=(1.5 if not condensed else 1.0 if uiscale is ba.UIScale.MEDIUM else 0.6), h_align='center', v_align='center', text=ba.Lstr(resource=self._r + '.titleText'), maxwidth=550) scroll_buffer_h = 130 + 2 * x_offs tab_buffer_h = ((320 if condensed else 250) + 2 * x_offs) # Build up the set of tabs we want. tabdefs: list[tuple[GatherWindow.TabID, ba.Lstr]] = [ (self.TabID.ABOUT, ba.Lstr(resource=self._r + '.aboutText')) ] if _ba.get_account_misc_read_val('enablePublicParties', True): tabdefs.append((self.TabID.INTERNET, ba.Lstr(resource=self._r + '.publicText'))) tabdefs.append( (self.TabID.PRIVATE, ba.Lstr(resource=self._r + '.privateText'))) tabdefs.append( (self.TabID.NEARBY, ba.Lstr(resource=self._r + '.nearbyText'))) tabdefs.append( (self.TabID.MANUAL, ba.Lstr(resource=self._r + '.manualText'))) # On small UI, push our tabs up closer to the top of the screen to # save a bit of space. tabs_top_extra = 42 if condensed else 0 self._tab_row = TabRow(self._root_widget, tabdefs, pos=(tab_buffer_h * 0.5, self._height - 130 + tabs_top_extra), size=(self._width - tab_buffer_h, 50), on_select_call=ba.WeakCall(self._set_tab)) # Now instantiate handlers for these tabs. tabtypes: dict[GatherWindow.TabID, type[GatherTab]] = { self.TabID.ABOUT: AboutGatherTab, self.TabID.MANUAL: ManualGatherTab, self.TabID.PRIVATE: PrivateGatherTab, self.TabID.INTERNET: PublicGatherTab, self.TabID.NEARBY: NearbyGatherTab } self._tabs: dict[GatherWindow.TabID, GatherTab] = {} for tab_id in self._tab_row.tabs: tabtype = tabtypes.get(tab_id) if tabtype is not None: self._tabs[tab_id] = tabtype(self) if ba.app.ui.use_toolbars: ba.widget(edit=self._tab_row.tabs[tabdefs[-1][0]].button, right_widget=_ba.get_special_widget('party_button')) if uiscale is ba.UIScale.SMALL: ba.widget(edit=self._tab_row.tabs[tabdefs[0][0]].button, left_widget=_ba.get_special_widget('back_button')) self._scroll_width = self._width - scroll_buffer_h self._scroll_height = self._height - 180.0 + tabs_top_extra self._scroll_left = (self._width - self._scroll_width) * 0.5 self._scroll_bottom = (self._height - self._scroll_height - 79 - 48 + tabs_top_extra) buffer_h = 10 buffer_v = 4 # Not actually using a scroll widget anymore; just an image. ba.imagewidget(parent=self._root_widget, position=(self._scroll_left - buffer_h, self._scroll_bottom - buffer_v), size=(self._scroll_width + 2 * buffer_h, self._scroll_height + 2 * buffer_v), texture=ba.gettexture('scrollWidget'), model_transparent=ba.getmodel('softEdgeOutside')) self._tab_container: Optional[ba.Widget] = None self._restore_state()
def __init__(self, path: str, callback: Callable[[Optional[str]], Any] = None, show_base_path: bool = True, valid_file_extensions: Sequence[str] = None, allow_folders: bool = False): if valid_file_extensions is None: valid_file_extensions = [] uiscale = ba.app.uiscale self._width = 700 if uiscale is ba.UIScale.SMALL else 600 self._x_inset = x_inset = 50 if uiscale is ba.UIScale.SMALL else 0 self._height = 365 if uiscale is ba.UIScale.SMALL else 418 self._callback = callback self._base_path = path self._path: Optional[str] = None self._recent_paths: List[str] = [] self._show_base_path = show_base_path self._valid_file_extensions = [ '.' + ext for ext in valid_file_extensions ] self._allow_folders = allow_folders self._subcontainer: Optional[ba.Widget] = None self._subcontainerheight: Optional[float] = None self._scroll_width = self._width - (80 + 2 * x_inset) self._scroll_height = self._height - 170 self._r = 'fileSelectorWindow' super().__init__(root_widget=ba.containerwidget( size=(self._width, self._height), transition='in_right', scale=(2.23 if uiscale is ba.UIScale.SMALL else 1.4 if uiscale is ba.UIScale.MEDIUM else 1.0), stack_offset=(0, -35) if uiscale is ba.UIScale.SMALL else (0, 0))) ba.textwidget( parent=self._root_widget, position=(self._width * 0.5, self._height - 42), size=(0, 0), color=ba.app.ui.title_color, h_align='center', v_align='center', text=ba.Lstr(resource=self._r + '.titleFolderText') if (allow_folders and not valid_file_extensions) else ba.Lstr( resource=self._r + '.titleFileText') if not allow_folders else ba.Lstr( resource=self._r + '.titleFileFolderText'), maxwidth=210) self._button_width = 146 self._cancel_button = ba.buttonwidget( parent=self._root_widget, position=(35 + x_inset, self._height - 67), autoselect=True, size=(self._button_width, 50), label=ba.Lstr(resource='cancelText'), on_activate_call=self._cancel) ba.widget(edit=self._cancel_button, left_widget=self._cancel_button) b_color = (0.6, 0.53, 0.63) self._back_button = ba.buttonwidget( parent=self._root_widget, button_type='square', position=(43 + x_inset, self._height - 113), color=b_color, textcolor=(0.75, 0.7, 0.8), enable_sound=False, size=(55, 35), label=ba.charstr(ba.SpecialChar.LEFT_ARROW), on_activate_call=self._on_back_press) self._folder_tex = ba.gettexture('folder') self._folder_color = (1.1, 0.8, 0.2) self._file_tex = ba.gettexture('file') self._file_color = (1, 1, 1) self._use_folder_button: Optional[ba.Widget] = None self._folder_center = self._width * 0.5 + 15 self._folder_icon = ba.imagewidget(parent=self._root_widget, size=(40, 40), position=(40, self._height - 117), texture=self._folder_tex, color=self._folder_color) self._path_text = ba.textwidget(parent=self._root_widget, position=(self._folder_center, self._height - 98), size=(0, 0), color=ba.app.ui.title_color, h_align='center', v_align='center', text=self._path, maxwidth=self._width * 0.9) self._scrollwidget: Optional[ba.Widget] = None ba.containerwidget(edit=self._root_widget, cancel_button=self._cancel_button) self._set_path(path)
def __init__(self, transition: str = 'in_right', origin_widget: ba.Widget = None): # pylint: disable=too-many-locals # pylint: disable=too-many-statements # If they provided an origin-widget, scale up from that. scale_origin: Optional[tuple[float, float]] if origin_widget is not None: self._transition_out = 'out_scale' scale_origin = origin_widget.get_screen_space_center() transition = 'in_scale' else: self._transition_out = 'out_right' scale_origin = None self._r = 'editSoundtrackWindow' uiscale = ba.app.ui.uiscale self._width = 800 if uiscale is ba.UIScale.SMALL else 600 x_inset = 100 if uiscale is ba.UIScale.SMALL else 0 self._height = (340 if uiscale is ba.UIScale.SMALL else 370 if uiscale is ba.UIScale.MEDIUM else 440) spacing = 40.0 v = self._height - 40.0 v -= spacing * 1.0 super().__init__(root_widget=ba.containerwidget( size=(self._width, self._height), transition=transition, toolbar_visibility='menu_minimal', scale_origin_stack_offset=scale_origin, scale=(2.3 if uiscale is ba.UIScale.SMALL else 1.6 if uiscale is ba.UIScale.MEDIUM else 1.0), stack_offset=(0, -18) if uiscale is ba.UIScale.SMALL else (0, 0))) if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL: self._back_button = None else: self._back_button = ba.buttonwidget( parent=self._root_widget, position=(45 + x_inset, self._height - 60), size=(120, 60), scale=0.8, label=ba.Lstr(resource='backText'), button_type='back', autoselect=True) ba.buttonwidget(edit=self._back_button, button_type='backSmall', size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, self._height - 35), size=(0, 0), maxwidth=300, text=ba.Lstr(resource=self._r + '.titleText'), color=ba.app.ui.title_color, h_align='center', v_align='center') h = 43 + x_inset v = self._height - 60 b_color = (0.6, 0.53, 0.63) b_textcolor = (0.75, 0.7, 0.8) lock_tex = ba.gettexture('lock') self._lock_images: list[ba.Widget] = [] scl = (1.0 if uiscale is ba.UIScale.SMALL else 1.13 if uiscale is ba.UIScale.MEDIUM else 1.4) v -= 60.0 * scl self._new_button = btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(100, 55.0 * scl), on_activate_call=self._new_soundtrack, color=b_color, button_type='square', autoselect=True, textcolor=b_textcolor, text_scale=0.7, label=ba.Lstr(resource=self._r + '.newText')) self._lock_images.append( ba.imagewidget(parent=self._root_widget, size=(30, 30), draw_controller=btn, position=(h - 10, v + 55.0 * scl - 28), texture=lock_tex)) if self._back_button is None: ba.widget(edit=btn, left_widget=_ba.get_special_widget('back_button')) v -= 60.0 * scl self._edit_button = btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(100, 55.0 * scl), on_activate_call=self._edit_soundtrack, color=b_color, button_type='square', autoselect=True, textcolor=b_textcolor, text_scale=0.7, label=ba.Lstr(resource=self._r + '.editText')) self._lock_images.append( ba.imagewidget(parent=self._root_widget, size=(30, 30), draw_controller=btn, position=(h - 10, v + 55.0 * scl - 28), texture=lock_tex)) if self._back_button is None: ba.widget(edit=btn, left_widget=_ba.get_special_widget('back_button')) v -= 60.0 * scl self._duplicate_button = btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(100, 55.0 * scl), on_activate_call=self._duplicate_soundtrack, button_type='square', autoselect=True, color=b_color, textcolor=b_textcolor, text_scale=0.7, label=ba.Lstr(resource=self._r + '.duplicateText')) self._lock_images.append( ba.imagewidget(parent=self._root_widget, size=(30, 30), draw_controller=btn, position=(h - 10, v + 55.0 * scl - 28), texture=lock_tex)) if self._back_button is None: ba.widget(edit=btn, left_widget=_ba.get_special_widget('back_button')) v -= 60.0 * scl self._delete_button = btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(100, 55.0 * scl), on_activate_call=self._delete_soundtrack, color=b_color, button_type='square', autoselect=True, textcolor=b_textcolor, text_scale=0.7, label=ba.Lstr(resource=self._r + '.deleteText')) self._lock_images.append( ba.imagewidget(parent=self._root_widget, size=(30, 30), draw_controller=btn, position=(h - 10, v + 55.0 * scl - 28), texture=lock_tex)) if self._back_button is None: ba.widget(edit=btn, left_widget=_ba.get_special_widget('back_button')) # Keep our lock images up to date/etc. self._update_timer = ba.Timer(1.0, ba.WeakCall(self._update), timetype=ba.TimeType.REAL, repeat=True) self._update() v = self._height - 65 scroll_height = self._height - 105 v -= scroll_height self._scrollwidget = scrollwidget = ba.scrollwidget( parent=self._root_widget, position=(152 + x_inset, v), highlight=False, size=(self._width - (205 + 2 * x_inset), scroll_height)) ba.widget(edit=self._scrollwidget, left_widget=self._new_button, right_widget=_ba.get_special_widget('party_button') if ba.app.ui.use_toolbars else self._scrollwidget) self._col = ba.columnwidget(parent=scrollwidget, border=2, margin=0) self._soundtracks: Optional[dict[str, Any]] = None self._selected_soundtrack: Optional[str] = None self._selected_soundtrack_index: Optional[int] = None self._soundtrack_widgets: list[ba.Widget] = [] self._allow_changing_soundtracks = False self._refresh() if self._back_button is not None: ba.buttonwidget(edit=self._back_button, on_activate_call=self._back) ba.containerwidget(edit=self._root_widget, cancel_button=self._back_button) else: ba.containerwidget(edit=self._root_widget, on_cancel_call=self._back)
def _update(self) -> None: # We may outlive our widgets. if not self.root_widget: return # If we've been foregrounded/backgrounded we need to re-grab data. if self._fg_state != ba.app.fg_state: self._fg_state = ba.app.fg_state self._have_valid_data = False # If we need to run another tournament query, do so. if not self._running_query and ( (self._last_query_time is None) or (not self._have_valid_data) or (ba.time(ba.TimeType.REAL) - self._last_query_time > 30.0)): _ba.tournament_query(args={ 'source': 'entry window' if self._tournament_activity is None else 'retry entry window' }, callback=ba.WeakCall( self._on_tournament_query_response)) self._last_query_time = ba.time(ba.TimeType.REAL) self._running_query = True # Grab the latest info on our tourney. self._tournament_info = ba.app.tournament_info[self._tournament_id] # If we don't have valid data always show a '-' for time. if not self._have_valid_data: ba.textwidget(edit=self._time_remaining_text, text='-') else: if self._seconds_remaining is not None: self._seconds_remaining = max(0, self._seconds_remaining - 1) ba.textwidget(edit=self._time_remaining_text, text=ba.timestring( self._seconds_remaining * 1000, centi=False, timeformat=ba.TimeFormat.MILLISECONDS)) # Keep price up-to-date and update the button with it. self._purchase_price = _ba.get_account_misc_read_val( self._purchase_price_name, None) ba.textwidget( edit=self._ticket_cost_text, text=(ba.Lstr(resource='getTicketsWindow.freeText') if self._purchase_price == 0 else ba.Lstr( resource='getTicketsWindow.ticketsText', subs=[('${COUNT}', str(self._purchase_price) if self._purchase_price is not None else '?')])), position=self._ticket_cost_text_position_free if self._purchase_price == 0 else self._ticket_cost_text_position, scale=1.0 if self._purchase_price == 0 else 0.6) ba.textwidget( edit=self._free_plays_remaining_text, text='' if (self._tournament_info['freeTriesRemaining'] in [None, 0] or self._purchase_price != 0) else '' + str(self._tournament_info['freeTriesRemaining'])) ba.imagewidget(edit=self._ticket_img, opacity=0.2 if self._purchase_price == 0 else 1.0, position=self._ticket_img_pos_free if self._purchase_price == 0 else self._ticket_img_pos) if self._do_ad_btn: enabled = _ba.have_incentivized_ad() have_ad_tries_remaining = ( self._tournament_info['adTriesRemaining'] is not None and self._tournament_info['adTriesRemaining'] > 0) ba.textwidget(edit=self._ad_text, position=self._ad_text_position_remaining if have_ad_tries_remaining else self._ad_text_position, color=(0, 1, 0) if enabled else (0.5, 0.5, 0.5)) ba.imagewidget(edit=self._pay_with_ad_img, opacity=1.0 if enabled else 0.2) ba.buttonwidget(edit=self._pay_with_ad_btn, color=(0.5, 0.7, 0.2) if enabled else (0.5, 0.5, 0.5)) ad_plays_remaining_text = ( '' if not have_ad_tries_remaining else '' + str(self._tournament_info['adTriesRemaining'])) ba.textwidget(edit=self._ad_plays_remaining_text, text=ad_plays_remaining_text, color=(0, 0.8, 0) if enabled else (0.4, 0.4, 0.4)) try: t_str = str(_ba.get_account_ticket_count()) except Exception: t_str = '?' if self._get_tickets_button is not None: ba.buttonwidget(edit=self._get_tickets_button, label=ba.charstr(ba.SpecialChar.TICKET) + t_str)
def __init__(self) -> None: from typing import cast width = 480 height = 170 spacing = 40 self._r = 'configGamepadSelectWindow' uiscale = ba.app.uiscale super().__init__(root_widget=ba.containerwidget( scale=(2.3 if uiscale is ba.UIScale.SMALL else 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0), size=(width, height), transition='in_right', )) btn = ba.buttonwidget(parent=self._root_widget, position=(20, height - 60), size=(130, 60), label=ba.Lstr(resource='backText'), button_type='back', scale=0.8, on_activate_call=self._back) # Let's not have anything selected by default; its misleading looking # for the controller getting configured. ba.containerwidget(edit=self._root_widget, cancel_button=btn, selected_child=cast(ba.Widget, 0)) ba.textwidget(parent=self._root_widget, position=(20, height - 50), size=(width, 25), text=ba.Lstr(resource=self._r + '.titleText'), maxwidth=250, color=ba.app.title_color, h_align='center', v_align='center') ba.buttonwidget(edit=btn, button_type='backSmall', size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) v: float = height - 60 v -= spacing ba.textwidget(parent=self._root_widget, position=(15, v), size=(width - 30, 30), scale=0.8, text=ba.Lstr(resource=self._r + '.pressAnyButtonText'), maxwidth=width * 0.95, color=ba.app.infotextcolor, h_align='center', v_align='top') v -= spacing * 1.24 if ba.app.platform == 'android': ba.textwidget(parent=self._root_widget, position=(15, v), size=(width - 30, 30), scale=0.46, text=ba.Lstr(resource=self._r + '.androidNoteText'), maxwidth=width * 0.95, color=(0.7, 0.9, 0.7, 0.5), h_align='center', v_align='top') _ba.capture_gamepad_input(gamepad_configure_callback)
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.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.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.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.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.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.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.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.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.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)
def __init__(self, items: List[str], transition: str = 'in_right', header_text: ba.Lstr = None): from ba.internal import get_store_item_display_size from bastd.ui.store import item as storeitemui if header_text is None: header_text = ba.Lstr(resource='unlockThisText', fallback_resource='unlockThisInTheStoreText') if len(items) != 1: raise ValueError('expected exactly 1 item') self._items = list(items) self._width = 580 self._height = 520 uiscale = ba.app.uiscale super().__init__(root_widget=ba.containerwidget( size=(self._width, self._height), transition=transition, toolbar_visibility='menu_currency', scale=(1.2 if uiscale is ba.UIScale.SMALL else 1.1 if uiscale is ba.UIScale.MEDIUM else 1.0), stack_offset=(0, -15) if uiscale is ba.UIScale.SMALL else (0, 0))) self._is_double = False self._title_text = ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, self._height - 30), size=(0, 0), text=header_text, h_align='center', v_align='center', maxwidth=self._width * 0.9 - 120, scale=1.2, color=(1, 0.8, 0.3, 1)) size = get_store_item_display_size(items[0]) display: Dict[str, Any] = {} storeitemui.instantiate_store_item_display( items[0], display, parent_widget=self._root_widget, b_pos=(self._width * 0.5 - size[0] * 0.5 + 10 - ((size[0] * 0.5 + 30) if self._is_double else 0), self._height * 0.5 - size[1] * 0.5 + 30 + (20 if self._is_double else 0)), b_width=size[0], b_height=size[1], button=False) # Wire up the parts we need. if self._is_double: pass # not working else: if self._items == ['pro']: price_str = _ba.get_price(self._items[0]) pyoffs = -15 else: pyoffs = 0 price = self._price = _ba.get_account_misc_read_val( 'price.' + str(items[0]), -1) price_str = ba.charstr(ba.SpecialChar.TICKET) + str(price) self._price_text = ba.textwidget(parent=self._root_widget, position=(self._width * 0.5, 150 + pyoffs), size=(0, 0), text=price_str, h_align='center', v_align='center', maxwidth=self._width * 0.9, scale=1.4, color=(0.2, 1, 0.2)) self._update_timer = ba.Timer(1.0, ba.WeakCall(self._update), timetype=ba.TimeType.REAL, repeat=True) self._cancel_button = ba.buttonwidget( parent=self._root_widget, position=(50, 40), size=(150, 60), scale=1.0, on_activate_call=self._cancel, autoselect=True, label=ba.Lstr(resource='cancelText')) self._purchase_button = ba.buttonwidget( parent=self._root_widget, position=(self._width - 200, 40), size=(150, 60), scale=1.0, on_activate_call=self._purchase, autoselect=True, label=ba.Lstr(resource='store.purchaseText')) ba.containerwidget(edit=self._root_widget, cancel_button=self._cancel_button, start_button=self._purchase_button, selected_child=self._purchase_button)
def _load_keyboard(self) -> None: # pylint: disable=too-many-locals self._keyboard = self._get_keyboard() # We want to get just chars without column data, etc. self._chars = [j for i in self._keyboard.chars for j in i] self._modes = ['normal'] + list(self._keyboard.pages) self._mode_index = 0 self._mode = self._modes[self._mode_index] v = self._height - 180.0 key_width = 46 * 10 / len(self._keyboard.chars[0]) key_height = 46 * 3 / len(self._keyboard.chars) key_textcolor = (1, 1, 1) row_starts = (69.0, 95.0, 151.0) key_color = self._key_color key_color_dark = self._key_color_dark self._click_sound = ba.getsound('click01') # kill prev char keys for key in self._char_keys: key.delete() self._char_keys = [] # dummy data just used for row/column lengths... we don't actually # set things until refresh chars: List[Tuple[str, ...]] = self._keyboard.chars for row_num, row in enumerate(chars): h = row_starts[row_num] # shift key before row 3 if row_num == 2 and self._shift_button is None: self._shift_button = ba.buttonwidget( parent=self._root_widget, position=(h - key_width * 2.0, v), size=(key_width * 1.7, key_height), autoselect=True, textcolor=key_textcolor, color=key_color_dark, label=charstr(SpCh.SHIFT), enable_sound=False, extra_touch_border_scale=0.3, button_type='square', ) for _ in row: btn = ba.buttonwidget( parent=self._root_widget, position=(h, v), size=(key_width, key_height), autoselect=True, enable_sound=False, textcolor=key_textcolor, color=key_color, label='', button_type='square', extra_touch_border_scale=0.1, ) self._char_keys.append(btn) h += key_width + 10 # Add delete key at end of third row. if row_num == 2: if self._backspace_button is not None: self._backspace_button.delete() self._backspace_button = ba.buttonwidget( parent=self._root_widget, position=(h + 4, v), size=(key_width * 1.8, key_height), autoselect=True, enable_sound=False, repeat=True, textcolor=key_textcolor, color=key_color_dark, label=charstr(SpCh.DELETE), button_type='square', on_activate_call=self._del) v -= (key_height + 9) # Do space bar and stuff. if row_num == 2: if self._num_mode_button is None: self._num_mode_button = ba.buttonwidget( parent=self._root_widget, position=(112, v - 8), size=(key_width * 2, key_height + 5), enable_sound=False, button_type='square', extra_touch_border_scale=0.3, autoselect=True, textcolor=key_textcolor, color=key_color_dark, label='', ) if self._emoji_button is None: self._emoji_button = ba.buttonwidget( parent=self._root_widget, position=(56, v - 8), size=(key_width, key_height + 5), autoselect=True, enable_sound=False, textcolor=key_textcolor, color=key_color_dark, label=charstr(SpCh.LOGO_FLAT), extra_touch_border_scale=0.3, button_type='square', ) btn1 = self._num_mode_button if self._space_button is None: self._space_button = ba.buttonwidget( parent=self._root_widget, position=(210, v - 12), size=(key_width * 6.1, key_height + 15), extra_touch_border_scale=0.3, enable_sound=False, autoselect=True, textcolor=key_textcolor, color=key_color_dark, label=ba.Lstr(resource='spaceKeyText'), on_activate_call=ba.Call(self._type_char, ' ')) # Show change instructions only if we have more than one # keyboard option. if (ba.app.meta.metascan is not None and len(ba.app.meta.metascan.keyboards) > 1): ba.textwidget( parent=self._root_widget, h_align='center', position=(210, v - 70), size=(key_width * 6.1, key_height + 15), text=ba.Lstr( resource='keyboardChangeInstructionsText'), scale=0.75) btn2 = self._space_button btn3 = self._emoji_button ba.widget(edit=btn1, right_widget=btn2, left_widget=btn3) ba.widget(edit=btn2, left_widget=btn1, right_widget=self._done_button) ba.widget(edit=btn3, left_widget=btn1) ba.widget(edit=self._done_button, left_widget=btn2) ba.containerwidget(edit=self._root_widget, selected_child=self._char_keys[14]) self._refresh()
def __init__(self) -> None: self._width = 650 self._height = 380 self._spacing = 40 self._r = 'configTouchscreenWindow' _ba.set_touchscreen_editing(True) uiscale = ba.app.uiscale super().__init__(root_widget=ba.containerwidget( size=(self._width, self._height), transition='in_right', scale=(1.9 if uiscale is ba.UIScale.SMALL else 1.55 if uiscale is ba.UIScale.MEDIUM else 1.2))) btn = ba.buttonwidget(parent=self._root_widget, position=(55, self._height - 60), size=(120, 60), label=ba.Lstr(resource='backText'), button_type='back', scale=0.8, on_activate_call=self._back) ba.containerwidget(edit=self._root_widget, cancel_button=btn) ba.textwidget(parent=self._root_widget, position=(25, self._height - 50), size=(self._width, 25), text=ba.Lstr(resource=self._r + '.titleText'), color=ba.app.title_color, maxwidth=280, h_align='center', v_align='center') ba.buttonwidget(edit=btn, button_type='backSmall', size=(60, 60), label=ba.charstr(ba.SpecialChar.BACK)) self._scroll_width = self._width - 100 self._scroll_height = self._height - 110 self._sub_width = self._scroll_width - 20 self._sub_height = 360 self._scrollwidget = ba.scrollwidget( parent=self._root_widget, position=((self._width - self._scroll_width) * 0.5, self._height - 65 - self._scroll_height), size=(self._scroll_width, self._scroll_height)) self._subcontainer = ba.containerwidget(parent=self._scrollwidget, size=(self._sub_width, self._sub_height), background=False) ba.containerwidget(edit=self._scrollwidget, claims_left_right=True, claims_tab=True, selection_loop_to_parent=True) ba.containerwidget(edit=self._subcontainer, claims_left_right=True, claims_tab=True, selection_loop_to_parent=True) self._build_gui()