bauiv1lib.play
Provides the top level play window.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides the top level play window.""" 4 5from __future__ import annotations 6 7import logging 8from typing import override, TYPE_CHECKING 9 10import bascenev1 as bs 11import bauiv1 as bui 12 13if TYPE_CHECKING: 14 from bauiv1 import MainWindowState 15 16 17class PlaylistSelectContext: 18 """For using PlayWindow to select a playlist instead of running game.""" 19 20 back_state: MainWindowState | None = None 21 22 23class PlayWindow(bui.MainWindow): 24 """Window for selecting overall play type.""" 25 26 def __init__( 27 self, 28 transition: str | None = 'in_right', 29 origin_widget: bui.Widget | None = None, 30 playlist_select_context: PlaylistSelectContext | None = None, 31 ): 32 # pylint: disable=too-many-statements 33 # pylint: disable=too-many-locals 34 35 # Preload some modules we use in a background thread so we won't 36 # have a visual hitch when the user taps them. 37 bui.app.threadpool.submit_no_wait(self._preload_modules) 38 39 classic = bui.app.classic 40 assert classic is not None 41 42 self._playlist_select_context = playlist_select_context 43 44 uiscale = bui.app.ui_v1.uiscale 45 width = 1100 if uiscale is bui.UIScale.SMALL else 1000 46 x_offs = 150 if uiscale is bui.UIScale.SMALL else 90 47 y_offs = -60 if uiscale is bui.UIScale.SMALL else 45 48 height = 650 if uiscale is bui.UIScale.SMALL else 550 49 button_width = 400 50 51 if origin_widget is not None: 52 53 # Need to store this ourself since we can function as a 54 # non-main window. 55 self._transition_out = 'out_scale' 56 else: 57 self._transition_out = 'out_right' 58 59 self._r = 'playWindow' 60 61 super().__init__( 62 root_widget=bui.containerwidget( 63 size=(width, height), 64 toolbar_visibility=( 65 'menu_full' 66 if playlist_select_context is None 67 else 'menu_minimal' 68 ), 69 scale=( 70 1.35 71 if uiscale is bui.UIScale.SMALL 72 else 0.9 if uiscale is bui.UIScale.MEDIUM else 0.8 73 ), 74 stack_offset=( 75 (0, 20) if uiscale is bui.UIScale.SMALL else (0, 0) 76 ), 77 ), 78 transition=transition, 79 origin_widget=origin_widget, 80 ) 81 82 self._back_button: bui.Widget | None 83 if uiscale is bui.UIScale.SMALL: 84 self._back_button = None 85 bui.containerwidget( 86 edit=self._root_widget, 87 on_cancel_call=self.main_window_back, 88 ) 89 else: 90 self._back_button = bui.buttonwidget( 91 parent=self._root_widget, 92 position=(5 + x_offs, height - 162 + y_offs), 93 size=(60, 60), 94 scale=1.1, 95 text_res_scale=1.5, 96 text_scale=1.2, 97 autoselect=True, 98 label=bui.charstr(bui.SpecialChar.BACK), 99 button_type='backSmall', 100 on_activate_call=self.main_window_back, 101 ) 102 bui.containerwidget( 103 edit=self._root_widget, cancel_button=self._back_button 104 ) 105 106 bui.textwidget( 107 parent=self._root_widget, 108 position=( 109 width * 0.5, 110 height - (83 if uiscale is bui.UIScale.SMALL else 131) + y_offs, 111 ), 112 size=(0, 0), 113 text=bui.Lstr( 114 resource=( 115 (f'{self._r}.titleText') 116 if self._playlist_select_context is None 117 else 'playlistsText' 118 ) 119 ), 120 scale=1.2 if uiscale is bui.UIScale.SMALL else 1.7, 121 res_scale=2.0, 122 maxwidth=400, 123 color=bui.app.ui_v1.heading_color, 124 h_align='center', 125 v_align='center', 126 ) 127 v = ( 128 height 129 - (110 if self._playlist_select_context is None else 90) 130 + y_offs 131 ) 132 v -= 100 133 clr = (0.6, 0.7, 0.6, 1.0) 134 v -= 270 if self._playlist_select_context is None else 280 135 v += 65 if uiscale is bui.UIScale.SMALL else 0 136 hoffs = ( 137 x_offs - 45 138 if self._playlist_select_context is None 139 else x_offs - 100 140 ) 141 scl = 0.75 if self._playlist_select_context is None else 0.68 142 143 self._lineup_tex = bui.gettexture('playerLineup') 144 angry_computer_transparent_mesh = bui.getmesh( 145 'angryComputerTransparent' 146 ) 147 self._lineup_1_transparent_mesh = bui.getmesh( 148 'playerLineup1Transparent' 149 ) 150 self._lineup_2_transparent_mesh = bui.getmesh( 151 'playerLineup2Transparent' 152 ) 153 self._lineup_3_transparent_mesh = bui.getmesh( 154 'playerLineup3Transparent' 155 ) 156 self._lineup_4_transparent_mesh = bui.getmesh( 157 'playerLineup4Transparent' 158 ) 159 self._eyes_mesh = bui.getmesh('plasticEyesTransparent') 160 161 self._coop_button: bui.Widget | None = None 162 163 # Only show coop button in regular variant. 164 if self._playlist_select_context is None: 165 self._coop_button = btn = bui.buttonwidget( 166 parent=self._root_widget, 167 position=(hoffs, v), 168 size=( 169 scl * button_width, 170 scl * 360, 171 ), 172 extra_touch_border_scale=0.1, 173 autoselect=True, 174 label='', 175 button_type='square', 176 on_activate_call=self._coop, 177 ) 178 179 if uiscale is bui.UIScale.SMALL: 180 bui.widget( 181 edit=btn, 182 left_widget=bui.get_special_widget('back_button'), 183 ) 184 bui.widget( 185 edit=btn, 186 up_widget=bui.get_special_widget('account_button'), 187 ) 188 bui.widget( 189 edit=btn, 190 down_widget=bui.get_special_widget('settings_button'), 191 ) 192 193 self._draw_dude( 194 0, 195 btn, 196 hoffs, 197 v, 198 scl, 199 position=(140, 30), 200 color=(0.72, 0.4, 1.0), 201 ) 202 self._draw_dude( 203 1, 204 btn, 205 hoffs, 206 v, 207 scl, 208 position=(185, 53), 209 color=(0.71, 0.5, 1.0), 210 ) 211 self._draw_dude( 212 2, 213 btn, 214 hoffs, 215 v, 216 scl, 217 position=(220, 27), 218 color=(0.67, 0.44, 1.0), 219 ) 220 self._draw_dude( 221 3, btn, hoffs, v, scl, position=(255, 57), color=(0.7, 0.3, 1.0) 222 ) 223 bui.imagewidget( 224 parent=self._root_widget, 225 draw_controller=btn, 226 position=(hoffs + scl * 230, v + scl * 153), 227 size=(scl * 115, scl * 115), 228 texture=self._lineup_tex, 229 mesh_transparent=angry_computer_transparent_mesh, 230 ) 231 232 bui.textwidget( 233 parent=self._root_widget, 234 draw_controller=btn, 235 position=(hoffs + scl * (-10), v + scl * 95), 236 size=(scl * button_width, scl * 50), 237 text=bui.Lstr( 238 resource='playModes.singlePlayerCoopText', 239 fallback_resource='playModes.coopText', 240 ), 241 maxwidth=scl * button_width * 0.7, 242 res_scale=1.5, 243 h_align='center', 244 v_align='center', 245 color=(0.7, 0.9, 0.7, 1.0), 246 scale=scl * 1.5, 247 ) 248 249 bui.textwidget( 250 parent=self._root_widget, 251 draw_controller=btn, 252 position=(hoffs + scl * (-10), v + (scl * 54)), 253 size=(scl * button_width, scl * 30), 254 text=bui.Lstr(resource=f'{self._r}.oneToFourPlayersText'), 255 h_align='center', 256 v_align='center', 257 scale=0.83 * scl, 258 flatness=1.0, 259 maxwidth=scl * button_width * 0.7, 260 color=clr, 261 ) 262 263 scl = 0.75 if self._playlist_select_context is None else 0.68 264 hoffs += 300 if self._playlist_select_context is None else 216 265 # v += 0 if self._playlist_select_context is None else -68 266 267 self._teams_button = btn = bui.buttonwidget( 268 parent=self._root_widget, 269 position=( 270 hoffs, 271 v, 272 # v + (scl * 15 if 273 # self._playlist_select_context is None else 0), 274 ), 275 size=( 276 scl * button_width, 277 scl * (360 if self._playlist_select_context is None else 360), 278 ), 279 extra_touch_border_scale=0.1, 280 autoselect=True, 281 label='', 282 button_type='square', 283 on_activate_call=self._team_tourney, 284 ) 285 286 xxx = -14 287 self._draw_dude( 288 2, 289 btn, 290 hoffs, 291 v, 292 scl, 293 position=(xxx + 148, 30), 294 color=(0.2, 0.4, 1.0), 295 ) 296 self._draw_dude( 297 3, 298 btn, 299 hoffs, 300 v, 301 scl, 302 position=(xxx + 181, 53), 303 color=(0.3, 0.4, 1.0), 304 ) 305 self._draw_dude( 306 1, 307 btn, 308 hoffs, 309 v, 310 scl, 311 position=(xxx + 216, 33), 312 color=(0.3, 0.5, 1.0), 313 ) 314 self._draw_dude( 315 0, 316 btn, 317 hoffs, 318 v, 319 scl, 320 position=(xxx + 245, 57), 321 color=(0.3, 0.5, 1.0), 322 ) 323 324 xxx = 155 325 self._draw_dude( 326 0, 327 btn, 328 hoffs, 329 v, 330 scl, 331 position=(xxx + 151, 30), 332 color=(1.0, 0.5, 0.4), 333 ) 334 self._draw_dude( 335 1, 336 btn, 337 hoffs, 338 v, 339 scl, 340 position=(xxx + 189, 53), 341 color=(1.0, 0.58, 0.58), 342 ) 343 self._draw_dude( 344 3, 345 btn, 346 hoffs, 347 v, 348 scl, 349 position=(xxx + 223, 27), 350 color=(1.0, 0.5, 0.5), 351 ) 352 self._draw_dude( 353 2, 354 btn, 355 hoffs, 356 v, 357 scl, 358 position=(xxx + 257, 57), 359 color=(1.0, 0.5, 0.5), 360 ) 361 362 bui.textwidget( 363 parent=self._root_widget, 364 draw_controller=btn, 365 position=(hoffs + scl * (-10), v + scl * 95), 366 size=(scl * button_width, scl * 50), 367 text=bui.Lstr( 368 resource='playModes.teamsText', fallback_resource='teamsText' 369 ), 370 res_scale=1.5, 371 maxwidth=scl * button_width * 0.7, 372 h_align='center', 373 v_align='center', 374 color=(0.7, 0.9, 0.7, 1.0), 375 scale=scl * 1.5, 376 ) 377 bui.textwidget( 378 parent=self._root_widget, 379 draw_controller=btn, 380 position=(hoffs + scl * (-10), v + (scl * 54)), 381 size=(scl * button_width, scl * 30), 382 text=bui.Lstr(resource=f'{self._r}.twoToEightPlayersText'), 383 h_align='center', 384 v_align='center', 385 res_scale=1.5, 386 scale=0.83 * scl, 387 flatness=1.0, 388 maxwidth=scl * button_width * 0.7, 389 color=clr, 390 ) 391 392 hoffs += 300 if self._playlist_select_context is None else 300 393 # v -= 0 if self._playlist_select_context is None else 0 394 self._free_for_all_button = btn = bui.buttonwidget( 395 parent=self._root_widget, 396 position=( 397 hoffs, 398 v, 399 # v + (scl * 15 400 # if self._playlist_select_context is None else 0), 401 ), 402 size=( 403 scl * button_width, 404 scl * (360 if self._playlist_select_context is None else 360), 405 ), 406 extra_touch_border_scale=0.1, 407 autoselect=True, 408 label='', 409 button_type='square', 410 on_activate_call=self._free_for_all, 411 ) 412 413 xxx = -5 414 self._draw_dude( 415 0, 416 btn, 417 hoffs, 418 v, 419 scl, 420 position=(xxx + 140, 30), 421 color=(0.4, 1.0, 0.4), 422 ) 423 self._draw_dude( 424 3, 425 btn, 426 hoffs, 427 v, 428 scl, 429 position=(xxx + 185, 53), 430 color=(1.0, 0.4, 0.5), 431 ) 432 self._draw_dude( 433 1, 434 btn, 435 hoffs, 436 v, 437 scl, 438 position=(xxx + 220, 27), 439 color=(0.4, 0.5, 1.0), 440 ) 441 self._draw_dude( 442 2, 443 btn, 444 hoffs, 445 v, 446 scl, 447 position=(xxx + 255, 57), 448 color=(0.5, 1.0, 0.4), 449 ) 450 xxx = 140 451 self._draw_dude( 452 2, 453 btn, 454 hoffs, 455 v, 456 scl, 457 position=(xxx + 148, 30), 458 color=(1.0, 0.9, 0.4), 459 ) 460 self._draw_dude( 461 0, 462 btn, 463 hoffs, 464 v, 465 scl, 466 position=(xxx + 182, 53), 467 color=(0.7, 1.0, 0.5), 468 ) 469 self._draw_dude( 470 3, 471 btn, 472 hoffs, 473 v, 474 scl, 475 position=(xxx + 233, 27), 476 color=(0.7, 0.5, 0.9), 477 ) 478 self._draw_dude( 479 1, 480 btn, 481 hoffs, 482 v, 483 scl, 484 position=(xxx + 266, 53), 485 color=(0.4, 0.5, 0.8), 486 ) 487 bui.textwidget( 488 parent=self._root_widget, 489 draw_controller=btn, 490 position=(hoffs + scl * (-10), v + scl * 95), 491 size=(scl * button_width, scl * 50), 492 text=bui.Lstr( 493 resource='playModes.freeForAllText', 494 fallback_resource='freeForAllText', 495 ), 496 maxwidth=scl * button_width * 0.7, 497 h_align='center', 498 v_align='center', 499 color=(0.7, 0.9, 0.7, 1.0), 500 scale=scl * 1.5, 501 ) 502 bui.textwidget( 503 parent=self._root_widget, 504 draw_controller=btn, 505 position=(hoffs + scl * (-10), v + (scl * 54)), 506 size=(scl * button_width, scl * 30), 507 text=bui.Lstr(resource=f'{self._r}.twoToEightPlayersText'), 508 h_align='center', 509 v_align='center', 510 scale=0.83 * scl, 511 flatness=1.0, 512 maxwidth=scl * button_width * 0.7, 513 color=clr, 514 ) 515 516 if uiscale is bui.UIScale.SMALL: 517 bui.containerwidget( 518 edit=self._root_widget, 519 selected_child=( 520 self._coop_button 521 if self._playlist_select_context is None 522 else self._teams_button 523 ), 524 ) 525 else: 526 bui.containerwidget( 527 edit=self._root_widget, 528 selected_child=( 529 self._coop_button 530 if self._playlist_select_context is None 531 else self._teams_button 532 ), 533 ) 534 535 self._restore_state() 536 537 @override 538 def get_main_window_state(self) -> bui.MainWindowState: 539 # Support recreating our window for back/refresh purposes. 540 cls = type(self) 541 542 # Pull any values out of self here; if we do it in the lambda 543 # we'll keep our window alive inadvertantly. 544 playlist_select_context = self._playlist_select_context 545 return bui.BasicMainWindowState( 546 create_call=lambda transition, origin_widget: cls( 547 transition=transition, 548 origin_widget=origin_widget, 549 playlist_select_context=playlist_select_context, 550 ) 551 ) 552 553 @override 554 def on_main_window_close(self) -> None: 555 self._save_state() 556 557 @staticmethod 558 def _preload_modules() -> None: 559 """Preload modules we use; avoids hitches (called in bg thread).""" 560 import bauiv1lib.mainmenu as _unused1 561 import bauiv1lib.account as _unused2 562 import bauiv1lib.coop.browser as _unused3 563 import bauiv1lib.playlist.browser as _unused4 564 565 def _coop(self) -> None: 566 # pylint: disable=cyclic-import 567 from bauiv1lib.account.signin import show_sign_in_prompt 568 from bauiv1lib.coop.browser import CoopBrowserWindow 569 570 # no-op if we're not currently in control. 571 if not self.main_window_has_control(): 572 return 573 574 plus = bui.app.plus 575 assert plus is not None 576 577 if plus.get_v1_account_state() != 'signed_in': 578 show_sign_in_prompt() 579 return 580 581 self.main_window_replace( 582 CoopBrowserWindow(origin_widget=self._coop_button) 583 ) 584 585 def _team_tourney(self) -> None: 586 # pylint: disable=cyclic-import 587 from bauiv1lib.playlist.browser import PlaylistBrowserWindow 588 589 # no-op if we're not currently in control. 590 if not self.main_window_has_control(): 591 return 592 593 self.main_window_replace( 594 PlaylistBrowserWindow( 595 origin_widget=self._teams_button, 596 sessiontype=bs.DualTeamSession, 597 playlist_select_context=self._playlist_select_context, 598 ) 599 ) 600 601 def _free_for_all(self) -> None: 602 # pylint: disable=cyclic-import 603 from bauiv1lib.playlist.browser import PlaylistBrowserWindow 604 605 # no-op if we're not currently in control. 606 if not self.main_window_has_control(): 607 return 608 609 self.main_window_replace( 610 PlaylistBrowserWindow( 611 origin_widget=self._free_for_all_button, 612 sessiontype=bs.FreeForAllSession, 613 playlist_select_context=self._playlist_select_context, 614 ) 615 ) 616 617 def _draw_dude( 618 self, 619 i: int, 620 btn: bui.Widget, 621 hoffs: float, 622 v: float, 623 scl: float, 624 position: tuple[float, float], 625 color: tuple[float, float, float], 626 ) -> None: 627 # pylint: disable=too-many-positional-arguments 628 h_extra = -100 629 v_extra = 130 630 eye_color = ( 631 0.7 * 1.0 + 0.3 * color[0], 632 0.7 * 1.0 + 0.3 * color[1], 633 0.7 * 1.0 + 0.3 * color[2], 634 ) 635 if i == 0: 636 bui.imagewidget( 637 parent=self._root_widget, 638 draw_controller=btn, 639 position=( 640 hoffs + scl * (h_extra + position[0]), 641 v + scl * (v_extra + position[1]), 642 ), 643 size=(scl * 60, scl * 80), 644 color=color, 645 texture=self._lineup_tex, 646 mesh_transparent=self._lineup_1_transparent_mesh, 647 ) 648 bui.imagewidget( 649 parent=self._root_widget, 650 draw_controller=btn, 651 position=( 652 hoffs + scl * (h_extra + position[0] + 12), 653 v + scl * (v_extra + position[1] + 53), 654 ), 655 size=(scl * 36, scl * 18), 656 texture=self._lineup_tex, 657 color=eye_color, 658 mesh_transparent=self._eyes_mesh, 659 ) 660 elif i == 1: 661 bui.imagewidget( 662 parent=self._root_widget, 663 draw_controller=btn, 664 position=( 665 hoffs + scl * (h_extra + position[0]), 666 v + scl * (v_extra + position[1]), 667 ), 668 size=(scl * 45, scl * 90), 669 color=color, 670 texture=self._lineup_tex, 671 mesh_transparent=self._lineup_2_transparent_mesh, 672 ) 673 bui.imagewidget( 674 parent=self._root_widget, 675 draw_controller=btn, 676 position=( 677 hoffs + scl * (h_extra + position[0] + 5), 678 v + scl * (v_extra + position[1] + 67), 679 ), 680 size=(scl * 32, scl * 16), 681 texture=self._lineup_tex, 682 color=eye_color, 683 mesh_transparent=self._eyes_mesh, 684 ) 685 elif i == 2: 686 bui.imagewidget( 687 parent=self._root_widget, 688 draw_controller=btn, 689 position=( 690 hoffs + scl * (h_extra + position[0]), 691 v + scl * (v_extra + position[1]), 692 ), 693 size=(scl * 45, scl * 90), 694 color=color, 695 texture=self._lineup_tex, 696 mesh_transparent=self._lineup_3_transparent_mesh, 697 ) 698 bui.imagewidget( 699 parent=self._root_widget, 700 draw_controller=btn, 701 position=( 702 hoffs + scl * (h_extra + position[0] + 5), 703 v + scl * (v_extra + position[1] + 59), 704 ), 705 size=(scl * 34, scl * 17), 706 texture=self._lineup_tex, 707 color=eye_color, 708 mesh_transparent=self._eyes_mesh, 709 ) 710 elif i == 3: 711 bui.imagewidget( 712 parent=self._root_widget, 713 draw_controller=btn, 714 position=( 715 hoffs + scl * (h_extra + position[0]), 716 v + scl * (v_extra + position[1]), 717 ), 718 size=(scl * 48, scl * 96), 719 color=color, 720 texture=self._lineup_tex, 721 mesh_transparent=self._lineup_4_transparent_mesh, 722 ) 723 bui.imagewidget( 724 parent=self._root_widget, 725 draw_controller=btn, 726 position=( 727 hoffs + scl * (h_extra + position[0] + 2), 728 v + scl * (v_extra + position[1] + 62), 729 ), 730 size=(scl * 38, scl * 19), 731 texture=self._lineup_tex, 732 color=eye_color, 733 mesh_transparent=self._eyes_mesh, 734 ) 735 736 def _save_state(self) -> None: 737 try: 738 sel = self._root_widget.get_selected_child() 739 if sel == self._teams_button: 740 sel_name = 'Team Games' 741 elif self._coop_button is not None and sel == self._coop_button: 742 sel_name = 'Co-op Games' 743 elif sel == self._free_for_all_button: 744 sel_name = 'Free-for-All Games' 745 elif sel == self._back_button: 746 sel_name = 'Back' 747 else: 748 raise ValueError(f'unrecognized selection {sel}') 749 assert bui.app.classic is not None 750 bui.app.ui_v1.window_states[type(self)] = sel_name 751 except Exception: 752 logging.exception('Error saving state for %s.', self) 753 754 def _restore_state(self) -> None: 755 try: 756 assert bui.app.classic is not None 757 sel_name = bui.app.ui_v1.window_states.get(type(self)) 758 if sel_name == 'Team Games': 759 sel = self._teams_button 760 elif sel_name == 'Co-op Games' and self._coop_button is not None: 761 sel = self._coop_button 762 elif sel_name == 'Free-for-All Games': 763 sel = self._free_for_all_button 764 elif sel_name == 'Back' and self._back_button is not None: 765 sel = self._back_button 766 else: 767 sel = ( 768 self._coop_button 769 if self._coop_button is not None 770 else self._teams_button 771 ) 772 bui.containerwidget(edit=self._root_widget, selected_child=sel) 773 except Exception: 774 logging.exception('Error restoring state for %s.', self)
class
PlaylistSelectContext:
18class PlaylistSelectContext: 19 """For using PlayWindow to select a playlist instead of running game.""" 20 21 back_state: MainWindowState | None = None
For using PlayWindow to select a playlist instead of running game.
class
PlayWindow(bauiv1._uitypes.MainWindow):
24class PlayWindow(bui.MainWindow): 25 """Window for selecting overall play type.""" 26 27 def __init__( 28 self, 29 transition: str | None = 'in_right', 30 origin_widget: bui.Widget | None = None, 31 playlist_select_context: PlaylistSelectContext | None = None, 32 ): 33 # pylint: disable=too-many-statements 34 # pylint: disable=too-many-locals 35 36 # Preload some modules we use in a background thread so we won't 37 # have a visual hitch when the user taps them. 38 bui.app.threadpool.submit_no_wait(self._preload_modules) 39 40 classic = bui.app.classic 41 assert classic is not None 42 43 self._playlist_select_context = playlist_select_context 44 45 uiscale = bui.app.ui_v1.uiscale 46 width = 1100 if uiscale is bui.UIScale.SMALL else 1000 47 x_offs = 150 if uiscale is bui.UIScale.SMALL else 90 48 y_offs = -60 if uiscale is bui.UIScale.SMALL else 45 49 height = 650 if uiscale is bui.UIScale.SMALL else 550 50 button_width = 400 51 52 if origin_widget is not None: 53 54 # Need to store this ourself since we can function as a 55 # non-main window. 56 self._transition_out = 'out_scale' 57 else: 58 self._transition_out = 'out_right' 59 60 self._r = 'playWindow' 61 62 super().__init__( 63 root_widget=bui.containerwidget( 64 size=(width, height), 65 toolbar_visibility=( 66 'menu_full' 67 if playlist_select_context is None 68 else 'menu_minimal' 69 ), 70 scale=( 71 1.35 72 if uiscale is bui.UIScale.SMALL 73 else 0.9 if uiscale is bui.UIScale.MEDIUM else 0.8 74 ), 75 stack_offset=( 76 (0, 20) if uiscale is bui.UIScale.SMALL else (0, 0) 77 ), 78 ), 79 transition=transition, 80 origin_widget=origin_widget, 81 ) 82 83 self._back_button: bui.Widget | None 84 if uiscale is bui.UIScale.SMALL: 85 self._back_button = None 86 bui.containerwidget( 87 edit=self._root_widget, 88 on_cancel_call=self.main_window_back, 89 ) 90 else: 91 self._back_button = bui.buttonwidget( 92 parent=self._root_widget, 93 position=(5 + x_offs, height - 162 + y_offs), 94 size=(60, 60), 95 scale=1.1, 96 text_res_scale=1.5, 97 text_scale=1.2, 98 autoselect=True, 99 label=bui.charstr(bui.SpecialChar.BACK), 100 button_type='backSmall', 101 on_activate_call=self.main_window_back, 102 ) 103 bui.containerwidget( 104 edit=self._root_widget, cancel_button=self._back_button 105 ) 106 107 bui.textwidget( 108 parent=self._root_widget, 109 position=( 110 width * 0.5, 111 height - (83 if uiscale is bui.UIScale.SMALL else 131) + y_offs, 112 ), 113 size=(0, 0), 114 text=bui.Lstr( 115 resource=( 116 (f'{self._r}.titleText') 117 if self._playlist_select_context is None 118 else 'playlistsText' 119 ) 120 ), 121 scale=1.2 if uiscale is bui.UIScale.SMALL else 1.7, 122 res_scale=2.0, 123 maxwidth=400, 124 color=bui.app.ui_v1.heading_color, 125 h_align='center', 126 v_align='center', 127 ) 128 v = ( 129 height 130 - (110 if self._playlist_select_context is None else 90) 131 + y_offs 132 ) 133 v -= 100 134 clr = (0.6, 0.7, 0.6, 1.0) 135 v -= 270 if self._playlist_select_context is None else 280 136 v += 65 if uiscale is bui.UIScale.SMALL else 0 137 hoffs = ( 138 x_offs - 45 139 if self._playlist_select_context is None 140 else x_offs - 100 141 ) 142 scl = 0.75 if self._playlist_select_context is None else 0.68 143 144 self._lineup_tex = bui.gettexture('playerLineup') 145 angry_computer_transparent_mesh = bui.getmesh( 146 'angryComputerTransparent' 147 ) 148 self._lineup_1_transparent_mesh = bui.getmesh( 149 'playerLineup1Transparent' 150 ) 151 self._lineup_2_transparent_mesh = bui.getmesh( 152 'playerLineup2Transparent' 153 ) 154 self._lineup_3_transparent_mesh = bui.getmesh( 155 'playerLineup3Transparent' 156 ) 157 self._lineup_4_transparent_mesh = bui.getmesh( 158 'playerLineup4Transparent' 159 ) 160 self._eyes_mesh = bui.getmesh('plasticEyesTransparent') 161 162 self._coop_button: bui.Widget | None = None 163 164 # Only show coop button in regular variant. 165 if self._playlist_select_context is None: 166 self._coop_button = btn = bui.buttonwidget( 167 parent=self._root_widget, 168 position=(hoffs, v), 169 size=( 170 scl * button_width, 171 scl * 360, 172 ), 173 extra_touch_border_scale=0.1, 174 autoselect=True, 175 label='', 176 button_type='square', 177 on_activate_call=self._coop, 178 ) 179 180 if uiscale is bui.UIScale.SMALL: 181 bui.widget( 182 edit=btn, 183 left_widget=bui.get_special_widget('back_button'), 184 ) 185 bui.widget( 186 edit=btn, 187 up_widget=bui.get_special_widget('account_button'), 188 ) 189 bui.widget( 190 edit=btn, 191 down_widget=bui.get_special_widget('settings_button'), 192 ) 193 194 self._draw_dude( 195 0, 196 btn, 197 hoffs, 198 v, 199 scl, 200 position=(140, 30), 201 color=(0.72, 0.4, 1.0), 202 ) 203 self._draw_dude( 204 1, 205 btn, 206 hoffs, 207 v, 208 scl, 209 position=(185, 53), 210 color=(0.71, 0.5, 1.0), 211 ) 212 self._draw_dude( 213 2, 214 btn, 215 hoffs, 216 v, 217 scl, 218 position=(220, 27), 219 color=(0.67, 0.44, 1.0), 220 ) 221 self._draw_dude( 222 3, btn, hoffs, v, scl, position=(255, 57), color=(0.7, 0.3, 1.0) 223 ) 224 bui.imagewidget( 225 parent=self._root_widget, 226 draw_controller=btn, 227 position=(hoffs + scl * 230, v + scl * 153), 228 size=(scl * 115, scl * 115), 229 texture=self._lineup_tex, 230 mesh_transparent=angry_computer_transparent_mesh, 231 ) 232 233 bui.textwidget( 234 parent=self._root_widget, 235 draw_controller=btn, 236 position=(hoffs + scl * (-10), v + scl * 95), 237 size=(scl * button_width, scl * 50), 238 text=bui.Lstr( 239 resource='playModes.singlePlayerCoopText', 240 fallback_resource='playModes.coopText', 241 ), 242 maxwidth=scl * button_width * 0.7, 243 res_scale=1.5, 244 h_align='center', 245 v_align='center', 246 color=(0.7, 0.9, 0.7, 1.0), 247 scale=scl * 1.5, 248 ) 249 250 bui.textwidget( 251 parent=self._root_widget, 252 draw_controller=btn, 253 position=(hoffs + scl * (-10), v + (scl * 54)), 254 size=(scl * button_width, scl * 30), 255 text=bui.Lstr(resource=f'{self._r}.oneToFourPlayersText'), 256 h_align='center', 257 v_align='center', 258 scale=0.83 * scl, 259 flatness=1.0, 260 maxwidth=scl * button_width * 0.7, 261 color=clr, 262 ) 263 264 scl = 0.75 if self._playlist_select_context is None else 0.68 265 hoffs += 300 if self._playlist_select_context is None else 216 266 # v += 0 if self._playlist_select_context is None else -68 267 268 self._teams_button = btn = bui.buttonwidget( 269 parent=self._root_widget, 270 position=( 271 hoffs, 272 v, 273 # v + (scl * 15 if 274 # self._playlist_select_context is None else 0), 275 ), 276 size=( 277 scl * button_width, 278 scl * (360 if self._playlist_select_context is None else 360), 279 ), 280 extra_touch_border_scale=0.1, 281 autoselect=True, 282 label='', 283 button_type='square', 284 on_activate_call=self._team_tourney, 285 ) 286 287 xxx = -14 288 self._draw_dude( 289 2, 290 btn, 291 hoffs, 292 v, 293 scl, 294 position=(xxx + 148, 30), 295 color=(0.2, 0.4, 1.0), 296 ) 297 self._draw_dude( 298 3, 299 btn, 300 hoffs, 301 v, 302 scl, 303 position=(xxx + 181, 53), 304 color=(0.3, 0.4, 1.0), 305 ) 306 self._draw_dude( 307 1, 308 btn, 309 hoffs, 310 v, 311 scl, 312 position=(xxx + 216, 33), 313 color=(0.3, 0.5, 1.0), 314 ) 315 self._draw_dude( 316 0, 317 btn, 318 hoffs, 319 v, 320 scl, 321 position=(xxx + 245, 57), 322 color=(0.3, 0.5, 1.0), 323 ) 324 325 xxx = 155 326 self._draw_dude( 327 0, 328 btn, 329 hoffs, 330 v, 331 scl, 332 position=(xxx + 151, 30), 333 color=(1.0, 0.5, 0.4), 334 ) 335 self._draw_dude( 336 1, 337 btn, 338 hoffs, 339 v, 340 scl, 341 position=(xxx + 189, 53), 342 color=(1.0, 0.58, 0.58), 343 ) 344 self._draw_dude( 345 3, 346 btn, 347 hoffs, 348 v, 349 scl, 350 position=(xxx + 223, 27), 351 color=(1.0, 0.5, 0.5), 352 ) 353 self._draw_dude( 354 2, 355 btn, 356 hoffs, 357 v, 358 scl, 359 position=(xxx + 257, 57), 360 color=(1.0, 0.5, 0.5), 361 ) 362 363 bui.textwidget( 364 parent=self._root_widget, 365 draw_controller=btn, 366 position=(hoffs + scl * (-10), v + scl * 95), 367 size=(scl * button_width, scl * 50), 368 text=bui.Lstr( 369 resource='playModes.teamsText', fallback_resource='teamsText' 370 ), 371 res_scale=1.5, 372 maxwidth=scl * button_width * 0.7, 373 h_align='center', 374 v_align='center', 375 color=(0.7, 0.9, 0.7, 1.0), 376 scale=scl * 1.5, 377 ) 378 bui.textwidget( 379 parent=self._root_widget, 380 draw_controller=btn, 381 position=(hoffs + scl * (-10), v + (scl * 54)), 382 size=(scl * button_width, scl * 30), 383 text=bui.Lstr(resource=f'{self._r}.twoToEightPlayersText'), 384 h_align='center', 385 v_align='center', 386 res_scale=1.5, 387 scale=0.83 * scl, 388 flatness=1.0, 389 maxwidth=scl * button_width * 0.7, 390 color=clr, 391 ) 392 393 hoffs += 300 if self._playlist_select_context is None else 300 394 # v -= 0 if self._playlist_select_context is None else 0 395 self._free_for_all_button = btn = bui.buttonwidget( 396 parent=self._root_widget, 397 position=( 398 hoffs, 399 v, 400 # v + (scl * 15 401 # if self._playlist_select_context is None else 0), 402 ), 403 size=( 404 scl * button_width, 405 scl * (360 if self._playlist_select_context is None else 360), 406 ), 407 extra_touch_border_scale=0.1, 408 autoselect=True, 409 label='', 410 button_type='square', 411 on_activate_call=self._free_for_all, 412 ) 413 414 xxx = -5 415 self._draw_dude( 416 0, 417 btn, 418 hoffs, 419 v, 420 scl, 421 position=(xxx + 140, 30), 422 color=(0.4, 1.0, 0.4), 423 ) 424 self._draw_dude( 425 3, 426 btn, 427 hoffs, 428 v, 429 scl, 430 position=(xxx + 185, 53), 431 color=(1.0, 0.4, 0.5), 432 ) 433 self._draw_dude( 434 1, 435 btn, 436 hoffs, 437 v, 438 scl, 439 position=(xxx + 220, 27), 440 color=(0.4, 0.5, 1.0), 441 ) 442 self._draw_dude( 443 2, 444 btn, 445 hoffs, 446 v, 447 scl, 448 position=(xxx + 255, 57), 449 color=(0.5, 1.0, 0.4), 450 ) 451 xxx = 140 452 self._draw_dude( 453 2, 454 btn, 455 hoffs, 456 v, 457 scl, 458 position=(xxx + 148, 30), 459 color=(1.0, 0.9, 0.4), 460 ) 461 self._draw_dude( 462 0, 463 btn, 464 hoffs, 465 v, 466 scl, 467 position=(xxx + 182, 53), 468 color=(0.7, 1.0, 0.5), 469 ) 470 self._draw_dude( 471 3, 472 btn, 473 hoffs, 474 v, 475 scl, 476 position=(xxx + 233, 27), 477 color=(0.7, 0.5, 0.9), 478 ) 479 self._draw_dude( 480 1, 481 btn, 482 hoffs, 483 v, 484 scl, 485 position=(xxx + 266, 53), 486 color=(0.4, 0.5, 0.8), 487 ) 488 bui.textwidget( 489 parent=self._root_widget, 490 draw_controller=btn, 491 position=(hoffs + scl * (-10), v + scl * 95), 492 size=(scl * button_width, scl * 50), 493 text=bui.Lstr( 494 resource='playModes.freeForAllText', 495 fallback_resource='freeForAllText', 496 ), 497 maxwidth=scl * button_width * 0.7, 498 h_align='center', 499 v_align='center', 500 color=(0.7, 0.9, 0.7, 1.0), 501 scale=scl * 1.5, 502 ) 503 bui.textwidget( 504 parent=self._root_widget, 505 draw_controller=btn, 506 position=(hoffs + scl * (-10), v + (scl * 54)), 507 size=(scl * button_width, scl * 30), 508 text=bui.Lstr(resource=f'{self._r}.twoToEightPlayersText'), 509 h_align='center', 510 v_align='center', 511 scale=0.83 * scl, 512 flatness=1.0, 513 maxwidth=scl * button_width * 0.7, 514 color=clr, 515 ) 516 517 if uiscale is bui.UIScale.SMALL: 518 bui.containerwidget( 519 edit=self._root_widget, 520 selected_child=( 521 self._coop_button 522 if self._playlist_select_context is None 523 else self._teams_button 524 ), 525 ) 526 else: 527 bui.containerwidget( 528 edit=self._root_widget, 529 selected_child=( 530 self._coop_button 531 if self._playlist_select_context is None 532 else self._teams_button 533 ), 534 ) 535 536 self._restore_state() 537 538 @override 539 def get_main_window_state(self) -> bui.MainWindowState: 540 # Support recreating our window for back/refresh purposes. 541 cls = type(self) 542 543 # Pull any values out of self here; if we do it in the lambda 544 # we'll keep our window alive inadvertantly. 545 playlist_select_context = self._playlist_select_context 546 return bui.BasicMainWindowState( 547 create_call=lambda transition, origin_widget: cls( 548 transition=transition, 549 origin_widget=origin_widget, 550 playlist_select_context=playlist_select_context, 551 ) 552 ) 553 554 @override 555 def on_main_window_close(self) -> None: 556 self._save_state() 557 558 @staticmethod 559 def _preload_modules() -> None: 560 """Preload modules we use; avoids hitches (called in bg thread).""" 561 import bauiv1lib.mainmenu as _unused1 562 import bauiv1lib.account as _unused2 563 import bauiv1lib.coop.browser as _unused3 564 import bauiv1lib.playlist.browser as _unused4 565 566 def _coop(self) -> None: 567 # pylint: disable=cyclic-import 568 from bauiv1lib.account.signin import show_sign_in_prompt 569 from bauiv1lib.coop.browser import CoopBrowserWindow 570 571 # no-op if we're not currently in control. 572 if not self.main_window_has_control(): 573 return 574 575 plus = bui.app.plus 576 assert plus is not None 577 578 if plus.get_v1_account_state() != 'signed_in': 579 show_sign_in_prompt() 580 return 581 582 self.main_window_replace( 583 CoopBrowserWindow(origin_widget=self._coop_button) 584 ) 585 586 def _team_tourney(self) -> None: 587 # pylint: disable=cyclic-import 588 from bauiv1lib.playlist.browser import PlaylistBrowserWindow 589 590 # no-op if we're not currently in control. 591 if not self.main_window_has_control(): 592 return 593 594 self.main_window_replace( 595 PlaylistBrowserWindow( 596 origin_widget=self._teams_button, 597 sessiontype=bs.DualTeamSession, 598 playlist_select_context=self._playlist_select_context, 599 ) 600 ) 601 602 def _free_for_all(self) -> None: 603 # pylint: disable=cyclic-import 604 from bauiv1lib.playlist.browser import PlaylistBrowserWindow 605 606 # no-op if we're not currently in control. 607 if not self.main_window_has_control(): 608 return 609 610 self.main_window_replace( 611 PlaylistBrowserWindow( 612 origin_widget=self._free_for_all_button, 613 sessiontype=bs.FreeForAllSession, 614 playlist_select_context=self._playlist_select_context, 615 ) 616 ) 617 618 def _draw_dude( 619 self, 620 i: int, 621 btn: bui.Widget, 622 hoffs: float, 623 v: float, 624 scl: float, 625 position: tuple[float, float], 626 color: tuple[float, float, float], 627 ) -> None: 628 # pylint: disable=too-many-positional-arguments 629 h_extra = -100 630 v_extra = 130 631 eye_color = ( 632 0.7 * 1.0 + 0.3 * color[0], 633 0.7 * 1.0 + 0.3 * color[1], 634 0.7 * 1.0 + 0.3 * color[2], 635 ) 636 if i == 0: 637 bui.imagewidget( 638 parent=self._root_widget, 639 draw_controller=btn, 640 position=( 641 hoffs + scl * (h_extra + position[0]), 642 v + scl * (v_extra + position[1]), 643 ), 644 size=(scl * 60, scl * 80), 645 color=color, 646 texture=self._lineup_tex, 647 mesh_transparent=self._lineup_1_transparent_mesh, 648 ) 649 bui.imagewidget( 650 parent=self._root_widget, 651 draw_controller=btn, 652 position=( 653 hoffs + scl * (h_extra + position[0] + 12), 654 v + scl * (v_extra + position[1] + 53), 655 ), 656 size=(scl * 36, scl * 18), 657 texture=self._lineup_tex, 658 color=eye_color, 659 mesh_transparent=self._eyes_mesh, 660 ) 661 elif i == 1: 662 bui.imagewidget( 663 parent=self._root_widget, 664 draw_controller=btn, 665 position=( 666 hoffs + scl * (h_extra + position[0]), 667 v + scl * (v_extra + position[1]), 668 ), 669 size=(scl * 45, scl * 90), 670 color=color, 671 texture=self._lineup_tex, 672 mesh_transparent=self._lineup_2_transparent_mesh, 673 ) 674 bui.imagewidget( 675 parent=self._root_widget, 676 draw_controller=btn, 677 position=( 678 hoffs + scl * (h_extra + position[0] + 5), 679 v + scl * (v_extra + position[1] + 67), 680 ), 681 size=(scl * 32, scl * 16), 682 texture=self._lineup_tex, 683 color=eye_color, 684 mesh_transparent=self._eyes_mesh, 685 ) 686 elif i == 2: 687 bui.imagewidget( 688 parent=self._root_widget, 689 draw_controller=btn, 690 position=( 691 hoffs + scl * (h_extra + position[0]), 692 v + scl * (v_extra + position[1]), 693 ), 694 size=(scl * 45, scl * 90), 695 color=color, 696 texture=self._lineup_tex, 697 mesh_transparent=self._lineup_3_transparent_mesh, 698 ) 699 bui.imagewidget( 700 parent=self._root_widget, 701 draw_controller=btn, 702 position=( 703 hoffs + scl * (h_extra + position[0] + 5), 704 v + scl * (v_extra + position[1] + 59), 705 ), 706 size=(scl * 34, scl * 17), 707 texture=self._lineup_tex, 708 color=eye_color, 709 mesh_transparent=self._eyes_mesh, 710 ) 711 elif i == 3: 712 bui.imagewidget( 713 parent=self._root_widget, 714 draw_controller=btn, 715 position=( 716 hoffs + scl * (h_extra + position[0]), 717 v + scl * (v_extra + position[1]), 718 ), 719 size=(scl * 48, scl * 96), 720 color=color, 721 texture=self._lineup_tex, 722 mesh_transparent=self._lineup_4_transparent_mesh, 723 ) 724 bui.imagewidget( 725 parent=self._root_widget, 726 draw_controller=btn, 727 position=( 728 hoffs + scl * (h_extra + position[0] + 2), 729 v + scl * (v_extra + position[1] + 62), 730 ), 731 size=(scl * 38, scl * 19), 732 texture=self._lineup_tex, 733 color=eye_color, 734 mesh_transparent=self._eyes_mesh, 735 ) 736 737 def _save_state(self) -> None: 738 try: 739 sel = self._root_widget.get_selected_child() 740 if sel == self._teams_button: 741 sel_name = 'Team Games' 742 elif self._coop_button is not None and sel == self._coop_button: 743 sel_name = 'Co-op Games' 744 elif sel == self._free_for_all_button: 745 sel_name = 'Free-for-All Games' 746 elif sel == self._back_button: 747 sel_name = 'Back' 748 else: 749 raise ValueError(f'unrecognized selection {sel}') 750 assert bui.app.classic is not None 751 bui.app.ui_v1.window_states[type(self)] = sel_name 752 except Exception: 753 logging.exception('Error saving state for %s.', self) 754 755 def _restore_state(self) -> None: 756 try: 757 assert bui.app.classic is not None 758 sel_name = bui.app.ui_v1.window_states.get(type(self)) 759 if sel_name == 'Team Games': 760 sel = self._teams_button 761 elif sel_name == 'Co-op Games' and self._coop_button is not None: 762 sel = self._coop_button 763 elif sel_name == 'Free-for-All Games': 764 sel = self._free_for_all_button 765 elif sel_name == 'Back' and self._back_button is not None: 766 sel = self._back_button 767 else: 768 sel = ( 769 self._coop_button 770 if self._coop_button is not None 771 else self._teams_button 772 ) 773 bui.containerwidget(edit=self._root_widget, selected_child=sel) 774 except Exception: 775 logging.exception('Error restoring state for %s.', self)
Window for selecting overall play type.
PlayWindow( transition: str | None = 'in_right', origin_widget: _bauiv1.Widget | None = None, playlist_select_context: PlaylistSelectContext | None = None)
27 def __init__( 28 self, 29 transition: str | None = 'in_right', 30 origin_widget: bui.Widget | None = None, 31 playlist_select_context: PlaylistSelectContext | None = None, 32 ): 33 # pylint: disable=too-many-statements 34 # pylint: disable=too-many-locals 35 36 # Preload some modules we use in a background thread so we won't 37 # have a visual hitch when the user taps them. 38 bui.app.threadpool.submit_no_wait(self._preload_modules) 39 40 classic = bui.app.classic 41 assert classic is not None 42 43 self._playlist_select_context = playlist_select_context 44 45 uiscale = bui.app.ui_v1.uiscale 46 width = 1100 if uiscale is bui.UIScale.SMALL else 1000 47 x_offs = 150 if uiscale is bui.UIScale.SMALL else 90 48 y_offs = -60 if uiscale is bui.UIScale.SMALL else 45 49 height = 650 if uiscale is bui.UIScale.SMALL else 550 50 button_width = 400 51 52 if origin_widget is not None: 53 54 # Need to store this ourself since we can function as a 55 # non-main window. 56 self._transition_out = 'out_scale' 57 else: 58 self._transition_out = 'out_right' 59 60 self._r = 'playWindow' 61 62 super().__init__( 63 root_widget=bui.containerwidget( 64 size=(width, height), 65 toolbar_visibility=( 66 'menu_full' 67 if playlist_select_context is None 68 else 'menu_minimal' 69 ), 70 scale=( 71 1.35 72 if uiscale is bui.UIScale.SMALL 73 else 0.9 if uiscale is bui.UIScale.MEDIUM else 0.8 74 ), 75 stack_offset=( 76 (0, 20) if uiscale is bui.UIScale.SMALL else (0, 0) 77 ), 78 ), 79 transition=transition, 80 origin_widget=origin_widget, 81 ) 82 83 self._back_button: bui.Widget | None 84 if uiscale is bui.UIScale.SMALL: 85 self._back_button = None 86 bui.containerwidget( 87 edit=self._root_widget, 88 on_cancel_call=self.main_window_back, 89 ) 90 else: 91 self._back_button = bui.buttonwidget( 92 parent=self._root_widget, 93 position=(5 + x_offs, height - 162 + y_offs), 94 size=(60, 60), 95 scale=1.1, 96 text_res_scale=1.5, 97 text_scale=1.2, 98 autoselect=True, 99 label=bui.charstr(bui.SpecialChar.BACK), 100 button_type='backSmall', 101 on_activate_call=self.main_window_back, 102 ) 103 bui.containerwidget( 104 edit=self._root_widget, cancel_button=self._back_button 105 ) 106 107 bui.textwidget( 108 parent=self._root_widget, 109 position=( 110 width * 0.5, 111 height - (83 if uiscale is bui.UIScale.SMALL else 131) + y_offs, 112 ), 113 size=(0, 0), 114 text=bui.Lstr( 115 resource=( 116 (f'{self._r}.titleText') 117 if self._playlist_select_context is None 118 else 'playlistsText' 119 ) 120 ), 121 scale=1.2 if uiscale is bui.UIScale.SMALL else 1.7, 122 res_scale=2.0, 123 maxwidth=400, 124 color=bui.app.ui_v1.heading_color, 125 h_align='center', 126 v_align='center', 127 ) 128 v = ( 129 height 130 - (110 if self._playlist_select_context is None else 90) 131 + y_offs 132 ) 133 v -= 100 134 clr = (0.6, 0.7, 0.6, 1.0) 135 v -= 270 if self._playlist_select_context is None else 280 136 v += 65 if uiscale is bui.UIScale.SMALL else 0 137 hoffs = ( 138 x_offs - 45 139 if self._playlist_select_context is None 140 else x_offs - 100 141 ) 142 scl = 0.75 if self._playlist_select_context is None else 0.68 143 144 self._lineup_tex = bui.gettexture('playerLineup') 145 angry_computer_transparent_mesh = bui.getmesh( 146 'angryComputerTransparent' 147 ) 148 self._lineup_1_transparent_mesh = bui.getmesh( 149 'playerLineup1Transparent' 150 ) 151 self._lineup_2_transparent_mesh = bui.getmesh( 152 'playerLineup2Transparent' 153 ) 154 self._lineup_3_transparent_mesh = bui.getmesh( 155 'playerLineup3Transparent' 156 ) 157 self._lineup_4_transparent_mesh = bui.getmesh( 158 'playerLineup4Transparent' 159 ) 160 self._eyes_mesh = bui.getmesh('plasticEyesTransparent') 161 162 self._coop_button: bui.Widget | None = None 163 164 # Only show coop button in regular variant. 165 if self._playlist_select_context is None: 166 self._coop_button = btn = bui.buttonwidget( 167 parent=self._root_widget, 168 position=(hoffs, v), 169 size=( 170 scl * button_width, 171 scl * 360, 172 ), 173 extra_touch_border_scale=0.1, 174 autoselect=True, 175 label='', 176 button_type='square', 177 on_activate_call=self._coop, 178 ) 179 180 if uiscale is bui.UIScale.SMALL: 181 bui.widget( 182 edit=btn, 183 left_widget=bui.get_special_widget('back_button'), 184 ) 185 bui.widget( 186 edit=btn, 187 up_widget=bui.get_special_widget('account_button'), 188 ) 189 bui.widget( 190 edit=btn, 191 down_widget=bui.get_special_widget('settings_button'), 192 ) 193 194 self._draw_dude( 195 0, 196 btn, 197 hoffs, 198 v, 199 scl, 200 position=(140, 30), 201 color=(0.72, 0.4, 1.0), 202 ) 203 self._draw_dude( 204 1, 205 btn, 206 hoffs, 207 v, 208 scl, 209 position=(185, 53), 210 color=(0.71, 0.5, 1.0), 211 ) 212 self._draw_dude( 213 2, 214 btn, 215 hoffs, 216 v, 217 scl, 218 position=(220, 27), 219 color=(0.67, 0.44, 1.0), 220 ) 221 self._draw_dude( 222 3, btn, hoffs, v, scl, position=(255, 57), color=(0.7, 0.3, 1.0) 223 ) 224 bui.imagewidget( 225 parent=self._root_widget, 226 draw_controller=btn, 227 position=(hoffs + scl * 230, v + scl * 153), 228 size=(scl * 115, scl * 115), 229 texture=self._lineup_tex, 230 mesh_transparent=angry_computer_transparent_mesh, 231 ) 232 233 bui.textwidget( 234 parent=self._root_widget, 235 draw_controller=btn, 236 position=(hoffs + scl * (-10), v + scl * 95), 237 size=(scl * button_width, scl * 50), 238 text=bui.Lstr( 239 resource='playModes.singlePlayerCoopText', 240 fallback_resource='playModes.coopText', 241 ), 242 maxwidth=scl * button_width * 0.7, 243 res_scale=1.5, 244 h_align='center', 245 v_align='center', 246 color=(0.7, 0.9, 0.7, 1.0), 247 scale=scl * 1.5, 248 ) 249 250 bui.textwidget( 251 parent=self._root_widget, 252 draw_controller=btn, 253 position=(hoffs + scl * (-10), v + (scl * 54)), 254 size=(scl * button_width, scl * 30), 255 text=bui.Lstr(resource=f'{self._r}.oneToFourPlayersText'), 256 h_align='center', 257 v_align='center', 258 scale=0.83 * scl, 259 flatness=1.0, 260 maxwidth=scl * button_width * 0.7, 261 color=clr, 262 ) 263 264 scl = 0.75 if self._playlist_select_context is None else 0.68 265 hoffs += 300 if self._playlist_select_context is None else 216 266 # v += 0 if self._playlist_select_context is None else -68 267 268 self._teams_button = btn = bui.buttonwidget( 269 parent=self._root_widget, 270 position=( 271 hoffs, 272 v, 273 # v + (scl * 15 if 274 # self._playlist_select_context is None else 0), 275 ), 276 size=( 277 scl * button_width, 278 scl * (360 if self._playlist_select_context is None else 360), 279 ), 280 extra_touch_border_scale=0.1, 281 autoselect=True, 282 label='', 283 button_type='square', 284 on_activate_call=self._team_tourney, 285 ) 286 287 xxx = -14 288 self._draw_dude( 289 2, 290 btn, 291 hoffs, 292 v, 293 scl, 294 position=(xxx + 148, 30), 295 color=(0.2, 0.4, 1.0), 296 ) 297 self._draw_dude( 298 3, 299 btn, 300 hoffs, 301 v, 302 scl, 303 position=(xxx + 181, 53), 304 color=(0.3, 0.4, 1.0), 305 ) 306 self._draw_dude( 307 1, 308 btn, 309 hoffs, 310 v, 311 scl, 312 position=(xxx + 216, 33), 313 color=(0.3, 0.5, 1.0), 314 ) 315 self._draw_dude( 316 0, 317 btn, 318 hoffs, 319 v, 320 scl, 321 position=(xxx + 245, 57), 322 color=(0.3, 0.5, 1.0), 323 ) 324 325 xxx = 155 326 self._draw_dude( 327 0, 328 btn, 329 hoffs, 330 v, 331 scl, 332 position=(xxx + 151, 30), 333 color=(1.0, 0.5, 0.4), 334 ) 335 self._draw_dude( 336 1, 337 btn, 338 hoffs, 339 v, 340 scl, 341 position=(xxx + 189, 53), 342 color=(1.0, 0.58, 0.58), 343 ) 344 self._draw_dude( 345 3, 346 btn, 347 hoffs, 348 v, 349 scl, 350 position=(xxx + 223, 27), 351 color=(1.0, 0.5, 0.5), 352 ) 353 self._draw_dude( 354 2, 355 btn, 356 hoffs, 357 v, 358 scl, 359 position=(xxx + 257, 57), 360 color=(1.0, 0.5, 0.5), 361 ) 362 363 bui.textwidget( 364 parent=self._root_widget, 365 draw_controller=btn, 366 position=(hoffs + scl * (-10), v + scl * 95), 367 size=(scl * button_width, scl * 50), 368 text=bui.Lstr( 369 resource='playModes.teamsText', fallback_resource='teamsText' 370 ), 371 res_scale=1.5, 372 maxwidth=scl * button_width * 0.7, 373 h_align='center', 374 v_align='center', 375 color=(0.7, 0.9, 0.7, 1.0), 376 scale=scl * 1.5, 377 ) 378 bui.textwidget( 379 parent=self._root_widget, 380 draw_controller=btn, 381 position=(hoffs + scl * (-10), v + (scl * 54)), 382 size=(scl * button_width, scl * 30), 383 text=bui.Lstr(resource=f'{self._r}.twoToEightPlayersText'), 384 h_align='center', 385 v_align='center', 386 res_scale=1.5, 387 scale=0.83 * scl, 388 flatness=1.0, 389 maxwidth=scl * button_width * 0.7, 390 color=clr, 391 ) 392 393 hoffs += 300 if self._playlist_select_context is None else 300 394 # v -= 0 if self._playlist_select_context is None else 0 395 self._free_for_all_button = btn = bui.buttonwidget( 396 parent=self._root_widget, 397 position=( 398 hoffs, 399 v, 400 # v + (scl * 15 401 # if self._playlist_select_context is None else 0), 402 ), 403 size=( 404 scl * button_width, 405 scl * (360 if self._playlist_select_context is None else 360), 406 ), 407 extra_touch_border_scale=0.1, 408 autoselect=True, 409 label='', 410 button_type='square', 411 on_activate_call=self._free_for_all, 412 ) 413 414 xxx = -5 415 self._draw_dude( 416 0, 417 btn, 418 hoffs, 419 v, 420 scl, 421 position=(xxx + 140, 30), 422 color=(0.4, 1.0, 0.4), 423 ) 424 self._draw_dude( 425 3, 426 btn, 427 hoffs, 428 v, 429 scl, 430 position=(xxx + 185, 53), 431 color=(1.0, 0.4, 0.5), 432 ) 433 self._draw_dude( 434 1, 435 btn, 436 hoffs, 437 v, 438 scl, 439 position=(xxx + 220, 27), 440 color=(0.4, 0.5, 1.0), 441 ) 442 self._draw_dude( 443 2, 444 btn, 445 hoffs, 446 v, 447 scl, 448 position=(xxx + 255, 57), 449 color=(0.5, 1.0, 0.4), 450 ) 451 xxx = 140 452 self._draw_dude( 453 2, 454 btn, 455 hoffs, 456 v, 457 scl, 458 position=(xxx + 148, 30), 459 color=(1.0, 0.9, 0.4), 460 ) 461 self._draw_dude( 462 0, 463 btn, 464 hoffs, 465 v, 466 scl, 467 position=(xxx + 182, 53), 468 color=(0.7, 1.0, 0.5), 469 ) 470 self._draw_dude( 471 3, 472 btn, 473 hoffs, 474 v, 475 scl, 476 position=(xxx + 233, 27), 477 color=(0.7, 0.5, 0.9), 478 ) 479 self._draw_dude( 480 1, 481 btn, 482 hoffs, 483 v, 484 scl, 485 position=(xxx + 266, 53), 486 color=(0.4, 0.5, 0.8), 487 ) 488 bui.textwidget( 489 parent=self._root_widget, 490 draw_controller=btn, 491 position=(hoffs + scl * (-10), v + scl * 95), 492 size=(scl * button_width, scl * 50), 493 text=bui.Lstr( 494 resource='playModes.freeForAllText', 495 fallback_resource='freeForAllText', 496 ), 497 maxwidth=scl * button_width * 0.7, 498 h_align='center', 499 v_align='center', 500 color=(0.7, 0.9, 0.7, 1.0), 501 scale=scl * 1.5, 502 ) 503 bui.textwidget( 504 parent=self._root_widget, 505 draw_controller=btn, 506 position=(hoffs + scl * (-10), v + (scl * 54)), 507 size=(scl * button_width, scl * 30), 508 text=bui.Lstr(resource=f'{self._r}.twoToEightPlayersText'), 509 h_align='center', 510 v_align='center', 511 scale=0.83 * scl, 512 flatness=1.0, 513 maxwidth=scl * button_width * 0.7, 514 color=clr, 515 ) 516 517 if uiscale is bui.UIScale.SMALL: 518 bui.containerwidget( 519 edit=self._root_widget, 520 selected_child=( 521 self._coop_button 522 if self._playlist_select_context is None 523 else self._teams_button 524 ), 525 ) 526 else: 527 bui.containerwidget( 528 edit=self._root_widget, 529 selected_child=( 530 self._coop_button 531 if self._playlist_select_context is None 532 else self._teams_button 533 ), 534 ) 535 536 self._restore_state()
Create a MainWindow given a root widget and transition info.
Automatically handles in and out transitions on the provided widget, so there is no need to set transitions when creating it.
538 @override 539 def get_main_window_state(self) -> bui.MainWindowState: 540 # Support recreating our window for back/refresh purposes. 541 cls = type(self) 542 543 # Pull any values out of self here; if we do it in the lambda 544 # we'll keep our window alive inadvertantly. 545 playlist_select_context = self._playlist_select_context 546 return bui.BasicMainWindowState( 547 create_call=lambda transition, origin_widget: cls( 548 transition=transition, 549 origin_widget=origin_widget, 550 playlist_select_context=playlist_select_context, 551 ) 552 )
Return a WindowState to recreate this window, if supported.