extends Node3D @export var low_angle: float = -5.0 @export var high_angle: float = -50.0 @export var min_zoom: float = 1.5 @export var max_zoom: float = 5.0 @onready var _camera = $Camera3D var _is_grabbing = false func _ready() -> void: _set_bg_ratio() get_viewport().size_changed.connect(_set_bg_ratio) func _set_bg_ratio() -> void: var background_plane: MeshInstance3D = $BackgroundPlane var frustum_height = tan(_camera.fov * PI / 180 * 0.5) * (_camera.position.z - background_plane.position.z) * 2 var viewport_size = get_viewport().size var ratio = float(viewport_size.x) / float(viewport_size.y) background_plane.mesh.size.x = frustum_height * ratio background_plane.mesh.size.y = frustum_height background_plane.material_override.set_shader_parameter("ratio", Vector2(ratio, 1.0)) func _unhandled_input(event: InputEvent) -> void: var wheel_direction = 0.0 if (event is InputEventMouseButton): if event.button_index == MOUSE_BUTTON_LEFT: _is_grabbing = event.pressed if event.pressed: var wheel_up = event.button_index == MOUSE_BUTTON_WHEEL_UP var wheel_down = event.button_index == MOUSE_BUTTON_WHEEL_DOWN wheel_direction = float(wheel_down) - float(wheel_up) if wheel_direction != 0: _camera.position.z += wheel_direction * 0.25 _camera.position.z = clamp(_camera.position.z, min_zoom, max_zoom) _set_bg_ratio() # Check mouse motion if (event is InputEventMouseMotion): if !_is_grabbing: return rotation.y += -event.relative.x * 0.005 rotation.x += -event.relative.y * 0.005 rotation.x = clamp(rotation.x, deg_to_rad(high_angle), deg_to_rad(low_angle))