ported from perforce

This commit is contained in:
2026-04-19 00:43:27 +02:00
commit 6c0c33f5d4
700 changed files with 19735 additions and 0 deletions

View File

@@ -0,0 +1,258 @@
using Godot;
public partial class BoardCameraController : Camera3D
{
public override void _Ready()
{
InitBoardBounds();
InitOrbit();
}
private void InitBoardBounds()
{
if (HexBoard != null && HexBoard.BoardBounds.Size != Vector2.Zero)
{
m_BoardRect = HexBoard.BoardBounds;
var center2D = m_BoardRect.Position + m_BoardRect.Size * 0.5f;
m_TargetPosition = new(center2D.X - 1, 0f, center2D.Y + 3);
}
else
{
m_BoardRect = new(-10, -10, 20, 20);
m_TargetPosition = new(-1, 0f, 3);
}
var radius = Mathf.Max(m_BoardRect.Size.X, m_BoardRect.Size.Y) * 0.5f;
m_MinDistance = MinZoomDistance;
m_MaxDistance = Mathf.Max(m_MinDistance * 2f, radius * MaxZoomOutFactor);
}
private void InitOrbit()
{
var startYawRad = GlobalTransform.Basis.GetEuler().Y;
var startYawDeg = Mathf.RadToDeg(startYawRad);
m_RotationIndex = Mathf.PosMod(Mathf.RoundToInt(startYawDeg / 60f), 6);
m_YawDegrees = m_RotationIndex * 60f;
m_Distance = (m_MaxDistance - m_MinDistance) * 0.75f + m_MinDistance;
UpdateTransformFromOrbit();
if (HexBoard != null)
HexBoard.SetCameraRotationIndex(m_RotationIndex);
}
private void UpdateTransformFromOrbit()
{
var pitchRad = Mathf.DegToRad(PitchDegrees);
var yawRad = Mathf.DegToRad(m_YawDegrees);
var horizontal = m_Distance * Mathf.Cos(pitchRad);
var height = m_Distance * Mathf.Sin(pitchRad);
var offset = new Vector3(Mathf.Sin(yawRad) * horizontal, height, Mathf.Cos(yawRad) * horizontal);
GlobalPosition = m_TargetPosition + offset;
LookAt(m_TargetPosition, Vector3.Up);
}
public override void _Process(double delta)
{
var dt = (float)delta;
HandleRotationInput(dt);
HandleMovementInput(dt);
HandleZoomInput(dt);
}
public override void _UnhandledInput(InputEvent @event)
{
if (@event is InputEventMouseButton mb && mb.Pressed)
{
if (mb.ButtonIndex == MouseButton.WheelUp)
m_PendingWheelSteps -= 1f;
else if (mb.ButtonIndex == MouseButton.WheelDown)
m_PendingWheelSteps += 1f;
}
}
private void HandleMovementInput(float delta)
{
var input = Vector2.Zero;
input.Y -= Input.GetActionStrength("camera_move_forward");
input.Y += Input.GetActionStrength("camera_move_back");
input.X -= Input.GetActionStrength("camera_move_left");
input.X += Input.GetActionStrength("camera_move_right");
if (input.LengthSquared() < 0.0001f)
return;
var yawRad = Mathf.DegToRad(m_YawDegrees);
var forward = new Vector2(Mathf.Sin(yawRad), Mathf.Cos(yawRad));
var right = new Vector2(forward.Y, -forward.X);
var worldDir = right * input.X + forward * input.Y;
var deltaPos = worldDir * MoveSpeed * delta;
m_TargetPosition.X += deltaPos.X;
m_TargetPosition.Z += deltaPos.Y;
ClampTargetToBoard();
UpdateTransformFromOrbit();
}
private void HandleZoomInput(float delta)
{
var zoomDelta = 0f;
var axis = Input.GetActionStrength("camera_zoom_out") - Input.GetActionStrength("camera_zoom_in");
if (Mathf.Abs(axis) > 0.001f)
zoomDelta += axis * PadZoomSpeed * delta;
if (Mathf.Abs(m_PendingWheelSteps) > 0.001f)
{
zoomDelta += m_PendingWheelSteps * WheelZoomStep;
m_PendingWheelSteps = 0f;
}
if (Mathf.Abs(zoomDelta) < 0.0001f)
return;
m_Distance = Mathf.Clamp(m_Distance + zoomDelta, m_MinDistance, m_MaxDistance);
UpdateTransformFromOrbit();
}
private void HandleRotationInput(float delta)
{
if (Input.IsActionJustPressed("camera_rotate_left"))
QueueRotate(-1);
if (Input.IsActionJustPressed("camera_rotate_right"))
QueueRotate(+1);
var axis = Input.GetActionStrength("camera_rotate_right") - Input.GetActionStrength("camera_rotate_left");
var axisDir = 0;
if (axis > GamepadDeadZone)
axisDir = +1;
else if (axis < -GamepadDeadZone)
axisDir = -1;
if (axisDir != 0)
{
if (m_RotateAxisDir != axisDir)
{
m_RotateAxisDir = axisDir;
m_RotateAxisTimer = 0f;
QueueRotate(axisDir);
}
else
{
m_RotateAxisTimer += delta;
if (m_RotateAxisTimer >= GamepadRotateRepeatDelay)
{
m_RotateAxisTimer = 0f;
QueueRotate(axisDir);
}
}
}
else
{
m_RotateAxisDir = 0;
m_RotateAxisTimer = 0f;
}
}
private void QueueRotate(int steps)
{
if (steps == 0 || m_RotationTween != null)
return;
m_RotationIndex = Mathf.PosMod(m_RotationIndex + steps, 6);
var targetYaw = m_RotationIndex * 60f;
var current = m_YawDegrees;
var deltaYaw = Mathf.Wrap(targetYaw - current, -180f, 180f);
targetYaw = current + deltaYaw;
HexBoard?.SetCameraRotationIndex(m_RotationIndex);
m_RotationTween = CreateTween();
m_RotationTween.SetTrans(Tween.TransitionType.Back);
m_RotationTween.SetEase(Tween.EaseType.Out);
m_RotationTween.TweenProperty(this, nameof(YawDegrees), targetYaw, RotationDuration);
m_RotationTween.TweenCallback(Callable.From(() =>
{
YawDegrees = m_RotationIndex * 60f;
m_RotationTween = null;
}));
}
private void ClampTargetToBoard()
{
if (m_BoardRect.Size == Vector2.Zero)
return;
var minX = m_BoardRect.Position.X;
var maxX = m_BoardRect.Position.X + m_BoardRect.Size.X;
var minZ = m_BoardRect.Position.Y;
var maxZ = m_BoardRect.Position.Y + m_BoardRect.Size.Y;
m_TargetPosition.X = Mathf.Clamp(m_TargetPosition.X, minX, maxX);
m_TargetPosition.Z = Mathf.Clamp(m_TargetPosition.Z, minZ, maxZ);
}
public float YawDegrees
{
get => m_YawDegrees;
set
{
m_YawDegrees = value;
UpdateTransformFromOrbit();
}
}
[Export]
public HexBoard3D HexBoard { get; set; }
[Export]
public float GamepadDeadZone = 0.4f;
[Export]
public float GamepadRotateRepeatDelay = 1.0f;
[Export]
public float MaxZoomOutFactor = 2.2f;
[ExportCategory("Zoom")]
[Export]
public float MinZoomDistance = 8f;
[ExportCategory("Movement")]
[Export]
public float MoveSpeed = 10f;
[Export]
public float PadZoomSpeed = 40f;
[ExportCategory("Rotation")]
[Export]
public float PitchDegrees = 60f;
[Export]
public float RotationDuration = 0.35f;
[Export]
public float WheelZoomStep = 3f;
private Rect2 m_BoardRect;
private float m_Distance;
private float m_MaxDistance;
private float m_MinDistance;
private float m_PendingWheelSteps;
private int m_RotateAxisDir;
private float m_RotateAxisTimer;
private int m_RotationIndex;
private Tween m_RotationTween;
private Vector3 m_TargetPosition = new(-1, 0f, 3);
private float m_YawDegrees;
}