blob: 6675fac28dcbc1c9cb57840f84b5609abf7f7ac1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
using Godot;
using System;
public partial class WorldCamera : Camera3D
{
[Export]
Node3D target;
[Export]
private Mode mode = Mode.Follow;
private Vector3 posDest; //current destination of camera
private Vector3 offset = new Vector3(0, 5, -10); //offset from target
private Vector3 vel; //current velocity of camera
private float accelCoeff = 10f; //acceleration coefficient
private float ct = 0.5f; //time to reach destination
[Export]
private float rotateSpeed = 2f; //radians per second
[Export]
private float mouseSensitivity = 0.005f;
private bool midDrag = false;
private enum Mode
{
Follow,
Fixed,
Rotate //rotates around target
}
public override void _Ready()
{
Global.camera = this;
CallDeferred(nameof(InitTarget));
}
private void InitTarget()
{
if (target == null){
target = Global.player;
}
}
public override void _Input(InputEvent @event)
{
if (@event is InputEventMouseButton mb && mb.ButtonIndex == MouseButton.Middle)
{
midDrag = mb.Pressed;
}
else if (@event is InputEventMouseMotion motion && midDrag)
{
// Horizontal orbit
offset = offset.Rotated(Vector3.Up, -motion.Relative.X * mouseSensitivity);
// Vertical orbit around the axis perpendicular to offset in the XZ plane
Vector3 right = Vector3.Up.Cross(offset).Normalized();
if (right.LengthSquared() > 0.001f)
{
Vector3 newOffset = offset.Rotated(right, -motion.Relative.Y * mouseSensitivity);
// Clamp to prevent flipping over top or going below horizontal
float angle = newOffset.AngleTo(Vector3.Up);
if (angle > 0.15f && angle < Mathf.Pi * 0.85f)
offset = newOffset;
}
}
}
public override void _Process(double delta)
{
float rotInput = Input.GetAxis("cam_rotate_cw", "cam_rotate_ccw");
switch (mode){
case Mode.Follow:
case Mode.Rotate:
if (rotInput != 0)
offset = offset.Rotated(Vector3.Up, rotateSpeed * rotInput * (float)delta);
break;
case Mode.Fixed:
break;
}
}
public override void _PhysicsProcess(double delta)
{
if (mode == Mode.Follow){
posDest = target.GlobalPosition + offset;
if (posDest != Position){
Vector3 dir = (posDest - Position).Normalized();
float d = (posDest - Position).Length(); //displacement
//vel = dir * accelCoeff * (float)delta + (posDest - Position) * .1f;
vel = (posDest-Position)/ct; // we want to reach the destination in ct seconds
Position += vel * (float)delta + .5f * accelCoeff * dir * (float)(delta*delta);
}
LookAt(target.GlobalPosition);
}
}
}
|