1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Redid some of the surface editor and started working on layout saving

This commit is contained in:
SpoinkyNL 2019-09-18 22:26:10 +02:00
parent 81294eef8f
commit 71f53c0833
48 changed files with 1012 additions and 107 deletions

View File

@ -55,11 +55,15 @@
<Reference Include="AppDomainToolkit, Version=1.0.4.1, Culture=neutral, PublicKeyToken=f2fc7ab5180cf5c4, processorArchitecture=MSIL">
<HintPath>..\packages\AppDomainToolkit.1.0.4.3\lib\net\AppDomainToolkit.dll</HintPath>
</Reference>
<Reference Include="Ben.Demystifier, Version=0.1.0.0, Culture=neutral, PublicKeyToken=a6d206e05440431a, processorArchitecture=MSIL">
<HintPath>..\packages\Ben.Demystifier.0.1.4\lib\net45\Ben.Demystifier.dll</HintPath>
</Reference>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Ninject, Version=3.3.4.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
<HintPath>..\packages\Ninject.3.3.4\lib\net45\Ninject.dll</HintPath>
@ -90,17 +94,44 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\RGB.NET\bin\net45\RGB.NET.Groups.dll</HintPath>
</Reference>
<Reference Include="Stylet, Version=1.1.22.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Stylet.1.1.22\lib\net45\Stylet.dll</HintPath>
<Reference Include="Serilog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.2.8.0\lib\net46\Serilog.dll</HintPath>
</Reference>
<Reference Include="Serilog.Enrichers.Demystify, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.Enrichers.Demystify.1.0.0-dev-00019\lib\net45\Serilog.Enrichers.Demystify.dll</HintPath>
</Reference>
<Reference Include="Serilog.Sinks.File, Version=2.0.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\packages\Serilog.Sinks.File.4.0.0\lib\net45\Serilog.Sinks.File.dll</HintPath>
</Reference>
<Reference Include="Stylet, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Stylet.1.2.0\lib\net45\Stylet.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Collections.Immutable, Version=1.2.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.6.0-preview8.19405.3\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.3.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.4.5.1\lib\net46\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.6.0-preview5.19224.8\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Reflection.Metadata, Version=1.4.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Reflection.Metadata.1.7.0-preview8.19405.3\lib\netstandard2.0\System.Reflection.Metadata.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0-preview8.19405.3\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
</Reference>
@ -118,6 +149,9 @@
<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="Ninject\LoggerProvider.cs" />
<Compile Include="Ninject\PluginSettingsProvider.cs" />
<Compile Include="Plugins\Abstract\ModuleDataModel.cs" />
<Compile Include="Plugins\Abstract\ModuleViewModel.cs" />
@ -132,10 +166,10 @@
<Compile Include="Plugins\Models\PluginInfo.cs" />
<Compile Include="Plugins\Models\PluginSetting.cs" />
<Compile Include="Plugins\Models\PluginSettings.cs" />
<Compile Include="ProfileElements\Folder.cs" />
<Compile Include="ProfileElements\Interfaces\IProfileElement.cs" />
<Compile Include="ProfileElements\Layer.cs" />
<Compile Include="ProfileElements\Profile.cs" />
<Compile Include="Models\Profile\Folder.cs" />
<Compile Include="Models\Profile\Interfaces\IProfileElement.cs" />
<Compile Include="Models\Profile\Layer.cs" />
<Compile Include="Models\Profile\Profile.cs" />
<Compile Include="Ninject\CoreModule.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RGB.NET\DirectBitmap.cs" />
@ -151,6 +185,7 @@
<Compile Include="Events\PluginEventArgs.cs" />
<Compile Include="Services\PluginService.cs" />
<Compile Include="Services\StorageService.cs" />
<Compile Include="Services\Storage\SurfaceService.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
@ -162,5 +197,8 @@
<Name>Artemis.Storage</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="ProfileElements\Interfaces\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,60 @@
using System.Collections.Generic;
using System.Drawing;
using Artemis.Core.Models.Profile.Interfaces;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Entities;
using RGB.NET.Core;
namespace Artemis.Core.Models.Profile
{
public class Folder : IProfileElement
{
public Folder(Profile profile)
{
Profile = profile;
Children = new List<IProfileElement>();
}
public Profile Profile { get; }
public List<IProfileElement> Children { get; set; }
public int Order { get; set; }
public string Name { get; set; }
public void Update(double deltaTime)
{
// Folders don't update but their children do
foreach (var profileElement in Children)
profileElement.Update(deltaTime);
}
public void Render(double deltaTime, RGBSurface surface, Graphics graphics)
{
// Folders don't render but their children do
foreach (var profileElement in Children)
profileElement.Render(deltaTime, surface, graphics);
}
public static Folder FromFolderEntity(Profile profile, FolderEntity folderEntity, IPluginService pluginService)
{
var folder = new Folder(profile)
{
Name = folderEntity.Name,
Order = folderEntity.Order
};
// Load child folders
foreach (var childFolder in folderEntity.Folders)
folder.Children.Add(FromFolderEntity(profile, childFolder, pluginService));
// Load child layers
foreach (var childLayer in folderEntity.Layers)
folder.Children.Add(Layer.FromLayerEntity(profile, childLayer, pluginService));
return folder;
}
public override string ToString()
{
return $"{nameof(Profile)}: {Profile}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}";
}
}
}

View File

