Files
Workspace/Assets/Demos/Demo2/Runtime/Demo2GridInput.cs
T
2026-08-18 02:03:34 +08:00

87 lines
3.5 KiB
C#

#nullable enable
using System;
using Demo2.Domain;
using UnityEngine;
using UnityEngine.UIElements;
namespace Demo2.Runtime
{
public sealed class Demo2GridInput : IDisposable
{
private readonly VisualElement _surface;
private readonly Camera _worldCamera;
private bool _middleDragging;
public event Action<int, int, int>? GridClicked;
public Demo2GridInput(VisualElement surface, Camera worldCamera)
{
_surface = surface;
_worldCamera = worldCamera;
_surface.RegisterCallback<PointerDownEvent>(OnPointerDown);
_surface.RegisterCallback<PointerUpEvent>(OnPointerUp);
_surface.RegisterCallback<PointerMoveEvent>(OnPointerMove);
_surface.RegisterCallback<WheelEvent>(OnWheel);
}
public void Dispose()
{
_surface.UnregisterCallback<PointerDownEvent>(OnPointerDown);
_surface.UnregisterCallback<PointerUpEvent>(OnPointerUp);
_surface.UnregisterCallback<PointerMoveEvent>(OnPointerMove);
_surface.UnregisterCallback<WheelEvent>(OnWheel);
}
private void OnPointerDown(PointerDownEvent eventData)
{
if (eventData.button == 2)
{
_middleDragging = true;
_surface.CapturePointer(eventData.pointerId);
eventData.StopPropagation();
return;
}
if (eventData.button is not (0 or 1)) return;
var world = _worldCamera.ScreenToWorldPoint(PanelToScreen(eventData.position));
var x = Mathf.FloorToInt(world.x);
var y = Demo2Protocol.GridHeight - 1 - Mathf.FloorToInt(world.y);
if (x >= 0 && x < Demo2Protocol.GridWidth && y >= 0 && y < Demo2Protocol.GridHeight) GridClicked?.Invoke(x, y, eventData.button);
eventData.StopPropagation();
}
private void OnPointerUp(PointerUpEvent eventData)
{
if (eventData.button != 2) return;
_middleDragging = false;
if (_surface.HasPointerCapture(eventData.pointerId)) _surface.ReleasePointer(eventData.pointerId);
eventData.StopPropagation();
}
private void OnPointerMove(PointerMoveEvent eventData)
{
if (!_middleDragging) return;
var scale = _worldCamera.orthographicSize * 2f / Mathf.Max(1, _surface.resolvedStyle.height);
var position = _worldCamera.transform.position;
position -= new Vector3(eventData.deltaPosition.x, -eventData.deltaPosition.y) * scale;
position.x = Mathf.Clamp(position.x, 4f, Demo2Protocol.GridWidth - 4f);
position.y = Mathf.Clamp(position.y, 3f, Demo2Protocol.GridHeight - 3f);
_worldCamera.transform.position = position;
eventData.StopPropagation();
}
private void OnWheel(WheelEvent eventData)
{
_worldCamera.orthographicSize = Mathf.Clamp(_worldCamera.orthographicSize + eventData.delta.y * 0.7f, 5f, 15f);
eventData.StopPropagation();
}
private Vector3 PanelToScreen(Vector3 panelPosition)
{
var root = _surface.panel?.visualTree;
var width = Mathf.Max(1, root?.resolvedStyle.width ?? Screen.width);
var height = Mathf.Max(1, root?.resolvedStyle.height ?? Screen.height);
return new Vector3(panelPosition.x / width * Screen.width, Screen.height - panelPosition.y / height * Screen.height, 0);
}
}
}