예제 #1
0
 def _config_keyboard2(self) -> None:
     # pylint: disable=cyclic-import
     from bastd.ui.settings import keyboard
     self._save_state()
     ba.containerwidget(edit=self._root_widget, transition='out_left')
     ba.app.main_menu_window = (keyboard.ConfigKeyboardWindow(
         _ba.get_input_device('Keyboard', '#2')).get_root_widget())
예제 #2
0
    def _check_fade_in(self) -> None:
        from ba.internal import get_device_value

        # If we have a touchscreen, we only fade in if we have a player with
        # an input device that is *not* the touchscreen.
        touchscreen: Optional[ba.InputDevice] = _ba.get_input_device(
            'TouchScreen', '#1', doraise=False)

        if touchscreen is not None:
            # We look at the session's players; not the activity's.
            # We want to get ones who are still in the process of
            # selecting a character, etc.
            input_devices = [
                p.get_input_device() for p in ba.getsession().players
            ]
            input_devices = [
                i for i in input_devices if i and i is not touchscreen
            ]
            fade_in = False
            if input_devices:
                # Only count this one if it has non-empty button names
                # (filters out wiimotes, the remote-app, etc).
                for device in input_devices:
                    for name in ('buttonPunch', 'buttonJump', 'buttonBomb',
                                 'buttonPickUp'):
                        if device.get_button_name(
                                get_device_value(device, name)) != '':
                            fade_in = True
                            break
                    if fade_in:
                        break  # No need to keep looking.
        else:
            # No touch-screen; fade in immediately.
            fade_in = True
        if fade_in:
            self._cancel_timer = None  # Didn't need this.
            self._fade_in_timer = None  # Done with this.
            self._fade_in()
예제 #3
0
def is_browser_likely_available() -> bool:
    """Return whether a browser likely exists on the current device.

    category: General Utility Functions

    If this returns False you may want to avoid calling ba.show_url()
    with any lengthy addresses. (ba.show_url() will display an address
    as a string in a window if unable to bring up a browser, but that
    is only useful for simple URLs.)
    """
    app = _ba.app
    platform = app.platform
    touchscreen = _ba.get_input_device('TouchScreen', '#1', doraise=False)

    # If we're on a vr device or an android device with no touchscreen,
    # assume no browser.
    # FIXME: Might not be the case anymore; should make this definable
    #  at the platform level.
    if app.vr_mode or (platform == 'android' and touchscreen is None):
        return False

    # Anywhere else assume we've got one.
    return True
