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())
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()
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
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
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)
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()