using System; using System.IO; using Artemis.Core; using Avalonia; using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Platform; using Avalonia.Visuals.Media.Imaging; using RGB.NET.Core; using Color = Avalonia.Media.Color; using Point = Avalonia.Point; using SolidColorBrush = Avalonia.Media.SolidColorBrush; namespace Artemis.UI.Shared { internal class DeviceVisualizerLed { private readonly SolidColorBrush _penBrush; private readonly SolidColorBrush _fillBrush; private readonly Pen _pen; public DeviceVisualizerLed(ArtemisLed led) { Led = led; LedRect = new Rect( Led.RgbLed.Location.X, Led.RgbLed.Location.Y, Led.RgbLed.Size.Width, Led.RgbLed.Size.Height ); _fillBrush = new SolidColorBrush(); _penBrush = new SolidColorBrush(); _pen = new Pen(_penBrush) {LineJoin = PenLineJoin.Round}; CreateLedGeometry(); } public ArtemisLed Led { get; } public Rect LedRect { get; set; } public Geometry? DisplayGeometry { get; private set; } public void DrawBitmap(IDrawingContextImpl drawingContext) { if (Led.Layout?.Image == null || !File.Exists(Led.Layout.Image.LocalPath)) return; try { using Bitmap bitmap = new(Led.Layout.Image.LocalPath); drawingContext.DrawBitmap( bitmap.PlatformImpl, 1, new Rect(bitmap.Size), new Rect(Led.RgbLed.Location.X * 4, Led.RgbLed.Location.Y * 4, Led.RgbLed.Size.Width * 4, Led.RgbLed.Size.Height * 4), BitmapInterpolationMode.HighQuality ); } catch { // ignored } } public void RenderGeometry(DrawingContext drawingContext, bool dimmed) { byte r = Led.RgbLed.Color.GetR(); byte g = Led.RgbLed.Color.GetG(); byte b = Led.RgbLed.Color.GetB(); if (dimmed) { _fillBrush.Color = new Color(50, r, g, b); _penBrush.Color = new Color(100, r, g, b); } else { _fillBrush.Color = new Color(100, r, g, b); _penBrush.Color = new Color(255, r, g, b); } // Render the LED geometry drawingContext.DrawGeometry(_fillBrush, _pen, DisplayGeometry); } public bool HitTest(Point position) { return DisplayGeometry != null && DisplayGeometry.FillContains(position); } private void CreateLedGeometry() { // The minimum required size for geometry to be created if (Led.RgbLed.Size.Width < 2 || Led.RgbLed.Size.Height < 2) return; switch (Led.RgbLed.Shape) { case Shape.Custom: if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad) CreateCustomGeometry(2.0); else CreateCustomGeometry(1.0); break; case Shape.Rectangle: if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad) CreateKeyCapGeometry(); else CreateRectangleGeometry(); break; case Shape.Circle: CreateCircleGeometry(); break; default: throw new ArgumentOutOfRangeException(); } } private void CreateRectangleGeometry() { DisplayGeometry = new RectangleGeometry(new Rect(Led.RgbLed.Location.X + 0.5, Led.RgbLed.Location.Y + 0.5, Led.RgbLed.Size.Width - 1, Led.RgbLed.Size.Height - 1)); } private void CreateCircleGeometry() { DisplayGeometry = new EllipseGeometry(new Rect(Led.RgbLed.Location.X + 0.5, Led.RgbLed.Location.Y + 0.5, Led.RgbLed.Size.Width - 1, Led.RgbLed.Size.Height - 1)); } private void CreateKeyCapGeometry() { DisplayGeometry = new RectangleGeometry(new Rect(Led.RgbLed.Location.X + 1, Led.RgbLed.Location.Y + 1, Led.RgbLed.Size.Width - 2, Led.RgbLed.Size.Height - 2)); } private void CreateCustomGeometry(double deflateAmount) { try { double width = Led.RgbLed.Size.Width - deflateAmount; double height = Led.RgbLed.Size.Height - deflateAmount; Geometry geometry = Geometry.Parse(Led.RgbLed.ShapeData); geometry.Transform = new TransformGroup { Children = new Transforms { new ScaleTransform(width, height), new TranslateTransform(Led.RgbLed.Location.X + deflateAmount / 2, Led.RgbLed.Location.Y + deflateAmount / 2) } }; DisplayGeometry = geometry; } catch (Exception) { CreateRectangleGeometry(); } } } }