Files
parkan-playground/NResUI/Rendering/Viewport/ViewportInputController.cs
T
2026-06-10 02:01:41 +03:00

94 lines
3.1 KiB
C#

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;
private bool _isPanningViewport;
public void Handle(
ViewportRenderer renderer,
ViewportScene scene,
ViewportCamera camera,
bool viewportHovered,
bool viewportFocused,
Vector2 imageMin,
Vector2 imageSize)
{
var io = ImGui.GetIO();
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))
_isRotatingViewport = true;
if (viewportHovered && wantsPanWithRight)
_isPanningViewport = true;
if (!ImGui.IsMouseDown(ImGuiMouseButton.Middle))
_isRotatingViewport = false;
if (!ImGui.IsMouseDown(ImGuiMouseButton.Right) && !(io.KeyAlt && ImGui.IsMouseDown(ImGuiMouseButton.Middle)))
_isPanningViewport = false;
if (_isRotatingViewport)
{
camera.YawDegrees += -io.MouseDelta.X * MouseRotationSpeed;
camera.PitchDegrees += io.MouseDelta.Y * MouseRotationSpeed;
camera.PitchDegrees = Math.Clamp(camera.PitchDegrees, -89.0f, 89.0f);
}
if (_isPanningViewport)
camera.Pan(io.MouseDelta, imageSize);
if (viewportHovered && Math.Abs(io.MouseWheel) > float.Epsilon)
{
camera.Distance -= io.MouseWheel * MouseZoomSpeed * MathF.Max(1.0f, camera.Distance * 0.15f);
camera.Distance = Math.Clamp(camera.Distance, 0.25f, 400.0f);
}
if (viewportHovered && ImGui.IsMouseClicked(ImGuiMouseButton.Left))
{
var mouse = ImGui.GetMousePos();
var localMouse = mouse - imageMin;
scene.SelectedPieceId = renderer.PickPiece(
Math.Max(1, (int)imageSize.X),
Math.Max(1, (int)imageSize.Y),
scene,
camera,
localMouse);
}
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();
}
}
}