93 lines
2.6 KiB
GDScript
93 lines
2.6 KiB
GDScript
class_name SpringArmCharacter
|
|
extends Node3D
|
|
|
|
signal perspective_changed(first_person: bool)
|
|
|
|
const MOUSE_SENSIBILITY: float = 0.005
|
|
|
|
@export_category("Objects")
|
|
@export var _spring_arm: SpringArm3D = null
|
|
@export var _first_person_anchor: Node3D = null
|
|
|
|
@export_category("Camera Perspective")
|
|
@export_range(0.0, 10.0, 0.05) var third_person_distance := 5.0
|
|
@export_range(0.0, 1.0, 0.05) var first_person_distance := 0.0
|
|
@export_range(0.0, 3.0, 0.05) var third_person_height := 2.0
|
|
@export_range(1.0, 179.0, 1.0) var third_person_fov := 75.0
|
|
@export_range(1.0, 179.0, 1.0) var first_person_fov := 90.0
|
|
|
|
var is_first_person := false
|
|
var _yaw := 0.0
|
|
var _pitch := 0.0
|
|
|
|
@onready var _camera: Camera3D = _spring_arm.get_node_or_null("Camera3D") as Camera3D
|
|
|
|
|
|
func _ready() -> void:
|
|
_yaw = rotation.y
|
|
_pitch = _spring_arm.rotation.x if _spring_arm else 0.0
|
|
_apply_axis_lock()
|
|
_apply_perspective()
|
|
|
|
# 进入直接切换第一人称
|
|
is_first_person = not is_first_person
|
|
_apply_perspective()
|
|
perspective_changed.emit(is_first_person)
|
|
get_viewport().set_input_as_handled()
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
_apply_axis_lock()
|
|
if is_first_person and _spring_arm and _first_person_anchor:
|
|
_spring_arm.global_position = _first_person_anchor.global_position
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if not is_multiplayer_authority():
|
|
return
|
|
|
|
var current_scene := get_tree().get_current_scene()
|
|
if current_scene and current_scene.has_method("is_camera_input_blocked"):
|
|
if current_scene.is_camera_input_blocked():
|
|
return
|
|
|
|
#if event.is_action_pressed("toggle_camera"):
|
|
#is_first_person = not is_first_person
|
|
#_apply_perspective()
|
|
#perspective_changed.emit(is_first_person)
|
|
#get_viewport().set_input_as_handled()
|
|
#return
|
|
|
|
if not (event is InputEventMouseMotion):
|
|
return
|
|
if Input.mouse_mode != Input.MOUSE_MODE_CAPTURED:
|
|
return
|
|
|
|
_yaw = wrapf(_yaw - event.relative.x * MOUSE_SENSIBILITY, -PI, PI)
|
|
_pitch = clampf(_pitch - event.relative.y * MOUSE_SENSIBILITY, -PI / 4.0, PI / 24.0)
|
|
_apply_axis_lock()
|
|
|
|
|
|
func _apply_axis_lock() -> void:
|
|
rotation = Vector3(0.0, _yaw, 0.0)
|
|
if _spring_arm:
|
|
_spring_arm.rotation = Vector3(_pitch, 0.0, 0.0)
|
|
if _camera:
|
|
_camera.rotation = Vector3.ZERO
|
|
|
|
|
|
func _apply_perspective() -> void:
|
|
if not _spring_arm:
|
|
return
|
|
if is_first_person:
|
|
_spring_arm.spring_length = first_person_distance
|
|
if _first_person_anchor:
|
|
_spring_arm.global_position = _first_person_anchor.global_position
|
|
if _camera:
|
|
_camera.fov = first_person_fov
|
|
else:
|
|
_spring_arm.spring_length = third_person_distance
|
|
_spring_arm.position = Vector3(0.0, third_person_height, 0.0)
|
|
if _camera:
|
|
_camera.fov = third_person_fov
|