Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extends Node3D
- # Variables to expose here
- ## Mouse Sensitivity
- @export var mouse_sensitivity : float = 100.0
- ## Minimum viewing angle (in degrees)
- @export_range(-90.0, 0.0, 0.1, "radians_as_degrees") var min_vertical_angle: float = -PI/2
- ## Maximum viewing angle (in degrees)
- @export_range(0.8, 90.0, 0.1, "radians_as_degrees") var max_vertical_angle: float = PI/4
- ## The target the camera is to follow
- @export var follow_target : NodePath
- # Onready vars here
- @onready var camera = %Camera3D
- @onready var marker = %Marker3D
- @onready var spring_arm = %SpringArm3D
- @onready var pivot = $"Pivot"
- var can_clip : bool = false
- var clipping : bool = false
- var target : Node
- var target_pos : Vector3 = Vector3()
- var cam_offset : Vector3 = Vector3()
- func _ready() -> void:
- Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
- if follow_target:
- target = get_node(follow_target)
- spring_arm.add_excluded_object(get_node(follow_target))
- cam_offset = global_position - target.global_position
- set_as_top_level(true)
- # Force physics interpolation OFF
- set_physics_interpolation_mode(Node.PHYSICS_INTERPOLATION_MODE_OFF)
- # Force VSync on
- DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED)
- func _unhandled_input(event: InputEvent) -> void:
- # Handle rotation of the camera here
- if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
- _rotate_camera(event)
- # Release/capture the mouse
- if event.is_action_pressed("ui_cancel"):
- if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
- Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
- else:
- Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
- # Quick Quit (ALT + Q)
- if event.is_action_pressed("quick_quit"):
- get_tree().quit()
- func _process(delta):
- _check_collision(delta)
- _rotate_camera(InputEvent)
- _follow_target(delta)
- func _check_collision(delta):
- var physics_tick = Engine.get_physics_interpolation_fraction()
- can_clip = spring_arm.get_hit_length() < spring_arm.spring_length
- if can_clip:
- if camera.position.z > marker.position.z:
- if not clipping:
- camera.position.z = lerp(camera.position.z, marker.position.z, 0.1)
- else:
- camera.position.z = lerp(camera.position.z, marker.position.z, 0.0001 * delta)
- elif camera.position.z < marker.position.z:
- if not clipping:
- camera.position.z = lerp(camera.position.z, marker.position.z, 0.08)
- else:
- camera.position.z = lerp(camera.position.z, marker.position.z, 0.0001 * delta)
- if is_equal_approx(camera.position.z, marker.position.z):
- clipping = true
- else:
- camera.position.z = lerp(camera.position.z, marker.position.z, 0.05)
- clipping = false
- func _follow_target(delta):
- var tf : Transform3D = target.get_global_transform_interpolated()
- var t_pos = tf.origin + cam_offset
- var distance = global_position - tf.origin
- target_pos = lerp(target_pos, t_pos, 1.0 - pow(0.01, delta))
- global_position = target_pos
- func _rotate_camera(event) -> void:
- if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
- var viewport_transform: Transform2D = get_tree().root.get_final_transform()
- var motion: Vector2 = event.xformed_by(viewport_transform).relative
- var degrees_per_unit: float = 0.001
- motion *= mouse_sensitivity
- motion *= degrees_per_unit
- # Don't apply rotation if we're not moving the mouse
- if is_zero_approx(motion.length() > 0.01):
- return
- # Apply pitch
- pivot.rotate_object_local(Vector3.LEFT, deg_to_rad(motion.y))
- # Apply yaw
- rotate_object_local(Vector3.DOWN, deg_to_rad(motion.x))
- if Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
- var input_vector = Input.get_vector("look_right", "look_left", "look_down", "look_up")
- rotate_y(input_vector.x * 0.05)
- pivot.rotate_x(input_vector.y * 0.05)
- # Clamp the rotation
- pivot.rotation.x = clamp(pivot.rotation.x, min_vertical_angle, max_vertical_angle)
- rotation.y = wrapf(rotation.y, 0.0, TAU)
- # Orthonormalize the transforms
- pivot.orthonormalize()
- orthonormalize()
Advertisement
Add Comment
Please, Sign In to add comment