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

Window for editing a player profile.

EditProfileWindow( existing_profile: str | None, in_main_menu: bool, transition: str = 'in_right')
 30    def __init__(
 31        self,
 32        existing_profile: str | None,
 33        in_main_menu: bool,
 34        transition: str = 'in_right',
 35    ):
 36        # FIXME: Tidy this up a bit.
 37        # pylint: disable=too-many-branches
 38        # pylint: disable=too-many-statements
 39        # pylint: disable=too-many-locals
 40        assert bui.app.classic is not None
 41
 42        plus = bui.app.plus
 43        assert plus is not None
 44
 45        self._in_main_menu = in_main_menu
 46        self._existing_profile = existing_profile
 47        self._r = 'editProfileWindow'
 48        self._spazzes: list[str] = []
 49        self._icon_textures: list[bui.Texture] = []
 50        self._icon_tint_textures: list[bui.Texture] = []
 51
 52        # Grab profile colors or pick random ones.
 53        (
 54            self._color,
 55            self._highlight,
 56        ) = bui.app.classic.get_player_profile_colors(existing_profile)
 57        uiscale = bui.app.ui_v1.uiscale
 58        self._width = width = 780.0 if uiscale is bui.UIScale.SMALL else 680.0
 59        self._x_inset = x_inset = 50.0 if uiscale is bui.UIScale.SMALL else 0.0
 60        self._height = height = (
 61            350.0
 62            if uiscale is bui.UIScale.SMALL
 63            else 400.0
 64            if uiscale is bui.UIScale.MEDIUM
 65            else 450.0
 66        )
 67        spacing = 40
 68        self._base_scale = (
 69            2.05
 70            if uiscale is bui.UIScale.SMALL
 71            else 1.5
 72            if uiscale is bui.UIScale.MEDIUM
 73            else 1.0
 74        )
 75        top_extra = 15 if uiscale is bui.UIScale.SMALL else 15
 76        super().__init__(
 77            root_widget=bui.containerwidget(
 78                size=(width, height + top_extra),
 79                transition=transition,
 80                scale=self._base_scale,
 81                stack_offset=(0, 15)
 82                if uiscale is bui.UIScale.SMALL
 83                else (0, 0),
 84            )
 85        )
 86        cancel_button = btn = bui.buttonwidget(
 87            parent=self._root_widget,
 88            position=(52 + x_inset, height - 60),
 89            size=(155, 60),
 90            scale=0.8,
 91            autoselect=True,
 92            label=bui.Lstr(resource='cancelText'),
 93            on_activate_call=self._cancel,
 94        )
 95        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 96        save_button = btn = bui.buttonwidget(
 97            parent=self._root_widget,
 98            position=(width - (177 + x_inset), height - 60),
 99            size=(155, 60),
100            autoselect=True,
101            scale=0.8,
102            label=bui.Lstr(resource='saveText'),
103        )
104        bui.widget(edit=save_button, left_widget=cancel_button)
105        bui.widget(edit=cancel_button, right_widget=save_button)
106        bui.containerwidget(edit=self._root_widget, start_button=btn)
107        bui.textwidget(
108            parent=self._root_widget,
109            position=(self._width * 0.5, height - 38),
110            size=(0, 0),
111            text=(
112                bui.Lstr(resource=self._r + '.titleNewText')
113                if existing_profile is None
114                else bui.Lstr(resource=self._r + '.titleEditText')
115            ),
116            color=bui.app.ui_v1.title_color,
117            maxwidth=290,
118            scale=1.0,
119            h_align='center',
120            v_align='center',
121        )
122
123        # Make a list of spaz icons.
124        self.refresh_characters()
125        profile = bui.app.config.get('Player Profiles', {}).get(
126            self._existing_profile, {}
127        )
128
129        if 'global' in profile:
130            self._global = profile['global']
131        else:
132            self._global = False
133
134        if 'icon' in profile:
135            self._icon = profile['icon']
136        else:
137            self._icon = bui.charstr(bui.SpecialChar.LOGO)
138
139        assigned_random_char = False
140
141        # Look for existing character choice or pick random one otherwise.
142        try:
143            icon_index = self._spazzes.index(profile['character'])
144        except Exception:
145            # Let's set the default icon to spaz for our first profile; after
146            # that we go random.
147            # (SCRATCH THAT.. we now hard-code account-profiles to start with
148            # spaz which has a similar effect)
149            # try: p_len = len(bui.app.config['Player Profiles'])
150            # except Exception: p_len = 0
151            # if p_len == 0: icon_index = self._spazzes.index('Spaz')
152            # else:
153            random.seed()
154            icon_index = random.randrange(len(self._spazzes))
155            assigned_random_char = True
156        self._icon_index = icon_index
157        bui.buttonwidget(edit=save_button, on_activate_call=self.save)
158
159        v = height - 115.0
160        self._name = (
161            '' if self._existing_profile is None else self._existing_profile
162        )
163        self._is_account_profile = self._name == '__account__'
164
165        # If we just picked a random character, see if it has specific
166        # colors/highlights associated with it and assign them if so.
167        if assigned_random_char:
168            assert bui.app.classic is not None
169            clr = bui.app.classic.spaz_appearances[
170                self._spazzes[icon_index]
171            ].default_color
172            if clr is not None:
173                self._color = clr
174            highlight = bui.app.classic.spaz_appearances[
175                self._spazzes[icon_index]
176            ].default_highlight
177            if highlight is not None:
178                self._highlight = highlight
179
180        # Assign a random name if they had none.
181        if self._name == '':
182            names = bs.get_random_names()
183            self._name = names[random.randrange(len(names))]
184
185        self._clipped_name_text = bui.textwidget(
186            parent=self._root_widget,
187            text='',
188            position=(540 + x_inset, v - 8),
189            flatness=1.0,
190            shadow=0.0,
191            scale=0.55,
192            size=(0, 0),
193            maxwidth=100,
194            h_align='center',
195            v_align='center',
196            color=(1, 1, 0, 0.5),
197        )
198
199        if not self._is_account_profile and not self._global:
200            bui.textwidget(
201                parent=self._root_widget,
202                text=bui.Lstr(resource=self._r + '.nameText'),
203                position=(200 + x_inset, v - 6),
204                size=(0, 0),
205                h_align='right',
206                v_align='center',
207                color=(1, 1, 1, 0.5),
208                scale=0.9,
209            )
210
211        self._upgrade_button = None
212        if self._is_account_profile:
213            if plus.get_v1_account_state() == 'signed_in':
214                sval = plus.get_v1_account_display_string()
215            else:
216                sval = '??'
217            bui.textwidget(
218                parent=self._root_widget,
219                position=(self._width * 0.5, v - 7),
220                size=(0, 0),
221                scale=1.2,
222                text=sval,
223                maxwidth=270,
224                h_align='center',
225                v_align='center',
226            )
227            txtl = bui.Lstr(
228                resource='editProfileWindow.accountProfileText'
229            ).evaluate()
230            b_width = min(
231                270.0,
232                bui.get_string_width(txtl, suppress_warning=True) * 0.6,
233            )
234            bui.textwidget(
235                parent=self._root_widget,
236                position=(self._width * 0.5, v - 39),
237                size=(0, 0),
238                scale=0.6,
239                color=bui.app.ui_v1.infotextcolor,
240                text=txtl,
241                maxwidth=270,
242                h_align='center',
243                v_align='center',
244            )
245            self._account_type_info_button = bui.buttonwidget(
246                parent=self._root_widget,
247                label='?',
248                size=(15, 15),
249                text_scale=0.6,
250                position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47),
251                button_type='square',
252                color=(0.6, 0.5, 0.65),
253                autoselect=True,
254                on_activate_call=self.show_account_profile_info,
255            )
256        elif self._global:
257            b_size = 60
258            self._icon_button = btn = bui.buttonwidget(
259                parent=self._root_widget,
260                autoselect=True,
261                position=(self._width * 0.5 - 160 - b_size * 0.5, v - 38 - 15),
262                size=(b_size, b_size),
263                color=(0.6, 0.5, 0.6),
264                label='',
265                button_type='square',
266                text_scale=1.2,
267                on_activate_call=self._on_icon_press,
268            )
269            self._icon_button_label = bui.textwidget(
270                parent=self._root_widget,
271                position=(self._width * 0.5 - 160, v - 35),
272                draw_controller=btn,
273                h_align='center',
274                v_align='center',
275                size=(0, 0),
276                color=(1, 1, 1),
277                text='',
278                scale=2.0,
279            )
280
281            bui.textwidget(
282                parent=self._root_widget,
283                h_align='center',
284                v_align='center',
285                position=(self._width * 0.5 - 160, v - 55 - 15),
286                size=(0, 0),
287                draw_controller=btn,
288                text=bui.Lstr(resource=self._r + '.iconText'),
289                scale=0.7,
290                color=bui.app.ui_v1.title_color,
291                maxwidth=120,
292            )
293
294            self._update_icon()
295
296            bui.textwidget(
297                parent=self._root_widget,
298                position=(self._width * 0.5, v - 7),
299                size=(0, 0),
300                scale=1.2,
301                text=self._name,
302                maxwidth=240,
303                h_align='center',
304                v_align='center',
305            )
306            # FIXME hard coded strings are bad
307            txtl = bui.Lstr(
308                resource='editProfileWindow.globalProfileText'
309            ).evaluate()
310            b_width = min(
311                240.0,
312                bui.get_string_width(txtl, suppress_warning=True) * 0.6,
313            )
314            bui.textwidget(
315                parent=self._root_widget,
316                position=(self._width * 0.5, v - 39),
317                size=(0, 0),
318                scale=0.6,
319                color=bui.app.ui_v1.infotextcolor,
320                text=txtl,
321                maxwidth=240,
322                h_align='center',
323                v_align='center',
324            )
325            self._account_type_info_button = bui.buttonwidget(
326                parent=self._root_widget,
327                label='?',
328                size=(15, 15),
329                text_scale=0.6,
330                position=(self._width * 0.5 + b_width * 0.5 + 13, v - 47),
331                button_type='square',
332                color=(0.6, 0.5, 0.65),
333                autoselect=True,
334                on_activate_call=self.show_global_profile_info,
335            )
336        else:
337            self._text_field = bui.textwidget(
338                parent=self._root_widget,
339                position=(220 + x_inset, v - 30),
340                size=(265, 40),
341                text=self._name,
342                h_align='left',
343                v_align='center',
344                max_chars=16,
345                description=bui.Lstr(resource=self._r + '.nameDescriptionText'),
346                autoselect=True,
347                editable=True,
348                padding=4,
349                color=(0.9, 0.9, 0.9, 1.0),
350                on_return_press_call=bui.Call(save_button.activate),
351            )
352
353            # FIXME hard coded strings are bad
354            txtl = bui.Lstr(
355                resource='editProfileWindow.localProfileText'
356            ).evaluate()
357            b_width = min(
358                270.0,
359                bui.get_string_width(txtl, suppress_warning=True) * 0.6,
360            )
361            bui.textwidget(
362                parent=self._root_widget,
363                position=(self._width * 0.5, v - 43),
364                size=(0, 0),
365                scale=0.6,
366                color=bui.app.ui_v1.infotextcolor,
367                text=txtl,
368                maxwidth=270,
369                h_align='center',
370                v_align='center',
371            )
372            self._account_type_info_button = bui.buttonwidget(
373                parent=self._root_widget,
374                label='?',
375                size=(15, 15),
376                text_scale=0.6,
377                position=(self._width * 0.5 + b_width * 0.5 + 13, v - 50),
378                button_type='square',
379                color=(0.6, 0.5, 0.65),
380                autoselect=True,
381                on_activate_call=self.show_local_profile_info,
382            )
383            self._upgrade_button = bui.buttonwidget(
384                parent=self._root_widget,
385                label=bui.Lstr(resource='upgradeText'),
386                size=(40, 17),
387                text_scale=1.0,
388                button_type='square',
389                position=(self._width * 0.5 + b_width * 0.5 + 13 + 43, v - 51),
390                color=(0.6, 0.5, 0.65),
391                autoselect=True,
392                on_activate_call=self.upgrade_profile,
393            )
394
395        self._update_clipped_name()
396        self._clipped_name_timer = bui.AppTimer(
397            0.333, bui.WeakCall(self._update_clipped_name), repeat=True
398        )
399
400        v -= spacing * 3.0
401        b_size = 80
402        b_size_2 = 100
403        b_offs = 150
404        self._color_button = btn = bui.buttonwidget(
405            parent=self._root_widget,
406            autoselect=True,
407            position=(self._width * 0.5 - b_offs - b_size * 0.5, v - 50),
408            size=(b_size, b_size),
409            color=self._color,
410            label='',
411            button_type='square',
412        )
413        origin = self._color_button.get_screen_space_center()
414        bui.buttonwidget(
415            edit=self._color_button,
416            on_activate_call=bui.WeakCall(self._make_picker, 'color', origin),
417        )
418        bui.textwidget(
419            parent=self._root_widget,
420            h_align='center',
421            v_align='center',
422            position=(self._width * 0.5 - b_offs, v - 65),
423            size=(0, 0),
424            draw_controller=btn,
425            text=bui.Lstr(resource=self._r + '.colorText'),
426            scale=0.7,
427            color=bui.app.ui_v1.title_color,
428            maxwidth=120,
429        )
430
431        self._character_button = btn = bui.buttonwidget(
432            parent=self._root_widget,
433            autoselect=True,
434            position=(self._width * 0.5 - b_size_2 * 0.5, v - 60),
435            up_widget=self._account_type_info_button,
436            on_activate_call=self._on_character_press,
437            size=(b_size_2, b_size_2),
438            label='',
439            color=(1, 1, 1),
440            mask_texture=bui.gettexture('characterIconMask'),
441        )
442        if not self._is_account_profile and not self._global:
443            bui.containerwidget(
444                edit=self._root_widget, selected_child=self._text_field
445            )
446        bui.textwidget(
447            parent=self._root_widget,
448            h_align='center',
449            v_align='center',
450            position=(self._width * 0.5, v - 80),
451            size=(0, 0),
452            draw_controller=btn,
453            text=bui.Lstr(resource=self._r + '.characterText'),
454            scale=0.7,
455            color=bui.app.ui_v1.title_color,
456            maxwidth=130,
457        )
458
459        self._highlight_button = btn = bui.buttonwidget(
460            parent=self._root_widget,
461            autoselect=True,
462            position=(self._width * 0.5 + b_offs - b_size * 0.5, v - 50),
463            up_widget=self._upgrade_button
464            if self._upgrade_button is not None
465            else self._account_type_info_button,
466            size=(b_size, b_size),
467            color=self._highlight,
468            label='',
469            button_type='square',
470        )
471
472        if not self._is_account_profile and not self._global:
473            bui.widget(edit=cancel_button, down_widget=self._text_field)
474            bui.widget(edit=save_button, down_widget=self._text_field)
475            bui.widget(edit=self._color_button, up_widget=self._text_field)
476        bui.widget(
477            edit=self._account_type_info_button,
478            down_widget=self._character_button,
479        )
480
481        origin = self._highlight_button.get_screen_space_center()
482        bui.buttonwidget(
483            edit=self._highlight_button,
484            on_activate_call=bui.WeakCall(
485                self._make_picker, 'highlight', origin
486            ),
487        )
488        bui.textwidget(
489            parent=self._root_widget,
490            h_align='center',
491            v_align='center',
492            position=(self._width * 0.5 + b_offs, v - 65),
493            size=(0, 0),
494            draw_controller=btn,
495            text=bui.Lstr(resource=self._r + '.highlightText'),
496            scale=0.7,
497            color=bui.app.ui_v1.title_color,
498            maxwidth=120,
499        )
500        self._update_character()
def reload_window(self) -> None:
20    def reload_window(self) -> None:
21        """Transitions out and recreates ourself."""
22        bui.containerwidget(edit=self._root_widget, transition='out_left')
23        assert bui.app.classic is not None
24        bui.app.ui_v1.set_main_menu_window(
25            EditProfileWindow(
26                self.getname(), self._in_main_menu
27            ).get_root_widget()
28        )

