2024-02-12 15:58:17 +00:00
|
|
|
class_name Camera
|
2024-01-16 22:01:16 +00:00
|
|
|
extends Camera3D
|
|
|
|
|
2024-02-12 15:58:17 +00:00
|
|
|
@export_flags_3d_physics var collision_mask := 1
|
|
|
|
|
2024-02-09 23:10:51 +00:00
|
|
|
@export_group("Zoom")
|
|
|
|
@export var zoom_speed := 0.5
|
|
|
|
@export var zoom_interpolation := 10.0
|
|
|
|
@export var zoom_min := 2.0
|
|
|
|
@export var zoom_max := 8.0
|
2024-02-05 22:42:04 +00:00
|
|
|
|
2024-02-09 23:10:51 +00:00
|
|
|
var target_distance: float
|
2024-02-12 15:58:17 +00:00
|
|
|
var occlusion_distance: float = far
|
|
|
|
var pivot: Node3D
|
2024-02-07 22:02:27 +00:00
|
|
|
|
2024-01-16 22:01:16 +00:00
|
|
|
func _ready():
|
2024-02-09 23:10:51 +00:00
|
|
|
target_distance = position.z
|
2024-02-12 15:58:17 +00:00
|
|
|
pivot = get_parent()
|
2024-01-16 22:01:16 +00:00
|
|
|
Global.camera = self
|
|
|
|
|
2024-02-12 10:53:16 +00:00
|
|
|
func _input(event):
|
|
|
|
if event.is_action_pressed("zoom_in", true):
|
2024-02-09 23:10:51 +00:00
|
|
|
target_distance -= zoom_speed
|
|
|
|
on_distance_changed()
|
2024-02-12 10:53:16 +00:00
|
|
|
get_viewport().set_input_as_handled()
|
2024-02-09 23:10:51 +00:00
|
|
|
|
2024-02-12 10:53:16 +00:00
|
|
|
if event.is_action_pressed("zoom_out", true):
|
2024-02-09 23:10:51 +00:00
|
|
|
target_distance += zoom_speed
|
|
|
|
on_distance_changed()
|
2024-02-12 10:53:16 +00:00
|
|
|
get_viewport().set_input_as_handled()
|
2024-02-07 22:02:27 +00:00
|
|
|
|
2024-02-09 23:10:51 +00:00
|
|
|
func on_distance_changed():
|
|
|
|
target_distance = clampf(target_distance, zoom_min, zoom_max)
|
|
|
|
Global.camera_attributes.dof_blur_far_distance = target_distance + 1.0
|
2024-02-07 22:02:27 +00:00
|
|
|
|
2024-02-09 23:10:51 +00:00
|
|
|
func _process(delta):
|
2024-02-12 15:58:17 +00:00
|
|
|
var distance := target_distance
|
|
|
|
|
|
|
|
if occlusion_distance < target_distance:
|
|
|
|
distance = occlusion_distance
|
|
|
|
|
|
|
|
if abs(distance - position.z) < 0.01:
|
2024-02-09 23:10:51 +00:00
|
|
|
return
|
|
|
|
|
2024-02-12 15:58:17 +00:00
|
|
|
position.z = lerpf(position.z, distance, zoom_interpolation * delta)
|
|
|
|
|
|
|
|
func _physics_process(_delta):
|
|
|
|
occlusion_distance = far
|
|
|
|
|
|
|
|
var corner: Vector2 = get_viewport().get_visible_rect().size
|
|
|
|
var space_state = get_world_3d().direct_space_state
|
|
|
|
|
|
|
|
send_ray(space_state, Vector2(0, 0))
|
|
|
|
send_ray(space_state, Vector2(corner.x, 0))
|
|
|
|
send_ray(space_state, Vector2(0, corner.y))
|
|
|
|
send_ray(space_state, Vector2(corner.x, corner.y))
|
|
|
|
send_ray(space_state, Vector2(corner.x / 2, corner.y / 2))
|
|
|
|
|
|
|
|
func send_ray(space_state: PhysicsDirectSpaceState3D, pos: Vector2):
|
|
|
|
var from := pivot.global_position
|
|
|
|
var to := project_position(pos, -1)
|
|
|
|
var query = PhysicsRayQueryParameters3D.create(from, to, collision_mask)
|
|
|
|
var result = space_state.intersect_ray(query)
|
|
|
|
|
|
|
|
if result:
|
|
|
|
var hit_point: Vector3 = result.position
|
|
|
|
var diff := hit_point - pivot.global_position
|
|
|
|
var distance := diff.length()
|
|
|
|
|
|
|
|
if distance < occlusion_distance:
|
|
|
|
occlusion_distance = distance
|