gfolf2/src/ui/camera/orbital_camera/orbital_camera.gd

53 lines
1.5 KiB
GDScript

class_name OrbitalCamera extends Node3D
const POSITION_ACCELERATION := 4.0
const BASIS_ACCELERATION := 4.0
const TARGETER_ACCELERATION := 4.0
@export var target: Node3D
@export var offset := Vector3(0, 1, 0)
@export var angular_speed := 0.007
var target_basis := Basis.IDENTITY
@onready var pivot: Node3D = %Pivot
@onready var camera: Camera3D = %Camera
@onready var targeter: Node3D = %Targeter
static var scene := preload("res://src/ui/camera/orbital_camera/orbital_camera.tscn")
func _physics_process(delta: float) -> void:
var up := Vector3.UP
# If target is a game ball, realign to gravity
if target is GameBall:
up = -(target as GameBall).current_gravity.normalized()
var right := up.cross(global_basis.z).normalized()
var forward := right.cross(up).normalized()
target_basis = Basis(right, up, forward)
# Slerp to basis
global_basis = global_basis.slerp(target_basis, delta * BASIS_ACCELERATION)
# Update position
global_position = global_position.lerp(
target.global_position + offset, delta * POSITION_ACCELERATION
)
# Update rotation
#camera.look_at(target.global_position, up)
targeter.look_at(target.global_position, up)
camera.global_basis = camera.global_basis.slerp(
targeter.global_basis.orthonormalized(), delta * TARGETER_ACCELERATION
)
# Update phase angle
pivot.rotation.y += angular_speed
static func create(_target: Node3D) -> OrbitalCamera:
var instance: OrbitalCamera = scene.instantiate()
instance.target = _target
return instance