Transitions out and recreates ourself.

def upgrade_profile(self) -> None:
502    def upgrade_profile(self) -> None:
503        """Attempt to ugrade the profile to global."""
504        from bauiv1lib import account
505        from bauiv1lib.profile import upgrade as pupgrade
506
507        plus = bui.app.plus
508        assert plus is not None
509
510        if plus.get_v1_account_state() != 'signed_in':
511            account.show_sign_in_prompt()
512            return
513
514        pupgrade.ProfileUpgradeWindow(self)

Attempt to ugrade the profile to global.

def show_account_profile_info(self) -> None:
516    def show_account_profile_info(self) -> None:
517        """Show an explanation of account profiles."""
518        from bauiv1lib.confirm import ConfirmWindow
519
520        icons_str = ' '.join(
521            [
522                bui.charstr(n)
523                for n in [
524                    bui.SpecialChar.GOOGLE_PLAY_GAMES_LOGO,
525                    bui.SpecialChar.GAME_CENTER_LOGO,
526                    bui.SpecialChar.GAME_CIRCLE_LOGO,
527                    bui.SpecialChar.OUYA_LOGO,
528                    bui.SpecialChar.LOCAL_ACCOUNT,
529                    bui.SpecialChar.OCULUS_LOGO,
530                    bui.SpecialChar.NVIDIA_LOGO,
531                    bui.SpecialChar.V2_LOGO,
532                ]
533            ]
534        )
535        txtl = bui.Lstr(
536            resource='editProfileWindow.accountProfileInfoText',
537            subs=[('${ICONS}', icons_str)],
538        )
539        ConfirmWindow(
540            txtl,
541            cancel_button=False,
542            width=500,
543            height=300,
544            origin_widget=self._account_type_info_button,
545        )

