221 lines
6.1 KiB
GDScript
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)
|