def ensure_have_account_player_profile() -> None: """ Ensure the standard account-named player profile exists; creating if needed. """ # This only applies when we're signed in. if _ba.get_account_state() != 'signed_in': return # If the short version of our account name currently cant be # displayed by the game, cancel. if not _ba.have_chars(_ba.get_account_display_string(full=False)): return config = _ba.app.config if ('Player Profiles' not in config or '__account__' not in config['Player Profiles']): # Create a spaz with a nice default purply color. _ba.add_transaction({ 'type': 'ADD_PLAYER_PROFILE', 'name': '__account__', 'profile': { 'character': 'Spaz', 'color': [0.5, 0.25, 1.0], 'highlight': [0.5, 0.25, 1.0] } }) _ba.run_transactions()
def _refresh_account_name_text(self) -> None: if self._account_name_text is None: return try: name_str = _ba.get_account_display_string() except Exception: ba.print_exception() name_str = '??' ba.textwidget(edit=self._account_name_text, text=name_str)
def _update_field(self, response: dict[str, Any]) -> None: if self._angry_computer_image is None: self._angry_computer_image = ba.imagewidget( parent=self._root_widget, position=(self._width - 180, self._height * 0.5 - 65), size=(150, 150), texture=self.lineup_tex, model_transparent=self._angry_computer_transparent_model) if self._line_image is None: self._line_image = ba.imagewidget( parent=self._root_widget, color=(0.0, 0.0, 0.0), opacity=0.2, position=(self._line_left, self._line_bottom - 2.0), size=(self._line_width, 4.0), texture=self._white_tex) # now go through the data they sent, creating dudes for us and our # enemies as needed and updating target positions on all of them.. # mark all as unclaimed so we know which ones to kill off.. for dude in self._dudes: dude.claimed = False # always have a dude for ourself.. if -1 not in self._dudes_by_id: dude = self.Dude( self, response['d'], self._initial_offset, True, _ba.get_account_misc_read_val_2('resolvedAccountID', None), _ba.get_account_display_string()) self._dudes_by_id[-1] = dude self._dudes.append(dude) else: self._dudes_by_id[-1].set_target_distance(response['d']) self._dudes_by_id[-1].claimed = True # now create/destroy enemies for (enemy_id, enemy_distance, enemy_account_id, enemy_name) in response['e']: if enemy_id not in self._dudes_by_id: dude = self.Dude(self, enemy_distance, self._initial_offset, False, enemy_account_id, enemy_name) self._dudes_by_id[enemy_id] = dude self._dudes.append(dude) else: self._dudes_by_id[enemy_id].set_target_distance(enemy_distance) self._dudes_by_id[enemy_id].claimed = True # remove unclaimed dudes from both of our lists # noinspection PyUnresolvedReferences self._dudes_by_id = dict([ item for item in list(self._dudes_by_id.items()) if item[1].claimed ]) self._dudes = [dude for dude in self._dudes if dude.claimed]
def get_last_player_name_from_input_device(device: ba.InputDevice) -> str: """Return a reasonable player name associated with a device. (generally the last one used there) """ appconfig = _ba.app.config # Look for a default player profile name for them; # otherwise default to their current random name. profilename = '_random' key_name = device.name + ' ' + device.unique_identifier if ('Default Player Profiles' in appconfig and key_name in appconfig['Default Player Profiles']): profilename = appconfig['Default Player Profiles'][key_name] if profilename == '_random': profilename = device.get_default_player_name() if profilename == '__account__': profilename = _ba.get_account_display_string() return profilename
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 _refresh_not_in_game( self, positions: List[Tuple[float, float, float]]) -> Tuple[float, float, float]: # pylint: disable=too-many-branches # pylint: disable=too-many-locals # pylint: disable=too-many-statements if not ba.app.did_menu_intro: self._tdelay = 2.0 self._t_delay_inc = 0.02 self._t_delay_play = 1.7 ba.app.did_menu_intro = True self._width = 400.0 self._height = 200.0 enable_account_button = True account_type_name: Union[str, ba.Lstr] if _ba.get_account_state() == 'signed_in': account_type_name = _ba.get_account_display_string() account_type_icon = None account_textcolor = (1.0, 1.0, 1.0) else: account_type_name = ba.Lstr( resource='notSignedInText', fallback_resource='accountSettingsWindow.titleText') account_type_icon = None account_textcolor = (1.0, 0.2, 0.2) account_type_icon_color = (1.0, 1.0, 1.0) account_type_call = self._show_account_window account_type_enable_button_sound = True b_count = 3 # play, help, credits if self._have_settings_button: b_count += 1 if enable_account_button: b_count += 1 if self._have_quit_button: b_count += 1 if self._have_store_button: b_count += 1 uiscale = ba.app.ui.uiscale if uiscale is ba.UIScale.SMALL: root_widget_scale = 1.6 play_button_width = self._button_width * 0.65 play_button_height = self._button_height * 1.1 small_button_scale = 0.51 if b_count > 6 else 0.63 button_y_offs = -20.0 button_y_offs2 = -60.0 self._button_height *= 1.3 button_spacing = 1.04 elif uiscale is ba.UIScale.MEDIUM: root_widget_scale = 1.3 play_button_width = self._button_width * 0.65 play_button_height = self._button_height * 1.1 small_button_scale = 0.6 button_y_offs = -55.0 button_y_offs2 = -75.0 self._button_height *= 1.25 button_spacing = 1.1 else: root_widget_scale = 1.0 play_button_width = self._button_width * 0.65 play_button_height = self._button_height * 1.1 small_button_scale = 0.75 button_y_offs = -80.0 button_y_offs2 = -100.0 self._button_height *= 1.2 button_spacing = 1.1 spc = self._button_width * small_button_scale * button_spacing ba.containerwidget(edit=self._root_widget, size=(self._width, self._height), background=False, scale=root_widget_scale) assert not positions positions.append((self._width * 0.5, button_y_offs, 1.7)) x_offs = self._width * 0.5 - (spc * (b_count - 1) * 0.5) + (spc * 0.5) for i in range(b_count - 1): positions.append( (x_offs + spc * i - 1.0, button_y_offs + button_y_offs2, small_button_scale)) # In kiosk mode, provide a button to get back to the kiosk menu. if ba.app.demo_mode or ba.app.arcade_mode: h, v, scale = positions[self._p_index] this_b_width = self._button_width * 0.4 * scale demo_menu_delay = 0.0 if self._t_delay_play == 0.0 else max( 0, self._t_delay_play + 0.1) self._demo_menu_button = ba.buttonwidget( parent=self._root_widget, position=(self._width * 0.5 - this_b_width * 0.5, v + 90), size=(this_b_width, 45), autoselect=True, color=(0.45, 0.55, 0.45), textcolor=(0.7, 0.8, 0.7), label=ba.Lstr(resource='modeArcadeText' if ba.app. arcade_mode else 'modeDemoText'), transition_delay=demo_menu_delay, on_activate_call=self._demo_menu_press) else: self._demo_menu_button = None uiscale = ba.app.ui.uiscale foof = (-1 if uiscale is ba.UIScale.SMALL else 1 if uiscale is ba.UIScale.MEDIUM else 3) h, v, scale = positions[self._p_index] v = v + foof gather_delay = 0.0 if self._t_delay_play == 0.0 else max( 0.0, self._t_delay_play + 0.1) assert play_button_width is not None assert play_button_height is not None this_h = h - play_button_width * 0.5 * scale - 40 * scale this_b_width = self._button_width * 0.25 * scale this_b_height = self._button_height * 0.82 * scale self._gather_button = btn = ba.buttonwidget( parent=self._root_widget, position=(this_h - this_b_width * 0.5, v), size=(this_b_width, this_b_height), autoselect=self._use_autoselect, button_type='square', label='', transition_delay=gather_delay, on_activate_call=self._gather_press) ba.textwidget(parent=self._root_widget, position=(this_h, v + self._button_height * 0.33), size=(0, 0), scale=0.75, transition_delay=gather_delay, draw_controller=btn, color=(0.75, 1.0, 0.7), maxwidth=self._button_width * 0.33, text=ba.Lstr(resource='gatherWindow.titleText'), h_align='center', v_align='center') icon_size = this_b_width * 0.6 ba.imagewidget(parent=self._root_widget, size=(icon_size, icon_size), draw_controller=btn, transition_delay=gather_delay, position=(this_h - 0.5 * icon_size, v + 0.31 * this_b_height), texture=ba.gettexture('usersButton')) # Play button. h, v, scale = positions[self._p_index] self._p_index += 1 self._start_button = start_button = ba.buttonwidget( parent=self._root_widget, position=(h - play_button_width * 0.5 * scale, v), size=(play_button_width, play_button_height), autoselect=self._use_autoselect, scale=scale, text_res_scale=2.0, label=ba.Lstr(resource='playText'), transition_delay=self._t_delay_play, on_activate_call=self._play_press) ba.containerwidget(edit=self._root_widget, start_button=start_button, selected_child=start_button) v = v + foof watch_delay = 0.0 if self._t_delay_play == 0.0 else max( 0.0, self._t_delay_play - 0.1) this_h = h + play_button_width * 0.5 * scale + 40 * scale this_b_width = self._button_width * 0.25 * scale this_b_height = self._button_height * 0.82 * scale self._watch_button = btn = ba.buttonwidget( parent=self._root_widget, position=(this_h - this_b_width * 0.5, v), size=(this_b_width, this_b_height), autoselect=self._use_autoselect, button_type='square', label='', transition_delay=watch_delay, on_activate_call=self._watch_press) ba.textwidget(parent=self._root_widget, position=(this_h, v + self._button_height * 0.33), size=(0, 0), scale=0.75, transition_delay=watch_delay, color=(0.75, 1.0, 0.7), draw_controller=btn, maxwidth=self._button_width * 0.33, text=ba.Lstr(resource='watchWindow.titleText'), h_align='center', v_align='center') icon_size = this_b_width * 0.55 ba.imagewidget(parent=self._root_widget, size=(icon_size, icon_size), draw_controller=btn, transition_delay=watch_delay, position=(this_h - 0.5 * icon_size, v + 0.33 * this_b_height), texture=ba.gettexture('tv')) if not self._in_game and enable_account_button: this_b_width = self._button_width h, v, scale = positions[self._p_index] self._p_index += 1 self._gc_button = ba.buttonwidget( parent=self._root_widget, position=(h - this_b_width * 0.5 * scale, v), size=(this_b_width, self._button_height), scale=scale, label=account_type_name, autoselect=self._use_autoselect, on_activate_call=account_type_call, textcolor=account_textcolor, icon=account_type_icon, icon_color=account_type_icon_color, transition_delay=self._tdelay, enable_sound=account_type_enable_button_sound) # Scattered eggs on easter. if _ba.get_account_misc_read_val('easter', False) and not self._in_game: icon_size = 32 ba.imagewidget(parent=self._root_widget, position=(h - icon_size * 0.5 + 35, v + self._button_height * scale - icon_size * 0.24 + 1.5), transition_delay=self._tdelay, size=(icon_size, icon_size), texture=ba.gettexture('egg2'), tilt_scale=0.0) self._tdelay += self._t_delay_inc else: self._gc_button = None # How-to-play button. h, v, scale = positions[self._p_index] self._p_index += 1 btn = ba.buttonwidget( parent=self._root_widget, position=(h - self._button_width * 0.5 * scale, v), scale=scale, autoselect=self._use_autoselect, size=(self._button_width, self._button_height), label=ba.Lstr(resource=self._r + '.howToPlayText'), transition_delay=self._tdelay, on_activate_call=self._howtoplay) self._how_to_play_button = btn # Scattered eggs on easter. if _ba.get_account_misc_read_val('easter', False) and not self._in_game: icon_size = 28 ba.imagewidget(parent=self._root_widget, position=(h - icon_size * 0.5 + 30, v + self._button_height * scale - icon_size * 0.24 + 1.5), transition_delay=self._tdelay, size=(icon_size, icon_size), texture=ba.gettexture('egg4'), tilt_scale=0.0) # Credits button. self._tdelay += self._t_delay_inc h, v, scale = positions[self._p_index] self._p_index += 1 self._credits_button = ba.buttonwidget( parent=self._root_widget, position=(h - self._button_width * 0.5 * scale, v), size=(self._button_width, self._button_height), autoselect=self._use_autoselect, label=ba.Lstr(resource=self._r + '.creditsText'), scale=scale, transition_delay=self._tdelay, on_activate_call=self._credits) self._tdelay += self._t_delay_inc return h, v, scale
def on_transition_in(self) -> None: super().on_transition_in() random.seed(123) self._logo_node: Optional[ba.Node] = None self._custom_logo_tex_name: Optional[str] = None self._word_actors: List[ba.Actor] = [] app = ba.app # FIXME: We shouldn't be doing things conditionally based on whether # the host is VR mode or not (clients may differ in that regard). # Any differences need to happen at the engine level so everyone # sees things in their own optimal way. vr_mode = ba.app.vr_mode if not ba.app.toolbar_test: color = ((1.0, 1.0, 1.0, 1.0) if vr_mode else (0.5, 0.6, 0.5, 0.6)) # FIXME: Need a node attr for vr-specific-scale. scale = (0.9 if (app.ui.uiscale is ba.UIScale.SMALL or vr_mode) else 0.7) self.my_name = ba.NodeActor( ba.newnode('text', attrs={ 'v_attach': 'bottom', 'h_align': 'center', 'color': color, 'flatness': 1.0, 'shadow': 1.0 if vr_mode else 0.5, 'scale': scale, 'position': (0, 10), 'vr_depth': -10, 'text': '\xa9 2011-2020 Eric Froemling' })) # Throw up some text that only clients can see so they know that the # host is navigating menus while they're just staring at an # empty-ish screen. tval = ba.Lstr(resource='hostIsNavigatingMenusText', subs=[('${HOST}', _ba.get_account_display_string())]) self._host_is_navigating_text = ba.NodeActor( ba.newnode('text', attrs={ 'text': tval, 'client_only': True, 'position': (0, -200), 'flatness': 1.0, 'h_align': 'center' })) if not ba.app.main_menu_did_initial_transition and hasattr( self, 'my_name'): assert self.my_name.node ba.animate(self.my_name.node, 'opacity', {2.3: 0, 3.0: 1.0}) # FIXME: We shouldn't be doing things conditionally based on whether # the host is vr mode or not (clients may not be or vice versa). # Any differences need to happen at the engine level so everyone sees # things in their own optimal way. vr_mode = app.vr_mode uiscale = app.ui.uiscale # In cases where we're doing lots of dev work lets always show the # build number. force_show_build_number = False if not ba.app.toolbar_test: if app.debug_build or app.test_build or force_show_build_number: if app.debug_build: text = ba.Lstr(value='${V} (${B}) (${D})', subs=[ ('${V}', app.version), ('${B}', str(app.build_number)), ('${D}', ba.Lstr(resource='debugText')), ]) else: text = ba.Lstr(value='${V} (${B})', subs=[ ('${V}', app.version), ('${B}', str(app.build_number)), ]) else: text = ba.Lstr(value='${V}', subs=[('${V}', app.version)]) scale = 0.9 if (uiscale is ba.UIScale.SMALL or vr_mode) else 0.7 color = (1, 1, 1, 1) if vr_mode else (0.5, 0.6, 0.5, 0.7) self.version = ba.NodeActor( ba.newnode( 'text', attrs={ 'v_attach': 'bottom', 'h_attach': 'right', 'h_align': 'right', 'flatness': 1.0, 'vr_depth': -10, 'shadow': 1.0 if vr_mode else 0.5, 'color': color, 'scale': scale, 'position': (-260, 10) if vr_mode else (-10, 10), 'text': text })) if not ba.app.main_menu_did_initial_transition: assert self.version.node ba.animate(self.version.node, 'opacity', {2.3: 0, 3.0: 1.0}) # Show the iircade logo on our iircade build. if app.iircade_mode: img = ba.NodeActor( ba.newnode('image', attrs={ 'texture': ba.gettexture('iircadeLogo'), 'attach': 'center', 'scale': (250, 250), 'position': (0, 0), 'tilt_translate': 0.21, 'absolute_scale': True })).autoretain() imgdelay = 0.0 if app.main_menu_did_initial_transition else 1.0 ba.animate(img.node, 'opacity', { imgdelay + 1.5: 0.0, imgdelay + 2.5: 1.0 }) # Throw in test build info. self.beta_info = self.beta_info_2 = None if app.test_build and not (app.demo_mode or app.arcade_mode): pos = ((230, 125) if (app.demo_mode or app.arcade_mode) else (230, 35)) self.beta_info = ba.NodeActor( ba.newnode('text', attrs={ 'v_attach': 'center', 'h_align': 'center', 'color': (1, 1, 1, 1), 'shadow': 0.5, 'flatness': 0.5, 'scale': 1, 'vr_depth': -60, 'position': pos, 'text': ba.Lstr(resource='testBuildText') })) if not ba.app.main_menu_did_initial_transition: assert self.beta_info.node ba.animate(self.beta_info.node, 'opacity', {1.3: 0, 1.8: 1.0}) model = ba.getmodel('thePadLevel') trees_model = ba.getmodel('trees') bottom_model = ba.getmodel('thePadLevelBottom') color_texture = ba.gettexture('thePadLevelColor') trees_texture = ba.gettexture('treesColor') bgtex = ba.gettexture('menuBG') bgmodel = ba.getmodel('thePadBG') # Load these last since most platforms don't use them. vr_bottom_fill_model = ba.getmodel('thePadVRFillBottom') vr_top_fill_model = ba.getmodel('thePadVRFillTop') gnode = self.globalsnode gnode.camera_mode = 'rotate' tint = (1.14, 1.1, 1.0) gnode.tint = tint gnode.ambient_color = (1.06, 1.04, 1.03) gnode.vignette_outer = (0.45, 0.55, 0.54) gnode.vignette_inner = (0.99, 0.98, 0.98) self.bottom = ba.NodeActor( ba.newnode('terrain', attrs={ 'model': bottom_model, 'lighting': False, 'reflection': 'soft', 'reflection_scale': [0.45], 'color_texture': color_texture })) self.vr_bottom_fill = ba.NodeActor( ba.newnode('terrain', attrs={ 'model': vr_bottom_fill_model, 'lighting': False, 'vr_only': True, 'color_texture': color_texture })) self.vr_top_fill = ba.NodeActor( ba.newnode('terrain', attrs={ 'model': vr_top_fill_model, 'vr_only': True, 'lighting': False, 'color_texture': bgtex })) self.terrain = ba.NodeActor( ba.newnode('terrain', attrs={ 'model': model, 'color_texture': color_texture, 'reflection': 'soft', 'reflection_scale': [0.3] })) self.trees = ba.NodeActor( ba.newnode('terrain', attrs={ 'model': trees_model, 'lighting': False, 'reflection': 'char', 'reflection_scale': [0.1], 'color_texture': trees_texture })) self.bgterrain = ba.NodeActor( ba.newnode('terrain', attrs={ 'model': bgmodel, 'color': (0.92, 0.91, 0.9), 'lighting': False, 'background': True, 'color_texture': bgtex })) self._ts = 0.86 self._language: Optional[str] = None self._update_timer = ba.Timer(1.0, self._update, repeat=True) self._update() # Hopefully this won't hitch but lets space these out anyway. _ba.add_clean_frame_callback(ba.WeakCall(self._start_preloads)) random.seed() # On the main menu, also show our news. class News: """Wrangles news display.""" def __init__(self, activity: ba.Activity): self._valid = True self._message_duration = 10.0 self._message_spacing = 2.0 self._text: Optional[ba.NodeActor] = None self._activity = weakref.ref(activity) # If we're signed in, fetch news immediately. # Otherwise wait until we are signed in. self._fetch_timer: Optional[ba.Timer] = ba.Timer( 1.0, ba.WeakCall(self._try_fetching_news), repeat=True) self._try_fetching_news() # We now want to wait until we're signed in before fetching news. def _try_fetching_news(self) -> None: if _ba.get_account_state() == 'signed_in': self._fetch_news() self._fetch_timer = None def _fetch_news(self) -> None: ba.app.main_menu_last_news_fetch_time = time.time() # UPDATE - We now just pull news from MRVs. news = _ba.get_account_misc_read_val('n', None) if news is not None: self._got_news(news) def _change_phrase(self) -> None: from bastd.actor.text import Text # If our news is way out of date, lets re-request it; # otherwise, rotate our phrase. assert ba.app.main_menu_last_news_fetch_time is not None if time.time() - ba.app.main_menu_last_news_fetch_time > 600.0: self._fetch_news() self._text = None else: if self._text is not None: if not self._phrases: for phr in self._used_phrases: self._phrases.insert(0, phr) val = self._phrases.pop() if val == '__ACH__': vrmode = app.vr_mode Text(ba.Lstr(resource='nextAchievementsText'), color=((1, 1, 1, 1) if vrmode else (0.95, 0.9, 1, 0.4)), host_only=True, maxwidth=200, position=(-300, -35), h_align=Text.HAlign.RIGHT, transition=Text.Transition.FADE_IN, scale=0.9 if vrmode else 0.7, flatness=1.0 if vrmode else 0.6, shadow=1.0 if vrmode else 0.5, h_attach=Text.HAttach.CENTER, v_attach=Text.VAttach.TOP, transition_delay=1.0, transition_out_delay=self._message_duration ).autoretain() achs = [ a for a in app.achievements if not a.complete ] if achs: ach = achs.pop( random.randrange(min(4, len(achs)))) ach.create_display( -180, -35, 1.0, outdelay=self._message_duration, style='news') if achs: ach = achs.pop( random.randrange(min(8, len(achs)))) ach.create_display( 180, -35, 1.25, outdelay=self._message_duration, style='news') else: spc = self._message_spacing keys = { spc: 0.0, spc + 1.0: 1.0, spc + self._message_duration - 1.0: 1.0, spc + self._message_duration: 0.0 } assert self._text.node ba.animate(self._text.node, 'opacity', keys) # {k: v # for k, v in list(keys.items())}) self._text.node.text = val def _got_news(self, news: str) -> None: # Run this stuff in the context of our activity since we # need to make nodes and stuff.. should fix the serverget # call so it. activity = self._activity() if activity is None or activity.expired: return with ba.Context(activity): self._phrases: List[str] = [] # Show upcoming achievements in non-vr versions # (currently too hard to read in vr). self._used_phrases = ( ['__ACH__'] if not ba.app.vr_mode else []) + [s for s in news.split('<br>\n') if s != ''] self._phrase_change_timer = ba.Timer( (self._message_duration + self._message_spacing), ba.WeakCall(self._change_phrase), repeat=True) scl = 1.2 if (ba.app.ui.uiscale is ba.UIScale.SMALL or ba.app.vr_mode) else 0.8 color2 = ((1, 1, 1, 1) if ba.app.vr_mode else (0.7, 0.65, 0.75, 1.0)) shadow = (1.0 if ba.app.vr_mode else 0.4) self._text = ba.NodeActor( ba.newnode('text', attrs={ 'v_attach': 'top', 'h_attach': 'center', 'h_align': 'center', 'vr_depth': -20, 'shadow': shadow, 'flatness': 0.8, 'v_align': 'top', 'color': color2, 'scale': scl, 'maxwidth': 900.0 / scl, 'position': (0, -10) })) self._change_phrase() if not (app.demo_mode or app.arcade_mode) and not app.toolbar_test: self._news = News(self) # Bring up the last place we were, or start at the main menu otherwise. with ba.Context('ui'): from bastd.ui import specialoffer if bool(False): uicontroller = ba.app.ui.controller assert uicontroller is not None uicontroller.show_main_menu() else: main_menu_location = ba.app.ui.get_main_menu_location() # When coming back from a kiosk-mode game, jump to # the kiosk start screen. if ba.app.demo_mode or ba.app.arcade_mode: # pylint: disable=cyclic-import from bastd.ui.kiosk import KioskWindow ba.app.ui.set_main_menu_window( KioskWindow().get_root_widget()) # ..or in normal cases go back to the main menu else: if main_menu_location == 'Gather': # pylint: disable=cyclic-import from bastd.ui.gather import GatherWindow ba.app.ui.set_main_menu_window( GatherWindow(transition=None).get_root_widget()) elif main_menu_location == 'Watch': # pylint: disable=cyclic-import from bastd.ui.watch import WatchWindow ba.app.ui.set_main_menu_window( WatchWindow(transition=None).get_root_widget()) elif main_menu_location == 'Team Game Select': # pylint: disable=cyclic-import from bastd.ui.playlist.browser import ( PlaylistBrowserWindow) ba.app.ui.set_main_menu_window( PlaylistBrowserWindow( sessiontype=ba.DualTeamSession, transition=None).get_root_widget()) elif main_menu_location == 'Free-for-All Game Select': # pylint: disable=cyclic-import from bastd.ui.playlist.browser import ( PlaylistBrowserWindow) ba.app.ui.set_main_menu_window( PlaylistBrowserWindow( sessiontype=ba.FreeForAllSession, transition=None).get_root_widget()) elif main_menu_location == 'Coop Select': # pylint: disable=cyclic-import from bastd.ui.coop.browser import CoopBrowserWindow ba.app.ui.set_main_menu_window( CoopBrowserWindow( transition=None).get_root_widget()) else: # pylint: disable=cyclic-import from bastd.ui.mainmenu import MainMenuWindow ba.app.ui.set_main_menu_window( MainMenuWindow(transition=None).get_root_widget()) # attempt to show any pending offers immediately. # If that doesn't work, try again in a few seconds # (we may not have heard back from the server) # ..if that doesn't work they'll just have to wait # until the next opportunity. if not specialoffer.show_offer(): def try_again() -> None: if not specialoffer.show_offer(): # Try one last time.. ba.timer(2.0, specialoffer.show_offer, timetype=ba.TimeType.REAL) ba.timer(2.0, try_again, timetype=ba.TimeType.REAL) ba.app.main_menu_did_initial_transition = True
def _refresh(self) -> None: # pylint: disable=too-many-locals from ba.internal import (PlayerProfilesChangedMessage, get_player_profile_colors, get_player_profile_icon) old_selection = self._selected_profile # Delete old. while self._profile_widgets: self._profile_widgets.pop().delete() try: self._profiles = ba.app.config['Player Profiles'] except Exception: self._profiles = {} assert self._profiles is not None items = list(self._profiles.items()) items.sort(key=lambda x: x[0].lower()) index = 0 account_name: Optional[str] if _ba.get_account_state() == 'signed_in': account_name = _ba.get_account_display_string() else: account_name = None widget_to_select = None for p_name, _ in items: if p_name == '__account__' and account_name is None: continue color, _highlight = get_player_profile_colors(p_name) scl = 1.1 txtw = ba.textwidget( parent=self._columnwidget, position=(0, 32), size=((self._width - 40) / scl, 28), text=ba.Lstr( value=account_name if p_name == '__account__' else get_player_profile_icon(p_name) + p_name), h_align='left', v_align='center', on_select_call=ba.WeakCall(self._select, p_name, index), maxwidth=self._scroll_width * 0.92, corner_scale=scl, color=ba.safecolor(color, 0.4), always_highlight=True, on_activate_call=ba.Call(self._edit_button.activate), selectable=True) if index == 0: ba.widget(edit=txtw, up_widget=self._back_button) ba.widget(edit=txtw, show_buffer_top=40, show_buffer_bottom=40) self._profile_widgets.append(txtw) # Select/show this one if it was previously selected # (but defer till after this loop since our height is # still changing). if p_name == old_selection: widget_to_select = txtw index += 1 if widget_to_select is not None: ba.columnwidget(edit=self._columnwidget, selected_child=widget_to_select, visible_child=widget_to_select) # If there's a team-chooser in existence, tell it the profile-list # has probably changed. session = _ba.get_foreground_host_session() if session is not None: session.handlemessage(PlayerProfilesChangedMessage())
def _refresh(self) -> None: # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals # pylint: disable=cyclic-import from bastd.ui import confirm account_state = _ba.get_account_state() account_type = (_ba.get_account_type() if account_state == 'signed_in' else 'unknown') is_google = account_type == 'Google Play' show_local_signed_in_as = False local_signed_in_as_space = 50.0 show_signed_in_as = self._signed_in signed_in_as_space = 95.0 show_sign_in_benefits = not self._signed_in sign_in_benefits_space = 80.0 show_signing_in_text = account_state == 'signing_in' signing_in_text_space = 80.0 show_google_play_sign_in_button = (account_state == 'signed_out' and 'Google Play' in self._show_sign_in_buttons) show_game_circle_sign_in_button = (account_state == 'signed_out' and 'Game Circle' in self._show_sign_in_buttons) show_ali_sign_in_button = (account_state == 'signed_out' and 'Ali' in self._show_sign_in_buttons) show_test_sign_in_button = (account_state == 'signed_out' and 'Test' in self._show_sign_in_buttons) show_device_sign_in_button = (account_state == 'signed_out' and 'Local' in self._show_sign_in_buttons) sign_in_button_space = 70.0 show_game_service_button = (self._signed_in and account_type in ['Game Center', 'Game Circle']) game_service_button_space = 60.0 show_linked_accounts_text = (self._signed_in and _ba.get_account_misc_read_val( 'allowAccountLinking2', False)) linked_accounts_text_space = 60.0 show_achievements_button = (self._signed_in and account_type in ('Google Play', 'Alibaba', 'Local', 'OUYA', 'Test')) achievements_button_space = 60.0 show_achievements_text = (self._signed_in and not show_achievements_button) achievements_text_space = 27.0 show_leaderboards_button = (self._signed_in and is_google) leaderboards_button_space = 60.0 show_campaign_progress = self._signed_in campaign_progress_space = 27.0 show_tickets = self._signed_in tickets_space = 27.0 show_reset_progress_button = False reset_progress_button_space = 70.0 show_player_profiles_button = self._signed_in player_profiles_button_space = 100.0 show_link_accounts_button = (self._signed_in and _ba.get_account_misc_read_val( 'allowAccountLinking2', False)) link_accounts_button_space = 70.0 show_unlink_accounts_button = show_link_accounts_button unlink_accounts_button_space = 90.0 show_sign_out_button = (self._signed_in and account_type in ['Test', 'Local', 'Google Play']) sign_out_button_space = 70.0 if self._subcontainer is not None: self._subcontainer.delete() self._sub_height = 60.0 if show_local_signed_in_as: self._sub_height += local_signed_in_as_space if show_signed_in_as: self._sub_height += signed_in_as_space if show_signing_in_text: self._sub_height += signing_in_text_space if show_google_play_sign_in_button: self._sub_height += sign_in_button_space if show_game_circle_sign_in_button: self._sub_height += sign_in_button_space if show_ali_sign_in_button: self._sub_height += sign_in_button_space if show_test_sign_in_button: self._sub_height += sign_in_button_space if show_device_sign_in_button: self._sub_height += sign_in_button_space if show_game_service_button: self._sub_height += game_service_button_space if show_linked_accounts_text: self._sub_height += linked_accounts_text_space if show_achievements_text: self._sub_height += achievements_text_space if show_achievements_button: self._sub_height += achievements_button_space if show_leaderboards_button: self._sub_height += leaderboards_button_space if show_campaign_progress: self._sub_height += campaign_progress_space if show_tickets: self._sub_height += tickets_space if show_sign_in_benefits: self._sub_height += sign_in_benefits_space if show_reset_progress_button: self._sub_height += reset_progress_button_space if show_player_profiles_button: self._sub_height += player_profiles_button_space if show_link_accounts_button: self._sub_height += link_accounts_button_space if show_unlink_accounts_button: self._sub_height += unlink_accounts_button_space if show_sign_out_button: self._sub_height += sign_out_button_space self._subcontainer = ba.containerwidget(parent=self._scrollwidget, size=(self._sub_width, self._sub_height), background=False) ba.containerwidget(edit=self._scrollwidget, claims_left_right=True, claims_tab=True, selection_loop_to_parent=True) ba.containerwidget(edit=self._subcontainer, claims_left_right=True, claims_tab=True, selection_loop_to_parent=True) first_selectable = None v = self._sub_height - 10.0 if show_local_signed_in_as: v -= local_signed_in_as_space * 0.6 ba.textwidget( parent=self._subcontainer, position=(self._sub_width * 0.5, v), size=(0, 0), text=ba.Lstr( resource='accountSettingsWindow.deviceSpecificAccountText', subs=[('${NAME}', _ba.get_account_display_string())]), scale=0.7, color=(0.5, 0.5, 0.6), maxwidth=self._sub_width * 0.9, flatness=1.0, h_align='center', v_align='center') v -= local_signed_in_as_space * 0.4 self._account_name_text: Optional[ba.Widget] if show_signed_in_as: v -= signed_in_as_space * 0.2 txt = ba.Lstr( resource='accountSettingsWindow.youAreSignedInAsText', fallback_resource='accountSettingsWindow.youAreLoggedInAsText') ba.textwidget(parent=self._subcontainer, position=(self._sub_width * 0.5, v), size=(0, 0), text=txt, scale=0.9, color=ba.app.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.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.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.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.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.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.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 Exception("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.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.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.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.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.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.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.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