mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Core - Added XML comments to all remaining public members/methods
Core - Refactored a lot of code for nullable reference types
This commit is contained in:
parent
61fc96742d
commit
a3cd32f6c4
@ -13,6 +13,7 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
<DocumentationFile>bin\x64\Debug\Artemis.Core.xml</DocumentationFile>
|
<DocumentationFile>bin\x64\Debug\Artemis.Core.xml</DocumentationFile>
|
||||||
|
<NoWarn>1701;1702</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@ -39,9 +39,9 @@ namespace Artemis.Core
|
|||||||
if (ValueTypeSetExpression == null)
|
if (ValueTypeSetExpression == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (DataBinding.LayerProperty.PropertyDescription.MaxInputValue is float max)
|
if (DataBinding!.LayerProperty.PropertyDescription.MaxInputValue is float max)
|
||||||
value = Math.Min(value, max);
|
value = Math.Min(value, max);
|
||||||
if (DataBinding.LayerProperty.PropertyDescription.MinInputValue is float min)
|
if (DataBinding!.LayerProperty.PropertyDescription.MinInputValue is float min)
|
||||||
value = Math.Max(value, min);
|
value = Math.Max(value, min);
|
||||||
|
|
||||||
base.ApplyValue(value);
|
base.ApplyValue(value);
|
||||||
|
|||||||
@ -5,6 +5,9 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public class SKColorDataBindingConverter : DataBindingConverter<SKColor, SKColor>
|
public class SKColorDataBindingConverter : DataBindingConverter<SKColor, SKColor>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="SKColorDataBindingConverter" /> class
|
||||||
|
/// </summary>
|
||||||
public SKColorDataBindingConverter()
|
public SKColorDataBindingConverter()
|
||||||
{
|
{
|
||||||
SupportsInterpolate = true;
|
SupportsInterpolate = true;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace Artemis.Core
|
|||||||
internal class CosecantModifierType : DataBindingModifierType<double>
|
internal class CosecantModifierType : DataBindingModifierType<double>
|
||||||
{
|
{
|
||||||
public override string Name => "Cosecant";
|
public override string Name => "Cosecant";
|
||||||
public override string Icon => null;
|
public override string? Icon => null;
|
||||||
public override string Category => "Trigonometry";
|
public override string Category => "Trigonometry";
|
||||||
public override string Description => "Treats the input as an angle and calculates the cosecant";
|
public override string Description => "Treats the input as an angle and calculates the cosecant";
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace Artemis.Core
|
|||||||
internal class CotangentModifierType : DataBindingModifierType<double>
|
internal class CotangentModifierType : DataBindingModifierType<double>
|
||||||
{
|
{
|
||||||
public override string Name => "Cotangent";
|
public override string Name => "Cotangent";
|
||||||
public override string Icon => null;
|
public override string? Icon => null;
|
||||||
public override string Category => "Trigonometry";
|
public override string Category => "Trigonometry";
|
||||||
public override string Description => "Treats the input as an angle and calculates the cotangent";
|
public override string Description => "Treats the input as an angle and calculates the cotangent";
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ namespace Artemis.Core
|
|||||||
internal class SecantModifierType : DataBindingModifierType<double>
|
internal class SecantModifierType : DataBindingModifierType<double>
|
||||||
{
|
{
|
||||||
public override string Name => "Secant";
|
public override string Name => "Secant";
|
||||||
public override string Icon => null;
|
public override string? Icon => null;
|
||||||
public override string Category => "Trigonometry";
|
public override string Category => "Trigonometry";
|
||||||
public override string Description => "Treats the input as an angle and calculates the secant";
|
public override string Description => "Treats the input as an angle and calculates the secant";
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
throw new ArtemisCoreException("Color Gradients do not support keyframes.");
|
throw new ArtemisCoreException("Color Gradients do not support keyframes.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCurrentValueSet(object sender, LayerPropertyEventArgs<ColorGradient> e)
|
private void OnCurrentValueSet(object? sender, LayerPropertyEventArgs<ColorGradient> e)
|
||||||
{
|
{
|
||||||
// Don't allow color gradients to be null
|
// Don't allow color gradients to be null
|
||||||
if (BaseValue == null)
|
if (BaseValue == null)
|
||||||
|
|||||||
@ -27,8 +27,8 @@
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
||||||
{
|
{
|
||||||
float diff = NextKeyframe.Value - CurrentKeyframe.Value;
|
float diff = NextKeyframe!.Value - CurrentKeyframe!.Value;
|
||||||
CurrentValue = CurrentKeyframe.Value + diff * keyframeProgressEased;
|
CurrentValue = CurrentKeyframe!.Value + diff * keyframeProgressEased;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,15 +14,15 @@
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
||||||
{
|
{
|
||||||
float startDiff = NextKeyframe.Value.Start - CurrentKeyframe.Value.Start;
|
float startDiff = NextKeyframe!.Value.Start - CurrentKeyframe!.Value.Start;
|
||||||
float endDiff = NextKeyframe.Value.End - CurrentKeyframe.Value.End;
|
float endDiff = NextKeyframe!.Value.End - CurrentKeyframe!.Value.End;
|
||||||
CurrentValue = new FloatRange(
|
CurrentValue = new FloatRange(
|
||||||
(int) (CurrentKeyframe.Value.Start + startDiff * keyframeProgressEased),
|
(int) (CurrentKeyframe!.Value.Start + startDiff * keyframeProgressEased),
|
||||||
(int) (CurrentKeyframe.Value.End + endDiff * keyframeProgressEased)
|
(int) (CurrentKeyframe!.Value.End + endDiff * keyframeProgressEased)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCurrentValueSet(object sender, LayerPropertyEventArgs<FloatRange> e)
|
private void OnCurrentValueSet(object? sender, LayerPropertyEventArgs<FloatRange> e)
|
||||||
{
|
{
|
||||||
// Don't allow the int range to be null
|
// Don't allow the int range to be null
|
||||||
BaseValue ??= DefaultValue ?? new FloatRange(0, 0);
|
BaseValue ??= DefaultValue ?? new FloatRange(0, 0);
|
||||||
|
|||||||
@ -37,8 +37,8 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
||||||
{
|
{
|
||||||
int diff = NextKeyframe.Value - CurrentKeyframe.Value;
|
int diff = NextKeyframe!.Value - CurrentKeyframe!.Value;
|
||||||
CurrentValue = (int) Math.Round(CurrentKeyframe.Value + diff * keyframeProgressEased, MidpointRounding.AwayFromZero);
|
CurrentValue = (int) Math.Round(CurrentKeyframe!.Value + diff * keyframeProgressEased, MidpointRounding.AwayFromZero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,15 +14,15 @@
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
||||||
{
|
{
|
||||||
float startDiff = NextKeyframe.Value.Start - CurrentKeyframe.Value.Start;
|
float startDiff = NextKeyframe!.Value.Start - CurrentKeyframe!.Value.Start;
|
||||||
float endDiff = NextKeyframe.Value.End - CurrentKeyframe.Value.End;
|
float endDiff = NextKeyframe!.Value.End - CurrentKeyframe!.Value.End;
|
||||||
CurrentValue = new IntRange(
|
CurrentValue = new IntRange(
|
||||||
(int) (CurrentKeyframe.Value.Start + startDiff * keyframeProgressEased),
|
(int) (CurrentKeyframe!.Value.Start + startDiff * keyframeProgressEased),
|
||||||
(int) (CurrentKeyframe.Value.End + endDiff * keyframeProgressEased)
|
(int) (CurrentKeyframe!.Value.End + endDiff * keyframeProgressEased)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCurrentValueSet(object sender, LayerPropertyEventArgs<IntRange> e)
|
private void OnCurrentValueSet(object? sender, LayerPropertyEventArgs<IntRange> e)
|
||||||
{
|
{
|
||||||
// Don't allow the int range to be null
|
// Don't allow the int range to be null
|
||||||
BaseValue ??= DefaultValue ?? new IntRange(0, 0);
|
BaseValue ??= DefaultValue ?? new IntRange(0, 0);
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A special layer property used to configure the selected layer brush
|
/// A special layer property used to configure the selected layer brush
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LayerBrushReferenceLayerProperty : LayerProperty<LayerBrushReference>
|
public class LayerBrushReferenceLayerProperty : LayerProperty<LayerBrushReference?>
|
||||||
{
|
{
|
||||||
internal LayerBrushReferenceLayerProperty()
|
internal LayerBrushReferenceLayerProperty()
|
||||||
{
|
{
|
||||||
@ -14,7 +14,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implicitly converts an <see cref="LayerBrushReferenceLayerProperty" /> to an <see cref="LayerBrushReference" />
|
/// Implicitly converts an <see cref="LayerBrushReferenceLayerProperty" /> to an <see cref="LayerBrushReference" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static implicit operator LayerBrushReference(LayerBrushReferenceLayerProperty p)
|
public static implicit operator LayerBrushReference?(LayerBrushReferenceLayerProperty p)
|
||||||
{
|
{
|
||||||
return p.CurrentValue;
|
return p.CurrentValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
||||||
{
|
{
|
||||||
CurrentValue = CurrentKeyframe.Value.Interpolate(NextKeyframe.Value, keyframeProgressEased);
|
CurrentValue = CurrentKeyframe!.Value.Interpolate(NextKeyframe!.Value, keyframeProgressEased);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,9 +22,9 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
||||||
{
|
{
|
||||||
float xDiff = NextKeyframe.Value.X - CurrentKeyframe.Value.X;
|
float xDiff = NextKeyframe!.Value.X - CurrentKeyframe!.Value.X;
|
||||||
float yDiff = NextKeyframe.Value.Y - CurrentKeyframe.Value.Y;
|
float yDiff = NextKeyframe!.Value.Y - CurrentKeyframe!.Value.Y;
|
||||||
CurrentValue = new SKPoint(CurrentKeyframe.Value.X + xDiff * keyframeProgressEased, CurrentKeyframe.Value.Y + yDiff * keyframeProgressEased);
|
CurrentValue = new SKPoint(CurrentKeyframe!.Value.X + xDiff * keyframeProgressEased, CurrentKeyframe!.Value.Y + yDiff * keyframeProgressEased);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,9 +22,9 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased)
|
||||||
{
|
{
|
||||||
float widthDiff = NextKeyframe.Value.Width - CurrentKeyframe.Value.Width;
|
float widthDiff = NextKeyframe!.Value.Width - CurrentKeyframe!.Value.Width;
|
||||||
float heightDiff = NextKeyframe.Value.Height - CurrentKeyframe.Value.Height;
|
float heightDiff = NextKeyframe!.Value.Height - CurrentKeyframe!.Value.Height;
|
||||||
CurrentValue = new SKSize(CurrentKeyframe.Value.Width + widthDiff * keyframeProgressEased, CurrentKeyframe.Value.Height + heightDiff * keyframeProgressEased);
|
CurrentValue = new SKSize(CurrentKeyframe!.Value.Width + widthDiff * keyframeProgressEased, CurrentKeyframe!.Value.Height + heightDiff * keyframeProgressEased);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,6 +12,9 @@ namespace Artemis.Core
|
|||||||
Surface = surface;
|
Surface = surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the active surface at the time the event fired
|
||||||
|
/// </summary>
|
||||||
public ArtemisSurface Surface { get; }
|
public ArtemisSurface Surface { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13,6 +13,9 @@ namespace Artemis.Core
|
|||||||
Device = device;
|
Device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the device this event is related to
|
||||||
|
/// </summary>
|
||||||
public IRGBDevice Device { get; }
|
public IRGBDevice Device { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,7 +14,14 @@ namespace Artemis.Core
|
|||||||
Key = key;
|
Key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the dynamic data model
|
||||||
|
/// </summary>
|
||||||
public DataModel DynamicDataModel { get; }
|
public DataModel DynamicDataModel { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the key of the dynamic data model on the parent <see cref="DataModel" />
|
||||||
|
/// </summary>
|
||||||
public string Key { get; }
|
public string Key { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,7 +14,14 @@ namespace Artemis.Core
|
|||||||
RgbSurface = rgbSurface;
|
RgbSurface = rgbSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the bitmap brush used to render this frame
|
||||||
|
/// </summary>
|
||||||
public BitmapBrush BitmapBrush { get; }
|
public BitmapBrush BitmapBrush { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the RGB surface used to render this frame
|
||||||
|
/// </summary>
|
||||||
public RGBSurface RgbSurface { get; }
|
public RGBSurface RgbSurface { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Artemis.Core.Modules;
|
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
@ -11,17 +9,26 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class FrameRenderingEventArgs : EventArgs
|
public class FrameRenderingEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
internal FrameRenderingEventArgs(List<Module> modules, SKCanvas canvas, double deltaTime, RGBSurface rgbSurface)
|
internal FrameRenderingEventArgs(SKCanvas canvas, double deltaTime, RGBSurface rgbSurface)
|
||||||
{
|
{
|
||||||
Modules = modules;
|
|
||||||
Canvas = canvas;
|
Canvas = canvas;
|
||||||
DeltaTime = deltaTime;
|
DeltaTime = deltaTime;
|
||||||
RgbSurface = rgbSurface;
|
RgbSurface = rgbSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Module> Modules { get; }
|
/// <summary>
|
||||||
|
/// Gets the canvas this frame is rendering on
|
||||||
|
/// </summary>
|
||||||
public SKCanvas Canvas { get; }
|
public SKCanvas Canvas { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the delta time since the last frame was rendered
|
||||||
|
/// </summary>
|
||||||
public double DeltaTime { get; }
|
public double DeltaTime { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the RGB surface used to render this frame
|
||||||
|
/// </summary>
|
||||||
public RGBSurface RgbSurface { get; }
|
public RGBSurface RgbSurface { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,17 +2,19 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data about plugin related events
|
||||||
|
/// </summary>
|
||||||
public class PluginEventArgs : EventArgs
|
public class PluginEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public PluginEventArgs()
|
internal PluginEventArgs(Plugin plugin)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public PluginEventArgs(Plugin plugin)
|
|
||||||
{
|
{
|
||||||
Plugin = plugin;
|
Plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the plugin this event is related to
|
||||||
|
/// </summary>
|
||||||
public Plugin Plugin { get; }
|
public Plugin Plugin { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,17 +2,19 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data about plugin feature related events
|
||||||
|
/// </summary>
|
||||||
public class PluginFeatureEventArgs : EventArgs
|
public class PluginFeatureEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public PluginFeatureEventArgs()
|
internal PluginFeatureEventArgs(PluginFeature pluginFeature)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public PluginFeatureEventArgs(PluginFeature pluginFeature)
|
|
||||||
{
|
{
|
||||||
PluginFeature = pluginFeature;
|
PluginFeature = pluginFeature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the plugin feature this event is related to
|
||||||
|
/// </summary>
|
||||||
public PluginFeature PluginFeature { get; }
|
public PluginFeature PluginFeature { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data for the <see langword='DataBindingPropertyUpdatedEvent' /> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
public class DataBindingPropertyUpdatedEvent<T> : EventArgs
|
public class DataBindingPropertyUpdatedEvent<T> : EventArgs
|
||||||
{
|
{
|
||||||
public DataBindingPropertyUpdatedEvent(T value)
|
internal DataBindingPropertyUpdatedEvent(T value)
|
||||||
{
|
{
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,23 +2,35 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides strongly typed data for layer property events of type <typeparamref name="T" />.
|
||||||
|
/// </summary>
|
||||||
public class LayerPropertyEventArgs<T> : EventArgs
|
public class LayerPropertyEventArgs<T> : EventArgs
|
||||||
{
|
{
|
||||||
public LayerPropertyEventArgs(LayerProperty<T> layerProperty)
|
internal LayerPropertyEventArgs(LayerProperty<T> layerProperty)
|
||||||
{
|
{
|
||||||
LayerProperty = layerProperty;
|
LayerProperty = layerProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the layer property this event is related to
|
||||||
|
/// </summary>
|
||||||
public LayerProperty<T> LayerProperty { get; }
|
public LayerProperty<T> LayerProperty { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data for layer property events.
|
||||||
|
/// </summary>
|
||||||
public class LayerPropertyEventArgs : EventArgs
|
public class LayerPropertyEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public LayerPropertyEventArgs(ILayerProperty layerProperty)
|
internal LayerPropertyEventArgs(ILayerProperty layerProperty)
|
||||||
{
|
{
|
||||||
LayerProperty = layerProperty;
|
LayerProperty = layerProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the layer property this event is related to
|
||||||
|
/// </summary>
|
||||||
public ILayerProperty LayerProperty { get; }
|
public ILayerProperty LayerProperty { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,14 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Artemis.Core
|
|
||||||
{
|
|
||||||
public class LayerPropertyGroupUpdatingEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
public LayerPropertyGroupUpdatingEventArgs(double deltaTime)
|
|
||||||
{
|
|
||||||
DeltaTime = deltaTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double DeltaTime { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,31 +2,37 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An exception thrown when a plugin-related error occurs
|
||||||
|
/// </summary>
|
||||||
public class ArtemisPluginException : Exception
|
public class ArtemisPluginException : Exception
|
||||||
{
|
{
|
||||||
public ArtemisPluginException(Plugin plugin)
|
internal ArtemisPluginException(Plugin plugin)
|
||||||
{
|
{
|
||||||
Plugin = plugin;
|
Plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisPluginException(Plugin plugin, string message) : base(message)
|
internal ArtemisPluginException(Plugin plugin, string message) : base(message)
|
||||||
{
|
{
|
||||||
Plugin = plugin;
|
Plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisPluginException(Plugin plugin, string message, Exception inner) : base(message, inner)
|
internal ArtemisPluginException(Plugin plugin, string message, Exception inner) : base(message, inner)
|
||||||
{
|
{
|
||||||
Plugin = plugin;
|
Plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisPluginException(string message) : base(message)
|
internal ArtemisPluginException(string message) : base(message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisPluginException(string message, Exception inner) : base(message, inner)
|
internal ArtemisPluginException(string message, Exception inner) : base(message, inner)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin Plugin { get; }
|
/// <summary>
|
||||||
|
/// Gets the plugin the error is related to
|
||||||
|
/// </summary>
|
||||||
|
public Plugin? Plugin { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,23 +2,29 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An exception thrown when a plugin feature-related error occurs
|
||||||
|
/// </summary>
|
||||||
public class ArtemisPluginFeatureException : Exception
|
public class ArtemisPluginFeatureException : Exception
|
||||||
{
|
{
|
||||||
|
internal ArtemisPluginFeatureException(PluginFeature pluginFeature)
|
||||||
|
{
|
||||||
|
PluginFeature = pluginFeature;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ArtemisPluginFeatureException(PluginFeature pluginFeature, string message) : base(message)
|
||||||
|
{
|
||||||
|
PluginFeature = pluginFeature;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ArtemisPluginFeatureException(PluginFeature pluginFeature, string message, Exception inner) : base(message, inner)
|
||||||
|
{
|
||||||
|
PluginFeature = pluginFeature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the plugin feature the error is related to
|
||||||
|
/// </summary>
|
||||||
public PluginFeature PluginFeature { get; }
|
public PluginFeature PluginFeature { get; }
|
||||||
|
|
||||||
public ArtemisPluginFeatureException(PluginFeature pluginFeature)
|
|
||||||
{
|
|
||||||
PluginFeature = pluginFeature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtemisPluginFeatureException(PluginFeature pluginFeature, string message) : base(message)
|
|
||||||
{
|
|
||||||
PluginFeature = pluginFeature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtemisPluginFeatureException(PluginFeature pluginFeature, string message, Exception inner) : base(message, inner)
|
|
||||||
{
|
|
||||||
PluginFeature = pluginFeature;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,13 +2,16 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An exception thrown when a plugin lock file error occurs
|
||||||
|
/// </summary>
|
||||||
public class ArtemisPluginLockException : Exception
|
public class ArtemisPluginLockException : Exception
|
||||||
{
|
{
|
||||||
public ArtemisPluginLockException(Exception innerException) : base(CreateExceptionMessage(innerException), innerException)
|
internal ArtemisPluginLockException(Exception? innerException) : base(CreateExceptionMessage(innerException), innerException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string CreateExceptionMessage(Exception innerException)
|
private static string CreateExceptionMessage(Exception? innerException)
|
||||||
{
|
{
|
||||||
return innerException != null
|
return innerException != null
|
||||||
? "Found a lock file, skipping load, see inner exception for last known exception."
|
? "Found a lock file, skipping load, see inner exception for last known exception."
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
public static class DirectoryInfoExtensions
|
internal static class DirectoryInfoExtensions
|
||||||
{
|
{
|
||||||
public static void CopyFilesRecursively(this DirectoryInfo source, DirectoryInfo target)
|
public static void CopyFilesRecursively(this DirectoryInfo source, DirectoryInfo target)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,8 +3,16 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A static class providing <see cref="double" /> extensions
|
||||||
|
/// </summary>
|
||||||
public static class DoubleExtensions
|
public static class DoubleExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Rounds the provided number away to zero and casts the result to an <see cref="int" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number">The number to round</param>
|
||||||
|
/// <returns>The rounded number as an integer</returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static int RoundToInt(this double number)
|
public static int RoundToInt(this double number)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,9 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A static class providing <see cref="float" /> extensions
|
||||||
|
/// </summary>
|
||||||
public static class FloatExtensions
|
public static class FloatExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Rounds the provided number away to zero and casts the result to an <see cref="int" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number">The number to round</param>
|
||||||
|
/// <returns>The rounded number as an integer</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static int RoundToInt(this float number)
|
public static int RoundToInt(this float number)
|
||||||
{
|
{
|
||||||
return (int) Math.Round(number, MidpointRounding.AwayFromZero);
|
return (int) Math.Round(number, MidpointRounding.AwayFromZero);
|
||||||
|
|||||||
@ -24,6 +24,10 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A static class providing <see cref="IEnumerable{T}" /> extensions
|
||||||
|
/// </summary>
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
public static class IEnumerableExtensions
|
public static class IEnumerableExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -46,7 +50,7 @@ namespace Artemis.Core
|
|||||||
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
|
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
|
||||||
Func<TSource, TKey> keySelector)
|
Func<TSource, TKey> keySelector)
|
||||||
{
|
{
|
||||||
return source.DistinctBy(keySelector, null);
|
return source.DistinctBy(keySelector, null!);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -5,8 +5,16 @@ using System.Text;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A static class providing <see cref="Process" /> extensions
|
||||||
|
/// </summary>
|
||||||
public static class ProcessExtensions
|
public static class ProcessExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the file name of the given process
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p">The process</param>
|
||||||
|
/// <returns>The filename of the given process</returns>
|
||||||
public static string GetProcessFilename(this Process p)
|
public static string GetProcessFilename(this Process p)
|
||||||
{
|
{
|
||||||
int capacity = 2000;
|
int capacity = 2000;
|
||||||
@ -17,7 +25,7 @@ namespace Artemis.Core
|
|||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||||
private static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] int dwFlags, [Out] StringBuilder lpExeName, ref int lpdwSize);
|
private static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] int dwFlags, [Out] StringBuilder lpExeName, ref int lpdwSize);
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll")]
|
||||||
|
|||||||
@ -3,7 +3,7 @@ using RGB.NET.Core;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
public static class RgbDeviceExtensions
|
internal static class RgbDeviceExtensions
|
||||||
{
|
{
|
||||||
public static string GetDeviceIdentifier(this IRGBDevice rgbDevice)
|
public static string GetDeviceIdentifier(this IRGBDevice rgbDevice)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
using RGB.NET.Core;
|
|
||||||
using SkiaSharp;
|
|
||||||
|
|
||||||
namespace Artemis.Core
|
|
||||||
{
|
|
||||||
public static class RgbRectangleExtensions
|
|
||||||
{
|
|
||||||
public static SKRect ToSKRect(this Rectangle rectangle, double scale)
|
|
||||||
{
|
|
||||||
return SKRect.Create(
|
|
||||||
(rectangle.Location.X * scale).RoundToInt(),
|
|
||||||
(rectangle.Location.Y * scale).RoundToInt(),
|
|
||||||
(rectangle.Size.Width * scale).RoundToInt(),
|
|
||||||
(rectangle.Size.Height * scale).RoundToInt()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,14 +4,28 @@ using SkiaSharp;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
// ReSharper disable once InconsistentNaming - I didn't come up with SKColor
|
/// <summary>
|
||||||
|
/// A static class providing <see cref="SKColor" /> extensions
|
||||||
|
/// </summary>
|
||||||
public static class SKColorExtensions
|
public static class SKColorExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts hte SKColor to an RGB.NET color
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">The color to convert</param>
|
||||||
|
/// <returns>The RGB.NET color</returns>
|
||||||
public static Color ToRgbColor(this SKColor color)
|
public static Color ToRgbColor(this SKColor color)
|
||||||
{
|
{
|
||||||
return new Color(color.Alpha, color.Red, color.Green, color.Blue);
|
return new Color(color.Alpha, color.Red, color.Green, color.Blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interpolates a color between the <paramref name="from" /> and <paramref name="to" /> color.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from">The first color</param>
|
||||||
|
/// <param name="to">The second color</param>
|
||||||
|
/// <param name="progress">A value between 0 and 1</param>
|
||||||
|
/// <returns>The interpolated color</returns>
|
||||||
public static SKColor Interpolate(this SKColor from, SKColor to, float progress)
|
public static SKColor Interpolate(this SKColor from, SKColor to, float progress)
|
||||||
{
|
{
|
||||||
int redDiff = to.Red - from.Red;
|
int redDiff = to.Red - from.Red;
|
||||||
@ -27,6 +41,12 @@ namespace Artemis.Core
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the two colors together
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">The first color</param>
|
||||||
|
/// <param name="b">The second color</param>
|
||||||
|
/// <returns>The sum of the two colors</returns>
|
||||||
public static SKColor Sum(this SKColor a, SKColor b)
|
public static SKColor Sum(this SKColor a, SKColor b)
|
||||||
{
|
{
|
||||||
return new SKColor(
|
return new SKColor(
|
||||||
|
|||||||
@ -6,6 +6,9 @@ using Humanizer;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A static class providing <see cref="Type" /> extensions
|
||||||
|
/// </summary>
|
||||||
public static class TypeExtensions
|
public static class TypeExtensions
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<Type, List<Type>> PrimitiveTypeConversions = new Dictionary<Type, List<Type>>
|
private static readonly Dictionary<Type, List<Type>> PrimitiveTypeConversions = new Dictionary<Type, List<Type>>
|
||||||
@ -40,6 +43,12 @@ namespace Artemis.Core
|
|||||||
{typeof(string), "string"}
|
{typeof(string), "string"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the provided type is of a specified generic type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type to check</param>
|
||||||
|
/// <param name="genericType">The generic type to match</param>
|
||||||
|
/// <returns>True if the <paramref name="type" /> is generic and of generic type <paramref name="genericType" /></returns>
|
||||||
public static bool IsGenericType(this Type type, Type genericType)
|
public static bool IsGenericType(this Type type, Type genericType)
|
||||||
{
|
{
|
||||||
if (type == null)
|
if (type == null)
|
||||||
@ -48,11 +57,21 @@ namespace Artemis.Core
|
|||||||
return type.BaseType?.GetGenericTypeDefinition() == genericType;
|
return type.BaseType?.GetGenericTypeDefinition() == genericType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsStruct(this Type source)
|
/// <summary>
|
||||||
|
/// Determines whether the provided type is a struct
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type to check</param>
|
||||||
|
/// <returns><see langword="true" /> if the type is a struct, otherwise <see langword="false" /></returns>
|
||||||
|
public static bool IsStruct(this Type type)
|
||||||
{
|
{
|
||||||
return source.IsValueType && !source.IsPrimitive && !source.IsEnum;
|
return type.IsValueType && !type.IsPrimitive && !type.IsEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the provided type is any kind of numeric type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type to check</param>
|
||||||
|
/// <returns><see langword="true" /> if the type a numeric type, otherwise <see langword="false" /></returns>
|
||||||
public static bool TypeIsNumber(this Type type)
|
public static bool TypeIsNumber(this Type type)
|
||||||
{
|
{
|
||||||
return type == typeof(sbyte)
|
return type == typeof(sbyte)
|
||||||
@ -68,6 +87,11 @@ namespace Artemis.Core
|
|||||||
|| type == typeof(decimal);
|
|| type == typeof(decimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the provided value is any kind of numeric type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to check</param>
|
||||||
|
/// <returns><see langword="true" /> if the value is of a numeric type, otherwise <see langword="false" /></returns>
|
||||||
public static bool IsNumber(this object value)
|
public static bool IsNumber(this object value)
|
||||||
{
|
{
|
||||||
return value is sbyte
|
return value is sbyte
|
||||||
@ -126,7 +150,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the default value of the given type
|
/// Returns the default value of the given type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static object GetDefault(this Type type)
|
public static object? GetDefault(this Type type)
|
||||||
{
|
{
|
||||||
return type.IsValueType ? Activator.CreateInstance(type) : null;
|
return type.IsValueType ? Activator.CreateInstance(type) : null;
|
||||||
}
|
}
|
||||||
@ -157,7 +181,7 @@ namespace Artemis.Core
|
|||||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
|
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
|
||||||
return type.GenericTypeArguments[0];
|
return type.GenericTypeArguments[0];
|
||||||
|
|
||||||
Type enumerableType = type.GetInterfaces().FirstOrDefault(x =>
|
Type? enumerableType = type.GetInterfaces().FirstOrDefault(x =>
|
||||||
x.IsGenericType &&
|
x.IsGenericType &&
|
||||||
x.GetGenericTypeDefinition() == typeof(IEnumerable<>));
|
x.GetGenericTypeDefinition() == typeof(IEnumerable<>));
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,9 @@ namespace Artemis.Core.JsonConverters
|
|||||||
|
|
||||||
public override int ReadJson(JsonReader reader, Type objectType, int existingValue, bool hasExistingValue, JsonSerializer serializer)
|
public override int ReadJson(JsonReader reader, Type objectType, int existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
JValue jsonValue = serializer.Deserialize<JValue>(reader);
|
JValue? jsonValue = serializer.Deserialize<JValue>(reader);
|
||||||
|
if (jsonValue == null)
|
||||||
|
throw new FormatException();
|
||||||
|
|
||||||
if (jsonValue.Type == JTokenType.Float)
|
if (jsonValue.Type == JTokenType.Float)
|
||||||
return (int) Math.Round(jsonValue.Value<double>());
|
return (int) Math.Round(jsonValue.Value<double>());
|
||||||
|
|||||||
@ -13,7 +13,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when a property value changes.
|
/// Occurs when a property value changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +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.Runtime.CompilerServices;
|
|
||||||
using Artemis.Core.Properties;
|
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -11,7 +8,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A gradient containing a list of <see cref="ColorGradientStop" />s
|
/// A gradient containing a list of <see cref="ColorGradientStop" />s
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ColorGradient : INotifyPropertyChanged
|
public class ColorGradient : CorePropertyChanged
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="ColorGradient" /> class
|
/// Creates a new instance of the <see cref="ColorGradient" /> class
|
||||||
@ -92,7 +89,8 @@ namespace Artemis.Core
|
|||||||
ColorGradientStop[] stops = Stops.OrderBy(x => x.Position).ToArray();
|
ColorGradientStop[] stops = Stops.OrderBy(x => x.Position).ToArray();
|
||||||
if (position <= 0) return stops[0].Color;
|
if (position <= 0) return stops[0].Color;
|
||||||
if (position >= 1) return stops[^1].Color;
|
if (position >= 1) return stops[^1].Color;
|
||||||
ColorGradientStop left = stops[0], right = null;
|
ColorGradientStop left = stops[0];
|
||||||
|
ColorGradientStop? right = null;
|
||||||
foreach (ColorGradientStop stop in stops)
|
foreach (ColorGradientStop stop in stops)
|
||||||
{
|
{
|
||||||
if (stop.Position >= position)
|
if (stop.Position >= position)
|
||||||
@ -130,18 +128,5 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
return gradient;
|
return gradient;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region PropertyChanged
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
|
|
||||||
[NotifyPropertyChangedInvocator]
|
|
||||||
internal virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,14 +1,11 @@
|
|||||||
using System.ComponentModel;
|
using SkiaSharp;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using Artemis.Core.Properties;
|
|
||||||
using SkiaSharp;
|
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A color with a position, usually contained in a <see cref="ColorGradient" />
|
/// A color with a position, usually contained in a <see cref="ColorGradient" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ColorGradientStop : INotifyPropertyChanged
|
public class ColorGradientStop : CorePropertyChanged
|
||||||
{
|
{
|
||||||
private SKColor _color;
|
private SKColor _color;
|
||||||
private float _position;
|
private float _position;
|
||||||
@ -28,12 +25,7 @@ namespace Artemis.Core
|
|||||||
public SKColor Color
|
public SKColor Color
|
||||||
{
|
{
|
||||||
get => _color;
|
get => _color;
|
||||||
set
|
set => SetAndNotify(ref _color, value);
|
||||||
{
|
|
||||||
if (value.Equals(_color)) return;
|
|
||||||
_color = value;
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -42,25 +34,7 @@ namespace Artemis.Core
|
|||||||
public float Position
|
public float Position
|
||||||
{
|
{
|
||||||
get => _position;
|
get => _position;
|
||||||
set
|
set => SetAndNotify(ref _position, value);
|
||||||
{
|
|
||||||
if (value.Equals(_position)) return;
|
|
||||||
_position = value;
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region PropertyChanged
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
|
|
||||||
[NotifyPropertyChangedInvocator]
|
|
||||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,7 +25,7 @@ namespace Artemis.Core
|
|||||||
/// Gets the plugin this condition operator belongs to
|
/// Gets the plugin this condition operator belongs to
|
||||||
/// <para>Note: Not set until after registering</para>
|
/// <para>Note: Not set until after registering</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin Plugin { get; internal set; }
|
public Plugin? Plugin { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the left side type of this condition operator
|
/// Gets the left side type of this condition operator
|
||||||
@ -64,9 +64,19 @@ namespace Artemis.Core
|
|||||||
internal abstract bool InternalEvaluate(object? leftSideValue, object? rightSideValue);
|
internal abstract bool InternalEvaluate(object? leftSideValue, object? rightSideValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a side of a condition parameter
|
||||||
|
/// </summary>
|
||||||
public enum ConditionParameterSide
|
public enum ConditionParameterSide
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The left side of a condition parameter
|
||||||
|
/// </summary>
|
||||||
Left,
|
Left,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The right side of a condition parameter
|
||||||
|
/// </summary>
|
||||||
Right
|
Right
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="target"></param>
|
/// <param name="target"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal abstract bool EvaluateObject(object target);
|
internal abstract bool EvaluateObject(object? target);
|
||||||
|
|
||||||
internal abstract void Save();
|
internal abstract void Save();
|
||||||
internal abstract DataModelConditionPartEntity GetEntity();
|
internal abstract DataModelConditionPartEntity GetEntity();
|
||||||
@ -104,14 +104,27 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler ChildAdded;
|
/// <summary>
|
||||||
public event EventHandler ChildRemoved;
|
/// Occurs when a child-condition was added
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? ChildAdded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a child-condition was removed
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? ChildRemoved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokers the <see cref="ChildAdded" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnChildAdded()
|
protected virtual void OnChildAdded()
|
||||||
{
|
{
|
||||||
ChildAdded?.Invoke(this, EventArgs.Empty);
|
ChildAdded?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokers the <see cref="ChildRemoved" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnChildRemoved()
|
protected virtual void OnChildRemoved()
|
||||||
{
|
{
|
||||||
ChildRemoved?.Invoke(this, EventArgs.Empty);
|
ChildRemoved?.Invoke(this, EventArgs.Empty);
|
||||||
|
|||||||
@ -63,8 +63,8 @@ namespace Artemis.Core
|
|||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic)
|
if (PredicateType == ProfileRightSideType.Dynamic)
|
||||||
return $"[Dynamic] {LeftPath} {Operator.Description} {RightPath}";
|
return $"[Dynamic] {LeftPath} {Operator?.Description} {RightPath}";
|
||||||
return $"[Static] {LeftPath} {Operator.Description} {RightStaticValue}";
|
return $"[Static] {LeftPath} {Operator?.Description} {RightStaticValue}";
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
@ -138,7 +138,14 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the left path of this condition predicate
|
||||||
|
/// </summary>
|
||||||
protected abstract void InitializeLeftPath();
|
protected abstract void InitializeLeftPath();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the right path of this condition predicate
|
||||||
|
/// </summary>
|
||||||
protected abstract void InitializeRightPath();
|
protected abstract void InitializeRightPath();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -315,7 +322,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
internal override bool EvaluateObject(object target)
|
internal override bool EvaluateObject(object? target)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -344,7 +351,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
||||||
|
|
||||||
if (Operator != null)
|
if (Operator?.Plugin != null)
|
||||||
{
|
{
|
||||||
Entity.OperatorPluginGuid = Operator.Plugin.Guid;
|
Entity.OperatorPluginGuid = Operator.Plugin.Guid;
|
||||||
Entity.OperatorType = Operator.GetType().Name;
|
Entity.OperatorType = Operator.GetType().Name;
|
||||||
@ -358,7 +365,7 @@ namespace Artemis.Core
|
|||||||
private void ConditionOperatorStoreOnConditionOperatorAdded(object? sender, ConditionOperatorStoreEvent e)
|
private void ConditionOperatorStoreOnConditionOperatorAdded(object? sender, ConditionOperatorStoreEvent e)
|
||||||
{
|
{
|
||||||
BaseConditionOperator conditionOperator = e.Registration.ConditionOperator;
|
BaseConditionOperator conditionOperator = e.Registration.ConditionOperator;
|
||||||
if (Entity.OperatorPluginGuid == conditionOperator.Plugin.Guid && Entity.OperatorType == conditionOperator.GetType().Name)
|
if (Entity.OperatorPluginGuid == conditionOperator.Plugin!.Guid && Entity.OperatorType == conditionOperator.GetType().Name)
|
||||||
UpdateOperator(conditionOperator);
|
UpdateOperator(conditionOperator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,9 +11,9 @@ namespace Artemis.Core
|
|||||||
public class DataModelConditionEvent : DataModelConditionPart
|
public class DataModelConditionEvent : DataModelConditionPart
|
||||||
{
|
{
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private bool _reinitializing;
|
|
||||||
private IDataModelEvent? _event;
|
private IDataModelEvent? _event;
|
||||||
private bool _eventTriggered;
|
private bool _eventTriggered;
|
||||||
|
private bool _reinitializing;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="DataModelConditionEvent" /> class
|
/// Creates a new instance of the <see cref="DataModelConditionEvent" /> class
|
||||||
@ -40,10 +40,13 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DataModelPath? EventPath { get; private set; }
|
public DataModelPath? EventPath { get; private set; }
|
||||||
|
|
||||||
public Type? EventArgumentType { get; set; }
|
/// <summary>
|
||||||
|
/// Gets or sets the type of argument the event provides
|
||||||
|
/// </summary>
|
||||||
|
public Type? EventArgumentType { get; private set; }
|
||||||
|
|
||||||
internal DataModelConditionEventEntity Entity { get; set; }
|
internal DataModelConditionEventEntity Entity { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Evaluate()
|
public override bool Evaluate()
|
||||||
{
|
{
|
||||||
@ -62,22 +65,12 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
// If there is a child (root group), it must evaluate to true whenever the event triggered
|
// If there is a child (root group), it must evaluate to true whenever the event triggered
|
||||||
if (Children.Any())
|
if (Children.Any())
|
||||||
return Children[0].EvaluateObject(_event.LastEventArgumentsUntyped);
|
return Children[0].EvaluateObject(_event?.LastEventArgumentsUntyped);
|
||||||
|
|
||||||
// If there are no children, we always evaluate to true whenever the event triggered
|
// If there are no children, we always evaluate to true whenever the event triggered
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SubscribeToDataModelEvent(IDataModelEvent dataModelEvent)
|
|
||||||
{
|
|
||||||
if (_event != null)
|
|
||||||
_event.EventTriggered -= OnEventTriggered;
|
|
||||||
|
|
||||||
_event = dataModelEvent;
|
|
||||||
if (_event != null)
|
|
||||||
_event.EventTriggered += OnEventTriggered;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the event the condition is triggered by
|
/// Updates the event the condition is triggered by
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -108,16 +101,6 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type? GetEventArgumentType()
|
|
||||||
{
|
|
||||||
if (EventPath == null || !EventPath.IsValid)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// Cannot rely on EventPath.GetValue() because part of the path might be null
|
|
||||||
Type eventType = EventPath.GetPropertyType()!;
|
|
||||||
return eventType.IsGenericType ? eventType.GetGenericArguments()[0] : typeof(DataModelEventArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -135,7 +118,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
internal override bool EvaluateObject(object target)
|
internal override bool EvaluateObject(object? target)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -191,6 +174,26 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SubscribeToDataModelEvent(IDataModelEvent dataModelEvent)
|
||||||
|
{
|
||||||
|
if (_event != null)
|
||||||
|
_event.EventTriggered -= OnEventTriggered;
|
||||||
|
|
||||||
|
_event = dataModelEvent;
|
||||||
|
if (_event != null)
|
||||||
|
_event.EventTriggered += OnEventTriggered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type? GetEventArgumentType()
|
||||||
|
{
|
||||||
|
if (EventPath == null || !EventPath.IsValid)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Cannot rely on EventPath.GetValue() because part of the path might be null
|
||||||
|
Type eventType = EventPath.GetPropertyType()!;
|
||||||
|
return eventType.IsGenericType ? eventType.GetGenericArguments()[0] : typeof(DataModelEventArgs);
|
||||||
|
}
|
||||||
|
|
||||||
private bool PointsToEvent(DataModelPath dataModelPath)
|
private bool PointsToEvent(DataModelPath dataModelPath)
|
||||||
{
|
{
|
||||||
Type? type = dataModelPath.GetPropertyType();
|
Type? type = dataModelPath.GetPropertyType();
|
||||||
|
|||||||
@ -53,7 +53,7 @@ namespace Artemis.Core
|
|||||||
throw new ArtemisCoreException("This data model condition event predicate does not belong to a data model condition event");
|
throw new ArtemisCoreException("This data model condition event predicate does not belong to a data model condition event");
|
||||||
}
|
}
|
||||||
|
|
||||||
private object? GetEventPathValue(DataModelPath path, object target)
|
private object? GetEventPathValue(DataModelPath path, object? target)
|
||||||
{
|
{
|
||||||
lock (path)
|
lock (path)
|
||||||
{
|
{
|
||||||
@ -67,6 +67,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Initialization
|
#region Initialization
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void InitializeLeftPath()
|
protected override void InitializeLeftPath()
|
||||||
{
|
{
|
||||||
if (Entity.LeftPath != null)
|
if (Entity.LeftPath != null)
|
||||||
@ -75,6 +76,7 @@ namespace Artemis.Core
|
|||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void InitializeRightPath()
|
protected override void InitializeRightPath()
|
||||||
{
|
{
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
||||||
@ -122,7 +124,7 @@ namespace Artemis.Core
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override bool EvaluateObject(object target)
|
internal override bool EvaluateObject(object? target)
|
||||||
{
|
{
|
||||||
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
|
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -46,12 +46,14 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Initialization
|
#region Initialization
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void InitializeLeftPath()
|
protected override void InitializeLeftPath()
|
||||||
{
|
{
|
||||||
if (Entity.LeftPath != null)
|
if (Entity.LeftPath != null)
|
||||||
LeftPath = new DataModelPath(null, Entity.LeftPath);
|
LeftPath = new DataModelPath(null, Entity.LeftPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void InitializeRightPath()
|
protected override void InitializeRightPath()
|
||||||
{
|
{
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
||||||
|
|||||||
@ -19,7 +19,7 @@ namespace Artemis.Core
|
|||||||
/// Creates a new instance of the <see cref="DataModelConditionGroup" /> class
|
/// Creates a new instance of the <see cref="DataModelConditionGroup" /> class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parent"></param>
|
/// <param name="parent"></param>
|
||||||
public DataModelConditionGroup(DataModelConditionPart parent)
|
public DataModelConditionGroup(DataModelConditionPart? parent)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
Entity = new DataModelConditionGroupEntity();
|
Entity = new DataModelConditionGroupEntity();
|
||||||
@ -32,7 +32,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parent"></param>
|
/// <param name="parent"></param>
|
||||||
/// <param name="entity"></param>
|
/// <param name="entity"></param>
|
||||||
public DataModelConditionGroup(DataModelConditionPart parent, DataModelConditionGroupEntity entity)
|
public DataModelConditionGroup(DataModelConditionPart? parent, DataModelConditionGroupEntity entity)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
@ -124,7 +124,7 @@ namespace Artemis.Core
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
internal override bool EvaluateObject(object target)
|
internal override bool EvaluateObject(object? target)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DataModelConditionGroup");
|
throw new ObjectDisposedException("DataModelConditionGroup");
|
||||||
|
|||||||
@ -94,7 +94,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
Type listType = ListPath.GetPropertyType()!;
|
Type listType = ListPath.GetPropertyType()!;
|
||||||
ListType = listType.GetGenericEnumerableType();
|
ListType = listType.GetGenericEnumerableType();
|
||||||
IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
|
IsPrimitiveList = ListType == null || ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
|
||||||
|
|
||||||
// Create a new root group
|
// Create a new root group
|
||||||
AddChild(new DataModelConditionGroup(this));
|
AddChild(new DataModelConditionGroup(this));
|
||||||
@ -188,7 +188,7 @@ namespace Artemis.Core
|
|||||||
if (ListPath.IsValid)
|
if (ListPath.IsValid)
|
||||||
{
|
{
|
||||||
ListType = listType.GetGenericEnumerableType();
|
ListType = listType.GetGenericEnumerableType();
|
||||||
IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
|
IsPrimitiveList = ListType == null || ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -53,7 +53,7 @@ namespace Artemis.Core
|
|||||||
throw new ArtemisCoreException("This data model condition list predicate does not belong to a data model condition list");
|
throw new ArtemisCoreException("This data model condition list predicate does not belong to a data model condition list");
|
||||||
}
|
}
|
||||||
|
|
||||||
private object? GetListPathValue(DataModelPath path, object target)
|
private object? GetListPathValue(DataModelPath path, object? target)
|
||||||
{
|
{
|
||||||
if (!(path.Target is ListPredicateWrapperDataModel wrapper))
|
if (!(path.Target is ListPredicateWrapperDataModel wrapper))
|
||||||
throw new ArtemisCoreException("Data model condition list predicate has a path with an invalid target");
|
throw new ArtemisCoreException("Data model condition list predicate has a path with an invalid target");
|
||||||
@ -64,6 +64,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Initialization
|
#region Initialization
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void InitializeLeftPath()
|
protected override void InitializeLeftPath()
|
||||||
{
|
{
|
||||||
if (Entity.LeftPath != null)
|
if (Entity.LeftPath != null)
|
||||||
@ -72,6 +73,7 @@ namespace Artemis.Core
|
|||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void InitializeRightPath()
|
protected override void InitializeRightPath()
|
||||||
{
|
{
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
||||||
@ -121,7 +123,7 @@ namespace Artemis.Core
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override bool EvaluateObject(object target)
|
internal override bool EvaluateObject(object? target)
|
||||||
{
|
{
|
||||||
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
|
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -19,11 +19,14 @@ namespace Artemis.Core
|
|||||||
Feature = Constants.CorePluginFeature;
|
Feature = Constants.CorePluginFeature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the last arguments of this event as an object
|
||||||
|
/// </summary>
|
||||||
[DataModelIgnore]
|
[DataModelIgnore]
|
||||||
public object? UntypedArguments { get; set; }
|
public object? UntypedArguments { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="EventPredicateWrapperDataModel"/> class
|
/// Creates a new instance of the <see cref="EventPredicateWrapperDataModel" /> class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static EventPredicateWrapperDataModel Create(Type type)
|
public static EventPredicateWrapperDataModel Create(Type type)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -19,6 +19,9 @@ namespace Artemis.Core
|
|||||||
Feature = Constants.CorePluginFeature;
|
Feature = Constants.CorePluginFeature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of this list as an object
|
||||||
|
/// </summary>
|
||||||
[DataModelIgnore]
|
[DataModelIgnore]
|
||||||
public object? UntypedValue { get; set; }
|
public object? UntypedValue { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,10 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public class DataBinding<TLayerProperty, TProperty> : IDataBinding
|
public class DataBinding<TLayerProperty, TProperty> : IDataBinding
|
||||||
{
|
{
|
||||||
private TProperty _currentValue;
|
private TProperty _currentValue = default!;
|
||||||
|
private TProperty _previousValue = default!;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private TimeSpan _easingProgress;
|
private TimeSpan _easingProgress;
|
||||||
private TProperty _previousValue;
|
|
||||||
|
|
||||||
internal DataBinding(DataBindingRegistration<TLayerProperty, TProperty> dataBindingRegistration)
|
internal DataBinding(DataBindingRegistration<TLayerProperty, TProperty> dataBindingRegistration)
|
||||||
{
|
{
|
||||||
@ -34,7 +34,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the data binding registration this data binding is based upon
|
/// Gets the data binding registration this data binding is based upon
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataBindingRegistration<TLayerProperty, TProperty> Registration { get; private set; }
|
public DataBindingRegistration<TLayerProperty, TProperty>? Registration { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the layer property this data binding targets
|
/// Gets the layer property this data binding targets
|
||||||
@ -44,12 +44,12 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the converter used to apply this data binding to the <see cref="LayerProperty" />
|
/// Gets the converter used to apply this data binding to the <see cref="LayerProperty" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataBindingConverter<TLayerProperty, TProperty> Converter { get; private set; }
|
public DataBindingConverter<TLayerProperty, TProperty>? Converter { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the data binding mode
|
/// Gets the data binding mode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDataBindingMode<TLayerProperty, TProperty> DataBindingMode { get; private set; }
|
public IDataBindingMode<TLayerProperty, TProperty>? DataBindingMode { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the easing time of the data binding
|
/// Gets or sets the easing time of the data binding
|
||||||
@ -93,9 +93,9 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the type of the target property of this data binding
|
/// Returns the type of the target property of this data binding
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Type GetTargetType()
|
public Type? GetTargetType()
|
||||||
{
|
{
|
||||||
return Registration.PropertyExpression.ReturnType;
|
return Registration?.PropertyExpression.ReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetEasing(TProperty value)
|
private void ResetEasing(TProperty value)
|
||||||
@ -111,15 +111,15 @@ namespace Artemis.Core
|
|||||||
throw new ArgumentNullException(nameof(dataBindingRegistration));
|
throw new ArgumentNullException(nameof(dataBindingRegistration));
|
||||||
|
|
||||||
dataBindingRegistration.DataBinding = this;
|
dataBindingRegistration.DataBinding = this;
|
||||||
Converter = dataBindingRegistration?.Converter;
|
Converter = dataBindingRegistration.Converter;
|
||||||
Registration = dataBindingRegistration;
|
Registration = dataBindingRegistration;
|
||||||
|
|
||||||
if (GetTargetType().IsValueType)
|
if (GetTargetType()!.IsValueType)
|
||||||
{
|
{
|
||||||
if (_currentValue == null)
|
if (_currentValue == null)
|
||||||
_currentValue = default;
|
_currentValue = default!;
|
||||||
if (_previousValue == null)
|
if (_previousValue == null)
|
||||||
_previousValue = default;
|
_previousValue = default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter?.Initialize(this);
|
Converter?.Initialize(this);
|
||||||
@ -127,7 +127,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private TProperty GetInterpolatedValue()
|
private TProperty GetInterpolatedValue()
|
||||||
{
|
{
|
||||||
if (_easingProgress == EasingTime || !Converter.SupportsInterpolate)
|
if (_easingProgress == EasingTime || Converter == null || !Converter.SupportsInterpolate)
|
||||||
return _currentValue;
|
return _currentValue;
|
||||||
|
|
||||||
double easingAmount = _easingProgress.TotalSeconds / EasingTime.TotalSeconds;
|
double easingAmount = _easingProgress.TotalSeconds / EasingTime.TotalSeconds;
|
||||||
@ -180,7 +180,8 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
Registration.DataBinding = null;
|
if (Registration != null)
|
||||||
|
Registration.DataBinding = null;
|
||||||
DataBindingMode?.Dispose();
|
DataBindingMode?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +235,7 @@ namespace Artemis.Core
|
|||||||
throw new ObjectDisposedException("DataBinding");
|
throw new ObjectDisposedException("DataBinding");
|
||||||
|
|
||||||
// General
|
// General
|
||||||
DataBindingRegistration<TLayerProperty, TProperty> registration = LayerProperty.GetDataBindingRegistration<TProperty>(Entity.TargetExpression);
|
DataBindingRegistration<TLayerProperty, TProperty>? registration = LayerProperty.GetDataBindingRegistration<TProperty>(Entity.TargetExpression);
|
||||||
if (registration != null)
|
if (registration != null)
|
||||||
ApplyRegistration(registration);
|
ApplyRegistration(registration);
|
||||||
|
|
||||||
@ -253,8 +254,10 @@ namespace Artemis.Core
|
|||||||
if (!LayerProperty.Entity.DataBindingEntities.Contains(Entity))
|
if (!LayerProperty.Entity.DataBindingEntities.Contains(Entity))
|
||||||
LayerProperty.Entity.DataBindingEntities.Add(Entity);
|
LayerProperty.Entity.DataBindingEntities.Add(Entity);
|
||||||
|
|
||||||
// General
|
// Don't save an invalid state
|
||||||
Entity.TargetExpression = Registration.PropertyExpression.ToString();
|
if (Registration != null)
|
||||||
|
Entity.TargetExpression = Registration.PropertyExpression.ToString();
|
||||||
|
|
||||||
Entity.EasingTime = EasingTime;
|
Entity.EasingTime = EasingTime;
|
||||||
Entity.EasingFunction = (int) EasingFunction;
|
Entity.EasingFunction = (int) EasingFunction;
|
||||||
|
|
||||||
|
|||||||
@ -13,22 +13,22 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a dynamically compiled getter pointing to the data bound property
|
/// Gets a dynamically compiled getter pointing to the data bound property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<TLayerProperty, TProperty> GetExpression { get; private set; }
|
public Func<TLayerProperty, TProperty>? GetExpression { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a dynamically compiled setter pointing to the data bound property used for value types
|
/// Gets a dynamically compiled setter pointing to the data bound property used for value types
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<TProperty> ValueTypeSetExpression { get; private set; }
|
public Action<TProperty>? ValueTypeSetExpression { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a dynamically compiled setter pointing to the data bound property used for reference types
|
/// Gets a dynamically compiled setter pointing to the data bound property used for reference types
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<TLayerProperty, TProperty> ReferenceTypeSetExpression { get; private set; }
|
public Action<TLayerProperty, TProperty>? ReferenceTypeSetExpression { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the data binding this converter is applied to
|
/// Gets the data binding this converter is applied to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataBinding<TLayerProperty, TProperty> DataBinding { get; private set; }
|
public DataBinding<TLayerProperty, TProperty>? DataBinding { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets whether or not this data binding converter supports the <see cref="Sum" /> method
|
/// Gets whether or not this data binding converter supports the <see cref="Sum" /> method
|
||||||
@ -65,6 +65,8 @@ namespace Artemis.Core
|
|||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
public virtual void ApplyValue(TProperty value)
|
public virtual void ApplyValue(TProperty value)
|
||||||
{
|
{
|
||||||
|
if (DataBinding == null)
|
||||||
|
throw new ArtemisCoreException("Data binding converter is not yet initialized");
|
||||||
if (ReferenceTypeSetExpression != null)
|
if (ReferenceTypeSetExpression != null)
|
||||||
ReferenceTypeSetExpression(DataBinding.LayerProperty.CurrentValue, value);
|
ReferenceTypeSetExpression(DataBinding.LayerProperty.CurrentValue, value);
|
||||||
else if (ValueTypeSetExpression != null)
|
else if (ValueTypeSetExpression != null)
|
||||||
@ -76,6 +78,8 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual TProperty GetValue()
|
public virtual TProperty GetValue()
|
||||||
{
|
{
|
||||||
|
if (DataBinding == null || GetExpression == null)
|
||||||
|
throw new ArtemisCoreException("Data binding converter is not yet initialized");
|
||||||
return GetExpression(DataBinding.LayerProperty.CurrentValue);
|
return GetExpression(DataBinding.LayerProperty.CurrentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +88,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual TProperty ConvertFromObject(object? source)
|
public virtual TProperty ConvertFromObject(object? source)
|
||||||
{
|
{
|
||||||
return (TProperty) Convert.ChangeType(source, typeof(TProperty));
|
return (TProperty) Convert.ChangeType(source, typeof(TProperty))!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -96,6 +100,9 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void Initialize(DataBinding<TLayerProperty, TProperty> dataBinding)
|
internal void Initialize(DataBinding<TLayerProperty, TProperty> dataBinding)
|
||||||
{
|
{
|
||||||
|
if (dataBinding.Registration == null)
|
||||||
|
throw new ArtemisCoreException("Cannot initialize a data binding converter for a data binding without a registration");
|
||||||
|
|
||||||
DataBinding = dataBinding;
|
DataBinding = dataBinding;
|
||||||
GetExpression = dataBinding.Registration.PropertyExpression.Compile();
|
GetExpression = dataBinding.Registration.PropertyExpression.Compile();
|
||||||
CreateSetExpression();
|
CreateSetExpression();
|
||||||
@ -106,14 +113,14 @@ namespace Artemis.Core
|
|||||||
private void CreateSetExpression()
|
private void CreateSetExpression()
|
||||||
{
|
{
|
||||||
// If the registration does not point towards a member of LayerProperty<T>.CurrentValue, assign directly to LayerProperty<T>.CurrentValue
|
// If the registration does not point towards a member of LayerProperty<T>.CurrentValue, assign directly to LayerProperty<T>.CurrentValue
|
||||||
if (DataBinding.Registration.Member == null)
|
if (DataBinding!.Registration?.Member == null)
|
||||||
{
|
{
|
||||||
CreateSetCurrentValueExpression();
|
CreateSetCurrentValueExpression();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the member of LayerProperty<T>.CurrentValue has a setter
|
// Ensure the member of LayerProperty<T>.CurrentValue has a setter
|
||||||
MethodInfo setterMethod = null;
|
MethodInfo? setterMethod = null;
|
||||||
if (DataBinding.Registration.Member is PropertyInfo propertyInfo)
|
if (DataBinding.Registration.Member is PropertyInfo propertyInfo)
|
||||||
setterMethod = propertyInfo.GetSetMethod();
|
setterMethod = propertyInfo.GetSetMethod();
|
||||||
// If there is no setter, the built-in data binding cannot do its job, stay null
|
// If there is no setter, the built-in data binding cannot do its job, stay null
|
||||||
@ -130,6 +137,9 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void CreateSetReferenceTypeExpression()
|
private void CreateSetReferenceTypeExpression()
|
||||||
{
|
{
|
||||||
|
if (DataBinding!.Registration?.Member == null)
|
||||||
|
throw new ArtemisCoreException("Cannot create value setter for data binding without a registration");
|
||||||
|
|
||||||
ParameterExpression propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
ParameterExpression propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
||||||
ParameterExpression parameter = Expression.Parameter(typeof(TLayerProperty), "currentValue");
|
ParameterExpression parameter = Expression.Parameter(typeof(TLayerProperty), "currentValue");
|
||||||
MemberExpression memberAccess = Expression.MakeMemberAccess(parameter, DataBinding.Registration.Member);
|
MemberExpression memberAccess = Expression.MakeMemberAccess(parameter, DataBinding.Registration.Member);
|
||||||
@ -141,6 +151,9 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void CreateSetValueTypeExpression()
|
private void CreateSetValueTypeExpression()
|
||||||
{
|
{
|
||||||
|
if (DataBinding!.Registration?.Member == null)
|
||||||
|
throw new ArtemisCoreException("Cannot create value setter for data binding without a registration");
|
||||||
|
|
||||||
ParameterExpression propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
ParameterExpression propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
||||||
ParameterExpression variableCurrent = Expression.Variable(typeof(TLayerProperty), "current");
|
ParameterExpression variableCurrent = Expression.Variable(typeof(TLayerProperty), "current");
|
||||||
ConstantExpression layerProperty = Expression.Constant(DataBinding.LayerProperty);
|
ConstantExpression layerProperty = Expression.Constant(DataBinding.LayerProperty);
|
||||||
@ -161,7 +174,7 @@ namespace Artemis.Core
|
|||||||
private void CreateSetCurrentValueExpression()
|
private void CreateSetCurrentValueExpression()
|
||||||
{
|
{
|
||||||
ParameterExpression propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
ParameterExpression propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
||||||
ConstantExpression layerProperty = Expression.Constant(DataBinding.LayerProperty);
|
ConstantExpression layerProperty = Expression.Constant(DataBinding!.LayerProperty);
|
||||||
MemberExpression layerPropertyMemberAccess = Expression.MakeMemberAccess(layerProperty,
|
MemberExpression layerPropertyMemberAccess = Expression.MakeMemberAccess(layerProperty,
|
||||||
DataBinding.LayerProperty.GetType().GetMember(nameof(DataBinding.LayerProperty.CurrentValue))[0]);
|
DataBinding.LayerProperty.GetType().GetMember(nameof(DataBinding.LayerProperty.CurrentValue))[0]);
|
||||||
|
|
||||||
|
|||||||
@ -38,28 +38,28 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the member the <see cref="PropertyExpression" /> targets
|
/// Gets the member the <see cref="PropertyExpression" /> targets
|
||||||
/// <para><c>null</c> if the <see cref="PropertyExpression" /> is not a member expression</para>
|
/// <para><see langword="null"/> if the <see cref="PropertyExpression" /> is not a member expression</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MemberInfo Member { get; }
|
public MemberInfo? Member { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the data binding created using this registration
|
/// Gets the data binding created using this registration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataBinding<TLayerProperty, TProperty> DataBinding { get; internal set; }
|
public DataBinding<TLayerProperty, TProperty>? DataBinding { get; internal set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IDataBinding GetDataBinding()
|
public IDataBinding? GetDataBinding()
|
||||||
{
|
{
|
||||||
return DataBinding;
|
return DataBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IDataBinding CreateDataBinding()
|
public IDataBinding? CreateDataBinding()
|
||||||
{
|
{
|
||||||
if (DataBinding != null)
|
if (DataBinding != null)
|
||||||
return DataBinding;
|
return DataBinding;
|
||||||
|
|
||||||
DataBindingEntity dataBinding = LayerProperty.Entity.DataBindingEntities.FirstOrDefault(e => e.TargetExpression == PropertyExpression.ToString());
|
DataBindingEntity? dataBinding = LayerProperty.Entity.DataBindingEntities.FirstOrDefault(e => e.TargetExpression == PropertyExpression.ToString());
|
||||||
if (dataBinding == null)
|
if (dataBinding == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|||||||
@ -8,12 +8,12 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the data binding applied using this registration
|
/// Returns the data binding applied using this registration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDataBinding GetDataBinding();
|
public IDataBinding? GetDataBinding();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If found, creates a data binding from storage
|
/// If found, creates a data binding from storage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
IDataBinding CreateDataBinding();
|
IDataBinding? CreateDataBinding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,13 +21,13 @@ namespace Artemis.Core
|
|||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ConditionalDataBindingEntity Entity { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of conditions applied to this data binding
|
/// Gets a list of conditions applied to this data binding
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReadOnlyCollection<DataBindingCondition<TLayerProperty, TProperty>> Conditions => _conditions.AsReadOnly();
|
public ReadOnlyCollection<DataBindingCondition<TLayerProperty, TProperty>> Conditions => _conditions.AsReadOnly();
|
||||||
|
|
||||||
|
internal ConditionalDataBindingEntity Entity { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public DataBinding<TLayerProperty, TProperty> DataBinding { get; }
|
public DataBinding<TLayerProperty, TProperty> DataBinding { get; }
|
||||||
|
|
||||||
@ -37,9 +37,7 @@ namespace Artemis.Core
|
|||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("ConditionalDataBinding");
|
throw new ObjectDisposedException("ConditionalDataBinding");
|
||||||
|
|
||||||
DataBindingCondition<TLayerProperty, TProperty> condition = Conditions.FirstOrDefault(c => c.Evaluate());
|
DataBindingCondition<TLayerProperty, TProperty>? condition = Conditions.FirstOrDefault(c => c.Evaluate());
|
||||||
if (condition != null)
|
|
||||||
Console.WriteLine();
|
|
||||||
return condition == null ? baseValue : condition.Value;
|
return condition == null ? baseValue : condition.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +73,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
return condition;
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a condition from the conditional data binding's <see cref="Conditions" /> collection and disposes it
|
/// Removes a condition from the conditional data binding's <see cref="Conditions" /> collection and disposes it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -111,7 +109,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Storage
|
#region Storage
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -138,8 +136,11 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when a condition is added or removed
|
/// Occurs when a condition is added or removed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler ConditionsUpdated;
|
public event EventHandler? ConditionsUpdated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ConditionsUpdated" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnConditionsUpdated()
|
protected virtual void OnConditionsUpdated()
|
||||||
{
|
{
|
||||||
ConditionsUpdated?.Invoke(this, EventArgs.Empty);
|
ConditionsUpdated?.Invoke(this, EventArgs.Empty);
|
||||||
|
|||||||
@ -18,6 +18,8 @@ namespace Artemis.Core
|
|||||||
ConditionalDataBinding = conditionalDataBinding ?? throw new ArgumentNullException(nameof(conditionalDataBinding));
|
ConditionalDataBinding = conditionalDataBinding ?? throw new ArgumentNullException(nameof(conditionalDataBinding));
|
||||||
Order = conditionalDataBinding.Conditions.Count + 1;
|
Order = conditionalDataBinding.Conditions.Count + 1;
|
||||||
Condition = new DataModelConditionGroup(null);
|
Condition = new DataModelConditionGroup(null);
|
||||||
|
Value = default!;
|
||||||
|
|
||||||
Entity = new DataBindingConditionEntity();
|
Entity = new DataBindingConditionEntity();
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
@ -26,6 +28,9 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
ConditionalDataBinding = conditionalDataBinding ?? throw new ArgumentNullException(nameof(conditionalDataBinding));
|
ConditionalDataBinding = conditionalDataBinding ?? throw new ArgumentNullException(nameof(conditionalDataBinding));
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
|
Condition = null!;
|
||||||
|
Value = default!;
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +88,7 @@ namespace Artemis.Core
|
|||||||
? new DataModelConditionGroup(null, Entity.Condition)
|
? new DataModelConditionGroup(null, Entity.Condition)
|
||||||
: new DataModelConditionGroup(null);
|
: new DataModelConditionGroup(null);
|
||||||
|
|
||||||
Value = Entity.Value == null ? default : JsonConvert.DeserializeObject<TProperty>(Entity.Value);
|
Value = (Entity.Value == null ? default : JsonConvert.DeserializeObject<TProperty>(Entity.Value))!;
|
||||||
Order = Entity.Order;
|
Order = Entity.Order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace Artemis.Core
|
|||||||
/// Gets the plugin this data binding modifier belongs to
|
/// Gets the plugin this data binding modifier belongs to
|
||||||
/// <para>Note: Not set until after registering</para>
|
/// <para>Note: Not set until after registering</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin Plugin { get; internal set; }
|
public Plugin? Plugin { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the value type of this modifier type
|
/// Gets the value type of this modifier type
|
||||||
@ -35,17 +35,17 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the icon of this modifier
|
/// Gets or sets the icon of this modifier
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract string Icon { get; }
|
public abstract string? Icon { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the description of this modifier
|
/// Gets the description of this modifier
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual string Description => null;
|
public virtual string? Description => null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the category of this modifier
|
/// Gets the category of this modifier
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual string Category => null;
|
public virtual string? Category => null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns whether the given type is supported by the modifier
|
/// Returns whether the given type is supported by the modifier
|
||||||
@ -69,14 +69,26 @@ namespace Artemis.Core
|
|||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="currentValue">The current value before modification, type should match <see cref="ValueType" /></param>
|
/// <param name="currentValue">The current value before modification, type should match <see cref="ValueType" /></param>
|
||||||
/// <param name="parameterValue">The parameter to use for the modification, type should match <see cref="ParameterType" /></param>
|
/// <param name="parameterValue">
|
||||||
|
/// The parameter to use for the modification, type should match <see cref="ParameterType" />
|
||||||
|
/// </param>
|
||||||
/// <returns>The modified value, with a type of <see cref="ValueType" /></returns>
|
/// <returns>The modified value, with a type of <see cref="ValueType" /></returns>
|
||||||
internal abstract object? InternalApply(object? currentValue, object? parameterValue);
|
internal abstract object? InternalApply(object? currentValue, object? parameterValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a part of a modifier type
|
||||||
|
/// </summary>
|
||||||
public enum ModifierTypePart
|
public enum ModifierTypePart
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The value part of a modifier, backed by <see cref="DataBindingModifierType{TValue}.ValueType" />
|
||||||
|
/// </summary>
|
||||||
Value,
|
Value,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The parameter part of a modifier, backed by <see cref="DataBindingModifierType{TValue,TParameter}.ParameterType" />
|
||||||
|
/// </summary>
|
||||||
Parameter
|
Parameter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,8 +103,8 @@ namespace Artemis.Core
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type targetType = DirectDataBinding.DataBinding.GetTargetType();
|
Type? targetType = DirectDataBinding.DataBinding.GetTargetType();
|
||||||
if (!modifierType.SupportsType(targetType, ModifierTypePart.Value))
|
if (targetType != null && !modifierType.SupportsType(targetType, ModifierTypePart.Value))
|
||||||
throw new ArtemisCoreException($"Cannot apply modifier type {modifierType.GetType().Name} to this modifier because " +
|
throw new ArtemisCoreException($"Cannot apply modifier type {modifierType.GetType().Name} to this modifier because " +
|
||||||
$"it does not support this data binding's type {targetType.Name}");
|
$"it does not support this data binding's type {targetType.Name}");
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ namespace Artemis.Core
|
|||||||
/// Updates the parameter of the modifier, makes the modifier static and re-compiles the expression
|
/// Updates the parameter of the modifier, makes the modifier static and re-compiles the expression
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="staticValue">The static value to use as a parameter</param>
|
/// <param name="staticValue">The static value to use as a parameter</param>
|
||||||
public void UpdateParameterStatic(object staticValue)
|
public void UpdateParameterStatic(object? staticValue)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DataBindingModifier");
|
throw new ObjectDisposedException("DataBindingModifier");
|
||||||
@ -167,10 +167,10 @@ namespace Artemis.Core
|
|||||||
ParameterPath?.Dispose();
|
ParameterPath?.Dispose();
|
||||||
ParameterPath = null;
|
ParameterPath = null;
|
||||||
|
|
||||||
Type parameterType = ModifierType?.ParameterType ?? DirectDataBinding.DataBinding.GetTargetType();
|
Type? parameterType = ModifierType?.ParameterType ?? DirectDataBinding.DataBinding.GetTargetType();
|
||||||
|
|
||||||
// If not null ensure the types match and if not, convert it
|
// If not null ensure the types match and if not, convert it
|
||||||
if (staticValue != null && staticValue.GetType() == parameterType)
|
if (parameterType == null || staticValue != null && staticValue.GetType() == parameterType)
|
||||||
ParameterStaticValue = staticValue;
|
ParameterStaticValue = staticValue;
|
||||||
else if (staticValue != null)
|
else if (staticValue != null)
|
||||||
ParameterStaticValue = Convert.ChangeType(staticValue, parameterType);
|
ParameterStaticValue = Convert.ChangeType(staticValue, parameterType);
|
||||||
@ -189,7 +189,7 @@ namespace Artemis.Core
|
|||||||
// Modifier type
|
// Modifier type
|
||||||
if (Entity.ModifierTypePluginGuid != null && ModifierType == null)
|
if (Entity.ModifierTypePluginGuid != null && ModifierType == null)
|
||||||
{
|
{
|
||||||
BaseDataBindingModifierType modifierType = DataBindingModifierTypeStore.Get(Entity.ModifierTypePluginGuid.Value, Entity.ModifierType)?.DataBindingModifierType;
|
BaseDataBindingModifierType? modifierType = DataBindingModifierTypeStore.Get(Entity.ModifierTypePluginGuid.Value, Entity.ModifierType)?.DataBindingModifierType;
|
||||||
if (modifierType != null)
|
if (modifierType != null)
|
||||||
UpdateModifierType(modifierType);
|
UpdateModifierType(modifierType);
|
||||||
}
|
}
|
||||||
@ -203,18 +203,21 @@ namespace Artemis.Core
|
|||||||
else if (ParameterType == ProfileRightSideType.Static && Entity.ParameterStaticValue != null)
|
else if (ParameterType == ProfileRightSideType.Static && Entity.ParameterStaticValue != null)
|
||||||
{
|
{
|
||||||
// Use the target type so JSON.NET has a better idea what to do
|
// Use the target type so JSON.NET has a better idea what to do
|
||||||
Type parameterType = ModifierType?.ParameterType ?? DirectDataBinding.DataBinding.GetTargetType();
|
Type? parameterType = ModifierType?.ParameterType ?? DirectDataBinding.DataBinding.GetTargetType();
|
||||||
object staticValue;
|
object? staticValue = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
staticValue = JsonConvert.DeserializeObject(Entity.ParameterStaticValue, parameterType);
|
staticValue = parameterType != null
|
||||||
|
? JsonConvert.DeserializeObject(Entity.ParameterStaticValue, parameterType)
|
||||||
|
: JsonConvert.DeserializeObject(Entity.ParameterStaticValue);
|
||||||
}
|
}
|
||||||
// If deserialization fails, use the type's default
|
// If deserialization fails, use the type's default
|
||||||
catch (JsonSerializationException e)
|
catch (JsonSerializationException e)
|
||||||
{
|
{
|
||||||
DeserializationLogger.LogModifierDeserializationFailure(GetType().Name, e);
|
DeserializationLogger.LogModifierDeserializationFailure(GetType().Name, e);
|
||||||
staticValue = Activator.CreateInstance(parameterType);
|
if (parameterType != null)
|
||||||
|
staticValue = Activator.CreateInstance(parameterType);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateParameterStatic(staticValue);
|
UpdateParameterStatic(staticValue);
|
||||||
@ -235,7 +238,7 @@ namespace Artemis.Core
|
|||||||
DirectDataBinding.Entity.Modifiers.Add(Entity);
|
DirectDataBinding.Entity.Modifiers.Add(Entity);
|
||||||
|
|
||||||
// Modifier
|
// Modifier
|
||||||
if (ModifierType != null)
|
if (ModifierType?.Plugin != null)
|
||||||
{
|
{
|
||||||
Entity.ModifierType = ModifierType.GetType().Name;
|
Entity.ModifierType = ModifierType.GetType().Name;
|
||||||
Entity.ModifierTypePluginGuid = ModifierType.Plugin.Guid;
|
Entity.ModifierTypePluginGuid = ModifierType.Plugin.Guid;
|
||||||
@ -280,17 +283,17 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Event handlers
|
#region Event handlers
|
||||||
|
|
||||||
private void DataBindingModifierTypeStoreOnDataBindingModifierAdded(object sender, DataBindingModifierTypeStoreEvent e)
|
private void DataBindingModifierTypeStoreOnDataBindingModifierAdded(object? sender, DataBindingModifierTypeStoreEvent e)
|
||||||
{
|
{
|
||||||
if (ModifierType != null)
|
if (ModifierType != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BaseDataBindingModifierType modifierType = e.TypeRegistration.DataBindingModifierType;
|
BaseDataBindingModifierType modifierType = e.TypeRegistration.DataBindingModifierType;
|
||||||
if (modifierType.Plugin.Guid == Entity.ModifierTypePluginGuid && modifierType.GetType().Name == Entity.ModifierType)
|
if (modifierType.Plugin!.Guid == Entity.ModifierTypePluginGuid && modifierType.GetType().Name == Entity.ModifierType)
|
||||||
UpdateModifierType(modifierType);
|
UpdateModifierType(modifierType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DataBindingModifierTypeStoreOnDataBindingModifierRemoved(object sender, DataBindingModifierTypeStoreEvent e)
|
private void DataBindingModifierTypeStoreOnDataBindingModifierRemoved(object? sender, DataBindingModifierTypeStoreEvent e)
|
||||||
{
|
{
|
||||||
if (e.TypeRegistration.DataBindingModifierType == ModifierType)
|
if (e.TypeRegistration.DataBindingModifierType == ModifierType)
|
||||||
UpdateModifierType(null);
|
UpdateModifierType(null);
|
||||||
|
|||||||
@ -42,7 +42,7 @@ namespace Artemis.Core
|
|||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DirectDataBinding");
|
throw new ObjectDisposedException("DirectDataBinding");
|
||||||
|
|
||||||
if (SourcePath == null || !SourcePath.IsValid)
|
if (SourcePath == null || !SourcePath.IsValid || DataBinding.Converter == null)
|
||||||
return baseValue;
|
return baseValue;
|
||||||
|
|
||||||
object? dataBindingValue = SourcePath.GetValue();
|
object? dataBindingValue = SourcePath.GetValue();
|
||||||
@ -188,6 +188,9 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler? ModifiersUpdated;
|
public event EventHandler? ModifiersUpdated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ModifiersUpdated" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnModifiersUpdated()
|
protected virtual void OnModifiersUpdated()
|
||||||
{
|
{
|
||||||
ModifiersUpdated?.Invoke(this, EventArgs.Empty);
|
ModifiersUpdated?.Invoke(this, EventArgs.Empty);
|
||||||
|
|||||||
@ -318,18 +318,24 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs whenever the path becomes invalid
|
/// Occurs whenever the path becomes invalid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler PathInvalidated;
|
public event EventHandler? PathInvalidated;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs whenever the path becomes valid
|
/// Occurs whenever the path becomes valid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler PathValidated;
|
public event EventHandler? PathValidated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="PathInvalidated" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnPathValidated()
|
protected virtual void OnPathValidated()
|
||||||
{
|
{
|
||||||
PathValidated?.Invoke(this, EventArgs.Empty);
|
PathValidated?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="PathValidated" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnPathInvalidated()
|
protected virtual void OnPathInvalidated()
|
||||||
{
|
{
|
||||||
PathInvalidated?.Invoke(this, EventArgs.Empty);
|
PathInvalidated?.Invoke(this, EventArgs.Empty);
|
||||||
|
|||||||
@ -115,8 +115,8 @@ namespace Artemis.Core
|
|||||||
// Dynamic types have a data model description
|
// Dynamic types have a data model description
|
||||||
if (Type == DataModelPathSegmentType.Dynamic)
|
if (Type == DataModelPathSegmentType.Dynamic)
|
||||||
return (GetValue() as DataModel)?.DataModelDescription;
|
return (GetValue() as DataModel)?.DataModelDescription;
|
||||||
if (IsStartSegment && DataModelPath.Target is DataModel targetDataModel)
|
if (IsStartSegment && DataModelPath.Target != null)
|
||||||
return targetDataModel.DataModelDescription;
|
return DataModelPath.Target.DataModelDescription;
|
||||||
if (IsStartSegment)
|
if (IsStartSegment)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ namespace Artemis.Core
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Static types may have one as an attribute
|
// Static types may have one as an attribute
|
||||||
DataModelPropertyAttribute? attribute = (DataModelPropertyAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(DataModelPropertyAttribute));
|
DataModelPropertyAttribute? attribute = (DataModelPropertyAttribute?) Attribute.GetCustomAttribute(propertyInfo, typeof(DataModelPropertyAttribute));
|
||||||
if (attribute != null)
|
if (attribute != null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(attribute.Name))
|
if (string.IsNullOrWhiteSpace(attribute.Name))
|
||||||
@ -187,8 +187,8 @@ namespace Artemis.Core
|
|||||||
return CreateExpression(parameter, expression, nullCondition);
|
return CreateExpression(parameter, expression, nullCondition);
|
||||||
|
|
||||||
// If a dynamic data model is found the use that
|
// If a dynamic data model is found the use that
|
||||||
bool hasDynamicDataModel = _dynamicDataModel.DynamicDataModels.TryGetValue(Identifier, out DataModel dynamicDataModel);
|
bool hasDynamicDataModel = _dynamicDataModel.DynamicDataModels.TryGetValue(Identifier, out DataModel? dynamicDataModel);
|
||||||
if (hasDynamicDataModel)
|
if (hasDynamicDataModel && dynamicDataModel != null)
|
||||||
DetermineDynamicType(dynamicDataModel);
|
DetermineDynamicType(dynamicDataModel);
|
||||||
|
|
||||||
_dynamicDataModel.DynamicDataModelAdded += DynamicDataModelOnDynamicDataModelAdded;
|
_dynamicDataModel.DynamicDataModelAdded += DynamicDataModelOnDynamicDataModelAdded;
|
||||||
@ -219,7 +219,7 @@ namespace Artemis.Core
|
|||||||
accessorExpression = Expression.Call(
|
accessorExpression = Expression.Call(
|
||||||
expression,
|
expression,
|
||||||
nameof(DataModel.DynamicChild),
|
nameof(DataModel.DynamicChild),
|
||||||
new[] {DynamicDataModelType},
|
DynamicDataModelType != null ? new[] {DynamicDataModelType} : null,
|
||||||
Expression.Constant(Identifier)
|
Expression.Constant(Identifier)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -30,8 +30,8 @@ namespace Artemis.Core
|
|||||||
Name = name;
|
Name = name;
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
|
|
||||||
_layerEffects = new List<BaseLayerEffect>();
|
LayerEffectsList = new List<BaseLayerEffect>();
|
||||||
_expandedPropertyGroups = new List<string>();
|
ExpandedPropertyGroups = new List<string>();
|
||||||
|
|
||||||
Parent.AddChild(this);
|
Parent.AddChild(this);
|
||||||
}
|
}
|
||||||
@ -47,8 +47,8 @@ namespace Artemis.Core
|
|||||||
Enabled = folderEntity.Enabled;
|
Enabled = folderEntity.Enabled;
|
||||||
Order = folderEntity.Order;
|
Order = folderEntity.Order;
|
||||||
|
|
||||||
_layerEffects = new List<BaseLayerEffect>();
|
LayerEffectsList = new List<BaseLayerEffect>();
|
||||||
_expandedPropertyGroups = new List<string>();
|
ExpandedPropertyGroups = new List<string>();
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
@ -58,11 +58,6 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsRootFolder => Parent == Profile;
|
public bool IsRootFolder => Parent == Profile;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the longest timeline of all this folders children
|
|
||||||
/// </summary>
|
|
||||||
public Timeline LongestChildTimeline { get; private set; }
|
|
||||||
|
|
||||||
internal FolderEntity FolderEntity { get; set; }
|
internal FolderEntity FolderEntity { get; set; }
|
||||||
|
|
||||||
internal override RenderElementEntity RenderElementEntity => FolderEntity;
|
internal override RenderElementEntity RenderElementEntity => FolderEntity;
|
||||||
@ -78,6 +73,7 @@ namespace Artemis.Core
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override void Update(double deltaTime)
|
public override void Update(double deltaTime)
|
||||||
{
|
{
|
||||||
if (Disposed)
|
if (Disposed)
|
||||||
@ -129,6 +125,9 @@ namespace Artemis.Core
|
|||||||
/// <returns>The newly created copy</returns>
|
/// <returns>The newly created copy</returns>
|
||||||
public Folder CreateCopy()
|
public Folder CreateCopy()
|
||||||
{
|
{
|
||||||
|
if (Parent == null)
|
||||||
|
throw new ArtemisCoreException("Cannot create a copy of a folder without a parent");
|
||||||
|
|
||||||
JsonSerializerSettings settings = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All};
|
JsonSerializerSettings settings = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All};
|
||||||
FolderEntity entityCopy = JsonConvert.DeserializeObject<FolderEntity>(JsonConvert.SerializeObject(FolderEntity, settings), settings)!;
|
FolderEntity entityCopy = JsonConvert.DeserializeObject<FolderEntity>(JsonConvert.SerializeObject(FolderEntity, settings), settings)!;
|
||||||
entityCopy.Id = Guid.NewGuid();
|
entityCopy.Id = Guid.NewGuid();
|
||||||
@ -139,12 +138,13 @@ namespace Artemis.Core
|
|||||||
return new Folder(Profile, Parent, entityCopy);
|
return new Folder(Profile, Parent, entityCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"[Folder] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
return $"[Folder] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculateRenderProperties()
|
internal void CalculateRenderProperties()
|
||||||
{
|
{
|
||||||
if (Disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Folder");
|
throw new ObjectDisposedException("Folder");
|
||||||
@ -163,57 +163,9 @@ namespace Artemis.Core
|
|||||||
OnRenderPropertiesUpdated();
|
OnRenderPropertiesUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
Disposed = true;
|
|
||||||
|
|
||||||
foreach (ProfileElement profileElement in Children)
|
|
||||||
profileElement.Dispose();
|
|
||||||
Renderer.Dispose();
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void Load()
|
|
||||||
{
|
|
||||||
_expandedPropertyGroups.AddRange(FolderEntity.ExpandedPropertyGroups);
|
|
||||||
|
|
||||||
// Load child folders
|
|
||||||
foreach (FolderEntity childFolder in Profile.ProfileEntity.Folders.Where(f => f.ParentId == EntityId))
|
|
||||||
ChildrenList.Add(new Folder(Profile, this, childFolder));
|
|
||||||
// Load child layers
|
|
||||||
foreach (LayerEntity childLayer in Profile.ProfileEntity.Layers.Where(f => f.ParentId == EntityId))
|
|
||||||
ChildrenList.Add(new Layer(Profile, this, childLayer));
|
|
||||||
|
|
||||||
// Ensure order integrity, should be unnecessary but no one is perfect specially me
|
|
||||||
ChildrenList = ChildrenList.OrderBy(c => c.Order).ToList();
|
|
||||||
for (int index = 0; index < ChildrenList.Count; index++)
|
|
||||||
ChildrenList[index].Order = index + 1;
|
|
||||||
|
|
||||||
LoadRenderElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void Save()
|
|
||||||
{
|
|
||||||
if (Disposed)
|
|
||||||
throw new ObjectDisposedException("Folder");
|
|
||||||
|
|
||||||
FolderEntity.Id = EntityId;
|
|
||||||
FolderEntity.ParentId = Parent?.EntityId ?? new Guid();
|
|
||||||
|
|
||||||
FolderEntity.Order = Order;
|
|
||||||
FolderEntity.Name = Name;
|
|
||||||
FolderEntity.Enabled = Enabled;
|
|
||||||
|
|
||||||
FolderEntity.ProfileId = Profile.EntityId;
|
|
||||||
FolderEntity.ExpandedPropertyGroups.Clear();
|
|
||||||
FolderEntity.ExpandedPropertyGroups.AddRange(_expandedPropertyGroups);
|
|
||||||
|
|
||||||
SaveRenderElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Rendering
|
#region Rendering
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override void Render(SKCanvas canvas)
|
public override void Render(SKCanvas canvas)
|
||||||
{
|
{
|
||||||
if (Disposed)
|
if (Disposed)
|
||||||
@ -278,9 +230,62 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
Disposed = true;
|
||||||
|
|
||||||
|
foreach (ProfileElement profileElement in Children)
|
||||||
|
profileElement.Dispose();
|
||||||
|
Renderer.Dispose();
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Load()
|
||||||
|
{
|
||||||
|
ExpandedPropertyGroups.AddRange(FolderEntity.ExpandedPropertyGroups);
|
||||||
|
|
||||||
|
// Load child folders
|
||||||
|
foreach (FolderEntity childFolder in Profile.ProfileEntity.Folders.Where(f => f.ParentId == EntityId))
|
||||||
|
ChildrenList.Add(new Folder(Profile, this, childFolder));
|
||||||
|
// Load child layers
|
||||||
|
foreach (LayerEntity childLayer in Profile.ProfileEntity.Layers.Where(f => f.ParentId == EntityId))
|
||||||
|
ChildrenList.Add(new Layer(Profile, this, childLayer));
|
||||||
|
|
||||||
|
// Ensure order integrity, should be unnecessary but no one is perfect specially me
|
||||||
|
ChildrenList = ChildrenList.OrderBy(c => c.Order).ToList();
|
||||||
|
for (int index = 0; index < ChildrenList.Count; index++)
|
||||||
|
ChildrenList[index].Order = index + 1;
|
||||||
|
|
||||||
|
LoadRenderElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Save()
|
||||||
|
{
|
||||||
|
if (Disposed)
|
||||||
|
throw new ObjectDisposedException("Folder");
|
||||||
|
|
||||||
|
FolderEntity.Id = EntityId;
|
||||||
|
FolderEntity.ParentId = Parent?.EntityId ?? new Guid();
|
||||||
|
|
||||||
|
FolderEntity.Order = Order;
|
||||||
|
FolderEntity.Name = Name;
|
||||||
|
FolderEntity.Enabled = Enabled;
|
||||||
|
|
||||||
|
FolderEntity.ProfileId = Profile.EntityId;
|
||||||
|
FolderEntity.ExpandedPropertyGroups.Clear();
|
||||||
|
FolderEntity.ExpandedPropertyGroups.AddRange(ExpandedPropertyGroups);
|
||||||
|
|
||||||
|
SaveRenderElement();
|
||||||
|
}
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler RenderPropertiesUpdated;
|
/// <summary>
|
||||||
|
/// Occurs when a property affecting the rendering properties of this folder has been updated
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? RenderPropertiesUpdated;
|
||||||
|
|
||||||
private void OnRenderPropertiesUpdated()
|
private void OnRenderPropertiesUpdated()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -17,10 +17,10 @@ namespace Artemis.Core
|
|||||||
public sealed class Layer : RenderProfileElement
|
public sealed class Layer : RenderProfileElement
|
||||||
{
|
{
|
||||||
private LayerGeneralProperties _general;
|
private LayerGeneralProperties _general;
|
||||||
private BaseLayerBrush _layerBrush;
|
private BaseLayerBrush? _layerBrush;
|
||||||
private LayerShape _layerShape;
|
|
||||||
private List<ArtemisLed> _leds;
|
|
||||||
private LayerTransformProperties _transform;
|
private LayerTransformProperties _transform;
|
||||||
|
private LayerShape? _layerShape;
|
||||||
|
private List<ArtemisLed> _leds;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="Layer" /> class and adds itself to the child collection of the provided
|
/// Creates a new instance of the <see cref="Layer" /> class and adds itself to the child collection of the provided
|
||||||
@ -37,12 +37,12 @@ namespace Artemis.Core
|
|||||||
Profile = Parent.Profile;
|
Profile = Parent.Profile;
|
||||||
Name = name;
|
Name = name;
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
General = new LayerGeneralProperties();
|
_general = new LayerGeneralProperties();
|
||||||
Transform = new LayerTransformProperties();
|
_transform = new LayerTransformProperties();
|
||||||
|
|
||||||
_layerEffects = new List<BaseLayerEffect>();
|
LayerEffectsList = new List<BaseLayerEffect>();
|
||||||
_leds = new List<ArtemisLed>();
|
_leds = new List<ArtemisLed>();
|
||||||
_expandedPropertyGroups = new List<string>();
|
ExpandedPropertyGroups = new List<string>();
|
||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
Parent.AddChild(this);
|
Parent.AddChild(this);
|
||||||
@ -55,12 +55,12 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
Profile = profile;
|
Profile = profile;
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
General = new LayerGeneralProperties();
|
_general = new LayerGeneralProperties();
|
||||||
Transform = new LayerTransformProperties();
|
_transform = new LayerTransformProperties();
|
||||||
|
|
||||||
_layerEffects = new List<BaseLayerEffect>();
|
LayerEffectsList = new List<BaseLayerEffect>();
|
||||||
_leds = new List<ArtemisLed>();
|
_leds = new List<ArtemisLed>();
|
||||||
_expandedPropertyGroups = new List<string>();
|
ExpandedPropertyGroups = new List<string>();
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
Initialize();
|
Initialize();
|
||||||
@ -74,7 +74,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the shape that is rendered by the <see cref="LayerBrush" />.
|
/// Defines the shape that is rendered by the <see cref="LayerBrush" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LayerShape LayerShape
|
public LayerShape? LayerShape
|
||||||
{
|
{
|
||||||
get => _layerShape;
|
get => _layerShape;
|
||||||
set
|
set
|
||||||
@ -85,24 +85,30 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the general properties of the layer
|
||||||
|
/// </summary>
|
||||||
[PropertyGroupDescription(Name = "General", Description = "A collection of general properties")]
|
[PropertyGroupDescription(Name = "General", Description = "A collection of general properties")]
|
||||||
public LayerGeneralProperties General
|
public LayerGeneralProperties General
|
||||||
{
|
{
|
||||||
get => _general;
|
get => _general;
|
||||||
set => SetAndNotify(ref _general, value);
|
private set => SetAndNotify(ref _general, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the transform properties of the layer
|
||||||
|
/// </summary>
|
||||||
[PropertyGroupDescription(Name = "Transform", Description = "A collection of transformation properties")]
|
[PropertyGroupDescription(Name = "Transform", Description = "A collection of transformation properties")]
|
||||||
public LayerTransformProperties Transform
|
public LayerTransformProperties Transform
|
||||||
{
|
{
|
||||||
get => _transform;
|
get => _transform;
|
||||||
set => SetAndNotify(ref _transform, value);
|
private set => SetAndNotify(ref _transform, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The brush that will fill the <see cref="LayerShape" />.
|
/// The brush that will fill the <see cref="LayerShape" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BaseLayerBrush LayerBrush
|
public BaseLayerBrush? LayerBrush
|
||||||
{
|
{
|
||||||
get => _layerBrush;
|
get => _layerBrush;
|
||||||
internal set => SetAndNotify(ref _layerBrush, value);
|
internal set => SetAndNotify(ref _layerBrush, value);
|
||||||
@ -111,20 +117,24 @@ namespace Artemis.Core
|
|||||||
internal LayerEntity LayerEntity { get; set; }
|
internal LayerEntity LayerEntity { get; set; }
|
||||||
|
|
||||||
internal override RenderElementEntity RenderElementEntity => LayerEntity;
|
internal override RenderElementEntity RenderElementEntity => LayerEntity;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a deep copy of the layer
|
/// Creates a deep copy of the layer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The newly created copy</returns>
|
/// <returns>The newly created copy</returns>
|
||||||
public Layer CreateCopy()
|
public Layer CreateCopy()
|
||||||
{
|
{
|
||||||
|
if (Parent == null)
|
||||||
|
throw new ArtemisCoreException("Cannot create a copy of a layer without a parent");
|
||||||
|
|
||||||
JsonSerializerSettings settings = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All};
|
JsonSerializerSettings settings = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All};
|
||||||
LayerEntity entityCopy = JsonConvert.DeserializeObject<LayerEntity>(JsonConvert.SerializeObject(LayerEntity, settings), settings)!;
|
LayerEntity entityCopy = JsonConvert.DeserializeObject<LayerEntity>(JsonConvert.SerializeObject(LayerEntity, settings), settings)!;
|
||||||
entityCopy.Id = Guid.NewGuid();
|
entityCopy.Id = Guid.NewGuid();
|
||||||
entityCopy.Name += " - Copy";
|
entityCopy.Name += " - Copy";
|
||||||
|
|
||||||
Layer copy = new Layer(Profile, Parent, entityCopy);
|
Layer copy = new Layer(Profile, Parent, entityCopy);
|
||||||
copy.ChangeLayerBrush(LayerBrush.Descriptor);
|
if (LayerBrush?.Descriptor != null)
|
||||||
|
copy.ChangeLayerBrush(LayerBrush.Descriptor);
|
||||||
copy.AddLeds(Leds);
|
copy.AddLeds(Leds);
|
||||||
|
|
||||||
Parent.AddChild(copy, Order + 1);
|
Parent.AddChild(copy, Order + 1);
|
||||||
@ -162,8 +172,8 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
// Brush first in case it depends on any of the other disposables during it's own disposal
|
// Brush first in case it depends on any of the other disposables during it's own disposal
|
||||||
_layerBrush?.Dispose();
|
_layerBrush?.Dispose();
|
||||||
_general?.Dispose();
|
_general.Dispose();
|
||||||
_transform?.Dispose();
|
_transform.Dispose();
|
||||||
Renderer.Dispose();
|
Renderer.Dispose();
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
@ -177,14 +187,14 @@ namespace Artemis.Core
|
|||||||
LayerBrushStore.LayerBrushRemoved += LayerBrushStoreOnLayerBrushRemoved;
|
LayerBrushStore.LayerBrushRemoved += LayerBrushStoreOnLayerBrushRemoved;
|
||||||
|
|
||||||
// Layers have two hardcoded property groups, instantiate them
|
// Layers have two hardcoded property groups, instantiate them
|
||||||
Attribute? generalAttribute = Attribute.GetCustomAttribute(
|
Attribute generalAttribute = Attribute.GetCustomAttribute(
|
||||||
GetType().GetProperty(nameof(General)),
|
GetType().GetProperty(nameof(General))!,
|
||||||
typeof(PropertyGroupDescriptionAttribute)
|
typeof(PropertyGroupDescriptionAttribute)
|
||||||
);
|
)!;
|
||||||
Attribute? transformAttribute = Attribute.GetCustomAttribute(
|
Attribute transformAttribute = Attribute.GetCustomAttribute(
|
||||||
GetType().GetProperty(nameof(Transform)),
|
GetType().GetProperty(nameof(Transform))!,
|
||||||
typeof(PropertyGroupDescriptionAttribute)
|
typeof(PropertyGroupDescriptionAttribute)
|
||||||
);
|
)!;
|
||||||
General.GroupDescription = (PropertyGroupDescriptionAttribute) generalAttribute;
|
General.GroupDescription = (PropertyGroupDescriptionAttribute) generalAttribute;
|
||||||
General.Initialize(this, "General.", Constants.CorePluginFeature);
|
General.Initialize(this, "General.", Constants.CorePluginFeature);
|
||||||
Transform.GroupDescription = (PropertyGroupDescriptionAttribute) transformAttribute;
|
Transform.GroupDescription = (PropertyGroupDescriptionAttribute) transformAttribute;
|
||||||
@ -204,7 +214,7 @@ namespace Artemis.Core
|
|||||||
Enabled = LayerEntity.Enabled;
|
Enabled = LayerEntity.Enabled;
|
||||||
Order = LayerEntity.Order;
|
Order = LayerEntity.Order;
|
||||||
|
|
||||||
_expandedPropertyGroups.AddRange(LayerEntity.ExpandedPropertyGroups);
|
ExpandedPropertyGroups.AddRange(LayerEntity.ExpandedPropertyGroups);
|
||||||
LoadRenderElement();
|
LoadRenderElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,11 +231,11 @@ namespace Artemis.Core
|
|||||||
LayerEntity.Name = Name;
|
LayerEntity.Name = Name;
|
||||||
LayerEntity.ProfileId = Profile.EntityId;
|
LayerEntity.ProfileId = Profile.EntityId;
|
||||||
LayerEntity.ExpandedPropertyGroups.Clear();
|
LayerEntity.ExpandedPropertyGroups.Clear();
|
||||||
LayerEntity.ExpandedPropertyGroups.AddRange(_expandedPropertyGroups);
|
LayerEntity.ExpandedPropertyGroups.AddRange(ExpandedPropertyGroups);
|
||||||
|
|
||||||
General.ApplyToEntity();
|
General.ApplyToEntity();
|
||||||
Transform.ApplyToEntity();
|
Transform.ApplyToEntity();
|
||||||
LayerBrush?.BaseProperties.ApplyToEntity();
|
LayerBrush?.BaseProperties?.ApplyToEntity();
|
||||||
|
|
||||||
// LEDs
|
// LEDs
|
||||||
LayerEntity.Leds.Clear();
|
LayerEntity.Leds.Clear();
|
||||||
@ -246,7 +256,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Shape management
|
#region Shape management
|
||||||
|
|
||||||
private void ShapeTypeOnCurrentValueSet(object sender, EventArgs e)
|
private void ShapeTypeOnCurrentValueSet(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
ApplyShapeType();
|
ApplyShapeType();
|
||||||
}
|
}
|
||||||
@ -316,8 +326,11 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
General.Update(timeline);
|
General.Update(timeline);
|
||||||
Transform.Update(timeline);
|
Transform.Update(timeline);
|
||||||
LayerBrush.BaseProperties?.Update(timeline);
|
if (LayerBrush != null)
|
||||||
LayerBrush.Update(timeline.Delta.TotalSeconds);
|
{
|
||||||
|
LayerBrush.BaseProperties?.Update(timeline);
|
||||||
|
LayerBrush.Update(timeline.Delta.TotalSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
||||||
{
|
{
|
||||||
@ -328,6 +341,9 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void RenderTimeline(Timeline timeline, SKCanvas canvas)
|
private void RenderTimeline(Timeline timeline, SKCanvas canvas)
|
||||||
{
|
{
|
||||||
|
if (Path == null || LayerBrush == null)
|
||||||
|
throw new ArtemisCoreException("The layer is not yet ready for rendering");
|
||||||
|
|
||||||
if (timeline.IsFinished)
|
if (timeline.IsFinished)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -392,6 +408,11 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void DelegateRendering(SKRect bounds)
|
private void DelegateRendering(SKRect bounds)
|
||||||
{
|
{
|
||||||
|
if (LayerBrush == null)
|
||||||
|
throw new ArtemisCoreException("The layer is not yet ready for rendering");
|
||||||
|
if (Renderer.Canvas == null || Renderer.Paint == null)
|
||||||
|
throw new ArtemisCoreException("Failed to open layer render context");
|
||||||
|
|
||||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
foreach (BaseLayerEffect baseLayerEffect in LayerEffects.Where(e => e.Enabled))
|
||||||
baseLayerEffect.PreProcess(Renderer.Canvas, bounds, Renderer.Paint);
|
baseLayerEffect.PreProcess(Renderer.Canvas, bounds, Renderer.Paint);
|
||||||
|
|
||||||
@ -459,12 +480,18 @@ namespace Artemis.Core
|
|||||||
/// If true, treats the layer as if it is located at 0,0 instead of its actual position on the
|
/// If true, treats the layer as if it is located at 0,0 instead of its actual position on the
|
||||||
/// surface
|
/// surface
|
||||||
/// </param>
|
/// </param>
|
||||||
|
/// <param name="includeTranslation">Whether translation should be included</param>
|
||||||
|
/// <param name="includeScale">Whether the scale should be included</param>
|
||||||
|
/// <param name="includeRotation">Whether the rotation should be included</param>
|
||||||
/// <returns>The transformation matrix containing the current transformation settings</returns>
|
/// <returns>The transformation matrix containing the current transformation settings</returns>
|
||||||
public SKMatrix GetTransformMatrix(bool zeroBased, bool includeTranslation, bool includeScale, bool includeRotation)
|
public SKMatrix GetTransformMatrix(bool zeroBased, bool includeTranslation, bool includeScale, bool includeRotation)
|
||||||
{
|
{
|
||||||
if (Disposed)
|
if (Disposed)
|
||||||
throw new ObjectDisposedException("Layer");
|
throw new ObjectDisposedException("Layer");
|
||||||
|
|
||||||
|
if (Path == null)
|
||||||
|
return SKMatrix.Empty;
|
||||||
|
|
||||||
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
SKSize sizeProperty = Transform.Scale.CurrentValue;
|
||||||
float rotationProperty = Transform.Rotation.CurrentValue;
|
float rotationProperty = Transform.Rotation.CurrentValue;
|
||||||
|
|
||||||
@ -478,25 +505,23 @@ namespace Artemis.Core
|
|||||||
SKMatrix transform = SKMatrix.Empty;
|
SKMatrix transform = SKMatrix.Empty;
|
||||||
|
|
||||||
if (includeTranslation)
|
if (includeTranslation)
|
||||||
{
|
|
||||||
// transform is always SKMatrix.Empty here...
|
// transform is always SKMatrix.Empty here...
|
||||||
transform = SKMatrix.MakeTranslation(x, y);
|
transform = SKMatrix.CreateTranslation(x, y);
|
||||||
}
|
|
||||||
|
|
||||||
if (includeScale)
|
if (includeScale)
|
||||||
{
|
{
|
||||||
if (transform == SKMatrix.Empty)
|
if (transform == SKMatrix.Empty)
|
||||||
transform = SKMatrix.MakeScale(sizeProperty.Width / 100f, sizeProperty.Height / 100f, anchorPosition.X, anchorPosition.Y);
|
transform = SKMatrix.CreateScale(sizeProperty.Width / 100f, sizeProperty.Height / 100f, anchorPosition.X, anchorPosition.Y);
|
||||||
else
|
else
|
||||||
transform = transform.PostConcat(SKMatrix.MakeScale(sizeProperty.Width / 100f, sizeProperty.Height / 100f, anchorPosition.X, anchorPosition.Y));
|
transform = transform.PostConcat(SKMatrix.CreateScale(sizeProperty.Width / 100f, sizeProperty.Height / 100f, anchorPosition.X, anchorPosition.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeRotation)
|
if (includeRotation)
|
||||||
{
|
{
|
||||||
if (transform == SKMatrix.Empty)
|
if (transform == SKMatrix.Empty)
|
||||||
transform = SKMatrix.MakeRotationDegrees(rotationProperty, anchorPosition.X, anchorPosition.Y);
|
transform = SKMatrix.CreateRotationDegrees(rotationProperty, anchorPosition.X, anchorPosition.Y);
|
||||||
else
|
else
|
||||||
transform = transform.PostConcat(SKMatrix.MakeRotationDegrees(rotationProperty, anchorPosition.X, anchorPosition.Y));
|
transform = transform.PostConcat(SKMatrix.CreateRotationDegrees(rotationProperty, anchorPosition.X, anchorPosition.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
return transform;
|
return transform;
|
||||||
@ -568,8 +593,8 @@ namespace Artemis.Core
|
|||||||
List<ArtemisLed> availableLeds = surface.Devices.SelectMany(d => d.Leds).ToList();
|
List<ArtemisLed> availableLeds = surface.Devices.SelectMany(d => d.Leds).ToList();
|
||||||
foreach (LedEntity ledEntity in LayerEntity.Leds)
|
foreach (LedEntity ledEntity in LayerEntity.Leds)
|
||||||
{
|
{
|
||||||
ArtemisLed match = availableLeds.FirstOrDefault(a => a.Device.RgbDevice.GetDeviceIdentifier() == ledEntity.DeviceIdentifier &&
|
ArtemisLed? match = availableLeds.FirstOrDefault(a => a.Device.RgbDevice.GetDeviceIdentifier() == ledEntity.DeviceIdentifier &&
|
||||||
a.RgbLed.Id.ToString() == ledEntity.LedName);
|
a.RgbLed.Id.ToString() == ledEntity.LedName);
|
||||||
if (match != null)
|
if (match != null)
|
||||||
leds.Add(match);
|
leds.Add(match);
|
||||||
}
|
}
|
||||||
@ -598,7 +623,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the brush reference matches the brush
|
// Ensure the brush reference matches the brush
|
||||||
LayerBrushReference current = General.BrushReference.BaseValue;
|
LayerBrushReference? current = General.BrushReference.BaseValue;
|
||||||
if (!descriptor.MatchesLayerBrushReference(current))
|
if (!descriptor.MatchesLayerBrushReference(current))
|
||||||
General.BrushReference.BaseValue = new LayerBrushReference(descriptor);
|
General.BrushReference.BaseValue = new LayerBrushReference(descriptor);
|
||||||
|
|
||||||
@ -620,11 +645,13 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void ActivateLayerBrush()
|
internal void ActivateLayerBrush()
|
||||||
{
|
{
|
||||||
LayerBrushReference current = General.BrushReference.CurrentValue;
|
LayerBrushReference? current = General.BrushReference.CurrentValue;
|
||||||
if (current == null)
|
if (current == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LayerBrushDescriptor? descriptor = LayerBrushStore.Get(current.LayerBrushProviderId, current.BrushType)?.LayerBrushDescriptor;
|
LayerBrushDescriptor? descriptor = current.LayerBrushProviderId != null && current.BrushType != null
|
||||||
|
? LayerBrushStore.Get(current.LayerBrushProviderId, current.BrushType)?.LayerBrushDescriptor
|
||||||
|
: null;
|
||||||
descriptor?.CreateInstance(this);
|
descriptor?.CreateInstance(this);
|
||||||
|
|
||||||
OnLayerBrushUpdated();
|
OnLayerBrushUpdated();
|
||||||
@ -646,19 +673,19 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Event handlers
|
#region Event handlers
|
||||||
|
|
||||||
private void LayerBrushStoreOnLayerBrushRemoved(object sender, LayerBrushStoreEvent e)
|
private void LayerBrushStoreOnLayerBrushRemoved(object? sender, LayerBrushStoreEvent e)
|
||||||
{
|
{
|
||||||
if (LayerBrush?.Descriptor == e.Registration.LayerBrushDescriptor)
|
if (LayerBrush?.Descriptor == e.Registration.LayerBrushDescriptor)
|
||||||
DeactivateLayerBrush();
|
DeactivateLayerBrush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LayerBrushStoreOnLayerBrushAdded(object sender, LayerBrushStoreEvent e)
|
private void LayerBrushStoreOnLayerBrushAdded(object? sender, LayerBrushStoreEvent e)
|
||||||
{
|
{
|
||||||
if (LayerBrush != null || General.BrushReference?.CurrentValue == null)
|
if (LayerBrush != null || !General.PropertiesInitialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LayerBrushReference current = General.BrushReference.CurrentValue;
|
LayerBrushReference? current = General.BrushReference.CurrentValue;
|
||||||
if (e.Registration.PluginFeature.Id == current.LayerBrushProviderId &&
|
if (e.Registration.PluginFeature.Id == current?.LayerBrushProviderId &&
|
||||||
e.Registration.LayerBrushDescriptor.LayerBrushType.Name == current.BrushType)
|
e.Registration.LayerBrushDescriptor.LayerBrushType.Name == current.BrushType)
|
||||||
ActivateLayerBrush();
|
ActivateLayerBrush();
|
||||||
}
|
}
|
||||||
@ -667,8 +694,15 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler RenderPropertiesUpdated;
|
/// <summary>
|
||||||
public event EventHandler LayerBrushUpdated;
|
/// Occurs when a property affecting the rendering properties of this layer has been updated
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? RenderPropertiesUpdated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the layer brush of this layer has been updated
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? LayerBrushUpdated;
|
||||||
|
|
||||||
private void OnRenderPropertiesUpdated()
|
private void OnRenderPropertiesUpdated()
|
||||||
{
|
{
|
||||||
@ -683,15 +717,35 @@ namespace Artemis.Core
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a type of layer shape
|
||||||
|
/// </summary>
|
||||||
public enum LayerShapeType
|
public enum LayerShapeType
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A circular layer shape
|
||||||
|
/// </summary>
|
||||||
Ellipse,
|
Ellipse,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A rectangular layer shape
|
||||||
|
/// </summary>
|
||||||
Rectangle
|
Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a layer transform mode
|
||||||
|
/// </summary>
|
||||||
public enum LayerTransformMode
|
public enum LayerTransformMode
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Normal transformation
|
||||||
|
/// </summary>
|
||||||
Normal,
|
Normal,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transforms only a clip
|
||||||
|
/// </summary>
|
||||||
Clip
|
Clip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7,10 +7,17 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LayerBrushReference
|
public class LayerBrushReference
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="LayerBrushReference" /> class
|
||||||
|
/// </summary>
|
||||||
public LayerBrushReference()
|
public LayerBrushReference()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="LayerBrushReference" /> class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="descriptor">The descriptor to point the new reference at</param>
|
||||||
public LayerBrushReference(LayerBrushDescriptor descriptor)
|
public LayerBrushReference(LayerBrushDescriptor descriptor)
|
||||||
{
|
{
|
||||||
LayerBrushProviderId = descriptor.Provider.Id;
|
LayerBrushProviderId = descriptor.Provider.Id;
|
||||||
@ -20,11 +27,11 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID of the layer brush provided the brush was provided by
|
/// The ID of the layer brush provided the brush was provided by
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LayerBrushProviderId { get; set; }
|
public string? LayerBrushProviderId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The full type name of the brush descriptor
|
/// The full type name of the brush descriptor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string BrushType { get; set; }
|
public string? BrushType { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,31 +1,51 @@
|
|||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
|
#pragma warning disable 8618
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the general properties of a layer
|
||||||
|
/// </summary>
|
||||||
public class LayerGeneralProperties : LayerPropertyGroup
|
public class LayerGeneralProperties : LayerPropertyGroup
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The type of shape to draw in this layer
|
||||||
|
/// </summary>
|
||||||
[PropertyDescription(Name = "Shape type", Description = "The type of shape to draw in this layer")]
|
[PropertyDescription(Name = "Shape type", Description = "The type of shape to draw in this layer")]
|
||||||
public EnumLayerProperty<LayerShapeType> ShapeType { get; set; }
|
public EnumLayerProperty<LayerShapeType> ShapeType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How to blend this layer into the resulting image
|
||||||
|
/// </summary>
|
||||||
[PropertyDescription(Name = "Blend mode", Description = "How to blend this layer into the resulting image")]
|
[PropertyDescription(Name = "Blend mode", Description = "How to blend this layer into the resulting image")]
|
||||||
public EnumLayerProperty<SKBlendMode> BlendMode { get; set; }
|
public EnumLayerProperty<SKBlendMode> BlendMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How the transformation properties are applied to the layer
|
||||||
|
/// </summary>
|
||||||
[PropertyDescription(Name = "Transform mode", Description = "How the transformation properties are applied to the layer")]
|
[PropertyDescription(Name = "Transform mode", Description = "How the transformation properties are applied to the layer")]
|
||||||
public EnumLayerProperty<LayerTransformMode> TransformMode { get; set; }
|
public EnumLayerProperty<LayerTransformMode> TransformMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of brush to use for this layer
|
||||||
|
/// </summary>
|
||||||
[PropertyDescription(Name = "Brush type", Description = "The type of brush to use for this layer")]
|
[PropertyDescription(Name = "Brush type", Description = "The type of brush to use for this layer")]
|
||||||
public LayerBrushReferenceLayerProperty BrushReference { get; set; }
|
public LayerBrushReferenceLayerProperty BrushReference { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void PopulateDefaults()
|
protected override void PopulateDefaults()
|
||||||
{
|
{
|
||||||
ShapeType.DefaultValue = LayerShapeType.Rectangle;
|
ShapeType.DefaultValue = LayerShapeType.Rectangle;
|
||||||
BlendMode.DefaultValue = SKBlendMode.SrcOver;
|
BlendMode.DefaultValue = SKBlendMode.SrcOver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void EnableProperties()
|
protected override void EnableProperties()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void DisableProperties()
|
protected override void DisableProperties()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,27 +2,30 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a description attribute used to decorate layer properties
|
||||||
|
/// </summary>
|
||||||
public class PropertyDescriptionAttribute : Attribute
|
public class PropertyDescriptionAttribute : Attribute
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user-friendly name for this property, shown in the UI
|
/// The user-friendly name for this property, shown in the UI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user-friendly description for this property, shown in the UI
|
/// The user-friendly description for this property, shown in the UI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Input prefix to show before input elements in the UI
|
/// Input prefix to show before input elements in the UI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string InputPrefix { get; set; }
|
public string? InputPrefix { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Input affix to show behind input elements in the UI
|
/// Input affix to show behind input elements in the UI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string InputAffix { get; set; }
|
public string? InputAffix { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The input drag step size, used in the UI
|
/// The input drag step size, used in the UI
|
||||||
@ -32,12 +35,12 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minimum input value, only enforced in the UI
|
/// Minimum input value, only enforced in the UI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object MinInputValue { get; set; }
|
public object? MinInputValue { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum input value, only enforced in the UI
|
/// Maximum input value, only enforced in the UI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object MaxInputValue { get; set; }
|
public object? MaxInputValue { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not keyframes are always disabled
|
/// Whether or not keyframes are always disabled
|
||||||
|
|||||||
@ -2,16 +2,19 @@
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a description attribute used to decorate layer property groups
|
||||||
|
/// </summary>
|
||||||
public class PropertyGroupDescriptionAttribute : Attribute
|
public class PropertyGroupDescriptionAttribute : Attribute
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user-friendly name for this property, shown in the UI.
|
/// The user-friendly name for this property, shown in the UI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user-friendly description for this property, shown in the UI.
|
/// The user-friendly description for this property, shown in the UI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Description { get; set; }
|
public string? Description { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,9 +25,22 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected LayerProperty()
|
protected LayerProperty()
|
||||||
{
|
{
|
||||||
|
// Cant define generic types as nullable ¯\_(ツ)_/¯
|
||||||
|
CurrentValue = default!;
|
||||||
|
DefaultValue = default!;
|
||||||
|
|
||||||
|
_baseValue = default!;
|
||||||
_keyframes = new List<LayerPropertyKeyframe<T>>();
|
_keyframes = new List<LayerPropertyKeyframe<T>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the type of the property
|
||||||
|
/// </summary>
|
||||||
|
public Type GetPropertyType()
|
||||||
|
{
|
||||||
|
return typeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public PropertyDescriptionAttribute PropertyDescription { get; internal set; }
|
public PropertyDescriptionAttribute PropertyDescription { get; internal set; }
|
||||||
|
|
||||||
@ -57,14 +70,6 @@ namespace Artemis.Core
|
|||||||
dataBinding.Dispose();
|
dataBinding.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the type of the property
|
|
||||||
/// </summary>
|
|
||||||
public Type GetPropertyType()
|
|
||||||
{
|
|
||||||
return typeof(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Hierarchy
|
#region Hierarchy
|
||||||
|
|
||||||
private bool _isHidden;
|
private bool _isHidden;
|
||||||
@ -150,11 +155,13 @@ namespace Artemis.Core
|
|||||||
throw new ObjectDisposedException("LayerProperty");
|
throw new ObjectDisposedException("LayerProperty");
|
||||||
|
|
||||||
if (time == null || !KeyframesEnabled || !KeyframesSupported)
|
if (time == null || !KeyframesEnabled || !KeyframesSupported)
|
||||||
|
{
|
||||||
BaseValue = value;
|
BaseValue = value;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If on a keyframe, update the keyframe
|
// If on a keyframe, update the keyframe
|
||||||
LayerPropertyKeyframe<T> currentKeyframe = Keyframes.FirstOrDefault(k => k.Position == time.Value);
|
LayerPropertyKeyframe<T>? currentKeyframe = Keyframes.FirstOrDefault(k => k.Position == time.Value);
|
||||||
// Create a new keyframe if none found
|
// Create a new keyframe if none found
|
||||||
if (currentKeyframe == null)
|
if (currentKeyframe == null)
|
||||||
AddKeyframe(new LayerPropertyKeyframe<T>(value, time.Value, Easings.Functions.Linear, this));
|
AddKeyframe(new LayerPropertyKeyframe<T>(value, time.Value, Easings.Functions.Linear, this));
|
||||||
@ -222,12 +229,12 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current keyframe in the timeline according to the current progress
|
/// Gets the current keyframe in the timeline according to the current progress
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LayerPropertyKeyframe<T> CurrentKeyframe { get; protected set; }
|
public LayerPropertyKeyframe<T>? CurrentKeyframe { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the next keyframe in the timeline according to the current progress
|
/// Gets the next keyframe in the timeline according to the current progress
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LayerPropertyKeyframe<T> NextKeyframe { get; protected set; }
|
public LayerPropertyKeyframe<T>? NextKeyframe { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a keyframe to the layer property
|
/// Adds a keyframe to the layer property
|
||||||
@ -249,26 +256,6 @@ namespace Artemis.Core
|
|||||||
OnKeyframeAdded();
|
OnKeyframeAdded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes a keyframe from the layer property
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="keyframe">The keyframe to remove</param>
|
|
||||||
public LayerPropertyKeyframe<T> CopyKeyframe(LayerPropertyKeyframe<T> keyframe)
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
throw new ObjectDisposedException("LayerProperty");
|
|
||||||
|
|
||||||
LayerPropertyKeyframe<T> newKeyframe = new LayerPropertyKeyframe<T>(
|
|
||||||
keyframe.Value,
|
|
||||||
keyframe.Position,
|
|
||||||
keyframe.EasingFunction,
|
|
||||||
keyframe.LayerProperty
|
|
||||||
);
|
|
||||||
AddKeyframe(newKeyframe);
|
|
||||||
|
|
||||||
return newKeyframe;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a keyframe from the layer property
|
/// Removes a keyframe from the layer property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -282,7 +269,6 @@ namespace Artemis.Core
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_keyframes.Remove(keyframe);
|
_keyframes.Remove(keyframe);
|
||||||
keyframe.LayerProperty = null;
|
|
||||||
SortKeyframes();
|
SortKeyframes();
|
||||||
OnKeyframeRemoved();
|
OnKeyframeRemoved();
|
||||||
}
|
}
|
||||||
@ -303,14 +289,25 @@ namespace Artemis.Core
|
|||||||
// The current keyframe is the last keyframe before the current time
|
// The current keyframe is the last keyframe before the current time
|
||||||
CurrentKeyframe = _keyframes.LastOrDefault(k => k.Position <= timeline.Position);
|
CurrentKeyframe = _keyframes.LastOrDefault(k => k.Position <= timeline.Position);
|
||||||
// Keyframes are sorted by position so we can safely assume the next keyframe's position is after the current
|
// Keyframes are sorted by position so we can safely assume the next keyframe's position is after the current
|
||||||
int nextIndex = _keyframes.IndexOf(CurrentKeyframe) + 1;
|
if (CurrentKeyframe != null)
|
||||||
NextKeyframe = _keyframes.Count > nextIndex ? _keyframes[nextIndex] : null;
|
{
|
||||||
|
int nextIndex = _keyframes.IndexOf(CurrentKeyframe) + 1;
|
||||||
|
NextKeyframe = _keyframes.Count > nextIndex ? _keyframes[nextIndex] : null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NextKeyframe = null;
|
||||||
|
}
|
||||||
|
|
||||||
// No need to update the current value if either of the keyframes are null
|
// No need to update the current value if either of the keyframes are null
|
||||||
if (CurrentKeyframe == null)
|
if (CurrentKeyframe == null)
|
||||||
|
{
|
||||||
CurrentValue = _keyframes.Any() ? _keyframes[0].Value : BaseValue;
|
CurrentValue = _keyframes.Any() ? _keyframes[0].Value : BaseValue;
|
||||||
|
}
|
||||||
else if (NextKeyframe == null)
|
else if (NextKeyframe == null)
|
||||||
|
{
|
||||||
CurrentValue = CurrentKeyframe.Value;
|
CurrentValue = CurrentKeyframe.Value;
|
||||||
|
}
|
||||||
// Only determine progress and current value if both keyframes are present
|
// Only determine progress and current value if both keyframes are present
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -325,8 +322,11 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Data bindings
|
#region Data bindings
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
internal readonly List<IDataBindingRegistration> _dataBindingRegistrations = new List<IDataBindingRegistration>();
|
internal readonly List<IDataBindingRegistration> _dataBindingRegistrations = new List<IDataBindingRegistration>();
|
||||||
|
|
||||||
internal readonly List<IDataBinding> _dataBindings = new List<IDataBinding>();
|
internal readonly List<IDataBinding> _dataBindings = new List<IDataBinding>();
|
||||||
|
// ReSharper restore InconsistentNaming
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets whether data bindings are supported on this type of property
|
/// Gets whether data bindings are supported on this type of property
|
||||||
@ -342,27 +342,36 @@ namespace Artemis.Core
|
|||||||
/// Gets a data binding registration by the expression used to register it
|
/// Gets a data binding registration by the expression used to register it
|
||||||
/// <para>Note: The expression must exactly match the one used to register the data binding</para>
|
/// <para>Note: The expression must exactly match the one used to register the data binding</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataBindingRegistration<T, TProperty> GetDataBindingRegistration<TProperty>(Expression<Func<T, TProperty>> propertyExpression)
|
public DataBindingRegistration<T, TProperty>? GetDataBindingRegistration<TProperty>(Expression<Func<T, TProperty>> propertyExpression)
|
||||||
{
|
{
|
||||||
return GetDataBindingRegistration<TProperty>(propertyExpression.ToString());
|
return GetDataBindingRegistration<TProperty>(propertyExpression.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataBindingRegistration<T, TProperty> GetDataBindingRegistration<TProperty>(string expression)
|
internal DataBindingRegistration<T, TProperty>? GetDataBindingRegistration<TProperty>(string expression)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("LayerProperty");
|
throw new ObjectDisposedException("LayerProperty");
|
||||||
|
|
||||||
IDataBindingRegistration match = _dataBindingRegistrations.FirstOrDefault(r => r is DataBindingRegistration<T, TProperty> registration &&
|
IDataBindingRegistration? match = _dataBindingRegistrations.FirstOrDefault(r => r is DataBindingRegistration<T, TProperty> registration &&
|
||||||
registration.PropertyExpression.ToString() == expression);
|
registration.PropertyExpression.ToString() == expression);
|
||||||
|
return (DataBindingRegistration<T, TProperty>?) match;
|
||||||
return (DataBindingRegistration<T, TProperty>) match;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list containing all data binding registrations of this layer property
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list containing all data binding registrations of this layer property</returns>
|
||||||
public List<IDataBindingRegistration> GetAllDataBindingRegistrations()
|
public List<IDataBindingRegistration> GetAllDataBindingRegistrations()
|
||||||
{
|
{
|
||||||
return _dataBindingRegistrations;
|
return _dataBindingRegistrations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers a data binding property so that is available to the data binding system
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TProperty">The type of the layer property</typeparam>
|
||||||
|
/// <param name="propertyExpression">The expression pointing to the value to register</param>
|
||||||
|
/// <param name="converter">The converter to use while applying the data binding</param>
|
||||||
public void RegisterDataBindingProperty<TProperty>(Expression<Func<T, TProperty>> propertyExpression, DataBindingConverter<T, TProperty> converter)
|
public void RegisterDataBindingProperty<TProperty>(Expression<Func<T, TProperty>> propertyExpression, DataBindingConverter<T, TProperty> converter)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
@ -372,10 +381,8 @@ namespace Artemis.Core
|
|||||||
throw new ArtemisCoreException("Provided expression is invalid, it must be 'value => value' or 'value => value.Property'");
|
throw new ArtemisCoreException("Provided expression is invalid, it must be 'value => value' or 'value => value.Property'");
|
||||||
|
|
||||||
if (converter.SupportedType != propertyExpression.ReturnType)
|
if (converter.SupportedType != propertyExpression.ReturnType)
|
||||||
{
|
|
||||||
throw new ArtemisCoreException($"Cannot register data binding property for property {PropertyDescription.Name} " +
|
throw new ArtemisCoreException($"Cannot register data binding property for property {PropertyDescription.Name} " +
|
||||||
"because the provided converter does not support the property's type");
|
"because the provided converter does not support the property's type");
|
||||||
}
|
|
||||||
|
|
||||||
_dataBindingRegistrations.Add(new DataBindingRegistration<T, TProperty>(this, converter, propertyExpression));
|
_dataBindingRegistrations.Add(new DataBindingRegistration<T, TProperty>(this, converter, propertyExpression));
|
||||||
}
|
}
|
||||||
@ -412,7 +419,8 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
_dataBindings.Remove(dataBinding);
|
_dataBindings.Remove(dataBinding);
|
||||||
|
|
||||||
dataBinding.Registration.DataBinding = null;
|
if (dataBinding.Registration != null)
|
||||||
|
dataBinding.Registration.DataBinding = null;
|
||||||
dataBinding.Dispose();
|
dataBinding.Dispose();
|
||||||
OnDataBindingDisabled(new LayerPropertyEventArgs<T>(dataBinding.LayerProperty));
|
OnDataBindingDisabled(new LayerPropertyEventArgs<T>(dataBinding.LayerProperty));
|
||||||
}
|
}
|
||||||
@ -471,17 +479,15 @@ namespace Artemis.Core
|
|||||||
if (!IsLoadedFromStorage)
|
if (!IsLoadedFromStorage)
|
||||||
ApplyDefaultValue();
|
ApplyDefaultValue();
|
||||||
else
|
else
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Entity.Value != null)
|
if (Entity.Value != null)
|
||||||
BaseValue = JsonConvert.DeserializeObject<T>(Entity.Value);
|
BaseValue = JsonConvert.DeserializeObject<T>(Entity.Value);
|
||||||
}
|
}
|
||||||
catch (JsonException e)
|
catch (JsonException)
|
||||||
{
|
{
|
||||||
// ignored for now
|
// ignored for now
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CurrentValue = BaseValue;
|
CurrentValue = BaseValue;
|
||||||
KeyframesEnabled = Entity.KeyframesEnabled;
|
KeyframesEnabled = Entity.KeyframesEnabled;
|
||||||
@ -494,7 +500,7 @@ namespace Artemis.Core
|
|||||||
.Select(k => new LayerPropertyKeyframe<T>(JsonConvert.DeserializeObject<T>(k.Value), k.Position, (Easings.Functions) k.EasingFunction, this))
|
.Select(k => new LayerPropertyKeyframe<T>(JsonConvert.DeserializeObject<T>(k.Value), k.Position, (Easings.Functions) k.EasingFunction, this))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (JsonException e)
|
catch (JsonException)
|
||||||
{
|
{
|
||||||
// ignored for now
|
// ignored for now
|
||||||
}
|
}
|
||||||
@ -502,15 +508,14 @@ namespace Artemis.Core
|
|||||||
_dataBindings.Clear();
|
_dataBindings.Clear();
|
||||||
foreach (IDataBindingRegistration dataBindingRegistration in _dataBindingRegistrations)
|
foreach (IDataBindingRegistration dataBindingRegistration in _dataBindingRegistrations)
|
||||||
{
|
{
|
||||||
IDataBinding dataBinding = dataBindingRegistration.CreateDataBinding();
|
IDataBinding? dataBinding = dataBindingRegistration.CreateDataBinding();
|
||||||
if (dataBinding != null)
|
if (dataBinding != null)
|
||||||
_dataBindings.Add(dataBinding);
|
_dataBindings.Add(dataBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the property to the underlying property entity that was configured when calling
|
/// Saves the property to the underlying property entity
|
||||||
/// <see cref="ApplyToLayerProperty" />
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
@ -542,79 +547,103 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs once every frame when the layer property is updated
|
/// Occurs once every frame when the layer property is updated
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<LayerPropertyEventArgs<T>> Updated;
|
public event EventHandler<LayerPropertyEventArgs<T>>? Updated;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when the current value of the layer property was updated by some form of input
|
/// Occurs when the current value of the layer property was updated by some form of input
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<LayerPropertyEventArgs<T>> CurrentValueSet;
|
public event EventHandler<LayerPropertyEventArgs<T>>? CurrentValueSet;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when the <see cref="IsHidden" /> value of the layer property was updated
|
/// Occurs when the <see cref="IsHidden" /> value of the layer property was updated
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<LayerPropertyEventArgs<T>> VisibilityChanged;
|
public event EventHandler<LayerPropertyEventArgs<T>>? VisibilityChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when keyframes are enabled/disabled
|
/// Occurs when keyframes are enabled/disabled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<LayerPropertyEventArgs<T>> KeyframesToggled;
|
public event EventHandler<LayerPropertyEventArgs<T>>? KeyframesToggled;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when a new keyframe was added to the layer property
|
/// Occurs when a new keyframe was added to the layer property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<LayerPropertyEventArgs<T>> KeyframeAdded;
|
public event EventHandler<LayerPropertyEventArgs<T>>? KeyframeAdded;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when a keyframe was removed from the layer property
|
/// Occurs when a keyframe was removed from the layer property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<LayerPropertyEventArgs<T>> KeyframeRemoved;
|
public event EventHandler<LayerPropertyEventArgs<T>>? KeyframeRemoved;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when a data binding has been enabled
|
/// Occurs when a data binding has been enabled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<LayerPropertyEventArgs<T>> DataBindingEnabled;
|
public event EventHandler<LayerPropertyEventArgs<T>>? DataBindingEnabled;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when a data binding has been disabled
|
/// Occurs when a data binding has been disabled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<LayerPropertyEventArgs<T>> DataBindingDisabled;
|
public event EventHandler<LayerPropertyEventArgs<T>>? DataBindingDisabled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="Updated" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnUpdated()
|
protected virtual void OnUpdated()
|
||||||
{
|
{
|
||||||
Updated?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
Updated?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="CurrentValueSet" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnCurrentValueSet()
|
protected virtual void OnCurrentValueSet()
|
||||||
{
|
{
|
||||||
CurrentValueSet?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
CurrentValueSet?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
||||||
LayerPropertyGroup.OnLayerPropertyOnCurrentValueSet(new LayerPropertyEventArgs(this));
|
LayerPropertyGroup.OnLayerPropertyOnCurrentValueSet(new LayerPropertyEventArgs(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="VisibilityChanged" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnVisibilityChanged()
|
protected virtual void OnVisibilityChanged()
|
||||||
{
|
{
|
||||||
VisibilityChanged?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
VisibilityChanged?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="KeyframesToggled" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnKeyframesToggled()
|
protected virtual void OnKeyframesToggled()
|
||||||
{
|
{
|
||||||
KeyframesToggled?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
KeyframesToggled?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="KeyframeAdded" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnKeyframeAdded()
|
protected virtual void OnKeyframeAdded()
|
||||||
{
|
{
|
||||||
KeyframeAdded?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
KeyframeAdded?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="KeyframeRemoved" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnKeyframeRemoved()
|
protected virtual void OnKeyframeRemoved()
|
||||||
{
|
{
|
||||||
KeyframeRemoved?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
KeyframeRemoved?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="DataBindingEnabled" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnDataBindingEnabled(LayerPropertyEventArgs<T> e)
|
protected virtual void OnDataBindingEnabled(LayerPropertyEventArgs<T> e)
|
||||||
{
|
{
|
||||||
DataBindingEnabled?.Invoke(this, e);
|
DataBindingEnabled?.Invoke(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="DataBindingDisabled" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnDataBindingDisabled(LayerPropertyEventArgs<T> e)
|
protected virtual void OnDataBindingDisabled(LayerPropertyEventArgs<T> e)
|
||||||
{
|
{
|
||||||
DataBindingDisabled?.Invoke(this, e);
|
DataBindingDisabled?.Invoke(this, e);
|
||||||
|
|||||||
@ -21,9 +21,9 @@ namespace Artemis.Core
|
|||||||
public LayerPropertyKeyframe(T value, TimeSpan position, Easings.Functions easingFunction, LayerProperty<T> layerProperty)
|
public LayerPropertyKeyframe(T value, TimeSpan position, Easings.Functions easingFunction, LayerProperty<T> layerProperty)
|
||||||
{
|
{
|
||||||
_position = position;
|
_position = position;
|
||||||
|
_layerProperty = layerProperty;
|
||||||
|
_value = value;
|
||||||
|
|
||||||
Value = value;
|
|
||||||
LayerProperty = layerProperty;
|
|
||||||
EasingFunction = easingFunction;
|
EasingFunction = easingFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,13 @@ using Humanizer;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a property group on a layer
|
||||||
|
/// <para>
|
||||||
|
/// Note: You cannot initialize property groups yourself. If properly placed and annotated, the Artemis core will
|
||||||
|
/// initialize these for you.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
public abstract class LayerPropertyGroup : IDisposable
|
public abstract class LayerPropertyGroup : IDisposable
|
||||||
{
|
{
|
||||||
private readonly List<ILayerProperty> _layerProperties;
|
private readonly List<ILayerProperty> _layerProperties;
|
||||||
@ -18,6 +25,9 @@ namespace Artemis.Core
|
|||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private bool _isHidden;
|
private bool _isHidden;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A base constructor for a <see cref="LayerPropertyGroup" />
|
||||||
|
/// </summary>
|
||||||
protected LayerPropertyGroup()
|
protected LayerPropertyGroup()
|
||||||
{
|
{
|
||||||
_layerProperties = new List<ILayerProperty>();
|
_layerProperties = new List<ILayerProperty>();
|
||||||
@ -28,7 +38,7 @@ namespace Artemis.Core
|
|||||||
/// Gets the description of this group
|
/// Gets the description of this group
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PropertyGroupDescriptionAttribute GroupDescription { get; internal set; }
|
public PropertyGroupDescriptionAttribute GroupDescription { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin feature this group is associated with
|
/// Gets the plugin feature this group is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -87,22 +97,6 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReadOnlyCollection<LayerPropertyGroup> LayerPropertyGroups => _layerPropertyGroups.AsReadOnly();
|
public ReadOnlyCollection<LayerPropertyGroup> LayerPropertyGroups => _layerPropertyGroups.AsReadOnly();
|
||||||
|
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_disposed = true;
|
|
||||||
DisableProperties();
|
|
||||||
|
|
||||||
foreach (ILayerProperty layerProperty in _layerProperties)
|
|
||||||
layerProperty.Dispose();
|
|
||||||
foreach (LayerPropertyGroup layerPropertyGroup in _layerPropertyGroups)
|
|
||||||
layerPropertyGroup.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recursively gets all layer properties on this group and any subgroups
|
/// Recursively gets all layer properties on this group and any subgroups
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -165,7 +159,9 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
Attribute? propertyDescription = Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyDescriptionAttribute));
|
Attribute? propertyDescription = Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyDescriptionAttribute));
|
||||||
if (propertyDescription != null)
|
if (propertyDescription != null)
|
||||||
|
{
|
||||||
InitializeProperty(propertyInfo, (PropertyDescriptionAttribute) propertyDescription);
|
InitializeProperty(propertyInfo, (PropertyDescriptionAttribute) propertyDescription);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Attribute? propertyGroupDescription = Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyGroupDescriptionAttribute));
|
Attribute? propertyGroupDescription = Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyGroupDescriptionAttribute));
|
||||||
@ -265,6 +261,22 @@ namespace Artemis.Core
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
DisableProperties();
|
||||||
|
|
||||||
|
foreach (ILayerProperty layerProperty in _layerProperties)
|
||||||
|
layerProperty.Dispose();
|
||||||
|
foreach (LayerPropertyGroup layerPropertyGroup in _layerPropertyGroups)
|
||||||
|
layerPropertyGroup.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -1,34 +1,57 @@
|
|||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
|
#pragma warning disable 8618
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the transform properties of a layer
|
||||||
|
/// </summary>
|
||||||
public class LayerTransformProperties : LayerPropertyGroup
|
public class LayerTransformProperties : LayerPropertyGroup
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The point at which the shape is attached to its position
|
||||||
|
/// </summary>
|
||||||
[PropertyDescription(Description = "The point at which the shape is attached to its position", InputStepSize = 0.001f)]
|
[PropertyDescription(Description = "The point at which the shape is attached to its position", InputStepSize = 0.001f)]
|
||||||
public SKPointLayerProperty AnchorPoint { get; set; }
|
public SKPointLayerProperty AnchorPoint { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The position of the shape
|
||||||
|
/// </summary>
|
||||||
[PropertyDescription(Description = "The position of the shape", InputStepSize = 0.001f)]
|
[PropertyDescription(Description = "The position of the shape", InputStepSize = 0.001f)]
|
||||||
public SKPointLayerProperty Position { get; set; }
|
public SKPointLayerProperty Position { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The scale of the shape
|
||||||
|
/// </summary>
|
||||||
[PropertyDescription(Description = "The scale of the shape", InputAffix = "%", MinInputValue = 0f)]
|
[PropertyDescription(Description = "The scale of the shape", InputAffix = "%", MinInputValue = 0f)]
|
||||||
public SKSizeLayerProperty Scale { get; set; }
|
public SKSizeLayerProperty Scale { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The rotation of the shape in degree
|
||||||
|
/// </summary>
|
||||||
[PropertyDescription(Description = "The rotation of the shape in degrees", InputAffix = "°")]
|
[PropertyDescription(Description = "The rotation of the shape in degrees", InputAffix = "°")]
|
||||||
public FloatLayerProperty Rotation { get; set; }
|
public FloatLayerProperty Rotation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The opacity of the shape
|
||||||
|
/// </summary>
|
||||||
[PropertyDescription(Description = "The opacity of the shape", InputAffix = "%", MinInputValue = 0f, MaxInputValue = 100f)]
|
[PropertyDescription(Description = "The opacity of the shape", InputAffix = "%", MinInputValue = 0f, MaxInputValue = 100f)]
|
||||||
public FloatLayerProperty Opacity { get; set; }
|
public FloatLayerProperty Opacity { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void PopulateDefaults()
|
protected override void PopulateDefaults()
|
||||||
{
|
{
|
||||||
Scale.DefaultValue = new SKSize(100, 100);
|
Scale.DefaultValue = new SKSize(100, 100);
|
||||||
Opacity.DefaultValue = 100;
|
Opacity.DefaultValue = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void EnableProperties()
|
protected override void EnableProperties()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void DisableProperties()
|
protected override void DisableProperties()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,9 @@ using SkiaSharp;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a profile containing folders and layers
|
||||||
|
/// </summary>
|
||||||
public sealed class Profile : ProfileElement
|
public sealed class Profile : ProfileElement
|
||||||
{
|
{
|
||||||
private bool _isActivated;
|
private bool _isActivated;
|
||||||
@ -39,8 +42,14 @@ namespace Artemis.Core
|
|||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the module backing this profile
|
||||||
|
/// </summary>
|
||||||
public ProfileModule Module { get; }
|
public ProfileModule Module { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether this profile is activated
|
||||||
|
/// </summary>
|
||||||
public bool IsActivated
|
public bool IsActivated
|
||||||
{
|
{
|
||||||
get => _isActivated;
|
get => _isActivated;
|
||||||
@ -52,6 +61,7 @@ namespace Artemis.Core
|
|||||||
internal Stack<string> UndoStack { get; set; }
|
internal Stack<string> UndoStack { get; set; }
|
||||||
internal Stack<string> RedoStack { get; set; }
|
internal Stack<string> RedoStack { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override void Update(double deltaTime)
|
public override void Update(double deltaTime)
|
||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
@ -66,6 +76,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override void Render(SKCanvas canvas)
|
public override void Render(SKCanvas canvas)
|
||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
@ -87,6 +98,11 @@ namespace Artemis.Core
|
|||||||
child.Reset();
|
child.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the root folder of this profile
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The root folder of the profile</returns>
|
||||||
|
/// <exception cref="ObjectDisposedException"></exception>
|
||||||
public Folder GetRootFolder()
|
public Folder GetRootFolder()
|
||||||
{
|
{
|
||||||
if (Disposed)
|
if (Disposed)
|
||||||
@ -95,6 +111,28 @@ namespace Artemis.Core
|
|||||||
return (Folder) Children.Single();
|
return (Folder) Children.Single();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"[Profile] {nameof(Name)}: {Name}, {nameof(IsActivated)}: {IsActivated}, {nameof(Module)}: {Module}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!disposing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OnDeactivating();
|
||||||
|
|
||||||
|
foreach (ProfileElement profileElement in Children)
|
||||||
|
profileElement.Dispose();
|
||||||
|
ChildrenList.Clear();
|
||||||
|
|
||||||
|
IsActivated = false;
|
||||||
|
Disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
internal override void Load()
|
internal override void Load()
|
||||||
{
|
{
|
||||||
if (Disposed)
|
if (Disposed)
|
||||||
@ -116,30 +154,12 @@ namespace Artemis.Core
|
|||||||
Folder _ = new Folder(this, "Root folder");
|
Folder _ = new Folder(this, "Root folder");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
AddChild(new Folder(this, this, rootFolder));
|
AddChild(new Folder(this, this, rootFolder));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"[Profile] {nameof(Name)}: {Name}, {nameof(IsActivated)}: {IsActivated}, {nameof(Module)}: {Module}";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (!disposing)
|
|
||||||
return;
|
|
||||||
|
|
||||||
OnDeactivating();
|
|
||||||
|
|
||||||
foreach (ProfileElement profileElement in Children)
|
|
||||||
profileElement.Dispose();
|
|
||||||
ChildrenList.Clear();
|
|
||||||
|
|
||||||
IsActivated = false;
|
|
||||||
Disposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void Save()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
if (Disposed)
|
if (Disposed)
|
||||||
@ -189,12 +209,12 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when the profile has been activated.
|
/// Occurs when the profile has been activated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler Activated;
|
public event EventHandler? Activated;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when the profile is being deactivated.
|
/// Occurs when the profile is being deactivated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler Deactivated;
|
public event EventHandler? Deactivated;
|
||||||
|
|
||||||
private void OnActivated()
|
private void OnActivated()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,6 +4,9 @@ using Artemis.Storage.Entities.Profile;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a descriptor that describes a profile
|
||||||
|
/// </summary>
|
||||||
public class ProfileDescriptor
|
public class ProfileDescriptor
|
||||||
{
|
{
|
||||||
internal ProfileDescriptor(ProfileModule profileModule, ProfileEntity profileEntity)
|
internal ProfileDescriptor(ProfileModule profileModule, ProfileEntity profileEntity)
|
||||||
@ -15,10 +18,24 @@ namespace Artemis.Core
|
|||||||
IsLastActiveProfile = profileEntity.IsActive;
|
IsLastActiveProfile = profileEntity.IsActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsLastActiveProfile { get; set; }
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether this was the last active profile
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLastActiveProfile { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the unique ID of the profile by which it can be loaded from storage
|
||||||
|
/// </summary>
|
||||||
public Guid Id { get; }
|
public Guid Id { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the module backing the profile
|
||||||
|
/// </summary>
|
||||||
public ProfileModule ProfileModule { get; }
|
public ProfileModule ProfileModule { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the profile
|
||||||
|
/// </summary>
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6,18 +6,22 @@ using SkiaSharp;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an element of a <see cref="Profile" />
|
||||||
|
/// </summary>
|
||||||
public abstract class ProfileElement : CorePropertyChanged, IDisposable
|
public abstract class ProfileElement : CorePropertyChanged, IDisposable
|
||||||
{
|
{
|
||||||
private bool _enabled;
|
private bool _enabled;
|
||||||
private Guid _entityId;
|
private Guid _entityId;
|
||||||
private string _name;
|
private string _name;
|
||||||
private int _order;
|
private int _order;
|
||||||
private ProfileElement _parent;
|
private ProfileElement? _parent;
|
||||||
private Profile _profile;
|
private Profile _profile;
|
||||||
protected List<ProfileElement> ChildrenList;
|
|
||||||
protected bool Disposed;
|
|
||||||
|
|
||||||
protected ProfileElement()
|
internal List<ProfileElement> ChildrenList;
|
||||||
|
internal bool Disposed;
|
||||||
|
|
||||||
|
internal ProfileElement()
|
||||||
{
|
{
|
||||||
ChildrenList = new List<ProfileElement>();
|
ChildrenList = new List<ProfileElement>();
|
||||||
}
|
}
|
||||||
@ -43,7 +47,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the parent of this element
|
/// Gets the parent of this element
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ProfileElement Parent
|
public ProfileElement? Parent
|
||||||
{
|
{
|
||||||
get => _parent;
|
get => _parent;
|
||||||
internal set => SetAndNotify(ref _parent, value);
|
internal set => SetAndNotify(ref _parent, value);
|
||||||
@ -233,6 +237,9 @@ namespace Artemis.Core
|
|||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes the profile element
|
||||||
|
/// </summary>
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
@ -244,14 +251,27 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler ChildAdded;
|
/// <summary>
|
||||||
public event EventHandler ChildRemoved;
|
/// Occurs when a child was added to the <see cref="Children" /> list
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? ChildAdded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a child was removed from the <see cref="Children" /> list
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? ChildRemoved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ChildAdded" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnChildAdded()
|
protected virtual void OnChildAdded()
|
||||||
{
|
{
|
||||||
ChildAdded?.Invoke(this, EventArgs.Empty);
|
ChildAdded?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ChildRemoved" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnChildRemoved()
|
protected virtual void OnChildRemoved()
|
||||||
{
|
{
|
||||||
ChildRemoved?.Invoke(this, EventArgs.Empty);
|
ChildRemoved?.Invoke(this, EventArgs.Empty);
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
namespace Artemis.Core
|
|
||||||
{
|
|
||||||
public abstract class PropertiesProfileElement : ProfileElement
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -11,9 +11,12 @@ using SkiaSharp;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an element of a <see cref="Profile" /> that has advanced rendering capabilities
|
||||||
|
/// </summary>
|
||||||
public abstract class RenderProfileElement : ProfileElement
|
public abstract class RenderProfileElement : ProfileElement
|
||||||
{
|
{
|
||||||
protected RenderProfileElement()
|
internal RenderProfileElement()
|
||||||
{
|
{
|
||||||
Timeline = new Timeline();
|
Timeline = new Timeline();
|
||||||
Renderer = new Renderer();
|
Renderer = new Renderer();
|
||||||
@ -22,8 +25,28 @@ namespace Artemis.Core
|
|||||||
LayerEffectStore.LayerEffectRemoved += LayerEffectStoreOnLayerEffectRemoved;
|
LayerEffectStore.LayerEffectRemoved += LayerEffectStoreOnLayerEffectRemoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a list of all layer properties present on this render element
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of all layer properties present on this render element</returns>
|
||||||
public abstract List<ILayerProperty> GetAllLayerProperties();
|
public abstract List<ILayerProperty> GetAllLayerProperties();
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
LayerEffectStore.LayerEffectAdded -= LayerEffectStoreOnLayerEffectAdded;
|
||||||
|
LayerEffectStore.LayerEffectRemoved -= LayerEffectStoreOnLayerEffectRemoved;
|
||||||
|
|
||||||
|
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
||||||
|
baseLayerEffect.Dispose();
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
internal void LoadRenderElement()
|
internal void LoadRenderElement()
|
||||||
{
|
{
|
||||||
DisplayCondition = RenderElementEntity.DisplayCondition != null
|
DisplayCondition = RenderElementEntity.DisplayCondition != null
|
||||||
@ -73,7 +96,8 @@ namespace Artemis.Core
|
|||||||
public Timeline Timeline { get; private set; }
|
public Timeline Timeline { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the <see cref="Timeline"/> according to the provided <paramref name="deltaTime"/> and current display condition status
|
/// Updates the <see cref="Timeline" /> according to the provided <paramref name="deltaTime" /> and current display
|
||||||
|
/// condition status
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateTimeline(double deltaTime)
|
public void UpdateTimeline(double deltaTime)
|
||||||
{
|
{
|
||||||
@ -86,31 +110,16 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
LayerEffectStore.LayerEffectAdded -= LayerEffectStoreOnLayerEffectAdded;
|
|
||||||
LayerEffectStore.LayerEffectRemoved -= LayerEffectStoreOnLayerEffectRemoved;
|
|
||||||
|
|
||||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
|
||||||
baseLayerEffect.Dispose();
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
private ProfileElement _parent;
|
private ProfileElement? _parent;
|
||||||
private SKPath _path;
|
private SKPath? _path;
|
||||||
internal abstract RenderElementEntity RenderElementEntity { get; }
|
internal abstract RenderElementEntity RenderElementEntity { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the parent of this element
|
/// Gets the parent of this element
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public new ProfileElement Parent
|
public new ProfileElement? Parent
|
||||||
{
|
{
|
||||||
get => _parent;
|
get => _parent;
|
||||||
internal set
|
internal set
|
||||||
@ -124,7 +133,7 @@ namespace Artemis.Core
|
|||||||
/// Gets the path containing all the LEDs this entity is applied to, any rendering outside the entity Path is
|
/// Gets the path containing all the LEDs this entity is applied to, any rendering outside the entity Path is
|
||||||
/// clipped.
|
/// clipped.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SKPath Path
|
public SKPath? Path
|
||||||
{
|
{
|
||||||
get => _path;
|
get => _path;
|
||||||
protected set
|
protected set
|
||||||
@ -150,20 +159,30 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Property group expansion
|
#region Property group expansion
|
||||||
|
|
||||||
protected List<string> _expandedPropertyGroups;
|
internal List<string> ExpandedPropertyGroups;
|
||||||
private SKRect _bounds;
|
private SKRect _bounds;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the provided property group is expanded
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layerPropertyGroup">The property group to check</param>
|
||||||
|
/// <returns>A boolean indicating whether the provided property group is expanded</returns>
|
||||||
public bool IsPropertyGroupExpanded(LayerPropertyGroup layerPropertyGroup)
|
public bool IsPropertyGroupExpanded(LayerPropertyGroup layerPropertyGroup)
|
||||||
{
|
{
|
||||||
return _expandedPropertyGroups.Contains(layerPropertyGroup.Path);
|
return ExpandedPropertyGroups.Contains(layerPropertyGroup.Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expands or collapses the provided property group
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="layerPropertyGroup">The group to expand or collapse</param>
|
||||||
|
/// <param name="expanded">Whether to expand or collapse the property group</param>
|
||||||
public void SetPropertyGroupExpanded(LayerPropertyGroup layerPropertyGroup, bool expanded)
|
public void SetPropertyGroupExpanded(LayerPropertyGroup layerPropertyGroup, bool expanded)
|
||||||
{
|
{
|
||||||
if (!expanded && IsPropertyGroupExpanded(layerPropertyGroup))
|
if (!expanded && IsPropertyGroupExpanded(layerPropertyGroup))
|
||||||
_expandedPropertyGroups.Remove(layerPropertyGroup.Path);
|
ExpandedPropertyGroups.Remove(layerPropertyGroup.Path);
|
||||||
else if (expanded && !IsPropertyGroupExpanded(layerPropertyGroup))
|
else if (expanded && !IsPropertyGroupExpanded(layerPropertyGroup))
|
||||||
_expandedPropertyGroups.Add(layerPropertyGroup.Path);
|
ExpandedPropertyGroups.Add(layerPropertyGroup.Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -172,12 +191,12 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Effect management
|
#region Effect management
|
||||||
|
|
||||||
protected List<BaseLayerEffect> _layerEffects;
|
internal List<BaseLayerEffect> LayerEffectsList;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a read-only collection of the layer effects on this entity
|
/// Gets a read-only collection of the layer effects on this entity
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReadOnlyCollection<BaseLayerEffect> LayerEffects => _layerEffects.AsReadOnly();
|
public ReadOnlyCollection<BaseLayerEffect> LayerEffects => LayerEffectsList.AsReadOnly();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a the layer effect described inthe provided <paramref name="descriptor" />
|
/// Adds a the layer effect described inthe provided <paramref name="descriptor" />
|
||||||
@ -208,7 +227,7 @@ namespace Artemis.Core
|
|||||||
if (effect == null) throw new ArgumentNullException(nameof(effect));
|
if (effect == null) throw new ArgumentNullException(nameof(effect));
|
||||||
|
|
||||||
// Remove the effect from the layer and dispose it
|
// Remove the effect from the layer and dispose it
|
||||||
_layerEffects.Remove(effect);
|
LayerEffectsList.Remove(effect);
|
||||||
effect.Dispose();
|
effect.Dispose();
|
||||||
|
|
||||||
// Update the order on the remaining effects
|
// Update the order on the remaining effects
|
||||||
@ -225,7 +244,7 @@ namespace Artemis.Core
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
_layerEffects.Sort((a, b) => a.Order.CompareTo(b.Order));
|
LayerEffectsList.Sort((a, b) => a.Order.CompareTo(b.Order));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ActivateEffects()
|
internal void ActivateEffects()
|
||||||
@ -233,7 +252,7 @@ namespace Artemis.Core
|
|||||||
foreach (LayerEffectEntity layerEffectEntity in RenderElementEntity.LayerEffects)
|
foreach (LayerEffectEntity layerEffectEntity in RenderElementEntity.LayerEffects)
|
||||||
{
|
{
|
||||||
// If there is a non-placeholder existing effect, skip this entity
|
// If there is a non-placeholder existing effect, skip this entity
|
||||||
BaseLayerEffect? existing = _layerEffects.FirstOrDefault(e => e.EntityId == layerEffectEntity.Id);
|
BaseLayerEffect? existing = LayerEffectsList.FirstOrDefault(e => e.EntityId == layerEffectEntity.Id);
|
||||||
if (existing != null && existing.Descriptor.PlaceholderFor == null)
|
if (existing != null && existing.Descriptor.PlaceholderFor == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -243,7 +262,7 @@ namespace Artemis.Core
|
|||||||
// If a descriptor is found but there is an existing placeholder, remove the placeholder
|
// If a descriptor is found but there is an existing placeholder, remove the placeholder
|
||||||
if (existing != null)
|
if (existing != null)
|
||||||
{
|
{
|
||||||
_layerEffects.Remove(existing);
|
LayerEffectsList.Remove(existing);
|
||||||
existing.Dispose();
|
existing.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,19 +283,19 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void ActivateLayerEffect(BaseLayerEffect layerEffect)
|
internal void ActivateLayerEffect(BaseLayerEffect layerEffect)
|
||||||
{
|
{
|
||||||
_layerEffects.Add(layerEffect);
|
LayerEffectsList.Add(layerEffect);
|
||||||
OnLayerEffectsUpdated();
|
OnLayerEffectsUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LayerEffectStoreOnLayerEffectRemoved(object sender, LayerEffectStoreEvent e)
|
private void LayerEffectStoreOnLayerEffectRemoved(object sender, LayerEffectStoreEvent e)
|
||||||
{
|
{
|
||||||
// If effects provided by the plugin are on the element, replace them with placeholders
|
// If effects provided by the plugin are on the element, replace them with placeholders
|
||||||
List<BaseLayerEffect> pluginEffects = _layerEffects.Where(ef => ef.Descriptor.Provider != null &&
|
List<BaseLayerEffect> pluginEffects = LayerEffectsList.Where(ef => ef.Descriptor.Provider != null &&
|
||||||
ef.ProviderId == e.Registration.PluginFeature.Id).ToList();
|
ef.ProviderId == e.Registration.PluginFeature.Id).ToList();
|
||||||
foreach (BaseLayerEffect pluginEffect in pluginEffects)
|
foreach (BaseLayerEffect pluginEffect in pluginEffects)
|
||||||
{
|
{
|
||||||
LayerEffectEntity entity = RenderElementEntity.LayerEffects.First(en => en.Id == pluginEffect.EntityId);
|
LayerEffectEntity entity = RenderElementEntity.LayerEffects.First(en => en.Id == pluginEffect.EntityId);
|
||||||
_layerEffects.Remove(pluginEffect);
|
LayerEffectsList.Remove(pluginEffect);
|
||||||
pluginEffect.Dispose();
|
pluginEffect.Dispose();
|
||||||
|
|
||||||
LayerEffectDescriptor descriptor = PlaceholderLayerEffectDescriptor.Create(pluginEffect.ProviderId);
|
LayerEffectDescriptor descriptor = PlaceholderLayerEffectDescriptor.Create(pluginEffect.ProviderId);
|
||||||
@ -317,7 +336,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Evaluates the display conditions on this element and applies any required changes to the <see cref="Timeline"/>
|
/// Evaluates the display conditions on this element and applies any required changes to the <see cref="Timeline" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateDisplayCondition()
|
public void UpdateDisplayCondition()
|
||||||
{
|
{
|
||||||
@ -344,7 +363,9 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
// Event conditions reset if the timeline finished
|
// Event conditions reset if the timeline finished
|
||||||
if (Timeline.IsFinished)
|
if (Timeline.IsFinished)
|
||||||
|
{
|
||||||
Timeline.JumpToStart();
|
Timeline.JumpToStart();
|
||||||
|
}
|
||||||
// and otherwise apply their overlap mode
|
// and otherwise apply their overlap mode
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -365,7 +386,10 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler LayerEffectsUpdated;
|
/// <summary>
|
||||||
|
/// Occurs when a layer effect has been added or removed to this render element
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? LayerEffectsUpdated;
|
||||||
|
|
||||||
internal void OnLayerEffectsUpdated()
|
internal void OnLayerEffectsUpdated()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -35,7 +35,7 @@ namespace Artemis.Core
|
|||||||
Bitmap = new SKBitmap(width, height);
|
Bitmap = new SKBitmap(width, height);
|
||||||
Path = new SKPath(path);
|
Path = new SKPath(path);
|
||||||
Canvas = new SKCanvas(Bitmap);
|
Canvas = new SKCanvas(Bitmap);
|
||||||
Path.Transform(SKMatrix.MakeTranslation(pathBounds.Left * -1, pathBounds.Top * -1));
|
Path.Transform(SKMatrix.CreateTranslation(pathBounds.Left * -1, pathBounds.Top * -1));
|
||||||
|
|
||||||
TargetLocation = new SKPoint(pathBounds.Location.X, pathBounds.Location.Y);
|
TargetLocation = new SKPoint(pathBounds.Location.X, pathBounds.Location.Y);
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
|
|||||||
@ -429,6 +429,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"Progress: {Position}/{Length} - delta: {Delta}";
|
return $"Progress: {Position}/{Length} - delta: {Delta}";
|
||||||
|
|||||||
@ -1,22 +1,26 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Artemis.Core.DeviceProviders;
|
||||||
using Artemis.Storage.Entities.Surface;
|
using Artemis.Storage.Entities.Surface;
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an RGB device usable by Artemis, provided by a <see cref="DeviceProviders.DeviceProvider" />
|
||||||
|
/// </summary>
|
||||||
public class ArtemisDevice : CorePropertyChanged
|
public class ArtemisDevice : CorePropertyChanged
|
||||||
{
|
{
|
||||||
private ReadOnlyCollection<ArtemisLed> _leds;
|
private ReadOnlyCollection<ArtemisLed> _leds;
|
||||||
private SKPath _renderPath;
|
private SKPath _renderPath;
|
||||||
private SKRect _renderRectangle;
|
private SKRect _renderRectangle;
|
||||||
|
|
||||||
internal ArtemisDevice(IRGBDevice rgbDevice, PluginFeature pluginFeature, ArtemisSurface surface)
|
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, ArtemisSurface surface)
|
||||||
{
|
{
|
||||||
RgbDevice = rgbDevice;
|
RgbDevice = rgbDevice;
|
||||||
PluginFeature = pluginFeature;
|
DeviceProvider = deviceProvider;
|
||||||
Surface = surface;
|
Surface = surface;
|
||||||
DeviceEntity = new DeviceEntity();
|
DeviceEntity = new DeviceEntity();
|
||||||
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
||||||
@ -29,38 +33,60 @@ namespace Artemis.Core
|
|||||||
CalculateRenderProperties();
|
CalculateRenderProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ArtemisDevice(IRGBDevice rgbDevice, PluginFeature pluginFeature, ArtemisSurface surface, DeviceEntity deviceEntity)
|
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, ArtemisSurface surface, DeviceEntity deviceEntity)
|
||||||
{
|
{
|
||||||
RgbDevice = rgbDevice;
|
RgbDevice = rgbDevice;
|
||||||
PluginFeature = pluginFeature;
|
DeviceProvider = deviceProvider;
|
||||||
Surface = surface;
|
Surface = surface;
|
||||||
DeviceEntity = deviceEntity;
|
DeviceEntity = deviceEntity;
|
||||||
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the rectangle covering the device, sized to match the render scale
|
||||||
|
/// </summary>
|
||||||
public SKRect RenderRectangle
|
public SKRect RenderRectangle
|
||||||
{
|
{
|
||||||
get => _renderRectangle;
|
get => _renderRectangle;
|
||||||
private set => SetAndNotify(ref _renderRectangle, value);
|
private set => SetAndNotify(ref _renderRectangle, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the path surrounding the device, sized to match the render scale
|
||||||
|
/// </summary>
|
||||||
public SKPath RenderPath
|
public SKPath RenderPath
|
||||||
{
|
{
|
||||||
get => _renderPath;
|
get => _renderPath;
|
||||||
private set => SetAndNotify(ref _renderPath, value);
|
private set => SetAndNotify(ref _renderPath, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the RGB.NET device backing this Artemis device
|
||||||
|
/// </summary>
|
||||||
public IRGBDevice RgbDevice { get; }
|
public IRGBDevice RgbDevice { get; }
|
||||||
public PluginFeature PluginFeature { get; }
|
|
||||||
public ArtemisSurface Surface { get; }
|
|
||||||
public DeviceEntity DeviceEntity { get; }
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the device provider that provided this device
|
||||||
|
/// </summary>
|
||||||
|
public DeviceProvider DeviceProvider { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the surface containing this device
|
||||||
|
/// </summary>
|
||||||
|
public ArtemisSurface Surface { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a read only collection containing the LEDs of this device
|
||||||
|
/// </summary>
|
||||||
public ReadOnlyCollection<ArtemisLed> Leds
|
public ReadOnlyCollection<ArtemisLed> Leds
|
||||||
{
|
{
|
||||||
get => _leds;
|
get => _leds;
|
||||||
set => SetAndNotify(ref _leds, value);
|
private set => SetAndNotify(ref _leds, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the X-position of the device
|
||||||
|
/// </summary>
|
||||||
public double X
|
public double X
|
||||||
{
|
{
|
||||||
get => DeviceEntity.X;
|
get => DeviceEntity.X;
|
||||||
@ -71,6 +97,9 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Y-position of the device
|
||||||
|
/// </summary>
|
||||||
public double Y
|
public double Y
|
||||||
{
|
{
|
||||||
get => DeviceEntity.Y;
|
get => DeviceEntity.Y;
|
||||||
@ -81,6 +110,9 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the rotation of the device
|
||||||
|
/// </summary>
|
||||||
public double Rotation
|
public double Rotation
|
||||||
{
|
{
|
||||||
get => DeviceEntity.Rotation;
|
get => DeviceEntity.Rotation;
|
||||||
@ -91,6 +123,9 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the scale of the device
|
||||||
|
/// </summary>
|
||||||
public double Scale
|
public double Scale
|
||||||
{
|
{
|
||||||
get => DeviceEntity.Scale;
|
get => DeviceEntity.Scale;
|
||||||
@ -101,6 +136,9 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Z-index of the device
|
||||||
|
/// </summary>
|
||||||
public int ZIndex
|
public int ZIndex
|
||||||
{
|
{
|
||||||
get => DeviceEntity.ZIndex;
|
get => DeviceEntity.ZIndex;
|
||||||
@ -111,13 +149,22 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal DeviceEntity DeviceEntity { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"[{RgbDevice.DeviceInfo.DeviceType}] {RgbDevice.DeviceInfo.DeviceName} - {X}.{Y}.{ZIndex}";
|
return $"[{RgbDevice.DeviceInfo.DeviceType}] {RgbDevice.DeviceInfo.DeviceName} - {X}.{Y}.{ZIndex}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler DeviceUpdated;
|
/// <summary>
|
||||||
|
/// Occurs when the underlying RGB.NET device was updated
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? DeviceUpdated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="DeviceUpdated" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnDeviceUpdated()
|
protected virtual void OnDeviceUpdated()
|
||||||
{
|
{
|
||||||
DeviceUpdated?.Invoke(this, EventArgs.Empty);
|
DeviceUpdated?.Invoke(this, EventArgs.Empty);
|
||||||
|
|||||||
@ -3,35 +3,51 @@ using SkiaSharp;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an RGB LED contained in an <see cref="ArtemisDevice" />
|
||||||
|
/// </summary>
|
||||||
public class ArtemisLed : CorePropertyChanged
|
public class ArtemisLed : CorePropertyChanged
|
||||||
{
|
{
|
||||||
private SKRect _absoluteRenderRectangle;
|
private SKRect _absoluteRenderRectangle;
|
||||||
private SKRect _renderRectangle;
|
private SKRect _renderRectangle;
|
||||||
|
|
||||||
public ArtemisLed(Led led, ArtemisDevice device)
|
internal ArtemisLed(Led led, ArtemisDevice device)
|
||||||
{
|
{
|
||||||
RgbLed = led;
|
RgbLed = led;
|
||||||
Device = device;
|
Device = device;
|
||||||
CalculateRenderRectangle();
|
CalculateRenderRectangle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int LedIndex => Device.Leds.IndexOf(this);
|
/// <summary>
|
||||||
|
/// Gets the RGB.NET LED backing this Artemis LED
|
||||||
|
/// </summary>
|
||||||
public Led RgbLed { get; }
|
public Led RgbLed { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the device that contains this LED
|
||||||
|
/// </summary>
|
||||||
public ArtemisDevice Device { get; }
|
public ArtemisDevice Device { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the rectangle covering the LED, sized to match the render scale and positioned relative to the
|
||||||
|
/// <see cref="Device" />
|
||||||
|
/// </summary>
|
||||||
public SKRect RenderRectangle
|
public SKRect RenderRectangle
|
||||||
{
|
{
|
||||||
get => _renderRectangle;
|
get => _renderRectangle;
|
||||||
private set => SetAndNotify(ref _renderRectangle, value);
|
private set => SetAndNotify(ref _renderRectangle, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the rectangle covering the LED, sized to match the render scale
|
||||||
|
/// </summary>
|
||||||
public SKRect AbsoluteRenderRectangle
|
public SKRect AbsoluteRenderRectangle
|
||||||
{
|
{
|
||||||
get => _absoluteRenderRectangle;
|
get => _absoluteRenderRectangle;
|
||||||
private set => SetAndNotify(ref _absoluteRenderRectangle, value);
|
private set => SetAndNotify(ref _absoluteRenderRectangle, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculateRenderRectangle()
|
internal void CalculateRenderRectangle()
|
||||||
{
|
{
|
||||||
RenderRectangle = SKRect.Create(
|
RenderRectangle = SKRect.Create(
|
||||||
(RgbLed.LedRectangle.Location.X * Device.Surface.Scale).RoundToInt(),
|
(RgbLed.LedRectangle.Location.X * Device.Surface.Scale).RoundToInt(),
|
||||||
|
|||||||
@ -6,6 +6,9 @@ using RGB.NET.Core;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a surface of a specific scale, containing all the available <see cref="ArtemisDevice" />s
|
||||||
|
/// </summary>
|
||||||
public class ArtemisSurface : CorePropertyChanged
|
public class ArtemisSurface : CorePropertyChanged
|
||||||
{
|
{
|
||||||
private List<ArtemisDevice> _devices;
|
private List<ArtemisDevice> _devices;
|
||||||
@ -17,14 +20,14 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
SurfaceEntity = new SurfaceEntity {DeviceEntities = new List<DeviceEntity>()};
|
SurfaceEntity = new SurfaceEntity {DeviceEntities = new List<DeviceEntity>()};
|
||||||
EntityId = Guid.NewGuid();
|
EntityId = Guid.NewGuid();
|
||||||
|
|
||||||
Name = name;
|
|
||||||
Scale = scale;
|
|
||||||
RgbSurface = rgbSurface;
|
RgbSurface = rgbSurface;
|
||||||
IsActive = false;
|
|
||||||
|
_name = name;
|
||||||
|
_scale = scale;
|
||||||
|
_isActive = false;
|
||||||
|
|
||||||
// Devices are not populated here but as they are detected
|
// Devices are not populated here but as they are detected
|
||||||
Devices = new List<ArtemisDevice>();
|
_devices = new List<ArtemisDevice>();
|
||||||
|
|
||||||
ApplyToEntity();
|
ApplyToEntity();
|
||||||
}
|
}
|
||||||
@ -33,36 +36,51 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
SurfaceEntity = surfaceEntity;
|
SurfaceEntity = surfaceEntity;
|
||||||
EntityId = surfaceEntity.Id;
|
EntityId = surfaceEntity.Id;
|
||||||
|
|
||||||
RgbSurface = rgbSurface;
|
RgbSurface = rgbSurface;
|
||||||
Scale = scale;
|
|
||||||
Name = surfaceEntity.Name;
|
_scale = scale;
|
||||||
IsActive = surfaceEntity.IsActive;
|
_name = surfaceEntity.Name;
|
||||||
|
_isActive = surfaceEntity.IsActive;
|
||||||
|
|
||||||
// Devices are not populated here but as they are detected
|
// Devices are not populated here but as they are detected
|
||||||
Devices = new List<ArtemisDevice>();
|
_devices = new List<ArtemisDevice>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the RGB.NET surface backing this Artemis surface
|
||||||
|
/// </summary>
|
||||||
public RGBSurface RgbSurface { get; }
|
public RGBSurface RgbSurface { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the scale at which this surface is rendered
|
||||||
|
/// </summary>
|
||||||
public double Scale
|
public double Scale
|
||||||
{
|
{
|
||||||
get => _scale;
|
get => _scale;
|
||||||
private set => SetAndNotify(ref _scale, value);
|
private set => SetAndNotify(ref _scale, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the surface
|
||||||
|
/// </summary>
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get => _name;
|
get => _name;
|
||||||
set => SetAndNotify(ref _name, value);
|
set => SetAndNotify(ref _name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether this surface is the currently active surface
|
||||||
|
/// </summary>
|
||||||
public bool IsActive
|
public bool IsActive
|
||||||
{
|
{
|
||||||
get => _isActive;
|
get => _isActive;
|
||||||
internal set => SetAndNotify(ref _isActive, value);
|
internal set => SetAndNotify(ref _isActive, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of devices this surface contains
|
||||||
|
/// </summary>
|
||||||
public List<ArtemisDevice> Devices
|
public List<ArtemisDevice> Devices
|
||||||
{
|
{
|
||||||
get => _devices;
|
get => _devices;
|
||||||
@ -72,6 +90,10 @@ namespace Artemis.Core
|
|||||||
internal SurfaceEntity SurfaceEntity { get; set; }
|
internal SurfaceEntity SurfaceEntity { get; set; }
|
||||||
internal Guid EntityId { get; set; }
|
internal Guid EntityId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the scale of the surface
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
public void UpdateScale(double value)
|
public void UpdateScale(double value)
|
||||||
{
|
{
|
||||||
Scale = value;
|
Scale = value;
|
||||||
@ -89,16 +111,20 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
// Add missing device entities, don't remove old ones in case they come back later
|
// Add missing device entities, don't remove old ones in case they come back later
|
||||||
foreach (DeviceEntity deviceEntity in Devices.Select(d => d.DeviceEntity).ToList())
|
foreach (DeviceEntity deviceEntity in Devices.Select(d => d.DeviceEntity).ToList())
|
||||||
{
|
|
||||||
if (!SurfaceEntity.DeviceEntities.Contains(deviceEntity))
|
if (!SurfaceEntity.DeviceEntities.Contains(deviceEntity))
|
||||||
SurfaceEntity.DeviceEntities.Add(deviceEntity);
|
SurfaceEntity.DeviceEntities.Add(deviceEntity);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler<EventArgs> ScaleChanged;
|
/// <summary>
|
||||||
|
/// Occurs when the scale of the surface is changed
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<EventArgs>? ScaleChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ScaleChanged" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnScaleChanged()
|
protected virtual void OnScaleChanged()
|
||||||
{
|
{
|
||||||
ScaleChanged?.Invoke(this, EventArgs.Empty);
|
ScaleChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -9,6 +8,9 @@ using Humanizer;
|
|||||||
|
|
||||||
namespace Artemis.Core.DataModelExpansions
|
namespace Artemis.Core.DataModelExpansions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a data model that contains information on a game/application etc.
|
||||||
|
/// </summary>
|
||||||
public abstract class DataModel
|
public abstract class DataModel
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, DataModel> _dynamicDataModels = new Dictionary<string, DataModel>();
|
private readonly Dictionary<string, DataModel> _dynamicDataModels = new Dictionary<string, DataModel>();
|
||||||
@ -154,11 +156,17 @@ namespace Artemis.Core.DataModelExpansions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<DynamicDataModelEventArgs>? DynamicDataModelRemoved;
|
public event EventHandler<DynamicDataModelEventArgs>? DynamicDataModelRemoved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="DynamicDataModelAdded" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnDynamicDataModelAdded(DynamicDataModelEventArgs e)
|
protected virtual void OnDynamicDataModelAdded(DynamicDataModelEventArgs e)
|
||||||
{
|
{
|
||||||
DynamicDataModelAdded?.Invoke(this, e);
|
DynamicDataModelAdded?.Invoke(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="DynamicDataModelRemoved" /> event
|
||||||
|
/// </summary>
|
||||||
protected virtual void OnDynamicDataModelRemoved(DynamicDataModelEventArgs e)
|
protected virtual void OnDynamicDataModelRemoved(DynamicDataModelEventArgs e)
|
||||||
{
|
{
|
||||||
DynamicDataModelRemoved?.Invoke(this, e);
|
DynamicDataModelRemoved?.Invoke(this, e);
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a configuration dialog for a <see cref="Plugin" />
|
||||||
|
/// </summary>
|
||||||
public interface IPluginConfigurationDialog
|
public interface IPluginConfigurationDialog
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9,8 +9,8 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
public abstract class BaseLayerBrush : CorePropertyChanged, IDisposable
|
public abstract class BaseLayerBrush : CorePropertyChanged, IDisposable
|
||||||
{
|
{
|
||||||
private LayerBrushType _brushType;
|
private LayerBrushType _brushType;
|
||||||
private ILayerBrushConfigurationDialog _configurationDialog;
|
private ILayerBrushConfigurationDialog? _configurationDialog;
|
||||||
private LayerBrushDescriptor _descriptor;
|
private LayerBrushDescriptor? _descriptor;
|
||||||
private Layer _layer;
|
private Layer _layer;
|
||||||
private bool _supportsTransformation = true;
|
private bool _supportsTransformation = true;
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the descriptor of this brush
|
/// Gets the descriptor of this brush
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LayerBrushDescriptor Descriptor
|
public LayerBrushDescriptor? Descriptor
|
||||||
{
|
{
|
||||||
get => _descriptor;
|
get => _descriptor;
|
||||||
internal set => SetAndNotify(ref _descriptor, value);
|
internal set => SetAndNotify(ref _descriptor, value);
|
||||||
@ -35,7 +35,7 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a configuration dialog complementing the regular properties
|
/// Gets or sets a configuration dialog complementing the regular properties
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ILayerBrushConfigurationDialog ConfigurationDialog
|
public ILayerBrushConfigurationDialog? ConfigurationDialog
|
||||||
{
|
{
|
||||||
get => _configurationDialog;
|
get => _configurationDialog;
|
||||||
protected set => SetAndNotify(ref _configurationDialog, value);
|
protected set => SetAndNotify(ref _configurationDialog, value);
|
||||||
@ -53,12 +53,12 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the ID of the <see cref="LayerBrushProvider" /> that provided this effect
|
/// Gets the ID of the <see cref="LayerBrushProvider" /> that provided this effect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ProviderId => Descriptor?.Provider?.Id;
|
public string? ProviderId => Descriptor?.Provider.Id;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a reference to the layer property group without knowing it's type
|
/// Gets a reference to the layer property group without knowing it's type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual LayerPropertyGroup BaseProperties => null;
|
public virtual LayerPropertyGroup? BaseProperties => null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets whether the brush supports transformations
|
/// Gets or sets whether the brush supports transformations
|
||||||
@ -70,7 +70,7 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
protected set
|
protected set
|
||||||
{
|
{
|
||||||
if (value && BrushType == LayerBrushType.RgbNet)
|
if (value && BrushType == LayerBrushType.RgbNet)
|
||||||
throw new ArtemisPluginFeatureException(Descriptor.Provider, "An RGB.NET brush cannot support transformation");
|
throw new ArtemisPluginFeatureException(Descriptor?.Provider!, "An RGB.NET brush cannot support transformation");
|
||||||
_supportsTransformation = value;
|
_supportsTransformation = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
DisableLayerBrush();
|
DisableLayerBrush();
|
||||||
BaseProperties.Dispose();
|
BaseProperties?.Dispose();
|
||||||
|
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
|||||||
@ -46,7 +46,7 @@ namespace Artemis.Core.LayerBrushes
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the provided <paramref name="reference" /> references to a brush provided by this descriptor
|
/// Determines whether the provided <paramref name="reference" /> references to a brush provided by this descriptor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool MatchesLayerBrushReference(LayerBrushReference reference)
|
public bool MatchesLayerBrushReference(LayerBrushReference? reference)
|
||||||
{
|
{
|
||||||
if (reference == null)
|
if (reference == null)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
namespace Artemis.Core.LayerEffects
|
|
||||||
{
|
|
||||||
public interface IEffectConfigurationViewModel
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,8 @@
|
|||||||
namespace Artemis.Core.LayerEffects
|
namespace Artemis.Core.LayerEffects
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a configuration dialog for a <see cref="LayerEffect{T}" />
|
||||||
|
/// </summary>
|
||||||
public interface ILayerEffectConfigurationDialog
|
public interface ILayerEffectConfigurationDialog
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -160,6 +160,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
foreach (PluginFeature feature in Features)
|
foreach (PluginFeature feature in Features)
|
||||||
|
|||||||
@ -104,7 +104,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TimerOnElapsed(object sender, ElapsedEventArgs e)
|
private void TimerOnElapsed(object? sender, ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
if (!Feature.IsEnabled)
|
if (!Feature.IsEnabled)
|
||||||
return;
|
return;
|
||||||
@ -128,12 +128,12 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FeatureOnEnabled(object sender, EventArgs e)
|
private void FeatureOnEnabled(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FeatureOnDisabled(object sender, EventArgs e)
|
private void FeatureOnDisabled(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -198,7 +198,7 @@ namespace Artemis.Core.Services
|
|||||||
module.InternalRender(args.DeltaTime, _surfaceService.ActiveSurface, canvas, _rgbService.BitmapBrush.Bitmap.Info);
|
module.InternalRender(args.DeltaTime, _surfaceService.ActiveSurface, canvas, _rgbService.BitmapBrush.Bitmap.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnFrameRendering(new FrameRenderingEventArgs(modules, canvas, args.DeltaTime, _rgbService.Surface));
|
OnFrameRendering(new FrameRenderingEventArgs(canvas, args.DeltaTime, _rgbService.Surface));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@ -44,6 +44,10 @@ namespace Artemis.Core.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="plugin">The plugin to enable</param>
|
/// <param name="plugin">The plugin to enable</param>
|
||||||
/// <param name="saveState">Whether or not to save the new enabled state</param>
|
/// <param name="saveState">Whether or not to save the new enabled state</param>
|
||||||
|
/// <param name="ignorePluginLock">
|
||||||
|
/// Whether or not plugin lock files should be ignored. If set to <see langword="true" />,
|
||||||
|
/// plugins with lock files will load successfully
|
||||||
|
/// </param>
|
||||||
void EnablePlugin(Plugin plugin, bool saveState, bool ignorePluginLock = false);
|
void EnablePlugin(Plugin plugin, bool saveState, bool ignorePluginLock = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -95,7 +99,7 @@ namespace Artemis.Core.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assembly"></param>
|
/// <param name="assembly"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Plugin GetPluginByAssembly(Assembly assembly);
|
Plugin? GetPluginByAssembly(Assembly? assembly);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the plugin info of the current call stack
|
/// Returns the plugin info of the current call stack
|
||||||
|
|||||||
@ -138,8 +138,10 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin? GetPluginByAssembly(Assembly assembly)
|
public Plugin? GetPluginByAssembly(Assembly? assembly)
|
||||||
{
|
{
|
||||||
|
if (assembly == null)
|
||||||
|
return null;
|
||||||
lock (_plugins)
|
lock (_plugins)
|
||||||
{
|
{
|
||||||
return _plugins.FirstOrDefault(p => p.Assembly == assembly);
|
return _plugins.FirstOrDefault(p => p.Assembly == assembly);
|
||||||
@ -159,8 +161,8 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
foreach (StackFrame stackFrame in stackFrames)
|
foreach (StackFrame stackFrame in stackFrames)
|
||||||
{
|
{
|
||||||
Assembly assembly = stackFrame.GetMethod().DeclaringType.Assembly;
|
Assembly? assembly = stackFrame.GetMethod()?.DeclaringType?.Assembly;
|
||||||
Plugin plugin = GetPluginByAssembly(assembly);
|
Plugin? plugin = GetPluginByAssembly(assembly);
|
||||||
if (plugin != null)
|
if (plugin != null)
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
@ -179,7 +181,7 @@ namespace Artemis.Core.Services
|
|||||||
{
|
{
|
||||||
if (LoadingPlugins)
|
if (LoadingPlugins)
|
||||||
throw new ArtemisCoreException("Cannot load plugins while a previous load hasn't been completed yet.");
|
throw new ArtemisCoreException("Cannot load plugins while a previous load hasn't been completed yet.");
|
||||||
|
|
||||||
LoadingPlugins = true;
|
LoadingPlugins = true;
|
||||||
|
|
||||||
// Unload all currently loaded plugins first
|
// Unload all currently loaded plugins first
|
||||||
@ -207,8 +209,10 @@ namespace Artemis.Core.Services
|
|||||||
public void UnloadPlugins()
|
public void UnloadPlugins()
|
||||||
{
|
{
|
||||||
// Unload all plugins
|
// Unload all plugins
|
||||||
|
// ReSharper disable InconsistentlySynchronizedField - UnloadPlugin will lock it when it has to
|
||||||
while (_plugins.Count > 0)
|
while (_plugins.Count > 0)
|
||||||
UnloadPlugin(_plugins[0]);
|
UnloadPlugin(_plugins[0]);
|
||||||
|
// ReSharper restore InconsistentlySynchronizedField
|
||||||
|
|
||||||
lock (_plugins)
|
lock (_plugins)
|
||||||
{
|
{
|
||||||
@ -297,7 +301,11 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
catch (ReflectionTypeLoadException e)
|
catch (ReflectionTypeLoadException e)
|
||||||
{
|
{
|
||||||
throw new ArtemisPluginException(plugin, "Failed to initialize the plugin assembly", new AggregateException(e.LoaderExceptions));
|
throw new ArtemisPluginException(
|
||||||
|
plugin,
|
||||||
|
"Failed to initialize the plugin assembly",
|
||||||
|
new AggregateException(e.LoaderExceptions.Where(le => le != null).Cast<Exception>().ToArray())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!featureTypes.Any())
|
if (!featureTypes.Any())
|
||||||
@ -318,7 +326,7 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
// Load the enabled state and if not found, default to true
|
// Load the enabled state and if not found, default to true
|
||||||
instance.Entity = plugin.Entity.Features.FirstOrDefault(i => i.Type == featureType.FullName) ??
|
instance.Entity = plugin.Entity.Features.FirstOrDefault(i => i.Type == featureType.FullName) ??
|
||||||
new PluginFeatureEntity {IsEnabled = true, Type = featureType.FullName};
|
new PluginFeatureEntity {IsEnabled = true, Type = featureType.FullName!};
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -385,7 +393,7 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
plugin.SetEnabled(false);
|
plugin.SetEnabled(false);
|
||||||
|
|
||||||
plugin.Kernel.Dispose();
|
plugin.Kernel?.Dispose();
|
||||||
plugin.Kernel = null;
|
plugin.Kernel = null;
|
||||||
|
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
@ -487,28 +495,22 @@ namespace Artemis.Core.Services
|
|||||||
_pluginRepository.SavePlugin(plugin.Entity);
|
_pluginRepository.SavePlugin(plugin.Entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PluginFeatureEntity GetOrCreateFeatureEntity(PluginFeature feature)
|
|
||||||
{
|
|
||||||
return feature.Plugin.Entity.Features.FirstOrDefault(i => i.Type == feature.GetType().FullName) ??
|
|
||||||
new PluginFeatureEntity {IsEnabled = true, Type = feature.GetType().FullName};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public event EventHandler CopyingBuildInPlugins;
|
public event EventHandler? CopyingBuildInPlugins;
|
||||||
public event EventHandler<PluginEventArgs> PluginLoading;
|
public event EventHandler<PluginEventArgs>? PluginLoading;
|
||||||
public event EventHandler<PluginEventArgs> PluginLoaded;
|
public event EventHandler<PluginEventArgs>? PluginLoaded;
|
||||||
public event EventHandler<PluginEventArgs> PluginUnloaded;
|
public event EventHandler<PluginEventArgs>? PluginUnloaded;
|
||||||
public event EventHandler<PluginEventArgs> PluginEnabling;
|
public event EventHandler<PluginEventArgs>? PluginEnabling;
|
||||||
public event EventHandler<PluginEventArgs> PluginEnabled;
|
public event EventHandler<PluginEventArgs>? PluginEnabled;
|
||||||
public event EventHandler<PluginEventArgs> PluginDisabled;
|
public event EventHandler<PluginEventArgs>? PluginDisabled;
|
||||||
|
|
||||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureEnabling;
|
public event EventHandler<PluginFeatureEventArgs>? PluginFeatureEnabling;
|
||||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureEnabled;
|
public event EventHandler<PluginFeatureEventArgs>? PluginFeatureEnabled;
|
||||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureDisabled;
|
public event EventHandler<PluginFeatureEventArgs>? PluginFeatureDisabled;
|
||||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureEnableFailed;
|
public event EventHandler<PluginFeatureEventArgs>? PluginFeatureEnableFailed;
|
||||||
|
|
||||||
protected virtual void OnCopyingBuildInPlugins()
|
protected virtual void OnCopyingBuildInPlugins()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Artemis.Core.DeviceProviders;
|
||||||
using Artemis.Storage.Entities.Surface;
|
using Artemis.Storage.Entities.Surface;
|
||||||
using Artemis.Storage.Repositories.Interfaces;
|
using Artemis.Storage.Repositories.Interfaces;
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
@ -44,8 +45,8 @@ namespace Artemis.Core.Services
|
|||||||
// Add all current devices
|
// Add all current devices
|
||||||
foreach (IRGBDevice rgbDevice in _rgbService.LoadedDevices)
|
foreach (IRGBDevice rgbDevice in _rgbService.LoadedDevices)
|
||||||
{
|
{
|
||||||
PluginFeature pluginFeature = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
|
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
|
||||||
configuration.Devices.Add(new ArtemisDevice(rgbDevice, pluginFeature, configuration));
|
configuration.Devices.Add(new ArtemisDevice(rgbDevice, deviceProvider, configuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (_surfaceConfigurations)
|
lock (_surfaceConfigurations)
|
||||||
@ -136,8 +137,8 @@ namespace Artemis.Core.Services
|
|||||||
IRGBDevice device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
|
IRGBDevice device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
|
||||||
if (device != null)
|
if (device != null)
|
||||||
{
|
{
|
||||||
PluginFeature pluginFeature = _pluginManagementService.GetDeviceProviderByDevice(device);
|
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(device);
|
||||||
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, pluginFeature, surfaceConfiguration, position));
|
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, deviceProvider, surfaceConfiguration, position));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,8 +179,8 @@ namespace Artemis.Core.Services
|
|||||||
DeviceEntity existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
|
DeviceEntity existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
|
||||||
if (existingDeviceConfig != null)
|
if (existingDeviceConfig != null)
|
||||||
{
|
{
|
||||||
PluginFeature pluginFeature = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
|
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
|
||||||
device = new ArtemisDevice(rgbDevice, pluginFeature, surface, existingDeviceConfig);
|
device = new ArtemisDevice(rgbDevice, deviceProvider, surface, existingDeviceConfig);
|
||||||
}
|
}
|
||||||
// Fall back on creating a new device
|
// Fall back on creating a new device
|
||||||
else
|
else
|
||||||
@ -189,8 +190,8 @@ namespace Artemis.Core.Services
|
|||||||
rgbDevice.DeviceInfo,
|
rgbDevice.DeviceInfo,
|
||||||
deviceIdentifier
|
deviceIdentifier
|
||||||
);
|
);
|
||||||
PluginFeature pluginFeature = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
|
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
|
||||||
device = new ArtemisDevice(rgbDevice, pluginFeature, surface);
|
device = new ArtemisDevice(rgbDevice, deviceProvider, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
surface.Devices.Add(device);
|
surface.Devices.Add(device);
|
||||||
|
|||||||
@ -38,7 +38,7 @@ namespace Artemis.Core
|
|||||||
OnConditionOperatorRemoved(new ConditionOperatorStoreEvent(registration));
|
OnConditionOperatorRemoved(new ConditionOperatorStoreEvent(registration));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ConditionOperatorRegistration Get(Guid pluginGuid, string type)
|
public static ConditionOperatorRegistration? Get(Guid pluginGuid, string type)
|
||||||
{
|
{
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -10,6 +10,9 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
public static DataBindingModifierTypeRegistration Add(BaseDataBindingModifierType modifierType)
|
public static DataBindingModifierTypeRegistration Add(BaseDataBindingModifierType modifierType)
|
||||||
{
|
{
|
||||||
|
if (modifierType.Plugin == null)
|
||||||
|
throw new ArtemisCoreException("Cannot add a data binding modifier type that is not associated with a plugin");
|
||||||
|
|
||||||
DataBindingModifierTypeRegistration typeRegistration;
|
DataBindingModifierTypeRegistration typeRegistration;
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
@ -38,7 +41,7 @@ namespace Artemis.Core
|
|||||||
OnDataBindingModifierRemoved(new DataBindingModifierTypeStoreEvent(typeRegistration));
|
OnDataBindingModifierRemoved(new DataBindingModifierTypeStoreEvent(typeRegistration));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataBindingModifierTypeRegistration Get(Guid pluginGuid, string type)
|
public static DataBindingModifierTypeRegistration? Get(Guid pluginGuid, string type)
|
||||||
{
|
{
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
@ -74,8 +77,8 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public static event EventHandler<DataBindingModifierTypeStoreEvent> DataBindingModifierAdded;
|
public static event EventHandler<DataBindingModifierTypeStoreEvent>? DataBindingModifierAdded;
|
||||||
public static event EventHandler<DataBindingModifierTypeStoreEvent> DataBindingModifierRemoved;
|
public static event EventHandler<DataBindingModifierTypeStoreEvent>? DataBindingModifierRemoved;
|
||||||
|
|
||||||
private static void OnDataBindingModifierAdded(DataBindingModifierTypeStoreEvent e)
|
private static void OnDataBindingModifierAdded(DataBindingModifierTypeStoreEvent e)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataModelRegistration Get(string id)
|
public static DataModelRegistration? Get(string id)
|
||||||
{
|
{
|
||||||
lock (Registrations)
|
lock (Registrations)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
@ -42,7 +41,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the provided URL in the default web browser
|
/// Opens the provided URL in the default web browser
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url">The URL to open</param>
|
/// <param name="url">The URL to open</param>
|
||||||
/// <returns>The process created to open the URL</returns>
|
/// <returns>The process created to open the URL</returns>
|
||||||
@ -67,7 +66,10 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|
||||||
public static event EventHandler ShutdownRequested;
|
/// <summary>
|
||||||
|
/// Occurs when the core has requested an application shutdown
|
||||||
|
/// </summary>
|
||||||
|
public static event EventHandler? ShutdownRequested;
|
||||||
|
|
||||||
private static void OnShutdownRequested()
|
private static void OnShutdownRequested()
|
||||||
{
|
{
|
||||||
@ -75,7 +77,5 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,6 +28,7 @@
|
|||||||
<NrtRequiredVcs>git</NrtRequiredVcs>
|
<NrtRequiredVcs>git</NrtRequiredVcs>
|
||||||
<NrtShowRevision>true</NrtShowRevision>
|
<NrtShowRevision>true</NrtShowRevision>
|
||||||
<Version>2.0.0</Version>
|
<Version>2.0.0</Version>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<DocumentationFile>bin\x64\Release\Artemis.UI.Shared.xml</DocumentationFile>
|
<DocumentationFile>bin\x64\Release\Artemis.UI.Shared.xml</DocumentationFile>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user