extends Node @export_subgroup("Camera/Objects") @export var controlled : Camera3D @export_subgroup("Camera/Angle") # Mouse sensitivity @export var orbit_sensitivity : Vector2 = Vector2(0.01, 0.01) # Minimum horizon angle @export var min_horizon_angle : float = PI/15.0 # Maximum diving angle @export var max_diving_angle : float = PI/3.5 @export_subgroup("Camera/Zoom") # Mouse zoom-in ratio @export var mouse_zoom_in_ratio : float = 0.9 # Mouse zoom-out ratio @export var mouse_zoom_out_ratio : float = 1.1 # Maximum zoom out ratio. @export var max_zoom_out_distance_ratio : float = 1.5 # Maximum zoom in ratio. @export var max_zoom_in_distance : float = 1.5 # Maximal distance @export var max_distance : float = 10.0 @export_subgroup("Camera/Interpolation") # Angle interpolation speed. @export var angle_interpolation_speed : float = 7.0 # Distance interpolation speed. @export var distance_interpolation_speed : float = 9.0 # Eye interpolation speed. @export var eye_interpolation_speed : float = 13.0 @export_subgroup("Camera/Controls") # Controls attribution @export var camera_orbit_mouse_button : MouseButton = MOUSE_BUTTON_MIDDLE @export var camera_zoom_mouse_button : MouseButton = MOUSE_BUTTON_NONE # Camera angles (Y, Z) @onready var current_angles : Vector2 = Vector2.ZERO @onready var angles : Vector2 = Vector2.ZERO # Camera distance @onready var current_distance : float = 32 @onready var distance : float = 32 # Camera eye posiyion @onready var current_eye : Vector3 = Vector3.ZERO @onready var eye : Vector3 = Vector3.ZERO # Mouse is dragged @onready var orbit_drag : bool = false @onready var zoom_drag : bool = false func _ready() -> void: reset_camera() func reset_camera() -> void: distance = max_distance current_distance = distance current_angles = angles eye = set_camera(current_distance, current_angles) current_eye = eye func _process(delta : float) -> void: current_angles = lerp(current_angles, angles, angle_interpolation_speed * delta) current_distance = lerp(current_distance, distance, distance_interpolation_speed * delta) eye = set_camera(current_distance, current_angles) current_eye = lerp(current_eye, eye, eye_interpolation_speed * delta) controlled.look_at_from_position(current_eye, Vector3.ZERO) func set_camera(dist : float, ang : Vector2) -> Vector3: return Vector3(dist, 0, 0).rotated(Vector3(0.0, 0.0, 1.0), ang.y).rotated(Vector3.UP, ang.x) func _input(event : InputEvent) -> void: match event.get_class(): "InputEventKey": var bevent : InputEventKey = event as InputEventKey if bevent.pressed and not bevent.is_echo(): match bevent.keycode: KEY_SPACE: print("Camera at %s" % (str(current_eye))) _: pass "InputEventMouseButton": var bevent : InputEventMouseButton = event as InputEventMouseButton match bevent.button_index: camera_orbit_mouse_button: orbit_drag = bevent.pressed && !zoom_drag camera_zoom_mouse_button: zoom_drag = bevent.pressed && !orbit_drag if camera_zoom_mouse_button == MOUSE_BUTTON_NONE and (bevent.button_index == MOUSE_BUTTON_WHEEL_UP or bevent.button_index == MOUSE_BUTTON_WHEEL_DOWN): perform_zoom(bevent.button_index == MOUSE_BUTTON_WHEEL_UP) "InputEventMouseMotion": var mevent : InputEventMouseMotion = event as InputEventMouseMotion if orbit_drag: var motion : Vector2 = mevent.relative * orbit_sensitivity angles += motion angles.y = clamp(angles.y, min_horizon_angle, max_diving_angle) if zoom_drag: perform_zoom(mevent.relative.y < 0) func perform_zoom(zoom_in : bool) -> void: if zoom_in: distance *= mouse_zoom_in_ratio distance = max(max_zoom_in_distance, distance) else: distance *= mouse_zoom_out_ratio distance = min(max_distance, distance)
or share this direct link: