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

Kiosk mode window.

KioskWindow( transition: str | None = 'in_right', origin_widget: _bauiv1.Widget | None = None)
 15    def __init__(
 16        self,
 17        transition: str | None = 'in_right',
 18        origin_widget: bui.Widget | None = None,
 19    ):
 20        # pylint: disable=too-many-locals, too-many-statements
 21        from bauiv1lib.confirm import QuitWindow
 22
 23        assert bui.app.classic is not None
 24
 25        self._width = 720.0
 26        self._height = 340.0
 27
 28        def _do_cancel() -> None:
 29            QuitWindow(swish=True, quit_type=bui.QuitType.BACK)
 30
 31        super().__init__(
 32            root_widget=bui.containerwidget(
 33                size=(self._width, self._height),
 34                # transition=transition,
 35                on_cancel_call=_do_cancel,
 36                background=False,
 37                stack_offset=(0, -130),
 38            ),
 39            transition=transition,
 40            origin_widget=origin_widget,
 41        )
 42
 43        self._r = 'kioskWindow'
 44
 45        self._show_multiplayer = False
 46
 47        # Let's reset all random player names every time we hit the main menu.
 48        bs.reset_random_player_names()
 49
 50        # Reset achievements too (at least locally).
 51        bui.app.config['Achievements'] = {}
 52
 53        t_delay_base = 0.0
 54        t_delay_scale = 0.0
 55        if not bui.app.classic.did_menu_intro:
 56            t_delay_base = 1.0
 57            t_delay_scale = 1.0
 58
 59        mesh_opaque = bui.getmesh('level_select_button_opaque')
 60        mesh_transparent = bui.getmesh('level_select_button_transparent')
 61        mask_tex = bui.gettexture('mapPreviewMask')
 62
 63        y_extra = 130.0 + (0.0 if self._show_multiplayer else -130.0)
 64        b_width = 250.0
 65        b_height = 200.0
 66        b_space = 280.0
 67        b_v = 80.0 + y_extra
 68        label_height = 130.0 + y_extra
 69        img_width = 180.0
 70        img_v = 158.0 + y_extra
 71
 72        if self._show_multiplayer:
 73            tdelay = t_delay_base + t_delay_scale * 1.3
 74            bui.textwidget(
 75                parent=self._root_widget,
 76                size=(0, 0),
 77                position=(self._width * 0.5, self._height + y_extra - 44),
 78                transition_delay=tdelay,
 79                text=bui.Lstr(resource=f'{self._r}.singlePlayerExamplesText'),
 80                flatness=1.0,
 81                scale=1.2,
 82                h_align='center',
 83                v_align='center',
 84                shadow=1.0,
 85            )
 86        else:
 87            tdelay = t_delay_base + t_delay_scale * 0.7
 88            bui.textwidget(
 89                parent=self._root_widget,
 90                size=(0, 0),
 91                position=(self._width * 0.5, self._height + y_extra - 34),
 92                transition_delay=tdelay,
 93                text=(
 94                    bui.Lstr(
 95                        resource='demoText',
 96                        fallback_resource='mainMenu.demoMenuText',
 97                    )
 98                    if bui.app.env.demo
 99                    else 'ARCADE'
100                ),
101                flatness=1.0,
102                scale=1.2,
103                h_align='center',
104                v_align='center',
105                shadow=1.0,
106            )
107        h = self._width * 0.5 - b_space
108        tdelay = t_delay_base + t_delay_scale * 0.7
109        self._b1 = btn = bui.buttonwidget(
110            parent=self._root_widget,
111            autoselect=True,
112            size=(b_width, b_height),
113            on_activate_call=bui.Call(self._do_game, 'easy'),
114            transition_delay=tdelay,
115            position=(h - b_width * 0.5, b_v),
116            label='',
117            button_type='square',
118        )
119        bui.textwidget(
120            parent=self._root_widget,
121            draw_controller=btn,
122            transition_delay=tdelay,
123            size=(0, 0),
124            position=(h, label_height),
125            maxwidth=b_width * 0.7,
126            text=bui.Lstr(resource=f'{self._r}.easyText'),
127            scale=1.3,
128            h_align='center',
129            v_align='center',
130        )
131        bui.imagewidget(
132            parent=self._root_widget,
133            draw_controller=btn,
134            size=(img_width, 0.5 * img_width),
135            transition_delay=tdelay,
136            position=(h - img_width * 0.5, img_v),
137            texture=bui.gettexture('doomShroomPreview'),
138            mesh_opaque=mesh_opaque,
139            mesh_transparent=mesh_transparent,
140            mask_texture=mask_tex,
141        )
142        h = self._width * 0.5
143        tdelay = t_delay_base + t_delay_scale * 0.65
144        self._b2 = btn = bui.buttonwidget(
145            parent=self._root_widget,
146            autoselect=True,
147            size=(b_width, b_height),
148            on_activate_call=bui.Call(self._do_game, 'medium'),
149            position=(h - b_width * 0.5, b_v),
150            label='',
151            button_type='square',
152            transition_delay=tdelay,
153        )
154        bui.textwidget(
155            parent=self._root_widget,
156            draw_controller=btn,
157            transition_delay=tdelay,
158            size=(0, 0),
159            position=(h, label_height),
160            maxwidth=b_width * 0.7,
161            text=bui.Lstr(resource=f'{self._r}.mediumText'),
162            scale=1.3,
163            h_align='center',
164            v_align='center',
165        )
166        bui.imagewidget(
167            parent=self._root_widget,
168            draw_controller=btn,
169            size=(img_width, 0.5 * img_width),
170            transition_delay=tdelay,
171            position=(h - img_width * 0.5, img_v),
172            texture=bui.gettexture('footballStadiumPreview'),
173            mesh_opaque=mesh_opaque,
174            mesh_transparent=mesh_transparent,
175            mask_texture=mask_tex,
176        )
177        h = self._width * 0.5 + b_space
178        tdelay = t_delay_base + t_delay_scale * 0.6
179        self._b3 = btn = bui.buttonwidget(
180            parent=self._root_widget,
181            autoselect=True,
182            size=(b_width, b_height),
183            on_activate_call=bui.Call(self._do_game, 'hard'),
184            transition_delay=tdelay,
185            position=(h - b_width * 0.5, b_v),
186            label='',
187            button_type='square',
188        )
189        bui.textwidget(
190            parent=self._root_widget,
191            draw_controller=btn,
192            transition_delay=tdelay,
193            size=(0, 0),
194            position=(h, label_height),
195            maxwidth=b_width * 0.7,
196            text='Hard',
197            scale=1.3,
198            h_align='center',
199            v_align='center',
200        )
201        bui.imagewidget(
202            parent=self._root_widget,
203            draw_controller=btn,
204            transition_delay=tdelay,
205            size=(img_width, 0.5 * img_width),
206            position=(h - img_width * 0.5, img_v),
207            texture=bui.gettexture('courtyardPreview'),
208            mesh_opaque=mesh_opaque,
209            mesh_transparent=mesh_transparent,
210            mask_texture=mask_tex,
211        )
212        if not bui.app.classic.did_menu_intro:
213            bui.app.classic.did_menu_intro = True
214
215        self._b4: bui.Widget | None
216        self._b5: bui.Widget | None
217        self._b6: bui.Widget | None
218
219        if bool(False):
220            bui.textwidget(
221                parent=self._root_widget,
222                size=(0, 0),
223                position=(self._width * 0.5, self._height + y_extra - 44),
224                transition_delay=tdelay,
225                text=bui.Lstr(resource=f'{self._r}.versusExamplesText'),
226                flatness=1.0,
227                scale=1.2,
228                h_align='center',
229                v_align='center',
230                shadow=1.0,
231            )
232            h = self._width * 0.5 - b_space
233            tdelay = t_delay_base + t_delay_scale * 0.7
234            self._b4 = btn = bui.buttonwidget(
235                parent=self._root_widget,
236                autoselect=True,
237                size=(b_width, b_height),
238                on_activate_call=bui.Call(self._do_game, 'ctf'),
239                transition_delay=tdelay,
240                position=(h - b_width * 0.5, b_v),
241                label='',
242                button_type='square',
243            )
244            bui.textwidget(
245                parent=self._root_widget,
246                draw_controller=btn,
247                transition_delay=tdelay,
248                size=(0, 0),
249                position=(h, label_height),
250                maxwidth=b_width * 0.7,
251                text=bui.Lstr(translate=('gameNames', 'Capture the Flag')),
252                scale=1.3,
253                h_align='center',
254                v_align='center',
255            )
256            bui.imagewidget(
257                parent=self._root_widget,
258                draw_controller=btn,
259                size=(img_width, 0.5 * img_width),
260                transition_delay=tdelay,
261                position=(h - img_width * 0.5, img_v),
262                texture=bui.gettexture('bridgitPreview'),
263                mesh_opaque=mesh_opaque,
264                mesh_transparent=mesh_transparent,
265                mask_texture=mask_tex,
266            )
267
268            h = self._width * 0.5
269            tdelay = t_delay_base + t_delay_scale * 0.65
270            self._b5 = btn = bui.buttonwidget(
271                parent=self._root_widget,
272                autoselect=True,
273                size=(b_width, b_height),
274                on_activate_call=bui.Call(self._do_game, 'hockey'),
275                position=(h - b_width * 0.5, b_v),
276                label='',
277                button_type='square',
278                transition_delay=tdelay,
279            )
280            bui.textwidget(
281                parent=self._root_widget,
282                draw_controller=btn,
283                transition_delay=tdelay,
284                size=(0, 0),
285                position=(h, label_height),
286                maxwidth=b_width * 0.7,
287                text=bui.Lstr(translate=('gameNames', 'Hockey')),
288                scale=1.3,
289                h_align='center',
290                v_align='center',
291            )
292            bui.imagewidget(
293                parent=self._root_widget,
294                draw_controller=btn,
295                size=(img_width, 0.5 * img_width),
296                transition_delay=tdelay,
297                position=(h - img_width * 0.5, img_v),
298                texture=bui.gettexture('hockeyStadiumPreview'),
299                mesh_opaque=mesh_opaque,
300                mesh_transparent=mesh_transparent,
301                mask_texture=mask_tex,
302            )
303            h = self._width * 0.5 + b_space
304            tdelay = t_delay_base + t_delay_scale * 0.6
305            self._b6 = btn = bui.buttonwidget(
306                parent=self._root_widget,
307                autoselect=True,
308                size=(b_width, b_height),
309                on_activate_call=bui.Call(self._do_game, 'epic'),
310                transition_delay=tdelay,
311                position=(h - b_width * 0.5, b_v),
312                label='',
313                button_type='square',
314            )
315            bui.textwidget(
316                parent=self._root_widget,
317                draw_controller=btn,
318                transition_delay=tdelay,
319                size=(0, 0),
320                position=(h, label_height),
321                maxwidth=b_width * 0.7,
322                text=bui.Lstr(resource=f'{self._r}.epicModeText'),
323                scale=1.3,
324                h_align='center',
325                v_align='center',
326            )
327            bui.imagewidget(
328                parent=self._root_widget,
329                draw_controller=btn,
330                transition_delay=tdelay,
331                size=(img_width, 0.5 * img_width),
332                position=(h - img_width * 0.5, img_v),
333                texture=bui.gettexture('tipTopPreview'),
334                mesh_opaque=mesh_opaque,
335                mesh_transparent=mesh_transparent,
336                mask_texture=mask_tex,
337            )
338        else:
339            self._b4 = self._b5 = self._b6 = None
340
341        self._b7: bui.Widget | None
342        if bui.app.env.arcade:
343            self._b7 = bui.buttonwidget(
344                parent=self._root_widget,
345                autoselect=True,
346                size=(b_width, 50),
347                color=(0.45, 0.55, 0.45),
348                textcolor=(0.7, 0.8, 0.7),
349                scale=0.5,
350                position=(self._width * 0.5 - 60.0, b_v - 70.0),
351                transition_delay=tdelay,
352                label=bui.Lstr(resource=f'{self._r}.fullMenuText'),
353                on_activate_call=self._do_full_menu,
354            )
355        else:
356            self._b7 = None
357        self._restore_state()
358        self._update()
359        self._update_timer = bui.AppTimer(
360            1.0, bui.WeakCall(self._update), repeat=True
361        )

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.

Inherited Members
bauiv1._uitypes.MainWindow
main_window_back_state
main_window_close
can_change_main_window
main_window_back
main_window_replace
on_main_window_close
get_main_window_state
bauiv1._uitypes.Window
get_root_widget