1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-31 01:42:02 +00:00

Surface - Removed the ArtemisSurface and reworked device loading

This commit is contained in:
Robert 2021-02-16 21:46:08 +01:00
parent 7ccc9c54fb
commit 056b2bface
50 changed files with 1292 additions and 1506 deletions

View File

@ -1,20 +0,0 @@
using System;
namespace Artemis.Core
{
/// <summary>
/// Provides data about surface configuration related events
/// </summary>
public class SurfaceConfigurationEventArgs : EventArgs
{
internal SurfaceConfigurationEventArgs(ArtemisSurface surface)
{
Surface = surface;
}
/// <summary>
/// Gets the active surface at the time the event fired
/// </summary>
public ArtemisSurface Surface { get; }
}
}

View File

@ -1,5 +1,4 @@
using System; using System;
using RGB.NET.Core;
namespace Artemis.Core namespace Artemis.Core
{ {
@ -8,7 +7,7 @@ namespace Artemis.Core
/// </summary> /// </summary>
public class DeviceEventArgs : EventArgs public class DeviceEventArgs : EventArgs
{ {
internal DeviceEventArgs(IRGBDevice device) internal DeviceEventArgs(ArtemisDevice device)
{ {
Device = device; Device = device;
} }
@ -16,6 +15,6 @@ namespace Artemis.Core
/// <summary> /// <summary>
/// Gets the device this event is related to /// Gets the device this event is related to
/// </summary> /// </summary>
public IRGBDevice Device { get; } public ArtemisDevice Device { get; }
} }
} }

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core
{
/// <summary>
/// Provides data about device configuration related events
/// </summary>
public class SurfaceConfigurationEventArgs : EventArgs
{
internal SurfaceConfigurationEventArgs(List<ArtemisDevice> devices)
{
Devices = devices;
}
/// <summary>
/// Gets the current list of devices
/// </summary>
public List<ArtemisDevice> Devices { get; }
}
}

View File

@ -567,7 +567,7 @@ namespace Artemis.Core
CalculateRenderProperties(); CalculateRenderProperties();
} }
internal void PopulateLeds(ArtemisSurface surface) internal void PopulateLeds(IEnumerable<ArtemisDevice> devices)
{ {
if (Disposed) if (Disposed)
throw new ObjectDisposedException("Layer"); throw new ObjectDisposedException("Layer");
@ -575,7 +575,7 @@ namespace Artemis.Core
List<ArtemisLed> leds = new(); List<ArtemisLed> leds = new();
// Get the surface LEDs for this layer // Get the surface LEDs for this layer
List<ArtemisLed> availableLeds = surface.Devices.Where(d => d.IsEnabled).SelectMany(d => d.Leds).ToList(); List<ArtemisLed> availableLeds = devices.SelectMany(d => d.Leds).ToList();
foreach (LedEntity ledEntity in LayerEntity.Leds) foreach (LedEntity ledEntity in LayerEntity.Leds)
{ {
ArtemisLed? match = availableLeds.FirstOrDefault(a => a.Device.RgbDevice.GetDeviceIdentifier() == ledEntity.DeviceIdentifier && ArtemisLed? match = availableLeds.FirstOrDefault(a => a.Device.RgbDevice.GetDeviceIdentifier() == ledEntity.DeviceIdentifier &&

View File

@ -124,14 +124,14 @@ namespace Artemis.Core
/// <summary> /// <summary>
/// Populates all the LEDs on the elements in this profile /// Populates all the LEDs on the elements in this profile
/// </summary> /// </summary>
/// <param name="surface">The currently active surface that contains the LEDs</param> /// <param name="devices">The devices to use while populating LEDs</param>
public void PopulateLeds(ArtemisSurface surface) public void PopulateLeds(IEnumerable<ArtemisDevice> devices)
{ {
if (Disposed) if (Disposed)
throw new ObjectDisposedException("Profile"); throw new ObjectDisposedException("Profile");
foreach (Layer layer in GetAllLayers()) foreach (Layer layer in GetAllLayers())
layer.PopulateLeds(surface); layer.PopulateLeds(devices);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -197,7 +197,7 @@ namespace Artemis.Core
ProfileEntity.Layers.AddRange(GetAllLayers().Select(f => f.LayerEntity)); ProfileEntity.Layers.AddRange(GetAllLayers().Select(f => f.LayerEntity));
} }
internal void Activate(ArtemisSurface surface) internal void Activate(IEnumerable<ArtemisDevice> devices)
{ {
lock (_lock) lock (_lock)
{ {
@ -206,7 +206,7 @@ namespace Artemis.Core
if (IsActivated) if (IsActivated)
return; return;
PopulateLeds(surface); PopulateLeds(devices);
OnActivated(); OnActivated();
IsActivated = true; IsActivated = true;
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Artemis.Core.DeviceProviders; using Artemis.Core.DeviceProviders;
using Artemis.Core.Services;
using Artemis.Storage.Entities.Surface; using Artemis.Storage.Entities.Surface;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Layout; using RGB.NET.Layout;
@ -18,12 +19,11 @@ namespace Artemis.Core
private SKPath? _path; private SKPath? _path;
private SKRect _rectangle; private SKRect _rectangle;
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, ArtemisSurface surface) internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider)
{ {
DeviceEntity = new DeviceEntity(); DeviceEntity = new DeviceEntity();
RgbDevice = rgbDevice; RgbDevice = rgbDevice;
DeviceProvider = deviceProvider; DeviceProvider = deviceProvider;
Surface = surface;
Rotation = 0; Rotation = 0;
Scale = 1; Scale = 1;
@ -43,12 +43,11 @@ namespace Artemis.Core
CalculateRenderProperties(); CalculateRenderProperties();
} }
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, ArtemisSurface surface, DeviceEntity deviceEntity) internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, DeviceEntity deviceEntity)
{ {
DeviceEntity = deviceEntity; DeviceEntity = deviceEntity;
RgbDevice = rgbDevice; RgbDevice = rgbDevice;
DeviceProvider = deviceProvider; DeviceProvider = deviceProvider;
Surface = surface;
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>(); InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers) foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers)
@ -88,11 +87,6 @@ namespace Artemis.Core
/// </summary> /// </summary>
public DeviceProvider DeviceProvider { get; } public DeviceProvider DeviceProvider { get; }
/// <summary>
/// Gets the surface containing this device
/// </summary>
public ArtemisSurface Surface { get; }
/// <summary> /// <summary>
/// Gets a read only collection containing the LEDs of this device /// Gets a read only collection containing the LEDs of this device
/// </summary> /// </summary>
@ -214,12 +208,13 @@ namespace Artemis.Core
} }
/// <summary> /// <summary>
/// Gets or sets a boolean indicating whether this devices is enabled or not /// Gets a boolean indicating whether this devices is enabled or not
/// <para>Note: To enable/disable a device use the methods provided by <see cref="IRgbService" /></para>
/// </summary> /// </summary>
public bool IsEnabled public bool IsEnabled
{ {
get => DeviceEntity.IsEnabled; get => DeviceEntity.IsEnabled;
set internal set
{ {
DeviceEntity.IsEnabled = value; DeviceEntity.IsEnabled = value;
OnPropertyChanged(nameof(IsEnabled)); OnPropertyChanged(nameof(IsEnabled));
@ -305,37 +300,6 @@ namespace Artemis.Core
return fileName; return fileName;
} }
/// <summary>
/// Loads the best layout for this device, preferring user layouts and falling back to default layouts
/// </summary>
public void LoadBestLayout()
{
// Look for a user layout
// ... here
// Try loading a device provider layout, if that comes back valid we use that
ArtemisLayout deviceProviderLayout = DeviceProvider.LoadLayout(this);
// Finally fall back to a default layout
// .. do it!
ApplyLayout(deviceProviderLayout);
}
private void ApplyKeyboardLayout()
{
if (!(RgbDevice is IKeyboard keyboard))
return;
// If supported, detect the device layout so that we can load the correct one
if (DeviceProvider.CanDetectLogicalLayout )
LogicalLayout = DeviceProvider.GetLogicalLayout(keyboard);
if (DeviceProvider.CanDetectPhysicalLayout)
PhysicalLayout = (KeyboardLayoutType) keyboard.DeviceInfo.Layout;
}
/// <summary> /// <summary>
/// Applies the provided layout to the device /// Applies the provided layout to the device
/// </summary> /// </summary>
@ -350,12 +314,13 @@ namespace Artemis.Core
Layout = layout; Layout = layout;
Layout.ApplyDevice(this); Layout.ApplyDevice(this);
OnDeviceUpdated();
} }
internal void ApplyToEntity() internal void ApplyToEntity()
{ {
// Other properties are computed // Other properties are computed
DeviceEntity.DeviceIdentifier = RgbDevice.GetDeviceIdentifier(); DeviceEntity.Id = RgbDevice.GetDeviceIdentifier();
DeviceEntity.InputIdentifiers.Clear(); DeviceEntity.InputIdentifiers.Clear();
foreach (ArtemisDeviceInputIdentifier identifier in InputIdentifiers) foreach (ArtemisDeviceInputIdentifier identifier in InputIdentifiers)
@ -400,6 +365,18 @@ namespace Artemis.Core
Path = path; Path = path;
} }
private void ApplyKeyboardLayout()
{
if (!(RgbDevice is IKeyboard keyboard))
return;
// If supported, detect the device layout so that we can load the correct one
if (DeviceProvider.CanDetectLogicalLayout)
LogicalLayout = DeviceProvider.GetLogicalLayout(keyboard);
if (DeviceProvider.CanDetectPhysicalLayout)
PhysicalLayout = (KeyboardLayoutType) keyboard.DeviceInfo.Layout;
}
#region Events #region Events
/// <summary> /// <summary>

View File

@ -1,134 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Artemis.Storage.Entities.Surface;
using RGB.NET.Core;
namespace Artemis.Core
{
/// <summary>
/// Represents a surface of a specific scale, containing all the available <see cref="ArtemisDevice" />s
/// </summary>
public class ArtemisSurface : CorePropertyChanged
{
private List<ArtemisDevice> _devices = new();
private ReadOnlyDictionary<Led, ArtemisLed> _ledMap = new(new Dictionary<Led, ArtemisLed>());
private bool _isActive;
private string _name;
internal ArtemisSurface(RGBSurface rgbSurface, string name)
{
SurfaceEntity = new SurfaceEntity {DeviceEntities = new List<DeviceEntity>()};
EntityId = Guid.NewGuid();
RgbSurface = rgbSurface;
_name = name;
_isActive = false;
ApplyToEntity();
}
internal ArtemisSurface(RGBSurface rgbSurface, SurfaceEntity surfaceEntity)
{
SurfaceEntity = surfaceEntity;
EntityId = surfaceEntity.Id;
RgbSurface = rgbSurface;
_name = surfaceEntity.Name;
_isActive = surfaceEntity.IsActive;
}
/// <summary>
/// Gets the RGB.NET surface backing this Artemis surface
/// </summary>
public RGBSurface RgbSurface { get; }
/// <summary>
/// Gets the name of the surface
/// </summary>
public string Name
{
get => _name;
set => SetAndNotify(ref _name, value);
}
/// <summary>
/// Gets a boolean indicating whether this surface is the currently active surface
/// </summary>
public bool IsActive
{
get => _isActive;
internal set => SetAndNotify(ref _isActive, value);
}
/// <summary>
/// Gets a list of devices this surface contains
/// </summary>
public List<ArtemisDevice> Devices
{
get => _devices;
internal set => SetAndNotify(ref _devices, value);
}
/// <summary>
/// Gets a dictionary containing all <see cref="ArtemisLed" />s on the surface with their corresponding RGB.NET
/// <see cref="Led" /> as key
/// </summary>
public ReadOnlyDictionary<Led, ArtemisLed> LedMap
{
get => _ledMap;
private set => SetAndNotify(ref _ledMap, value);
}
internal SurfaceEntity SurfaceEntity { get; set; }
internal Guid EntityId { get; set; }
/// <summary>
/// Attempts to retrieve the <see cref="ArtemisLed" /> that corresponds the provided RGB.NET <see cref="Led" />
/// </summary>
/// <param name="led">The RGB.NET <see cref="Led" /> to find the corresponding <see cref="ArtemisLed" /> for </param>
/// <returns>If found, the corresponding <see cref="ArtemisLed" />; otherwise <see langword="null" />.</returns>
public ArtemisLed? GetArtemisLed(Led led)
{
LedMap.TryGetValue(led, out ArtemisLed? artemisLed);
return artemisLed;
}
internal void UpdateLedMap()
{
LedMap = new ReadOnlyDictionary<Led, ArtemisLed>(
_devices.Where(d => d.IsEnabled).SelectMany(d => d.Leds.Select(al => new KeyValuePair<Led, ArtemisLed>(al.RgbLed, al))).ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
);
}
internal void ApplyToEntity()
{
SurfaceEntity.Id = EntityId;
SurfaceEntity.Name = Name;
SurfaceEntity.IsActive = IsActive;
// Add missing device entities, don't remove old ones in case they come back later
foreach (DeviceEntity deviceEntity in Devices.Select(d => d.DeviceEntity).ToList())
if (!SurfaceEntity.DeviceEntities.Contains(deviceEntity))
SurfaceEntity.DeviceEntities.Add(deviceEntity);
}
#region Events
/// <summary>
/// Occurs when the scale of the surface is changed
/// </summary>
public event EventHandler<EventArgs>? ScaleChanged;
/// <summary>
/// Invokes the <see cref="ScaleChanged" /> event
/// </summary>
protected virtual void OnScaleChanged()
{
ScaleChanged?.Invoke(this, EventArgs.Empty);
}
#endregion
}
}

View File

@ -20,6 +20,53 @@ namespace Artemis.Core
FilePath = filePath; FilePath = filePath;
Leds = new List<ArtemisLedLayout>(); Leds = new List<ArtemisLedLayout>();
LoadLayout();
}
/// <summary>
/// Gets the file path the layout was (attempted to be) loaded from
/// </summary>
public string FilePath { get; }
/// <summary>
/// Gets the RGB.NET device layout
/// </summary>
public DeviceLayout RgbLayout { get; private set; }
/// <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>
public bool IsValid { get; private set; }
/// <summary>
/// Gets the image of the device
/// </summary>
public Uri? Image { get; private set; }
public List<ArtemisLedLayout> Leds { get; }
internal LayoutCustomDeviceData LayoutCustomDeviceData { get; set; }
public void ReloadFromDisk()
{
Leds.Clear();
LoadLayout();
}
internal void ApplyDevice(ArtemisDevice artemisDevice)
{
Device = artemisDevice;
foreach (ArtemisLedLayout artemisLedLayout in Leds)
artemisLedLayout.ApplyDevice(Device);
}
private void LoadLayout()
{
DeviceLayout? deviceLayout = DeviceLayout.Load(FilePath, typeof(LayoutCustomDeviceData), typeof(LayoutCustomLedData)); DeviceLayout? deviceLayout = DeviceLayout.Load(FilePath, typeof(LayoutCustomDeviceData), typeof(LayoutCustomLedData));
if (deviceLayout != null) if (deviceLayout != null)
{ {
@ -39,47 +86,13 @@ namespace Artemis.Core
ApplyCustomDeviceData(); ApplyCustomDeviceData();
} }
/// <summary>
/// Gets the file path the layout was (attempted to be) loaded from
/// </summary>
public string FilePath { get; }
/// <summary>
/// Gets the RGB.NET device layout
/// </summary>
public DeviceLayout RgbLayout { 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>
public bool IsValid { get; }
/// <summary>
/// Gets the image of the device
/// </summary>
public Uri? Image { get; private set; }
public List<ArtemisLedLayout> Leds { get; }
internal LayoutCustomDeviceData LayoutCustomDeviceData { get; set; }
internal void ApplyDevice(ArtemisDevice artemisDevice)
{
Device = artemisDevice;
foreach (ArtemisLedLayout artemisLedLayout in Leds)
artemisLedLayout.ApplyDevice(Device);
}
private void ApplyCustomDeviceData() private void ApplyCustomDeviceData()
{ {
Uri layoutDirectory = new(Path.GetDirectoryName(FilePath)! + "\\", UriKind.Absolute); Uri layoutDirectory = new(Path.GetDirectoryName(FilePath)! + "\\", UriKind.Absolute);
if (LayoutCustomDeviceData.DeviceImage != null) if (LayoutCustomDeviceData.DeviceImage != null)
Image = new Uri(layoutDirectory, new Uri(LayoutCustomDeviceData.DeviceImage, UriKind.Relative)); Image = new Uri(layoutDirectory, new Uri(LayoutCustomDeviceData.DeviceImage, UriKind.Relative));
else
Image = null;
} }
} }
} }

View File

@ -146,10 +146,9 @@ namespace Artemis.Core.Modules
/// Called each frame when the module should render /// Called each frame when the module should render
/// </summary> /// </summary>
/// <param name="deltaTime">Time since the last render</param> /// <param name="deltaTime">Time since the last render</param>
/// <param name="surface">The RGB Surface to render to</param>
/// <param name="canvas"></param> /// <param name="canvas"></param>
/// <param name="canvasInfo"></param> /// <param name="canvasInfo"></param>
public abstract void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo); public abstract void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo);
/// <summary> /// <summary>
/// Called when the <see cref="ActivationRequirements" /> are met or during an override /// Called when the <see cref="ActivationRequirements" /> are met or during an override
@ -191,9 +190,9 @@ namespace Artemis.Core.Modules
Update(deltaTime); Update(deltaTime);
} }
internal virtual void InternalRender(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo) internal virtual void InternalRender(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
{ {
Render(deltaTime, surface, canvas, canvasInfo); Render(deltaTime, canvas, canvasInfo);
} }
internal virtual void Activate(bool isOverride) internal virtual void Activate(bool isOverride)

View File

@ -142,10 +142,9 @@ namespace Artemis.Core.Modules
/// Called after the profile has rendered /// Called after the profile has rendered
/// </summary> /// </summary>
/// <param name="deltaTime">Time since the last render</param> /// <param name="deltaTime">Time since the last render</param>
/// <param name="surface">The RGB Surface to render to</param>
/// <param name="canvas"></param> /// <param name="canvas"></param>
/// <param name="canvasInfo"></param> /// <param name="canvasInfo"></param>
public virtual void ProfileRendered(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo) public virtual void ProfileRendered(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
{ {
} }
@ -168,9 +167,9 @@ namespace Artemis.Core.Modules
ProfileUpdated(deltaTime); ProfileUpdated(deltaTime);
} }
internal override void InternalRender(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo) internal override void InternalRender(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
{ {
Render(deltaTime, surface, canvas, canvasInfo); Render(deltaTime, canvas, canvasInfo);
lock (_lock) lock (_lock)
{ {
@ -178,10 +177,10 @@ namespace Artemis.Core.Modules
ActiveProfile?.Render(canvas); ActiveProfile?.Render(canvas);
} }
ProfileRendered(deltaTime, surface, canvas, canvasInfo); ProfileRendered(deltaTime, canvas, canvasInfo);
} }
internal async Task ChangeActiveProfileAnimated(Profile? profile, ArtemisSurface? surface) internal async Task ChangeActiveProfileAnimated(Profile? profile, IEnumerable<ArtemisDevice> devices)
{ {
if (profile != null && profile.Module != this) if (profile != null && profile.Module != this)
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {this}."); throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {this}.");
@ -196,21 +195,19 @@ namespace Artemis.Core.Modules
while (OpacityOverride > 0) while (OpacityOverride > 0)
await Task.Delay(50); await Task.Delay(50);
ChangeActiveProfile(profile, surface); ChangeActiveProfile(profile, devices);
AnimatingProfileChange = false; AnimatingProfileChange = false;
while (OpacityOverride < 1) while (OpacityOverride < 1)
await Task.Delay(50); await Task.Delay(50);
} }
internal void ChangeActiveProfile(Profile? profile, ArtemisSurface? surface) internal void ChangeActiveProfile(Profile? profile, IEnumerable<ArtemisDevice> devices)
{ {
if (profile != null && profile.Module != this) if (profile != null && profile.Module != this)
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {this}."); throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {this}.");
if (!IsActivated) if (!IsActivated)
throw new ArtemisCoreException("Cannot activate a profile on a deactivated module"); throw new ArtemisCoreException("Cannot activate a profile on a deactivated module");
if (profile != null && surface == null)
throw new ArtemisCoreException("If changing the active profile to a non-null profile, a surface is required");
lock (_lock) lock (_lock)
{ {
@ -220,7 +217,7 @@ namespace Artemis.Core.Modules
ActiveProfile?.Dispose(); ActiveProfile?.Dispose();
ActiveProfile = profile; ActiveProfile = profile;
ActiveProfile?.Activate(surface!); ActiveProfile?.Activate(devices);
} }
OnActiveProfileChanged(); OnActiveProfileChanged();

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Artemis.Core.Services;
using RGB.NET.Core; using RGB.NET.Core;
using SkiaSharp; using SkiaSharp;
@ -12,13 +13,15 @@ namespace Artemis.Core
{ {
private readonly object _disposeLock; private readonly object _disposeLock;
private readonly PluginSetting<int> _sampleSizeSetting; private readonly PluginSetting<int> _sampleSizeSetting;
private readonly IRgbService _rgbService;
#region Constructors #region Constructors
internal BitmapBrush(Scale scale, PluginSetting<int> sampleSizeSetting) internal BitmapBrush(Scale scale, PluginSetting<int> sampleSizeSetting, IRgbService rgbService)
{ {
_disposeLock = new object(); _disposeLock = new object();
_sampleSizeSetting = sampleSizeSetting; _sampleSizeSetting = sampleSizeSetting;
_rgbService = rgbService;
Scale = scale; Scale = scale;
} }
@ -103,7 +106,7 @@ namespace Artemis.Core
if (scaledLocation.X < Bitmap.Width && scaledLocation.Y < Bitmap.Height) if (scaledLocation.X < Bitmap.Width && scaledLocation.Y < Bitmap.Height)
{ {
Color pixel = Bitmap.GetPixel(scaledLocation.X.RoundToInt(), scaledLocation.Y.RoundToInt()).ToRgbColor(); Color pixel = Bitmap.GetPixel(scaledLocation.X.RoundToInt(), scaledLocation.Y.RoundToInt()).ToRgbColor();
ArtemisDevice? artemisDevice = Surface?.GetArtemisLed(renderTarget.Led)?.Device; ArtemisDevice? artemisDevice = _rgbService.GetLed(renderTarget.Led)?.Device;
if (artemisDevice != null) if (artemisDevice != null)
pixel = pixel.MultiplyRGB(artemisDevice.RedScale, artemisDevice.GreenScale, artemisDevice.BlueScale); pixel = pixel.MultiplyRGB(artemisDevice.RedScale, artemisDevice.GreenScale, artemisDevice.BlueScale);
RenderedTargets[renderTarget] = pixel; RenderedTargets[renderTarget] = pixel;
@ -157,7 +160,7 @@ namespace Artemis.Core
Color pixel = new(a / sampleSize, r / sampleSize, g / sampleSize, b / sampleSize); Color pixel = new(a / sampleSize, r / sampleSize, g / sampleSize, b / sampleSize);
ArtemisDevice? artemisDevice = Surface?.GetArtemisLed(renderTarget.Led)?.Device; ArtemisDevice? artemisDevice = _rgbService.GetLed(renderTarget.Led)?.Device;
if (artemisDevice is not null) if (artemisDevice is not null)
pixel = pixel.MultiplyRGB(artemisDevice.RedScale, artemisDevice.GreenScale, artemisDevice.BlueScale); pixel = pixel.MultiplyRGB(artemisDevice.RedScale, artemisDevice.GreenScale, artemisDevice.BlueScale);
@ -188,7 +191,6 @@ namespace Artemis.Core
} }
internal bool IsDisposed { get; set; } internal bool IsDisposed { get; set; }
internal ArtemisSurface? Surface { get; set; }
#endregion #endregion
} }

View File

@ -34,7 +34,6 @@ namespace Artemis.Core.Services
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
private readonly PluginSetting<double> _renderScale; private readonly PluginSetting<double> _renderScale;
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private readonly ISurfaceService _surfaceService;
private readonly List<Exception> _updateExceptions = new(); private readonly List<Exception> _updateExceptions = new();
private List<BaseDataModelExpansion> _dataModelExpansions = new(); private List<BaseDataModelExpansion> _dataModelExpansions = new();
private DateTime _lastExceptionLog; private DateTime _lastExceptionLog;
@ -47,7 +46,6 @@ namespace Artemis.Core.Services
ISettingsService settingsService, ISettingsService settingsService,
IPluginManagementService pluginManagementService, IPluginManagementService pluginManagementService,
IRgbService rgbService, IRgbService rgbService,
ISurfaceService surfaceService,
IProfileService profileService, IProfileService profileService,
IModuleService moduleService // injected to ensure module priorities get applied IModuleService moduleService // injected to ensure module priorities get applied
) )
@ -58,7 +56,6 @@ namespace Artemis.Core.Services
_logger = logger; _logger = logger;
_pluginManagementService = pluginManagementService; _pluginManagementService = pluginManagementService;
_rgbService = rgbService; _rgbService = rgbService;
_surfaceService = surfaceService;
_profileService = profileService; _profileService = profileService;
_loggingLevel = settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Debug); _loggingLevel = settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Debug);
_renderScale = settingsService.GetSetting("Core.RenderScale", 0.5); _renderScale = settingsService.GetSetting("Core.RenderScale", 0.5);
@ -121,9 +118,6 @@ namespace Artemis.Core.Services
IsElevated IsElevated
); );
ArtemisSurface surfaceConfig = _surfaceService.ActiveSurface;
_logger.Information("Initialized with active surface entity {surfaceConfig}-{guid}", surfaceConfig.Name, surfaceConfig.EntityId);
OnInitialized(); OnInitialized();
} }
@ -139,7 +133,7 @@ namespace Artemis.Core.Services
public void PlayIntroAnimation() public void PlayIntroAnimation()
{ {
IntroAnimation intro = new(_logger, _profileService, _surfaceService); IntroAnimation intro = new(_logger, _profileService, _rgbService.EnabledDevices);
// Draw a white overlay over the device // Draw a white overlay over the device
void DrawOverlay(object? sender, FrameRenderingEventArgs args) void DrawOverlay(object? sender, FrameRenderingEventArgs args)
@ -236,7 +230,7 @@ namespace Artemis.Core.Services
if (!ModuleRenderingDisabled) if (!ModuleRenderingDisabled)
// While non-activated modules may be updated above if they expand the main data model, they may never render // While non-activated modules may be updated above if they expand the main data model, they may never render
foreach (Module module in modules.Where(m => m.IsActivated)) foreach (Module module in modules.Where(m => m.IsActivated))
module.InternalRender(args.DeltaTime, _surfaceService.ActiveSurface, canvas, _rgbService.BitmapBrush.Bitmap.Info); module.InternalRender(args.DeltaTime, canvas, _rgbService.BitmapBrush.Bitmap.Info);
OnFrameRendering(new FrameRenderingEventArgs(canvas, args.DeltaTime, _rgbService.Surface)); OnFrameRendering(new FrameRenderingEventArgs(canvas, args.DeltaTime, _rgbService.Surface));
} }

