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