예제 #4
0
    def _update(self) -> None:
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        from ba.internal import get_device_value, get_remote_app_name
        if self._dead:
            return
        punch_button_names = set()
        jump_button_names = set()
        pickup_button_names = set()
        bomb_button_names = set()

        # We look at the session's players; not the activity's - we want to
        # get ones who are still in the process of selecting a character, etc.
        input_devices = [p.get_input_device() for p in ba.getsession().players]
        input_devices = [i for i in input_devices if i]

        # If there's no players with input devices yet, try to default to
        # showing keyboard controls.
        if not input_devices:
            kbd = _ba.get_input_device('Keyboard', '#1', doraise=False)
            if kbd is not None:
                input_devices.append(kbd)

        # We word things specially if we have nothing but keyboards.
        all_keyboards = (input_devices
                         and all(i.name == 'Keyboard' for i in input_devices))
        only_remote = (len(input_devices) == 1
                       and all(i.name == 'Amazon Fire TV Remote'
                               for i in input_devices))

        right_button_names = set()
        left_button_names = set()
        up_button_names = set()
        down_button_names = set()

        # For each player in the game with an input device,
        # get the name of the button for each of these 4 actions.
        # If any of them are uniform across all devices, display the name.
        for device in input_devices:
            # We only care about movement buttons in the case of keyboards.
            if all_keyboards:
                right_button_names.add(
                    device.get_button_name(
                        get_device_value(device, 'buttonRight')))
                left_button_names.add(
                    device.get_button_name(
                        get_device_value(device, 'buttonLeft')))
                down_button_names.add(
                    device.get_button_name(
                        get_device_value(device, 'buttonDown')))
                up_button_names.add(
                    device.get_button_name(get_device_value(
                        device, 'buttonUp')))

            # Ignore empty values; things like the remote app or
            # wiimotes can return these.
            bname = device.get_button_name(
                get_device_value(device, 'buttonPunch'))
            if bname != '':
                punch_button_names.add(bname)
            bname = device.get_button_name(
                get_device_value(device, 'buttonJump'))
            if bname != '':
                jump_button_names.add(bname)
            bname = device.get_button_name(
                get_device_value(device, 'buttonBomb'))
            if bname != '':
                bomb_button_names.add(bname)
            bname = device.get_button_name(
                get_device_value(device, 'buttonPickUp'))
            if bname != '':
                pickup_button_names.add(bname)

        # If we have no values yet, we may want to throw out some sane
        # defaults.
        if all(not lst for lst in (punch_button_names, jump_button_names,
                                   bomb_button_names, pickup_button_names)):
            # Otherwise on android show standard buttons.
            if ba.app.platform == 'android':
                punch_button_names.add('X')
                jump_button_names.add('A')
                bomb_button_names.add('B')
                pickup_button_names.add('Y')

        run_text = ba.Lstr(
            value='${R}: ${B}',
            subs=[('${R}', ba.Lstr(resource='runText')),
                  ('${B}',
                   ba.Lstr(resource='holdAnyKeyText'
                           if all_keyboards else 'holdAnyButtonText'))])

        # If we're all keyboards, lets show move keys too.
        if (all_keyboards and len(up_button_names) == 1
                and len(down_button_names) == 1 and len(left_button_names) == 1
                and len(right_button_names) == 1):
            up_text = list(up_button_names)[0]
            down_text = list(down_button_names)[0]
            left_text = list(left_button_names)[0]
            right_text = list(right_button_names)[0]
            run_text = ba.Lstr(value='${M}: ${U}, ${L}, ${D}, ${R}\n${RUN}',
                               subs=[('${M}', ba.Lstr(resource='moveText')),
                                     ('${U}', up_text), ('${L}', left_text),
                                     ('${D}', down_text), ('${R}', right_text),
                                     ('${RUN}', run_text)])

        self._run_text.text = run_text
        w_text: Union[ba.Lstr, str]
        if only_remote and self._lifespan is None:
            w_text = ba.Lstr(resource='fireTVRemoteWarningText',
                             subs=[('${REMOTE_APP_NAME}',
                                    get_remote_app_name())])
        else:
            w_text = ''
        self._extra_text.text = w_text
        if len(punch_button_names) == 1:
            self._punch_text.text = list(punch_button_names)[0]
        else:
            self._punch_text.text = ''

        if len(jump_button_names) == 1:
            tval = list(jump_button_names)[0]
        else:
            tval = ''
        self._jump_text.text = tval
        if tval == '':
            self._run_text.position = self._run_text_pos_top
            self._extra_text.position = (self._run_text_pos_top[0],
                                         self._run_text_pos_top[1] - 50)
        else:
            self._run_text.position = self._run_text_pos_bottom
            self._extra_text.position = (self._run_text_pos_bottom[0],
                                         self._run_text_pos_bottom[1] - 50)
        if len(bomb_button_names) == 1:
            self._bomb_text.text = list(bomb_button_names)[0]
        else:
            self._bomb_text.text = ''

        # Also move our title up/down depending on if this is shown.
        if len(pickup_button_names) == 1:
            self._pick_up_text.text = list(pickup_button_names)[0]
            if self._title_text is not None:
                self._title_text.position = self._title_text_pos_top
        else:
            self._pick_up_text.text = ''
            if self._title_text is not None:
                self._title_text.position = self._title_text_pos_bottom
