225 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			GDScript
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			6.3 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)
 | |
| 
 | |
| 	Debugger.add_event("mode_changed")
 | |
| 	mode_changed.connect(
 | |
| 		func(new_mode: Mode) -> void:
 | |
| 			Debugger.event_emitted("mode_changed", [Mode.keys()[new_mode]])
 | |
| 	)
 | |
| 	Debugger.add_event("joy_connection_changed")
 | |
| 	Input.joy_connection_changed.connect(
 | |
| 		func(device: int, connected: bool) -> void:
 | |
| 			Debugger.event_emitted("joy_connection_changed", [device, connected])
 | |
| 	)
 | |
| 
 | |
| 	_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)
 | |
| 
 | |
| 	if Debugger.show_debug() and event.is_pressed():
 | |
| 		Debugger.text("input", _get_event_prompt_current_mode(event))
 | |
| 
 | |
| 
 | |
| 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
 | |
| 		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)
 |