@ -0,0 +1,35 @@
using System.Collections.Generic;
using System.Drawing;
using RGB.NET.Core;
namespace Artemis.Core.Models.Profile.Interfaces
{
public interface IProfileElement
{
/// <summary>
/// The element's children
/// </summary>
List<IProfileElement> Children { get; set; }
/// <summary>
/// The order in which this element appears in the update loop and editor
/// </summary>
int Order { get; set; }
/// <summary>
/// The name which appears in the editor
/// </summary>
string Name { get; set; }
/// <summary>
/// Updates the element
/// </summary>
/// <param name="deltaTime"></param>
void Update(double deltaTime);
/// <summary>
/// Renders the element
/// </summary>
void Render(double deltaTime, RGBSurface surface, Graphics graphics);
}
}

View File

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using Artemis.Core.Models.Profile.Interfaces;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.Interfaces;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Entities;
using RGB.NET.Core;
namespace Artemis.Core.Models.Profile
{
public class Layer : IProfileElement
{
public Layer(Profile profile)
{
Profile = profile;
Children = new List<IProfileElement>();
}
public Profile Profile { get; }
public LayerType LayerType { get; private set; }
public ILayerTypeConfiguration LayerTypeConfiguration { get; set; }
public List<IProfileElement> Children { get; set; }
public int Order { get; set; }
public string Name { get; set; }
public void Update(double deltaTime)
{
if (LayerType == null)
return;
lock (LayerType)
{
LayerType.Update(this);
}
}
public void Render(double deltaTime, RGBSurface surface, Graphics graphics)
{
if (LayerType == null)
return;
lock (LayerType)
{
LayerType.Render(this, surface, graphics);
}
}
public static Layer FromLayerEntity(Profile profile, LayerEntity layerEntity, IPluginService pluginService)
{
var layer = new Layer(profile)
{
Name = layerEntity.Name,
Order = layerEntity.Order,
LayerType = pluginService.GetLayerTypeByGuid(Guid.Parse(layerEntity.Guid))
};
return layer;
}
public void UpdateLayerType(LayerType layerType)
{
if (LayerType != null)
{
lock (LayerType)
{
LayerType.Dispose();
}
}
LayerType = layerType;
}
public override string ToString()
{
return $"{nameof(Profile)}: {Profile}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}";
}
}
}

View File

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using Artemis.Core.Exceptions;
using Artemis.Core.Models.Profile.Interfaces;
using Artemis.Core.Plugins.Models;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Entities;
using RGB.NET.Core;
namespace Artemis.Core.Models.Profile
{
public class Profile : IProfileElement
{
private Profile(PluginInfo pluginInfo)
{
PluginInfo = pluginInfo;
}
public PluginInfo PluginInfo { get; }
public bool IsActivated { get; private set; }
public int Order { get; set; }
public string Name { get; set; }
public List<IProfileElement> Children { get; set; }
public void Update(double deltaTime)
{
lock (this)
{
if (!IsActivated)
throw new ArtemisCoreException($"Cannot update inactive profile: {this}");
foreach (var profileElement in Children)
profileElement.Update(deltaTime);
}
}
public void Render(double deltaTime, RGBSurface surface, Graphics graphics)
{
lock (this)
{
if (!IsActivated)
throw new ArtemisCoreException($"Cannot render inactive profile: {this}");
foreach (var profileElement in Children)
profileElement.Render(deltaTime, surface, graphics);
}
}
public static Profile FromProfileEntity(PluginInfo pluginInfo, ProfileEntity profileEntity, IPluginService pluginService)
{
var profile = new Profile(pluginInfo) {Name = profileEntity.Name};
lock (profile)
{
// Populate the profile starting at the root, the rest is populated recursively
profile.Children.Add(Folder.FromFolderEntity(profile, profileEntity.RootFolder, pluginService));
return profile;
}
}
public void Activate()
{
lock (this)
{
if (IsActivated) return;
OnActivated();
IsActivated = true;
}
}
public void Deactivate()
{
lock (this)
{
if (!IsActivated) return;
IsActivated = false;
OnDeactivated();
}
}
public override string ToString()
{
return $"{nameof(Order)}: {Order}, {nameof(Name)}: {Name}, {nameof(PluginInfo)}: {PluginInfo}";
}
#region Events
/// <summary>
/// Occurs when the profile is being activated.
/// </summary>
public event EventHandler Activated;
/// <summary>
/// Occurs when the profile is being deactivated.
/// </summary>
public event EventHandler Deactivated;
private void OnActivated()
{
Activated?.Invoke(this, EventArgs.Empty);
}
private void OnDeactivated()
{
Deactivated?.Invoke(this, EventArgs.Empty);
}
#endregion
}
}

View File

