Fix controller text entry without native keyboards
This commit is contained in:
parent
57df54d82d
commit
abedd64782
5 changed files with 79 additions and 11 deletions
|
|
@ -189,9 +189,22 @@ func _run() -> void:
|
||||||
accept_button.button_index = JOY_BUTTON_A
|
accept_button.button_index = JOY_BUTTON_A
|
||||||
accept_button.pressed = true
|
accept_button.pressed = true
|
||||||
assert(bool(game_ui.call("_handle_controller_chat_controls", accept_button)))
|
assert(bool(game_ui.call("_handle_controller_chat_controls", accept_button)))
|
||||||
|
var ui_pixelation := main.get("_ui_pixelation") as UIPixelationPresenter
|
||||||
|
assert(ui_pixelation != null)
|
||||||
|
var on_screen_keyboard := ui_pixelation.get(
|
||||||
|
"_on_screen_keyboard"
|
||||||
|
) as OnScreenKeyboard
|
||||||
|
assert(on_screen_keyboard != null)
|
||||||
|
if DisplayServer.has_feature(DisplayServer.FEATURE_VIRTUAL_KEYBOARD):
|
||||||
assert(typed_chat_entry.virtual_keyboard_enabled)
|
assert(typed_chat_entry.virtual_keyboard_enabled)
|
||||||
|
assert(not on_screen_keyboard.is_open())
|
||||||
await process_frame
|
await process_frame
|
||||||
assert(typed_chat_entry.has_focus())
|
assert(typed_chat_entry.has_focus())
|
||||||
|
else:
|
||||||
|
assert(not typed_chat_entry.virtual_keyboard_enabled)
|
||||||
|
assert(on_screen_keyboard.is_open())
|
||||||
|
on_screen_keyboard.call("_close_keyboard", true)
|
||||||
|
assert(typed_chat_entry.has_focus())
|
||||||
var left_bumper := InputEventJoypadButton.new()
|
var left_bumper := InputEventJoypadButton.new()
|
||||||
left_bumper.button_index = JOY_BUTTON_LEFT_SHOULDER
|
left_bumper.button_index = JOY_BUTTON_LEFT_SHOULDER
|
||||||
left_bumper.pressed = true
|
left_bumper.pressed = true
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ func _run() -> void:
|
||||||
func _validate_default_and_persistence() -> void:
|
func _validate_default_and_persistence() -> void:
|
||||||
var defaults := PlayerSettings.new()
|
var defaults := PlayerSettings.new()
|
||||||
assert(not defaults.on_screen_keyboard_enabled)
|
assert(not defaults.on_screen_keyboard_enabled)
|
||||||
|
assert(KeyboardType.should_enable_for_controller(false, false))
|
||||||
|
assert(not KeyboardType.should_enable_for_controller(false, true))
|
||||||
|
assert(KeyboardType.should_enable_for_controller(true, true))
|
||||||
var manager := SettingsManagerType.new()
|
var manager := SettingsManagerType.new()
|
||||||
root.add_child(manager)
|
root.add_child(manager)
|
||||||
assert(manager.load_settings())
|
assert(manager.load_settings())
|
||||||
|
|
@ -43,11 +46,24 @@ func _validate_keyboard_entry() -> void:
|
||||||
var keyboard := KeyboardType.new()
|
var keyboard := KeyboardType.new()
|
||||||
host.add_child(keyboard)
|
host.add_child(keyboard)
|
||||||
await process_frame
|
await process_frame
|
||||||
keyboard.set_enabled(true)
|
keyboard.set_enabled(false)
|
||||||
edit.grab_focus()
|
assert(
|
||||||
|
keyboard.is_enabled()
|
||||||
|
== not DisplayServer.has_feature(
|
||||||
|
DisplayServer.FEATURE_VIRTUAL_KEYBOARD
|
||||||
|
)
|
||||||
|
)
|
||||||
var activate_event := InputEventJoypadButton.new()
|
var activate_event := InputEventJoypadButton.new()
|
||||||
activate_event.button_index = JOY_BUTTON_A
|
activate_event.button_index = JOY_BUTTON_A
|
||||||
activate_event.pressed = true
|
activate_event.pressed = true
|
||||||
|
if keyboard.is_enabled():
|
||||||
|
edit.grab_focus()
|
||||||
|
keyboard.call("_input", activate_event)
|
||||||
|
assert(keyboard.is_open())
|
||||||
|
keyboard.call("_close_keyboard", true)
|
||||||
|
assert(not keyboard.is_open())
|
||||||
|
keyboard.set_enabled(true)
|
||||||
|
edit.grab_focus()
|
||||||
keyboard.call("_input", activate_event)
|
keyboard.call("_input", activate_event)
|
||||||
assert(keyboard.is_open())
|
assert(keyboard.is_open())
|
||||||
keyboard.call("_type_character", "a")
|
keyboard.call("_type_character", "a")
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,7 @@ var _virtual_mouse_trigger_rest_by_device: Dictionary[int, float] = {}
|
||||||
var _shared_trigger_rest_by_device: Dictionary[int, float] = {}
|
var _shared_trigger_rest_by_device: Dictionary[int, float] = {}
|
||||||
var _controller_mapping_manager: ControllerMappingManagerType
|
var _controller_mapping_manager: ControllerMappingManagerType
|
||||||
var _settings_manager: PlayerSettingsManagerType
|
var _settings_manager: PlayerSettingsManagerType
|
||||||
|
var _controller_text_entry_request: Callable
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
|
@ -252,6 +253,10 @@ func _ready() -> void:
|
||||||
Input.joy_connection_changed.connect(_on_controller_connection_changed)
|
Input.joy_connection_changed.connect(_on_controller_connection_changed)
|
||||||
|
|
||||||
|
|
||||||
|
func set_controller_text_entry_request(request: Callable) -> void:
|
||||||
|
_controller_text_entry_request = request
|
||||||
|
|
||||||
|
|
||||||
func setup(
|
func setup(
|
||||||
player: PlayerType,
|
player: PlayerType,
|
||||||
inventory: FishInventoryType,
|
inventory: FishInventoryType,
|
||||||
|
|
@ -600,6 +605,11 @@ func _handle_controller_chat_controls(event: InputEvent) -> bool:
|
||||||
_chat_ui.refocus_gameplay()
|
_chat_ui.refocus_gameplay()
|
||||||
return true
|
return true
|
||||||
if accept_pressed:
|
if accept_pressed:
|
||||||
|
if (
|
||||||
|
_controller_text_entry_request.is_valid()
|
||||||
|
and bool(_controller_text_entry_request.call())
|
||||||
|
):
|
||||||
|
return true
|
||||||
return _chat_ui.request_virtual_keyboard()
|
return _chat_ui.request_virtual_keyboard()
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,20 +50,30 @@ func _ready() -> void:
|
||||||
|
|
||||||
func set_enabled(enabled: bool) -> void:
|
func set_enabled(enabled: bool) -> void:
|
||||||
_enabled = enabled
|
_enabled = enabled
|
||||||
if not _enabled and visible:
|
if not _is_available_for_controller() and visible:
|
||||||
_close_keyboard(false)
|
_close_keyboard(false)
|
||||||
|
|
||||||
|
|
||||||
func is_enabled() -> bool:
|
func is_enabled() -> bool:
|
||||||
return _enabled
|
return _is_available_for_controller()
|
||||||
|
|
||||||
|
|
||||||
func is_open() -> bool:
|
func is_open() -> bool:
|
||||||
return visible
|
return visible
|
||||||
|
|
||||||
|
|
||||||
|
func request_for_focused_control() -> bool:
|
||||||
|
if not _is_available_for_controller() or visible:
|
||||||
|
return false
|
||||||
|
var focus_owner: Control = get_viewport().gui_get_focus_owner()
|
||||||
|
if not _can_edit(focus_owner):
|
||||||
|
return false
|
||||||
|
_open_for(focus_owner)
|
||||||
|
return true
|
||||||
|
|
||||||
|
|
||||||
func _input(event: InputEvent) -> void:
|
func _input(event: InputEvent) -> void:
|
||||||
if not _enabled:
|
if not _is_available_for_controller():
|
||||||
return
|
return
|
||||||
if visible:
|
if visible:
|
||||||
var joy_motion := event as InputEventJoypadMotion
|
var joy_motion := event as InputEventJoypadMotion
|
||||||
|
|
@ -98,12 +108,27 @@ func _input(event: InputEvent) -> void:
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
var focus_owner: Control = get_viewport().gui_get_focus_owner()
|
if request_for_focused_control():
|
||||||
if _can_edit(focus_owner):
|
|
||||||
_open_for(focus_owner)
|
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
|
|
||||||
|
|
||||||
|
func _is_available_for_controller() -> bool:
|
||||||
|
return should_enable_for_controller(
|
||||||
|
_enabled,
|
||||||
|
DisplayServer.has_feature(DisplayServer.FEATURE_VIRTUAL_KEYBOARD),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
static func should_enable_for_controller(
|
||||||
|
preference_enabled: bool,
|
||||||
|
native_virtual_keyboard_available: bool,
|
||||||
|
) -> bool:
|
||||||
|
# A controller user must always have one viable text-entry path. Android
|
||||||
|
# and any future display backend with native support can keep using the
|
||||||
|
# platform keyboard unless the in-game keyboard is explicitly requested.
|
||||||
|
return preference_enabled or not native_virtual_keyboard_available
|
||||||
|
|
||||||
|
|
||||||
func _can_edit(control: Control) -> bool:
|
func _can_edit(control: Control) -> bool:
|
||||||
if control is LineEdit:
|
if control is LineEdit:
|
||||||
return (control as LineEdit).editable
|
return (control as LineEdit).editable
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ signal effective_pixel_size_changed(
|
||||||
)
|
)
|
||||||
|
|
||||||
@onready var _ui_viewport: SubViewport = $UIViewport
|
@onready var _ui_viewport: SubViewport = $UIViewport
|
||||||
|
@onready var _game_ui: GameUI = $UIViewport/GameUI
|
||||||
@onready var _ui_root: Control = $UIViewport/GameUI/UIRoot
|
@onready var _ui_root: Control = $UIViewport/GameUI/UIRoot
|
||||||
@onready var _canonical_stage: Control = (
|
@onready var _canonical_stage: Control = (
|
||||||
$UIViewport/GameUI/UIRoot/CanonicalStage
|
$UIViewport/GameUI/UIRoot/CanonicalStage
|
||||||
|
|
@ -42,6 +43,9 @@ var _on_screen_keyboard: OnScreenKeyboardType
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
_on_screen_keyboard = OnScreenKeyboardType.new()
|
_on_screen_keyboard = OnScreenKeyboardType.new()
|
||||||
_ui_root.add_child(_on_screen_keyboard)
|
_ui_root.add_child(_on_screen_keyboard)
|
||||||
|
_game_ui.set_controller_text_entry_request(
|
||||||
|
Callable(_on_screen_keyboard, "request_for_focused_control")
|
||||||
|
)
|
||||||
var controller_focus_recovery := ControllerFocusRecoveryType.new()
|
var controller_focus_recovery := ControllerFocusRecoveryType.new()
|
||||||
_ui_root.add_child(controller_focus_recovery)
|
_ui_root.add_child(controller_focus_recovery)
|
||||||
var controller_focus_presentation := ControllerFocusPresentationType.new()
|
var controller_focus_presentation := ControllerFocusPresentationType.new()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue