bastd.ui.characterpicker
Provides a picker for characters.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides a picker for characters.""" 4 5from __future__ import annotations 6 7import math 8from typing import TYPE_CHECKING 9 10import _ba 11import ba 12from bastd.ui import popup 13 14if TYPE_CHECKING: 15 from typing import Any, Sequence 16 17 18class CharacterPicker(popup.PopupWindow): 19 """Popup window for selecting characters.""" 20 21 def __init__(self, 22 parent: ba.Widget, 23 position: tuple[float, float] = (0.0, 0.0), 24 delegate: Any = None, 25 scale: float | None = None, 26 offset: tuple[float, float] = (0.0, 0.0), 27 tint_color: Sequence[float] = (1.0, 1.0, 1.0), 28 tint2_color: Sequence[float] = (1.0, 1.0, 1.0), 29 selected_character: str | None = None): 30 # pylint: disable=too-many-locals 31 from bastd.actor import spazappearance 32 del parent # unused here 33 uiscale = ba.app.ui.uiscale 34 if scale is None: 35 scale = (1.85 if uiscale is ba.UIScale.SMALL else 36 1.65 if uiscale is ba.UIScale.MEDIUM else 1.23) 37 38 self._delegate = delegate 39 self._transitioning_out = False 40 41 # make a list of spaz icons 42 self._spazzes = spazappearance.get_appearances() 43 self._spazzes.sort() 44 self._icon_textures = [ 45 ba.gettexture(ba.app.spaz_appearances[s].icon_texture) 46 for s in self._spazzes 47 ] 48 self._icon_tint_textures = [ 49 ba.gettexture(ba.app.spaz_appearances[s].icon_mask_texture) 50 for s in self._spazzes 51 ] 52 53 count = len(self._spazzes) 54 55 columns = 3 56 rows = int(math.ceil(float(count) / columns)) 57 58 button_width = 100 59 button_height = 100 60 button_buffer_h = 10 61 button_buffer_v = 15 62 63 self._width = (10 + columns * (button_width + 2 * button_buffer_h) * 64 (1.0 / 0.95) * (1.0 / 0.8)) 65 self._height = self._width * (0.8 66 if uiscale is ba.UIScale.SMALL else 1.06) 67 68 self._scroll_width = self._width * 0.8 69 self._scroll_height = self._height * 0.8 70 self._scroll_position = ((self._width - self._scroll_width) * 0.5, 71 (self._height - self._scroll_height) * 0.5) 72 73 # creates our _root_widget 74 popup.PopupWindow.__init__(self, 75 position=position, 76 size=(self._width, self._height), 77 scale=scale, 78 bg_color=(0.5, 0.5, 0.5), 79 offset=offset, 80 focus_position=self._scroll_position, 81 focus_size=(self._scroll_width, 82 self._scroll_height)) 83 84 self._scrollwidget = ba.scrollwidget(parent=self.root_widget, 85 size=(self._scroll_width, 86 self._scroll_height), 87 color=(0.55, 0.55, 0.55), 88 highlight=False, 89 position=self._scroll_position) 90 ba.containerwidget(edit=self._scrollwidget, claims_left_right=True) 91 92 self._sub_width = self._scroll_width * 0.95 93 self._sub_height = 5 + rows * (button_height + 94 2 * button_buffer_v) + 100 95 self._subcontainer = ba.containerwidget(parent=self._scrollwidget, 96 size=(self._sub_width, 97 self._sub_height), 98 background=False) 99 index = 0 100 mask_texture = ba.gettexture('characterIconMask') 101 for y in range(rows): 102 for x in range(columns): 103 pos = (x * (button_width + 2 * button_buffer_h) + 104 button_buffer_h, self._sub_height - (y + 1) * 105 (button_height + 2 * button_buffer_v) + 12) 106 btn = ba.buttonwidget( 107 parent=self._subcontainer, 108 button_type='square', 109 size=(button_width, button_height), 110 autoselect=True, 111 texture=self._icon_textures[index], 112 tint_texture=self._icon_tint_textures[index], 113 mask_texture=mask_texture, 114 label='', 115 color=(1, 1, 1), 116 tint_color=tint_color, 117 tint2_color=tint2_color, 118 on_activate_call=ba.Call(self._select_character, 119 self._spazzes[index]), 120 position=pos) 121 ba.widget(edit=btn, show_buffer_top=60, show_buffer_bottom=60) 122 if self._spazzes[index] == selected_character: 123 ba.containerwidget(edit=self._subcontainer, 124 selected_child=btn, 125 visible_child=btn) 126 name = ba.Lstr(translate=('characterNames', 127 self._spazzes[index])) 128 ba.textwidget(parent=self._subcontainer, 129 text=name, 130 position=(pos[0] + button_width * 0.5, 131 pos[1] - 12), 132 size=(0, 0), 133 scale=0.5, 134 maxwidth=button_width, 135 draw_controller=btn, 136 h_align='center', 137 v_align='center', 138 color=(0.8, 0.8, 0.8, 0.8)) 139 index += 1 140 141 if index >= count: 142 break 143 if index >= count: 144 break 145 self._get_more_characters_button = btn = ba.buttonwidget( 146 parent=self._subcontainer, 147 size=(self._sub_width * 0.8, 60), 148 position=(self._sub_width * 0.1, 30), 149 label=ba.Lstr(resource='editProfileWindow.getMoreCharactersText'), 150 on_activate_call=self._on_store_press, 151 color=(0.6, 0.6, 0.6), 152 textcolor=(0.8, 0.8, 0.8), 153 autoselect=True) 154 ba.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30) 155 156 def _on_store_press(self) -> None: 157 from bastd.ui.account import show_sign_in_prompt 158 from bastd.ui.store.browser import StoreBrowserWindow 159 if _ba.get_v1_account_state() != 'signed_in': 160 show_sign_in_prompt() 161 return 162 self._transition_out() 163 StoreBrowserWindow(modal=True, 164 show_tab=StoreBrowserWindow.TabID.CHARACTERS, 165 origin_widget=self._get_more_characters_button) 166 167 def _select_character(self, character: str) -> None: 168 if self._delegate is not None: 169 self._delegate.on_character_picker_pick(character) 170 self._transition_out() 171 172 def _transition_out(self) -> None: 173 if not self._transitioning_out: 174 self._transitioning_out = True 175 ba.containerwidget(edit=self.root_widget, transition='out_scale') 176 177 def on_popup_cancel(self) -> None: 178 ba.playsound(ba.getsound('swish')) 179 self._transition_out()
19class CharacterPicker(popup.PopupWindow): 20 """Popup window for selecting characters.""" 21 22 def __init__(self, 23 parent: ba.Widget, 24 position: tuple[float, float] = (0.0, 0.0), 25 delegate: Any = None, 26 scale: float | None = None, 27 offset: tuple[float, float] = (0.0, 0.0), 28 tint_color: Sequence[float] = (1.0, 1.0, 1.0), 29 tint2_color: Sequence[float] = (1.0, 1.0, 1.0), 30 selected_character: str | None = None): 31 # pylint: disable=too-many-locals 32 from bastd.actor import spazappearance 33 del parent # unused here 34 uiscale = ba.app.ui.uiscale 35 if scale is None: 36 scale = (1.85 if uiscale is ba.UIScale.SMALL else 37 1.65 if uiscale is ba.UIScale.MEDIUM else 1.23) 38 39 self._delegate = delegate 40 self._transitioning_out = False 41 42 # make a list of spaz icons 43 self._spazzes = spazappearance.get_appearances() 44 self._spazzes.sort() 45 self._icon_textures = [ 46 ba.gettexture(ba.app.spaz_appearances[s].icon_texture) 47 for s in self._spazzes 48 ] 49 self._icon_tint_textures = [ 50 ba.gettexture(ba.app.spaz_appearances[s].icon_mask_texture) 51 for s in self._spazzes 52 ] 53 54 count = len(self._spazzes) 55 56 columns = 3 57 rows = int(math.ceil(float(count) / columns)) 58 59 button_width = 100 60 button_height = 100 61 button_buffer_h = 10 62 button_buffer_v = 15 63 64 self._width = (10 + columns * (button_width + 2 * button_buffer_h) * 65 (1.0 / 0.95) * (1.0 / 0.8)) 66 self._height = self._width * (0.8 67 if uiscale is ba.UIScale.SMALL else 1.06) 68 69 self._scroll_width = self._width * 0.8 70 self._scroll_height = self._height * 0.8 71 self._scroll_position = ((self._width - self._scroll_width) * 0.5, 72 (self._height - self._scroll_height) * 0.5) 73 74 # creates our _root_widget 75 popup.PopupWindow.__init__(self, 76 position=position, 77 size=(self._width, self._height), 78 scale=scale, 79 bg_color=(0.5, 0.5, 0.5), 80 offset=offset, 81 focus_position=self._scroll_position, 82 focus_size=(self._scroll_width, 83 self._scroll_height)) 84 85 self._scrollwidget = ba.scrollwidget(parent=self.root_widget, 86 size=(self._scroll_width, 87 self._scroll_height), 88 color=(0.55, 0.55, 0.55), 89 highlight=False, 90 position=self._scroll_position) 91 ba.containerwidget(edit=self._scrollwidget, claims_left_right=True) 92 93 self._sub_width = self._scroll_width * 0.95 94 self._sub_height = 5 + rows * (button_height + 95 2 * button_buffer_v) + 100 96 self._subcontainer = ba.containerwidget(parent=self._scrollwidget, 97 size=(self._sub_width, 98 self._sub_height), 99 background=False) 100 index = 0 101 mask_texture = ba.gettexture('characterIconMask') 102 for y in range(rows): 103 for x in range(columns): 104 pos = (x * (button_width + 2 * button_buffer_h) + 105 button_buffer_h, self._sub_height - (y + 1) * 106 (button_height + 2 * button_buffer_v) + 12) 107 btn = ba.buttonwidget( 108 parent=self._subcontainer, 109 button_type='square', 110 size=(button_width, button_height), 111 autoselect=True, 112 texture=self._icon_textures[index], 113 tint_texture=self._icon_tint_textures[index], 114 mask_texture=mask_texture, 115 label='', 116 color=(1, 1, 1), 117 tint_color=tint_color, 118 tint2_color=tint2_color, 119 on_activate_call=ba.Call(self._select_character, 120 self._spazzes[index]), 121 position=pos) 122 ba.widget(edit=btn, show_buffer_top=60, show_buffer_bottom=60) 123 if self._spazzes[index] == selected_character: 124 ba.containerwidget(edit=self._subcontainer, 125 selected_child=btn, 126 visible_child=btn) 127 name = ba.Lstr(translate=('characterNames', 128 self._spazzes[index])) 129 ba.textwidget(parent=self._subcontainer, 130 text=name, 131 position=(pos[0] + button_width * 0.5, 132 pos[1] - 12), 133 size=(0, 0), 134 scale=0.5, 135 maxwidth=button_width, 136 draw_controller=btn, 137 h_align='center', 138 v_align='center', 139 color=(0.8, 0.8, 0.8, 0.8)) 140 index += 1 141 142 if index >= count: 143 break 144 if index >= count: 145 break 146 self._get_more_characters_button = btn = ba.buttonwidget( 147 parent=self._subcontainer, 148 size=(self._sub_width * 0.8, 60), 149 position=(self._sub_width * 0.1, 30), 150 label=ba.Lstr(resource='editProfileWindow.getMoreCharactersText'), 151 on_activate_call=self._on_store_press, 152 color=(0.6, 0.6, 0.6), 153 textcolor=(0.8, 0.8, 0.8), 154 autoselect=True) 155 ba.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30) 156 157 def _on_store_press(self) -> None: 158 from bastd.ui.account import show_sign_in_prompt 159 from bastd.ui.store.browser import StoreBrowserWindow 160 if _ba.get_v1_account_state() != 'signed_in': 161 show_sign_in_prompt() 162 return 163 self._transition_out() 164 StoreBrowserWindow(modal=True, 165 show_tab=StoreBrowserWindow.TabID.CHARACTERS, 166 origin_widget=self._get_more_characters_button) 167 168 def _select_character(self, character: str) -> None: 169 if self._delegate is not None: 170 self._delegate.on_character_picker_pick(character) 171 self._transition_out() 172 173 def _transition_out(self) -> None: 174 if not self._transitioning_out: 175 self._transitioning_out = True 176 ba.containerwidget(edit=self.root_widget, transition='out_scale') 177 178 def on_popup_cancel(self) -> None: 179 ba.playsound(ba.getsound('swish')) 180 self._transition_out()
Popup window for selecting characters.
CharacterPicker( parent: _ba.Widget, position: tuple[float, float] = (0.0, 0.0), delegate: Any = None, scale: float | None = None, offset: tuple[float, float] = (0.0, 0.0), tint_color: Sequence[float] = (1.0, 1.0, 1.0), tint2_color: Sequence[float] = (1.0, 1.0, 1.0), selected_character: str | None = None)
22 def __init__(self, 23 parent: ba.Widget, 24 position: tuple[float, float] = (0.0, 0.0), 25 delegate: Any = None, 26 scale: float | None = None, 27 offset: tuple[float, float] = (0.0, 0.0), 28 tint_color: Sequence[float] = (1.0, 1.0, 1.0), 29 tint2_color: Sequence[float] = (1.0, 1.0, 1.0), 30 selected_character: str | None = None): 31 # pylint: disable=too-many-locals 32 from bastd.actor import spazappearance 33 del parent # unused here 34 uiscale = ba.app.ui.uiscale 35 if scale is None: 36 scale = (1.85 if uiscale is ba.UIScale.SMALL else 37 1.65 if uiscale is ba.UIScale.MEDIUM else 1.23) 38 39 self._delegate = delegate 40 self._transitioning_out = False 41 42 # make a list of spaz icons 43 self._spazzes = spazappearance.get_appearances() 44 self._spazzes.sort() 45 self._icon_textures = [ 46 ba.gettexture(ba.app.spaz_appearances[s].icon_texture) 47 for s in self._spazzes 48 ] 49 self._icon_tint_textures = [ 50 ba.gettexture(ba.app.spaz_appearances[s].icon_mask_texture) 51 for s in self._spazzes 52 ] 53 54 count = len(self._spazzes) 55 56 columns = 3 57 rows = int(math.ceil(float(count) / columns)) 58 59 button_width = 100 60 button_height = 100 61 button_buffer_h = 10 62 button_buffer_v = 15 63 64 self._width = (10 + columns * (button_width + 2 * button_buffer_h) * 65 (1.0 / 0.95) * (1.0 / 0.8)) 66 self._height = self._width * (0.8 67 if uiscale is ba.UIScale.SMALL else 1.06) 68 69 self._scroll_width = self._width * 0.8 70 self._scroll_height = self._height * 0.8 71 self._scroll_position = ((self._width - self._scroll_width) * 0.5, 72 (self._height - self._scroll_height) * 0.5) 73 74 # creates our _root_widget 75 popup.PopupWindow.__init__(self, 76 position=position, 77 size=(self._width, self._height), 78 scale=scale, 79 bg_color=(0.5, 0.5, 0.5), 80 offset=offset, 81 focus_position=self._scroll_position, 82 focus_size=(self._scroll_width, 83 self._scroll_height)) 84 85 self._scrollwidget = ba.scrollwidget(parent=self.root_widget, 86 size=(self._scroll_width, 87 self._scroll_height), 88 color=(0.55, 0.55, 0.55), 89 highlight=False, 90 position=self._scroll_position) 91 ba.containerwidget(edit=self._scrollwidget, claims_left_right=True) 92 93 self._sub_width = self._scroll_width * 0.95 94 self._sub_height = 5 + rows * (button_height + 95 2 * button_buffer_v) + 100 96 self._subcontainer = ba.containerwidget(parent=self._scrollwidget, 97 size=(self._sub_width, 98 self._sub_height), 99 background=False) 100 index = 0 101 mask_texture = ba.gettexture('characterIconMask') 102 for y in range(rows): 103 for x in range(columns): 104 pos = (x * (button_width + 2 * button_buffer_h) + 105 button_buffer_h, self._sub_height - (y + 1) * 106 (button_height + 2 * button_buffer_v) + 12) 107 btn = ba.buttonwidget( 108 parent=self._subcontainer, 109 button_type='square', 110 size=(button_width, button_height), 111 autoselect=True, 112 texture=self._icon_textures[index], 113 tint_texture=self._icon_tint_textures[index], 114 mask_texture=mask_texture, 115 label='', 116 color=(1, 1, 1), 117 tint_color=tint_color, 118 tint2_color=tint2_color, 119 on_activate_call=ba.Call(self._select_character, 120 self._spazzes[index]), 121 position=pos) 122 ba.widget(edit=btn, show_buffer_top=60, show_buffer_bottom=60) 123 if self._spazzes[index] == selected_character: 124 ba.containerwidget(edit=self._subcontainer, 125 selected_child=btn, 126 visible_child=btn) 127 name = ba.Lstr(translate=('characterNames', 128 self._spazzes[index])) 129 ba.textwidget(parent=self._subcontainer, 130 text=name, 131 position=(pos[0] + button_width * 0.5, 132 pos[1] - 12), 133 size=(0, 0), 134 scale=0.5, 135 maxwidth=button_width, 136 draw_controller=btn, 137 h_align='center', 138 v_align='center', 139 color=(0.8, 0.8, 0.8, 0.8)) 140 index += 1 141 142 if index >= count: 143 break 144 if index >= count: 145 break 146 self._get_more_characters_button = btn = ba.buttonwidget( 147 parent=self._subcontainer, 148 size=(self._sub_width * 0.8, 60), 149 position=(self._sub_width * 0.1, 30), 150 label=ba.Lstr(resource='editProfileWindow.getMoreCharactersText'), 151 on_activate_call=self._on_store_press, 152 color=(0.6, 0.6, 0.6), 153 textcolor=(0.8, 0.8, 0.8), 154 autoselect=True) 155 ba.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30)