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