Show an explanation of account profiles.

def show_local_profile_info(self) -> None:
547    def show_local_profile_info(self) -> None:
548        """Show an explanation of local profiles."""
549        from bauiv1lib.confirm import ConfirmWindow
550
551        txtl = bui.Lstr(resource='editProfileWindow.localProfileInfoText')
552        ConfirmWindow(
553            txtl,
554            cancel_button=False,
555            width=600,
556            height=250,
557            origin_widget=self._account_type_info_button,
558        )

Show an explanation of local profiles.

def show_global_profile_info(self) -> None:
560    def show_global_profile_info(self) -> None:
561        """Show an explanation of global profiles."""
562        from bauiv1lib.confirm import ConfirmWindow
563
564        txtl = bui.Lstr(resource='editProfileWindow.globalProfileInfoText')
565        ConfirmWindow(
566            txtl,
567            cancel_button=False,
568            width=600,
569            height=250,
570            origin_widget=self._account_type_info_button,
571        )

Show an explanation of global profiles.

def refresh_characters(self) -> None:
573    def refresh_characters(self) -> None:
574        """Refresh available characters/icons."""
575        from bascenev1lib.actor import spazappearance
576
577        assert bui.app.classic is not None
578
579        self._spazzes = spazappearance.get_appearances()
580        self._spazzes.sort()
581        self._icon_textures = [
582            bui.gettexture(bui.app.classic.spaz_appearances[s].icon_texture)
583            for s in self._spazzes
584        ]
585        self._icon_tint_textures = [
586            bui.gettexture(
587                bui.app.classic.spaz_appearances[s].icon_mask_texture
588            )
589            for s in self._spazzes
590        ]

