using System; using KitsuneCafe.UI.MVVM; using UnityEngine; using UnityEngine.UIElements; namespace KitsuneCafe.UI { public class RotateEvent : EventBase { public Vector2 Delta { get; set; } protected override void Init() { base.Init(); bubbles = true; tricklesDown = true; } } public class ZoomEvent : EventBase { 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(OnAttachToPanel); } private void OnAttachToPanel(AttachToPanelEvent evt) { var root = panel.visualTree; root.RegisterCallback(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 EnableRotationCommand; public readonly ICommand RotateCommand; public readonly ICommand ZoomCommand; private bool isRotating = false; public event EventHandler Rotated; public event EventHandler Zoomed; public PreviewViewModel() { EnableRotationCommand = new RelayCommand(CanEnableRotation, EnableRotation); RotateCommand = new RelayCommand(CanRotate, Rotate); ZoomCommand = new RelayCommand(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)); } } }