Files
project-vivi/Assets/Classes/PlayerCharacter/player_camera_3d.gd
T
2026-09-19 10:06:28 -04:00

103 lines
4.1 KiB
GDScript

class_name PlayerCamera3D
extends Node3D
@export var follow_target : Node3D
@export_range(0.0, 5.0, 0.05) var follow_max_distance : float = 1.0
@export_range(0.05, 20.0, 0.05) var follow_speed : float = 1.0
@export var follow_distance_curve : Curve
@export var animation_tree : AnimationTree
@export_category("Nodes")
@export var camera : Camera3D
@export var state_chart : StateChart
@export var gimbal_x : Node3D
@export var gimbal_y : Node3D
@export_category("Input Settings")
@export var _camera_movement_speed : Vector2 = Vector2.ONE
@export var _camera_accelerate_speed : float = 1.0
@export_category("Input Resources")
@export var _camera_movement_resource : InputResource
var _reset_orientation : Vector2 = Vector2.ZERO
var _target_camera_orientation : Vector2 = Vector2.ZERO
var _debug_input_resource : InputResource
func _ready() -> void:
_reset_orientation = Vector2(gimbal_y.rotation.y, gimbal_x.rotation.x)
if follow_target: global_position = follow_target.global_position
_target_camera_orientation = _reset_orientation
InputHandler.add_input_resource(self, _camera_movement_resource)
_debug_input_resource = load("uid://xh7ux5jkfxle")
InputHandler.add_input_resource(self, _debug_input_resource)
top_level = true
func _physics_process(_delta:float) -> void:
gimbal_y.rotation.y = lerp_angle(gimbal_y.rotation.y, -_target_camera_orientation.x, _camera_accelerate_speed * _delta)
gimbal_x.rotation.x = lerp_angle(gimbal_x.rotation.x, _target_camera_orientation.y, _camera_accelerate_speed * _delta)
if follow_target:
var max_position : Vector3 = (global_position - follow_target.global_position).normalized() * follow_max_distance
global_position = lerp(global_position, follow_target.global_position, follow_distance_curve.sample_baked(max_position.length()) * follow_speed * _delta)
if global_position.distance_squared_to(follow_target.global_position) > (follow_target.global_position + max_position).distance_squared_to(follow_target.global_position):
global_position = (follow_target.global_position + max_position)
func _on_camera_rotate_2d(_delta:float, _vector:Vector2) -> void:
_on_camera_rotate(_delta, _vector)
func _on_camera_rotate_mouse(_delta:float, _vector:Vector2) -> void:
_on_camera_rotate(_delta, _vector)
func _on_camera_rotate(_delta:float, _vector:Vector2) -> void:
_target_camera_orientation += _vector * _camera_movement_speed * _delta
const rotation_limit = (PI / 2.0) - 0.075
_target_camera_orientation.y = clamp(_target_camera_orientation.y, -rotation_limit, rotation_limit)
func _on_camera_reset_pressed() -> void:
_target_camera_orientation = _reset_orientation
_target_camera_orientation.x -= follow_target.global_rotation.y
func _on___debug_show_performance_pressed() -> void:
DebugMenu.visible = !DebugMenu.visible
func _on___debug_debugdraw_disabled_pressed() -> void:
get_viewport().debug_draw = Viewport.DEBUG_DRAW_DISABLED
func _on___debug_debugdraw_wireframe_pressed() -> void:
get_viewport().debug_draw = Viewport.DEBUG_DRAW_WIREFRAME
func _on___debug_debugdraw_normalbuffer_pressed() -> void:
get_viewport().debug_draw = Viewport.DEBUG_DRAW_NORMAL_BUFFER
func _on___debug_debugdraw_overdraw_pressed() -> void:
get_viewport().debug_draw = Viewport.DEBUG_DRAW_OVERDRAW
func _on___debug_debugdraw_ssao_pressed() -> void:
get_viewport().debug_draw = Viewport.DEBUG_DRAW_SSAO
func _on___debug_debugdraw_sdfgi_pressed() -> void:
get_viewport().debug_draw = Viewport.DEBUG_DRAW_SDFGI
func _on___debug_debugdraw_ssil_pressed() -> void:
get_viewport().debug_draw = Viewport.DEBUG_DRAW_SSIL
func _on_standard_state_entered() -> void:
InputHandler.add_input_resource(self, _camera_movement_resource)
_on_camera_reset_pressed()
func _on_slice_time_state_entered() -> void:
InputHandler.remove_input_resource(self, _camera_movement_resource)
_on_camera_reset_pressed()
animation_tree["parameters/playback"].travel("slice_time_zoom_in")
func _on_slice_time_state_exited() -> void:
animation_tree["parameters/playback"].travel("standard_zoom")
func _on_slice_time_state_physics_processing(_delta:float) -> void:
gimbal_y.global_rotation.y = follow_target.global_rotation.y