Refresh available characters/icons.

def on_icon_picker_pick(self, icon: str) -> None:
592    def on_icon_picker_pick(self, icon: str) -> None:
593        """An icon has been selected by the picker."""
594        self._icon = icon
595        self._update_icon()

An icon has been selected by the picker.

def on_character_picker_pick(self, character: str) -> None:
597    def on_character_picker_pick(self, character: str) -> None:
598        """A character has been selected by the picker."""
599        if not self._root_widget:
600            return
601
602        # The player could have bought a new one while the picker was up.
603        self.refresh_characters()
604        self._icon_index = (
605            self._spazzes.index(character) if character in self._spazzes else 0
606        )
607        self._update_character()

A character has been selected by the picker.

def color_picker_closing(self, picker: bauiv1lib.colorpicker.ColorPicker) -> None:
677    def color_picker_closing(self, picker: ColorPicker) -> None:
678        """Called when a color picker is closing."""
679        if not self._root_widget:
680            return
681        tag = picker.get_tag()
682        if tag == 'color':
683            bui.containerwidget(
684                edit=self._root_widget, selected_child=self._color_button
685            )
686        elif tag == 'highlight':
687            bui.containerwidget(
688                edit=self._root_widget, selected_child=self._highlight_button
689            )
690        else:
691            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:
693    def color_picker_selected_color(
694        self, picker: ColorPicker, color: tuple[float, float, float]
695    ) -> None:
696        """Called when a color is selected in a color picker."""
697        if not self._root_widget:
698            return
699        tag = picker.get_tag()
700        if tag == 'color':
701            self._set_color(color)
702        elif tag == 'highlight':
703            self._set_highlight(color)
704        else:
705            print('color_picker_selected_color got unknown tag ' + str(tag))
706        self._update_character()

