# Hurry Curry! - a game about cooking # Copyright 2024 nokoe # Copyright 2024 tpart # Copyright 2024 metamuffin # Copyright 2024 BigBrotherNii # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, version 3 of the License only. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # class_name FollowCamera extends Camera3D const ROTATE_SPEED: float = 1.5 const ROTATE_WEIGHT: float = 8.0 const ROTATE_UP_SPEED: float = 0.7 const ROTATE_UP_WEIGHT: float = 4.0 const ANGLE_UP_MIN: float = 0.5 const ANGLE_UP_MAX: float = 0.4999 * PI const LOOK_WEIGHT: float = 8.0 const MOVE_WEIGHT: float = 2.0 const ZOOM_SPEED: float = 1.0 const DISCRETE_DURATION: float = 0.3 const ZOOM_WEIGHT: float = 10.0 const MAX_ZOOM: float = 20.0 const MIN_ZOOM: float = 2.0 const ZOOM_CURRENT_TO_MAX_RATIO: float = 1.35 @export var target: Node3D var angle_target: float = 0 var angle: float = 0 var angle_up_target: float = 1 var angle_up: float = 1 var ground: Vector3 var camera_distance: float = 10. var camera_distance_target: float = camera_distance var disable_input_menu := false var disable_input_lobby := false var _disable_input := false func _ready(): if target == null: push_warning("target is not set") else: ground = target.position func _process(delta): if target != null: follow(delta) func _input(_event): if _disable_input: return if Input.is_action_just_pressed("reset"): reset() func reset(): angle_target = 0 angle_up_target = 1 camera_distance_target = 10 func follow(delta): if not _disable_input: angle_target += Input.get_axis("rotate_left", "rotate_right") * ( ROTATE_SPEED * delta * (-1 if Global.get_setting("gameplay.invert_camera") else 1) ) angle = G.interpolate_angle(angle, angle_target, delta * ROTATE_WEIGHT) if not _disable_input: angle_up_target += Input.get_axis("rotate_down", "rotate_up") * ( ROTATE_UP_SPEED * delta * (-1 if Global.get_setting("gameplay.invert_camera") else 1) ) angle_up_target = clamp(angle_up_target, ANGLE_UP_MIN, ANGLE_UP_MAX) angle_up = G.interpolate_angle(angle_up, angle_up_target, delta * ROTATE_UP_WEIGHT) var offset = Vector3(0, sin(angle_up) * camera_distance, cos(angle_up) * camera_distance).rotated(Vector3.UP, angle) var new_transform = transform new_transform.origin = target.position + offset new_transform = new_transform.looking_at(target.position) if Global.get_setting("gameplay.interpolate_camera_rotation"): transform.basis = Basis.from_euler(Vector3( G.interpolate_angle(transform.basis.get_euler().x, new_transform.basis.get_euler().x, delta * LOOK_WEIGHT), G.interpolate_angle(transform.basis.get_euler().y, new_transform.basis.get_euler().y, delta * LOOK_WEIGHT), G.interpolate_angle(transform.basis.get_euler().z, new_transform.basis.get_euler().z, delta * LOOK_WEIGHT) )) else: transform.basis = new_transform.basis # add 0.5, this is the head height ground = G.interpolate(ground, target.position + Vector3(0., 0.5, 0.), delta * MOVE_WEIGHT) if not _disable_input: var zoom_dist = Input.get_axis("zoom_in", "zoom_out") * delta zoom_dist += float(Input.is_action_just_pressed("zoom_out_discrete")) * DISCRETE_DURATION zoom_dist -= float(Input.is_action_just_pressed("zoom_in_discrete")) * DISCRETE_DURATION camera_distance_target *= exp(zoom_dist * ZOOM_SPEED) camera_distance_target = clamp(camera_distance_target, MIN_ZOOM, MAX_ZOOM) camera_distance = G.interpolate(camera_distance, camera_distance_target, delta * ZOOM_WEIGHT) position = ground + offset func set_ingame(state: bool, in_lobby: bool): # Disable input in lobby if state and in_lobby: reset() disable_input_lobby = true else: disable_input_lobby = false update_disable_input() func update_disable_input(): _disable_input = disable_input_lobby or disable_input_menu