mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Merge branch 'development' into VisualScripting
This commit is contained in:
commit
3874078f16
@ -313,13 +313,10 @@
|
|||||||
},
|
},
|
||||||
"Serilog.Sinks.Console": {
|
"Serilog.Sinks.Console": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "3.1.1",
|
"resolved": "4.0.0",
|
||||||
"contentHash": "56mI5AqvyF/i/c2451nvV71kq370XOCE4Uu5qiaJ295sOhMb9q3BWwG7mWLOVSnmpWiq0SBT3SXfgRXGNP6vzA==",
|
"contentHash": "yJQit9sTJ4xGLKgCujqDJsaGqBNJwGB/H898z+xYlMG06twy4//6LLnSrsmpduZxcHIG4im7cv+JmXLzXz2EkQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Serilog": "2.5.0",
|
"Serilog": "2.10.0"
|
||||||
"System.Console": "4.3.0",
|
|
||||||
"System.Runtime.InteropServices": "4.3.0",
|
|
||||||
"System.Runtime.InteropServices.RuntimeInformation": "4.3.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Serilog.Sinks.Debug": {
|
"Serilog.Sinks.Debug": {
|
||||||
@ -332,19 +329,16 @@
|
|||||||
},
|
},
|
||||||
"Serilog.Sinks.File": {
|
"Serilog.Sinks.File": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "4.1.0",
|
"resolved": "5.0.0",
|
||||||
"contentHash": "U0b34w+ZikbqWEZ3ui7BdzxY/19zwrdhLtI3o6tfmLdD3oXxg7n2TZJjwCCTlKPgRuYic9CBWfrZevbb70mTaw==",
|
"contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Serilog": "2.5.0",
|
"Serilog": "2.10.0"
|
||||||
"System.IO.FileSystem": "4.0.1",
|
|
||||||
"System.Text.Encoding.Extensions": "4.0.11",
|
|
||||||
"System.Threading.Timer": "4.0.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"SkiaSharp": {
|
"SkiaSharp": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "2.80.2",
|
"resolved": "2.80.3",
|
||||||
"contentHash": "D25rzdCwh+3L+XyXqpNa+H/yiLJbE3/R3K/XexwHyQjGdzZvSufFW3oqf3En7hhqSIsxsJ8f5NEZ0J5W5wlGBg==",
|
"contentHash": "qX6tGNP3+MXNYe2pKm0PCRiJ/cx+LTeLaggwZifB7sUMXhECfKKKHJq45VqZKt37xQegnCCdf1jHXwmHeJQs5Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Memory": "4.5.3"
|
"System.Memory": "4.5.3"
|
||||||
}
|
}
|
||||||
@ -1230,10 +1224,10 @@
|
|||||||
"Ninject.Extensions.ChildKernel": "3.3.0",
|
"Ninject.Extensions.ChildKernel": "3.3.0",
|
||||||
"Ninject.Extensions.Conventions": "3.3.0",
|
"Ninject.Extensions.Conventions": "3.3.0",
|
||||||
"Serilog": "2.10.0",
|
"Serilog": "2.10.0",
|
||||||
"Serilog.Sinks.Console": "3.1.1",
|
"Serilog.Sinks.Console": "4.0.0",
|
||||||
"Serilog.Sinks.Debug": "2.0.0",
|
"Serilog.Sinks.Debug": "2.0.0",
|
||||||
"Serilog.Sinks.File": "4.1.0",
|
"Serilog.Sinks.File": "5.0.0",
|
||||||
"SkiaSharp": "2.80.2",
|
"SkiaSharp": "2.80.3",
|
||||||
"System.Buffers": "4.5.1",
|
"System.Buffers": "4.5.1",
|
||||||
"System.IO.FileSystem.AccessControl": "5.0.0",
|
"System.IO.FileSystem.AccessControl": "5.0.0",
|
||||||
"System.Numerics.Vectors": "4.5.0",
|
"System.Numerics.Vectors": "4.5.0",
|
||||||
|
|||||||
@ -48,10 +48,10 @@
|
|||||||
<PackageReference Include="Ninject.Extensions.ChildKernel" Version="3.3.0" />
|
<PackageReference Include="Ninject.Extensions.ChildKernel" Version="3.3.0" />
|
||||||
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" />
|
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" />
|
||||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
|
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
<PackageReference Include="SkiaSharp" Version="2.80.2" />
|
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||||
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
|
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
|
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
|
||||||
|
|||||||
@ -27,7 +27,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The full path to the Artemis data folder
|
/// The full path to the Artemis data folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string DataFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Artemis\\";
|
public static readonly string DataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Artemis");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The plugin info used by core components of Artemis
|
/// The plugin info used by core components of Artemis
|
||||||
|
|||||||
@ -169,29 +169,29 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal static ArtemisLayout? GetDefaultLayout(ArtemisDevice device)
|
internal static ArtemisLayout? GetDefaultLayout(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
string layoutFolder = Path.Combine(Constants.ApplicationFolder, "DefaultLayouts\\Artemis");
|
string layoutFolder = Path.Combine(Constants.ApplicationFolder, "DefaultLayouts", "Artemis");
|
||||||
if (device.DeviceType == RGBDeviceType.Keyboard)
|
if (device.DeviceType == RGBDeviceType.Keyboard)
|
||||||
{
|
{
|
||||||
// XL layout is defined by its programmable macro keys
|
// XL layout is defined by its programmable macro keys
|
||||||
if (device.Leds.Any(l => l.RgbLed.Id >= LedId.Keyboard_Programmable1 && l.RgbLed.Id <= LedId.Keyboard_Programmable32))
|
if (device.Leds.Any(l => l.RgbLed.Id >= LedId.Keyboard_Programmable1 && l.RgbLed.Id <= LedId.Keyboard_Programmable32))
|
||||||
{
|
{
|
||||||
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
||||||
return new ArtemisLayout(layoutFolder + "\\Keyboard\\Artemis XL keyboard-ANSI.xml", LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(layoutFolder, "Keyboard", "Artemis XL keyboard-ANSI.xml"), LayoutSource.Default);
|
||||||
return new ArtemisLayout(layoutFolder + "\\Keyboard\\Artemis XL keyboard-ISO.xml", LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(layoutFolder, "Keyboard", "Artemis XL keyboard-ISO.xml"), LayoutSource.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
// L layout is defined by its numpad
|
// L layout is defined by its numpad
|
||||||
if (device.Leds.Any(l => l.RgbLed.Id >= LedId.Keyboard_NumLock && l.RgbLed.Id <= LedId.Keyboard_NumPeriodAndDelete))
|
if (device.Leds.Any(l => l.RgbLed.Id >= LedId.Keyboard_NumLock && l.RgbLed.Id <= LedId.Keyboard_NumPeriodAndDelete))
|
||||||
{
|
{
|
||||||
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
||||||
return new ArtemisLayout(layoutFolder + "\\Keyboard\\Artemis L keyboard-ANSI.xml", LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(layoutFolder + "Keyboard","Artemis L keyboard-ANSI.xml"), LayoutSource.Default);
|
||||||
return new ArtemisLayout(layoutFolder + "\\Keyboard\\Artemis L keyboard-ISO.xml", LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(layoutFolder + "Keyboard","Artemis L keyboard-ISO.xml"), LayoutSource.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No numpad will result in TKL
|
// No numpad will result in TKL
|
||||||
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
||||||
return new ArtemisLayout(layoutFolder + "\\Keyboard\\Artemis TKL keyboard-ANSI.xml", LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(layoutFolder + "Keyboard","Artemis TKL keyboard-ANSI.xml"), LayoutSource.Default);
|
||||||
return new ArtemisLayout(layoutFolder + "\\Keyboard\\Artemis TKL keyboard-ISO.xml", LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(layoutFolder + "Keyboard","Artemis TKL keyboard-ISO.xml"), LayoutSource.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (device.DeviceType == RGBDeviceType.Mouse)
|
// if (device.DeviceType == RGBDeviceType.Mouse)
|
||||||
@ -199,21 +199,21 @@ namespace Artemis.Core
|
|||||||
// if (device.Leds.Count == 1)
|
// if (device.Leds.Count == 1)
|
||||||
// {
|
// {
|
||||||
// if (device.Leds.Any(l => l.RgbLed.Id == LedId.Logo))
|
// if (device.Leds.Any(l => l.RgbLed.Id == LedId.Logo))
|
||||||
// return new ArtemisLayout(layoutFolder + "\\Mouse\\1 LED mouse logo.xml", LayoutSource.Default);
|
// return new ArtemisLayout(Path.Combine(layoutFolder + "Mouse", "1 LED mouse logo.xml"), LayoutSource.Default);
|
||||||
// return new ArtemisLayout(layoutFolder + "\\Mouse\\1 LED mouse.xml", LayoutSource.Default);
|
// return new ArtemisLayout(Path.Combine(layoutFolder + "Mouse", "1 LED mouse.xml"), LayoutSource.Default);
|
||||||
// }
|
// }
|
||||||
// if (device.Leds.Any(l => l.RgbLed.Id == LedId.Logo))
|
// if (device.Leds.Any(l => l.RgbLed.Id == LedId.Logo))
|
||||||
// return new ArtemisLayout(layoutFolder + "\\Mouse\\4 LED mouse logo.xml", LayoutSource.Default);
|
// return new ArtemisLayout(Path.Combine(layoutFolder + "Mouse", "4 LED mouse logo.xml"), LayoutSource.Default);
|
||||||
// return new ArtemisLayout(layoutFolder + "\\Mouse\\4 LED mouse.xml", LayoutSource.Default);
|
// return new ArtemisLayout(Path.Combine(layoutFolder + "Mouse", "4 LED mouse.xml"), LayoutSource.Default);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (device.DeviceType == RGBDeviceType.Headset)
|
if (device.DeviceType == RGBDeviceType.Headset)
|
||||||
{
|
{
|
||||||
if (device.Leds.Count == 1)
|
if (device.Leds.Count == 1)
|
||||||
return new ArtemisLayout(layoutFolder + "\\Headset\\Artemis 1 LED headset.xml", LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(layoutFolder + "Headset", "Artemis 1 LED headset.xml"), LayoutSource.Default);
|
||||||
if (device.Leds.Count == 2)
|
if (device.Leds.Count == 2)
|
||||||
return new ArtemisLayout(layoutFolder + "\\Headset\\Artemis 2 LED headset.xml", LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(layoutFolder + "Headset", "Artemis 2 LED headset.xml"), LayoutSource.Default);
|
||||||
return new ArtemisLayout(layoutFolder + "\\Headset\\Artemis 4 LED headset.xml", LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(layoutFolder + "Headset", "Artemis 4 LED headset.xml"), LayoutSource.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -61,7 +61,6 @@ namespace Artemis.Core
|
|||||||
if (LayoutCustomLedData.LogicalLayouts == null || !LayoutCustomLedData.LogicalLayouts.Any())
|
if (LayoutCustomLedData.LogicalLayouts == null || !LayoutCustomLedData.LogicalLayouts.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Uri layoutDirectory = new(Path.GetDirectoryName(DeviceLayout.FilePath)! + "\\", UriKind.Absolute);
|
|
||||||
// Prefer a matching layout or else a default layout (that has no name)
|
// Prefer a matching layout or else a default layout (that has no name)
|
||||||
LayoutCustomLedDataLogicalLayout logicalLayout = LayoutCustomLedData.LogicalLayouts
|
LayoutCustomLedDataLogicalLayout logicalLayout = LayoutCustomLedData.LogicalLayouts
|
||||||
.OrderBy(l => l.Name == artemisDevice.LogicalLayout)
|
.OrderBy(l => l.Name == artemisDevice.LogicalLayout)
|
||||||
@ -69,7 +68,7 @@ namespace Artemis.Core
|
|||||||
.First();
|
.First();
|
||||||
|
|
||||||
LogicalName = logicalLayout.Name;
|
LogicalName = logicalLayout.Name;
|
||||||
Image = new Uri(layoutDirectory, logicalLayout.Image);
|
Image = new Uri(Path.Combine(Path.GetDirectoryName(DeviceLayout.FilePath)!, logicalLayout.Image!), UriKind.Absolute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using Ninject.Activation;
|
using Ninject.Activation;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Core;
|
using Serilog.Core;
|
||||||
@ -12,7 +13,7 @@ namespace Artemis.Core.Ninject
|
|||||||
|
|
||||||
private static readonly ILogger Logger = new LoggerConfiguration()
|
private static readonly ILogger Logger = new LoggerConfiguration()
|
||||||
.Enrich.FromLogContext()
|
.Enrich.FromLogContext()
|
||||||
.WriteTo.File(Constants.DataFolder + "logs/Artemis log-.log",
|
.WriteTo.File(Path.Combine(Constants.DataFolder, "logs", "Artemis log-.log"),
|
||||||
rollingInterval: RollingInterval.Day,
|
rollingInterval: RollingInterval.Day,
|
||||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}")
|
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}")
|
||||||
.WriteTo.Console()
|
.WriteTo.Console()
|
||||||
|
|||||||
@ -11,8 +11,8 @@ namespace Artemis.Core
|
|||||||
public abstract class PluginFeature : CorePropertyChanged, IDisposable
|
public abstract class PluginFeature : CorePropertyChanged, IDisposable
|
||||||
{
|
{
|
||||||
private bool _isEnabled;
|
private bool _isEnabled;
|
||||||
private Exception? _loadException;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin feature info related to this feature
|
/// Gets the plugin feature info related to this feature
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -37,14 +37,7 @@ namespace Artemis.Core
|
|||||||
internal set => SetAndNotify(ref _isEnabled, value);
|
internal set => SetAndNotify(ref _isEnabled, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
internal int AutoEnableAttempts { get; set; }
|
||||||
/// Gets the exception thrown while loading
|
|
||||||
/// </summary>
|
|
||||||
public Exception? LoadException
|
|
||||||
{
|
|
||||||
get => _loadException;
|
|
||||||
internal set => SetAndNotify(ref _loadException, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the identifier of this plugin feature
|
/// Gets the identifier of this plugin feature
|
||||||
@ -82,7 +75,8 @@ namespace Artemis.Core
|
|||||||
/// </param>
|
/// </param>
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing) InternalDisable();
|
if (disposing)
|
||||||
|
SetEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -111,16 +105,6 @@ namespace Artemis.Core
|
|||||||
Profiler.StopMeasurement("Update");
|
Profiler.StopMeasurement("Update");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void StartRenderMeasure()
|
|
||||||
{
|
|
||||||
Profiler.StartMeasurement("Render");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void StopRenderMeasure()
|
|
||||||
{
|
|
||||||
Profiler.StopMeasurement("Render");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void SetEnabled(bool enable, bool isAutoEnable = false)
|
internal void SetEnabled(bool enable, bool isAutoEnable = false)
|
||||||
{
|
{
|
||||||
if (enable == IsEnabled)
|
if (enable == IsEnabled)
|
||||||
@ -146,13 +130,16 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (isAutoEnable)
|
||||||
|
AutoEnableAttempts++;
|
||||||
|
|
||||||
if (isAutoEnable && GetLockFileCreated())
|
if (isAutoEnable && GetLockFileCreated())
|
||||||
{
|
{
|
||||||
// Don't wrap existing lock exceptions, simply rethrow them
|
// Don't wrap existing lock exceptions, simply rethrow them
|
||||||
if (LoadException is ArtemisPluginLockException)
|
if (Info.LoadException is ArtemisPluginLockException)
|
||||||
throw LoadException;
|
throw Info.LoadException;
|
||||||
|
|
||||||
throw new ArtemisPluginLockException(LoadException);
|
throw new ArtemisPluginLockException(Info.LoadException);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateLockFile();
|
CreateLockFile();
|
||||||
@ -165,21 +152,22 @@ namespace Artemis.Core
|
|||||||
if (!enableTask.Wait(TimeSpan.FromSeconds(15)))
|
if (!enableTask.Wait(TimeSpan.FromSeconds(15)))
|
||||||
throw new ArtemisPluginException(Plugin, "Plugin load timeout");
|
throw new ArtemisPluginException(Plugin, "Plugin load timeout");
|
||||||
|
|
||||||
LoadException = null;
|
Info.LoadException = null;
|
||||||
|
AutoEnableAttempts = 0;
|
||||||
OnEnabled();
|
OnEnabled();
|
||||||
}
|
}
|
||||||
// If enable failed, put it back in a disabled state
|
// If enable failed, put it back in a disabled state
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
IsEnabled = false;
|
IsEnabled = false;
|
||||||
LoadException = e;
|
Info.LoadException = e;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// Clean up the lock file unless the failure was due to the lock file
|
// Clean up the lock file unless the failure was due to the lock file
|
||||||
// After all, we failed but not miserably :)
|
// After all, we failed but not miserably :)
|
||||||
if (!(LoadException is ArtemisPluginLockException))
|
if (Info.LoadException is not ArtemisPluginLockException)
|
||||||
DeleteLockFile();
|
DeleteLockFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ namespace Artemis.Core
|
|||||||
[JsonObject(MemberSerialization.OptIn)]
|
[JsonObject(MemberSerialization.OptIn)]
|
||||||
public class PluginFeatureInfo : CorePropertyChanged, IPrerequisitesSubject
|
public class PluginFeatureInfo : CorePropertyChanged, IPrerequisitesSubject
|
||||||
{
|
{
|
||||||
|
private Exception? _loadException;
|
||||||
private string? _description;
|
private string? _description;
|
||||||
private string? _icon;
|
private string? _icon;
|
||||||
private PluginFeature? _instance;
|
private PluginFeature? _instance;
|
||||||
@ -80,6 +81,15 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Type FeatureType { get; }
|
public Type FeatureType { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the exception thrown while loading
|
||||||
|
/// </summary>
|
||||||
|
public Exception? LoadException
|
||||||
|
{
|
||||||
|
get => _loadException;
|
||||||
|
internal set => SetAndNotify(ref _loadException, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the plugin
|
/// The name of the plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -8,21 +8,6 @@ namespace Artemis.Core.Services
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
internal class ColorQuantizerService : IColorQuantizerService
|
internal class ColorQuantizerService : IColorQuantizerService
|
||||||
{
|
{
|
||||||
private static float GetComparisonValue(float sat, float targetSaturation, float luma, float targetLuma)
|
|
||||||
{
|
|
||||||
static float InvertDiff(float value, float target)
|
|
||||||
{
|
|
||||||
return 1 - Math.Abs(value - target);
|
|
||||||
}
|
|
||||||
|
|
||||||
const float totalWeight = weightSaturation + weightLuma;
|
|
||||||
|
|
||||||
float totalValue = InvertDiff(sat, targetSaturation) * weightSaturation +
|
|
||||||
InvertDiff(luma, targetLuma) * weightLuma;
|
|
||||||
|
|
||||||
return totalValue / totalWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public SKColor[] Quantize(IEnumerable<SKColor> colors, int amount)
|
public SKColor[] Quantize(IEnumerable<SKColor> colors, int amount)
|
||||||
{
|
{
|
||||||
@ -48,29 +33,12 @@ namespace Artemis.Core.Services
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public SKColor FindColorVariation(IEnumerable<SKColor> colors, ColorType type, bool ignoreLimits = false)
|
public SKColor FindColorVariation(IEnumerable<SKColor> colors, ColorType type, bool ignoreLimits = false)
|
||||||
{
|
{
|
||||||
(float targetLuma, float minLuma, float maxLuma, float targetSaturation, float minSaturation, float maxSaturation) = type switch
|
float bestColorScore = 0;
|
||||||
{
|
|
||||||
ColorType.Vibrant => (targetNormalLuma, minNormalLuma, maxNormalLuma, targetVibrantSaturation, minVibrantSaturation, 1f),
|
|
||||||
ColorType.LightVibrant => (targetLightLuma, minLightLuma, 1f, targetVibrantSaturation, minVibrantSaturation, 1f),
|
|
||||||
ColorType.DarkVibrant => (targetDarkLuma, 0f, maxDarkLuma, targetVibrantSaturation, minVibrantSaturation, 1f),
|
|
||||||
ColorType.Muted => (targetNormalLuma, minNormalLuma, maxNormalLuma, targetMutesSaturation, 0, maxMutesSaturation),
|
|
||||||
ColorType.LightMuted => (targetLightLuma, minLightLuma, 1f, targetMutesSaturation, 0, maxMutesSaturation),
|
|
||||||
ColorType.DarkMuted => (targetDarkLuma, 0, maxDarkLuma, targetMutesSaturation, 0, maxMutesSaturation),
|
|
||||||
_ => (0.5f, 0f, 1f, 0.5f, 0f, 1f)
|
|
||||||
};
|
|
||||||
|
|
||||||
float bestColorScore = float.MinValue;
|
|
||||||
SKColor bestColor = SKColor.Empty;
|
SKColor bestColor = SKColor.Empty;
|
||||||
|
|
||||||
foreach (SKColor clr in colors)
|
foreach (SKColor clr in colors)
|
||||||
{
|
{
|
||||||
clr.ToHsl(out float _, out float sat, out float luma);
|
float score = GetScore(clr, type, ignoreLimits);
|
||||||
sat /= 100f;
|
|
||||||
luma /= 100f;
|
|
||||||
|
|
||||||
if (!ignoreLimits && (sat <= minSaturation || sat >= maxSaturation || luma <= minLuma || luma >= maxLuma))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
float score = GetComparisonValue(sat, targetSaturation, luma, targetLuma);
|
|
||||||
if (score > bestColorScore)
|
if (score > bestColorScore)
|
||||||
{
|
{
|
||||||
bestColorScore = score;
|
bestColorScore = score;
|
||||||
@ -81,6 +49,82 @@ namespace Artemis.Core.Services
|
|||||||
return bestColor;
|
return bestColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ColorSwatch FindAllColorVariations(IEnumerable<SKColor> colors, bool ignoreLimits = false)
|
||||||
|
{
|
||||||
|
SKColor bestVibrantColor = SKColor.Empty;
|
||||||
|
SKColor bestLightVibrantColor = SKColor.Empty;
|
||||||
|
SKColor bestDarkVibrantColor = SKColor.Empty;
|
||||||
|
SKColor bestMutedColor = SKColor.Empty;
|
||||||
|
SKColor bestLightMutedColor = SKColor.Empty;
|
||||||
|
SKColor bestDarkMutedColor = SKColor.Empty;
|
||||||
|
float bestVibrantScore = 0;
|
||||||
|
float bestLightVibrantScore = 0;
|
||||||
|
float bestDarkVibrantScore = 0;
|
||||||
|
float bestMutedScore = 0;
|
||||||
|
float bestLightMutedScore = 0;
|
||||||
|
float bestDarkMutedScore = 0;
|
||||||
|
|
||||||
|
//ugly but at least we only loop through the enumerable once ¯\_(ツ)_/¯
|
||||||
|
foreach (var color in colors)
|
||||||
|
{
|
||||||
|
static void SetIfBetterScore(ref float bestScore, ref SKColor bestColor, SKColor newColor, ColorType type, bool ignoreLimits)
|
||||||
|
{
|
||||||
|
float newScore = GetScore(newColor, type, ignoreLimits);
|
||||||
|
if (newScore > bestScore)
|
||||||
|
{
|
||||||
|
bestScore = newScore;
|
||||||
|
bestColor = newColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIfBetterScore(ref bestVibrantScore, ref bestVibrantColor, color, ColorType.Vibrant, ignoreLimits);
|
||||||
|
SetIfBetterScore(ref bestLightVibrantScore, ref bestLightVibrantColor, color, ColorType.LightVibrant, ignoreLimits);
|
||||||
|
SetIfBetterScore(ref bestDarkVibrantScore, ref bestDarkVibrantColor, color, ColorType.DarkVibrant, ignoreLimits);
|
||||||
|
SetIfBetterScore(ref bestMutedScore, ref bestMutedColor, color, ColorType.Muted, ignoreLimits);
|
||||||
|
SetIfBetterScore(ref bestLightMutedScore, ref bestLightMutedColor, color, ColorType.LightMuted, ignoreLimits);
|
||||||
|
SetIfBetterScore(ref bestDarkMutedScore, ref bestDarkMutedColor, color, ColorType.DarkMuted, ignoreLimits);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
Vibrant = bestVibrantColor,
|
||||||
|
LightVibrant = bestLightVibrantColor,
|
||||||
|
DarkVibrant = bestDarkVibrantColor,
|
||||||
|
Muted = bestMutedColor,
|
||||||
|
LightMuted = bestLightMutedColor,
|
||||||
|
DarkMuted = bestDarkMutedColor,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float GetScore(SKColor color, ColorType type, bool ignoreLimits = false)
|
||||||
|
{
|
||||||
|
static float InvertDiff(float value, float target)
|
||||||
|
{
|
||||||
|
return 1 - Math.Abs(value - target);
|
||||||
|
}
|
||||||
|
|
||||||
|
color.ToHsl(out float _, out float saturation, out float luma);
|
||||||
|
saturation /= 100f;
|
||||||
|
luma /= 100f;
|
||||||
|
|
||||||
|
if (!ignoreLimits &&
|
||||||
|
(saturation <= GetMinSaturation(type) || saturation >= GetMaxSaturation(type)
|
||||||
|
|| luma <= GetMinLuma(type) || luma >= GetMaxLuma(type)))
|
||||||
|
{
|
||||||
|
//if either saturation or luma falls outside the min-max, return the
|
||||||
|
//lowest score possible unless we're ignoring these limits.
|
||||||
|
return float.MinValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float totalValue = (InvertDiff(saturation, GetTargetSaturation(type)) * weightSaturation) +
|
||||||
|
(InvertDiff(luma, GetTargetLuma(type)) * weightLuma);
|
||||||
|
|
||||||
|
const float totalWeight = weightSaturation + weightLuma;
|
||||||
|
|
||||||
|
return totalValue / totalWeight;
|
||||||
|
}
|
||||||
|
|
||||||
#region Constants
|
#region Constants
|
||||||
|
|
||||||
private const float targetDarkLuma = 0.26f;
|
private const float targetDarkLuma = 0.26f;
|
||||||
@ -97,6 +141,72 @@ namespace Artemis.Core.Services
|
|||||||
private const float weightSaturation = 3f;
|
private const float weightSaturation = 3f;
|
||||||
private const float weightLuma = 5f;
|
private const float weightLuma = 5f;
|
||||||
|
|
||||||
|
private static float GetTargetLuma(ColorType colorType) => colorType switch
|
||||||
|
{
|
||||||
|
ColorType.Vibrant => targetNormalLuma,
|
||||||
|
ColorType.LightVibrant => targetLightLuma,
|
||||||
|
ColorType.DarkVibrant => targetDarkLuma,
|
||||||
|
ColorType.Muted => targetNormalLuma,
|
||||||
|
ColorType.LightMuted => targetLightLuma,
|
||||||
|
ColorType.DarkMuted => targetDarkLuma,
|
||||||
|
_ => throw new ArgumentException(nameof(colorType))
|
||||||
|
};
|
||||||
|
|
||||||
|
private static float GetMinLuma(ColorType colorType) => colorType switch
|
||||||
|
{
|
||||||
|
ColorType.Vibrant => minNormalLuma,
|
||||||
|
ColorType.LightVibrant => minLightLuma,
|
||||||
|
ColorType.DarkVibrant => 0f,
|
||||||
|
ColorType.Muted => minNormalLuma,
|
||||||
|
ColorType.LightMuted => minLightLuma,
|
||||||
|
ColorType.DarkMuted => 0,
|
||||||
|
_ => throw new ArgumentException(nameof(colorType))
|
||||||
|
};
|
||||||
|
|
||||||
|
private static float GetMaxLuma(ColorType colorType) => colorType switch
|
||||||
|
{
|
||||||
|
ColorType.Vibrant => maxNormalLuma,
|
||||||
|
ColorType.LightVibrant => 1f,
|
||||||
|
ColorType.DarkVibrant => maxDarkLuma,
|
||||||
|
ColorType.Muted => maxNormalLuma,
|
||||||
|
ColorType.LightMuted => 1f,
|
||||||
|
ColorType.DarkMuted => maxDarkLuma,
|
||||||
|
_ => throw new ArgumentException(nameof(colorType))
|
||||||
|
};
|
||||||
|
|
||||||
|
private static float GetTargetSaturation(ColorType colorType) => colorType switch
|
||||||
|
{
|
||||||
|
ColorType.Vibrant => targetVibrantSaturation,
|
||||||
|
ColorType.LightVibrant => targetVibrantSaturation,
|
||||||
|
ColorType.DarkVibrant => targetVibrantSaturation,
|
||||||
|
ColorType.Muted => targetMutesSaturation,
|
||||||
|
ColorType.LightMuted => targetMutesSaturation,
|
||||||
|
ColorType.DarkMuted => targetMutesSaturation,
|
||||||
|
_ => throw new ArgumentException(nameof(colorType))
|
||||||
|
};
|
||||||
|
|
||||||
|
private static float GetMinSaturation(ColorType colorType) => colorType switch
|
||||||
|
{
|
||||||
|
ColorType.Vibrant => minVibrantSaturation,
|
||||||
|
ColorType.LightVibrant => minVibrantSaturation,
|
||||||
|
ColorType.DarkVibrant => minVibrantSaturation,
|
||||||
|
ColorType.Muted => 0,
|
||||||
|
ColorType.LightMuted => 0,
|
||||||
|
ColorType.DarkMuted => 0,
|
||||||
|
_ => throw new ArgumentException(nameof(colorType))
|
||||||
|
};
|
||||||
|
|
||||||
|
private static float GetMaxSaturation(ColorType colorType) => colorType switch
|
||||||
|
{
|
||||||
|
ColorType.Vibrant => 1f,
|
||||||
|
ColorType.LightVibrant => 1f,
|
||||||
|
ColorType.DarkVibrant => 1f,
|
||||||
|
ColorType.Muted => maxMutesSaturation,
|
||||||
|
ColorType.LightMuted => maxMutesSaturation,
|
||||||
|
ColorType.DarkMuted => maxMutesSaturation,
|
||||||
|
_ => throw new ArgumentException(nameof(colorType))
|
||||||
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
40
src/Artemis.Core/Services/ColorQuantizer/ColorSwatch.cs
Normal file
40
src/Artemis.Core/Services/ColorQuantizer/ColorSwatch.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Artemis.Core.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Swatch containing the known useful color variations.
|
||||||
|
/// </summary>
|
||||||
|
public struct ColorSwatch
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="ColorType.Vibrant"/> component.
|
||||||
|
/// </summary>
|
||||||
|
public SKColor Vibrant { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="ColorType.LightVibrant"/> component.
|
||||||
|
/// </summary>
|
||||||
|
public SKColor LightVibrant { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="ColorType.DarkVibrant"/> component.
|
||||||
|
/// </summary>
|
||||||
|
public SKColor DarkVibrant { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="ColorType.Muted"/> component.
|
||||||
|
/// </summary>
|
||||||
|
public SKColor Muted { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="ColorType.LightMuted"/> component.
|
||||||
|
/// </summary>
|
||||||
|
public SKColor LightMuted { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="ColorType.DarkMuted"/> component.
|
||||||
|
/// </summary>
|
||||||
|
public SKColor DarkMuted { get; init; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -26,5 +26,13 @@ namespace Artemis.Core.Services
|
|||||||
/// <param name="ignoreLimits">Ignore hard limits on whether a color is considered for each category. Result may be <see cref="SKColor.Empty"/> if this is false</param>
|
/// <param name="ignoreLimits">Ignore hard limits on whether a color is considered for each category. Result may be <see cref="SKColor.Empty"/> if this is false</param>
|
||||||
/// <returns>The color found</returns>
|
/// <returns>The color found</returns>
|
||||||
public SKColor FindColorVariation(IEnumerable<SKColor> colors, ColorType type, bool ignoreLimits = false);
|
public SKColor FindColorVariation(IEnumerable<SKColor> colors, ColorType type, bool ignoreLimits = false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds all the color variations available and returns a struct containing them all.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="colors">The colors to find the variations in</param>
|
||||||
|
/// <param name="ignoreLimits">Ignore hard limits on whether a color is considered for each category. Some colors may be <see cref="SKColor.Empty"/> if this is false</param>
|
||||||
|
/// <returns>A swatch containing all color variations</returns>
|
||||||
|
public ColorSwatch FindAllColorVariations(IEnumerable<SKColor> colors, bool ignoreLimits = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.Ninject;
|
using Artemis.Core.Ninject;
|
||||||
using Artemis.Core.ScriptingProviders;
|
using Artemis.Core.ScriptingProviders;
|
||||||
@ -13,7 +14,6 @@ using RGB.NET.Core;
|
|||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
using Module = Artemis.Core.Modules.Module;
|
|
||||||
|
|
||||||
namespace Artemis.Core.Services
|
namespace Artemis.Core.Services
|
||||||
{
|
{
|
||||||
@ -59,7 +59,6 @@ namespace Artemis.Core.Services
|
|||||||
_frameStopWatch = new Stopwatch();
|
_frameStopWatch = new Stopwatch();
|
||||||
StartupArguments = new List<string>();
|
StartupArguments = new List<string>();
|
||||||
|
|
||||||
_rgbService.IsRenderPaused = true;
|
|
||||||
_rgbService.Surface.Updating += SurfaceOnUpdating;
|
_rgbService.Surface.Updating += SurfaceOnUpdating;
|
||||||
_loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel();
|
_loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel();
|
||||||
}
|
}
|
||||||
@ -107,6 +106,13 @@ namespace Artemis.Core.Services
|
|||||||
if (_rgbService.IsRenderPaused)
|
if (_rgbService.IsRenderPaused)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (_rgbService.FlushLeds)
|
||||||
|
{
|
||||||
|
_rgbService.FlushLeds = false;
|
||||||
|
_rgbService.Surface.Update(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_frameStopWatch.Restart();
|
_frameStopWatch.Restart();
|
||||||
@ -214,7 +220,7 @@ namespace Artemis.Core.Services
|
|||||||
_pluginManagementService.CopyBuiltInPlugins();
|
_pluginManagementService.CopyBuiltInPlugins();
|
||||||
_pluginManagementService.LoadPlugins(StartupArguments, IsElevated);
|
_pluginManagementService.LoadPlugins(StartupArguments, IsElevated);
|
||||||
|
|
||||||
_rgbService.IsRenderPaused = false;
|
_rgbService.SetRenderPaused(false);
|
||||||
OnInitialized();
|
OnInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,12 +34,17 @@ namespace Artemis.Core.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets whether rendering should be paused
|
/// Gets or sets whether rendering should be paused
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsRenderPaused { get; set; }
|
bool IsRenderPaused { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether the render pipeline is open
|
/// Gets a boolean indicating whether the render pipeline is open
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool RenderOpen { get; }
|
bool RenderOpen { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a boolean indicating whether to flush the RGB.NET LEDs during next update
|
||||||
|
/// </summary>
|
||||||
|
bool FlushLeds { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the render pipeline
|
/// Opens the render pipeline
|
||||||
@ -133,6 +138,13 @@ namespace Artemis.Core.Services
|
|||||||
/// <param name="device">The device to disable</param>
|
/// <param name="device">The device to disable</param>
|
||||||
void DisableDevice(ArtemisDevice device);
|
void DisableDevice(ArtemisDevice device);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pauses or resumes rendering, method won't return until the current frame finished rendering
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="paused"></param>
|
||||||
|
/// <returns><see langword="true"/> if the pause state was changed; otherwise <see langword="false"/>.</returns>
|
||||||
|
bool SetRenderPaused(bool paused);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when a single device was added
|
/// Occurs when a single device was added
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -5,6 +5,7 @@ using System.IO;
|
|||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.DeviceProviders;
|
using Artemis.Core.DeviceProviders;
|
||||||
using Artemis.Core.Ninject;
|
using Artemis.Core.Ninject;
|
||||||
using Artemis.Storage.Entities.General;
|
using Artemis.Storage.Entities.General;
|
||||||
@ -90,11 +91,6 @@ namespace Artemis.Core.Services
|
|||||||
using StreamReader reader = new(metaDataFileEntry.Open());
|
using StreamReader reader = new(metaDataFileEntry.Open());
|
||||||
PluginInfo builtInPluginInfo = CoreJson.DeserializeObject<PluginInfo>(reader.ReadToEnd())!;
|
PluginInfo builtInPluginInfo = CoreJson.DeserializeObject<PluginInfo>(reader.ReadToEnd())!;
|
||||||
string preferred = builtInPluginInfo.PreferredPluginDirectory;
|
string preferred = builtInPluginInfo.PreferredPluginDirectory;
|
||||||
string oldPreferred = Path.GetFileNameWithoutExtension(zipFile.Name);
|
|
||||||
// Rename folders to the new format
|
|
||||||
// TODO: Get rid of this eventually, it's nice to keep around but it's extra IO that's best avoided
|
|
||||||
if (pluginDirectory.EnumerateDirectories().FirstOrDefault(d => d.Name == oldPreferred) != null)
|
|
||||||
Directory.Move(Path.Combine(pluginDirectory.FullName, oldPreferred), Path.Combine(pluginDirectory.FullName, preferred));
|
|
||||||
|
|
||||||
// Find the matching plugin in the plugin folder
|
// Find the matching plugin in the plugin folder
|
||||||
DirectoryInfo? match = pluginDirectory.EnumerateDirectories().FirstOrDefault(d => d.Name == preferred);
|
DirectoryInfo? match = pluginDirectory.EnumerateDirectories().FirstOrDefault(d => d.Name == preferred);
|
||||||
@ -431,6 +427,7 @@ namespace Artemis.Core.Services
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Warning(new ArtemisPluginException(plugin, "Failed to instantiate feature", e), "Failed to instantiate feature", plugin);
|
_logger.Warning(new ArtemisPluginException(plugin, "Failed to instantiate feature", e), "Failed to instantiate feature", plugin);
|
||||||
|
featureInfo.LoadException = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,10 +611,38 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
if (isAutoEnable)
|
||||||
new ArtemisPluginException(pluginFeature.Plugin, $"Exception during SetEnabled(true) on {pluginFeature}", e),
|
{
|
||||||
"Failed to enable plugin"
|
// Schedule a retry based on the amount of attempts
|
||||||
);
|
if (pluginFeature.AutoEnableAttempts < 4)
|
||||||
|
{
|
||||||
|
TimeSpan retryDelay = TimeSpan.FromSeconds(pluginFeature.AutoEnableAttempts * 10);
|
||||||
|
_logger.Warning(
|
||||||
|
e,
|
||||||
|
"Plugin feature '{feature} - {plugin}' failed to enable during attempt ({attempt}/3), scheduling a retry in {retryDelay}.",
|
||||||
|
pluginFeature,
|
||||||
|
pluginFeature.Plugin,
|
||||||
|
pluginFeature.AutoEnableAttempts,
|
||||||
|
retryDelay
|
||||||
|
);
|
||||||
|
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(retryDelay);
|
||||||
|
if (!pluginFeature.IsEnabled)
|
||||||
|
EnablePluginFeature(pluginFeature, saveState, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Warning(e, "Plugin feature '{feature} - {plugin}' failed to enable after 3 attempts, giving up.", pluginFeature, pluginFeature.Plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Warning(e, "Plugin feature '{feature} - {plugin}' failed to enable.", pluginFeature, pluginFeature.Plugin);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Artemis.Core.DeviceProviders;
|
using Artemis.Core.DeviceProviders;
|
||||||
@ -28,7 +27,6 @@ namespace Artemis.Core.Services
|
|||||||
private readonly PluginSetting<int> _targetFrameRateSetting;
|
private readonly PluginSetting<int> _targetFrameRateSetting;
|
||||||
private readonly TextureBrush _textureBrush = new(ITexture.Empty) {CalculationMode = RenderMode.Absolute};
|
private readonly TextureBrush _textureBrush = new(ITexture.Empty) {CalculationMode = RenderMode.Absolute};
|
||||||
private Dictionary<Led, ArtemisLed> _ledMap;
|
private Dictionary<Led, ArtemisLed> _ledMap;
|
||||||
private bool _modifyingProviders;
|
|
||||||
private ListLedGroup? _surfaceLedGroup;
|
private ListLedGroup? _surfaceLedGroup;
|
||||||
private SKTexture? _texture;
|
private SKTexture? _texture;
|
||||||
|
|
||||||
@ -52,8 +50,9 @@ namespace Artemis.Core.Services
|
|||||||
_ledMap = new Dictionary<Led, ArtemisLed>();
|
_ledMap = new Dictionary<Led, ArtemisLed>();
|
||||||
|
|
||||||
UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value};
|
UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value};
|
||||||
|
SetRenderPaused(true);
|
||||||
Surface.RegisterUpdateTrigger(UpdateTrigger);
|
Surface.RegisterUpdateTrigger(UpdateTrigger);
|
||||||
|
|
||||||
Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
|
Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,16 +81,14 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
private void UpdateLedGroup()
|
private void UpdateLedGroup()
|
||||||
{
|
{
|
||||||
lock (_devices)
|
bool changedRenderPaused = SetRenderPaused(true);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (_modifyingProviders)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_ledMap = new Dictionary<Led, ArtemisLed>(_devices.SelectMany(d => d.Leds).ToDictionary(l => l.RgbLed));
|
_ledMap = new Dictionary<Led, ArtemisLed>(_devices.SelectMany(d => d.Leds).ToDictionary(l => l.RgbLed));
|
||||||
|
|
||||||
if (_surfaceLedGroup == null)
|
if (_surfaceLedGroup == null)
|
||||||
{
|
{
|
||||||
_surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) {Brush = _textureBrush};
|
_surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) { Brush = _textureBrush };
|
||||||
OnLedsChanged();
|
OnLedsChanged();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -102,10 +99,16 @@ namespace Artemis.Core.Services
|
|||||||
_surfaceLedGroup.Detach();
|
_surfaceLedGroup.Detach();
|
||||||
|
|
||||||
// Apply the application wide brush and decorator
|
// Apply the application wide brush and decorator
|
||||||
_surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) {Brush = _textureBrush};
|
_surfaceLedGroup = new ListLedGroup(Surface, LedMap.Select(l => l.Key)) { Brush = _textureBrush };
|
||||||
OnLedsChanged();
|
OnLedsChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (changedRenderPaused)
|
||||||
|
SetRenderPaused(false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TargetFrameRateSettingOnSettingChanged(object? sender, EventArgs e)
|
private void TargetFrameRateSettingOnSettingChanged(object? sender, EventArgs e)
|
||||||
@ -137,91 +140,90 @@ namespace Artemis.Core.Services
|
|||||||
public bool IsRenderPaused { get; set; }
|
public bool IsRenderPaused { get; set; }
|
||||||
public bool RenderOpen { get; private set; }
|
public bool RenderOpen { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool FlushLeds { get; set; }
|
||||||
|
|
||||||
public void AddDeviceProvider(IRGBDeviceProvider deviceProvider)
|
public void AddDeviceProvider(IRGBDeviceProvider deviceProvider)
|
||||||
{
|
{
|
||||||
lock (_devices)
|
bool changedRenderPaused = SetRenderPaused(true);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
|
||||||
|
Surface.Detach(toRemove.Select(d => d.RgbDevice));
|
||||||
|
foreach (ArtemisDevice device in toRemove)
|
||||||
|
RemoveDevice(device);
|
||||||
|
|
||||||
|
List<Exception> providerExceptions = new();
|
||||||
|
|
||||||
|
void DeviceProviderOnException(object? sender, ExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
_modifyingProviders = true;
|
if (e.IsCritical)
|
||||||
|
providerExceptions.Add(e.Exception);
|
||||||
List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
|
else
|
||||||
Surface.Detach(toRemove.Select(d => d.RgbDevice));
|
_logger.Warning(e.Exception, "Device provider {deviceProvider} threw non-critical exception", deviceProvider.GetType().Name);
|
||||||
foreach (ArtemisDevice device in toRemove)
|
|
||||||
RemoveDevice(device);
|
|
||||||
|
|
||||||
List<Exception> providerExceptions = new();
|
|
||||||
|
|
||||||
void DeviceProviderOnException(object? sender, ExceptionEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.IsCritical)
|
|
||||||
providerExceptions.Add(e.Exception);
|
|
||||||
else
|
|
||||||
_logger.Warning(e.Exception, "Device provider {deviceProvider} threw non-critical exception", deviceProvider.GetType().Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceProvider.Exception += DeviceProviderOnException;
|
|
||||||
deviceProvider.Initialize();
|
|
||||||
Surface.Attach(deviceProvider.Devices);
|
|
||||||
deviceProvider.Exception -= DeviceProviderOnException;
|
|
||||||
if (providerExceptions.Count == 1)
|
|
||||||
throw new ArtemisPluginException("RGB.NET threw exception: " + providerExceptions.First().Message, providerExceptions.First());
|
|
||||||
if (providerExceptions.Count > 1)
|
|
||||||
throw new ArtemisPluginException("RGB.NET threw multiple exceptions", new AggregateException(providerExceptions));
|
|
||||||
|
|
||||||
if (!deviceProvider.Devices.Any())
|
|
||||||
{
|
|
||||||
_logger.Warning("Device provider {deviceProvider} has no devices", deviceProvider.GetType().Name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (IRGBDevice rgbDevice in deviceProvider.Devices)
|
|
||||||
{
|
|
||||||
ArtemisDevice artemisDevice = GetArtemisDevice(rgbDevice);
|
|
||||||
AddDevice(artemisDevice);
|
|
||||||
_logger.Debug("Device provider {deviceProvider} added {deviceName}", deviceProvider.GetType().Name, rgbDevice.DeviceInfo.DeviceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
_devices.Sort((a, b) => a.ZIndex - b.ZIndex);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
|
||||||
|
deviceProvider.Exception += DeviceProviderOnException;
|
||||||
|
deviceProvider.Initialize();
|
||||||
|
Surface.Attach(deviceProvider.Devices);
|
||||||
|
deviceProvider.Exception -= DeviceProviderOnException;
|
||||||
|
if (providerExceptions.Count == 1)
|
||||||
|
throw new ArtemisPluginException("RGB.NET threw exception: " + providerExceptions.First().Message, providerExceptions.First());
|
||||||
|
if (providerExceptions.Count > 1)
|
||||||
|
throw new ArtemisPluginException("RGB.NET threw multiple exceptions", new AggregateException(providerExceptions));
|
||||||
|
|
||||||
|
if (!deviceProvider.Devices.Any())
|
||||||
{
|
{
|
||||||
_logger.Error(e, "Exception during device loading for device provider {deviceProvider}", deviceProvider.GetType().Name);
|
_logger.Warning("Device provider {deviceProvider} has no devices", deviceProvider.GetType().Name);
|
||||||
throw;
|
return;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
|
foreach (IRGBDevice rgbDevice in deviceProvider.Devices)
|
||||||
{
|
{
|
||||||
_modifyingProviders = false;
|
ArtemisDevice artemisDevice = GetArtemisDevice(rgbDevice);
|
||||||
UpdateLedGroup();
|
AddDevice(artemisDevice);
|
||||||
|
_logger.Debug("Device provider {deviceProvider} added {deviceName}", deviceProvider.GetType().Name, rgbDevice.DeviceInfo.DeviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_devices.Sort((a, b) => a.ZIndex - b.ZIndex);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Error(e, "Exception during device loading for device provider {deviceProvider}", deviceProvider.GetType().Name);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
UpdateLedGroup();
|
||||||
|
if (changedRenderPaused)
|
||||||
|
SetRenderPaused(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveDeviceProvider(IRGBDeviceProvider deviceProvider)
|
public void RemoveDeviceProvider(IRGBDeviceProvider deviceProvider)
|
||||||
{
|
{
|
||||||
lock (_devices)
|
bool changedRenderPaused = SetRenderPaused(true);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
|
||||||
{
|
Surface.Detach(toRemove.Select(d => d.RgbDevice));
|
||||||
_modifyingProviders = true;
|
foreach (ArtemisDevice device in toRemove)
|
||||||
|
RemoveDevice(device);
|
||||||
|
|
||||||
List<ArtemisDevice> toRemove = _devices.Where(a => deviceProvider.Devices.Any(d => a.RgbDevice == d)).ToList();
|
_devices.Sort((a, b) => a.ZIndex - b.ZIndex);
|
||||||
Surface.Detach(toRemove.Select(d => d.RgbDevice));
|
}
|
||||||
foreach (ArtemisDevice device in toRemove)
|
catch (Exception e)
|
||||||
RemoveDevice(device);
|
{
|
||||||
|
_logger.Error(e, "Exception during device removal for device provider {deviceProvider}", deviceProvider.GetType().Name);
|
||||||
_devices.Sort((a, b) => a.ZIndex - b.ZIndex);
|
throw;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
finally
|
||||||
{
|
{
|
||||||
_logger.Error(e, "Exception during device removal for device provider {deviceProvider}", deviceProvider.GetType().Name);
|
UpdateLedGroup();
|
||||||
throw;
|
if (changedRenderPaused)
|
||||||
}
|
SetRenderPaused(false);
|
||||||
finally
|
|
||||||
{
|
|
||||||
_modifyingProviders = false;
|
|
||||||
UpdateLedGroup();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,6 +235,24 @@ namespace Artemis.Core.Services
|
|||||||
Surface.Dispose();
|
Surface.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool SetRenderPaused(bool paused)
|
||||||
|
{
|
||||||
|
if (IsRenderPaused == paused)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (paused)
|
||||||
|
{
|
||||||
|
UpdateTrigger.Stop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateTrigger.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
IsRenderPaused = paused;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public event EventHandler<DeviceEventArgs>? DeviceAdded;
|
public event EventHandler<DeviceEventArgs>? DeviceAdded;
|
||||||
public event EventHandler<DeviceEventArgs>? DeviceRemoved;
|
public event EventHandler<DeviceEventArgs>? DeviceRemoved;
|
||||||
public event EventHandler? LedsChanged;
|
public event EventHandler? LedsChanged;
|
||||||
@ -267,36 +287,39 @@ namespace Artemis.Core.Services
|
|||||||
if (RenderOpen)
|
if (RenderOpen)
|
||||||
throw new ArtemisCoreException("Cannot update the texture while rendering");
|
throw new ArtemisCoreException("Cannot update the texture while rendering");
|
||||||
|
|
||||||
IManagedGraphicsContext? graphicsContext = Constants.ManagedGraphicsContext = _newGraphicsContext;
|
lock (_devices)
|
||||||
if (!ReferenceEquals(graphicsContext, _newGraphicsContext))
|
|
||||||
graphicsContext = _newGraphicsContext;
|
|
||||||
|
|
||||||
if (graphicsContext != null)
|
|
||||||
_logger.Debug("Creating SKTexture with graphics context {graphicsContext}", graphicsContext.GetType().Name);
|
|
||||||
else
|
|
||||||
_logger.Debug("Creating SKTexture with software-based graphics context");
|
|
||||||
|
|
||||||
float evenWidth = Surface.Boundary.Size.Width;
|
|
||||||
if (evenWidth % 2 != 0)
|
|
||||||
evenWidth++;
|
|
||||||
float evenHeight = Surface.Boundary.Size.Height;
|
|
||||||
if (evenHeight % 2 != 0)
|
|
||||||
evenHeight++;
|
|
||||||
|
|
||||||
float renderScale = (float) _renderScaleSetting.Value;
|
|
||||||
int width = Math.Max(1, MathF.Min(evenWidth * renderScale, 4096).RoundToInt());
|
|
||||||
int height = Math.Max(1, MathF.Min(evenHeight * renderScale, 4096).RoundToInt());
|
|
||||||
|
|
||||||
_texture?.Dispose();
|
|
||||||
_texture = new SKTexture(graphicsContext, width, height, renderScale);
|
|
||||||
_textureBrush.Texture = _texture;
|
|
||||||
|
|
||||||
|
|
||||||
if (!ReferenceEquals(_newGraphicsContext, Constants.ManagedGraphicsContext = _newGraphicsContext))
|
|
||||||
{
|
{
|
||||||
Constants.ManagedGraphicsContext?.Dispose();
|
IManagedGraphicsContext? graphicsContext = Constants.ManagedGraphicsContext = _newGraphicsContext;
|
||||||
Constants.ManagedGraphicsContext = _newGraphicsContext;
|
if (!ReferenceEquals(graphicsContext, _newGraphicsContext))
|
||||||
_newGraphicsContext = null;
|
graphicsContext = _newGraphicsContext;
|
||||||
|
|
||||||
|
if (graphicsContext != null)
|
||||||
|
_logger.Debug("Creating SKTexture with graphics context {graphicsContext}", graphicsContext.GetType().Name);
|
||||||
|
else
|
||||||
|
_logger.Debug("Creating SKTexture with software-based graphics context");
|
||||||
|
|
||||||
|
float evenWidth = Surface.Boundary.Size.Width;
|
||||||
|
if (evenWidth % 2 != 0)
|
||||||
|
evenWidth++;
|
||||||
|
float evenHeight = Surface.Boundary.Size.Height;
|
||||||
|
if (evenHeight % 2 != 0)
|
||||||
|
evenHeight++;
|
||||||
|
|
||||||
|
float renderScale = (float) _renderScaleSetting.Value;
|
||||||
|
int width = Math.Max(1, MathF.Min(evenWidth * renderScale, 4096).RoundToInt());
|
||||||
|
int height = Math.Max(1, MathF.Min(evenHeight * renderScale, 4096).RoundToInt());
|
||||||
|
|
||||||
|
_texture?.Dispose();
|
||||||
|
_texture = new SKTexture(graphicsContext, width, height, renderScale);
|
||||||
|
_textureBrush.Texture = _texture;
|
||||||
|
|
||||||
|
|
||||||
|
if (!ReferenceEquals(_newGraphicsContext, Constants.ManagedGraphicsContext = _newGraphicsContext))
|
||||||
|
{
|
||||||
|
Constants.ManagedGraphicsContext?.Dispose();
|
||||||
|
Constants.ManagedGraphicsContext = _newGraphicsContext;
|
||||||
|
_newGraphicsContext = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,12 +338,22 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
public void AutoArrangeDevices()
|
public void AutoArrangeDevices()
|
||||||
{
|
{
|
||||||
SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement();
|
bool changedRenderPaused = SetRenderPaused(true);
|
||||||
surfaceArrangement.Arrange(_devices);
|
|
||||||
foreach (ArtemisDevice artemisDevice in _devices)
|
|
||||||
artemisDevice.ApplyDefaultCategories();
|
|
||||||
|
|
||||||
SaveDevices();
|
try
|
||||||
|
{
|
||||||
|
SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement();
|
||||||
|
surfaceArrangement.Arrange(_devices);
|
||||||
|
foreach (ArtemisDevice artemisDevice in _devices)
|
||||||
|
artemisDevice.ApplyDefaultCategories();
|
||||||
|
|
||||||
|
SaveDevices();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (changedRenderPaused)
|
||||||
|
SetRenderPaused(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisLayout? ApplyBestDeviceLayout(ArtemisDevice device)
|
public ArtemisLayout? ApplyBestDeviceLayout(ArtemisDevice device)
|
||||||
@ -391,7 +424,7 @@ namespace Artemis.Core.Services
|
|||||||
_deviceRepository.Save(device.DeviceEntity);
|
_deviceRepository.Save(device.DeviceEntity);
|
||||||
|
|
||||||
DeviceProvider deviceProvider = device.DeviceProvider;
|
DeviceProvider deviceProvider = device.DeviceProvider;
|
||||||
|
|
||||||
// Feels bad but need to in order to get the initial LEDs back
|
// Feels bad but need to in order to get the initial LEDs back
|
||||||
_pluginManagementService.DisablePluginFeature(deviceProvider, false);
|
_pluginManagementService.DisablePluginFeature(deviceProvider, false);
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
|
|||||||
@ -18,8 +18,8 @@ namespace Artemis.Core
|
|||||||
public static void PrepareFirstLaunch()
|
public static void PrepareFirstLaunch()
|
||||||
{
|
{
|
||||||
CreateAccessibleDirectory(Constants.DataFolder);
|
CreateAccessibleDirectory(Constants.DataFolder);
|
||||||
CreateAccessibleDirectory(Constants.DataFolder + "plugins");
|
CreateAccessibleDirectory(Path.Combine(Constants.DataFolder ,"plugins"));
|
||||||
CreateAccessibleDirectory(Constants.DataFolder + "user layouts");
|
CreateAccessibleDirectory(Path.Combine(Constants.DataFolder ,"user layouts"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -81,14 +81,11 @@
|
|||||||
},
|
},
|
||||||
"Serilog.Sinks.Console": {
|
"Serilog.Sinks.Console": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[3.1.1, )",
|
"requested": "[4.0.0, )",
|
||||||
"resolved": "3.1.1",
|
"resolved": "4.0.0",
|
||||||
"contentHash": "56mI5AqvyF/i/c2451nvV71kq370XOCE4Uu5qiaJ295sOhMb9q3BWwG7mWLOVSnmpWiq0SBT3SXfgRXGNP6vzA==",
|
"contentHash": "yJQit9sTJ4xGLKgCujqDJsaGqBNJwGB/H898z+xYlMG06twy4//6LLnSrsmpduZxcHIG4im7cv+JmXLzXz2EkQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Serilog": "2.5.0",
|
"Serilog": "2.10.0"
|
||||||
"System.Console": "4.3.0",
|
|
||||||
"System.Runtime.InteropServices": "4.3.0",
|
|
||||||
"System.Runtime.InteropServices.RuntimeInformation": "4.3.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Serilog.Sinks.Debug": {
|
"Serilog.Sinks.Debug": {
|
||||||
@ -102,21 +99,18 @@
|
|||||||
},
|
},
|
||||||
"Serilog.Sinks.File": {
|
"Serilog.Sinks.File": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[4.1.0, )",
|
"requested": "[5.0.0, )",
|
||||||
"resolved": "4.1.0",
|
"resolved": "5.0.0",
|
||||||
"contentHash": "U0b34w+ZikbqWEZ3ui7BdzxY/19zwrdhLtI3o6tfmLdD3oXxg7n2TZJjwCCTlKPgRuYic9CBWfrZevbb70mTaw==",
|
"contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Serilog": "2.5.0",
|
"Serilog": "2.10.0"
|
||||||
"System.IO.FileSystem": "4.0.1",
|
|
||||||
"System.Text.Encoding.Extensions": "4.0.11",
|
|
||||||
"System.Threading.Timer": "4.0.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"SkiaSharp": {
|
"SkiaSharp": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[2.80.2, )",
|
"requested": "[2.80.3, )",
|
||||||
"resolved": "2.80.2",
|
"resolved": "2.80.3",
|
||||||
"contentHash": "D25rzdCwh+3L+XyXqpNa+H/yiLJbE3/R3K/XexwHyQjGdzZvSufFW3oqf3En7hhqSIsxsJ8f5NEZ0J5W5wlGBg==",
|
"contentHash": "qX6tGNP3+MXNYe2pKm0PCRiJ/cx+LTeLaggwZifB7sUMXhECfKKKHJq45VqZKt37xQegnCCdf1jHXwmHeJQs5Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Memory": "4.5.3"
|
"System.Memory": "4.5.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,11 +19,11 @@ namespace Artemis.Storage
|
|||||||
if (_inUse)
|
if (_inUse)
|
||||||
throw new Exception("Storage is already in use, can't backup now.");
|
throw new Exception("Storage is already in use, can't backup now.");
|
||||||
|
|
||||||
string database = $"{dataFolder}\\database.db";
|
string database = Path.Combine(dataFolder, "database.db");
|
||||||
if (!File.Exists(database))
|
if (!File.Exists(database))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string backupFolder = $"{dataFolder}\\database backups";
|
string backupFolder = Path.Combine(dataFolder, "database backups");
|
||||||
Directory.CreateDirectory(backupFolder);
|
Directory.CreateDirectory(backupFolder);
|
||||||
FileSystemInfo[] files = new DirectoryInfo(backupFolder).GetFileSystemInfos();
|
FileSystemInfo[] files = new DirectoryInfo(backupFolder).GetFileSystemInfos();
|
||||||
if (files.Length >= 5)
|
if (files.Length >= 5)
|
||||||
@ -36,7 +36,7 @@ namespace Artemis.Storage
|
|||||||
oldest.Delete();
|
oldest.Delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
File.Copy(database, $"{backupFolder}\\database-{DateTime.Now:yyyy-dd-M--HH-mm-ss}.db");
|
File.Copy(database, Path.Combine(backupFolder, $"database-{DateTime.Now:yyyy-dd-M--HH-mm-ss}.db"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -51,7 +51,7 @@ namespace Artemis.Storage
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_inUse = true;
|
_inUse = true;
|
||||||
return new LiteRepository($"FileName={dataFolder}\\database.db");
|
return new LiteRepository($"FileName={Path.Combine(dataFolder, "database.db")}");
|
||||||
}
|
}
|
||||||
catch (LiteException e)
|
catch (LiteException e)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -40,8 +40,8 @@
|
|||||||
<PackageReference Include="Ninject" Version="3.3.4" />
|
<PackageReference Include="Ninject" Version="3.3.4" />
|
||||||
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" />
|
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" />
|
||||||
<PackageReference Include="SharpVectors.Reloaded" Version="1.7.5" />
|
<PackageReference Include="SharpVectors.Reloaded" Version="1.7.5" />
|
||||||
<PackageReference Include="SkiaSharp" Version="2.80.2" />
|
<PackageReference Include="SkiaSharp" Version="2.80.3" />
|
||||||
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" />
|
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.3" />
|
||||||
<PackageReference Include="Stylet" Version="1.3.6" />
|
<PackageReference Include="Stylet" Version="1.3.6" />
|
||||||
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
|
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
|
||||||
|
|||||||
@ -60,21 +60,21 @@
|
|||||||
},
|
},
|
||||||
"SkiaSharp": {
|
"SkiaSharp": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[2.80.2, )",
|
"requested": "[2.80.3, )",
|
||||||
"resolved": "2.80.2",
|
"resolved": "2.80.3",
|
||||||
"contentHash": "D25rzdCwh+3L+XyXqpNa+H/yiLJbE3/R3K/XexwHyQjGdzZvSufFW3oqf3En7hhqSIsxsJ8f5NEZ0J5W5wlGBg==",
|
"contentHash": "qX6tGNP3+MXNYe2pKm0PCRiJ/cx+LTeLaggwZifB7sUMXhECfKKKHJq45VqZKt37xQegnCCdf1jHXwmHeJQs5Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Memory": "4.5.3"
|
"System.Memory": "4.5.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"SkiaSharp.Views.WPF": {
|
"SkiaSharp.Views.WPF": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[2.80.2, )",
|
"requested": "[2.80.3, )",
|
||||||
"resolved": "2.80.2",
|
"resolved": "2.80.3",
|
||||||
"contentHash": "Fzo2+MNwHDh9Cob8sk7OO26kp3bhofjXMwlEK8IncF1ehu9hi3sH9iQDJrue9a88VEJJ+yyLISPUFcmXlGHSyQ==",
|
"contentHash": "oKUMm7WzFeoie6rW5nnwSGKZ94misyRsAc1wU6SEqgd6ssW17nyfohHxHuBHtmpLtIRwvjhfAu3cMLrpX/oNcw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"SkiaSharp": "2.80.2",
|
"SkiaSharp": "2.80.3",
|
||||||
"SkiaSharp.Views.Desktop.Common": "2.80.2"
|
"SkiaSharp.Views.Desktop.Common": "2.80.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Stylet": {
|
"Stylet": {
|
||||||
@ -378,13 +378,10 @@
|
|||||||
},
|
},
|
||||||
"Serilog.Sinks.Console": {
|
"Serilog.Sinks.Console": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "3.1.1",
|
"resolved": "4.0.0",
|
||||||
"contentHash": "56mI5AqvyF/i/c2451nvV71kq370XOCE4Uu5qiaJ295sOhMb9q3BWwG7mWLOVSnmpWiq0SBT3SXfgRXGNP6vzA==",
|
"contentHash": "yJQit9sTJ4xGLKgCujqDJsaGqBNJwGB/H898z+xYlMG06twy4//6LLnSrsmpduZxcHIG4im7cv+JmXLzXz2EkQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Serilog": "2.5.0",
|
"Serilog": "2.10.0"
|
||||||
"System.Console": "4.3.0",
|
|
||||||
"System.Runtime.InteropServices": "4.3.0",
|
|
||||||
"System.Runtime.InteropServices.RuntimeInformation": "4.3.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Serilog.Sinks.Debug": {
|
"Serilog.Sinks.Debug": {
|
||||||
@ -397,21 +394,19 @@
|
|||||||
},
|
},
|
||||||
"Serilog.Sinks.File": {
|
"Serilog.Sinks.File": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "4.1.0",
|
"resolved": "5.0.0",
|
||||||
"contentHash": "U0b34w+ZikbqWEZ3ui7BdzxY/19zwrdhLtI3o6tfmLdD3oXxg7n2TZJjwCCTlKPgRuYic9CBWfrZevbb70mTaw==",
|
"contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Serilog": "2.5.0",
|
"Serilog": "2.10.0"
|
||||||
"System.IO.FileSystem": "4.0.1",
|
|
||||||
"System.Text.Encoding.Extensions": "4.0.11",
|
|
||||||
"System.Threading.Timer": "4.0.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"SkiaSharp.Views.Desktop.Common": {
|
"SkiaSharp.Views.Desktop.Common": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "2.80.2",
|
"resolved": "2.80.3",
|
||||||
"contentHash": "0vBvweMysgl1wgjuTQUhdJMD5z5nBjtYqmnHPeX+qHfkc336Wj2L3jEqwmGb0YP+RV47gFGz0EzMAW6szZch9w==",
|
"contentHash": "CMQu9fr3BxGRsRryDC6lkYbYaSI2CI+RqisFX0WIdbOdbigUOLhqchmKIMb4EdFAZk13vk862qiE9v97iDZS7g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"SkiaSharp": "2.80.2"
|
"SkiaSharp": "2.80.3",
|
||||||
|
"System.Drawing.Common": "4.5.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.AppContext": {
|
"System.AppContext": {
|
||||||
@ -1309,10 +1304,10 @@
|
|||||||
"Ninject.Extensions.ChildKernel": "3.3.0",
|
"Ninject.Extensions.ChildKernel": "3.3.0",
|
||||||
"Ninject.Extensions.Conventions": "3.3.0",
|
"Ninject.Extensions.Conventions": "3.3.0",
|
||||||
"Serilog": "2.10.0",
|
"Serilog": "2.10.0",
|
||||||
"Serilog.Sinks.Console": "3.1.1",
|
"Serilog.Sinks.Console": "4.0.0",
|
||||||
"Serilog.Sinks.Debug": "2.0.0",
|
"Serilog.Sinks.Debug": "2.0.0",
|
||||||
"Serilog.Sinks.File": "4.1.0",
|
"Serilog.Sinks.File": "5.0.0",
|
||||||
"SkiaSharp": "2.80.2",
|
"SkiaSharp": "2.80.3",
|
||||||
"System.Buffers": "4.5.1",
|
"System.Buffers": "4.5.1",
|
||||||
"System.IO.FileSystem.AccessControl": "5.0.0",
|
"System.IO.FileSystem.AccessControl": "5.0.0",
|
||||||
"System.Numerics.Vectors": "4.5.0",
|
"System.Numerics.Vectors": "4.5.0",
|
||||||
|
|||||||
@ -92,7 +92,10 @@ namespace Artemis.UI
|
|||||||
using HttpClient client = new();
|
using HttpClient client = new();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpResponseMessage httpResponseMessage = client.Send(new HttpRequestMessage(HttpMethod.Post, url + "remote/bring-to-foreground"));
|
CancellationTokenSource cts = new();
|
||||||
|
cts.CancelAfter(2000);
|
||||||
|
|
||||||
|
HttpResponseMessage httpResponseMessage = client.Send(new HttpRequestMessage(HttpMethod.Post, url + "remote/bring-to-foreground"), cts.Token);
|
||||||
httpResponseMessage.EnsureSuccessStatusCode();
|
httpResponseMessage.EnsureSuccessStatusCode();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -138,7 +138,7 @@
|
|||||||
<Resource Include="Resources\Images\Sidebar\sidebar-header.png" />
|
<Resource Include="Resources\Images\Sidebar\sidebar-header.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentValidation" Version="10.2.3" />
|
<PackageReference Include="FluentValidation" Version="10.3.0" />
|
||||||
<PackageReference Include="Flurl.Http" Version="3.2.0" />
|
<PackageReference Include="Flurl.Http" Version="3.2.0" />
|
||||||
<PackageReference Include="gong-wpf-dragdrop" Version="2.3.2" />
|
<PackageReference Include="gong-wpf-dragdrop" Version="2.3.2" />
|
||||||
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.18" />
|
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.18" />
|
||||||
@ -153,8 +153,8 @@
|
|||||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="3.1.0" />
|
<PackageReference Include="Ookii.Dialogs.Wpf" Version="3.1.0" />
|
||||||
<PackageReference Include="RawInput.Sharp" Version="0.0.4" />
|
<PackageReference Include="RawInput.Sharp" Version="0.0.4" />
|
||||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||||
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" />
|
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.3" />
|
||||||
<PackageReference Include="SkiaSharp.Vulkan.SharpVk" Version="2.80.2" />
|
<PackageReference Include="SkiaSharp.Vulkan.SharpVk" Version="2.80.3" />
|
||||||
<PackageReference Include="Stylet" Version="1.3.6" />
|
<PackageReference Include="Stylet" Version="1.3.6" />
|
||||||
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
|
|||||||
@ -38,199 +38,193 @@
|
|||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Image Source="{svgc:SvgImage Source=/Resources/Images/Logo/bow.svg}" Height="100" Width="100" />
|
<Image Source="{svgc:SvgImage Source=/Resources/Images/Logo/bow.svg}" Height="80" Width="80" />
|
||||||
<StackPanel Grid.Column="1" Margin="24 0 0 0" VerticalAlignment="Center">
|
<TextBlock Grid.Column="1" Margin="24 0 0 0" VerticalAlignment="Center" Style="{StaticResource MaterialDesignHeadline4TextBlock}" TextWrapping="Wrap">
|
||||||
<TextBlock Style="{StaticResource MaterialDesignHeadline4TextBlock}" TextWrapping="Wrap">
|
<Run Text="Welcome to Artemis, the unified" />
|
||||||
<Run Text="Welcome to Artemis, the unified" />
|
<Run Text="RGB">
|
||||||
<Run Text="RGB">
|
<Run.Foreground>
|
||||||
<Run.Foreground>
|
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
|
||||||
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
|
<GradientStop Color="#f19d25" />
|
||||||
<GradientStop Color="#f19d25" />
|
<GradientStop Color="#f63d3d" Offset="0.2" />
|
||||||
<GradientStop Color="#f63d3d" Offset="0.2" />
|
<GradientStop Color="#c93cec" Offset="0.4" />
|
||||||
<GradientStop Color="#c93cec" Offset="0.4" />
|
<GradientStop Color="#2667f4" Offset="0.6" />
|
||||||
<GradientStop Color="#2667f4" Offset="0.6" />
|
<GradientStop Color="#1cb6e7" Offset="0.8" />
|
||||||
<GradientStop Color="#1cb6e7" Offset="0.8" />
|
<GradientStop Color="#2df4b5" Offset="1" />
|
||||||
<GradientStop Color="#2df4b5" Offset="1" />
|
</LinearGradientBrush>
|
||||||
</LinearGradientBrush>
|
</Run.Foreground>
|
||||||
</Run.Foreground>
|
</Run>
|
||||||
</Run>
|
<Run Text="platform." />
|
||||||
<Run Text="platform." />
|
</TextBlock>
|
||||||
</TextBlock>
|
|
||||||
<Button Style="{StaticResource MaterialDesignFlatButton}"
|
|
||||||
Foreground="{StaticResource SecondaryHueMidBrush}"
|
|
||||||
materialDesign:RippleAssist.Feedback="{StaticResource SecondaryHueMidBrush}"
|
|
||||||
Command="{x:Static materialDesign:DrawerHost.OpenDrawerCommand}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="Binoculars" />
|
|
||||||
<TextBlock Margin="8 0 0 0">EXPLORE</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled"
|
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
Margin="0 0 0 32">
|
Margin="0 0 0 32">
|
||||||
|
<StackPanel>
|
||||||
<StackPanel Orientation="Horizontal">
|
<materialDesign:Card Width="840" Margin="8 16" Height="Auto">
|
||||||
<materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto">
|
|
||||||
<Grid VerticalAlignment="Stretch">
|
<Grid VerticalAlignment="Stretch">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="155" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="95" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="200" />
|
<ColumnDefinition Width="200" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<materialDesign:PackIcon Kind="Discord" Width="140" Height="140"
|
<materialDesign:PackIcon Kind="Plug" Width="140" Height="140" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||||
HorizontalAlignment="Center" VerticalAlignment="Center" />
|
|
||||||
<StackPanel Grid.Row="0" Grid.Column="1">
|
<StackPanel Grid.Row="0" Grid.Column="1">
|
||||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Have a chat</TextBlock>
|
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Plugins</TextBlock>
|
||||||
<TextBlock TextWrapping="Wrap" Margin="16 0 16 8"
|
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||||
|
TextWrapping="Wrap" Margin="16 0 16 8"
|
||||||
Foreground="{DynamicResource MaterialDesignBodyLight}"
|
Foreground="{DynamicResource MaterialDesignBodyLight}"
|
||||||
VerticalAlignment="Top">
|
VerticalAlignment="Top">
|
||||||
If you need help, have some feedback or have any other questions feel free to contact us through any of the
|
Artemis is built up using plugins. This means devices, brushes, effects and modules (for supporting games!) can all be added via plugins. <LineBreak /> <LineBreak />
|
||||||
following channels.
|
Under Settings > Plugins you can find your currently installed plugins, these default plugins are created by Artemis developers.
|
||||||
|
<LineBreak /> <LineBreak />
|
||||||
|
We're also keeping track of a list of third-party plugins on our wiki.
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0"
|
<Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0" BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8">
|
||||||
BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8">
|
|
||||||
<DockPanel>
|
|
||||||
<Grid Margin="8">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition />
|
|
||||||
<RowDefinition />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Button Style="{DynamicResource MaterialDesignFlatButton}"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
x:Name="GitHubButton" Command="{s:Action OpenUrl}"
|
|
||||||
CommandParameter="https://github.com/Artemis-RGB/Artemis">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="Github" />
|
|
||||||
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">GitHub</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Button Grid.Row="0" Style="{DynamicResource MaterialDesignFlatButton}"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
x:Name="WebsiteButton" Command="{s:Action OpenUrl}"
|
|
||||||
CommandParameter="https://artemis-rgb.com">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="Web" />
|
|
||||||
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Website</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Button Grid.Row="1" Style="{DynamicResource MaterialDesignFlatButton}"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
x:Name="DiscordButton" Command="{s:Action OpenUrl}"
|
|
||||||
CommandParameter="https://discordapp.com/invite/S3MVaC9">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="Discord" />
|
|
||||||
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Discord</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Button Grid.Row="1" Style="{DynamicResource MaterialDesignFlatButton}"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
x:Name="MailButton" Command="{s:Action OpenUrl}"
|
|
||||||
CommandParameter="mailto:spoinky.nl@gmail.com">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="Email" />
|
|
||||||
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">E-mail</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
</Grid>
|
|
||||||
</DockPanel>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
|
||||||
</materialDesign:Card>
|
|
||||||
<materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto">
|
|
||||||
<Grid VerticalAlignment="Stretch">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="155" />
|
|
||||||
<RowDefinition Height="95" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="200" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<materialDesign:PackIcon Kind="Github" Width="160" Height="160"
|
|
||||||
HorizontalAlignment="Center" VerticalAlignment="Center" />
|
|
||||||
<StackPanel Grid.Row="0" Grid.Column="1">
|
|
||||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Open Source</TextBlock>
|
|
||||||
<TextBlock TextWrapping="Wrap" Margin="16 0 16 8"
|
|
||||||
Foreground="{DynamicResource MaterialDesignBodyLight}"
|
|
||||||
VerticalAlignment="Top">
|
|
||||||
This project is completely open source. If you like it and want to say thanks you could hit the GitHub Star button,
|
|
||||||
I like numbers. You could even make plugins, there's a full documentation on the website
|
|
||||||
</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
<Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0"
|
|
||||||
BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8">
|
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<Button Style="{DynamicResource MaterialDesignFlatButton}"
|
<Button Style="{DynamicResource MaterialDesignFlatButton}"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
x:Name="DonateButton"
|
|
||||||
Command="{s:Action OpenUrl}"
|
Command="{s:Action OpenUrl}"
|
||||||
CommandParameter="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VQBAEJYUFLU4J">
|
CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/plugins">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<materialDesign:PackIcon Kind="Gift" />
|
<materialDesign:PackIcon Kind="OpenInBrowser" />
|
||||||
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Donate</TextBlock>
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Get more plugins</TextBlock>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Button>
|
</Button>
|
||||||
<TextBlock Foreground="{DynamicResource MaterialDesignBodyLight}"
|
<TextBlock Foreground="{DynamicResource MaterialDesignBodyLight}"
|
||||||
TextWrapping="Wrap"
|
TextWrapping="Wrap"
|
||||||
Margin="16"
|
Margin="16"
|
||||||
VerticalAlignment="Center">
|
VerticalAlignment="Center">
|
||||||
Feel like you want to make a donation? It would be gratefully received. Click the button to donate via PayPal.
|
Want more plugins? You can find them on our wiki.
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</materialDesign:Card>
|
</materialDesign:Card>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto">
|
||||||
|
<Grid VerticalAlignment="Stretch">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="175" />
|
||||||
|
<RowDefinition Height="95" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="200" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<materialDesign:PackIcon Kind="Discord" Width="140" Height="140"
|
||||||
|
HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||||
|
<StackPanel Grid.Row="0" Grid.Column="1">
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Have a chat</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||||
|
TextWrapping="Wrap" Margin="16 0 16 8"
|
||||||
|
Foreground="{DynamicResource MaterialDesignBodyLight}"
|
||||||
|
VerticalAlignment="Top">
|
||||||
|
If you need help, have some feedback or have any other questions feel free to contact us through any of the
|
||||||
|
following channels.
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
<Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0"
|
||||||
|
BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8">
|
||||||
|
<DockPanel>
|
||||||
|
<Grid Margin="8">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Button Style="{DynamicResource MaterialDesignFlatButton}"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
x:Name="GitHubButton" Command="{s:Action OpenUrl}"
|
||||||
|
CommandParameter="https://github.com/Artemis-RGB/Artemis">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<materialDesign:PackIcon Kind="Github" />
|
||||||
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">GitHub</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Grid.Row="0" Style="{DynamicResource MaterialDesignFlatButton}"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
x:Name="WebsiteButton" Command="{s:Action OpenUrl}"
|
||||||
|
CommandParameter="https://artemis-rgb.com">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<materialDesign:PackIcon Kind="Web" />
|
||||||
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Website</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Grid.Row="1" Style="{DynamicResource MaterialDesignFlatButton}"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
x:Name="DiscordButton" Command="{s:Action OpenUrl}"
|
||||||
|
CommandParameter="https://discordapp.com/invite/S3MVaC9">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<materialDesign:PackIcon Kind="Discord" />
|
||||||
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Discord</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Grid.Row="1" Style="{DynamicResource MaterialDesignFlatButton}"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
x:Name="MailButton" Command="{s:Action OpenUrl}"
|
||||||
|
CommandParameter="mailto:spoinky.nl@gmail.com">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<materialDesign:PackIcon Kind="Email" />
|
||||||
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">E-mail</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</DockPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</materialDesign:Card>
|
||||||
|
<materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto">
|
||||||
|
<Grid VerticalAlignment="Stretch">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="175" />
|
||||||
|
<RowDefinition Height="95" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="200" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<materialDesign:PackIcon Kind="Github" Width="160" Height="160"
|
||||||
|
HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||||
|
<StackPanel Grid.Row="0" Grid.Column="1">
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Open Source</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
|
||||||
|
TextWrapping="Wrap" Margin="16 0 16 8"
|
||||||
|
Foreground="{DynamicResource MaterialDesignBodyLight}"
|
||||||
|
VerticalAlignment="Top">
|
||||||
|
This project is completely open source. If you like it and want to say thanks you could hit the GitHub Star button,
|
||||||
|
I like numbers. You could even make plugins, there's a full documentation on the website
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
<Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0"
|
||||||
|
BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8">
|
||||||
|
<DockPanel>
|
||||||
|
<Button Style="{DynamicResource MaterialDesignFlatButton}"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
x:Name="DonateButton"
|
||||||
|
Command="{s:Action OpenUrl}"
|
||||||
|
CommandParameter="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VQBAEJYUFLU4J">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<materialDesign:PackIcon Kind="Gift" />
|
||||||
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Donate</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<TextBlock Foreground="{DynamicResource MaterialDesignBodyLight}"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Margin="16"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
Feel like you want to make a donation? It would be gratefully received. Click the button to donate via PayPal.
|
||||||
|
</TextBlock>
|
||||||
|
</DockPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</materialDesign:Card>
|
||||||
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
<!-- PopupBox could be nice in the future when we actually have some stuff to send ppl to -->
|
|
||||||
<!--<materialDesign:PopupBox Style="{StaticResource MaterialDesignMultiFloatingActionPopupBox}"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
|
||||||
Margin="32" Grid.Row="1">
|
|
||||||
--><!-- add the visibility binding https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/issues/723 --><!--
|
|
||||||
<StackPanel Visibility="{Binding Path=IsPopupOpen, ElementName=MyPopupBox, Converter={StaticResource BoolToVisibilityConverter}}">
|
|
||||||
<Button ToolTip="GitHub" Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis">
|
|
||||||
<materialDesign:PackIcon Kind="Github" Height="20" Width="20" />
|
|
||||||
</Button>
|
|
||||||
<Button ToolTip="Twitter" Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis"
|
|
||||||
Background="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
Foreground="{DynamicResource PrimaryHueMidForegroundBrush}">
|
|
||||||
<materialDesign:PackIcon Kind="Twitter" />
|
|
||||||
</Button>
|
|
||||||
<Button ToolTip="Chat" Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis">
|
|
||||||
--><!-- mix up the colours by brinking in a named palette (see merged dictionaries at top) --><!--
|
|
||||||
<Button.Background>
|
|
||||||
<SolidColorBrush Color="{StaticResource GreenPrimary500}" />
|
|
||||||
</Button.Background>
|
|
||||||
<Button.Foreground>
|
|
||||||
<SolidColorBrush Color="{StaticResource GreenPrimary500Foreground}" />
|
|
||||||
</Button.Foreground>
|
|
||||||
<materialDesign:PackIcon Kind="Message" />
|
|
||||||
</Button>
|
|
||||||
<Button ToolTip="Email" Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis"
|
|
||||||
Background="{DynamicResource SecondaryHueMidBrush}"
|
|
||||||
Foreground="{DynamicResource SecondaryHueMidForegroundBrush}"
|
|
||||||
>
|
|
||||||
<materialDesign:PackIcon Kind="Email" />
|
|
||||||
</Button>
|
|
||||||
<Button ToolTip="Feel like you want to make a donation? It would be gratefully received. Click the button to donate via Pledgie."
|
|
||||||
Command="{s:Action OpenUrl}" CommandParameter="https://github.com/SpoinkyNL/Artemis">
|
|
||||||
<Button.Background>
|
|
||||||
<SolidColorBrush Color="{StaticResource GreenPrimary200}" />
|
|
||||||
</Button.Background>
|
|
||||||
<Button.Foreground>
|
|
||||||
<SolidColorBrush Color="{StaticResource GreenPrimary200Foreground}" />
|
|
||||||
</Button.Foreground>
|
|
||||||
<materialDesign:PackIcon Kind="Gift" />
|
|
||||||
</Button>
|
|
||||||
</StackPanel>
|
|
||||||
</materialDesign:PopupBox>-->
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -259,8 +259,14 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
|
|
||||||
public void ResetZoomAndPan()
|
public void ResetZoomAndPan()
|
||||||
{
|
{
|
||||||
|
if (!Devices.Any())
|
||||||
|
{
|
||||||
|
PanZoomViewModel.Reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a rect surrounding all devices
|
// Create a rect surrounding all devices
|
||||||
SKRect rect = new SKRect(
|
SKRect rect = new(
|
||||||
Devices.Min(d => d.Rectangle.Left),
|
Devices.Min(d => d.Rectangle.Left),
|
||||||
Devices.Min(d => d.Rectangle.Top),
|
Devices.Min(d => d.Rectangle.Top),
|
||||||
Devices.Max(d => d.Rectangle.Right),
|
Devices.Max(d => d.Rectangle.Right),
|
||||||
|
|||||||
@ -140,7 +140,7 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
|
|||||||
Device.GreenScale = GreenScale / 100f;
|
Device.GreenScale = GreenScale / 100f;
|
||||||
Device.BlueScale = BlueScale / 100f;
|
Device.BlueScale = BlueScale / 100f;
|
||||||
|
|
||||||
_rgbService.Surface.Update(true);
|
_rgbService.FlushLeds = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BrowseCustomLayout(object sender, MouseEventArgs e)
|
public void BrowseCustomLayout(object sender, MouseEventArgs e)
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.Settings"
|
xmlns:local="clr-namespace:Artemis.UI.Screens.Settings"
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance local:SettingsTabsViewModel}">
|
d:DataContext="{d:DesignInstance local:SettingsTabsViewModel}">
|
||||||
@ -16,18 +17,31 @@
|
|||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
<TabControl Style="{StaticResource MaterialDesignAppBarTabControl}"
|
<Grid>
|
||||||
ItemsSource="{Binding Items}"
|
<TabControl Style="{StaticResource MaterialDesignAppBarTabControl}"
|
||||||
SelectedItem="{Binding ActiveItem}"
|
ItemsSource="{Binding Items}"
|
||||||
DisplayMemberPath="DisplayName">
|
SelectedItem="{Binding ActiveItem}"
|
||||||
<TabControl.ContentTemplate>
|
DisplayMemberPath="DisplayName">
|
||||||
<DataTemplate>
|
<TabControl.ContentTemplate>
|
||||||
<ContentControl s:View.Model="{Binding IsAsync=True}"
|
<DataTemplate>
|
||||||
VerticalContentAlignment="Stretch"
|
<ContentControl s:View.Model="{Binding IsAsync=True}"
|
||||||
HorizontalContentAlignment="Stretch"
|
VerticalContentAlignment="Stretch"
|
||||||
IsTabStop="False"
|
HorizontalContentAlignment="Stretch"
|
||||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}" />
|
IsTabStop="False"
|
||||||
</DataTemplate>
|
TextElement.Foreground="{DynamicResource MaterialDesignBody}" />
|
||||||
</TabControl.ContentTemplate>
|
</DataTemplate>
|
||||||
</TabControl>
|
</TabControl.ContentTemplate>
|
||||||
|
</TabControl>
|
||||||
|
|
||||||
|
<!-- Bug: materialDesign:RippleAssist.RippleOnTop doesn't look as nice but otherwise it doesn't work at all, not sure why -->
|
||||||
|
<Button Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
ToolTip="Open debugger"
|
||||||
|
Command="{s:Action ShowDebugger}"
|
||||||
|
materialDesign:RippleAssist.RippleOnTop="True">
|
||||||
|
<materialDesign:PackIcon Kind="Matrix" />
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -2,18 +2,23 @@
|
|||||||
using Artemis.UI.Screens.Settings.Tabs.Devices;
|
using Artemis.UI.Screens.Settings.Tabs.Devices;
|
||||||
using Artemis.UI.Screens.Settings.Tabs.General;
|
using Artemis.UI.Screens.Settings.Tabs.General;
|
||||||
using Artemis.UI.Screens.Settings.Tabs.Plugins;
|
using Artemis.UI.Screens.Settings.Tabs.Plugins;
|
||||||
|
using Artemis.UI.Services;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Settings
|
namespace Artemis.UI.Screens.Settings
|
||||||
{
|
{
|
||||||
public class SettingsTabsViewModel : Conductor<Screen>.Collection.OneActive
|
public class SettingsTabsViewModel : Conductor<Screen>.Collection.OneActive
|
||||||
{
|
{
|
||||||
|
private readonly IDebugService _debugService;
|
||||||
|
|
||||||
public SettingsTabsViewModel(
|
public SettingsTabsViewModel(
|
||||||
GeneralSettingsTabViewModel generalSettingsTabViewModel,
|
GeneralSettingsTabViewModel generalSettingsTabViewModel,
|
||||||
PluginSettingsTabViewModel pluginSettingsTabViewModel,
|
PluginSettingsTabViewModel pluginSettingsTabViewModel,
|
||||||
DeviceSettingsTabViewModel deviceSettingsTabViewModel,
|
DeviceSettingsTabViewModel deviceSettingsTabViewModel,
|
||||||
AboutTabViewModel aboutTabViewModel)
|
AboutTabViewModel aboutTabViewModel,
|
||||||
|
IDebugService debugService)
|
||||||
{
|
{
|
||||||
|
_debugService = debugService;
|
||||||
DisplayName = "Settings";
|
DisplayName = "Settings";
|
||||||
|
|
||||||
Items.Add(generalSettingsTabViewModel);
|
Items.Add(generalSettingsTabViewModel);
|
||||||
@ -23,5 +28,10 @@ namespace Artemis.UI.Screens.Settings
|
|||||||
|
|
||||||
ActiveItem = generalSettingsTabViewModel;
|
ActiveItem = generalSettingsTabViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ShowDebugger()
|
||||||
|
{
|
||||||
|
_debugService.ShowDebugger();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PluginFeatureInfo FeatureInfo { get; }
|
public PluginFeatureInfo FeatureInfo { get; }
|
||||||
public Exception LoadException => FeatureInfo.Instance?.LoadException;
|
public Exception LoadException => FeatureInfo.LoadException;
|
||||||
|
|
||||||
public bool ShowShield { get; }
|
public bool ShowShield { get; }
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
public async Task InstallPrerequisites()
|
public async Task InstallPrerequisites()
|
||||||
{
|
{
|
||||||
if (FeatureInfo.Prerequisites.Any())
|
if (FeatureInfo.Prerequisites.Any())
|
||||||
await PluginPrerequisitesInstallDialogViewModel.Show(_dialogService, new List<IPrerequisitesSubject> { FeatureInfo });
|
await PluginPrerequisitesInstallDialogViewModel.Show(_dialogService, new List<IPrerequisitesSubject> {FeatureInfo});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RemovePrerequisites()
|
public async Task RemovePrerequisites()
|
||||||
@ -119,12 +119,19 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
|
|
||||||
private async Task UpdateEnabled(bool enable)
|
private async Task UpdateEnabled(bool enable)
|
||||||
{
|
{
|
||||||
if (IsEnabled == enable || FeatureInfo.Instance == null)
|
if (IsEnabled == enable)
|
||||||
{
|
{
|
||||||
NotifyOfPropertyChange(nameof(IsEnabled));
|
NotifyOfPropertyChange(nameof(IsEnabled));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FeatureInfo.Instance == null)
|
||||||
|
{
|
||||||
|
NotifyOfPropertyChange(nameof(IsEnabled));
|
||||||
|
_messageService.ShowMessage($"Feature '{FeatureInfo.Name}' is in a broken state and cannot enable.", "VIEW LOGS", ShowLogsFolder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
Enabling = true;
|
Enabling = true;
|
||||||
@ -144,7 +151,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
// Check if all prerequisites are met async
|
// Check if all prerequisites are met async
|
||||||
if (!FeatureInfo.ArePrerequisitesMet())
|
if (!FeatureInfo.ArePrerequisitesMet())
|
||||||
{
|
{
|
||||||
await PluginPrerequisitesInstallDialogViewModel.Show(_dialogService, new List<IPrerequisitesSubject> { FeatureInfo });
|
await PluginPrerequisitesInstallDialogViewModel.Show(_dialogService, new List<IPrerequisitesSubject> {FeatureInfo});
|
||||||
if (!FeatureInfo.ArePrerequisitesMet())
|
if (!FeatureInfo.ArePrerequisitesMet())
|
||||||
{
|
{
|
||||||
NotifyOfPropertyChange(nameof(IsEnabled));
|
NotifyOfPropertyChange(nameof(IsEnabled));
|
||||||
@ -156,7 +163,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_messageService.ShowMessage($"Failed to enable {FeatureInfo.Name}\r\n{e.Message}", "VIEW LOGS", ShowLogsFolder);
|
_messageService.ShowMessage($"Failed to enable '{FeatureInfo.Name}'.\r\n{e.Message}", "VIEW LOGS", ShowLogsFolder);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="200" />
|
<ColumnDefinition Width="200" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Grid.Column="0" TextWrapping="Wrap">
|
<TextBlock Grid.Column="0" TextWrapping="Wrap">
|
||||||
The list below shows all loaded plugins. <LineBreak />
|
The list below shows all loaded plugins. <LineBreak />
|
||||||
@ -38,7 +39,17 @@
|
|||||||
Margin="5 0"
|
Margin="5 0"
|
||||||
Text="{Binding SearchPluginInput, Delay=300, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding SearchPluginInput, Delay=300, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
|
||||||
<Button Grid.Column="3"
|
<Button Grid.Column="3" Style="{DynamicResource MaterialDesignFlatButton}"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Command="{s:Action OpenUrl}"
|
||||||
|
CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/plugins">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<materialDesign:PackIcon Kind="OpenInBrowser" />
|
||||||
|
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Get more plugins</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button Grid.Column="4"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Style="{StaticResource MaterialDesignRaisedButton}"
|
Style="{StaticResource MaterialDesignRaisedButton}"
|
||||||
Command="{s:Action ImportPlugin}"
|
Command="{s:Action ImportPlugin}"
|
||||||
|
|||||||
@ -77,6 +77,11 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
|||||||
base.OnInitialActivate();
|
base.OnInitialActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OpenUrl(string url)
|
||||||
|
{
|
||||||
|
Core.Utilities.OpenUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task ImportPlugin()
|
public async Task ImportPlugin()
|
||||||
{
|
{
|
||||||
VistaOpenFileDialog dialog = new() {Filter = "ZIP files (*.zip)|*.zip", Title = "Import Artemis plugin"};
|
VistaOpenFileDialog dialog = new() {Filter = "ZIP files (*.zip)|*.zip", Title = "Import Artemis plugin"};
|
||||||
|
|||||||
@ -31,14 +31,14 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnActivate()
|
protected override void OnActivate()
|
||||||
{
|
{
|
||||||
_rgbService.IsRenderPaused = true;
|
_rgbService.SetRenderPaused(true);
|
||||||
base.OnActivate();
|
base.OnActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnDeactivate()
|
protected override void OnDeactivate()
|
||||||
{
|
{
|
||||||
_rgbService.IsRenderPaused = false;
|
_rgbService.SetRenderPaused(false);
|
||||||
base.OnDeactivate();
|
base.OnDeactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -63,9 +63,8 @@
|
|||||||
<Border BorderBrush="{DynamicResource MaterialDesignDivider}" BorderThickness="0 0 0 1" Margin="0 10" />
|
<Border BorderBrush="{DynamicResource MaterialDesignDivider}" BorderThickness="0 0 0 1" Margin="0 10" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" Grid.Row="1" Grid.Column="0"
|
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" Grid.Row="1" Grid.Column="0" VerticalAlignment="Stretch" Margin="0,0,5,0">
|
||||||
VerticalAlignment="Stretch" Margin="0,0,5,0">
|
<Grid ClipToBounds="False"
|
||||||
<Grid ClipToBounds="True"
|
|
||||||
Focusable="True"
|
Focusable="True"
|
||||||
FocusVisualStyle="{StaticResource FocusVisual}"
|
FocusVisualStyle="{StaticResource FocusVisual}"
|
||||||
KeyUp="{s:Action EditorGridKeyUp}"
|
KeyUp="{s:Action EditorGridKeyUp}"
|
||||||
@ -188,8 +187,16 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
|
<Canvas>
|
||||||
|
<Rectangle ClipToBounds="False"
|
||||||
|
Width="{Binding MaxTextureSize}"
|
||||||
|
Height="{Binding MaxTextureSize}"
|
||||||
|
Stroke="{DynamicResource SecondaryHueMidBrush}"
|
||||||
|
StrokeThickness="{Binding MaxTextureSizeIndicatorThickness}"
|
||||||
|
StrokeDashArray="2 2" />
|
||||||
|
</Canvas>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Multi-selection rectangle -->
|
<!-- Multi-selection rectangle -->
|
||||||
<Path Data="{Binding SelectionRectangle}" Opacity="0"
|
<Path Data="{Binding SelectionRectangle}" Opacity="0"
|
||||||
Stroke="{DynamicResource PrimaryHueLightBrush}"
|
Stroke="{DynamicResource PrimaryHueLightBrush}"
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
@ -106,6 +107,9 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
|||||||
set => SetAndNotify(ref _colorFirstLedOnly, value);
|
set => SetAndNotify(ref _colorFirstLedOnly, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double MaxTextureSize => 4096 / _settingsService.GetSetting("Core.RenderScale", 0.5).Value;
|
||||||
|
public double MaxTextureSizeIndicatorThickness => 2 / PanZoomViewModel.Zoom;
|
||||||
|
|
||||||
public void OpenHyperlink(object sender, RequestNavigateEventArgs e)
|
public void OpenHyperlink(object sender, RequestNavigateEventArgs e)
|
||||||
{
|
{
|
||||||
Core.Utilities.OpenUrl(e.Uri.AbsoluteUri);
|
Core.Utilities.OpenUrl(e.Uri.AbsoluteUri);
|
||||||
@ -155,7 +159,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
|||||||
protected override void OnInitialActivate()
|
protected override void OnInitialActivate()
|
||||||
{
|
{
|
||||||
LoadWorkspaceSettings();
|
LoadWorkspaceSettings();
|
||||||
SurfaceDeviceViewModels.AddRange(_rgbService.EnabledDevices.OrderBy(d => d.ZIndex).Select(d => new SurfaceDeviceViewModel(d, _rgbService)));
|
SurfaceDeviceViewModels.AddRange(_rgbService.EnabledDevices.OrderBy(d => d.ZIndex).Select(d => new SurfaceDeviceViewModel(d, _rgbService, _settingsService)));
|
||||||
ListDeviceViewModels.AddRange(_rgbService.EnabledDevices.OrderBy(d => d.ZIndex * -1).Select(d => new ListDeviceViewModel(d, this)));
|
ListDeviceViewModels.AddRange(_rgbService.EnabledDevices.OrderBy(d => d.ZIndex * -1).Select(d => new ListDeviceViewModel(d, this)));
|
||||||
|
|
||||||
List<ArtemisDevice> shuffledDevices = _rgbService.EnabledDevices.OrderBy(d => Guid.NewGuid()).ToList();
|
List<ArtemisDevice> shuffledDevices = _rgbService.EnabledDevices.OrderBy(d => Guid.NewGuid()).ToList();
|
||||||
@ -168,7 +172,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
_coreService.FrameRendering += CoreServiceOnFrameRendering;
|
_coreService.FrameRendering += CoreServiceOnFrameRendering;
|
||||||
|
PanZoomViewModel.PropertyChanged += PanZoomViewModelOnPropertyChanged;
|
||||||
base.OnInitialActivate();
|
base.OnInitialActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,10 +183,17 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
|||||||
ListDeviceViewModels.Clear();
|
ListDeviceViewModels.Clear();
|
||||||
|
|
||||||
_coreService.FrameRendering -= CoreServiceOnFrameRendering;
|
_coreService.FrameRendering -= CoreServiceOnFrameRendering;
|
||||||
|
PanZoomViewModel.PropertyChanged -= PanZoomViewModelOnPropertyChanged;
|
||||||
|
|
||||||
base.OnClose();
|
base.OnClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PanZoomViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.PropertyName == nameof(PanZoomViewModel.Zoom))
|
||||||
|
NotifyOfPropertyChange(nameof(MaxTextureSizeIndicatorThickness));
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Context menu actions
|
#region Context menu actions
|
||||||
@ -322,7 +333,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
|||||||
SurfaceDeviceViewModel device = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, selectedRect).FirstOrDefault();
|
SurfaceDeviceViewModel device = HitTestUtilities.GetHitViewModels<SurfaceDeviceViewModel>((Visual) sender, selectedRect).FirstOrDefault();
|
||||||
if (device != null)
|
if (device != null)
|
||||||
{
|
{
|
||||||
_rgbService.IsRenderPaused = true;
|
_rgbService.SetRenderPaused(true);
|
||||||
_mouseDragStatus = MouseDragStatus.Dragging;
|
_mouseDragStatus = MouseDragStatus.Dragging;
|
||||||
// If the device is not selected, deselect others and select only this one (if shift not held)
|
// If the device is not selected, deselect others and select only this one (if shift not held)
|
||||||
if (device.SelectionStatus != SelectionStatus.Selected)
|
if (device.SelectionStatus != SelectionStatus.Selected)
|
||||||
@ -367,7 +378,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
_mouseDragStatus = MouseDragStatus.None;
|
_mouseDragStatus = MouseDragStatus.None;
|
||||||
_rgbService.IsRenderPaused = false;
|
_rgbService.SetRenderPaused(false);
|
||||||
ApplySurfaceSelection();
|
ApplySurfaceSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,15 +14,17 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
|||||||
public class SurfaceDeviceViewModel : PropertyChangedBase
|
public class SurfaceDeviceViewModel : PropertyChangedBase
|
||||||
{
|
{
|
||||||
private readonly IRgbService _rgbService;
|
private readonly IRgbService _rgbService;
|
||||||
|
private readonly ISettingsService _settingsService;
|
||||||
private Cursor _cursor;
|
private Cursor _cursor;
|
||||||
private double _dragOffsetX;
|
private double _dragOffsetX;
|
||||||
private double _dragOffsetY;
|
private double _dragOffsetY;
|
||||||
private SelectionStatus _selectionStatus;
|
private SelectionStatus _selectionStatus;
|
||||||
|
|
||||||
public SurfaceDeviceViewModel(ArtemisDevice device, IRgbService rgbService)
|
public SurfaceDeviceViewModel(ArtemisDevice device, IRgbService rgbService, ISettingsService settingsService)
|
||||||
{
|
{
|
||||||
Device = device;
|
Device = device;
|
||||||
_rgbService = rgbService;
|
_rgbService = rgbService;
|
||||||
|
_settingsService = settingsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisDevice Device { get; }
|
public ArtemisDevice Device { get; }
|
||||||
@ -101,6 +103,10 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
|
|||||||
if (x < 0 || y < 0)
|
if (x < 0 || y < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
double maxTextureSize = 4096 / _settingsService.GetSetting("Core.RenderScale", 0.5).Value;
|
||||||
|
if (x + Device.Rectangle.Width > maxTextureSize || y + Device.Rectangle.Height > maxTextureSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
List<SKRect> own = Device.Leds
|
List<SKRect> own = Device.Leds
|
||||||
.Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height))
|
.Select(l => SKRect.Create(l.Rectangle.Left + x, l.Rectangle.Top + y, l.Rectangle.Width, l.Rectangle.Height))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|||||||
@ -4,9 +4,9 @@
|
|||||||
".NETCoreApp,Version=v5.0": {
|
".NETCoreApp,Version=v5.0": {
|
||||||
"FluentValidation": {
|
"FluentValidation": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[10.2.3, )",
|
"requested": "[10.3.0, )",
|
||||||
"resolved": "10.2.3",
|
"resolved": "10.3.0",
|
||||||
"contentHash": "R2w/E6jgg9RPSlg7JQSTHg6AWDwlOXARaV4ZUKrPJ1gi1e+oaBEcomxmo29j9BLZivkyQhOpAboJ9nKZS4/xYA=="
|
"contentHash": "ujEB9UMBPDLib6dyhSRhl93IE6ko4ZU6Nz9MFqohaKcvyf06Hk0yDQUFJGF6RgAOsm27O7ZZHVDpXx7oU5vBcg=="
|
||||||
},
|
},
|
||||||
"Flurl.Http": {
|
"Flurl.Http": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
@ -130,22 +130,22 @@
|
|||||||
},
|
},
|
||||||
"SkiaSharp.Views.WPF": {
|
"SkiaSharp.Views.WPF": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[2.80.2, )",
|
"requested": "[2.80.3, )",
|
||||||
"resolved": "2.80.2",
|
"resolved": "2.80.3",
|
||||||
"contentHash": "Fzo2+MNwHDh9Cob8sk7OO26kp3bhofjXMwlEK8IncF1ehu9hi3sH9iQDJrue9a88VEJJ+yyLISPUFcmXlGHSyQ==",
|
"contentHash": "oKUMm7WzFeoie6rW5nnwSGKZ94misyRsAc1wU6SEqgd6ssW17nyfohHxHuBHtmpLtIRwvjhfAu3cMLrpX/oNcw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"SkiaSharp": "2.80.2",
|
"SkiaSharp": "2.80.3",
|
||||||
"SkiaSharp.Views.Desktop.Common": "2.80.2"
|
"SkiaSharp.Views.Desktop.Common": "2.80.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"SkiaSharp.Vulkan.SharpVk": {
|
"SkiaSharp.Vulkan.SharpVk": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[2.80.2, )",
|
"requested": "[2.80.3, )",
|
||||||
"resolved": "2.80.2",
|
"resolved": "2.80.3",
|
||||||
"contentHash": "qiqlbgMsSdxTsaPErtE1lXoMXolVVF9E6irmSTzlW++6BbW8tzA89n7GNsgMYJgyo2ljHZhX5ydhFn0Rkj7VHw==",
|
"contentHash": "IeR9oOHBsJUqpuVs23XgZXnrFV6WuOTaLpFhLVlXt2XILWIRrlrqx1PILgJm5bLqesceJLYZyMxVb/Ow7/uReA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"SharpVk": "0.4.2",
|
"SharpVk": "0.4.2",
|
||||||
"SkiaSharp": "2.80.2"
|
"SkiaSharp": "2.80.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Stylet": {
|
"Stylet": {
|
||||||
@ -491,13 +491,10 @@
|
|||||||
},
|
},
|
||||||
"Serilog.Sinks.Console": {
|
"Serilog.Sinks.Console": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "3.1.1",
|
"resolved": "4.0.0",
|
||||||
"contentHash": "56mI5AqvyF/i/c2451nvV71kq370XOCE4Uu5qiaJ295sOhMb9q3BWwG7mWLOVSnmpWiq0SBT3SXfgRXGNP6vzA==",
|
"contentHash": "yJQit9sTJ4xGLKgCujqDJsaGqBNJwGB/H898z+xYlMG06twy4//6LLnSrsmpduZxcHIG4im7cv+JmXLzXz2EkQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Serilog": "2.5.0",
|
"Serilog": "2.10.0"
|
||||||
"System.Console": "4.3.0",
|
|
||||||
"System.Runtime.InteropServices": "4.3.0",
|
|
||||||
"System.Runtime.InteropServices.RuntimeInformation": "4.3.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Serilog.Sinks.Debug": {
|
"Serilog.Sinks.Debug": {
|
||||||
@ -510,13 +507,10 @@
|
|||||||
},
|
},
|
||||||
"Serilog.Sinks.File": {
|
"Serilog.Sinks.File": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "4.1.0",
|
"resolved": "5.0.0",
|
||||||
"contentHash": "U0b34w+ZikbqWEZ3ui7BdzxY/19zwrdhLtI3o6tfmLdD3oXxg7n2TZJjwCCTlKPgRuYic9CBWfrZevbb70mTaw==",
|
"contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Serilog": "2.5.0",
|
"Serilog": "2.10.0"
|
||||||
"System.IO.FileSystem": "4.0.1",
|
|
||||||
"System.Text.Encoding.Extensions": "4.0.11",
|
|
||||||
"System.Threading.Timer": "4.0.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"SharpVectors.Reloaded": {
|
"SharpVectors.Reloaded": {
|
||||||
@ -543,10 +537,11 @@
|
|||||||
},
|
},
|
||||||
"SkiaSharp.Views.Desktop.Common": {
|
"SkiaSharp.Views.Desktop.Common": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "2.80.2",
|
"resolved": "2.80.3",
|
||||||
"contentHash": "0vBvweMysgl1wgjuTQUhdJMD5z5nBjtYqmnHPeX+qHfkc336Wj2L3jEqwmGb0YP+RV47gFGz0EzMAW6szZch9w==",
|
"contentHash": "CMQu9fr3BxGRsRryDC6lkYbYaSI2CI+RqisFX0WIdbOdbigUOLhqchmKIMb4EdFAZk13vk862qiE9v97iDZS7g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"SkiaSharp": "2.80.2"
|
"SkiaSharp": "2.80.3",
|
||||||
|
"System.Drawing.Common": "4.5.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.AppContext": {
|
"System.AppContext": {
|
||||||
@ -1442,10 +1437,10 @@
|
|||||||
"Ninject.Extensions.ChildKernel": "3.3.0",
|
"Ninject.Extensions.ChildKernel": "3.3.0",
|
||||||
"Ninject.Extensions.Conventions": "3.3.0",
|
"Ninject.Extensions.Conventions": "3.3.0",
|
||||||
"Serilog": "2.10.0",
|
"Serilog": "2.10.0",
|
||||||
"Serilog.Sinks.Console": "3.1.1",
|
"Serilog.Sinks.Console": "4.0.0",
|
||||||
"Serilog.Sinks.Debug": "2.0.0",
|
"Serilog.Sinks.Debug": "2.0.0",
|
||||||
"Serilog.Sinks.File": "4.1.0",
|
"Serilog.Sinks.File": "5.0.0",
|
||||||
"SkiaSharp": "2.80.2",
|
"SkiaSharp": "2.80.3",
|
||||||
"System.Buffers": "4.5.1",
|
"System.Buffers": "4.5.1",
|
||||||
"System.IO.FileSystem.AccessControl": "5.0.0",
|
"System.IO.FileSystem.AccessControl": "5.0.0",
|
||||||
"System.Numerics.Vectors": "4.5.0",
|
"System.Numerics.Vectors": "4.5.0",
|
||||||
@ -1471,8 +1466,8 @@
|
|||||||
"Ninject": "3.3.4",
|
"Ninject": "3.3.4",
|
||||||
"Ninject.Extensions.Conventions": "3.3.0",
|
"Ninject.Extensions.Conventions": "3.3.0",
|
||||||
"SharpVectors.Reloaded": "1.7.5",
|
"SharpVectors.Reloaded": "1.7.5",
|
||||||
"SkiaSharp": "2.80.2",
|
"SkiaSharp": "2.80.3",
|
||||||
"SkiaSharp.Views.WPF": "2.80.2",
|
"SkiaSharp.Views.WPF": "2.80.3",
|
||||||
"Stylet": "1.3.6",
|
"Stylet": "1.3.6",
|
||||||
"System.Buffers": "4.5.1",
|
"System.Buffers": "4.5.1",
|
||||||
"System.Numerics.Vectors": "4.5.0"
|
"System.Numerics.Vectors": "4.5.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user