1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 21:38:38 +00:00

Core - Refactored layout loading, fixing LED images

Core - Make a better effort at removing orphaned devices from device providers that failed to load
This commit is contained in:
Robert 2023-10-16 19:44:13 +02:00
parent 38f18613c1
commit 43e396bf6d
10 changed files with 111 additions and 124 deletions

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using Artemis.Core.DeviceProviders;
using Artemis.Storage.Entities.Surface;
@ -22,6 +23,7 @@ public class ArtemisDevice : CorePropertyChanged
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider)
{
Debug.WriteLine("Creating Artemis device for " + rgbDevice.DeviceInfo.DeviceName);
rgbDevice.EnsureValidDimensions();
_originalLeds = new List<OriginalLed>(rgbDevice.Select(l => new OriginalLed(l)));
_originalSize = rgbDevice.Size;
@ -48,7 +50,7 @@ public class ArtemisDevice : CorePropertyChanged
RgbDevice.ColorCorrections.Clear();
RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this));
UpdateLeds(false);
CreateArtemisLeds(false);
ApplyKeyboardLayout();
CalculateRenderProperties();
Save();
@ -58,6 +60,7 @@ public class ArtemisDevice : CorePropertyChanged
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, DeviceEntity deviceEntity)
{
Debug.WriteLine("Creating Artemis device for " + rgbDevice.DeviceInfo.DeviceName);
rgbDevice.EnsureValidDimensions();
_originalLeds = new List<OriginalLed>(rgbDevice.Select(l => new OriginalLed(l)));
_originalSize = rgbDevice.Size;
@ -79,7 +82,7 @@ public class ArtemisDevice : CorePropertyChanged
RgbDevice.ColorCorrections.Clear();
RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this));
UpdateLeds(false);
CreateArtemisLeds(false);
Load();
ApplyKeyboardLayout();
CalculateRenderProperties();
@ -475,30 +478,28 @@ public class ArtemisDevice : CorePropertyChanged
/// </param>
internal void ApplyLayout(ArtemisLayout? layout, bool createMissingLeds, bool removeExcessiveLeds)
{
if (layout == null)
{
ClearLayout();
UpdateLeds(true);
if (layout != null && layout.IsValid && createMissingLeds && !DeviceProvider.CreateMissingLedsSupported)
throw new ArtemisCoreException($"Cannot apply layout with {nameof(createMissingLeds)} set to true because the device provider does not support it");
if (layout != null && layout.IsValid && removeExcessiveLeds && !DeviceProvider.RemoveExcessiveLedsSupported)
throw new ArtemisCoreException($"Cannot apply layout with {nameof(removeExcessiveLeds)} set to true because the device provider does not support it");
CalculateRenderProperties();
return;
// Always clear the current layout
ClearLayout();
// If a valid layout was supplied, apply the layout to the device
if (layout != null && layout.IsValid)
{
layout.ApplyToDevice(RgbDevice, createMissingLeds, removeExcessiveLeds);
Layout = layout;
}
else
{
Layout = null;
}
if (createMissingLeds && !DeviceProvider.CreateMissingLedsSupported)
throw new ArtemisCoreException($"Cannot apply layout with {nameof(createMissingLeds)} " +
"set to true because the device provider does not support it");
if (removeExcessiveLeds && !DeviceProvider.RemoveExcessiveLedsSupported)
throw new ArtemisCoreException($"Cannot apply layout with {nameof(removeExcessiveLeds)} " +
"set to true because the device provider does not support it");
ClearLayout();
if (layout.IsValid)
layout.ApplyTo(RgbDevice, createMissingLeds, removeExcessiveLeds);
UpdateLeds(true);
Layout = layout;
Layout.ApplyDevice(this);
// Recreate Artemis LEDs
CreateArtemisLeds(true);
// Calculate render properties with the new layout
CalculateRenderProperties();
}
@ -569,7 +570,7 @@ public class ArtemisDevice : CorePropertyChanged
OnDeviceUpdated();
}
private void UpdateLeds(bool loadInputMappings)
private void CreateArtemisLeds(bool loadInputMappings)
{
Leds = RgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l));
@ -578,6 +579,12 @@ public class ArtemisDevice : CorePropertyChanged
LoadInputMappings();
}
private void UpdateArtemisLeds()
{
foreach (ArtemisLed artemisLed in Leds)
artemisLed.CalculateRectangles();
}
private void LoadInputMappings()
{
InputMappings.Clear();
@ -624,7 +631,7 @@ public class ArtemisDevice : CorePropertyChanged
RgbDevice.Location = new Point(1, 1);
RgbDevice.Location = new Point(x, y);
UpdateLeds(false);
UpdateArtemisLeds();
CalculateRenderProperties();
}
}