View File

@ -9,15 +9,13 @@ namespace Artemis.Core.Services
internal class InputService : IInputService internal class InputService : IInputService
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ISurfaceService _surfaceService; private readonly IRgbService _rgbService;
public InputService(ILogger logger, ISurfaceService surfaceService) public InputService(ILogger logger, IRgbService rgbService)
{ {
_logger = logger; _logger = logger;
_surfaceService = surfaceService; _rgbService = rgbService;
_surfaceService.ActiveSurfaceConfigurationSelected += SurfaceConfigurationChanged;
_surfaceService.SurfaceConfigurationUpdated += SurfaceConfigurationChanged;
BustIdentifierCache(); BustIdentifierCache();
} }
@ -91,7 +89,7 @@ namespace Artemis.Core.Services
_logger.Debug("Stop identifying device {device}", _identifyingDevice); _logger.Debug("Stop identifying device {device}", _identifyingDevice);
_identifyingDevice = null; _identifyingDevice = null;
_surfaceService.UpdateSurfaceConfiguration(_surfaceService.ActiveSurface, true); _rgbService.SaveDevices();
BustIdentifierCache(); BustIdentifierCache();
} }
@ -123,7 +121,7 @@ namespace Artemis.Core.Services
{ {
if (_cachedFallbackKeyboard != null) if (_cachedFallbackKeyboard != null)
return _cachedFallbackKeyboard; return _cachedFallbackKeyboard;
_cachedFallbackKeyboard = _surfaceService.ActiveSurface.Devices.FirstOrDefault(d => d.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard); _cachedFallbackKeyboard = _rgbService.EnabledDevices.FirstOrDefault(d => d.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard);
return _cachedFallbackKeyboard; return _cachedFallbackKeyboard;
} }
@ -131,7 +129,7 @@ namespace Artemis.Core.Services
{ {
if (_cachedFallbackMouse != null) if (_cachedFallbackMouse != null)
return _cachedFallbackMouse; return _cachedFallbackMouse;
_cachedFallbackMouse = _surfaceService.ActiveSurface.Devices.FirstOrDefault(d => d.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse); _cachedFallbackMouse = _rgbService.EnabledDevices.FirstOrDefault(d => d.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse);
return _cachedFallbackMouse; return _cachedFallbackMouse;
} }
@ -144,7 +142,7 @@ namespace Artemis.Core.Services
_cachedFallbackKeyboard = null; _cachedFallbackKeyboard = null;
_cachedFallbackMouse = null; _cachedFallbackMouse = null;
_devices = _surfaceService.ActiveSurface.Devices.Where(d => d.InputIdentifiers.Any()).ToList(); _devices = _rgbService.EnabledDevices.Where(d => d.InputIdentifiers.Any()).ToList();
} }
private void AddDeviceToCache(ArtemisDevice match, InputProvider provider, object identifier) private void AddDeviceToCache(ArtemisDevice match, InputProvider provider, object identifier)

View File

@ -9,6 +9,22 @@ namespace Artemis.Core.Services
/// </summary> /// </summary>
public interface IRgbService : IArtemisService, IDisposable public interface IRgbService : IArtemisService, IDisposable
{ {
/// <summary>
/// Gets a read-only collection containing all enabled devices
/// </summary>
IReadOnlyCollection<ArtemisDevice> EnabledDevices { get; }
/// <summary>
/// Gets a read-only collection containing all registered devices
/// </summary>
IReadOnlyCollection<ArtemisDevice> Devices { get; }
/// <summary>
/// Gets a dictionary containing all <see cref="ArtemisLed" />s on the surface with their corresponding RGB.NET
/// <see cref="Led" /> as key
/// </summary>
IReadOnlyDictionary<Led, ArtemisLed> LedMap { get; }
/// <summary> /// <summary>
/// Gets or sets the RGB surface rendering is performed on /// Gets or sets the RGB surface rendering is performed on
/// </summary> /// </summary>
@ -19,16 +35,6 @@ namespace Artemis.Core.Services
/// </summary> /// </summary>
BitmapBrush? BitmapBrush { get; } BitmapBrush? BitmapBrush { get; }
/// <summary>
/// Gets the scale the frames are rendered on, a scale of 1.0 means 1 pixel = 1mm
/// </summary>
double RenderScale { get; }
/// <summary>
/// Gets all loaded RGB devices
/// </summary>
IReadOnlyCollection<IRGBDevice> LoadedDevices { get; }
/// <summary> /// <summary>
/// Gets the update trigger that drives the render loop /// Gets the update trigger that drives the render loop
/// </summary> /// </summary>
@ -46,14 +52,66 @@ namespace Artemis.Core.Services
void AddDeviceProvider(IRGBDeviceProvider deviceProvider); void AddDeviceProvider(IRGBDeviceProvider deviceProvider);
/// <summary> /// <summary>
/// Occurs when a single device has loaded /// Removes the given device provider from the <see cref="Surface" />
/// </summary> /// </summary>
event EventHandler<DeviceEventArgs> DeviceLoaded; /// <param name="deviceProvider"></param>
void RemoveDeviceProvider(IRGBDeviceProvider deviceProvider);
/// <summary> /// <summary>
/// Occurs when a single device has reloaded /// Applies auto-arranging logic to the surface
/// </summary> /// </summary>
event EventHandler<DeviceEventArgs> DeviceReloaded; void AutoArrangeDevices();
/// <summary>
/// Applies the best available layout for the given <see cref="ArtemisDevice" />
/// </summary>
/// <param name="device">The device to apply the best available layout to</param>
/// <returns>The layout that was applied to the device</returns>
ArtemisLayout ApplyBestDeviceLayout(ArtemisDevice device);
/// <summary>
/// Apples the provided <see cref="ArtemisLayout" /> to the provided <see cref="ArtemisDevice" />
/// </summary>
/// <param name="device"></param>
/// <param name="layout"></param>
void ApplyDeviceLayout(ArtemisDevice device, ArtemisLayout layout);
/// <summary>
/// Attempts to retrieve the <see cref="ArtemisDevice" /> that corresponds the provided RGB.NET
/// <see cref="IRGBDevice" />
/// </summary>
/// <param name="rgbDevice">
/// The RGB.NET <see cref="IRGBDevice" /> to find the corresponding <see cref="ArtemisDevice" />
/// for
/// </param>
/// <returns>If found, the corresponding <see cref="ArtemisDevice" />; otherwise <see langword="null" />.</returns>
ArtemisDevice? GetDevice(IRGBDevice rgbDevice);
/// <summary>
/// Attempts to retrieve the <see cref="ArtemisLed" /> that corresponds the provided RGB.NET <see cref="Led" />
/// </summary>
/// <param name="led">The RGB.NET <see cref="Led" /> to find the corresponding <see cref="ArtemisLed" /> for </param>
/// <returns>If found, the corresponding <see cref="ArtemisLed" />; otherwise <see langword="null" />.</returns>
ArtemisLed? GetLed(Led led);
/// <summary>
/// Saves the configuration of the provided device to persistent storage
/// </summary>
/// <param name="artemisDevice"></param>
void SaveDevice(ArtemisDevice artemisDevice);
/// <summary>
/// Saves the configuration of all current devices to persistent storage
/// </summary>
void SaveDevices();
void EnableDevice(ArtemisDevice device);
void DisableDevice(ArtemisDevice device);
/// <summary>
/// Occurs when a single device was added
/// </summary>
event EventHandler<DeviceEventArgs> DeviceAdded;
/// <summary> /// <summary>
/// Occurs when a single device was removed /// Occurs when a single device was removed
@ -61,9 +119,8 @@ namespace Artemis.Core.Services
event EventHandler<DeviceEventArgs> DeviceRemoved; event EventHandler<DeviceEventArgs> DeviceRemoved;
/// <summary> /// <summary>
/// Recalculates the LED group used by the <see cref="BitmapBrush" /> /// Occurs when the surface has had modifications to its LED collection
/// </summary> /// </summary>
/// <param name="artemisSurface"></param> event EventHandler LedsChanged;
void UpdateSurfaceLedGroup(ArtemisSurface artemisSurface);
} }
} }

View File

