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

Kiosk mode window.

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