canto/Assets/Scripts/UI/Elements/Preview.cs
2025-08-16 16:17:16 -04:00

138 lines
3.1 KiB
C#

using System;
using KitsuneCafe.UI.MVVM;
using UnityEngine;
using UnityEngine.UIElements;
namespace KitsuneCafe.UI
{
public class RotateEvent : EventBase<RotateEvent>
{
public Vector2 Delta { get; set; }
protected override void Init()
{
base.Init();
bubbles = true;
tricklesDown = true;
}
}
public class ZoomEvent : EventBase<ZoomEvent>
{
public float Amount { get; set; }
protected override void Init()
{
base.Init();
bubbles = true;
tricklesDown = true;
}
}
[UxmlElement]
public partial class PreviewView : VisualElement
{
public const string BaseClass = "kitsunecafe__preview";
private readonly PreviewViewModel viewModel = new();
private readonly DragManipulator drag;
public PreviewView()
{
AddToClassList(BaseClass);
drag = new DragManipulator(this);
drag.Started += () => viewModel.EnableRotationCommand.TryExecute(true);
drag.Stopped += () => viewModel.EnableRotationCommand.TryExecute(false);
drag.Dragged += delta => viewModel.RotateCommand.TryExecute(delta);
this.AddManipulator(drag);
RegisterCallback<AttachToPanelEvent>(OnAttachToPanel);
}
private void OnAttachToPanel(AttachToPanelEvent evt)
{
var root = panel.visualTree;
root.RegisterCallback<WheelEvent>(OnMouseWheel);
viewModel.Rotated += OnRotate;
viewModel.Zoomed += OnZoom;
}
private void OnRotate(object sender, PreviewViewModel.RotateEvent e)
{
using RotateEvent ev = RotateEvent.GetPooled();
ev.target = this;
ev.Delta = e.Rotation;
SendEvent(ev);
}
private void OnZoom(object sender, PreviewViewModel.ZoomEvent e)
{
using ZoomEvent ev = ZoomEvent.GetPooled();
ev.target = this;
ev.Amount = e.Amount;
SendEvent(ev);
}
private void OnMouseWheel(WheelEvent evt)
{
viewModel.ZoomCommand.TryExecute(evt.delta.y);
}
}
public class PreviewViewModel
{
public record RotateEvent(Vector2 Rotation);
public record ZoomEvent(float Amount);
public readonly ICommand<bool> EnableRotationCommand;
public readonly ICommand<Vector2> RotateCommand;
public readonly ICommand<float> ZoomCommand;
private bool isRotating = false;
public event EventHandler<RotateEvent> Rotated;
public event EventHandler<ZoomEvent> Zoomed;
public PreviewViewModel()
{
EnableRotationCommand = new RelayCommand<bool>(CanEnableRotation, EnableRotation);
RotateCommand = new RelayCommand<Vector2>(CanRotate, Rotate);
ZoomCommand = new RelayCommand<float>(CanZoom, Zoom);
}
private void EnableRotation(bool enabled)
{
isRotating = enabled;
}
private bool CanEnableRotation(bool _enabled)
{
return true;
}
public bool CanRotate(Vector2 _delta)
{
return isRotating;
}
private void Rotate(Vector2 delta)
{
Rotated?.Invoke(this, new RotateEvent(delta));
}
private bool CanZoom(float value)
{
return true;
}
private void Zoom(float value)
{
Zoomed?.Invoke(this, new ZoomEvent(value));
}
}
}