@ -1,9 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Artemis.Core.DeviceProviders;
using Artemis.Core.Services.Models;
using Artemis.Storage.Entities.Surface;
using Artemis.Storage.Repositories.Interfaces;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Groups; using RGB.NET.Groups;
using RGB.NET.Layout;
using Serilog; using Serilog;
namespace Artemis.Core.Services namespace Artemis.Core.Services
@ -13,16 +17,24 @@ namespace Artemis.Core.Services
/// </summary> /// </summary>
internal class RgbService : IRgbService internal class RgbService : IRgbService
{ {
private readonly List<IRGBDevice> _loadedDevices; private readonly List<ArtemisDevice> _devices;
private readonly ILogger _logger; private readonly List<ArtemisDevice> _enabledDevices;
private readonly PluginSetting<double> _renderScaleSetting; private Dictionary<Led, ArtemisLed> _ledMap;
private readonly PluginSetting<int> _sampleSizeSetting;
private readonly PluginSetting<int> _targetFrameRateSetting;
private ListLedGroup? _surfaceLedGroup;
public RgbService(ILogger logger, ISettingsService settingsService) private readonly ILogger _logger;
private readonly IPluginManagementService _pluginManagementService;
private readonly IDeviceRepository _deviceRepository;
private readonly PluginSetting<double> _renderScaleSetting;
private readonly PluginSetting<int> _targetFrameRateSetting;
private readonly PluginSetting<int> _sampleSizeSetting;
private ListLedGroup? _surfaceLedGroup;
private bool _modifyingProviders;
public RgbService(ILogger logger, ISettingsService settingsService, IPluginManagementService pluginManagementService, IDeviceRepository deviceRepository)
{ {
_logger = logger; _logger = logger;
_pluginManagementService = pluginManagementService;
_deviceRepository = deviceRepository;
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.5); _renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.5);
_targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25); _targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25);
_sampleSizeSetting = settingsService.GetSetting("Core.SampleSize", 1); _sampleSizeSetting = settingsService.GetSetting("Core.SampleSize", 1);
@ -33,57 +45,131 @@ namespace Artemis.Core.Services
Surface.Exception += SurfaceOnException; Surface.Exception += SurfaceOnException;
_renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged; _renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged;
_targetFrameRateSetting.SettingChanged += TargetFrameRateSettingOnSettingChanged; _targetFrameRateSetting.SettingChanged += TargetFrameRateSettingOnSettingChanged;
_loadedDevices = new List<IRGBDevice>(); _enabledDevices = new List<ArtemisDevice>();
_devices = new List<ArtemisDevice>();
_ledMap = new Dictionary<Led, ArtemisLed>();
UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value}; UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value};
Surface.RegisterUpdateTrigger(UpdateTrigger); Surface.RegisterUpdateTrigger(UpdateTrigger);
} }
public IReadOnlyCollection<ArtemisDevice> EnabledDevices => _enabledDevices.AsReadOnly();
public IReadOnlyCollection<ArtemisDevice> Devices => _devices.AsReadOnly();
public IReadOnlyDictionary<Led, ArtemisLed> LedMap => new ReadOnlyDictionary<Led, ArtemisLed>(_ledMap);
/// <inheritdoc /> /// <inheritdoc />
public RGBSurface Surface { get; set; } public RGBSurface Surface { get; set; }
public TimerUpdateTrigger UpdateTrigger { get; } public TimerUpdateTrigger UpdateTrigger { get; }
public BitmapBrush? BitmapBrush { get; private set; } public BitmapBrush? BitmapBrush { get; private set; }
public IReadOnlyCollection<IRGBDevice> LoadedDevices => _loadedDevices.AsReadOnly();
public double RenderScale => _renderScaleSetting.Value;
public bool IsRenderPaused { get; set; } public bool IsRenderPaused { get; set; }
public void AddDeviceProvider(IRGBDeviceProvider deviceProvider) public void AddDeviceProvider(IRGBDeviceProvider deviceProvider)
{ {
try lock (_devices)
{ {
List<IRGBDevice> toRemove = deviceProvider.Devices.Where(d => Surface.Devices.Contains(d)).ToList(); try
Surface.Detach(deviceProvider.Devices);
foreach (IRGBDevice rgbDevice in toRemove)
OnDeviceRemoved(new DeviceEventArgs(rgbDevice));
deviceProvider.Initialize(RGBDeviceType.All, true);
Surface.Attach(deviceProvider.Devices);
}
catch (Exception e)
{
_logger.Error(e, "Exception during device loading for device provider {deviceProvider}", deviceProvider.GetType().Name);
throw;
}
if (deviceProvider.Devices == null || !deviceProvider.Devices.Any())
{
_logger.Warning("Device provider {deviceProvider} has no devices", deviceProvider.GetType().Name);
return;
}
foreach (IRGBDevice surfaceDevice in deviceProvider.Devices)
{
_logger.Debug("Device provider {deviceProvider} added {deviceName}", deviceProvider.GetType().Name, surfaceDevice.DeviceInfo?.DeviceName);
if (!_loadedDevices.Contains(surfaceDevice))
{ {
_loadedDevices.Add(surfaceDevice); _modifyingProviders = true;
OnDeviceLoaded(new DeviceEventArgs(surfaceDevice));
List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
Surface.Detach(deviceProvider.Devices);
foreach (ArtemisDevice device in toRemove)
RemoveDevice(device);
deviceProvider.Initialize(RGBDeviceType.All, true);
Surface.Attach(deviceProvider.Devices);
if (!deviceProvider.Devices.Any())
{
_logger.Warning("Device provider {deviceProvider} has no devices", deviceProvider.GetType().Name);
return;
}
foreach (IRGBDevice rgbDevice in deviceProvider.Devices)
{
ArtemisDevice artemisDevice = GetArtemisDevice(rgbDevice);
AddDevice(artemisDevice);
_logger.Debug("Device provider {deviceProvider} added {deviceName}", deviceProvider.GetType().Name, rgbDevice.DeviceInfo?.DeviceName);
}
_devices.Sort((a, b) => a.ZIndex - b.ZIndex);
}
catch (Exception e)
{
_logger.Error(e, "Exception during device loading for device provider {deviceProvider}", deviceProvider.GetType().Name);
throw;
}
finally
{
_modifyingProviders = false;
UpdateBitmapBrush();
} }
else
OnDeviceReloaded(new DeviceEventArgs(surfaceDevice));
} }
} }
public void RemoveDeviceProvider(IRGBDeviceProvider deviceProvider)
{
lock (_devices)
{
try
{
_modifyingProviders = true;
List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
Surface.Detach(deviceProvider.Devices);
foreach (ArtemisDevice device in toRemove)
RemoveDevice(device);
_devices.Sort((a, b) => a.ZIndex - b.ZIndex);
}
catch (Exception e)
{
_logger.Error(e, "Exception during device removal for device provider {deviceProvider}", deviceProvider.GetType().Name);
throw;
}
finally
{
_modifyingProviders = false;
UpdateBitmapBrush();
}
}
}
private void UpdateBitmapBrush()
{
lock (_devices)
{
if (_modifyingProviders)
return;
_ledMap = new Dictionary<Led, ArtemisLed>(_devices.SelectMany(d => d.Leds).ToDictionary(l => l.RgbLed));
if (_surfaceLedGroup == null || BitmapBrush == null)
{
// Apply the application wide brush and decorator
BitmapBrush = new BitmapBrush(new Scale(_renderScaleSetting.Value), _sampleSizeSetting, this);
_surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) {Brush = BitmapBrush};
OnLedsChanged();
return;
}
lock (_surfaceLedGroup)
{
// Clean up the old background
_surfaceLedGroup.Detach(Surface);
// Apply the application wide brush and decorator
BitmapBrush.Scale = new Scale(_renderScaleSetting.Value);
_surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) {Brush = BitmapBrush};
OnLedsChanged();
}
}
}
#region IDisposable
public void Dispose() public void Dispose()
{ {
Surface.UnregisterUpdateTrigger(UpdateTrigger); Surface.UnregisterUpdateTrigger(UpdateTrigger);
@ -92,10 +178,154 @@ namespace Artemis.Core.Services
Surface.Dispose(); Surface.Dispose();
} }
#endregion
#region EnabledDevices
public void AutoArrangeDevices()
{
SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement();
surfaceArrangement.Arrange(_devices);
SaveDevices();
}
public ArtemisLayout ApplyBestDeviceLayout(ArtemisDevice device)
{
// Look for a user layout
// ... here
// Try loading a device provider layout, if that comes back valid we use that
ArtemisLayout layout = device.DeviceProvider.LoadLayout(device);
// Finally fall back to a default layout
// .. do it!
ApplyDeviceLayout(device, layout);
return layout;
}
public void ApplyDeviceLayout(ArtemisDevice device, ArtemisLayout layout)
{
device.ApplyLayout(layout);
// Applying layouts can affect LEDs, update LED group
UpdateBitmapBrush();
}
public ArtemisDevice? GetDevice(IRGBDevice rgbDevice)
{
return _devices.FirstOrDefault(d => d.RgbDevice == rgbDevice);
}
public ArtemisLed? GetLed(Led led)
{
LedMap.TryGetValue(led, out ArtemisLed? artemisLed);
return artemisLed;
}
public void EnableDevice(ArtemisDevice device)
{
if (device.IsEnabled)
return;
_enabledDevices.Add(device);
device.IsEnabled = true;
device.ApplyToEntity();
_deviceRepository.Save(device.DeviceEntity);
UpdateBitmapBrush();
OnDeviceAdded(new DeviceEventArgs(device));
}
public void DisableDevice(ArtemisDevice device)
{
if (!device.IsEnabled)
return;
_enabledDevices.Remove(device);
device.IsEnabled = false;
device.ApplyToEntity();
_deviceRepository.Save(device.DeviceEntity);
UpdateBitmapBrush();
OnDeviceRemoved(new DeviceEventArgs(device));
}
private void AddDevice(ArtemisDevice device)
{
if (_devices.Any(d => d.RgbDevice == device.RgbDevice))
throw new ArtemisCoreException("Attempted to add a duplicate device to the RGB Service");
device.ApplyToRgbDevice();
_devices.Add(device);
if (device.IsEnabled)
_enabledDevices.Add(device);
// Will call UpdateBitmapBrush()
ApplyBestDeviceLayout(device);
OnDeviceAdded(new DeviceEventArgs(device));
}
private void RemoveDevice(ArtemisDevice device)
{
_devices.Remove(device);
if (device.IsEnabled)
_enabledDevices.Remove(device);
UpdateBitmapBrush();
OnDeviceRemoved(new DeviceEventArgs(device));
}
#endregion
#region Storage
private ArtemisDevice GetArtemisDevice(IRGBDevice rgbDevice)
{
string deviceIdentifier = rgbDevice.GetDeviceIdentifier();
DeviceEntity? deviceEntity = _deviceRepository.Get(deviceIdentifier);
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
if (deviceEntity != null)
return new ArtemisDevice(rgbDevice, deviceProvider, deviceEntity);
// Fall back on creating a new device
_logger.Information(
"No device config found for {deviceInfo}, device hash: {deviceHashCode}. Adding a new entry.",
rgbDevice.DeviceInfo,
deviceIdentifier
);
return new ArtemisDevice(rgbDevice, deviceProvider);
}
public void SaveDevice(ArtemisDevice artemisDevice)
{
artemisDevice.ApplyToEntity();
artemisDevice.ApplyToRgbDevice();
_deviceRepository.Save(artemisDevice.DeviceEntity);
OnLedsChanged();
}
public void SaveDevices()
{
foreach (ArtemisDevice artemisDevice in _devices)
{
artemisDevice.ApplyToEntity();
artemisDevice.ApplyToRgbDevice();
}
_deviceRepository.Save(_devices.Select(d => d.DeviceEntity));
OnLedsChanged();
}
#endregion
#region Event handlers
private void RenderScaleSettingOnSettingChanged(object? sender, EventArgs e) private void RenderScaleSettingOnSettingChanged(object? sender, EventArgs e)
{ {
// The surface hasn't changed so we can safely reuse it // The surface hasn't changed so we can safely reuse it
UpdateSurfaceLedGroup(BitmapBrush?.Surface); UpdateBitmapBrush();
} }
private void TargetFrameRateSettingOnSettingChanged(object? sender, EventArgs e) private void TargetFrameRateSettingOnSettingChanged(object? sender, EventArgs e)
@ -109,52 +339,29 @@ namespace Artemis.Core.Services
throw args.Exception; throw args.Exception;
} }
#endregion
#region Events #region Events
public event EventHandler<DeviceEventArgs>? DeviceLoaded; public event EventHandler<DeviceEventArgs>? DeviceAdded;
public event EventHandler<DeviceEventArgs>? DeviceReloaded; public event EventHandler<DeviceEventArgs>? DeviceRemoved;
public event EventHandler<DeviceEventArgs> DeviceRemoved; public event EventHandler? LedsChanged;
public void UpdateSurfaceLedGroup(ArtemisSurface? artemisSurface) private void OnDeviceAdded(DeviceEventArgs e)
{ {
if (artemisSurface == null) DeviceAdded?.Invoke(this, e);
return;
if (_surfaceLedGroup == null || BitmapBrush == null)
{
// Apply the application wide brush and decorator
BitmapBrush = new BitmapBrush(new Scale(_renderScaleSetting.Value), _sampleSizeSetting);
_surfaceLedGroup = new ListLedGroup(Surface, artemisSurface.LedMap.Select(l => l.Key)) {Brush = BitmapBrush};
return;
}
lock (_surfaceLedGroup)
{
// Clean up the old background
_surfaceLedGroup.Detach(Surface);
// Apply the application wide brush and decorator
BitmapBrush.Scale = new Scale(_renderScaleSetting.Value);
BitmapBrush.Surface = artemisSurface;
_surfaceLedGroup = new ListLedGroup(Surface, artemisSurface.LedMap.Select(l => l.Key)) {Brush = BitmapBrush};
}
}
private void OnDeviceLoaded(DeviceEventArgs e)
{
DeviceLoaded?.Invoke(this, e);
}
private void OnDeviceReloaded(DeviceEventArgs e)
{
DeviceReloaded?.Invoke(this, e);
} }
protected virtual void OnDeviceRemoved(DeviceEventArgs e) protected virtual void OnDeviceRemoved(DeviceEventArgs e)
{ {
DeviceRemoved?.Invoke(this, e); DeviceRemoved?.Invoke(this, e);
} }
#endregion
protected virtual void OnLedsChanged()
{
LedsChanged?.Invoke(this, EventArgs.Empty);
}
#endregion
} }
} }

View File

@ -1,66 +0,0 @@
using System;
using System.Collections.ObjectModel;
namespace Artemis.Core.Services
{
/// <summary>
/// Provides access to the device surface and its configuration
/// </summary>
public interface ISurfaceService : IArtemisService
{
/// <summary>
/// Gets the currently active surface entity, to change config use <see cref="SetActiveSurfaceConfiguration" />
/// </summary>
ArtemisSurface ActiveSurface { get; }
/// <summary>
/// Gets a read-only list of all surface configurations
/// </summary>
ReadOnlyCollection<ArtemisSurface> SurfaceConfigurations { get; }
/// <summary>
/// Creates a new surface entity with the supplied name
/// </summary>
/// <param name="name">The name for the new surface entity</param>
/// <returns></returns>
ArtemisSurface CreateSurfaceConfiguration(string name);
/// <summary>
/// Sets the provided entity as active and applies it to the surface
/// </summary>
/// <param name="surface">The entity to activate and apply</param>
void SetActiveSurfaceConfiguration(ArtemisSurface surface);
/// <summary>
/// Saves the provided surface entity to permanent storage and if config is active, applies it to the surface
/// </summary>
/// <param name="surface">The entity to save (and apply if active)</param>
/// <param name="includeDevices">Whether to also save devices. If false, devices changes won't be applied either</param>
void UpdateSurfaceConfiguration(ArtemisSurface surface, bool includeDevices);
/// <summary>
/// Deletes the supplied surface entity, surface entity may not be the active surface entity
/// </summary>
/// <param name="surface">The surface entity to delete, may not be the active surface entity</param>
void DeleteSurfaceConfiguration(ArtemisSurface surface);
/// <summary>
/// Applies auto-arranging logic to a surface
/// </summary>
/// <param name="artemisSurface">
/// The surface to apply auto-arrange to. If <see langword="null" /> the
/// <see cref="ActiveSurface" /> is used.
/// </param>
void AutoArrange(ArtemisSurface? artemisSurface = null);
/// <summary>
/// Occurs when the active device entity has been changed
/// </summary>
event EventHandler<SurfaceConfigurationEventArgs> ActiveSurfaceConfigurationSelected;
/// <summary>
/// Occurs when a surface configuration has been updated
/// </summary>
event EventHandler<SurfaceConfigurationEventArgs> SurfaceConfigurationUpdated;
}
}

View File

