bastd.ui.store.item
UI functionality related to UI items.
1# Released under the MIT License. See LICENSE for details. 2# 3"""UI functionality related to UI items.""" 4from __future__ import annotations 5 6from typing import TYPE_CHECKING 7 8import _ba 9import ba 10 11if TYPE_CHECKING: 12 from typing import Any 13 14 15def instantiate_store_item_display(item_name: str, 16 item: dict[str, Any], 17 parent_widget: ba.Widget, 18 b_pos: tuple[float, float], 19 b_width: float, 20 b_height: float, 21 boffs_h: float = 0.0, 22 boffs_h2: float = 0.0, 23 boffs_v2: float = 0, 24 delay: float = 0.0, 25 button: bool = True) -> None: 26 """(internal)""" 27 # pylint: disable=too-many-statements 28 # pylint: disable=too-many-branches 29 # pylint: disable=too-many-locals 30 from ba.internal import (get_store_item, get_store_item_name_translated, 31 get_clean_price) 32 del boffs_h # unused arg 33 del boffs_h2 # unused arg 34 del boffs_v2 # unused arg 35 item_info = get_store_item(item_name) 36 title_v = 0.24 37 price_v = 0.145 38 base_text_scale = 1.0 39 40 item['name'] = title = get_store_item_name_translated(item_name) 41 42 btn: ba.Widget | None 43 if button: 44 item['button'] = btn = ba.buttonwidget(parent=parent_widget, 45 position=b_pos, 46 transition_delay=delay, 47 show_buffer_top=76.0, 48 enable_sound=False, 49 button_type='square', 50 size=(b_width, b_height), 51 autoselect=True, 52 label='') 53 ba.widget(edit=btn, show_buffer_bottom=76.0) 54 else: 55 btn = None 56 57 b_offs_x = -0.015 * b_width 58 check_pos = 0.76 59 60 icon_tex = None 61 tint_tex = None 62 tint_color = None 63 tint2_color = None 64 tex_name: str | None = None 65 desc: str | None = None 66 modes: ba.Lstr | None = None 67 68 if item_name.startswith('characters.'): 69 character = ba.app.spaz_appearances[item_info['character']] 70 tint_color = ( 71 item_info['color'] if 'color' in item_info else 72 character.default_color if character.default_color is not None else 73 (1, 1, 1)) 74 tint2_color = (item_info['highlight'] if 'highlight' in item_info else 75 character.default_highlight if 76 character.default_highlight is not None else (1, 1, 1)) 77 icon_tex = character.icon_texture 78 tint_tex = character.icon_mask_texture 79 title_v = 0.255 80 price_v = 0.145 81 elif item_name in ['upgrades.pro', 'pro']: 82 base_text_scale = 0.6 83 title_v = 0.85 84 price_v = 0.15 85 elif item_name.startswith('maps.'): 86 map_type = item_info['map_type'] 87 tex_name = map_type.get_preview_texture_name() 88 title_v = 0.312 89 price_v = 0.17 90 91 elif item_name.startswith('games.'): 92 gametype = item_info['gametype'] 93 modes_l = [] 94 if gametype.supports_session_type(ba.CoopSession): 95 modes_l.append(ba.Lstr(resource='playModes.coopText')) 96 if gametype.supports_session_type(ba.DualTeamSession): 97 modes_l.append(ba.Lstr(resource='playModes.teamsText')) 98 if gametype.supports_session_type(ba.FreeForAllSession): 99 modes_l.append(ba.Lstr(resource='playModes.freeForAllText')) 100 101 if len(modes_l) == 3: 102 modes = ba.Lstr(value='${A}, ${B}, ${C}', 103 subs=[('${A}', modes_l[0]), ('${B}', modes_l[1]), 104 ('${C}', modes_l[2])]) 105 elif len(modes_l) == 2: 106 modes = ba.Lstr(value='${A}, ${B}', 107 subs=[('${A}', modes_l[0]), ('${B}', modes_l[1])]) 108 elif len(modes_l) == 1: 109 modes = modes_l[0] 110 else: 111 raise Exception() 112 desc = gametype.get_description_display_string(ba.CoopSession) 113 tex_name = item_info['previewTex'] 114 base_text_scale = 0.8 115 title_v = 0.48 116 price_v = 0.17 117 118 elif item_name.startswith('icons.'): 119 base_text_scale = 1.5 120 price_v = 0.2 121 check_pos = 0.6 122 123 if item_name.startswith('characters.'): 124 frame_size = b_width * 0.7 125 im_dim = frame_size * (100.0 / 113.0) 126 im_pos = (b_pos[0] + b_width * 0.5 - im_dim * 0.5 + b_offs_x, 127 b_pos[1] + b_height * 0.57 - im_dim * 0.5) 128 mask_texture = ba.gettexture('characterIconMask') 129 assert icon_tex is not None 130 assert tint_tex is not None 131 ba.imagewidget(parent=parent_widget, 132 position=im_pos, 133 size=(im_dim, im_dim), 134 color=(1, 1, 1), 135 transition_delay=delay, 136 mask_texture=mask_texture, 137 draw_controller=btn, 138 texture=ba.gettexture(icon_tex), 139 tint_texture=ba.gettexture(tint_tex), 140 tint_color=tint_color, 141 tint2_color=tint2_color) 142 143 if item_name in ['pro', 'upgrades.pro']: 144 frame_size = b_width * 0.5 145 im_dim = frame_size * (100.0 / 113.0) 146 im_pos = (b_pos[0] + b_width * 0.5 - im_dim * 0.5 + b_offs_x, 147 b_pos[1] + b_height * 0.5 - im_dim * 0.5) 148 ba.imagewidget(parent=parent_widget, 149 position=im_pos, 150 size=(im_dim, im_dim), 151 transition_delay=delay, 152 draw_controller=btn, 153 color=(0.3, 0.0, 0.3), 154 opacity=0.3, 155 texture=ba.gettexture('logo')) 156 txt = ba.Lstr(resource='store.bombSquadProNewDescriptionText') 157 158 # t = 'foo\nfoo\nfoo\nfoo\nfoo\nfoo' 159 item['descriptionText'] = ba.textwidget( 160 parent=parent_widget, 161 text=txt, 162 position=(b_pos[0] + b_width * 0.5, b_pos[1] + b_height * 0.69), 163 transition_delay=delay, 164 scale=b_width * (1.0 / 230.0) * base_text_scale * 0.75, 165 maxwidth=b_width * 0.75, 166 max_height=b_height * 0.2, 167 size=(0, 0), 168 h_align='center', 169 v_align='center', 170 draw_controller=btn, 171 color=(0.3, 1, 0.3)) 172 173 extra_backings = item['extra_backings'] = [] 174 extra_images = item['extra_images'] = [] 175 extra_texts = item['extra_texts'] = [] 176 extra_texts_2 = item['extra_texts_2'] = [] 177 178 backing_color = (0.5, 0.8, 0.3) if button else (0.6, 0.5, 0.65) 179 b_square_texture = ba.gettexture('buttonSquare') 180 char_mask_texture = ba.gettexture('characterIconMask') 181 182 pos = (0.17, 0.43) 183 tile_size = (b_width * 0.16 * 1.2, b_width * 0.2 * 1.2) 184 tile_pos = (b_pos[0] + b_width * pos[0], b_pos[1] + b_height * pos[1]) 185 extra_backings.append( 186 ba.imagewidget(parent=parent_widget, 187 position=(tile_pos[0] - tile_size[0] * 0.5, 188 tile_pos[1] - tile_size[1] * 0.5), 189 size=tile_size, 190 transition_delay=delay, 191 draw_controller=btn, 192 color=backing_color, 193 texture=b_square_texture)) 194 im_size = tile_size[0] * 0.8 195 extra_images.append( 196 ba.imagewidget(parent=parent_widget, 197 position=(tile_pos[0] - im_size * 0.5, 198 tile_pos[1] - im_size * 0.4), 199 size=(im_size, im_size), 200 transition_delay=delay, 201 draw_controller=btn, 202 color=(1, 1, 1), 203 texture=ba.gettexture('ticketsMore'))) 204 bonus_tickets = str( 205 _ba.get_v1_account_misc_read_val('proBonusTickets', 100)) 206 extra_texts.append( 207 ba.textwidget(parent=parent_widget, 208 draw_controller=btn, 209 position=(tile_pos[0] - tile_size[0] * 0.03, 210 tile_pos[1] - tile_size[1] * 0.25), 211 size=(0, 0), 212 color=(0.6, 1, 0.6), 213 transition_delay=delay, 214 h_align='center', 215 v_align='center', 216 maxwidth=tile_size[0] * 0.7, 217 scale=0.55, 218 text=ba.Lstr(resource='getTicketsWindow.ticketsText', 219 subs=[('${COUNT}', bonus_tickets)]), 220 flatness=1.0, 221 shadow=0.0)) 222 223 for charname, pos in [('Kronk', (0.32, 0.45)), ('Zoe', (0.425, 0.4)), 224 ('Jack Morgan', (0.555, 0.45)), 225 ('Mel', (0.645, 0.4))]: 226 tile_size = (b_width * 0.16 * 0.9, b_width * 0.2 * 0.9) 227 tile_pos = (b_pos[0] + b_width * pos[0], 228 b_pos[1] + b_height * pos[1]) 229 character = ba.app.spaz_appearances[charname] 230 extra_backings.append( 231 ba.imagewidget(parent=parent_widget, 232 position=(tile_pos[0] - tile_size[0] * 0.5, 233 tile_pos[1] - tile_size[1] * 0.5), 234 size=tile_size, 235 transition_delay=delay, 236 draw_controller=btn, 237 color=backing_color, 238 texture=b_square_texture)) 239 im_size = tile_size[0] * 0.7 240 extra_images.append( 241 ba.imagewidget(parent=parent_widget, 242 position=(tile_pos[0] - im_size * 0.53, 243 tile_pos[1] - im_size * 0.35), 244 size=(im_size, im_size), 245 transition_delay=delay, 246 draw_controller=btn, 247 color=(1, 1, 1), 248 texture=ba.gettexture(character.icon_texture), 249 tint_texture=ba.gettexture( 250 character.icon_mask_texture), 251 tint_color=character.default_color, 252 tint2_color=character.default_highlight, 253 mask_texture=char_mask_texture)) 254 extra_texts.append( 255 ba.textwidget(parent=parent_widget, 256 draw_controller=btn, 257 position=(tile_pos[0] - im_size * 0.03, 258 tile_pos[1] - im_size * 0.51), 259 size=(0, 0), 260 color=(0.6, 1, 0.6), 261 transition_delay=delay, 262 h_align='center', 263 v_align='center', 264 maxwidth=tile_size[0] * 0.7, 265 scale=0.55, 266 text=ba.Lstr(translate=('characterNames', 267 charname)), 268 flatness=1.0, 269 shadow=0.0)) 270 271 # If we have a 'total-worth' item-id for this id, show that price so 272 # the user knows how much this is worth. 273 total_worth_item = _ba.get_v1_account_misc_read_val('twrths', 274 {}).get(item_name) 275 total_worth_price: str | None 276 if total_worth_item is not None: 277 price = _ba.get_price(total_worth_item) 278 total_worth_price = (get_clean_price(price) 279 if price is not None else '??') 280 else: 281 total_worth_price = None 282 283 if total_worth_price is not None: 284 total_worth_text = ba.Lstr(resource='store.totalWorthText', 285 subs=[('${TOTAL_WORTH}', 286 total_worth_price)]) 287 extra_texts_2.append( 288 ba.textwidget(parent=parent_widget, 289 text=total_worth_text, 290 position=(b_pos[0] + b_width * 0.5 + b_offs_x, 291 b_pos[1] + b_height * 0.25), 292 transition_delay=delay, 293 scale=b_width * (1.0 / 230.0) * base_text_scale * 294 0.45, 295 maxwidth=b_width * 0.5, 296 size=(0, 0), 297 h_align='center', 298 v_align='center', 299 shadow=1.0, 300 flatness=1.0, 301 draw_controller=btn, 302 color=(0.3, 1, 1))) 303 304 model_opaque = ba.getmodel('level_select_button_opaque') 305 model_transparent = ba.getmodel('level_select_button_transparent') 306 mask_tex = ba.gettexture('mapPreviewMask') 307 for levelname, preview_tex_name, pos in [ 308 ('Infinite Onslaught', 'doomShroomPreview', (0.80, 0.48)), 309 ('Infinite Runaround', 'towerDPreview', (0.80, 0.32)) 310 ]: 311 tile_size = (b_width * 0.2, b_width * 0.13) 312 tile_pos = (b_pos[0] + b_width * pos[0], 313 b_pos[1] + b_height * pos[1]) 314 im_size = tile_size[0] * 0.8 315 extra_backings.append( 316 ba.imagewidget(parent=parent_widget, 317 position=(tile_pos[0] - tile_size[0] * 0.5, 318 tile_pos[1] - tile_size[1] * 0.5), 319 size=tile_size, 320 transition_delay=delay, 321 draw_controller=btn, 322 color=backing_color, 323 texture=b_square_texture)) 324 325 # Hack - gotta draw two transparent versions to avoid z issues. 326 for mod in model_opaque, model_transparent: 327 extra_images.append( 328 ba.imagewidget(parent=parent_widget, 329 position=(tile_pos[0] - im_size * 0.52, 330 tile_pos[1] - im_size * 0.2), 331 size=(im_size, im_size * 0.5), 332 transition_delay=delay, 333 model_transparent=mod, 334 mask_texture=mask_tex, 335 draw_controller=btn, 336 texture=ba.gettexture(preview_tex_name))) 337 338 extra_texts.append( 339 ba.textwidget(parent=parent_widget, 340 draw_controller=btn, 341 position=(tile_pos[0] - im_size * 0.03, 342 tile_pos[1] - im_size * 0.2), 343 size=(0, 0), 344 color=(0.6, 1, 0.6), 345 transition_delay=delay, 346 h_align='center', 347 v_align='center', 348 maxwidth=tile_size[0] * 0.7, 349 scale=0.55, 350 text=ba.Lstr(translate=('coopLevelNames', 351 levelname)), 352 flatness=1.0, 353 shadow=0.0)) 354 355 if item_name.startswith('icons.'): 356 item['icon_text'] = ba.textwidget( 357 parent=parent_widget, 358 text=item_info['icon'], 359 position=(b_pos[0] + b_width * 0.5, b_pos[1] + b_height * 0.5), 360 transition_delay=delay, 361 scale=b_width * (1.0 / 230.0) * base_text_scale * 2.0, 362 maxwidth=b_width * 0.9, 363 max_height=b_height * 0.9, 364 size=(0, 0), 365 h_align='center', 366 v_align='center', 367 draw_controller=btn) 368 369 if item_name.startswith('maps.'): 370 frame_size = b_width * 0.9 371 im_dim = frame_size * (100.0 / 113.0) 372 im_pos = (b_pos[0] + b_width * 0.5 - im_dim * 0.5 + b_offs_x, 373 b_pos[1] + b_height * 0.62 - im_dim * 0.25) 374 model_opaque = ba.getmodel('level_select_button_opaque') 375 model_transparent = ba.getmodel('level_select_button_transparent') 376 mask_tex = ba.gettexture('mapPreviewMask') 377 assert tex_name is not None 378 ba.imagewidget(parent=parent_widget, 379 position=im_pos, 380 size=(im_dim, im_dim * 0.5), 381 transition_delay=delay, 382 model_opaque=model_opaque, 383 model_transparent=model_transparent, 384 mask_texture=mask_tex, 385 draw_controller=btn, 386 texture=ba.gettexture(tex_name)) 387 388 if item_name.startswith('games.'): 389 frame_size = b_width * 0.8 390 im_dim = frame_size * (100.0 / 113.0) 391 im_pos = (b_pos[0] + b_width * 0.5 - im_dim * 0.5 + b_offs_x, 392 b_pos[1] + b_height * 0.72 - im_dim * 0.25) 393 model_opaque = ba.getmodel('level_select_button_opaque') 394 model_transparent = ba.getmodel('level_select_button_transparent') 395 mask_tex = ba.gettexture('mapPreviewMask') 396 assert tex_name is not None 397 ba.imagewidget(parent=parent_widget, 398 position=im_pos, 399 size=(im_dim, im_dim * 0.5), 400 transition_delay=delay, 401 model_opaque=model_opaque, 402 model_transparent=model_transparent, 403 mask_texture=mask_tex, 404 draw_controller=btn, 405 texture=ba.gettexture(tex_name)) 406 item['descriptionText'] = ba.textwidget( 407 parent=parent_widget, 408 text=desc, 409 position=(b_pos[0] + b_width * 0.5, b_pos[1] + b_height * 0.36), 410 transition_delay=delay, 411 scale=b_width * (1.0 / 230.0) * base_text_scale * 0.78, 412 maxwidth=b_width * 0.8, 413 max_height=b_height * 0.14, 414 size=(0, 0), 415 h_align='center', 416 v_align='center', 417 draw_controller=btn, 418 flatness=1.0, 419 shadow=0.0, 420 color=(0.6, 1, 0.6)) 421 item['gameModesText'] = ba.textwidget( 422 parent=parent_widget, 423 text=modes, 424 position=(b_pos[0] + b_width * 0.5, b_pos[1] + b_height * 0.26), 425 transition_delay=delay, 426 scale=b_width * (1.0 / 230.0) * base_text_scale * 0.65, 427 maxwidth=b_width * 0.8, 428 size=(0, 0), 429 h_align='center', 430 v_align='center', 431 draw_controller=btn, 432 shadow=0, 433 flatness=1.0, 434 color=(0.6, 0.8, 0.6)) 435 436 if not item_name.startswith('icons.'): 437 item['title_text'] = ba.textwidget( 438 parent=parent_widget, 439 text=title, 440 position=(b_pos[0] + b_width * 0.5 + b_offs_x, 441 b_pos[1] + b_height * title_v), 442 transition_delay=delay, 443 scale=b_width * (1.0 / 230.0) * base_text_scale, 444 maxwidth=b_width * 0.8, 445 size=(0, 0), 446 h_align='center', 447 v_align='center', 448 draw_controller=btn, 449 color=(0.7, 0.9, 0.7, 1.0)) 450 451 item['purchase_check'] = ba.imagewidget( 452 parent=parent_widget, 453 position=(b_pos[0] + b_width * check_pos, b_pos[1] + b_height * 0.05), 454 transition_delay=delay, 455 model_transparent=ba.getmodel('checkTransparent'), 456 opacity=0.0, 457 size=(60, 60), 458 color=(0.6, 0.5, 0.8), 459 draw_controller=btn, 460 texture=ba.gettexture('uiAtlas')) 461 item['price_widget'] = ba.textwidget( 462 parent=parent_widget, 463 text='', 464 position=(b_pos[0] + b_width * 0.5 + b_offs_x, 465 b_pos[1] + b_height * price_v), 466 transition_delay=delay, 467 scale=b_width * (1.0 / 300.0) * base_text_scale, 468 maxwidth=b_width * 0.9, 469 size=(0, 0), 470 h_align='center', 471 v_align='center', 472 draw_controller=btn, 473 color=(0.2, 1, 0.2, 1.0)) 474 item['price_widget_left'] = ba.textwidget( 475 parent=parent_widget, 476 text='', 477 position=(b_pos[0] + b_width * 0.33 + b_offs_x, 478 b_pos[1] + b_height * price_v), 479 transition_delay=delay, 480 scale=b_width * (1.0 / 300.0) * base_text_scale, 481 maxwidth=b_width * 0.3, 482 size=(0, 0), 483 h_align='center', 484 v_align='center', 485 draw_controller=btn, 486 color=(0.2, 1, 0.2, 0.5)) 487 item['price_widget_right'] = ba.textwidget( 488 parent=parent_widget, 489 text='', 490 position=(b_pos[0] + b_width * 0.66 + b_offs_x, 491 b_pos[1] + b_height * price_v), 492 transition_delay=delay, 493 scale=1.1 * b_width * (1.0 / 300.0) * base_text_scale, 494 maxwidth=b_width * 0.3, 495 size=(0, 0), 496 h_align='center', 497 v_align='center', 498 draw_controller=btn, 499 color=(0.2, 1, 0.2, 1.0)) 500 item['price_slash_widget'] = ba.imagewidget( 501 parent=parent_widget, 502 position=(b_pos[0] + b_width * 0.33 + b_offs_x - 36, 503 b_pos[1] + b_height * price_v - 35), 504 transition_delay=delay, 505 texture=ba.gettexture('slash'), 506 opacity=0.0, 507 size=(70, 70), 508 draw_controller=btn, 509 color=(1, 0, 0)) 510 badge_rad = 44 511 badge_center = (b_pos[0] + b_width * 0.1 + b_offs_x, 512 b_pos[1] + b_height * 0.87) 513 item['sale_bg_widget'] = ba.imagewidget( 514 parent=parent_widget, 515 position=(badge_center[0] - badge_rad, badge_center[1] - badge_rad), 516 opacity=0.0, 517 transition_delay=delay, 518 texture=ba.gettexture('circleZigZag'), 519 draw_controller=btn, 520 size=(badge_rad * 2, badge_rad * 2), 521 color=(0.5, 0, 1)) 522 item['sale_title_widget'] = ba.textwidget(parent=parent_widget, 523 position=(badge_center[0], 524 badge_center[1] + 12), 525 transition_delay=delay, 526 scale=1.0, 527 maxwidth=badge_rad * 1.6, 528 size=(0, 0), 529 h_align='center', 530 v_align='center', 531 draw_controller=btn, 532 shadow=0.0, 533 flatness=1.0, 534 color=(0, 1, 0)) 535 item['sale_time_widget'] = ba.textwidget(parent=parent_widget, 536 position=(badge_center[0], 537 badge_center[1] - 12), 538 transition_delay=delay, 539 scale=0.7, 540 maxwidth=badge_rad * 1.6, 541 size=(0, 0), 542 h_align='center', 543 v_align='center', 544 draw_controller=btn, 545 shadow=0.0, 546 flatness=1.0, 547 color=(0.0, 1, 0.0, 1))