diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj
index b6cf25e6d..ed6e16421 100644
--- a/src/Artemis.Core/Artemis.Core.csproj
+++ b/src/Artemis.Core/Artemis.Core.csproj
@@ -43,9 +43,9 @@
-
-
-
+
+
+
diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs
index fb304baf5..964f5b0dd 100644
--- a/src/Artemis.Core/Services/PluginManagementService.cs
+++ b/src/Artemis.Core/Services/PluginManagementService.cs
@@ -396,7 +396,7 @@ internal class PluginManagementService : IPluginManagementService
List featureTypes;
try
{
- featureTypes = plugin.Assembly.GetTypes().Where(t => typeof(PluginFeature).IsAssignableFrom(t)).ToList();
+ featureTypes = plugin.Assembly.GetTypes().Where(t => typeof(PluginFeature).IsAssignableFrom(t) && !t.IsAbstract).ToList();
}
catch (ReflectionTypeLoadException e)
{
diff --git a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
index c297f372f..0c4439627 100644
--- a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
+++ b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs
index 3d8a3192e..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.Render) {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);
diff --git a/src/Artemis.UI.Shared/Controls/DraggableNumberBox.axaml b/src/Artemis.UI.Shared/Controls/DraggableNumberBox.axaml
index 8322b5738..0c571239e 100644
--- a/src/Artemis.UI.Shared/Controls/DraggableNumberBox.axaml
+++ b/src/Artemis.UI.Shared/Controls/DraggableNumberBox.axaml
@@ -32,8 +32,7 @@
SimpleNumberFormat="{CompiledBinding $parent[sharedControls:DraggableNumberBox].SimpleNumberFormat}"
attachedProperties:NumberBoxAssist.PrefixText="{CompiledBinding $parent[sharedControls:DraggableNumberBox].Prefix}"
attachedProperties:NumberBoxAssist.SuffixText="{CompiledBinding $parent[sharedControls:DraggableNumberBox].Suffix}"
- HorizontalAlignment="{CompiledBinding $parent[sharedControls:DraggableNumberBox].HorizontalAlignment}"
- ValueChanged="NumberBox_OnValueChanged"/>
+ HorizontalAlignment="{CompiledBinding $parent[sharedControls:DraggableNumberBox].HorizontalAlignment}"/>
diff --git a/src/Artemis.UI.Shared/Controls/DraggableNumberBox.axaml.cs b/src/Artemis.UI.Shared/Controls/DraggableNumberBox.axaml.cs
index 663a76a13..1b3124421 100644
--- a/src/Artemis.UI.Shared/Controls/DraggableNumberBox.axaml.cs
+++ b/src/Artemis.UI.Shared/Controls/DraggableNumberBox.axaml.cs
@@ -4,7 +4,7 @@ using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
-using Avalonia.Markup.Xaml;
+using Avalonia.LogicalTree;
using Avalonia.VisualTree;
using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls;
@@ -68,13 +68,12 @@ public partial class DraggableNumberBox : UserControl
public DraggableNumberBox()
{
InitializeComponent();
- InnerNumberBox.Value = Value;
-
+
PointerPressed += OnPointerPressed;
PointerMoved += OnPointerMoved;
PointerReleased += OnPointerReleased;
PropertyChanged += OnPropertyChanged;
-
+
AddHandler(KeyUpEvent, HandleKeyUp, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true);
}
@@ -159,7 +158,22 @@ public partial class DraggableNumberBox : UserControl
/// Occurs when the user finishes dragging over the control.
///
public event TypedEventHandler? DragFinished;
-
+
+ ///
+ protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
+ {
+ InnerNumberBox.Value = Value;
+ InnerNumberBox.ValueChanged += InnerNumberBoxOnValueChanged;
+ base.OnAttachedToLogicalTree(e);
+ }
+
+ ///
+ protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
+ {
+ InnerNumberBox.ValueChanged -= InnerNumberBoxOnValueChanged;
+ base.OnDetachedFromLogicalTree(e);
+ }
+
private void SetNumberBoxValue(double value)
{
if (!(Math.Abs(InnerNumberBox.Value - Value) > 0.00001))
@@ -243,14 +257,14 @@ public partial class DraggableNumberBox : UserControl
e.Handled = true;
}
-
+
private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == ValueProperty)
SetNumberBoxValue(Value);
}
- private void NumberBox_OnValueChanged(NumberBox sender, NumberBoxValueChangedEventArgs args)
+ private void InnerNumberBoxOnValueChanged(NumberBox sender, NumberBoxValueChangedEventArgs args)
{
if (_updating)
return;
diff --git a/src/Artemis.UI.Shared/Services/Builders/OpenFileDialogBuilder.cs b/src/Artemis.UI.Shared/Services/Builders/OpenFileDialogBuilder.cs
index 616b7977a..c9ef09d65 100644
--- a/src/Artemis.UI.Shared/Services/Builders/OpenFileDialogBuilder.cs
+++ b/src/Artemis.UI.Shared/Services/Builders/OpenFileDialogBuilder.cs
@@ -78,6 +78,6 @@ public class OpenFileDialogBuilder
public async Task ShowAsync()
{
IReadOnlyList files = await _parent.StorageProvider.OpenFilePickerAsync(_options);
- return files.Select(f => f.Path.LocalPath).ToArray();
+ return files.Count == 0 ? null : files.Select(f => f.Path.LocalPath).ToArray();
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Services/PropertyInput/PropertyInputViewModel.cs b/src/Artemis.UI.Shared/Services/PropertyInput/PropertyInputViewModel.cs
index 1382de03b..ede68d21f 100644
--- a/src/Artemis.UI.Shared/Services/PropertyInput/PropertyInputViewModel.cs
+++ b/src/Artemis.UI.Shared/Services/PropertyInput/PropertyInputViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reactive.Disposables;
using System.Reactive.Linq;
@@ -193,7 +194,7 @@ public abstract class PropertyInputViewModel : PropertyInputViewModel
_updating = true;
// Avoid unnecessary UI updates and validator cycles
- if (Equals(_inputValue, LayerProperty.CurrentValue))
+ if (EqualityComparer.Default.Equals(_inputValue, LayerProperty.CurrentValue))
return;
// Override the input value
diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj
index 054ca5857..ce2eaaf18 100644
--- a/src/Artemis.UI/Artemis.UI.csproj
+++ b/src/Artemis.UI/Artemis.UI.csproj
@@ -32,8 +32,8 @@
-
-
+
+
diff --git a/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml b/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml
index 37234283e..22b63510e 100644
--- a/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml
+++ b/src/Artemis.UI/Screens/Device/DevicePropertiesView.axaml
@@ -30,12 +30,12 @@
-
diff --git a/src/Artemis.UI/Screens/Device/DeviceSettingsView.axaml b/src/Artemis.UI/Screens/Device/DeviceSettingsView.axaml
index 064ea7154..e3157ba28 100644
--- a/src/Artemis.UI/Screens/Device/DeviceSettingsView.axaml
+++ b/src/Artemis.UI/Screens/Device/DeviceSettingsView.axaml
@@ -18,7 +18,7 @@
Margin="10"
ShowColors="False"
Device="{CompiledBinding Device}"
- RenderOptions.BitmapInterpolationMode="HighQuality" />
+ RenderOptions.BitmapInterpolationMode="MediumQuality" />