예제 #5
0
    def __init__(self, lobby: ba.Lobby):
        # pylint: disable=too-many-locals
        from ba import _input
        from ba._lang import Lstr
        from ba._nodeactor import NodeActor
        from ba._general import WeakCall
        from ba._enums import SpecialChar
        can_switch_teams = (len(lobby.teams) > 1)
        self._state = 0
        press_to_punch: Union[str,
                              ba.Lstr] = _ba.charstr(SpecialChar.LEFT_BUTTON)
        press_to_bomb: Union[str,
                             ba.Lstr] = _ba.charstr(SpecialChar.RIGHT_BUTTON)

        # If we have a keyboard, grab keys for punch and pickup.
        # FIXME: This of course is only correct on the local device;
        #  Should change this for net games.
        keyboard: Optional[ba.InputDevice] = _ba.get_input_device(
            'Keyboard', '#1', doraise=False)
        if keyboard is not None:
            punch_key = keyboard.get_button_name(
                _input.get_device_value(keyboard, 'buttonPunch'))
            press_to_punch = Lstr(resource='orText',
                                  subs=[('${A}',
                                         Lstr(value='\'${K}\'',
                                              subs=[('${K}', punch_key)])),
                                        ('${B}', press_to_punch)])
            bomb_key = keyboard.get_button_name(
                _input.get_device_value(keyboard, 'buttonBomb'))
            press_to_bomb = Lstr(resource='orText',
                                 subs=[('${A}',
                                        Lstr(value='\'${K}\'',
                                             subs=[('${K}', bomb_key)])),
                                       ('${B}', press_to_bomb)])
            join_str = Lstr(value='${A} < ${B} >',
                            subs=[('${A}',
                                   Lstr(resource='pressPunchToJoinText')),
                                  ('${B}', press_to_punch)])
        else:
            join_str = Lstr(resource='pressAnyButtonToJoinText')

        flatness = 1.0 if _ba.app.vr_mode else 0.0
        self._text = NodeActor(
            _ba.newnode('text',
                        attrs={
                            'position': (0, -40),
                            'h_attach': 'center',
                            'v_attach': 'top',
                            'h_align': 'center',
                            'color': (0.7, 0.7, 0.95, 1.0),
                            'flatness': flatness,
                            'text': join_str
                        }))

        if _ba.app.kiosk_mode:
            self._messages = [join_str]
        else:
            msg1 = Lstr(resource='pressToSelectProfileText',
                        subs=[
                            ('${BUTTONS}', _ba.charstr(SpecialChar.UP_ARROW) +
                             ' ' + _ba.charstr(SpecialChar.DOWN_ARROW))
                        ])
            msg2 = Lstr(resource='pressToOverrideCharacterText',
                        subs=[('${BUTTONS}', Lstr(resource='bombBoldText'))])
            msg3 = Lstr(value='${A} < ${B} >',
                        subs=[('${A}', msg2), ('${B}', press_to_bomb)])
            self._messages = (([
                Lstr(resource='pressToSelectTeamText',
                     subs=[('${BUTTONS}', _ba.charstr(SpecialChar.LEFT_ARROW) +
                            ' ' + _ba.charstr(SpecialChar.RIGHT_ARROW))])
            ] if can_switch_teams else []) + [msg1] + [msg3] + [join_str])

        self._timer = _ba.Timer(4.0, WeakCall(self._update), repeat=True)
