Files
parkan-playground/NResUI/Rendering/Viewport/ViewportInputController.cs
T

92 lines
3.0 KiB
C#
Raw Normal View History

2026-06-05 20:33:21 +03:00
using System.Numerics;
using ImGuiNET;
namespace NResUI.Rendering.Viewport;
public sealed class ViewportInputController
{
private const float MouseRotationSpeed = 0.25f;
private const float MouseZoomSpeed = 0.35f;
private bool _isRotatingViewport;
2026-06-05 20:47:57 +03:00
private bool _isPanningViewport;
2026-06-05 20:33:21 +03:00
public void Handle(
ViewportScene scene,
ViewportCamera camera,
bool viewportHovered,
2026-06-05 20:47:57 +03:00
bool viewportFocused,
2026-06-05 20:33:21 +03:00
Vector2 imageMin,
Vector2 imageSize)
{
var io = ImGui.GetIO();
2026-06-05 20:47:57 +03:00
var wantsPanWithMiddle = io.KeyAlt && ImGui.IsMouseClicked(ImGuiMouseButton.Middle);
var wantsPanWithRight = ImGui.IsMouseClicked(ImGuiMouseButton.Right);
if (viewportHovered && wantsPanWithMiddle)
_isPanningViewport = true;
else if (viewportHovered && ImGui.IsMouseClicked(ImGuiMouseButton.Middle))
2026-06-05 20:33:21 +03:00
_isRotatingViewport = true;
2026-06-05 20:47:57 +03:00
if (viewportHovered && wantsPanWithRight)
_isPanningViewport = true;
2026-06-05 20:33:21 +03:00
if (!ImGui.IsMouseDown(ImGuiMouseButton.Middle))
_isRotatingViewport = false;
2026-06-05 20:47:57 +03:00
if (!ImGui.IsMouseDown(ImGuiMouseButton.Right) && !(io.KeyAlt && ImGui.IsMouseDown(ImGuiMouseButton.Middle)))
_isPanningViewport = false;
2026-06-05 20:33:21 +03:00
if (_isRotatingViewport)
{
2026-06-05 20:47:57 +03:00
camera.YawDegrees += -io.MouseDelta.X * MouseRotationSpeed;
2026-06-05 20:33:21 +03:00
camera.PitchDegrees += io.MouseDelta.Y * MouseRotationSpeed;
camera.PitchDegrees = Math.Clamp(camera.PitchDegrees, -89.0f, 89.0f);
}
2026-06-05 20:47:57 +03:00
if (_isPanningViewport)
camera.Pan(io.MouseDelta, imageSize);
2026-06-05 20:33:21 +03:00
if (viewportHovered && Math.Abs(io.MouseWheel) > float.Epsilon)
{
2026-06-05 20:47:57 +03:00
camera.Distance -= io.MouseWheel * MouseZoomSpeed * MathF.Max(1.0f, camera.Distance * 0.15f);
camera.Distance = Math.Clamp(camera.Distance, 0.25f, 400.0f);
2026-06-05 20:33:21 +03:00
}
if (viewportHovered && ImGui.IsMouseClicked(ImGuiMouseButton.Left))
{
var mouse = ImGui.GetMousePos();
var localMouse = mouse - imageMin;
scene.SelectedPieceId = ViewportSelection.PickPiece(
scene,
camera,
localMouse,
imageSize);
}
2026-06-05 20:47:57 +03:00
if (viewportFocused || viewportHovered)
HandleKeyboardShortcuts(scene, camera);
}
private static void HandleKeyboardShortcuts(ViewportScene scene, ViewportCamera camera)
{
if (ImGui.IsKeyPressed(ImGuiKey.F))
{
if (scene.TryGetSelectedPieceWorldBounds(out var selectedBounds))
camera.FrameBounds(selectedBounds.Min, selectedBounds.Max);
else if (scene.TryGetSceneWorldBounds(out var sceneBounds))
camera.FrameBounds(sceneBounds.Min, sceneBounds.Max);
}
if (ImGui.IsKeyPressed(ImGuiKey.Home))
{
if (scene.TryGetSceneWorldBounds(out var sceneBounds))
camera.FrameBounds(sceneBounds.Min, sceneBounds.Max);
else
camera.Reset();
}
2026-06-05 20:33:21 +03:00
}
}