From 71f53c0833638cfcb2c9d8f25e06378e9bc5c364 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Wed, 18 Sep 2019 22:26:10 +0200 Subject: [PATCH] Redid some of the surface editor and started working on layout saving --- src/Artemis.Core/Artemis.Core.csproj | 52 ++++- src/Artemis.Core/Models/Profile/Folder.cs | 60 +++++ .../Profile/Interfaces/IProfileElement.cs | 35 +++ src/Artemis.Core/Models/Profile/Layer.cs | 80 +++++++ src/Artemis.Core/Models/Profile/Profile.cs | 113 ++++++++++ .../Models/Surface/SurfaceConfiguration.cs | 32 +++ .../Surface/SurfaceDeviceConfiguration.cs | 47 ++++ src/Artemis.Core/Ninject/CoreModule.cs | 10 +- src/Artemis.Core/Ninject/LoggerProvider.cs | 25 +++ .../Ninject/PluginSettingsProvider.cs | 2 +- .../Plugins/Abstract/LayerType.cs | 2 +- .../Plugins/Abstract/ProfileModule.cs | 2 +- .../Plugins/Models/PluginSetting.cs | 1 + .../Plugins/Models/PluginSettings.cs | 1 + src/Artemis.Core/Services/CoreService.cs | 7 +- src/Artemis.Core/Services/RgbService.cs | 54 ++++- .../Services/Storage/SurfaceService.cs | 41 ++++ src/Artemis.Core/Services/StorageService.cs | 2 +- src/Artemis.Core/app.config | 8 +- src/Artemis.Core/packages.config | 6 +- .../app.config | 20 ++ .../Artemis.Plugins.LayerTypes.Brush.csproj | 5 +- .../BrushLayerType.cs | 2 +- .../app.config | 20 ++ .../packages.config | 2 +- .../Artemis.Plugins.Modules.General.csproj | 5 +- .../app.config | 20 ++ .../packages.config | 2 +- src/Artemis.Storage/Entities/LedEntity.cs | 2 +- .../Entities/SurfaceDeviceEntity.cs | 22 ++ src/Artemis.Storage/Entities/SurfaceEntity.cs | 16 ++ .../Entities/SurfacePositionEntity.cs | 22 ++ .../Repositories/IRepository.cs | 6 - .../IPluginSettingRepository.cs | 2 +- .../Interfaces/IProfileRepository.cs | 17 ++ .../Repositories/Interfaces/IRepository.cs | 6 + .../{ => Interfaces}/ISettingRepository.cs | 2 +- .../Interfaces/ISurfaceRepository.cs | 18 ++ .../Repositories/PluginSettingRepository.cs | 1 + .../Repositories/ProfileRepository.cs | 8 +- .../Repositories/SettingRepository.cs | 1 + .../Repositories/SurfaceRepository.cs | 55 +++++ src/Artemis.Storage/StorageContext.cs | 1 + src/Artemis.UI/App.config | 8 +- src/Artemis.UI/Artemis.UI.csproj | 4 +- .../Screens/SurfaceEditorViewModel.cs | 63 +++++- .../Views/Screens/SurfaceEditorView.xaml | 207 +++++++++++++----- src/Artemis.UI/packages.config | 2 +- 48 files changed, 1012 insertions(+), 107 deletions(-) create mode 100644 src/Artemis.Core/Models/Profile/Folder.cs create mode 100644 src/Artemis.Core/Models/Profile/Interfaces/IProfileElement.cs create mode 100644 src/Artemis.Core/Models/Profile/Layer.cs create mode 100644 src/Artemis.Core/Models/Profile/Profile.cs create mode 100644 src/Artemis.Core/Models/Surface/SurfaceConfiguration.cs create mode 100644 src/Artemis.Core/Models/Surface/SurfaceDeviceConfiguration.cs create mode 100644 src/Artemis.Core/Ninject/LoggerProvider.cs create mode 100644 src/Artemis.Core/Services/Storage/SurfaceService.cs create mode 100644 src/Artemis.Storage/Entities/SurfaceDeviceEntity.cs create mode 100644 src/Artemis.Storage/Entities/SurfaceEntity.cs create mode 100644 src/Artemis.Storage/Entities/SurfacePositionEntity.cs delete mode 100644 src/Artemis.Storage/Repositories/IRepository.cs rename src/Artemis.Storage/Repositories/{ => Interfaces}/IPluginSettingRepository.cs (92%) create mode 100644 src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs create mode 100644 src/Artemis.Storage/Repositories/Interfaces/IRepository.cs rename src/Artemis.Storage/Repositories/{ => Interfaces}/ISettingRepository.cs (89%) create mode 100644 src/Artemis.Storage/Repositories/Interfaces/ISurfaceRepository.cs create mode 100644 src/Artemis.Storage/Repositories/SurfaceRepository.cs diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index ac35c3c37..e2fbcde73 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -55,11 +55,15 @@ ..\packages\AppDomainToolkit.1.0.4.3\lib\net\AppDomainToolkit.dll + + ..\packages\Ben.Demystifier.0.1.4\lib\net45\Ben.Demystifier.dll + ..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll + - ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll ..\packages\Ninject.3.3.4\lib\net45\Ninject.dll @@ -90,17 +94,44 @@ False ..\..\..\RGB.NET\bin\net45\RGB.NET.Groups.dll - - ..\packages\Stylet.1.1.22\lib\net45\Stylet.dll + + ..\packages\Serilog.2.8.0\lib\net46\Serilog.dll + + + ..\packages\Serilog.Enrichers.Demystify.1.0.0-dev-00019\lib\net45\Serilog.Enrichers.Demystify.dll + + + ..\packages\Serilog.Sinks.File.4.0.0\lib\net45\Serilog.Sinks.File.dll + + + ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll + + ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll + + + ..\packages\System.Collections.Immutable.1.6.0-preview8.19405.3\lib\netstandard2.0\System.Collections.Immutable.dll + ..\packages\System.Diagnostics.DiagnosticSource.4.5.1\lib\net46\System.Diagnostics.DiagnosticSource.dll + + ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll + + + ..\packages\System.Numerics.Vectors.4.6.0-preview5.19224.8\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Reflection.Metadata.1.7.0-preview8.19405.3\lib\netstandard2.0\System.Reflection.Metadata.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0-preview8.19405.3\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll @@ -118,6 +149,9 @@ + + + @@ -132,10 +166,10 @@ - - - - + + + + @@ -151,6 +185,7 @@ + @@ -162,5 +197,8 @@ Artemis.Storage + + + \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs new file mode 100644 index 000000000..8d2556d04 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using System.Drawing; +using Artemis.Core.Models.Profile.Interfaces; +using Artemis.Core.Services.Interfaces; +using Artemis.Storage.Entities; +using RGB.NET.Core; + +namespace Artemis.Core.Models.Profile +{ + public class Folder : IProfileElement + { + public Folder(Profile profile) + { + Profile = profile; + Children = new List(); + } + + public Profile Profile { get; } + public List Children { get; set; } + public int Order { get; set; } + public string Name { get; set; } + + public void Update(double deltaTime) + { + // Folders don't update but their children do + foreach (var profileElement in Children) + profileElement.Update(deltaTime); + } + + public void Render(double deltaTime, RGBSurface surface, Graphics graphics) + { + // Folders don't render but their children do + foreach (var profileElement in Children) + profileElement.Render(deltaTime, surface, graphics); + } + + public static Folder FromFolderEntity(Profile profile, FolderEntity folderEntity, IPluginService pluginService) + { + var folder = new Folder(profile) + { + Name = folderEntity.Name, + Order = folderEntity.Order + }; + + // Load child folders + foreach (var childFolder in folderEntity.Folders) + folder.Children.Add(FromFolderEntity(profile, childFolder, pluginService)); + // Load child layers + foreach (var childLayer in folderEntity.Layers) + folder.Children.Add(Layer.FromLayerEntity(profile, childLayer, pluginService)); + + return folder; + } + + public override string ToString() + { + return $"{nameof(Profile)}: {Profile}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}"; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Interfaces/IProfileElement.cs b/src/Artemis.Core/Models/Profile/Interfaces/IProfileElement.cs new file mode 100644 index 000000000..95423f681 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/Interfaces/IProfileElement.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Drawing; +using RGB.NET.Core; + +namespace Artemis.Core.Models.Profile.Interfaces +{ + public interface IProfileElement + { + /// + /// The element's children + /// + List Children { get; set; } + + /// + /// The order in which this element appears in the update loop and editor + /// + int Order { get; set; } + + /// + /// The name which appears in the editor + /// + string Name { get; set; } + + /// + /// Updates the element + /// + /// + void Update(double deltaTime); + + /// + /// Renders the element + /// + void Render(double deltaTime, RGBSurface surface, Graphics graphics); + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs new file mode 100644 index 000000000..bb3def768 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using Artemis.Core.Models.Profile.Interfaces; +using Artemis.Core.Plugins.Abstract; +using Artemis.Core.Plugins.Interfaces; +using Artemis.Core.Services.Interfaces; +using Artemis.Storage.Entities; +using RGB.NET.Core; + +namespace Artemis.Core.Models.Profile +{ + public class Layer : IProfileElement + { + public Layer(Profile profile) + { + Profile = profile; + Children = new List(); + } + + public Profile Profile { get; } + public LayerType LayerType { get; private set; } + public ILayerTypeConfiguration LayerTypeConfiguration { get; set; } + public List Children { get; set; } + public int Order { get; set; } + public string Name { get; set; } + + public void Update(double deltaTime) + { + if (LayerType == null) + return; + + lock (LayerType) + { + LayerType.Update(this); + } + } + + public void Render(double deltaTime, RGBSurface surface, Graphics graphics) + { + if (LayerType == null) + return; + + lock (LayerType) + { + LayerType.Render(this, surface, graphics); + } + } + + public static Layer FromLayerEntity(Profile profile, LayerEntity layerEntity, IPluginService pluginService) + { + var layer = new Layer(profile) + { + Name = layerEntity.Name, + Order = layerEntity.Order, + LayerType = pluginService.GetLayerTypeByGuid(Guid.Parse(layerEntity.Guid)) + }; + + return layer; + } + + public void UpdateLayerType(LayerType layerType) + { + if (LayerType != null) + { + lock (LayerType) + { + LayerType.Dispose(); + } + } + + LayerType = layerType; + } + + public override string ToString() + { + return $"{nameof(Profile)}: {Profile}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}"; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs new file mode 100644 index 000000000..228e44b40 --- /dev/null +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using Artemis.Core.Exceptions; +using Artemis.Core.Models.Profile.Interfaces; +using Artemis.Core.Plugins.Models; +using Artemis.Core.Services.Interfaces; +using Artemis.Storage.Entities; +using RGB.NET.Core; + +namespace Artemis.Core.Models.Profile +{ + public class Profile : IProfileElement + { + private Profile(PluginInfo pluginInfo) + { + PluginInfo = pluginInfo; + } + + public PluginInfo PluginInfo { get; } + public bool IsActivated { get; private set; } + public int Order { get; set; } + public string Name { get; set; } + public List Children { get; set; } + + public void Update(double deltaTime) + { + lock (this) + { + if (!IsActivated) + throw new ArtemisCoreException($"Cannot update inactive profile: {this}"); + + foreach (var profileElement in Children) + profileElement.Update(deltaTime); + } + } + + public void Render(double deltaTime, RGBSurface surface, Graphics graphics) + { + lock (this) + { + if (!IsActivated) + throw new ArtemisCoreException($"Cannot render inactive profile: {this}"); + + foreach (var profileElement in Children) + profileElement.Render(deltaTime, surface, graphics); + } + } + + public static Profile FromProfileEntity(PluginInfo pluginInfo, ProfileEntity profileEntity, IPluginService pluginService) + { + var profile = new Profile(pluginInfo) {Name = profileEntity.Name}; + lock (profile) + { + // Populate the profile starting at the root, the rest is populated recursively + profile.Children.Add(Folder.FromFolderEntity(profile, profileEntity.RootFolder, pluginService)); + + return profile; + } + } + + public void Activate() + { + lock (this) + { + if (IsActivated) return; + + OnActivated(); + IsActivated = true; + } + } + + public void Deactivate() + { + lock (this) + { + if (!IsActivated) return; + + IsActivated = false; + OnDeactivated(); + } + } + + public override string ToString() + { + return $"{nameof(Order)}: {Order}, {nameof(Name)}: {Name}, {nameof(PluginInfo)}: {PluginInfo}"; + } + + #region Events + + /// + /// Occurs when the profile is being activated. + /// + public event EventHandler Activated; + + /// + /// Occurs when the profile is being deactivated. + /// + public event EventHandler Deactivated; + + private void OnActivated() + { + Activated?.Invoke(this, EventArgs.Empty); + } + + private void OnDeactivated() + { + Deactivated?.Invoke(this, EventArgs.Empty); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Surface/SurfaceConfiguration.cs b/src/Artemis.Core/Models/Surface/SurfaceConfiguration.cs new file mode 100644 index 000000000..9d249552d --- /dev/null +++ b/src/Artemis.Core/Models/Surface/SurfaceConfiguration.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using Artemis.Storage.Entities; + +namespace Artemis.Core.Models.Surface +{ + public class SurfaceConfiguration + { + public SurfaceConfiguration(string name) + { + Name = name; + DeviceConfigurations = new List(); + } + + internal SurfaceConfiguration(SurfaceEntity surfaceEntity) + { + Guid = surfaceEntity.Guid; + Name = surfaceEntity.Name; + IsActive = surfaceEntity.IsActive; + DeviceConfigurations = new List(); + + if (surfaceEntity.SurfacePositions == null) + return; + foreach (var position in surfaceEntity.SurfacePositions) + DeviceConfigurations.Add(new SurfaceDeviceConfiguration(position, this)); + } + + internal string Guid { get; set; } + public string Name { get; set; } + public bool IsActive { get; set; } + public List DeviceConfigurations { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Models/Surface/SurfaceDeviceConfiguration.cs b/src/Artemis.Core/Models/Surface/SurfaceDeviceConfiguration.cs new file mode 100644 index 000000000..fca8fb704 --- /dev/null +++ b/src/Artemis.Core/Models/Surface/SurfaceDeviceConfiguration.cs @@ -0,0 +1,47 @@ +using Artemis.Storage.Entities; +using RGB.NET.Core; + +namespace Artemis.Core.Models.Surface +{ + public class SurfaceDeviceConfiguration + { + internal SurfaceDeviceConfiguration(int deviceId, IRGBDeviceInfo deviceInfo, SurfaceConfiguration surface) + { + DeviceId = deviceId; + DeviceName = deviceInfo.DeviceName; + DeviceModel = deviceInfo.Model; + DeviceManufacturer = deviceInfo.Manufacturer; + + Surface = surface; + } + + internal SurfaceDeviceConfiguration(SurfacePositionEntity position, SurfaceConfiguration surfaceConfiguration) + { + Guid = position.Guid; + + DeviceId = position.DeviceId; + DeviceName = position.DeviceName; + DeviceModel = position.DeviceModel; + DeviceManufacturer = position.DeviceManufacturer; + + X = position.X; + Y = position.Y; + Rotation = position.Rotation; + + Surface = surfaceConfiguration; + } + + internal string Guid { get; set; } + + public int DeviceId { get; set; } + public string DeviceName { get; set; } + public string DeviceModel { get; set; } + public string DeviceManufacturer { get; set; } + + public double X { get; set; } + public double Y { get; set; } + public double Rotation { get; set; } + + public SurfaceConfiguration Surface { get; internal set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Ninject/CoreModule.cs b/src/Artemis.Core/Ninject/CoreModule.cs index 458f01162..831450fc3 100644 --- a/src/Artemis.Core/Ninject/CoreModule.cs +++ b/src/Artemis.Core/Ninject/CoreModule.cs @@ -1,8 +1,10 @@ -using Artemis.Core.Plugins.Models; +using Artemis.Core.Exceptions; +using Artemis.Core.Plugins.Models; using Artemis.Core.Services.Interfaces; -using Artemis.Storage.Repositories; +using Artemis.Storage.Repositories.Interfaces; using Ninject.Extensions.Conventions; using Ninject.Modules; +using Serilog; namespace Artemis.Core.Ninject { @@ -10,6 +12,9 @@ namespace Artemis.Core.Ninject { public override void Load() { + if (Kernel == null) + throw new ArtemisCoreException("Failed to bind Ninject Core module, kernel is null."); + // Bind all services as singletons Kernel.Bind(x => { @@ -31,6 +36,7 @@ namespace Artemis.Core.Ninject }); Kernel.Bind().ToProvider(); + Kernel.Bind().ToProvider(); } } } \ No newline at end of file diff --git a/src/Artemis.Core/Ninject/LoggerProvider.cs b/src/Artemis.Core/Ninject/LoggerProvider.cs new file mode 100644 index 000000000..3019930cf --- /dev/null +++ b/src/Artemis.Core/Ninject/LoggerProvider.cs @@ -0,0 +1,25 @@ +using Ninject.Activation; +using Serilog; + +namespace Artemis.Core.Ninject +{ + internal class LoggerProvider : Provider + { + private static readonly ILogger _logger = new LoggerConfiguration() + .Enrich.FromLogContext() + .Enrich.WithDemystifiedStackTraces() + .WriteTo.File("Artemis log-.txt", + rollingInterval: RollingInterval.Day, + outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext:l}] {Message:lj}{NewLine}{Exception}") + .CreateLogger(); + + protected override ILogger CreateInstance(IContext context) + { + var requestingType = context.Request.ParentContext?.Plan?.Type; + if (requestingType != null) + return _logger.ForContext(requestingType); + return _logger; + + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Ninject/PluginSettingsProvider.cs b/src/Artemis.Core/Ninject/PluginSettingsProvider.cs index 7de90072a..43f3dc3d7 100644 --- a/src/Artemis.Core/Ninject/PluginSettingsProvider.cs +++ b/src/Artemis.Core/Ninject/PluginSettingsProvider.cs @@ -2,7 +2,7 @@ using Artemis.Core.Exceptions; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Models; -using Artemis.Storage.Repositories; +using Artemis.Storage.Repositories.Interfaces; using Ninject.Activation; namespace Artemis.Core.Ninject diff --git a/src/Artemis.Core/Plugins/Abstract/LayerType.cs b/src/Artemis.Core/Plugins/Abstract/LayerType.cs index b20e57d98..ac6717f70 100644 --- a/src/Artemis.Core/Plugins/Abstract/LayerType.cs +++ b/src/Artemis.Core/Plugins/Abstract/LayerType.cs @@ -1,6 +1,6 @@ using System.Drawing; +using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Models; -using Artemis.Core.ProfileElements; using RGB.NET.Core; namespace Artemis.Core.Plugins.Abstract diff --git a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs index 648fe98b8..a5561457b 100644 --- a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs +++ b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs @@ -1,7 +1,7 @@ using System; using System.Drawing; +using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Models; -using Artemis.Core.ProfileElements; using RGB.NET.Core; namespace Artemis.Core.Plugins.Abstract diff --git a/src/Artemis.Core/Plugins/Models/PluginSetting.cs b/src/Artemis.Core/Plugins/Models/PluginSetting.cs index ed27ce3c7..7d8af0994 100644 --- a/src/Artemis.Core/Plugins/Models/PluginSetting.cs +++ b/src/Artemis.Core/Plugins/Models/PluginSetting.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using Artemis.Storage.Entities; using Artemis.Storage.Repositories; +using Artemis.Storage.Repositories.Interfaces; using Newtonsoft.Json; namespace Artemis.Core.Plugins.Models diff --git a/src/Artemis.Core/Plugins/Models/PluginSettings.cs b/src/Artemis.Core/Plugins/Models/PluginSettings.cs index a5220849b..351da09b9 100644 --- a/src/Artemis.Core/Plugins/Models/PluginSettings.cs +++ b/src/Artemis.Core/Plugins/Models/PluginSettings.cs @@ -2,6 +2,7 @@ using System.Linq; using Artemis.Storage.Entities; using Artemis.Storage.Repositories; +using Artemis.Storage.Repositories.Interfaces; using Newtonsoft.Json; namespace Artemis.Core.Plugins.Models diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index 74cf6f9cc..0042f5200 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -4,6 +4,7 @@ using Artemis.Core.Exceptions; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Services.Interfaces; using RGB.NET.Core; +using Serilog; using Color = System.Drawing.Color; namespace Artemis.Core.Services @@ -13,11 +14,13 @@ namespace Artemis.Core.Services /// public class CoreService : ICoreService { + private readonly ILogger _logger; private readonly IPluginService _pluginService; private readonly IRgbService _rgbService; - internal CoreService(IPluginService pluginService, IRgbService rgbService) + internal CoreService(ILogger logger, IPluginService pluginService, IRgbService rgbService) { + _logger = logger; _pluginService = pluginService; _rgbService = rgbService; _rgbService.Surface.Updating += SurfaceOnUpdating; @@ -38,6 +41,8 @@ namespace Artemis.Core.Services if (IsInitialized) throw new ArtemisCoreException("Cannot initialize the core as it is already initialized."); + _logger.Information("Initializing Artemis Core version {version}", typeof(CoreService).Assembly.GetName().Version); + // Initialize the services await Task.Run(() => _pluginService.CopyBuiltInPlugins()); await Task.Run(() => _pluginService.LoadPlugins()); diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs index 3edbe0426..ebf0e2433 100644 --- a/src/Artemis.Core/Services/RgbService.cs +++ b/src/Artemis.Core/Services/RgbService.cs @@ -1,13 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Artemis.Core.Events; +using Artemis.Core.Models.Surface; using Artemis.Core.RGB.NET; using Artemis.Core.Services.Interfaces; +using Artemis.Core.Services.Storage; +using Artemis.Storage.Entities; using RGB.NET.Brushes; using RGB.NET.Core; using RGB.NET.Groups; +using Serilog; namespace Artemis.Core.Services { @@ -17,10 +20,14 @@ namespace Artemis.Core.Services public class RgbService : IRgbService, IDisposable { private readonly List _loadedDevices; + private readonly ILogger _logger; + private readonly ISurfaceService _surfaceService; private readonly TimerUpdateTrigger _updateTrigger; - internal RgbService() + internal RgbService(ILogger logger, ISurfaceService surfaceService) { + _logger = logger; + _surfaceService = surfaceService; Surface = RGBSurface.Instance; LoadingDevices = false; @@ -33,7 +40,7 @@ namespace Artemis.Core.Services } /// - public bool LoadingDevices { get; private set; } + public bool LoadingDevices { get; } /// public RGBSurface Surface { get; set; } @@ -43,9 +50,17 @@ namespace Artemis.Core.Services public void AddDeviceProvider(IRGBDeviceProvider deviceProvider) { Surface.LoadDevices(deviceProvider); - + if (deviceProvider.Devices == null) + { + _logger.Warning("Device provider {deviceProvider} has no devices", deviceProvider.GetType().Name); return; + } + + // Get the currently active surface configuration + var surface = _surfaceService.GetActiveSurfaceConfiguration(); + if (surface == null) + _logger.Information("No active surface configuration found, not positioning device"); lock (_loadedDevices) { @@ -54,10 +69,16 @@ namespace Artemis.Core.Services if (!_loadedDevices.Contains(surfaceDevice)) { _loadedDevices.Add(surfaceDevice); + if (surface != null) + ApplyDeviceConfiguration(surfaceDevice, surface); OnDeviceLoaded(new DeviceEventArgs(surfaceDevice)); } else + { + if (surface != null) + ApplyDeviceConfiguration(surfaceDevice, surface); OnDeviceReloaded(new DeviceEventArgs(surfaceDevice)); + } } } @@ -75,6 +96,31 @@ namespace Artemis.Core.Services Surface.Dispose(); } + public void ApplyDeviceConfiguration(IRGBDevice rgbDevice, SurfaceConfiguration surface) + { + // Determine the device ID by assuming devices are always added to the loaded devices list in the same order + lock (_loadedDevices) + { + var deviceId = _loadedDevices.Where(d => d.DeviceInfo.DeviceName == rgbDevice.DeviceInfo.DeviceName && + d.DeviceInfo.Model == rgbDevice.DeviceInfo.Model && + d.DeviceInfo.Manufacturer == rgbDevice.DeviceInfo.Manufacturer) + .ToList() + .IndexOf(rgbDevice) + 1; + + var deviceConfig = surface.DeviceConfigurations.FirstOrDefault(d => d.DeviceName == rgbDevice.DeviceInfo.DeviceName && + d.DeviceModel == rgbDevice.DeviceInfo.Model && + d.DeviceManufacturer == rgbDevice.DeviceInfo.Manufacturer && + d.DeviceId == deviceId); + if (deviceConfig == null) + { + _logger.Information("No surface device config found for {deviceInfo}, device ID: {deviceId}", rgbDevice.DeviceInfo, deviceId); + return; + } + + rgbDevice.Location = new Point(deviceConfig.X, deviceConfig.Y); + } + } + private void SurfaceOnException(ExceptionEventArgs args) { throw args.Exception; diff --git a/src/Artemis.Core/Services/Storage/SurfaceService.cs b/src/Artemis.Core/Services/Storage/SurfaceService.cs new file mode 100644 index 000000000..a93d26a29 --- /dev/null +++ b/src/Artemis.Core/Services/Storage/SurfaceService.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Artemis.Core.Models.Surface; +using Artemis.Core.Services.Interfaces; +using Artemis.Storage.Repositories.Interfaces; + +namespace Artemis.Core.Services.Storage +{ + public class SurfaceService : ISurfaceService + { + private readonly ISurfaceRepository _surfaceRepository; + + public SurfaceService(ISurfaceRepository surfaceRepository) + { + _surfaceRepository = surfaceRepository; + } + + public async Task> GetSurfaceConfigurations() + { + var surfaceEntities = await _surfaceRepository.GetAllAsync(); + var configs = new List(); + foreach (var surfaceEntity in surfaceEntities) + configs.Add(new SurfaceConfiguration(surfaceEntity)); + + return configs; + } + + public SurfaceConfiguration GetActiveSurfaceConfiguration() + { + var entity = _surfaceRepository.GetAll().FirstOrDefault(d => d.IsActive); + return entity != null ? new SurfaceConfiguration(entity) : null; + } + } + + public interface ISurfaceService : IArtemisService + { + Task> GetSurfaceConfigurations(); + SurfaceConfiguration GetActiveSurfaceConfiguration(); + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Services/StorageService.cs b/src/Artemis.Core/Services/StorageService.cs index 2a7293270..fcb4891a2 100644 --- a/src/Artemis.Core/Services/StorageService.cs +++ b/src/Artemis.Core/Services/StorageService.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Models; -using Artemis.Core.ProfileElements; using Artemis.Core.Services.Interfaces; using Artemis.Storage.Repositories; diff --git a/src/Artemis.Core/app.config b/src/Artemis.Core/app.config index 52d8e8241..87be05efa 100644 --- a/src/Artemis.Core/app.config +++ b/src/Artemis.Core/app.config @@ -12,7 +12,7 @@ - + @@ -56,7 +56,7 @@ - + @@ -84,7 +84,7 @@ - + @@ -96,7 +96,7 @@ - + diff --git a/src/Artemis.Core/packages.config b/src/Artemis.Core/packages.config index a033fbcaa..cdc45c62b 100644 --- a/src/Artemis.Core/packages.config +++ b/src/Artemis.Core/packages.config @@ -2,12 +2,14 @@ - + - + + + \ No newline at end of file diff --git a/src/Artemis.Plugins.Devices.Corsair/app.config b/src/Artemis.Plugins.Devices.Corsair/app.config index ee2d2a7c2..eee083bd7 100644 --- a/src/Artemis.Plugins.Devices.Corsair/app.config +++ b/src/Artemis.Plugins.Devices.Corsair/app.config @@ -10,6 +10,26 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerTypes.Brush.csproj b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerTypes.Brush.csproj index 2c58a3f9f..b2da4aa8a 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerTypes.Brush.csproj +++ b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerTypes.Brush.csproj @@ -42,9 +42,8 @@ False ..\..\..\RGB.NET\bin\net45\RGB.NET.Core.dll - - ..\packages\Stylet.1.1.22\lib\net45\Stylet.dll - False + + ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerType.cs b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerType.cs index 49687d99a..ff3707bae 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerType.cs +++ b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerType.cs @@ -1,7 +1,7 @@ using System.Drawing; +using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Models; -using Artemis.Core.ProfileElements; using QRCoder; using RGB.NET.Core; diff --git a/src/Artemis.Plugins.LayerTypes.Brush/app.config b/src/Artemis.Plugins.LayerTypes.Brush/app.config index d05a8de20..718870ef0 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/app.config +++ b/src/Artemis.Plugins.LayerTypes.Brush/app.config @@ -10,6 +10,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/Artemis.Plugins.LayerTypes.Brush/packages.config b/src/Artemis.Plugins.LayerTypes.Brush/packages.config index c8a756cdc..255a27498 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/packages.config +++ b/src/Artemis.Plugins.LayerTypes.Brush/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj index 1e9ca81a7..bef9f7b45 100644 --- a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj +++ b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj @@ -42,9 +42,8 @@ False ..\..\..\RGB.NET\bin\net45\RGB.NET.Core.dll - - ..\packages\Stylet.1.1.17\lib\net45\Stylet.dll - False + + ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll diff --git a/src/Artemis.Plugins.Modules.General/app.config b/src/Artemis.Plugins.Modules.General/app.config index d05a8de20..718870ef0 100644 --- a/src/Artemis.Plugins.Modules.General/app.config +++ b/src/Artemis.Plugins.Modules.General/app.config @@ -10,6 +10,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/Artemis.Plugins.Modules.General/packages.config b/src/Artemis.Plugins.Modules.General/packages.config index 17b3103fd..cddaad4d2 100644 --- a/src/Artemis.Plugins.Modules.General/packages.config +++ b/src/Artemis.Plugins.Modules.General/packages.config @@ -1,7 +1,7 @@  - + \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/LedEntity.cs b/src/Artemis.Storage/Entities/LedEntity.cs index 1060c1c0a..69886bb32 100644 --- a/src/Artemis.Storage/Entities/LedEntity.cs +++ b/src/Artemis.Storage/Entities/LedEntity.cs @@ -12,7 +12,7 @@ namespace Artemis.Storage.Entities public string LedName { get; set; } public string LimitedToDevice { get; set; } - public int LayerId { get; set; } + public string LayerId { get; set; } public virtual LayerEntity Layer { get; set; } } } \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/SurfaceDeviceEntity.cs b/src/Artemis.Storage/Entities/SurfaceDeviceEntity.cs new file mode 100644 index 000000000..30fcc71c8 --- /dev/null +++ b/src/Artemis.Storage/Entities/SurfaceDeviceEntity.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace Artemis.Storage.Entities +{ + public class SurfaceDeviceEntity + { + [Key] + public string Guid { get; set; } + + public int DeviceId { get; set; } + public string DeviceName { get; set; } + public string DeviceModel { get; set; } + public string DeviceManufacturer { get; set; } + + public double X { get; set; } + public double Y { get; set; } + public double Rotation { get; set; } + + public string SurfaceId { get; set; } + public virtual SurfaceEntity Surface { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/SurfaceEntity.cs b/src/Artemis.Storage/Entities/SurfaceEntity.cs new file mode 100644 index 000000000..1f5ee520d --- /dev/null +++ b/src/Artemis.Storage/Entities/SurfaceEntity.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Artemis.Storage.Entities +{ + public class SurfaceEntity + { + [Key] + public string Guid { get; set; } + + public string Name { get; set; } + public bool IsActive { get; set; } + + public virtual ICollection SurfacePositions { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/SurfacePositionEntity.cs b/src/Artemis.Storage/Entities/SurfacePositionEntity.cs new file mode 100644 index 000000000..7f2bfcbc9 --- /dev/null +++ b/src/Artemis.Storage/Entities/SurfacePositionEntity.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace Artemis.Storage.Entities +{ + public class SurfacePositionEntity + { + [Key] + public string Guid { get; set; } + + public int DeviceId { get; set; } + public string DeviceName { get; set; } + public string DeviceModel { get; set; } + public string DeviceManufacturer { get; set; } + + public double X { get; set; } + public double Y { get; set; } + public double Rotation { get; set; } + + public string SurfaceId { get; set; } + public virtual SurfaceEntity Surface { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/IRepository.cs b/src/Artemis.Storage/Repositories/IRepository.cs deleted file mode 100644 index cd79f9641..000000000 --- a/src/Artemis.Storage/Repositories/IRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Artemis.Storage.Repositories -{ - public interface IRepository - { - } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/IPluginSettingRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IPluginSettingRepository.cs similarity index 92% rename from src/Artemis.Storage/Repositories/IPluginSettingRepository.cs rename to src/Artemis.Storage/Repositories/Interfaces/IPluginSettingRepository.cs index 16a7d11d1..6b522abd5 100644 --- a/src/Artemis.Storage/Repositories/IPluginSettingRepository.cs +++ b/src/Artemis.Storage/Repositories/Interfaces/IPluginSettingRepository.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Artemis.Storage.Entities; -namespace Artemis.Storage.Repositories +namespace Artemis.Storage.Repositories.Interfaces { public interface IPluginSettingRepository : IRepository { diff --git a/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs new file mode 100644 index 000000000..f56215db2 --- /dev/null +++ b/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Artemis.Storage.Entities; + +namespace Artemis.Storage.Repositories.Interfaces +{ + public interface IProfileRepository : IRepository + { + IQueryable GetAll(); + Task> GetByPluginGuidAsync(Guid pluginGuid); + Task GetByGuidAsync(string guid); + void Save(); + Task SaveAsync(); + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/Interfaces/IRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IRepository.cs new file mode 100644 index 000000000..f18958117 --- /dev/null +++ b/src/Artemis.Storage/Repositories/Interfaces/IRepository.cs @@ -0,0 +1,6 @@ +namespace Artemis.Storage.Repositories.Interfaces +{ + public interface IRepository + { + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/ISettingRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/ISettingRepository.cs similarity index 89% rename from src/Artemis.Storage/Repositories/ISettingRepository.cs rename to src/Artemis.Storage/Repositories/Interfaces/ISettingRepository.cs index e0b5550cd..f3240c0eb 100644 --- a/src/Artemis.Storage/Repositories/ISettingRepository.cs +++ b/src/Artemis.Storage/Repositories/Interfaces/ISettingRepository.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using Artemis.Storage.Entities; -namespace Artemis.Storage.Repositories +namespace Artemis.Storage.Repositories.Interfaces { public interface ISettingRepository : IRepository { diff --git a/src/Artemis.Storage/Repositories/Interfaces/ISurfaceRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/ISurfaceRepository.cs new file mode 100644 index 000000000..47be22342 --- /dev/null +++ b/src/Artemis.Storage/Repositories/Interfaces/ISurfaceRepository.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Artemis.Storage.Entities; + +namespace Artemis.Storage.Repositories.Interfaces +{ + public interface ISurfaceRepository : IRepository + { + void Add(SurfaceEntity surfaceEntity); + SurfaceEntity Get(string name); + Task GetAsync(string name); + List GetAll(); + Task> GetAllAsync(); + + void Save(); + Task SaveAsync(); + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/PluginSettingRepository.cs b/src/Artemis.Storage/Repositories/PluginSettingRepository.cs index a62aaaa90..d6663a003 100644 --- a/src/Artemis.Storage/Repositories/PluginSettingRepository.cs +++ b/src/Artemis.Storage/Repositories/PluginSettingRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Artemis.Storage.Entities; +using Artemis.Storage.Repositories.Interfaces; using Microsoft.EntityFrameworkCore; namespace Artemis.Storage.Repositories diff --git a/src/Artemis.Storage/Repositories/ProfileRepository.cs b/src/Artemis.Storage/Repositories/ProfileRepository.cs index cb1c826a9..c4b0d544a 100644 --- a/src/Artemis.Storage/Repositories/ProfileRepository.cs +++ b/src/Artemis.Storage/Repositories/ProfileRepository.cs @@ -3,11 +3,12 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Artemis.Storage.Entities; +using Artemis.Storage.Repositories.Interfaces; using Microsoft.EntityFrameworkCore; namespace Artemis.Storage.Repositories { - public class ProfileRepository + public class ProfileRepository : IProfileRepository { private readonly StorageContext _dbContext; @@ -32,6 +33,11 @@ namespace Artemis.Storage.Repositories return await _dbContext.Profiles.FirstOrDefaultAsync(p => p.Guid == guid); } + public void Save() + { + _dbContext.SaveChanges(); + } + public async Task SaveAsync() { await _dbContext.SaveChangesAsync(); diff --git a/src/Artemis.Storage/Repositories/SettingRepository.cs b/src/Artemis.Storage/Repositories/SettingRepository.cs index fafe9308c..ea05b1e37 100644 --- a/src/Artemis.Storage/Repositories/SettingRepository.cs +++ b/src/Artemis.Storage/Repositories/SettingRepository.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Artemis.Storage.Entities; +using Artemis.Storage.Repositories.Interfaces; using Microsoft.EntityFrameworkCore; namespace Artemis.Storage.Repositories diff --git a/src/Artemis.Storage/Repositories/SurfaceRepository.cs b/src/Artemis.Storage/Repositories/SurfaceRepository.cs new file mode 100644 index 000000000..69ef4d6c7 --- /dev/null +++ b/src/Artemis.Storage/Repositories/SurfaceRepository.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Artemis.Storage.Entities; +using Artemis.Storage.Repositories.Interfaces; +using Microsoft.EntityFrameworkCore; + +namespace Artemis.Storage.Repositories +{ + public class SurfaceRepository : ISurfaceRepository + { + private readonly StorageContext _dbContext; + + internal SurfaceRepository() + { + _dbContext = new StorageContext(); + _dbContext.Database.EnsureCreated(); + } + + public void Add(SurfaceEntity surfaceEntity) + { + _dbContext.Surfaces.Add(surfaceEntity); + } + + public SurfaceEntity Get(string name) + { + return _dbContext.Surfaces.Include(s => s.SurfacePositions).FirstOrDefault(p => p.Name == name); + } + + public async Task GetAsync(string name) + { + return await _dbContext.Surfaces.Include(s => s.SurfacePositions).FirstOrDefaultAsync(p => p.Name == name); + } + + public List GetAll() + { + return _dbContext.Surfaces.Include(s => s.SurfacePositions).ToList(); + } + + public async Task> GetAllAsync() + { + return await _dbContext.Surfaces.Include(s => s.SurfacePositions).ToListAsync(); + } + + public void Save() + { + _dbContext.SaveChanges(); + } + + public async Task SaveAsync() + { + await _dbContext.SaveChangesAsync(); + } + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/StorageContext.cs b/src/Artemis.Storage/StorageContext.cs index d2b0ed115..758a15ece 100644 --- a/src/Artemis.Storage/StorageContext.cs +++ b/src/Artemis.Storage/StorageContext.cs @@ -10,6 +10,7 @@ namespace Artemis.Storage { public DbSet Profiles { get; set; } public DbSet Settings { get; set; } + public DbSet Surfaces { get; set; } public DbSet PluginSettings { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) diff --git a/src/Artemis.UI/App.config b/src/Artemis.UI/App.config index 3e8cfd535..4f6c695cc 100644 --- a/src/Artemis.UI/App.config +++ b/src/Artemis.UI/App.config @@ -11,7 +11,7 @@ - + @@ -59,7 +59,7 @@ - + @@ -87,7 +87,7 @@ - + @@ -99,7 +99,7 @@ - + diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index f4e825062..3daec2b82 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -119,8 +119,8 @@ ..\packages\SQLitePCLRaw.provider.e_sqlite3.net45.1.1.12\lib\net45\SQLitePCLRaw.provider.e_sqlite3.dll - - ..\packages\Stylet.1.1.22\lib\net45\Stylet.dll + + ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll diff --git a/src/Artemis.UI/ViewModels/Screens/SurfaceEditorViewModel.cs b/src/Artemis.UI/ViewModels/Screens/SurfaceEditorViewModel.cs index 55b41984f..2dcdadd7d 100644 --- a/src/Artemis.UI/ViewModels/Screens/SurfaceEditorViewModel.cs +++ b/src/Artemis.UI/ViewModels/Screens/SurfaceEditorViewModel.cs @@ -1,10 +1,13 @@ using System.Collections.ObjectModel; using System.Linq; +using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Media; using Artemis.Core.Events; +using Artemis.Core.Models.Surface; using Artemis.Core.Services.Interfaces; +using Artemis.Core.Services.Storage; using Artemis.UI.ViewModels.Controls.RgbDevice; using Artemis.UI.ViewModels.Interfaces; using RGB.NET.Core; @@ -16,21 +19,23 @@ namespace Artemis.UI.ViewModels.Screens public class SurfaceEditorViewModel : Screen, ISurfaceEditorViewModel { private readonly IRgbService _rgbService; + private readonly ISurfaceService _surfaceService; - - public SurfaceEditorViewModel(IRgbService rgbService) + public SurfaceEditorViewModel(IRgbService rgbService, ISurfaceService surfaceService) { Devices = new ObservableCollection(); + SurfaceConfigurations = new ObservableCollection(); SelectionRectangle = new RectangleGeometry(); _rgbService = rgbService; + _surfaceService = surfaceService; _rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded; _rgbService.Surface.Updated += SurfaceOnUpdated; foreach (var surfaceDevice in _rgbService.Surface.Devices) { var device = new RgbDeviceViewModel(surfaceDevice) {Cursor = Cursors.Hand}; -// device.SetColorsEnabled(false); + device.SetColorsEnabled(false); Devices.Add(device); } @@ -39,6 +44,10 @@ namespace Artemis.UI.ViewModels.Screens public RectangleGeometry SelectionRectangle { get; set; } public ObservableCollection Devices { get; set; } + public SurfaceConfiguration SelectedSurfaceConfiguration { get; set; } + public ObservableCollection SurfaceConfigurations { get; set; } + public string NewConfigurationName { get; set; } + public string Title => "Surface Editor"; private void RgbServiceOnDeviceLoaded(object sender, DeviceEventArgs e) @@ -48,7 +57,7 @@ namespace Artemis.UI.ViewModels.Screens if (Devices.All(d => d.Device != e.Device)) { var device = new RgbDeviceViewModel(e.Device) {Cursor = Cursors.Hand}; -// device.SetColorsEnabled(false); + device.SetColorsEnabled(false); Devices.Add(device); } }); @@ -60,6 +69,51 @@ namespace Artemis.UI.ViewModels.Screens rgbDeviceViewModel.Update(); } + #region Overrides of Screen + + protected override void OnActivate() + { + Task.Run(LoadSurfaceConfigurations); + base.OnActivate(); + } + + #endregion + + private async Task LoadSurfaceConfigurations() + { + SurfaceConfigurations.Clear(); + + // Get surface configs + var configs = await _surfaceService.GetSurfaceConfigurations(); + // Populate the UI collection + foreach (var surfaceConfiguration in configs) + SurfaceConfigurations.Add(surfaceConfiguration); + // Select either the first active surface or the first available surface + SelectedSurfaceConfiguration = SurfaceConfigurations.FirstOrDefault(s => s.IsActive) ?? SurfaceConfigurations.FirstOrDefault(); + + // Create a default if there is none + if (SelectedSurfaceConfiguration == null) + SelectedSurfaceConfiguration = AddSurfaceConfiguration("Default"); + } + + + public SurfaceConfiguration AddSurfaceConfiguration(string name) + { + var config = new SurfaceConfiguration(name); + Execute.OnUIThread(() => SurfaceConfigurations.Add(config)); + return config; + } + + public void ConfigurationDialogClosing() + { + if (!string.IsNullOrWhiteSpace(NewConfigurationName)) + { + var newConfig = AddSurfaceConfiguration(NewConfigurationName); + SelectedSurfaceConfiguration = newConfig; + } + NewConfigurationName = null; + } + #region Mouse actions private MouseDragStatus _mouseDragStatus; @@ -79,6 +133,7 @@ namespace Artemis.UI.ViewModels.Screens others.SelectionStatus = SelectionStatus.None; device.SelectionStatus = SelectionStatus.Selected; } + foreach (var selectedDevice in Devices.Where(d => d.SelectionStatus == SelectionStatus.Selected)) selectedDevice.StartMouseDrag(position); } diff --git a/src/Artemis.UI/Views/Screens/SurfaceEditorView.xaml b/src/Artemis.UI/Views/Screens/SurfaceEditorView.xaml index 11dd5da70..2fa308297 100644 --- a/src/Artemis.UI/Views/Screens/SurfaceEditorView.xaml +++ b/src/Artemis.UI/Views/Screens/SurfaceEditorView.xaml @@ -5,74 +5,175 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:screens="clr-namespace:Artemis.UI.ViewModels.Screens" xmlns:s="https://github.com/canton7/Stylet" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:models="clr-namespace:Artemis.Core.Models.Surface;assembly=Artemis.Core" mc:Ignorable="d" d:DataContext="{d:DesignInstance screens:SurfaceEditorViewModel}" d:DesignHeight="600" d:DesignWidth="600"> - + + + + + + + - The surface is a digital representation of your LED setup. Set this up accurately and effects will seamlessly move from one device to the other. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Surface layout + The surface is a digital representation of your LED setup. Set this up accurately and effects will seamlessly move from one device to the other. - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Add a new surface layout. + + + + + + + + + + + + + Add a new surface layout. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/packages.config b/src/Artemis.UI/packages.config index 585a0fd43..fc891e360 100644 --- a/src/Artemis.UI/packages.config +++ b/src/Artemis.UI/packages.config @@ -20,6 +20,6 @@ - + \ No newline at end of file