87 lines
3.5 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|