View File

@ -1,4 +1,5 @@
using RGB.NET.Core;
using System.Linq;
using RGB.NET.Core;
using SkiaSharp;
namespace Artemis.Core;
@ -15,6 +16,9 @@ public class ArtemisLed : CorePropertyChanged
{
RgbLed = led;
Device = device;
Layout = device.Layout?.Leds.FirstOrDefault(l => l.RgbLayout.Id == led.Id.ToString());
Layout?.ApplyCustomLedData(Device);
CalculateRectangles();
}

View File

@ -36,11 +36,6 @@ public class ArtemisLayout
/// </summary>
public LayoutSource Source { get; }
/// <summary>
/// Gets the device this layout is applied to
/// </summary>
public ArtemisDevice? Device { get; private set; }
/// <summary>
/// Gets a boolean indicating whether a valid layout was loaded
/// </summary>
@ -69,7 +64,7 @@ public class ArtemisLayout
/// <summary>
/// Applies the layout to the provided device
/// </summary>
public void ApplyTo(IRGBDevice device, bool createMissingLeds = false, bool removeExcessiveLeds = false)
public void ApplyToDevice(IRGBDevice device, bool createMissingLeds = false, bool removeExcessiveLeds = false)
{
device.Size = new Size(MathF.Round(RgbLayout.Width), MathF.Round(RgbLayout.Height));
device.DeviceInfo.LayoutMetadata = RgbLayout.CustomData;
@ -124,13 +119,6 @@ public class ArtemisLayout
}
}
internal void ApplyDevice(ArtemisDevice artemisDevice)
{
Device = artemisDevice;
foreach (ArtemisLedLayout artemisLedLayout in Leds)
artemisLedLayout.ApplyDevice(Device);
}
internal static ArtemisLayout? GetDefaultLayout(ArtemisDevice device)
{
string layoutFolder = Path.Combine(Constants.ApplicationFolder, "DefaultLayouts", "Artemis");

View File

@ -27,11 +27,6 @@ public class ArtemisLedLayout
/// </summary>
public ILedLayout RgbLayout { get; }
/// <summary>
/// Gets the LED this layout is applied to
/// </summary>
public ArtemisLed? Led { get; protected set; }
/// <summary>
/// Gets the name of the logical layout this LED belongs to
/// </summary>
@ -47,16 +42,8 @@ public class ArtemisLedLayout
/// </summary>
public LayoutCustomLedData LayoutCustomLedData { get; }
internal void ApplyDevice(ArtemisDevice device)
{
Led = device.Leds.FirstOrDefault(d => d.RgbLed.Id.ToString() == RgbLayout.Id);
if (Led != null)
Led.Layout = this;
ApplyCustomLedData(device);
}
private void ApplyCustomLedData(ArtemisDevice artemisDevice)
internal void ApplyCustomLedData(ArtemisDevice artemisDevice)
{
if (LayoutCustomLedData.LogicalLayouts == null || !LayoutCustomLedData.LogicalLayouts.Any())
return;

View File

@ -52,11 +52,12 @@ internal class DeviceService : IDeviceService
try
{
// Can't see why this would happen, RgbService used to do this though
List<ArtemisDevice> toRemove = _devices.Where(a => rgbDeviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
List<ArtemisDevice> toRemove = _devices.Where(a => a.DeviceProvider.Id == deviceProvider.Id).ToList();
_logger.Verbose("[AddDeviceProvider] Removing {Count} old device(s)", toRemove.Count);
foreach (ArtemisDevice device in toRemove)
{
_devices.Remove(device);
_enabledDevices.Remove(device);
OnDeviceRemoved(new DeviceEventArgs(device));
}
@ -118,8 +119,7 @@ internal class DeviceService : IDeviceService
public void RemoveDeviceProvider(DeviceProvider deviceProvider)
{
_logger.Verbose("[RemoveDeviceProvider] Pausing rendering to remove {DeviceProvider}", deviceProvider.GetType().Name);
IRGBDeviceProvider rgbDeviceProvider = deviceProvider.RgbDeviceProvider;
List<ArtemisDevice> toRemove = _devices.Where(a => rgbDeviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
List<ArtemisDevice> toRemove = _devices.Where(a => a.DeviceProvider.Id == deviceProvider.Id).ToList();
try
{

View File

@ -21,11 +21,6 @@ public interface IRenderService : IArtemisService
/// </summary>
RGBSurface Surface { get; }
/// <summary>
/// Gets a list of registered renderers.
/// </summary>
List<IRenderer> Renderers { get; }
/// <summary>
/// Gets or sets a boolean indicating whether rendering is paused.
/// </summary>

View File

@ -56,9 +56,6 @@ internal class RenderService : IRenderService, IRenderer, IDisposable
/// <inheritdoc />
public RGBSurface Surface => _surfaceManager.Surface;
/// <inheritdoc />
public List<IRenderer> Renderers { get; } = new();
/// <inheritdoc />
public bool IsPaused
{

View File

@ -123,27 +123,35 @@ public class DeviceVisualizer : Control
if (Device == null)
return false;
bool difference = false;
int newLedCount = Device.RgbDevice.Count();
if (_previousState.Length != newLedCount)
// Device might be modified mid-check, in that case just pretend it was not dirty
try
{
_previousState = new Color[newLedCount];
difference = true;
}
bool difference = false;
// Check all LEDs for differences and copy the colors to a new state
int index = 0;
foreach (Led led in Device.RgbDevice)
{
if (_previousState[index] != led.Color)
int newLedCount = Device.RgbDevice.Count();
if (_previousState.Length != newLedCount)
{
_previousState = new Color[newLedCount];
difference = true;
}
_previousState[index] = led.Color;
index++;
// Check all LEDs for differences and copy the colors to a new state
int index = 0;
foreach (Led led in Device.RgbDevice)
{
if (_previousState[index] != led.Color)
difference = true;
_previousState[index] = led.Color;
index++;
}
return difference;
}
catch (Exception)
{
return false;
}
return difference;
}
private void Update()
@ -335,7 +343,7 @@ public class DeviceVisualizer : Control
deviceVisualizerLed.DrawBitmap(context, 2 * device.Scale);
}
BitmapCache[path] = renderTargetBitmap;
// BitmapCache[path] = renderTargetBitmap;
return renderTargetBitmap;
}

View File

@ -52,7 +52,7 @@
<TextBlock Classes="subtitle" FontSize="12" Text="With this checked, Artemis will not load a layout for this device unless you specifically provide one." />
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center">
<CheckBox HorizontalAlignment="Right" Margin="0,0,-10,0" IsChecked="{CompiledBinding Device.DisableDefaultLayout}" />
<CheckBox HorizontalAlignment="Right" Margin="0,0,-10,0" IsChecked="{CompiledBinding Device.DisableDefaultLayout}"/>
</StackPanel>
</Grid>
<Border Classes="card-separator" />

View File

@ -57,8 +57,6 @@ public class DeviceLayoutTabViewModel : ActivatableViewModelBase
_notificationService.CreateNotification()
.WithMessage("Cleared imported layout.")
.WithSeverity(NotificationSeverity.Informational);
_deviceService.SaveDevice(Device);
}
public async Task BrowseCustomLayout()
@ -75,8 +73,6 @@ public class DeviceLayoutTabViewModel : ActivatableViewModelBase
.WithTitle("Imported layout")
.WithMessage($"File loaded from {files[0]}")
.WithSeverity(NotificationSeverity.Informational);
_deviceService.SaveDevice(Device);
}
}
@ -154,7 +150,12 @@ public class DeviceLayoutTabViewModel : ActivatableViewModelBase
{
if (e.PropertyName is nameof(Device.CustomLayoutPath) or nameof(Device.DisableDefaultLayout))
{
Task.Run(() => _deviceService.ApplyDeviceLayout(Device, Device.GetBestDeviceLayout()));
Task.Run(() =>
{
_deviceService.ApplyDeviceLayout(Device, Device.GetBestDeviceLayout());
_deviceService.SaveDevice(Device);
});
this.RaisePropertyChanged(nameof(CustomLayoutPath));
this.RaisePropertyChanged(nameof(HasCustomLayout));
}