@ -76,10 +76,10 @@ namespace Artemis.Core.Services.Models
return surfaceArrangementType; return surfaceArrangementType;
} }
public void Arrange(ArtemisSurface surface) public void Arrange(List<ArtemisDevice> devices)
{ {
ArrangedDevices.Clear(); ArrangedDevices.Clear();
foreach (ArtemisDevice surfaceDevice in surface.Devices) foreach (ArtemisDevice surfaceDevice in devices)
{ {
surfaceDevice.X = 0; surfaceDevice.X = 0;
surfaceDevice.Y = 0; surfaceDevice.Y = 0;
@ -87,14 +87,14 @@ namespace Artemis.Core.Services.Models
} }
foreach (SurfaceArrangementType surfaceArrangementType in Types) foreach (SurfaceArrangementType surfaceArrangementType in Types)
surfaceArrangementType.Arrange(surface); surfaceArrangementType.Arrange(devices);
// See if we need to move the surface to keep X and Y values positive // See if we need to move the surface to keep X and Y values positive
double x = surface.Devices.Min(d => d.RgbDevice.Location.X); double x = devices.Min(d => d.RgbDevice.Location.X);
double y = surface.Devices.Min(d => d.RgbDevice.Location.Y); double y = devices.Min(d => d.RgbDevice.Location.Y);
if (x < 0) if (x < 0)
{ {
foreach (ArtemisDevice surfaceDevice in surface.Devices) foreach (ArtemisDevice surfaceDevice in devices)
{ {
surfaceDevice.X += x * -1; surfaceDevice.X += x * -1;
surfaceDevice.ApplyToRgbDevice(); surfaceDevice.ApplyToRgbDevice();
@ -103,7 +103,7 @@ namespace Artemis.Core.Services.Models
if (y < 0) if (y < 0)
{ {
foreach (ArtemisDevice surfaceDevice in surface.Devices) foreach (ArtemisDevice surfaceDevice in devices)
{ {
surfaceDevice.Y += y * -1; surfaceDevice.Y += y * -1;
surfaceDevice.ApplyToRgbDevice(); surfaceDevice.ApplyToRgbDevice();

View File

@ -32,14 +32,14 @@ namespace Artemis.Core.Services.Models
public int MarginBottom { get; } public int MarginBottom { get; }
public SurfaceArrangement SurfaceArrangement { get; set; } public SurfaceArrangement SurfaceArrangement { get; set; }
public bool Apply(List<ArtemisDevice> devices, ArtemisSurface surface) public bool Apply(List<ArtemisDevice> devices)
{ {
if (Anchor != null && !Anchor.HasDevices(surface)) if (Anchor != null && !Anchor.HasDevices(devices))
return false; return false;
// Start at the edge of the anchor, if there is no anchor start at any device // Start at the edge of the anchor, if there is no anchor start at any device
Point startPoint = Anchor?.GetEdge(HorizontalPosition, VerticalPosition, surface) ?? Point startPoint = Anchor?.GetEdge(HorizontalPosition, VerticalPosition) ??
new SurfaceArrangementType(SurfaceArrangement, RGBDeviceType.All, 1).GetEdge(HorizontalPosition, VerticalPosition, surface); new SurfaceArrangementType(SurfaceArrangement, RGBDeviceType.All, 1).GetEdge(HorizontalPosition, VerticalPosition);
// Stack multiple devices of the same type vertically if they are wider than they are tall // Stack multiple devices of the same type vertically if they are wider than they are tall
bool stackVertically = devices.Average(d => d.RgbDevice.Size.Width) >= devices.Average(d => d.RgbDevice.Size.Height); bool stackVertically = devices.Average(d => d.RgbDevice.Size.Width) >= devices.Average(d => d.RgbDevice.Size.Height);

View File

@ -21,21 +21,21 @@ namespace Artemis.Core.Services.Models
public List<SurfaceArrangementConfiguration> Configurations { get; } public List<SurfaceArrangementConfiguration> Configurations { get; }
public SurfaceArrangementConfiguration? AppliedConfiguration { get; set; } public SurfaceArrangementConfiguration? AppliedConfiguration { get; set; }
public bool HasDevices(ArtemisSurface surface) public bool HasDevices(List<ArtemisDevice> devices)
{ {
return surface.Devices.Any(d => d.RgbDevice.DeviceInfo.DeviceType == DeviceType); return devices.Any(d => d.RgbDevice.DeviceInfo.DeviceType == DeviceType);
} }
public void Arrange(ArtemisSurface surface) public void Arrange(List<ArtemisDevice> devices)
{ {
List<ArtemisDevice> devices = surface.Devices.Where(d => d.RgbDevice.DeviceInfo.DeviceType == DeviceType).ToList(); devices = devices.Where(d => d.RgbDevice.DeviceInfo.DeviceType == DeviceType).ToList();
if (!devices.Any()) if (!devices.Any())
return; return;
AppliedConfiguration = null; AppliedConfiguration = null;
foreach (SurfaceArrangementConfiguration configuration in Configurations) foreach (SurfaceArrangementConfiguration configuration in Configurations)
{ {
bool applied = configuration.Apply(devices, surface); bool applied = configuration.Apply(devices);
if (applied) if (applied)
{ {
AppliedConfiguration = configuration; AppliedConfiguration = configuration;
@ -52,11 +52,11 @@ namespace Artemis.Core.Services.Models
VerticalArrangementPosition.Equal, VerticalArrangementPosition.Equal,
10 10
) {SurfaceArrangement = SurfaceArrangement}; ) {SurfaceArrangement = SurfaceArrangement};
fallback.Apply(devices, surface); fallback.Apply(devices);
AppliedConfiguration = fallback; AppliedConfiguration = fallback;
} }
public Point GetEdge(HorizontalArrangementPosition horizontalPosition, VerticalArrangementPosition verticalPosition, ArtemisSurface surface) public Point GetEdge(HorizontalArrangementPosition horizontalPosition, VerticalArrangementPosition verticalPosition)
{ {
List<ArtemisDevice> devices = SurfaceArrangement.ArrangedDevices.Where(d => d.RgbDevice.DeviceInfo.DeviceType == DeviceType || DeviceType == RGBDeviceType.All).ToList(); List<ArtemisDevice> devices = SurfaceArrangement.ArrangedDevices.Where(d => d.RgbDevice.DeviceInfo.DeviceType == DeviceType || DeviceType == RGBDeviceType.All).ToList();
if (!devices.Any()) if (!devices.Any())

View File

@ -14,23 +14,22 @@ namespace Artemis.Core.Services
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IPluginManagementService _pluginManagementService; private readonly IPluginManagementService _pluginManagementService;
private readonly IRgbService _rgbService;
private readonly IProfileRepository _profileRepository; private readonly IProfileRepository _profileRepository;
private readonly ISurfaceService _surfaceService;
public ProfileService(ILogger logger, public ProfileService(ILogger logger,
IPluginManagementService pluginManagementService, IPluginManagementService pluginManagementService,
ISurfaceService surfaceService, IRgbService rgbService,
IConditionOperatorService conditionOperatorService, IConditionOperatorService conditionOperatorService,
IDataBindingService dataBindingService, IDataBindingService dataBindingService,
IProfileRepository profileRepository) IProfileRepository profileRepository)
{ {
_logger = logger; _logger = logger;
_pluginManagementService = pluginManagementService; _pluginManagementService = pluginManagementService;
_surfaceService = surfaceService; _rgbService = rgbService;
_profileRepository = profileRepository; _profileRepository = profileRepository;
_surfaceService.ActiveSurfaceConfigurationSelected += OnActiveSurfaceConfigurationSelected; _rgbService.LedsChanged += RgbServiceOnLedsChanged;
_surfaceService.SurfaceConfigurationUpdated += OnSurfaceConfigurationUpdated;
} }
public JsonSerializerSettings MementoSettings { get; set; } = new() {TypeNameHandling = TypeNameHandling.All}; public JsonSerializerSettings MementoSettings { get; set; } = new() {TypeNameHandling = TypeNameHandling.All};
@ -62,12 +61,11 @@ namespace Artemis.Core.Services
/// <summary> /// <summary>
/// Populates all missing LEDs on all currently active profiles /// Populates all missing LEDs on all currently active profiles
/// </summary> /// </summary>
/// <param name="surface"></param> private void ActiveProfilesPopulateLeds()
private void ActiveProfilesPopulateLeds(ArtemisSurface surface)
{ {
List<ProfileModule> profileModules = _pluginManagementService.GetFeaturesOfType<ProfileModule>(); List<ProfileModule> profileModules = _pluginManagementService.GetFeaturesOfType<ProfileModule>();
foreach (ProfileModule profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList()) foreach (ProfileModule profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList())
profileModule.ActiveProfile?.PopulateLeds(surface); // Avoid race condition profileModule.ActiveProfile?.PopulateLeds(_rgbService.EnabledDevices); // Avoid race condition
} }
public List<ProfileDescriptor> GetProfileDescriptors(ProfileModule module) public List<ProfileDescriptor> GetProfileDescriptors(ProfileModule module)
@ -110,7 +108,7 @@ namespace Artemis.Core.Services
Profile profile = new(profileDescriptor.ProfileModule, profileEntity); Profile profile = new(profileDescriptor.ProfileModule, profileEntity);
InstantiateProfile(profile); InstantiateProfile(profile);
profileDescriptor.ProfileModule.ChangeActiveProfile(profile, _surfaceService.ActiveSurface); profileDescriptor.ProfileModule.ChangeActiveProfile(profile, _rgbService.EnabledDevices);
SaveActiveProfile(profileDescriptor.ProfileModule); SaveActiveProfile(profileDescriptor.ProfileModule);
return profile; return profile;
@ -124,9 +122,9 @@ namespace Artemis.Core.Services
ProfileEntity entity = _profileRepository.Get(module.ActiveProfile.EntityId); ProfileEntity entity = _profileRepository.Get(module.ActiveProfile.EntityId);
Profile profile = new(module, entity); Profile profile = new(module, entity);
InstantiateProfile(profile); InstantiateProfile(profile);
module.ChangeActiveProfile(null, _surfaceService.ActiveSurface); module.ChangeActiveProfile(null, _rgbService.EnabledDevices);
module.ChangeActiveProfile(profile, _surfaceService.ActiveSurface); module.ChangeActiveProfile(profile, _rgbService.EnabledDevices);
} }
public async Task<Profile> ActivateProfileAnimated(ProfileDescriptor profileDescriptor) public async Task<Profile> ActivateProfileAnimated(ProfileDescriptor profileDescriptor)
@ -141,9 +139,9 @@ namespace Artemis.Core.Services
Profile profile = new(profileDescriptor.ProfileModule, profileEntity); Profile profile = new(profileDescriptor.ProfileModule, profileEntity);
InstantiateProfile(profile); InstantiateProfile(profile);
void ActivatingProfileSurfaceUpdate(object? sender, SurfaceConfigurationEventArgs e) void ActivatingRgbServiceOnLedsChanged(object? sender, EventArgs e)
{ {
profile.PopulateLeds(e.Surface); profile.PopulateLeds(_rgbService.EnabledDevices);
} }
void ActivatingProfilePluginToggle(object? sender, PluginEventArgs e) void ActivatingProfilePluginToggle(object? sender, PluginEventArgs e)
@ -154,28 +152,29 @@ namespace Artemis.Core.Services
// This could happen during activation so subscribe to it // This could happen during activation so subscribe to it
_pluginManagementService.PluginEnabled += ActivatingProfilePluginToggle; _pluginManagementService.PluginEnabled += ActivatingProfilePluginToggle;
_pluginManagementService.PluginDisabled += ActivatingProfilePluginToggle; _pluginManagementService.PluginDisabled += ActivatingProfilePluginToggle;
_surfaceService.SurfaceConfigurationUpdated += ActivatingProfileSurfaceUpdate; _rgbService.LedsChanged += ActivatingRgbServiceOnLedsChanged;
await profileDescriptor.ProfileModule.ChangeActiveProfileAnimated(profile, _surfaceService.ActiveSurface); await profileDescriptor.ProfileModule.ChangeActiveProfileAnimated(profile, _rgbService.EnabledDevices);
SaveActiveProfile(profileDescriptor.ProfileModule); SaveActiveProfile(profileDescriptor.ProfileModule);
_pluginManagementService.PluginEnabled -= ActivatingProfilePluginToggle; _pluginManagementService.PluginEnabled -= ActivatingProfilePluginToggle;
_pluginManagementService.PluginDisabled -= ActivatingProfilePluginToggle; _pluginManagementService.PluginDisabled -= ActivatingProfilePluginToggle;
_surfaceService.SurfaceConfigurationUpdated -= ActivatingProfileSurfaceUpdate; _rgbService.LedsChanged -= ActivatingRgbServiceOnLedsChanged;
return profile; return profile;
} }
public void ClearActiveProfile(ProfileModule module) public void ClearActiveProfile(ProfileModule module)
{ {
module.ChangeActiveProfile(null, _surfaceService.ActiveSurface); module.ChangeActiveProfile(null, _rgbService.EnabledDevices);
SaveActiveProfile(module); SaveActiveProfile(module);
} }
public async Task ClearActiveProfileAnimated(ProfileModule module) public async Task ClearActiveProfileAnimated(ProfileModule module)
{ {
await module.ChangeActiveProfileAnimated(null, _surfaceService.ActiveSurface); await module.ChangeActiveProfileAnimated(null, _rgbService.EnabledDevices);
} }
public void DeleteProfile(Profile profile) public void DeleteProfile(Profile profile)
@ -255,7 +254,7 @@ namespace Artemis.Core.Services
string top = profile.RedoStack.Pop(); string top = profile.RedoStack.Pop();
string memento = JsonConvert.SerializeObject(profile.ProfileEntity, MementoSettings); string memento = JsonConvert.SerializeObject(profile.ProfileEntity, MementoSettings);
profile.UndoStack.Push(memento); profile.UndoStack.Push(memento);
profile.ProfileEntity = JsonConvert.DeserializeObject<ProfileEntity>(top, MementoSettings) profile.ProfileEntity = JsonConvert.DeserializeObject<ProfileEntity>(top, MementoSettings)
?? throw new InvalidOperationException("Failed to deserialize memento"); ?? throw new InvalidOperationException("Failed to deserialize memento");
profile.Load(); profile.Load();
@ -268,7 +267,7 @@ namespace Artemis.Core.Services
public void InstantiateProfile(Profile profile) public void InstantiateProfile(Profile profile)
{ {
profile.PopulateLeds(_surfaceService.ActiveSurface); profile.PopulateLeds(_rgbService.EnabledDevices);
} }
public string ExportProfile(ProfileDescriptor profileDescriptor) public string ExportProfile(ProfileDescriptor profileDescriptor)
@ -296,17 +295,11 @@ namespace Artemis.Core.Services
#region Event handlers #region Event handlers
private void OnActiveSurfaceConfigurationSelected(object? sender, SurfaceConfigurationEventArgs e) private void RgbServiceOnLedsChanged(object? sender, EventArgs e)
{ {
ActiveProfilesPopulateLeds(e.Surface); ActiveProfilesPopulateLeds();
} }
private void OnSurfaceConfigurationUpdated(object? sender, SurfaceConfigurationEventArgs e)
{
if (e.Surface.IsActive)
ActiveProfilesPopulateLeds(e.Surface);
}
#endregion #endregion
} }
} }

View File

@ -1,265 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Artemis.Core.DeviceProviders;
using Artemis.Core.Services.Models;
using Artemis.Storage.Entities.Surface;
using Artemis.Storage.Repositories.Interfaces;
using RGB.NET.Core;
using Serilog;
namespace Artemis.Core.Services
{
internal class SurfaceService : ISurfaceService
{
private readonly ILogger _logger;
private readonly IPluginManagementService _pluginManagementService;
private readonly IRgbService _rgbService;
private readonly List<ArtemisSurface> _surfaceConfigurations;
private readonly ISurfaceRepository _surfaceRepository;
public SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, IPluginManagementService pluginManagementService)
{
_logger = logger;
_surfaceRepository = surfaceRepository;
_rgbService = rgbService;
_pluginManagementService = pluginManagementService;
_surfaceConfigurations = new List<ArtemisSurface>();
// LoadFromRepository is guaranteed to set the ActiveSurface
ActiveSurface = null!;
LoadFromRepository();
_rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded;
_rgbService.DeviceRemoved += RgbServiceOnDeviceRemoved;
}
#region Repository
private void LoadFromRepository()
{
List<SurfaceEntity> configs = _surfaceRepository.GetAll();
foreach (SurfaceEntity surfaceEntity in configs)
{
// Create the surface entity
ArtemisSurface surfaceConfiguration = new(_rgbService.Surface, surfaceEntity);
foreach (DeviceEntity position in surfaceEntity.DeviceEntities)
{
IRGBDevice? device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
if (device != null)
{
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(device);
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, deviceProvider, surfaceConfiguration, position));
}
}
// Finally, add the surface config to the collection
lock (_surfaceConfigurations)
{
_surfaceConfigurations.Add(surfaceConfiguration);
}
}
// When all surface configs are loaded, apply the active surface config
ArtemisSurface? active = SurfaceConfigurations.FirstOrDefault(c => c.IsActive);
if (active != null)
{
SetActiveSurfaceConfiguration(active);
}
else
{
active = SurfaceConfigurations.FirstOrDefault();
if (active != null)
SetActiveSurfaceConfiguration(active);
else
SetActiveSurfaceConfiguration(CreateSurfaceConfiguration("Default"));
}
}
#endregion
#region Utilities
private void AddDeviceIfMissing(IRGBDevice rgbDevice, ArtemisSurface surface)
{
string deviceIdentifier = rgbDevice.GetDeviceIdentifier();
ArtemisDevice? device = surface.Devices.FirstOrDefault(d => d.DeviceEntity.DeviceIdentifier == deviceIdentifier);
if (device != null)
return;
// Find an existing device config and use that
DeviceEntity? existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
if (existingDeviceConfig != null)
{
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
device = new ArtemisDevice(rgbDevice, deviceProvider, surface, existingDeviceConfig);
}
// Fall back on creating a new device
else
{
_logger.Information(
"No device config found for {deviceInfo}, device hash: {deviceHashCode}. Adding a new entry.",
rgbDevice.DeviceInfo,
deviceIdentifier
);
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
device = new ArtemisDevice(rgbDevice, deviceProvider, surface);
}
surface.Devices.Add(device);
}
#endregion
public ArtemisSurface ActiveSurface { get; private set; }
public ReadOnlyCollection<ArtemisSurface> SurfaceConfigurations => _surfaceConfigurations.AsReadOnly();
public ArtemisSurface CreateSurfaceConfiguration(string name)
{
// Create a blank config
ArtemisSurface configuration = new(_rgbService.Surface, name);
// Add all current devices
foreach (IRGBDevice rgbDevice in _rgbService.LoadedDevices)
{
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
configuration.Devices.Add(new ArtemisDevice(rgbDevice, deviceProvider, configuration));
}
// Auto-arrange the new config
AutoArrange(configuration);
lock (_surfaceConfigurations)
{
_surfaceRepository.Add(configuration.SurfaceEntity);
_surfaceConfigurations.Add(configuration);
UpdateSurfaceConfiguration(configuration, true);
return configuration;
}
}
public void SetActiveSurfaceConfiguration(ArtemisSurface surface)
{
if (surface == null) throw new ArgumentNullException(nameof(surface));
if (ActiveSurface == surface)
return;
// Set the new entity
ActiveSurface = surface;
// Ensure only the new entity is marked as active
lock (_surfaceConfigurations)
{
// Mark only the new surface as active
foreach (ArtemisSurface configuration in _surfaceConfigurations)
{
configuration.IsActive = configuration == ActiveSurface;
configuration.ApplyToEntity();
_surfaceRepository.Save(configuration.SurfaceEntity);
}
}
// Apply the active surface entity to the devices
foreach (ArtemisDevice device in ActiveSurface.Devices)
device.ApplyToRgbDevice();
// Update the RGB service's graphics decorator to work with the new surface entity
_rgbService.UpdateSurfaceLedGroup(ActiveSurface);
OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(ActiveSurface));
}
public void UpdateSurfaceConfiguration(ArtemisSurface surface, bool includeDevices)
{
surface.ApplyToEntity();
if (includeDevices)
foreach (ArtemisDevice deviceConfiguration in surface.Devices)
{
deviceConfiguration.ApplyToEntity();
if (surface.IsActive)
deviceConfiguration.ApplyToRgbDevice();
}
surface.UpdateLedMap();
_surfaceRepository.Save(surface.SurfaceEntity);
_rgbService.UpdateSurfaceLedGroup(ActiveSurface);
OnSurfaceConfigurationUpdated(new SurfaceConfigurationEventArgs(surface));
}
public void DeleteSurfaceConfiguration(ArtemisSurface surface)
{
if (surface == ActiveSurface)
throw new ArtemisCoreException($"Cannot delete surface entity '{surface.Name}' because it is active.");
lock (_surfaceConfigurations)
{
SurfaceEntity entity = surface.SurfaceEntity;
_surfaceConfigurations.Remove(surface);
_surfaceRepository.Remove(entity);
}
}
#region AutoLayout
public void AutoArrange(ArtemisSurface? artemisSurface = null)
{
artemisSurface ??= ActiveSurface;
if (!artemisSurface.Devices.Any())
return;
SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement();
surfaceArrangement.Arrange(artemisSurface);
UpdateSurfaceConfiguration(artemisSurface, true);
}
#endregion
#region Event handlers
private void RgbServiceOnDeviceLoaded(object? sender, DeviceEventArgs e)
{
lock (_surfaceConfigurations)
{
foreach (ArtemisSurface surfaceConfiguration in _surfaceConfigurations)
AddDeviceIfMissing(e.Device, surfaceConfiguration);
}
UpdateSurfaceConfiguration(ActiveSurface, true);
}
private void RgbServiceOnDeviceRemoved(object? sender, DeviceEventArgs e)
{
lock (_surfaceConfigurations)
{
foreach (ArtemisSurface surfaceConfiguration in _surfaceConfigurations)
surfaceConfiguration.Devices.RemoveAll(d => d.RgbDevice == e.Device);
}
UpdateSurfaceConfiguration(ActiveSurface, true);
}
#endregion
#region Events
public event EventHandler<SurfaceConfigurationEventArgs>? ActiveSurfaceConfigurationSelected;
public event EventHandler<SurfaceConfigurationEventArgs>? SurfaceConfigurationUpdated;
protected virtual void OnActiveSurfaceConfigurationChanged(SurfaceConfigurationEventArgs e)
{
ActiveSurfaceConfigurationSelected?.Invoke(this, e);
}
protected virtual void OnSurfaceConfigurationUpdated(SurfaceConfigurationEventArgs e)
{
SurfaceConfigurationUpdated?.Invoke(this, e);
}
#endregion
}
}

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Artemis.Core.Modules; using Artemis.Core.Modules;
@ -13,13 +14,13 @@ namespace Artemis.Core
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
private readonly ISurfaceService _surfaceService; private readonly IEnumerable<ArtemisDevice> _devices;
public IntroAnimation(ILogger logger, IProfileService profileService, ISurfaceService surfaceService) public IntroAnimation(ILogger logger, IProfileService profileService, IEnumerable<ArtemisDevice> devices)
{ {
_logger = logger; _logger = logger;
_profileService = profileService; _profileService = profileService;
_surfaceService = surfaceService; _devices = devices;
AnimationProfile = CreateIntroProfile(); AnimationProfile = CreateIntroProfile();
} }
@ -41,14 +42,14 @@ namespace Artemis.Core
ProfileEntity profileEntity = CoreJson.DeserializeObject<ProfileEntity>(json)!; ProfileEntity profileEntity = CoreJson.DeserializeObject<ProfileEntity>(json)!;
// Inject every LED on the surface into each layer // Inject every LED on the surface into each layer
foreach (LayerEntity profileEntityLayer in profileEntity.Layers) foreach (LayerEntity profileEntityLayer in profileEntity.Layers)
profileEntityLayer.Leds.AddRange(_surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds).Select(l => new LedEntity profileEntityLayer.Leds.AddRange(_devices.SelectMany(d => d.Leds).Select(l => new LedEntity
{ {
DeviceIdentifier = l.Device.RgbDevice.GetDeviceIdentifier(), DeviceIdentifier = l.Device.RgbDevice.GetDeviceIdentifier(),
LedName = l.RgbLed.Id.ToString() LedName = l.RgbLed.Id.ToString()
})); }));
Profile profile = new(new DummyModule(), profileEntity); Profile profile = new(new DummyModule(), profileEntity);
profile.Activate(_surfaceService.ActiveSurface); profile.Activate(_devices);
_profileService.InstantiateProfile(profile); _profileService.InstantiateProfile(profile);
return profile; return profile;
@ -79,7 +80,7 @@ namespace Artemis.Core
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo) public override void Render(double deltaTime, SKCanvas canvas, SKImageInfo canvasInfo)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@ -8,8 +8,8 @@ namespace Artemis.Storage.Entities.Surface
{ {
InputIdentifiers = new List<DeviceInputIdentifierEntity>(); InputIdentifiers = new List<DeviceInputIdentifierEntity>();
} }
public string DeviceIdentifier { get; set; } public string Id { get; set; }
public double X { get; set; } public double X { get; set; }
public double Y { get; set; } public double Y { get; set; }
public double Rotation { get; set; } public double Rotation { get; set; }

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
namespace Artemis.Storage.Entities.Surface
{
public class SurfaceEntity
{
public Guid Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public List<DeviceEntity> DeviceEntities { get; set; }
}
}

View File

@ -0,0 +1,48 @@
using System.Collections.Generic;
using Artemis.Storage.Entities.Surface;
using Artemis.Storage.Repositories.Interfaces;
using LiteDB;
namespace Artemis.Storage.Repositories
{
internal class DeviceRepository : IDeviceRepository
{
private readonly LiteRepository _repository;
public DeviceRepository(LiteRepository repository)
{
_repository = repository;
_repository.Database.GetCollection<DeviceEntity>().EnsureIndex(s => s.Id);
}
public void Add(DeviceEntity deviceEntity)
{
_repository.Insert(deviceEntity);
}
public void Remove(DeviceEntity deviceEntity)
{
_repository.Delete<DeviceEntity>(deviceEntity.Id);
}
public DeviceEntity Get(string id)
{
return _repository.FirstOrDefault<DeviceEntity>(s => s.Id == id);
}
public List<DeviceEntity> GetAll()
{
return _repository.Query<DeviceEntity>().Include(s => s.InputIdentifiers).ToList();
}
public void Save(DeviceEntity deviceEntity)
{
_repository.Upsert(deviceEntity);
}
public void Save(IEnumerable<DeviceEntity> deviceEntities)
{
_repository.Upsert(deviceEntities);
}
}
}

View File

@ -0,0 +1,15 @@
using System.Collections.Generic;
using Artemis.Storage.Entities.Surface;
namespace Artemis.Storage.Repositories.Interfaces
{
public interface IDeviceRepository : IRepository
{
void Add(DeviceEntity deviceEntity);
void Remove(DeviceEntity deviceEntity);
DeviceEntity Get(string id);
List<DeviceEntity> GetAll();
void Save(DeviceEntity deviceEntity);
void Save(IEnumerable<DeviceEntity> deviceEntities);
}
}

View File

@ -1,15 +0,0 @@
using System.Collections.Generic;
using Artemis.Storage.Entities.Surface;
namespace Artemis.Storage.Repositories.Interfaces
{
public interface ISurfaceRepository : IRepository
{
void Add(SurfaceEntity surfaceEntity);
void Remove(SurfaceEntity surfaceEntity);
SurfaceEntity GetByName(string name);
List<SurfaceEntity> GetAll();
void Save(SurfaceEntity surfaceEntity);
}
}

View File

@ -1,44 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Storage.Entities.Surface;
using Artemis.Storage.Repositories.Interfaces;
using LiteDB;
namespace Artemis.Storage.Repositories
{
internal class SurfaceRepository : ISurfaceRepository
{
private readonly LiteRepository _repository;
public SurfaceRepository(LiteRepository repository)
{
_repository = repository;
_repository.Database.GetCollection<SurfaceEntity>().EnsureIndex(s => s.Name);
}
public void Add(SurfaceEntity surfaceEntity)
{
_repository.Insert(surfaceEntity);
}
public void Remove(SurfaceEntity surfaceEntity)
{
_repository.Delete<SurfaceEntity>(surfaceEntity.Id);
}
public SurfaceEntity GetByName(string name)
{
return _repository.FirstOrDefault<SurfaceEntity>(s => s.Name == name);
}
public List<SurfaceEntity> GetAll()
{
return _repository.Query<SurfaceEntity>().Include(s => s.DeviceEntities.Select(de => de.InputIdentifiers)).ToList();
}
public void Save(SurfaceEntity surfaceEntity)
{
_repository.Upsert(surfaceEntity);
}
}
}

View File

@ -182,7 +182,11 @@ namespace Artemis.UI.Shared
if (_oldDevice != null) if (_oldDevice != null)
{ {
if (Device != null) if (Device != null)
{
Device.RgbDevice.PropertyChanged -= DevicePropertyChanged; Device.RgbDevice.PropertyChanged -= DevicePropertyChanged;
Device.DeviceUpdated -= DeviceUpdated;
}
_oldDevice = null; _oldDevice = null;
} }
} }
@ -228,10 +232,15 @@ namespace Artemis.UI.Shared
return; return;
if (_oldDevice != null) if (_oldDevice != null)
{
Device.RgbDevice.PropertyChanged -= DevicePropertyChanged; Device.RgbDevice.PropertyChanged -= DevicePropertyChanged;
Device.DeviceUpdated -= DeviceUpdated;
}
_oldDevice = Device; _oldDevice = Device;
Device.RgbDevice.PropertyChanged += DevicePropertyChanged; Device.RgbDevice.PropertyChanged += DevicePropertyChanged;
Device.DeviceUpdated += DeviceUpdated;
UpdateTransform(); UpdateTransform();
// Load the device main image // Load the device main image
@ -277,13 +286,16 @@ namespace Artemis.UI.Shared
InvalidateMeasure(); InvalidateMeasure();
} }
private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e) private void DeviceUpdated(object sender, EventArgs e)
{ {
if (e.PropertyName == nameof(Device.RgbDevice.Scale) || e.PropertyName == nameof(Device.RgbDevice.Rotation)) SetupForDevice();
UpdateTransform();
} }
private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e)
{
SetupForDevice();
}
private void Render() private void Render()
{ {
DrawingContext drawingContext = _backingStore.Open(); DrawingContext drawingContext = _backingStore.Open();

View File

@ -8,7 +8,6 @@ using Artemis.Core.Modules;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.Storage.Entities.Profile; using Artemis.Storage.Entities.Profile;
using Artemis.UI.Shared.Services.Models; using Artemis.UI.Shared.Services.Models;
using Newtonsoft.Json;
using Ninject; using Ninject;
using Ninject.Parameters; using Ninject.Parameters;
using Serilog; using Serilog;
@ -20,23 +19,23 @@ namespace Artemis.UI.Shared.Services
internal class ProfileEditorService : IProfileEditorService internal class ProfileEditorService : IProfileEditorService
{ {
private readonly ICoreService _coreService; private readonly ICoreService _coreService;
private readonly ISurfaceService _surfaceService;
private readonly IKernel _kernel; private readonly IKernel _kernel;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
private readonly List<PropertyInputRegistration> _registeredPropertyEditors; private readonly List<PropertyInputRegistration> _registeredPropertyEditors;
private readonly IRgbService _rgbService;
private readonly object _selectedProfileElementLock = new(); private readonly object _selectedProfileElementLock = new();
private readonly object _selectedProfileLock = new(); private readonly object _selectedProfileLock = new();
private TimeSpan _currentTime; private TimeSpan _currentTime;
private int _pixelsPerSecond; private int _pixelsPerSecond;
public ProfileEditorService(IKernel kernel, ILogger logger, IProfileService profileService, ICoreService coreService, ISurfaceService surfaceService) public ProfileEditorService(IKernel kernel, ILogger logger, IProfileService profileService, ICoreService coreService, IRgbService rgbService)
{ {
_kernel = kernel; _kernel = kernel;
_logger = logger; _logger = logger;
_profileService = profileService; _profileService = profileService;
_coreService = coreService; _coreService = coreService;
_surfaceService = surfaceService; _rgbService = rgbService;
_registeredPropertyEditors = new List<PropertyInputRegistration>(); _registeredPropertyEditors = new List<PropertyInputRegistration>();
PixelsPerSecond = 100; PixelsPerSecond = 100;
@ -351,7 +350,7 @@ namespace Artemis.UI.Shared.Services
public List<ArtemisLed> GetLedsInRectangle(Rect rect) public List<ArtemisLed> GetLedsInRectangle(Rect rect)
{ {
return _surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds).Where(led => led.AbsoluteRectangle.IntersectsWith(rect.ToSKRect())).ToList(); return _rgbService.EnabledDevices.SelectMany(d => d.Leds).Where(led => led.AbsoluteRectangle.IntersectsWith(rect.ToSKRect())).ToList();
} }
#region Copy/paste #region Copy/paste
@ -424,7 +423,7 @@ namespace Artemis.UI.Shared.Services
if (pasted != null) if (pasted != null)
{ {
target.Profile.PopulateLeds(_surfaceService.ActiveSurface); target.Profile.PopulateLeds(_rgbService.EnabledDevices);
UpdateSelectedProfile(); UpdateSelectedProfile();
ChangeSelectedProfileElement(pasted); ChangeSelectedProfileElement(pasted);
} }

View File

@ -1,360 +1,361 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework> <TargetFramework>net5.0-windows</TargetFramework>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<AssemblyTitle>Artemis</AssemblyTitle> <AssemblyTitle>Artemis</AssemblyTitle>
<Product>Artemis</Product> <Product>Artemis</Product>
<NeutralLanguage>en-US</NeutralLanguage> <NeutralLanguage>en-US</NeutralLanguage>
<Description>Provides advanced unified lighting across many different brands RGB peripherals</Description> <Description>Provides advanced unified lighting across many different brands RGB peripherals</Description>
<Copyright>Copyright © Robert Beekman - 2021</Copyright> <Copyright>Copyright © Robert Beekman - 2021</Copyright>
<FileVersion>2.0.0.0</FileVersion> <FileVersion>2.0.0.0</FileVersion>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath> <OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<Platforms>x64</Platforms> <Platforms>x64</Platforms>
</PropertyGroup> <SupportedPlatform>windows</SupportedPlatform>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> </PropertyGroup>
<PlatformTarget>x64</PlatformTarget> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PropertyGroup> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ApplicationIcon>Resources\Images\Logo\logo-512.ico</ApplicationIcon> <ApplicationIcon>Resources\Images\Logo\logo-512.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PostBuildEvent /> <PostBuildEvent />
<AssemblyVersion>2.0.0.0</AssemblyVersion> <AssemblyVersion>2.0.0.0</AssemblyVersion>
<Version>2.0.0</Version> <Version>2.0.0</Version>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<NrtRevisionFormat>2.0-{chash:6}</NrtRevisionFormat> <NrtRevisionFormat>2.0-{chash:6}</NrtRevisionFormat>
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes> <NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
<NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute> <NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute>
<NrtResolveCopyright>true</NrtResolveCopyright> <NrtResolveCopyright>true</NrtResolveCopyright>
<NrtTagMatch>v[0-9]*</NrtTagMatch> <NrtTagMatch>v[0-9]*</NrtTagMatch>
<NrtRemoveTagV>true</NrtRemoveTagV> <NrtRemoveTagV>true</NrtRemoveTagV>
<NrtRequiredVcs>git</NrtRequiredVcs> <NrtRequiredVcs>git</NrtRequiredVcs>
<NrtShowRevision>true</NrtShowRevision> <NrtShowRevision>true</NrtShowRevision>
</PropertyGroup> </PropertyGroup>
<Target Name="SkiaCleanUpAfterBuild" AfterTargets="AfterBuild"> <Target Name="SkiaCleanUpAfterBuild" AfterTargets="AfterBuild">
<Delete Files="$(OutputPath)\libSkiaSharp.dylib" /> <Delete Files="$(OutputPath)\libSkiaSharp.dylib" />
</Target> </Target>
<ItemGroup> <ItemGroup>
<FluentValidationExcludedCultures Include="ar-DZ;cs;cs-CZ;da;de;es;fa;fi;fr;fr-FR;it;ko;mk;nl;pl;pt;pt-BR;ru;ru-ru;sv;tr;zh-CN;uz-Latn-UZ"> <FluentValidationExcludedCultures Include="ar-DZ;cs;cs-CZ;da;de;es;fa;fi;fr;fr-FR;it;ko;mk;nl;pl;pt;pt-BR;ru;ru-ru;sv;tr;zh-CN;uz-Latn-UZ">
<InProject>false</InProject> <InProject>false</InProject>
</FluentValidationExcludedCultures> </FluentValidationExcludedCultures>
</ItemGroup> </ItemGroup>
<Target Name="RemoveTranslationsAfterBuild" AfterTargets="AfterBuild"> <Target Name="RemoveTranslationsAfterBuild" AfterTargets="AfterBuild">
<RemoveDir Directories="@(FluentValidationExcludedCultures->'$(OutputPath)%(Filename)')" /> <RemoveDir Directories="@(FluentValidationExcludedCultures->'$(OutputPath)%(Filename)')" />
</Target> </Target>
<ItemGroup> <ItemGroup>
<Compile Remove="publish\**" /> <Compile Remove="publish\**" />
<EmbeddedResource Remove="publish\**" /> <EmbeddedResource Remove="publish\**" />
<None Remove="publish\**" /> <None Remove="publish\**" />
<Page Remove="publish\**" /> <Page Remove="publish\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<!-- TODO: Remove when moving to Nuget, this is so the plugin templates have the DLL to reference --> <!-- TODO: Remove when moving to Nuget, this is so the plugin templates have the DLL to reference -->
<Reference Include="RGB.NET.Brushes"> <Reference Include="RGB.NET.Brushes">
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Brushes.dll</HintPath> <HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Brushes.dll</HintPath>
</Reference> </Reference>
<Reference Include="RGB.NET.Core"> <Reference Include="RGB.NET.Core">
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll</HintPath> <HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="RGB.NET.Groups"> <Reference Include="RGB.NET.Groups">
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Groups.dll</HintPath> <HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Groups.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Management" /> <Reference Include="System.Management" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx"> <EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj"> <ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj">
<Private>true</Private> <Private>true</Private>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj"> <ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj">
<Private>true</Private> <Private>true</Private>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj"> <ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj">
<Private>true</Private> <Private>true</Private>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Fonts\RobotoMono-Regular.ttf" /> <Resource Include="Resources\Fonts\RobotoMono-Regular.ttf" />
<Resource Include="Resources\Images\Logo\bow.svg" /> <Resource Include="Resources\Images\Logo\bow.svg" />
<Resource Include="Resources\Images\Logo\logo-512.ico" /> <Resource Include="Resources\Images\Logo\logo-512.ico" />
<Resource Include="Resources\Images\Logo\logo-512.png" /> <Resource Include="Resources\Images\Logo\logo-512.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate_tl.cur" /> <Resource Include="Resources\Cursors\aero_rotate_tl.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate_tr.cur" /> <Resource Include="Resources\Cursors\aero_rotate_tr.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate_bl.cur" /> <Resource Include="Resources\Cursors\aero_rotate_bl.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate_br.cur" /> <Resource Include="Resources\Cursors\aero_rotate_br.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_crosshair.cur" /> <Resource Include="Resources\Cursors\aero_crosshair.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_crosshair_minus.cur" /> <Resource Include="Resources\Cursors\aero_crosshair_minus.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_crosshair_plus.cur" /> <Resource Include="Resources\Cursors\aero_crosshair_plus.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_pen_min.cur" /> <Resource Include="Resources\Cursors\aero_pen_min.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_pen_plus.cur" /> <Resource Include="Resources\Cursors\aero_pen_plus.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_fill.cur" /> <Resource Include="Resources\Cursors\aero_fill.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_drag.cur" /> <Resource Include="Resources\Cursors\aero_drag.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_drag_ew.cur" /> <Resource Include="Resources\Cursors\aero_drag_ew.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate.cur" /> <Resource Include="Resources\Cursors\aero_rotate.cur" />
<Resource Include="Resources\Images\Sidebar\sidebar-header.png" /> <Resource Include="Resources\Images\Sidebar\sidebar-header.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FluentValidation" Version="9.3.0" /> <PackageReference Include="FluentValidation" Version="9.3.0" />
<PackageReference Include="Flurl.Http" Version="3.0.1" /> <PackageReference Include="Flurl.Http" Version="3.0.1" />
<PackageReference Include="gong-wpf-dragdrop" Version="2.3.2" /> <PackageReference Include="gong-wpf-dragdrop" Version="2.3.2" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.14" /> <PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.14" />
<PackageReference Include="Humanizer.Core" Version="2.8.26" /> <PackageReference Include="Humanizer.Core" Version="2.8.26" />
<PackageReference Include="MaterialDesignExtensions" Version="3.3.0-a01" /> <PackageReference Include="MaterialDesignExtensions" Version="3.3.0-a01" />
<PackageReference Include="MaterialDesignThemes" Version="3.2.0" /> <PackageReference Include="MaterialDesignThemes" Version="3.2.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" /> <PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" /> <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" />
<PackageReference Include="Ninject" Version="3.3.4" /> <PackageReference Include="Ninject" Version="3.3.4" />
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" /> <PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="3.1.0" /> <PackageReference Include="Ookii.Dialogs.Wpf" Version="3.1.0" />
<PackageReference Include="RawInput.Sharp" Version="0.0.3" /> <PackageReference Include="RawInput.Sharp" Version="0.0.3" />
<PackageReference Include="Serilog" Version="2.10.0" /> <PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" /> <PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" />
<PackageReference Include="Stylet" Version="1.3.5" /> <PackageReference Include="Stylet" Version="1.3.5" />
<PackageReference Include="System.Buffers" Version="4.5.1" /> <PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Drawing.Common" Version="5.0.0" /> <PackageReference Include="System.Drawing.Common" Version="5.0.0" />
<PackageReference Include="System.Management" Version="5.0.0" /> <PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" /> <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.3.0"> <PackageReference Include="Unclassified.NetRevisionTask" Version="0.3.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="obj\x64\Debug\App.g.cs" /> <Compile Remove="obj\x64\Debug\App.g.cs" />
<Compile Remove="obj\x64\Debug\App.g.i.cs" /> <Compile Remove="obj\x64\Debug\App.g.i.cs" />
<Compile Remove="obj\x64\Debug\GeneratedInternalTypeHelper.g.cs" /> <Compile Remove="obj\x64\Debug\GeneratedInternalTypeHelper.g.cs" />
<Compile Remove="obj\x64\Debug\GeneratedInternalTypeHelper.g.i.cs" /> <Compile Remove="obj\x64\Debug\GeneratedInternalTypeHelper.g.i.cs" />
<Compile Remove="obj\x64\Release\App.g.cs" /> <Compile Remove="obj\x64\Release\App.g.cs" />
<Compile Remove="obj\x64\Release\GeneratedInternalTypeHelper.g.cs" /> <Compile Remove="obj\x64\Release\GeneratedInternalTypeHelper.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\RootView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\RootView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\RootView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\RootView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\RootView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\RootView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Dialogs\ConfirmDialogView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Dialogs\ConfirmDialogView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Dialogs\ConfirmDialogView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Dialogs\ConfirmDialogView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\GradientEditor\GradientEditorView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\GradientEditor\GradientEditorView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\GradientEditor\GradientEditorView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\GradientEditor\GradientEditorView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Home\HomeView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Home\HomeView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Home\HomeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Home\HomeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ModuleRootView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ModuleRootView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ModuleRootView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ModuleRootView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\News\NewsView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\News\NewsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\News\NewsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\News\NewsView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\SettingsView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\SettingsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\SettingsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\SettingsView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Sidebar\SidebarView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Sidebar\SidebarView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Sidebar\SidebarView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Sidebar\SidebarView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Splash\SplashView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Splash\SplashView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Splash\SplashView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Splash\SplashView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\SurfaceEditorView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\SurfaceEditorView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\SurfaceEditorView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\SurfaceEditorView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Workshop\WorkshopView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Workshop\WorkshopView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Workshop\WorkshopView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Workshop\WorkshopView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\Dialogs\ConfirmDialogView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Dialogs\ConfirmDialogView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Home\HomeView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Home\HomeView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ModuleRootView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ModuleRootView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\News\NewsView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\News\NewsView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Settings\SettingsView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Settings\SettingsView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Splash\SplashView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Splash\SplashView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Workshop\WorkshopView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Workshop\WorkshopView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileEditorView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileEditorView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileEditorView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileEditorView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\Debug\DebugView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\Debug\DebugView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\Debug\DebugView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\Debug\DebugView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ProfileEditorView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ProfileEditorView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Settings\Debug\DebugView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Settings\Debug\DebugView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Layers\LayersView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Layers\LayersView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\ProfileTreeView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\ProfileTreeView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\ProfileTreeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\ProfileTreeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLayerView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLayerView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLayerView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLayerView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Layers\LayersView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Layers\LayersView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\Dialogs\AddLayerElementView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\Dialogs\AddLayerElementView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeItemView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeItemView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\LayerPropertiesTimelineView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\LayerPropertiesTimelineView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyRailItemView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyRailItemView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineKeyframeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineKeyframeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePartView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePartView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyRailView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyRailView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineTimeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineTimeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EditToolView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EditToolView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EditToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EditToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EllipseToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EllipseToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\FillToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\FillToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\PolygonToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\PolygonToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\RectangleToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\RectangleToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionAddToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionAddToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionRemoveToolView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionRemoveToolView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionRemoveToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionRemoveToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionToolView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionToolView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\ViewpointMoveToolView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\ViewpointMoveToolView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\ViewpointMoveToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\ViewpointMoveToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\UserControls\LayerShapeControl.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\UserControls\LayerShapeControl.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\UserControls\LayerShapeControl.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\UserControls\LayerShapeControl.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\BrushPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\BrushPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\BrushPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\BrushPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\EnumPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\EnumPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\EnumPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\EnumPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\FloatPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\FloatPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\FloatPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\FloatPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView - Copy.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView - Copy.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKColorPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKColorPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKColorPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKColorPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKPointPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKPointPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKPointPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKPointPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKSizePropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKSizePropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKSizePropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKSizePropertyInputView.g.i.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="Resources\Fonts\RobotoMono-Regular.ttf" /> <None Remove="Resources\Fonts\RobotoMono-Regular.ttf" />
<None Remove="Resources\Images\Logo\bow.svg" /> <None Remove="Resources\Images\Logo\bow.svg" />
<None Remove="Resources\Images\Logo\logo-512.ico" /> <None Remove="Resources\Images\Logo\logo-512.ico" />
<None Remove="Resources\Images\Sidebar\sidebar-header.png" /> <None Remove="Resources\Images\Sidebar\sidebar-header.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" /> <None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Properties\Resources.Designer.cs"> <Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Update="Properties\Settings.Designer.cs"> <Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="buildinfo.json"> <None Update="buildinfo.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Update="Properties\Settings.settings"> <None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Update="DefaultTypes\DataModel\Display\SKColorDataModelDisplayView.xaml"> <Page Update="DefaultTypes\DataModel\Display\SKColorDataModelDisplayView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="DefaultTypes\DataModel\Input\DoubleDataModelInputView.xaml"> <Page Update="DefaultTypes\DataModel\Input\DoubleDataModelInputView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="DefaultTypes\DataModel\Input\IntDataModelInputView.xaml"> <Page Update="DefaultTypes\DataModel\Input\IntDataModelInputView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="DefaultTypes\DataModel\Input\SKColorDataModelInputView.xaml"> <Page Update="DefaultTypes\DataModel\Input\SKColorDataModelInputView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="DefaultTypes\DataModel\Input\StringDataModelInputView.xaml"> <Page Update="DefaultTypes\DataModel\Input\StringDataModelInputView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="DefaultTypes\PropertyInput\FloatRangePropertyInputView.xaml"> <Page Update="DefaultTypes\PropertyInput\FloatRangePropertyInputView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="Screens\ProfileEditor\Dialogs\ProfileEditView.xaml"> <Page Update="Screens\ProfileEditor\Dialogs\ProfileEditView.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime> <XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page> </Page>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -9,12 +9,12 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
{ {
// I hate this about DI, oh well // I hate this about DI, oh well
public FolderViewModel(ProfileElement folder, public FolderViewModel(ProfileElement folder,
IRgbService rgbService,
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IDialogService dialogService, IDialogService dialogService,
IProfileTreeVmFactory profileTreeVmFactory, IProfileTreeVmFactory profileTreeVmFactory,
ILayerBrushService layerBrushService, ILayerBrushService layerBrushService) :
ISurfaceService surfaceService) : base(folder, rgbService, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService)
base(folder, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService, surfaceService)
{ {
} }

View File

@ -8,12 +8,12 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
public class LayerViewModel : TreeItemViewModel public class LayerViewModel : TreeItemViewModel
{ {
public LayerViewModel(ProfileElement layer, public LayerViewModel(ProfileElement layer,
IRgbService rgbService,
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IDialogService dialogService, IDialogService dialogService,
IProfileTreeVmFactory profileTreeVmFactory, IProfileTreeVmFactory profileTreeVmFactory,
ILayerBrushService layerBrushService, ILayerBrushService layerBrushService) :
ISurfaceService surfaceService) : base(layer, rgbService, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService)
base(layer, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService, surfaceService)
{ {
} }

View File

@ -18,23 +18,23 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
{ {
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly ILayerBrushService _layerBrushService; private readonly ILayerBrushService _layerBrushService;
private readonly IRgbService _rgbService;
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private readonly IProfileTreeVmFactory _profileTreeVmFactory; private readonly IProfileTreeVmFactory _profileTreeVmFactory;
private readonly ISurfaceService _surfaceService;
private ProfileElement _profileElement; private ProfileElement _profileElement;
protected TreeItemViewModel(ProfileElement profileElement, protected TreeItemViewModel(ProfileElement profileElement,
IRgbService rgbService,
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IDialogService dialogService, IDialogService dialogService,
IProfileTreeVmFactory profileTreeVmFactory, IProfileTreeVmFactory profileTreeVmFactory,
ILayerBrushService layerBrushService, ILayerBrushService layerBrushService)
ISurfaceService surfaceService)
{ {
_rgbService = rgbService;
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_dialogService = dialogService; _dialogService = dialogService;
_profileTreeVmFactory = profileTreeVmFactory; _profileTreeVmFactory = profileTreeVmFactory;
_layerBrushService = layerBrushService; _layerBrushService = layerBrushService;
_surfaceService = surfaceService;
ProfileElement = profileElement; ProfileElement = profileElement;
@ -144,7 +144,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
if (brush != null) if (brush != null)
layer.ChangeLayerBrush(brush); layer.ChangeLayerBrush(brush);
layer.AddLeds(_surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds)); layer.AddLeds(_rgbService.EnabledDevices.SelectMany(d => d.Leds));
_profileEditorService.UpdateSelectedProfile(); _profileEditorService.UpdateSelectedProfile();
_profileEditorService.ChangeSelectedProfileElement(layer); _profileEditorService.ChangeSelectedProfileElement(layer);
} }

View File

@ -99,7 +99,10 @@
</ItemsControl> </ItemsControl>
</Grid> </Grid>
<Grid Name="EditorDisplayGrid"> <Grid Name="EditorDisplayGrid"
shared:SizeObserver.Observe="True"
shared:SizeObserver.ObservedHeight="{Binding PanZoomViewModel.CanvasHeight}"
shared:SizeObserver.ObservedWidth="{Binding PanZoomViewModel.CanvasWidth}">
<Grid.RenderTransform> <Grid.RenderTransform>
<TransformGroup> <TransformGroup>
<ScaleTransform ScaleX="{Binding PanZoomViewModel.Zoom}" ScaleY="{Binding PanZoomViewModel.Zoom}" /> <ScaleTransform ScaleX="{Binding PanZoomViewModel.Zoom}" ScaleY="{Binding PanZoomViewModel.Zoom}" />

View File

@ -6,48 +6,48 @@ using System.Windows.Input;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Events; using Artemis.UI.Events;
using Artemis.UI.Extensions;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.Visualization.Tools; using Artemis.UI.Screens.ProfileEditor.Visualization.Tools;
using Artemis.UI.Screens.Shared; using Artemis.UI.Screens.Shared;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using SkiaSharp;
using Stylet; using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.Visualization namespace Artemis.UI.Screens.ProfileEditor.Visualization
{ {
public class ProfileViewModel : Conductor<CanvasViewModel>.Collection.AllActive, IProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent> public class ProfileViewModel : Conductor<CanvasViewModel>.Collection.AllActive, IProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
{ {
private readonly IProfileEditorService _profileEditorService;
private readonly ICoreService _coreService; private readonly ICoreService _coreService;
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileLayerVmFactory _profileLayerVmFactory; private readonly IProfileLayerVmFactory _profileLayerVmFactory;
private readonly IRgbService _rgbService;
private readonly ISettingsService _settingsService; private readonly ISettingsService _settingsService;
private readonly ISurfaceService _surfaceService;
private readonly IVisualizationToolVmFactory _visualizationToolVmFactory; private readonly IVisualizationToolVmFactory _visualizationToolVmFactory;
private int _activeToolIndex; private int _activeToolIndex;
private VisualizationToolViewModel _activeToolViewModel; private VisualizationToolViewModel _activeToolViewModel;
private PluginSetting<bool> _alwaysApplyDataBindings;
private bool _canApplyToLayer; private bool _canApplyToLayer;
private bool _canSelectEditTool; private bool _canSelectEditTool;
private BindableCollection<ArtemisDevice> _devices; private BindableCollection<ArtemisDevice> _devices;
private BindableCollection<ArtemisLed> _highlightedLeds; private BindableCollection<ArtemisLed> _highlightedLeds;
private PluginSetting<bool> _highlightSelectedLayer; private PluginSetting<bool> _highlightSelectedLayer;
private PluginSetting<bool> _alwaysApplyDataBindings; private DateTime _lastUpdate;
private PanZoomViewModel _panZoomViewModel; private PanZoomViewModel _panZoomViewModel;
private Layer _previousSelectedLayer; private Layer _previousSelectedLayer;
private int _previousTool; private int _previousTool;
private DateTime _lastUpdate;
public ProfileViewModel(IProfileEditorService profileEditorService, public ProfileViewModel(IProfileEditorService profileEditorService,
IRgbService rgbService,
ICoreService coreService, ICoreService coreService,
ISurfaceService surfaceService,
ISettingsService settingsService, ISettingsService settingsService,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IVisualizationToolVmFactory visualizationToolVmFactory, IVisualizationToolVmFactory visualizationToolVmFactory,
IProfileLayerVmFactory profileLayerVmFactory) IProfileLayerVmFactory profileLayerVmFactory)
{ {
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_rgbService = rgbService;
_coreService = coreService; _coreService = coreService;
_surfaceService = surfaceService;
_settingsService = settingsService; _settingsService = settingsService;
_visualizationToolVmFactory = visualizationToolVmFactory; _visualizationToolVmFactory = visualizationToolVmFactory;
_profileLayerVmFactory = profileLayerVmFactory; _profileLayerVmFactory = profileLayerVmFactory;
@ -99,25 +99,21 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
{ {
// Remove the tool from the canvas // Remove the tool from the canvas
if (_activeToolViewModel != null) if (_activeToolViewModel != null)
{
lock (Items) lock (Items)
{ {
Items.Remove(_activeToolViewModel); Items.Remove(_activeToolViewModel);
NotifyOfPropertyChange(() => Items); NotifyOfPropertyChange(() => Items);
} }
}
// Set the new tool // Set the new tool
SetAndNotify(ref _activeToolViewModel, value); SetAndNotify(ref _activeToolViewModel, value);
// Add the new tool to the canvas // Add the new tool to the canvas
if (_activeToolViewModel != null) if (_activeToolViewModel != null)
{
lock (Items) lock (Items)
{ {
Items.Add(_activeToolViewModel); Items.Add(_activeToolViewModel);
NotifyOfPropertyChange(() => Items); NotifyOfPropertyChange(() => Items);
} }
}
} }
} }
@ -144,7 +140,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
Devices = new BindableCollection<ArtemisDevice>(); Devices = new BindableCollection<ArtemisDevice>();
HighlightedLeds = new BindableCollection<ArtemisLed>(); HighlightedLeds = new BindableCollection<ArtemisLed>();
ApplySurfaceConfiguration(_surfaceService.ActiveSurface); ApplyDevices();
ActivateToolByIndex(0); ActivateToolByIndex(0);
ApplyActiveProfile(); ApplyActiveProfile();
@ -156,7 +152,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
_coreService.FrameRendered += OnFrameRendered; _coreService.FrameRendered += OnFrameRendered;
HighlightSelectedLayer.SettingChanged += HighlightSelectedLayerOnSettingChanged; HighlightSelectedLayer.SettingChanged += HighlightSelectedLayerOnSettingChanged;
_surfaceService.ActiveSurfaceConfigurationSelected += OnActiveSurfaceConfigurationSelected; _rgbService.DeviceAdded += RgbServiceOnDevicesModified;
_rgbService.DeviceRemoved += RgbServiceOnDevicesModified;
_profileEditorService.ProfileSelected += OnProfileSelected; _profileEditorService.ProfileSelected += OnProfileSelected;
_profileEditorService.ProfileElementSelected += OnProfileElementSelected; _profileEditorService.ProfileElementSelected += OnProfileElementSelected;
_profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated; _profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated;
@ -168,7 +165,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
{ {
_coreService.FrameRendered -= OnFrameRendered; _coreService.FrameRendered -= OnFrameRendered;
HighlightSelectedLayer.SettingChanged -= HighlightSelectedLayerOnSettingChanged; HighlightSelectedLayer.SettingChanged -= HighlightSelectedLayerOnSettingChanged;
_surfaceService.ActiveSurfaceConfigurationSelected -= OnActiveSurfaceConfigurationSelected; _rgbService.DeviceAdded -= RgbServiceOnDevicesModified;
_rgbService.DeviceRemoved -= RgbServiceOnDevicesModified;
_profileEditorService.ProfileSelected -= OnProfileSelected; _profileEditorService.ProfileSelected -= OnProfileSelected;
_profileEditorService.ProfileElementSelected -= OnProfileElementSelected; _profileEditorService.ProfileElementSelected -= OnProfileElementSelected;
_profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated; _profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated;
@ -181,9 +179,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
base.OnClose(); base.OnClose();
} }
private void OnActiveSurfaceConfigurationSelected(object sender, SurfaceConfigurationEventArgs e) private void RgbServiceOnDevicesModified(object? sender, DeviceEventArgs e)
{ {
ApplySurfaceConfiguration(e.Surface); ApplyDevices();
} }
private void ApplyActiveProfile() private void ApplyActiveProfile()
@ -193,10 +191,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
// Add new layers missing a VM // Add new layers missing a VM
foreach (Layer layer in layers) foreach (Layer layer in layers)
{
if (layerViewModels.All(vm => vm.Layer != layer)) if (layerViewModels.All(vm => vm.Layer != layer))
Items.Add(_profileLayerVmFactory.Create(layer, PanZoomViewModel)); Items.Add(_profileLayerVmFactory.Create(layer, PanZoomViewModel));
}
// Remove layers that no longer exist // Remove layers that no longer exist
IEnumerable<ProfileLayerViewModel> toRemove = layerViewModels.Where(vm => !layers.Contains(vm.Layer)); IEnumerable<ProfileLayerViewModel> toRemove = layerViewModels.Where(vm => !layers.Contains(vm.Layer));
@ -204,10 +200,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
Items.Remove(profileLayerViewModel); Items.Remove(profileLayerViewModel);
} }
private void ApplySurfaceConfiguration(ArtemisSurface surface) private void ApplyDevices()
{ {
Devices.Clear(); Devices.Clear();
Devices.AddRange(surface.Devices.Where(d => d.IsEnabled).OrderBy(d => d.ZIndex)); Devices.AddRange(_rgbService.EnabledDevices.Where(d => d.IsEnabled).OrderBy(d => d.ZIndex));
} }
private void UpdateLedsDimStatus() private void UpdateLedsDimStatus()
@ -259,7 +255,15 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
public void ResetZoomAndPan() public void ResetZoomAndPan()
{ {
PanZoomViewModel.Reset(); // Create a rect surrounding all devices
SKRect rect = new SKRect(
Devices.Min(d => d.Rectangle.Left),
Devices.Min(d => d.Rectangle.Top),
Devices.Max(d => d.Rectangle.Right),
Devices.Max(d => d.Rectangle.Bottom)
);
PanZoomViewModel.Reset(rect);
} }
#endregion #endregion
@ -339,7 +343,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
_previousSelectedLayer.Transform.LayerPropertyOnCurrentValueSet += TransformValueChanged; _previousSelectedLayer.Transform.LayerPropertyOnCurrentValueSet += TransformValueChanged;
} }
else else
{
_previousSelectedLayer = null; _previousSelectedLayer = null;
}
ApplyActiveProfile(); ApplyActiveProfile();
UpdateLedsDimStatus(); UpdateLedsDimStatus();

View File

@ -42,6 +42,7 @@
<StackPanel> <StackPanel>
<Button Content="Open plugin directory" Command="{s:Action OpenPluginDirectory}" /> <Button Content="Open plugin directory" Command="{s:Action OpenPluginDirectory}" />
<Button Content="Open image directory" Command="{s:Action OpenImageDirectory}" /> <Button Content="Open image directory" Command="{s:Action OpenImageDirectory}" />
<Button Content="Reload layout" Command="{s:Action ReloadLayout}" />
</StackPanel> </StackPanel>
</materialDesign:PopupBox> </materialDesign:PopupBox>
</StackPanel> </StackPanel>

View File

@ -12,12 +12,14 @@ namespace Artemis.UI.Screens.Settings.Debug
public class DeviceDebugViewModel : Screen public class DeviceDebugViewModel : Screen
{ {
private readonly IDeviceService _deviceService; private readonly IDeviceService _deviceService;
private readonly IRgbService _rgbService;
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private ArtemisLed _selectedLed; private ArtemisLed _selectedLed;
public DeviceDebugViewModel(ArtemisDevice device, IDeviceService deviceService, IDialogService dialogService) public DeviceDebugViewModel(ArtemisDevice device, IDeviceService deviceService, IRgbService rgbService, IDialogService dialogService)
{ {
_deviceService = deviceService; _deviceService = deviceService;
_rgbService = rgbService;
_dialogService = dialogService; _dialogService = dialogService;
Device = device; Device = device;
} }
@ -78,6 +80,17 @@ namespace Artemis.UI.Screens.Settings.Debug
} }
} }
public void ReloadLayout()
{
if (Device.Layout == null)
_rgbService.ApplyBestDeviceLayout(Device);
else
{
Device.Layout.ReloadFromDisk();
_rgbService.ApplyDeviceLayout(Device, Device.Layout);
}
}
#endregion #endregion
// ReSharper restore UnusedMember.Global // ReSharper restore UnusedMember.Global

View File

@ -11,15 +11,15 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
public class DeviceSettingsTabViewModel : Conductor<DeviceSettingsViewModel>.Collection.AllActive public class DeviceSettingsTabViewModel : Conductor<DeviceSettingsViewModel>.Collection.AllActive
{ {
private readonly ISettingsVmFactory _settingsVmFactory; private readonly ISettingsVmFactory _settingsVmFactory;
private readonly ISurfaceService _surfaceService; private readonly IRgbService _rgbService;
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private bool _confirmedDisable; private bool _confirmedDisable;
public DeviceSettingsTabViewModel(ISurfaceService surfaceService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory) public DeviceSettingsTabViewModel(IRgbService rgbService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory)
{ {
DisplayName = "DEVICES"; DisplayName = "DEVICES";
_surfaceService = surfaceService; _rgbService = rgbService;
_dialogService = dialogService; _dialogService = dialogService;
_settingsVmFactory = settingsVmFactory; _settingsVmFactory = settingsVmFactory;
} }
@ -32,7 +32,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
Items.Clear(); Items.Clear();
await Task.Delay(200); await Task.Delay(200);
List<DeviceSettingsViewModel> instances = _surfaceService.ActiveSurface.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList(); List<DeviceSettingsViewModel> instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
foreach (DeviceSettingsViewModel deviceSettingsViewModel in instances) foreach (DeviceSettingsViewModel deviceSettingsViewModel in instances)
Items.Add(deviceSettingsViewModel); Items.Add(deviceSettingsViewModel);
}); });

View File

@ -6,7 +6,6 @@ using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.SurfaceEditor.Dialogs; using Artemis.UI.Screens.SurfaceEditor.Dialogs;
using Artemis.UI.Screens.SurfaceEditor.Visualization;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using Humanizer; using Humanizer;
using RGB.NET.Core; using RGB.NET.Core;
@ -17,9 +16,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
public class DeviceSettingsViewModel : Screen public class DeviceSettingsViewModel : Screen
{ {
private readonly IDeviceDebugVmFactory _deviceDebugVmFactory; private readonly IDeviceDebugVmFactory _deviceDebugVmFactory;
private readonly ISurfaceService _surfaceService;
private readonly IDeviceService _deviceService; private readonly IDeviceService _deviceService;
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly IRgbService _rgbService;
private readonly IWindowManager _windowManager; private readonly IWindowManager _windowManager;
public DeviceSettingsViewModel(ArtemisDevice device, public DeviceSettingsViewModel(ArtemisDevice device,
@ -27,13 +26,13 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
IDialogService dialogService, IDialogService dialogService,
IWindowManager windowManager, IWindowManager windowManager,
IDeviceDebugVmFactory deviceDebugVmFactory, IDeviceDebugVmFactory deviceDebugVmFactory,
ISurfaceService surfaceService) IRgbService rgbService)
{ {
_deviceService = deviceService; _deviceService = deviceService;
_dialogService = dialogService; _dialogService = dialogService;
_windowManager = windowManager; _windowManager = windowManager;
_deviceDebugVmFactory = deviceDebugVmFactory; _deviceDebugVmFactory = deviceDebugVmFactory;
_surfaceService = surfaceService; _rgbService = rgbService;
Device = device; Device = device;
Type = Device.RgbDevice.DeviceInfo.DeviceType.ToString().Humanize(); Type = Device.RgbDevice.DeviceInfo.DeviceType.ToString().Humanize();
@ -53,26 +52,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
public bool IsDeviceEnabled public bool IsDeviceEnabled
{ {
get => Device.IsEnabled; get => Device.IsEnabled;
set set { Task.Run(() => UpdateIsDeviceEnabled(value)); }
{
Task.Run(() => UpdateIsDeviceEnabled(value));
}
}
private async Task UpdateIsDeviceEnabled(bool value)
{
if (!value)
value = !await ((DeviceSettingsTabViewModel)Parent).ShowDeviceDisableDialog();
Device.IsEnabled = value;
NotifyOfPropertyChange(nameof(IsDeviceEnabled));
SaveDevice();
}
private void SaveDevice()
{
_surfaceService.UpdateSurfaceConfiguration(_surfaceService.ActiveSurface, true);
} }
public void IdentifyDevice() public void IdentifyDevice()
@ -104,7 +84,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
); );
if ((bool) madeChanges) if ((bool) madeChanges)
_surfaceService.UpdateSurfaceConfiguration(_surfaceService.ActiveSurface, true); _rgbService.SaveDevice(Device);
} }
public async Task ViewProperties() public async Task ViewProperties()
@ -114,7 +94,25 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
); );
if ((bool) madeChanges) if ((bool) madeChanges)
_surfaceService.UpdateSurfaceConfiguration(_surfaceService.ActiveSurface, true); _rgbService.SaveDevice(Device);
}
private async Task UpdateIsDeviceEnabled(bool value)
{
if (!value)
value = !await ((DeviceSettingsTabViewModel) Parent).ShowDeviceDisableDialog();
if (value)
_rgbService.EnableDevice(Device);
else
_rgbService.DisableDevice(Device);
NotifyOfPropertyChange(nameof(IsDeviceEnabled));
SaveDevice();
}
private void SaveDevice()
{
_rgbService.SaveDevice(Device);
} }
} }
} }

