134 lines
4.2 KiB
C#
134 lines
4.2 KiB
C#
using System.Linq;
|
|
using Godot;
|
|
|
|
namespace KarrotStarterTemplate.Common.CameraController;
|
|
|
|
[GlobalClass]
|
|
public partial class CharacterCameraController : Node3D
|
|
{
|
|
[ExportCategory("Nodes")]
|
|
[Export] public Node3D characterToFollow { get; set; }
|
|
|
|
[ExportCategory("Properties")]
|
|
[ExportGroup("Mouse input")]
|
|
[Export] public bool enableInput = true;
|
|
[Export] public float mouseSensitivity { get; set; } = .5f;
|
|
[Export] public Vector2 cameraTiltLimit { get; set; } = new(-45f, 45f);
|
|
|
|
[ExportGroup("Player")]
|
|
[Export] public bool followPlayer = true;
|
|
[Export(PropertyHint.Range, "0, 1")] public float followDelay { get; set; } = .5f;
|
|
[Export] public bool rotatePlayer = true;
|
|
[Export(PropertyHint.Range, "0, 1")] public float rotateDelay { get; set; } = .5f;
|
|
|
|
private Camera3D _camera; // todo
|
|
private SpringArm3D _springArm;
|
|
private Vector2 _mouseInput = Vector2.Zero;
|
|
|
|
public Camera3D camera => _camera;
|
|
public SpringArm3D springArm => _springArm;
|
|
// Called when the node enters the scene tree for the first time.
|
|
public override void _Ready()
|
|
{
|
|
if (Engine.IsEditorHint())
|
|
{
|
|
TopLevel = true;
|
|
return;
|
|
}
|
|
|
|
characterToFollow ??= (CharacterBody3D)GetParent();
|
|
|
|
_springArm = GetChildren().OfType<SpringArm3D>().First();
|
|
_camera = _springArm.GetChildren().OfType<Camera3D>().First();
|
|
|
|
GlobalPosition = characterToFollow.GlobalPosition;
|
|
// Input.SetMouseMode(Input.MouseModeEnum.Captured);
|
|
}
|
|
|
|
public override void _UnhandledInput(InputEvent @event)
|
|
{
|
|
if (Engine.IsEditorHint())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!enableInput)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (@event is InputEventMouseMotion mouseMotion)
|
|
{
|
|
_mouseInput = -mouseMotion.Relative * mouseSensitivity;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
{
|
|
if (Engine.IsEditorHint())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (followPlayer)
|
|
{
|
|
float weight = Mathf.Clamp(20 * (1 - followDelay) * (float)delta, 0,1 );
|
|
GlobalPosition = followDelay > 0 ? GlobalPosition.Lerp(characterToFollow.GlobalPosition, weight) : characterToFollow.GlobalPosition;
|
|
}
|
|
|
|
if (rotatePlayer)
|
|
{
|
|
float weight = Mathf.Clamp(20 * (1 - rotateDelay) * (float)delta, 0,1 );
|
|
Vector3 v = characterToFollow.GlobalRotation;
|
|
characterToFollow.GlobalRotation = new Vector3(v.X, Mathf.LerpAngle(v.Y, _springArm.GlobalRotation.Y, weight) , v.Z);
|
|
}
|
|
|
|
if (enableInput)
|
|
{
|
|
_springArm.Rotation += new Vector3(_mouseInput.Y * (float)delta, 0f, 0f);
|
|
Rotation += new Vector3(0f, _mouseInput.X * (float)delta, characterToFollow.GlobalPosition.Y);
|
|
|
|
var (x, y, z) = _springArm.RotationDegrees;
|
|
_springArm.RotationDegrees = new Vector3(Mathf.Clamp(x, cameraTiltLimit.X, cameraTiltLimit.Y), y, z);
|
|
|
|
_mouseInput = Vector2.Zero;
|
|
}
|
|
}
|
|
|
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
public override void _Process(double delta)
|
|
{
|
|
if (Engine.IsEditorHint())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (Input.IsActionJustPressed("click"))
|
|
{
|
|
var position2D = GetViewport().GetMousePosition();
|
|
var dropPlane = new Plane(new Vector3(0, 10f, 0), 0f);
|
|
var position3D =
|
|
dropPlane.IntersectsRay(camera.ProjectRayOrigin(position2D), camera.ProjectRayNormal(position2D));
|
|
if (position3D != null)
|
|
{
|
|
GD.Print(position3D);
|
|
DebugDraw3D.DrawSphere(position3D ?? Vector3.Zero, .5f, Colors.Aqua, 2f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
TODO:
|
|
1. Zrobić enuma z presetami
|
|
|
|
if Input.is_action_pressed("click"):
|
|
var position2D = get_viewport().get_mouse_position()
|
|
var dropPlane = Plane(Vector3(0, 0, 10), z)
|
|
var position3D = dropPlane.intersects_ray(camera.project_ray_origin(position2D),camera.project_ray_normal(position2D))
|
|
print(position3D)
|
|
|
|
*/ |