188 lines
5.7 KiB
C#
Executable File
188 lines
5.7 KiB
C#
Executable File
using Godot;
|
|
using System;
|
|
using SJK.Math;
|
|
using Chickensoft.SaveFileBuilder;
|
|
using Chickensoft.Introspection;
|
|
using Chickensoft.Serialization;
|
|
|
|
|
|
[Meta, Id("save_data")]
|
|
public partial class SaveData
|
|
{
|
|
[Save("player_transform")]
|
|
public Transform3D Transform3D {get;set;}
|
|
[Save("player_camera")]
|
|
public Transform3D CameraTransform {get;set;}
|
|
}
|
|
public partial class RTSCamera : Node3D, ISaveable<SaveData>
|
|
{
|
|
[Export]
|
|
public Camera3D camera;
|
|
Vector3 positionStartPos;
|
|
Vector3 positionOffsetPos;
|
|
Vector3 lastTransalation;
|
|
|
|
Vector3 cameraTargetOffset;
|
|
Action Update_CurrentFunc;
|
|
|
|
//Generic bookkeeping variables;
|
|
Vector2 LastMousePostition;
|
|
//Camera Dragging Bookkeeping variables
|
|
Vector3 LastMouseGroundPlanePositon;
|
|
//Camera Rotating Bookkeeping variables
|
|
float CameraRotateSpeed = .5f;
|
|
bool isDraging;
|
|
public override void _Ready()
|
|
{
|
|
Update_CurrentFunc = Update_DetectModeStart;
|
|
}
|
|
void Update_DetectModeStart()
|
|
{
|
|
if (Input.IsActionJustPressed("move_mouse"))
|
|
{
|
|
//Mouse Left went Down
|
|
//Does nothing basicly
|
|
}
|
|
else if (Input.IsActionPressed("move_mouse") && GetViewport().GetMousePosition() != LastMousePostition)
|
|
{
|
|
LastMouseGroundPlanePositon = camera.MouseToGroundPlane() ?? Vector3.Zero;
|
|
Update_CurrentFunc = Update_CameraDrag;
|
|
Update_CurrentFunc();
|
|
// GD.Print("1");
|
|
}
|
|
else if (Input.IsActionPressed("camera_rotate") && GetViewport().GetMousePosition() != LastMousePostition)
|
|
{
|
|
LastMouseGroundPlanePositon = camera.MouseToGroundPlane() ?? Vector3.Zero;
|
|
Update_CurrentFunc = Update_RotateCamera;
|
|
Update_CurrentFunc();
|
|
// GD.Print("2");
|
|
}
|
|
|
|
}
|
|
public override void _Process(double delta)
|
|
{
|
|
if (Input.IsActionJustPressed("ui_cancel"))
|
|
{
|
|
CancelUpdateFunc();
|
|
}
|
|
// GD.PrintS(positionStartPos,positionOffsetPos,lastTransalation,LastMouseGroundPlanePositon,LastMousePostition,cameraTargetOffset,scrollAmount);
|
|
Update_CurrentFunc();
|
|
Update_CameraScroll((float)delta);
|
|
LastMousePostition = GetViewport().GetMousePosition();
|
|
camera.Fov = Mathf.Lerp(camera.Fov, Mathf.Lerp(90, 50, (camera.Position.Y - 5) / (80 - 5)), (float)delta * 10);
|
|
}
|
|
void CancelUpdateFunc()
|
|
{
|
|
Update_CurrentFunc = Update_DetectModeStart;
|
|
}
|
|
void Update_CameraDrag()
|
|
{
|
|
if (Input.IsActionJustReleased("move_mouse"))
|
|
{
|
|
CancelUpdateFunc();
|
|
}
|
|
|
|
var hitpos = camera.MouseToGroundPlane() ?? Vector3.Zero;
|
|
|
|
|
|
var diff = LastMouseGroundPlanePositon - hitpos;
|
|
|
|
GlobalTranslate(diff);
|
|
LastMouseGroundPlanePositon = hitpos = camera.MouseToGroundPlane() ?? Vector3.Zero;
|
|
|
|
}
|
|
float scrollAmount;
|
|
public override void _UnhandledInput(InputEvent @event)
|
|
{
|
|
scrollAmount += Input.IsActionJustReleased("mouse_scroll_up") ? 1 : 0;
|
|
scrollAmount += Input.IsActionJustReleased("mouse_scroll_down") ? -1 : 0;
|
|
if (@event is InputEventKey eventKey && eventKey.Keycode == Key.F)
|
|
{
|
|
GlobalPosition = Vector3.Zero;
|
|
camera.Position = Vector3.Zero;
|
|
CancelUpdateFunc();
|
|
}
|
|
}
|
|
void Update_CameraScroll(float delta)
|
|
{
|
|
|
|
// Zoom to scrollwheel
|
|
// float scrollAmount = Input.IsActionJustReleased("mouse_scroll_up")?1:0;
|
|
// scrollAmount += Input.IsActionJustReleased( "mouse_scroll_down")?-1:0;
|
|
// GD.Print(scrollAmount);
|
|
float minHeight = 2;
|
|
float maxHeight = 30;
|
|
// Move camera towards hitPos
|
|
// var hitPos = camera.MouseToGroundPlane();
|
|
// Vector3 dir = hitPos - camera.Translation;
|
|
var dir = -camera.GlobalTransform.Basis.Z * .5f;
|
|
|
|
var p = camera.Position;
|
|
|
|
// Stop zooming out at a certain distance.
|
|
// TODO: Maybe you should still slide around at 20 zoom?
|
|
if (scrollAmount > 0 || p.Y < (maxHeight - 0.1f))
|
|
{
|
|
cameraTargetOffset += dir * scrollAmount;
|
|
}
|
|
// DebugDraw3D.DrawArrow(Vector3.Zero,cameraTargetOffset);
|
|
Vector3 lastCameraPosition = camera.Position;
|
|
camera.Position = camera.Position.Lerp(camera.Position + cameraTargetOffset, delta);
|
|
cameraTargetOffset -= camera.Position - lastCameraPosition;
|
|
|
|
p = camera.Position;
|
|
if (p.Y < minHeight)
|
|
{
|
|
p.Y = minHeight;
|
|
}
|
|
if (p.Y > maxHeight)
|
|
{
|
|
p.Y = maxHeight;
|
|
}
|
|
|
|
camera.Position = p;
|
|
// Change camera angle
|
|
camera.RotationDegrees = new Vector3(
|
|
Mathf.Lerp(-50, -75, camera.Position.Y / maxHeight),
|
|
camera.RotationDegrees.Y,
|
|
camera.RotationDegrees.Z
|
|
);
|
|
scrollAmount = 0;
|
|
}
|
|
void Update_RotateCamera()
|
|
{
|
|
if (!Input.IsActionPressed("move_mouse"))
|
|
{
|
|
CancelUpdateFunc();
|
|
}
|
|
Vector2 hitpos = GetViewport().GetMousePosition();
|
|
|
|
Vector2 diff = LastMousePostition - hitpos;
|
|
camera.RotationDegrees = new Vector3(
|
|
camera.RotationDegrees.X,
|
|
camera.RotationDegrees.Y + (diff.X * CameraRotateSpeed),
|
|
camera.RotationDegrees.Z
|
|
);
|
|
LastMousePostition = hitpos = GetViewport().GetMousePosition();
|
|
}
|
|
|
|
public SaveData Save() => new(){Transform3D = Transform, CameraTransform = camera.Transform};
|
|
public void Load(in SaveData data)
|
|
{
|
|
Transform = data.Transform3D;
|
|
camera.Transform = data.CameraTransform;
|
|
}
|
|
}
|
|
|
|
public static partial class SJKMath
|
|
{
|
|
public static Vector3? MouseToPlane(this Plane plane, Camera3D viewCamera, Vector2? mousePos = null)
|
|
{
|
|
var from = viewCamera.ProjectRayOrigin( mousePos ?? viewCamera.GetViewport().GetMousePosition());
|
|
var normal = viewCamera.ProjectRayNormal(mousePos ?? viewCamera.GetViewport().GetMousePosition());
|
|
return plane.IntersectsRay(from, normal);
|
|
}
|
|
public static Vector3? MouseToGroundPlane(this Camera3D viewCamera, Vector2? mousePos = null, float offset = 0) =>
|
|
(Plane.PlaneXZ with { D = offset }).MouseToPlane(viewCamera, mousePos);
|
|
}
|