예제 #6
0
    def __init__(self,
                 transition: str = 'in_right',
                 origin_widget: ba.Widget = None):
        # FIXME: should tidy up here.
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        # pylint: disable=cyclic-import
        from bastd.ui import popup as popup_ui
        self._have_selected_child = False

        scale_origin: Optional[Tuple[float, float]]

        # If they provided an origin-widget, scale up from that.
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None

        self._r = 'configControllersWindow'
        app = ba.app

        is_fire_tv = _ba.is_running_on_fire_tv()

        spacing = 50.0
        button_width = 350.0
        width = 460.0
        height = 135.0

        space_height = spacing * 0.3

        # FIXME: should create vis settings in platform for these,
        #  not hard code them here..

        show_gamepads = False
        platform = app.platform
        subplatform = app.subplatform
        non_vr_windows = (platform == 'windows'
                          and (subplatform != 'oculus' or not app.vr_mode))
        if platform in ('linux', 'android', 'mac') or non_vr_windows:
            show_gamepads = True
            height += spacing

        show_touch = False
        if _ba.have_touchscreen_input():
            show_touch = True
            height += spacing

        show_space_1 = False
        if show_gamepads or show_touch:
            show_space_1 = True
            height += space_height

        show_keyboard = False
        if _ba.get_input_device('Keyboard', '#1', doraise=False) is not None:
            show_keyboard = True
            height += spacing * 2
        show_keyboard_p2 = False if app.vr_mode else show_keyboard
        if show_keyboard_p2:
            height += spacing

        show_space_2 = False
        if show_keyboard:
            show_space_2 = True
            height += space_height

        if bool(True):
            show_remote = True
            height += spacing
        else:
            show_remote = False

        show_ps3 = False
        if platform == 'mac':
            show_ps3 = True
            height += spacing

        show360 = False
        if platform == 'mac' or is_fire_tv:
            show360 = True
            height += spacing

        show_mac_wiimote = False
        if platform == 'mac':
            show_mac_wiimote = True
            height += spacing

        # on non-oculus-vr windows, show an option to disable xinput
        show_xinput_toggle = False
        if platform == 'windows' and (subplatform != 'oculus'
                                      or not app.vr_mode):
            show_xinput_toggle = True

        # on mac builds, show an option to switch between generic and
        # made-for-iOS/Mac systems
        # (we can run into problems where devices register as one of each
        # type otherwise)..
        show_mac_controller_subsystem = False
        if platform == 'mac':
            show_mac_controller_subsystem = True

        if show_mac_controller_subsystem:
            height += spacing

        if show_xinput_toggle:
            height += spacing

        super().__init__(root_widget=ba.containerwidget(
            size=(width, height),
            transition=transition,
            scale_origin_stack_offset=scale_origin,
            scale=(1.7 if show_keyboard else 2.2
                   ) if ba.app.small_ui else 1.5 if ba.app.med_ui else 1.0))
        self._back_button = btn = ba.buttonwidget(
            parent=self._root_widget,
            position=(35, height - 60),
            size=(140, 65),
            scale=0.8,
            text_scale=1.2,
            autoselect=True,
            label=ba.Lstr(resource='backText'),
            button_type='back',
            on_activate_call=self._back)
        ba.containerwidget(edit=self._root_widget, cancel_button=btn)

        # need these vars to exist even if the buttons don't
        self._gamepads_button: Optional[ba.Widget] = None
        self._touch_button: Optional[ba.Widget] = None
        self._keyboard_button: Optional[ba.Widget] = None
        self._keyboard_2_button: Optional[ba.Widget] = None
        self._idevices_button: Optional[ba.Widget] = None
        self._ps3_button: Optional[ba.Widget] = None
        self._xbox_360_button: Optional[ba.Widget] = None
        self._wiimotes_button: Optional[ba.Widget] = None

        ba.textwidget(parent=self._root_widget,
                      position=(0, height - 49),
                      size=(width, 25),
                      text=ba.Lstr(resource=self._r + '.titleText'),
                      color=ba.app.title_color,
                      h_align='center',
                      v_align='top')
        ba.buttonwidget(edit=btn,
                        button_type='backSmall',
                        size=(60, 60),
                        label=ba.charstr(ba.SpecialChar.BACK))

        v = height - 75
        v -= spacing

        if show_touch:
            self._touch_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureTouchText'),
                on_activate_call=self._do_touchscreen)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=self._touch_button)
                ba.widget(edit=self._back_button,
                          down_widget=self._touch_button)
                self._have_selected_child = True
            v -= spacing

        if show_gamepads:
            self._gamepads_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 - 7, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureControllersText'),
                on_activate_call=self._do_gamepads)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=self._gamepads_button)
                ba.widget(edit=self._back_button,
                          down_widget=self._gamepads_button)
                self._have_selected_child = True
            v -= spacing
        else:
            self._gamepads_button = None

        if show_space_1:
            v -= space_height

        if show_keyboard:
            self._keyboard_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 + 5, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureKeyboardText'),
                on_activate_call=self._config_keyboard)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=self._keyboard_button)
                ba.widget(edit=self._back_button,
                          down_widget=self._keyboard_button)
                self._have_selected_child = True
            v -= spacing
        if show_keyboard_p2:
            self._keyboard_2_button = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 - 3, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureKeyboard2Text'),
                on_activate_call=self._config_keyboard2)
            v -= spacing
        if show_space_2:
            v -= space_height
        if show_remote:
            self._idevices_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 - 5, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.configureMobileText'),
                on_activate_call=self._do_mobile_devices)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            if not self._have_selected_child:
                ba.containerwidget(edit=self._root_widget,
                                   selected_child=self._idevices_button)
                ba.widget(edit=self._back_button,
                          down_widget=self._idevices_button)
                self._have_selected_child = True
            v -= spacing
        if show_ps3:
            self._ps3_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 + 5, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.ps3Text'),
                on_activate_call=self._do_ps3_controllers)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            v -= spacing
        if show360:
            self._xbox_360_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 - 1, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.xbox360Text'),
                on_activate_call=self._do_360_controllers)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            v -= spacing
        if show_mac_wiimote:
            self._wiimotes_button = btn = ba.buttonwidget(
                parent=self._root_widget,
                position=((width - button_width) / 2 + 5, v),
                size=(button_width, 43),
                autoselect=True,
                label=ba.Lstr(resource=self._r + '.wiimotesText'),
                on_activate_call=self._do_wiimotes)
            if ba.app.toolbars:
                ba.widget(edit=btn,
                          right_widget=_ba.get_special_widget('party_button'))
            v -= spacing

        if show_xinput_toggle:

            def do_toggle(value: bool) -> None:
                ba.screenmessage(
                    ba.Lstr(resource='settingsWindowAdvanced.mustRestartText'),
                    color=(1, 1, 0))
                ba.playsound(ba.getsound('gunCocking'))
                _ba.set_low_level_config_value('enablexinput', not value)

            ba.checkboxwidget(
                parent=self._root_widget,
                position=(100, v + 3),
                size=(120, 30),
                value=(not _ba.get_low_level_config_value('enablexinput', 1)),
                maxwidth=200,
                on_value_change_call=do_toggle,
                text=ba.Lstr(resource='disableXInputText'),
                autoselect=True)
            ba.textwidget(
                parent=self._root_widget,
                position=(width * 0.5, v - 5),
                size=(0, 0),
                text=ba.Lstr(resource='disableXInputDescriptionText'),
                scale=0.5,
                h_align='center',
                v_align='center',
                color=ba.app.infotextcolor,
                maxwidth=width * 0.8)
            v -= spacing
        if show_mac_controller_subsystem:
            popup_ui.PopupMenu(
                parent=self._root_widget,
                position=(260, v - 10),
                width=160,
                button_size=(150, 50),
                scale=1.5,
                choices=['Classic', 'MFi', 'Both'],
                choices_display=[
                    ba.Lstr(resource='macControllerSubsystemClassicText'),
                    ba.Lstr(resource='macControllerSubsystemMFiText'),
                    ba.Lstr(resource='macControllerSubsystemBothText')
                ],
                current_choice=ba.app.config.resolve(
                    'Mac Controller Subsystem'),
                on_value_change_call=self._set_mac_controller_subsystem)
            ba.textwidget(
                parent=self._root_widget,
                position=(245, v + 13),
                size=(0, 0),
                text=ba.Lstr(resource='macControllerSubsystemTitleText'),
                scale=1.0,
                h_align='right',
                v_align='center',
                color=ba.app.infotextcolor,
                maxwidth=180)
            ba.textwidget(
                parent=self._root_widget,
                position=(width * 0.5, v - 20),
                size=(0, 0),
                text=ba.Lstr(resource='macControllerSubsystemDescriptionText'),
                scale=0.5,
                h_align='center',
                v_align='center',
                color=ba.app.infotextcolor,
                maxwidth=width * 0.8)
            v -= spacing
        self._restore_state()