using System; using System.Collections.Generic; using System.Linq; using System.Windows.Input; using Artemis.Core; using Artemis.Core.Services; using RGB.NET.Core; using SkiaSharp; using Stylet; using Point = System.Windows.Point; namespace Artemis.UI.Screens.SurfaceEditor.Visualization { public class SurfaceDeviceViewModel : PropertyChangedBase { private readonly IRgbService _rgbService; private readonly ISettingsService _settingsService; private Cursor _cursor; private double _dragOffsetX; private double _dragOffsetY; private SelectionStatus _selectionStatus; public SurfaceDeviceViewModel(ArtemisDevice device, IRgbService rgbService, ISettingsService settingsService) { Device = device; _rgbService = rgbService; _settingsService = settingsService; } public ArtemisDevice Device { get; } public SelectionStatus SelectionStatus { get => _selectionStatus; set => SetAndNotify(ref _selectionStatus, value); } public bool CanDetectInput => Device.DeviceType == RGBDeviceType.Keyboard || Device.DeviceType == RGBDeviceType.Mouse; public Cursor Cursor { get => _cursor; set => SetAndNotify(ref _cursor, value); } public void StartMouseDrag(Point mouseStartPosition) { _dragOffsetX = Device.X - mouseStartPosition.X; _dragOffsetY = Device.Y - mouseStartPosition.Y; } public void UpdateMouseDrag(Point mousePosition) { float roundedX = (float) Math.Round((mousePosition.X + _dragOffsetX) / 10d, 0, MidpointRounding.AwayFromZero) * 10f; float roundedY = (float) Math.Round((mousePosition.Y + _dragOffsetY) / 10d, 0, MidpointRounding.AwayFromZero) * 10f; if (Fits(roundedX, roundedY)) { Device.X = roundedX; Device.Y = roundedY; } else if (Fits(roundedX, (float) Device.Y)) { Device.X = roundedX; } else if (Fits((float) Device.X, roundedY)) { Device.Y = roundedY; } } // ReSharper disable once UnusedMember.Global - Called from view public void MouseEnter(object sender, MouseEventArgs e) { if (SelectionStatus == SelectionStatus.None) { SelectionStatus = SelectionStatus.Hover; Cursor = Cursors.Hand; } } // ReSharper disable once UnusedMember.Global - Called from view public void MouseLeave() { if (SelectionStatus == SelectionStatus.Hover) { SelectionStatus = SelectionStatus.None; Cursor = Cursors.Arrow; } } public MouseDevicePosition GetMouseDevicePosition(Point position) { if ((new Point(0, 0) - position).LengthSquared < 5) return MouseDevicePosition.TopLeft; return MouseDevicePosition.Regular; } private bool Fits(float x, float y) { if (x < 0 || y < 0) return false; double maxTextureSize = 4096 / _settingsService.GetSetting("Core.RenderScale", 0.25).Value; if (x + Device.Rectangle.Width > maxTextureSize || y + Device.Rectangle.Height > maxTextureSize) return false; List own = Device.Leds .Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height)) .ToList(); List others = _rgbService.EnabledDevices .Where(d => d != Device && d.IsEnabled) .SelectMany(d => d.Leds) .Select(l => SKRect.Create(l.Rectangle.Left + (float) l.Device.X, l.Rectangle.Top + (float) l.Device.Y, l.Rectangle.Width, l.Rectangle.Height)) .ToList(); return !own.Any(o => others.Any(l => l.IntersectsWith(o))); } } public enum MouseDevicePosition { Regular, TopLeft, TopRight, BottomLeft, BottomRight } public enum SelectionStatus { None, Hover, Selected } }