View File

@ -5,6 +5,7 @@ using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Artemis.UI.Extensions; using Artemis.UI.Extensions;
using RGB.NET.Core; using RGB.NET.Core;
using SkiaSharp;
using Stylet; using Stylet;
using Point = System.Windows.Point; using Point = System.Windows.Point;
@ -144,6 +145,13 @@ namespace Artemis.UI.Screens.Shared
PanY = 0; PanY = 0;
} }
public void Reset(SKRect rect)
{
Zoom = Math.Min(CanvasWidth / rect.Width, CanvasHeight / rect.Height);
PanX = rect.Left * -1 * Zoom;
PanY = rect.Top * -1 * Zoom;
}
public Rect TransformContainingRect(Rectangle rect) public Rect TransformContainingRect(Rectangle rect)
{ {
return TransformContainingRect(rect.ToWindowsRect(1)); return TransformContainingRect(rect.ToWindowsRect(1));
@ -168,11 +176,15 @@ namespace Artemis.UI.Screens.Shared
private void SetZoomFromPercentage(double value) private void SetZoomFromPercentage(double value)
{ {
double newZoom = value / 100; Point relative = new((PanX * -1 + CanvasWidth / 2) / Zoom, (PanY * -1 + CanvasHeight / 2) / Zoom);
// Focus towards the center of the zoomed area double absoluteX = relative.X * Zoom + PanX;
PanX += newZoom - Zoom; double absoluteY = relative.Y * Zoom + PanY;
PanY += newZoom - Zoom;
Zoom = value / 100; Zoom = value / 100;
// Focus towards the center of the zoomed area
PanX = absoluteX - relative.X * Zoom;
PanY = absoluteY - relative.Y * Zoom;
} }
} }
} }

