177 lines
6.6 KiB
GDScript
177 lines
6.6 KiB
GDScript
extends Node3D
|
|
class_name Player
|
|
#region Declarations
|
|
@export_category("Speed")
|
|
@onready var move_speed: float = ProjectSettings.get_setting("game/controls/camera_move_speed",20.0)
|
|
@onready var zoom_speed: float = ProjectSettings.get_setting("game/controls/camera_zoom_speed",20.0)
|
|
@export_category("Limits")
|
|
@export_range(-10,10,1) var zoom_min: float = -4
|
|
@export_range(11,50,1) var zoom_max: float = 20
|
|
@export_range(0,0.95,0.01) var zoom_speed_damp: float = ProjectSettings.get_setting("game/controls/camera_zoom_damp",0.85)
|
|
|
|
@export_range(0,32,4) var edge_scrolling_margin: int = ProjectSettings.get_setting("game/controls/edge_scrolling_margin",8)
|
|
@onready var edge_scrolling_speed: float = ProjectSettings.get_setting("game/controls/edge_scrolling_speed",25.0)
|
|
|
|
@onready var cam: Camera3D = %camera_player
|
|
|
|
var mouse_velocity
|
|
|
|
var zoom_direction: float = 0.0 # if different than zero, zoom is happening
|
|
var move_disabled:bool = false
|
|
var zoom_disabled:bool = false
|
|
var edge_scroll_disabled:bool = ProjectSettings.get_setting("game/controls/edge_scrolling_disabled",false)
|
|
var invert_rotation_x:bool = ProjectSettings.get_setting("game/controls/invert_cam_rotation_x",false)
|
|
var invert_rotation_y:bool = ProjectSettings.get_setting("game/controls/invert_cam_rotation_y",false)
|
|
var default_mouse_mode:= Input.MOUSE_MODE_VISIBLE if ProjectSettings.get_setting("game/controls/edge_scrolling_disabled",false) else Input.MOUSE_MODE_CONFINED
|
|
|
|
var rotation_mode:bool = false
|
|
|
|
@export_range(0,1,0.01) var rotation_speed_x:float = ProjectSettings.get_setting("game/controls/cam_rotation_speed_x",0.5)
|
|
@export_range(0,1,0.01) var rotation_speed_y:float = ProjectSettings.get_setting("game/controls/cam_rotation_speed_y",0.5)
|
|
|
|
@export_category("Signals")
|
|
signal cursor_edge_scrolling(direction:Vector2)
|
|
|
|
#endregion
|
|
|
|
###### DEBUG
|
|
const quit_screen_load = preload("uid://hne6njnc23ur")
|
|
|
|
|
|
func _ready():
|
|
Input.mouse_mode = default_mouse_mode # Maybe should be moved in a better script
|
|
|
|
|
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
func _process(delta: float) -> void:
|
|
cam_move(delta)
|
|
cam_zoom(delta)
|
|
cam_edge_scroll(delta)
|
|
|
|
|
|
func _notification(what: int):
|
|
if edge_scroll_disabled:return
|
|
if what == NOTIFICATION_APPLICATION_FOCUS_OUT:
|
|
print("focus out!")
|
|
#get_tree().paused = true
|
|
#edge_scroll_disabled = true
|
|
move_disabled = true
|
|
if what == NOTIFICATION_APPLICATION_FOCUS_IN:
|
|
print("focus in!")
|
|
#get_tree().paused = false
|
|
#edge_scroll_disabled = false
|
|
move_disabled = false
|
|
if what == NOTIFICATION_WM_MOUSE_ENTER:
|
|
print("focus in!")
|
|
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
if event is InputEventMouseMotion and rotation_mode:
|
|
mouse_velocity = event.screen_relative
|
|
cam_rotation(event.screen_relative)
|
|
else:
|
|
mouse_velocity = Vector2(0,0)
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event.is_action("scroll_up"):
|
|
zoom_direction = -1
|
|
if event.is_action("scroll_down"):
|
|
zoom_direction = 1
|
|
if event.is_action_pressed("rotation_mode"):
|
|
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
|
mouse_velocity = Vector2(0,0)
|
|
rotation_mode = true
|
|
|
|
if event.is_action_released("rotation_mode"):
|
|
rotation_mode = false
|
|
Input.mouse_mode = default_mouse_mode
|
|
if event.is_action_pressed("DEBUG-quit"):
|
|
quit_game()
|
|
|
|
|
|
func quit_game() -> void:
|
|
var quit_screen = quit_screen_load.instantiate()
|
|
get_tree().current_scene.add_child(quit_screen)
|
|
Input.mouse_mode = Input.MOUSE_MODE_HIDDEN
|
|
get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST)
|
|
get_tree().call_deferred("quit")
|
|
|
|
|
|
#region Getter
|
|
func get_mouse_position() -> Vector2:
|
|
return get_viewport().get_mouse_position()
|
|
|
|
|
|
## multiplicator for movement speed, based on zoom level
|
|
## [br][br]
|
|
## Return a remapped float between [param _min] and [param _max]
|
|
func get_zoom_factor(_min:=0.1,_max:=2.0) -> float:
|
|
return remap(cam.position.z,zoom_min,zoom_max,_min,_max)
|
|
|
|
#endregion
|
|
|
|
|
|
#region Movement
|
|
## Controls the movement of the player camera
|
|
func cam_move(delta:float) -> void:
|
|
if move_disabled:return
|
|
var velocity_direction := Vector3.ZERO
|
|
|
|
if Input.is_action_pressed("cam_backward"): velocity_direction -= transform.basis.x
|
|
if Input.is_action_pressed("cam_forward"): velocity_direction += transform.basis.x
|
|
if Input.is_action_pressed("cam_left"): velocity_direction -= transform.basis.z
|
|
if Input.is_action_pressed("cam_right"): velocity_direction += transform.basis.z
|
|
|
|
position.x += velocity_direction.normalized().x * delta * move_speed * get_zoom_factor()
|
|
position.z += velocity_direction.normalized().z * delta * move_speed * get_zoom_factor()
|
|
|
|
|
|
## Controls the zoom of the player camera
|
|
## [br]
|
|
## [param zoom_direction] control the direction.
|
|
## 0.0 means no zoom. Use 1.0 for moving toward the floor
|
|
func cam_zoom(delta:float) -> void:
|
|
if zoom_disabled:return
|
|
|
|
var new_zoom: float = clamp(cam.position.z + (zoom_speed * zoom_direction * delta),zoom_min,zoom_max)
|
|
if new_zoom != cam.position.z and abs(zoom_direction) > 0.001: # FIXME: Magic Number
|
|
cam.position.z = new_zoom
|
|
zoom_direction *= zoom_speed_damp #Smooth the deceleration
|
|
|
|
|
|
func cam_edge_scroll(delta: float) -> void:
|
|
if edge_scroll_disabled:return
|
|
|
|
var current_viewport = get_viewport()
|
|
var pan_direction := Vector2.ZERO
|
|
var viewport_rect := current_viewport.get_visible_rect()
|
|
var viewport_size := viewport_rect.size
|
|
var mouse_position = get_mouse_position()
|
|
|
|
# TODO: Clamp mouse to edge ?
|
|
# X PAN
|
|
if (mouse_position.x < edge_scrolling_margin or (mouse_position.x > viewport_size.x - edge_scrolling_margin)):
|
|
pan_direction.x = 1 if (mouse_position.x > viewport_size.x / 2) else -1 # detect if we are in the half of the screen or not
|
|
|
|
# Y PAN
|
|
if (mouse_position.y < edge_scrolling_margin or (mouse_position.y > viewport_size.y - edge_scrolling_margin)):
|
|
pan_direction.y = 1 if (mouse_position.y < viewport_size.y / 2) else -1 # detect if we are in the half of the screen or not
|
|
|
|
# actual camera movement vector
|
|
var pan_vector := pan_direction * delta * edge_scrolling_speed * get_zoom_factor()
|
|
if pan_vector.length() > 0:
|
|
translate_object_local(Vector3(pan_vector.y, 0, pan_vector.x))
|
|
|
|
# Emit a normalized version just for the cursor
|
|
var quantized_direction := Vector2(
|
|
sign(pan_direction.x) if pan_direction.x != 0 else 0,
|
|
sign(pan_direction.y) if pan_direction.y != 0 else 0
|
|
)
|
|
cursor_edge_scrolling.emit(quantized_direction)
|
|
|
|
|
|
func cam_rotation(mouse_relative:Vector2) -> void:
|
|
rotation.y += mouse_velocity.x * get_process_delta_time() * rotation_speed_x * (-1 if invert_rotation_x else 1)
|
|
%camera_rot.rotation.z = clamp(%camera_rot.rotation.z + (mouse_relative.y * get_process_delta_time() * rotation_speed_y) * (-1 if invert_rotation_y else 1),-0.75,0.35) #= clamp(desired_rot.x,-0.75,0.35) #FIXME: REMOVE MAGIC NUMBERS
|
|
#endregion
|