def _format_names(names2: Sequence[str], inset: float) -> str: sval = '' # measure a series since there's overlaps and stuff.. space_width = _ba.get_string_width(' ' * 10, suppress_warning=True) / 10.0 spacing = 330.0 col1 = inset col2 = col1 + spacing col3 = col2 + spacing line_width = 0.0 nline = '' for name in names2: # move to the next column (or row) and print if line_width > col3: sval += nline + '\n' nline = '' line_width = 0 if line_width > col2: target = col3 elif line_width > col1: target = col2 else: target = col1 spacingstr = ' ' * int((target - line_width) / space_width) nline += spacingstr nline += name line_width = _ba.get_string_width(nline, suppress_warning=True) if nline != '': sval += nline + '\n' return sval
def _on_query_response(self, data: Optional[Dict[str, Any]]) -> None: # FIXME: Tidy this up. # pylint: disable=too-many-locals # pylint: disable=too-many-branches # pylint: disable=too-many-statements # pylint: disable=too-many-nested-blocks if data is None: ba.textwidget( edit=self._loading_text, text=ba.Lstr(resource='internal.unavailableNoConnectionText')) else: try: self._loading_text.delete() trophystr = '' try: trophystr = data['trophies'] num = 10 chunks = [ trophystr[i:i + num] for i in range(0, len(trophystr), num) ] trophystr = ('\n\n'.join(chunks)) if trophystr == '': trophystr = '-' except Exception: ba.print_exception('Error displaying trophies.') account_name_spacing = 15 tscale = 0.65 ts_height = _ba.get_string_height(trophystr, suppress_warning=True) sub_width = self._width - 80 sub_height = 200 + ts_height * tscale + \ account_name_spacing * len(data['accountDisplayStrings']) self._subcontainer = ba.containerwidget( parent=self._scrollwidget, size=(sub_width, sub_height), background=False) v = sub_height - 20 title_scale = 0.37 center = 0.3 maxwidth_scale = 0.45 showing_character = False if data['profileDisplayString'] is not None: tint_color = (1, 1, 1) try: if data['profile'] is not None: profile = data['profile'] character = ba.app.spaz_appearances.get( profile['character'], None) if character is not None: tint_color = (profile['color'] if 'color' in profile else (1, 1, 1)) tint2_color = (profile['highlight'] if 'highlight' in profile else (1, 1, 1)) icon_tex = character.icon_texture tint_tex = character.icon_mask_texture mask_texture = ba.gettexture( 'characterIconMask') ba.imagewidget( parent=self._subcontainer, position=(sub_width * center - 40, v - 80), size=(80, 80), color=(1, 1, 1), mask_texture=mask_texture, texture=ba.gettexture(icon_tex), tint_texture=ba.gettexture(tint_tex), tint_color=tint_color, tint2_color=tint2_color) v -= 95 except Exception: ba.print_exception('Error displaying character.') ba.textwidget( parent=self._subcontainer, size=(0, 0), position=(sub_width * center, v), h_align='center', v_align='center', scale=0.9, color=ba.safecolor(tint_color, 0.7), shadow=1.0, text=ba.Lstr(value=data['profileDisplayString']), maxwidth=sub_width * maxwidth_scale * 0.75) showing_character = True v -= 33 center = 0.75 if showing_character else 0.5 maxwidth_scale = 0.45 if showing_character else 0.9 v = sub_height - 20 if len(data['accountDisplayStrings']) <= 1: account_title = ba.Lstr( resource='settingsWindow.accountText') else: account_title = ba.Lstr( resource='accountSettingsWindow.accountsText', fallback_resource='settingsWindow.accountText') ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center, v), flatness=1.0, h_align='center', v_align='center', scale=title_scale, color=ba.app.infotextcolor, text=account_title, maxwidth=sub_width * maxwidth_scale) draw_small = (showing_character or len(data['accountDisplayStrings']) > 1) v -= 14 if draw_small else 20 for account_string in data['accountDisplayStrings']: ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center, v), h_align='center', v_align='center', scale=0.55 if draw_small else 0.8, text=account_string, maxwidth=sub_width * maxwidth_scale) v -= account_name_spacing v += account_name_spacing v -= 25 if showing_character else 29 ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center, v), flatness=1.0, h_align='center', v_align='center', scale=title_scale, color=ba.app.infotextcolor, text=ba.Lstr(resource='rankText'), maxwidth=sub_width * maxwidth_scale) v -= 14 if data['rank'] is None: rank_str = '-' suffix_offset = None else: str_raw = ba.Lstr( resource='league.rankInLeagueText').evaluate() # FIXME: Would be nice to not have to eval this. rank_str = ba.Lstr( resource='league.rankInLeagueText', subs=[('${RANK}', str(data['rank'][2])), ('${NAME}', ba.Lstr(translate=('leagueNames', data['rank'][0]))), ('${SUFFIX}', '')]).evaluate() rank_str_width = min( sub_width * maxwidth_scale, _ba.get_string_width(rank_str, suppress_warning=True) * 0.55) # Only tack our suffix on if its at the end and only for # non-diamond leagues. if (str_raw.endswith('${SUFFIX}') and data['rank'][0] != 'Diamond'): suffix_offset = rank_str_width * 0.5 + 2 else: suffix_offset = None ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center, v), h_align='center', v_align='center', scale=0.55, text=rank_str, maxwidth=sub_width * maxwidth_scale) if suffix_offset is not None: assert data['rank'] is not None ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center + suffix_offset, v + 3), h_align='left', v_align='center', scale=0.29, flatness=1.0, text='[' + str(data['rank'][1]) + ']') v -= 14 str_raw = ba.Lstr( resource='league.rankInLeagueText').evaluate() old_offs = -50 prev_ranks_shown = 0 for prev_rank in data['prevRanks']: rank_str = ba.Lstr( value='${S}: ${I}', subs=[ ('${S}', ba.Lstr(resource='league.seasonText', subs=[('${NUMBER}', str(prev_rank[0]))])), ('${I}', ba.Lstr(resource='league.rankInLeagueText', subs=[('${RANK}', str(prev_rank[3])), ('${NAME}', ba.Lstr(translate=('leagueNames', prev_rank[1]))), ('${SUFFIX}', '')])) ]).evaluate() rank_str_width = min( sub_width * maxwidth_scale, _ba.get_string_width(rank_str, suppress_warning=True) * 0.3) # Only tack our suffix on if its at the end and only for # non-diamond leagues. if (str_raw.endswith('${SUFFIX}') and prev_rank[1] != 'Diamond'): suffix_offset = rank_str_width + 2 else: suffix_offset = None ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center + old_offs, v), h_align='left', v_align='center', scale=0.3, text=rank_str, flatness=1.0, maxwidth=sub_width * maxwidth_scale) if suffix_offset is not None: ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center + old_offs + suffix_offset, v + 1), h_align='left', v_align='center', scale=0.20, flatness=1.0, text='[' + str(prev_rank[2]) + ']') prev_ranks_shown += 1 v -= 10 v -= 13 ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center, v), flatness=1.0, h_align='center', v_align='center', scale=title_scale, color=ba.app.infotextcolor, text=ba.Lstr(resource='achievementsText'), maxwidth=sub_width * maxwidth_scale) v -= 14 ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center, v), h_align='center', v_align='center', scale=0.55, text=str(data['achievementsCompleted']) + ' / ' + str(len(ba.app.achievements)), maxwidth=sub_width * maxwidth_scale) v -= 25 if prev_ranks_shown == 0 and showing_character: v -= 20 elif prev_ranks_shown == 1 and showing_character: v -= 10 center = 0.5 maxwidth_scale = 0.9 ba.textwidget(parent=self._subcontainer, size=(0, 0), position=(sub_width * center, v), h_align='center', v_align='center', scale=title_scale, color=ba.app.infotextcolor, flatness=1.0, text=ba.Lstr(resource='trophiesThisSeasonText', fallback_resource='trophiesText'), maxwidth=sub_width * maxwidth_scale) v -= 19 ba.textwidget(parent=self._subcontainer, size=(0, ts_height), position=(sub_width * 0.5, v - ts_height * tscale), h_align='center', v_align='top', corner_scale=tscale, text=trophystr) except Exception: ba.print_exception('Error displaying account info.')
def __init__(self, main_menu: bool = False, origin_widget: ba.Widget = None): # pylint: disable=too-many-statements # pylint: disable=too-many-locals from ba.internal import get_remote_app_name from ba.deprecated import get_resource ba.set_analytics_screen('Help Window') # If they provided an origin-widget, scale up from that. scale_origin: Optional[Tuple[float, float]] if origin_widget is not None: self._transition_out = 'out_scale' scale_origin = origin_widget.get_screen_space_center() transition = 'in_scale' else: self._transition_out = 'out_right' scale_origin = None transition = 'in_right' self._r = 'helpWindow' self._main_menu = main_menu width = 950 if ba.app.small_ui else 750 x_offs = 100 if ba.app.small_ui else 0 height = 460 if ba.app.small_ui else 530 if ba.app.med_ui else 600 super().__init__(root_widget=ba.containerwidget( size=(width, height), transition=transition, toolbar_visibility='menu_minimal', scale_origin_stack_offset=scale_origin, scale=( 1.77 if ba.app.small_ui else 1.25 if ba.app.med_ui else 1.0), stack_offset=(0, -30) if ba.app.small_ui else ( 0, 15) if ba.app.med_ui else (0, 0))) ba.textwidget(parent=self._root_widget, position=(0, height - (50 if ba.app.small_ui else 45)), size=(width, 25), text=ba.Lstr(resource=self._r + '.titleText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))]), color=ba.app.title_color, h_align='center', v_align='top') self._scrollwidget = ba.scrollwidget( parent=self._root_widget, position=(44 + x_offs, 55 if ba.app.small_ui else 55), simple_culling_v=100.0, size=(width - (88 + 2 * x_offs), height - 120 + (5 if ba.app.small_ui else 0)), capture_arrows=True) if ba.app.toolbars: ba.widget(edit=self._scrollwidget, right_widget=_ba.get_special_widget('party_button')) ba.containerwidget(edit=self._root_widget, selected_child=self._scrollwidget) # ugly: create this last so it gets first dibs at touch events (since # we have it close to the scroll widget) if ba.app.small_ui and ba.app.toolbars: ba.containerwidget(edit=self._root_widget, on_cancel_call=self._close) ba.widget(edit=self._scrollwidget, left_widget=_ba.get_special_widget('back_button')) else: btn = ba.buttonwidget( parent=self._root_widget, position=(x_offs + (40 + 0 if ba.app.small_ui else 70), height - (59 if ba.app.small_ui else 50)), size=(140, 60), scale=0.7 if ba.app.small_ui else 0.8, label=ba.Lstr( resource='backText') if self._main_menu else 'Close', button_type='back' if self._main_menu else None, extra_touch_border_scale=2.0, autoselect=True, on_activate_call=self._close) ba.containerwidget(edit=self._root_widget, cancel_button=btn) if self._main_menu: ba.buttonwidget(edit=btn, button_type='backSmall', size=(60, 55), label=ba.charstr(ba.SpecialChar.BACK)) # interface_type = ba.app.interface_type self._sub_width = 660 self._sub_height = 1590 + get_resource( self._r + '.someDaysExtraSpace') + get_resource( self._r + '.orPunchingSomethingExtraSpace') self._subcontainer = ba.containerwidget(parent=self._scrollwidget, size=(self._sub_width, self._sub_height), background=False, claims_left_right=False, claims_tab=False) spacing = 1.0 h = self._sub_width * 0.5 v = self._sub_height - 55 logo_tex = ba.gettexture('logo') icon_buffer = 1.1 header = (0.7, 1.0, 0.7, 1.0) header2 = (0.8, 0.8, 1.0, 1.0) paragraph = (0.8, 0.8, 1.0, 1.0) txt = ba.Lstr(resource=self._r + '.welcomeText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText')) ]).evaluate() txt_scale = 1.4 txt_maxwidth = 480 ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), scale=txt_scale, flatness=0.5, res_scale=1.5, text=txt, h_align='center', color=header, v_align='center', maxwidth=txt_maxwidth) txt_width = min( txt_maxwidth, _ba.get_string_width(txt, suppress_warning=True) * txt_scale) icon_size = 70 hval2 = h - (txt_width * 0.5 + icon_size * 0.5 * icon_buffer) ba.imagewidget(parent=self._subcontainer, size=(icon_size, icon_size), position=(hval2 - 0.5 * icon_size, v - 0.45 * icon_size), texture=logo_tex) force_test = False app = ba.app if (app.platform == 'android' and app.subplatform == 'alibaba') or force_test: v -= 120.0 txtv = ( '\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa\xe5\x8f\xaf' '\xe4\xbb\xa5\xe5\x92\x8c\xe5\xae\xb6\xe4\xba\xba\xe6\x9c\x8b' '\xe5\x8f\x8b\xe4\xb8\x80\xe8\xb5\xb7\xe7\x8e\xa9\xe7\x9a\x84' '\xe6\xb8\xb8\xe6\x88\x8f,\xe5\x90\x8c\xe6\x97\xb6\xe6\x94\xaf' '\xe6\x8c\x81\xe8\x81\x94 \xe2\x80\xa8\xe7\xbd\x91\xe5\xaf\xb9' '\xe6\x88\x98\xe3\x80\x82\n' '\xe5\xa6\x82\xe6\xb2\xa1\xe6\x9c\x89\xe6\xb8\xb8\xe6\x88\x8f' '\xe6\x89\x8b\xe6\x9f\x84,\xe5\x8f\xaf\xe4\xbb\xa5\xe4\xbd\xbf' '\xe7\x94\xa8\xe7\xa7\xbb\xe5\x8a\xa8\xe8\xae\xbe\xe5\xa4\x87' '\xe6\x89\xab\xe7\xa0\x81\xe4\xb8\x8b\xe8\xbd\xbd\xe2\x80\x9c' '\xe9\x98\xbf\xe9\x87\x8c\xc2' '\xa0TV\xc2\xa0\xe5\x8a\xa9\xe6\x89' '\x8b\xe2\x80\x9d\xe7\x94\xa8 \xe6\x9d\xa5\xe4\xbb\xa3\xe6\x9b' '\xbf\xe5\xa4\x96\xe8\xae\xbe\xe3\x80\x82\n' '\xe6\x9c\x80\xe5\xa4\x9a\xe6\x94\xaf\xe6\x8c\x81\xe6\x8e\xa5' '\xe5\x85\xa5\xc2\xa08\xc2\xa0\xe4\xb8\xaa\xe5\xa4\x96\xe8' '\xae\xbe') ba.textwidget(parent=self._subcontainer, size=(0, 0), h_align='center', v_align='center', maxwidth=self._sub_width * 0.9, position=(self._sub_width * 0.5, v - 180), text=txtv) ba.imagewidget(parent=self._subcontainer, position=(self._sub_width - 320, v - 120), size=(200, 200), texture=ba.gettexture('aliControllerQR')) ba.imagewidget(parent=self._subcontainer, position=(90, v - 130), size=(210, 210), texture=ba.gettexture('multiplayerExamples')) v -= 120.0 else: v -= spacing * 50.0 txt = ba.Lstr(resource=self._r + '.someDaysText').evaluate() ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), scale=1.2, maxwidth=self._sub_width * 0.9, text=txt, h_align='center', color=paragraph, v_align='center', flatness=1.0) v -= (spacing * 25.0 + get_resource(self._r + '.someDaysExtraSpace')) txt_scale = 0.66 txt = ba.Lstr(resource=self._r + '.orPunchingSomethingText').evaluate() ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), scale=txt_scale, maxwidth=self._sub_width * 0.9, text=txt, h_align='center', color=paragraph, v_align='center', flatness=1.0) v -= (spacing * 27.0 + get_resource(self._r + '.orPunchingSomethingExtraSpace')) txt_scale = 1.0 txt = ba.Lstr(resource=self._r + '.canHelpText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText')) ]).evaluate() ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), scale=txt_scale, flatness=1.0, text=txt, h_align='center', color=paragraph, v_align='center') v -= spacing * 70.0 txt_scale = 1.0 txt = ba.Lstr(resource=self._r + '.toGetTheMostText').evaluate() ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), scale=txt_scale, maxwidth=self._sub_width * 0.9, text=txt, h_align='center', color=header, v_align='center', flatness=1.0) v -= spacing * 40.0 txt_scale = 0.74 txt = ba.Lstr(resource=self._r + '.friendsText').evaluate() hval2 = h - 220 ba.textwidget(parent=self._subcontainer, position=(hval2, v), size=(0, 0), scale=txt_scale, maxwidth=100, text=txt, h_align='right', color=header, v_align='center', flatness=1.0) txt = ba.Lstr(resource=self._r + '.friendsGoodText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText')) ]).evaluate() txt_scale = 0.7 ba.textwidget(parent=self._subcontainer, position=(hval2 + 10, v + 8), size=(0, 0), scale=txt_scale, maxwidth=500, text=txt, h_align='left', color=paragraph, flatness=1.0) app = ba.app v -= spacing * 45.0 txt = (ba.Lstr(resource=self._r + '.devicesText').evaluate() if app.vr_mode else ba.Lstr(resource=self._r + '.controllersText').evaluate()) txt_scale = 0.74 hval2 = h - 220 ba.textwidget(parent=self._subcontainer, position=(hval2, v), size=(0, 0), scale=txt_scale, maxwidth=100, text=txt, h_align='right', color=header, v_align='center', flatness=1.0) txt_scale = 0.7 if not app.vr_mode: txt = ba.Lstr(resource=self._r + '.controllersInfoText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText')), ('${REMOTE_APP_NAME}', get_remote_app_name())]).evaluate() else: txt = ba.Lstr(resource=self._r + '.devicesInfoText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText')) ]).evaluate() ba.textwidget(parent=self._subcontainer, position=(hval2 + 10, v + 8), size=(0, 0), scale=txt_scale, maxwidth=500, max_height=105, text=txt, h_align='left', color=paragraph, flatness=1.0) v -= spacing * 150.0 txt = ba.Lstr(resource=self._r + '.controlsText').evaluate() txt_scale = 1.4 txt_maxwidth = 480 ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), scale=txt_scale, flatness=0.5, text=txt, h_align='center', color=header, v_align='center', res_scale=1.5, maxwidth=txt_maxwidth) txt_width = min( txt_maxwidth, _ba.get_string_width(txt, suppress_warning=True) * txt_scale) icon_size = 70 hval2 = h - (txt_width * 0.5 + icon_size * 0.5 * icon_buffer) ba.imagewidget(parent=self._subcontainer, size=(icon_size, icon_size), position=(hval2 - 0.5 * icon_size, v - 0.45 * icon_size), texture=logo_tex) v -= spacing * 45.0 txt_scale = 0.7 txt = ba.Lstr(resource=self._r + '.controlsSubtitleText', subs=[('${APP_NAME}', ba.Lstr(resource='titleText')) ]).evaluate() ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), scale=txt_scale, maxwidth=self._sub_width * 0.9, flatness=1.0, text=txt, h_align='center', color=paragraph, v_align='center') v -= spacing * 160.0 sep = 70 icon_size = 100 # icon_size_2 = 30 hval2 = h - sep vval2 = v ba.imagewidget(parent=self._subcontainer, size=(icon_size, icon_size), position=(hval2 - 0.5 * icon_size, vval2 - 0.5 * icon_size), texture=ba.gettexture('buttonPunch'), color=(1, 0.7, 0.3)) txt_scale = get_resource(self._r + '.punchInfoTextScale') txt = ba.Lstr(resource=self._r + '.punchInfoText').evaluate() ba.textwidget(parent=self._subcontainer, position=(h - sep - 185 + 70, v + 120), size=(0, 0), scale=txt_scale, flatness=1.0, text=txt, h_align='center', color=(1, 0.7, 0.3, 1.0), v_align='top') hval2 = h + sep vval2 = v ba.imagewidget(parent=self._subcontainer, size=(icon_size, icon_size), position=(hval2 - 0.5 * icon_size, vval2 - 0.5 * icon_size), texture=ba.gettexture('buttonBomb'), color=(1, 0.3, 0.3)) txt = ba.Lstr(resource=self._r + '.bombInfoText').evaluate() txt_scale = get_resource(self._r + '.bombInfoTextScale') ba.textwidget(parent=self._subcontainer, position=(h + sep + 50 + 60, v - 35), size=(0, 0), scale=txt_scale, flatness=1.0, maxwidth=270, text=txt, h_align='center', color=(1, 0.3, 0.3, 1.0), v_align='top') hval2 = h vval2 = v + sep ba.imagewidget(parent=self._subcontainer, size=(icon_size, icon_size), position=(hval2 - 0.5 * icon_size, vval2 - 0.5 * icon_size), texture=ba.gettexture('buttonPickUp'), color=(0.5, 0.5, 1)) txtl = ba.Lstr(resource=self._r + '.pickUpInfoText') txt_scale = get_resource(self._r + '.pickUpInfoTextScale') ba.textwidget(parent=self._subcontainer, position=(h + 60 + 120, v + sep + 50), size=(0, 0), scale=txt_scale, flatness=1.0, text=txtl, h_align='center', color=(0.5, 0.5, 1, 1.0), v_align='top') hval2 = h vval2 = v - sep ba.imagewidget(parent=self._subcontainer, size=(icon_size, icon_size), position=(hval2 - 0.5 * icon_size, vval2 - 0.5 * icon_size), texture=ba.gettexture('buttonJump'), color=(0.4, 1, 0.4)) txt = ba.Lstr(resource=self._r + '.jumpInfoText').evaluate() txt_scale = get_resource(self._r + '.jumpInfoTextScale') ba.textwidget(parent=self._subcontainer, position=(h - 250 + 75, v - sep - 15 + 30), size=(0, 0), scale=txt_scale, flatness=1.0, text=txt, h_align='center', color=(0.4, 1, 0.4, 1.0), v_align='top') txt = ba.Lstr(resource=self._r + '.runInfoText').evaluate() txt_scale = get_resource(self._r + '.runInfoTextScale') ba.textwidget(parent=self._subcontainer, position=(h, v - sep - 100), size=(0, 0), scale=txt_scale, maxwidth=self._sub_width * 0.93, flatness=1.0, text=txt, h_align='center', color=(0.7, 0.7, 1.0, 1.0), v_align='center') v -= spacing * 280.0 txt = ba.Lstr(resource=self._r + '.powerupsText').evaluate() txt_scale = 1.4 txt_maxwidth = 480 ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), scale=txt_scale, flatness=0.5, text=txt, h_align='center', color=header, v_align='center', maxwidth=txt_maxwidth) txt_width = min( txt_maxwidth, _ba.get_string_width(txt, suppress_warning=True) * txt_scale) icon_size = 70 hval2 = h - (txt_width * 0.5 + icon_size * 0.5 * icon_buffer) ba.imagewidget(parent=self._subcontainer, size=(icon_size, icon_size), position=(hval2 - 0.5 * icon_size, v - 0.45 * icon_size), texture=logo_tex) v -= spacing * 50.0 txt_scale = get_resource(self._r + '.powerupsSubtitleTextScale') txt = ba.Lstr(resource=self._r + '.powerupsSubtitleText').evaluate() ba.textwidget(parent=self._subcontainer, position=(h, v), size=(0, 0), scale=txt_scale, maxwidth=self._sub_width * 0.9, text=txt, h_align='center', color=paragraph, v_align='center', flatness=1.0) v -= spacing * 1.0 mm1 = -270 mm2 = -215 mm3 = 0 icon_size = 50 shadow_size = 80 shadow_offs_x = 3 shadow_offs_y = -4 t_big = 1.1 t_small = 0.65 shadow_tex = ba.gettexture('shadowSharp') for tex in [ 'powerupPunch', 'powerupShield', 'powerupBomb', 'powerupHealth', 'powerupIceBombs', 'powerupImpactBombs', 'powerupStickyBombs', 'powerupLandMines', 'powerupCurse' ]: name = ba.Lstr(resource=self._r + '.' + tex + 'NameText') desc = ba.Lstr(resource=self._r + '.' + tex + 'DescriptionText') v -= spacing * 60.0 ba.imagewidget( parent=self._subcontainer, size=(shadow_size, shadow_size), position=(h + mm1 + shadow_offs_x - 0.5 * shadow_size, v + shadow_offs_y - 0.5 * shadow_size), texture=shadow_tex, color=(0, 0, 0), opacity=0.5) ba.imagewidget(parent=self._subcontainer, size=(icon_size, icon_size), position=(h + mm1 - 0.5 * icon_size, v - 0.5 * icon_size), texture=ba.gettexture(tex)) txt_scale = t_big txtl = name ba.textwidget(parent=self._subcontainer, position=(h + mm2, v + 3), size=(0, 0), scale=txt_scale, maxwidth=200, flatness=1.0, text=txtl, h_align='left', color=header2, v_align='center') txt_scale = t_small txtl = desc ba.textwidget(parent=self._subcontainer, position=(h + mm3, v), size=(0, 0), scale=txt_scale, maxwidth=300, flatness=1.0, text=txtl, h_align='left', color=paragraph, v_align='center', res_scale=0.5)
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 _update_for_league_rank_data(self, data: Optional[Dict[str, Any]]) -> None: # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals from ba.internal import get_league_rank_points if not self._root_widget: return in_top = (data is not None and data['rank'] is not None) eq_text = self._rdict.powerRankingPointsEqualsText pts_txt = self._rdict.powerRankingPointsText num_text = ba.Lstr(resource='numberText').evaluate() do_percent = False finished_season_unranked = False self._can_do_more_button = True extra_text = '' if _ba.get_account_state() != 'signed_in': status_text = '(' + ba.Lstr( resource='notSignedInText').evaluate() + ')' elif in_top: assert data is not None status_text = num_text.replace('${NUMBER}', str(data['rank'])) elif data is not None: try: # handle old seasons where we didn't wind up ranked # at the end.. if not data['scores']: status_text = ( self._rdict.powerRankingFinishedSeasonUnrankedText) extra_text = '' finished_season_unranked = True self._can_do_more_button = False else: our_points = get_league_rank_points(data) progress = float(our_points) / max(1, data['scores'][-1][1]) status_text = str(int(progress * 100.0)) + '%' extra_text = ( '\n' + self._rdict.powerRankingPointsToRankedText.replace( '${CURRENT}', str(our_points)).replace( '${REMAINING}', str(data['scores'][-1][1]))) do_percent = True except Exception: ba.print_exception('error updating power ranking') status_text = self._rdict.powerRankingNotInTopText.replace( '${NUMBER}', str(data['listSize'])) extra_text = '' else: status_text = '-' self._season = data['s'] if data is not None else None v = self._subcontainerheight - 20 popup_was_selected = False if self._season_popup_menu is not None: btn = self._season_popup_menu.get_button() assert self._subcontainer if self._subcontainer.get_selected_child() == btn: popup_was_selected = True btn.delete() season_choices = [] season_choices_display = [] did_first = False self._is_current_season = False if data is not None: # build our list of seasons we have available for ssn in data['sl']: season_choices.append(ssn) if ssn != 'a' and not did_first: season_choices_display.append( ba.Lstr(resource='league.currentSeasonText', subs=[('${NUMBER}', ssn)])) did_first = True # if we either did not specify a season or specified the # first, we're looking at the current.. if self._season in [ssn, None]: self._is_current_season = True elif ssn == 'a': season_choices_display.append( ba.Lstr(resource='league.allTimeText')) else: season_choices_display.append( ba.Lstr(resource='league.seasonText', subs=[('${NUMBER}', ssn)])) assert self._subcontainer self._season_popup_menu = popup_ui.PopupMenu( parent=self._subcontainer, position=(390, v - 45), width=150, button_size=(200, 50), choices=season_choices, on_value_change_call=ba.WeakCall(self._on_season_change), choices_display=season_choices_display, current_choice=self._season) if popup_was_selected: ba.containerwidget( edit=self._subcontainer, selected_child=self._season_popup_menu.get_button()) ba.widget(edit=self._see_more_button, show_buffer_bottom=100) ba.widget(edit=self._season_popup_menu.get_button(), up_widget=self._back_button) ba.widget(edit=self._back_button, down_widget=self._power_ranking_achievements_button, right_widget=self._season_popup_menu.get_button()) ba.textwidget(edit=self._league_title_text, text='' if self._season == 'a' else ba.Lstr( resource='league.leagueText')) if data is None: lname = '' lnum = '' lcolor = (1, 1, 1) self._league_url_arg = '' elif self._season == 'a': lname = ba.Lstr(resource='league.allTimeText').evaluate() lnum = '' lcolor = (1, 1, 1) self._league_url_arg = '' else: lnum = ('[' + str(data['l']['i']) + ']') if data['l']['i2'] else '' lname = ba.Lstr(translate=('leagueNames', data['l']['n'])).evaluate() lcolor = data['l']['c'] self._league_url_arg = (data['l']['n'] + '_' + str(data['l']['i'])).lower() to_end_string: Union[ba.Lstr, str] if data is None or self._season == 'a' or data['se'] is None: to_end_string = '' show_season_end = False else: show_season_end = True days_to_end = data['se'][0] minutes_to_end = data['se'][1] if days_to_end > 0: to_end_string = ba.Lstr(resource='league.seasonEndsDaysText', subs=[('${NUMBER}', str(days_to_end))]) elif days_to_end == 0 and minutes_to_end >= 60: to_end_string = ba.Lstr(resource='league.seasonEndsHoursText', subs=[('${NUMBER}', str(minutes_to_end // 60))]) elif days_to_end == 0 and minutes_to_end >= 0: to_end_string = ba.Lstr( resource='league.seasonEndsMinutesText', subs=[('${NUMBER}', str(minutes_to_end))]) else: to_end_string = ba.Lstr( resource='league.seasonEndedDaysAgoText', subs=[('${NUMBER}', str(-(days_to_end + 1)))]) ba.textwidget(edit=self._season_ends_text, text=to_end_string) ba.textwidget(edit=self._trophy_counts_reset_text, text=ba.Lstr(resource='league.trophyCountsResetText') if self._is_current_season and show_season_end else '') ba.textwidget(edit=self._league_text, text=lname, color=lcolor) l_text_width = min( self._league_text_maxwidth, _ba.get_string_width(lname, suppress_warning=True) * self._league_text_scale) ba.textwidget( edit=self._league_number_text, text=lnum, color=lcolor, position=(self._league_number_base_pos[0] + l_text_width * 0.5 + 8, self._league_number_base_pos[1] + 10)) ba.textwidget( edit=self._to_ranked_text, text=ba.Lstr(resource='coopSelectWindow.toRankedText').evaluate() + '' + extra_text if do_percent else '') ba.textwidget( edit=self._your_power_ranking_text, text=ba.Lstr( resource='rankText', fallback_resource='coopSelectWindow.yourPowerRankingText') if (not do_percent) else '') ba.textwidget(edit=self._power_ranking_rank_text, position=(473, v - 70 - (170 if do_percent else 220)), text=status_text, big=(in_top or do_percent), scale=3.0 if (in_top or do_percent) else 0.7 if finished_season_unranked else 1.0) if self._activity_mult_button is not None: if data is None or data['act'] is None: ba.buttonwidget(edit=self._activity_mult_button, textcolor=(0.7, 0.7, 0.8, 0.5), icon_color=(0.5, 0, 0.5, 0.3)) ba.textwidget(edit=self._activity_mult_text, text=' -') else: ba.buttonwidget(edit=self._activity_mult_button, textcolor=(0.7, 0.7, 0.8, 1.0), icon_color=(0.5, 0, 0.5, 1.0)) ba.textwidget(edit=self._activity_mult_text, text='x ' + ('%.2f' % data['act'])) have_pro = False if data is None else data['p'] pro_mult = 1.0 + float( _ba.get_account_misc_read_val('proPowerRankingBoost', 0.0)) * 0.01 ba.textwidget(edit=self._pro_mult_text, text=' -' if (data is None or not have_pro) else 'x ' + ('%.2f' % pro_mult)) ba.buttonwidget(edit=self._pro_mult_button, textcolor=(0.7, 0.7, 0.8, (1.0 if have_pro else 0.5)), icon_color=(0.5, 0, 0.5) if have_pro else (0.5, 0, 0.5, 0.2)) ba.buttonwidget(edit=self._power_ranking_achievements_button, label=('' if data is None else (str(data['a']) + ' ')) + ba.Lstr(resource='achievementsText').evaluate()) # for the achievement value, use the number they gave us for # non-current seasons; otherwise calc our own total_ach_value = 0 for ach in ba.app.achievements: if ach.complete: total_ach_value += ach.power_ranking_value if self._season != 'a' and not self._is_current_season: if data is not None and 'at' in data: total_ach_value = data['at'] ba.textwidget(edit=self._power_ranking_achievement_total_text, text='-' if data is None else ('+ ' + pts_txt.replace('${NUMBER}', str(total_ach_value)))) total_trophies_count = (get_league_rank_points(data, 'trophyCount')) total_trophies_value = (get_league_rank_points(data, 'trophies')) ba.buttonwidget(edit=self._power_ranking_trophies_button, label=('' if data is None else (str(total_trophies_count) + ' ')) + ba.Lstr(resource='trophiesText').evaluate()) ba.textwidget( edit=self._power_ranking_trophies_total_text, text='-' if data is None else ('+ ' + pts_txt.replace('${NUMBER}', str(total_trophies_value)))) ba.textwidget(edit=self._power_ranking_total_text, text='-' if data is None else eq_text.replace( '${NUMBER}', str(get_league_rank_points(data)))) for widget in self._power_ranking_score_widgets: widget.delete() self._power_ranking_score_widgets = [] scores = data['scores'] if data is not None else [] tally_color = (0.5, 0.6, 0.8) w_parent = self._subcontainer v2 = self._power_ranking_score_v for score in scores: h2 = 680 is_us = score[3] self._power_ranking_score_widgets.append( ba.textwidget(parent=w_parent, position=(h2 - 20, v2), size=(0, 0), color=(1, 1, 1) if is_us else (0.6, 0.6, 0.7), maxwidth=40, flatness=1.0, shadow=0.0, text=num_text.replace('${NUMBER}', str(score[0])), h_align='right', v_align='center', scale=0.5)) self._power_ranking_score_widgets.append( ba.textwidget(parent=w_parent, position=(h2 + 20, v2), size=(0, 0), color=(1, 1, 1) if is_us else tally_color, maxwidth=60, text=str(score[1]), flatness=1.0, shadow=0.0, h_align='center', v_align='center', scale=0.7)) txt = ba.textwidget(parent=w_parent, position=(h2 + 60, v2 - (28 * 0.5) / 0.9), size=(210 / 0.9, 28), color=(1, 1, 1) if is_us else (0.6, 0.6, 0.6), maxwidth=210, flatness=1.0, shadow=0.0, autoselect=True, selectable=True, click_activate=True, text=score[2], h_align='left', v_align='center', scale=0.9) self._power_ranking_score_widgets.append(txt) ba.textwidget(edit=txt, on_activate_call=ba.Call(self._show_account_info, score[4], txt)) assert self._season_popup_menu is not None ba.widget(edit=txt, left_widget=self._season_popup_menu.get_button()) v2 -= 28
def _refresh(self, file_names: List[str], error: Optional[str]) -> None: # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals if not self._root_widget: return scrollwidget_selected = (self._scrollwidget is None or self._root_widget.get_selected_child() == self._scrollwidget) in_top_folder = (self._path == self._base_path) hide_top_folder = in_top_folder and self._show_base_path is False if hide_top_folder: folder_name = '' elif self._path == '/': folder_name = '/' else: assert self._path is not None folder_name = os.path.basename(self._path) b_color = (0.6, 0.53, 0.63) b_color_disabled = (0.65, 0.65, 0.65) if len(self._recent_paths) < 2: ba.buttonwidget(edit=self._back_button, color=b_color_disabled, textcolor=(0.5, 0.5, 0.5)) else: ba.buttonwidget(edit=self._back_button, color=b_color, textcolor=(0.75, 0.7, 0.8)) max_str_width = 300.0 str_width = min( max_str_width, _ba.get_string_width(folder_name, suppress_warning=True)) ba.textwidget(edit=self._path_text, text=folder_name, maxwidth=max_str_width) ba.imagewidget(edit=self._folder_icon, position=(self._folder_center - str_width * 0.5 - 40, self._height - 117), opacity=0.0 if hide_top_folder else 1.0) if self._scrollwidget is not None: self._scrollwidget.delete() if self._use_folder_button is not None: self._use_folder_button.delete() ba.widget(edit=self._cancel_button, right_widget=self._back_button) self._scrollwidget = ba.scrollwidget( parent=self._root_widget, position=((self._width - self._scroll_width) * 0.5, self._height - self._scroll_height - 119), size=(self._scroll_width, self._scroll_height)) if scrollwidget_selected: ba.containerwidget(edit=self._root_widget, selected_child=self._scrollwidget) # show error case.. if error is not None: self._subcontainer = ba.containerwidget(parent=self._scrollwidget, size=(self._scroll_width, self._scroll_height), background=False) ba.textwidget(parent=self._subcontainer, color=(1, 1, 0, 1), text=error, maxwidth=self._scroll_width * 0.9, position=(self._scroll_width * 0.48, self._scroll_height * 0.57), size=(0, 0), h_align='center', v_align='center') else: file_names = [f for f in file_names if not f.startswith('.')] file_names.sort(key=lambda x: x[0].lower()) entries = file_names entry_height = 35 folder_entry_height = 100 show_folder_entry = False show_use_folder_button = (self._allow_folders and not in_top_folder) self._subcontainerheight = entry_height * len(entries) + ( folder_entry_height if show_folder_entry else 0) v = self._subcontainerheight - (folder_entry_height if show_folder_entry else 0) self._subcontainer = ba.containerwidget( parent=self._scrollwidget, size=(self._scroll_width, self._subcontainerheight), background=False) ba.containerwidget(edit=self._scrollwidget, claims_left_right=False, claims_tab=False) ba.containerwidget(edit=self._subcontainer, claims_left_right=False, claims_tab=False, selection_loops=False, print_list_exit_instructions=False) ba.widget(edit=self._subcontainer, up_widget=self._back_button) if show_use_folder_button: self._use_folder_button = btn = ba.buttonwidget( parent=self._root_widget, position=(self._width - self._button_width - 35 - self._x_inset, self._height - 67), size=(self._button_width, 50), label=ba.Lstr(resource=self._r + '.useThisFolderButtonText'), on_activate_call=self._on_folder_entry_activated) ba.widget(edit=btn, left_widget=self._cancel_button, down_widget=self._scrollwidget) ba.widget(edit=self._cancel_button, right_widget=btn) ba.containerwidget(edit=self._root_widget, start_button=btn) folder_icon_size = 35 for num, entry in enumerate(entries): cnt = ba.containerwidget( parent=self._subcontainer, position=(0, v - entry_height), size=(self._scroll_width, entry_height), root_selectable=True, background=False, click_activate=True, on_activate_call=ba.Call(self._on_entry_activated, entry)) if num == 0: ba.widget(edit=cnt, up_widget=self._back_button) is_valid_file_path = self._is_valid_file_path(entry) assert self._path is not None is_dir = os.path.isdir(self._path + '/' + entry) if is_dir: ba.imagewidget(parent=cnt, size=(folder_icon_size, folder_icon_size), position=(10, 0.5 * entry_height - folder_icon_size * 0.5), draw_controller=cnt, texture=self._folder_tex, color=self._folder_color) else: ba.imagewidget(parent=cnt, size=(folder_icon_size, folder_icon_size), position=(10, 0.5 * entry_height - folder_icon_size * 0.5), opacity=1.0 if is_valid_file_path else 0.5, draw_controller=cnt, texture=self._file_tex, color=self._file_color) ba.textwidget(parent=cnt, draw_controller=cnt, text=entry, h_align='left', v_align='center', position=(10 + folder_icon_size * 1.05, entry_height * 0.5), size=(0, 0), maxwidth=self._scroll_width * 0.93 - 50, color=(1, 1, 1, 1) if (is_valid_file_path or is_dir) else (0.5, 0.5, 0.5, 1)) v -= entry_height
def __init__(self, position: Tuple[float, float], choices: Sequence[str], current_choice: str, delegate: Any = None, width: float = 230.0, maxwidth: float = None, scale: float = 1.0, choices_disabled: Sequence[str] = None, choices_display: Sequence[ba.Lstr] = None): # FIXME: Clean up a bit. # pylint: disable=too-many-branches # pylint: disable=too-many-locals # pylint: disable=too-many-statements if choices_disabled is None: choices_disabled = [] if choices_display is None: choices_display = [] # FIXME: For the moment we base our width on these strings so # we need to flatten them. choices_display_fin: List[str] = [] for choice_display in choices_display: choices_display_fin.append(choice_display.evaluate()) if maxwidth is None: maxwidth = width * 1.5 self._transitioning_out = False self._choices = list(choices) self._choices_display = list(choices_display_fin) self._current_choice = current_choice self._choices_disabled = list(choices_disabled) self._done_building = False if not choices: raise Exception('Must pass at least one choice') self._width = width self._scale = scale if len(choices) > 8: self._height = 280 self._use_scroll = True else: self._height = 20 + len(choices) * 33 self._use_scroll = False self._delegate = None # don't want this stuff called just yet.. # extend width to fit our longest string (or our max-width) for index, choice in enumerate(choices): if len(choices_display_fin) == len(choices): choice_display_name = choices_display_fin[index] else: choice_display_name = choice if self._use_scroll: self._width = max( self._width, min( maxwidth, _ba.get_string_width(choice_display_name, suppress_warning=True)) + 75) else: self._width = max( self._width, min( maxwidth, _ba.get_string_width(choice_display_name, suppress_warning=True)) + 60) # init parent class - this will rescale and reposition things as # needed and create our root widget PopupWindow.__init__(self, position, size=(self._width, self._height), scale=self._scale) if self._use_scroll: self._scrollwidget = ba.scrollwidget(parent=self.root_widget, position=(20, 20), highlight=False, color=(0.35, 0.55, 0.15), size=(self._width - 40, self._height - 40)) self._columnwidget = ba.columnwidget(parent=self._scrollwidget) else: self._offset_widget = ba.containerwidget(parent=self.root_widget, position=(30, 15), size=(self._width - 40, self._height), background=False) self._columnwidget = ba.columnwidget(parent=self._offset_widget) for index, choice in enumerate(choices): if len(choices_display_fin) == len(choices): choice_display_name = choices_display_fin[index] else: choice_display_name = choice inactive = (choice in self._choices_disabled) wdg = ba.textwidget(parent=self._columnwidget, size=(self._width - 40, 28), on_select_call=ba.Call(self._select, index), click_activate=True, color=(0.5, 0.5, 0.5, 0.5) if inactive else ((0.5, 1, 0.5, 1) if choice == self._current_choice else (0.8, 0.8, 0.8, 1.0)), padding=0, maxwidth=maxwidth, text=choice_display_name, on_activate_call=self._activate, v_align='center', selectable=(not inactive)) if choice == self._current_choice: ba.containerwidget(edit=self._columnwidget, selected_child=wdg, visible_child=wdg) # ok from now on our delegate can be called self._delegate = weakref.ref(delegate) self._done_building = True
def _update(self) -> None: # pylint: disable=too-many-locals # pylint: disable=too-many-branches # pylint: disable=too-many-statements # pylint: disable=too-many-nested-blocks # update muted state if ba.app.config.resolve('Chat Muted'): ba.textwidget(edit=self._muted_text, color=(1, 1, 1, 0.3)) # clear any chat texts we're showing if self._chat_texts: while self._chat_texts: first = self._chat_texts.pop() first.delete() else: ba.textwidget(edit=self._muted_text, color=(1, 1, 1, 0.0)) # update roster section roster = _ba.get_game_roster() if roster != self._roster: self._roster = roster # clear out old for widget in self._name_widgets: widget.delete() self._name_widgets = [] if not self._roster: top_section_height = 60 ba.textwidget(edit=self._empty_str, text=ba.Lstr(resource=self._r + '.emptyText')) ba.scrollwidget(edit=self._scrollwidget, size=(self._width - 50, self._height - top_section_height - 110), position=(30, 80)) else: columns = 1 if len( self._roster) == 1 else 2 if len(self._roster) == 2 else 3 rows = int(math.ceil(float(len(self._roster)) / columns)) c_width = (self._width * 0.9) / max(3, columns) c_width_total = c_width * columns c_height = 24 c_height_total = c_height * rows for y in range(rows): for x in range(columns): index = y * columns + x if index < len(self._roster): t_scale = 0.65 pos = (self._width * 0.53 - c_width_total * 0.5 + c_width * x - 23, self._height - 65 - c_height * y - 15) # if there are players present for this client, use # their names as a display string instead of the # client spec-string try: if self._roster[index]['players']: # if there's just one, use the full name; # otherwise combine short names if len(self._roster[index] ['players']) == 1: p_str = self._roster[index]['players'][ 0]['name_full'] else: p_str = ('/'.join([ entry['name'] for entry in self._roster[index]['players'] ])) if len(p_str) > 25: p_str = p_str[:25] + '...' else: p_str = self._roster[index][ 'display_string'] except Exception: ba.print_exception( 'Error calcing client name str.') p_str = '???' widget = ba.textwidget(parent=self._root_widget, position=(pos[0], pos[1]), scale=t_scale, size=(c_width * 0.85, 30), maxwidth=c_width * 0.85, color=(1, 1, 1) if index == 0 else (1, 1, 1), selectable=True, autoselect=True, click_activate=True, text=ba.Lstr(value=p_str), h_align='left', v_align='center') self._name_widgets.append(widget) # in newer versions client_id will be present and # we can use that to determine who the host is. # in older versions we assume the first client is # host if self._roster[index]['client_id'] is not None: is_host = self._roster[index][ 'client_id'] == -1 else: is_host = (index == 0) # FIXME: Should pass client_id to these sort of # calls; not spec-string (perhaps should wait till # client_id is more readily available though). ba.textwidget(edit=widget, on_activate_call=ba.Call( self._on_party_member_press, self._roster[index]['client_id'], is_host, widget)) pos = (self._width * 0.53 - c_width_total * 0.5 + c_width * x, self._height - 65 - c_height * y) # Make the assumption that the first roster # entry is the server. # FIXME: Shouldn't do this. if is_host: twd = min( c_width * 0.85, _ba.get_string_width( p_str, suppress_warning=True) * t_scale) self._name_widgets.append( ba.textwidget( parent=self._root_widget, position=(pos[0] + twd + 1, pos[1] - 0.5), size=(0, 0), h_align='left', v_align='center', maxwidth=c_width * 0.96 - twd, color=(0.1, 1, 0.1, 0.5), text=ba.Lstr(resource=self._r + '.hostText'), scale=0.4, shadow=0.1, flatness=1.0)) ba.textwidget(edit=self._empty_str, text='') ba.scrollwidget(edit=self._scrollwidget, size=(self._width - 50, max(100, self._height - 139 - c_height_total)), position=(30, 80))
def __init__(self, activity: ba.Activity, cost: int, continue_call: Callable[[], Any], cancel_call: Callable[[], Any]): self._activity = weakref.ref(activity) self._cost = cost self._continue_call = continue_call self._cancel_call = cancel_call self._start_count = self._count = 20 self._width = 300 self._height = 200 self._transitioning_out = False super().__init__( ba.containerwidget(size=(self._width, self._height), background=False, toolbar_visibility='menu_currency', transition='in_scale', scale=1.5)) txt = (ba.Lstr( resource='continuePurchaseText').evaluate().split('${PRICE}')) t_left = txt[0] t_left_width = _ba.get_string_width(t_left, suppress_warning=True) t_price = ba.charstr(ba.SpecialChar.TICKET) + str(self._cost) t_price_width = _ba.get_string_width(t_price, suppress_warning=True) t_right = txt[-1] t_right_width = _ba.get_string_width(t_right, suppress_warning=True) width_total_half = (t_left_width + t_price_width + t_right_width) * 0.5 ba.textwidget(parent=self._root_widget, text=t_left, flatness=1.0, shadow=1.0, size=(0, 0), h_align='left', v_align='center', position=(self._width * 0.5 - width_total_half, self._height - 30)) ba.textwidget(parent=self._root_widget, text=t_price, flatness=1.0, shadow=1.0, color=(0.2, 1.0, 0.2), size=(0, 0), position=(self._width * 0.5 - width_total_half + t_left_width, self._height - 30), h_align='left', v_align='center') ba.textwidget(parent=self._root_widget, text=t_right, flatness=1.0, shadow=1.0, size=(0, 0), h_align='left', v_align='center', position=(self._width * 0.5 - width_total_half + t_left_width + t_price_width + 5, self._height - 30)) self._tickets_text_base: Optional[str] self._tickets_text: Optional[ba.Widget] if not ba.app.toolbars: self._tickets_text_base = ba.Lstr( resource='getTicketsWindow.youHaveShortText', fallback_resource='getTicketsWindow.youHaveText').evaluate() self._tickets_text = ba.textwidget( parent=self._root_widget, text='', flatness=1.0, color=(0.2, 1.0, 0.2), shadow=1.0, position=(self._width * 0.5 + width_total_half, self._height - 50), size=(0, 0), scale=0.35, h_align='right', v_align='center') else: self._tickets_text_base = None self._tickets_text = None self._counter_text = ba.textwidget(parent=self._root_widget, text=str(self._count), color=(0.7, 0.7, 0.7), scale=1.2, size=(0, 0), big=True, position=(self._width * 0.5, self._height - 80), flatness=1.0, shadow=1.0, h_align='center', v_align='center') self._cancel_button = ba.buttonwidget( parent=self._root_widget, position=(30, 30), size=(120, 50), label=ba.Lstr(resource='endText', fallback_resource='cancelText'), autoselect=True, enable_sound=False, on_activate_call=self._on_cancel_press) self._continue_button = ba.buttonwidget( parent=self._root_widget, label=ba.Lstr(resource='continueText'), autoselect=True, position=(self._width - 130, 30), size=(120, 50), on_activate_call=self._on_continue_press) ba.containerwidget(edit=self._root_widget, cancel_button=self._cancel_button, start_button=self._continue_button, selected_child=self._cancel_button) self._counting_down = True self._countdown_timer = ba.Timer(1.0, ba.WeakCall(self._tick), repeat=True, timetype=ba.TimeType.REAL) self._tick()