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