View File

@ -16,7 +16,7 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Grid.Row="0" Style="{StaticResource MaterialDesignBody1TextBlock}" TextWrapping="Wrap"> <TextBlock Grid.Row="0" Style="{StaticResource MaterialDesignBody1TextBlock}" TextWrapping="Wrap">
Devices are supported through the use of device providers. <LineBreak /> EnabledDevices are supported through the use of device providers. <LineBreak />
In the list below you can enable device providers for each brand you own by checking <Run Text="Feature enabled" FontWeight="Bold" />. In the list below you can enable device providers for each brand you own by checking <Run Text="Feature enabled" FontWeight="Bold" />.
</TextBlock> </TextBlock>

View File

@ -5,23 +5,23 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
{ {
public class LayoutStepViewModel : Screen public class LayoutStepViewModel : Screen
{ {
private readonly ISurfaceService _surfaceService; private readonly IRgbService _rgbService;
public LayoutStepViewModel(ISurfaceService surfaceService) public LayoutStepViewModel(IRgbService rgbService)
{ {
_surfaceService = surfaceService; _rgbService = rgbService;
} }
public void ApplyLeftHandedPreset() public void ApplyLeftHandedPreset()
{ {
_surfaceService.AutoArrange(); _rgbService.AutoArrangeDevices();
StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent; StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent;
startupWizardViewModel.Continue(); startupWizardViewModel.Continue();
} }
public void ApplyRightHandedPreset() public void ApplyRightHandedPreset()
{ {
_surfaceService.AutoArrange(); _rgbService.AutoArrangeDevices();
StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent; StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent;
startupWizardViewModel.Continue(); startupWizardViewModel.Continue();
} }

View File

@ -5,11 +5,12 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="https://github.com/canton7/Stylet" xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:Converters="clr-namespace:Artemis.UI.Converters" xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:models="clr-namespace:Artemis.Core;assembly=Artemis.Core" xmlns:local="clr-namespace:Artemis.UI.Screens.SurfaceEditor"
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceEditorView" x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceEditorView"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="600"> d:DesignHeight="600" d:DesignWidth="600"
d:DataContext="{d:DesignInstance {x:Type local:SurfaceEditorViewModel}}">
<UserControl.Resources> <UserControl.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
@ -18,7 +19,6 @@
<ResourceDictionary <ResourceDictionary
Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.PopupBox.xaml" /> Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.PopupBox.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<Converters:InverseBooleanConverter x:Key="InverseBooleanConverter" />
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid Margin="16"> <Grid Margin="16">
@ -113,14 +113,17 @@
</EventTrigger> </EventTrigger>
</Grid.Triggers> </Grid.Triggers>
<Grid x:Name="EditorDisplayGrid"> <Grid x:Name="EditorDisplayGrid"
shared:SizeObserver.Observe="True"
shared:SizeObserver.ObservedHeight="{Binding PanZoomViewModel.CanvasHeight, Mode=TwoWay}"
shared:SizeObserver.ObservedWidth="{Binding PanZoomViewModel.CanvasWidth, Mode=TwoWay}">
<Grid.RenderTransform> <Grid.RenderTransform>
<TransformGroup> <TransformGroup>
<ScaleTransform ScaleX="{Binding PanZoomViewModel.Zoom}" ScaleY="{Binding PanZoomViewModel.Zoom}" /> <ScaleTransform ScaleX="{Binding PanZoomViewModel.Zoom}" ScaleY="{Binding PanZoomViewModel.Zoom}" />
<TranslateTransform X="{Binding PanZoomViewModel.PanX}" Y="{Binding PanZoomViewModel.PanY}" /> <TranslateTransform X="{Binding PanZoomViewModel.PanX}" Y="{Binding PanZoomViewModel.PanY}" />
</TransformGroup> </TransformGroup>
</Grid.RenderTransform> </Grid.RenderTransform>
<ItemsControl ItemsSource="{Binding Devices}"> <ItemsControl ItemsSource="{Binding SurfaceDeviceViewModels}">
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<Canvas /> <Canvas />
@ -137,28 +140,28 @@
<ContentControl s:View.Model="{Binding}"> <ContentControl s:View.Model="{Binding}">
<ContentControl.ContextMenu> <ContentControl.ContextMenu>
<ContextMenu> <ContextMenu>
<MenuItem Header="Identify" Command="{s:Action IdentifyDevice}" CommandParameter="{Binding}"> <MenuItem Header="Identify" Command="{s:Action IdentifyDevice}" CommandParameter="{Binding Device}">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="AlarmLight" /> <materialDesign:PackIcon Kind="AlarmLight" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<Separator /> <Separator />
<MenuItem Header="Bring to Front" Command="{s:Action BringToFront}" CommandParameter="{Binding}"> <MenuItem Header="Bring to Front" Command="{s:Action BringToFront}" CommandParameter="{Binding Device}">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="ArrangeBringToFront" /> <materialDesign:PackIcon Kind="ArrangeBringToFront" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="Bring Forward" Command="{s:Action BringForward}" CommandParameter="{Binding}"> <MenuItem Header="Bring Forward" Command="{s:Action BringForward}" CommandParameter="{Binding Device}">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="ArrangeBringForward" /> <materialDesign:PackIcon Kind="ArrangeBringForward" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="Send to Back" Command="{s:Action SendToBack}" CommandParameter="{Binding}"> <MenuItem Header="Send to Back" Command="{s:Action SendToBack}" CommandParameter="{Binding Device}">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="ArrangeSendToBack" /> <materialDesign:PackIcon Kind="ArrangeSendToBack" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="Send Backward" Command="{s:Action SendBackward}" CommandParameter="{Binding}"> <MenuItem Header="Send Backward" Command="{s:Action SendBackward}" CommandParameter="{Binding Device}">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="ArrangeSendBackward" /> <materialDesign:PackIcon Kind="ArrangeSendBackward" />
</MenuItem.Icon> </MenuItem.Icon>
@ -167,14 +170,14 @@
<!-- Stylet can't disable it for us here, do it ourselves --> <!-- Stylet can't disable it for us here, do it ourselves -->
<MenuItem Header="Identify input" <MenuItem Header="Identify input"
Command="{s:Action DetectInput}" Command="{s:Action DetectInput}"
CommandParameter="{Binding}" CommandParameter="{Binding Device}"
IsEnabled="{Binding CanDetectInput}" IsEnabled="{Binding CanDetectInput}"
ToolTip="Teach Artemis which keypresses and/or button presses belong to this device"> ToolTip="Teach Artemis which keypresses and/or button presses belong to this device">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="GestureDoubleTap" /> <materialDesign:PackIcon Kind="GestureDoubleTap" />
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="View properties" Command="{s:Action ViewProperties}" CommandParameter="{Binding}"> <MenuItem Header="View properties" Command="{s:Action ViewProperties}" CommandParameter="{Binding Device}">
<MenuItem.Icon> <MenuItem.Icon>
<materialDesign:PackIcon Kind="Gear" /> <materialDesign:PackIcon Kind="Gear" />
</MenuItem.Icon> </MenuItem.Icon>
@ -236,29 +239,65 @@
<RowDefinition Height="*" /> <RowDefinition Height="*" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<ListBox Grid.Row="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding SurfaceConfigurations}" SelectedItem="{Binding SelectedSurface}"> <ListBox Grid.Row="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding ListDeviceViewModels}" SelectionMode="Multiple">
<ListBox.Resources> <ListBox.ItemContainerStyle>
<DataTemplate DataType="{x:Type models:ArtemisSurface}"> <Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Grid> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Grid.ColumnDefinitions> </Style>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" ToolTip="{Binding Name}"
HorizontalAlignment="Left" VerticalAlignment="Center" />
<Button Grid.Column="1"
Command="{s:Action DeleteSurfaceConfiguration}"
CommandParameter="{Binding}"
IsEnabled="{Binding IsActive, Converter={StaticResource InverseBooleanConverter}}"
Style="{StaticResource MaterialDesignIconForegroundButton}"
ToolTip="Delete layout configuration"
HorizontalAlignment="Right">
<materialDesign:PackIcon Kind="Trashcan" />
</Button>
</Grid>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False">
<ContentControl.ContextMenu>
<ContextMenu>
<MenuItem Header="Identify" Command="{s:Action IdentifyDevice}" CommandParameter="{Binding Device}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="AlarmLight" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Bring to Front" Command="{s:Action BringToFront}" CommandParameter="{Binding Device}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="ArrangeBringToFront" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Bring Forward" Command="{s:Action BringForward}" CommandParameter="{Binding Device}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="ArrangeBringForward" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Send to Back" Command="{s:Action SendToBack}" CommandParameter="{Binding Device}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="ArrangeSendToBack" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Send Backward" Command="{s:Action SendBackward}" CommandParameter="{Binding Device}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="ArrangeSendBackward" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<!-- Stylet can't disable it for us here, do it ourselves -->
<MenuItem Header="Identify input"
Command="{s:Action DetectInput}"
CommandParameter="{Binding Device}"
IsEnabled="{Binding CanDetectInput}"
ToolTip="Teach Artemis which keypresses and/or button presses belong to this device">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="GestureDoubleTap" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="View properties" Command="{s:Action ViewProperties}" CommandParameter="{Binding Device}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="Gear" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ContentControl.ContextMenu>
</ContentControl>
</DataTemplate> </DataTemplate>
</ListBox.Resources> </ListBox.ItemTemplate>
</ListBox> </ListBox>
<Button Grid.Row="0" <Button Grid.Row="0"
Style="{StaticResource MaterialDesignFloatingActionButton}" Style="{StaticResource MaterialDesignFloatingActionButton}"

View File

@ -10,6 +10,7 @@ using System.Windows.Media;
using System.Windows.Navigation; using System.Windows.Navigation;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Extensions;
using Artemis.UI.Screens.Shared; using Artemis.UI.Screens.Shared;
using Artemis.UI.Screens.SurfaceEditor.Dialogs; using Artemis.UI.Screens.SurfaceEditor.Dialogs;
using Artemis.UI.Screens.SurfaceEditor.Visualization; using Artemis.UI.Screens.SurfaceEditor.Visualization;
@ -27,49 +28,34 @@ namespace Artemis.UI.Screens.SurfaceEditor
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private readonly ISettingsService _settingsService; private readonly ISettingsService _settingsService;
private readonly ISurfaceService _surfaceService;
private Cursor _cursor; private Cursor _cursor;
private ObservableCollection<SurfaceDeviceViewModel> _devices;
private PanZoomViewModel _panZoomViewModel; private PanZoomViewModel _panZoomViewModel;
private ArtemisSurface _selectedSurface;
private RectangleGeometry _selectionRectangle; private RectangleGeometry _selectionRectangle;
private ObservableCollection<ArtemisSurface> _surfaceConfigurations;
private PluginSetting<GridLength> _surfaceListWidth; private PluginSetting<GridLength> _surfaceListWidth;
public SurfaceEditorViewModel(IRgbService rgbService, public SurfaceEditorViewModel(IRgbService rgbService,
ISurfaceService surfaceService,
IDialogService dialogService, IDialogService dialogService,
ISettingsService settingsService, ISettingsService settingsService,
IDeviceService deviceService, IDeviceService deviceService,
IInputService inputService) IInputService inputService)
{ {
DisplayName = "Surface Editor"; DisplayName = "Surface Editor";
Devices = new ObservableCollection<SurfaceDeviceViewModel>();
SurfaceConfigurations = new ObservableCollection<ArtemisSurface>();
SelectionRectangle = new RectangleGeometry(); SelectionRectangle = new RectangleGeometry();
PanZoomViewModel = new PanZoomViewModel(); PanZoomViewModel = new PanZoomViewModel();
Cursor = null; Cursor = null;
SurfaceDeviceViewModels = new BindableCollection<SurfaceDeviceViewModel>();
ListDeviceViewModels = new BindableCollection<ListDeviceViewModel>();
_rgbService = rgbService; _rgbService = rgbService;
_surfaceService = surfaceService;
_dialogService = dialogService; _dialogService = dialogService;
_settingsService = settingsService; _settingsService = settingsService;
_deviceService = deviceService; _deviceService = deviceService;
_inputService = inputService; _inputService = inputService;
} }
public ObservableCollection<SurfaceDeviceViewModel> Devices public BindableCollection<SurfaceDeviceViewModel> SurfaceDeviceViewModels { get; }
{ public BindableCollection<ListDeviceViewModel> ListDeviceViewModels { get; }
get => _devices;
set => SetAndNotify(ref _devices, value);
}
public ObservableCollection<ArtemisSurface> SurfaceConfigurations
{
get => _surfaceConfigurations;
set => SetAndNotify(ref _surfaceConfigurations, value);
}
public RectangleGeometry SelectionRectangle public RectangleGeometry SelectionRectangle
{ {
@ -95,26 +81,6 @@ namespace Artemis.UI.Screens.SurfaceEditor
set => SetAndNotify(ref _cursor, value); set => SetAndNotify(ref _cursor, value);
} }
public ArtemisSurface SelectedSurface
{
get => _selectedSurface;
set
{
if (value == null)
return;
SetAndNotify(ref _selectedSurface, value);
ApplySelectedSurfaceConfiguration();
}
}
public ArtemisSurface CreateSurfaceConfiguration(string name)
{
ArtemisSurface config = _surfaceService.CreateSurfaceConfiguration(name);
Execute.PostToUIThread(() => SurfaceConfigurations.Add(config));
return config;
}
public void OpenHyperlink(object sender, RequestNavigateEventArgs e) public void OpenHyperlink(object sender, RequestNavigateEventArgs e)
{ {
Core.Utilities.OpenUrl(e.Uri.AbsoluteUri); Core.Utilities.OpenUrl(e.Uri.AbsoluteUri);
@ -126,7 +92,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
if (!confirmed) if (!confirmed)
return; return;
_surfaceService.AutoArrange(); _rgbService.AutoArrangeDevices();
} }
private void LoadWorkspaceSettings() private void LoadWorkspaceSettings()
@ -139,184 +105,112 @@ namespace Artemis.UI.Screens.SurfaceEditor
SurfaceListWidth.Save(); SurfaceListWidth.Save();
} }
private void LoadSurfaceConfigurations()
{
// Get surface configs
List<ArtemisSurface> configs = _surfaceService.SurfaceConfigurations.ToList();
// Get the active config, if empty, create a default config
ArtemisSurface activeConfig = _surfaceService.ActiveSurface;
if (activeConfig == null)
{
activeConfig = CreateSurfaceConfiguration("Default");
configs.Add(activeConfig);
_surfaceService.SetActiveSurfaceConfiguration(activeConfig);
}
Execute.PostToUIThread(() =>
{
// Populate the UI collection
SurfaceConfigurations.Clear();
foreach (ArtemisSurface surfaceConfiguration in configs)
SurfaceConfigurations.Add(surfaceConfiguration);
// Set the active config
SelectedSurface = activeConfig;
});
}
private void ApplySelectedSurfaceConfiguration()
{
// Make sure all devices have an up-to-date VM
Execute.PostToUIThread(() =>
{
lock (Devices)
{
List<SurfaceDeviceViewModel> existing = Devices.ToList();
List<SurfaceDeviceViewModel> deviceViewModels = new();
// Add missing/update existing
foreach (ArtemisDevice surfaceDeviceConfiguration in SelectedSurface.Devices.Where(d => d.IsEnabled).OrderBy(d => d.ZIndex).ToList())
{
// Create VMs for missing devices
SurfaceDeviceViewModel viewModel = existing.FirstOrDefault(vm => vm.Device.RgbDevice == surfaceDeviceConfiguration.RgbDevice);
if (viewModel == null)
viewModel = new SurfaceDeviceViewModel(surfaceDeviceConfiguration);
// Update existing devices
else
viewModel.Device = surfaceDeviceConfiguration;
// Add the viewModel to the list of VMs we want to keep
deviceViewModels.Add(viewModel);
}
Devices = new ObservableCollection<SurfaceDeviceViewModel>(deviceViewModels);
}
});
_surfaceService.SetActiveSurfaceConfiguration(SelectedSurface);
}
#region Overrides of Screen #region Overrides of Screen
protected override void OnInitialActivate() protected override void OnInitialActivate()
{ {
LoadSurfaceConfigurations();
LoadWorkspaceSettings(); LoadWorkspaceSettings();
SurfaceDeviceViewModels.AddRange(_rgbService.EnabledDevices.OrderBy(d => d.ZIndex).Select(d => new SurfaceDeviceViewModel(d, _rgbService)));
ListDeviceViewModels.AddRange(_rgbService.EnabledDevices.OrderBy(d => d.ZIndex * -1).Select(d => new ListDeviceViewModel(d)));
base.OnInitialActivate(); base.OnInitialActivate();
} }
protected override void OnClose() protected override void OnClose()
{ {
SaveWorkspaceSettings(); SaveWorkspaceSettings();
SurfaceDeviceViewModels.Clear();
ListDeviceViewModels.Clear();
base.OnClose(); base.OnClose();
} }
#endregion #endregion
#region Configuration management
public async Task DeleteSurfaceConfiguration(ArtemisSurface surface)
{
bool result = await _dialogService.ShowConfirmDialogAt(
"SurfaceListDialogHost",
"Delete surface configuration",
"Are you sure you want to delete\nthis surface configuration?"
);
if (result)
{
SurfaceConfigurations.Remove(surface);
_surfaceService.DeleteSurfaceConfiguration(surface);
}
}
public async Task AddSurfaceConfiguration()
{
object result = await _dialogService.ShowDialogAt<SurfaceCreateViewModel>("SurfaceListDialogHost");
if (result is string name)
CreateSurfaceConfiguration(name);
}
#endregion
#region Context menu actions #region Context menu actions
public void IdentifyDevice(SurfaceDeviceViewModel surfaceDeviceViewModel) public void IdentifyDevice(ArtemisDevice device)
{ {
_deviceService.IdentifyDevice(surfaceDeviceViewModel.Device); _deviceService.IdentifyDevice(device);
} }
public void BringToFront(SurfaceDeviceViewModel surfaceDeviceViewModel) public void BringToFront(ArtemisDevice device)
{ {
Devices.Move(Devices.IndexOf(surfaceDeviceViewModel), Devices.Count - 1); SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
for (int i = 0; i < Devices.Count; i++) SurfaceDeviceViewModels.Move(SurfaceDeviceViewModels.IndexOf(surfaceDeviceViewModel), SurfaceDeviceViewModels.Count - 1);
for (int i = 0; i < SurfaceDeviceViewModels.Count; i++)
{ {
SurfaceDeviceViewModel deviceViewModel = Devices[i]; SurfaceDeviceViewModel deviceViewModel = SurfaceDeviceViewModels[i];
deviceViewModel.Device.ZIndex = i + 1; deviceViewModel.Device.ZIndex = i + 1;
} }
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true); _rgbService.SaveDevices();
} }
public void BringForward(SurfaceDeviceViewModel surfaceDeviceViewModel) public void BringForward(ArtemisDevice device)
{ {
int currentIndex = Devices.IndexOf(surfaceDeviceViewModel); SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
int newIndex = Math.Min(currentIndex + 1, Devices.Count - 1); int currentIndex = SurfaceDeviceViewModels.IndexOf(surfaceDeviceViewModel);
Devices.Move(currentIndex, newIndex); int newIndex = Math.Min(currentIndex + 1, SurfaceDeviceViewModels.Count - 1);
SurfaceDeviceViewModels.Move(currentIndex, newIndex);
for (int i = 0; i < Devices.Count; i++) for (int i = 0; i < SurfaceDeviceViewModels.Count; i++)
{ {
SurfaceDeviceViewModel deviceViewModel = Devices[i]; SurfaceDeviceViewModel deviceViewModel = SurfaceDeviceViewModels[i];
deviceViewModel.Device.ZIndex = i + 1; deviceViewModel.Device.ZIndex = i + 1;
} }
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true); _rgbService.SaveDevices();
} }
public void SendToBack(SurfaceDeviceViewModel surfaceDeviceViewModel) public void SendToBack(ArtemisDevice device)
{ {
Devices.Move(Devices.IndexOf(surfaceDeviceViewModel), 0); SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
for (int i = 0; i < Devices.Count; i++) SurfaceDeviceViewModels.Move(SurfaceDeviceViewModels.IndexOf(surfaceDeviceViewModel), 0);
for (int i = 0; i < SurfaceDeviceViewModels.Count; i++)
{ {
SurfaceDeviceViewModel deviceViewModel = Devices[i]; SurfaceDeviceViewModel deviceViewModel = SurfaceDeviceViewModels[i];
deviceViewModel.Device.ZIndex = i + 1; deviceViewModel.Device.ZIndex = i + 1;
} }
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true); _rgbService.SaveDevices();
} }
public void SendBackward(SurfaceDeviceViewModel surfaceDeviceViewModel) public void SendBackward(ArtemisDevice device)
{ {
int currentIndex = Devices.IndexOf(surfaceDeviceViewModel); SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
int currentIndex = SurfaceDeviceViewModels.IndexOf(surfaceDeviceViewModel);
int newIndex = Math.Max(currentIndex - 1, 0); int newIndex = Math.Max(currentIndex - 1, 0);
Devices.Move(currentIndex, newIndex); SurfaceDeviceViewModels.Move(currentIndex, newIndex);
for (int i = 0; i < Devices.Count; i++) for (int i = 0; i < SurfaceDeviceViewModels.Count; i++)
{ {
SurfaceDeviceViewModel deviceViewModel = Devices[i]; SurfaceDeviceViewModel deviceViewModel = SurfaceDeviceViewModels[i];
deviceViewModel.Device.ZIndex = i + 1; deviceViewModel.Device.ZIndex = i + 1;
} }
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true); _rgbService.SaveDevices();
} }
public async Task ViewProperties(SurfaceDeviceViewModel surfaceDeviceViewModel) public async Task ViewProperties(ArtemisDevice device)
{ {
object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceConfigViewModel>( object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceConfigViewModel>(
new Dictionary<string, object> {{"device", surfaceDeviceViewModel.Device}} new Dictionary<string, object> {{"device", device}}
); );
if ((bool) madeChanges) if ((bool) madeChanges)
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true); _rgbService.SaveDevice(device);
} }
public async Task DetectInput(SurfaceDeviceViewModel surfaceDeviceViewModel) public async Task DetectInput(ArtemisDevice device)
{ {
object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceDetectInputViewModel>( object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceDetectInputViewModel>(
new Dictionary<string, object> {{"device", surfaceDeviceViewModel.Device}} new Dictionary<string, object> {{"device", device}}
); );
if ((bool) madeChanges) if ((bool) madeChanges)
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true); _rgbService.SaveDevice(device);
} }
#endregion #endregion
@ -377,13 +271,15 @@ namespace Artemis.UI.Screens.SurfaceEditor
if (device.SelectionStatus != SelectionStatus.Selected) if (device.SelectionStatus != SelectionStatus.Selected)
{ {
if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
foreach (SurfaceDeviceViewModel others in Devices) {
foreach (SurfaceDeviceViewModel others in SurfaceDeviceViewModels)
others.SelectionStatus = SelectionStatus.None; others.SelectionStatus = SelectionStatus.None;
}
device.SelectionStatus = SelectionStatus.Selected; device.SelectionStatus = SelectionStatus.Selected;
} }
foreach (SurfaceDeviceViewModel selectedDevice in Devices.Where(d => d.SelectionStatus == SelectionStatus.Selected)) foreach (SurfaceDeviceViewModel selectedDevice in SurfaceDeviceViewModels.Where(d => d.SelectionStatus == SelectionStatus.Selected))
selectedDevice.StartMouseDrag(relative); selectedDevice.StartMouseDrag(relative);
} }
// Start multi-selection // Start multi-selection
@ -395,6 +291,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
// Any time dragging starts, start with a new rect // Any time dragging starts, start with a new rect
SelectionRectangle.Rect = new Rect(); SelectionRectangle.Rect = new Rect();
ApplySurfaceSelection();
} }
private void StopMouseDrag(object sender, Point position) private void StopMouseDrag(object sender, Point position)
@ -403,17 +300,22 @@ namespace Artemis.UI.Screens.SurfaceEditor
{ {
RectangleGeometry selectedRect = new(new Rect(_mouseDragStartPoint, position)); RectangleGeometry selectedRect = new(new Rect(_mouseDragStartPoint, position));
List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, selectedRect); List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, selectedRect);
foreach (SurfaceDeviceViewModel device in Devices) foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels)
{
if (devices.Contains(device)) if (devices.Contains(device))
device.SelectionStatus = SelectionStatus.Selected; device.SelectionStatus = SelectionStatus.Selected;
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
device.SelectionStatus = SelectionStatus.None; device.SelectionStatus = SelectionStatus.None;
}
} }
else else
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true); {
_rgbService.SaveDevices();
}
_mouseDragStatus = MouseDragStatus.None; _mouseDragStatus = MouseDragStatus.None;
_rgbService.IsRenderPaused = false; _rgbService.IsRenderPaused = false;
ApplySurfaceSelection();
} }
private void UpdateSelection(object sender, Point position) private void UpdateSelection(object sender, Point position)
@ -425,19 +327,29 @@ namespace Artemis.UI.Screens.SurfaceEditor
SelectionRectangle.Rect = selectedRect; SelectionRectangle.Rect = selectedRect;
List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, SelectionRectangle); List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, SelectionRectangle);
foreach (SurfaceDeviceViewModel device in Devices) foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels)
{
if (devices.Contains(device)) if (devices.Contains(device))
device.SelectionStatus = SelectionStatus.Selected; device.SelectionStatus = SelectionStatus.Selected;
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
device.SelectionStatus = SelectionStatus.None; device.SelectionStatus = SelectionStatus.None;
}
ApplySurfaceSelection();
} }
private void MoveSelected(Point position) private void MoveSelected(Point position)
{ {
foreach (SurfaceDeviceViewModel device in Devices.Where(d => d.SelectionStatus == SelectionStatus.Selected)) foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels.Where(d => d.SelectionStatus == SelectionStatus.Selected))
device.UpdateMouseDrag(position); device.UpdateMouseDrag(position);
} }
private void ApplySurfaceSelection()
{
foreach (ListDeviceViewModel viewModel in ListDeviceViewModels)
viewModel.IsSelected = SurfaceDeviceViewModels.Any(s => s.Device == viewModel.Device && s.SelectionStatus == SelectionStatus.Selected);
}
#endregion #endregion
#region Panning and zooming #region Panning and zooming

