From e190059623fa7e087cd92c6f0c0bc8e8661c38c2 Mon Sep 17 00:00:00 2001 From: Robert Date: Sun, 21 May 2023 10:33:15 +0200 Subject: [PATCH] Device visualizer - Only rerender dirty devices --- .../Controls/DeviceVisualizer.cs | 66 +++++++++++-------- .../Controls/DeviceVisualizerLed.cs | 24 ++----- 2 files changed, 41 insertions(+), 49 deletions(-) diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs index 111675973..eca232ba4 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.Linq; @@ -13,6 +12,10 @@ using Avalonia.LogicalTree; using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Threading; +using RGB.NET.Core; +using Color = RGB.NET.Core.Color; +using Point = Avalonia.Point; +using Size = Avalonia.Size; namespace Artemis.UI.Shared; @@ -21,20 +24,20 @@ namespace Artemis.UI.Shared; /// public class DeviceVisualizer : Control { - private const double UpdateFrameRate = 25.0; + private const double UPDATE_FRAME_RATE = 25.0; private readonly List _deviceVisualizerLeds; private readonly DispatcherTimer _timer; private Rect _deviceBounds; private RenderTargetBitmap? _deviceImage; - private List? _dimmedLeds; - private List? _highlightedLeds; private ArtemisDevice? _oldDevice; - + private bool _loading; + private Color[] _previousState = Array.Empty(); + /// public DeviceVisualizer() { - _timer = new DispatcherTimer(DispatcherPriority.Background) {Interval = TimeSpan.FromMilliseconds(1000.0 / UpdateFrameRate)}; + _timer = new DispatcherTimer(DispatcherPriority.Background) {Interval = TimeSpan.FromMilliseconds(1000.0 / UPDATE_FRAME_RATE)}; _deviceVisualizerLeds = new List(); PointerReleased += OnPointerReleased; @@ -77,7 +80,7 @@ public class DeviceVisualizer : Control // Apply device scale using DrawingContext.PushedState scalePush = drawingContext.PushTransform(Matrix.CreateScale(Device.Scale, Device.Scale)); foreach (DeviceVisualizerLed deviceVisualizerLed in _deviceVisualizerLeds) - deviceVisualizerLed.RenderGeometry(drawingContext, false); + deviceVisualizerLed.RenderGeometry(drawingContext); } } finally @@ -112,6 +115,31 @@ public class DeviceVisualizer : Control Clicked?.Invoke(this, e); } + private bool IsDirty() + { + if (Device == null) + return false; + + Color[] state = new Color[Device.RgbDevice.Count()]; + bool difference = _previousState.Length != state.Length; + + // Check all LEDs for differences and copy the colors to a new state + int index = 0; + foreach (Led led in Device.RgbDevice) + { + if (!difference && !led.Color.Equals(_previousState[index])) + difference = true; + + state[index] = led.Color; + index++; + } + + // Store the new state for next time + _previousState = state; + + return difference; + } + private void Update() { InvalidateVisual(); @@ -131,7 +159,7 @@ public class DeviceVisualizer : Control private void TimerOnTick(object? sender, EventArgs e) { - if (ShowColors && IsVisible && Opacity > 0) + if (IsDirty() && ShowColors && IsVisible && Opacity > 0) Update(); } @@ -200,23 +228,6 @@ public class DeviceVisualizer : Control set => SetValue(ShowColorsProperty, value); } - /// - /// Gets or sets a list of LEDs to highlight - /// - public static readonly StyledProperty?> HighlightedLedsProperty = - AvaloniaProperty.Register?>(nameof(HighlightedLeds)); - - private bool _loading; - - /// - /// Gets or sets a list of LEDs to highlight - /// - public ObservableCollection? HighlightedLeds - { - get => GetValue(HighlightedLedsProperty); - set => SetValue(HighlightedLedsProperty, value); - } - #endregion #region Lifetime management @@ -254,9 +265,6 @@ public class DeviceVisualizer : Control private void SetupForDevice() { - _highlightedLeds = new List(); - _dimmedLeds = new List(); - lock (_deviceVisualizerLeds) { _deviceVisualizerLeds.Clear(); @@ -305,7 +313,7 @@ public class DeviceVisualizer : Control using DrawingContext context = renderTargetBitmap.CreateDrawingContext(); using Bitmap bitmap = new(device.Layout.Image.LocalPath); using Bitmap scaledBitmap = bitmap.CreateScaledBitmap(renderTargetBitmap.PixelSize); - + context.DrawImage(scaledBitmap, new Rect(scaledBitmap.Size)); lock (_deviceVisualizerLeds) { diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs index 6c69cc674..576dd836d 100644 --- a/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs +++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizerLed.cs @@ -20,13 +20,7 @@ internal class DeviceVisualizerLed 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}; @@ -35,7 +29,6 @@ internal class DeviceVisualizerLed } public ArtemisLed Led { get; } - public Rect LedRect { get; set; } public Geometry? DisplayGeometry { get; private set; } public void DrawBitmap(DrawingContext drawingContext, double scale) @@ -58,7 +51,7 @@ internal class DeviceVisualizerLed } } - public void RenderGeometry(DrawingContext drawingContext, bool dimmed) + public void RenderGeometry(DrawingContext drawingContext) { if (DisplayGeometry == null) return; @@ -66,17 +59,8 @@ internal class DeviceVisualizerLed 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); - } + _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);