add ability to gradually move camera to a target (aka heading to)

This commit is contained in:
2024-10-06 04:35:47 +10:00
parent e3a958f770
commit abd2ea2e93

View File

@@ -1,11 +1,17 @@
extends Camera3D
enum CameraState {
FREE,
HEADING_TO,
}
const ZOOM_SPEED: float = 0.1
const ZOOM_DAMP: float = 5
const ZOOM_VALUE_DEFAULT: float = 0.3
## How many pixels the mouse needs to be away
## from the screen edge to move the camera.
const EDGE_THRESHOLD: float = 10
const HEADING_SPEED: float = 1
@export var zoom_in_distance: float = 5
@export var zoom_in_fov: float = 25
@@ -23,10 +29,18 @@ var mouse_position: Vector2 = Vector2()
var zoom_value: float = ZOOM_VALUE_DEFAULT
var zoom_raw: float = zoom_value
var mouse_outside_window: bool = false
var heading_to_position: Vector3 = Vector3.ZERO
var heading_from_position: Vector3 = Vector3.ZERO
var heading_from_zoom: float = 0
var heading_progress: float = 0
var state: CameraState = CameraState.FREE
var window_out_of_focus: bool = false
func _process(delta: float) -> void:
_handle_heading_to(delta)
zoom_value = lerp(zoom_value, zoom_raw, delta * ZOOM_DAMP)
_handle_movement(delta)
@@ -56,19 +70,26 @@ func _input(event: InputEvent) -> void:
zoom_raw = clamp(zoom_raw, 0, 1)
if event.is_action_pressed("reset_camera"):
target_position = Vector3.ZERO
zoom_raw = ZOOM_VALUE_DEFAULT
head_to(Vector3.ZERO)
func _notification(what: int) -> void:
if what == NOTIFICATION_WM_MOUSE_ENTER:
mouse_outside_window = false
elif what == NOTIFICATION_WM_MOUSE_EXIT:
mouse_outside_window = true
if what == NOTIFICATION_WM_WINDOW_FOCUS_IN:
window_out_of_focus = false
elif what == NOTIFICATION_WM_WINDOW_FOCUS_OUT:
window_out_of_focus = true
func head_to(to: Vector3) -> void:
heading_to_position = to
heading_from_position = target_position
heading_progress = 0
heading_from_zoom = zoom_value
state = CameraState.HEADING_TO
func _handle_movement(delta: float) -> void:
if mouse_outside_window:
if window_out_of_focus or state != CameraState.FREE:
return
var viewport_size := get_viewport().get_visible_rect().size
@@ -99,3 +120,29 @@ func _handle_movement(delta: float) -> void:
var speed: float = lerp(zoom_in_speed, zoom_out_speed, zoom_value)
var velocity := direction * speed
target_position += velocity * delta
func _handle_heading_to(delta: float) -> void:
if state != CameraState.HEADING_TO:
return
if heading_progress >= 1:
target_position = heading_to_position
state = CameraState.FREE
heading_progress += HEADING_SPEED * delta
target_position = lerp(heading_from_position, heading_to_position, heading_progress)
zoom_raw = quadratic_bezier(heading_from_zoom, 1, ZOOM_VALUE_DEFAULT, heading_progress)
zoom_value = zoom_raw
func quadratic_bezier(
p0: float,
p1: float,
p2: float,
t: float,
) -> float:
var q0: float = lerp(p0, p1, t)
var q1: float = lerp(p1, p2, t)
var r: float = lerp(q0, q1, t)
return r