bastd.ui.profile.edit
Provides UI to edit a player profile.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides UI to edit a player profile.""" 4 5from __future__ import annotations 6 7import random 8from typing import TYPE_CHECKING, cast 9 10import _ba 11import ba 12 13if TYPE_CHECKING: 14 from bastd.ui.colorpicker import ColorPicker 15 16 17class EditProfileWindow(ba.Window): 18 """Window for editing a player profile.""" 19 20 # FIXME: WILL NEED TO CHANGE THIS FOR UILOCATION. 21 def reload_window(self) -> None: 22 """Transitions out and recreates ourself.""" 23 ba.containerwidget(edit=self._root_widget, transition='out_left') 24 ba.app.ui.set_main_menu_window( 25 EditProfileWindow(self.getname(), 26 self._in_main_menu).get_root_widget()) 27 28 def __init__(self, 29 existing_profile: str | None, 30 in_main_menu: bool, 31 transition: str = 'in_right'): 32 # FIXME: Tidy this up a bit. 33 # pylint: disable=too-many-branches 34 # pylint: disable=too-many-statements 35 # pylint: disable=too-many-locals 36 from ba.internal import get_player_profile_colors 37 self._in_main_menu = in_main_menu 38 self._existing_profile = existing_profile 39 self._r = 'editProfileWindow' 40 self._spazzes: list[str] = [] 41 self._icon_textures: list[ba.Texture] = [] 42 self._icon_tint_textures: list[ba.Texture] = [] 43 44 # Grab profile colors or pick random ones. 45 self._color, self._highlight = get_player_profile_colors( 46 existing_profile) 47 uiscale = ba.app.ui.uiscale 48 self._width = width = 780.0 if uiscale is ba.UIScale.SMALL else 680.0 49 self._x_inset = x_inset = 50.0 if uiscale is ba.UIScale.SMALL else 0.0 50 self._height = height = ( 51 350.0 if uiscale is ba.UIScale.SMALL else 52 400.0 if uiscale is ba.UIScale.MEDIUM else 450.0) 53 spacing = 40 54 self._base_scale = (2.05 if uiscale is ba.UIScale.SMALL else 55 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0) 56 top_extra = 15 if uiscale is ba.UIScale.SMALL else 15 57 super().__init__(root_widget=ba.containerwidget( 58 size=(width, height + top_extra), 59 transition=transition, 60 scale=self._base_scale, 61 stack_offset=(0, 15) if uiscale is ba.UIScale.SMALL else (0, 0))) 62 cancel_button = btn = ba.buttonwidget( 63 parent=self._root_widget, 64 position=(52 + x_inset, height - 60), 65 size=(155, 60), 66 scale=0.8, 67 autoselect=True, 68 label=ba.Lstr(resource='cancelText'), 69 on_activate_call=self._cancel) 70 ba.containerwidget(edit=self._root_widget, cancel_button=btn) 71 save_button = btn = ba.buttonwidget(parent=self._root_widget, 72 position=(width - (177 + x_inset), 73 height - 60), 74 size=(155, 60), 75 autoselect=True, 76 scale=0.8, 77 label=ba.Lstr(resource='saveText')) 78 ba.widget(edit=save_button, left_widget=cancel_button) 79 ba.widget(edit=cancel_button, right_widget=save_button) 80 ba.containerwidget(edit=self._root_widget, start_button=btn) 81 ba.textwidget(parent=self._root_widget, 82 position=(self._width * 0.5, height - 38), 83 size=(0, 0), 84 text=(ba.Lstr(resource=self._r + '.titleNewText') 85 if existing_profile is None else ba.Lstr( 86 resource=self._r + '.titleEditText')), 87 color=ba.app.ui.title_color, 88 maxwidth=290, 89 scale=1.0, 90 h_align='center', 91 v_align='center') 92 93 # Make a list of spaz icons. 94 self.refresh_characters() 95 profile = ba.app.config.get('Player Profiles', 96 {}).get(self._existing_profile, {}) 97 98 if 'global' in profile: 99 self._global = profile['global'] 100 else: 101 self._global = False 102 103 if 'icon' in profile: 104 self._icon = profile['icon'] 105 else: 106 self._icon = ba.charstr(ba.SpecialChar.LOGO) 107 108 assigned_random_char = False 109 110 # Look for existing character choice or pick random one otherwise. 111 try: 112 icon_index = self._spazzes.index(profile['character']) 113 except Exception: 114 # Let's set the default icon to spaz for our first profile; after 115 # that we go random. 116 # (SCRATCH THAT.. we now hard-code account-profiles to start with 117 # spaz which has a similar effect) 118 # try: p_len = len(ba.app.config['Player Profiles']) 119 # except Exception: p_len = 0 120 # if p_len == 0: icon_index = self._spazzes.index('Spaz') 121 # else: 122 random.seed() 123 icon_index = random.randrange(len(self._spazzes)) 124 assigned_random_char = True 125 self._icon_index = icon_index 126 ba.buttonwidget(edit=save_button, on_activate_call=self.save) 127 128 v = height - 115.0 129 self._name = ('' if self._existing_profile is None else 130 self._existing_profile) 131 self._is_account_profile = (self._name == '__account__') 132 133 # If we just picked a random character, see if it has specific 134 # colors/highlights associated with it and assign them if so. 135 if assigned_random_char: 136 clr = ba.app.spaz_appearances[ 137 self._spazzes[icon_index]].default_color 138 if clr is not None: 139 self._color = clr 140 highlight = ba.app.spaz_appearances[ 141 self._spazzes[icon_index]].default_highlight 142 if highlight is not None: 143 self._highlight = highlight 144 145 # Assign a random name if they had none. 146 if self._name == '': 147 names = _ba.get_random_names() 148 self._name = names[random.randrange(len(names))] 149 150 self._clipped_name_text = ba.textwidget(parent=self._root_widget, 151 text='', 152 position=(540 + x_inset, 153 v - 8), 154 flatness=1.0, 155 shadow=0.0, 156 scale=0.55, 157 size=(0, 0), 158 maxwidth=100, 159 h_align='center', 160 v_align='center', 161 color=(1, 1, 0, 0.5)) 162 163 if not self._is_account_profile and not self._global: 164 ba.textwidget(parent=self._root_widget, 165 text=ba.Lstr(resource=self._r + '.nameText'), 166 position=(200 + x_inset, v - 6), 167 size=(0, 0), 168 h_align='right', 169 v_align='center', 170 color=(1, 1, 1, 0.5), 171 scale=0.9) 172 173 self._upgrade_button = None 174 if self._is_account_profile: 175 if _ba.get_v1_account_state() == 'signed_in': 176 sval = _ba.get_v1_account_display_string() 177 else: 178 sval = '??' 179 ba.textwidget(parent=self._root_widget, 180 position=(self._width * 0.5, v - 7), 181 size=(0, 0), 182 scale=1.2, 183 text=sval, 184 maxwidth=270, 185 h_align='center', 186 v_align='center') 187 txtl = ba.Lstr( 188 resource='editProfileWindow.accountProfileText').evaluate() 189 b_width = min( 190 270.0, 191 _ba.get_string_width(txtl, suppress_warning=True) * 0.6) 192 ba.textwidget(parent=self._root_widget, 193 position=(self._width * 0.5, v - 39), 194 size=(0, 0), 195 scale=0.6, 196 color=ba.app.ui.infotextcolor, 197 text=txtl, 198 maxwidth=270, 199 h_align='center', 200 v_align='center') 201 self._account_type_info_button = ba.buttonwidget( 202 parent=self._root_widget, 203 label='?', 204 size=(15, 15), 205 text_scale=0.6, 206 position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47), 207 button_type='square', 208 color=(0.6, 0.5, 0.65), 209 autoselect=True, 210 on_activate_call=self.show_account_profile_info) 211 elif self._global: 212 213 b_size = 60 214 self._icon_button = btn = ba.buttonwidget( 215 parent=self._root_widget, 216 autoselect=True, 217 position=(self._width * 0.5 - 160 - b_size * 0.5, v - 38 - 15), 218 size=(b_size, b_size), 219 color=(0.6, 0.5, 0.6), 220 label='', 221 button_type='square', 222 text_scale=1.2, 223 on_activate_call=self._on_icon_press) 224 self._icon_button_label = ba.textwidget( 225 parent=self._root_widget, 226 position=(self._width * 0.5 - 160, v - 35), 227 draw_controller=btn, 228 h_align='center', 229 v_align='center', 230 size=(0, 0), 231 color=(1, 1, 1), 232 text='', 233 scale=2.0) 234 235 ba.textwidget(parent=self._root_widget, 236 h_align='center', 237 v_align='center', 238 position=(self._width * 0.5 - 160, v - 55 - 15), 239 size=(0, 0), 240 draw_controller=btn, 241 text=ba.Lstr(resource=self._r + '.iconText'), 242 scale=0.7, 243 color=ba.app.ui.title_color, 244 maxwidth=120) 245 246 self._update_icon() 247 248 ba.textwidget(parent=self._root_widget, 249 position=(self._width * 0.5, v - 7), 250 size=(0, 0), 251 scale=1.2, 252 text=self._name, 253 maxwidth=240, 254 h_align='center', 255 v_align='center') 256 # FIXME hard coded strings are bad 257 txtl = ba.Lstr( 258 resource='editProfileWindow.globalProfileText').evaluate() 259 b_width = min( 260 240.0, 261 _ba.get_string_width(txtl, suppress_warning=True) * 0.6) 262 ba.textwidget(parent=self._root_widget, 263 position=(self._width * 0.5, v - 39), 264 size=(0, 0), 265 scale=0.6, 266 color=ba.app.ui.infotextcolor, 267 text=txtl, 268 maxwidth=240, 269 h_align='center', 270 v_align='center') 271 self._account_type_info_button = ba.buttonwidget( 272 parent=self._root_widget, 273 label='?', 274 size=(15, 15), 275 text_scale=0.6, 276 position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47), 277 button_type='square', 278 color=(0.6, 0.5, 0.65), 279 autoselect=True, 280 on_activate_call=self.show_global_profile_info) 281 else: 282 self._text_field = ba.textwidget( 283 parent=self._root_widget, 284 position=(220 + x_inset, v - 30), 285 size=(265, 40), 286 text=self._name, 287 h_align='left', 288 v_align='center', 289 max_chars=16, 290 description=ba.Lstr(resource=self._r + '.nameDescriptionText'), 291 autoselect=True, 292 editable=True, 293 padding=4, 294 color=(0.9, 0.9, 0.9, 1.0), 295 on_return_press_call=ba.Call(save_button.activate)) 296 297 # FIXME hard coded strings are bad 298 txtl = ba.Lstr( 299 resource='editProfileWindow.localProfileText').evaluate() 300 b_width = min( 301 270.0, 302 _ba.get_string_width(txtl, suppress_warning=True) * 0.6) 303 ba.textwidget(parent=self._root_widget, 304 position=(self._width * 0.5, v - 43), 305 size=(0, 0), 306 scale=0.6, 307 color=ba.app.ui.infotextcolor, 308 text=txtl, 309 maxwidth=270, 310 h_align='center', 311 v_align='center') 312 self._account_type_info_button = ba.buttonwidget( 313 parent=self._root_widget, 314 label='?', 315 size=(15, 15), 316 text_scale=0.6, 317 position=(self._width * 0.5 + b_width * 0.5 + 13, v - 50), 318 button_type='square', 319 color=(0.6, 0.5, 0.65), 320 autoselect=True, 321 on_activate_call=self.show_local_profile_info) 322 self._upgrade_button = ba.buttonwidget( 323 parent=self._root_widget, 324 label=ba.Lstr(resource='upgradeText'), 325 size=(40, 17), 326 text_scale=1.0, 327 button_type='square', 328 position=(self._width * 0.5 + b_width * 0.5 + 13 + 43, v - 51), 329 color=(0.6, 0.5, 0.65), 330 autoselect=True, 331 on_activate_call=self.upgrade_profile) 332 333 self._update_clipped_name() 334 self._clipped_name_timer = ba.Timer(0.333, 335 ba.WeakCall( 336 self._update_clipped_name), 337 timetype=ba.TimeType.REAL, 338 repeat=True) 339 340 v -= spacing * 3.0 341 b_size = 80 342 b_size_2 = 100 343 b_offs = 150 344 self._color_button = btn = ba.buttonwidget( 345 parent=self._root_widget, 346 autoselect=True, 347 position=(self._width * 0.5 - b_offs - b_size * 0.5, v - 50), 348 size=(b_size, b_size), 349 color=self._color, 350 label='', 351 button_type='square') 352 origin = self._color_button.get_screen_space_center() 353 ba.buttonwidget(edit=self._color_button, 354 on_activate_call=ba.WeakCall(self._make_picker, 355 'color', origin)) 356 ba.textwidget(parent=self._root_widget, 357 h_align='center', 358 v_align='center', 359 position=(self._width * 0.5 - b_offs, v - 65), 360 size=(0, 0), 361 draw_controller=btn, 362 text=ba.Lstr(resource=self._r + '.colorText'), 363 scale=0.7, 364 color=ba.app.ui.title_color, 365 maxwidth=120) 366 367 self._character_button = btn = ba.buttonwidget( 368 parent=self._root_widget, 369 autoselect=True, 370 position=(self._width * 0.5 - b_size_2 * 0.5, v - 60), 371 up_widget=self._account_type_info_button, 372 on_activate_call=self._on_character_press, 373 size=(b_size_2, b_size_2), 374 label='', 375 color=(1, 1, 1), 376 mask_texture=ba.gettexture('characterIconMask')) 377 if not self._is_account_profile and not self._global: 378 ba.containerwidget(edit=self._root_widget, 379 selected_child=self._text_field) 380 ba.textwidget(parent=self._root_widget, 381 h_align='center', 382 v_align='center', 383 position=(self._width * 0.5, v - 80), 384 size=(0, 0), 385 draw_controller=btn, 386 text=ba.Lstr(resource=self._r + '.characterText'), 387 scale=0.7, 388 color=ba.app.ui.title_color, 389 maxwidth=130) 390 391 self._highlight_button = btn = ba.buttonwidget( 392 parent=self._root_widget, 393 autoselect=True, 394 position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50), 395 up_widget=self._upgrade_button if self._upgrade_button is not None 396 else self._account_type_info_button, 397 size=(b_size, b_size), 398 color=self._highlight, 399 label='', 400 button_type='square') 401 402 if not self._is_account_profile and not self._global: 403 ba.widget(edit=cancel_button, down_widget=self._text_field) 404 ba.widget(edit=save_button, down_widget=self._text_field) 405 ba.widget(edit=self._color_button, up_widget=self._text_field) 406 ba.widget(edit=self._account_type_info_button, 407 down_widget=self._character_button) 408 409 origin = self._highlight_button.get_screen_space_center() 410 ba.buttonwidget(edit=self._highlight_button, 411 on_activate_call=ba.WeakCall(self._make_picker, 412 'highlight', origin)) 413 ba.textwidget(parent=self._root_widget, 414 h_align='center', 415 v_align='center', 416 position=(self._width * 0.5 + b_offs, v - 65), 417 size=(0, 0), 418 draw_controller=btn, 419 text=ba.Lstr(resource=self._r + '.highlightText'), 420 scale=0.7, 421 color=ba.app.ui.title_color, 422 maxwidth=120) 423 self._update_character() 424 425 def upgrade_profile(self) -> None: 426 """Attempt to ugrade the profile to global.""" 427 from bastd.ui import account 428 from bastd.ui.profile import upgrade as pupgrade 429 if _ba.get_v1_account_state() != 'signed_in': 430 account.show_sign_in_prompt() 431 return 432 433 pupgrade.ProfileUpgradeWindow(self) 434 435 def show_account_profile_info(self) -> None: 436 """Show an explanation of account profiles.""" 437 from bastd.ui.confirm import ConfirmWindow 438 icons_str = ' '.join([ 439 ba.charstr(n) for n in [ 440 ba.SpecialChar.GOOGLE_PLAY_GAMES_LOGO, 441 ba.SpecialChar.GAME_CENTER_LOGO, 442 ba.SpecialChar.GAME_CIRCLE_LOGO, ba.SpecialChar.OUYA_LOGO, 443 ba.SpecialChar.LOCAL_ACCOUNT, ba.SpecialChar.ALIBABA_LOGO, 444 ba.SpecialChar.OCULUS_LOGO, ba.SpecialChar.NVIDIA_LOGO 445 ] 446 ]) 447 txtl = ba.Lstr(resource='editProfileWindow.accountProfileInfoText', 448 subs=[('${ICONS}', icons_str)]) 449 ConfirmWindow(txtl, 450 cancel_button=False, 451 width=500, 452 height=300, 453 origin_widget=self._account_type_info_button) 454 455 def show_local_profile_info(self) -> None: 456 """Show an explanation of local profiles.""" 457 from bastd.ui.confirm import ConfirmWindow 458 txtl = ba.Lstr(resource='editProfileWindow.localProfileInfoText') 459 ConfirmWindow(txtl, 460 cancel_button=False, 461 width=600, 462 height=250, 463 origin_widget=self._account_type_info_button) 464 465 def show_global_profile_info(self) -> None: 466 """Show an explanation of global profiles.""" 467 from bastd.ui.confirm import ConfirmWindow 468 txtl = ba.Lstr(resource='editProfileWindow.globalProfileInfoText') 469 ConfirmWindow(txtl, 470 cancel_button=False, 471 width=600, 472 height=250, 473 origin_widget=self._account_type_info_button) 474 475 def refresh_characters(self) -> None: 476 """Refresh available characters/icons.""" 477 from bastd.actor import spazappearance 478 self._spazzes = spazappearance.get_appearances() 479 self._spazzes.sort() 480 self._icon_textures = [ 481 ba.gettexture(ba.app.spaz_appearances[s].icon_texture) 482 for s in self._spazzes 483 ] 484 self._icon_tint_textures = [ 485 ba.gettexture(ba.app.spaz_appearances[s].icon_mask_texture) 486 for s in self._spazzes 487 ] 488 489 def on_icon_picker_pick(self, icon: str) -> None: 490 """An icon has been selected by the picker.""" 491 self._icon = icon 492 self._update_icon() 493 494 def on_character_picker_pick(self, character: str) -> None: 495 """A character has been selected by the picker.""" 496 if not self._root_widget: 497 return 498 499 # The player could have bought a new one while the picker was up. 500 self.refresh_characters() 501 self._icon_index = self._spazzes.index( 502 character) if character in self._spazzes else 0 503 self._update_character() 504 505 def _on_character_press(self) -> None: 506 from bastd.ui import characterpicker 507 characterpicker.CharacterPicker( 508 parent=self._root_widget, 509 position=self._character_button.get_screen_space_center(), 510 selected_character=self._spazzes[self._icon_index], 511 delegate=self, 512 tint_color=self._color, 513 tint2_color=self._highlight) 514 515 def _on_icon_press(self) -> None: 516 from bastd.ui import iconpicker 517 iconpicker.IconPicker( 518 parent=self._root_widget, 519 position=self._icon_button.get_screen_space_center(), 520 selected_icon=self._icon, 521 delegate=self, 522 tint_color=self._color, 523 tint2_color=self._highlight) 524 525 def _make_picker(self, picker_type: str, origin: tuple[float, 526 float]) -> None: 527 from bastd.ui import colorpicker 528 if picker_type == 'color': 529 initial_color = self._color 530 elif picker_type == 'highlight': 531 initial_color = self._highlight 532 else: 533 raise ValueError('invalid picker_type: ' + picker_type) 534 colorpicker.ColorPicker( 535 parent=self._root_widget, 536 position=origin, 537 offset=(self._base_scale * 538 (-100 if picker_type == 'color' else 100), 0), 539 initial_color=initial_color, 540 delegate=self, 541 tag=picker_type) 542 543 def _cancel(self) -> None: 544 from bastd.ui.profile.browser import ProfileBrowserWindow 545 ba.containerwidget(edit=self._root_widget, transition='out_right') 546 ba.app.ui.set_main_menu_window( 547 ProfileBrowserWindow( 548 'in_left', 549 selected_profile=self._existing_profile, 550 in_main_menu=self._in_main_menu).get_root_widget()) 551 552 def _set_color(self, color: tuple[float, float, float]) -> None: 553 self._color = color 554 if self._color_button: 555 ba.buttonwidget(edit=self._color_button, color=color) 556 557 def _set_highlight(self, color: tuple[float, float, float]) -> None: 558 self._highlight = color 559 if self._highlight_button: 560 ba.buttonwidget(edit=self._highlight_button, color=color) 561 562 def color_picker_closing(self, picker: ColorPicker) -> None: 563 """Called when a color picker is closing.""" 564 if not self._root_widget: 565 return 566 tag = picker.get_tag() 567 if tag == 'color': 568 ba.containerwidget(edit=self._root_widget, 569 selected_child=self._color_button) 570 elif tag == 'highlight': 571 ba.containerwidget(edit=self._root_widget, 572 selected_child=self._highlight_button) 573 else: 574 print('color_picker_closing got unknown tag ' + str(tag)) 575 576 def color_picker_selected_color(self, picker: ColorPicker, 577 color: tuple[float, float, float]) -> None: 578 """Called when a color is selected in a color picker.""" 579 if not self._root_widget: 580 return 581 tag = picker.get_tag() 582 if tag == 'color': 583 self._set_color(color) 584 elif tag == 'highlight': 585 self._set_highlight(color) 586 else: 587 print('color_picker_selected_color got unknown tag ' + str(tag)) 588 self._update_character() 589 590 def _update_clipped_name(self) -> None: 591 if not self._clipped_name_text: 592 return 593 name = self.getname() 594 if name == '__account__': 595 name = (_ba.get_v1_account_name() 596 if _ba.get_v1_account_state() == 'signed_in' else '???') 597 if len(name) > 10 and not (self._global or self._is_account_profile): 598 ba.textwidget(edit=self._clipped_name_text, 599 text=ba.Lstr(resource='inGameClippedNameText', 600 subs=[('${NAME}', name[:10] + '...')])) 601 else: 602 ba.textwidget(edit=self._clipped_name_text, text='') 603 604 def _update_character(self, change: int = 0) -> None: 605 self._icon_index = (self._icon_index + change) % len(self._spazzes) 606 if self._character_button: 607 ba.buttonwidget( 608 edit=self._character_button, 609 texture=self._icon_textures[self._icon_index], 610 tint_texture=self._icon_tint_textures[self._icon_index], 611 tint_color=self._color, 612 tint2_color=self._highlight) 613 614 def _update_icon(self) -> None: 615 if self._icon_button_label: 616 ba.textwidget(edit=self._icon_button_label, text=self._icon) 617 618 def getname(self) -> str: 619 """Return the current profile name value.""" 620 if self._is_account_profile: 621 new_name = '__account__' 622 elif self._global: 623 new_name = self._name 624 else: 625 new_name = cast(str, ba.textwidget(query=self._text_field)) 626 return new_name 627 628 def save(self, transition_out: bool = True) -> bool: 629 """Save has been selected.""" 630 from bastd.ui.profile.browser import ProfileBrowserWindow 631 new_name = self.getname().strip() 632 633 if not new_name: 634 ba.screenmessage(ba.Lstr(resource='nameNotEmptyText')) 635 ba.playsound(ba.getsound('error')) 636 return False 637 638 if transition_out: 639 ba.playsound(ba.getsound('gunCocking')) 640 641 # Delete old in case we're renaming. 642 if self._existing_profile and self._existing_profile != new_name: 643 _ba.add_transaction({ 644 'type': 'REMOVE_PLAYER_PROFILE', 645 'name': self._existing_profile 646 }) 647 648 # Also lets be aware we're no longer global if we're taking a 649 # new name (will need to re-request it). 650 self._global = False 651 652 _ba.add_transaction({ 653 'type': 'ADD_PLAYER_PROFILE', 654 'name': new_name, 655 'profile': { 656 'character': self._spazzes[self._icon_index], 657 'color': list(self._color), 658 'global': self._global, 659 'icon': self._icon, 660 'highlight': list(self._highlight) 661 } 662 }) 663 664 if transition_out: 665 _ba.run_transactions() 666 ba.containerwidget(edit=self._root_widget, transition='out_right') 667 ba.app.ui.set_main_menu_window( 668 ProfileBrowserWindow( 669 'in_left', 670 selected_profile=new_name, 671 in_main_menu=self._in_main_menu).get_root_widget()) 672 return True
class
EditProfileWindow(ba.ui.Window):
18class EditProfileWindow(ba.Window): 19 """Window for editing a player profile.""" 20 21 # FIXME: WILL NEED TO CHANGE THIS FOR UILOCATION. 22 def reload_window(self) -> None: 23 """Transitions out and recreates ourself.""" 24 ba.containerwidget(edit=self._root_widget, transition='out_left') 25 ba.app.ui.set_main_menu_window( 26 EditProfileWindow(self.getname(), 27 self._in_main_menu).get_root_widget()) 28 29 def __init__(self, 30 existing_profile: str | None, 31 in_main_menu: bool, 32 transition: str = 'in_right'): 33 # FIXME: Tidy this up a bit. 34 # pylint: disable=too-many-branches 35 # pylint: disable=too-many-statements 36 # pylint: disable=too-many-locals 37 from ba.internal import get_player_profile_colors 38 self._in_main_menu = in_main_menu 39 self._existing_profile = existing_profile 40 self._r = 'editProfileWindow' 41 self._spazzes: list[str] = [] 42 self._icon_textures: list[ba.Texture] = [] 43 self._icon_tint_textures: list[ba.Texture] = [] 44 45 # Grab profile colors or pick random ones. 46 self._color, self._highlight = get_player_profile_colors( 47 existing_profile) 48 uiscale = ba.app.ui.uiscale 49 self._width = width = 780.0 if uiscale is ba.UIScale.SMALL else 680.0 50 self._x_inset = x_inset = 50.0 if uiscale is ba.UIScale.SMALL else 0.0 51 self._height = height = ( 52 350.0 if uiscale is ba.UIScale.SMALL else 53 400.0 if uiscale is ba.UIScale.MEDIUM else 450.0) 54 spacing = 40 55 self._base_scale = (2.05 if uiscale is ba.UIScale.SMALL else 56 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0) 57 top_extra = 15 if uiscale is ba.UIScale.SMALL else 15 58 super().__init__(root_widget=ba.containerwidget( 59 size=(width, height + top_extra), 60 transition=transition, 61 scale=self._base_scale, 62 stack_offset=(0, 15) if uiscale is ba.UIScale.SMALL else (0, 0))) 63 cancel_button = btn = ba.buttonwidget( 64 parent=self._root_widget, 65 position=(52 + x_inset, height - 60), 66 size=(155, 60), 67 scale=0.8, 68 autoselect=True, 69 label=ba.Lstr(resource='cancelText'), 70 on_activate_call=self._cancel) 71 ba.containerwidget(edit=self._root_widget, cancel_button=btn) 72 save_button = btn = ba.buttonwidget(parent=self._root_widget, 73 position=(width - (177 + x_inset), 74 height - 60), 75 size=(155, 60), 76 autoselect=True, 77 scale=0.8, 78 label=ba.Lstr(resource='saveText')) 79 ba.widget(edit=save_button, left_widget=cancel_button) 80 ba.widget(edit=cancel_button, right_widget=save_button) 81 ba.containerwidget(edit=self._root_widget, start_button=btn) 82 ba.textwidget(parent=self._root_widget, 83 position=(self._width * 0.5, height - 38), 84 size=(0, 0), 85 text=(ba.Lstr(resource=self._r + '.titleNewText') 86 if existing_profile is None else ba.Lstr( 87 resource=self._r + '.titleEditText')), 88 color=ba.app.ui.title_color, 89 maxwidth=290, 90 scale=1.0, 91 h_align='center', 92 v_align='center') 93 94 # Make a list of spaz icons. 95 self.refresh_characters() 96 profile = ba.app.config.get('Player Profiles', 97 {}).get(self._existing_profile, {}) 98 99 if 'global' in profile: 100 self._global = profile['global'] 101 else: 102 self._global = False 103 104 if 'icon' in profile: 105 self._icon = profile['icon'] 106 else: 107 self._icon = ba.charstr(ba.SpecialChar.LOGO) 108 109 assigned_random_char = False 110 111 # Look for existing character choice or pick random one otherwise. 112 try: 113 icon_index = self._spazzes.index(profile['character']) 114 except Exception: 115 # Let's set the default icon to spaz for our first profile; after 116 # that we go random. 117 # (SCRATCH THAT.. we now hard-code account-profiles to start with 118 # spaz which has a similar effect) 119 # try: p_len = len(ba.app.config['Player Profiles']) 120 # except Exception: p_len = 0 121 # if p_len == 0: icon_index = self._spazzes.index('Spaz') 122 # else: 123 random.seed() 124 icon_index = random.randrange(len(self._spazzes)) 125 assigned_random_char = True 126 self._icon_index = icon_index 127 ba.buttonwidget(edit=save_button, on_activate_call=self.save) 128 129 v = height - 115.0 130 self._name = ('' if self._existing_profile is None else 131 self._existing_profile) 132 self._is_account_profile = (self._name == '__account__') 133 134 # If we just picked a random character, see if it has specific 135 # colors/highlights associated with it and assign them if so. 136 if assigned_random_char: 137 clr = ba.app.spaz_appearances[ 138 self._spazzes[icon_index]].default_color 139 if clr is not None: 140 self._color = clr 141 highlight = ba.app.spaz_appearances[ 142 self._spazzes[icon_index]].default_highlight 143 if highlight is not None: 144 self._highlight = highlight 145 146 # Assign a random name if they had none. 147 if self._name == '': 148 names = _ba.get_random_names() 149 self._name = names[random.randrange(len(names))] 150 151 self._clipped_name_text = ba.textwidget(parent=self._root_widget, 152 text='', 153 position=(540 + x_inset, 154 v - 8), 155 flatness=1.0, 156 shadow=0.0, 157 scale=0.55, 158 size=(0, 0), 159 maxwidth=100, 160 h_align='center', 161 v_align='center', 162 color=(1, 1, 0, 0.5)) 163 164 if not self._is_account_profile and not self._global: 165 ba.textwidget(parent=self._root_widget, 166 text=ba.Lstr(resource=self._r + '.nameText'), 167 position=(200 + x_inset, v - 6), 168 size=(0, 0), 169 h_align='right', 170 v_align='center', 171 color=(1, 1, 1, 0.5), 172 scale=0.9) 173 174 self._upgrade_button = None 175 if self._is_account_profile: 176 if _ba.get_v1_account_state() == 'signed_in': 177 sval = _ba.get_v1_account_display_string() 178 else: 179 sval = '??' 180 ba.textwidget(parent=self._root_widget, 181 position=(self._width * 0.5, v - 7), 182 size=(0, 0), 183 scale=1.2, 184 text=sval, 185 maxwidth=270, 186 h_align='center', 187 v_align='center') 188 txtl = ba.Lstr( 189 resource='editProfileWindow.accountProfileText').evaluate() 190 b_width = min( 191 270.0, 192 _ba.get_string_width(txtl, suppress_warning=True) * 0.6) 193 ba.textwidget(parent=self._root_widget, 194 position=(self._width * 0.5, v - 39), 195 size=(0, 0), 196 scale=0.6, 197 color=ba.app.ui.infotextcolor, 198 text=txtl, 199 maxwidth=270, 200 h_align='center', 201 v_align='center') 202 self._account_type_info_button = ba.buttonwidget( 203 parent=self._root_widget, 204 label='?', 205 size=(15, 15), 206 text_scale=0.6, 207 position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47), 208 button_type='square', 209 color=(0.6, 0.5, 0.65), 210 autoselect=True, 211 on_activate_call=self.show_account_profile_info) 212 elif self._global: 213 214 b_size = 60 215 self._icon_button = btn = ba.buttonwidget( 216 parent=self._root_widget, 217 autoselect=True, 218 position=(self._width * 0.5 - 160 - b_size * 0.5, v - 38 - 15), 219 size=(b_size, b_size), 220 color=(0.6, 0.5, 0.6), 221 label='', 222 button_type='square', 223 text_scale=1.2, 224 on_activate_call=self._on_icon_press) 225 self._icon_button_label = ba.textwidget( 226 parent=self._root_widget, 227 position=(self._width * 0.5 - 160, v - 35), 228 draw_controller=btn, 229 h_align='center', 230 v_align='center', 231 size=(0, 0), 232 color=(1, 1, 1), 233 text='', 234 scale=2.0) 235 236 ba.textwidget(parent=self._root_widget, 237 h_align='center', 238 v_align='center', 239 position=(self._width * 0.5 - 160, v - 55 - 15), 240 size=(0, 0), 241 draw_controller=btn, 242 text=ba.Lstr(resource=self._r + '.iconText'), 243 scale=0.7, 244 color=ba.app.ui.title_color, 245 maxwidth=120) 246 247 self._update_icon() 248 249 ba.textwidget(parent=self._root_widget, 250 position=(self._width * 0.5, v - 7), 251 size=(0, 0), 252 scale=1.2, 253 text=self._name, 254 maxwidth=240, 255 h_align='center', 256 v_align='center') 257 # FIXME hard coded strings are bad 258 txtl = ba.Lstr( 259 resource='editProfileWindow.globalProfileText').evaluate() 260 b_width = min( 261 240.0, 262 _ba.get_string_width(txtl, suppress_warning=True) * 0.6) 263 ba.textwidget(parent=self._root_widget, 264 position=(self._width * 0.5, v - 39), 265 size=(0, 0), 266 scale=0.6, 267 color=ba.app.ui.infotextcolor, 268 text=txtl, 269 maxwidth=240, 270 h_align='center', 271 v_align='center') 272 self._account_type_info_button = ba.buttonwidget( 273 parent=self._root_widget, 274 label='?', 275 size=(15, 15), 276 text_scale=0.6, 277 position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47), 278 button_type='square', 279 color=(0.6, 0.5, 0.65), 280 autoselect=True, 281 on_activate_call=self.show_global_profile_info) 282 else: 283 self._text_field = ba.textwidget( 284 parent=self._root_widget, 285 position=(220 + x_inset, v - 30), 286 size=(265, 40), 287 text=self._name, 288 h_align='left', 289 v_align='center', 290 max_chars=16, 291 description=ba.Lstr(resource=self._r + '.nameDescriptionText'), 292 autoselect=True, 293 editable=True, 294 padding=4, 295 color=(0.9, 0.9, 0.9, 1.0), 296 on_return_press_call=ba.Call(save_button.activate)) 297 298 # FIXME hard coded strings are bad 299 txtl = ba.Lstr( 300 resource='editProfileWindow.localProfileText').evaluate() 301 b_width = min( 302 270.0, 303 _ba.get_string_width(txtl, suppress_warning=True) * 0.6) 304 ba.textwidget(parent=self._root_widget, 305 position=(self._width * 0.5, v - 43), 306 size=(0, 0), 307 scale=0.6, 308 color=ba.app.ui.infotextcolor, 309 text=txtl, 310 maxwidth=270, 311 h_align='center', 312 v_align='center') 313 self._account_type_info_button = ba.buttonwidget( 314 parent=self._root_widget, 315 label='?', 316 size=(15, 15), 317 text_scale=0.6, 318 position=(self._width * 0.5 + b_width * 0.5 + 13, v - 50), 319 button_type='square', 320 color=(0.6, 0.5, 0.65), 321 autoselect=True, 322 on_activate_call=self.show_local_profile_info) 323 self._upgrade_button = ba.buttonwidget( 324 parent=self._root_widget, 325 label=ba.Lstr(resource='upgradeText'), 326 size=(40, 17), 327 text_scale=1.0, 328 button_type='square', 329 position=(self._width * 0.5 + b_width * 0.5 + 13 + 43, v - 51), 330 color=(0.6, 0.5, 0.65), 331 autoselect=True, 332 on_activate_call=self.upgrade_profile) 333 334 self._update_clipped_name() 335 self._clipped_name_timer = ba.Timer(0.333, 336 ba.WeakCall( 337 self._update_clipped_name), 338 timetype=ba.TimeType.REAL, 339 repeat=True) 340 341 v -= spacing * 3.0 342 b_size = 80 343 b_size_2 = 100 344 b_offs = 150 345 self._color_button = btn = ba.buttonwidget( 346 parent=self._root_widget, 347 autoselect=True, 348 position=(self._width * 0.5 - b_offs - b_size * 0.5, v - 50), 349 size=(b_size, b_size), 350 color=self._color, 351 label='', 352 button_type='square') 353 origin = self._color_button.get_screen_space_center() 354 ba.buttonwidget(edit=self._color_button, 355 on_activate_call=ba.WeakCall(self._make_picker, 356 'color', origin)) 357 ba.textwidget(parent=self._root_widget, 358 h_align='center', 359 v_align='center', 360 position=(self._width * 0.5 - b_offs, v - 65), 361 size=(0, 0), 362 draw_controller=btn, 363 text=ba.Lstr(resource=self._r + '.colorText'), 364 scale=0.7, 365 color=ba.app.ui.title_color, 366 maxwidth=120) 367 368 self._character_button = btn = ba.buttonwidget( 369 parent=self._root_widget, 370 autoselect=True, 371 position=(self._width * 0.5 - b_size_2 * 0.5, v - 60), 372 up_widget=self._account_type_info_button, 373 on_activate_call=self._on_character_press, 374 size=(b_size_2, b_size_2), 375 label='', 376 color=(1, 1, 1), 377 mask_texture=ba.gettexture('characterIconMask')) 378 if not self._is_account_profile and not self._global: 379 ba.containerwidget(edit=self._root_widget, 380 selected_child=self._text_field) 381 ba.textwidget(parent=self._root_widget, 382 h_align='center', 383 v_align='center', 384 position=(self._width * 0.5, v - 80), 385 size=(0, 0), 386 draw_controller=btn, 387 text=ba.Lstr(resource=self._r + '.characterText'), 388 scale=0.7, 389 color=ba.app.ui.title_color, 390 maxwidth=130) 391 392 self._highlight_button = btn = ba.buttonwidget( 393 parent=self._root_widget, 394 autoselect=True, 395 position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50), 396 up_widget=self._upgrade_button if self._upgrade_button is not None 397 else self._account_type_info_button, 398 size=(b_size, b_size), 399 color=self._highlight, 400 label='', 401 button_type='square') 402 403 if not self._is_account_profile and not self._global: 404 ba.widget(edit=cancel_button, down_widget=self._text_field) 405 ba.widget(edit=save_button, down_widget=self._text_field) 406 ba.widget(edit=self._color_button, up_widget=self._text_field) 407 ba.widget(edit=self._account_type_info_button, 408 down_widget=self._character_button) 409 410 origin = self._highlight_button.get_screen_space_center() 411 ba.buttonwidget(edit=self._highlight_button, 412 on_activate_call=ba.WeakCall(self._make_picker, 413 'highlight', origin)) 414 ba.textwidget(parent=self._root_widget, 415 h_align='center', 416 v_align='center', 417 position=(self._width * 0.5 + b_offs, v - 65), 418 size=(0, 0), 419 draw_controller=btn, 420 text=ba.Lstr(resource=self._r + '.highlightText'), 421 scale=0.7, 422 color=ba.app.ui.title_color, 423 maxwidth=120) 424 self._update_character() 425 426 def upgrade_profile(self) -> None: 427 """Attempt to ugrade the profile to global.""" 428 from bastd.ui import account 429 from bastd.ui.profile import upgrade as pupgrade 430 if _ba.get_v1_account_state() != 'signed_in': 431 account.show_sign_in_prompt() 432 return 433 434 pupgrade.ProfileUpgradeWindow(self) 435 436 def show_account_profile_info(self) -> None: 437 """Show an explanation of account profiles.""" 438 from bastd.ui.confirm import ConfirmWindow 439 icons_str = ' '.join([ 440 ba.charstr(n) for n in [ 441 ba.SpecialChar.GOOGLE_PLAY_GAMES_LOGO, 442 ba.SpecialChar.GAME_CENTER_LOGO, 443 ba.SpecialChar.GAME_CIRCLE_LOGO, ba.SpecialChar.OUYA_LOGO, 444 ba.SpecialChar.LOCAL_ACCOUNT, ba.SpecialChar.ALIBABA_LOGO, 445 ba.SpecialChar.OCULUS_LOGO, ba.SpecialChar.NVIDIA_LOGO 446 ] 447 ]) 448 txtl = ba.Lstr(resource='editProfileWindow.accountProfileInfoText', 449 subs=[('${ICONS}', icons_str)]) 450 ConfirmWindow(txtl, 451 cancel_button=False, 452 width=500, 453 height=300, 454 origin_widget=self._account_type_info_button) 455 456 def show_local_profile_info(self) -> None: 457 """Show an explanation of local profiles.""" 458 from bastd.ui.confirm import ConfirmWindow 459 txtl = ba.Lstr(resource='editProfileWindow.localProfileInfoText') 460 ConfirmWindow(txtl, 461 cancel_button=False, 462 width=600, 463 height=250, 464 origin_widget=self._account_type_info_button) 465 466 def show_global_profile_info(self) -> None: 467 """Show an explanation of global profiles.""" 468 from bastd.ui.confirm import ConfirmWindow 469 txtl = ba.Lstr(resource='editProfileWindow.globalProfileInfoText') 470 ConfirmWindow(txtl, 471 cancel_button=False, 472 width=600, 473 height=250, 474 origin_widget=self._account_type_info_button) 475 476 def refresh_characters(self) -> None: 477 """Refresh available characters/icons.""" 478 from bastd.actor import spazappearance 479 self._spazzes = spazappearance.get_appearances() 480 self._spazzes.sort() 481 self._icon_textures = [ 482 ba.gettexture(ba.app.spaz_appearances[s].icon_texture) 483 for s in self._spazzes 484 ] 485 self._icon_tint_textures = [ 486 ba.gettexture(ba.app.spaz_appearances[s].icon_mask_texture) 487 for s in self._spazzes 488 ] 489 490 def on_icon_picker_pick(self, icon: str) -> None: 491 """An icon has been selected by the picker.""" 492 self._icon = icon 493 self._update_icon() 494 495 def on_character_picker_pick(self, character: str) -> None: 496 """A character has been selected by the picker.""" 497 if not self._root_widget: 498 return 499 500 # The player could have bought a new one while the picker was up. 501 self.refresh_characters() 502 self._icon_index = self._spazzes.index( 503 character) if character in self._spazzes else 0 504 self._update_character() 505 506 def _on_character_press(self) -> None: 507 from bastd.ui import characterpicker 508 characterpicker.CharacterPicker( 509 parent=self._root_widget, 510 position=self._character_button.get_screen_space_center(), 511 selected_character=self._spazzes[self._icon_index], 512 delegate=self, 513 tint_color=self._color, 514 tint2_color=self._highlight) 515 516 def _on_icon_press(self) -> None: 517 from bastd.ui import iconpicker 518 iconpicker.IconPicker( 519 parent=self._root_widget, 520 position=self._icon_button.get_screen_space_center(), 521 selected_icon=self._icon, 522 delegate=self, 523 tint_color=self._color, 524 tint2_color=self._highlight) 525 526 def _make_picker(self, picker_type: str, origin: tuple[float, 527 float]) -> None: 528 from bastd.ui import colorpicker 529 if picker_type == 'color': 530 initial_color = self._color 531 elif picker_type == 'highlight': 532 initial_color = self._highlight 533 else: 534 raise ValueError('invalid picker_type: ' + picker_type) 535 colorpicker.ColorPicker( 536 parent=self._root_widget, 537 position=origin, 538 offset=(self._base_scale * 539 (-100 if picker_type == 'color' else 100), 0), 540 initial_color=initial_color, 541 delegate=self, 542 tag=picker_type) 543 544 def _cancel(self) -> None: 545 from bastd.ui.profile.browser import ProfileBrowserWindow 546 ba.containerwidget(edit=self._root_widget, transition='out_right') 547 ba.app.ui.set_main_menu_window( 548 ProfileBrowserWindow( 549 'in_left', 550 selected_profile=self._existing_profile, 551 in_main_menu=self._in_main_menu).get_root_widget()) 552 553 def _set_color(self, color: tuple[float, float, float]) -> None: 554 self._color = color 555 if self._color_button: 556 ba.buttonwidget(edit=self._color_button, color=color) 557 558 def _set_highlight(self, color: tuple[float, float, float]) -> None: 559 self._highlight = color 560 if self._highlight_button: 561 ba.buttonwidget(edit=self._highlight_button, color=color) 562 563 def color_picker_closing(self, picker: ColorPicker) -> None: 564 """Called when a color picker is closing.""" 565 if not self._root_widget: 566 return 567 tag = picker.get_tag() 568 if tag == 'color': 569 ba.containerwidget(edit=self._root_widget, 570 selected_child=self._color_button) 571 elif tag == 'highlight': 572 ba.containerwidget(edit=self._root_widget, 573 selected_child=self._highlight_button) 574 else: 575 print('color_picker_closing got unknown tag ' + str(tag)) 576 577 def color_picker_selected_color(self, picker: ColorPicker, 578 color: tuple[float, float, float]) -> None: 579 """Called when a color is selected in a color picker.""" 580 if not self._root_widget: 581 return 582 tag = picker.get_tag() 583 if tag == 'color': 584 self._set_color(color) 585 elif tag == 'highlight': 586 self._set_highlight(color) 587 else: 588 print('color_picker_selected_color got unknown tag ' + str(tag)) 589 self._update_character() 590 591 def _update_clipped_name(self) -> None: 592 if not self._clipped_name_text: 593 return 594 name = self.getname() 595 if name == '__account__': 596 name = (_ba.get_v1_account_name() 597 if _ba.get_v1_account_state() == 'signed_in' else '???') 598 if len(name) > 10 and not (self._global or self._is_account_profile): 599 ba.textwidget(edit=self._clipped_name_text, 600 text=ba.Lstr(resource='inGameClippedNameText', 601 subs=[('${NAME}', name[:10] + '...')])) 602 else: 603 ba.textwidget(edit=self._clipped_name_text, text='') 604 605 def _update_character(self, change: int = 0) -> None: 606 self._icon_index = (self._icon_index + change) % len(self._spazzes) 607 if self._character_button: 608 ba.buttonwidget( 609 edit=self._character_button, 610 texture=self._icon_textures[self._icon_index], 611 tint_texture=self._icon_tint_textures[self._icon_index], 612 tint_color=self._color, 613 tint2_color=self._highlight) 614 615 def _update_icon(self) -> None: 616 if self._icon_button_label: 617 ba.textwidget(edit=self._icon_button_label, text=self._icon) 618 619 def getname(self) -> str: 620 """Return the current profile name value.""" 621 if self._is_account_profile: 622 new_name = '__account__' 623 elif self._global: 624 new_name = self._name 625 else: 626 new_name = cast(str, ba.textwidget(query=self._text_field)) 627 return new_name 628 629 def save(self, transition_out: bool = True) -> bool: 630 """Save has been selected.""" 631 from bastd.ui.profile.browser import ProfileBrowserWindow 632 new_name = self.getname().strip() 633 634 if not new_name: 635 ba.screenmessage(ba.Lstr(resource='nameNotEmptyText')) 636 ba.playsound(ba.getsound('error')) 637 return False 638 639 if transition_out: 640 ba.playsound(ba.getsound('gunCocking')) 641 642 # Delete old in case we're renaming. 643 if self._existing_profile and self._existing_profile != new_name: 644 _ba.add_transaction({ 645 'type': 'REMOVE_PLAYER_PROFILE', 646 'name': self._existing_profile 647 }) 648 649 # Also lets be aware we're no longer global if we're taking a 650 # new name (will need to re-request it). 651 self._global = False 652 653 _ba.add_transaction({ 654 'type': 'ADD_PLAYER_PROFILE', 655 'name': new_name, 656 'profile': { 657 'character': self._spazzes[self._icon_index], 658 'color': list(self._color), 659 'global': self._global, 660 'icon': self._icon, 661 'highlight': list(self._highlight) 662 } 663 }) 664 665 if transition_out: 666 _ba.run_transactions() 667 ba.containerwidget(edit=self._root_widget, transition='out_right') 668 ba.app.ui.set_main_menu_window( 669 ProfileBrowserWindow( 670 'in_left', 671 selected_profile=new_name, 672 in_main_menu=self._in_main_menu).get_root_widget()) 673 return True
Window for editing a player profile.
EditProfileWindow( existing_profile: str | None, in_main_menu: bool, transition: str = 'in_right')
29 def __init__(self, 30 existing_profile: str | None, 31 in_main_menu: bool, 32 transition: str = 'in_right'): 33 # FIXME: Tidy this up a bit. 34 # pylint: disable=too-many-branches 35 # pylint: disable=too-many-statements 36 # pylint: disable=too-many-locals 37 from ba.internal import get_player_profile_colors 38 self._in_main_menu = in_main_menu 39 self._existing_profile = existing_profile 40 self._r = 'editProfileWindow' 41 self._spazzes: list[str] = [] 42 self._icon_textures: list[ba.Texture] = [] 43 self._icon_tint_textures: list[ba.Texture] = [] 44 45 # Grab profile colors or pick random ones. 46 self._color, self._highlight = get_player_profile_colors( 47 existing_profile) 48 uiscale = ba.app.ui.uiscale 49 self._width = width = 780.0 if uiscale is ba.UIScale.SMALL else 680.0 50 self._x_inset = x_inset = 50.0 if uiscale is ba.UIScale.SMALL else 0.0 51 self._height = height = ( 52 350.0 if uiscale is ba.UIScale.SMALL else 53 400.0 if uiscale is ba.UIScale.MEDIUM else 450.0) 54 spacing = 40 55 self._base_scale = (2.05 if uiscale is ba.UIScale.SMALL else 56 1.5 if uiscale is ba.UIScale.MEDIUM else 1.0) 57 top_extra = 15 if uiscale is ba.UIScale.SMALL else 15 58 super().__init__(root_widget=ba.containerwidget( 59 size=(width, height + top_extra), 60 transition=transition, 61 scale=self._base_scale, 62 stack_offset=(0, 15) if uiscale is ba.UIScale.SMALL else (0, 0))) 63 cancel_button = btn = ba.buttonwidget( 64 parent=self._root_widget, 65 position=(52 + x_inset, height - 60), 66 size=(155, 60), 67 scale=0.8, 68 autoselect=True, 69 label=ba.Lstr(resource='cancelText'), 70 on_activate_call=self._cancel) 71 ba.containerwidget(edit=self._root_widget, cancel_button=btn) 72 save_button = btn = ba.buttonwidget(parent=self._root_widget, 73 position=(width - (177 + x_inset), 74 height - 60), 75 size=(155, 60), 76 autoselect=True, 77 scale=0.8, 78 label=ba.Lstr(resource='saveText')) 79 ba.widget(edit=save_button, left_widget=cancel_button) 80 ba.widget(edit=cancel_button, right_widget=save_button) 81 ba.containerwidget(edit=self._root_widget, start_button=btn) 82 ba.textwidget(parent=self._root_widget, 83 position=(self._width * 0.5, height - 38), 84 size=(0, 0), 85 text=(ba.Lstr(resource=self._r + '.titleNewText') 86 if existing_profile is None else ba.Lstr( 87 resource=self._r + '.titleEditText')), 88 color=ba.app.ui.title_color, 89 maxwidth=290, 90 scale=1.0, 91 h_align='center', 92 v_align='center') 93 94 # Make a list of spaz icons. 95 self.refresh_characters() 96 profile = ba.app.config.get('Player Profiles', 97 {}).get(self._existing_profile, {}) 98 99 if 'global' in profile: 100 self._global = profile['global'] 101 else: 102 self._global = False 103 104 if 'icon' in profile: 105 self._icon = profile['icon'] 106 else: 107 self._icon = ba.charstr(ba.SpecialChar.LOGO) 108 109 assigned_random_char = False 110 111 # Look for existing character choice or pick random one otherwise. 112 try: 113 icon_index = self._spazzes.index(profile['character']) 114 except Exception: 115 # Let's set the default icon to spaz for our first profile; after 116 # that we go random. 117 # (SCRATCH THAT.. we now hard-code account-profiles to start with 118 # spaz which has a similar effect) 119 # try: p_len = len(ba.app.config['Player Profiles']) 120 # except Exception: p_len = 0 121 # if p_len == 0: icon_index = self._spazzes.index('Spaz') 122 # else: 123 random.seed() 124 icon_index = random.randrange(len(self._spazzes)) 125 assigned_random_char = True 126 self._icon_index = icon_index 127 ba.buttonwidget(edit=save_button, on_activate_call=self.save) 128 129 v = height - 115.0 130 self._name = ('' if self._existing_profile is None else 131 self._existing_profile) 132 self._is_account_profile = (self._name == '__account__') 133 134 # If we just picked a random character, see if it has specific 135 # colors/highlights associated with it and assign them if so. 136 if assigned_random_char: 137 clr = ba.app.spaz_appearances[ 138 self._spazzes[icon_index]].default_color 139 if clr is not None: 140 self._color = clr 141 highlight = ba.app.spaz_appearances[ 142 self._spazzes[icon_index]].default_highlight 143 if highlight is not None: 144 self._highlight = highlight 145 146 # Assign a random name if they had none. 147 if self._name == '': 148 names = _ba.get_random_names() 149 self._name = names[random.randrange(len(names))] 150 151 self._clipped_name_text = ba.textwidget(parent=self._root_widget, 152 text='', 153 position=(540 + x_inset, 154 v - 8), 155 flatness=1.0, 156 shadow=0.0, 157 scale=0.55, 158 size=(0, 0), 159 maxwidth=100, 160 h_align='center', 161 v_align='center', 162 color=(1, 1, 0, 0.5)) 163 164 if not self._is_account_profile and not self._global: 165 ba.textwidget(parent=self._root_widget, 166 text=ba.Lstr(resource=self._r + '.nameText'), 167 position=(200 + x_inset, v - 6), 168 size=(0, 0), 169 h_align='right', 170 v_align='center', 171 color=(1, 1, 1, 0.5), 172 scale=0.9) 173 174 self._upgrade_button = None 175 if self._is_account_profile: 176 if _ba.get_v1_account_state() == 'signed_in': 177 sval = _ba.get_v1_account_display_string() 178 else: 179 sval = '??' 180 ba.textwidget(parent=self._root_widget, 181 position=(self._width * 0.5, v - 7), 182 size=(0, 0), 183 scale=1.2, 184 text=sval, 185 maxwidth=270, 186 h_align='center', 187 v_align='center') 188 txtl = ba.Lstr( 189 resource='editProfileWindow.accountProfileText').evaluate() 190 b_width = min( 191 270.0, 192 _ba.get_string_width(txtl, suppress_warning=True) * 0.6) 193 ba.textwidget(parent=self._root_widget, 194 position=(self._width * 0.5, v - 39), 195 size=(0, 0), 196 scale=0.6, 197 color=ba.app.ui.infotextcolor, 198 text=txtl, 199 maxwidth=270, 200 h_align='center', 201 v_align='center') 202 self._account_type_info_button = ba.buttonwidget( 203 parent=self._root_widget, 204 label='?', 205 size=(15, 15), 206 text_scale=0.6, 207 position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47), 208 button_type='square', 209 color=(0.6, 0.5, 0.65), 210 autoselect=True, 211 on_activate_call=self.show_account_profile_info) 212 elif self._global: 213 214 b_size = 60 215 self._icon_button = btn = ba.buttonwidget( 216 parent=self._root_widget, 217 autoselect=True, 218 position=(self._width * 0.5 - 160 - b_size * 0.5, v - 38 - 15), 219 size=(b_size, b_size), 220 color=(0.6, 0.5, 0.6), 221 label='', 222 button_type='square', 223 text_scale=1.2, 224 on_activate_call=self._on_icon_press) 225 self._icon_button_label = ba.textwidget( 226 parent=self._root_widget, 227 position=(self._width * 0.5 - 160, v - 35), 228 draw_controller=btn, 229 h_align='center', 230 v_align='center', 231 size=(0, 0), 232 color=(1, 1, 1), 233 text='', 234 scale=2.0) 235 236 ba.textwidget(parent=self._root_widget, 237 h_align='center', 238 v_align='center', 239 position=(self._width * 0.5 - 160, v - 55 - 15), 240 size=(0, 0), 241 draw_controller=btn, 242 text=ba.Lstr(resource=self._r + '.iconText'), 243 scale=0.7, 244 color=ba.app.ui.title_color, 245 maxwidth=120) 246 247 self._update_icon() 248 249 ba.textwidget(parent=self._root_widget, 250 position=(self._width * 0.5, v - 7), 251 size=(0, 0), 252 scale=1.2, 253 text=self._name, 254 maxwidth=240, 255 h_align='center', 256 v_align='center') 257 # FIXME hard coded strings are bad 258 txtl = ba.Lstr( 259 resource='editProfileWindow.globalProfileText').evaluate() 260 b_width = min( 261 240.0, 262 _ba.get_string_width(txtl, suppress_warning=True) * 0.6) 263 ba.textwidget(parent=self._root_widget, 264 position=(self._width * 0.5, v - 39), 265 size=(0, 0), 266 scale=0.6, 267 color=ba.app.ui.infotextcolor, 268 text=txtl, 269 maxwidth=240, 270 h_align='center', 271 v_align='center') 272 self._account_type_info_button = ba.buttonwidget( 273 parent=self._root_widget, 274 label='?', 275 size=(15, 15), 276 text_scale=0.6, 277 position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47), 278 button_type='square', 279 color=(0.6, 0.5, 0.65), 280 autoselect=True, 281 on_activate_call=self.show_global_profile_info) 282 else: 283 self._text_field = ba.textwidget( 284 parent=self._root_widget, 285 position=(220 + x_inset, v - 30), 286 size=(265, 40), 287 text=self._name, 288 h_align='left', 289 v_align='center', 290 max_chars=16, 291 description=ba.Lstr(resource=self._r + '.nameDescriptionText'), 292 autoselect=True, 293 editable=True, 294 padding=4, 295 color=(0.9, 0.9, 0.9, 1.0), 296 on_return_press_call=ba.Call(save_button.activate)) 297 298 # FIXME hard coded strings are bad 299 txtl = ba.Lstr( 300 resource='editProfileWindow.localProfileText').evaluate() 301 b_width = min( 302 270.0, 303 _ba.get_string_width(txtl, suppress_warning=True) * 0.6) 304 ba.textwidget(parent=self._root_widget, 305 position=(self._width * 0.5, v - 43), 306 size=(0, 0), 307 scale=0.6, 308 color=ba.app.ui.infotextcolor, 309 text=txtl, 310 maxwidth=270, 311 h_align='center', 312 v_align='center') 313 self._account_type_info_button = ba.buttonwidget( 314 parent=self._root_widget, 315 label='?', 316 size=(15, 15), 317 text_scale=0.6, 318 position=(self._width * 0.5 + b_width * 0.5 + 13, v - 50), 319 button_type='square', 320 color=(0.6, 0.5, 0.65), 321 autoselect=True, 322 on_activate_call=self.show_local_profile_info) 323 self._upgrade_button = ba.buttonwidget( 324 parent=self._root_widget, 325 label=ba.Lstr(resource='upgradeText'), 326 size=(40, 17), 327 text_scale=1.0, 328 button_type='square', 329 position=(self._width * 0.5 + b_width * 0.5 + 13 + 43, v - 51), 330 color=(0.6, 0.5, 0.65), 331 autoselect=True, 332 on_activate_call=self.upgrade_profile) 333 334 self._update_clipped_name() 335 self._clipped_name_timer = ba.Timer(0.333, 336 ba.WeakCall( 337 self._update_clipped_name), 338 timetype=ba.TimeType.REAL, 339 repeat=True) 340 341 v -= spacing * 3.0 342 b_size = 80 343 b_size_2 = 100 344 b_offs = 150 345 self._color_button = btn = ba.buttonwidget( 346 parent=self._root_widget, 347 autoselect=True, 348 position=(self._width * 0.5 - b_offs - b_size * 0.5, v - 50), 349 size=(b_size, b_size), 350 color=self._color, 351 label='', 352 button_type='square') 353 origin = self._color_button.get_screen_space_center() 354 ba.buttonwidget(edit=self._color_button, 355 on_activate_call=ba.WeakCall(self._make_picker, 356 'color', origin)) 357 ba.textwidget(parent=self._root_widget, 358 h_align='center', 359 v_align='center', 360 position=(self._width * 0.5 - b_offs, v - 65), 361 size=(0, 0), 362 draw_controller=btn, 363 text=ba.Lstr(resource=self._r + '.colorText'), 364 scale=0.7, 365 color=ba.app.ui.title_color, 366 maxwidth=120) 367 368 self._character_button = btn = ba.buttonwidget( 369 parent=self._root_widget, 370 autoselect=True, 371 position=(self._width * 0.5 - b_size_2 * 0.5, v - 60), 372 up_widget=self._account_type_info_button, 373 on_activate_call=self._on_character_press, 374 size=(b_size_2, b_size_2), 375 label='', 376 color=(1, 1, 1), 377 mask_texture=ba.gettexture('characterIconMask')) 378 if not self._is_account_profile and not self._global: 379 ba.containerwidget(edit=self._root_widget, 380 selected_child=self._text_field) 381 ba.textwidget(parent=self._root_widget, 382 h_align='center', 383 v_align='center', 384 position=(self._width * 0.5, v - 80), 385 size=(0, 0), 386 draw_controller=btn, 387 text=ba.Lstr(resource=self._r + '.characterText'), 388 scale=0.7, 389 color=ba.app.ui.title_color, 390 maxwidth=130) 391 392 self._highlight_button = btn = ba.buttonwidget( 393 parent=self._root_widget, 394 autoselect=True, 395 position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50), 396 up_widget=self._upgrade_button if self._upgrade_button is not None 397 else self._account_type_info_button, 398 size=(b_size, b_size), 399 color=self._highlight, 400 label='', 401 button_type='square') 402 403 if not self._is_account_profile and not self._global: 404 ba.widget(edit=cancel_button, down_widget=self._text_field) 405 ba.widget(edit=save_button, down_widget=self._text_field) 406 ba.widget(edit=self._color_button, up_widget=self._text_field) 407 ba.widget(edit=self._account_type_info_button, 408 down_widget=self._character_button) 409 410 origin = self._highlight_button.get_screen_space_center() 411 ba.buttonwidget(edit=self._highlight_button, 412 on_activate_call=ba.WeakCall(self._make_picker, 413 'highlight', origin)) 414 ba.textwidget(parent=self._root_widget, 415 h_align='center', 416 v_align='center', 417 position=(self._width * 0.5 + b_offs, v - 65), 418 size=(0, 0), 419 draw_controller=btn, 420 text=ba.Lstr(resource=self._r + '.highlightText'), 421 scale=0.7, 422 color=ba.app.ui.title_color, 423 maxwidth=120) 424 self._update_character()
def
reload_window(self) -> None:
22 def reload_window(self) -> None: 23 """Transitions out and recreates ourself.""" 24 ba.containerwidget(edit=self._root_widget, transition='out_left') 25 ba.app.ui.set_main_menu_window( 26 EditProfileWindow(self.getname(), 27 self._in_main_menu).get_root_widget())
Transitions out and recreates ourself.
def
upgrade_profile(self) -> None:
426 def upgrade_profile(self) -> None: 427 """Attempt to ugrade the profile to global.""" 428 from bastd.ui import account 429 from bastd.ui.profile import upgrade as pupgrade 430 if _ba.get_v1_account_state() != 'signed_in': 431 account.show_sign_in_prompt() 432 return 433 434 pupgrade.ProfileUpgradeWindow(self)
Attempt to ugrade the profile to global.
def
show_account_profile_info(self) -> None:
436 def show_account_profile_info(self) -> None: 437 """Show an explanation of account profiles.""" 438 from bastd.ui.confirm import ConfirmWindow 439 icons_str = ' '.join([ 440 ba.charstr(n) for n in [ 441 ba.SpecialChar.GOOGLE_PLAY_GAMES_LOGO, 442 ba.SpecialChar.GAME_CENTER_LOGO, 443 ba.SpecialChar.GAME_CIRCLE_LOGO, ba.SpecialChar.OUYA_LOGO, 444 ba.SpecialChar.LOCAL_ACCOUNT, ba.SpecialChar.ALIBABA_LOGO, 445 ba.SpecialChar.OCULUS_LOGO, ba.SpecialChar.NVIDIA_LOGO 446 ] 447 ]) 448 txtl = ba.Lstr(resource='editProfileWindow.accountProfileInfoText', 449 subs=[('${ICONS}', icons_str)]) 450 ConfirmWindow(txtl, 451 cancel_button=False, 452 width=500, 453 height=300, 454 origin_widget=self._account_type_info_button)
Show an explanation of account profiles.
def
show_local_profile_info(self) -> None:
456 def show_local_profile_info(self) -> None: 457 """Show an explanation of local profiles.""" 458 from bastd.ui.confirm import ConfirmWindow 459 txtl = ba.Lstr(resource='editProfileWindow.localProfileInfoText') 460 ConfirmWindow(txtl, 461 cancel_button=False, 462 width=600, 463 height=250, 464 origin_widget=self._account_type_info_button)
Show an explanation of local profiles.
def
show_global_profile_info(self) -> None:
466 def show_global_profile_info(self) -> None: 467 """Show an explanation of global profiles.""" 468 from bastd.ui.confirm import ConfirmWindow 469 txtl = ba.Lstr(resource='editProfileWindow.globalProfileInfoText') 470 ConfirmWindow(txtl, 471 cancel_button=False, 472 width=600, 473 height=250, 474 origin_widget=self._account_type_info_button)
Show an explanation of global profiles.
def
refresh_characters(self) -> None:
476 def refresh_characters(self) -> None: 477 """Refresh available characters/icons.""" 478 from bastd.actor import spazappearance 479 self._spazzes = spazappearance.get_appearances() 480 self._spazzes.sort() 481 self._icon_textures = [ 482 ba.gettexture(ba.app.spaz_appearances[s].icon_texture) 483 for s in self._spazzes 484 ] 485 self._icon_tint_textures = [ 486 ba.gettexture(ba.app.spaz_appearances[s].icon_mask_texture) 487 for s in self._spazzes 488 ]
Refresh available characters/icons.
def
on_icon_picker_pick(self, icon: str) -> None:
490 def on_icon_picker_pick(self, icon: str) -> None: 491 """An icon has been selected by the picker.""" 492 self._icon = icon 493 self._update_icon()
An icon has been selected by the picker.
def
on_character_picker_pick(self, character: str) -> None:
495 def on_character_picker_pick(self, character: str) -> None: 496 """A character has been selected by the picker.""" 497 if not self._root_widget: 498 return 499 500 # The player could have bought a new one while the picker was up. 501 self.refresh_characters() 502 self._icon_index = self._spazzes.index( 503 character) if character in self._spazzes else 0 504 self._update_character()
A character has been selected by the picker.
563 def color_picker_closing(self, picker: ColorPicker) -> None: 564 """Called when a color picker is closing.""" 565 if not self._root_widget: 566 return 567 tag = picker.get_tag() 568 if tag == 'color': 569 ba.containerwidget(edit=self._root_widget, 570 selected_child=self._color_button) 571 elif tag == 'highlight': 572 ba.containerwidget(edit=self._root_widget, 573 selected_child=self._highlight_button) 574 else: 575 print('color_picker_closing got unknown tag ' + str(tag))
Called when a color picker is closing.
def
color_picker_selected_color( self, picker: bastd.ui.colorpicker.ColorPicker, color: tuple[float, float, float]) -> None:
577 def color_picker_selected_color(self, picker: ColorPicker, 578 color: tuple[float, float, float]) -> None: 579 """Called when a color is selected in a color picker.""" 580 if not self._root_widget: 581 return 582 tag = picker.get_tag() 583 if tag == 'color': 584 self._set_color(color) 585 elif tag == 'highlight': 586 self._set_highlight(color) 587 else: 588 print('color_picker_selected_color got unknown tag ' + str(tag)) 589 self._update_character()
Called when a color is selected in a color picker.
def
getname(self) -> str:
619 def getname(self) -> str: 620 """Return the current profile name value.""" 621 if self._is_account_profile: 622 new_name = '__account__' 623 elif self._global: 624 new_name = self._name 625 else: 626 new_name = cast(str, ba.textwidget(query=self._text_field)) 627 return new_name
Return the current profile name value.
def
save(self, transition_out: bool = True) -> bool:
629 def save(self, transition_out: bool = True) -> bool: 630 """Save has been selected.""" 631 from bastd.ui.profile.browser import ProfileBrowserWindow 632 new_name = self.getname().strip() 633 634 if not new_name: 635 ba.screenmessage(ba.Lstr(resource='nameNotEmptyText')) 636 ba.playsound(ba.getsound('error')) 637 return False 638 639 if transition_out: 640 ba.playsound(ba.getsound('gunCocking')) 641 642 # Delete old in case we're renaming. 643 if self._existing_profile and self._existing_profile != new_name: 644 _ba.add_transaction({ 645 'type': 'REMOVE_PLAYER_PROFILE', 646 'name': self._existing_profile 647 }) 648 649 # Also lets be aware we're no longer global if we're taking a 650 # new name (will need to re-request it). 651 self._global = False 652 653 _ba.add_transaction({ 654 'type': 'ADD_PLAYER_PROFILE', 655 'name': new_name, 656 'profile': { 657 'character': self._spazzes[self._icon_index], 658 'color': list(self._color), 659 'global': self._global, 660 'icon': self._icon, 661 'highlight': list(self._highlight) 662 } 663 }) 664 665 if transition_out: 666 _ba.run_transactions() 667 ba.containerwidget(edit=self._root_widget, transition='out_right') 668 ba.app.ui.set_main_menu_window( 669 ProfileBrowserWindow( 670 'in_left', 671 selected_profile=new_name, 672 in_main_menu=self._in_main_menu).get_root_widget()) 673 return True
Save has been selected.
Inherited Members
- ba.ui.Window
- get_root_widget