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=self._r + '.titleNewText') 114 if existing_profile is None 115 else bui.Lstr(resource=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=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=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=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=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=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=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.GAME_CIRCLE_LOGO, 549 bui.SpecialChar.OUYA_LOGO, 550 bui.SpecialChar.LOCAL_ACCOUNT, 551 bui.SpecialChar.OCULUS_LOGO, 552 bui.SpecialChar.NVIDIA_LOGO, 553 bui.SpecialChar.V2_LOGO, 554 ] 555 ] 556 ) 557 txtl = bui.Lstr( 558 resource='editProfileWindow.accountProfileInfoText', 559 subs=[('${ICONS}', icons_str)], 560 ) 561 ConfirmWindow( 562 txtl, 563 cancel_button=False, 564 width=500, 565 height=300, 566 origin_widget=self._account_type_info_button, 567 ) 568 569 def show_local_profile_info(self) -> None: 570 """Show an explanation of local profiles.""" 571 from bauiv1lib.confirm import ConfirmWindow 572 573 txtl = bui.Lstr(resource='editProfileWindow.localProfileInfoText') 574 ConfirmWindow( 575 txtl, 576 cancel_button=False, 577 width=600, 578 height=250, 579 origin_widget=self._account_type_info_button, 580 ) 581 582 def show_global_profile_info(self) -> None: 583 """Show an explanation of global profiles.""" 584 from bauiv1lib.confirm import ConfirmWindow 585 586 txtl = bui.Lstr(resource='editProfileWindow.globalProfileInfoText') 587 ConfirmWindow( 588 txtl, 589 cancel_button=False, 590 width=600, 591 height=250, 592 origin_widget=self._account_type_info_button, 593 ) 594 595 def refresh_characters(self) -> None: 596 """Refresh available characters/icons.""" 597 from bascenev1lib.actor import spazappearance 598 599 assert bui.app.classic is not None 600 601 self._spazzes = spazappearance.get_appearances() 602 self._spazzes.sort() 603 self._icon_textures = [ 604 bui.gettexture(bui.app.classic.spaz_appearances[s].icon_texture) 605 for s in self._spazzes 606 ] 607 self._icon_tint_textures = [ 608 bui.gettexture( 609 bui.app.classic.spaz_appearances[s].icon_mask_texture 610 ) 611 for s in self._spazzes 612 ] 613 614 def on_icon_picker_pick(self, icon: str) -> None: 615 """An icon has been selected by the picker.""" 616 self._icon = icon 617 self._update_icon() 618 619 def on_character_picker_pick(self, character: str) -> None: 620 """A character has been selected by the picker.""" 621 if not self._root_widget: 622 return 623 624 # The player could have bought a new one while the picker was up. 625 self.refresh_characters() 626 self._icon_index = ( 627 self._spazzes.index(character) if character in self._spazzes else 0 628 ) 629 self._update_character() 630 631 def _on_character_press(self) -> None: 632 from bauiv1lib import characterpicker 633 634 characterpicker.CharacterPicker( 635 parent=self._root_widget, 636 position=self._character_button.get_screen_space_center(), 637 selected_character=self._spazzes[self._icon_index], 638 delegate=self, 639 tint_color=self._color, 640 tint2_color=self._highlight, 641 ) 642 643 def _on_icon_press(self) -> None: 644 from bauiv1lib import iconpicker 645 646 iconpicker.IconPicker( 647 parent=self._root_widget, 648 position=self._icon_button.get_screen_space_center(), 649 selected_icon=self._icon, 650 delegate=self, 651 tint_color=self._color, 652 tint2_color=self._highlight, 653 ) 654 655 def _make_picker( 656 self, picker_type: str, origin: tuple[float, float] 657 ) -> None: 658 if picker_type == 'color': 659 initial_color = self._color 660 elif picker_type == 'highlight': 661 initial_color = self._highlight 662 else: 663 raise ValueError('invalid picker_type: ' + picker_type) 664 ColorPicker( 665 parent=self._root_widget, 666 position=origin, 667 offset=( 668 self._base_scale * (-100 if picker_type == 'color' else 100), 669 0, 670 ), 671 initial_color=initial_color, 672 delegate=self, 673 tag=picker_type, 674 ) 675 676 def _cancel(self) -> None: 677 from bauiv1lib.profile.browser import ProfileBrowserWindow 678 679 # no-op if our underlying widget is dead or on its way out. 680 if not self._root_widget or self._root_widget.transitioning_out: 681 return 682 683 bui.containerwidget(edit=self._root_widget, transition='out_right') 684 assert bui.app.classic is not None 685 bui.app.ui_v1.set_main_menu_window( 686 ProfileBrowserWindow( 687 'in_left', 688 selected_profile=self._existing_profile, 689 in_main_menu=self._in_main_menu, 690 ).get_root_widget(), 691 from_window=self._root_widget, 692 ) 693 694 def _set_color(self, color: tuple[float, float, float]) -> None: 695 self._color = color 696 if self._color_button: 697 bui.buttonwidget(edit=self._color_button, color=color) 698 699 def _set_highlight(self, color: tuple[float, float, float]) -> None: 700 self._highlight = color 701 if self._highlight_button: 702 bui.buttonwidget(edit=self._highlight_button, color=color) 703 704 def color_picker_closing(self, picker: ColorPicker) -> None: 705 """Called when a color picker is closing.""" 706 if not self._root_widget: 707 return 708 tag = picker.get_tag() 709 if tag == 'color': 710 bui.containerwidget( 711 edit=self._root_widget, selected_child=self._color_button 712 ) 713 elif tag == 'highlight': 714 bui.containerwidget( 715 edit=self._root_widget, selected_child=self._highlight_button 716 ) 717 else: 718 print('color_picker_closing got unknown tag ' + str(tag)) 719 720 def color_picker_selected_color( 721 self, picker: ColorPicker, color: tuple[float, float, float] 722 ) -> None: 723 """Called when a color is selected in a color picker.""" 724 if not self._root_widget: 725 return 726 tag = picker.get_tag() 727 if tag == 'color': 728 self._set_color(color) 729 elif tag == 'highlight': 730 self._set_highlight(color) 731 else: 732 print('color_picker_selected_color got unknown tag ' + str(tag)) 733 self._update_character() 734 735 def _update_clipped_name(self) -> None: 736 plus = bui.app.plus 737 assert plus is not None 738 739 if not self._clipped_name_text: 740 return 741 name = self.getname() 742 if name == '__account__': 743 name = ( 744 plus.get_v1_account_name() 745 if plus.get_v1_account_state() == 'signed_in' 746 else '???' 747 ) 748 if len(name) > 10 and not (self._global or self._is_account_profile): 749 name = name.strip() 750 display_name = (name[:10] + '...') if len(name) > 10 else name 751 bui.textwidget( 752 edit=self._clipped_name_text, 753 text=bui.Lstr( 754 resource='inGameClippedNameText', 755 subs=[('${NAME}', display_name)], 756 ), 757 ) 758 else: 759 bui.textwidget(edit=self._clipped_name_text, text='') 760 761 def _update_character(self, change: int = 0) -> None: 762 self._icon_index = (self._icon_index + change) % len(self._spazzes) 763 if self._character_button: 764 bui.buttonwidget( 765 edit=self._character_button, 766 texture=self._icon_textures[self._icon_index], 767 tint_texture=self._icon_tint_textures[self._icon_index], 768 tint_color=self._color, 769 tint2_color=self._highlight, 770 ) 771 772 def _update_icon(self) -> None: 773 if self._icon_button_label: 774 bui.textwidget(edit=self._icon_button_label, text=self._icon) 775 776 def getname(self) -> str: 777 """Return the current profile name value.""" 778 if self._is_account_profile: 779 new_name = '__account__' 780 elif self._global: 781 new_name = self._name 782 else: 783 new_name = cast(str, bui.textwidget(query=self._text_field)) 784 return new_name 785 786 def save(self, transition_out: bool = True) -> bool: 787 """Save has been selected.""" 788 from bauiv1lib.profile.browser import ProfileBrowserWindow 789 790 # no-op if our underlying widget is dead or on its way out. 791 if not self._root_widget or self._root_widget.transitioning_out: 792 return False 793 794 plus = bui.app.plus 795 assert plus is not None 796 797 new_name = self.getname().strip() 798 799 if not new_name: 800 bui.screenmessage(bui.Lstr(resource='nameNotEmptyText')) 801 bui.getsound('error').play() 802 return False 803 804 # Make sure we're not renaming to another existing profile. 805 profiles: dict = bui.app.config.get('Player Profiles', {}) 806 if self._existing_profile != new_name and new_name in profiles.keys(): 807 bui.screenmessage( 808 bui.Lstr(resource='editProfileWindow.profileAlreadyExistsText') 809 ) 810 bui.getsound('error').play() 811 return False 812 813 if transition_out: 814 bui.getsound('gunCocking').play() 815 816 # Delete old in case we're renaming. 817 if self._existing_profile and self._existing_profile != new_name: 818 plus.add_v1_account_transaction( 819 { 820 'type': 'REMOVE_PLAYER_PROFILE', 821 'name': self._existing_profile, 822 } 823 ) 824 825 # Also lets be aware we're no longer global if we're taking a 826 # new name (will need to re-request it). 827 self._global = False 828 829 plus.add_v1_account_transaction( 830 { 831 'type': 'ADD_PLAYER_PROFILE', 832 'name': new_name, 833 'profile': { 834 'character': self._spazzes[self._icon_index], 835 'color': list(self._color), 836 'global': self._global, 837 'icon': self._icon, 838 'highlight': list(self._highlight), 839 }, 840 } 841 ) 842 843 if transition_out: 844 plus.run_v1_account_transactions() 845 bui.containerwidget(edit=self._root_widget, transition='out_right') 846 assert bui.app.classic is not None 847 bui.app.ui_v1.set_main_menu_window( 848 ProfileBrowserWindow( 849 'in_left', 850 selected_profile=new_name, 851 in_main_menu=self._in_main_menu, 852 ).get_root_widget(), 853 from_window=self._root_widget, 854 ) 855 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=self._r + '.titleNewText') 115 if existing_profile is None 116 else bui.Lstr(resource=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=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=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=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=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=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=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.GAME_CIRCLE_LOGO, 550 bui.SpecialChar.OUYA_LOGO, 551 bui.SpecialChar.LOCAL_ACCOUNT, 552 bui.SpecialChar.OCULUS_LOGO, 553 bui.SpecialChar.NVIDIA_LOGO, 554 bui.SpecialChar.V2_LOGO, 555 ] 556 ] 557 ) 558 txtl = bui.Lstr( 559 resource='editProfileWindow.accountProfileInfoText', 560 subs=[('${ICONS}', icons_str)], 561 ) 562 ConfirmWindow( 563 txtl, 564 cancel_button=False, 565 width=500, 566 height=300, 567 origin_widget=self._account_type_info_button, 568 ) 569 570 def show_local_profile_info(self) -> None: 571 """Show an explanation of local profiles.""" 572 from bauiv1lib.confirm import ConfirmWindow 573 574 txtl = bui.Lstr(resource='editProfileWindow.localProfileInfoText') 575 ConfirmWindow( 576 txtl, 577 cancel_button=False, 578 width=600, 579 height=250, 580 origin_widget=self._account_type_info_button, 581 ) 582 583 def show_global_profile_info(self) -> None: 584 """Show an explanation of global profiles.""" 585 from bauiv1lib.confirm import ConfirmWindow 586 587 txtl = bui.Lstr(resource='editProfileWindow.globalProfileInfoText') 588 ConfirmWindow( 589 txtl, 590 cancel_button=False, 591 width=600, 592 height=250, 593 origin_widget=self._account_type_info_button, 594 ) 595 596 def refresh_characters(self) -> None: 597 """Refresh available characters/icons.""" 598 from bascenev1lib.actor import spazappearance 599 600 assert bui.app.classic is not None 601 602 self._spazzes = spazappearance.get_appearances() 603 self._spazzes.sort() 604 self._icon_textures = [ 605 bui.gettexture(bui.app.classic.spaz_appearances[s].icon_texture) 606 for s in self._spazzes 607 ] 608 self._icon_tint_textures = [ 609 bui.gettexture( 610 bui.app.classic.spaz_appearances[s].icon_mask_texture 611 ) 612 for s in self._spazzes 613 ] 614 615 def on_icon_picker_pick(self, icon: str) -> None: 616 """An icon has been selected by the picker.""" 617 self._icon = icon 618 self._update_icon() 619 620 def on_character_picker_pick(self, character: str) -> None: 621 """A character has been selected by the picker.""" 622 if not self._root_widget: 623 return 624 625 # The player could have bought a new one while the picker was up. 626 self.refresh_characters() 627 self._icon_index = ( 628 self._spazzes.index(character) if character in self._spazzes else 0 629 ) 630 self._update_character() 631 632 def _on_character_press(self) -> None: 633 from bauiv1lib import characterpicker 634 635 characterpicker.CharacterPicker( 636 parent=self._root_widget, 637 position=self._character_button.get_screen_space_center(), 638 selected_character=self._spazzes[self._icon_index], 639 delegate=self, 640 tint_color=self._color, 641 tint2_color=self._highlight, 642 ) 643 644 def _on_icon_press(self) -> None: 645 from bauiv1lib import iconpicker 646 647 iconpicker.IconPicker( 648 parent=self._root_widget, 649 position=self._icon_button.get_screen_space_center(), 650 selected_icon=self._icon, 651 delegate=self, 652 tint_color=self._color, 653 tint2_color=self._highlight, 654 ) 655 656 def _make_picker( 657 self, picker_type: str, origin: tuple[float, float] 658 ) -> None: 659 if picker_type == 'color': 660 initial_color = self._color 661 elif picker_type == 'highlight': 662 initial_color = self._highlight 663 else: 664 raise ValueError('invalid picker_type: ' + picker_type) 665 ColorPicker( 666 parent=self._root_widget, 667 position=origin, 668 offset=( 669 self._base_scale * (-100 if picker_type == 'color' else 100), 670 0, 671 ), 672 initial_color=initial_color, 673 delegate=self, 674 tag=picker_type, 675 ) 676 677 def _cancel(self) -> None: 678 from bauiv1lib.profile.browser import ProfileBrowserWindow 679 680 # no-op if our underlying widget is dead or on its way out. 681 if not self._root_widget or self._root_widget.transitioning_out: 682 return 683 684 bui.containerwidget(edit=self._root_widget, transition='out_right') 685 assert bui.app.classic is not None 686 bui.app.ui_v1.set_main_menu_window( 687 ProfileBrowserWindow( 688 'in_left', 689 selected_profile=self._existing_profile, 690 in_main_menu=self._in_main_menu, 691 ).get_root_widget(), 692 from_window=self._root_widget, 693 ) 694 695 def _set_color(self, color: tuple[float, float, float]) -> None: 696 self._color = color 697 if self._color_button: 698 bui.buttonwidget(edit=self._color_button, color=color) 699 700 def _set_highlight(self, color: tuple[float, float, float]) -> None: 701 self._highlight = color 702 if self._highlight_button: 703 bui.buttonwidget(edit=self._highlight_button, color=color) 704 705 def color_picker_closing(self, picker: ColorPicker) -> None: 706 """Called when a color picker is closing.""" 707 if not self._root_widget: 708 return 709 tag = picker.get_tag() 710 if tag == 'color': 711 bui.containerwidget( 712 edit=self._root_widget, selected_child=self._color_button 713 ) 714 elif tag == 'highlight': 715 bui.containerwidget( 716 edit=self._root_widget, selected_child=self._highlight_button 717 ) 718 else: 719 print('color_picker_closing got unknown tag ' + str(tag)) 720 721 def color_picker_selected_color( 722 self, picker: ColorPicker, color: tuple[float, float, float] 723 ) -> None: 724 """Called when a color is selected in a color picker.""" 725 if not self._root_widget: 726 return 727 tag = picker.get_tag() 728 if tag == 'color': 729 self._set_color(color) 730 elif tag == 'highlight': 731 self._set_highlight(color) 732 else: 733 print('color_picker_selected_color got unknown tag ' + str(tag)) 734 self._update_character() 735 736 def _update_clipped_name(self) -> None: 737 plus = bui.app.plus 738 assert plus is not None 739 740 if not self._clipped_name_text: 741 return 742 name = self.getname() 743 if name == '__account__': 744 name = ( 745 plus.get_v1_account_name() 746 if plus.get_v1_account_state() == 'signed_in' 747 else '???' 748 ) 749 if len(name) > 10 and not (self._global or self._is_account_profile): 750 name = name.strip() 751 display_name = (name[:10] + '...') if len(name) > 10 else name 752 bui.textwidget( 753 edit=self._clipped_name_text, 754 text=bui.Lstr( 755 resource='inGameClippedNameText', 756 subs=[('${NAME}', display_name)], 757 ), 758 ) 759 else: 760 bui.textwidget(edit=self._clipped_name_text, text='') 761 762 def _update_character(self, change: int = 0) -> None: 763 self._icon_index = (self._icon_index + change) % len(self._spazzes) 764 if self._character_button: 765 bui.buttonwidget( 766 edit=self._character_button, 767 texture=self._icon_textures[self._icon_index], 768 tint_texture=self._icon_tint_textures[self._icon_index], 769 tint_color=self._color, 770 tint2_color=self._highlight, 771 ) 772 773 def _update_icon(self) -> None: 774 if self._icon_button_label: 775 bui.textwidget(edit=self._icon_button_label, text=self._icon) 776 777 def getname(self) -> str: 778 """Return the current profile name value.""" 779 if self._is_account_profile: 780 new_name = '__account__' 781 elif self._global: 782 new_name = self._name 783 else: 784 new_name = cast(str, bui.textwidget(query=self._text_field)) 785 return new_name 786 787 def save(self, transition_out: bool = True) -> bool: 788 """Save has been selected.""" 789 from bauiv1lib.profile.browser import ProfileBrowserWindow 790 791 # no-op if our underlying widget is dead or on its way out. 792 if not self._root_widget or self._root_widget.transitioning_out: 793 return False 794 795 plus = bui.app.plus 796 assert plus is not None 797 798 new_name = self.getname().strip() 799 800 if not new_name: 801 bui.screenmessage(bui.Lstr(resource='nameNotEmptyText')) 802 bui.getsound('error').play() 803 return False 804 805 # Make sure we're not renaming to another existing profile. 806 profiles: dict = bui.app.config.get('Player Profiles', {}) 807 if self._existing_profile != new_name and new_name in profiles.keys(): 808 bui.screenmessage( 809 bui.Lstr(resource='editProfileWindow.profileAlreadyExistsText') 810 ) 811 bui.getsound('error').play() 812 return False 813 814 if transition_out: 815 bui.getsound('gunCocking').play() 816 817 # Delete old in case we're renaming. 818 if self._existing_profile and self._existing_profile != new_name: 819 plus.add_v1_account_transaction( 820 { 821 'type': 'REMOVE_PLAYER_PROFILE', 822 'name': self._existing_profile, 823 } 824 ) 825 826 # Also lets be aware we're no longer global if we're taking a 827 # new name (will need to re-request it). 828 self._global = False 829 830 plus.add_v1_account_transaction( 831 { 832 'type': 'ADD_PLAYER_PROFILE', 833 'name': new_name, 834 'profile': { 835 'character': self._spazzes[self._icon_index], 836 'color': list(self._color), 837 'global': self._global, 838 'icon': self._icon, 839 'highlight': list(self._highlight), 840 }, 841 } 842 ) 843 844 if transition_out: 845 plus.run_v1_account_transactions() 846 bui.containerwidget(edit=self._root_widget, transition='out_right') 847 assert bui.app.classic is not None 848 bui.app.ui_v1.set_main_menu_window( 849 ProfileBrowserWindow( 850 'in_left', 851 selected_profile=new_name, 852 in_main_menu=self._in_main_menu, 853 ).get_root_widget(), 854 from_window=self._root_widget, 855 ) 856 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=self._r + '.titleNewText') 115 if existing_profile is None 116 else bui.Lstr(resource=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=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=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=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=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=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=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.GAME_CIRCLE_LOGO, 550 bui.SpecialChar.OUYA_LOGO, 551 bui.SpecialChar.LOCAL_ACCOUNT, 552 bui.SpecialChar.OCULUS_LOGO, 553 bui.SpecialChar.NVIDIA_LOGO, 554 bui.SpecialChar.V2_LOGO, 555 ] 556 ] 557 ) 558 txtl = bui.Lstr( 559 resource='editProfileWindow.accountProfileInfoText', 560 subs=[('${ICONS}', icons_str)], 561 ) 562 ConfirmWindow( 563 txtl, 564 cancel_button=False, 565 width=500, 566 height=300, 567 origin_widget=self._account_type_info_button, 568 )
Show an explanation of account profiles.
def
show_local_profile_info(self) -> None:
570 def show_local_profile_info(self) -> None: 571 """Show an explanation of local profiles.""" 572 from bauiv1lib.confirm import ConfirmWindow 573 574 txtl = bui.Lstr(resource='editProfileWindow.localProfileInfoText') 575 ConfirmWindow( 576 txtl, 577 cancel_button=False, 578 width=600, 579 height=250, 580 origin_widget=self._account_type_info_button, 581 )
Show an explanation of local profiles.
def
show_global_profile_info(self) -> None:
583 def show_global_profile_info(self) -> None: 584 """Show an explanation of global profiles.""" 585 from bauiv1lib.confirm import ConfirmWindow 586 587 txtl = bui.Lstr(resource='editProfileWindow.globalProfileInfoText') 588 ConfirmWindow( 589 txtl, 590 cancel_button=False, 591 width=600, 592 height=250, 593 origin_widget=self._account_type_info_button, 594 )
Show an explanation of global profiles.
def
refresh_characters(self) -> None:
596 def refresh_characters(self) -> None: 597 """Refresh available characters/icons.""" 598 from bascenev1lib.actor import spazappearance 599 600 assert bui.app.classic is not None 601 602 self._spazzes = spazappearance.get_appearances() 603 self._spazzes.sort() 604 self._icon_textures = [ 605 bui.gettexture(bui.app.classic.spaz_appearances[s].icon_texture) 606 for s in self._spazzes 607 ] 608 self._icon_tint_textures = [ 609 bui.gettexture( 610 bui.app.classic.spaz_appearances[s].icon_mask_texture 611 ) 612 for s in self._spazzes 613 ]
Refresh available characters/icons.
def
on_icon_picker_pick(self, icon: str) -> None:
615 def on_icon_picker_pick(self, icon: str) -> None: 616 """An icon has been selected by the picker.""" 617 self._icon = icon 618 self._update_icon()
An icon has been selected by the picker.
def
on_character_picker_pick(self, character: str) -> None:
620 def on_character_picker_pick(self, character: str) -> None: 621 """A character has been selected by the picker.""" 622 if not self._root_widget: 623 return 624 625 # The player could have bought a new one while the picker was up. 626 self.refresh_characters() 627 self._icon_index = ( 628 self._spazzes.index(character) if character in self._spazzes else 0 629 ) 630 self._update_character()
A character has been selected by the picker.
705 def color_picker_closing(self, picker: ColorPicker) -> None: 706 """Called when a color picker is closing.""" 707 if not self._root_widget: 708 return 709 tag = picker.get_tag() 710 if tag == 'color': 711 bui.containerwidget( 712 edit=self._root_widget, selected_child=self._color_button 713 ) 714 elif tag == 'highlight': 715 bui.containerwidget( 716 edit=self._root_widget, selected_child=self._highlight_button 717 ) 718 else: 719 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:
721 def color_picker_selected_color( 722 self, picker: ColorPicker, color: tuple[float, float, float] 723 ) -> None: 724 """Called when a color is selected in a color picker.""" 725 if not self._root_widget: 726 return 727 tag = picker.get_tag() 728 if tag == 'color': 729 self._set_color(color) 730 elif tag == 'highlight': 731 self._set_highlight(color) 732 else: 733 print('color_picker_selected_color got unknown tag ' + str(tag)) 734 self._update_character()
Called when a color is selected in a color picker.
def
getname(self) -> str:
777 def getname(self) -> str: 778 """Return the current profile name value.""" 779 if self._is_account_profile: 780 new_name = '__account__' 781 elif self._global: 782 new_name = self._name 783 else: 784 new_name = cast(str, bui.textwidget(query=self._text_field)) 785 return new_name
Return the current profile name value.
def
save(self, transition_out: bool = True) -> bool:
787 def save(self, transition_out: bool = True) -> bool: 788 """Save has been selected.""" 789 from bauiv1lib.profile.browser import ProfileBrowserWindow 790 791 # no-op if our underlying widget is dead or on its way out. 792 if not self._root_widget or self._root_widget.transitioning_out: 793 return False 794 795 plus = bui.app.plus 796 assert plus is not None 797 798 new_name = self.getname().strip() 799 800 if not new_name: 801 bui.screenmessage(bui.Lstr(resource='nameNotEmptyText')) 802 bui.getsound('error').play() 803 return False 804 805 # Make sure we're not renaming to another existing profile. 806 profiles: dict = bui.app.config.get('Player Profiles', {}) 807 if self._existing_profile != new_name and new_name in profiles.keys(): 808 bui.screenmessage( 809 bui.Lstr(resource='editProfileWindow.profileAlreadyExistsText') 810 ) 811 bui.getsound('error').play() 812 return False 813 814 if transition_out: 815 bui.getsound('gunCocking').play() 816 817 # Delete old in case we're renaming. 818 if self._existing_profile and self._existing_profile != new_name: 819 plus.add_v1_account_transaction( 820 { 821 'type': 'REMOVE_PLAYER_PROFILE', 822 'name': self._existing_profile, 823 } 824 ) 825 826 # Also lets be aware we're no longer global if we're taking a 827 # new name (will need to re-request it). 828 self._global = False 829 830 plus.add_v1_account_transaction( 831 { 832 'type': 'ADD_PLAYER_PROFILE', 833 'name': new_name, 834 'profile': { 835 'character': self._spazzes[self._icon_index], 836 'color': list(self._color), 837 'global': self._global, 838 'icon': self._icon, 839 'highlight': list(self._highlight), 840 }, 841 } 842 ) 843 844 if transition_out: 845 plus.run_v1_account_transactions() 846 bui.containerwidget(edit=self._root_widget, transition='out_right') 847 assert bui.app.classic is not None 848 bui.app.ui_v1.set_main_menu_window( 849 ProfileBrowserWindow( 850 'in_left', 851 selected_profile=new_name, 852 in_main_menu=self._in_main_menu, 853 ).get_root_widget(), 854 from_window=self._root_widget, 855 ) 856 return True
Save has been selected.
Inherited Members
- bauiv1._uitypes.Window
- get_root_widget