Example #1
0
 def _free_for_all(self) -> None:
     # pylint: disable=cyclic-import
     from bastd.ui.playlist.browser import PlaylistBrowserWindow
     self._save_state()
     ba.containerwidget(edit=self._root_widget, transition='out_left')
     ba.app.main_menu_window = (PlaylistBrowserWindow(
         origin_widget=self._free_for_all_button,
         sessiontype=ba.FreeForAllSession).get_root_widget())
Example #2
0
 def _team_tourney(self) -> None:
     # pylint: disable=cyclic-import
     from bastd.ui.playlist.browser import PlaylistBrowserWindow
     self._save_state()
     ba.containerwidget(edit=self._root_widget, transition='out_left')
     ba.app.main_menu_window = (PlaylistBrowserWindow(
         origin_widget=self._teams_button,
         sessiontype=ba.DualTeamSession).get_root_widget())
Example #3
0
    def on_transition_in(self) -> None:
        super().on_transition_in()
        random.seed(123)
        self._logo_node: Optional[ba.Node] = None
        self._custom_logo_tex_name: Optional[str] = None
        self._word_actors: List[ba.Actor] = []
        app = ba.app

        # FIXME: We shouldn't be doing things conditionally based on whether
        #  the host is VR mode or not (clients may differ in that regard).
        #  Any differences need to happen at the engine level so everyone
        #  sees things in their own optimal way.
        vr_mode = ba.app.vr_mode

        if not ba.app.toolbar_test:
            color = ((1.0, 1.0, 1.0, 1.0) if vr_mode else (0.5, 0.6, 0.5, 0.6))
            # FIXME: Need a node attr for vr-specific-scale.
            scale = (0.9 if
                     (app.ui.uiscale is ba.UIScale.SMALL or vr_mode) else 0.7)
            self.my_name = ba.NodeActor(
                ba.newnode('text',
                           attrs={
                               'v_attach': 'bottom',
                               'h_align': 'center',
                               'color': color,
                               'flatness': 1.0,
                               'shadow': 1.0 if vr_mode else 0.5,
                               'scale': scale,
                               'position': (0, 10),
                               'vr_depth': -10,
                               'text': '\xa9 2011-2020 Eric Froemling'
                           }))

        # Throw up some text that only clients can see so they know that the
        # host is navigating menus while they're just staring at an
        # empty-ish screen.
        tval = ba.Lstr(resource='hostIsNavigatingMenusText',
                       subs=[('${HOST}', _ba.get_account_display_string())])
        self._host_is_navigating_text = ba.NodeActor(
            ba.newnode('text',
                       attrs={
                           'text': tval,
                           'client_only': True,
                           'position': (0, -200),
                           'flatness': 1.0,
                           'h_align': 'center'
                       }))
        if not ba.app.main_menu_did_initial_transition and hasattr(
                self, 'my_name'):
            assert self.my_name.node
            ba.animate(self.my_name.node, 'opacity', {2.3: 0, 3.0: 1.0})

        # FIXME: We shouldn't be doing things conditionally based on whether
        #  the host is vr mode or not (clients may not be or vice versa).
        #  Any differences need to happen at the engine level so everyone sees
        #  things in their own optimal way.
        vr_mode = app.vr_mode
        uiscale = app.ui.uiscale

        # In cases where we're doing lots of dev work lets always show the
        # build number.
        force_show_build_number = False

        if not ba.app.toolbar_test:
            if app.debug_build or app.test_build or force_show_build_number:
                if app.debug_build:
                    text = ba.Lstr(value='${V} (${B}) (${D})',
                                   subs=[
                                       ('${V}', app.version),
                                       ('${B}', str(app.build_number)),
                                       ('${D}', ba.Lstr(resource='debugText')),
                                   ])
                else:
                    text = ba.Lstr(value='${V} (${B})',
                                   subs=[
                                       ('${V}', app.version),
                                       ('${B}', str(app.build_number)),
                                   ])
            else:
                text = ba.Lstr(value='${V}', subs=[('${V}', app.version)])
            scale = 0.9 if (uiscale is ba.UIScale.SMALL or vr_mode) else 0.7
            color = (1, 1, 1, 1) if vr_mode else (0.5, 0.6, 0.5, 0.7)
            self.version = ba.NodeActor(
                ba.newnode(
                    'text',
                    attrs={
                        'v_attach': 'bottom',
                        'h_attach': 'right',
                        'h_align': 'right',
                        'flatness': 1.0,
                        'vr_depth': -10,
                        'shadow': 1.0 if vr_mode else 0.5,
                        'color': color,
                        'scale': scale,
                        'position': (-260, 10) if vr_mode else (-10, 10),
                        'text': text
                    }))
            if not ba.app.main_menu_did_initial_transition:
                assert self.version.node
                ba.animate(self.version.node, 'opacity', {2.3: 0, 3.0: 1.0})

        # Show the iircade logo on our iircade build.
        if app.iircade_mode:
            img = ba.NodeActor(
                ba.newnode('image',
                           attrs={
                               'texture': ba.gettexture('iircadeLogo'),
                               'attach': 'center',
                               'scale': (250, 250),
                               'position': (0, 0),
                               'tilt_translate': 0.21,
                               'absolute_scale': True
                           })).autoretain()
            imgdelay = 0.0 if app.main_menu_did_initial_transition else 1.0
            ba.animate(img.node, 'opacity', {
                imgdelay + 1.5: 0.0,
                imgdelay + 2.5: 1.0
            })

        # Throw in test build info.
        self.beta_info = self.beta_info_2 = None
        if app.test_build and not (app.demo_mode or app.arcade_mode):
            pos = ((230, 125) if (app.demo_mode or app.arcade_mode) else
                   (230, 35))
            self.beta_info = ba.NodeActor(
                ba.newnode('text',
                           attrs={
                               'v_attach': 'center',
                               'h_align': 'center',
                               'color': (1, 1, 1, 1),
                               'shadow': 0.5,
                               'flatness': 0.5,
                               'scale': 1,
                               'vr_depth': -60,
                               'position': pos,
                               'text': ba.Lstr(resource='testBuildText')
                           }))
            if not ba.app.main_menu_did_initial_transition:
                assert self.beta_info.node
                ba.animate(self.beta_info.node, 'opacity', {1.3: 0, 1.8: 1.0})

        model = ba.getmodel('thePadLevel')
        trees_model = ba.getmodel('trees')
        bottom_model = ba.getmodel('thePadLevelBottom')
        color_texture = ba.gettexture('thePadLevelColor')
        trees_texture = ba.gettexture('treesColor')
        bgtex = ba.gettexture('menuBG')
        bgmodel = ba.getmodel('thePadBG')

        # Load these last since most platforms don't use them.
        vr_bottom_fill_model = ba.getmodel('thePadVRFillBottom')
        vr_top_fill_model = ba.getmodel('thePadVRFillTop')

        gnode = self.globalsnode
        gnode.camera_mode = 'rotate'

        tint = (1.14, 1.1, 1.0)
        gnode.tint = tint
        gnode.ambient_color = (1.06, 1.04, 1.03)
        gnode.vignette_outer = (0.45, 0.55, 0.54)
        gnode.vignette_inner = (0.99, 0.98, 0.98)

        self.bottom = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': bottom_model,
                           'lighting': False,
                           'reflection': 'soft',
                           'reflection_scale': [0.45],
                           'color_texture': color_texture
                       }))
        self.vr_bottom_fill = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': vr_bottom_fill_model,
                           'lighting': False,
                           'vr_only': True,
                           'color_texture': color_texture
                       }))
        self.vr_top_fill = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': vr_top_fill_model,
                           'vr_only': True,
                           'lighting': False,
                           'color_texture': bgtex
                       }))
        self.terrain = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': model,
                           'color_texture': color_texture,
                           'reflection': 'soft',
                           'reflection_scale': [0.3]
                       }))
        self.trees = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': trees_model,
                           'lighting': False,
                           'reflection': 'char',
                           'reflection_scale': [0.1],
                           'color_texture': trees_texture
                       }))
        self.bgterrain = ba.NodeActor(
            ba.newnode('terrain',
                       attrs={
                           'model': bgmodel,
                           'color': (0.92, 0.91, 0.9),
                           'lighting': False,
                           'background': True,
                           'color_texture': bgtex
                       }))

        self._ts = 0.86

        self._language: Optional[str] = None
        self._update_timer = ba.Timer(1.0, self._update, repeat=True)
        self._update()

        # Hopefully this won't hitch but lets space these out anyway.
        _ba.add_clean_frame_callback(ba.WeakCall(self._start_preloads))

        random.seed()

        # On the main menu, also show our news.
        class News:
            """Wrangles news display."""

            def __init__(self, activity: ba.Activity):
                self._valid = True
                self._message_duration = 10.0
                self._message_spacing = 2.0
                self._text: Optional[ba.NodeActor] = None
                self._activity = weakref.ref(activity)

                # If we're signed in, fetch news immediately.
                # Otherwise wait until we are signed in.
                self._fetch_timer: Optional[ba.Timer] = ba.Timer(
                    1.0, ba.WeakCall(self._try_fetching_news), repeat=True)
                self._try_fetching_news()

            # We now want to wait until we're signed in before fetching news.
            def _try_fetching_news(self) -> None:
                if _ba.get_account_state() == 'signed_in':
                    self._fetch_news()
                    self._fetch_timer = None

            def _fetch_news(self) -> None:
                ba.app.main_menu_last_news_fetch_time = time.time()

                # UPDATE - We now just pull news from MRVs.
                news = _ba.get_account_misc_read_val('n', None)
                if news is not None:
                    self._got_news(news)

            def _change_phrase(self) -> None:
                from bastd.actor.text import Text

                # If our news is way out of date, lets re-request it;
                # otherwise, rotate our phrase.
                assert ba.app.main_menu_last_news_fetch_time is not None
                if time.time() - ba.app.main_menu_last_news_fetch_time > 600.0:
                    self._fetch_news()
                    self._text = None
                else:
                    if self._text is not None:
                        if not self._phrases:
                            for phr in self._used_phrases:
                                self._phrases.insert(0, phr)
                        val = self._phrases.pop()
                        if val == '__ACH__':
                            vrmode = app.vr_mode
                            Text(ba.Lstr(resource='nextAchievementsText'),
                                 color=((1, 1, 1, 1) if vrmode else
                                        (0.95, 0.9, 1, 0.4)),
                                 host_only=True,
                                 maxwidth=200,
                                 position=(-300, -35),
                                 h_align=Text.HAlign.RIGHT,
                                 transition=Text.Transition.FADE_IN,
                                 scale=0.9 if vrmode else 0.7,
                                 flatness=1.0 if vrmode else 0.6,
                                 shadow=1.0 if vrmode else 0.5,
                                 h_attach=Text.HAttach.CENTER,
                                 v_attach=Text.VAttach.TOP,
                                 transition_delay=1.0,
                                 transition_out_delay=self._message_duration
                                 ).autoretain()
                            achs = [
                                a for a in app.achievements if not a.complete
                            ]
                            if achs:
                                ach = achs.pop(
                                    random.randrange(min(4, len(achs))))
                                ach.create_display(
                                    -180,
                                    -35,
                                    1.0,
                                    outdelay=self._message_duration,
                                    style='news')
                            if achs:
                                ach = achs.pop(
                                    random.randrange(min(8, len(achs))))
                                ach.create_display(
                                    180,
                                    -35,
                                    1.25,
                                    outdelay=self._message_duration,
                                    style='news')
                        else:
                            spc = self._message_spacing
                            keys = {
                                spc: 0.0,
                                spc + 1.0: 1.0,
                                spc + self._message_duration - 1.0: 1.0,
                                spc + self._message_duration: 0.0
                            }
                            assert self._text.node
                            ba.animate(self._text.node, 'opacity', keys)
                            # {k: v
                            #  for k, v in list(keys.items())})
                            self._text.node.text = val

            def _got_news(self, news: str) -> None:
                # Run this stuff in the context of our activity since we
                # need to make nodes and stuff.. should fix the serverget
                # call so it.
                activity = self._activity()
                if activity is None or activity.expired:
                    return
                with ba.Context(activity):

                    self._phrases: List[str] = []

                    # Show upcoming achievements in non-vr versions
                    # (currently too hard to read in vr).
                    self._used_phrases = (
                        ['__ACH__'] if not ba.app.vr_mode else
                        []) + [s for s in news.split('<br>\n') if s != '']
                    self._phrase_change_timer = ba.Timer(
                        (self._message_duration + self._message_spacing),
                        ba.WeakCall(self._change_phrase),
                        repeat=True)

                    scl = 1.2 if (ba.app.ui.uiscale is ba.UIScale.SMALL
                                  or ba.app.vr_mode) else 0.8

                    color2 = ((1, 1, 1, 1) if ba.app.vr_mode else
                              (0.7, 0.65, 0.75, 1.0))
                    shadow = (1.0 if ba.app.vr_mode else 0.4)
                    self._text = ba.NodeActor(
                        ba.newnode('text',
                                   attrs={
                                       'v_attach': 'top',
                                       'h_attach': 'center',
                                       'h_align': 'center',
                                       'vr_depth': -20,
                                       'shadow': shadow,
                                       'flatness': 0.8,
                                       'v_align': 'top',
                                       'color': color2,
                                       'scale': scl,
                                       'maxwidth': 900.0 / scl,
                                       'position': (0, -10)
                                   }))
                    self._change_phrase()

        if not (app.demo_mode or app.arcade_mode) and not app.toolbar_test:
            self._news = News(self)

        # Bring up the last place we were, or start at the main menu otherwise.
        with ba.Context('ui'):
            from bastd.ui import specialoffer
            if bool(False):
                uicontroller = ba.app.ui.controller
                assert uicontroller is not None
                uicontroller.show_main_menu()
            else:
                main_menu_location = ba.app.ui.get_main_menu_location()

                # When coming back from a kiosk-mode game, jump to
                # the kiosk start screen.
                if ba.app.demo_mode or ba.app.arcade_mode:
                    # pylint: disable=cyclic-import
                    from bastd.ui.kiosk import KioskWindow
                    ba.app.ui.set_main_menu_window(
                        KioskWindow().get_root_widget())
                # ..or in normal cases go back to the main menu
                else:
                    if main_menu_location == 'Gather':
                        # pylint: disable=cyclic-import
                        from bastd.ui.gather import GatherWindow
                        ba.app.ui.set_main_menu_window(
                            GatherWindow(transition=None).get_root_widget())
                    elif main_menu_location == 'Watch':
                        # pylint: disable=cyclic-import
                        from bastd.ui.watch import WatchWindow
                        ba.app.ui.set_main_menu_window(
                            WatchWindow(transition=None).get_root_widget())
                    elif main_menu_location == 'Team Game Select':
                        # pylint: disable=cyclic-import
                        from bastd.ui.playlist.browser import (
                            PlaylistBrowserWindow)
                        ba.app.ui.set_main_menu_window(
                            PlaylistBrowserWindow(
                                sessiontype=ba.DualTeamSession,
                                transition=None).get_root_widget())
                    elif main_menu_location == 'Free-for-All Game Select':
                        # pylint: disable=cyclic-import
                        from bastd.ui.playlist.browser import (
                            PlaylistBrowserWindow)
                        ba.app.ui.set_main_menu_window(
                            PlaylistBrowserWindow(
                                sessiontype=ba.FreeForAllSession,
                                transition=None).get_root_widget())
                    elif main_menu_location == 'Coop Select':
                        # pylint: disable=cyclic-import
                        from bastd.ui.coop.browser import CoopBrowserWindow
                        ba.app.ui.set_main_menu_window(
                            CoopBrowserWindow(
                                transition=None).get_root_widget())
                    else:
                        # pylint: disable=cyclic-import
                        from bastd.ui.mainmenu import MainMenuWindow
                        ba.app.ui.set_main_menu_window(
                            MainMenuWindow(transition=None).get_root_widget())

                # attempt to show any pending offers immediately.
                # If that doesn't work, try again in a few seconds
                # (we may not have heard back from the server)
                # ..if that doesn't work they'll just have to wait
                # until the next opportunity.
                if not specialoffer.show_offer():

                    def try_again() -> None:
                        if not specialoffer.show_offer():
                            # Try one last time..
                            ba.timer(2.0,
                                     specialoffer.show_offer,
                                     timetype=ba.TimeType.REAL)

                    ba.timer(2.0, try_again, timetype=ba.TimeType.REAL)
        ba.app.main_menu_did_initial_transition = True