91 lines
2.2 KiB
GDScript
91 lines
2.2 KiB
GDScript
extends Camera3D
|
|
|
|
@export var height: float = 25.0
|
|
@export var horizontal_distance: float = 25.0
|
|
@export var horizontal_angle_deg: float = 45.0
|
|
|
|
# Perspective zoom (FOV)
|
|
@export var fov_min: float = 20.0
|
|
@export var fov_max: float = 75.0
|
|
@export var default_fov: float = 30.0
|
|
|
|
@export var focus_slice_thickness: float = 6.0
|
|
@export var blur_transition: float = 15.0
|
|
|
|
var _shake_amount: float = 0.0
|
|
var _shake_decay: float = 0.0
|
|
var _user_fov: float = 0.0
|
|
|
|
|
|
func _ready() -> void:
|
|
set_as_top_level(true)
|
|
|
|
projection = Camera3D.PROJECTION_PERSPECTIVE
|
|
fov = default_fov
|
|
_user_fov = default_fov
|
|
|
|
near = 0.1
|
|
far = 150.0
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event.is_action_pressed("zoom_in"):
|
|
_user_fov = clamp(_user_fov / 1.1, fov_min, fov_max)
|
|
|
|
if event.is_action_pressed("zoom_out"):
|
|
_user_fov = clamp(_user_fov * 1.1, fov_min, fov_max)
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
fov = lerpf(fov, _user_fov, delta * 8.0)
|
|
|
|
var angle_rad := deg_to_rad(horizontal_angle_deg)
|
|
|
|
var offset := Vector3(
|
|
sin(angle_rad) * horizontal_distance,
|
|
height,
|
|
cos(angle_rad) * horizontal_distance
|
|
)
|
|
|
|
var target := get_parent() as Node3D
|
|
|
|
global_position = target.global_position + offset
|
|
look_at(target.global_position, Vector3.UP)
|
|
|
|
_update_dof(target.global_position)
|
|
|
|
if _shake_amount > 0.005:
|
|
global_position += Vector3(
|
|
randf_range(-_shake_amount, _shake_amount),
|
|
randf_range(-_shake_amount * 0.25, _shake_amount * 0.25),
|
|
randf_range(-_shake_amount, _shake_amount)
|
|
)
|
|
|
|
_shake_amount = move_toward(_shake_amount, 0.0, _shake_decay * delta)
|
|
|
|
|
|
func trigger_hit(strength: float) -> void:
|
|
_shake_amount = strength * 0.5
|
|
_shake_decay = _shake_amount / 0.4
|
|
|
|
|
|
func _update_dof(target_pos: Vector3) -> void:
|
|
var cam_attr: CameraAttributesPractical = null
|
|
|
|
if attributes is CameraAttributesPractical:
|
|
cam_attr = attributes
|
|
|
|
if cam_attr == null:
|
|
return
|
|
|
|
var distance := global_position.distance_to(target_pos)
|
|
|
|
cam_attr.dof_blur_near_distance = max(distance - focus_slice_thickness * 0.5, near + 0.1)
|
|
cam_attr.dof_blur_far_distance = distance + focus_slice_thickness * 0.5
|
|
|
|
cam_attr.dof_blur_near_transition = blur_transition
|
|
cam_attr.dof_blur_far_transition = blur_transition
|
|
|
|
cam_attr.dof_blur_near_enabled = false
|
|
cam_attr.dof_blur_far_enabled = false
|