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