@ -0,0 +1,32 @@
using System.Collections.Generic;
using Artemis.Storage.Entities;
namespace Artemis.Core.Models.Surface
{
public class SurfaceConfiguration
{
public SurfaceConfiguration(string name)
{
Name = name;
DeviceConfigurations = new List<SurfaceDeviceConfiguration>();
}
internal SurfaceConfiguration(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 string Guid { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public List<SurfaceDeviceConfiguration> DeviceConfigurations { get; set; }
}
}

View File

@ -0,0 +1,47 @@
using Artemis.Storage.Entities;
using RGB.NET.Core;
namespace Artemis.Core.Models.Surface
{
public class SurfaceDeviceConfiguration
{
internal SurfaceDeviceConfiguration(int deviceId, IRGBDeviceInfo deviceInfo, SurfaceConfiguration surface)
{
DeviceId = deviceId;
DeviceName = deviceInfo.DeviceName;
DeviceModel = deviceInfo.Model;
DeviceManufacturer = deviceInfo.Manufacturer;
Surface = surface;
}
internal SurfaceDeviceConfiguration(SurfacePositionEntity position, SurfaceConfiguration surfaceConfiguration)
{
Guid = position.Guid;
DeviceId = position.DeviceId;
DeviceName = position.DeviceName;
DeviceModel = position.DeviceModel;
DeviceManufacturer = position.DeviceManufacturer;
X = position.X;
Y = position.Y;
Rotation = position.Rotation;
Surface = surfaceConfiguration;
}
internal string Guid { get; set; }
public int DeviceId { get; set; }
public string DeviceName { get; set; }
public string DeviceModel { get; set; }
public string DeviceManufacturer { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Rotation { get; set; }
public SurfaceConfiguration Surface { get; internal set; }
}
}

View File

@ -1,8 +1,10 @@
using Artemis.Core.Plugins.Models;
using Artemis.Core.Exceptions;
using Artemis.Core.Plugins.Models;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Repositories;
using Artemis.Storage.Repositories.Interfaces;
using Ninject.Extensions.Conventions;
using Ninject.Modules;
using Serilog;
namespace Artemis.Core.Ninject
{
@ -10,6 +12,9 @@ namespace Artemis.Core.Ninject
{
public override void Load()
{
if (Kernel == null)
throw new ArtemisCoreException("Failed to bind Ninject Core module, kernel is null.");
// Bind all services as singletons
Kernel.Bind(x =>
{
@ -31,6 +36,7 @@ namespace Artemis.Core.Ninject
});
Kernel.Bind<PluginSettings>().ToProvider<PluginSettingsProvider>();
Kernel.Bind<ILogger>().ToProvider<LoggerProvider>();
}
}
}

View File

@ -0,0 +1,25 @@
using Ninject.Activation;
using Serilog;
namespace Artemis.Core.Ninject
{
internal class LoggerProvider : Provider<ILogger>
{
private static readonly ILogger _logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithDemystifiedStackTraces()
.WriteTo.File("Artemis log-.txt",
rollingInterval: RollingInterval.Day,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext:l}] {Message:lj}{NewLine}{Exception}")
.CreateLogger();
protected override ILogger CreateInstance(IContext context)
{
var requestingType = context.Request.ParentContext?.Plan?.Type;
if (requestingType != null)
return _logger.ForContext(requestingType);
return _logger;
}
}
}

View File

@ -2,7 +2,7 @@
using Artemis.Core.Exceptions;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.Models;
using Artemis.Storage.Repositories;
using Artemis.Storage.Repositories.Interfaces;
using Ninject.Activation;
namespace Artemis.Core.Ninject

View File

@ -1,6 +1,6 @@
using System.Drawing;
using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Models;
using Artemis.Core.ProfileElements;
using RGB.NET.Core;
namespace Artemis.Core.Plugins.Abstract

View File

@ -1,7 +1,7 @@
using System;
using System.Drawing;
using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Models;
using Artemis.Core.ProfileElements;
using RGB.NET.Core;
namespace Artemis.Core.Plugins.Abstract

View File

@ -1,6 +1,7 @@
using System.Threading.Tasks;
using Artemis.Storage.Entities;
using Artemis.Storage.Repositories;
using Artemis.Storage.Repositories.Interfaces;
using Newtonsoft.Json;
namespace Artemis.Core.Plugins.Models

View File

@ -2,6 +2,7 @@
using System.Linq;
using Artemis.Storage.Entities;
using Artemis.Storage.Repositories;
using Artemis.Storage.Repositories.Interfaces;
using Newtonsoft.Json;
namespace Artemis.Core.Plugins.Models

View File

@ -4,6 +4,7 @@ using Artemis.Core.Exceptions;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Services.Interfaces;
using RGB.NET.Core;
using Serilog;
using Color = System.Drawing.Color;
namespace Artemis.Core.Services
@ -13,11 +14,13 @@ namespace Artemis.Core.Services
/// </summary>
public class CoreService : ICoreService
{
private readonly ILogger _logger;
private readonly IPluginService _pluginService;
private readonly IRgbService _rgbService;
internal CoreService(IPluginService pluginService, IRgbService rgbService)
internal CoreService(ILogger logger, IPluginService pluginService, IRgbService rgbService)
{
_logger = logger;
_pluginService = pluginService;
_rgbService = rgbService;
_rgbService.Surface.Updating += SurfaceOnUpdating;
@ -38,6 +41,8 @@ namespace Artemis.Core.Services
if (IsInitialized)
throw new ArtemisCoreException("Cannot initialize the core as it is already initialized.");
_logger.Information("Initializing Artemis Core version {version}", typeof(CoreService).Assembly.GetName().Version);
// Initialize the services
await Task.Run(() => _pluginService.CopyBuiltInPlugins());
await Task.Run(() => _pluginService.LoadPlugins());

View File

@ -1,13 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Core.Events;
using Artemis.Core.Models.Surface;
using Artemis.Core.RGB.NET;
using Artemis.Core.Services.Interfaces;
using Artemis.Core.Services.Storage;
using Artemis.Storage.Entities;
using RGB.NET.Brushes;
using RGB.NET.Core;
using RGB.NET.Groups;
using Serilog;
namespace Artemis.Core.Services
{
@ -17,10 +20,14 @@ namespace Artemis.Core.Services
public class RgbService : IRgbService, IDisposable
{
private readonly List<IRGBDevice> _loadedDevices;
private readonly ILogger _logger;
private readonly ISurfaceService _surfaceService;
private readonly TimerUpdateTrigger _updateTrigger;
internal RgbService()
internal RgbService(ILogger logger, ISurfaceService surfaceService)
{
_logger = logger;
_surfaceService = surfaceService;
Surface = RGBSurface.Instance;
LoadingDevices = false;
@ -33,7 +40,7 @@ namespace Artemis.Core.Services
}
/// <inheritdoc />
public bool LoadingDevices { get; private set; }
public bool LoadingDevices { get; }
/// <inheritdoc />
public RGBSurface Surface { get; set; }
@ -43,9 +50,17 @@ namespace Artemis.Core.Services
public void AddDeviceProvider(IRGBDeviceProvider deviceProvider)
{
Surface.LoadDevices(deviceProvider);
if (deviceProvider.Devices == null)
{
_logger.Warning("Device provider {deviceProvider} has no devices", deviceProvider.GetType().Name);
return;
}
// Get the currently active surface configuration
var surface = _surfaceService.GetActiveSurfaceConfiguration();
if (surface == null)
_logger.Information("No active surface configuration found, not positioning device");
lock (_loadedDevices)
{
@ -54,10 +69,16 @@ namespace Artemis.Core.Services
if (!_loadedDevices.Contains(surfaceDevice))
{
_loadedDevices.Add(surfaceDevice);
if (surface != null)
ApplyDeviceConfiguration(surfaceDevice, surface);
OnDeviceLoaded(new DeviceEventArgs(surfaceDevice));
}
else
{
if (surface != null)
ApplyDeviceConfiguration(surfaceDevice, surface);
OnDeviceReloaded(new DeviceEventArgs(surfaceDevice));
}
}
}
@ -75,6 +96,31 @@ namespace Artemis.Core.Services
Surface.Dispose();
}
public void ApplyDeviceConfiguration(IRGBDevice rgbDevice, SurfaceConfiguration surface)
{
// Determine the device ID by assuming devices are always added to the loaded devices list in the same order
lock (_loadedDevices)
{
var deviceId = _loadedDevices.Where(d => d.DeviceInfo.DeviceName == rgbDevice.DeviceInfo.DeviceName &&
d.DeviceInfo.Model == rgbDevice.DeviceInfo.Model &&
d.DeviceInfo.Manufacturer == rgbDevice.DeviceInfo.Manufacturer)
.ToList()
.IndexOf(rgbDevice) + 1;
var deviceConfig = surface.DeviceConfigurations.FirstOrDefault(d => d.DeviceName == rgbDevice.DeviceInfo.DeviceName &&
d.DeviceModel == rgbDevice.DeviceInfo.Model &&
d.DeviceManufacturer == rgbDevice.DeviceInfo.Manufacturer &&
d.DeviceId == deviceId);
if (deviceConfig == null)
{
_logger.Information("No surface device config found for {deviceInfo}, device ID: {deviceId}", rgbDevice.DeviceInfo, deviceId);
return;
}
rgbDevice.Location = new Point(deviceConfig.X, deviceConfig.Y);
}
}
private void SurfaceOnException(ExceptionEventArgs args)
{
throw args.Exception;

View File

@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Core.Models.Surface;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Repositories.Interfaces;
namespace Artemis.Core.Services.Storage
{
public class SurfaceService : ISurfaceService
{
private readonly ISurfaceRepository _surfaceRepository;
public SurfaceService(ISurfaceRepository surfaceRepository)
{
_surfaceRepository = surfaceRepository;
}
public async Task<List<SurfaceConfiguration>> GetSurfaceConfigurations()
{
var surfaceEntities = await _surfaceRepository.GetAllAsync();
var configs = new List<SurfaceConfiguration>();
foreach (var surfaceEntity in surfaceEntities)
configs.Add(new SurfaceConfiguration(surfaceEntity));
return configs;
}
public SurfaceConfiguration GetActiveSurfaceConfiguration()
{
var entity = _surfaceRepository.GetAll().FirstOrDefault(d => d.IsActive);
return entity != null ? new SurfaceConfiguration(entity) : null;
}
}
public interface ISurfaceService : IArtemisService
{
Task<List<SurfaceConfiguration>> GetSurfaceConfigurations();
SurfaceConfiguration GetActiveSurfaceConfiguration();
}
}

View File

@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Models;
using Artemis.Core.ProfileElements;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Repositories;

View File

@ -12,7 +12,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.3.0" newVersion="1.2.3.0" />
<bindingRedirect oldVersion="0.0.0.0-1.2.4.0" newVersion="1.2.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
@ -56,7 +56,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0" />
<bindingRedirect oldVersion="0.0.0.0-1.4.4.0" newVersion="1.4.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
@ -84,7 +84,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
@ -96,7 +96,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
<bindingRedirect oldVersion="0.0.0.0-4.1.5.0" newVersion="4.1.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />

View File

@ -2,12 +2,14 @@
<packages>
<package id="AppDomainToolkit" version="1.0.4.3" targetFramework="net461" />
<package id="Castle.Core" version="4.4.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="12.0.1" targetFramework="net461" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" />
<package id="Ninject" version="3.3.4" targetFramework="net461" />
<package id="Ninject.Extensions.ChildKernel" version="3.3.0" targetFramework="net461" />
<package id="Ninject.Extensions.Conventions" version="3.3.0" targetFramework="net461" />
<package id="Ninject.Extensions.Factory" version="3.3.2" targetFramework="net461" />
<package id="Stylet" version="1.1.22" targetFramework="net461" />
<package id="Serilog" version="2.8.0" targetFramework="net472" />
<package id="Serilog.Sinks.File" version="4.0.0" targetFramework="net472" />
<package id="Stylet" version="1.2.0" targetFramework="net472" />
<package id="System.Diagnostics.DiagnosticSource" version="4.5.1" targetFramework="net472" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
</packages>

View File

@ -10,6 +10,26 @@
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.5.0" newVersion="4.1.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.4.0" newVersion="1.4.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.4.0" newVersion="1.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -42,9 +42,8 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\RGB.NET\bin\net45\RGB.NET.Core.dll</HintPath>
</Reference>
<Reference Include="Stylet, Version=1.1.22.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Stylet.1.1.22\lib\net45\Stylet.dll</HintPath>
<Private>False</Private>
<Reference Include="Stylet, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Stylet.1.2.0\lib\net45\Stylet.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@ -1,7 +1,7 @@
using System.Drawing;
using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.Models;
using Artemis.Core.ProfileElements;
using QRCoder;
using RGB.NET.Core;

View File

@ -10,6 +10,26 @@
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.5.0" newVersion="4.1.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.4.0" newVersion="1.4.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.4.0" newVersion="1.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /></startup></configuration>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="QRCoder" version="1.2.5" targetFramework="net461" />
<package id="Stylet" version="1.1.22" targetFramework="net461" />
<package id="Stylet" version="1.2.0" targetFramework="net472" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
</packages>

View File

@ -42,9 +42,8 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\RGB.NET\bin\net45\RGB.NET.Core.dll</HintPath>
</Reference>
<Reference Include="Stylet, Version=1.1.17.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Stylet.1.1.17\lib\net45\Stylet.dll</HintPath>
<Private>False</Private>
<Reference Include="Stylet, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Stylet.1.2.0\lib\net45\Stylet.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@ -10,6 +10,26 @@
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.5.0" newVersion="4.1.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.4.0" newVersion="1.4.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.4.0" newVersion="1.2.4.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /></startup></configuration>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="QRCoder" version="1.3.5" targetFramework="net461" />
<package id="Stylet" version="1.1.17" targetFramework="net461" />
<package id="Stylet" version="1.2.0" targetFramework="net472" />
<package id="System.Drawing.Common" version="4.5.0" targetFramework="net461" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
</packages>

View File

@ -12,7 +12,7 @@ namespace Artemis.Storage.Entities
public string LedName { get; set; }
public string LimitedToDevice { get; set; }
public int LayerId { get; set; }
public string LayerId { get; set; }
public virtual LayerEntity Layer { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using System.ComponentModel.DataAnnotations;
namespace Artemis.Storage.Entities
{
public class SurfaceDeviceEntity
{
[Key]
public string Guid { get; set; }
public int DeviceId { get; set; }
public string DeviceName { get; set; }
public string DeviceModel { get; set; }
public string DeviceManufacturer { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Rotation { get; set; }
public string SurfaceId { get; set; }
public virtual SurfaceEntity Surface { get; set; }
}
}

View File

@ -0,0 +1,16 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Artemis.Storage.Entities
{
public class SurfaceEntity
{
[Key]
public string Guid { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<SurfacePositionEntity> SurfacePositions { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using System.ComponentModel.DataAnnotations;
namespace Artemis.Storage.Entities
{
public class SurfacePositionEntity
{
[Key]
public string Guid { get; set; }
public int DeviceId { get; set; }
public string DeviceName { get; set; }
public string DeviceModel { get; set; }
public string DeviceManufacturer { get; set; }
public double X { get; set; }
public double Y { get; set; }
public double Rotation { get; set; }
public string SurfaceId { get; set; }
public virtual SurfaceEntity Surface { get; set; }
}
}

View File

@ -1,6 +0,0 @@
namespace Artemis.Storage.Repositories
{
public interface IRepository
{
}
}

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Artemis.Storage.Entities;
namespace Artemis.Storage.Repositories
namespace Artemis.Storage.Repositories.Interfaces
{
public interface IPluginSettingRepository : IRepository
{

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Storage.Entities;
namespace Artemis.Storage.Repositories.Interfaces
{
public interface IProfileRepository : IRepository
{
IQueryable<ProfileEntity> GetAll();
Task<IList<ProfileEntity>> GetByPluginGuidAsync(Guid pluginGuid);
Task<ProfileEntity> GetByGuidAsync(string guid);
void Save();
Task SaveAsync();
}
}

View File

@ -0,0 +1,6 @@
namespace Artemis.Storage.Repositories.Interfaces
{
public interface IRepository
{
}
}

View File

@ -2,7 +2,7 @@
using System.Threading.Tasks;
using Artemis.Storage.Entities;
namespace Artemis.Storage.Repositories
namespace Artemis.Storage.Repositories.Interfaces
{
public interface ISettingRepository : IRepository
{

View File

@ -0,0 +1,18 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Artemis.Storage.Entities;
namespace Artemis.Storage.Repositories.Interfaces
{
public interface ISurfaceRepository : IRepository
{
void Add(SurfaceEntity surfaceEntity);
SurfaceEntity Get(string name);
Task<SurfaceEntity> GetAsync(string name);
List<SurfaceEntity> GetAll();
Task<List<SurfaceEntity>> GetAllAsync();
void Save();
Task SaveAsync();
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Storage.Entities;
using Artemis.Storage.Repositories.Interfaces;
using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Repositories

View File

@ -3,11 +3,12 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Storage.Entities;
using Artemis.Storage.Repositories.Interfaces;
using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Repositories
{
public class ProfileRepository
public class ProfileRepository : IProfileRepository
{
private readonly StorageContext _dbContext;
@ -32,6 +33,11 @@ namespace Artemis.Storage.Repositories
return await _dbContext.Profiles.FirstOrDefaultAsync(p => p.Guid == guid);
}
public void Save()
{
_dbContext.SaveChanges();
}
public async Task SaveAsync()
{
await _dbContext.SaveChangesAsync();

View File

@ -2,6 +2,7 @@
using System.Linq;
using System.Threading.Tasks;
using Artemis.Storage.Entities;
using Artemis.Storage.Repositories.Interfaces;
using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Repositories

View File

@ -0,0 +1,55 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Storage.Entities;
using Artemis.Storage.Repositories.Interfaces;
using Microsoft.EntityFrameworkCore;
namespace Artemis.Storage.Repositories
{
public class SurfaceRepository : ISurfaceRepository
{
private readonly StorageContext _dbContext;
internal SurfaceRepository()
{
_dbContext = new StorageContext();
_dbContext.Database.EnsureCreated();
}
public void Add(SurfaceEntity surfaceEntity)
{
_dbContext.Surfaces.Add(surfaceEntity);
}
public SurfaceEntity Get(string name)
{
return _dbContext.Surfaces.Include(s => s.SurfacePositions).FirstOrDefault(p => p.Name == name);
}
public async Task<SurfaceEntity> GetAsync(string name)
{
return await _dbContext.Surfaces.Include(s => s.SurfacePositions).FirstOrDefaultAsync(p => p.Name == name);
}
public List<SurfaceEntity> GetAll()
{
return _dbContext.Surfaces.Include(s => s.SurfacePositions).ToList();
}
public async Task<List<SurfaceEntity>> GetAllAsync()
{
return await _dbContext.Surfaces.Include(s => s.SurfacePositions).ToListAsync();
}
public void Save()
{
_dbContext.SaveChanges();
}
public async Task SaveAsync()
{
await _dbContext.SaveChangesAsync();
}
}
}

View File

@ -10,6 +10,7 @@ namespace Artemis.Storage
{
public DbSet<ProfileEntity> Profiles { get; set; }
public DbSet<SettingEntity> Settings { get; set; }
public DbSet<SurfaceEntity> Surfaces { get; set; }
public DbSet<PluginSettingEntity> PluginSettings { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

View File

@ -11,7 +11,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.3.0" newVersion="1.2.3.0" />
<bindingRedirect oldVersion="0.0.0.0-1.2.4.0" newVersion="1.2.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
@ -59,7 +59,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0" />
<bindingRedirect oldVersion="0.0.0.0-1.4.4.0" newVersion="1.4.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
@ -87,7 +87,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
@ -99,7 +99,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
<bindingRedirect oldVersion="0.0.0.0-4.1.5.0" newVersion="4.1.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />

View File

@ -119,8 +119,8 @@
<Reference Include="SQLitePCLRaw.provider.e_sqlite3, Version=1.1.12.351, Culture=neutral, PublicKeyToken=9c301db686d0bd12, processorArchitecture=MSIL">
<HintPath>..\packages\SQLitePCLRaw.provider.e_sqlite3.net45.1.1.12\lib\net45\SQLitePCLRaw.provider.e_sqlite3.dll</HintPath>
</Reference>
<Reference Include="Stylet, Version=1.1.22.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Stylet.1.1.22\lib\net45\Stylet.dll</HintPath>
<Reference Include="Stylet, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Stylet.1.2.0\lib\net45\Stylet.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />

View File

@ -1,10 +1,13 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Artemis.Core.Events;
using Artemis.Core.Models.Surface;
using Artemis.Core.Services.Interfaces;
using Artemis.Core.Services.Storage;
using Artemis.UI.ViewModels.Controls.RgbDevice;
using Artemis.UI.ViewModels.Interfaces;
using RGB.NET.Core;
@ -16,21 +19,23 @@ namespace Artemis.UI.ViewModels.Screens
public class SurfaceEditorViewModel : Screen, ISurfaceEditorViewModel
{
private readonly IRgbService _rgbService;
private readonly ISurfaceService _surfaceService;
public SurfaceEditorViewModel(IRgbService rgbService)
public SurfaceEditorViewModel(IRgbService rgbService, ISurfaceService surfaceService)
{
Devices = new ObservableCollection<RgbDeviceViewModel>();
SurfaceConfigurations = new ObservableCollection<SurfaceConfiguration>();
SelectionRectangle = new RectangleGeometry();
_rgbService = rgbService;
_surfaceService = surfaceService;
_rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded;
_rgbService.Surface.Updated += SurfaceOnUpdated;
foreach (var surfaceDevice in _rgbService.Surface.Devices)
{
var device = new RgbDeviceViewModel(surfaceDevice) {Cursor = Cursors.Hand};
// device.SetColorsEnabled(false);
device.SetColorsEnabled(false);
Devices.Add(device);
}
@ -39,6 +44,10 @@ namespace Artemis.UI.ViewModels.Screens
public RectangleGeometry SelectionRectangle { get; set; }
public ObservableCollection<RgbDeviceViewModel> Devices { get; set; }
public SurfaceConfiguration SelectedSurfaceConfiguration { get; set; }
public ObservableCollection<SurfaceConfiguration> SurfaceConfigurations { get; set; }
public string NewConfigurationName { get; set; }
public string Title => "Surface Editor";
private void RgbServiceOnDeviceLoaded(object sender, DeviceEventArgs e)
@ -48,7 +57,7 @@ namespace Artemis.UI.ViewModels.Screens
if (Devices.All(d => d.Device != e.Device))
{
var device = new RgbDeviceViewModel(e.Device) {Cursor = Cursors.Hand};
// device.SetColorsEnabled(false);
device.SetColorsEnabled(false);
Devices.Add(device);
}
});
@ -60,6 +69,51 @@ namespace Artemis.UI.ViewModels.Screens
rgbDeviceViewModel.Update();
}
#region Overrides of Screen
protected override void OnActivate()
{
Task.Run(LoadSurfaceConfigurations);
base.OnActivate();
}
#endregion
private async Task LoadSurfaceConfigurations()
{
SurfaceConfigurations.Clear();
// Get surface configs
var configs = await _surfaceService.GetSurfaceConfigurations();
// Populate the UI collection
foreach (var surfaceConfiguration in configs)
SurfaceConfigurations.Add(surfaceConfiguration);
// Select either the first active surface or the first available surface
SelectedSurfaceConfiguration = SurfaceConfigurations.FirstOrDefault(s => s.IsActive) ?? SurfaceConfigurations.FirstOrDefault();
// Create a default if there is none
if (SelectedSurfaceConfiguration == null)
SelectedSurfaceConfiguration = AddSurfaceConfiguration("Default");
}
public SurfaceConfiguration AddSurfaceConfiguration(string name)
{
var config = new SurfaceConfiguration(name);
Execute.OnUIThread(() => SurfaceConfigurations.Add(config));
return config;
}
public void ConfigurationDialogClosing()
{
if (!string.IsNullOrWhiteSpace(NewConfigurationName))
{
var newConfig = AddSurfaceConfiguration(NewConfigurationName);
SelectedSurfaceConfiguration = newConfig;
}
NewConfigurationName = null;
}
#region Mouse actions
private MouseDragStatus _mouseDragStatus;
@ -79,6 +133,7 @@ namespace Artemis.UI.ViewModels.Screens
others.SelectionStatus = SelectionStatus.None;
device.SelectionStatus = SelectionStatus.Selected;
}
foreach (var selectedDevice in Devices.Where(d => d.SelectionStatus == SelectionStatus.Selected))
selectedDevice.StartMouseDrag(position);
}

View File

@ -5,74 +5,175 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:screens="clr-namespace:Artemis.UI.ViewModels.Screens"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:models="clr-namespace:Artemis.Core.Models.Surface;assembly=Artemis.Core"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance screens:SurfaceEditorViewModel}"
d:DesignHeight="600" d:DesignWidth="600">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.TextBlock.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.TextBlock.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.PopupBox.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid Margin="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock>The surface is a digital representation of your LED setup. Set this up accurately and effects will seamlessly move from one device to the other.</TextBlock>
<Grid Name="EditorDisplayGrid"
Grid.Row="1"
Margin="0 5 0 0"
MouseUp="{s:Action EditorGridMouseClick}"
MouseDown="{s:Action EditorGridMouseClick}"
MouseMove="{s:Action EditorGridMouseMove}">
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.MouseDown">
<BeginStoryboard>
<Storyboard TargetName="MultiSelectionPath" TargetProperty="Opacity">
<DoubleAnimation From="0" To="1" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Grid.MouseUp">
<BeginStoryboard>
<Storyboard TargetName="MultiSelectionPath" TargetProperty="Opacity">
<DoubleAnimation From="1" To="0" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid.Background>
<ImageBrush TileMode="Tile" ViewportUnits="Absolute" Viewport="0,0,15,15" ImageSource="/Artemis.UI;component/Resources/tile.png" />
</Grid.Background>
<ItemsControl ItemsSource="{Binding Devices}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Device.Location.X}" />
<Setter Property="Canvas.Top" Value="{Binding Device.Location.Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Width="{Binding Device.Size.Width}" Height="{Binding Device.Size.Height}" s:View.Model="{Binding }" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Grid.Row="0" Grid.Column="0" Style="{StaticResource MaterialDesignDisplay1TextBlock}">Surface layout</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0" Style="{StaticResource MaterialDesignCaptionTextBlock}">The surface is a digital representation of your LED setup. Set this up accurately and effects will seamlessly move from one device to the other.</TextBlock>
<!-- Multi-selection rectangle -->
<Path Data="{Binding SelectionRectangle}" Opacity="0" Stroke="{DynamicResource PrimaryHueLightBrush}" StrokeThickness="1" Name="MultiSelectionPath">
<Path.Fill>
<SolidColorBrush Color="{DynamicResource Primary400}" Opacity="0.25" />
</Path.Fill>
</Path>
</Grid>
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" Grid.Row="2" Grid.Column="0" VerticalAlignment="Stretch" Margin="0,0,5,0">
<Grid Name="EditorDisplayGrid"
Margin="5"
MouseUp="{s:Action EditorGridMouseClick}"
MouseDown="{s:Action EditorGridMouseClick}"
MouseMove="{s:Action EditorGridMouseMove}">
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.MouseDown">
<BeginStoryboard>
<Storyboard TargetName="MultiSelectionPath" TargetProperty="Opacity">
<DoubleAnimation From="0" To="1" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Grid.MouseUp">
<BeginStoryboard>
<Storyboard TargetName="MultiSelectionPath" TargetProperty="Opacity">
<DoubleAnimation From="1" To="0" Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid.Background>
<ImageBrush TileMode="Tile" ViewportUnits="Absolute" Viewport="0,0,15,15" ImageSource="/Artemis.UI;component/Resources/tile.png" />
</Grid.Background>
<ItemsControl ItemsSource="{Binding Devices}" ClipToBounds="True">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Device.Location.X}" />
<Setter Property="Canvas.Top" Value="{Binding Device.Location.Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Width="{Binding Device.Size.Width}" Height="{Binding Device.Size.Height}" s:View.Model="{Binding }" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Multi-selection rectangle -->
<Path Data="{Binding SelectionRectangle}" Opacity="0" Stroke="{DynamicResource PrimaryHueLightBrush}" StrokeThickness="1" Name="MultiSelectionPath">
<Path.Fill>
<SolidColorBrush Color="{DynamicResource Primary400}" Opacity="0.25" />
</Path.Fill>
</Path>
</Grid>
</materialDesign:Card>
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" Grid.Row="2" Grid.Column="1" VerticalAlignment="Stretch" Margin="5,0,0,0">
<materialDesign:DialogHost DialogClosing="{s:Action ConfirmationDialogClosing}">
<materialDesign:DialogHost.DialogContent>
<StackPanel Margin="16">
<TextBlock>
Add a new surface layout.
</TextBlock>
<TextBox Margin="0 8 0 0" HorizontalAlignment="Stretch" Text="{Binding NewConfigurationName}" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 8 8 0" Command="materialDesign:DialogHost.CloseDialogCommand">
<Button.CommandParameter>
<system:Boolean xmlns:system="clr-namespace:System;assembly=mscorlib">
True
</system:Boolean>
</Button.CommandParameter>
ACCEPT
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Margin="0 8 8 0" Command="materialDesign:DialogHost.CloseDialogCommand">
<Button.CommandParameter>
<system:Boolean xmlns:system="clr-namespace:System;assembly=mscorlib">
False
</system:Boolean>
</Button.CommandParameter>
CANCEL
</Button>
</StackPanel>
</StackPanel>
</materialDesign:DialogHost.DialogContent>
<materialDesign:DialogHost DialogClosing="{s:Action ConfigurationDialogClosing}">
<materialDesign:DialogHost.DialogContent>
<StackPanel Margin="16">
<TextBlock>
Add a new surface layout.
</TextBlock>
<TextBox Margin="0 8 0 0" HorizontalAlignment="Stretch" Text="{Binding NewConfigurationName}" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 8 8 0" Command="materialDesign:DialogHost.CloseDialogCommand">
<Button.CommandParameter>
<system:Boolean xmlns:system="clr-namespace:System;assembly=mscorlib">
True
</system:Boolean>
</Button.CommandParameter>
ACCEPT
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Margin="0 8 8 0" Command="materialDesign:DialogHost.CloseDialogCommand">
<Button.CommandParameter>
<system:Boolean xmlns:system="clr-namespace:System;assembly=mscorlib">
False
</system:Boolean>
</Button.CommandParameter>
CANCEL
</Button>
</StackPanel>
</StackPanel>
</materialDesign:DialogHost.DialogContent>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" ItemsSource="{Binding SurfaceConfigurations}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type models:SurfaceConfiguration}">
<TextBlock Text="{Binding Name}" ToolTip="{Binding Name}" />
</DataTemplate>
</ListBox.Resources>
</ListBox>
<materialDesign:PopupBox
Grid.Row="0"
Style="{StaticResource MaterialDesignMultiFloatingActionPopupBox}"
PlacementMode="LeftAndAlignMiddles"
UnfurlOrientation="Horizontal"
ToolTip="Manage surface layouts"
Margin="0 0 10 10"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<StackPanel
Orientation="Horizontal">
<Button ToolTip="Add a new surface layout" Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}">
<materialDesign:PackIcon Kind="Add" />
</Button>
<Button ToolTip="Remove selected surface layout" Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}">
<materialDesign:PackIcon Kind="Delete" />
</Button>
</StackPanel>
</materialDesign:PopupBox>
</Grid>
</materialDesign:DialogHost>
</materialDesign:DialogHost>
</materialDesign:Card>
</Grid>
</UserControl>

View File

@ -20,6 +20,6 @@
<package id="SQLitePCLRaw.lib.e_sqlite3.osx" version="1.1.12" targetFramework="net472" />
<package id="SQLitePCLRaw.lib.e_sqlite3.v110_xp" version="1.1.12" targetFramework="net472" />
<package id="SQLitePCLRaw.provider.e_sqlite3.net45" version="1.1.12" targetFramework="net472" />
<package id="Stylet" version="1.1.22" targetFramework="net461" />
<package id="Stylet" version="1.2.0" targetFramework="net472" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
</packages>