View File

@ -0,0 +1,19 @@
<UserControl x:Class="Artemis.UI.Screens.SurfaceEditor.Visualization.ListDeviceView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Visualization"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type local:ListDeviceViewModel}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<shared:DeviceVisualizer Device="{Binding Device}" Width="30" Height="30" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}" Grid.Column="1" VerticalAlignment="Center" />
</Grid>
</UserControl>

View File

@ -0,0 +1,22 @@
using Artemis.Core;
using Stylet;
namespace Artemis.UI.Screens.SurfaceEditor.Visualization
{
public class ListDeviceViewModel : PropertyChangedBase
{
private bool _isSelected;
public ArtemisDevice Device { get; }
public bool IsSelected
{
get => _isSelected;
set => SetAndNotify(ref _isSelected, value);
}
public ListDeviceViewModel(ArtemisDevice device)
{
Device = device;
}
}
}

View File

@ -5,10 +5,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="https://github.com/canton7/Stylet" xmlns:s="https://github.com/canton7/Stylet"
xmlns:converters="clr-namespace:Artemis.UI.Converters" xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:surfaceEditor="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Visualization"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared" xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:local="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Visualization"
mc:Ignorable="d" mc:Ignorable="d"
d:DataContext="{d:DesignInstance {x:Type surfaceEditor:SurfaceDeviceViewModel}}" d:DataContext="{d:DesignInstance {x:Type local:SurfaceDeviceViewModel}}"
d:DesignHeight="450" d:DesignWidth="800" d:DesignHeight="450" d:DesignWidth="800"
Cursor="{Binding Cursor}" Cursor="{Binding Cursor}"
MouseEnter="{s:Action MouseEnter}" MouseEnter="{s:Action MouseEnter}"
@ -20,21 +20,22 @@
<Grid> <Grid>
<!-- Content --> <!-- Content -->
<Grid> <Grid>
<shared:DeviceVisualizer Device="{Binding Device}" ShowColors="True" VerticalAlignment="Top" HorizontalAlignment="Left" />
<Rectangle Fill="{DynamicResource MaterialDesignCardBackground}" <Rectangle Fill="{DynamicResource MaterialDesignCardBackground}"
Stroke="{DynamicResource MaterialDesignTextBoxBorder}" Stroke="{DynamicResource MaterialDesignTextBoxBorder}"
StrokeThickness="1" StrokeThickness="1"
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}" Visibility="{Binding Device.Layout.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}" <TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
TextWrapping="Wrap" TextWrapping="Wrap"
TextAlignment="Center" TextAlignment="Center"
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}" Visibility="{Binding Device.Layout.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
IsHitTestVisible="False"/> IsHitTestVisible="False"/>
</Grid>
<shared:DeviceVisualizer Device="{Binding Device}" ShowColors="True" VerticalAlignment="Top" HorizontalAlignment="Left" />
</Grid>
<!-- Selection rectangle --> <!-- Selection rectangle -->
<Rectangle Width="Auto" Height="Auto" StrokeThickness="2"> <Rectangle Width="Auto" Height="Auto" StrokeThickness="2">
@ -47,7 +48,7 @@
<Rectangle.Style> <Rectangle.Style>
<Style TargetType="{x:Type Rectangle}"> <Style TargetType="{x:Type Rectangle}">
<Style.Triggers> <Style.Triggers>
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.Hover}"> <DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static local:SelectionStatus.Hover}">
<DataTrigger.EnterActions> <DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="ToSelected" /> <StopStoryboard BeginStoryboardName="ToSelected" />
<BeginStoryboard x:Name="ToHover"> <BeginStoryboard x:Name="ToHover">
@ -62,7 +63,7 @@
</BeginStoryboard> </BeginStoryboard>
</DataTrigger.EnterActions> </DataTrigger.EnterActions>
</DataTrigger> </DataTrigger>
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.Selected}"> <DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static local:SelectionStatus.Selected}">
<DataTrigger.EnterActions> <DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="ToHover" /> <StopStoryboard BeginStoryboardName="ToHover" />
<BeginStoryboard x:Name="ToSelected"> <BeginStoryboard x:Name="ToSelected">
@ -77,7 +78,7 @@
</BeginStoryboard> </BeginStoryboard>
</DataTrigger.EnterActions> </DataTrigger.EnterActions>
</DataTrigger> </DataTrigger>
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.None}"> <DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static local:SelectionStatus.None}">
<DataTrigger.EnterActions> <DataTrigger.EnterActions>
<BeginStoryboard> <BeginStoryboard>
<Storyboard> <Storyboard>

