mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Added a layer of abstraction between RGB.NET and Artemis
This means Artemis can add extra functionality It also avoid having to reference RGB.NET for basic rendering Implemented rendering scaling
This commit is contained in:
parent
498b6a6111
commit
8777e8975f
@ -148,13 +148,16 @@
|
||||
<Compile Include="Exceptions\ArtemisCoreException.cs" />
|
||||
<Compile Include="Extensions\DirectoryInfoExtensions.cs" />
|
||||
<Compile Include="Extensions\RgbColorExtensions.cs" />
|
||||
<Compile Include="Extensions\RgbDeviceExtensions.cs" />
|
||||
<Compile Include="Extensions\RgbRectangleExtensions.cs" />
|
||||
<Compile Include="Extensions\TypeExtensions.cs" />
|
||||
<Compile Include="Models\DataModelDescription.cs" />
|
||||
<Compile Include="Models\Surface\SurfaceConfiguration.cs" />
|
||||
<Compile Include="Models\Surface\SurfaceDeviceConfiguration.cs" />
|
||||
<Compile Include="Models\Surface\Led.cs" />
|
||||
<Compile Include="Models\Surface\Surface.cs" />
|
||||
<Compile Include="Models\Surface\Device.cs" />
|
||||
<Compile Include="Ninject\LoggerProvider.cs" />
|
||||
<Compile Include="Ninject\PluginSettingsProvider.cs" />
|
||||
<Compile Include="Ninject\SettingsServiceProvider.cs" />
|
||||
<Compile Include="Plugins\Abstract\ModuleDataModel.cs" />
|
||||
<Compile Include="Plugins\Abstract\ModuleViewModel.cs" />
|
||||
<Compile Include="Plugins\Abstract\ProfileModule.cs" />
|
||||
@ -176,6 +179,7 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RGB.NET\DirectBitmap.cs" />
|
||||
<Compile Include="RGB.NET\GraphicsDecorator.cs" />
|
||||
<Compile Include="Services\Interfaces\IProtectedArtemisService.cs" />
|
||||
<Compile Include="Services\Interfaces\IMainDataModelService.cs" />
|
||||
<Compile Include="Services\CoreService.cs" />
|
||||
<Compile Include="Services\MainDataModelService.cs" />
|
||||
@ -186,6 +190,7 @@
|
||||
<Compile Include="Services\Interfaces\IPluginService.cs" />
|
||||
<Compile Include="Events\PluginEventArgs.cs" />
|
||||
<Compile Include="Services\PluginService.cs" />
|
||||
<Compile Include="Services\SettingsService.cs" />
|
||||
<Compile Include="Services\StorageService.cs" />
|
||||
<Compile Include="Services\Storage\ISurfaceService.cs" />
|
||||
<Compile Include="Services\Storage\SurfaceService.cs" />
|
||||
|
||||
@ -5,11 +5,11 @@ namespace Artemis.Core.Events
|
||||
{
|
||||
public class SurfaceConfigurationEventArgs : EventArgs
|
||||
{
|
||||
public SurfaceConfigurationEventArgs(SurfaceConfiguration surfaceConfiguration)
|
||||
public SurfaceConfigurationEventArgs(Surface surface)
|
||||
{
|
||||
SurfaceConfiguration = surfaceConfiguration;
|
||||
Surface = surface;
|
||||
}
|
||||
|
||||
public SurfaceConfiguration SurfaceConfiguration { get; }
|
||||
public Surface Surface { get; }
|
||||
}
|
||||
}
|
||||
20
src/Artemis.Core/Extensions/RgbDeviceExtensions.cs
Normal file
20
src/Artemis.Core/Extensions/RgbDeviceExtensions.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace Artemis.Core.Extensions
|
||||
{
|
||||
public static class RgbDeviceExtensions
|
||||
{
|
||||
public static int GetDeviceHashCode(this IRGBDevice rgbDevice)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hashCode = rgbDevice.DeviceInfo.DeviceName?.GetHashCode() ?? 0;
|
||||
hashCode = (hashCode * 397) ^ (rgbDevice.DeviceInfo.Manufacturer?.GetHashCode() ?? 0);
|
||||
hashCode = (hashCode * 397) ^ (rgbDevice.DeviceInfo.Model?.GetHashCode() ?? 0);
|
||||
hashCode = (hashCode * 397) ^ (int) rgbDevice.DeviceInfo.DeviceType;
|
||||
hashCode = (hashCode * 397) ^ (int) rgbDevice.DeviceInfo.Lighting;
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@ namespace Artemis.Core.Models.Profile
|
||||
profileElement.Update(deltaTime);
|
||||
}
|
||||
|
||||
public void Render(double deltaTime, RGBSurface surface, Graphics graphics)
|
||||
public void Render(double deltaTime, Surface.Surface surface, Graphics graphics)
|
||||
{
|
||||
// Folders don't render but their children do
|
||||
foreach (var profileElement in Children)
|
||||
|
||||
@ -30,6 +30,6 @@ namespace Artemis.Core.Models.Profile.Interfaces
|
||||
/// <summary>
|
||||
/// Renders the element
|
||||
/// </summary>
|
||||
void Render(double deltaTime, RGBSurface surface, Graphics graphics);
|
||||
void Render(double deltaTime, Surface.Surface surface, Graphics graphics);
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,6 @@ 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
|
||||
{
|
||||
@ -36,7 +35,7 @@ namespace Artemis.Core.Models.Profile
|
||||
}
|
||||
}
|
||||
|
||||
public void Render(double deltaTime, RGBSurface surface, Graphics graphics)
|
||||
public void Render(double deltaTime, Surface.Surface surface, Graphics graphics)
|
||||
{
|
||||
if (LayerType == null)
|
||||
return;
|
||||
|
||||
@ -35,7 +35,7 @@ namespace Artemis.Core.Models.Profile
|
||||
}
|
||||
}
|
||||
|
||||
public void Render(double deltaTime, RGBSurface surface, Graphics graphics)
|
||||
public void Render(double deltaTime, Surface.Surface surface, Graphics graphics)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
|
||||
105
src/Artemis.Core/Models/Surface/Device.cs
Normal file
105
src/Artemis.Core/Models/Surface/Device.cs
Normal file
@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Extensions;
|
||||
using Artemis.Storage.Entities;
|
||||
using RGB.NET.Core;
|
||||
using Rectangle = System.Drawing.Rectangle;
|
||||
|
||||
namespace Artemis.Core.Models.Surface
|
||||
{
|
||||
public class Device
|
||||
{
|
||||
internal Device(IRGBDevice rgbDevice, Surface surface)
|
||||
{
|
||||
RgbDevice = rgbDevice;
|
||||
Surface = surface;
|
||||
Configuration = new DeviceEntity();
|
||||
Leds = rgbDevice.Select(l => new DeviceLed(l, this)).ToList().AsReadOnly();
|
||||
|
||||
Rotation = 0;
|
||||
ZIndex = 1;
|
||||
|
||||
ApplyToConfiguration();
|
||||
CalculateRenderRectangle();
|
||||
}
|
||||
|
||||
internal Device(IRGBDevice rgbDevice, Surface surface, DeviceEntity configuration)
|
||||
{
|
||||
RgbDevice = rgbDevice;
|
||||
Surface = surface;
|
||||
Configuration = configuration;
|
||||
Leds = rgbDevice.Select(l => new DeviceLed(l, this)).ToList().AsReadOnly();
|
||||
|
||||
Rotation = configuration.Rotation;
|
||||
ZIndex = configuration.ZIndex;
|
||||
}
|
||||
|
||||
public Rectangle RenderRectangle { get; private set; }
|
||||
|
||||
public IRGBDevice RgbDevice { get; private set; }
|
||||
public Surface Surface { get; private set; }
|
||||
public DeviceEntity Configuration { get; private set; }
|
||||
public ReadOnlyCollection<DeviceLed> Leds { get; set; }
|
||||
|
||||
public double X
|
||||
{
|
||||
get => Configuration.X;
|
||||
set => Configuration.X = value;
|
||||
}
|
||||
|
||||
public double Y
|
||||
{
|
||||
get => Configuration.Y;
|
||||
set => Configuration.Y = value;
|
||||
}
|
||||
|
||||
public double Rotation
|
||||
{
|
||||
get => Configuration.Rotation;
|
||||
set => Configuration.Rotation = value;
|
||||
}
|
||||
|
||||
public int ZIndex
|
||||
{
|
||||
get => Configuration.ZIndex;
|
||||
set => Configuration.ZIndex = value;
|
||||
}
|
||||
|
||||
internal void ApplyToConfiguration()
|
||||
{
|
||||
Configuration.SurfaceId = Surface.Guid;
|
||||
Configuration.DeviceHashCode = RgbDevice.GetDeviceHashCode();
|
||||
|
||||
// Ensure the position configuration is in the surface configuration's' collection of positions
|
||||
if (Surface.SurfaceEntity.DeviceEntities.All(p => p.Guid != Configuration.Guid))
|
||||
Surface.SurfaceEntity.DeviceEntities.Add(Configuration);
|
||||
}
|
||||
|
||||
internal void ApplyToRgbDevice()
|
||||
{
|
||||
RgbDevice.Location = new Point(Configuration.X, Configuration.Y);
|
||||
CalculateRenderRectangle();
|
||||
}
|
||||
|
||||
internal void CalculateRenderRectangle()
|
||||
{
|
||||
RenderRectangle = new Rectangle(
|
||||
(int) Math.Round(RgbDevice.Location.X * Surface.Scale, MidpointRounding.AwayFromZero),
|
||||
(int) Math.Round(RgbDevice.Location.Y * Surface.Scale, MidpointRounding.AwayFromZero),
|
||||
(int) Math.Round(RgbDevice.Size.Width * Surface.Scale, MidpointRounding.AwayFromZero),
|
||||
(int) Math.Round(RgbDevice.Size.Height * Surface.Scale, MidpointRounding.AwayFromZero)
|
||||
);
|
||||
|
||||
foreach (var led in Leds)
|
||||
led.CalculateRenderRectangle();
|
||||
}
|
||||
|
||||
internal void Destroy()
|
||||
{
|
||||
Configuration = null;
|
||||
RgbDevice = null;
|
||||
Surface = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/Artemis.Core/Models/Surface/Led.cs
Normal file
38
src/Artemis.Core/Models/Surface/Led.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using RGB.NET.Core;
|
||||
using Rectangle = System.Drawing.Rectangle;
|
||||
|
||||
namespace Artemis.Core.Models.Surface
|
||||
{
|
||||
public class DeviceLed
|
||||
{
|
||||
public DeviceLed(Led led, Device device)
|
||||
{
|
||||
RgbLed = led;
|
||||
Device = device;
|
||||
CalculateRenderRectangle();
|
||||
}
|
||||
|
||||
public Led RgbLed { get; }
|
||||
public Device Device { get; }
|
||||
|
||||
public Rectangle RenderRectangle { get; private set; }
|
||||
public Rectangle AbsoluteRenderRectangle { get; private set; }
|
||||
|
||||
public void CalculateRenderRectangle()
|
||||
{
|
||||
RenderRectangle = new Rectangle(
|
||||
(int) Math.Round(RgbLed.LedRectangle.X * Device.Surface.Scale, MidpointRounding.AwayFromZero),
|
||||
(int) Math.Round(RgbLed.LedRectangle.Y * Device.Surface.Scale, MidpointRounding.AwayFromZero),
|
||||
(int) Math.Round(RgbLed.LedRectangle.Width * Device.Surface.Scale, MidpointRounding.AwayFromZero),
|
||||
(int) Math.Round(RgbLed.LedRectangle.Height * Device.Surface.Scale, MidpointRounding.AwayFromZero)
|
||||
);
|
||||
AbsoluteRenderRectangle = new Rectangle(
|
||||
(int) Math.Round(RgbLed.AbsoluteLedRectangle.X * Device.Surface.Scale, MidpointRounding.AwayFromZero),
|
||||
(int) Math.Round(RgbLed.AbsoluteLedRectangle.Y * Device.Surface.Scale, MidpointRounding.AwayFromZero),
|
||||
(int) Math.Round(RgbLed.AbsoluteLedRectangle.Width * Device.Surface.Scale, MidpointRounding.AwayFromZero),
|
||||
(int) Math.Round(RgbLed.AbsoluteLedRectangle.Height * Device.Surface.Scale, MidpointRounding.AwayFromZero)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
93
src/Artemis.Core/Models/Surface/Surface.cs
Normal file
93
src/Artemis.Core/Models/Surface/Surface.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Extensions;
|
||||
using Artemis.Storage.Entities;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace Artemis.Core.Models.Surface
|
||||
{
|
||||
public class Surface
|
||||
{
|
||||
internal Surface(RGBSurface rgbSurface, string name, double scale)
|
||||
{
|
||||
SurfaceEntity = new SurfaceEntity {DeviceEntities = new List<DeviceEntity>()};
|
||||
Guid = System.Guid.NewGuid().ToString();
|
||||
|
||||
Name = name;
|
||||
Scale = scale;
|
||||
RgbSurface = rgbSurface;
|
||||
IsActive = false;
|
||||
Devices = new List<Device>();
|
||||
|
||||
ApplyToEntity();
|
||||
}
|
||||
|
||||
internal Surface(RGBSurface rgbSurface, SurfaceEntity surfaceEntity, double scale)
|
||||
{
|
||||
RgbSurface = rgbSurface;
|
||||
SurfaceEntity = surfaceEntity;
|
||||
Scale = scale;
|
||||
Guid = surfaceEntity.Guid;
|
||||
|
||||
Name = surfaceEntity.Name;
|
||||
IsActive = surfaceEntity.IsActive;
|
||||
Devices = new List<Device>();
|
||||
|
||||
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; }
|
||||
public double Scale { get; private set; }
|
||||
public string Name { get; set; }
|
||||
public bool IsActive { get; internal set; }
|
||||
public List<Device> Devices { get; internal set; }
|
||||
|
||||
internal SurfaceEntity SurfaceEntity { get; set; }
|
||||
internal string Guid { get; set; }
|
||||
|
||||
internal void ApplyToEntity()
|
||||
{
|
||||
SurfaceEntity.Guid = Guid;
|
||||
SurfaceEntity.Name = Name;
|
||||
SurfaceEntity.IsActive = IsActive;
|
||||
}
|
||||
|
||||
internal void Destroy()
|
||||
{
|
||||
SurfaceEntity = null;
|
||||
|
||||
foreach (var deviceConfiguration in Devices)
|
||||
deviceConfiguration.Destroy();
|
||||
Devices.Clear();
|
||||
}
|
||||
|
||||
public void UpdateScale(double value)
|
||||
{
|
||||
Scale = value;
|
||||
foreach (var device in Devices)
|
||||
device.CalculateRenderRectangle();
|
||||
|
||||
OnScaleChanged();
|
||||
}
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler<EventArgs> ScaleChanged;
|
||||
|
||||
protected virtual void OnScaleChanged()
|
||||
{
|
||||
ScaleChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Storage.Entities;
|
||||
|
||||
namespace Artemis.Core.Models.Surface
|
||||
{
|
||||
public class SurfaceConfiguration
|
||||
{
|
||||
internal SurfaceConfiguration(string name)
|
||||
{
|
||||
SurfaceEntity = new SurfaceEntity {SurfacePositions = new List<SurfacePositionEntity>()};
|
||||
Guid = System.Guid.NewGuid().ToString();
|
||||
|
||||
Name = name;
|
||||
IsActive = false;
|
||||
DeviceConfigurations = new List<SurfaceDeviceConfiguration>();
|
||||
|
||||
ApplyToEntity();
|
||||
}
|
||||
|
||||
internal SurfaceConfiguration(SurfaceEntity surfaceEntity)
|
||||
{
|
||||
SurfaceEntity = surfaceEntity;
|
||||
Guid = surfaceEntity.Guid;
|
||||
|
||||
Name = surfaceEntity.Name;
|
||||
IsActive = surfaceEntity.IsActive;
|
||||
DeviceConfigurations = new List<SurfaceDeviceConfiguration>();
|
||||
|
||||
if (surfaceEntity.SurfacePositions == null)
|
||||
return;
|
||||
foreach (var position in surfaceEntity.SurfacePositions)
|
||||
DeviceConfigurations.Add(new SurfaceDeviceConfiguration(position, this));
|
||||
}
|
||||
|
||||
internal SurfaceEntity SurfaceEntity { get; set; }
|
||||
internal string Guid { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public bool IsActive { get; internal set; }
|
||||
public List<SurfaceDeviceConfiguration> DeviceConfigurations { get; internal set; }
|
||||
|
||||
internal void ApplyToEntity()
|
||||
{
|
||||
SurfaceEntity.Guid = Guid;
|
||||
SurfaceEntity.Name = Name;
|
||||
SurfaceEntity.IsActive = IsActive;
|
||||
}
|
||||
|
||||
internal void Destroy()
|
||||
{
|
||||
SurfaceEntity = null;
|
||||
|
||||
foreach (var deviceConfiguration in DeviceConfigurations)
|
||||
deviceConfiguration.Destroy();
|
||||
DeviceConfigurations.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
using System.Linq;
|
||||
using Artemis.Storage.Entities;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace Artemis.Core.Models.Surface
|
||||
{
|
||||
public class SurfaceDeviceConfiguration
|
||||
{
|
||||
internal SurfaceDeviceConfiguration(IRGBDevice device, int deviceId, SurfaceConfiguration surface)
|
||||
{
|
||||
PositionEntity = new SurfacePositionEntity();
|
||||
Guid = System.Guid.NewGuid().ToString();
|
||||
|
||||
Device = device;
|
||||
DeviceId = deviceId;
|
||||
DeviceName = device.DeviceInfo.DeviceName;
|
||||
DeviceModel = device.DeviceInfo.Model;
|
||||
DeviceManufacturer = device.DeviceInfo.Manufacturer;
|
||||
|
||||
X = device.Location.X;
|
||||
Y = device.Location.Y;
|
||||
Rotation = 0;
|
||||
ZIndex = 1;
|
||||
|
||||
Surface = surface;
|
||||
|
||||
ApplyToEntity();
|
||||
}
|
||||
|
||||
internal SurfaceDeviceConfiguration(SurfacePositionEntity positionEntity, SurfaceConfiguration surfaceConfiguration)
|
||||
{
|
||||
PositionEntity = positionEntity;
|
||||
Guid = positionEntity.Guid;
|
||||
|
||||
DeviceId = positionEntity.DeviceId;
|
||||
DeviceName = positionEntity.DeviceName;
|
||||
DeviceModel = positionEntity.DeviceModel;
|
||||
DeviceManufacturer = positionEntity.DeviceManufacturer;
|
||||
|
||||
X = positionEntity.X;
|
||||
Y = positionEntity.Y;
|
||||
Rotation = positionEntity.Rotation;
|
||||
ZIndex = positionEntity.ZIndex;
|
||||
|
||||
Surface = surfaceConfiguration;
|
||||
}
|
||||
|
||||
internal SurfacePositionEntity PositionEntity { get; set; }
|
||||
internal string Guid { get; }
|
||||
|
||||
public IRGBDevice Device { get; internal set; }
|
||||
public int DeviceId { get; }
|
||||
public string DeviceName { get; }
|
||||
public string DeviceModel { get; }
|
||||
public string DeviceManufacturer { get; }
|
||||
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
public double Rotation { get; set; }
|
||||
public int ZIndex { get; set; }
|
||||
|
||||
public SurfaceConfiguration Surface { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Applies the configuration to the device
|
||||
/// </summary>
|
||||
internal void ApplyToDevice()
|
||||
{
|
||||
if (Device != null)
|
||||
{
|
||||
Device.Location = new Point(X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Must be called when saving to the database
|
||||
/// </summary>
|
||||
internal void ApplyToEntity()
|
||||
{
|
||||
PositionEntity.Guid = Guid;
|
||||
PositionEntity.SurfaceId = Surface.Guid;
|
||||
|
||||
PositionEntity.DeviceId = DeviceId;
|
||||
PositionEntity.DeviceName = DeviceName;
|
||||
PositionEntity.DeviceModel = DeviceModel;
|
||||
PositionEntity.DeviceManufacturer = DeviceManufacturer;
|
||||
|
||||
PositionEntity.X = X;
|
||||
PositionEntity.Y = Y;
|
||||
PositionEntity.Rotation = Rotation;
|
||||
PositionEntity.ZIndex = ZIndex;
|
||||
|
||||
// Ensure the position entity is in the surface entity's' collection of positions
|
||||
if (Surface.SurfaceEntity.SurfacePositions.All(p => p.Guid != Guid))
|
||||
Surface.SurfaceEntity.SurfacePositions.Add(PositionEntity);
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
PositionEntity = null;
|
||||
Device = null;
|
||||
Surface = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
using Artemis.Core.Exceptions;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Core.Services.Interfaces;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using Ninject.Extensions.Conventions;
|
||||
@ -25,6 +26,16 @@ namespace Artemis.Core.Ninject
|
||||
.Configure(c => c.InSingletonScope());
|
||||
});
|
||||
|
||||
// Bind all protected services as singletons TODO: Protect 'em
|
||||
Kernel.Bind(x =>
|
||||
{
|
||||
x.FromThisAssembly()
|
||||
.SelectAllClasses()
|
||||
.InheritedFrom<IProtectedArtemisService>()
|
||||
.BindAllInterfaces()
|
||||
.Configure(c => c.InSingletonScope());
|
||||
});
|
||||
|
||||
// Bind all repositories as singletons
|
||||
Kernel.Bind(x =>
|
||||
{
|
||||
@ -34,7 +45,7 @@ namespace Artemis.Core.Ninject
|
||||
.BindAllInterfaces()
|
||||
.Configure(c => c.InSingletonScope());
|
||||
});
|
||||
|
||||
|
||||
Kernel.Bind<PluginSettings>().ToProvider<PluginSettingsProvider>();
|
||||
Kernel.Bind<ILogger>().ToProvider<LoggerProvider>();
|
||||
}
|
||||
|
||||
30
src/Artemis.Core/Ninject/SettingsServiceProvider.cs
Normal file
30
src/Artemis.Core/Ninject/SettingsServiceProvider.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Artemis.Core.Plugins.Abstract;
|
||||
using Artemis.Core.Plugins.Exceptions;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using Artemis.Core.Services;
|
||||
using Ninject;
|
||||
using Ninject.Activation;
|
||||
|
||||
namespace Artemis.Core.Ninject
|
||||
{
|
||||
public class SettingsServiceProvider : Provider<ISettingsService>
|
||||
{
|
||||
private readonly SettingsService _instance;
|
||||
|
||||
public SettingsServiceProvider(IKernel kernel)
|
||||
{
|
||||
// This is not lazy, but the core is always going to be using this anyway
|
||||
_instance = kernel.Get<SettingsService>();
|
||||
}
|
||||
|
||||
protected override ISettingsService CreateInstance(IContext context)
|
||||
{
|
||||
var parentRequest = context.Request.ParentRequest;
|
||||
if (parentRequest == null || typeof(Plugin).IsAssignableFrom(parentRequest.Service))
|
||||
throw new ArtemisPluginException($"SettingsService can not be injected into a plugin. Inject {nameof(PluginSettings)} instead.");
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
using System.Drawing;
|
||||
using Artemis.Core.Models.Profile;
|
||||
using Artemis.Core.Models.Surface;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using RGB.NET.Core;
|
||||
|
||||
@ -24,6 +25,6 @@ namespace Artemis.Core.Plugins.Abstract
|
||||
/// <summary>
|
||||
/// Renders the layer type
|
||||
/// </summary>
|
||||
public abstract void Render(Layer device, RGBSurface surface, Graphics graphics);
|
||||
public abstract void Render(Layer device, Surface surface, Graphics graphics);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Drawing;
|
||||
using Artemis.Core.Models.Surface;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using RGB.NET.Core;
|
||||
using Stylet;
|
||||
@ -38,7 +39,7 @@ namespace Artemis.Core.Plugins.Abstract
|
||||
/// <param name="deltaTime">Time since the last render</param>
|
||||
/// <param name="surface">The RGB Surface to render to</param>
|
||||
/// <param name="graphics"></param>
|
||||
public abstract void Render(double deltaTime, RGBSurface surface, Graphics graphics);
|
||||
public abstract void Render(double deltaTime, Surface surface, Graphics graphics);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the module's main view is being shown
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using Artemis.Core.Models.Profile;
|
||||
using Artemis.Core.Models.Surface;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using RGB.NET.Core;
|
||||
|
||||
@ -25,7 +26,7 @@ namespace Artemis.Core.Plugins.Abstract
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Render(double deltaTime, RGBSurface surface, Graphics graphics)
|
||||
public override void Render(double deltaTime, Surface surface, Graphics graphics)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Storage.Entities;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using Newtonsoft.Json;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core.Plugins.Models
|
||||
{
|
||||
public class PluginSetting<T>
|
||||
public class PluginSetting<T> : PropertyChangedBase
|
||||
{
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
private readonly PluginInfo _pluginInfo;
|
||||
@ -20,6 +23,15 @@ namespace Artemis.Core.Plugins.Models
|
||||
|
||||
Name = pluginSettingEntity.Name;
|
||||
Value = JsonConvert.DeserializeObject<T>(pluginSettingEntity.Value);
|
||||
|
||||
// PropertyChanged is for bindings, but we can use it here to create a easy to use SettingsChanged event
|
||||
PropertyChanged += OnPropertyChanged;
|
||||
}
|
||||
|
||||
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(Value))
|
||||
OnSettingChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -69,5 +81,12 @@ namespace Artemis.Core.Plugins.Models
|
||||
_pluginSettingEntity.Value = JsonConvert.SerializeObject(Value);
|
||||
await _pluginSettingRepository.SaveAsync();
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> SettingChanged;
|
||||
|
||||
protected virtual void OnSettingChanged()
|
||||
{
|
||||
SettingChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,10 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Artemis.Core.Plugins.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>This contains all the settings for your plugin. To access a setting use <see cref="GetSetting{T}" />.</para>
|
||||
/// <para>To use this class, inject it into the constructor of your plugin.</para>
|
||||
/// </summary>
|
||||
public class PluginSettings
|
||||
{
|
||||
private readonly PluginInfo _pluginInfo;
|
||||
@ -19,17 +23,27 @@ namespace Artemis.Core.Plugins.Models
|
||||
_settingEntities = pluginSettingRepository.GetByPluginGuid(_pluginInfo.Guid).ToDictionary(se => se.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the setting with the provided name. If the setting does not exist yet, it is created.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the setting, can be any serializable type</typeparam>
|
||||
/// <param name="name">The name of the setting</param>
|
||||
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
|
||||
/// <returns></returns>
|
||||
public PluginSetting<T> GetSetting<T>(string name, T defaultValue = default(T))
|
||||
{
|
||||
if (_settingEntities.ContainsKey(name))
|
||||
lock (_settingEntities)
|
||||
{
|
||||
if (_settingEntities.ContainsKey(name))
|
||||
return new PluginSetting<T>(_pluginInfo, _pluginSettingRepository, _settingEntities[name]);
|
||||
|
||||
var settingEntity = new PluginSettingEntity {Name = name, PluginGuid = _pluginInfo.Guid, Value = JsonConvert.SerializeObject(defaultValue)};
|
||||
_pluginSettingRepository.Add(settingEntity);
|
||||
_pluginSettingRepository.Save();
|
||||
|
||||
_settingEntities.Add(name, settingEntity);
|
||||
return new PluginSetting<T>(_pluginInfo, _pluginSettingRepository, _settingEntities[name]);
|
||||
|
||||
var settingEntity = new PluginSettingEntity {Name = name, PluginGuid = _pluginInfo.Guid, Value = JsonConvert.SerializeObject(defaultValue)};
|
||||
_pluginSettingRepository.Add(settingEntity);
|
||||
_pluginSettingRepository.Save();
|
||||
|
||||
_settingEntities.Add(name, settingEntity);
|
||||
return new PluginSetting<T>(_pluginInfo, _pluginSettingRepository, _settingEntities[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,11 +52,11 @@ namespace Artemis.Core.Services
|
||||
await Task.Run(() => _pluginService.CopyBuiltInPlugins());
|
||||
await Task.Run(() => _pluginService.LoadPlugins());
|
||||
|
||||
var surfaceConfig = _surfaceService.ActiveSurfaceConfiguration;
|
||||
var surfaceConfig = _surfaceService.ActiveSurface;
|
||||
if (surfaceConfig != null)
|
||||
_logger.Information("Initialized with active surface configuration {surfaceConfig}-{guid}", surfaceConfig.Name, surfaceConfig.Guid);
|
||||
_logger.Information("Initialized with active surface entity {surfaceConfig}-{guid}", surfaceConfig.Name, surfaceConfig.Guid);
|
||||
else
|
||||
_logger.Information("Initialized without an active surface configuration");
|
||||
_logger.Information("Initialized without an active surface entity");
|
||||
|
||||
OnInitialized();
|
||||
}
|
||||
@ -84,7 +84,7 @@ namespace Artemis.Core.Services
|
||||
|
||||
g.Clear(Color.Black);
|
||||
foreach (var module in modules)
|
||||
module.Render(args.DeltaTime, _rgbService.Surface, g);
|
||||
module.Render(args.DeltaTime, _surfaceService.ActiveSurface, g);
|
||||
}
|
||||
|
||||
OnFrameRendered(new FrameEventArgs(modules, _rgbService.GraphicsDecorator.GetBitmap(), args.DeltaTime, _rgbService.Surface));
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
namespace Artemis.Core.Services.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// A singleton service
|
||||
/// </summary>
|
||||
public interface IArtemisService
|
||||
{
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Artemis.Core.Services.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// A singleton service that cannot be used by plugins
|
||||
/// </summary>
|
||||
public interface IProtectedArtemisService
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -102,7 +102,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())
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Core.Events;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using Artemis.Core.RGB.NET;
|
||||
using Artemis.Core.Services.Interfaces;
|
||||
using Artemis.Core.Services.Storage;
|
||||
@ -20,15 +21,18 @@ namespace Artemis.Core.Services
|
||||
private readonly ILogger _logger;
|
||||
private readonly TimerUpdateTrigger _updateTrigger;
|
||||
private ListLedGroup _background;
|
||||
private PluginSetting<double> _renderScaleSetting;
|
||||
|
||||
internal RgbService(ILogger logger)
|
||||
internal RgbService(ILogger logger, ISettingsService settingsService)
|
||||
{
|
||||
_logger = logger;
|
||||
_renderScaleSetting = settingsService.GetSetting("RenderScale", 1.0);
|
||||
|
||||
Surface = RGBSurface.Instance;
|
||||
|
||||
// Let's throw these for now
|
||||
Surface.Exception += SurfaceOnException;
|
||||
|
||||
_renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged;
|
||||
_loadedDevices = new List<IRGBDevice>();
|
||||
_updateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / 25};
|
||||
Surface.RegisterUpdateTrigger(_updateTrigger);
|
||||
@ -39,16 +43,7 @@ namespace Artemis.Core.Services
|
||||
|
||||
public GraphicsDecorator GraphicsDecorator { get; private set; }
|
||||
|
||||
public IReadOnlyCollection<IRGBDevice> LoadedDevices
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_loadedDevices)
|
||||
{
|
||||
return _loadedDevices.AsReadOnly();
|
||||
}
|
||||
}
|
||||
}
|
||||
public IReadOnlyCollection<IRGBDevice> LoadedDevices => _loadedDevices.AsReadOnly();
|
||||
|
||||
public void AddDeviceProvider(IRGBDeviceProvider deviceProvider)
|
||||
{
|
||||
@ -56,23 +51,20 @@ namespace Artemis.Core.Services
|
||||
|
||||
if (deviceProvider.Devices == null)
|
||||
{
|
||||
_logger.Warning("Device provider {deviceProvider} has no devices", deviceProvider.GetType().Name);
|
||||
_logger.Warning("RgbDevice provider {deviceProvider} has no devices", deviceProvider.GetType().Name);
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_loadedDevices)
|
||||
foreach (var surfaceDevice in deviceProvider.Devices)
|
||||
{
|
||||
foreach (var surfaceDevice in deviceProvider.Devices)
|
||||
if (!_loadedDevices.Contains(surfaceDevice))
|
||||
{
|
||||
if (!_loadedDevices.Contains(surfaceDevice))
|
||||
{
|
||||
_loadedDevices.Add(surfaceDevice);
|
||||
OnDeviceLoaded(new DeviceEventArgs(surfaceDevice));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnDeviceReloaded(new DeviceEventArgs(surfaceDevice));
|
||||
}
|
||||
_loadedDevices.Add(surfaceDevice);
|
||||
OnDeviceLoaded(new DeviceEventArgs(surfaceDevice));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnDeviceReloaded(new DeviceEventArgs(surfaceDevice));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,6 +77,11 @@ namespace Artemis.Core.Services
|
||||
Surface.Dispose();
|
||||
}
|
||||
|
||||
private void RenderScaleSettingOnSettingChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateGraphicsDecorator();
|
||||
}
|
||||
|
||||
private void SurfaceOnException(ExceptionEventArgs args)
|
||||
{
|
||||
throw args.Exception;
|
||||
@ -108,7 +105,7 @@ namespace Artemis.Core.Services
|
||||
|
||||
// Apply the application wide brush and decorator
|
||||
_background = new ListLedGroup(Surface.Leds) {Brush = new SolidColorBrush(new Color(255, 255, 255, 255))};
|
||||
GraphicsDecorator = new GraphicsDecorator(_background, 0.25);
|
||||
GraphicsDecorator = new GraphicsDecorator(_background, _renderScaleSetting.Value);
|
||||
_background.Brush.RemoveAllDecorators();
|
||||
|
||||
_background.Brush.AddDecorator(GraphicsDecorator);
|
||||
|
||||
52
src/Artemis.Core/Services/SettingsService.cs
Normal file
52
src/Artemis.Core/Services/SettingsService.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using Artemis.Core.Services.Interfaces;
|
||||
using Artemis.Storage.Entities;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Artemis.Core.Services
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class SettingsService : ISettingsService
|
||||
{
|
||||
private readonly PluginInfo _buildInPluginInfo;
|
||||
private readonly IPluginSettingRepository _pluginSettingRepository;
|
||||
private readonly Dictionary<string, PluginSettingEntity> _settingEntities;
|
||||
|
||||
internal SettingsService(IPluginSettingRepository pluginSettingRepository)
|
||||
{
|
||||
_pluginSettingRepository = pluginSettingRepository;
|
||||
_buildInPluginInfo = new PluginInfo {Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core"};
|
||||
|
||||
_settingEntities = pluginSettingRepository.GetByPluginGuid(_buildInPluginInfo.Guid).ToDictionary(se => se.Name);
|
||||
}
|
||||
|
||||
public PluginSetting<T> GetSetting<T>(string name, T defaultValue = default(T))
|
||||
{
|
||||
lock (_settingEntities)
|
||||
{
|
||||
if (_settingEntities.ContainsKey(name))
|
||||
return new PluginSetting<T>(_buildInPluginInfo, _pluginSettingRepository, _settingEntities[name]);
|
||||
|
||||
var settingEntity = new PluginSettingEntity {Name = name, PluginGuid = _buildInPluginInfo.Guid, Value = JsonConvert.SerializeObject(defaultValue)};
|
||||
_pluginSettingRepository.Add(settingEntity);
|
||||
_pluginSettingRepository.Save();
|
||||
|
||||
_settingEntities.Add(name, settingEntity);
|
||||
return new PluginSetting<T>(_buildInPluginInfo, _pluginSettingRepository, _settingEntities[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>A wrapper around plugin settings for internal use.</para>
|
||||
/// <para>Do not inject into a plugin, for plugins inject <see cref="PluginSettings" /> instead.</para>
|
||||
/// </summary>
|
||||
public interface ISettingsService : IProtectedArtemisService
|
||||
{
|
||||
PluginSetting<T> GetSetting<T>(string name, T defaultValue = default(T));
|
||||
}
|
||||
}
|
||||
@ -9,43 +9,43 @@ namespace Artemis.Core.Services.Storage
|
||||
public interface ISurfaceService : IArtemisService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the currently active surface configuration, to change config use <see cref="SetActiveSurfaceConfiguration" />
|
||||
/// Gets the currently active surface entity, to change config use <see cref="SetActiveSurfaceConfiguration" />
|
||||
/// </summary>
|
||||
SurfaceConfiguration ActiveSurfaceConfiguration { get; }
|
||||
Surface ActiveSurface { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read-only list of all surface configurations
|
||||
/// </summary>
|
||||
ReadOnlyCollection<SurfaceConfiguration> SurfaceConfigurations { get; }
|
||||
ReadOnlyCollection<Surface> SurfaceConfigurations { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new surface configuration with the supplied name
|
||||
/// Creates a new surface entity with the supplied name
|
||||
/// </summary>
|
||||
/// <param name="name">The name for the new surface configuration</param>
|
||||
/// <param name="name">The name for the new surface entity</param>
|
||||
/// <returns></returns>
|
||||
SurfaceConfiguration CreateSurfaceConfiguration(string name);
|
||||
Surface CreateSurfaceConfiguration(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the provided configuration as active and applies it to the surface
|
||||
/// Sets the provided entity as active and applies it to the surface
|
||||
/// </summary>
|
||||
/// <param name="surfaceConfiguration">The configuration to activate and apply</param>
|
||||
void SetActiveSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration);
|
||||
/// <param name="surface">The entity to activate and apply</param>
|
||||
void SetActiveSurfaceConfiguration(Surface surface);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the provided surface configuration to permanent storage and if config is active, applies it to the surface
|
||||
/// Saves the provided surface entity to permanent storage and if config is active, applies it to the surface
|
||||
/// </summary>
|
||||
/// <param name="surfaceConfiguration">The configuration to save (and apply if active)</param>
|
||||
/// <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(SurfaceConfiguration surfaceConfiguration, bool includeDevices);
|
||||
void UpdateSurfaceConfiguration(Surface surface, bool includeDevices);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the supplied surface configuration, surface configuration may not be the active surface configuration
|
||||
/// Deletes the supplied surface entity, surface entity may not be the active surface entity
|
||||
/// </summary>
|
||||
/// <param name="surfaceConfiguration">The surface configuration to delete, may not be the active surface configuration</param>
|
||||
void DeleteSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration);
|
||||
/// <param name="surface">The surface entity to delete, may not be the active surface entity</param>
|
||||
void DeleteSurfaceConfiguration(Surface surface);
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the active device configuration has been changed
|
||||
/// Occurs when the active device entity has been changed
|
||||
/// </summary>
|
||||
event EventHandler<SurfaceConfigurationEventArgs> ActiveSurfaceConfigurationChanged;
|
||||
}
|
||||
|
||||
@ -4,7 +4,9 @@ using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Events;
|
||||
using Artemis.Core.Exceptions;
|
||||
using Artemis.Core.Extensions;
|
||||
using Artemis.Core.Models.Surface;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using Artemis.Core.Services.Interfaces;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using RGB.NET.Core;
|
||||
@ -16,45 +18,37 @@ namespace Artemis.Core.Services.Storage
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly List<SurfaceConfiguration> _surfaceConfigurations;
|
||||
private readonly List<Surface> _surfaceConfigurations;
|
||||
private readonly ISurfaceRepository _surfaceRepository;
|
||||
private readonly PluginSetting<double> _renderScaleSetting;
|
||||
|
||||
public SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService)
|
||||
internal SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, ISettingsService settingsService)
|
||||
{
|
||||
_logger = logger;
|
||||
_surfaceRepository = surfaceRepository;
|
||||
_rgbService = rgbService;
|
||||
_surfaceConfigurations = new List<SurfaceConfiguration>();
|
||||
_surfaceConfigurations = new List<Surface>();
|
||||
_renderScaleSetting = settingsService.GetSetting("RenderScale", 1.0);
|
||||
|
||||
LoadFromRepository();
|
||||
|
||||
_rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded;
|
||||
_renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged;
|
||||
}
|
||||
|
||||
public SurfaceConfiguration ActiveSurfaceConfiguration { get; private set; }
|
||||
|
||||
public ReadOnlyCollection<SurfaceConfiguration> SurfaceConfigurations
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_surfaceConfigurations)
|
||||
{
|
||||
return _surfaceConfigurations.AsReadOnly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SurfaceConfiguration CreateSurfaceConfiguration(string name)
|
||||
public Surface ActiveSurface { get; private set; }
|
||||
public ReadOnlyCollection<Surface> SurfaceConfigurations => _surfaceConfigurations.AsReadOnly();
|
||||
|
||||
public Surface CreateSurfaceConfiguration(string name)
|
||||
{
|
||||
// Create a blank config
|
||||
var configuration = new SurfaceConfiguration(name);
|
||||
var configuration = new Surface(_rgbService.Surface, name, _renderScaleSetting.Value);
|
||||
|
||||
// Add all current devices
|
||||
foreach (var rgbDevice in _rgbService.LoadedDevices)
|
||||
{
|
||||
var deviceId = GetDeviceId(rgbDevice);
|
||||
configuration.DeviceConfigurations.Add(new SurfaceDeviceConfiguration(rgbDevice, deviceId, configuration));
|
||||
}
|
||||
foreach (var rgbDevice in _rgbService.LoadedDevices)
|
||||
configuration.Devices.Add(new Device(rgbDevice, configuration));
|
||||
|
||||
lock (_surfaceConfigurations)
|
||||
{
|
||||
@ -64,67 +58,67 @@ namespace Artemis.Core.Services.Storage
|
||||
}
|
||||
}
|
||||
|
||||
public void SetActiveSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration)
|
||||
public void SetActiveSurfaceConfiguration(Surface surface)
|
||||
{
|
||||
if (ActiveSurfaceConfiguration == surfaceConfiguration)
|
||||
if (ActiveSurface == surface)
|
||||
return;
|
||||
|
||||
// Set the new configuration
|
||||
ActiveSurfaceConfiguration = surfaceConfiguration;
|
||||
// Set the new entity
|
||||
ActiveSurface = surface;
|
||||
|
||||
// Ensure only the new configuration is marked as active
|
||||
// Ensure only the new entity is marked as active
|
||||
lock (_surfaceConfigurations)
|
||||
{
|
||||
// Mark only the new surfaceConfiguration as active
|
||||
// Mark only the new surface as active
|
||||
foreach (var configuration in _surfaceConfigurations)
|
||||
{
|
||||
configuration.IsActive = configuration == ActiveSurfaceConfiguration;
|
||||
configuration.IsActive = configuration == ActiveSurface;
|
||||
configuration.ApplyToEntity();
|
||||
}
|
||||
|
||||
_surfaceRepository.Save();
|
||||
}
|
||||
|
||||
// Apply the active surface configuration to the devices
|
||||
if (ActiveSurfaceConfiguration != null)
|
||||
// Apply the active surface entity to the devices
|
||||
if (ActiveSurface != null)
|
||||
{
|
||||
foreach (var deviceConfiguration in ActiveSurfaceConfiguration.DeviceConfigurations)
|
||||
deviceConfiguration.ApplyToDevice();
|
||||
foreach (var device in ActiveSurface.Devices)
|
||||
device.ApplyToRgbDevice();
|
||||
}
|
||||
|
||||
// Update the RGB service's graphics decorator to work with the new surface configuration
|
||||
// Update the RGB service's graphics decorator to work with the new surface entity
|
||||
_rgbService.UpdateGraphicsDecorator();
|
||||
OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(ActiveSurfaceConfiguration));
|
||||
OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(ActiveSurface));
|
||||
}
|
||||
|
||||
public void UpdateSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration, bool includeDevices)
|
||||
public void UpdateSurfaceConfiguration(Surface surface, bool includeDevices)
|
||||
{
|
||||
surfaceConfiguration.ApplyToEntity();
|
||||
surface.ApplyToEntity();
|
||||
if (includeDevices)
|
||||
{
|
||||
foreach (var deviceConfiguration in surfaceConfiguration.DeviceConfigurations)
|
||||
foreach (var deviceConfiguration in surface.Devices)
|
||||
{
|
||||
deviceConfiguration.ApplyToEntity();
|
||||
if (surfaceConfiguration.IsActive)
|
||||
deviceConfiguration.ApplyToDevice();
|
||||
deviceConfiguration.ApplyToConfiguration();
|
||||
if (surface.IsActive)
|
||||
deviceConfiguration.ApplyToRgbDevice();
|
||||
}
|
||||
}
|
||||
|
||||
_surfaceRepository.Save();
|
||||
_rgbService.UpdateGraphicsDecorator();
|
||||
OnSurfaceConfigurationUpdated(new SurfaceConfigurationEventArgs(surfaceConfiguration));
|
||||
OnSurfaceConfigurationUpdated(new SurfaceConfigurationEventArgs(surface));
|
||||
}
|
||||
|
||||
public void DeleteSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration)
|
||||
public void DeleteSurfaceConfiguration(Surface surface)
|
||||
{
|
||||
if (surfaceConfiguration == ActiveSurfaceConfiguration)
|
||||
throw new ArtemisCoreException($"Cannot delete surface configuration '{surfaceConfiguration.Name}' because it is active.");
|
||||
if (surface == ActiveSurface)
|
||||
throw new ArtemisCoreException($"Cannot delete surface entity '{surface.Name}' because it is active.");
|
||||
|
||||
lock (_surfaceConfigurations)
|
||||
{
|
||||
var entity = surfaceConfiguration.SurfaceEntity;
|
||||
surfaceConfiguration.Destroy();
|
||||
_surfaceConfigurations.Remove(surfaceConfiguration);
|
||||
var entity = surface.SurfaceEntity;
|
||||
surface.Destroy();
|
||||
_surfaceConfigurations.Remove(surface);
|
||||
|
||||
_surfaceRepository.Remove(entity);
|
||||
_surfaceRepository.Save();
|
||||
@ -138,10 +132,17 @@ namespace Artemis.Core.Services.Storage
|
||||
lock (_surfaceConfigurations)
|
||||
{
|
||||
foreach (var surfaceConfiguration in _surfaceConfigurations)
|
||||
MatchDeviceConfiguration(e.Device, surfaceConfiguration);
|
||||
AddDeviceIfMissing(e.Device, surfaceConfiguration);
|
||||
}
|
||||
|
||||
UpdateSurfaceConfiguration(ActiveSurfaceConfiguration, true);
|
||||
UpdateSurfaceConfiguration(ActiveSurface, true);
|
||||
}
|
||||
|
||||
private void RenderScaleSettingOnSettingChanged(object sender, EventArgs e)
|
||||
{
|
||||
foreach (var surfaceConfiguration in SurfaceConfigurations)
|
||||
surfaceConfiguration.UpdateScale(_renderScaleSetting.Value);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -153,12 +154,9 @@ namespace Artemis.Core.Services.Storage
|
||||
var configs = _surfaceRepository.GetAll();
|
||||
foreach (var surfaceEntity in configs)
|
||||
{
|
||||
// Create the surface configuration
|
||||
var surfaceConfiguration = new SurfaceConfiguration(surfaceEntity);
|
||||
// For each loaded device, match a device configuration
|
||||
var devices = _rgbService.LoadedDevices;
|
||||
foreach (var rgbDevice in devices)
|
||||
MatchDeviceConfiguration(rgbDevice, surfaceConfiguration);
|
||||
// Create the surface entity
|
||||
var surfaceConfiguration = new Surface(_rgbService.Surface, surfaceEntity, _renderScaleSetting.Value);
|
||||
|
||||
// Finally, add the surface config to the collection
|
||||
lock (_surfaceConfigurations)
|
||||
{
|
||||
@ -170,39 +168,44 @@ namespace Artemis.Core.Services.Storage
|
||||
var 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 MatchDeviceConfiguration(IRGBDevice rgbDevice, SurfaceConfiguration surfaceConfiguration)
|
||||
private void AddDeviceIfMissing(IRGBDevice rgbDevice, Surface surface)
|
||||
{
|
||||
var deviceId = GetDeviceId(rgbDevice);
|
||||
var deviceConfig = surfaceConfiguration.DeviceConfigurations.FirstOrDefault(d => d.DeviceName == rgbDevice.DeviceInfo.DeviceName &&
|
||||
d.DeviceModel == rgbDevice.DeviceInfo.Model &&
|
||||
d.DeviceManufacturer == rgbDevice.DeviceInfo.Manufacturer &&
|
||||
d.DeviceId == deviceId);
|
||||
var deviceHashCode = rgbDevice.GetDeviceHashCode();
|
||||
var device = surface.Devices.FirstOrDefault(d => d.Configuration.DeviceHashCode == deviceHashCode);
|
||||
|
||||
if (deviceConfig == null)
|
||||
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);
|
||||
// Fall back on creating a new device
|
||||
else
|
||||
{
|
||||
_logger.Information("No active surface config found for {deviceInfo}, device ID: {deviceId}. Adding a new entry.", rgbDevice.DeviceInfo, deviceId);
|
||||
deviceConfig = new SurfaceDeviceConfiguration(rgbDevice, deviceId, surfaceConfiguration);
|
||||
surfaceConfiguration.DeviceConfigurations.Add(deviceConfig);
|
||||
_logger.Information(
|
||||
"No device config found for {deviceInfo}, device hash: {deviceHashCode}. Adding a new entry.",
|
||||
rgbDevice.DeviceInfo,
|
||||
deviceHashCode
|
||||
);
|
||||
device = new Device(rgbDevice, surface);
|
||||
}
|
||||
|
||||
deviceConfig.Device = rgbDevice;
|
||||
deviceConfig.ApplyToDevice();
|
||||
}
|
||||
|
||||
private int GetDeviceId(IRGBDevice rgbDevice)
|
||||
{
|
||||
return _rgbService.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;
|
||||
surface.Devices.Add(device);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using System.Drawing;
|
||||
using Artemis.Core.Models.Profile;
|
||||
using Artemis.Core.Models.Surface;
|
||||
using Artemis.Core.Plugins.Abstract;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using QRCoder;
|
||||
@ -31,7 +32,7 @@ namespace Artemis.Plugins.LayerTypes.Brush
|
||||
// Update the brush
|
||||
}
|
||||
|
||||
public override void Render(Layer device, RGBSurface surface, Graphics graphics)
|
||||
public override void Render(Layer device, Surface surface, Graphics graphics)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using Artemis.Core.Extensions;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Models.Surface;
|
||||
using Artemis.Core.Plugins.Abstract;
|
||||
using Artemis.Core.Plugins.Models;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Plugins.Modules.General.ViewModels;
|
||||
using RGB.NET.Core;
|
||||
using Stylet;
|
||||
using Color = System.Drawing.Color;
|
||||
using Rectangle = System.Drawing.Rectangle;
|
||||
|
||||
namespace Artemis.Plugins.Modules.General
|
||||
{
|
||||
@ -15,7 +14,7 @@ namespace Artemis.Plugins.Modules.General
|
||||
{
|
||||
private readonly PluginSettings _settings;
|
||||
|
||||
public GeneralModule(PluginInfo pluginInfo, PluginSettings settings) : base(pluginInfo)
|
||||
public GeneralModule(PluginInfo pluginInfo, PluginSettings settings, ISettingsService settingsService) : base(pluginInfo)
|
||||
{
|
||||
_settings = settings;
|
||||
DisplayName = "General";
|
||||
@ -44,7 +43,7 @@ namespace Artemis.Plugins.Modules.General
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(double deltaTime, RGBSurface surface, Graphics graphics)
|
||||
public override void Render(double deltaTime, Surface surface, Graphics graphics)
|
||||
{
|
||||
// Per-device coloring, slower
|
||||
// RenderPerDevice(surface, graphics);
|
||||
@ -53,11 +52,11 @@ namespace Artemis.Plugins.Modules.General
|
||||
RenderPerLed(surface, graphics);
|
||||
}
|
||||
|
||||
public void RenderFullSurface(RGBSurface surface, Graphics graphics)
|
||||
public void RenderFullSurface(Surface surface, Graphics graphics)
|
||||
{
|
||||
}
|
||||
|
||||
public void RenderPerDevice(RGBSurface surface, Graphics graphics)
|
||||
public void RenderPerDevice(Surface surface, Graphics graphics)
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var device in surface.Devices)
|
||||
@ -69,16 +68,15 @@ namespace Artemis.Plugins.Modules.General
|
||||
Colors[index] = color;
|
||||
}
|
||||
|
||||
var rectangle = new Rectangle((int) device.Location.X, (int) device.Location.Y, (int) device.Size.Width, (int) device.Size.Height);
|
||||
graphics.FillRectangle(new SolidBrush(color), rectangle);
|
||||
graphics.FillRectangle(new SolidBrush(color), device.RenderRectangle);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderPerLed(RGBSurface surface, Graphics graphics)
|
||||
public void RenderPerLed(Surface surface, Graphics graphics)
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var led in surface.Leds)
|
||||
foreach (var led in surface.Devices.SelectMany(d => d.Leds))
|
||||
{
|
||||
var color = Colors[index];
|
||||
if (color.A == 0)
|
||||
@ -87,8 +85,7 @@ namespace Artemis.Plugins.Modules.General
|
||||
Colors[index] = color;
|
||||
}
|
||||
|
||||
var rectangle = led.AbsoluteLedRectangle.ToDrawingRectangle(0.25);
|
||||
graphics.FillRectangle(new SolidBrush(color), rectangle);
|
||||
graphics.FillRectangle(new SolidBrush(color), led.AbsoluteRenderRectangle);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,16 +2,17 @@
|
||||
|
||||
namespace Artemis.Storage.Entities
|
||||
{
|
||||
public class SurfacePositionEntity
|
||||
public class DeviceEntity
|
||||
{
|
||||
public DeviceEntity()
|
||||
{
|
||||
Guid = System.Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
[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 int DeviceHashCode { get; set; }
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
public double Rotation { get; set; }
|
||||
@ -5,12 +5,17 @@ namespace Artemis.Storage.Entities
|
||||
{
|
||||
public class SurfaceEntity
|
||||
{
|
||||
public SurfaceEntity()
|
||||
{
|
||||
Guid = System.Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
[Key]
|
||||
public string Guid { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
public virtual ICollection<SurfacePositionEntity> SurfacePositions { get; set; }
|
||||
public virtual ICollection<DeviceEntity> DeviceEntities { get; set; }
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace Artemis.Storage.Migrations
|
||||
{
|
||||
[DbContext(typeof(StorageContext))]
|
||||
[Migration("20191013153102_InitialCreate")]
|
||||
[Migration("20191028171528_InitialCreate")]
|
||||
partial class InitialCreate
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@ -18,6 +18,30 @@ namespace Artemis.Storage.Migrations
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.DeviceEntity", b =>
|
||||
{
|
||||
b.Property<string>("Guid")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("DeviceHashCode");
|
||||
|
||||
b.Property<double>("Rotation");
|
||||
|
||||
b.Property<string>("SurfaceId");
|
||||
|
||||
b.Property<double>("X");
|
||||
|
||||
b.Property<double>("Y");
|
||||
|
||||
b.Property<int>("ZIndex");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.HasIndex("SurfaceId");
|
||||
|
||||
b.ToTable("DeviceEntity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.FolderEntity", b =>
|
||||
{
|
||||
b.Property<string>("Guid")
|
||||
@ -167,34 +191,11 @@ namespace Artemis.Storage.Migrations
|
||||
b.ToTable("Surfaces");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.SurfacePositionEntity", b =>
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.DeviceEntity", b =>
|
||||
{
|
||||
b.Property<string>("Guid")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("DeviceId");
|
||||
|
||||
b.Property<string>("DeviceManufacturer");
|
||||
|
||||
b.Property<string>("DeviceModel");
|
||||
|
||||
b.Property<string>("DeviceName");
|
||||
|
||||
b.Property<double>("Rotation");
|
||||
|
||||
b.Property<string>("SurfaceId");
|
||||
|
||||
b.Property<double>("X");
|
||||
|
||||
b.Property<double>("Y");
|
||||
|
||||
b.Property<int>("ZIndex");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.HasIndex("SurfaceId");
|
||||
|
||||
b.ToTable("SurfacePositionEntity");
|
||||
b.HasOne("Artemis.Storage.Entities.SurfaceEntity", "Surface")
|
||||
.WithMany("DeviceEntities")
|
||||
.HasForeignKey("SurfaceId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.FolderEntity", b =>
|
||||
@ -238,13 +239,6 @@ namespace Artemis.Storage.Migrations
|
||||
.WithMany()
|
||||
.HasForeignKey("RootFolderGuid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.SurfacePositionEntity", b =>
|
||||
{
|
||||
b.HasOne("Artemis.Storage.Entities.SurfaceEntity", "Surface")
|
||||
.WithMany("SurfacePositions")
|
||||
.HasForeignKey("SurfaceId");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
@ -107,14 +107,11 @@ namespace Artemis.Storage.Migrations
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SurfacePositionEntity",
|
||||
name: "DeviceEntity",
|
||||
columns: table => new
|
||||
{
|
||||
Guid = table.Column<string>(nullable: false),
|
||||
DeviceId = table.Column<int>(nullable: false),
|
||||
DeviceName = table.Column<string>(nullable: true),
|
||||
DeviceModel = table.Column<string>(nullable: true),
|
||||
DeviceManufacturer = table.Column<string>(nullable: true),
|
||||
DeviceHashCode = table.Column<int>(nullable: false),
|
||||
X = table.Column<double>(nullable: false),
|
||||
Y = table.Column<double>(nullable: false),
|
||||
Rotation = table.Column<double>(nullable: false),
|
||||
@ -123,9 +120,9 @@ namespace Artemis.Storage.Migrations
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SurfacePositionEntity", x => x.Guid);
|
||||
table.PrimaryKey("PK_DeviceEntity", x => x.Guid);
|
||||
table.ForeignKey(
|
||||
name: "FK_SurfacePositionEntity_Surfaces_SurfaceId",
|
||||
name: "FK_DeviceEntity_Surfaces_SurfaceId",
|
||||
column: x => x.SurfaceId,
|
||||
principalTable: "Surfaces",
|
||||
principalColumn: "Guid",
|
||||
@ -192,6 +189,11 @@ namespace Artemis.Storage.Migrations
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_DeviceEntity_SurfaceId",
|
||||
table: "DeviceEntity",
|
||||
column: "SurfaceId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Folders_FolderEntityGuid",
|
||||
table: "Folders",
|
||||
@ -221,15 +223,13 @@ namespace Artemis.Storage.Migrations
|
||||
name: "IX_Profiles_RootFolderGuid",
|
||||
table: "Profiles",
|
||||
column: "RootFolderGuid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SurfacePositionEntity_SurfaceId",
|
||||
table: "SurfacePositionEntity",
|
||||
column: "SurfaceId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "DeviceEntity");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Keypoints");
|
||||
|
||||
@ -246,14 +246,11 @@ namespace Artemis.Storage.Migrations
|
||||
name: "Settings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "SurfacePositionEntity");
|
||||
name: "Surfaces");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LayerSettings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Surfaces");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Layers");
|
||||
|
||||
@ -16,6 +16,30 @@ namespace Artemis.Storage.Migrations
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.DeviceEntity", b =>
|
||||
{
|
||||
b.Property<string>("Guid")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("DeviceHashCode");
|
||||
|
||||
b.Property<double>("Rotation");
|
||||
|
||||
b.Property<string>("SurfaceId");
|
||||
|
||||
b.Property<double>("X");
|
||||
|
||||
b.Property<double>("Y");
|
||||
|
||||
b.Property<int>("ZIndex");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.HasIndex("SurfaceId");
|
||||
|
||||
b.ToTable("DeviceEntity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.FolderEntity", b =>
|
||||
{
|
||||
b.Property<string>("Guid")
|
||||
@ -165,34 +189,11 @@ namespace Artemis.Storage.Migrations
|
||||
b.ToTable("Surfaces");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.SurfacePositionEntity", b =>
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.DeviceEntity", b =>
|
||||
{
|
||||
b.Property<string>("Guid")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("DeviceId");
|
||||
|
||||
b.Property<string>("DeviceManufacturer");
|
||||
|
||||
b.Property<string>("DeviceModel");
|
||||
|
||||
b.Property<string>("DeviceName");
|
||||
|
||||
b.Property<double>("Rotation");
|
||||
|
||||
b.Property<string>("SurfaceId");
|
||||
|
||||
b.Property<double>("X");
|
||||
|
||||
b.Property<double>("Y");
|
||||
|
||||
b.Property<int>("ZIndex");
|
||||
|
||||
b.HasKey("Guid");
|
||||
|
||||
b.HasIndex("SurfaceId");
|
||||
|
||||
b.ToTable("SurfacePositionEntity");
|
||||
b.HasOne("Artemis.Storage.Entities.SurfaceEntity", "Surface")
|
||||
.WithMany("DeviceEntities")
|
||||
.HasForeignKey("SurfaceId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.FolderEntity", b =>
|
||||
@ -236,13 +237,6 @@ namespace Artemis.Storage.Migrations
|
||||
.WithMany()
|
||||
.HasForeignKey("RootFolderGuid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Artemis.Storage.Entities.SurfacePositionEntity", b =>
|
||||
{
|
||||
b.HasOne("Artemis.Storage.Entities.SurfaceEntity", "Surface")
|
||||
.WithMany("SurfacePositions")
|
||||
.HasForeignKey("SurfaceId");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,22 +29,22 @@ namespace Artemis.Storage.Repositories
|
||||
|
||||
public SurfaceEntity Get(string name)
|
||||
{
|
||||
return _dbContext.Surfaces.Include(s => s.SurfacePositions).FirstOrDefault(p => p.Name == name);
|
||||
return _dbContext.Surfaces.Include(s => s.DeviceEntities).FirstOrDefault(p => p.Name == name);
|
||||
}
|
||||
|
||||
public async Task<SurfaceEntity> GetAsync(string name)
|
||||
{
|
||||
return await _dbContext.Surfaces.Include(s => s.SurfacePositions).FirstOrDefaultAsync(p => p.Name == name);
|
||||
return await _dbContext.Surfaces.Include(s => s.DeviceEntities).FirstOrDefaultAsync(p => p.Name == name);
|
||||
}
|
||||
|
||||
public List<SurfaceEntity> GetAll()
|
||||
{
|
||||
return _dbContext.Surfaces.Include(s => s.SurfacePositions).ToList();
|
||||
return _dbContext.Surfaces.Include(s => s.DeviceEntities).ToList();
|
||||
}
|
||||
|
||||
public async Task<List<SurfaceEntity>> GetAllAsync()
|
||||
{
|
||||
return await _dbContext.Surfaces.Include(s => s.SurfacePositions).ToListAsync();
|
||||
return await _dbContext.Surfaces.Include(s => s.DeviceEntities).ToListAsync();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
|
||||
@ -15,45 +15,45 @@ namespace Artemis.UI.ViewModels.Controls.SurfaceEditor
|
||||
private double _dragOffsetY;
|
||||
private readonly List<SurfaceLedViewModel> _leds;
|
||||
|
||||
public SurfaceDeviceViewModel(SurfaceDeviceConfiguration deviceConfiguration)
|
||||
public SurfaceDeviceViewModel(Device device)
|
||||
{
|
||||
DeviceConfiguration = deviceConfiguration;
|
||||
Device = device;
|
||||
_leds = new List<SurfaceLedViewModel>();
|
||||
|
||||
if (DeviceConfiguration.Device != null)
|
||||
if (Device.RgbDevice != null)
|
||||
{
|
||||
foreach (var led in DeviceConfiguration.Device)
|
||||
foreach (var led in Device.RgbDevice)
|
||||
_leds.Add(new SurfaceLedViewModel(led));
|
||||
}
|
||||
}
|
||||
|
||||
public SurfaceDeviceConfiguration DeviceConfiguration { get; set; }
|
||||
public Device Device { get; set; }
|
||||
public SelectionStatus SelectionStatus { get; set; }
|
||||
public Cursor Cursor { get; set; }
|
||||
|
||||
public double X
|
||||
{
|
||||
get => DeviceConfiguration.X;
|
||||
set => DeviceConfiguration.X = value;
|
||||
get => Device.X;
|
||||
set => Device.X = value;
|
||||
}
|
||||
|
||||
public double Y
|
||||
{
|
||||
get => DeviceConfiguration.Y;
|
||||
set => DeviceConfiguration.Y = value;
|
||||
get => Device.Y;
|
||||
set => Device.Y = value;
|
||||
}
|
||||
|
||||
public int ZIndex
|
||||
{
|
||||
get => DeviceConfiguration.ZIndex;
|
||||
set => DeviceConfiguration.ZIndex = value;
|
||||
get => Device.ZIndex;
|
||||
set => Device.ZIndex = value;
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<SurfaceLedViewModel> Leds => _leds.AsReadOnly();
|
||||
|
||||
public Rect DeviceRectangle => DeviceConfiguration.Device == null
|
||||
public Rect DeviceRectangle => Device.RgbDevice == null
|
||||
? new Rect()
|
||||
: new Rect(X, Y, DeviceConfiguration.Device.Size.Width, DeviceConfiguration.Device.Size.Height);
|
||||
: new Rect(X, Y, Device.RgbDevice.Size.Width, Device.RgbDevice.Size.Height);
|
||||
|
||||
public void StartMouseDrag(Point mouseStartPosition)
|
||||
{
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Artemis.Core.Events;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Core.Services.Interfaces;
|
||||
using Artemis.UI.ViewModels.Controls.Settings;
|
||||
using Artemis.UI.ViewModels.Interfaces;
|
||||
@ -12,7 +13,7 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
private readonly IKernel _kernel;
|
||||
private readonly IWindowManager _windowManager;
|
||||
|
||||
public SettingsViewModel(IKernel kernel, IRgbService rgbService, IWindowManager windowManager)
|
||||
public SettingsViewModel(IKernel kernel, IRgbService rgbService, IWindowManager windowManager, ISettingsService settingsService)
|
||||
{
|
||||
_kernel = kernel;
|
||||
_windowManager = windowManager;
|
||||
|
||||
@ -25,7 +25,7 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
public SurfaceEditorViewModel(ISurfaceService surfaceService, IDialogService dialogService)
|
||||
{
|
||||
Devices = new ObservableCollection<SurfaceDeviceViewModel>();
|
||||
SurfaceConfigurations = new ObservableCollection<SurfaceConfiguration>();
|
||||
SurfaceConfigurations = new ObservableCollection<Surface>();
|
||||
SelectionRectangle = new RectangleGeometry();
|
||||
PanZoomViewModel = new PanZoomViewModel();
|
||||
|
||||
@ -35,14 +35,14 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
|
||||
public RectangleGeometry SelectionRectangle { get; set; }
|
||||
public ObservableCollection<SurfaceDeviceViewModel> Devices { get; set; }
|
||||
public ObservableCollection<SurfaceConfiguration> SurfaceConfigurations { get; set; }
|
||||
public ObservableCollection<Surface> SurfaceConfigurations { get; set; }
|
||||
|
||||
public SurfaceConfiguration SelectedSurfaceConfiguration
|
||||
public Surface SelectedSurface
|
||||
{
|
||||
get => _selectedSurfaceConfiguration;
|
||||
get => _selectedSurface;
|
||||
set
|
||||
{
|
||||
_selectedSurfaceConfiguration = value;
|
||||
_selectedSurface = value;
|
||||
ApplySelectedSurfaceConfiguration();
|
||||
}
|
||||
}
|
||||
@ -50,7 +50,7 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
public PanZoomViewModel PanZoomViewModel { get; set; }
|
||||
public string Title => "Surface Editor";
|
||||
|
||||
public SurfaceConfiguration CreateSurfaceConfiguration(string name)
|
||||
public Surface CreateSurfaceConfiguration(string name)
|
||||
{
|
||||
var config = _surfaceService.CreateSurfaceConfiguration(name);
|
||||
Execute.OnUIThread(() => SurfaceConfigurations.Add(config));
|
||||
@ -63,7 +63,7 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
var configs = _surfaceService.SurfaceConfigurations;
|
||||
|
||||
// Get the active config, if empty, create a default config
|
||||
var activeConfig = _surfaceService.ActiveSurfaceConfiguration;
|
||||
var activeConfig = _surfaceService.ActiveSurface;
|
||||
if (activeConfig == null)
|
||||
{
|
||||
activeConfig = CreateSurfaceConfiguration("Default");
|
||||
@ -78,31 +78,31 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
SurfaceConfigurations.Add(surfaceConfiguration);
|
||||
|
||||
// Set the active config
|
||||
SelectedSurfaceConfiguration = activeConfig;
|
||||
SelectedSurface = activeConfig;
|
||||
});
|
||||
}
|
||||
|
||||
private void ApplySelectedSurfaceConfiguration()
|
||||
{
|
||||
if (SelectedSurfaceConfiguration == null)
|
||||
if (SelectedSurface == null)
|
||||
{
|
||||
Execute.OnUIThread(Devices.Clear);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure all devices have an up-to-date VM
|
||||
foreach (var surfaceDeviceConfiguration in SelectedSurfaceConfiguration.DeviceConfigurations)
|
||||
foreach (var surfaceDeviceConfiguration in SelectedSurface.Devices)
|
||||
{
|
||||
// Create VMs for missing devices
|
||||
var viewModel = Devices.FirstOrDefault(vm => vm.DeviceConfiguration.Device == surfaceDeviceConfiguration.Device);
|
||||
var viewModel = Devices.FirstOrDefault(vm => vm.Device.RgbDevice == surfaceDeviceConfiguration.RgbDevice);
|
||||
if (viewModel == null)
|
||||
Execute.OnUIThread(() => Devices.Add(new SurfaceDeviceViewModel(surfaceDeviceConfiguration)));
|
||||
// Update existing devices
|
||||
else
|
||||
viewModel.DeviceConfiguration = surfaceDeviceConfiguration;
|
||||
viewModel.Device = surfaceDeviceConfiguration;
|
||||
}
|
||||
|
||||
_surfaceService.SetActiveSurfaceConfiguration(SelectedSurfaceConfiguration);
|
||||
_surfaceService.SetActiveSurfaceConfiguration(SelectedSurface);
|
||||
}
|
||||
|
||||
#region Overrides of Screen
|
||||
@ -117,7 +117,7 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
|
||||
#region Configuration management
|
||||
|
||||
public async Task DeleteSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration)
|
||||
public async Task DeleteSurfaceConfiguration(Surface surface)
|
||||
{
|
||||
var result = await _dialogService.ShowConfirmDialogAt(
|
||||
"SurfaceListDialogHost",
|
||||
@ -126,8 +126,8 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
);
|
||||
if (result)
|
||||
{
|
||||
SurfaceConfigurations.Remove(surfaceConfiguration);
|
||||
_surfaceService.DeleteSurfaceConfiguration(surfaceConfiguration);
|
||||
SurfaceConfigurations.Remove(surface);
|
||||
_surfaceService.DeleteSurfaceConfiguration(surface);
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,11 +189,11 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
|
||||
#endregion
|
||||
|
||||
#region Device selection
|
||||
#region RgbDevice selection
|
||||
|
||||
private MouseDragStatus _mouseDragStatus;
|
||||
private Point _mouseDragStartPoint;
|
||||
private SurfaceConfiguration _selectedSurfaceConfiguration;
|
||||
private Surface _selectedSurface;
|
||||
|
||||
// ReSharper disable once UnusedMember.Global - Called from view
|
||||
public void EditorGridMouseClick(object sender, MouseEventArgs e)
|
||||
@ -280,7 +280,7 @@ namespace Artemis.UI.ViewModels.Screens
|
||||
}
|
||||
}
|
||||
else
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurfaceConfiguration, true);
|
||||
_surfaceService.UpdateSurfaceConfiguration(SelectedSurface, true);
|
||||
|
||||
Mouse.OverrideCursor = null;
|
||||
_mouseDragStatus = MouseDragStatus.None;
|
||||
|
||||
@ -13,20 +13,20 @@
|
||||
Cursor="{Binding Cursor}"
|
||||
MouseEnter="{s:Action MouseEnter}"
|
||||
MouseLeave="{s:Action MouseLeave}"
|
||||
ToolTip="{Binding DeviceConfiguration.Device.DeviceInfo.DeviceName}">
|
||||
ToolTip="{Binding Device.RgbDevice.DeviceInfo.DeviceName}">
|
||||
<UserControl.Resources>
|
||||
<converters:NullToImageConverter x:Key="NullToImageConverter"/>
|
||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Image Source="{Binding DeviceConfiguration.Device.DeviceInfo.Image, Converter={StaticResource NullToImageConverter}}" />
|
||||
<Image Source="{Binding Device.RgbDevice.DeviceInfo.Image, Converter={StaticResource NullToImageConverter}}" />
|
||||
|
||||
<Rectangle Fill="{DynamicResource ControlBackgroundBrush}"
|
||||
Stroke="{DynamicResource ControlBorderBrush}"
|
||||
StrokeThickness="1"
|
||||
Visibility="{Binding DeviceConfiguration.Device.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}" />
|
||||
<TextBlock Text="{Binding DeviceConfiguration.Device.DeviceInfo.DeviceName}"
|
||||
Visibility="{Binding DeviceConfiguration.Device.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
|
||||
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}" />
|
||||
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}"
|
||||
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
|
||||
@ -17,37 +17,40 @@
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<StackPanel Margin="16">
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}">General</TextBlock>
|
||||
<StackPanel>
|
||||
<TextBlock>General settings like start up with Windows etc.</TextBlock>
|
||||
<ScrollViewer>
|
||||
<StackPanel Margin="16">
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}">General</TextBlock>
|
||||
<StackPanel>
|
||||
<TextBlock>General settings like start up with Windows etc.</TextBlock>
|
||||
|
||||
<Button Command="{s:Action ShowDebugger}" Style="{StaticResource MaterialDesignRaisedButton}" HorizontalAlignment="Left" Margin="0, 10, 0, 0">
|
||||
Show debugger
|
||||
</Button>
|
||||
<Button Command="{s:Action ShowDebugger}" Style="{StaticResource MaterialDesignRaisedButton}" HorizontalAlignment="Left" Margin="0, 10, 0, 0">
|
||||
Show debugger
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}">Devices</TextBlock>
|
||||
|
||||
<TextBlock>A list of devices and options to disable them</TextBlock>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="0 12 0 0">
|
||||
<ItemsControl ItemsSource="{Binding DeviceSettingsViewModels}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ContentControl xaml:View.Model="{Binding}" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Top" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}">Plugins</TextBlock>
|
||||
<Grid>
|
||||
<TextBlock>A list of plugins and options to disable them</TextBlock>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}">Devices</TextBlock>
|
||||
|
||||
<TextBlock>A list of devices and options to disable them</TextBlock>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="0 12 0 0">
|
||||
<ItemsControl ItemsSource="{Binding DeviceSettingsViewModels}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ContentControl xaml:View.Model="{Binding}" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Top" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadlineTextBlock}">Plugins</TextBlock>
|
||||
<Grid>
|
||||
<TextBlock>A list of plugins and options to disable them</TextBlock>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</UserControl>
|
||||
@ -108,8 +108,8 @@
|
||||
</ItemsControl.ItemContainerStyle>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ContentControl Width="{Binding DeviceConfiguration.Device.Size.Width}"
|
||||
Height="{Binding DeviceConfiguration.Device.Size.Height}"
|
||||
<ContentControl Width="{Binding Device.RgbDevice.Size.Width}"
|
||||
Height="{Binding Device.RgbDevice.Size.Height}"
|
||||
s:View.Model="{Binding}">
|
||||
<ContentControl.ContextMenu>
|
||||
<ContextMenu>
|
||||
@ -183,9 +183,9 @@
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ListBox Grid.Row="0" ItemsSource="{Binding SurfaceConfigurations}" SelectedItem="{Binding SelectedSurfaceConfiguration}">
|
||||
<ListBox Grid.Row="0" ItemsSource="{Binding SurfaceConfigurations}" SelectedItem="{Binding SelectedSurface}">
|
||||
<ListBox.Resources>
|
||||
<DataTemplate DataType="{x:Type models:SurfaceConfiguration}">
|
||||
<DataTemplate DataType="{x:Type models:Surface}">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="230"/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user