From 05eed5ba00e96a28e040e996c9dcd566a6918d89 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Sun, 3 Nov 2019 11:38:28 +0100 Subject: [PATCH] Made devices aware of the plugin that loaded them Fixed Corsair LL Fans layout Expanded render events Added identify option to device settings, must move this to be reusable though --- src/Artemis.Core/Artemis.Core.csproj | 3 +- .../Events/FrameRenderedEventArgs.cs | 18 ++++ ...ventArgs.cs => FrameRenderingEventArgs.cs} | 4 +- src/Artemis.Core/Models/Surface/Device.cs | 18 +++- src/Artemis.Core/Models/Surface/Surface.cs | 10 -- src/Artemis.Core/Plugins/Abstract/Device.cs | 9 +- src/Artemis.Core/Plugins/Abstract/Plugin.cs | 2 +- src/Artemis.Core/Services/CoreService.cs | 19 +++- .../Services/Interfaces/ICoreService.cs | 9 +- .../Services/Interfaces/IPluginService.cs | 3 + src/Artemis.Core/Services/PluginService.cs | 8 +- .../Services/Storage/SurfaceService.cs | 37 +++++--- .../CorsairDevice.cs | 4 +- .../Layouts/Corsair/Customs/LLFAN.xml | 95 ++++++++++--------- .../GeneralModule.cs | 49 +++++++++- src/Artemis.UI/Artemis.UI.csproj | 4 +- .../Settings/DeviceSettingsViewModel.cs | 76 +++++++++++++++ .../Settings/RgbDeviceSettingsViewModel.cs | 25 ----- .../ViewModels/Screens/DebugViewModel.cs | 12 ++- .../ViewModels/Screens/SettingsViewModel.cs | 37 +++++--- .../Controls/Settings/DeviceSettingsView.xaml | 60 ++++++++++++ .../Settings/RgbDeviceSettingsView.xaml | 94 ------------------ .../Views/Screens/SettingsView.xaml | 33 ++++++- 23 files changed, 400 insertions(+), 229 deletions(-) create mode 100644 src/Artemis.Core/Events/FrameRenderedEventArgs.cs rename src/Artemis.Core/Events/{FrameEventArgs.cs => FrameRenderingEventArgs.cs} (74%) create mode 100644 src/Artemis.UI/ViewModels/Controls/Settings/DeviceSettingsViewModel.cs delete mode 100644 src/Artemis.UI/ViewModels/Controls/Settings/RgbDeviceSettingsViewModel.cs create mode 100644 src/Artemis.UI/Views/Controls/Settings/DeviceSettingsView.xaml delete mode 100644 src/Artemis.UI/Views/Controls/Settings/RgbDeviceSettingsView.xaml diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 251ed3094..b77c9e7fd 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -144,7 +144,8 @@ - + + diff --git a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs new file mode 100644 index 000000000..144482c9c --- /dev/null +++ b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs @@ -0,0 +1,18 @@ +using System; +using System.Drawing; +using RGB.NET.Core; + +namespace Artemis.Core.Events +{ + public class FrameRenderedEventArgs : EventArgs + { + public FrameRenderedEventArgs(Bitmap bitmap, RGBSurface rgbSurface) + { + Bitmap = bitmap; + RgbSurface = rgbSurface; + } + + public Bitmap Bitmap { get; } + public RGBSurface RgbSurface { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Events/FrameEventArgs.cs b/src/Artemis.Core/Events/FrameRenderingEventArgs.cs similarity index 74% rename from src/Artemis.Core/Events/FrameEventArgs.cs rename to src/Artemis.Core/Events/FrameRenderingEventArgs.cs index b21cd9e91..70ed191ac 100644 --- a/src/Artemis.Core/Events/FrameEventArgs.cs +++ b/src/Artemis.Core/Events/FrameRenderingEventArgs.cs @@ -6,9 +6,9 @@ using RGB.NET.Core; namespace Artemis.Core.Events { - public class FrameEventArgs : EventArgs + public class FrameRenderingEventArgs : EventArgs { - public FrameEventArgs(List modules, Bitmap bitmap, double deltaTime, RGBSurface rgbSurface) + public FrameRenderingEventArgs(List modules, Bitmap bitmap, double deltaTime, RGBSurface rgbSurface) { Modules = modules; Bitmap = bitmap; diff --git a/src/Artemis.Core/Models/Surface/Device.cs b/src/Artemis.Core/Models/Surface/Device.cs index 161bea746..4ca88f17b 100644 --- a/src/Artemis.Core/Models/Surface/Device.cs +++ b/src/Artemis.Core/Models/Surface/Device.cs @@ -1,18 +1,23 @@ using System; using System.Collections.ObjectModel; +using System.Drawing; +using System.Drawing.Drawing2D; using System.Linq; using Artemis.Core.Extensions; +using Artemis.Core.Plugins.Abstract; using Artemis.Storage.Entities; using RGB.NET.Core; +using Point = RGB.NET.Core.Point; using Rectangle = System.Drawing.Rectangle; namespace Artemis.Core.Models.Surface { public class Device { - internal Device(IRGBDevice rgbDevice, Surface surface) + internal Device(IRGBDevice rgbDevice, Plugin plugin, Surface surface) { RgbDevice = rgbDevice; + Plugin = plugin; Surface = surface; Configuration = new DeviceEntity(); Leds = rgbDevice.Select(l => new DeviceLed(l, this)).ToList().AsReadOnly(); @@ -24,9 +29,10 @@ namespace Artemis.Core.Models.Surface CalculateRenderRectangle(); } - internal Device(IRGBDevice rgbDevice, Surface surface, DeviceEntity configuration) + internal Device(IRGBDevice rgbDevice, Plugin plugin, Surface surface, DeviceEntity configuration) { RgbDevice = rgbDevice; + Plugin = plugin; Surface = surface; Configuration = configuration; Leds = rgbDevice.Select(l => new DeviceLed(l, this)).ToList().AsReadOnly(); @@ -36,8 +42,10 @@ namespace Artemis.Core.Models.Surface } public Rectangle RenderRectangle { get; private set; } + public GraphicsPath RenderPath { get; private set; } public IRGBDevice RgbDevice { get; private set; } + public Plugin Plugin { get; } public Surface Surface { get; private set; } public DeviceEntity Configuration { get; private set; } public ReadOnlyCollection Leds { get; set; } @@ -93,8 +101,12 @@ namespace Artemis.Core.Models.Surface foreach (var led in Leds) led.CalculateRenderRectangle(); - } + var path = new GraphicsPath(); + path.AddRectangles(Leds.Select(l => l.AbsoluteRenderRectangle).ToArray()); + RenderPath = path; + } + internal void Destroy() { Configuration = null; diff --git a/src/Artemis.Core/Models/Surface/Surface.cs b/src/Artemis.Core/Models/Surface/Surface.cs index 05fec03e7..be8d9a37c 100644 --- a/src/Artemis.Core/Models/Surface/Surface.cs +++ b/src/Artemis.Core/Models/Surface/Surface.cs @@ -33,16 +33,6 @@ namespace Artemis.Core.Models.Surface Name = surfaceEntity.Name; IsActive = surfaceEntity.IsActive; Devices = new List(); - - if (surfaceEntity.DeviceEntities == null) - return; - - foreach (var position in surfaceEntity.DeviceEntities) - { - var device = rgbSurface.Devices.FirstOrDefault(d => d.GetDeviceHashCode() == position.DeviceHashCode); - if (device != null) - Devices.Add(new Device(device, this, position)); - } } public RGBSurface RgbSurface { get; } diff --git a/src/Artemis.Core/Plugins/Abstract/Device.cs b/src/Artemis.Core/Plugins/Abstract/Device.cs index a945b9cab..e48bda8b7 100644 --- a/src/Artemis.Core/Plugins/Abstract/Device.cs +++ b/src/Artemis.Core/Plugins/Abstract/Device.cs @@ -1,4 +1,6 @@ -using Artemis.Core.Plugins.Models; +using System; +using Artemis.Core.Plugins.Models; +using RGB.NET.Core; namespace Artemis.Core.Plugins.Abstract { @@ -8,8 +10,11 @@ namespace Artemis.Core.Plugins.Abstract /// public abstract class Device : Plugin { - protected Device(PluginInfo pluginInfo) : base(pluginInfo) + public IRGBDeviceProvider DeviceProvider { get; } + + protected Device(PluginInfo pluginInfo, IRGBDeviceProvider deviceProvider) : base(pluginInfo) { + DeviceProvider = deviceProvider ?? throw new ArgumentNullException(nameof(deviceProvider)); } } } \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/Abstract/Plugin.cs b/src/Artemis.Core/Plugins/Abstract/Plugin.cs index 410f98617..1f1146c96 100644 --- a/src/Artemis.Core/Plugins/Abstract/Plugin.cs +++ b/src/Artemis.Core/Plugins/Abstract/Plugin.cs @@ -12,7 +12,7 @@ namespace Artemis.Core.Plugins.Abstract { internal Plugin(PluginInfo pluginInfo) { - PluginInfo = pluginInfo; + PluginInfo = pluginInfo ?? throw new ArgumentNullException(nameof(pluginInfo)); } public PluginInfo PluginInfo { get; internal set; } diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index 37e8b13bb..ca61bdc34 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -29,7 +29,7 @@ namespace Artemis.Core.Services _rgbService = rgbService; _surfaceService = surfaceService; _rgbService.Surface.Updating += SurfaceOnUpdating; - + _rgbService.Surface.Updated += SurfaceOnUpdated; Task.Run(Initialize); } @@ -87,7 +87,7 @@ namespace Artemis.Core.Services module.Render(args.DeltaTime, _surfaceService.ActiveSurface, g); } - OnFrameRendered(new FrameEventArgs(modules, _rgbService.GraphicsDecorator.GetBitmap(), args.DeltaTime, _rgbService.Surface)); + OnFrameRendering(new FrameRenderingEventArgs(modules, _rgbService.GraphicsDecorator.GetBitmap(), args.DeltaTime, _rgbService.Surface)); } catch (Exception e) { @@ -95,10 +95,16 @@ namespace Artemis.Core.Services } } + private void SurfaceOnUpdated(UpdatedEventArgs args) + { + OnFrameRendered(new FrameRenderedEventArgs(_rgbService.GraphicsDecorator.GetBitmap(), _rgbService.Surface)); + } + #region Events public event EventHandler Initialized; - public event EventHandler FrameRendered; + public event EventHandler FrameRendering; + public event EventHandler FrameRendered; private void OnInitialized() { @@ -108,7 +114,12 @@ namespace Artemis.Core.Services #endregion - protected virtual void OnFrameRendered(FrameEventArgs e) + protected virtual void OnFrameRendering(FrameRenderingEventArgs e) + { + FrameRendering?.Invoke(this, e); + } + + protected virtual void OnFrameRendered(FrameRenderedEventArgs e) { FrameRendered?.Invoke(this, e); } diff --git a/src/Artemis.Core/Services/Interfaces/ICoreService.cs b/src/Artemis.Core/Services/Interfaces/ICoreService.cs index c82b1eb6c..2aced5183 100644 --- a/src/Artemis.Core/Services/Interfaces/ICoreService.cs +++ b/src/Artemis.Core/Services/Interfaces/ICoreService.cs @@ -16,8 +16,13 @@ namespace Artemis.Core.Services.Interfaces event EventHandler Initialized; /// - /// Occurs whenever a frame has finished rendering + /// Occurs whenever a frame is rendering, after modules have rendered /// - event EventHandler FrameRendered; + event EventHandler FrameRendering; + + /// + /// Occurs whenever a frame is finished rendering and processed by RGB.NET + /// + event EventHandler FrameRendered; } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/Interfaces/IPluginService.cs b/src/Artemis.Core/Services/Interfaces/IPluginService.cs index 50b904711..af6b27c5e 100644 --- a/src/Artemis.Core/Services/Interfaces/IPluginService.cs +++ b/src/Artemis.Core/Services/Interfaces/IPluginService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Artemis.Core.Events; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Models; +using RGB.NET.Core; namespace Artemis.Core.Services.Interfaces { @@ -91,5 +92,7 @@ namespace Artemis.Core.Services.Interfaces event EventHandler PluginDisabled; #endregion + + Plugin GetDevicePlugin(IRGBDevice device); } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/PluginService.cs b/src/Artemis.Core/Services/PluginService.cs index d9a57bd59..bce9a577b 100644 --- a/src/Artemis.Core/Services/PluginService.cs +++ b/src/Artemis.Core/Services/PluginService.cs @@ -14,6 +14,7 @@ using Newtonsoft.Json; using Ninject; using Ninject.Extensions.ChildKernel; using Ninject.Parameters; +using RGB.NET.Core; namespace Artemis.Core.Services { @@ -102,7 +103,7 @@ namespace Artemis.Core.Services // Create a child kernel and app domain that will only contain the plugins _childKernel = new ChildKernel(_kernel); - + // Load the plugin assemblies into the plugin context var pluginDirectory = new DirectoryInfo(Path.Combine(Constants.DataFolder, "plugins")); foreach (var subDirectory in pluginDirectory.EnumerateDirectories()) @@ -282,6 +283,11 @@ namespace Artemis.Core.Services } } + public Plugin GetDevicePlugin(IRGBDevice rgbDevice) + { + return GetPluginsOfType().First(d => d.DeviceProvider.Devices.Contains(rgbDevice)); + } + public void Dispose() { UnloadPlugins(); diff --git a/src/Artemis.Core/Services/Storage/SurfaceService.cs b/src/Artemis.Core/Services/Storage/SurfaceService.cs index c0492d8cd..a6f2c38ca 100644 --- a/src/Artemis.Core/Services/Storage/SurfaceService.cs +++ b/src/Artemis.Core/Services/Storage/SurfaceService.cs @@ -18,15 +18,17 @@ namespace Artemis.Core.Services.Storage { private readonly ILogger _logger; private readonly IRgbService _rgbService; + private readonly IPluginService _pluginService; private readonly List _surfaceConfigurations; private readonly ISurfaceRepository _surfaceRepository; private readonly PluginSetting _renderScaleSetting; - internal SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, ISettingsService settingsService) + internal SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, IPluginService pluginService, ISettingsService settingsService) { _logger = logger; _surfaceRepository = surfaceRepository; _rgbService = rgbService; + _pluginService = pluginService; _surfaceConfigurations = new List(); _renderScaleSetting = settingsService.GetSetting("RenderScale", 1.0); @@ -36,8 +38,6 @@ namespace Artemis.Core.Services.Storage _renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged; } - - public Surface ActiveSurface { get; private set; } public ReadOnlyCollection SurfaceConfigurations => _surfaceConfigurations.AsReadOnly(); @@ -47,8 +47,11 @@ namespace Artemis.Core.Services.Storage var configuration = new Surface(_rgbService.Surface, name, _renderScaleSetting.Value); // Add all current devices - foreach (var rgbDevice in _rgbService.LoadedDevices) - configuration.Devices.Add(new Device(rgbDevice, configuration)); + foreach (var rgbDevice in _rgbService.LoadedDevices) + { + var plugin = _pluginService.GetDevicePlugin(rgbDevice); + configuration.Devices.Add(new Device(rgbDevice, plugin, configuration)); + } lock (_surfaceConfigurations) { @@ -140,9 +143,8 @@ namespace Artemis.Core.Services.Storage private void RenderScaleSettingOnSettingChanged(object sender, EventArgs e) { - foreach (var surfaceConfiguration in SurfaceConfigurations) + foreach (var surfaceConfiguration in SurfaceConfigurations) surfaceConfiguration.UpdateScale(_renderScaleSetting.Value); - } #endregion @@ -156,6 +158,15 @@ namespace Artemis.Core.Services.Storage { // Create the surface entity var surfaceConfiguration = new Surface(_rgbService.Surface, surfaceEntity, _renderScaleSetting.Value); + foreach (var position in surfaceEntity.DeviceEntities) + { + var device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceHashCode() == position.DeviceHashCode); + if (device != null) + { + var plugin = _pluginService.GetDevicePlugin(device); + surfaceConfiguration.Devices.Add(new Device(device, plugin, surfaceConfiguration, position)); + } + } // Finally, add the surface config to the collection lock (_surfaceConfigurations) @@ -189,11 +200,14 @@ namespace Artemis.Core.Services.Storage if (device != null) return; - + // Find an existing device config and use that var existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceHashCode == deviceHashCode); - if (existingDeviceConfig != null) - device = new Device(rgbDevice,surface, existingDeviceConfig); + if (existingDeviceConfig != null) + { + var plugin = _pluginService.GetDevicePlugin(rgbDevice); + device = new Device(rgbDevice, plugin, surface, existingDeviceConfig); + } // Fall back on creating a new device else { @@ -202,7 +216,8 @@ namespace Artemis.Core.Services.Storage rgbDevice.DeviceInfo, deviceHashCode ); - device = new Device(rgbDevice, surface); + var plugin = _pluginService.GetDevicePlugin(rgbDevice); + device = new Device(rgbDevice, plugin, surface); } surface.Devices.Add(device); diff --git a/src/Artemis.Plugins.Devices.Corsair/CorsairDevice.cs b/src/Artemis.Plugins.Devices.Corsair/CorsairDevice.cs index 6ccee5969..98e4b0272 100644 --- a/src/Artemis.Plugins.Devices.Corsair/CorsairDevice.cs +++ b/src/Artemis.Plugins.Devices.Corsair/CorsairDevice.cs @@ -13,7 +13,7 @@ namespace Artemis.Plugins.Devices.Corsair { private readonly IRgbService _rgbService; - public CorsairDevice(PluginInfo pluginInfo, IRgbService rgbService) : base(pluginInfo) + public CorsairDevice(PluginInfo pluginInfo, IRgbService rgbService) : base(pluginInfo, CorsairDeviceProvider.Instance) { _rgbService = rgbService; } @@ -23,7 +23,7 @@ namespace Artemis.Plugins.Devices.Corsair PathHelper.ResolvingAbsolutePath += ResolveCorsairPath; CorsairDeviceProvider.PossibleX64NativePaths.Add(Path.Combine(PluginInfo.Directory.FullName, "x64", "CUESDK.dll")); CorsairDeviceProvider.PossibleX86NativePaths.Add(Path.Combine(PluginInfo.Directory.FullName, "x86", "CUESDK.dll")); - _rgbService.AddDeviceProvider(CorsairDeviceProvider.Instance); + _rgbService.AddDeviceProvider(DeviceProvider); } private void ResolveCorsairPath(object sender, ResolvePathEventArgs e) diff --git a/src/Artemis.Plugins.Devices.Corsair/Layouts/Corsair/Customs/LLFAN.xml b/src/Artemis.Plugins.Devices.Corsair/Layouts/Corsair/Customs/LLFAN.xml index ae64a3466..81e38baa1 100644 --- a/src/Artemis.Plugins.Devices.Corsair/Layouts/Corsair/Customs/LLFAN.xml +++ b/src/Artemis.Plugins.Devices.Corsair/Layouts/Corsair/Customs/LLFAN.xml @@ -32,62 +32,63 @@ - - - + + Circle - 59.5 - 0 - - - Circle - 90.5 - 7.6 - - - Circle - 113 + 7.9 29.8 - - - Circle - 120.5 - 59.9 - - - Circle - 113 - 90.4 - - - Circle - 90.5 - 113.1 - - - Circle - 59.5 - 120.5 - - - Circle - 30.7 - 113.1 - - - Circle - 8 - 90.4 - - + + Circle 0.4 59.9 - + Circle - 7.9 + 8 + 90.4 + + + Circle + 30.7 + 113.1 + + + Circle + 59.5 + 120.5 + + + Circle + 90.5 + 113.1 + + + Circle + 113 + 90.4 + + + Circle + 120.5 + 59.9 + + + Circle + 113 29.8 - + + Circle + 90.5 + 7.6 + + + Circle + 59.5 + 0 + + Circle 28 7.6 diff --git a/src/Artemis.Plugins.Modules.General/GeneralModule.cs b/src/Artemis.Plugins.Modules.General/GeneralModule.cs index 65be4624a..3ae230ed6 100644 --- a/src/Artemis.Plugins.Modules.General/GeneralModule.cs +++ b/src/Artemis.Plugins.Modules.General/GeneralModule.cs @@ -1,17 +1,20 @@ using System; using System.Drawing; +using System.Drawing.Drawing2D; using System.Linq; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Models; using Artemis.Plugins.Modules.General.ViewModels; using Stylet; +using Device = Artemis.Core.Models.Surface.Device; namespace Artemis.Plugins.Modules.General { public class GeneralModule : Module { private readonly PluginSettings _settings; + private readonly ColorBlend _rainbowColorBlend; public GeneralModule(PluginInfo pluginInfo, PluginSettings settings) : base(pluginInfo) { @@ -24,9 +27,20 @@ namespace Artemis.Plugins.Modules.General Hues = new int[1000]; for (var i = 0; i < 1000; i++) Hues[i] = ColorHelpers.GetRandomHue(); + + _rainbowColorBlend = new ColorBlend(9); + for (var i = 0; i < 9; i++) + { + _rainbowColorBlend.Positions[i] = i / 8f; + if (i != 8) + _rainbowColorBlend.Colors[i] = ColorHelpers.ColorFromHSV(i * 32, 1, 1); + else + _rainbowColorBlend.Colors[i] = ColorHelpers.ColorFromHSV(0, 1, 1); + } } public int[] Hues { get; set; } + public int MovePercentage { get; set; } public override void EnablePlugin() { @@ -44,15 +58,20 @@ namespace Artemis.Plugins.Modules.General if (Hues[i] > 360) Hues[i] = 0; } + + MovePercentage++; + if (MovePercentage > 100) + MovePercentage = 0; } + public override void Render(double deltaTime, Surface surface, Graphics graphics) { // Per-device coloring, slower - RenderPerDevice(surface, graphics); +// RenderPerDevice(surface, graphics); // Per-LED coloring, slowest - // RenderPerLed(surface, graphics); + RenderPerLed(surface, graphics); } public void RenderFullSurface(Surface surface, Graphics graphics) @@ -61,14 +80,34 @@ namespace Artemis.Plugins.Modules.General public void RenderPerDevice(Surface surface, Graphics graphics) { - var index = 0; foreach (var device in surface.Devices) { - graphics.FillRectangle(new SolidBrush(ColorHelpers.ColorFromHSV(Hues[index], 1, 1)), device.RenderRectangle); - index++; + using (var gradient = RenderGradientForDevice(device)) + { + using (var brush = new TextureBrush(gradient, WrapMode.Tile)) + { + brush.TranslateTransform((int) Math.Round(device.RenderRectangle.Width / 100.0 * MovePercentage), 0); + graphics.FillPath(brush, device.RenderPath); + } + } } } + private Image RenderGradientForDevice(Device device) + { + var brush = new LinearGradientBrush(device.RenderRectangle, Color.Black, Color.Black, 0, false) + { + InterpolationColors = _rainbowColorBlend + }; + var bitmap = new Bitmap(device.RenderRectangle.Width, device.RenderRectangle.Height); + using (var g = Graphics.FromImage(bitmap)) + { + g.FillRectangle(brush, 0, 0, device.RenderRectangle.Width, device.RenderRectangle.Height); + } + + return bitmap; + } + public void RenderPerLed(Surface surface, Graphics graphics) { var index = 0; diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index dd4d2c624..4a4b7c781 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -184,7 +184,7 @@ - + @@ -235,7 +235,7 @@ MSBuild:Compile Designer - + Designer MSBuild:Compile diff --git a/src/Artemis.UI/ViewModels/Controls/Settings/DeviceSettingsViewModel.cs b/src/Artemis.UI/ViewModels/Controls/Settings/DeviceSettingsViewModel.cs new file mode 100644 index 000000000..533c70ac7 --- /dev/null +++ b/src/Artemis.UI/ViewModels/Controls/Settings/DeviceSettingsViewModel.cs @@ -0,0 +1,76 @@ +using System.Diagnostics; +using System.Drawing; +using System.Threading.Tasks; +using Artemis.Core.Events; +using Artemis.Core.Models.Surface; +using Artemis.Core.Services.Interfaces; +using Humanizer; + +namespace Artemis.UI.ViewModels.Controls.Settings +{ + public class DeviceSettingsViewModel + { + private readonly ICoreService _coreService; + + public DeviceSettingsViewModel(Device device, ICoreService coreService) + { + _coreService = coreService; + + Device = device; + + Type = Device.RgbDevice.DeviceInfo.DeviceType.ToString().Humanize(); + Name = Device.RgbDevice.DeviceInfo.Model; + Manufacturer = Device.RgbDevice.DeviceInfo.Manufacturer; + IsDeviceEnabled = true; + } + + public Device Device { get; } + + public string Type { get; set; } + public string Name { get; set; } + public string Manufacturer { get; set; } + public bool IsDeviceEnabled { get; set; } + + public void Identify() + { + BlinkDevice(0); + } + + private void BlinkDevice(int blinkCount) + { + // Draw a white overlay over the device + void DrawOverlay(object sender, FrameRenderingEventArgs args) + { + using (var g = Graphics.FromImage(args.Bitmap)) + { + g.FillPath(new SolidBrush(Color.White), Device.RenderPath); + } + } + + _coreService.FrameRendering += DrawOverlay; + + // After 200ms, stop drawing the overlay + Task.Run(async () => + { + await Task.Delay(200); + _coreService.FrameRendering -= DrawOverlay; + + if (blinkCount < 5) + { + // After another 200ms, draw the overlay again, repeat six times + await Task.Delay(200); + BlinkDevice(blinkCount + 1); + } + }); + } + + public void ShowDeviceDebugger() + { + } + + public void OpenPluginDirectory() + { + Process.Start(Device.Plugin.PluginInfo.Directory.FullName); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/ViewModels/Controls/Settings/RgbDeviceSettingsViewModel.cs b/src/Artemis.UI/ViewModels/Controls/Settings/RgbDeviceSettingsViewModel.cs deleted file mode 100644 index ee0553900..000000000 --- a/src/Artemis.UI/ViewModels/Controls/Settings/RgbDeviceSettingsViewModel.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Humanizer; -using RGB.NET.Core; - -namespace Artemis.UI.ViewModels.Controls.Settings -{ - public class RgbDeviceSettingsViewModel - { - public IRGBDevice Device { get; } - - public RgbDeviceSettingsViewModel(IRGBDevice device) - { - Device = device; - - Type = Device.DeviceInfo.DeviceType.ToString().Humanize(); - Name = Device.DeviceInfo.Model; - Manufacturer = Device.DeviceInfo.Manufacturer; - Enabled = true; - } - - public string Type { get; set; } - public string Name { get; set; } - public string Manufacturer { get; set; } - public bool Enabled { get; set; } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/ViewModels/Screens/DebugViewModel.cs b/src/Artemis.UI/ViewModels/Screens/DebugViewModel.cs index a14e71a72..c7b85f262 100644 --- a/src/Artemis.UI/ViewModels/Screens/DebugViewModel.cs +++ b/src/Artemis.UI/ViewModels/Screens/DebugViewModel.cs @@ -22,6 +22,7 @@ namespace Artemis.UI.ViewModels.Screens _rgbService = rgbService; _coreService.FrameRendered += CoreServiceOnFrameRendered; + _coreService.FrameRendering += CoreServiceOnFrameRendering; } public ImageSource CurrentFrame { get; set; } @@ -33,20 +34,25 @@ namespace Artemis.UI.ViewModels.Screens GC.WaitForPendingFinalizers(); } - private void CoreServiceOnFrameRendered(object sender, FrameEventArgs e) + private void CoreServiceOnFrameRendered(object sender, FrameRenderedEventArgs e) { var imageSource = ImageSourceFromBitmap(e.Bitmap); imageSource.Freeze(); - CurrentFps = Math.Round(1.0 / e.DeltaTime, 2); Execute.OnUIThread(() => { CurrentFrame = imageSource; }); } - + + private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e) + { + CurrentFps = Math.Round(1.0 / e.DeltaTime, 2); + } + protected override void OnClose() { _coreService.FrameRendered -= CoreServiceOnFrameRendered; + _coreService.FrameRendering -= CoreServiceOnFrameRendering; base.OnClose(); } diff --git a/src/Artemis.UI/ViewModels/Screens/SettingsViewModel.cs b/src/Artemis.UI/ViewModels/Screens/SettingsViewModel.cs index b55e8b996..e14733ffc 100644 --- a/src/Artemis.UI/ViewModels/Screens/SettingsViewModel.cs +++ b/src/Artemis.UI/ViewModels/Screens/SettingsViewModel.cs @@ -1,6 +1,7 @@ -using Artemis.Core.Events; +using System.Windows.Media; using Artemis.Core.Services; using Artemis.Core.Services.Interfaces; +using Artemis.Core.Services.Storage; using Artemis.UI.ViewModels.Controls.Settings; using Artemis.UI.ViewModels.Interfaces; using Ninject; @@ -11,30 +12,42 @@ namespace Artemis.UI.ViewModels.Screens public class SettingsViewModel : Screen, ISettingsViewModel { private readonly IKernel _kernel; + private readonly ICoreService _coreService; + private readonly ISurfaceService _surfaceService; private readonly IWindowManager _windowManager; + private readonly ISettingsService _settingsService; - public SettingsViewModel(IKernel kernel, IRgbService rgbService, IWindowManager windowManager, ISettingsService settingsService) + public SettingsViewModel(IKernel kernel, ICoreService coreService, ISurfaceService surfaceService, IWindowManager windowManager, ISettingsService settingsService) { _kernel = kernel; + _coreService = coreService; + _surfaceService = surfaceService; _windowManager = windowManager; - DeviceSettingsViewModels = new BindableCollection(); - foreach (var device in rgbService.LoadedDevices) - DeviceSettingsViewModels.Add(new RgbDeviceSettingsViewModel(device)); + _settingsService = settingsService; - rgbService.DeviceLoaded += UpdateDevices; + DeviceSettingsViewModels = new BindableCollection(); + RenderScale = _settingsService.GetSetting("RenderScale", 1.0).Value; + TargetFrameRate = _settingsService.GetSetting("FrameRate", 25).Value; } - public BindableCollection DeviceSettingsViewModels { get; set; } + public BindableCollection DeviceSettingsViewModels { get; set; } public string Title => "Settings"; + public double RenderScale { get; set; } + public int TargetFrameRate { get; set; } + + protected override void OnActivate() + { + DeviceSettingsViewModels.Clear(); + foreach (var device in _surfaceService.ActiveSurface.Devices) + DeviceSettingsViewModels.Add(new DeviceSettingsViewModel(device, _coreService)); + + base.OnActivate(); + } + public void ShowDebugger() { _windowManager.ShowWindow(_kernel.Get()); } - - private void UpdateDevices(object sender, DeviceEventArgs deviceEventArgs) - { - DeviceSettingsViewModels.Add(new RgbDeviceSettingsViewModel(deviceEventArgs.Device)); - } } } \ No newline at end of file diff --git a/src/Artemis.UI/Views/Controls/Settings/DeviceSettingsView.xaml b/src/Artemis.UI/Views/Controls/Settings/DeviceSettingsView.xaml new file mode 100644 index 000000000..8d9559d0c --- /dev/null +++ b/src/Artemis.UI/Views/Controls/Settings/DeviceSettingsView.xaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + Device enabled + + + + - - - - - - - - - - - - - - - -