Called when a color is selected in a color picker.

def getname(self) -> str:
749    def getname(self) -> str:
750        """Return the current profile name value."""
751        if self._is_account_profile:
752            new_name = '__account__'
753        elif self._global:
754            new_name = self._name
755        else:
756            new_name = cast(str, bui.textwidget(query=self._text_field))
757        return new_name

Return the current profile name value.

def save(self, transition_out: bool = True) -> bool:
759    def save(self, transition_out: bool = True) -> bool:
760        """Save has been selected."""
761        from bauiv1lib.profile.browser import ProfileBrowserWindow
762
763        plus = bui.app.plus
764        assert plus is not None
765
766        new_name = self.getname().strip()
767
768        if not new_name:
769            bui.screenmessage(bui.Lstr(resource='nameNotEmptyText'))
770            bui.getsound('error').play()
771            return False
772
773        if transition_out:
774            bui.getsound('gunCocking').play()
775
776        # Delete old in case we're renaming.
777        if self._existing_profile and self._existing_profile != new_name:
778            plus.add_v1_account_transaction(
779                {
780                    'type': 'REMOVE_PLAYER_PROFILE',
781                    'name': self._existing_profile,
782                }
783            )
784
785            # Also lets be aware we're no longer global if we're taking a
786            # new name (will need to re-request it).
787            self._global = False
788
789        plus.add_v1_account_transaction(
790            {
791                'type': 'ADD_PLAYER_PROFILE',
792                'name': new_name,
793                'profile': {
794                    'character': self._spazzes[self._icon_index],
795                    'color': list(self._color),
796                    'global': self._global,
797                    'icon': self._icon,
798                    'highlight': list(self._highlight),
799                },
800            }
801        )
802
803        if transition_out:
804            plus.run_v1_account_transactions()
805            bui.containerwidget(edit=self._root_widget, transition='out_right')
806            assert bui.app.classic is not None
807            bui.app.ui_v1.set_main_menu_window(
808                ProfileBrowserWindow(
809                    'in_left',
810                    selected_profile=new_name,
811                    in_main_menu=self._in_main_menu,
812                ).get_root_widget()
813            )
814        return True

Save has been selected.

Inherited Members
bauiv1._uitypes.Window
get_root_widget