batrix/scripts/globals/inputer.gd

221 lines
6.1 KiB
GDScript

extends Node
signal mode_changed(mode: Mode)
enum Mode { KB_MOUSE, CONTROLLER }
enum ControllerType { UNSET, XBOX, SONY, NINTENDO, STEAM, KNOCKOFF }
const LEFT_TRIGGER_SPRITE_INDEX: int = 20
const RIGHT_TRIGGER_SPRITE_INDEX: int = 21
const LEFT_STICK_SPRITE_INDEX: int = 23
const RIGHT_STICK_SPRITE_INDEX: int = 24
@export var mode: Mode = Mode.KB_MOUSE
@export var _controller: ControllerType = ControllerType.UNSET:
set(value):
_set_current_prompts(value)
_controller = value
@export var _prompt_grid_size: int = 5
@export var _prompt_icon_size: int = 60
var _prompts_xbox := preload("res://assets/textures/ui/prompts_xbox.png")
var _prompts_sony := preload("res://assets/textures/ui/prompts_sony.png")
var _prompts_nintendo := preload("res://assets/textures/ui/prompts_nintendo.png")
var _prompts_steam := preload("res://assets/textures/ui/prompts_steam.png")
var _prompts_knockoff := preload("res://assets/textures/ui/prompts_knockoff.png")
var _current_prompts: CompressedTexture2D = _prompts_xbox
func _ready() -> void:
Input.joy_connection_changed.connect(_on_input_joy_connection_changed)
_get_controller_type()
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
return
var event_mode := get_event_mode(event)
if mode == Mode.KB_MOUSE and event_mode == Mode.CONTROLLER:
mode = Mode.CONTROLLER
mode_changed.emit(mode)
if mode == Mode.CONTROLLER and event_mode == Mode.KB_MOUSE:
mode = Mode.KB_MOUSE
mode_changed.emit(mode)
func get_vector_from_raw_strengths(
negative_x: float,
positive_x: float,
negative_y: float,
positive_y: float,
deadzone := 0.5
) -> Vector2:
var vector := Vector2(positive_x - negative_x, positive_y - negative_y)
var length := vector.length()
if length <= deadzone:
return Vector2.ZERO
if length > 1.0:
return vector.normalized()
return vector * inverse_lerp(deadzone, 1.0, length) / length
func get_event_mode(event: InputEvent) -> Mode:
if event is InputEventJoypadButton or event is InputEventJoypadMotion:
return Mode.CONTROLLER
return Mode.KB_MOUSE
func get_action_prompt(action: StringName) -> String:
var events := InputMap.action_get_events(action)
var bbcode: PackedStringArray = []
for event in events:
var event_bbcode := _get_event_prompt_current_mode(event)
if event_bbcode:
bbcode.append(event_bbcode)
if bbcode.size() > 0:
return " / ".join(bbcode)
return _get_event_prompt(events[0]) if events.size() > 0 else "???"
func _get_event_prompt_current_mode(event: InputEvent) -> String:
var event_mode := get_event_mode(event)
if mode == Mode.CONTROLLER and event_mode == Mode.CONTROLLER:
return _get_controller_prompt(event)
if mode == Mode.KB_MOUSE and event_mode == Mode.KB_MOUSE:
return _get_kb_mouse_prompt(event)
return ""
func _get_event_prompt(event: InputEvent) -> String:
var event_mode := get_event_mode(event)
if event_mode == Mode.CONTROLLER:
return _get_controller_prompt(event)
if event_mode == Mode.KB_MOUSE:
return _get_kb_mouse_prompt(event)
return event.as_text()
func _get_kb_mouse_prompt(event: InputEvent) -> String:
if event is InputEventKey:
var button_event := event as InputEventKey
return button_event.as_text_physical_keycode()
if event is InputEventMouseButton:
return event.as_text()
return event.as_text()
func _get_controller_prompt(event: InputEvent) -> String:
if event is InputEventJoypadButton:
var button_event := event as InputEventJoypadButton
if (
(
button_event.button_index >= JOY_BUTTON_A
and button_event.button_index <= JOY_BUTTON_BACK
)
or (
button_event.button_index >= JOY_BUTTON_START
and button_event.button_index <= JOY_BUTTON_DPAD_RIGHT
)
):
return _get_prompt_sprite(button_event.button_index)
if event is InputEventJoypadMotion:
var motion_event := event as InputEventJoypadMotion
if motion_event.axis == JOY_AXIS_LEFT_X or motion_event.axis == JOY_AXIS_LEFT_Y:
return _get_prompt_sprite(LEFT_STICK_SPRITE_INDEX)
if (
motion_event.axis == JOY_AXIS_RIGHT_X
or motion_event.axis == JOY_AXIS_RIGHT_Y
):
return _get_prompt_sprite(RIGHT_STICK_SPRITE_INDEX)
if motion_event.axis == JOY_AXIS_TRIGGER_LEFT:
return _get_prompt_sprite(LEFT_TRIGGER_SPRITE_INDEX)
if motion_event.axis == JOY_AXIS_TRIGGER_RIGHT:
return _get_prompt_sprite(RIGHT_TRIGGER_SPRITE_INDEX)
return event.as_text()
func _get_prompt_sprite(index: int) -> String:
var region := _get_prompt_sprite_region(index)
return (
"[img region=%d,%d,%d,%d height=%d width=%d]%s[/img]"
% [
region.position.x,
region.position.y,
region.size.x,
region.size.y,
_prompt_icon_size,
_prompt_icon_size,
_current_prompts.resource_path
]
)
func _get_prompt_sprite_region(index: int) -> Rect2i:
var corner_x: int = index % _prompt_grid_size
var corner_y: int = index / _prompt_grid_size
var sprite_size: int = _current_prompts.get_width() / _prompt_grid_size
return Rect2i(
corner_x * sprite_size,
corner_y * sprite_size,
sprite_size,
sprite_size,
)
func _get_controller_type(id: int = 0) -> void:
if Settings.controller_button_icons != ControllerType.UNSET:
_controller = Settings.controller_button_icons
return
var controller_name := Input.get_joy_name(id).to_lower()
if not controller_name:
return
if controller_name.contains("steam") or controller_name.contains("valve"):
_controller = ControllerType.STEAM
elif controller_name.contains("nintendo") or controller_name.contains("switch"):
_controller = ControllerType.NINTENDO
elif (
controller_name.contains("ps")
or controller_name.contains("sony")
or controller_name.contains("playstation")
):
_controller = ControllerType.SONY
else:
_controller = ControllerType.XBOX
func _set_current_prompts(type: ControllerType) -> void:
match type:
ControllerType.XBOX:
_current_prompts = _prompts_xbox
ControllerType.SONY:
_current_prompts = _prompts_sony
ControllerType.NINTENDO:
_current_prompts = _prompts_nintendo
ControllerType.STEAM:
_current_prompts = _prompts_steam
ControllerType.KNOCKOFF:
_current_prompts = _prompts_knockoff
func _on_input_joy_connection_changed(device: int, connected: bool) -> void:
if connected:
_get_controller_type(device)