bastd.ui.store.button
UI functionality for a button leading to the store.
1# Released under the MIT License. See LICENSE for details. 2# 3"""UI functionality for a button leading to the store.""" 4from __future__ import annotations 5 6from typing import TYPE_CHECKING 7 8import ba 9import ba.internal 10 11if TYPE_CHECKING: 12 from typing import Any, Sequence, Callable 13 14 15class StoreButton: 16 """A button leading to the store.""" 17 18 def __init__( 19 self, 20 parent: ba.Widget, 21 position: Sequence[float], 22 size: Sequence[float], 23 scale: float, 24 on_activate_call: Callable[[], Any] | None = None, 25 transition_delay: float | None = None, 26 color: Sequence[float] | None = None, 27 textcolor: Sequence[float] | None = None, 28 show_tickets: bool = False, 29 button_type: str | None = None, 30 sale_scale: float = 1.0, 31 ): 32 self._position = position 33 self._size = size 34 self._scale = scale 35 36 if on_activate_call is None: 37 on_activate_call = ba.WeakCall(self._default_on_activate_call) 38 self._on_activate_call = on_activate_call 39 40 self._button = ba.buttonwidget( 41 parent=parent, 42 size=size, 43 label='' if show_tickets else ba.Lstr(resource='storeText'), 44 scale=scale, 45 autoselect=True, 46 on_activate_call=self._on_activate, 47 transition_delay=transition_delay, 48 color=color, 49 button_type=button_type, 50 ) 51 52 self._title_text: ba.Widget | None 53 self._ticket_text: ba.Widget | None 54 55 if show_tickets: 56 self._title_text = ba.textwidget( 57 parent=parent, 58 position=( 59 position[0] + size[0] * 0.5 * scale, 60 position[1] + size[1] * 0.65 * scale, 61 ), 62 size=(0, 0), 63 h_align='center', 64 v_align='center', 65 maxwidth=size[0] * scale * 0.65, 66 text=ba.Lstr(resource='storeText'), 67 draw_controller=self._button, 68 scale=scale, 69 transition_delay=transition_delay, 70 color=textcolor, 71 ) 72 self._ticket_text = ba.textwidget( 73 parent=parent, 74 size=(0, 0), 75 h_align='center', 76 v_align='center', 77 maxwidth=size[0] * scale * 0.85, 78 text='', 79 color=(0.2, 1.0, 0.2), 80 flatness=1.0, 81 shadow=0.0, 82 scale=scale * 0.6, 83 transition_delay=transition_delay, 84 ) 85 else: 86 self._title_text = None 87 self._ticket_text = None 88 89 self._circle_rad = 12 * scale 90 self._circle_center = (0.0, 0.0) 91 self._sale_circle_center = (0.0, 0.0) 92 93 self._available_purchase_backing = ba.imagewidget( 94 parent=parent, 95 color=(1, 0, 0), 96 draw_controller=self._button, 97 size=(2.2 * self._circle_rad, 2.2 * self._circle_rad), 98 texture=ba.gettexture('circleShadow'), 99 transition_delay=transition_delay, 100 ) 101 self._available_purchase_text = ba.textwidget( 102 parent=parent, 103 size=(0, 0), 104 h_align='center', 105 v_align='center', 106 text='', 107 draw_controller=self._button, 108 color=(1, 1, 1), 109 flatness=1.0, 110 shadow=1.0, 111 scale=0.6 * scale, 112 maxwidth=self._circle_rad * 1.4, 113 transition_delay=transition_delay, 114 ) 115 116 self._sale_circle_rad = 18 * scale * sale_scale 117 self._sale_backing = ba.imagewidget( 118 parent=parent, 119 color=(0.5, 0, 1.0), 120 draw_controller=self._button, 121 size=(2 * self._sale_circle_rad, 2 * self._sale_circle_rad), 122 texture=ba.gettexture('circleZigZag'), 123 transition_delay=transition_delay, 124 ) 125 self._sale_title_text = ba.textwidget( 126 parent=parent, 127 size=(0, 0), 128 h_align='center', 129 v_align='center', 130 draw_controller=self._button, 131 color=(0, 1, 0), 132 flatness=1.0, 133 shadow=0.0, 134 scale=0.5 * scale * sale_scale, 135 maxwidth=self._sale_circle_rad * 1.5, 136 transition_delay=transition_delay, 137 ) 138 self._sale_time_text = ba.textwidget( 139 parent=parent, 140 size=(0, 0), 141 h_align='center', 142 v_align='center', 143 draw_controller=self._button, 144 color=(0, 1, 0), 145 flatness=1.0, 146 shadow=0.0, 147 scale=0.4 * scale * sale_scale, 148 maxwidth=self._sale_circle_rad * 1.5, 149 transition_delay=transition_delay, 150 ) 151 152 self.set_position(position) 153 self._update_timer = ba.Timer( 154 1.0, 155 ba.WeakCall(self._update), 156 repeat=True, 157 timetype=ba.TimeType.REAL, 158 ) 159 self._update() 160 161 def _on_activate(self) -> None: 162 ba.internal.increment_analytics_count('Store button press') 163 self._on_activate_call() 164 165 def set_position(self, position: Sequence[float]) -> None: 166 """Set the button position.""" 167 self._position = position 168 self._circle_center = ( 169 position[0] + 0.1 * self._size[0] * self._scale, 170 position[1] + self._size[1] * self._scale * 0.8, 171 ) 172 self._sale_circle_center = ( 173 position[0] + 0.07 * self._size[0] * self._scale, 174 position[1] + self._size[1] * self._scale * 0.8, 175 ) 176 177 if not self._button: 178 return 179 ba.buttonwidget(edit=self._button, position=self._position) 180 if self._title_text is not None: 181 ba.textwidget( 182 edit=self._title_text, 183 position=( 184 self._position[0] + self._size[0] * 0.5 * self._scale, 185 self._position[1] + self._size[1] * 0.65 * self._scale, 186 ), 187 ) 188 if self._ticket_text is not None: 189 ba.textwidget( 190 edit=self._ticket_text, 191 position=( 192 position[0] + self._size[0] * 0.5 * self._scale, 193 position[1] + self._size[1] * 0.28 * self._scale, 194 ), 195 size=(0, 0), 196 ) 197 ba.imagewidget( 198 edit=self._available_purchase_backing, 199 position=( 200 self._circle_center[0] - self._circle_rad * 1.02, 201 self._circle_center[1] - self._circle_rad * 1.13, 202 ), 203 ) 204 ba.textwidget( 205 edit=self._available_purchase_text, position=self._circle_center 206 ) 207 208 ba.imagewidget( 209 edit=self._sale_backing, 210 position=( 211 self._sale_circle_center[0] - self._sale_circle_rad, 212 self._sale_circle_center[1] - self._sale_circle_rad, 213 ), 214 ) 215 ba.textwidget( 216 edit=self._sale_title_text, 217 position=( 218 self._sale_circle_center[0], 219 self._sale_circle_center[1] + self._sale_circle_rad * 0.3, 220 ), 221 ) 222 ba.textwidget( 223 edit=self._sale_time_text, 224 position=( 225 self._sale_circle_center[0], 226 self._sale_circle_center[1] - self._sale_circle_rad * 0.3, 227 ), 228 ) 229 230 def _default_on_activate_call(self) -> None: 231 # pylint: disable=cyclic-import 232 from bastd.ui.account import show_sign_in_prompt 233 from bastd.ui.store.browser import StoreBrowserWindow 234 235 if ba.internal.get_v1_account_state() != 'signed_in': 236 show_sign_in_prompt() 237 return 238 StoreBrowserWindow(modal=True, origin_widget=self._button) 239 240 def get_button(self) -> ba.Widget: 241 """Return the underlying button widget.""" 242 return self._button 243 244 def _update(self) -> None: 245 # pylint: disable=too-many-branches 246 # pylint: disable=cyclic-import 247 from ba import SpecialChar, TimeFormat 248 from ba.internal import ( 249 get_available_sale_time, 250 get_available_purchase_count, 251 ) 252 253 if not self._button: 254 return # Our instance may outlive our UI objects. 255 256 if self._ticket_text is not None: 257 if ba.internal.get_v1_account_state() == 'signed_in': 258 sval = ba.charstr(SpecialChar.TICKET) + str( 259 ba.internal.get_v1_account_ticket_count() 260 ) 261 else: 262 sval = '-' 263 ba.textwidget(edit=self._ticket_text, text=sval) 264 available_purchases = get_available_purchase_count() 265 266 # Old pro sale stuff.. 267 sale_time = get_available_sale_time('extras') 268 269 # ..also look for new style sales. 270 if sale_time is None: 271 import datetime 272 273 sales_raw = ba.internal.get_v1_account_misc_read_val('sales', {}) 274 sale_times = [] 275 try: 276 # Look at the current set of sales; filter any with time 277 # remaining that we don't own. 278 for sale_item, sale_info in list(sales_raw.items()): 279 if not ba.internal.get_purchased(sale_item): 280 to_end = ( 281 datetime.datetime.utcfromtimestamp(sale_info['e']) 282 - datetime.datetime.utcnow() 283 ).total_seconds() 284 if to_end > 0: 285 sale_times.append(to_end) 286 except Exception: 287 ba.print_exception('Error parsing sales.') 288 if sale_times: 289 sale_time = int(min(sale_times) * 1000) 290 291 if sale_time is not None: 292 ba.textwidget( 293 edit=self._sale_title_text, 294 text=ba.Lstr(resource='store.saleText'), 295 ) 296 ba.textwidget( 297 edit=self._sale_time_text, 298 text=ba.timestring( 299 sale_time, centi=False, timeformat=TimeFormat.MILLISECONDS 300 ), 301 ) 302 ba.imagewidget(edit=self._sale_backing, opacity=1.0) 303 ba.imagewidget(edit=self._available_purchase_backing, opacity=1.0) 304 ba.textwidget(edit=self._available_purchase_text, text='') 305 ba.imagewidget(edit=self._available_purchase_backing, opacity=0.0) 306 else: 307 ba.imagewidget(edit=self._sale_backing, opacity=0.0) 308 ba.textwidget(edit=self._sale_time_text, text='') 309 ba.textwidget(edit=self._sale_title_text, text='') 310 if available_purchases > 0: 311 ba.textwidget( 312 edit=self._available_purchase_text, 313 text=str(available_purchases), 314 ) 315 ba.imagewidget( 316 edit=self._available_purchase_backing, opacity=1.0 317 ) 318 else: 319 ba.textwidget(edit=self._available_purchase_text, text='') 320 ba.imagewidget( 321 edit=self._available_purchase_backing, opacity=0.0 322 )
class
StoreButton:
16class StoreButton: 17 """A button leading to the store.""" 18 19 def __init__( 20 self, 21 parent: ba.Widget, 22 position: Sequence[float], 23 size: Sequence[float], 24 scale: float, 25 on_activate_call: Callable[[], Any] | None = None, 26 transition_delay: float | None = None, 27 color: Sequence[float] | None = None, 28 textcolor: Sequence[float] | None = None, 29 show_tickets: bool = False, 30 button_type: str | None = None, 31 sale_scale: float = 1.0, 32 ): 33 self._position = position 34 self._size = size 35 self._scale = scale 36 37 if on_activate_call is None: 38 on_activate_call = ba.WeakCall(self._default_on_activate_call) 39 self._on_activate_call = on_activate_call 40 41 self._button = ba.buttonwidget( 42 parent=parent, 43 size=size, 44 label='' if show_tickets else ba.Lstr(resource='storeText'), 45 scale=scale, 46 autoselect=True, 47 on_activate_call=self._on_activate, 48 transition_delay=transition_delay, 49 color=color, 50 button_type=button_type, 51 ) 52 53 self._title_text: ba.Widget | None 54 self._ticket_text: ba.Widget | None 55 56 if show_tickets: 57 self._title_text = ba.textwidget( 58 parent=parent, 59 position=( 60 position[0] + size[0] * 0.5 * scale, 61 position[1] + size[1] * 0.65 * scale, 62 ), 63 size=(0, 0), 64 h_align='center', 65 v_align='center', 66 maxwidth=size[0] * scale * 0.65, 67 text=ba.Lstr(resource='storeText'), 68 draw_controller=self._button, 69 scale=scale, 70 transition_delay=transition_delay, 71 color=textcolor, 72 ) 73 self._ticket_text = ba.textwidget( 74 parent=parent, 75 size=(0, 0), 76 h_align='center', 77 v_align='center', 78 maxwidth=size[0] * scale * 0.85, 79 text='', 80 color=(0.2, 1.0, 0.2), 81 flatness=1.0, 82 shadow=0.0, 83 scale=scale * 0.6, 84 transition_delay=transition_delay, 85 ) 86 else: 87 self._title_text = None 88 self._ticket_text = None 89 90 self._circle_rad = 12 * scale 91 self._circle_center = (0.0, 0.0) 92 self._sale_circle_center = (0.0, 0.0) 93 94 self._available_purchase_backing = ba.imagewidget( 95 parent=parent, 96 color=(1, 0, 0), 97 draw_controller=self._button, 98 size=(2.2 * self._circle_rad, 2.2 * self._circle_rad), 99 texture=ba.gettexture('circleShadow'), 100 transition_delay=transition_delay, 101 ) 102 self._available_purchase_text = ba.textwidget( 103 parent=parent, 104 size=(0, 0), 105 h_align='center', 106 v_align='center', 107 text='', 108 draw_controller=self._button, 109 color=(1, 1, 1), 110 flatness=1.0, 111 shadow=1.0, 112 scale=0.6 * scale, 113 maxwidth=self._circle_rad * 1.4, 114 transition_delay=transition_delay, 115 ) 116 117 self._sale_circle_rad = 18 * scale * sale_scale 118 self._sale_backing = ba.imagewidget( 119 parent=parent, 120 color=(0.5, 0, 1.0), 121 draw_controller=self._button, 122 size=(2 * self._sale_circle_rad, 2 * self._sale_circle_rad), 123 texture=ba.gettexture('circleZigZag'), 124 transition_delay=transition_delay, 125 ) 126 self._sale_title_text = ba.textwidget( 127 parent=parent, 128 size=(0, 0), 129 h_align='center', 130 v_align='center', 131 draw_controller=self._button, 132 color=(0, 1, 0), 133 flatness=1.0, 134 shadow=0.0, 135 scale=0.5 * scale * sale_scale, 136 maxwidth=self._sale_circle_rad * 1.5, 137 transition_delay=transition_delay, 138 ) 139 self._sale_time_text = ba.textwidget( 140 parent=parent, 141 size=(0, 0), 142 h_align='center', 143 v_align='center', 144 draw_controller=self._button, 145 color=(0, 1, 0), 146 flatness=1.0, 147 shadow=0.0, 148 scale=0.4 * scale * sale_scale, 149 maxwidth=self._sale_circle_rad * 1.5, 150 transition_delay=transition_delay, 151 ) 152 153 self.set_position(position) 154 self._update_timer = ba.Timer( 155 1.0, 156 ba.WeakCall(self._update), 157 repeat=True, 158 timetype=ba.TimeType.REAL, 159 ) 160 self._update() 161 162 def _on_activate(self) -> None: 163 ba.internal.increment_analytics_count('Store button press') 164 self._on_activate_call() 165 166 def set_position(self, position: Sequence[float]) -> None: 167 """Set the button position.""" 168 self._position = position 169 self._circle_center = ( 170 position[0] + 0.1 * self._size[0] * self._scale, 171 position[1] + self._size[1] * self._scale * 0.8, 172 ) 173 self._sale_circle_center = ( 174 position[0] + 0.07 * self._size[0] * self._scale, 175 position[1] + self._size[1] * self._scale * 0.8, 176 ) 177 178 if not self._button: 179 return 180 ba.buttonwidget(edit=self._button, position=self._position) 181 if self._title_text is not None: 182 ba.textwidget( 183 edit=self._title_text, 184 position=( 185 self._position[0] + self._size[0] * 0.5 * self._scale, 186 self._position[1] + self._size[1] * 0.65 * self._scale, 187 ), 188 ) 189 if self._ticket_text is not None: 190 ba.textwidget( 191 edit=self._ticket_text, 192 position=( 193 position[0] + self._size[0] * 0.5 * self._scale, 194 position[1] + self._size[1] * 0.28 * self._scale, 195 ), 196 size=(0, 0), 197 ) 198 ba.imagewidget( 199 edit=self._available_purchase_backing, 200 position=( 201 self._circle_center[0] - self._circle_rad * 1.02, 202 self._circle_center[1] - self._circle_rad * 1.13, 203 ), 204 ) 205 ba.textwidget( 206 edit=self._available_purchase_text, position=self._circle_center 207 ) 208 209 ba.imagewidget( 210 edit=self._sale_backing, 211 position=( 212 self._sale_circle_center[0] - self._sale_circle_rad, 213 self._sale_circle_center[1] - self._sale_circle_rad, 214 ), 215 ) 216 ba.textwidget( 217 edit=self._sale_title_text, 218 position=( 219 self._sale_circle_center[0], 220 self._sale_circle_center[1] + self._sale_circle_rad * 0.3, 221 ), 222 ) 223 ba.textwidget( 224 edit=self._sale_time_text, 225 position=( 226 self._sale_circle_center[0], 227 self._sale_circle_center[1] - self._sale_circle_rad * 0.3, 228 ), 229 ) 230 231 def _default_on_activate_call(self) -> None: 232 # pylint: disable=cyclic-import 233 from bastd.ui.account import show_sign_in_prompt 234 from bastd.ui.store.browser import StoreBrowserWindow 235 236 if ba.internal.get_v1_account_state() != 'signed_in': 237 show_sign_in_prompt() 238 return 239 StoreBrowserWindow(modal=True, origin_widget=self._button) 240 241 def get_button(self) -> ba.Widget: 242 """Return the underlying button widget.""" 243 return self._button 244 245 def _update(self) -> None: 246 # pylint: disable=too-many-branches 247 # pylint: disable=cyclic-import 248 from ba import SpecialChar, TimeFormat 249 from ba.internal import ( 250 get_available_sale_time, 251 get_available_purchase_count, 252 ) 253 254 if not self._button: 255 return # Our instance may outlive our UI objects. 256 257 if self._ticket_text is not None: 258 if ba.internal.get_v1_account_state() == 'signed_in': 259 sval = ba.charstr(SpecialChar.TICKET) + str( 260 ba.internal.get_v1_account_ticket_count() 261 ) 262 else: 263 sval = '-' 264 ba.textwidget(edit=self._ticket_text, text=sval) 265 available_purchases = get_available_purchase_count() 266 267 # Old pro sale stuff.. 268 sale_time = get_available_sale_time('extras') 269 270 # ..also look for new style sales. 271 if sale_time is None: 272 import datetime 273 274 sales_raw = ba.internal.get_v1_account_misc_read_val('sales', {}) 275 sale_times = [] 276 try: 277 # Look at the current set of sales; filter any with time 278 # remaining that we don't own. 279 for sale_item, sale_info in list(sales_raw.items()): 280 if not ba.internal.get_purchased(sale_item): 281 to_end = ( 282 datetime.datetime.utcfromtimestamp(sale_info['e']) 283 - datetime.datetime.utcnow() 284 ).total_seconds() 285 if to_end > 0: 286 sale_times.append(to_end) 287 except Exception: 288 ba.print_exception('Error parsing sales.') 289 if sale_times: 290 sale_time = int(min(sale_times) * 1000) 291 292 if sale_time is not None: 293 ba.textwidget( 294 edit=self._sale_title_text, 295 text=ba.Lstr(resource='store.saleText'), 296 ) 297 ba.textwidget( 298 edit=self._sale_time_text, 299 text=ba.timestring( 300 sale_time, centi=False, timeformat=TimeFormat.MILLISECONDS 301 ), 302 ) 303 ba.imagewidget(edit=self._sale_backing, opacity=1.0) 304 ba.imagewidget(edit=self._available_purchase_backing, opacity=1.0) 305 ba.textwidget(edit=self._available_purchase_text, text='') 306 ba.imagewidget(edit=self._available_purchase_backing, opacity=0.0) 307 else: 308 ba.imagewidget(edit=self._sale_backing, opacity=0.0) 309 ba.textwidget(edit=self._sale_time_text, text='') 310 ba.textwidget(edit=self._sale_title_text, text='') 311 if available_purchases > 0: 312 ba.textwidget( 313 edit=self._available_purchase_text, 314 text=str(available_purchases), 315 ) 316 ba.imagewidget( 317 edit=self._available_purchase_backing, opacity=1.0 318 ) 319 else: 320 ba.textwidget(edit=self._available_purchase_text, text='') 321 ba.imagewidget( 322 edit=self._available_purchase_backing, opacity=0.0 323 )
A button leading to the store.
StoreButton( parent: _ba.Widget, position: Sequence[float], size: Sequence[float], scale: float, on_activate_call: Optional[Callable[[], Any]] = None, transition_delay: float | None = None, color: Optional[Sequence[float]] = None, textcolor: Optional[Sequence[float]] = None, show_tickets: bool = False, button_type: str | None = None, sale_scale: float = 1.0)
19 def __init__( 20 self, 21 parent: ba.Widget, 22 position: Sequence[float], 23 size: Sequence[float], 24 scale: float, 25 on_activate_call: Callable[[], Any] | None = None, 26 transition_delay: float | None = None, 27 color: Sequence[float] | None = None, 28 textcolor: Sequence[float] | None = None, 29 show_tickets: bool = False, 30 button_type: str | None = None, 31 sale_scale: float = 1.0, 32 ): 33 self._position = position 34 self._size = size 35 self._scale = scale 36 37 if on_activate_call is None: 38 on_activate_call = ba.WeakCall(self._default_on_activate_call) 39 self._on_activate_call = on_activate_call 40 41 self._button = ba.buttonwidget( 42 parent=parent, 43 size=size, 44 label='' if show_tickets else ba.Lstr(resource='storeText'), 45 scale=scale, 46 autoselect=True, 47 on_activate_call=self._on_activate, 48 transition_delay=transition_delay, 49 color=color, 50 button_type=button_type, 51 ) 52 53 self._title_text: ba.Widget | None 54 self._ticket_text: ba.Widget | None 55 56 if show_tickets: 57 self._title_text = ba.textwidget( 58 parent=parent, 59 position=( 60 position[0] + size[0] * 0.5 * scale, 61 position[1] + size[1] * 0.65 * scale, 62 ), 63 size=(0, 0), 64 h_align='center', 65 v_align='center', 66 maxwidth=size[0] * scale * 0.65, 67 text=ba.Lstr(resource='storeText'), 68 draw_controller=self._button, 69 scale=scale, 70 transition_delay=transition_delay, 71 color=textcolor, 72 ) 73 self._ticket_text = ba.textwidget( 74 parent=parent, 75 size=(0, 0), 76 h_align='center', 77 v_align='center', 78 maxwidth=size[0] * scale * 0.85, 79 text='', 80 color=(0.2, 1.0, 0.2), 81 flatness=1.0, 82 shadow=0.0, 83 scale=scale * 0.6, 84 transition_delay=transition_delay, 85 ) 86 else: 87 self._title_text = None 88 self._ticket_text = None 89 90 self._circle_rad = 12 * scale 91 self._circle_center = (0.0, 0.0) 92 self._sale_circle_center = (0.0, 0.0) 93 94 self._available_purchase_backing = ba.imagewidget( 95 parent=parent, 96 color=(1, 0, 0), 97 draw_controller=self._button, 98 size=(2.2 * self._circle_rad, 2.2 * self._circle_rad), 99 texture=ba.gettexture('circleShadow'), 100 transition_delay=transition_delay, 101 ) 102 self._available_purchase_text = ba.textwidget( 103 parent=parent, 104 size=(0, 0), 105 h_align='center', 106 v_align='center', 107 text='', 108 draw_controller=self._button, 109 color=(1, 1, 1), 110 flatness=1.0, 111 shadow=1.0, 112 scale=0.6 * scale, 113 maxwidth=self._circle_rad * 1.4, 114 transition_delay=transition_delay, 115 ) 116 117 self._sale_circle_rad = 18 * scale * sale_scale 118 self._sale_backing = ba.imagewidget( 119 parent=parent, 120 color=(0.5, 0, 1.0), 121 draw_controller=self._button, 122 size=(2 * self._sale_circle_rad, 2 * self._sale_circle_rad), 123 texture=ba.gettexture('circleZigZag'), 124 transition_delay=transition_delay, 125 ) 126 self._sale_title_text = ba.textwidget( 127 parent=parent, 128 size=(0, 0), 129 h_align='center', 130 v_align='center', 131 draw_controller=self._button, 132 color=(0, 1, 0), 133 flatness=1.0, 134 shadow=0.0, 135 scale=0.5 * scale * sale_scale, 136 maxwidth=self._sale_circle_rad * 1.5, 137 transition_delay=transition_delay, 138 ) 139 self._sale_time_text = ba.textwidget( 140 parent=parent, 141 size=(0, 0), 142 h_align='center', 143 v_align='center', 144 draw_controller=self._button, 145 color=(0, 1, 0), 146 flatness=1.0, 147 shadow=0.0, 148 scale=0.4 * scale * sale_scale, 149 maxwidth=self._sale_circle_rad * 1.5, 150 transition_delay=transition_delay, 151 ) 152 153 self.set_position(position) 154 self._update_timer = ba.Timer( 155 1.0, 156 ba.WeakCall(self._update), 157 repeat=True, 158 timetype=ba.TimeType.REAL, 159 ) 160 self._update()
def
set_position(self, position: Sequence[float]) -> None:
166 def set_position(self, position: Sequence[float]) -> None: 167 """Set the button position.""" 168 self._position = position 169 self._circle_center = ( 170 position[0] + 0.1 * self._size[0] * self._scale, 171 position[1] + self._size[1] * self._scale * 0.8, 172 ) 173 self._sale_circle_center = ( 174 position[0] + 0.07 * self._size[0] * self._scale, 175 position[1] + self._size[1] * self._scale * 0.8, 176 ) 177 178 if not self._button: 179 return 180 ba.buttonwidget(edit=self._button, position=self._position) 181 if self._title_text is not None: 182 ba.textwidget( 183 edit=self._title_text, 184 position=( 185 self._position[0] + self._size[0] * 0.5 * self._scale, 186 self._position[1] + self._size[1] * 0.65 * self._scale, 187 ), 188 ) 189 if self._ticket_text is not None: 190 ba.textwidget( 191 edit=self._ticket_text, 192 position=( 193 position[0] + self._size[0] * 0.5 * self._scale, 194 position[1] + self._size[1] * 0.28 * self._scale, 195 ), 196 size=(0, 0), 197 ) 198 ba.imagewidget( 199 edit=self._available_purchase_backing, 200 position=( 201 self._circle_center[0] - self._circle_rad * 1.02, 202 self._circle_center[1] - self._circle_rad * 1.13, 203 ), 204 ) 205 ba.textwidget( 206 edit=self._available_purchase_text, position=self._circle_center 207 ) 208 209 ba.imagewidget( 210 edit=self._sale_backing, 211 position=( 212 self._sale_circle_center[0] - self._sale_circle_rad, 213 self._sale_circle_center[1] - self._sale_circle_rad, 214 ), 215 ) 216 ba.textwidget( 217 edit=self._sale_title_text, 218 position=( 219 self._sale_circle_center[0], 220 self._sale_circle_center[1] + self._sale_circle_rad * 0.3, 221 ), 222 ) 223 ba.textwidget( 224 edit=self._sale_time_text, 225 position=( 226 self._sale_circle_center[0], 227 self._sale_circle_center[1] - self._sale_circle_rad * 0.3, 228 ), 229 )
Set the button position.