bauiv1lib.kiosk
UI functionality for running the game in kiosk mode.
1# Released under the MIT License. See LICENSE for details. 2# 3"""UI functionality for running the game in kiosk mode.""" 4 5from __future__ import annotations 6 7from typing import override 8 9import bascenev1 as bs 10import bauiv1 as bui 11 12 13class KioskWindow(bui.MainWindow): 14 """Kiosk mode window.""" 15 16 def __init__( 17 self, 18 transition: str | None = 'in_right', 19 origin_widget: bui.Widget | None = None, 20 ): 21 # pylint: disable=too-many-locals, too-many-statements 22 from bauiv1lib.confirm import QuitWindow 23 24 assert bui.app.classic is not None 25 26 self._width = 720.0 27 self._height = 340.0 28 29 def _do_cancel() -> None: 30 QuitWindow(swish=True, quit_type=bui.QuitType.BACK) 31 32 super().__init__( 33 root_widget=bui.containerwidget( 34 size=(self._width, self._height), 35 # transition=transition, 36 on_cancel_call=_do_cancel, 37 background=False, 38 stack_offset=(0, -130), 39 ), 40 transition=transition, 41 origin_widget=origin_widget, 42 ) 43 44 self._r = 'kioskWindow' 45 46 self._show_multiplayer = False 47 48 # Let's reset all random player names every time we hit the main menu. 49 bs.reset_random_player_names() 50 51 # Reset achievements too (at least locally). 52 bui.app.config['Achievements'] = {} 53 54 t_delay_base = 0.0 55 t_delay_scale = 0.0 56 if not bui.app.classic.did_menu_intro: 57 t_delay_base = 1.0 58 t_delay_scale = 1.0 59 60 mesh_opaque = bui.getmesh('level_select_button_opaque') 61 mesh_transparent = bui.getmesh('level_select_button_transparent') 62 mask_tex = bui.gettexture('mapPreviewMask') 63 64 y_extra = 130.0 + (0.0 if self._show_multiplayer else -130.0) 65 b_width = 250.0 66 b_height = 200.0 67 b_space = 280.0 68 b_v = 80.0 + y_extra 69 label_height = 130.0 + y_extra 70 img_width = 180.0 71 img_v = 158.0 + y_extra 72 73 if self._show_multiplayer: 74 tdelay = t_delay_base + t_delay_scale * 1.3 75 bui.textwidget( 76 parent=self._root_widget, 77 size=(0, 0), 78 position=(self._width * 0.5, self._height + y_extra - 44), 79 transition_delay=tdelay, 80 text=bui.Lstr(resource=f'{self._r}.singlePlayerExamplesText'), 81 flatness=1.0, 82 scale=1.2, 83 h_align='center', 84 v_align='center', 85 shadow=1.0, 86 ) 87 else: 88 tdelay = t_delay_base + t_delay_scale * 0.7 89 bui.textwidget( 90 parent=self._root_widget, 91 size=(0, 0), 92 position=(self._width * 0.5, self._height + y_extra - 34), 93 transition_delay=tdelay, 94 text=( 95 bui.Lstr( 96 resource='demoText', 97 fallback_resource='mainMenu.demoMenuText', 98 ) 99 if bui.app.env.demo 100 else 'ARCADE' 101 ), 102 flatness=1.0, 103 scale=1.2, 104 h_align='center', 105 v_align='center', 106 shadow=1.0, 107 ) 108 h = self._width * 0.5 - b_space 109 tdelay = t_delay_base + t_delay_scale * 0.7 110 self._b1 = btn = bui.buttonwidget( 111 parent=self._root_widget, 112 autoselect=True, 113 size=(b_width, b_height), 114 on_activate_call=bui.Call(self._do_game, 'easy'), 115 transition_delay=tdelay, 116 position=(h - b_width * 0.5, b_v), 117 label='', 118 button_type='square', 119 ) 120 bui.textwidget( 121 parent=self._root_widget, 122 draw_controller=btn, 123 transition_delay=tdelay, 124 size=(0, 0), 125 position=(h, label_height), 126 maxwidth=b_width * 0.7, 127 text=bui.Lstr(resource=f'{self._r}.easyText'), 128 scale=1.3, 129 h_align='center', 130 v_align='center', 131 ) 132 bui.imagewidget( 133 parent=self._root_widget, 134 draw_controller=btn, 135 size=(img_width, 0.5 * img_width), 136 transition_delay=tdelay, 137 position=(h - img_width * 0.5, img_v), 138 texture=bui.gettexture('doomShroomPreview'), 139 mesh_opaque=mesh_opaque, 140 mesh_transparent=mesh_transparent, 141 mask_texture=mask_tex, 142 ) 143 h = self._width * 0.5 144 tdelay = t_delay_base + t_delay_scale * 0.65 145 self._b2 = btn = bui.buttonwidget( 146 parent=self._root_widget, 147 autoselect=True, 148 size=(b_width, b_height), 149 on_activate_call=bui.Call(self._do_game, 'medium'), 150 position=(h - b_width * 0.5, b_v), 151 label='', 152 button_type='square', 153 transition_delay=tdelay, 154 ) 155 bui.textwidget( 156 parent=self._root_widget, 157 draw_controller=btn, 158 transition_delay=tdelay, 159 size=(0, 0), 160 position=(h, label_height), 161 maxwidth=b_width * 0.7, 162 text=bui.Lstr(resource=f'{self._r}.mediumText'), 163 scale=1.3, 164 h_align='center', 165 v_align='center', 166 ) 167 bui.imagewidget( 168 parent=self._root_widget, 169 draw_controller=btn, 170 size=(img_width, 0.5 * img_width), 171 transition_delay=tdelay, 172 position=(h - img_width * 0.5, img_v), 173 texture=bui.gettexture('footballStadiumPreview'), 174 mesh_opaque=mesh_opaque, 175 mesh_transparent=mesh_transparent, 176 mask_texture=mask_tex, 177 ) 178 h = self._width * 0.5 + b_space 179 tdelay = t_delay_base + t_delay_scale * 0.6 180 self._b3 = btn = bui.buttonwidget( 181 parent=self._root_widget, 182 autoselect=True, 183 size=(b_width, b_height), 184 on_activate_call=bui.Call(self._do_game, 'hard'), 185 transition_delay=tdelay, 186 position=(h - b_width * 0.5, b_v), 187 label='', 188 button_type='square', 189 ) 190 bui.textwidget( 191 parent=self._root_widget, 192 draw_controller=btn, 193 transition_delay=tdelay, 194 size=(0, 0), 195 position=(h, label_height), 196 maxwidth=b_width * 0.7, 197 text='Hard', 198 scale=1.3, 199 h_align='center', 200 v_align='center', 201 ) 202 bui.imagewidget( 203 parent=self._root_widget, 204 draw_controller=btn, 205 transition_delay=tdelay, 206 size=(img_width, 0.5 * img_width), 207 position=(h - img_width * 0.5, img_v), 208 texture=bui.gettexture('courtyardPreview'), 209 mesh_opaque=mesh_opaque, 210 mesh_transparent=mesh_transparent, 211 mask_texture=mask_tex, 212 ) 213 if not bui.app.classic.did_menu_intro: 214 bui.app.classic.did_menu_intro = True 215 216 self._b4: bui.Widget | None 217 self._b5: bui.Widget | None 218 self._b6: bui.Widget | None 219 220 if bool(False): 221 bui.textwidget( 222 parent=self._root_widget, 223 size=(0, 0), 224 position=(self._width * 0.5, self._height + y_extra - 44), 225 transition_delay=tdelay, 226 text=bui.Lstr(resource=f'{self._r}.versusExamplesText'), 227 flatness=1.0, 228 scale=1.2, 229 h_align='center', 230 v_align='center', 231 shadow=1.0, 232 ) 233 h = self._width * 0.5 - b_space 234 tdelay = t_delay_base + t_delay_scale * 0.7 235 self._b4 = btn = bui.buttonwidget( 236 parent=self._root_widget, 237 autoselect=True, 238 size=(b_width, b_height), 239 on_activate_call=bui.Call(self._do_game, 'ctf'), 240 transition_delay=tdelay, 241 position=(h - b_width * 0.5, b_v), 242 label='', 243 button_type='square', 244 ) 245 bui.textwidget( 246 parent=self._root_widget, 247 draw_controller=btn, 248 transition_delay=tdelay, 249 size=(0, 0), 250 position=(h, label_height), 251 maxwidth=b_width * 0.7, 252 text=bui.Lstr(translate=('gameNames', 'Capture the Flag')), 253 scale=1.3, 254 h_align='center', 255 v_align='center', 256 ) 257 bui.imagewidget( 258 parent=self._root_widget, 259 draw_controller=btn, 260 size=(img_width, 0.5 * img_width), 261 transition_delay=tdelay, 262 position=(h - img_width * 0.5, img_v), 263 texture=bui.gettexture('bridgitPreview'), 264 mesh_opaque=mesh_opaque, 265 mesh_transparent=mesh_transparent, 266 mask_texture=mask_tex, 267 ) 268 269 h = self._width * 0.5 270 tdelay = t_delay_base + t_delay_scale * 0.65 271 self._b5 = btn = bui.buttonwidget( 272 parent=self._root_widget, 273 autoselect=True, 274 size=(b_width, b_height), 275 on_activate_call=bui.Call(self._do_game, 'hockey'), 276 position=(h - b_width * 0.5, b_v), 277 label='', 278 button_type='square', 279 transition_delay=tdelay, 280 ) 281 bui.textwidget( 282 parent=self._root_widget, 283 draw_controller=btn, 284 transition_delay=tdelay, 285 size=(0, 0), 286 position=(h, label_height), 287 maxwidth=b_width * 0.7, 288 text=bui.Lstr(translate=('gameNames', 'Hockey')), 289 scale=1.3, 290 h_align='center', 291 v_align='center', 292 ) 293 bui.imagewidget( 294 parent=self._root_widget, 295 draw_controller=btn, 296 size=(img_width, 0.5 * img_width), 297 transition_delay=tdelay, 298 position=(h - img_width * 0.5, img_v), 299 texture=bui.gettexture('hockeyStadiumPreview'), 300 mesh_opaque=mesh_opaque, 301 mesh_transparent=mesh_transparent, 302 mask_texture=mask_tex, 303 ) 304 h = self._width * 0.5 + b_space 305 tdelay = t_delay_base + t_delay_scale * 0.6 306 self._b6 = btn = bui.buttonwidget( 307 parent=self._root_widget, 308 autoselect=True, 309 size=(b_width, b_height), 310 on_activate_call=bui.Call(self._do_game, 'epic'), 311 transition_delay=tdelay, 312 position=(h - b_width * 0.5, b_v), 313 label='', 314 button_type='square', 315 ) 316 bui.textwidget( 317 parent=self._root_widget, 318 draw_controller=btn, 319 transition_delay=tdelay, 320 size=(0, 0), 321 position=(h, label_height), 322 maxwidth=b_width * 0.7, 323 text=bui.Lstr(resource=f'{self._r}.epicModeText'), 324 scale=1.3, 325 h_align='center', 326 v_align='center', 327 ) 328 bui.imagewidget( 329 parent=self._root_widget, 330 draw_controller=btn, 331 transition_delay=tdelay, 332 size=(img_width, 0.5 * img_width), 333 position=(h - img_width * 0.5, img_v), 334 texture=bui.gettexture('tipTopPreview'), 335 mesh_opaque=mesh_opaque, 336 mesh_transparent=mesh_transparent, 337 mask_texture=mask_tex, 338 ) 339 else: 340 self._b4 = self._b5 = self._b6 = None 341 342 self._b7: bui.Widget | None 343 if bui.app.env.arcade: 344 self._b7 = bui.buttonwidget( 345 parent=self._root_widget, 346 autoselect=True, 347 size=(b_width, 50), 348 color=(0.45, 0.55, 0.45), 349 textcolor=(0.7, 0.8, 0.7), 350 scale=0.5, 351 position=(self._width * 0.5 - 60.0, b_v - 70.0), 352 transition_delay=tdelay, 353 label=bui.Lstr(resource=f'{self._r}.fullMenuText'), 354 on_activate_call=self._do_full_menu, 355 ) 356 else: 357 self._b7 = None 358 self._restore_state() 359 self._update() 360 self._update_timer = bui.AppTimer( 361 1.0, bui.WeakCall(self._update), repeat=True 362 ) 363 364 @override 365 def get_main_window_state(self) -> bui.MainWindowState: 366 # Support recreating our window for back/refresh purposes. 367 cls = type(self) 368 return bui.BasicMainWindowState( 369 create_call=lambda transition, origin_widget: cls( 370 transition=transition, origin_widget=origin_widget 371 ) 372 ) 373 374 @override 375 def on_main_window_close(self) -> None: 376 self._save_state() 377 378 def _restore_state(self) -> None: 379 assert bui.app.classic is not None 380 sel_name = bui.app.ui_v1.window_states.get(type(self)) 381 sel: bui.Widget | None 382 if sel_name == 'b1': 383 sel = self._b1 384 elif sel_name == 'b2': 385 sel = self._b2 386 elif sel_name == 'b3': 387 sel = self._b3 388 elif sel_name == 'b4': 389 sel = self._b4 390 elif sel_name == 'b5': 391 sel = self._b5 392 elif sel_name == 'b6': 393 sel = self._b6 394 elif sel_name == 'b7': 395 sel = self._b7 396 else: 397 sel = self._b1 398 if sel: 399 bui.containerwidget(edit=self._root_widget, selected_child=sel) 400 401 def _save_state(self) -> None: 402 sel = self._root_widget.get_selected_child() 403 if sel == self._b1: 404 sel_name = 'b1' 405 elif sel == self._b2: 406 sel_name = 'b2' 407 elif sel == self._b3: 408 sel_name = 'b3' 409 elif sel == self._b4: 410 sel_name = 'b4' 411 elif sel == self._b5: 412 sel_name = 'b5' 413 elif sel == self._b6: 414 sel_name = 'b6' 415 elif sel == self._b7: 416 sel_name = 'b7' 417 else: 418 sel_name = 'b1' 419 assert bui.app.classic is not None 420 bui.app.ui_v1.window_states[type(self)] = sel_name 421 422 def _update(self) -> None: 423 plus = bui.app.plus 424 assert plus is not None 425 426 # Kiosk-mode is designed to be used signed-out... try for force 427 # the issue. 428 if plus.get_v1_account_state() == 'signed_in': 429 # _bs.sign_out() 430 # FIXME: Try to delete player profiles here too. 431 pass 432 else: 433 # Also make sure there's no player profiles. 434 appconfig = bui.app.config 435 appconfig['Player Profiles'] = {} 436 437 def _do_game(self, mode: str) -> None: 438 assert bui.app.classic is not None 439 self._save_state() 440 if mode in ['epic', 'ctf', 'hockey']: 441 appconfig = bui.app.config 442 if 'Team Tournament Playlists' not in appconfig: 443 appconfig['Team Tournament Playlists'] = {} 444 if 'Free-for-All Playlists' not in appconfig: 445 appconfig['Free-for-All Playlists'] = {} 446 appconfig['Show Tutorial'] = False 447 if mode == 'epic': 448 appconfig['Free-for-All Playlists']['Just Epic Elim'] = [ 449 { 450 'settings': { 451 'Epic Mode': 1, 452 'Lives Per Player': 1, 453 'Respawn Times': 1.0, 454 'Time Limit': 0, 455 'map': 'Tip Top', 456 }, 457 'type': 'bs_elimination.EliminationGame', 458 } 459 ] 460 appconfig['Free-for-All Playlist Selection'] = 'Just Epic Elim' 461 bui.fade_screen( 462 False, 463 endcall=bui.Call( 464 bui.pushcall, 465 bui.Call(bs.new_host_session, bs.FreeForAllSession), 466 ), 467 ) 468 else: 469 if mode == 'ctf': 470 appconfig['Team Tournament Playlists']['Just CTF'] = [ 471 { 472 'settings': { 473 'Epic Mode': False, 474 'Flag Idle Return Time': 30, 475 'Flag Touch Return Time': 0, 476 'Respawn Times': 1.0, 477 'Score to Win': 3, 478 'Time Limit': 0, 479 'map': 'Bridgit', 480 }, 481 'type': 'bs_capture_the_flag.CTFGame', 482 } 483 ] 484 appconfig['Team Tournament Playlist Selection'] = 'Just CTF' 485 else: 486 appconfig['Team Tournament Playlists']['Just Hockey'] = [ 487 { 488 'settings': { 489 'Respawn Times': 1.0, 490 'Score to Win': 1, 491 'Time Limit': 0, 492 'map': 'Hockey Stadium', 493 }, 494 'type': 'bs_hockey.HockeyGame', 495 } 496 ] 497 appconfig['Team Tournament Playlist Selection'] = ( 498 'Just Hockey' 499 ) 500 bui.fade_screen( 501 False, 502 endcall=bui.Call( 503 bui.pushcall, 504 bui.Call(bs.new_host_session, bs.DualTeamSession), 505 ), 506 ) 507 bui.containerwidget(edit=self._root_widget, transition='out_left') 508 return 509 510 game = ( 511 'Easy:Onslaught Training' 512 if mode == 'easy' 513 else ( 514 'Easy:Rookie Football' 515 if mode == 'medium' 516 else 'Easy:Uber Onslaught' 517 ) 518 ) 519 cfg = bui.app.config 520 cfg['Selected Coop Game'] = game 521 cfg.commit() 522 if bui.app.classic.launch_coop_game(game, force=True): 523 bui.containerwidget(edit=self._root_widget, transition='out_left') 524 525 def _do_full_menu(self) -> None: 526 # pylint: disable=cyclic-import 527 from bauiv1lib.mainmenu import MainMenuWindow 528 529 # no-op if we're not in control. 530 if not self.main_window_has_control(): 531 return 532 533 assert bui.app.classic is not None 534 535 self._save_state() 536 bui.app.classic.did_menu_intro = True # prevent delayed transition-in 537 538 self.main_window_replace(MainMenuWindow())
class
KioskWindow(bauiv1._uitypes.MainWindow):
14class KioskWindow(bui.MainWindow): 15 """Kiosk mode window.""" 16 17 def __init__( 18 self, 19 transition: str | None = 'in_right', 20 origin_widget: bui.Widget | None = None, 21 ): 22 # pylint: disable=too-many-locals, too-many-statements 23 from bauiv1lib.confirm import QuitWindow 24 25 assert bui.app.classic is not None 26 27 self._width = 720.0 28 self._height = 340.0 29 30 def _do_cancel() -> None: 31 QuitWindow(swish=True, quit_type=bui.QuitType.BACK) 32 33 super().__init__( 34 root_widget=bui.containerwidget( 35 size=(self._width, self._height), 36 # transition=transition, 37 on_cancel_call=_do_cancel, 38 background=False, 39 stack_offset=(0, -130), 40 ), 41 transition=transition, 42 origin_widget=origin_widget, 43 ) 44 45 self._r = 'kioskWindow' 46 47 self._show_multiplayer = False 48 49 # Let's reset all random player names every time we hit the main menu. 50 bs.reset_random_player_names() 51 52 # Reset achievements too (at least locally). 53 bui.app.config['Achievements'] = {} 54 55 t_delay_base = 0.0 56 t_delay_scale = 0.0 57 if not bui.app.classic.did_menu_intro: 58 t_delay_base = 1.0 59 t_delay_scale = 1.0 60 61 mesh_opaque = bui.getmesh('level_select_button_opaque') 62 mesh_transparent = bui.getmesh('level_select_button_transparent') 63 mask_tex = bui.gettexture('mapPreviewMask') 64 65 y_extra = 130.0 + (0.0 if self._show_multiplayer else -130.0) 66 b_width = 250.0 67 b_height = 200.0 68 b_space = 280.0 69 b_v = 80.0 + y_extra 70 label_height = 130.0 + y_extra 71 img_width = 180.0 72 img_v = 158.0 + y_extra 73 74 if self._show_multiplayer: 75 tdelay = t_delay_base + t_delay_scale * 1.3 76 bui.textwidget( 77 parent=self._root_widget, 78 size=(0, 0), 79 position=(self._width * 0.5, self._height + y_extra - 44), 80 transition_delay=tdelay, 81 text=bui.Lstr(resource=f'{self._r}.singlePlayerExamplesText'), 82 flatness=1.0, 83 scale=1.2, 84 h_align='center', 85 v_align='center', 86 shadow=1.0, 87 ) 88 else: 89 tdelay = t_delay_base + t_delay_scale * 0.7 90 bui.textwidget( 91 parent=self._root_widget, 92 size=(0, 0), 93 position=(self._width * 0.5, self._height + y_extra - 34), 94 transition_delay=tdelay, 95 text=( 96 bui.Lstr( 97 resource='demoText', 98 fallback_resource='mainMenu.demoMenuText', 99 ) 100 if bui.app.env.demo 101 else 'ARCADE' 102 ), 103 flatness=1.0, 104 scale=1.2, 105 h_align='center', 106 v_align='center', 107 shadow=1.0, 108 ) 109 h = self._width * 0.5 - b_space 110 tdelay = t_delay_base + t_delay_scale * 0.7 111 self._b1 = btn = bui.buttonwidget( 112 parent=self._root_widget, 113 autoselect=True, 114 size=(b_width, b_height), 115 on_activate_call=bui.Call(self._do_game, 'easy'), 116 transition_delay=tdelay, 117 position=(h - b_width * 0.5, b_v), 118 label='', 119 button_type='square', 120 ) 121 bui.textwidget( 122 parent=self._root_widget, 123 draw_controller=btn, 124 transition_delay=tdelay, 125 size=(0, 0), 126 position=(h, label_height), 127 maxwidth=b_width * 0.7, 128 text=bui.Lstr(resource=f'{self._r}.easyText'), 129 scale=1.3, 130 h_align='center', 131 v_align='center', 132 ) 133 bui.imagewidget( 134 parent=self._root_widget, 135 draw_controller=btn, 136 size=(img_width, 0.5 * img_width), 137 transition_delay=tdelay, 138 position=(h - img_width * 0.5, img_v), 139 texture=bui.gettexture('doomShroomPreview'), 140 mesh_opaque=mesh_opaque, 141 mesh_transparent=mesh_transparent, 142 mask_texture=mask_tex, 143 ) 144 h = self._width * 0.5 145 tdelay = t_delay_base + t_delay_scale * 0.65 146 self._b2 = btn = bui.buttonwidget( 147 parent=self._root_widget, 148 autoselect=True, 149 size=(b_width, b_height), 150 on_activate_call=bui.Call(self._do_game, 'medium'), 151 position=(h - b_width * 0.5, b_v), 152 label='', 153 button_type='square', 154 transition_delay=tdelay, 155 ) 156 bui.textwidget( 157 parent=self._root_widget, 158 draw_controller=btn, 159 transition_delay=tdelay, 160 size=(0, 0), 161 position=(h, label_height), 162 maxwidth=b_width * 0.7, 163 text=bui.Lstr(resource=f'{self._r}.mediumText'), 164 scale=1.3, 165 h_align='center', 166 v_align='center', 167 ) 168 bui.imagewidget( 169 parent=self._root_widget, 170 draw_controller=btn, 171 size=(img_width, 0.5 * img_width), 172 transition_delay=tdelay, 173 position=(h - img_width * 0.5, img_v), 174 texture=bui.gettexture('footballStadiumPreview'), 175 mesh_opaque=mesh_opaque, 176 mesh_transparent=mesh_transparent, 177 mask_texture=mask_tex, 178 ) 179 h = self._width * 0.5 + b_space 180 tdelay = t_delay_base + t_delay_scale * 0.6 181 self._b3 = btn = bui.buttonwidget( 182 parent=self._root_widget, 183 autoselect=True, 184 size=(b_width, b_height), 185 on_activate_call=bui.Call(self._do_game, 'hard'), 186 transition_delay=tdelay, 187 position=(h - b_width * 0.5, b_v), 188 label='', 189 button_type='square', 190 ) 191 bui.textwidget( 192 parent=self._root_widget, 193 draw_controller=btn, 194 transition_delay=tdelay, 195 size=(0, 0), 196 position=(h, label_height), 197 maxwidth=b_width * 0.7, 198 text='Hard', 199 scale=1.3, 200 h_align='center', 201 v_align='center', 202 ) 203 bui.imagewidget( 204 parent=self._root_widget, 205 draw_controller=btn, 206 transition_delay=tdelay, 207 size=(img_width, 0.5 * img_width), 208 position=(h - img_width * 0.5, img_v), 209 texture=bui.gettexture('courtyardPreview'), 210 mesh_opaque=mesh_opaque, 211 mesh_transparent=mesh_transparent, 212 mask_texture=mask_tex, 213 ) 214 if not bui.app.classic.did_menu_intro: 215 bui.app.classic.did_menu_intro = True 216 217 self._b4: bui.Widget | None 218 self._b5: bui.Widget | None 219 self._b6: bui.Widget | None 220 221 if bool(False): 222 bui.textwidget( 223 parent=self._root_widget, 224 size=(0, 0), 225 position=(self._width * 0.5, self._height + y_extra - 44), 226 transition_delay=tdelay, 227 text=bui.Lstr(resource=f'{self._r}.versusExamplesText'), 228 flatness=1.0, 229 scale=1.2, 230 h_align='center', 231 v_align='center', 232 shadow=1.0, 233 ) 234 h = self._width * 0.5 - b_space 235 tdelay = t_delay_base + t_delay_scale * 0.7 236 self._b4 = btn = bui.buttonwidget( 237 parent=self._root_widget, 238 autoselect=True, 239 size=(b_width, b_height), 240 on_activate_call=bui.Call(self._do_game, 'ctf'), 241 transition_delay=tdelay, 242 position=(h - b_width * 0.5, b_v), 243 label='', 244 button_type='square', 245 ) 246 bui.textwidget( 247 parent=self._root_widget, 248 draw_controller=btn, 249 transition_delay=tdelay, 250 size=(0, 0), 251 position=(h, label_height), 252 maxwidth=b_width * 0.7, 253 text=bui.Lstr(translate=('gameNames', 'Capture the Flag')), 254 scale=1.3, 255 h_align='center', 256 v_align='center', 257 ) 258 bui.imagewidget( 259 parent=self._root_widget, 260 draw_controller=btn, 261 size=(img_width, 0.5 * img_width), 262 transition_delay=tdelay, 263 position=(h - img_width * 0.5, img_v), 264 texture=bui.gettexture('bridgitPreview'), 265 mesh_opaque=mesh_opaque, 266 mesh_transparent=mesh_transparent, 267 mask_texture=mask_tex, 268 ) 269 270 h = self._width * 0.5 271 tdelay = t_delay_base + t_delay_scale * 0.65 272 self._b5 = btn = bui.buttonwidget( 273 parent=self._root_widget, 274 autoselect=True, 275 size=(b_width, b_height), 276 on_activate_call=bui.Call(self._do_game, 'hockey'), 277 position=(h - b_width * 0.5, b_v), 278 label='', 279 button_type='square', 280 transition_delay=tdelay, 281 ) 282 bui.textwidget( 283 parent=self._root_widget, 284 draw_controller=btn, 285 transition_delay=tdelay, 286 size=(0, 0), 287 position=(h, label_height), 288 maxwidth=b_width * 0.7, 289 text=bui.Lstr(translate=('gameNames', 'Hockey')), 290 scale=1.3, 291 h_align='center', 292 v_align='center', 293 ) 294 bui.imagewidget( 295 parent=self._root_widget, 296 draw_controller=btn, 297 size=(img_width, 0.5 * img_width), 298 transition_delay=tdelay, 299 position=(h - img_width * 0.5, img_v), 300 texture=bui.gettexture('hockeyStadiumPreview'), 301 mesh_opaque=mesh_opaque, 302 mesh_transparent=mesh_transparent, 303 mask_texture=mask_tex, 304 ) 305 h = self._width * 0.5 + b_space 306 tdelay = t_delay_base + t_delay_scale * 0.6 307 self._b6 = btn = bui.buttonwidget( 308 parent=self._root_widget, 309 autoselect=True, 310 size=(b_width, b_height), 311 on_activate_call=bui.Call(self._do_game, 'epic'), 312 transition_delay=tdelay, 313 position=(h - b_width * 0.5, b_v), 314 label='', 315 button_type='square', 316 ) 317 bui.textwidget( 318 parent=self._root_widget, 319 draw_controller=btn, 320 transition_delay=tdelay, 321 size=(0, 0), 322 position=(h, label_height), 323 maxwidth=b_width * 0.7, 324 text=bui.Lstr(resource=f'{self._r}.epicModeText'), 325 scale=1.3, 326 h_align='center', 327 v_align='center', 328 ) 329 bui.imagewidget( 330 parent=self._root_widget, 331 draw_controller=btn, 332 transition_delay=tdelay, 333 size=(img_width, 0.5 * img_width), 334 position=(h - img_width * 0.5, img_v), 335 texture=bui.gettexture('tipTopPreview'), 336 mesh_opaque=mesh_opaque, 337 mesh_transparent=mesh_transparent, 338 mask_texture=mask_tex, 339 ) 340 else: 341 self._b4 = self._b5 = self._b6 = None 342 343 self._b7: bui.Widget | None 344 if bui.app.env.arcade: 345 self._b7 = bui.buttonwidget( 346 parent=self._root_widget, 347 autoselect=True, 348 size=(b_width, 50), 349 color=(0.45, 0.55, 0.45), 350 textcolor=(0.7, 0.8, 0.7), 351 scale=0.5, 352 position=(self._width * 0.5 - 60.0, b_v - 70.0), 353 transition_delay=tdelay, 354 label=bui.Lstr(resource=f'{self._r}.fullMenuText'), 355 on_activate_call=self._do_full_menu, 356 ) 357 else: 358 self._b7 = None 359 self._restore_state() 360 self._update() 361 self._update_timer = bui.AppTimer( 362 1.0, bui.WeakCall(self._update), repeat=True 363 ) 364 365 @override 366 def get_main_window_state(self) -> bui.MainWindowState: 367 # Support recreating our window for back/refresh purposes. 368 cls = type(self) 369 return bui.BasicMainWindowState( 370 create_call=lambda transition, origin_widget: cls( 371 transition=transition, origin_widget=origin_widget 372 ) 373 ) 374 375 @override 376 def on_main_window_close(self) -> None: 377 self._save_state() 378 379 def _restore_state(self) -> None: 380 assert bui.app.classic is not None 381 sel_name = bui.app.ui_v1.window_states.get(type(self)) 382 sel: bui.Widget | None 383 if sel_name == 'b1': 384 sel = self._b1 385 elif sel_name == 'b2': 386 sel = self._b2 387 elif sel_name == 'b3': 388 sel = self._b3 389 elif sel_name == 'b4': 390 sel = self._b4 391 elif sel_name == 'b5': 392 sel = self._b5 393 elif sel_name == 'b6': 394 sel = self._b6 395 elif sel_name == 'b7': 396 sel = self._b7 397 else: 398 sel = self._b1 399 if sel: 400 bui.containerwidget(edit=self._root_widget, selected_child=sel) 401 402 def _save_state(self) -> None: 403 sel = self._root_widget.get_selected_child() 404 if sel == self._b1: 405 sel_name = 'b1' 406 elif sel == self._b2: 407 sel_name = 'b2' 408 elif sel == self._b3: 409 sel_name = 'b3' 410 elif sel == self._b4: 411 sel_name = 'b4' 412 elif sel == self._b5: 413 sel_name = 'b5' 414 elif sel == self._b6: 415 sel_name = 'b6' 416 elif sel == self._b7: 417 sel_name = 'b7' 418 else: 419 sel_name = 'b1' 420 assert bui.app.classic is not None 421 bui.app.ui_v1.window_states[type(self)] = sel_name 422 423 def _update(self) -> None: 424 plus = bui.app.plus 425 assert plus is not None 426 427 # Kiosk-mode is designed to be used signed-out... try for force 428 # the issue. 429 if plus.get_v1_account_state() == 'signed_in': 430 # _bs.sign_out() 431 # FIXME: Try to delete player profiles here too. 432 pass 433 else: 434 # Also make sure there's no player profiles. 435 appconfig = bui.app.config 436 appconfig['Player Profiles'] = {} 437 438 def _do_game(self, mode: str) -> None: 439 assert bui.app.classic is not None 440 self._save_state() 441 if mode in ['epic', 'ctf', 'hockey']: 442 appconfig = bui.app.config 443 if 'Team Tournament Playlists' not in appconfig: 444 appconfig['Team Tournament Playlists'] = {} 445 if 'Free-for-All Playlists' not in appconfig: 446 appconfig['Free-for-All Playlists'] = {} 447 appconfig['Show Tutorial'] = False 448 if mode == 'epic': 449 appconfig['Free-for-All Playlists']['Just Epic Elim'] = [ 450 { 451 'settings': { 452 'Epic Mode': 1, 453 'Lives Per Player': 1, 454 'Respawn Times': 1.0, 455 'Time Limit': 0, 456 'map': 'Tip Top', 457 }, 458 'type': 'bs_elimination.EliminationGame', 459 } 460 ] 461 appconfig['Free-for-All Playlist Selection'] = 'Just Epic Elim' 462 bui.fade_screen( 463 False, 464 endcall=bui.Call( 465 bui.pushcall, 466 bui.Call(bs.new_host_session, bs.FreeForAllSession), 467 ), 468 ) 469 else: 470 if mode == 'ctf': 471 appconfig['Team Tournament Playlists']['Just CTF'] = [ 472 { 473 'settings': { 474 'Epic Mode': False, 475 'Flag Idle Return Time': 30, 476 'Flag Touch Return Time': 0, 477 'Respawn Times': 1.0, 478 'Score to Win': 3, 479 'Time Limit': 0, 480 'map': 'Bridgit', 481 }, 482 'type': 'bs_capture_the_flag.CTFGame', 483 } 484 ] 485 appconfig['Team Tournament Playlist Selection'] = 'Just CTF' 486 else: 487 appconfig['Team Tournament Playlists']['Just Hockey'] = [ 488 { 489 'settings': { 490 'Respawn Times': 1.0, 491 'Score to Win': 1, 492 'Time Limit': 0, 493 'map': 'Hockey Stadium', 494 }, 495 'type': 'bs_hockey.HockeyGame', 496 } 497 ] 498 appconfig['Team Tournament Playlist Selection'] = ( 499 'Just Hockey' 500 ) 501 bui.fade_screen( 502 False, 503 endcall=bui.Call( 504 bui.pushcall, 505 bui.Call(bs.new_host_session, bs.DualTeamSession), 506 ), 507 ) 508 bui.containerwidget(edit=self._root_widget, transition='out_left') 509 return 510 511 game = ( 512 'Easy:Onslaught Training' 513 if mode == 'easy' 514 else ( 515 'Easy:Rookie Football' 516 if mode == 'medium' 517 else 'Easy:Uber Onslaught' 518 ) 519 ) 520 cfg = bui.app.config 521 cfg['Selected Coop Game'] = game 522 cfg.commit() 523 if bui.app.classic.launch_coop_game(game, force=True): 524 bui.containerwidget(edit=self._root_widget, transition='out_left') 525 526 def _do_full_menu(self) -> None: 527 # pylint: disable=cyclic-import 528 from bauiv1lib.mainmenu import MainMenuWindow 529 530 # no-op if we're not in control. 531 if not self.main_window_has_control(): 532 return 533 534 assert bui.app.classic is not None 535 536 self._save_state() 537 bui.app.classic.did_menu_intro = True # prevent delayed transition-in 538 539 self.main_window_replace(MainMenuWindow())
Kiosk mode window.
KioskWindow( transition: str | None = 'in_right', origin_widget: _bauiv1.Widget | None = None)
17 def __init__( 18 self, 19 transition: str | None = 'in_right', 20 origin_widget: bui.Widget | None = None, 21 ): 22 # pylint: disable=too-many-locals, too-many-statements 23 from bauiv1lib.confirm import QuitWindow 24 25 assert bui.app.classic is not None 26 27 self._width = 720.0 28 self._height = 340.0 29 30 def _do_cancel() -> None: 31 QuitWindow(swish=True, quit_type=bui.QuitType.BACK) 32 33 super().__init__( 34 root_widget=bui.containerwidget( 35 size=(self._width, self._height), 36 # transition=transition, 37 on_cancel_call=_do_cancel, 38 background=False, 39 stack_offset=(0, -130), 40 ), 41 transition=transition, 42 origin_widget=origin_widget, 43 ) 44 45 self._r = 'kioskWindow' 46 47 self._show_multiplayer = False 48 49 # Let's reset all random player names every time we hit the main menu. 50 bs.reset_random_player_names() 51 52 # Reset achievements too (at least locally). 53 bui.app.config['Achievements'] = {} 54 55 t_delay_base = 0.0 56 t_delay_scale = 0.0 57 if not bui.app.classic.did_menu_intro: 58 t_delay_base = 1.0 59 t_delay_scale = 1.0 60 61 mesh_opaque = bui.getmesh('level_select_button_opaque') 62 mesh_transparent = bui.getmesh('level_select_button_transparent') 63 mask_tex = bui.gettexture('mapPreviewMask') 64 65 y_extra = 130.0 + (0.0 if self._show_multiplayer else -130.0) 66 b_width = 250.0 67 b_height = 200.0 68 b_space = 280.0 69 b_v = 80.0 + y_extra 70 label_height = 130.0 + y_extra 71 img_width = 180.0 72 img_v = 158.0 + y_extra 73 74 if self._show_multiplayer: 75 tdelay = t_delay_base + t_delay_scale * 1.3 76 bui.textwidget( 77 parent=self._root_widget, 78 size=(0, 0), 79 position=(self._width * 0.5, self._height + y_extra - 44), 80 transition_delay=tdelay, 81 text=bui.Lstr(resource=f'{self._r}.singlePlayerExamplesText'), 82 flatness=1.0, 83 scale=1.2, 84 h_align='center', 85 v_align='center', 86 shadow=1.0, 87 ) 88 else: 89 tdelay = t_delay_base + t_delay_scale * 0.7 90 bui.textwidget( 91 parent=self._root_widget, 92 size=(0, 0), 93 position=(self._width * 0.5, self._height + y_extra - 34), 94 transition_delay=tdelay, 95 text=( 96 bui.Lstr( 97 resource='demoText', 98 fallback_resource='mainMenu.demoMenuText', 99 ) 100 if bui.app.env.demo 101 else 'ARCADE' 102 ), 103 flatness=1.0, 104 scale=1.2, 105 h_align='center', 106 v_align='center', 107 shadow=1.0, 108 ) 109 h = self._width * 0.5 - b_space 110 tdelay = t_delay_base + t_delay_scale * 0.7 111 self._b1 = btn = bui.buttonwidget( 112 parent=self._root_widget, 113 autoselect=True, 114 size=(b_width, b_height), 115 on_activate_call=bui.Call(self._do_game, 'easy'), 116 transition_delay=tdelay, 117 position=(h - b_width * 0.5, b_v), 118 label='', 119 button_type='square', 120 ) 121 bui.textwidget( 122 parent=self._root_widget, 123 draw_controller=btn, 124 transition_delay=tdelay, 125 size=(0, 0), 126 position=(h, label_height), 127 maxwidth=b_width * 0.7, 128 text=bui.Lstr(resource=f'{self._r}.easyText'), 129 scale=1.3, 130 h_align='center', 131 v_align='center', 132 ) 133 bui.imagewidget( 134 parent=self._root_widget, 135 draw_controller=btn, 136 size=(img_width, 0.5 * img_width), 137 transition_delay=tdelay, 138 position=(h - img_width * 0.5, img_v), 139 texture=bui.gettexture('doomShroomPreview'), 140 mesh_opaque=mesh_opaque, 141 mesh_transparent=mesh_transparent, 142 mask_texture=mask_tex, 143 ) 144 h = self._width * 0.5 145 tdelay = t_delay_base + t_delay_scale * 0.65 146 self._b2 = btn = bui.buttonwidget( 147 parent=self._root_widget, 148 autoselect=True, 149 size=(b_width, b_height), 150 on_activate_call=bui.Call(self._do_game, 'medium'), 151 position=(h - b_width * 0.5, b_v), 152 label='', 153 button_type='square', 154 transition_delay=tdelay, 155 ) 156 bui.textwidget( 157 parent=self._root_widget, 158 draw_controller=btn, 159 transition_delay=tdelay, 160 size=(0, 0), 161 position=(h, label_height), 162 maxwidth=b_width * 0.7, 163 text=bui.Lstr(resource=f'{self._r}.mediumText'), 164 scale=1.3, 165 h_align='center', 166 v_align='center', 167 ) 168 bui.imagewidget( 169 parent=self._root_widget, 170 draw_controller=btn, 171 size=(img_width, 0.5 * img_width), 172 transition_delay=tdelay, 173 position=(h - img_width * 0.5, img_v), 174 texture=bui.gettexture('footballStadiumPreview'), 175 mesh_opaque=mesh_opaque, 176 mesh_transparent=mesh_transparent, 177 mask_texture=mask_tex, 178 ) 179 h = self._width * 0.5 + b_space 180 tdelay = t_delay_base + t_delay_scale * 0.6 181 self._b3 = btn = bui.buttonwidget( 182 parent=self._root_widget, 183 autoselect=True, 184 size=(b_width, b_height), 185 on_activate_call=bui.Call(self._do_game, 'hard'), 186 transition_delay=tdelay, 187 position=(h - b_width * 0.5, b_v), 188 label='', 189 button_type='square', 190 ) 191 bui.textwidget( 192 parent=self._root_widget, 193 draw_controller=btn, 194 transition_delay=tdelay, 195 size=(0, 0), 196 position=(h, label_height), 197 maxwidth=b_width * 0.7, 198 text='Hard', 199 scale=1.3, 200 h_align='center', 201 v_align='center', 202 ) 203 bui.imagewidget( 204 parent=self._root_widget, 205 draw_controller=btn, 206 transition_delay=tdelay, 207 size=(img_width, 0.5 * img_width), 208 position=(h - img_width * 0.5, img_v), 209 texture=bui.gettexture('courtyardPreview'), 210 mesh_opaque=mesh_opaque, 211 mesh_transparent=mesh_transparent, 212 mask_texture=mask_tex, 213 ) 214 if not bui.app.classic.did_menu_intro: 215 bui.app.classic.did_menu_intro = True 216 217 self._b4: bui.Widget | None 218 self._b5: bui.Widget | None 219 self._b6: bui.Widget | None 220 221 if bool(False): 222 bui.textwidget( 223 parent=self._root_widget, 224 size=(0, 0), 225 position=(self._width * 0.5, self._height + y_extra - 44), 226 transition_delay=tdelay, 227 text=bui.Lstr(resource=f'{self._r}.versusExamplesText'), 228 flatness=1.0, 229 scale=1.2, 230 h_align='center', 231 v_align='center', 232 shadow=1.0, 233 ) 234 h = self._width * 0.5 - b_space 235 tdelay = t_delay_base + t_delay_scale * 0.7 236 self._b4 = btn = bui.buttonwidget( 237 parent=self._root_widget, 238 autoselect=True, 239 size=(b_width, b_height), 240 on_activate_call=bui.Call(self._do_game, 'ctf'), 241 transition_delay=tdelay, 242 position=(h - b_width * 0.5, b_v), 243 label='', 244 button_type='square', 245 ) 246 bui.textwidget( 247 parent=self._root_widget, 248 draw_controller=btn, 249 transition_delay=tdelay, 250 size=(0, 0), 251 position=(h, label_height), 252 maxwidth=b_width * 0.7, 253 text=bui.Lstr(translate=('gameNames', 'Capture the Flag')), 254 scale=1.3, 255 h_align='center', 256 v_align='center', 257 ) 258 bui.imagewidget( 259 parent=self._root_widget, 260 draw_controller=btn, 261 size=(img_width, 0.5 * img_width), 262 transition_delay=tdelay, 263 position=(h - img_width * 0.5, img_v), 264 texture=bui.gettexture('bridgitPreview'), 265 mesh_opaque=mesh_opaque, 266 mesh_transparent=mesh_transparent, 267 mask_texture=mask_tex, 268 ) 269 270 h = self._width * 0.5 271 tdelay = t_delay_base + t_delay_scale * 0.65 272 self._b5 = btn = bui.buttonwidget( 273 parent=self._root_widget, 274 autoselect=True, 275 size=(b_width, b_height), 276 on_activate_call=bui.Call(self._do_game, 'hockey'), 277 position=(h - b_width * 0.5, b_v), 278 label='', 279 button_type='square', 280 transition_delay=tdelay, 281 ) 282 bui.textwidget( 283 parent=self._root_widget, 284 draw_controller=btn, 285 transition_delay=tdelay, 286 size=(0, 0), 287 position=(h, label_height), 288 maxwidth=b_width * 0.7, 289 text=bui.Lstr(translate=('gameNames', 'Hockey')), 290 scale=1.3, 291 h_align='center', 292 v_align='center', 293 ) 294 bui.imagewidget( 295 parent=self._root_widget, 296 draw_controller=btn, 297 size=(img_width, 0.5 * img_width), 298 transition_delay=tdelay, 299 position=(h - img_width * 0.5, img_v), 300 texture=bui.gettexture('hockeyStadiumPreview'), 301 mesh_opaque=mesh_opaque, 302 mesh_transparent=mesh_transparent, 303 mask_texture=mask_tex, 304 ) 305 h = self._width * 0.5 + b_space 306 tdelay = t_delay_base + t_delay_scale * 0.6 307 self._b6 = btn = bui.buttonwidget( 308 parent=self._root_widget, 309 autoselect=True, 310 size=(b_width, b_height), 311 on_activate_call=bui.Call(self._do_game, 'epic'), 312 transition_delay=tdelay, 313 position=(h - b_width * 0.5, b_v), 314 label='', 315 button_type='square', 316 ) 317 bui.textwidget( 318 parent=self._root_widget, 319 draw_controller=btn, 320 transition_delay=tdelay, 321 size=(0, 0), 322 position=(h, label_height), 323 maxwidth=b_width * 0.7, 324 text=bui.Lstr(resource=f'{self._r}.epicModeText'), 325 scale=1.3, 326 h_align='center', 327 v_align='center', 328 ) 329 bui.imagewidget( 330 parent=self._root_widget, 331 draw_controller=btn, 332 transition_delay=tdelay, 333 size=(img_width, 0.5 * img_width), 334 position=(h - img_width * 0.5, img_v), 335 texture=bui.gettexture('tipTopPreview'), 336 mesh_opaque=mesh_opaque, 337 mesh_transparent=mesh_transparent, 338 mask_texture=mask_tex, 339 ) 340 else: 341 self._b4 = self._b5 = self._b6 = None 342 343 self._b7: bui.Widget | None 344 if bui.app.env.arcade: 345 self._b7 = bui.buttonwidget( 346 parent=self._root_widget, 347 autoselect=True, 348 size=(b_width, 50), 349 color=(0.45, 0.55, 0.45), 350 textcolor=(0.7, 0.8, 0.7), 351 scale=0.5, 352 position=(self._width * 0.5 - 60.0, b_v - 70.0), 353 transition_delay=tdelay, 354 label=bui.Lstr(resource=f'{self._r}.fullMenuText'), 355 on_activate_call=self._do_full_menu, 356 ) 357 else: 358 self._b7 = None 359 self._restore_state() 360 self._update() 361 self._update_timer = bui.AppTimer( 362 1.0, bui.WeakCall(self._update), repeat=True 363 )
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.
365 @override 366 def get_main_window_state(self) -> bui.MainWindowState: 367 # Support recreating our window for back/refresh purposes. 368 cls = type(self) 369 return bui.BasicMainWindowState( 370 create_call=lambda transition, origin_widget: cls( 371 transition=transition, origin_widget=origin_widget 372 ) 373 )
Return a WindowState to recreate this window, if supported.