bastd.ui.league.rankbutton
Provides a button showing league rank.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides a button showing league rank.""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8 9import _ba 10import ba 11 12if TYPE_CHECKING: 13 from typing import Any, Callable 14 15 16class LeagueRankButton: 17 """Button showing league rank.""" 18 19 def __init__(self, 20 parent: ba.Widget, 21 position: tuple[float, float], 22 size: tuple[float, float], 23 scale: float, 24 on_activate_call: Callable[[], Any] | None = None, 25 transition_delay: float | None = None, 26 color: tuple[float, float, float] | None = None, 27 textcolor: tuple[float, float, float] | None = None, 28 smooth_update_delay: float | None = None): 29 if on_activate_call is None: 30 on_activate_call = ba.WeakCall(self._default_on_activate_call) 31 self._on_activate_call = on_activate_call 32 if smooth_update_delay is None: 33 smooth_update_delay = 1000 34 self._smooth_update_delay = smooth_update_delay 35 self._size = size 36 self._scale = scale 37 if color is None: 38 color = (0.5, 0.6, 0.5) 39 if textcolor is None: 40 textcolor = (1, 1, 1) 41 self._color = color 42 self._textcolor = textcolor 43 self._header_color = (0.8, 0.8, 2.0) 44 self._parent = parent 45 self._position: tuple[float, float] = (0.0, 0.0) 46 47 self._button = ba.buttonwidget(parent=parent, 48 size=size, 49 label='', 50 button_type='square', 51 scale=scale, 52 autoselect=True, 53 on_activate_call=self._on_activate, 54 transition_delay=transition_delay, 55 color=color) 56 57 self._title_text = ba.textwidget( 58 parent=parent, 59 size=(0, 0), 60 draw_controller=self._button, 61 h_align='center', 62 v_align='center', 63 maxwidth=size[0] * scale * 0.85, 64 text=ba.Lstr( 65 resource='league.leagueRankText', 66 fallback_resource='coopSelectWindow.powerRankingText'), 67 color=self._header_color, 68 flatness=1.0, 69 shadow=1.0, 70 scale=scale * 0.5, 71 transition_delay=transition_delay) 72 73 self._value_text = ba.textwidget(parent=parent, 74 size=(0, 0), 75 h_align='center', 76 v_align='center', 77 maxwidth=size[0] * scale * 0.85, 78 text='-', 79 draw_controller=self._button, 80 big=True, 81 scale=scale, 82 transition_delay=transition_delay, 83 color=textcolor) 84 85 self._smooth_percent: float | None = None 86 self._percent: int | None = None 87 self._smooth_rank: float | None = None 88 self._rank: int | None = None 89 self._ticking_node: ba.Node | None = None 90 self._smooth_increase_speed = 1.0 91 self._league: str | None = None 92 self._improvement_text: str | None = None 93 94 self._smooth_update_timer: ba.Timer | None = None 95 96 # Take note of our account state; we'll refresh later if this changes. 97 self._account_state_num = _ba.get_v1_account_state_num() 98 self._last_power_ranking_query_time: float | None = None 99 self._doing_power_ranking_query = False 100 self.set_position(position) 101 self._bg_flash = False 102 self._update_timer = ba.Timer(1.0, 103 ba.WeakCall(self._update), 104 timetype=ba.TimeType.REAL, 105 repeat=True) 106 self._update() 107 108 # If we've got cached power-ranking data already, apply it. 109 data = ba.app.accounts_v1.get_cached_league_rank_data() 110 if data is not None: 111 self._update_for_league_rank_data(data) 112 113 def _on_activate(self) -> None: 114 _ba.increment_analytics_count('League rank button press') 115 self._on_activate_call() 116 117 def __del__(self) -> None: 118 if self._ticking_node is not None: 119 self._ticking_node.delete() 120 121 def _start_smooth_update(self) -> None: 122 self._smooth_update_timer = ba.Timer(0.05, 123 ba.WeakCall(self._smooth_update), 124 repeat=True, 125 timetype=ba.TimeType.REAL) 126 127 def _smooth_update(self) -> None: 128 # pylint: disable=too-many-branches 129 # pylint: disable=too-many-statements 130 try: 131 if not self._button: 132 return 133 if self._ticking_node is None: 134 with ba.Context('ui'): 135 self._ticking_node = ba.newnode( 136 'sound', 137 attrs={ 138 'sound': ba.getsound('scoreIncrease'), 139 'positional': False 140 }) 141 self._bg_flash = (not self._bg_flash) 142 color_used = ((self._color[0] * 2, self._color[1] * 2, 143 self._color[2] * 144 2) if self._bg_flash else self._color) 145 textcolor_used = ((1, 1, 1) if self._bg_flash else self._textcolor) 146 header_color_used = ((1, 1, 147 1) if self._bg_flash else self._header_color) 148 149 if self._rank is not None: 150 assert self._smooth_rank is not None 151 self._smooth_rank -= 1.0 * self._smooth_increase_speed 152 finished = (int(self._smooth_rank) <= self._rank) 153 elif self._smooth_percent is not None: 154 self._smooth_percent += 1.0 * self._smooth_increase_speed 155 assert self._percent is not None 156 finished = (int(self._smooth_percent) >= self._percent) 157 else: 158 finished = True 159 if finished: 160 if self._rank is not None: 161 self._smooth_rank = float(self._rank) 162 elif self._percent is not None: 163 self._smooth_percent = float(self._percent) 164 color_used = self._color 165 textcolor_used = self._textcolor 166 self._smooth_update_timer = None 167 if self._ticking_node is not None: 168 self._ticking_node.delete() 169 self._ticking_node = None 170 ba.playsound(ba.getsound('cashRegister2')) 171 assert self._improvement_text is not None 172 diff_text = ba.textwidget( 173 parent=self._parent, 174 size=(0, 0), 175 h_align='center', 176 v_align='center', 177 text='+' + self._improvement_text + '!', 178 position=(self._position[0] + 179 self._size[0] * 0.5 * self._scale, 180 self._position[1] + 181 self._size[1] * -0.2 * self._scale), 182 color=(0, 1, 0), 183 flatness=1.0, 184 shadow=0.0, 185 scale=self._scale * 0.7) 186 187 def safe_delete(widget: ba.Widget) -> None: 188 if widget: 189 widget.delete() 190 191 ba.timer(2.0, 192 ba.Call(safe_delete, diff_text), 193 timetype=ba.TimeType.REAL) 194 status_text: str | ba.Lstr 195 if self._rank is not None: 196 assert self._smooth_rank is not None 197 status_text = ba.Lstr(resource='numberText', 198 subs=[('${NUMBER}', 199 str(int(self._smooth_rank)))]) 200 elif self._smooth_percent is not None: 201 status_text = str(int(self._smooth_percent)) + '%' 202 else: 203 status_text = '-' 204 ba.textwidget(edit=self._value_text, 205 text=status_text, 206 color=textcolor_used) 207 ba.textwidget(edit=self._title_text, color=header_color_used) 208 ba.buttonwidget(edit=self._button, color=color_used) 209 210 except Exception: 211 ba.print_exception('Error doing smooth update.') 212 self._smooth_update_timer = None 213 214 def _update_for_league_rank_data(self, 215 data: dict[str, Any] | None) -> None: 216 # pylint: disable=too-many-branches 217 # pylint: disable=too-many-statements 218 219 # If our button has died, ignore. 220 if not self._button: 221 return 222 223 status_text: str | ba.Lstr 224 225 in_top = data is not None and data['rank'] is not None 226 do_percent = False 227 if data is None or _ba.get_v1_account_state() != 'signed_in': 228 self._percent = self._rank = None 229 status_text = '-' 230 elif in_top: 231 self._percent = None 232 self._rank = data['rank'] 233 prev_league = self._league 234 self._league = data['l'] 235 236 # If this is the first set, league has changed, or rank has gotten 237 # worse, snap the smooth value immediately. 238 assert self._rank is not None 239 if (self._smooth_rank is None or prev_league != self._league 240 or self._rank > int(self._smooth_rank)): 241 self._smooth_rank = float(self._rank) 242 status_text = ba.Lstr(resource='numberText', 243 subs=[('${NUMBER}', 244 str(int(self._smooth_rank)))]) 245 else: 246 try: 247 if not data['scores'] or data['scores'][-1][1] <= 0: 248 self._percent = self._rank = None 249 status_text = '-' 250 else: 251 our_points = ba.app.accounts_v1.get_league_rank_points( 252 data) 253 progress = float(our_points) / data['scores'][-1][1] 254 self._percent = int(progress * 100.0) 255 self._rank = None 256 do_percent = True 257 prev_league = self._league 258 self._league = data['l'] 259 260 # If this is the first set, league has changed, or percent 261 # has decreased, snap the smooth value immediately. 262 if (self._smooth_percent is None 263 or prev_league != self._league 264 or self._percent < int(self._smooth_percent)): 265 self._smooth_percent = float(self._percent) 266 status_text = str(int(self._smooth_percent)) + '%' 267 268 except Exception: 269 ba.print_exception('Error updating power ranking.') 270 self._percent = self._rank = None 271 status_text = '-' 272 273 # If we're doing a smooth update, set a timer. 274 if (self._rank is not None and self._smooth_rank is not None 275 and int(self._smooth_rank) != self._rank): 276 self._improvement_text = str(-(int(self._rank) - 277 int(self._smooth_rank))) 278 diff = abs(self._rank - self._smooth_rank) 279 if diff > 100: 280 self._smooth_increase_speed = diff / 80.0 281 elif diff > 50: 282 self._smooth_increase_speed = diff / 70.0 283 elif diff > 25: 284 self._smooth_increase_speed = diff / 55.0 285 else: 286 self._smooth_increase_speed = diff / 40.0 287 self._smooth_increase_speed = max(0.4, self._smooth_increase_speed) 288 ba.timer(self._smooth_update_delay, 289 ba.WeakCall(self._start_smooth_update), 290 timetype=ba.TimeType.REAL, 291 timeformat=ba.TimeFormat.MILLISECONDS) 292 293 if (self._percent is not None and self._smooth_percent is not None 294 and int(self._smooth_percent) != self._percent): 295 self._improvement_text = str( 296 (int(self._percent) - int(self._smooth_percent))) 297 self._smooth_increase_speed = 0.3 298 ba.timer(self._smooth_update_delay, 299 ba.WeakCall(self._start_smooth_update), 300 timetype=ba.TimeType.REAL, 301 timeformat=ba.TimeFormat.MILLISECONDS) 302 303 if do_percent: 304 ba.textwidget( 305 edit=self._title_text, 306 text=ba.Lstr(resource='coopSelectWindow.toRankedText')) 307 else: 308 try: 309 assert data is not None 310 txt = ba.Lstr( 311 resource='league.leagueFullText', 312 subs=[ 313 ( 314 '${NAME}', 315 ba.Lstr(translate=('leagueNames', data['l']['n'])), 316 ), 317 ], 318 ) 319 t_color = data['l']['c'] 320 except Exception: 321 txt = ba.Lstr( 322 resource='league.leagueRankText', 323 fallback_resource='coopSelectWindow.powerRankingText') 324 t_color = ba.app.ui.title_color 325 ba.textwidget(edit=self._title_text, text=txt, color=t_color) 326 ba.textwidget(edit=self._value_text, text=status_text) 327 328 def _on_power_ranking_query_response(self, 329 data: dict[str, Any] | None) -> None: 330 self._doing_power_ranking_query = False 331 ba.app.accounts_v1.cache_league_rank_data(data) 332 self._update_for_league_rank_data(data) 333 334 def _update(self) -> None: 335 cur_time = ba.time(ba.TimeType.REAL) 336 337 # If our account state has changed, refresh our UI. 338 account_state_num = _ba.get_v1_account_state_num() 339 if account_state_num != self._account_state_num: 340 self._account_state_num = account_state_num 341 342 # And power ranking too... 343 if not self._doing_power_ranking_query: 344 self._last_power_ranking_query_time = None 345 346 # Send off a new power-ranking query if its been 347 # long enough or whatnot. 348 if not self._doing_power_ranking_query and ( 349 self._last_power_ranking_query_time is None 350 or cur_time - self._last_power_ranking_query_time > 30.0): 351 self._last_power_ranking_query_time = cur_time 352 self._doing_power_ranking_query = True 353 _ba.power_ranking_query( 354 callback=ba.WeakCall(self._on_power_ranking_query_response)) 355 356 def _default_on_activate_call(self) -> None: 357 # pylint: disable=cyclic-import 358 from bastd.ui.league.rankwindow import LeagueRankWindow 359 LeagueRankWindow(modal=True, origin_widget=self._button) 360 361 def set_position(self, position: tuple[float, float]) -> None: 362 """Set the button's position.""" 363 self._position = position 364 if not self._button: 365 return 366 ba.buttonwidget(edit=self._button, position=self._position) 367 ba.textwidget( 368 edit=self._title_text, 369 position=(self._position[0] + self._size[0] * 0.5 * self._scale, 370 self._position[1] + self._size[1] * 0.82 * self._scale)) 371 ba.textwidget( 372 edit=self._value_text, 373 position=(self._position[0] + self._size[0] * 0.5 * self._scale, 374 self._position[1] + self._size[1] * 0.36 * self._scale)) 375 376 def get_button(self) -> ba.Widget: 377 """Return the underlying button ba.Widget>""" 378 return self._button
class
LeagueRankButton:
17class LeagueRankButton: 18 """Button showing league rank.""" 19 20 def __init__(self, 21 parent: ba.Widget, 22 position: tuple[float, float], 23 size: tuple[float, float], 24 scale: float, 25 on_activate_call: Callable[[], Any] | None = None, 26 transition_delay: float | None = None, 27 color: tuple[float, float, float] | None = None, 28 textcolor: tuple[float, float, float] | None = None, 29 smooth_update_delay: float | None = None): 30 if on_activate_call is None: 31 on_activate_call = ba.WeakCall(self._default_on_activate_call) 32 self._on_activate_call = on_activate_call 33 if smooth_update_delay is None: 34 smooth_update_delay = 1000 35 self._smooth_update_delay = smooth_update_delay 36 self._size = size 37 self._scale = scale 38 if color is None: 39 color = (0.5, 0.6, 0.5) 40 if textcolor is None: 41 textcolor = (1, 1, 1) 42 self._color = color 43 self._textcolor = textcolor 44 self._header_color = (0.8, 0.8, 2.0) 45 self._parent = parent 46 self._position: tuple[float, float] = (0.0, 0.0) 47 48 self._button = ba.buttonwidget(parent=parent, 49 size=size, 50 label='', 51 button_type='square', 52 scale=scale, 53 autoselect=True, 54 on_activate_call=self._on_activate, 55 transition_delay=transition_delay, 56 color=color) 57 58 self._title_text = ba.textwidget( 59 parent=parent, 60 size=(0, 0), 61 draw_controller=self._button, 62 h_align='center', 63 v_align='center', 64 maxwidth=size[0] * scale * 0.85, 65 text=ba.Lstr( 66 resource='league.leagueRankText', 67 fallback_resource='coopSelectWindow.powerRankingText'), 68 color=self._header_color, 69 flatness=1.0, 70 shadow=1.0, 71 scale=scale * 0.5, 72 transition_delay=transition_delay) 73 74 self._value_text = ba.textwidget(parent=parent, 75 size=(0, 0), 76 h_align='center', 77 v_align='center', 78 maxwidth=size[0] * scale * 0.85, 79 text='-', 80 draw_controller=self._button, 81 big=True, 82 scale=scale, 83 transition_delay=transition_delay, 84 color=textcolor) 85 86 self._smooth_percent: float | None = None 87 self._percent: int | None = None 88 self._smooth_rank: float | None = None 89 self._rank: int | None = None 90 self._ticking_node: ba.Node | None = None 91 self._smooth_increase_speed = 1.0 92 self._league: str | None = None 93 self._improvement_text: str | None = None 94 95 self._smooth_update_timer: ba.Timer | None = None 96 97 # Take note of our account state; we'll refresh later if this changes. 98 self._account_state_num = _ba.get_v1_account_state_num() 99 self._last_power_ranking_query_time: float | None = None 100 self._doing_power_ranking_query = False 101 self.set_position(position) 102 self._bg_flash = False 103 self._update_timer = ba.Timer(1.0, 104 ba.WeakCall(self._update), 105 timetype=ba.TimeType.REAL, 106 repeat=True) 107 self._update() 108 109 # If we've got cached power-ranking data already, apply it. 110 data = ba.app.accounts_v1.get_cached_league_rank_data() 111 if data is not None: 112 self._update_for_league_rank_data(data) 113 114 def _on_activate(self) -> None: 115 _ba.increment_analytics_count('League rank button press') 116 self._on_activate_call() 117 118 def __del__(self) -> None: 119 if self._ticking_node is not None: 120 self._ticking_node.delete() 121 122 def _start_smooth_update(self) -> None: 123 self._smooth_update_timer = ba.Timer(0.05, 124 ba.WeakCall(self._smooth_update), 125 repeat=True, 126 timetype=ba.TimeType.REAL) 127 128 def _smooth_update(self) -> None: 129 # pylint: disable=too-many-branches 130 # pylint: disable=too-many-statements 131 try: 132 if not self._button: 133 return 134 if self._ticking_node is None: 135 with ba.Context('ui'): 136 self._ticking_node = ba.newnode( 137 'sound', 138 attrs={ 139 'sound': ba.getsound('scoreIncrease'), 140 'positional': False 141 }) 142 self._bg_flash = (not self._bg_flash) 143 color_used = ((self._color[0] * 2, self._color[1] * 2, 144 self._color[2] * 145 2) if self._bg_flash else self._color) 146 textcolor_used = ((1, 1, 1) if self._bg_flash else self._textcolor) 147 header_color_used = ((1, 1, 148 1) if self._bg_flash else self._header_color) 149 150 if self._rank is not None: 151 assert self._smooth_rank is not None 152 self._smooth_rank -= 1.0 * self._smooth_increase_speed 153 finished = (int(self._smooth_rank) <= self._rank) 154 elif self._smooth_percent is not None: 155 self._smooth_percent += 1.0 * self._smooth_increase_speed 156 assert self._percent is not None 157 finished = (int(self._smooth_percent) >= self._percent) 158 else: 159 finished = True 160 if finished: 161 if self._rank is not None: 162 self._smooth_rank = float(self._rank) 163 elif self._percent is not None: 164 self._smooth_percent = float(self._percent) 165 color_used = self._color 166 textcolor_used = self._textcolor 167 self._smooth_update_timer = None 168 if self._ticking_node is not None: 169 self._ticking_node.delete() 170 self._ticking_node = None 171 ba.playsound(ba.getsound('cashRegister2')) 172 assert self._improvement_text is not None 173 diff_text = ba.textwidget( 174 parent=self._parent, 175 size=(0, 0), 176 h_align='center', 177 v_align='center', 178 text='+' + self._improvement_text + '!', 179 position=(self._position[0] + 180 self._size[0] * 0.5 * self._scale, 181 self._position[1] + 182 self._size[1] * -0.2 * self._scale), 183 color=(0, 1, 0), 184 flatness=1.0, 185 shadow=0.0, 186 scale=self._scale * 0.7) 187 188 def safe_delete(widget: ba.Widget) -> None: 189 if widget: 190 widget.delete() 191 192 ba.timer(2.0, 193 ba.Call(safe_delete, diff_text), 194 timetype=ba.TimeType.REAL) 195 status_text: str | ba.Lstr 196 if self._rank is not None: 197 assert self._smooth_rank is not None 198 status_text = ba.Lstr(resource='numberText', 199 subs=[('${NUMBER}', 200 str(int(self._smooth_rank)))]) 201 elif self._smooth_percent is not None: 202 status_text = str(int(self._smooth_percent)) + '%' 203 else: 204 status_text = '-' 205 ba.textwidget(edit=self._value_text, 206 text=status_text, 207 color=textcolor_used) 208 ba.textwidget(edit=self._title_text, color=header_color_used) 209 ba.buttonwidget(edit=self._button, color=color_used) 210 211 except Exception: 212 ba.print_exception('Error doing smooth update.') 213 self._smooth_update_timer = None 214 215 def _update_for_league_rank_data(self, 216 data: dict[str, Any] | None) -> None: 217 # pylint: disable=too-many-branches 218 # pylint: disable=too-many-statements 219 220 # If our button has died, ignore. 221 if not self._button: 222 return 223 224 status_text: str | ba.Lstr 225 226 in_top = data is not None and data['rank'] is not None 227 do_percent = False 228 if data is None or _ba.get_v1_account_state() != 'signed_in': 229 self._percent = self._rank = None 230 status_text = '-' 231 elif in_top: 232 self._percent = None 233 self._rank = data['rank'] 234 prev_league = self._league 235 self._league = data['l'] 236 237 # If this is the first set, league has changed, or rank has gotten 238 # worse, snap the smooth value immediately. 239 assert self._rank is not None 240 if (self._smooth_rank is None or prev_league != self._league 241 or self._rank > int(self._smooth_rank)): 242 self._smooth_rank = float(self._rank) 243 status_text = ba.Lstr(resource='numberText', 244 subs=[('${NUMBER}', 245 str(int(self._smooth_rank)))]) 246 else: 247 try: 248 if not data['scores'] or data['scores'][-1][1] <= 0: 249 self._percent = self._rank = None 250 status_text = '-' 251 else: 252 our_points = ba.app.accounts_v1.get_league_rank_points( 253 data) 254 progress = float(our_points) / data['scores'][-1][1] 255 self._percent = int(progress * 100.0) 256 self._rank = None 257 do_percent = True 258 prev_league = self._league 259 self._league = data['l'] 260 261 # If this is the first set, league has changed, or percent 262 # has decreased, snap the smooth value immediately. 263 if (self._smooth_percent is None 264 or prev_league != self._league 265 or self._percent < int(self._smooth_percent)): 266 self._smooth_percent = float(self._percent) 267 status_text = str(int(self._smooth_percent)) + '%' 268 269 except Exception: 270 ba.print_exception('Error updating power ranking.') 271 self._percent = self._rank = None 272 status_text = '-' 273 274 # If we're doing a smooth update, set a timer. 275 if (self._rank is not None and self._smooth_rank is not None 276 and int(self._smooth_rank) != self._rank): 277 self._improvement_text = str(-(int(self._rank) - 278 int(self._smooth_rank))) 279 diff = abs(self._rank - self._smooth_rank) 280 if diff > 100: 281 self._smooth_increase_speed = diff / 80.0 282 elif diff > 50: 283 self._smooth_increase_speed = diff / 70.0 284 elif diff > 25: 285 self._smooth_increase_speed = diff / 55.0 286 else: 287 self._smooth_increase_speed = diff / 40.0 288 self._smooth_increase_speed = max(0.4, self._smooth_increase_speed) 289 ba.timer(self._smooth_update_delay, 290 ba.WeakCall(self._start_smooth_update), 291 timetype=ba.TimeType.REAL, 292 timeformat=ba.TimeFormat.MILLISECONDS) 293 294 if (self._percent is not None and self._smooth_percent is not None 295 and int(self._smooth_percent) != self._percent): 296 self._improvement_text = str( 297 (int(self._percent) - int(self._smooth_percent))) 298 self._smooth_increase_speed = 0.3 299 ba.timer(self._smooth_update_delay, 300 ba.WeakCall(self._start_smooth_update), 301 timetype=ba.TimeType.REAL, 302 timeformat=ba.TimeFormat.MILLISECONDS) 303 304 if do_percent: 305 ba.textwidget( 306 edit=self._title_text, 307 text=ba.Lstr(resource='coopSelectWindow.toRankedText')) 308 else: 309 try: 310 assert data is not None 311 txt = ba.Lstr( 312 resource='league.leagueFullText', 313 subs=[ 314 ( 315 '${NAME}', 316 ba.Lstr(translate=('leagueNames', data['l']['n'])), 317 ), 318 ], 319 ) 320 t_color = data['l']['c'] 321 except Exception: 322 txt = ba.Lstr( 323 resource='league.leagueRankText', 324 fallback_resource='coopSelectWindow.powerRankingText') 325 t_color = ba.app.ui.title_color 326 ba.textwidget(edit=self._title_text, text=txt, color=t_color) 327 ba.textwidget(edit=self._value_text, text=status_text) 328 329 def _on_power_ranking_query_response(self, 330 data: dict[str, Any] | None) -> None: 331 self._doing_power_ranking_query = False 332 ba.app.accounts_v1.cache_league_rank_data(data) 333 self._update_for_league_rank_data(data) 334 335 def _update(self) -> None: 336 cur_time = ba.time(ba.TimeType.REAL) 337 338 # If our account state has changed, refresh our UI. 339 account_state_num = _ba.get_v1_account_state_num() 340 if account_state_num != self._account_state_num: 341 self._account_state_num = account_state_num 342 343 # And power ranking too... 344 if not self._doing_power_ranking_query: 345 self._last_power_ranking_query_time = None 346 347 # Send off a new power-ranking query if its been 348 # long enough or whatnot. 349 if not self._doing_power_ranking_query and ( 350 self._last_power_ranking_query_time is None 351 or cur_time - self._last_power_ranking_query_time > 30.0): 352 self._last_power_ranking_query_time = cur_time 353 self._doing_power_ranking_query = True 354 _ba.power_ranking_query( 355 callback=ba.WeakCall(self._on_power_ranking_query_response)) 356 357 def _default_on_activate_call(self) -> None: 358 # pylint: disable=cyclic-import 359 from bastd.ui.league.rankwindow import LeagueRankWindow 360 LeagueRankWindow(modal=True, origin_widget=self._button) 361 362 def set_position(self, position: tuple[float, float]) -> None: 363 """Set the button's position.""" 364 self._position = position 365 if not self._button: 366 return 367 ba.buttonwidget(edit=self._button, position=self._position) 368 ba.textwidget( 369 edit=self._title_text, 370 position=(self._position[0] + self._size[0] * 0.5 * self._scale, 371 self._position[1] + self._size[1] * 0.82 * self._scale)) 372 ba.textwidget( 373 edit=self._value_text, 374 position=(self._position[0] + self._size[0] * 0.5 * self._scale, 375 self._position[1] + self._size[1] * 0.36 * self._scale)) 376 377 def get_button(self) -> ba.Widget: 378 """Return the underlying button ba.Widget>""" 379 return self._button
Button showing league rank.
LeagueRankButton( parent: _ba.Widget, position: tuple[float, float], size: tuple[float, float], scale: float, on_activate_call: Optional[Callable[[], Any]] = None, transition_delay: float | None = None, color: tuple[float, float, float] | None = None, textcolor: tuple[float, float, float] | None = None, smooth_update_delay: float | None = None)
20 def __init__(self, 21 parent: ba.Widget, 22 position: tuple[float, float], 23 size: tuple[float, float], 24 scale: float, 25 on_activate_call: Callable[[], Any] | None = None, 26 transition_delay: float | None = None, 27 color: tuple[float, float, float] | None = None, 28 textcolor: tuple[float, float, float] | None = None, 29 smooth_update_delay: float | None = None): 30 if on_activate_call is None: 31 on_activate_call = ba.WeakCall(self._default_on_activate_call) 32 self._on_activate_call = on_activate_call 33 if smooth_update_delay is None: 34 smooth_update_delay = 1000 35 self._smooth_update_delay = smooth_update_delay 36 self._size = size 37 self._scale = scale 38 if color is None: 39 color = (0.5, 0.6, 0.5) 40 if textcolor is None: 41 textcolor = (1, 1, 1) 42 self._color = color 43 self._textcolor = textcolor 44 self._header_color = (0.8, 0.8, 2.0) 45 self._parent = parent 46 self._position: tuple[float, float] = (0.0, 0.0) 47 48 self._button = ba.buttonwidget(parent=parent, 49 size=size, 50 label='', 51 button_type='square', 52 scale=scale, 53 autoselect=True, 54 on_activate_call=self._on_activate, 55 transition_delay=transition_delay, 56 color=color) 57 58 self._title_text = ba.textwidget( 59 parent=parent, 60 size=(0, 0), 61 draw_controller=self._button, 62 h_align='center', 63 v_align='center', 64 maxwidth=size[0] * scale * 0.85, 65 text=ba.Lstr( 66 resource='league.leagueRankText', 67 fallback_resource='coopSelectWindow.powerRankingText'), 68 color=self._header_color, 69 flatness=1.0, 70 shadow=1.0, 71 scale=scale * 0.5, 72 transition_delay=transition_delay) 73 74 self._value_text = ba.textwidget(parent=parent, 75 size=(0, 0), 76 h_align='center', 77 v_align='center', 78 maxwidth=size[0] * scale * 0.85, 79 text='-', 80 draw_controller=self._button, 81 big=True, 82 scale=scale, 83 transition_delay=transition_delay, 84 color=textcolor) 85 86 self._smooth_percent: float | None = None 87 self._percent: int | None = None 88 self._smooth_rank: float | None = None 89 self._rank: int | None = None 90 self._ticking_node: ba.Node | None = None 91 self._smooth_increase_speed = 1.0 92 self._league: str | None = None 93 self._improvement_text: str | None = None 94 95 self._smooth_update_timer: ba.Timer | None = None 96 97 # Take note of our account state; we'll refresh later if this changes. 98 self._account_state_num = _ba.get_v1_account_state_num() 99 self._last_power_ranking_query_time: float | None = None 100 self._doing_power_ranking_query = False 101 self.set_position(position) 102 self._bg_flash = False 103 self._update_timer = ba.Timer(1.0, 104 ba.WeakCall(self._update), 105 timetype=ba.TimeType.REAL, 106 repeat=True) 107 self._update() 108 109 # If we've got cached power-ranking data already, apply it. 110 data = ba.app.accounts_v1.get_cached_league_rank_data() 111 if data is not None: 112 self._update_for_league_rank_data(data)
def
set_position(self, position: tuple[float, float]) -> None:
362 def set_position(self, position: tuple[float, float]) -> None: 363 """Set the button's position.""" 364 self._position = position 365 if not self._button: 366 return 367 ba.buttonwidget(edit=self._button, position=self._position) 368 ba.textwidget( 369 edit=self._title_text, 370 position=(self._position[0] + self._size[0] * 0.5 * self._scale, 371 self._position[1] + self._size[1] * 0.82 * self._scale)) 372 ba.textwidget( 373 edit=self._value_text, 374 position=(self._position[0] + self._size[0] * 0.5 * self._scale, 375 self._position[1] + self._size[1] * 0.36 * self._scale))
Set the button's position.