mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 21:38:38 +00:00
Merge branch 'development'
This commit is contained in:
commit
7f30950af1
@ -73,6 +73,9 @@
|
||||
<Reference Include="RGB.NET.Groups">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Groups.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Layout">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Resources\intro-profile.json">
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Clayerproperties_005Ctypes/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Clayershapes/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Csurface/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Csurface_005Clayout/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=mvvm/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=placeholders/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
@ -8,7 +7,7 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public class DeviceEventArgs : EventArgs
|
||||
{
|
||||
internal DeviceEventArgs(IRGBDevice device)
|
||||
internal DeviceEventArgs(ArtemisDevice device)
|
||||
{
|
||||
Device = device;
|
||||
}
|
||||
@ -16,6 +15,6 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the device this event is related to
|
||||
/// </summary>
|
||||
public IRGBDevice Device { get; }
|
||||
public ArtemisDevice Device { get; }
|
||||
}
|
||||
}
|
||||
21
src/Artemis.Core/Events/SurfaceConfigurationEventArgs.cs
Normal file
21
src/Artemis.Core/Events/SurfaceConfigurationEventArgs.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@ -16,8 +16,6 @@ namespace Artemis.Core
|
||||
builder.Append(rgbDevice.DeviceInfo.Model);
|
||||
builder.Append('-');
|
||||
builder.Append(rgbDevice.DeviceInfo.DeviceType);
|
||||
builder.Append('-');
|
||||
builder.Append(rgbDevice.DeviceInfo.Lighting);
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,7 +287,7 @@ namespace Artemis.Core
|
||||
if (!Enabled || Path == null || LayerShape?.Path == null || !General.PropertiesInitialized || !Transform.PropertiesInitialized)
|
||||
return;
|
||||
// Ensure the brush is ready
|
||||
if (LayerBrush?.BaseProperties?.PropertiesInitialized == false || LayerBrush?.BrushType != LayerBrushType.Regular)
|
||||
if (LayerBrush?.BaseProperties?.PropertiesInitialized == false)
|
||||
return;
|
||||
|
||||
RenderTimeline(Timeline, canvas);
|
||||
@ -322,6 +322,9 @@ namespace Artemis.Core
|
||||
return;
|
||||
|
||||
ApplyTimeline(timeline);
|
||||
|
||||
if (LayerBrush?.BrushType != LayerBrushType.Regular)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
@ -564,7 +567,7 @@ namespace Artemis.Core
|
||||
CalculateRenderProperties();
|
||||
}
|
||||
|
||||
internal void PopulateLeds(ArtemisSurface surface)
|
||||
internal void PopulateLeds(IEnumerable<ArtemisDevice> devices)
|
||||
{
|
||||
if (Disposed)
|
||||
throw new ObjectDisposedException("Layer");
|
||||
@ -572,7 +575,7 @@ namespace Artemis.Core
|
||||
List<ArtemisLed> leds = new();
|
||||
|
||||
// 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)
|
||||
{
|
||||
ArtemisLed? match = availableLeds.FirstOrDefault(a => a.Device.RgbDevice.GetDeviceIdentifier() == ledEntity.DeviceIdentifier &&
|
||||
|
||||
@ -124,14 +124,14 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Populates all the LEDs on the elements in this profile
|
||||
/// </summary>
|
||||
/// <param name="surface">The currently active surface that contains the LEDs</param>
|
||||
public void PopulateLeds(ArtemisSurface surface)
|
||||
/// <param name="devices">The devices to use while populating LEDs</param>
|
||||
public void PopulateLeds(IEnumerable<ArtemisDevice> devices)
|
||||
{
|
||||
if (Disposed)
|
||||
throw new ObjectDisposedException("Profile");
|
||||
|
||||
foreach (Layer layer in GetAllLayers())
|
||||
layer.PopulateLeds(surface);
|
||||
layer.PopulateLeds(devices);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -197,7 +197,7 @@ namespace Artemis.Core
|
||||
ProfileEntity.Layers.AddRange(GetAllLayers().Select(f => f.LayerEntity));
|
||||
}
|
||||
|
||||
internal void Activate(ArtemisSurface surface)
|
||||
internal void Activate(IEnumerable<ArtemisDevice> devices)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
@ -206,7 +206,7 @@ namespace Artemis.Core
|
||||
if (IsActivated)
|
||||
return;
|
||||
|
||||
PopulateLeds(surface);
|
||||
PopulateLeds(devices);
|
||||
OnActivated();
|
||||
IsActivated = true;
|
||||
}
|
||||
|
||||
@ -3,8 +3,10 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Core.DeviceProviders;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Storage.Entities.Surface;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Layout;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.Core
|
||||
@ -17,12 +19,11 @@ namespace Artemis.Core
|
||||
private SKPath? _path;
|
||||
private SKRect _rectangle;
|
||||
|
||||
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, ArtemisSurface surface)
|
||||
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider)
|
||||
{
|
||||
DeviceEntity = new DeviceEntity();
|
||||
RgbDevice = rgbDevice;
|
||||
DeviceProvider = deviceProvider;
|
||||
Surface = surface;
|
||||
|
||||
Rotation = 0;
|
||||
Scale = 1;
|
||||
@ -31,27 +32,22 @@ namespace Artemis.Core
|
||||
GreenScale = 1;
|
||||
BlueScale = 1;
|
||||
IsEnabled = true;
|
||||
|
||||
deviceProvider.DeviceLayoutPaths.TryGetValue(rgbDevice, out string? layoutPath);
|
||||
LayoutPath = layoutPath;
|
||||
|
||||
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
|
||||
|
||||
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
||||
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l));
|
||||
|
||||
ApplyKeyboardLayout();
|
||||
ApplyToEntity();
|
||||
CalculateRenderProperties();
|
||||
}
|
||||
|
||||
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, ArtemisSurface surface, DeviceEntity deviceEntity)
|
||||
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, DeviceEntity deviceEntity)
|
||||
{
|
||||
DeviceEntity = deviceEntity;
|
||||
RgbDevice = rgbDevice;
|
||||
DeviceProvider = deviceProvider;
|
||||
Surface = surface;
|
||||
|
||||
deviceProvider.DeviceLayoutPaths.TryGetValue(rgbDevice, out string? layoutPath);
|
||||
LayoutPath = layoutPath;
|
||||
|
||||
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
|
||||
foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers)
|
||||
@ -59,6 +55,8 @@ namespace Artemis.Core
|
||||
|
||||
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
||||
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l));
|
||||
|
||||
ApplyKeyboardLayout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -89,21 +87,16 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public DeviceProvider DeviceProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the surface containing this device
|
||||
/// </summary>
|
||||
public ArtemisSurface Surface { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read only collection containing the LEDs of this device
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<ArtemisLed> Leds { get; }
|
||||
public ReadOnlyCollection<ArtemisLed> Leds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a dictionary containing all the LEDs of this device with their corresponding RGB.NET <see cref="LedId" /> as
|
||||
/// key
|
||||
/// </summary>
|
||||
public ReadOnlyDictionary<LedId, ArtemisLed> LedIds { get; }
|
||||
public ReadOnlyDictionary<LedId, ArtemisLed> LedIds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of input identifiers associated with this device
|
||||
@ -215,12 +208,13 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => DeviceEntity.IsEnabled;
|
||||
set
|
||||
internal set
|
||||
{
|
||||
DeviceEntity.IsEnabled = value;
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
@ -228,9 +222,51 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to where the layout of the device was (attempted to be) loaded from
|
||||
/// Gets or sets the physical layout of the device e.g. ISO or ANSI.
|
||||
/// <para>Only applicable to keyboards</para>
|
||||
/// </summary>
|
||||
public string? LayoutPath { get; internal set; }
|
||||
public KeyboardLayoutType PhysicalLayout
|
||||
{
|
||||
get => (KeyboardLayoutType) DeviceEntity.PhysicalLayout;
|
||||
set
|
||||
{
|
||||
DeviceEntity.PhysicalLayout = (int) value;
|
||||
OnPropertyChanged(nameof(PhysicalLayout));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the logical layout of the device e.g. DE, UK or US.
|
||||
/// <para>Only applicable to keyboards</para>
|
||||
/// </summary>
|
||||
public string? LogicalLayout
|
||||
{
|
||||
get => DeviceEntity.LogicalLayout;
|
||||
set
|
||||
{
|
||||
DeviceEntity.LogicalLayout = value;
|
||||
OnPropertyChanged(nameof(LogicalLayout));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path of the custom layout to load when calling <see cref="IRgbService.ApplyBestDeviceLayout" />
|
||||
/// for this device
|
||||
/// </summary>
|
||||
public string? CustomLayoutPath
|
||||
{
|
||||
get => DeviceEntity.CustomLayoutPath;
|
||||
set
|
||||
{
|
||||
DeviceEntity.CustomLayoutPath = value;
|
||||
OnPropertyChanged(nameof(CustomLayoutPath));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the layout of the device expanded with Artemis-specific data
|
||||
/// </summary>
|
||||
public ArtemisLayout? Layout { get; internal set; }
|
||||
|
||||
internal DeviceEntity DeviceEntity { get; }
|
||||
|
||||
@ -261,10 +297,46 @@ namespace Artemis.Core
|
||||
return artemisLed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the default layout file name of the device
|
||||
/// </summary>
|
||||
/// <param name="includeExtension">If true, the .xml extension is added to the file name</param>
|
||||
/// <returns>The resulting file name e.g. CORSAIR GLAIVE.xml or K95 RGB-ISO.xml</returns>
|
||||
public string GetLayoutFileName(bool includeExtension = true)
|
||||
{
|
||||
// Take out invalid file name chars, may not be perfect but neither are you
|
||||
string fileName = System.IO.Path.GetInvalidFileNameChars().Aggregate(RgbDevice.DeviceInfo.Model, (current, c) => current.Replace(c, '-'));
|
||||
if (RgbDevice is IKeyboard)
|
||||
fileName = $"{fileName}-{PhysicalLayout.ToString().ToUpper()}";
|
||||
if (includeExtension)
|
||||
fileName = $"{fileName}.xml";
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the provided layout to the device
|
||||
/// </summary>
|
||||
/// <param name="layout">The layout to apply</param>
|
||||
/// <param name="createMissingLeds">A boolean indicating whether to add missing LEDs defined in the layout but missing on the device</param>
|
||||
/// <param name="removeExcessiveLeds">A boolean indicating whether to remove excess LEDs present in the device but missing in the layout</param>
|
||||
internal void ApplyLayout(ArtemisLayout layout, bool createMissingLeds, bool removeExcessiveLeds)
|
||||
{
|
||||
if (layout.IsValid)
|
||||
layout.RgbLayout!.ApplyTo(RgbDevice, createMissingLeds, removeExcessiveLeds);
|
||||
|
||||
Leds = RgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
||||
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l));
|
||||
|
||||
Layout = layout;
|
||||
Layout.ApplyDevice(this);
|
||||
OnDeviceUpdated();
|
||||
}
|
||||
|
||||
internal void ApplyToEntity()
|
||||
{
|
||||
// Other properties are computed
|
||||
DeviceEntity.DeviceIdentifier = RgbDevice.GetDeviceIdentifier();
|
||||
DeviceEntity.Id = RgbDevice.GetDeviceIdentifier();
|
||||
|
||||
DeviceEntity.InputIdentifiers.Clear();
|
||||
foreach (ArtemisDeviceInputIdentifier identifier in InputIdentifiers)
|
||||
@ -295,7 +367,7 @@ namespace Artemis.Core
|
||||
|
||||
internal void CalculateRenderProperties()
|
||||
{
|
||||
Rectangle = RgbDevice.DeviceRectangle.ToSKRect();
|
||||
Rectangle = RgbDevice.Boundary.ToSKRect();
|
||||
if (!Leds.Any())
|
||||
return;
|
||||
|
||||
@ -309,6 +381,18 @@ namespace Artemis.Core
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -46,11 +46,7 @@ namespace Artemis.Core
|
||||
private set => SetAndNotify(ref _absoluteRectangle, value);
|
||||
}
|
||||
|
||||
internal void CalculateRectangles()
|
||||
{
|
||||
Rectangle = RgbLed.LedRectangle.ToSKRect();
|
||||
AbsoluteRectangle = RgbLed.AbsoluteLedRectangle.ToSKRect();
|
||||
}
|
||||
public ArtemisLedLayout? Layout { get; internal set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
@ -66,5 +62,11 @@ namespace Artemis.Core
|
||||
{
|
||||
return RgbLed.Color.DivideRGB(Device.RedScale, Device.GreenScale, Device.BlueScale);
|
||||
}
|
||||
|
||||
internal void CalculateRectangles()
|
||||
{
|
||||
Rectangle = RgbLed.Boundary.ToSKRect();
|
||||
AbsoluteRectangle = RgbLed.AbsoluteBoundary.ToSKRect();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
41
src/Artemis.Core/Models/Surface/KeyboardLayoutType.cs
Normal file
41
src/Artemis.Core/Models/Surface/KeyboardLayoutType.cs
Normal file
@ -0,0 +1,41 @@
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
// Copied from RGB.NET to avoid needing to reference RGB.NET
|
||||
/// <summary>
|
||||
/// Represents a physical layout type for a keyboard
|
||||
/// </summary>
|
||||
public enum KeyboardLayoutType
|
||||
{
|
||||
/// <summary>
|
||||
/// An unknown layout type
|
||||
/// </summary>
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The ANSI layout type, often used in the US (uses a short enter)
|
||||
/// </summary>
|
||||
ANSI = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The ISO layout type, often used in the EU (uses a tall enter)
|
||||
/// </summary>
|
||||
ISO = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The JIS layout type, often used in Japan (based on ISO)
|
||||
/// </summary>
|
||||
JIS = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The ABNT layout type, often used in Brazil/Portugal (based on ISO)
|
||||
/// </summary>
|
||||
ABNT = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The KS layout type, often used in South Korea
|
||||
/// </summary>
|
||||
KS = 5
|
||||
}
|
||||
}
|
||||
143
src/Artemis.Core/Models/Surface/Layout/ArtemisLayout.cs
Normal file
143
src/Artemis.Core/Models/Surface/Layout/ArtemisLayout.cs
Normal file
@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using RGB.NET.Layout;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a device layout decorated with extra Artemis-specific data
|
||||
/// </summary>
|
||||
public class ArtemisLayout
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="ArtemisLayout" /> class
|
||||
/// </summary>
|
||||
/// <param name="filePath">The path of the layout XML file</param>
|
||||
/// <param name="source">The source from where this layout is being loaded</param>
|
||||
public ArtemisLayout(string filePath, LayoutSource source)
|
||||
{
|
||||
FilePath = filePath;
|
||||
Source = source;
|
||||
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 source from where this layout was loaded
|
||||
/// </summary>
|
||||
public LayoutSource Source { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the device this layout is applied to
|
||||
/// </summary>
|
||||
public ArtemisDevice? Device { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether a valid layout was loaded
|
||||
/// </summary>
|
||||
public bool IsValid { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image of the device
|
||||
/// </summary>
|
||||
public Uri? Image { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of LEDs this layout contains
|
||||
/// </summary>
|
||||
public List<ArtemisLedLayout> Leds { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the RGB.NET device layout
|
||||
/// </summary>
|
||||
public DeviceLayout RgbLayout { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the custom layout data embedded in the RGB.NET layout
|
||||
/// </summary>
|
||||
public LayoutCustomDeviceData LayoutCustomDeviceData { get; private set; } = null!;
|
||||
|
||||
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));
|
||||
if (deviceLayout != null)
|
||||
{
|
||||
RgbLayout = deviceLayout;
|
||||
IsValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RgbLayout = new DeviceLayout();
|
||||
IsValid = false;
|
||||
}
|
||||
|
||||
if (IsValid)
|
||||
Leds.AddRange(RgbLayout.Leds.Select(l => new ArtemisLedLayout(this, l)));
|
||||
|
||||
LayoutCustomDeviceData = (LayoutCustomDeviceData?) RgbLayout.CustomData ?? new LayoutCustomDeviceData();
|
||||
ApplyCustomDeviceData();
|
||||
}
|
||||
|
||||
private void ApplyCustomDeviceData()
|
||||
{
|
||||
if (!IsValid)
|
||||
{
|
||||
Image = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Uri layoutDirectory = new(Path.GetDirectoryName(FilePath)! + "/", UriKind.Absolute);
|
||||
if (LayoutCustomDeviceData.DeviceImage != null)
|
||||
Image = new Uri(layoutDirectory, new Uri(LayoutCustomDeviceData.DeviceImage, UriKind.Relative));
|
||||
else
|
||||
Image = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a source from where a layout came
|
||||
/// </summary>
|
||||
public enum LayoutSource
|
||||
{
|
||||
/// <summary>
|
||||
/// A layout loaded from config
|
||||
/// </summary>
|
||||
Configured,
|
||||
|
||||
/// <summary>
|
||||
/// A layout loaded from the user layout folder
|
||||
/// </summary>
|
||||
User,
|
||||
|
||||
/// <summary>
|
||||
/// A layout loaded from the plugin folder
|
||||
/// </summary>
|
||||
Plugin,
|
||||
|
||||
/// <summary>
|
||||
/// A default layout loaded as a fallback option
|
||||
/// </summary>
|
||||
Default
|
||||
}
|
||||
}
|
||||
72
src/Artemis.Core/Models/Surface/Layout/ArtemisLedLayout.cs
Normal file
72
src/Artemis.Core/Models/Surface/Layout/ArtemisLedLayout.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using RGB.NET.Layout;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class ArtemisLedLayout
|
||||
{
|
||||
internal ArtemisLedLayout(ArtemisLayout deviceLayout, ILedLayout led)
|
||||
{
|
||||
DeviceLayout = deviceLayout;
|
||||
RgbLayout = led;
|
||||
LayoutCustomLedData = (LayoutCustomLedData?) led.CustomData ?? new LayoutCustomLedData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the device layout of this LED layout
|
||||
/// </summary>
|
||||
public ArtemisLayout DeviceLayout { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the RGB.NET LED Layout of this LED layout
|
||||
/// </summary>
|
||||
public ILedLayout RgbLayout { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the LED this layout is applied to
|
||||
/// </summary>
|
||||
public ArtemisLed? Led { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the logical layout this LED belongs to
|
||||
/// </summary>
|
||||
public string? LogicalName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image of the LED
|
||||
/// </summary>
|
||||
public Uri? Image { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the custom layout data embedded in the RGB.NET layout
|
||||
/// </summary>
|
||||
public LayoutCustomLedData LayoutCustomLedData { get; }
|
||||
|
||||
internal void ApplyDevice(ArtemisDevice device)
|
||||
{
|
||||
Led = device.Leds.FirstOrDefault(d => d.RgbLed.Id.ToString() == RgbLayout.Id);
|
||||
if (Led != null)
|
||||
Led.Layout = this;
|
||||
|
||||
ApplyCustomLedData(device);
|
||||
}
|
||||
|
||||
private void ApplyCustomLedData(ArtemisDevice artemisDevice)
|
||||
{
|
||||
if (LayoutCustomLedData.LogicalLayouts == null || !LayoutCustomLedData.LogicalLayouts.Any())
|
||||
return;
|
||||
|
||||
Uri layoutDirectory = new(Path.GetDirectoryName(DeviceLayout.FilePath)! + "\\", UriKind.Absolute);
|
||||
// Prefer a matching layout or else a default layout (that has no name)
|
||||
LayoutCustomLedDataLogicalLayout logicalLayout = LayoutCustomLedData.LogicalLayouts
|
||||
.OrderBy(l => l.Name == artemisDevice.LogicalLayout)
|
||||
.ThenBy(l => l.Name == null)
|
||||
.First();
|
||||
|
||||
LogicalName = logicalLayout.Name;
|
||||
Image = new Uri(layoutDirectory, logicalLayout.Image);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
using System.Xml.Serialization;
|
||||
#pragma warning disable 1591
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents extra Artemis-specific information stored in RGB.NET layouts
|
||||
/// </summary>
|
||||
[XmlRoot("CustomData")]
|
||||
public class LayoutCustomDeviceData
|
||||
{
|
||||
[XmlElement("DeviceImage")]
|
||||
public string? DeviceImage { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
#pragma warning disable 1591
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents extra Artemis-specific information stored in RGB.NET layouts
|
||||
/// </summary>
|
||||
[XmlRoot("CustomData")]
|
||||
public class LayoutCustomLedData
|
||||
{
|
||||
[XmlArray("LogicalLayouts")]
|
||||
public List<LayoutCustomLedDataLogicalLayout>? LogicalLayouts { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents extra Artemis-specific information stored in RGB.NET layouts
|
||||
/// </summary>
|
||||
[XmlType("LogicalLayout")]
|
||||
public class LayoutCustomLedDataLogicalLayout
|
||||
{
|
||||
[XmlAttribute("Name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[XmlAttribute("Image")]
|
||||
public string? Image { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Ninject;
|
||||
using RGB.NET.Core;
|
||||
@ -34,7 +33,23 @@ namespace Artemis.Core.DeviceProviders
|
||||
[Inject]
|
||||
public ILogger? Logger { get; set; }
|
||||
|
||||
internal Dictionary<IRGBDevice, string> DeviceLayoutPaths { get; set; } = new();
|
||||
/// <summary>
|
||||
/// A boolean indicating whether this device provider detects the physical layout of connected keyboards.
|
||||
/// <para>
|
||||
/// Note: <see cref="GetLogicalLayout" /> is only called when this or <see cref="CanDetectLogicalLayout" />
|
||||
/// is <see langword="true" />.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public bool CanDetectPhysicalLayout { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// A boolean indicating whether this device provider detects the logical layout of connected keyboards
|
||||
/// <para>
|
||||
/// Note: <see cref="GetLogicalLayout" /> is only called when this or <see cref="CanDetectPhysicalLayout" />
|
||||
/// is <see langword="true" />.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public bool CanDetectLogicalLayout { get; protected set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Disable()
|
||||
@ -43,31 +58,49 @@ namespace Artemis.Core.DeviceProviders
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a layout for the specified device and wraps it in an <see cref="ArtemisLayout" />
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
protected void ResolveAbsolutePath(Type type, object sender, ResolvePathEventArgs e)
|
||||
/// <param name="device">The device to load the layout for</param>
|
||||
/// <returns>The resulting Artemis layout</returns>
|
||||
public virtual ArtemisLayout LoadLayout(ArtemisDevice device)
|
||||
{
|
||||
if (sender.GetType() == type || sender.GetType().IsGenericType(type))
|
||||
{
|
||||
// Start from the plugin directory
|
||||
if (e.RelativePart != null && e.FileName != null)
|
||||
e.FinalPath = Path.Combine(Plugin.Directory.FullName, e.RelativePart, e.FileName);
|
||||
else if (e.RelativePath != null)
|
||||
e.FinalPath = Path.Combine(Plugin.Directory.FullName, e.RelativePath);
|
||||
string layoutDir = Path.Combine(Plugin.Directory.FullName, "Layouts");
|
||||
string filePath = Path.Combine(
|
||||
layoutDir,
|
||||
device.RgbDevice.DeviceInfo.Manufacturer,
|
||||
device.RgbDevice.DeviceInfo.DeviceType.ToString(),
|
||||
device.GetLayoutFileName()
|
||||
);
|
||||
return new ArtemisLayout(filePath, LayoutSource.Plugin);
|
||||
}
|
||||
|
||||
IRGBDevice device = (IRGBDevice) sender;
|
||||
IRGBDeviceInfo deviceInfo = device.DeviceInfo;
|
||||
if (e.FileName != null && !File.Exists(e.FinalPath))
|
||||
{
|
||||
Logger?.Information("Couldn't find a layout for device {deviceName}, model {deviceModel} at {filePath}",
|
||||
deviceInfo.DeviceName, deviceInfo.Model, e.FinalPath);
|
||||
}
|
||||
/// <summary>
|
||||
/// Loads a layout from the user layout folder for the specified device and wraps it in an <see cref="ArtemisLayout" />
|
||||
/// </summary>
|
||||
/// <param name="device">The device to load the layout for</param>
|
||||
/// <returns>The resulting Artemis layout</returns>
|
||||
public virtual ArtemisLayout LoadUserLayout(ArtemisDevice device)
|
||||
{
|
||||
string layoutDir = Path.Combine(Constants.DataFolder, "user layouts");
|
||||
string filePath = Path.Combine(
|
||||
layoutDir,
|
||||
device.RgbDevice.DeviceInfo.Manufacturer,
|
||||
device.RgbDevice.DeviceInfo.DeviceType.ToString(),
|
||||
device.GetLayoutFileName()
|
||||
);
|
||||
return new ArtemisLayout(filePath, LayoutSource.User);
|
||||
}
|
||||
|
||||
if (e.FileName != null)
|
||||
DeviceLayoutPaths[device] = e.FinalPath;
|
||||
}
|
||||
/// <summary>
|
||||
/// Called when a specific RGB device's logical and physical layout must be detected
|
||||
/// <para>
|
||||
/// Note: Only called when <see cref="CanDetectLogicalLayout" /> is <see langword="true" />.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="keyboard">The device to detect the layout for, always a keyboard</param>
|
||||
public virtual string GetLogicalLayout(IKeyboard keyboard)
|
||||
{
|
||||
throw new NotImplementedException("Device provider does not support detecting logical layouts (don't call base.GetLogicalLayout())");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Services;
|
||||
using Ninject;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Groups;
|
||||
using SkiaSharp;
|
||||
@ -20,7 +21,6 @@ namespace Artemis.Core.LayerBrushes
|
||||
/// </summary>
|
||||
protected RgbNetLayerBrush()
|
||||
{
|
||||
LedGroup = new ListLedGroup();
|
||||
BrushType = LayerBrushType.RgbNet;
|
||||
SupportsTransformation = false;
|
||||
}
|
||||
@ -28,7 +28,10 @@ namespace Artemis.Core.LayerBrushes
|
||||
/// <summary>
|
||||
/// The LED group this layer effect is applied to
|
||||
/// </summary>
|
||||
public ListLedGroup LedGroup { get; internal set; }
|
||||
public ListLedGroup? LedGroup { get; internal set; }
|
||||
|
||||
[Inject]
|
||||
public IRgbService? RgbService { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when Artemis needs an instance of the RGB.NET effect you are implementing
|
||||
@ -38,9 +41,14 @@ namespace Artemis.Core.LayerBrushes
|
||||
|
||||
internal void UpdateLedGroup()
|
||||
{
|
||||
// TODO: This simply renders it on top of the rest, get a ZIndex based on layer position
|
||||
LedGroup.ZIndex = 1;
|
||||
if (LedGroup == null)
|
||||
return;
|
||||
|
||||
if (Layer.Parent != null)
|
||||
LedGroup.ZIndex = Layer.Parent.Children.Count - Layer.Parent.Children.IndexOf(Layer);
|
||||
else
|
||||
LedGroup.ZIndex = 1;
|
||||
|
||||
List<Led> missingLeds = Layer.Leds.Where(l => !LedGroup.ContainsLed(l.RgbLed)).Select(l => l.RgbLed).ToList();
|
||||
List<Led> extraLeds = LedGroup.GetLeds().Where(l => Layer.Leds.All(layerLed => layerLed.RgbLed != l)).ToList();
|
||||
LedGroup.AddLeds(missingLeds);
|
||||
@ -50,7 +58,10 @@ namespace Artemis.Core.LayerBrushes
|
||||
|
||||
internal override void Initialize()
|
||||
{
|
||||
LedGroup = new ListLedGroup();
|
||||
if (RgbService == null)
|
||||
throw new ArtemisCoreException("Cannot initialize RGB.NET layer brush because RgbService is not set");
|
||||
|
||||
LedGroup = new ListLedGroup(RgbService.Surface);
|
||||
Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated;
|
||||
|
||||
InitializeProperties();
|
||||
@ -64,8 +75,12 @@ namespace Artemis.Core.LayerBrushes
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (RgbService == null)
|
||||
throw new ArtemisCoreException("Cannot dispose RGB.NET layer brush because RgbService is not set");
|
||||
|
||||
Layer.RenderPropertiesUpdated -= LayerOnRenderPropertiesUpdated;
|
||||
LedGroup.Detach();
|
||||
LedGroup?.Detach(RgbService.Surface);
|
||||
LedGroup = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
|
||||
@ -146,10 +146,9 @@ namespace Artemis.Core.Modules
|
||||
/// Called each frame when the module should render
|
||||
/// </summary>
|
||||
/// <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="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>
|
||||
/// Called when the <see cref="ActivationRequirements" /> are met or during an override
|
||||
@ -191,9 +190,9 @@ namespace Artemis.Core.Modules
|
||||
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)
|
||||
|
||||
@ -142,10 +142,9 @@ namespace Artemis.Core.Modules
|
||||
/// Called after the profile has rendered
|
||||
/// </summary>
|
||||
/// <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="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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -178,10 +177,10 @@ namespace Artemis.Core.Modules
|
||||
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)
|
||||
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)
|
||||
await Task.Delay(50);
|
||||
|
||||
ChangeActiveProfile(profile, surface);
|
||||
ChangeActiveProfile(profile, devices);
|
||||
AnimatingProfileChange = false;
|
||||
|
||||
while (OpacityOverride < 1)
|
||||
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)
|
||||
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {this}.");
|
||||
if (!IsActivated)
|
||||
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)
|
||||
{
|
||||
@ -220,7 +217,7 @@ namespace Artemis.Core.Modules
|
||||
ActiveProfile?.Dispose();
|
||||
|
||||
ActiveProfile = profile;
|
||||
ActiveProfile?.Activate(surface!);
|
||||
ActiveProfile?.Activate(devices);
|
||||
}
|
||||
|
||||
OnActiveProfileChanged();
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Core.Services;
|
||||
using RGB.NET.Core;
|
||||
using SkiaSharp;
|
||||
|
||||
@ -12,13 +13,15 @@ namespace Artemis.Core
|
||||
{
|
||||
private readonly object _disposeLock;
|
||||
private readonly PluginSetting<int> _sampleSizeSetting;
|
||||
private readonly IRgbService _rgbService;
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal BitmapBrush(Scale scale, PluginSetting<int> sampleSizeSetting)
|
||||
internal BitmapBrush(Scale scale, PluginSetting<int> sampleSizeSetting, IRgbService rgbService)
|
||||
{
|
||||
_disposeLock = new object();
|
||||
_sampleSizeSetting = sampleSizeSetting;
|
||||
_rgbService = rgbService;
|
||||
Scale = scale;
|
||||
}
|
||||
|
||||
@ -103,7 +106,7 @@ namespace Artemis.Core
|
||||
if (scaledLocation.X < Bitmap.Width && scaledLocation.Y < Bitmap.Height)
|
||||
{
|
||||
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)
|
||||
pixel = pixel.MultiplyRGB(artemisDevice.RedScale, artemisDevice.GreenScale, artemisDevice.BlueScale);
|
||||
RenderedTargets[renderTarget] = pixel;
|
||||
@ -157,7 +160,7 @@ namespace Artemis.Core
|
||||
|
||||
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)
|
||||
pixel = pixel.MultiplyRGB(artemisDevice.RedScale, artemisDevice.GreenScale, artemisDevice.BlueScale);
|
||||
|
||||
@ -188,7 +191,6 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
internal bool IsDisposed { get; set; }
|
||||
internal ArtemisSurface? Surface { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -34,7 +34,6 @@ namespace Artemis.Core.Services
|
||||
private readonly IProfileService _profileService;
|
||||
private readonly PluginSetting<double> _renderScale;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly List<Exception> _updateExceptions = new();
|
||||
private List<BaseDataModelExpansion> _dataModelExpansions = new();
|
||||
private DateTime _lastExceptionLog;
|
||||
@ -47,7 +46,6 @@ namespace Artemis.Core.Services
|
||||
ISettingsService settingsService,
|
||||
IPluginManagementService pluginManagementService,
|
||||
IRgbService rgbService,
|
||||
ISurfaceService surfaceService,
|
||||
IProfileService profileService,
|
||||
IModuleService moduleService // injected to ensure module priorities get applied
|
||||
)
|
||||
@ -58,7 +56,6 @@ namespace Artemis.Core.Services
|
||||
_logger = logger;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_rgbService = rgbService;
|
||||
_surfaceService = surfaceService;
|
||||
_profileService = profileService;
|
||||
_loggingLevel = settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Debug);
|
||||
_renderScale = settingsService.GetSetting("Core.RenderScale", 0.5);
|
||||
@ -121,9 +118,6 @@ namespace Artemis.Core.Services
|
||||
IsElevated
|
||||
);
|
||||
|
||||
ArtemisSurface surfaceConfig = _surfaceService.ActiveSurface;
|
||||
_logger.Information("Initialized with active surface entity {surfaceConfig}-{guid}", surfaceConfig.Name, surfaceConfig.EntityId);
|
||||
|
||||
OnInitialized();
|
||||
}
|
||||
|
||||
@ -139,7 +133,7 @@ namespace Artemis.Core.Services
|
||||
|
||||
public void PlayIntroAnimation()
|
||||
{
|
||||
IntroAnimation intro = new(_logger, _profileService, _surfaceService);
|
||||
IntroAnimation intro = new(_logger, _profileService, _rgbService.EnabledDevices);
|
||||
|
||||
// Draw a white overlay over the device
|
||||
void DrawOverlay(object? sender, FrameRenderingEventArgs args)
|
||||
@ -236,7 +230,7 @@ namespace Artemis.Core.Services
|
||||
if (!ModuleRenderingDisabled)
|
||||
// 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))
|
||||
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));
|
||||
}
|
||||
|
||||
@ -8,6 +8,13 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
internal class DeviceService : IDeviceService
|
||||
{
|
||||
private readonly IRgbService _rgbService;
|
||||
|
||||
public DeviceService(IRgbService rgbService)
|
||||
{
|
||||
_rgbService = rgbService;
|
||||
}
|
||||
|
||||
public void IdentifyDevice(ArtemisDevice device)
|
||||
{
|
||||
BlinkDevice(device, 0);
|
||||
@ -16,9 +23,9 @@ namespace Artemis.Core.Services
|
||||
private void BlinkDevice(ArtemisDevice device, int blinkCount)
|
||||
{
|
||||
// Create a LED group way at the top
|
||||
ListLedGroup ledGroup = new(device.Leds.Select(l => l.RgbLed))
|
||||
ListLedGroup ledGroup = new(_rgbService.Surface, device.Leds.Select(l => l.RgbLed))
|
||||
{
|
||||
Brush = new SolidColorBrush(new Color(255, 255, 255)),
|
||||
Brush = new SolidColorBrush(new Color(255, 255, 255)),
|
||||
ZIndex = 999
|
||||
};
|
||||
|
||||
@ -26,7 +33,7 @@ namespace Artemis.Core.Services
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(200);
|
||||
ledGroup.Detach();
|
||||
ledGroup.Detach(_rgbService.Surface);
|
||||
|
||||
if (blinkCount < 5)
|
||||
{
|
||||
|
||||
@ -9,15 +9,13 @@ namespace Artemis.Core.Services
|
||||
internal class InputService : IInputService
|
||||
{
|
||||
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;
|
||||
_surfaceService = surfaceService;
|
||||
_rgbService = rgbService;
|
||||
|
||||
_surfaceService.ActiveSurfaceConfigurationSelected += SurfaceConfigurationChanged;
|
||||
_surfaceService.SurfaceConfigurationUpdated += SurfaceConfigurationChanged;
|
||||
BustIdentifierCache();
|
||||
}
|
||||
|
||||
@ -91,7 +89,7 @@ namespace Artemis.Core.Services
|
||||
_logger.Debug("Stop identifying device {device}", _identifyingDevice);
|
||||
|
||||
_identifyingDevice = null;
|
||||
_surfaceService.UpdateSurfaceConfiguration(_surfaceService.ActiveSurface, true);
|
||||
_rgbService.SaveDevices();
|
||||
|
||||
BustIdentifierCache();
|
||||
}
|
||||
@ -123,7 +121,7 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
if (_cachedFallbackKeyboard != null)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -131,7 +129,7 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
if (_cachedFallbackMouse != null)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -144,7 +142,7 @@ namespace Artemis.Core.Services
|
||||
_cachedFallbackKeyboard = 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)
|
||||
|
||||
@ -9,6 +9,22 @@ namespace Artemis.Core.Services
|
||||
/// </summary>
|
||||
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>
|
||||
/// Gets or sets the RGB surface rendering is performed on
|
||||
/// </summary>
|
||||
@ -19,16 +35,6 @@ namespace Artemis.Core.Services
|
||||
/// </summary>
|
||||
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>
|
||||
/// Gets the update trigger that drives the render loop
|
||||
/// </summary>
|
||||
@ -46,19 +52,77 @@ namespace Artemis.Core.Services
|
||||
void AddDeviceProvider(IRGBDeviceProvider deviceProvider);
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a single device has loaded
|
||||
/// Removes the given device provider from the <see cref="Surface" />
|
||||
/// </summary>
|
||||
event EventHandler<DeviceEventArgs> DeviceLoaded;
|
||||
/// <param name="deviceProvider"></param>
|
||||
void RemoveDeviceProvider(IRGBDeviceProvider deviceProvider);
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a single device has reloaded
|
||||
/// Applies auto-arranging logic to the surface
|
||||
/// </summary>
|
||||
event EventHandler<DeviceEventArgs> DeviceReloaded;
|
||||
void AutoArrangeDevices();
|
||||
|
||||
/// <summary>
|
||||
/// Recalculates the LED group used by the <see cref="BitmapBrush" />
|
||||
/// Applies the best available layout for the given <see cref="ArtemisDevice" />
|
||||
/// </summary>
|
||||
/// <param name="artemisSurface"></param>
|
||||
void UpdateSurfaceLedGroup(ArtemisSurface artemisSurface);
|
||||
/// <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>
|
||||
/// <param name="createMissingLeds"></param>
|
||||
/// <param name="removeExessiveLeds"></param>
|
||||
void ApplyDeviceLayout(ArtemisDevice device, ArtemisLayout layout, bool createMissingLeds, bool removeExessiveLeds);
|
||||
|
||||
/// <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>
|
||||
/// Occurs when a single device was removed
|
||||
/// </summary>
|
||||
event EventHandler<DeviceEventArgs> DeviceRemoved;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the surface has had modifications to its LED collection
|
||||
/// </summary>
|
||||
event EventHandler LedsChanged;
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,6 @@ using Artemis.Core.DeviceProviders;
|
||||
using Artemis.Core.Ninject;
|
||||
using Artemis.Storage.Entities.Plugins;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using Humanizer;
|
||||
using McMaster.NETCore.Plugins;
|
||||
using Ninject;
|
||||
using Ninject.Extensions.ChildKernel;
|
||||
@ -147,7 +146,7 @@ namespace Artemis.Core.Services
|
||||
// TODO: move to a more appropriate service
|
||||
public DeviceProvider GetDeviceProviderByDevice(IRGBDevice rgbDevice)
|
||||
{
|
||||
return GetFeaturesOfType<DeviceProvider>().First(d => d.RgbDeviceProvider.Devices != null && d.RgbDeviceProvider.Devices.Contains(rgbDevice));
|
||||
return GetFeaturesOfType<DeviceProvider>().First(d => d.RgbDeviceProvider.Devices.Contains(rgbDevice));
|
||||
}
|
||||
|
||||
public Plugin? GetCallingPlugin()
|
||||
@ -186,7 +185,6 @@ namespace Artemis.Core.Services
|
||||
// Load the plugin assemblies into the plugin context
|
||||
DirectoryInfo pluginDirectory = new(Path.Combine(Constants.DataFolder, "plugins"));
|
||||
foreach (DirectoryInfo subDirectory in pluginDirectory.EnumerateDirectories())
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadPlugin(subDirectory);
|
||||
@ -195,7 +193,6 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
_logger.Warning(new ArtemisPluginException("Failed to load plugin", e), "Plugin exception");
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable InconsistentlySynchronizedField - It's read-only, idc
|
||||
_logger.Debug("Loaded {count} plugin(s)", _plugins.Count);
|
||||
@ -338,7 +335,6 @@ namespace Artemis.Core.Services
|
||||
// Create instances of each feature and add them to the plugin
|
||||
// Construction should be simple and not contain any logic so failure at this point means the entire plugin fails
|
||||
foreach (Type featureType in featureTypes)
|
||||
{
|
||||
try
|
||||
{
|
||||
plugin.Kernel.Bind(featureType).ToSelf().InSingletonScope();
|
||||
@ -358,13 +354,11 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArtemisPluginException(plugin, "Failed to instantiate feature", e);
|
||||
_logger.Warning(new ArtemisPluginException(plugin, "Failed to instantiate feature", e), "Failed to instantiate feature", plugin);
|
||||
}
|
||||
}
|
||||
|
||||
// Activate plugins after they are all loaded
|
||||
foreach (PluginFeature pluginFeature in plugin.Features.Where(i => i.Entity.IsEnabled))
|
||||
{
|
||||
try
|
||||
{
|
||||
EnablePluginFeature(pluginFeature, false, !ignorePluginLock);
|
||||
@ -373,7 +367,6 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
// ignored, logged in EnablePluginFeature
|
||||
}
|
||||
}
|
||||
|
||||
if (saveState)
|
||||
{
|
||||
@ -474,13 +467,11 @@ namespace Artemis.Core.Services
|
||||
Directory.CreateDirectory(directoryInfo.FullName);
|
||||
string metaDataDirectory = metaDataFileEntry.FullName.Replace(metaDataFileEntry.Name, "");
|
||||
foreach (ZipArchiveEntry zipArchiveEntry in archive.Entries)
|
||||
{
|
||||
if (zipArchiveEntry.FullName.StartsWith(metaDataDirectory))
|
||||
{
|
||||
string target = Path.Combine(directoryInfo.FullName, zipArchiveEntry.FullName.Remove(0, metaDataDirectory.Length));
|
||||
zipArchiveEntry.ExtractToFile(target);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the newly extracted plugin and return the result
|
||||
return LoadPlugin(directoryInfo);
|
||||
@ -563,10 +554,8 @@ namespace Artemis.Core.Services
|
||||
private void SavePlugin(Plugin plugin)
|
||||
{
|
||||
foreach (PluginFeature pluginFeature in plugin.Features)
|
||||
{
|
||||
if (plugin.Entity.Features.All(i => i.Type != pluginFeature.GetType().FullName))
|
||||
plugin.Entity.Features.Add(pluginFeature.Entity);
|
||||
}
|
||||
|
||||
_pluginRepository.SavePlugin(plugin.Entity);
|
||||
}
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
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 RGB.NET.Groups;
|
||||
using Serilog;
|
||||
@ -12,72 +17,159 @@ namespace Artemis.Core.Services
|
||||
/// </summary>
|
||||
internal class RgbService : IRgbService
|
||||
{
|
||||
private readonly List<IRGBDevice> _loadedDevices;
|
||||
private readonly ILogger _logger;
|
||||
private readonly PluginSetting<double> _renderScaleSetting;
|
||||
private readonly PluginSetting<int> _sampleSizeSetting;
|
||||
private readonly PluginSetting<int> _targetFrameRateSetting;
|
||||
private ListLedGroup? _surfaceLedGroup;
|
||||
private readonly List<ArtemisDevice> _devices;
|
||||
private readonly List<ArtemisDevice> _enabledDevices;
|
||||
private Dictionary<Led, ArtemisLed> _ledMap;
|
||||
|
||||
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;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_deviceRepository = deviceRepository;
|
||||
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.5);
|
||||
_targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25);
|
||||
_sampleSizeSetting = settingsService.GetSetting("Core.SampleSize", 1);
|
||||
|
||||
Surface = RGBSurface.Instance;
|
||||
Surface = new RGBSurface();
|
||||
|
||||
// Let's throw these for now
|
||||
Surface.Exception += SurfaceOnException;
|
||||
_renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged;
|
||||
_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};
|
||||
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 />
|
||||
public RGBSurface Surface { get; set; }
|
||||
|
||||
public TimerUpdateTrigger UpdateTrigger { get; }
|
||||
public BitmapBrush? BitmapBrush { get; private set; }
|
||||
public IReadOnlyCollection<IRGBDevice> LoadedDevices => _loadedDevices.AsReadOnly();
|
||||
public double RenderScale => _renderScaleSetting.Value;
|
||||
|
||||
public bool IsRenderPaused { get; set; }
|
||||
|
||||
public void AddDeviceProvider(IRGBDeviceProvider deviceProvider)
|
||||
{
|
||||
try
|
||||
lock (_devices)
|
||||
{
|
||||
Surface.LoadDevices(deviceProvider, RGBDeviceType.All, false, true);
|
||||
}
|
||||
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))
|
||||
try
|
||||
{
|
||||
_loadedDevices.Add(surfaceDevice);
|
||||
OnDeviceLoaded(new DeviceEventArgs(surfaceDevice));
|
||||
_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);
|
||||
|
||||
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()
|
||||
{
|
||||
Surface.UnregisterUpdateTrigger(UpdateTrigger);
|
||||
@ -86,10 +178,181 @@ namespace Artemis.Core.Services
|
||||
Surface.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EnabledDevices
|
||||
|
||||
public void AutoArrangeDevices()
|
||||
{
|
||||
SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement();
|
||||
surfaceArrangement.Arrange(_devices);
|
||||
SaveDevices();
|
||||
}
|
||||
|
||||
public ArtemisLayout ApplyBestDeviceLayout(ArtemisDevice device)
|
||||
{
|
||||
ArtemisLayout layout;
|
||||
|
||||
// Configured layout path takes precedence over all other options
|
||||
if (device.CustomLayoutPath != null)
|
||||
{
|
||||
layout = new ArtemisLayout(device.CustomLayoutPath, LayoutSource.Configured);
|
||||
if (layout.IsValid)
|
||||
{
|
||||
ApplyDeviceLayout(device, layout, true, true);
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for a layout provided by the user
|
||||
layout = device.DeviceProvider.LoadUserLayout(device);
|
||||
if (layout.IsValid)
|
||||
{
|
||||
ApplyDeviceLayout(device, layout, true, true);
|
||||
return layout;
|
||||
}
|
||||
|
||||
// Look for a layout provided by the plugin
|
||||
layout = device.DeviceProvider.LoadLayout(device);
|
||||
if (layout.IsValid)
|
||||
{
|
||||
ApplyDeviceLayout(device, layout, true, true);
|
||||
return layout;
|
||||
}
|
||||
|
||||
// Finally fall back to a default layout
|
||||
layout = LoadDefaultLayout(device);
|
||||
ApplyDeviceLayout(device, layout, true, true);
|
||||
return layout;
|
||||
}
|
||||
|
||||
private ArtemisLayout LoadDefaultLayout(ArtemisDevice device)
|
||||
{
|
||||
return new ArtemisLayout("NYI", LayoutSource.Default);
|
||||
}
|
||||
|
||||
public void ApplyDeviceLayout(ArtemisDevice device, ArtemisLayout layout, bool createMissingLeds, bool removeExessiveLeds)
|
||||
{
|
||||
device.ApplyLayout(layout, createMissingLeds, removeExessiveLeds);
|
||||
// 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)
|
||||
{
|
||||
// The surface hasn't changed so we can safely reuse it
|
||||
UpdateSurfaceLedGroup(BitmapBrush?.Surface);
|
||||
UpdateBitmapBrush();
|
||||
}
|
||||
|
||||
private void TargetFrameRateSettingOnSettingChanged(object? sender, EventArgs e)
|
||||
@ -103,44 +366,27 @@ namespace Artemis.Core.Services
|
||||
throw args.Exception;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler<DeviceEventArgs>? DeviceLoaded;
|
||||
public event EventHandler<DeviceEventArgs>? DeviceReloaded;
|
||||
public event EventHandler<DeviceEventArgs>? DeviceAdded;
|
||||
public event EventHandler<DeviceEventArgs>? DeviceRemoved;
|
||||
public event EventHandler? LedsChanged;
|
||||
|
||||
public void UpdateSurfaceLedGroup(ArtemisSurface? artemisSurface)
|
||||
private void OnDeviceAdded(DeviceEventArgs e)
|
||||
{
|
||||
if (artemisSurface == null)
|
||||
return;
|
||||
|
||||
if (_surfaceLedGroup == null || BitmapBrush == null)
|
||||
{
|
||||
// Apply the application wide brush and decorator
|
||||
BitmapBrush = new BitmapBrush(new Scale(_renderScaleSetting.Value), _sampleSizeSetting);
|
||||
_surfaceLedGroup = new ListLedGroup(artemisSurface.LedMap.Select(l => l.Key)) {Brush = BitmapBrush};
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_surfaceLedGroup)
|
||||
{
|
||||
// Clean up the old background
|
||||
_surfaceLedGroup.Detach();
|
||||
|
||||
// Apply the application wide brush and decorator
|
||||
BitmapBrush.Scale = new Scale(_renderScaleSetting.Value);
|
||||
BitmapBrush.Surface = artemisSurface;
|
||||
_surfaceLedGroup = new ListLedGroup(artemisSurface.LedMap.Select(l => l.Key)) {Brush = BitmapBrush};
|
||||
}
|
||||
DeviceAdded?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void OnDeviceLoaded(DeviceEventArgs e)
|
||||
protected virtual void OnDeviceRemoved(DeviceEventArgs e)
|
||||
{
|
||||
DeviceLoaded?.Invoke(this, e);
|
||||
DeviceRemoved?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void OnDeviceReloaded(DeviceEventArgs e)
|
||||
protected virtual void OnLedsChanged()
|
||||
{
|
||||
DeviceReloaded?.Invoke(this, e);
|
||||
LedsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -76,10 +76,10 @@ namespace Artemis.Core.Services.Models
|
||||
return surfaceArrangementType;
|
||||
}
|
||||
|
||||
public void Arrange(ArtemisSurface surface)
|
||||
public void Arrange(List<ArtemisDevice> devices)
|
||||
{
|
||||
ArrangedDevices.Clear();
|
||||
foreach (ArtemisDevice surfaceDevice in surface.Devices)
|
||||
foreach (ArtemisDevice surfaceDevice in devices)
|
||||
{
|
||||
surfaceDevice.X = 0;
|
||||
surfaceDevice.Y = 0;
|
||||
@ -87,14 +87,14 @@ namespace Artemis.Core.Services.Models
|
||||
}
|
||||
|
||||
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
|
||||
double x = surface.Devices.Min(d => d.RgbDevice.Location.X);
|
||||
double y = surface.Devices.Min(d => d.RgbDevice.Location.Y);
|
||||
double x = devices.Min(d => d.RgbDevice.Location.X);
|
||||
double y = devices.Min(d => d.RgbDevice.Location.Y);
|
||||
if (x < 0)
|
||||
{
|
||||
foreach (ArtemisDevice surfaceDevice in surface.Devices)
|
||||
foreach (ArtemisDevice surfaceDevice in devices)
|
||||
{
|
||||
surfaceDevice.X += x * -1;
|
||||
surfaceDevice.ApplyToRgbDevice();
|
||||
@ -103,7 +103,7 @@ namespace Artemis.Core.Services.Models
|
||||
|
||||
if (y < 0)
|
||||
{
|
||||
foreach (ArtemisDevice surfaceDevice in surface.Devices)
|
||||
foreach (ArtemisDevice surfaceDevice in devices)
|
||||
{
|
||||
surfaceDevice.Y += y * -1;
|
||||
surfaceDevice.ApplyToRgbDevice();
|
||||
|
||||
@ -32,14 +32,14 @@ namespace Artemis.Core.Services.Models
|
||||
public int MarginBottom { get; }
|
||||
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;
|
||||
|
||||
// Start at the edge of the anchor, if there is no anchor start at any device
|
||||
Point startPoint = Anchor?.GetEdge(HorizontalPosition, VerticalPosition, surface) ??
|
||||
new SurfaceArrangementType(SurfaceArrangement, RGBDeviceType.All, 1).GetEdge(HorizontalPosition, VerticalPosition, surface);
|
||||
Point startPoint = Anchor?.GetEdge(HorizontalPosition, VerticalPosition) ??
|
||||
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
|
||||
bool stackVertically = devices.Average(d => d.RgbDevice.Size.Width) >= devices.Average(d => d.RgbDevice.Size.Height);
|
||||
|
||||
@ -21,21 +21,21 @@ namespace Artemis.Core.Services.Models
|
||||
public List<SurfaceArrangementConfiguration> Configurations { get; }
|
||||
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())
|
||||
return;
|
||||
|
||||
AppliedConfiguration = null;
|
||||
foreach (SurfaceArrangementConfiguration configuration in Configurations)
|
||||
{
|
||||
bool applied = configuration.Apply(devices, surface);
|
||||
bool applied = configuration.Apply(devices);
|
||||
if (applied)
|
||||
{
|
||||
AppliedConfiguration = configuration;
|
||||
@ -52,11 +52,11 @@ namespace Artemis.Core.Services.Models
|
||||
VerticalArrangementPosition.Equal,
|
||||
10
|
||||
) {SurfaceArrangement = SurfaceArrangement};
|
||||
fallback.Apply(devices, surface);
|
||||
fallback.Apply(devices);
|
||||
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();
|
||||
if (!devices.Any())
|
||||
@ -66,7 +66,7 @@ namespace Artemis.Core.Services.Models
|
||||
{
|
||||
HorizontalArrangementPosition.Left => devices.Min(d => d.RgbDevice.Location.X) - (AppliedConfiguration?.MarginLeft ?? 0.0),
|
||||
HorizontalArrangementPosition.Right => devices.Max(d => d.RgbDevice.Location.X + d.RgbDevice.Size.Width) + (AppliedConfiguration?.MarginRight ?? 0.0),
|
||||
HorizontalArrangementPosition.Center => devices.First().RgbDevice.DeviceRectangle.Center.X,
|
||||
HorizontalArrangementPosition.Center => devices.First().RgbDevice.Boundary.Center.X,
|
||||
HorizontalArrangementPosition.Equal => devices.First().RgbDevice.Location.X,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(horizontalPosition), horizontalPosition, null)
|
||||
};
|
||||
@ -74,7 +74,7 @@ namespace Artemis.Core.Services.Models
|
||||
{
|
||||
VerticalArrangementPosition.Top => devices.Min(d => d.RgbDevice.Location.Y) - (AppliedConfiguration?.MarginTop ?? 0.0),
|
||||
VerticalArrangementPosition.Bottom => devices.Max(d => d.RgbDevice.Location.Y + d.RgbDevice.Size.Height) + (AppliedConfiguration?.MarginBottom ?? 0.0),
|
||||
VerticalArrangementPosition.Center => devices.First().RgbDevice.DeviceRectangle.Center.Y,
|
||||
VerticalArrangementPosition.Center => devices.First().RgbDevice.Boundary.Center.Y,
|
||||
VerticalArrangementPosition.Equal => devices.First().RgbDevice.Location.Y,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(verticalPosition), verticalPosition, null)
|
||||
};
|
||||
|
||||
@ -14,23 +14,22 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IProfileRepository _profileRepository;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
|
||||
public ProfileService(ILogger logger,
|
||||
IPluginManagementService pluginManagementService,
|
||||
ISurfaceService surfaceService,
|
||||
IRgbService rgbService,
|
||||
IConditionOperatorService conditionOperatorService,
|
||||
IDataBindingService dataBindingService,
|
||||
IProfileRepository profileRepository)
|
||||
{
|
||||
_logger = logger;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_surfaceService = surfaceService;
|
||||
_rgbService = rgbService;
|
||||
_profileRepository = profileRepository;
|
||||
|
||||
_surfaceService.ActiveSurfaceConfigurationSelected += OnActiveSurfaceConfigurationSelected;
|
||||
_surfaceService.SurfaceConfigurationUpdated += OnSurfaceConfigurationUpdated;
|
||||
_rgbService.LedsChanged += RgbServiceOnLedsChanged;
|
||||
}
|
||||
|
||||
public JsonSerializerSettings MementoSettings { get; set; } = new() {TypeNameHandling = TypeNameHandling.All};
|
||||
@ -62,12 +61,11 @@ namespace Artemis.Core.Services
|
||||
/// <summary>
|
||||
/// Populates all missing LEDs on all currently active profiles
|
||||
/// </summary>
|
||||
/// <param name="surface"></param>
|
||||
private void ActiveProfilesPopulateLeds(ArtemisSurface surface)
|
||||
private void ActiveProfilesPopulateLeds()
|
||||
{
|
||||
List<ProfileModule> profileModules = _pluginManagementService.GetFeaturesOfType<ProfileModule>();
|
||||
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)
|
||||
@ -110,7 +108,7 @@ namespace Artemis.Core.Services
|
||||
Profile profile = new(profileDescriptor.ProfileModule, profileEntity);
|
||||
InstantiateProfile(profile);
|
||||
|
||||
profileDescriptor.ProfileModule.ChangeActiveProfile(profile, _surfaceService.ActiveSurface);
|
||||
profileDescriptor.ProfileModule.ChangeActiveProfile(profile, _rgbService.EnabledDevices);
|
||||
SaveActiveProfile(profileDescriptor.ProfileModule);
|
||||
|
||||
return profile;
|
||||
@ -124,9 +122,9 @@ namespace Artemis.Core.Services
|
||||
ProfileEntity entity = _profileRepository.Get(module.ActiveProfile.EntityId);
|
||||
Profile profile = new(module, entity);
|
||||
InstantiateProfile(profile);
|
||||
|
||||
module.ChangeActiveProfile(null, _surfaceService.ActiveSurface);
|
||||
module.ChangeActiveProfile(profile, _surfaceService.ActiveSurface);
|
||||
|
||||
module.ChangeActiveProfile(null, _rgbService.EnabledDevices);
|
||||
module.ChangeActiveProfile(profile, _rgbService.EnabledDevices);
|
||||
}
|
||||
|
||||
public async Task<Profile> ActivateProfileAnimated(ProfileDescriptor profileDescriptor)
|
||||
@ -141,9 +139,9 @@ namespace Artemis.Core.Services
|
||||
Profile profile = new(profileDescriptor.ProfileModule, profileEntity);
|
||||
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)
|
||||
@ -154,28 +152,29 @@ namespace Artemis.Core.Services
|
||||
// This could happen during activation so subscribe to it
|
||||
_pluginManagementService.PluginEnabled += 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);
|
||||
|
||||
_pluginManagementService.PluginEnabled -= ActivatingProfilePluginToggle;
|
||||
_pluginManagementService.PluginDisabled -= ActivatingProfilePluginToggle;
|
||||
_surfaceService.SurfaceConfigurationUpdated -= ActivatingProfileSurfaceUpdate;
|
||||
_rgbService.LedsChanged -= ActivatingRgbServiceOnLedsChanged;
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ClearActiveProfile(ProfileModule module)
|
||||
{
|
||||
module.ChangeActiveProfile(null, _surfaceService.ActiveSurface);
|
||||
module.ChangeActiveProfile(null, _rgbService.EnabledDevices);
|
||||
SaveActiveProfile(module);
|
||||
}
|
||||
|
||||
public async Task ClearActiveProfileAnimated(ProfileModule module)
|
||||
{
|
||||
await module.ChangeActiveProfileAnimated(null, _surfaceService.ActiveSurface);
|
||||
await module.ChangeActiveProfileAnimated(null, _rgbService.EnabledDevices);
|
||||
}
|
||||
|
||||
public void DeleteProfile(Profile profile)
|
||||
@ -255,7 +254,7 @@ namespace Artemis.Core.Services
|
||||
string top = profile.RedoStack.Pop();
|
||||
string memento = JsonConvert.SerializeObject(profile.ProfileEntity, MementoSettings);
|
||||
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");
|
||||
|
||||
profile.Load();
|
||||
@ -268,7 +267,7 @@ namespace Artemis.Core.Services
|
||||
|
||||
public void InstantiateProfile(Profile profile)
|
||||
{
|
||||
profile.PopulateLeds(_surfaceService.ActiveSurface);
|
||||
profile.PopulateLeds(_rgbService.EnabledDevices);
|
||||
}
|
||||
|
||||
public string ExportProfile(ProfileDescriptor profileDescriptor)
|
||||
@ -296,17 +295,11 @@ namespace Artemis.Core.Services
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
@ -1,252 +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;
|
||||
}
|
||||
|
||||
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 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
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
@ -43,9 +43,9 @@ namespace Artemis.Core.Services
|
||||
/// <inheritdoc />
|
||||
protected override async Task ProcessRequest(IHttpContext context)
|
||||
{
|
||||
if (context.Request.HttpVerb != HttpVerbs.Post)
|
||||
throw HttpException.MethodNotAllowed("This end point only accepts POST calls");
|
||||
|
||||
if (context.Request.HttpVerb != HttpVerbs.Post && context.Request.HttpVerb != HttpVerbs.Put)
|
||||
throw HttpException.MethodNotAllowed("This end point only accepts POST and PUT calls");
|
||||
|
||||
context.Response.ContentType = MimeType.Json;
|
||||
|
||||
using TextReader reader = context.OpenRequestText();
|
||||
|
||||
@ -29,7 +29,7 @@ namespace Artemis.Core.Services
|
||||
/// <summary>
|
||||
/// Gets the full URL of the end point
|
||||
/// </summary>
|
||||
public string Url => $"{_pluginsModule.ServerUrl.TrimEnd('/')}{_pluginsModule.BaseRoute}{PluginFeature.Plugin.Guid}/{Name}";
|
||||
public string Url => $"{_pluginsModule.ServerUrl?.TrimEnd('/')}{_pluginsModule.BaseRoute}{PluginFeature.Plugin.Guid}/{Name}";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin the end point is associated with
|
||||
@ -45,12 +45,12 @@ namespace Artemis.Core.Services
|
||||
/// <summary>
|
||||
/// Gets the mime type of the input this end point accepts
|
||||
/// </summary>
|
||||
public string Accepts { get; protected set; }
|
||||
public string? Accepts { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mime type of the output this end point returns
|
||||
/// </summary>
|
||||
public string Returns { get; protected set; }
|
||||
public string? Returns { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called whenever the end point has to process a request
|
||||
|
||||
@ -32,8 +32,8 @@ namespace Artemis.Core.Services
|
||||
/// <inheritdoc />
|
||||
protected override async Task ProcessRequest(IHttpContext context)
|
||||
{
|
||||
if (context.Request.HttpVerb != HttpVerbs.Post)
|
||||
throw HttpException.MethodNotAllowed("This end point only accepts POST calls");
|
||||
if (context.Request.HttpVerb != HttpVerbs.Post && context.Request.HttpVerb != HttpVerbs.Put)
|
||||
throw HttpException.MethodNotAllowed("This end point only accepts POST and PUT calls");
|
||||
|
||||
context.Response.ContentType = MimeType.PlainText;
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Modules;
|
||||
@ -13,13 +14,13 @@ namespace Artemis.Core
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
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;
|
||||
_profileService = profileService;
|
||||
_surfaceService = surfaceService;
|
||||
_devices = devices;
|
||||
|
||||
AnimationProfile = CreateIntroProfile();
|
||||
}
|
||||
@ -41,14 +42,14 @@ namespace Artemis.Core
|
||||
ProfileEntity profileEntity = CoreJson.DeserializeObject<ProfileEntity>(json)!;
|
||||
// Inject every LED on the surface into each layer
|
||||
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(),
|
||||
LedName = l.RgbLed.Id.ToString()
|
||||
}));
|
||||
|
||||
Profile profile = new(new DummyModule(), profileEntity);
|
||||
profile.Activate(_surfaceService.ActiveSurface);
|
||||
profile.Activate(_devices);
|
||||
|
||||
_profileService.InstantiateProfile(profile);
|
||||
return profile;
|
||||
@ -79,7 +80,7 @@ namespace Artemis.Core
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -18,8 +17,9 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public static void PrepareFirstLaunch()
|
||||
{
|
||||
CreateArtemisFolderIfMissing(Constants.DataFolder);
|
||||
CreateArtemisFolderIfMissing(Constants.DataFolder + "plugins");
|
||||
CreateAccessibleDirectory(Constants.DataFolder);
|
||||
CreateAccessibleDirectory(Constants.DataFolder + "plugins");
|
||||
CreateAccessibleDirectory(Constants.DataFolder + "user layouts");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -62,15 +62,11 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current application location
|
||||
/// Creates all directories and subdirectories in the specified path unless they already exist with permissions
|
||||
/// allowing access by everyone.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static string GetCurrentLocation()
|
||||
{
|
||||
return Process.GetCurrentProcess().MainModule!.FileName!;
|
||||
}
|
||||
|
||||
private static void CreateArtemisFolderIfMissing(string path)
|
||||
/// <param name="path">The directory to create.</param>
|
||||
public static void CreateAccessibleDirectory(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
@ -92,6 +88,15 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current application location
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static string GetCurrentLocation()
|
||||
{
|
||||
return Process.GetCurrentProcess().MainModule!.FileName!;
|
||||
}
|
||||
|
||||
private static void OnRestartRequested(RestartEventArgs e)
|
||||
{
|
||||
RestartRequested?.Invoke(null, e);
|
||||
|
||||
@ -8,8 +8,8 @@ namespace Artemis.Storage.Entities.Surface
|
||||
{
|
||||
InputIdentifiers = new List<DeviceInputIdentifierEntity>();
|
||||
}
|
||||
|
||||
public string DeviceIdentifier { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
public double Rotation { get; set; }
|
||||
@ -20,7 +20,12 @@ namespace Artemis.Storage.Entities.Surface
|
||||
public double BlueScale { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public int PhysicalLayout { get; set; }
|
||||
public string LogicalLayout { get; set; }
|
||||
public string CustomLayoutPath { get; set; }
|
||||
|
||||
public List<DeviceInputIdentifierEntity> InputIdentifiers { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class DeviceInputIdentifierEntity
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
48
src/Artemis.Storage/Repositories/DeviceRepository.cs
Normal file
48
src/Artemis.Storage/Repositories/DeviceRepository.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -182,7 +182,11 @@ namespace Artemis.UI.Shared
|
||||
if (_oldDevice != null)
|
||||
{
|
||||
if (Device != null)
|
||||
{
|
||||
Device.RgbDevice.PropertyChanged -= DevicePropertyChanged;
|
||||
Device.DeviceUpdated -= DeviceUpdated;
|
||||
}
|
||||
|
||||
_oldDevice = null;
|
||||
}
|
||||
}
|
||||
@ -228,15 +232,20 @@ namespace Artemis.UI.Shared
|
||||
return;
|
||||
|
||||
if (_oldDevice != null)
|
||||
{
|
||||
Device.RgbDevice.PropertyChanged -= DevicePropertyChanged;
|
||||
Device.DeviceUpdated -= DeviceUpdated;
|
||||
}
|
||||
|
||||
_oldDevice = Device;
|
||||
|
||||
Device.RgbDevice.PropertyChanged += DevicePropertyChanged;
|
||||
Device.DeviceUpdated += DeviceUpdated;
|
||||
UpdateTransform();
|
||||
|
||||
// Load the device main image
|
||||
if (Device.RgbDevice.DeviceInfo?.Image?.AbsolutePath != null && File.Exists(Device.RgbDevice.DeviceInfo.Image.AbsolutePath))
|
||||
_deviceImage = new BitmapImage(Device.RgbDevice.DeviceInfo.Image);
|
||||
if (Device.Layout?.Image != null && File.Exists(Device.Layout.Image.LocalPath))
|
||||
_deviceImage = new BitmapImage(Device.Layout.Image);
|
||||
|
||||
// Create all the LEDs
|
||||
foreach (ArtemisLed artemisLed in Device.Leds)
|
||||
@ -277,13 +286,16 @@ namespace Artemis.UI.Shared
|
||||
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))
|
||||
UpdateTransform();
|
||||
SetupForDevice();
|
||||
}
|
||||
|
||||
|
||||
private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
SetupForDevice();
|
||||
}
|
||||
|
||||
private void Render()
|
||||
{
|
||||
DrawingContext drawingContext = _backingStore.Open();
|
||||
|
||||
@ -11,6 +11,9 @@ namespace Artemis.UI.Shared
|
||||
{
|
||||
internal class DeviceVisualizerLed
|
||||
{
|
||||
private SolidColorBrush? _renderColorBrush;
|
||||
private Color _renderColor;
|
||||
|
||||
public DeviceVisualizerLed(ArtemisLed led)
|
||||
{
|
||||
Led = led;
|
||||
@ -21,9 +24,9 @@ namespace Artemis.UI.Shared
|
||||
Led.RgbLed.Size.Height
|
||||
);
|
||||
|
||||
if (Led.RgbLed.Image != null && File.Exists(Led.RgbLed.Image.AbsolutePath))
|
||||
LedImage = new BitmapImage(Led.RgbLed.Image);
|
||||
|
||||
if (Led.Layout?.Image != null && File.Exists(Led.Layout.Image.LocalPath))
|
||||
LedImage = new BitmapImage(Led.Layout.Image);
|
||||
|
||||
CreateLedGeometry();
|
||||
}
|
||||
|
||||
@ -38,14 +41,19 @@ namespace Artemis.UI.Shared
|
||||
if (DisplayGeometry == null)
|
||||
return;
|
||||
|
||||
_renderColorBrush ??= new SolidColorBrush();
|
||||
|
||||
RGB.NET.Core.Color originalColor = Led.GetOriginalColor();
|
||||
byte r = originalColor.GetR();
|
||||
byte g = originalColor.GetG();
|
||||
byte b = originalColor.GetB();
|
||||
|
||||
drawingContext.DrawRectangle(isDimmed
|
||||
? new SolidColorBrush(Color.FromArgb(100, r, g, b))
|
||||
: new SolidColorBrush(Color.FromRgb(r, g, b)), null, LedRect);
|
||||
_renderColor.A = isDimmed ? 100 : 255;
|
||||
_renderColor.R = r;
|
||||
_renderColor.G = g;
|
||||
_renderColor.B = b;
|
||||
_renderColorBrush.Color = _renderColor;
|
||||
drawingContext.DrawRectangle(_renderColorBrush, null, LedRect);
|
||||
}
|
||||
|
||||
public void RenderImage(DrawingContext drawingContext)
|
||||
|
||||
@ -8,7 +8,6 @@ using Artemis.Core.Modules;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.UI.Shared.Services.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Ninject;
|
||||
using Ninject.Parameters;
|
||||
using Serilog;
|
||||
@ -20,23 +19,23 @@ namespace Artemis.UI.Shared.Services
|
||||
internal class ProfileEditorService : IProfileEditorService
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly IKernel _kernel;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IProfileService _profileService;
|
||||
private readonly List<PropertyInputRegistration> _registeredPropertyEditors;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly object _selectedProfileElementLock = new();
|
||||
private readonly object _selectedProfileLock = new();
|
||||
private TimeSpan _currentTime;
|
||||
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;
|
||||
_logger = logger;
|
||||
_profileService = profileService;
|
||||
_coreService = coreService;
|
||||
_surfaceService = surfaceService;
|
||||
_rgbService = rgbService;
|
||||
_registeredPropertyEditors = new List<PropertyInputRegistration>();
|
||||
|
||||
PixelsPerSecond = 100;
|
||||
@ -351,7 +350,7 @@ namespace Artemis.UI.Shared.Services
|
||||
|
||||
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
|
||||
@ -424,7 +423,7 @@ namespace Artemis.UI.Shared.Services
|
||||
|
||||
if (pasted != null)
|
||||
{
|
||||
target.Profile.PopulateLeds(_surfaceService.ActiveSurface);
|
||||
target.Profile.PopulateLeds(_rgbService.EnabledDevices);
|
||||
UpdateSelectedProfile();
|
||||
ChangeSelectedProfileElement(pasted);
|
||||
}
|
||||
|
||||
@ -1,361 +1,364 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net5.0-windows</TargetFramework>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<AssemblyTitle>Artemis</AssemblyTitle>
|
||||
<Product>Artemis</Product>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<Description>Provides advanced unified lighting across many different brands RGB peripherals</Description>
|
||||
<Copyright>Copyright © Robert Beekman - 2021</Copyright>
|
||||
<FileVersion>2.0.0.0</FileVersion>
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<UseWPF>true</UseWPF>
|
||||
<Platforms>x64</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net5.0-windows</TargetFramework>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<AssemblyTitle>Artemis</AssemblyTitle>
|
||||
<Product>Artemis</Product>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<Description>Provides advanced unified lighting across many different brands RGB peripherals</Description>
|
||||
<Copyright>Copyright © Robert Beekman - 2021</Copyright>
|
||||
<FileVersion>2.0.0.0</FileVersion>
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
<UseWPF>true</UseWPF>
|
||||
<Platforms>x64</Platforms>
|
||||
<SupportedPlatform>windows</SupportedPlatform>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Resources\Images\Logo\logo-512.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent />
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
<Version>2.0.0</Version>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<NrtRevisionFormat>2.0-{chash:6}</NrtRevisionFormat>
|
||||
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
|
||||
<NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute>
|
||||
<NrtResolveCopyright>true</NrtResolveCopyright>
|
||||
<NrtTagMatch>v[0-9]*</NrtTagMatch>
|
||||
<NrtRemoveTagV>true</NrtRemoveTagV>
|
||||
<NrtRequiredVcs>git</NrtRequiredVcs>
|
||||
<NrtShowRevision>true</NrtShowRevision>
|
||||
</PropertyGroup>
|
||||
<Target Name="SkiaCleanUpAfterBuild" AfterTargets="AfterBuild">
|
||||
<Delete Files="$(OutputPath)\libSkiaSharp.dylib" />
|
||||
</Target>
|
||||
<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">
|
||||
<InProject>false</InProject>
|
||||
</FluentValidationExcludedCultures>
|
||||
</ItemGroup>
|
||||
<Target Name="RemoveTranslationsAfterBuild" AfterTargets="AfterBuild">
|
||||
<RemoveDir Directories="@(FluentValidationExcludedCultures->'$(OutputPath)%(Filename)')" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<Compile Remove="publish\**" />
|
||||
<EmbeddedResource Remove="publish\**" />
|
||||
<None Remove="publish\**" />
|
||||
<Page Remove="publish\**" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- TODO: Remove when moving to Nuget, this is so the plugin templates have the DLL to reference -->
|
||||
<Reference Include="RGB.NET.Brushes">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Brushes.dll</HintPath>
|
||||
<Private>true</Private>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Core">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Groups">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Groups.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Management" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj">
|
||||
<Private>true</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj">
|
||||
<Private>true</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj">
|
||||
<Private>true</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Fonts\RobotoMono-Regular.ttf" />
|
||||
<Resource Include="Resources\Images\Logo\bow.svg" />
|
||||
<Resource Include="Resources\Images\Logo\logo-512.ico" />
|
||||
<Resource Include="Resources\Images\Logo\logo-512.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate_tl.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate_tr.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate_bl.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate_br.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_crosshair.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_crosshair_minus.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_crosshair_plus.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_pen_min.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_pen_plus.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_fill.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_drag.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_drag_ew.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate.cur" />
|
||||
<Resource Include="Resources\Images\Sidebar\sidebar-header.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="9.3.0" />
|
||||
<PackageReference Include="Flurl.Http" Version="3.0.1" />
|
||||
<PackageReference Include="gong-wpf-dragdrop" Version="2.3.2" />
|
||||
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.14" />
|
||||
<PackageReference Include="Humanizer.Core" Version="2.8.26" />
|
||||
<PackageReference Include="MaterialDesignExtensions" Version="3.3.0-a01" />
|
||||
<PackageReference Include="MaterialDesignThemes" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" />
|
||||
<PackageReference Include="Ninject" Version="3.3.4" />
|
||||
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" />
|
||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="3.1.0" />
|
||||
<PackageReference Include="RawInput.Sharp" Version="0.0.3" />
|
||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" />
|
||||
<PackageReference Include="Stylet" Version="1.3.5" />
|
||||
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="5.0.0" />
|
||||
<PackageReference Include="System.Management" Version="5.0.0" />
|
||||
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="obj\x64\Debug\App.g.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.i.cs" />
|
||||
<Compile Remove="obj\x64\Release\App.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.i.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.i.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\Home\HomeView.g.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.i.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\Settings\SettingsView.g.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.i.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\SurfaceEditor\SurfaceEditorView.g.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.i.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\Module\ModuleRootView.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\Splash\SplashView.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.i.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\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\SurfaceDeviceConfigView.g.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.i.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\Release\Screens\Module\ProfileEditor\ProfileEditorView.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\SurfaceDeviceConfigView.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\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\ProfileElementRenameView.g.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.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.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\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\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\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.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.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.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.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.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.i.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\DataModelConditionView.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\LayerElements\LayerElementsView.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\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\ProfileView.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\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\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.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\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\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\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\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\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.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.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.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\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\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.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.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.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.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.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.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.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.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.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.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.i.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\Fonts\RobotoMono-Regular.ttf" />
|
||||
<None Remove="Resources\Images\Logo\bow.svg" />
|
||||
<None Remove="Resources\Images\Logo\logo-512.ico" />
|
||||
<None Remove="Resources\Images\Sidebar\sidebar-header.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="buildinfo.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="DefaultTypes\DataModel\Display\SKColorDataModelDisplayView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\DataModel\Input\DoubleDataModelInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\DataModel\Input\IntDataModelInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\DataModel\Input\SKColorDataModelInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\DataModel\Input\StringDataModelInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\PropertyInput\FloatRangePropertyInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Screens\ProfileEditor\Dialogs\ProfileEditView.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Resources\Images\Logo\logo-512.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent />
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
<Version>2.0.0</Version>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<NrtRevisionFormat>2.0-{chash:6}</NrtRevisionFormat>
|
||||
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
|
||||
<NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute>
|
||||
<NrtResolveCopyright>true</NrtResolveCopyright>
|
||||
<NrtTagMatch>v[0-9]*</NrtTagMatch>
|
||||
<NrtRemoveTagV>true</NrtRemoveTagV>
|
||||
<NrtRequiredVcs>git</NrtRequiredVcs>
|
||||
<NrtShowRevision>true</NrtShowRevision>
|
||||
</PropertyGroup>
|
||||
<Target Name="SkiaCleanUpAfterBuild" AfterTargets="AfterBuild">
|
||||
<Delete Files="$(OutputPath)\libSkiaSharp.dylib" />
|
||||
</Target>
|
||||
<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">
|
||||
<InProject>false</InProject>
|
||||
</FluentValidationExcludedCultures>
|
||||
</ItemGroup>
|
||||
<Target Name="RemoveTranslationsAfterBuild" AfterTargets="AfterBuild">
|
||||
<RemoveDir Directories="@(FluentValidationExcludedCultures->'$(OutputPath)%(Filename)')" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<Compile Remove="publish\**" />
|
||||
<EmbeddedResource Remove="publish\**" />
|
||||
<None Remove="publish\**" />
|
||||
<Page Remove="publish\**" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<!-- TODO: Remove when moving to Nuget, this is so the plugin templates have the DLL to reference -->
|
||||
<Reference Include="RGB.NET.Brushes">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Brushes.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Core">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Groups">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Groups.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RGB.NET.Layout">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Management" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj">
|
||||
<Private>true</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj">
|
||||
<Private>true</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj">
|
||||
<Private>true</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Fonts\RobotoMono-Regular.ttf" />
|
||||
<Resource Include="Resources\Images\Logo\bow.svg" />
|
||||
<Resource Include="Resources\Images\Logo\logo-512.ico" />
|
||||
<Resource Include="Resources\Images\Logo\logo-512.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate_tl.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate_tr.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate_bl.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate_br.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_crosshair.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_crosshair_minus.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_crosshair_plus.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_pen_min.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_pen_plus.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_fill.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_drag.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_drag_ew.cur" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\Cursors\aero_rotate.cur" />
|
||||
<Resource Include="Resources\Images\Sidebar\sidebar-header.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="9.3.0" />
|
||||
<PackageReference Include="Flurl.Http" Version="3.0.1" />
|
||||
<PackageReference Include="gong-wpf-dragdrop" Version="2.3.2" />
|
||||
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.14" />
|
||||
<PackageReference Include="Humanizer.Core" Version="2.8.26" />
|
||||
<PackageReference Include="MaterialDesignExtensions" Version="3.3.0-a01" />
|
||||
<PackageReference Include="MaterialDesignThemes" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" />
|
||||
<PackageReference Include="Ninject" Version="3.3.4" />
|
||||
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" />
|
||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="3.1.0" />
|
||||
<PackageReference Include="RawInput.Sharp" Version="0.0.3" />
|
||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" />
|
||||
<PackageReference Include="Stylet" Version="1.3.5" />
|
||||
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="5.0.0" />
|
||||
<PackageReference Include="System.Management" Version="5.0.0" />
|
||||
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="obj\x64\Debug\App.g.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.i.cs" />
|
||||
<Compile Remove="obj\x64\Release\App.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.i.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.i.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\Home\HomeView.g.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.i.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\Settings\SettingsView.g.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.i.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\SurfaceEditor\SurfaceEditorView.g.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.i.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\Module\ModuleRootView.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\Splash\SplashView.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.i.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\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\SurfaceDeviceConfigView.g.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.i.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\Release\Screens\Module\ProfileEditor\ProfileEditorView.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\SurfaceDeviceConfigView.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\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\ProfileElementRenameView.g.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.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.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\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\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\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.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.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.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.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.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.i.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\DataModelConditionView.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\LayerElements\LayerElementsView.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\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\ProfileView.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\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\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.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\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\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\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\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\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.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.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.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\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\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.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.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.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.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.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.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.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.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.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.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.i.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\Fonts\RobotoMono-Regular.ttf" />
|
||||
<None Remove="Resources\Images\Logo\bow.svg" />
|
||||
<None Remove="Resources\Images\Logo\logo-512.ico" />
|
||||
<None Remove="Resources\Images\Sidebar\sidebar-header.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="buildinfo.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="DefaultTypes\DataModel\Display\SKColorDataModelDisplayView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\DataModel\Input\DoubleDataModelInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\DataModel\Input\IntDataModelInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\DataModel\Input\SKColorDataModelInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\DataModel\Input\StringDataModelInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="DefaultTypes\PropertyInput\FloatRangePropertyInputView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Screens\ProfileEditor\Dialogs\ProfileEditView.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -9,12 +9,12 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
{
|
||||
// I hate this about DI, oh well
|
||||
public FolderViewModel(ProfileElement folder,
|
||||
IRgbService rgbService,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IProfileTreeVmFactory profileTreeVmFactory,
|
||||
ILayerBrushService layerBrushService,
|
||||
ISurfaceService surfaceService) :
|
||||
base(folder, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService, surfaceService)
|
||||
ILayerBrushService layerBrushService) :
|
||||
base(folder, rgbService, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -8,12 +8,12 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
public class LayerViewModel : TreeItemViewModel
|
||||
{
|
||||
public LayerViewModel(ProfileElement layer,
|
||||
IRgbService rgbService,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IProfileTreeVmFactory profileTreeVmFactory,
|
||||
ILayerBrushService layerBrushService,
|
||||
ISurfaceService surfaceService) :
|
||||
base(layer, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService, surfaceService)
|
||||
ILayerBrushService layerBrushService) :
|
||||
base(layer, rgbService, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -18,23 +18,23 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
{
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly ILayerBrushService _layerBrushService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private ProfileElement _profileElement;
|
||||
|
||||
protected TreeItemViewModel(ProfileElement profileElement,
|
||||
IRgbService rgbService,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IProfileTreeVmFactory profileTreeVmFactory,
|
||||
ILayerBrushService layerBrushService,
|
||||
ISurfaceService surfaceService)
|
||||
ILayerBrushService layerBrushService)
|
||||
{
|
||||
_rgbService = rgbService;
|
||||
_profileEditorService = profileEditorService;
|
||||
_dialogService = dialogService;
|
||||
_profileTreeVmFactory = profileTreeVmFactory;
|
||||
_layerBrushService = layerBrushService;
|
||||
_surfaceService = surfaceService;
|
||||
|
||||
ProfileElement = profileElement;
|
||||
|
||||
@ -144,7 +144,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
if (brush != null)
|
||||
layer.ChangeLayerBrush(brush);
|
||||
|
||||
layer.AddLeds(_surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds));
|
||||
layer.AddLeds(_rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
_profileEditorService.ChangeSelectedProfileElement(layer);
|
||||
}
|
||||
|
||||
@ -134,19 +134,19 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
|
||||
private Geometry CreateRectangleGeometry(ArtemisLed led)
|
||||
{
|
||||
Rect rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
|
||||
Rect rect = led.RgbLed.AbsoluteBoundary.ToWindowsRect(1);
|
||||
return new RectangleGeometry(rect);
|
||||
}
|
||||
|
||||
private Geometry CreateCircleGeometry(ArtemisLed led)
|
||||
{
|
||||
Rect rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
|
||||
Rect rect = led.RgbLed.AbsoluteBoundary.ToWindowsRect(1);
|
||||
return new EllipseGeometry(rect);
|
||||
}
|
||||
|
||||
private Geometry CreateCustomGeometry(ArtemisLed led, double deflateAmount)
|
||||
{
|
||||
Rect rect = led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1);
|
||||
Rect rect = led.RgbLed.AbsoluteBoundary.ToWindowsRect(1);
|
||||
try
|
||||
{
|
||||
PathGeometry geometry = Geometry.Combine(
|
||||
|
||||
@ -99,7 +99,10 @@
|
||||
</ItemsControl>
|
||||
</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>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="{Binding PanZoomViewModel.Zoom}" ScaleY="{Binding PanZoomViewModel.Zoom}" />
|
||||
|
||||
@ -6,48 +6,48 @@ using System.Windows.Input;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Events;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.ProfileEditor.Visualization.Tools;
|
||||
using Artemis.UI.Screens.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
public class ProfileViewModel : Conductor<CanvasViewModel>.Collection.AllActive, IProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IProfileLayerVmFactory _profileLayerVmFactory;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly IVisualizationToolVmFactory _visualizationToolVmFactory;
|
||||
|
||||
private int _activeToolIndex;
|
||||
private VisualizationToolViewModel _activeToolViewModel;
|
||||
private PluginSetting<bool> _alwaysApplyDataBindings;
|
||||
private bool _canApplyToLayer;
|
||||
private bool _canSelectEditTool;
|
||||
private BindableCollection<ArtemisDevice> _devices;
|
||||
private BindableCollection<ArtemisLed> _highlightedLeds;
|
||||
private PluginSetting<bool> _highlightSelectedLayer;
|
||||
private PluginSetting<bool> _alwaysApplyDataBindings;
|
||||
private DateTime _lastUpdate;
|
||||
private PanZoomViewModel _panZoomViewModel;
|
||||
private Layer _previousSelectedLayer;
|
||||
private int _previousTool;
|
||||
private DateTime _lastUpdate;
|
||||
|
||||
public ProfileViewModel(IProfileEditorService profileEditorService,
|
||||
IRgbService rgbService,
|
||||
ICoreService coreService,
|
||||
ISurfaceService surfaceService,
|
||||
ISettingsService settingsService,
|
||||
IEventAggregator eventAggregator,
|
||||
IVisualizationToolVmFactory visualizationToolVmFactory,
|
||||
IProfileLayerVmFactory profileLayerVmFactory)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_rgbService = rgbService;
|
||||
_coreService = coreService;
|
||||
_surfaceService = surfaceService;
|
||||
_settingsService = settingsService;
|
||||
_visualizationToolVmFactory = visualizationToolVmFactory;
|
||||
_profileLayerVmFactory = profileLayerVmFactory;
|
||||
@ -99,25 +99,21 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
// Remove the tool from the canvas
|
||||
if (_activeToolViewModel != null)
|
||||
{
|
||||
lock (Items)
|
||||
{
|
||||
Items.Remove(_activeToolViewModel);
|
||||
NotifyOfPropertyChange(() => Items);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new tool
|
||||
SetAndNotify(ref _activeToolViewModel, value);
|
||||
// Add the new tool to the canvas
|
||||
if (_activeToolViewModel != null)
|
||||
{
|
||||
lock (Items)
|
||||
{
|
||||
Items.Add(_activeToolViewModel);
|
||||
NotifyOfPropertyChange(() => Items);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +140,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
Devices = new BindableCollection<ArtemisDevice>();
|
||||
HighlightedLeds = new BindableCollection<ArtemisLed>();
|
||||
|
||||
ApplySurfaceConfiguration(_surfaceService.ActiveSurface);
|
||||
ApplyDevices();
|
||||
ActivateToolByIndex(0);
|
||||
|
||||
ApplyActiveProfile();
|
||||
@ -156,7 +152,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
_coreService.FrameRendered += OnFrameRendered;
|
||||
|
||||
HighlightSelectedLayer.SettingChanged += HighlightSelectedLayerOnSettingChanged;
|
||||
_surfaceService.ActiveSurfaceConfigurationSelected += OnActiveSurfaceConfigurationSelected;
|
||||
_rgbService.DeviceAdded += RgbServiceOnDevicesModified;
|
||||
_rgbService.DeviceRemoved += RgbServiceOnDevicesModified;
|
||||
_profileEditorService.ProfileSelected += OnProfileSelected;
|
||||
_profileEditorService.ProfileElementSelected += OnProfileElementSelected;
|
||||
_profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated;
|
||||
@ -168,7 +165,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
_coreService.FrameRendered -= OnFrameRendered;
|
||||
HighlightSelectedLayer.SettingChanged -= HighlightSelectedLayerOnSettingChanged;
|
||||
_surfaceService.ActiveSurfaceConfigurationSelected -= OnActiveSurfaceConfigurationSelected;
|
||||
_rgbService.DeviceAdded -= RgbServiceOnDevicesModified;
|
||||
_rgbService.DeviceRemoved -= RgbServiceOnDevicesModified;
|
||||
_profileEditorService.ProfileSelected -= OnProfileSelected;
|
||||
_profileEditorService.ProfileElementSelected -= OnProfileElementSelected;
|
||||
_profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated;
|
||||
@ -181,9 +179,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
private void OnActiveSurfaceConfigurationSelected(object sender, SurfaceConfigurationEventArgs e)
|
||||
private void RgbServiceOnDevicesModified(object sender, DeviceEventArgs e)
|
||||
{
|
||||
ApplySurfaceConfiguration(e.Surface);
|
||||
ApplyDevices();
|
||||
}
|
||||
|
||||
private void ApplyActiveProfile()
|
||||
@ -193,10 +191,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
|
||||
// Add new layers missing a VM
|
||||
foreach (Layer layer in layers)
|
||||
{
|
||||
if (layerViewModels.All(vm => vm.Layer != layer))
|
||||
Items.Add(_profileLayerVmFactory.Create(layer, PanZoomViewModel));
|
||||
}
|
||||
|
||||
// Remove layers that no longer exist
|
||||
IEnumerable<ProfileLayerViewModel> toRemove = layerViewModels.Where(vm => !layers.Contains(vm.Layer));
|
||||
@ -204,10 +200,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
Items.Remove(profileLayerViewModel);
|
||||
}
|
||||
|
||||
private void ApplySurfaceConfiguration(ArtemisSurface surface)
|
||||
private void ApplyDevices()
|
||||
{
|
||||
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()
|
||||
@ -259,7 +255,15 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
|
||||
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
|
||||
@ -339,7 +343,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
_previousSelectedLayer.Transform.LayerPropertyOnCurrentValueSet += TransformValueChanged;
|
||||
}
|
||||
else
|
||||
{
|
||||
_previousSelectedLayer = null;
|
||||
}
|
||||
|
||||
ApplyActiveProfile();
|
||||
UpdateLedsDimStatus();
|
||||
|
||||
@ -40,8 +40,31 @@
|
||||
</Button>
|
||||
<materialDesign:PopupBox PlacementMode="BottomAndAlignRightEdges" StaysOpen="False">
|
||||
<StackPanel>
|
||||
<Button Content="Open plugin directory" Command="{s:Action OpenPluginDirectory}" />
|
||||
<Button Content="Open image directory" Command="{s:Action OpenImageDirectory}" />
|
||||
<Button Command="{s:Action OpenPluginDirectory}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="Plugin" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
||||
<TextBlock VerticalAlignment="Center">Open plugin directory</TextBlock>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Command="{s:Action OpenImageDirectory}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="Image" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
||||
<TextBlock VerticalAlignment="Center">Open layout image directory</TextBlock>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button Command="{s:Action ReloadLayout}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="Reload" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
||||
<TextBlock VerticalAlignment="Center">Reload layout</TextBlock>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button Command="{s:Action ExportLayout}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="Xml" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
||||
<TextBlock VerticalAlignment="Center">Export layout</TextBlock>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</materialDesign:PopupBox>
|
||||
</StackPanel>
|
||||
@ -55,27 +78,27 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock TextWrapping="Wrap" Margin="0 0 00 10">
|
||||
In this window you can view detailed information of the device.
|
||||
Please note that having this window open can have a performance impact on your system.
|
||||
<TextBlock TextWrapping="Wrap" Margin="0 0 0 10">
|
||||
In this window you can view detailed information of the device.
|
||||
Please note that having this window open can have a performance impact on your system.
|
||||
</TextBlock>
|
||||
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" Grid.Row="1" Padding="15">
|
||||
<shared:DeviceVisualizer Device="{Binding Device}"
|
||||
HighlightedLeds="{Binding SelectedLeds}"
|
||||
HorizontalAlignment="Center"
|
||||
MaxHeight="400"
|
||||
ShowColors="True"/>
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" Grid.Row="1" Padding="15" Margin="0 10">
|
||||
<shared:DeviceVisualizer Device="{Binding Device}"
|
||||
HighlightedLeds="{Binding SelectedLeds}"
|
||||
HorizontalAlignment="Center"
|
||||
MaxHeight="400"
|
||||
ShowColors="True" />
|
||||
</materialDesign:Card>
|
||||
|
||||
<Expander Grid.Row="2" VerticalAlignment="Center" Header="Device properties" Margin="0 15">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<materialDesign:Card Grid.Column="0" materialDesign:ShadowAssist.ShadowDepth="Depth1" Margin="0,0,5,0">
|
||||
<StackPanel Margin="15" HorizontalAlignment="Stretch">
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" Grid.Row="2" Padding="15" Margin="0 10">
|
||||
<Expander VerticalAlignment="Center" Header="Device properties">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" Margin="15" HorizontalAlignment="Stretch">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
@ -87,12 +110,12 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Device name</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}" />
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="0 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@ -105,30 +128,12 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Manufacturer</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.DeviceInfo.Manufacturer}" />
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.DeviceInfo.Manufacturer}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Lighting support</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.DeviceInfo.Lighting}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="0 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@ -141,12 +146,30 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Device type</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.DeviceInfo.DeviceType}" />
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.DeviceInfo.DeviceType}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="0 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Physical layout</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.PhysicalLayout}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="0 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@ -159,15 +182,13 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Device image</TextBlock>
|
||||
<TextBox Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.DeviceInfo.Image, Mode=OneWay}"
|
||||
IsReadOnly="True" />
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.Layout.Image, Mode=OneWay}"
|
||||
IsReadOnly="True" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
<materialDesign:Card Grid.Column="1" materialDesign:ShadowAssist.ShadowDepth="Depth1" Margin="5,0,0,0" >
|
||||
<StackPanel Margin="15" HorizontalAlignment="Stretch">
|
||||
<StackPanel Grid.Column="1" Margin="15" HorizontalAlignment="Stretch">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
@ -179,12 +200,12 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Size (1px = 1mm)</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.Size}" />
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.Size}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="0 5" />
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
@ -196,12 +217,12 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Location (1px = 1mm)</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.Location}" />
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.Location}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="0 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@ -214,12 +235,12 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Rotation (degrees)</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.Rotation.Degrees}" />
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.Rotation.Degrees}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="0 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@ -230,14 +251,14 @@
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Syncback supported</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Logical layout</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.RgbDevice.DeviceInfo.SupportsSyncBack}" />
|
||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.LogicalLayout}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="0 5" />
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@ -250,17 +271,17 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Layout file path</TextBlock>
|
||||
<TextBox Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.LayoutPath, Mode=OneWay}"
|
||||
IsReadOnly="True" />
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Device.Layout.FilePath, Mode=OneWay}"
|
||||
IsReadOnly="True" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
</Grid>
|
||||
</Expander>
|
||||
</Grid>
|
||||
</Expander>
|
||||
</materialDesign:Card>
|
||||
|
||||
<materialDesign:Card Grid.Row="3" materialDesign:ShadowAssist.ShadowDepth="Depth1" Padding="15" MaxHeight="413">
|
||||
<materialDesign:Card Grid.Row="3" materialDesign:ShadowAssist.ShadowDepth="Depth1" Padding="15" MaxHeight="413" Margin="0 10">
|
||||
<DataGrid ItemsSource="{Binding Device.Leds}"
|
||||
d:DataContext="{d:DesignInstance Type=core:ArtemisLed}"
|
||||
CanUserSortColumns="True"
|
||||
@ -270,8 +291,7 @@
|
||||
materialDesign:DataGridAssist.CellPadding="13 8 8 8"
|
||||
materialDesign:DataGridAssist.ColumnHeaderPadding="8"
|
||||
SelectedItem="{Binding SelectedLed}"
|
||||
CanUserResizeRows="False"
|
||||
>
|
||||
CanUserResizeRows="False">
|
||||
<DataGrid.Columns>
|
||||
<materialDesign:DataGridTextColumn Binding="{Binding RgbLed.Id}" Header="LED ID" Width="Auto" />
|
||||
<materialDesign:DataGridTextColumn Binding="{Binding RgbLed.Color}" Header="Color (ARGB)" Width="Auto" />
|
||||
@ -282,9 +302,9 @@
|
||||
</DataGrid>
|
||||
</materialDesign:Card>
|
||||
|
||||
|
||||
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
|
||||
</DockPanel>
|
||||
</mde:MaterialWindow>
|
||||
@ -2,10 +2,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Stylet; // using PropertyChanged;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using RGB.NET.Layout;
|
||||
using Stylet;
|
||||
|
||||
// using PropertyChanged;
|
||||
|
||||
namespace Artemis.UI.Screens.Settings.Debug
|
||||
{
|
||||
@ -13,11 +18,13 @@ namespace Artemis.UI.Screens.Settings.Debug
|
||||
{
|
||||
private readonly IDeviceService _deviceService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private ArtemisLed _selectedLed;
|
||||
|
||||
public DeviceDebugViewModel(ArtemisDevice device, IDeviceService deviceService, IDialogService dialogService)
|
||||
public DeviceDebugViewModel(ArtemisDevice device, IDeviceService deviceService, IRgbService rgbService, IDialogService dialogService)
|
||||
{
|
||||
_deviceService = deviceService;
|
||||
_rgbService = rgbService;
|
||||
_dialogService = dialogService;
|
||||
Device = device;
|
||||
}
|
||||
@ -35,7 +42,7 @@ namespace Artemis.UI.Screens.Settings.Debug
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanOpenImageDirectory => Device.RgbDevice.DeviceInfo.Image != null;
|
||||
public bool CanOpenImageDirectory => Device.Layout?.Image != null;
|
||||
|
||||
// ReSharper disable UnusedMember.Global
|
||||
|
||||
@ -70,7 +77,7 @@ namespace Artemis.UI.Screens.Settings.Debug
|
||||
|
||||
try
|
||||
{
|
||||
Process.Start(Environment.GetEnvironmentVariable("WINDIR") + @"\explorer.exe", Path.GetDirectoryName(Device.RgbDevice.DeviceInfo.Image.AbsolutePath));
|
||||
Process.Start(Environment.GetEnvironmentVariable("WINDIR") + @"\explorer.exe", Path.GetDirectoryName(Device.Layout.Image.AbsolutePath));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -78,6 +85,73 @@ namespace Artemis.UI.Screens.Settings.Debug
|
||||
}
|
||||
}
|
||||
|
||||
public void ReloadLayout()
|
||||
{
|
||||
_rgbService.ApplyBestDeviceLayout(Device);
|
||||
}
|
||||
|
||||
public void ExportLayout()
|
||||
{
|
||||
if (Device.Layout == null)
|
||||
return;
|
||||
|
||||
VistaFolderBrowserDialog dialog = new()
|
||||
{
|
||||
Description = "Select layout export target folder",
|
||||
UseDescriptionForTitle = true,
|
||||
ShowNewFolderButton = true,
|
||||
SelectedPath = Path.Combine(Constants.DataFolder, "user layouts")
|
||||
};
|
||||
|
||||
bool? result = dialog.ShowDialog();
|
||||
if (result != true)
|
||||
return;
|
||||
|
||||
string directory = Path.Combine(
|
||||
dialog.SelectedPath,
|
||||
Device.RgbDevice.DeviceInfo.Manufacturer,
|
||||
Device.RgbDevice.DeviceInfo.DeviceType.ToString()
|
||||
);
|
||||
string filePath = Path.Combine(directory, Device.GetLayoutFileName());
|
||||
Core.Utilities.CreateAccessibleDirectory(directory);
|
||||
|
||||
// XML
|
||||
XmlSerializer serializer = new(typeof(DeviceLayout));
|
||||
using StreamWriter writer = new(filePath);
|
||||
serializer.Serialize(writer, Device.Layout!.RgbLayout);
|
||||
|
||||
// Device images
|
||||
if (!Uri.IsWellFormedUriString(Device.Layout.FilePath, UriKind.Absolute))
|
||||
return;
|
||||
|
||||
Uri targetDirectory = new(directory + "/", UriKind.Absolute);
|
||||
Uri sourceDirectory = new(Path.GetDirectoryName(Device.Layout.FilePath)! + "/", UriKind.Absolute);
|
||||
Uri deviceImageTarget = new(targetDirectory, Device.Layout.LayoutCustomDeviceData.DeviceImage);
|
||||
|
||||
// Create folder (if needed) and copy image
|
||||
Core.Utilities.CreateAccessibleDirectory(Path.GetDirectoryName(deviceImageTarget.LocalPath)!);
|
||||
if (Device.Layout.Image != null && File.Exists(Device.Layout.Image.LocalPath) && !File.Exists(deviceImageTarget.LocalPath))
|
||||
File.Copy(Device.Layout.Image.LocalPath, deviceImageTarget.LocalPath);
|
||||
|
||||
foreach (ArtemisLedLayout ledLayout in Device.Layout.Leds)
|
||||
{
|
||||
if (ledLayout.LayoutCustomLedData.LogicalLayouts == null)
|
||||
continue;
|
||||
|
||||
// Only the image of the current logical layout is available as an URI, iterate each layout and find the images manually
|
||||
foreach (LayoutCustomLedDataLogicalLayout logicalLayout in ledLayout.LayoutCustomLedData.LogicalLayouts)
|
||||
{
|
||||
Uri image = new(sourceDirectory, logicalLayout.Image);
|
||||
Uri imageTarget = new(targetDirectory, logicalLayout.Image);
|
||||
|
||||
// Create folder (if needed) and copy image
|
||||
Core.Utilities.CreateAccessibleDirectory(Path.GetDirectoryName(imageTarget.LocalPath)!);
|
||||
if (File.Exists(image.LocalPath) && !File.Exists(imageTarget.LocalPath))
|
||||
File.Copy(image.LocalPath, imageTarget.LocalPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// ReSharper restore UnusedMember.Global
|
||||
|
||||
@ -11,15 +11,15 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
public class DeviceSettingsTabViewModel : Conductor<DeviceSettingsViewModel>.Collection.AllActive
|
||||
{
|
||||
private readonly ISettingsVmFactory _settingsVmFactory;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private bool _confirmedDisable;
|
||||
|
||||
public DeviceSettingsTabViewModel(ISurfaceService surfaceService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory)
|
||||
public DeviceSettingsTabViewModel(IRgbService rgbService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory)
|
||||
{
|
||||
DisplayName = "DEVICES";
|
||||
|
||||
_surfaceService = surfaceService;
|
||||
_rgbService = rgbService;
|
||||
_dialogService = dialogService;
|
||||
_settingsVmFactory = settingsVmFactory;
|
||||
}
|
||||
@ -32,7 +32,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
Items.Clear();
|
||||
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)
|
||||
Items.Add(deviceSettingsViewModel);
|
||||
});
|
||||
|
||||
@ -76,7 +76,7 @@
|
||||
<Button Command="{s:Action ViewProperties}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="Gear" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
||||
<TextBlock VerticalAlignment="Center">View surface properties</TextBlock>
|
||||
<TextBlock VerticalAlignment="Center">Device properties</TextBlock>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
@ -6,7 +6,6 @@ using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Dialogs;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Visualization;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Humanizer;
|
||||
using RGB.NET.Core;
|
||||
@ -17,9 +16,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
public class DeviceSettingsViewModel : Screen
|
||||
{
|
||||
private readonly IDeviceDebugVmFactory _deviceDebugVmFactory;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly IDeviceService _deviceService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IWindowManager _windowManager;
|
||||
|
||||
public DeviceSettingsViewModel(ArtemisDevice device,
|
||||
@ -27,13 +26,13 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
IDialogService dialogService,
|
||||
IWindowManager windowManager,
|
||||
IDeviceDebugVmFactory deviceDebugVmFactory,
|
||||
ISurfaceService surfaceService)
|
||||
IRgbService rgbService)
|
||||
{
|
||||
_deviceService = deviceService;
|
||||
_dialogService = dialogService;
|
||||
_windowManager = windowManager;
|
||||
_deviceDebugVmFactory = deviceDebugVmFactory;
|
||||
_surfaceService = surfaceService;
|
||||
_rgbService = rgbService;
|
||||
Device = device;
|
||||
|
||||
Type = Device.RgbDevice.DeviceInfo.DeviceType.ToString().Humanize();
|
||||
@ -53,26 +52,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
public bool IsDeviceEnabled
|
||||
{
|
||||
get => Device.IsEnabled;
|
||||
set
|
||||
{
|
||||
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);
|
||||
set { Task.Run(() => UpdateIsDeviceEnabled(value)); }
|
||||
}
|
||||
|
||||
public void IdentifyDevice()
|
||||
@ -104,7 +84,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
);
|
||||
|
||||
if ((bool) madeChanges)
|
||||
_surfaceService.UpdateSurfaceConfiguration(_surfaceService.ActiveSurface, true);
|
||||
_rgbService.SaveDevice(Device);
|
||||
}
|
||||
|
||||
public async Task ViewProperties()
|
||||
@ -114,7 +94,25 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
||||
);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -57,6 +57,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
// Take it off the UI thread to avoid freezing on tab change
|
||||
Task.Run(async () =>
|
||||
{
|
||||
Items.Clear();
|
||||
await Task.Delay(200);
|
||||
_instances = _pluginManagementService.GetAllPlugins()
|
||||
.Select(p => _settingsVmFactory.CreatePluginSettingsViewModel(p))
|
||||
|
||||
@ -5,6 +5,7 @@ using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Artemis.UI.Extensions;
|
||||
using RGB.NET.Core;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
@ -144,6 +145,13 @@ namespace Artemis.UI.Screens.Shared
|
||||
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)
|
||||
{
|
||||
return TransformContainingRect(rect.ToWindowsRect(1));
|
||||
@ -168,11 +176,15 @@ namespace Artemis.UI.Screens.Shared
|
||||
|
||||
private void SetZoomFromPercentage(double value)
|
||||
{
|
||||
double newZoom = value / 100;
|
||||
// Focus towards the center of the zoomed area
|
||||
PanX += newZoom - Zoom;
|
||||
PanY += newZoom - Zoom;
|
||||
Point relative = new((PanX * -1 + CanvasWidth / 2) / Zoom, (PanY * -1 + CanvasHeight / 2) / Zoom);
|
||||
double absoluteX = relative.X * Zoom + PanX;
|
||||
double absoluteY = relative.Y * Zoom + PanY;
|
||||
|
||||
Zoom = value / 100;
|
||||
|
||||
// Focus towards the center of the zoomed area
|
||||
PanX = absoluteX - relative.X * Zoom;
|
||||
PanY = absoluteY - relative.Y * Zoom;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<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" />.
|
||||
</TextBlock>
|
||||
|
||||
|
||||
@ -5,23 +5,23 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
|
||||
{
|
||||
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()
|
||||
{
|
||||
_surfaceService.AutoArrange();
|
||||
_rgbService.AutoArrangeDevices();
|
||||
StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent;
|
||||
startupWizardViewModel.Continue();
|
||||
}
|
||||
|
||||
public void ApplyRightHandedPreset()
|
||||
{
|
||||
_surfaceService.AutoArrange();
|
||||
_rgbService.AutoArrangeDevices();
|
||||
StartupWizardViewModel startupWizardViewModel = (StartupWizardViewModel) Parent;
|
||||
startupWizardViewModel.Continue();
|
||||
}
|
||||
|
||||
@ -155,12 +155,39 @@
|
||||
<shared:ColorPicker Grid.Column="1"
|
||||
Margin="0,0,5,0"
|
||||
HorizontalAlignment="Right"
|
||||
Color="{Binding CurrentColor, Converter={StaticResource SKColorToColorConverter}}"
|
||||
VerticalAlignment="Center"/>
|
||||
Color="{Binding CurrentColor, Converter={StaticResource SKColorToColorConverter}}"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<!-- Layout -->
|
||||
<TextBlock Style="{StaticResource MaterialDesignSubtitle1TextBlock}" Margin="0 25 0 0">
|
||||
Custom layout
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignCaptionTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignBodyLight}"
|
||||
TextWrapping="Wrap"
|
||||
TextAlignment="Justify">
|
||||
Select a custom layout below if you want to change the appearance and/or LEDs of this device.
|
||||
</TextBlock>
|
||||
|
||||
<TextBox Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||
Text="{Binding Device.CustomLayoutPath}"
|
||||
VerticalAlignment="Center"
|
||||
materialDesign:TextFieldAssist.HasClearButton="True"
|
||||
IsReadOnly="True"
|
||||
PreviewMouseLeftButtonUp="{s:Action BrowseCustomLayout}">
|
||||
<materialDesign:HintAssist.Hint>
|
||||
<StackPanel Orientation="Horizontal" Margin="-2 0 0 0">
|
||||
<materialDesign:PackIcon Kind="Xml" Width="20" />
|
||||
<TextBlock>
|
||||
Layout path
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</materialDesign:HintAssist.Hint>
|
||||
</TextBox>
|
||||
|
||||
<!-- Buttons -->
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Right">
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
@ -10,6 +15,8 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
public class SurfaceDeviceConfigViewModel : DialogViewModelBase
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IMessageService _messageService;
|
||||
private readonly double _initialRedScale;
|
||||
private readonly double _initialGreenScale;
|
||||
private readonly double _initialBlueScale;
|
||||
@ -23,41 +30,43 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
private SKColor _currentColor;
|
||||
private bool _displayOnDevices;
|
||||
|
||||
public SurfaceDeviceConfigViewModel(ArtemisDevice device, ICoreService coreService, IModelValidator<SurfaceDeviceConfigViewModel> validator) : base(validator)
|
||||
public SurfaceDeviceConfigViewModel(ArtemisDevice device,
|
||||
ICoreService coreService,
|
||||
IRgbService rgbService,
|
||||
IMessageService messageService,
|
||||
IModelValidator<SurfaceDeviceConfigViewModel> validator) : base(validator)
|
||||
{
|
||||
_coreService = coreService;
|
||||
_rgbService = rgbService;
|
||||
_messageService = messageService;
|
||||
|
||||
Device = device;
|
||||
|
||||
X = (int)Device.X;
|
||||
Y = (int)Device.Y;
|
||||
X = (int) Device.X;
|
||||
Y = (int) Device.Y;
|
||||
Scale = Device.Scale;
|
||||
Rotation = (int)Device.Rotation;
|
||||
Rotation = (int) Device.Rotation;
|
||||
RedScale = Device.RedScale * 100d;
|
||||
GreenScale = Device.GreenScale * 100d;
|
||||
BlueScale = Device.BlueScale * 100d;
|
||||
//we need to store the initial values to be able to restore them when the user clicks "Cancel"
|
||||
_initialRedScale = Device.RedScale;
|
||||
_initialRedScale = Device.RedScale;
|
||||
_initialGreenScale = Device.GreenScale;
|
||||
_initialBlueScale = Device.BlueScale;
|
||||
CurrentColor = SKColors.White;
|
||||
_coreService.FrameRendering += OnFrameRendering;
|
||||
}
|
||||
|
||||
private void OnFrameRendering(object sender, FrameRenderingEventArgs e)
|
||||
{
|
||||
if (!_displayOnDevices)
|
||||
return;
|
||||
|
||||
using SKPaint overlayPaint = new()
|
||||
{
|
||||
Color = CurrentColor
|
||||
};
|
||||
e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint);
|
||||
Device.PropertyChanged += DeviceOnPropertyChanged;
|
||||
}
|
||||
|
||||
public ArtemisDevice Device { get; }
|
||||
|
||||
public override void OnDialogClosed(object sender, DialogClosingEventArgs e)
|
||||
{
|
||||
_coreService.FrameRendering -= OnFrameRendering;
|
||||
Device.PropertyChanged -= DeviceOnPropertyChanged;
|
||||
base.OnDialogClosed(sender, e);
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get => _x;
|
||||
@ -130,7 +139,6 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
Device.BlueScale = BlueScale / 100d;
|
||||
|
||||
_coreService.ModuleRenderingDisabled = false;
|
||||
_coreService.FrameRendering -= OnFrameRendering;
|
||||
Session.Close(true);
|
||||
}
|
||||
|
||||
@ -141,6 +149,26 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
Device.BlueScale = BlueScale / 100d;
|
||||
}
|
||||
|
||||
public void BrowseCustomLayout(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is Button)
|
||||
{
|
||||
Device.CustomLayoutPath = null;
|
||||
_messageService.ShowMessage("Cleared imported layout");
|
||||
return;
|
||||
}
|
||||
|
||||
VistaOpenFileDialog dialog = new();
|
||||
dialog.Filter = "Layout files (*.xml)|*.xml";
|
||||
dialog.Title = "Select device layout file";
|
||||
bool? result = dialog.ShowDialog();
|
||||
if (result == true)
|
||||
{
|
||||
Device.CustomLayoutPath = dialog.FileName;
|
||||
_messageService.ShowMessage($"Imported layout from {dialog.FileName}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Cancel()
|
||||
{
|
||||
Device.RedScale = _initialRedScale;
|
||||
@ -149,5 +177,25 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
|
||||
base.Cancel();
|
||||
}
|
||||
|
||||
private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(Device.CustomLayoutPath))
|
||||
{
|
||||
_rgbService.ApplyBestDeviceLayout(Device);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFrameRendering(object sender, FrameRenderingEventArgs e)
|
||||
{
|
||||
if (!_displayOnDevices)
|
||||
return;
|
||||
|
||||
using SKPaint overlayPaint = new()
|
||||
{
|
||||
Color = CurrentColor
|
||||
};
|
||||
e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14,9 +14,10 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
{
|
||||
private readonly IInputService _inputService;
|
||||
private readonly IMessageService _messageService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly ListLedGroup _ledGroup;
|
||||
|
||||
public SurfaceDeviceDetectInputViewModel(ArtemisDevice device, IInputService inputService, IMessageService messageService)
|
||||
public SurfaceDeviceDetectInputViewModel(ArtemisDevice device, IInputService inputService, IMessageService messageService, IRgbService rgbService)
|
||||
{
|
||||
Device = device;
|
||||
Title = $"{Device.RgbDevice.DeviceInfo.DeviceName} - Detect input";
|
||||
@ -24,11 +25,12 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
|
||||
_inputService = inputService;
|
||||
_messageService = messageService;
|
||||
_rgbService = rgbService;
|
||||
_inputService.IdentifyDevice(Device);
|
||||
_inputService.DeviceIdentified += InputServiceOnDeviceIdentified;
|
||||
|
||||
// Create a LED group way at the top
|
||||
_ledGroup = new ListLedGroup(Device.Leds.Select(l => l.RgbLed))
|
||||
_ledGroup = new ListLedGroup(_rgbService.Surface, Device.Leds.Select(l => l.RgbLed))
|
||||
{
|
||||
Brush = new SolidColorBrush(new Color(255, 255, 0)),
|
||||
ZIndex = 999
|
||||
@ -43,7 +45,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
{
|
||||
base.OnDialogClosed(sender, e);
|
||||
_inputService.DeviceIdentified -= InputServiceOnDeviceIdentified;
|
||||
_ledGroup.Detach();
|
||||
_ledGroup.Detach(_rgbService.Surface);
|
||||
}
|
||||
|
||||
private void InputServiceOnDeviceIdentified(object sender, EventArgs e)
|
||||
|
||||
@ -5,11 +5,12 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:Converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:models="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Screens.SurfaceEditor"
|
||||
x:Class="Artemis.UI.Screens.SurfaceEditor.SurfaceEditorView"
|
||||
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>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
@ -18,7 +19,6 @@
|
||||
<ResourceDictionary
|
||||
Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.PopupBox.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<Converters:InverseBooleanConverter x:Key="InverseBooleanConverter" />
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Margin="16">
|
||||
@ -113,14 +113,17 @@
|
||||
</EventTrigger>
|
||||
</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>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="{Binding PanZoomViewModel.Zoom}" ScaleY="{Binding PanZoomViewModel.Zoom}" />
|
||||
<TranslateTransform X="{Binding PanZoomViewModel.PanX}" Y="{Binding PanZoomViewModel.PanY}" />
|
||||
</TransformGroup>
|
||||
</Grid.RenderTransform>
|
||||
<ItemsControl ItemsSource="{Binding Devices}">
|
||||
<ItemsControl ItemsSource="{Binding SurfaceDeviceViewModels}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas />
|
||||
@ -137,28 +140,28 @@
|
||||
<ContentControl s:View.Model="{Binding}">
|
||||
<ContentControl.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Identify" Command="{s:Action IdentifyDevice}" CommandParameter="{Binding}">
|
||||
<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}">
|
||||
<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}">
|
||||
<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}">
|
||||
<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}">
|
||||
<MenuItem Header="Send Backward" Command="{s:Action SendBackward}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ArrangeSendBackward" />
|
||||
</MenuItem.Icon>
|
||||
@ -167,14 +170,14 @@
|
||||
<!-- Stylet can't disable it for us here, do it ourselves -->
|
||||
<MenuItem Header="Identify input"
|
||||
Command="{s:Action DetectInput}"
|
||||
CommandParameter="{Binding}"
|
||||
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}">
|
||||
<MenuItem Header="View properties" Command="{s:Action ViewProperties}" CommandParameter="{Binding Device}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="Gear" />
|
||||
</MenuItem.Icon>
|
||||
@ -231,45 +234,67 @@
|
||||
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" Grid.Row="1" Grid.Column="2" VerticalAlignment="Stretch" Margin="5,0,0,0">
|
||||
<materialDesign:DialogHost Identifier="SurfaceListDialogHost" DialogTheme="Inherit" CloseOnClickAway="True">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ListBox Grid.Row="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding SurfaceConfigurations}" SelectedItem="{Binding SelectedSurface}">
|
||||
<ListBox.Resources>
|
||||
<DataTemplate DataType="{x:Type models:ArtemisSurface}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<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>
|
||||
|
||||
</DataTemplate>
|
||||
</ListBox.Resources>
|
||||
</ListBox>
|
||||
<Button Grid.Row="0"
|
||||
Style="{StaticResource MaterialDesignFloatingActionButton}"
|
||||
Command="{s:Action AddSurfaceConfiguration}"
|
||||
Margin="0 0 10 10"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
ToolTip="Add a new surface layout">
|
||||
<materialDesign:PackIcon Kind="Add" Height="24" Width="24" />
|
||||
</Button>
|
||||
</Grid>
|
||||
<ListBox Grid.Row="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding ListDeviceViewModels}" SelectionMode="Multiple">
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
|
||||
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
|
||||
</Style>
|
||||
|
||||
</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>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</materialDesign:DialogHost>
|
||||
</materialDesign:Card>
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
@ -10,11 +9,13 @@ using System.Windows.Media;
|
||||
using System.Windows.Navigation;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Screens.Shared;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Dialogs;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Visualization;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
using MouseButton = System.Windows.Input.MouseButton;
|
||||
|
||||
@ -22,54 +23,42 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
{
|
||||
public class SurfaceEditorViewModel : Screen, IMainScreenViewModel
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IDeviceService _deviceService;
|
||||
private readonly IInputService _inputService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IInputService _inputService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private Cursor _cursor;
|
||||
private ObservableCollection<SurfaceDeviceViewModel> _devices;
|
||||
private PanZoomViewModel _panZoomViewModel;
|
||||
private ArtemisSurface _selectedSurface;
|
||||
private RectangleGeometry _selectionRectangle;
|
||||
private ObservableCollection<ArtemisSurface> _surfaceConfigurations;
|
||||
private PluginSetting<GridLength> _surfaceListWidth;
|
||||
|
||||
public SurfaceEditorViewModel(IRgbService rgbService,
|
||||
ISurfaceService surfaceService,
|
||||
ICoreService coreService,
|
||||
IDialogService dialogService,
|
||||
ISettingsService settingsService,
|
||||
IDeviceService deviceService,
|
||||
IInputService inputService)
|
||||
{
|
||||
DisplayName = "Surface Editor";
|
||||
|
||||
Devices = new ObservableCollection<SurfaceDeviceViewModel>();
|
||||
SurfaceConfigurations = new ObservableCollection<ArtemisSurface>();
|
||||
SelectionRectangle = new RectangleGeometry();
|
||||
PanZoomViewModel = new PanZoomViewModel();
|
||||
Cursor = null;
|
||||
|
||||
SurfaceDeviceViewModels = new BindableCollection<SurfaceDeviceViewModel>();
|
||||
ListDeviceViewModels = new BindableCollection<ListDeviceViewModel>();
|
||||
|
||||
_rgbService = rgbService;
|
||||
_surfaceService = surfaceService;
|
||||
_coreService = coreService;
|
||||
_dialogService = dialogService;
|
||||
_settingsService = settingsService;
|
||||
_deviceService = deviceService;
|
||||
_inputService = inputService;
|
||||
}
|
||||
|
||||
public ObservableCollection<SurfaceDeviceViewModel> Devices
|
||||
{
|
||||
get => _devices;
|
||||
set => SetAndNotify(ref _devices, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<ArtemisSurface> SurfaceConfigurations
|
||||
{
|
||||
get => _surfaceConfigurations;
|
||||
set => SetAndNotify(ref _surfaceConfigurations, value);
|
||||
}
|
||||
public BindableCollection<SurfaceDeviceViewModel> SurfaceDeviceViewModels { get; }
|
||||
public BindableCollection<ListDeviceViewModel> ListDeviceViewModels { get; }
|
||||
|
||||
public RectangleGeometry SelectionRectangle
|
||||
{
|
||||
@ -95,26 +84,6 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
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)
|
||||
{
|
||||
Core.Utilities.OpenUrl(e.Uri.AbsoluteUri);
|
||||
@ -126,7 +95,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
_surfaceService.AutoArrange();
|
||||
_rgbService.AutoArrangeDevices();
|
||||
}
|
||||
|
||||
private void LoadWorkspaceSettings()
|
||||
@ -139,184 +108,139 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
SurfaceListWidth.Save();
|
||||
}
|
||||
|
||||
private void LoadSurfaceConfigurations()
|
||||
|
||||
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
|
||||
{
|
||||
// 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);
|
||||
foreach (ListDeviceViewModel listDeviceViewModel in ListDeviceViewModels)
|
||||
foreach (ArtemisLed artemisLed in listDeviceViewModel.Device.Leds)
|
||||
e.Canvas.DrawRect(artemisLed.AbsoluteRectangle, new SKPaint {Color = listDeviceViewModel.Color});
|
||||
}
|
||||
|
||||
#region Overrides of Screen
|
||||
|
||||
protected override void OnInitialActivate()
|
||||
{
|
||||
LoadSurfaceConfigurations();
|
||||
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)));
|
||||
|
||||
List<ArtemisDevice> shuffledDevices = _rgbService.EnabledDevices.OrderBy(d => Guid.NewGuid()).ToList();
|
||||
float amount = 360f / shuffledDevices.Count;
|
||||
for (int i = 0; i < shuffledDevices.Count; i++)
|
||||
{
|
||||
ArtemisDevice rgbServiceDevice = shuffledDevices[i];
|
||||
ListDeviceViewModel vm = ListDeviceViewModels.First(l => l.Device == rgbServiceDevice);
|
||||
vm.Color = SKColor.FromHsv(amount * i, 100, 100);
|
||||
}
|
||||
|
||||
_coreService.FrameRendering += CoreServiceOnFrameRendering;
|
||||
|
||||
base.OnInitialActivate();
|
||||
}
|
||||
|
||||
protected override void OnClose()
|
||||
{
|
||||
SaveWorkspaceSettings();
|
||||
SurfaceDeviceViewModels.Clear();
|
||||
ListDeviceViewModels.Clear();
|
||||
|
||||
_coreService.FrameRendering -= CoreServiceOnFrameRendering;
|
||||
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
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);
|
||||
for (int i = 0; i < Devices.Count; i++)
|
||||
SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
|
||||
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;
|
||||
}
|
||||
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
|
||||
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
public void BringForward(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public void BringForward(ArtemisDevice device)
|
||||
{
|
||||
int currentIndex = Devices.IndexOf(surfaceDeviceViewModel);
|
||||
int newIndex = Math.Min(currentIndex + 1, Devices.Count - 1);
|
||||
Devices.Move(currentIndex, newIndex);
|
||||
SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
|
||||
int currentIndex = SurfaceDeviceViewModels.IndexOf(surfaceDeviceViewModel);
|
||||
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;
|
||||
}
|
||||
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
|
||||
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
public void SendToBack(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public void SendToBack(ArtemisDevice device)
|
||||
{
|
||||
Devices.Move(Devices.IndexOf(surfaceDeviceViewModel), 0);
|
||||
for (int i = 0; i < Devices.Count; i++)
|
||||
SurfaceDeviceViewModel surfaceDeviceViewModel = SurfaceDeviceViewModels.First(d => d.Device == device);
|
||||
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;
|
||||
}
|
||||
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
|
||||
|
||||
_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);
|
||||
Devices.Move(currentIndex, newIndex);
|
||||
for (int i = 0; i < Devices.Count; i++)
|
||||
SurfaceDeviceViewModels.Move(currentIndex, newIndex);
|
||||
for (int i = 0; i < SurfaceDeviceViewModels.Count; i++)
|
||||
{
|
||||
SurfaceDeviceViewModel deviceViewModel = Devices[i];
|
||||
SurfaceDeviceViewModel deviceViewModel = SurfaceDeviceViewModels[i];
|
||||
deviceViewModel.Device.ZIndex = i + 1;
|
||||
}
|
||||
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
ListDeviceViewModels.Sort(l => l.Device.ZIndex * -1);
|
||||
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
public async Task ViewProperties(SurfaceDeviceViewModel surfaceDeviceViewModel)
|
||||
public async Task ViewProperties(ArtemisDevice device)
|
||||
{
|
||||
object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceConfigViewModel>(
|
||||
new Dictionary<string, object> {{"device", surfaceDeviceViewModel.Device}}
|
||||
new Dictionary<string, object> {{"device", device}}
|
||||
);
|
||||
|
||||
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>(
|
||||
new Dictionary<string, object> {{"device", surfaceDeviceViewModel.Device}}
|
||||
new Dictionary<string, object> {{"device", device}}
|
||||
);
|
||||
|
||||
if ((bool) madeChanges)
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
_rgbService.SaveDevice(device);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -377,13 +301,13 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
if (device.SelectionStatus != SelectionStatus.Selected)
|
||||
{
|
||||
if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
|
||||
foreach (SurfaceDeviceViewModel others in Devices)
|
||||
foreach (SurfaceDeviceViewModel others in SurfaceDeviceViewModels)
|
||||
others.SelectionStatus = SelectionStatus.None;
|
||||
|
||||
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);
|
||||
}
|
||||
// Start multi-selection
|
||||
@ -395,6 +319,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
|
||||
// Any time dragging starts, start with a new rect
|
||||
SelectionRectangle.Rect = new Rect();
|
||||
ApplySurfaceSelection();
|
||||
}
|
||||
|
||||
private void StopMouseDrag(object sender, Point position)
|
||||
@ -403,17 +328,20 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
{
|
||||
RectangleGeometry selectedRect = new(new Rect(_mouseDragStartPoint, position));
|
||||
List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, selectedRect);
|
||||
foreach (SurfaceDeviceViewModel device in Devices)
|
||||
foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels)
|
||||
if (devices.Contains(device))
|
||||
device.SelectionStatus = SelectionStatus.Selected;
|
||||
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
|
||||
device.SelectionStatus = SelectionStatus.None;
|
||||
}
|
||||
else
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
{
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
_mouseDragStatus = MouseDragStatus.None;
|
||||
_rgbService.IsRenderPaused = false;
|
||||
ApplySurfaceSelection();
|
||||
}
|
||||
|
||||
private void UpdateSelection(object sender, Point position)
|
||||
@ -425,19 +353,27 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
SelectionRectangle.Rect = selectedRect;
|
||||
|
||||
List<SurfaceDeviceViewModel> devices = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, SelectionRectangle);
|
||||
foreach (SurfaceDeviceViewModel device in Devices)
|
||||
foreach (SurfaceDeviceViewModel device in SurfaceDeviceViewModels)
|
||||
if (devices.Contains(device))
|
||||
device.SelectionStatus = SelectionStatus.Selected;
|
||||
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
|
||||
device.SelectionStatus = SelectionStatus.None;
|
||||
|
||||
ApplySurfaceSelection();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private void ApplySurfaceSelection()
|
||||
{
|
||||
foreach (ListDeviceViewModel viewModel in ListDeviceViewModels)
|
||||
viewModel.IsSelected = SurfaceDeviceViewModels.Any(s => s.Device == viewModel.Device && s.SelectionStatus == SelectionStatus.Selected);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Panning and zooming
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
<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}}">
|
||||
<UserControl.Resources>
|
||||
<shared:SKColorToColorConverter x:Key="SKColorToColorConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="50" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<shared:DeviceVisualizer Device="{Binding Device}" Width="30" Height="30" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.Model}" />
|
||||
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.Manufacturer}" Foreground="{DynamicResource MaterialDesignBodyLight}" />
|
||||
</StackPanel>
|
||||
<Ellipse Grid.Column="2" Width="20" Height="20" Stroke="{DynamicResource MaterialDesignBody}" StrokeThickness="1">
|
||||
<Ellipse.Fill>
|
||||
<SolidColorBrush Color="{Binding Color, Converter={StaticResource SKColorToColorConverter}}" />
|
||||
</Ellipse.Fill>
|
||||
</Ellipse>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,30 @@
|
||||
using Artemis.Core;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
{
|
||||
public class ListDeviceViewModel : PropertyChangedBase
|
||||
{
|
||||
private bool _isSelected;
|
||||
private SKColor _color;
|
||||
public ArtemisDevice Device { get; }
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => _isSelected;
|
||||
set => SetAndNotify(ref _isSelected, value);
|
||||
}
|
||||
|
||||
public SKColor Color
|
||||
{
|
||||
get => _color;
|
||||
set => SetAndNotify(ref _color, value);
|
||||
}
|
||||
|
||||
public ListDeviceViewModel(ArtemisDevice device)
|
||||
{
|
||||
Device = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,10 +5,10 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
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:local="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Visualization"
|
||||
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"
|
||||
Cursor="{Binding Cursor}"
|
||||
MouseEnter="{s:Action MouseEnter}"
|
||||
@ -20,21 +20,22 @@
|
||||
<Grid>
|
||||
<!-- Content -->
|
||||
<Grid>
|
||||
<shared:DeviceVisualizer Device="{Binding Device}" ShowColors="True" VerticalAlignment="Top" HorizontalAlignment="Left" />
|
||||
|
||||
<Rectangle Fill="{DynamicResource MaterialDesignCardBackground}"
|
||||
Stroke="{DynamicResource MaterialDesignTextBoxBorder}"
|
||||
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"/>
|
||||
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
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"/>
|
||||
</Grid>
|
||||
|
||||
<shared:DeviceVisualizer Device="{Binding Device}" ShowColors="True" VerticalAlignment="Top" HorizontalAlignment="Left" />
|
||||
|
||||
</Grid>
|
||||
|
||||
<!-- Selection rectangle -->
|
||||
<Rectangle Width="Auto" Height="Auto" StrokeThickness="2">
|
||||
@ -47,7 +48,7 @@
|
||||
<Rectangle.Style>
|
||||
<Style TargetType="{x:Type Rectangle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.Hover}">
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static local:SelectionStatus.Hover}">
|
||||
<DataTrigger.EnterActions>
|
||||
<StopStoryboard BeginStoryboardName="ToSelected" />
|
||||
<BeginStoryboard x:Name="ToHover">
|
||||
@ -62,7 +63,7 @@
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.Selected}">
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static local:SelectionStatus.Selected}">
|
||||
<DataTrigger.EnterActions>
|
||||
<StopStoryboard BeginStoryboardName="ToHover" />
|
||||
<BeginStoryboard x:Name="ToSelected">
|
||||
@ -77,7 +78,7 @@
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.None}">
|
||||
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static local:SelectionStatus.None}">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using RGB.NET.Core;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
@ -13,26 +13,19 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
{
|
||||
public class SurfaceDeviceViewModel : PropertyChangedBase
|
||||
{
|
||||
private readonly IRgbService _rgbService;
|
||||
private Cursor _cursor;
|
||||
private ArtemisDevice _device;
|
||||
private double _dragOffsetX;
|
||||
private double _dragOffsetY;
|
||||
private SelectionStatus _selectionStatus;
|
||||
|
||||
public SurfaceDeviceViewModel(ArtemisDevice device)
|
||||
public SurfaceDeviceViewModel(ArtemisDevice device, IRgbService rgbService)
|
||||
{
|
||||
Device = device;
|
||||
_rgbService = rgbService;
|
||||
}
|
||||
|
||||
public ArtemisDevice Device
|
||||
{
|
||||
get => _device;
|
||||
set
|
||||
{
|
||||
if (SetAndNotify(ref _device, value)) return;
|
||||
NotifyOfPropertyChange(nameof(DeviceRectangle));
|
||||
}
|
||||
}
|
||||
public ArtemisDevice Device { get; }
|
||||
|
||||
public SelectionStatus SelectionStatus
|
||||
{
|
||||
@ -40,19 +33,15 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
set => SetAndNotify(ref _selectionStatus, value);
|
||||
}
|
||||
|
||||
public bool CanDetectInput => Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard ||
|
||||
Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse;
|
||||
|
||||
public Cursor Cursor
|
||||
{
|
||||
get => _cursor;
|
||||
set => SetAndNotify(ref _cursor, value);
|
||||
}
|
||||
|
||||
public Rect DeviceRectangle => Device.RgbDevice == null
|
||||
? new Rect()
|
||||
: new Rect(Device.X, Device.Y, Device.RgbDevice.DeviceRectangle.Size.Width, Device.RgbDevice.DeviceRectangle.Size.Height);
|
||||
|
||||
public bool CanDetectInput => Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard ||
|
||||
Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse;
|
||||
|
||||
|
||||
public void StartMouseDrag(Point mouseStartPosition)
|
||||
{
|
||||
_dragOffsetX = Device.X - mouseStartPosition.X;
|
||||
@ -115,7 +104,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
List<SKRect> own = Device.Leds
|
||||
.Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height))
|
||||
.ToList();
|
||||
List<SKRect> others = Device.Surface.Devices
|
||||
List<SKRect> others = _rgbService.EnabledDevices
|
||||
.Where(d => d != Device && d.IsEnabled)
|
||||
.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))
|
||||
@ -133,7 +122,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
||||
BottomLeft,
|
||||
BottomRight
|
||||
}
|
||||
|
||||
|
||||
public enum SelectionStatus
|
||||
{
|
||||
None,
|
||||
|
||||
@ -18,7 +18,6 @@ namespace Artemis.UI.Services
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
private readonly IInputService _inputService;
|
||||
private readonly IWebServerService _webServerService;
|
||||
private bool _registeredBuiltInDataModelDisplays;
|
||||
@ -29,7 +28,6 @@ namespace Artemis.UI.Services
|
||||
IDataModelUIService dataModelUIService,
|
||||
IProfileEditorService profileEditorService,
|
||||
IPluginManagementService pluginManagementService,
|
||||
ISurfaceService surfaceService,
|
||||
IInputService inputService,
|
||||
IWebServerService webServerService)
|
||||
{
|
||||
@ -37,7 +35,6 @@ namespace Artemis.UI.Services
|
||||
_dataModelUIService = dataModelUIService;
|
||||
_profileEditorService = profileEditorService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_surfaceService = surfaceService;
|
||||
_inputService = inputService;
|
||||
_webServerService = webServerService;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user