View File

@ -1,9 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services;
using RGB.NET.Core; using RGB.NET.Core;
using SkiaSharp; using SkiaSharp;
using Stylet; using Stylet;
@ -13,26 +13,19 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
{ {
public class SurfaceDeviceViewModel : PropertyChangedBase public class SurfaceDeviceViewModel : PropertyChangedBase
{ {
private readonly IRgbService _rgbService;
private Cursor _cursor; private Cursor _cursor;
private ArtemisDevice _device;
private double _dragOffsetX; private double _dragOffsetX;
private double _dragOffsetY; private double _dragOffsetY;
private SelectionStatus _selectionStatus; private SelectionStatus _selectionStatus;
public SurfaceDeviceViewModel(ArtemisDevice device) public SurfaceDeviceViewModel(ArtemisDevice device, IRgbService rgbService)
{ {
Device = device; Device = device;
_rgbService = rgbService;
} }
public ArtemisDevice Device public ArtemisDevice Device { get; }
{
get => _device;
set
{
if (SetAndNotify(ref _device, value)) return;
NotifyOfPropertyChange(nameof(DeviceRectangle));
}
}
public SelectionStatus SelectionStatus public SelectionStatus SelectionStatus
{ {
@ -40,19 +33,15 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
set => SetAndNotify(ref _selectionStatus, value); set => SetAndNotify(ref _selectionStatus, value);
} }
public bool CanDetectInput => Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard ||
Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse;
public Cursor Cursor public Cursor Cursor
{ {
get => _cursor; get => _cursor;
set => SetAndNotify(ref _cursor, value); set => SetAndNotify(ref _cursor, value);
} }
public Rect DeviceRectangle => Device.RgbDevice == null
? new Rect()
: new Rect(Device.X, Device.Y, Device.RgbDevice.Boundary.Size.Width, Device.RgbDevice.Boundary.Size.Height);
public bool CanDetectInput => Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard ||
Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse;
public void StartMouseDrag(Point mouseStartPosition) public void StartMouseDrag(Point mouseStartPosition)
{ {
_dragOffsetX = Device.X - mouseStartPosition.X; _dragOffsetX = Device.X - mouseStartPosition.X;
@ -115,7 +104,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
List<SKRect> own = Device.Leds List<SKRect> own = Device.Leds
.Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height)) .Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height))
.ToList(); .ToList();
List<SKRect> others = Device.Surface.Devices List<SKRect> others = _rgbService.EnabledDevices
.Where(d => d != Device && d.IsEnabled) .Where(d => d != Device && d.IsEnabled)
.SelectMany(d => d.Leds) .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)) .Select(l => SKRect.Create(l.Rectangle.Left + (float) l.Device.X, l.Rectangle.Top + (float) l.Device.Y, l.Rectangle.Width, l.Rectangle.Height))
@ -133,7 +122,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
BottomLeft, BottomLeft,
BottomRight BottomRight
} }
public enum SelectionStatus public enum SelectionStatus
{ {
None, None,

View File

@ -18,7 +18,6 @@ namespace Artemis.UI.Services
private readonly IDataModelUIService _dataModelUIService; private readonly IDataModelUIService _dataModelUIService;
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private readonly IPluginManagementService _pluginManagementService; private readonly IPluginManagementService _pluginManagementService;
private readonly ISurfaceService _surfaceService;
private readonly IInputService _inputService; private readonly IInputService _inputService;
private readonly IWebServerService _webServerService; private readonly IWebServerService _webServerService;
private bool _registeredBuiltInDataModelDisplays; private bool _registeredBuiltInDataModelDisplays;
@ -29,7 +28,6 @@ namespace Artemis.UI.Services
IDataModelUIService dataModelUIService, IDataModelUIService dataModelUIService,
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IPluginManagementService pluginManagementService, IPluginManagementService pluginManagementService,
ISurfaceService surfaceService,
IInputService inputService, IInputService inputService,
IWebServerService webServerService) IWebServerService webServerService)
{ {
@ -37,7 +35,6 @@ namespace Artemis.UI.Services
_dataModelUIService = dataModelUIService; _dataModelUIService = dataModelUIService;
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_pluginManagementService = pluginManagementService; _pluginManagementService = pluginManagementService;
_surfaceService = surfaceService;
_inputService = inputService; _inputService = inputService;
_webServerService = webServerService; _webServerService = webServerService;