mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Plugins - Implemented features
Core - Removed Stylet dependency for #500
This commit is contained in:
parent
b56966c585
commit
e812929215
@ -50,7 +50,6 @@
|
||||
<PackageReference Include="Serilog.Sinks.Debug" Version="1.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
|
||||
<PackageReference Include="SkiaSharp" Version="1.68.3" />
|
||||
<PackageReference Include="Stylet" Version="1.3.4" />
|
||||
<PackageReference Include="System.Buffers" Version="4.5.0" />
|
||||
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
|
||||
<PackageReference Include="System.Reflection.Metadata" Version="1.8.0" />
|
||||
|
||||
@ -42,6 +42,7 @@
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Clayerproperties_005Ctypes/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Clayershapes/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Csurface/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=mvvm/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=placeholders/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cdatamodelexpansions_005Cattributes/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@ -12,7 +12,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// The full path to the Artemis application folder
|
||||
/// </summary>
|
||||
public static readonly string ApplicationFolder = Path.GetDirectoryName(typeof(Constants).Assembly.Location);
|
||||
public static readonly string ApplicationFolder = Path.GetDirectoryName(typeof(Constants).Assembly.Location)!;
|
||||
|
||||
/// <summary>
|
||||
/// The full path to the Artemis executable
|
||||
@ -34,11 +34,16 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public static readonly PluginInfo CorePluginInfo = new PluginInfo
|
||||
{
|
||||
Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core", IsEnabled = true
|
||||
Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core"
|
||||
};
|
||||
|
||||
internal static readonly CorePluginImplementation CorePluginImplementation = new CorePluginImplementation {PluginInfo = CorePluginInfo};
|
||||
internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new EffectPlaceholderPlugin {PluginInfo = CorePluginInfo};
|
||||
/// <summary>
|
||||
/// The plugin used by core components of Artemis
|
||||
/// </summary>
|
||||
public static readonly Plugin CorePlugin = new Plugin(CorePluginInfo, new DirectoryInfo(ApplicationFolder));
|
||||
|
||||
internal static readonly CorePluginFeature CorePluginFeature = new CorePluginFeature {Plugin = CorePlugin};
|
||||
internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new EffectPlaceholderPlugin {Plugin = CorePlugin};
|
||||
|
||||
/// <summary>
|
||||
/// A read-only collection containing all primitive numeric types
|
||||
|
||||
18
src/Artemis.Core/Events/Plugins/PluginFeatureEventArgs.cs
Normal file
18
src/Artemis.Core/Events/Plugins/PluginFeatureEventArgs.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class PluginFeatureEventArgs : EventArgs
|
||||
{
|
||||
public PluginFeatureEventArgs()
|
||||
{
|
||||
}
|
||||
|
||||
public PluginFeatureEventArgs(PluginFeature pluginFeature)
|
||||
{
|
||||
PluginFeature = pluginFeature;
|
||||
}
|
||||
|
||||
public PluginFeature PluginFeature { get; }
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class PluginImplementationEventArgs : EventArgs
|
||||
{
|
||||
public PluginImplementationEventArgs()
|
||||
{
|
||||
}
|
||||
|
||||
public PluginImplementationEventArgs(PluginImplementation pluginImplementation)
|
||||
{
|
||||
PluginImplementation = pluginImplementation;
|
||||
}
|
||||
|
||||
public PluginImplementation PluginImplementation { get; }
|
||||
}
|
||||
}
|
||||
24
src/Artemis.Core/Exceptions/ArtemisPluginFeatureException.cs
Normal file
24
src/Artemis.Core/Exceptions/ArtemisPluginFeatureException.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class ArtemisPluginFeatureException : Exception
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/Artemis.Core/MVVM/CorePropertyChanged.cs
Normal file
72
src/Artemis.Core/MVVM/CorePropertyChanged.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a basic bindable class which notifies when a property value changes.
|
||||
/// </summary>
|
||||
public abstract class CorePropertyChanged : INotifyPropertyChanged
|
||||
{
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a property value changes.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the property already matches the desirec value or needs to be updated.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the property.</typeparam>
|
||||
/// <param name="storage">Reference to the backing-filed.</param>
|
||||
/// <param name="value">Value to apply.</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected virtual bool RequiresUpdate<T>(ref T storage, T value)
|
||||
{
|
||||
return !Equals(storage, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the property already matches the desired value and updates it if not.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the property.</typeparam>
|
||||
/// <param name="storage">Reference to the backing-filed.</param>
|
||||
/// <param name="value">Value to apply.</param>
|
||||
/// <param name="propertyName">
|
||||
/// Name of the property used to notify listeners. This value is optional
|
||||
/// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute" />
|
||||
/// .
|
||||
/// </param>
|
||||
/// <returns><c>true</c> if the value was changed, <c>false</c> if the existing value matched the desired value.</returns>
|
||||
protected virtual bool SetAndNotify<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (!RequiresUpdate(ref storage, value)) return false;
|
||||
|
||||
storage = value;
|
||||
// ReSharper disable once ExplicitCallerInfoArgument
|
||||
OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the <see cref="PropertyChanged" />-event when a a property value has changed.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">
|
||||
/// Name of the property used to notify listeners. This value is optional
|
||||
/// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute" />
|
||||
/// .
|
||||
/// </param>
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,6 @@ using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Artemis.Core.Properties;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
@ -19,13 +18,13 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public ColorGradient()
|
||||
{
|
||||
Stops = new BindableCollection<ColorGradientStop>();
|
||||
Stops = new List<ColorGradientStop>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all the <see cref="ColorGradientStop" />s in the gradient
|
||||
/// </summary>
|
||||
public BindableCollection<ColorGradientStop> Stops { get; }
|
||||
public List<ColorGradientStop> Stops { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the colors in the color gradient
|
||||
|
||||
@ -22,10 +22,10 @@ namespace Artemis.Core
|
||||
public abstract string Icon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin info this condition operator belongs to
|
||||
/// Gets the plugin this condition operator belongs to
|
||||
/// <para>Note: Not set until after registering</para>
|
||||
/// </summary>
|
||||
public PluginInfo PluginInfo { get; internal set; }
|
||||
public Plugin Plugin { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the left side type of this condition operator
|
||||
|
||||
@ -346,7 +346,7 @@ namespace Artemis.Core
|
||||
|
||||
if (Operator != null)
|
||||
{
|
||||
Entity.OperatorPluginGuid = Operator.PluginInfo.Guid;
|
||||
Entity.OperatorPluginGuid = Operator.Plugin.Guid;
|
||||
Entity.OperatorType = Operator.GetType().Name;
|
||||
}
|
||||
}
|
||||
@ -358,7 +358,7 @@ namespace Artemis.Core
|
||||
private void ConditionOperatorStoreOnConditionOperatorAdded(object? sender, ConditionOperatorStoreEvent e)
|
||||
{
|
||||
BaseConditionOperator conditionOperator = e.Registration.ConditionOperator;
|
||||
if (Entity.OperatorPluginGuid == conditionOperator.PluginInfo.Guid && Entity.OperatorType == conditionOperator.GetType().Name)
|
||||
if (Entity.OperatorPluginGuid == conditionOperator.Plugin.Guid && Entity.OperatorType == conditionOperator.GetType().Name)
|
||||
UpdateOperator(conditionOperator);
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Core
|
||||
{
|
||||
internal EventPredicateWrapperDataModel()
|
||||
{
|
||||
Implementation = Constants.CorePluginInfo;
|
||||
Feature = Constants.CorePluginFeature;
|
||||
}
|
||||
|
||||
[DataModelIgnore]
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Core
|
||||
{
|
||||
internal ListPredicateWrapperDataModel()
|
||||
{
|
||||
Implementation = Constants.CorePluginInfo;
|
||||
Feature = Constants.CorePluginFeature;
|
||||
}
|
||||
|
||||
[DataModelIgnore]
|
||||
|
||||
@ -12,10 +12,10 @@ namespace Artemis.Core
|
||||
public abstract class BaseDataBindingModifierType
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the plugin info this data binding modifier belongs to
|
||||
/// Gets the plugin this data binding modifier belongs to
|
||||
/// <para>Note: Not set until after registering</para>
|
||||
/// </summary>
|
||||
public PluginInfo PluginInfo { get; internal set; }
|
||||
public Plugin Plugin { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value type of this modifier type
|
||||
|
||||
@ -238,7 +238,7 @@ namespace Artemis.Core
|
||||
if (ModifierType != null)
|
||||
{
|
||||
Entity.ModifierType = ModifierType.GetType().Name;
|
||||
Entity.ModifierTypePluginGuid = ModifierType.PluginInfo.Guid;
|
||||
Entity.ModifierTypePluginGuid = ModifierType.Plugin.Guid;
|
||||
}
|
||||
|
||||
// General
|
||||
@ -286,7 +286,7 @@ namespace Artemis.Core
|
||||
return;
|
||||
|
||||
BaseDataBindingModifierType modifierType = e.TypeRegistration.DataBindingModifierType;
|
||||
if (modifierType.PluginInfo.Guid == Entity.ModifierTypePluginGuid && modifierType.GetType().Name == Entity.ModifierType)
|
||||
if (modifierType.Plugin.Guid == Entity.ModifierTypePluginGuid && modifierType.GetType().Name == Entity.ModifierType)
|
||||
UpdateModifierType(modifierType);
|
||||
}
|
||||
|
||||
|
||||
@ -91,9 +91,9 @@ namespace Artemis.Core
|
||||
public DataModel? Target { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data model GUID of the <see cref="Target" /> if it is a <see cref="DataModel" />
|
||||
/// Gets the data model ID of the <see cref="Target" /> if it is a <see cref="DataModel" />
|
||||
/// </summary>
|
||||
public Guid? DataModelGuid => Target?.Implementation.Guid;
|
||||
public string? DataModelId => Target?.Feature.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the point-separated path associated with this <see cref="DataModelPath" />
|
||||
@ -267,8 +267,8 @@ namespace Artemis.Core
|
||||
{
|
||||
Path = Entity.Path;
|
||||
|
||||
if (Target == null && Entity.DataModelGuid != null)
|
||||
Target = DataModelStore.Get(Entity.DataModelGuid.Value)?.DataModel;
|
||||
if (Target == null && Entity.DataModelId != null)
|
||||
Target = DataModelStore.Get(Entity.DataModelId)?.DataModel;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -279,7 +279,7 @@ namespace Artemis.Core
|
||||
return;
|
||||
|
||||
Entity.Path = Path;
|
||||
Entity.DataModelGuid = DataModelGuid;
|
||||
Entity.DataModelId = DataModelId;
|
||||
|
||||
Entity.WrapperType = Target switch
|
||||
{
|
||||
@ -295,7 +295,7 @@ namespace Artemis.Core
|
||||
|
||||
private void DataModelStoreOnDataModelAdded(object? sender, DataModelStoreEvent e)
|
||||
{
|
||||
if (e.Registration.DataModel.Implementation.Guid != Entity.DataModelGuid)
|
||||
if (e.Registration.DataModel.Feature.Id != Entity.DataModelId)
|
||||
return;
|
||||
|
||||
Target = e.Registration.DataModel;
|
||||
@ -304,7 +304,7 @@ namespace Artemis.Core
|
||||
|
||||
private void DataModelStoreOnDataModelRemoved(object? sender, DataModelStoreEvent e)
|
||||
{
|
||||
if (e.Registration.DataModel.Implementation.Guid != Entity.DataModelGuid)
|
||||
if (e.Registration.DataModel.Feature.Id != Entity.DataModelId)
|
||||
return;
|
||||
|
||||
Target = null;
|
||||
|
||||
@ -190,9 +190,9 @@ namespace Artemis.Core
|
||||
typeof(PropertyGroupDescriptionAttribute)
|
||||
);
|
||||
General.GroupDescription = (PropertyGroupDescriptionAttribute) generalAttribute;
|
||||
General.Initialize(this, "General.", Constants.CorePluginInfo);
|
||||
General.Initialize(this, "General.", Constants.CorePluginFeature);
|
||||
Transform.GroupDescription = (PropertyGroupDescriptionAttribute) transformAttribute;
|
||||
Transform.Initialize(this, "Transform.", Constants.CorePluginInfo);
|
||||
Transform.Initialize(this, "Transform.", Constants.CorePluginFeature);
|
||||
|
||||
General.ShapeType.CurrentValueSet += ShapeTypeOnCurrentValueSet;
|
||||
ApplyShapeType();
|
||||
@ -619,7 +619,7 @@ namespace Artemis.Core
|
||||
|
||||
BaseLayerBrush brush = LayerBrush;
|
||||
DeactivateLayerBrush();
|
||||
LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == brush.PluginInfo.Guid && p.Path.StartsWith("LayerBrush."));
|
||||
LayerEntity.PropertyEntities.RemoveAll(p => p.FeatureId == brush.ProviderId && p.Path.StartsWith("LayerBrush."));
|
||||
}
|
||||
|
||||
internal void ActivateLayerBrush()
|
||||
@ -628,7 +628,7 @@ namespace Artemis.Core
|
||||
if (current == null)
|
||||
return;
|
||||
|
||||
LayerBrushDescriptor descriptor = LayerBrushStore.Get(current.BrushPluginGuid, current.BrushType)?.LayerBrushDescriptor;
|
||||
LayerBrushDescriptor? descriptor = LayerBrushStore.Get(current.LayerBrushProviderId, current.BrushType)?.LayerBrushDescriptor;
|
||||
descriptor?.CreateInstance(this);
|
||||
|
||||
OnLayerBrushUpdated();
|
||||
@ -662,7 +662,7 @@ namespace Artemis.Core
|
||||
return;
|
||||
|
||||
LayerBrushReference current = General.BrushReference.CurrentValue;
|
||||
if (e.Registration.PluginImplementation.PluginInfo.Guid == current.BrushPluginGuid &&
|
||||
if (e.Registration.PluginFeature.Id == current.LayerBrushProviderId &&
|
||||
e.Registration.LayerBrushDescriptor.LayerBrushType.Name == current.BrushType)
|
||||
ActivateLayerBrush();
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using Artemis.Core.LayerBrushes;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
@ -8,24 +7,24 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public class LayerBrushReference
|
||||
{
|
||||
/// <summary>
|
||||
/// The GUID of the plugin the brush descriptor resides in
|
||||
/// </summary>
|
||||
public Guid BrushPluginGuid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The full type name of the brush descriptor
|
||||
/// </summary>
|
||||
public string BrushType { get; set; }
|
||||
|
||||
public LayerBrushReference()
|
||||
{
|
||||
}
|
||||
|
||||
public LayerBrushReference(LayerBrushDescriptor descriptor)
|
||||
{
|
||||
BrushPluginGuid = descriptor.LayerBrushProvider.PluginInfo.Guid;
|
||||
LayerBrushProviderId = descriptor.Provider.Id;
|
||||
BrushType = descriptor.LayerBrushType.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the layer brush provided the brush was provided by
|
||||
/// </summary>
|
||||
public string LayerBrushProviderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The full type name of the brush descriptor
|
||||
/// </summary>
|
||||
public string BrushType { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,11 @@
|
||||
using System;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a keyframe on a <see cref="LayerProperty{T}" /> containing a value and a timestamp
|
||||
/// </summary>
|
||||
public class LayerPropertyKeyframe<T> : PropertyChangedBase
|
||||
public class LayerPropertyKeyframe<T> : CorePropertyChanged
|
||||
{
|
||||
private LayerProperty<T> _layerProperty;
|
||||
private TimeSpan _position;
|
||||
|
||||
@ -28,11 +28,11 @@ namespace Artemis.Core
|
||||
/// Gets the description of this group
|
||||
/// </summary>
|
||||
public PropertyGroupDescriptionAttribute GroupDescription { get; internal set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the info of the plugin this group is associated with
|
||||
/// Gets the plugin feature this group is associated with
|
||||
/// </summary>
|
||||
public PluginInfo PluginInfo { get; internal set; }
|
||||
public PluginFeature Feature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the profile element (such as layer or folder) this group is associated with
|
||||
@ -145,18 +145,18 @@ namespace Artemis.Core
|
||||
PropertyGroupInitialized?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
internal void Initialize(RenderProfileElement profileElement, [NotNull] string path, PluginInfo pluginInfo)
|
||||
internal void Initialize(RenderProfileElement profileElement, [NotNull] string path, PluginFeature feature)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (pluginInfo == null)
|
||||
throw new ArgumentNullException(nameof(pluginInfo));
|
||||
if (feature == null)
|
||||
throw new ArgumentNullException(nameof(feature));
|
||||
|
||||
// Doubt this will happen but let's make sure
|
||||
if (PropertiesInitialized)
|
||||
throw new ArtemisCoreException("Layer property group already initialized, wut");
|
||||
|
||||
PluginInfo = pluginInfo;
|
||||
Feature = feature;
|
||||
ProfileElement = profileElement;
|
||||
Path = path.TrimEnd('.');
|
||||
|
||||
@ -246,7 +246,7 @@ namespace Artemis.Core
|
||||
instance.GroupDescription = propertyGroupDescription;
|
||||
instance.LayerBrush = LayerBrush;
|
||||
instance.LayerEffect = LayerEffect;
|
||||
instance.Initialize(ProfileElement, $"{path}{propertyInfo.Name}.", PluginInfo);
|
||||
instance.Initialize(ProfileElement, $"{path}{propertyInfo.Name}.", Feature);
|
||||
|
||||
propertyInfo.SetValue(this, instance);
|
||||
_layerPropertyGroups.Add(instance);
|
||||
@ -254,11 +254,11 @@ namespace Artemis.Core
|
||||
|
||||
private PropertyEntity GetPropertyEntity(RenderProfileElement profileElement, string path, out bool fromStorage)
|
||||
{
|
||||
PropertyEntity entity = profileElement.RenderElementEntity.PropertyEntities.FirstOrDefault(p => p.PluginGuid == PluginInfo.Guid && p.Path == path);
|
||||
PropertyEntity entity = profileElement.RenderElementEntity.PropertyEntities.FirstOrDefault(p => p.FeatureId == Feature.Id && p.Path == path);
|
||||
fromStorage = entity != null;
|
||||
if (entity == null)
|
||||
{
|
||||
entity = new PropertyEntity {PluginGuid = PluginInfo.Guid, Path = path};
|
||||
entity = new PropertyEntity {FeatureId = Feature.Id, Path = path};
|
||||
profileElement.RenderElementEntity.PropertyEntities.Add(entity);
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Modules;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Newtonsoft.Json;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.Core
|
||||
@ -147,7 +146,7 @@ namespace Artemis.Core
|
||||
throw new ObjectDisposedException("Profile");
|
||||
|
||||
ProfileEntity.Id = EntityId;
|
||||
ProfileEntity.PluginGuid = Module.PluginInfo.Guid;
|
||||
ProfileEntity.ModuleId = Module.Id;
|
||||
ProfileEntity.Name = Name;
|
||||
ProfileEntity.IsActive = IsActivated;
|
||||
|
||||
|
||||
@ -3,11 +3,10 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public abstract class ProfileElement : PropertyChangedBase, IDisposable
|
||||
public abstract class ProfileElement : CorePropertyChanged, IDisposable
|
||||
{
|
||||
private bool _enabled;
|
||||
private Guid _entityId;
|
||||
|
||||
@ -44,7 +44,7 @@ namespace Artemis.Core
|
||||
LayerEffectEntity layerEffectEntity = new LayerEffectEntity
|
||||
{
|
||||
Id = layerEffect.EntityId,
|
||||
PluginGuid = layerEffect.Descriptor.PlaceholderFor ?? layerEffect.PluginInfo.Guid,
|
||||
ProviderId = layerEffect.Descriptor.PlaceholderFor ?? layerEffect.ProviderId,
|
||||
EffectType = layerEffect.GetEffectTypeName(),
|
||||
Name = layerEffect.Name,
|
||||
Enabled = layerEffect.Enabled,
|
||||
@ -215,11 +215,11 @@ namespace Artemis.Core
|
||||
foreach (LayerEffectEntity layerEffectEntity in RenderElementEntity.LayerEffects)
|
||||
{
|
||||
// If there is a non-placeholder existing effect, skip this entity
|
||||
BaseLayerEffect existing = _layerEffects.FirstOrDefault(e => e.EntityId == layerEffectEntity.Id);
|
||||
BaseLayerEffect? existing = _layerEffects.FirstOrDefault(e => e.EntityId == layerEffectEntity.Id);
|
||||
if (existing != null && existing.Descriptor.PlaceholderFor == null)
|
||||
continue;
|
||||
|
||||
LayerEffectDescriptor descriptor = LayerEffectStore.Get(layerEffectEntity.PluginGuid, layerEffectEntity.EffectType)?.LayerEffectDescriptor;
|
||||
LayerEffectDescriptor? descriptor = LayerEffectStore.Get(layerEffectEntity.ProviderId, layerEffectEntity.EffectType)?.LayerEffectDescriptor;
|
||||
if (descriptor != null)
|
||||
{
|
||||
// If a descriptor is found but there is an existing placeholder, remove the placeholder
|
||||
@ -235,7 +235,7 @@ namespace Artemis.Core
|
||||
else if (existing == null)
|
||||
{
|
||||
// If no descriptor was found and there was no existing placeholder, create a placeholder
|
||||
descriptor = PlaceholderLayerEffectDescriptor.Create(layerEffectEntity.PluginGuid);
|
||||
descriptor = PlaceholderLayerEffectDescriptor.Create(layerEffectEntity.ProviderId);
|
||||
descriptor.CreateInstance(this, layerEffectEntity);
|
||||
}
|
||||
}
|
||||
@ -253,22 +253,22 @@ namespace Artemis.Core
|
||||
private void LayerEffectStoreOnLayerEffectRemoved(object sender, LayerEffectStoreEvent e)
|
||||
{
|
||||
// If effects provided by the plugin are on the element, replace them with placeholders
|
||||
List<BaseLayerEffect> pluginEffects = _layerEffects.Where(ef => ef.Descriptor.LayerEffectProvider != null &&
|
||||
ef.PluginInfo.Guid == e.Registration.PluginImplementation.PluginInfo.Guid).ToList();
|
||||
List<BaseLayerEffect> pluginEffects = _layerEffects.Where(ef => ef.Descriptor.Provider != null &&
|
||||
ef.ProviderId == e.Registration.PluginFeature.Id).ToList();
|
||||
foreach (BaseLayerEffect pluginEffect in pluginEffects)
|
||||
{
|
||||
LayerEffectEntity entity = RenderElementEntity.LayerEffects.First(en => en.Id == pluginEffect.EntityId);
|
||||
_layerEffects.Remove(pluginEffect);
|
||||
pluginEffect.Dispose();
|
||||
|
||||
LayerEffectDescriptor descriptor = PlaceholderLayerEffectDescriptor.Create(pluginEffect.PluginInfo.Guid);
|
||||
LayerEffectDescriptor descriptor = PlaceholderLayerEffectDescriptor.Create(pluginEffect.ProviderId);
|
||||
descriptor.CreateInstance(this, entity);
|
||||
}
|
||||
}
|
||||
|
||||
private void LayerEffectStoreOnLayerEffectAdded(object sender, LayerEffectStoreEvent e)
|
||||
{
|
||||
if (RenderElementEntity.LayerEffects.Any(ef => ef.PluginGuid == e.Registration.PluginImplementation.PluginInfo.Guid))
|
||||
if (RenderElementEntity.LayerEffects.Any(ef => ef.ProviderId == e.Registration.PluginFeature.Id))
|
||||
ActivateEffects();
|
||||
}
|
||||
|
||||
|
||||
@ -3,14 +3,13 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a timeline used by profile elements
|
||||
/// </summary>
|
||||
public class Timeline : PropertyChangedBase, IStorageModel
|
||||
public class Timeline : CorePropertyChanged, IStorageModel
|
||||
{
|
||||
private const int MaxExtraTimelines = 15;
|
||||
|
||||
@ -275,20 +274,20 @@ namespace Artemis.Core
|
||||
if (segment <= TimelineSegment.End)
|
||||
{
|
||||
if (startUpdated || segment < TimelineSegment.End)
|
||||
NotifyOfPropertyChange(nameof(EndSegmentStartPosition));
|
||||
NotifyOfPropertyChange(nameof(EndSegmentEndPosition));
|
||||
OnPropertyChanged(nameof(EndSegmentStartPosition));
|
||||
OnPropertyChanged(nameof(EndSegmentEndPosition));
|
||||
}
|
||||
|
||||
if (segment <= TimelineSegment.Main)
|
||||
{
|
||||
if (startUpdated || segment < TimelineSegment.Main)
|
||||
NotifyOfPropertyChange(nameof(MainSegmentStartPosition));
|
||||
NotifyOfPropertyChange(nameof(MainSegmentEndPosition));
|
||||
OnPropertyChanged(nameof(MainSegmentStartPosition));
|
||||
OnPropertyChanged(nameof(MainSegmentEndPosition));
|
||||
}
|
||||
|
||||
if (segment <= TimelineSegment.Start) NotifyOfPropertyChange(nameof(StartSegmentEndPosition));
|
||||
if (segment <= TimelineSegment.Start) OnPropertyChanged(nameof(StartSegmentEndPosition));
|
||||
|
||||
NotifyOfPropertyChange(nameof(Length));
|
||||
OnPropertyChanged(nameof(Length));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -4,20 +4,19 @@ using System.Linq;
|
||||
using Artemis.Storage.Entities.Surface;
|
||||
using RGB.NET.Core;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class ArtemisDevice : PropertyChangedBase
|
||||
public class ArtemisDevice : CorePropertyChanged
|
||||
{
|
||||
private ReadOnlyCollection<ArtemisLed> _leds;
|
||||
private SKPath _renderPath;
|
||||
private SKRect _renderRectangle;
|
||||
|
||||
internal ArtemisDevice(IRGBDevice rgbDevice, PluginImplementation pluginImplementation, ArtemisSurface surface)
|
||||
internal ArtemisDevice(IRGBDevice rgbDevice, PluginFeature pluginFeature, ArtemisSurface surface)
|
||||
{
|
||||
RgbDevice = rgbDevice;
|
||||
PluginImplementation = pluginImplementation;
|
||||
PluginFeature = pluginFeature;
|
||||
Surface = surface;
|
||||
DeviceEntity = new DeviceEntity();
|
||||
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
||||
@ -30,10 +29,10 @@ namespace Artemis.Core
|
||||
CalculateRenderProperties();
|
||||
}
|
||||
|
||||
internal ArtemisDevice(IRGBDevice rgbDevice, PluginImplementation pluginImplementation, ArtemisSurface surface, DeviceEntity deviceEntity)
|
||||
internal ArtemisDevice(IRGBDevice rgbDevice, PluginFeature pluginFeature, ArtemisSurface surface, DeviceEntity deviceEntity)
|
||||
{
|
||||
RgbDevice = rgbDevice;
|
||||
PluginImplementation = pluginImplementation;
|
||||
PluginFeature = pluginFeature;
|
||||
Surface = surface;
|
||||
DeviceEntity = deviceEntity;
|
||||
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
||||
@ -52,7 +51,7 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
public IRGBDevice RgbDevice { get; }
|
||||
public PluginImplementation PluginImplementation { get; }
|
||||
public PluginFeature PluginFeature { get; }
|
||||
public ArtemisSurface Surface { get; }
|
||||
public DeviceEntity DeviceEntity { get; }
|
||||
|
||||
@ -68,7 +67,7 @@ namespace Artemis.Core
|
||||
set
|
||||
{
|
||||
DeviceEntity.X = value;
|
||||
NotifyOfPropertyChange(nameof(X));
|
||||
OnPropertyChanged(nameof(X));
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +77,7 @@ namespace Artemis.Core
|
||||
set
|
||||
{
|
||||
DeviceEntity.Y = value;
|
||||
NotifyOfPropertyChange(nameof(Y));
|
||||
OnPropertyChanged(nameof(Y));
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +87,7 @@ namespace Artemis.Core
|
||||
set
|
||||
{
|
||||
DeviceEntity.Rotation = value;
|
||||
NotifyOfPropertyChange(nameof(Rotation));
|
||||
OnPropertyChanged(nameof(Rotation));
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +97,7 @@ namespace Artemis.Core
|
||||
set
|
||||
{
|
||||
DeviceEntity.Scale = value;
|
||||
NotifyOfPropertyChange(nameof(Scale));
|
||||
OnPropertyChanged(nameof(Scale));
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +107,7 @@ namespace Artemis.Core
|
||||
set
|
||||
{
|
||||
DeviceEntity.ZIndex = value;
|
||||
NotifyOfPropertyChange(nameof(ZIndex));
|
||||
OnPropertyChanged(nameof(ZIndex));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
using RGB.NET.Core;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class ArtemisLed : PropertyChangedBase
|
||||
public class ArtemisLed : CorePropertyChanged
|
||||
{
|
||||
private SKRect _absoluteRenderRectangle;
|
||||
private SKRect _renderRectangle;
|
||||
|
||||
@ -3,11 +3,10 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Storage.Entities.Surface;
|
||||
using RGB.NET.Core;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class ArtemisSurface : PropertyChangedBase
|
||||
public class ArtemisSurface : CorePropertyChanged
|
||||
{
|
||||
private List<ArtemisDevice> _devices;
|
||||
private bool _isActive;
|
||||
|
||||
@ -6,6 +6,7 @@ using Ninject.Activation;
|
||||
|
||||
namespace Artemis.Core.Ninject
|
||||
{
|
||||
// TODO: Investigate if this can't just be set as a constant on the plugin child kernel
|
||||
internal class PluginSettingsProvider : Provider<PluginSettings>
|
||||
{
|
||||
private static readonly List<PluginSettings> PluginSettings = new List<PluginSettings>();
|
||||
@ -25,21 +26,22 @@ namespace Artemis.Core.Ninject
|
||||
throw new ArtemisCoreException("PluginSettings couldn't be injected, failed to get the injection parent request");
|
||||
|
||||
// First try by PluginInfo parameter
|
||||
PluginInfo pluginInfo = parentRequest.Parameters.FirstOrDefault(p => p.Name == "PluginInfo")?.GetValue(context, null) as PluginInfo;
|
||||
if (pluginInfo == null)
|
||||
pluginInfo = _pluginManagementService.GetPluginByAssembly(parentRequest.Service.Assembly)?.PluginInfo;
|
||||
Plugin? plugin = parentRequest.Parameters.FirstOrDefault(p => p.Name == "Plugin")?.GetValue(context, null) as Plugin;
|
||||
// Fall back to assembly based detection
|
||||
if (pluginInfo == null)
|
||||
if (plugin == null)
|
||||
plugin = _pluginManagementService.GetPluginByAssembly(parentRequest.Service.Assembly);
|
||||
|
||||
if (plugin == null)
|
||||
throw new ArtemisCoreException("PluginSettings can only be injected with the PluginInfo parameter provided " +
|
||||
"or into a class defined in a plugin assembly");
|
||||
|
||||
lock (PluginSettings)
|
||||
{
|
||||
PluginSettings? existingSettings = PluginSettings.FirstOrDefault(p => p.PluginInfo == pluginInfo);
|
||||
PluginSettings? existingSettings = PluginSettings.FirstOrDefault(p => p.Plugin == plugin);
|
||||
if (existingSettings != null)
|
||||
return existingSettings;
|
||||
|
||||
PluginSettings? settings = new PluginSettings(pluginInfo, _pluginRepository);
|
||||
PluginSettings? settings = new PluginSettings(plugin, _pluginRepository);
|
||||
PluginSettings.Add(settings);
|
||||
return settings;
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Core.Ninject
|
||||
protected override ISettingsService CreateInstance(IContext context)
|
||||
{
|
||||
IRequest parentRequest = context.Request.ParentRequest;
|
||||
if (parentRequest == null || typeof(PluginImplementation).IsAssignableFrom(parentRequest.Service))
|
||||
if (parentRequest == null || typeof(PluginFeature).IsAssignableFrom(parentRequest.Service))
|
||||
throw new ArtemisPluginException($"SettingsService can not be injected into a plugin. Inject {nameof(PluginSettings)} instead.");
|
||||
|
||||
return _instance;
|
||||
|
||||
@ -14,10 +14,10 @@ namespace Artemis.Core.DataModelExpansions
|
||||
private readonly Dictionary<string, DataModel> _dynamicDataModels = new Dictionary<string, DataModel>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin implementation this data model belongs to
|
||||
/// Gets the plugin feature this data model belongs to
|
||||
/// </summary>
|
||||
[DataModelIgnore]
|
||||
public DataModelPluginImplementation Implementation { get; internal set; }
|
||||
public DataModelPluginFeature Feature { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="DataModelPropertyAttribute" /> describing this data model
|
||||
@ -43,9 +43,9 @@ namespace Artemis.Core.DataModelExpansions
|
||||
/// <returns></returns>
|
||||
public ReadOnlyCollection<PropertyInfo> GetHiddenProperties()
|
||||
{
|
||||
if (Implementation is ProfileModule profileModule)
|
||||
if (Feature is ProfileModule profileModule)
|
||||
return profileModule.HiddenProperties;
|
||||
if (Implementation is BaseDataModelExpansion dataModelExpansion)
|
||||
if (Feature is BaseDataModelExpansion dataModelExpansion)
|
||||
return dataModelExpansion.HiddenProperties;
|
||||
|
||||
return new List<PropertyInfo>().AsReadOnly();
|
||||
@ -81,7 +81,7 @@ namespace Artemis.Core.DataModelExpansions
|
||||
throw new ArtemisCoreException($"Cannot add a dynamic data model with key '{key}' " +
|
||||
"because the key is already in use by a static property on this data model.");
|
||||
|
||||
dynamicDataModel.Implementation = Implementation;
|
||||
dynamicDataModel.Feature = Feature;
|
||||
dynamicDataModel.DataModelDescription = new DataModelPropertyAttribute
|
||||
{
|
||||
Name = string.IsNullOrWhiteSpace(name) ? key.Humanize() : name,
|
||||
|
||||
@ -45,7 +45,7 @@ namespace Artemis.Core.DataModelExpansions
|
||||
internal override void InternalEnable()
|
||||
{
|
||||
DataModel = Activator.CreateInstance<T>();
|
||||
DataModel.Implementation = PluginInfo;
|
||||
DataModel.Feature = this;
|
||||
DataModel.DataModelDescription = GetDataModelDescription();
|
||||
base.InternalEnable();
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ namespace Artemis.Core.DataModelExpansions
|
||||
/// For internal use only, to implement your own layer property type, extend <see cref="DataModelExpansion{T}" />
|
||||
/// instead.
|
||||
/// </summary>
|
||||
public abstract class BaseDataModelExpansion : DataModelPluginImplementation
|
||||
public abstract class BaseDataModelExpansion : DataModelPluginFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a list of all properties ignored at runtime using <c>IgnoreProperty(x => x.y)</c>
|
||||
@ -35,7 +35,7 @@ namespace Artemis.Core.DataModelExpansions
|
||||
/// <returns></returns>
|
||||
public virtual DataModelPropertyAttribute GetDataModelDescription()
|
||||
{
|
||||
return new DataModelPropertyAttribute {Name = PluginInfo.Name, Description = PluginInfo.Description};
|
||||
return new DataModelPropertyAttribute {Name = Plugin.Info.Name, Description = Plugin.Info.Description};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,9 +4,9 @@ using System.Threading.Tasks;
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an implementation of a certain type provided by a plugin with support for data models
|
||||
/// Represents an feature of a certain type provided by a plugin with support for data models
|
||||
/// </summary>
|
||||
public abstract class DataModelPluginImplementation : PluginImplementation
|
||||
public abstract class DataModelPluginFeature : PluginFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers a timed update that whenever the plugin is enabled calls the provided <paramref name="action" /> at the
|
||||
@ -23,11 +23,11 @@ namespace Artemis.Core
|
||||
{
|
||||
if (action == null)
|
||||
throw new ArgumentNullException(nameof(action));
|
||||
return new TimedUpdateRegistration(PluginInfo, interval, action);
|
||||
return new TimedUpdateRegistration(this, interval, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a timed update that whenever the plugin is enabled calls the provided <paramref name="action" /> at the
|
||||
/// Registers a timed update that whenever the plugin is enabled calls the provided <paramref name="asyncAction" /> at the
|
||||
/// provided
|
||||
/// <paramref name="interval" />
|
||||
/// </summary>
|
||||
@ -41,7 +41,7 @@ namespace Artemis.Core
|
||||
{
|
||||
if (asyncAction == null)
|
||||
throw new ArgumentNullException(nameof(asyncAction));
|
||||
return new TimedUpdateRegistration(PluginInfo, interval, asyncAction);
|
||||
return new TimedUpdateRegistration(this, interval, asyncAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@ namespace Artemis.Core.DeviceProviders
|
||||
/// <summary>
|
||||
/// Allows you to implement and register your own device provider
|
||||
/// </summary>
|
||||
public abstract class DeviceProvider : PluginImplementation
|
||||
public abstract class DeviceProvider : PluginFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DeviceProvider" /> class
|
||||
@ -50,9 +50,9 @@ namespace Artemis.Core.DeviceProviders
|
||||
{
|
||||
// Start from the plugin directory
|
||||
if (e.RelativePart != null && e.FileName != null)
|
||||
e.FinalPath = Path.Combine(PluginInfo.Directory.FullName, e.RelativePart, e.FileName);
|
||||
e.FinalPath = Path.Combine(Plugin.Directory.FullName, e.RelativePart, e.FileName);
|
||||
else if (e.RelativePath != null)
|
||||
e.FinalPath = Path.Combine(PluginInfo.Directory.FullName, e.RelativePath);
|
||||
e.FinalPath = Path.Combine(Plugin.Directory.FullName, e.RelativePath);
|
||||
|
||||
IRGBDeviceInfo deviceInfo = ((IRGBDevice) sender).DeviceInfo;
|
||||
if (e.FileName != null && !File.Exists(e.FinalPath))
|
||||
|
||||
20
src/Artemis.Core/Plugins/IPluginBootstrapper.cs
Normal file
20
src/Artemis.Core/Plugins/IPluginBootstrapper.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// An optional entry point for your plugin
|
||||
/// </summary>
|
||||
public interface IPluginBootstrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when the plugin is activated
|
||||
/// </summary>
|
||||
/// <param name="plugin">The plugin instance of your plugin</param>
|
||||
void Enable(Plugin plugin);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the plugin is deactivated or when Artemis shuts down
|
||||
/// </summary>
|
||||
/// <param name="plugin">The plugin instance of your plugin</param>
|
||||
void Disable(Plugin plugin);
|
||||
}
|
||||
}
|
||||
7
src/Artemis.Core/Plugins/IPluginConfigurationDialog.cs
Normal file
7
src/Artemis.Core/Plugins/IPluginConfigurationDialog.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public interface IPluginConfigurationDialog
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
10
src/Artemis.Core/Plugins/IPluginConfigurationViewModel.cs
Normal file
10
src/Artemis.Core/Plugins/IPluginConfigurationViewModel.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a view model for a plugin configuration window
|
||||
/// </summary>
|
||||
public interface IPluginConfigurationViewModel
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Artemis.Core.LayerBrushes
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the configuration dialog of a layer brush
|
||||
/// </summary>
|
||||
public interface ILayerBrushConfigurationDialog
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,15 @@
|
||||
using System;
|
||||
using Artemis.Core.Services;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core.LayerBrushes
|
||||
{
|
||||
/// <summary>
|
||||
/// For internal use only, please use <see cref="LayerBrush{T}" /> or <see cref="RgbNetLayerBrush{T}" /> or instead
|
||||
/// </summary>
|
||||
public abstract class BaseLayerBrush : PropertyChangedBase, IDisposable
|
||||
public abstract class BaseLayerBrush : CorePropertyChanged, IDisposable
|
||||
{
|
||||
private LayerBrushType _brushType;
|
||||
private LayerBrushConfigurationDialog _configurationDialog;
|
||||
private ILayerBrushConfigurationDialog _configurationDialog;
|
||||
private LayerBrushDescriptor _descriptor;
|
||||
private Layer _layer;
|
||||
private bool _supportsTransformation = true;
|
||||
@ -37,7 +35,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
/// <summary>
|
||||
/// Gets or sets a configuration dialog complementing the regular properties
|
||||
/// </summary>
|
||||
public LayerBrushConfigurationDialog ConfigurationDialog
|
||||
public ILayerBrushConfigurationDialog ConfigurationDialog
|
||||
{
|
||||
get => _configurationDialog;
|
||||
protected set => SetAndNotify(ref _configurationDialog, value);
|
||||
@ -53,9 +51,9 @@ namespace Artemis.Core.LayerBrushes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin info that defined this brush
|
||||
/// Gets the ID of the <see cref="LayerBrushProvider" /> that provided this effect
|
||||
/// </summary>
|
||||
public PluginInfo PluginInfo => Descriptor.LayerBrushProvider.PluginInfo;
|
||||
public string ProviderId => Descriptor?.Provider?.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reference to the layer property group without knowing it's type
|
||||
@ -72,21 +70,11 @@ namespace Artemis.Core.LayerBrushes
|
||||
protected set
|
||||
{
|
||||
if (value && BrushType == LayerBrushType.RgbNet)
|
||||
throw new ArtemisPluginException(PluginInfo, "An RGB.NET brush cannot support transformation");
|
||||
throw new ArtemisPluginFeatureException(Descriptor.Provider, "An RGB.NET brush cannot support transformation");
|
||||
_supportsTransformation = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
DisableLayerBrush();
|
||||
BaseProperties.Dispose();
|
||||
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the layer brush is activated
|
||||
/// </summary>
|
||||
@ -112,6 +100,16 @@ namespace Artemis.Core.LayerBrushes
|
||||
internal virtual void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
DisableLayerBrush();
|
||||
BaseProperties.Dispose();
|
||||
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -37,7 +37,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
Properties = Activator.CreateInstance<T>();
|
||||
Properties.GroupDescription ??= new PropertyGroupDescriptionAttribute {Name = Descriptor.DisplayName, Description = Descriptor.Description};
|
||||
Properties.LayerBrush = this;
|
||||
Properties.Initialize(Layer, "LayerBrush.", PluginInfo);
|
||||
Properties.Initialize(Layer, "LayerBrush.", Descriptor.Provider);
|
||||
PropertiesInitialized = true;
|
||||
|
||||
EnableLayerBrush();
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Artemis.Core.Services;
|
||||
using Ninject;
|
||||
|
||||
namespace Artemis.Core.LayerBrushes
|
||||
@ -9,13 +8,13 @@ namespace Artemis.Core.LayerBrushes
|
||||
/// </summary>
|
||||
public class LayerBrushDescriptor
|
||||
{
|
||||
internal LayerBrushDescriptor(string displayName, string description, string icon, Type layerBrushType, LayerBrushProvider layerBrushProvider)
|
||||
internal LayerBrushDescriptor(string displayName, string description, string icon, Type layerBrushType, LayerBrushProvider provider)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
Description = description;
|
||||
Icon = icon;
|
||||
LayerBrushType = layerBrushType;
|
||||
LayerBrushProvider = layerBrushProvider;
|
||||
Provider = provider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -42,7 +41,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
/// <summary>
|
||||
/// The plugin that provided this <see cref="LayerBrushDescriptor" />
|
||||
/// </summary>
|
||||
public LayerBrushProvider LayerBrushProvider { get; }
|
||||
public LayerBrushProvider Provider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the provided <paramref name="reference" /> references to a brush provided by this descriptor
|
||||
@ -51,7 +50,8 @@ namespace Artemis.Core.LayerBrushes
|
||||
{
|
||||
if (reference == null)
|
||||
return false;
|
||||
return LayerBrushProvider.PluginInfo.Guid == reference.BrushPluginGuid && LayerBrushType.Name == reference.BrushType;
|
||||
|
||||
return Provider.Id == reference.LayerBrushProviderId && LayerBrushType.Name == reference.BrushType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -62,7 +62,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
if (layer.LayerBrush != null)
|
||||
throw new ArtemisCoreException("Layer already has an instantiated layer brush");
|
||||
|
||||
BaseLayerBrush brush = (BaseLayerBrush) LayerBrushProvider.PluginInfo.Kernel.Get(LayerBrushType);
|
||||
BaseLayerBrush brush = (BaseLayerBrush) Provider.Plugin.Kernel!.Get(LayerBrushType);
|
||||
brush.Layer = layer;
|
||||
brush.Descriptor = this;
|
||||
brush.Initialize();
|
||||
|
||||
@ -7,7 +7,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
/// <summary>
|
||||
/// Allows you to create one or more <see cref="LayerBrush{T}" />s usable by profile layers.
|
||||
/// </summary>
|
||||
public abstract class LayerBrushProvider : PluginImplementation
|
||||
public abstract class LayerBrushProvider : PluginFeature
|
||||
{
|
||||
private readonly List<LayerBrushDescriptor> _layerBrushDescriptors;
|
||||
|
||||
@ -39,7 +39,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
protected void RegisterLayerBrushDescriptor<T>(string displayName, string description, string icon) where T : BaseLayerBrush
|
||||
{
|
||||
if (!IsEnabled)
|
||||
throw new ArtemisPluginException(PluginInfo, "Can only add a layer brush descriptor when the plugin is enabled");
|
||||
throw new ArtemisPluginException(Plugin, "Can only add a layer brush descriptor when the plugin is enabled");
|
||||
|
||||
LayerBrushDescriptor descriptor = new LayerBrushDescriptor(displayName, description, icon, typeof(T), this);
|
||||
_layerBrushDescriptors.Add(descriptor);
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
namespace Artemis.Core.LayerEffects
|
||||
{
|
||||
public interface IEffectConfigurationViewModel
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
namespace Artemis.Core.LayerEffects
|
||||
{
|
||||
public interface ILayerEffectConfigurationDialog
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -1,16 +1,15 @@
|
||||
using System;
|
||||
using Artemis.Core.Services;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core.LayerEffects
|
||||
{
|
||||
/// <summary>
|
||||
/// For internal use only, please use <see cref="LayerEffect{T}" /> instead
|
||||
/// </summary>
|
||||
public abstract class BaseLayerEffect : PropertyChangedBase, IDisposable
|
||||
public abstract class BaseLayerEffect : CorePropertyChanged, IDisposable
|
||||
{
|
||||
private LayerEffectConfigurationDialog _configurationDialog;
|
||||
private ILayerEffectConfigurationDialog _configurationDialog;
|
||||
private LayerEffectDescriptor _descriptor;
|
||||
private bool _enabled;
|
||||
private Guid _entityId;
|
||||
@ -77,7 +76,7 @@ namespace Artemis.Core.LayerEffects
|
||||
/// <summary>
|
||||
/// Gets the <see cref="LayerEffectDescriptor" /> that registered this effect
|
||||
/// </summary>
|
||||
public LayerEffectDescriptor Descriptor
|
||||
public LayerEffectDescriptor? Descriptor
|
||||
{
|
||||
get => _descriptor;
|
||||
internal set => SetAndNotify(ref _descriptor, value);
|
||||
@ -86,16 +85,16 @@ namespace Artemis.Core.LayerEffects
|
||||
/// <summary>
|
||||
/// Gets or sets a configuration dialog complementing the regular properties
|
||||
/// </summary>
|
||||
public LayerEffectConfigurationDialog ConfigurationDialog
|
||||
public ILayerEffectConfigurationDialog ConfigurationDialog
|
||||
{
|
||||
get => _configurationDialog;
|
||||
protected set => SetAndNotify(ref _configurationDialog, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin info that defined this effect
|
||||
/// Gets the ID of the <see cref="LayerEffectProvider"/> that provided this effect
|
||||
/// </summary>
|
||||
public PluginInfo PluginInfo => Descriptor.LayerEffectProvider?.PluginInfo;
|
||||
public string ProviderId => Descriptor?.Provider?.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reference to the layer property group without knowing it's type
|
||||
|
||||
@ -37,7 +37,7 @@ namespace Artemis.Core.LayerEffects
|
||||
{
|
||||
Properties = Activator.CreateInstance<T>();
|
||||
Properties.LayerEffect = this;
|
||||
Properties.Initialize(ProfileElement, PropertyRootPath, PluginInfo);
|
||||
Properties.Initialize(ProfileElement, PropertyRootPath, Descriptor.Provider);
|
||||
PropertiesInitialized = true;
|
||||
|
||||
EnableLayerEffect();
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Artemis.Core.LayerEffects.Placeholder;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Ninject;
|
||||
|
||||
@ -12,13 +11,13 @@ namespace Artemis.Core.LayerEffects
|
||||
/// </summary>
|
||||
public class LayerEffectDescriptor
|
||||
{
|
||||
internal LayerEffectDescriptor(string displayName, string description, string icon, Type layerEffectType, LayerEffectProvider layerEffectProvider)
|
||||
internal LayerEffectDescriptor(string displayName, string description, string icon, Type layerEffectType, LayerEffectProvider provider)
|
||||
{
|
||||
DisplayName = displayName;
|
||||
Description = description;
|
||||
Icon = icon;
|
||||
LayerEffectType = layerEffectType;
|
||||
LayerEffectProvider = layerEffectProvider;
|
||||
Provider = provider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -45,12 +44,12 @@ namespace Artemis.Core.LayerEffects
|
||||
/// <summary>
|
||||
/// The plugin that provided this <see cref="LayerEffectDescriptor" />
|
||||
/// </summary>
|
||||
public LayerEffectProvider LayerEffectProvider { get; }
|
||||
public LayerEffectProvider? Provider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GUID this descriptor is acting as a placeholder for. If null, this descriptor is not a placeholder
|
||||
/// </summary>
|
||||
public Guid? PlaceholderFor { get; internal set; }
|
||||
public string? PlaceholderFor { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of the described effect and applies it to the render element
|
||||
@ -67,7 +66,10 @@ namespace Artemis.Core.LayerEffects
|
||||
return;
|
||||
}
|
||||
|
||||
BaseLayerEffect effect = (BaseLayerEffect) LayerEffectProvider.PluginInfo.Kernel.Get(LayerEffectType);
|
||||
if (Provider == null)
|
||||
throw new ArtemisCoreException("Cannot create an instance of a layer effect because this descriptor is not a placeholder but is still missing its provider");
|
||||
|
||||
BaseLayerEffect effect = (BaseLayerEffect) Provider.Plugin.Kernel!.Get(LayerEffectType);
|
||||
effect.ProfileElement = renderElement;
|
||||
effect.EntityId = entity.Id;
|
||||
effect.Order = entity.Order;
|
||||
@ -83,7 +85,7 @@ namespace Artemis.Core.LayerEffects
|
||||
|
||||
private void CreatePlaceHolderInstance(RenderProfileElement renderElement, LayerEffectEntity entity)
|
||||
{
|
||||
PlaceholderLayerEffect effect = new PlaceholderLayerEffect(entity, PlaceholderFor.Value) {ProfileElement = renderElement, Descriptor = this};
|
||||
PlaceholderLayerEffect effect = new PlaceholderLayerEffect(entity, PlaceholderFor) {ProfileElement = renderElement, Descriptor = this};
|
||||
effect.Initialize();
|
||||
renderElement.ActivateLayerEffect(effect);
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ namespace Artemis.Core.LayerEffects
|
||||
/// <summary>
|
||||
/// Allows you to register one or more <see cref="LayerEffect{T}" />s usable by profile layers.
|
||||
/// </summary>
|
||||
public abstract class LayerEffectProvider : PluginImplementation
|
||||
public abstract class LayerEffectProvider : PluginFeature
|
||||
{
|
||||
private readonly List<LayerEffectDescriptor> _layerEffectDescriptors;
|
||||
|
||||
@ -39,7 +39,7 @@ namespace Artemis.Core.LayerEffects
|
||||
protected void RegisterLayerEffectDescriptor<T>(string displayName, string description, string icon) where T : BaseLayerEffect
|
||||
{
|
||||
if (!IsEnabled)
|
||||
throw new ArtemisPluginException(PluginInfo, "Can only add a layer effect descriptor when the plugin is enabled");
|
||||
throw new ArtemisPluginFeatureException(this, "Can only add a layer effect descriptor when the plugin is enabled");
|
||||
|
||||
LayerEffectDescriptor descriptor = new LayerEffectDescriptor(displayName, description, icon, typeof(T), this);
|
||||
_layerEffectDescriptors.Add(descriptor);
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.Core.LayerEffects.Placeholder
|
||||
@ -9,7 +8,7 @@ namespace Artemis.Core.LayerEffects.Placeholder
|
||||
/// </summary>
|
||||
internal class PlaceholderLayerEffect : LayerEffect<PlaceholderProperties>
|
||||
{
|
||||
internal PlaceholderLayerEffect(LayerEffectEntity originalEntity, Guid placeholderFor)
|
||||
internal PlaceholderLayerEffect(LayerEffectEntity originalEntity, string placeholderFor)
|
||||
{
|
||||
OriginalEntity = originalEntity;
|
||||
PlaceholderFor = placeholderFor;
|
||||
@ -21,8 +20,9 @@ namespace Artemis.Core.LayerEffects.Placeholder
|
||||
HasBeenRenamed = OriginalEntity.HasBeenRenamed;
|
||||
}
|
||||
|
||||
public string PlaceholderFor { get; }
|
||||
|
||||
internal LayerEffectEntity OriginalEntity { get; }
|
||||
public Guid PlaceholderFor { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void EnableLayerEffect()
|
||||
@ -56,7 +56,7 @@ namespace Artemis.Core.LayerEffects.Placeholder
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is in place so that the UI has something to show
|
||||
/// This is in place so that the UI has something to show
|
||||
/// </summary>
|
||||
internal class PlaceholderProperties : LayerPropertyGroup
|
||||
{
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core.LayerEffects.Placeholder
|
||||
namespace Artemis.Core.LayerEffects.Placeholder
|
||||
{
|
||||
internal static class PlaceholderLayerEffectDescriptor
|
||||
{
|
||||
public static LayerEffectDescriptor Create(Guid missingPluginGuid)
|
||||
public static LayerEffectDescriptor Create(string missingProviderId)
|
||||
{
|
||||
LayerEffectDescriptor descriptor = new LayerEffectDescriptor("Missing effect", "This effect could not be loaded", "FileQuestion", null, Constants.EffectPlaceholderPlugin)
|
||||
{
|
||||
PlaceholderFor = missingPluginGuid
|
||||
PlaceholderFor = missingProviderId
|
||||
};
|
||||
|
||||
return descriptor;
|
||||
|
||||
10
src/Artemis.Core/Plugins/Modules/IModuleViewModel.cs
Normal file
10
src/Artemis.Core/Plugins/Modules/IModuleViewModel.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Artemis.Core.Modules
|
||||
{
|
||||
/// <summary>
|
||||
/// The base class for any view model that belongs to a module
|
||||
/// </summary>
|
||||
public interface IModuleViewModel
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -42,13 +42,13 @@ namespace Artemis.Core.Modules
|
||||
/// <returns></returns>
|
||||
public virtual DataModelPropertyAttribute GetDataModelDescription()
|
||||
{
|
||||
return new DataModelPropertyAttribute {Name = PluginInfo.Name, Description = PluginInfo.Description};
|
||||
return new DataModelPropertyAttribute {Name = Plugin.Info.Name, Description = Plugin.Info.Description};
|
||||
}
|
||||
|
||||
internal override void InternalEnable()
|
||||
{
|
||||
DataModel = Activator.CreateInstance<T>();
|
||||
DataModel.Implementation = PluginInfo;
|
||||
DataModel.Feature = this;
|
||||
DataModel.DataModelDescription = GetDataModelDescription();
|
||||
base.InternalEnable();
|
||||
}
|
||||
@ -64,7 +64,7 @@ namespace Artemis.Core.Modules
|
||||
/// <summary>
|
||||
/// Allows you to add support for new games/applications
|
||||
/// </summary>
|
||||
public abstract class Module : DataModelPluginImplementation
|
||||
public abstract class Module : DataModelPluginFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The modules display name that's shown in the menu
|
||||
@ -236,7 +236,7 @@ namespace Artemis.Core.Modules
|
||||
if (Entity == null)
|
||||
Entity = new ModuleSettingsEntity();
|
||||
|
||||
Entity.PluginGuid = PluginInfo.Guid;
|
||||
Entity.ModuleId = Id;
|
||||
Entity.PriorityCategory = (int) PriorityCategory;
|
||||
Entity.Priority = Priority;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
namespace Artemis.Core.Modules
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class ModuleTab<T> : ModuleTab where T : ModuleViewModel
|
||||
public class ModuleTab<T> : ModuleTab where T : IModuleViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModuleTab{T}" /> class
|
||||
|
||||
@ -46,7 +46,7 @@ namespace Artemis.Core.Modules
|
||||
/// <returns></returns>
|
||||
public virtual DataModelPropertyAttribute GetDataModelDescription()
|
||||
{
|
||||
return new DataModelPropertyAttribute {Name = PluginInfo.Name, Description = PluginInfo.Description};
|
||||
return new DataModelPropertyAttribute {Name = Plugin.Info.Name, Description = Plugin.Info.Description};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -74,7 +74,7 @@ namespace Artemis.Core.Modules
|
||||
internal override void InternalEnable()
|
||||
{
|
||||
DataModel = Activator.CreateInstance<T>();
|
||||
DataModel.Implementation = PluginInfo;
|
||||
DataModel.Feature = this;
|
||||
DataModel.DataModelDescription = GetDataModelDescription();
|
||||
base.InternalEnable();
|
||||
}
|
||||
@ -184,7 +184,7 @@ namespace Artemis.Core.Modules
|
||||
internal async Task ChangeActiveProfileAnimated(Profile profile, ArtemisSurface surface)
|
||||
{
|
||||
if (profile != null && profile.Module != this)
|
||||
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {PluginInfo}.");
|
||||
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {this}.");
|
||||
if (!IsActivated)
|
||||
throw new ArtemisCoreException("Cannot activate a profile on a deactivated module");
|
||||
|
||||
@ -206,7 +206,7 @@ namespace Artemis.Core.Modules
|
||||
internal void ChangeActiveProfile(Profile profile, ArtemisSurface surface)
|
||||
{
|
||||
if (profile != null && profile.Module != this)
|
||||
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {PluginInfo}.");
|
||||
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {this}.");
|
||||
if (!IsActivated)
|
||||
throw new ArtemisCoreException("Cannot activate a profile on a deactivated module");
|
||||
|
||||
|
||||
@ -7,16 +7,15 @@ using System.Reflection;
|
||||
using Artemis.Storage.Entities.Plugins;
|
||||
using McMaster.NETCore.Plugins;
|
||||
using Ninject;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a plugin
|
||||
/// </summary>
|
||||
public class Plugin : PropertyChangedBase, IDisposable
|
||||
public class Plugin : CorePropertyChanged, IDisposable
|
||||
{
|
||||
private readonly List<PluginImplementation> _implementations;
|
||||
private readonly List<PluginFeature> _features;
|
||||
|
||||
private bool _isEnabled;
|
||||
|
||||
@ -25,7 +24,7 @@ namespace Artemis.Core
|
||||
Info = info;
|
||||
Directory = directory;
|
||||
|
||||
_implementations = new List<PluginImplementation>();
|
||||
_features = new List<PluginFeature>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -46,8 +45,8 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets or sets a configuration dialog for this plugin that is accessible in the UI under Settings > Plugins
|
||||
/// </summary>
|
||||
public PluginConfigurationDialog? ConfigurationDialog { get; protected set; }
|
||||
|
||||
public IPluginConfigurationDialog? ConfigurationDialog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the user enabled the plugin or not
|
||||
/// </summary>
|
||||
@ -58,19 +57,24 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read-only collection of all implementations this plugin provides
|
||||
/// Gets a read-only collection of all features this plugin provides
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<PluginImplementation> Implementations => _implementations.AsReadOnly();
|
||||
public ReadOnlyCollection<PluginFeature> Features => _features.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// The assembly the plugin code lives in
|
||||
/// </summary>
|
||||
internal Assembly? Assembly { get; set; }
|
||||
public Assembly? Assembly { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin bootstrapper
|
||||
/// </summary>
|
||||
public IPluginBootstrapper? Bootstrapper { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Ninject kernel of the plugin
|
||||
/// </summary>
|
||||
internal IKernel? Kernel { get; set; }
|
||||
public IKernel? Kernel { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The PluginLoader backing this plugin
|
||||
@ -80,7 +84,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// The entity representing the plugin
|
||||
/// </summary>
|
||||
internal PluginEntity? Entity { get; set; }
|
||||
internal PluginEntity Entity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the relative path provided in the <paramref name="path" /> parameter to an absolute path
|
||||
@ -92,25 +96,15 @@ namespace Artemis.Core
|
||||
return path == null ? null : Path.Combine(Directory.FullName, path);
|
||||
}
|
||||
|
||||
internal void ApplyToEntity()
|
||||
/// <summary>
|
||||
/// Looks up the instance of the feature of type <typeparamref name="T" />
|
||||
/// <para>Note: This method only returns instances of enabled features</para>
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of feature to find</typeparam>
|
||||
/// <returns>If found, the instance of the feature</returns>
|
||||
public T? GetFeature<T>() where T : PluginFeature
|
||||
{
|
||||
Entity.Id = Guid;
|
||||
Entity.IsEnabled = IsEnabled;
|
||||
}
|
||||
|
||||
internal void AddImplementation(PluginImplementation implementation)
|
||||
{
|
||||
implementation.Plugin = this;
|
||||
_implementations.Add(implementation);
|
||||
}
|
||||
|
||||
public void SetEnabled(bool enable)
|
||||
{
|
||||
if (IsEnabled == enable)
|
||||
return;
|
||||
|
||||
if (!enable && Implementations.Any(e => e.IsEnabled))
|
||||
throw new ArtemisCoreException("Cannot disable this plugin because it still has enabled implementations");
|
||||
return _features.FirstOrDefault(i => i is T) as T;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -119,13 +113,118 @@ namespace Artemis.Core
|
||||
return Info.ToString();
|
||||
}
|
||||
|
||||
internal void ApplyToEntity()
|
||||
{
|
||||
Entity.Id = Guid;
|
||||
Entity.IsEnabled = IsEnabled;
|
||||
}
|
||||
|
||||
internal void AddFeature(PluginFeature feature)
|
||||
{
|
||||
feature.Plugin = this;
|
||||
_features.Add(feature);
|
||||
|
||||
OnFeatureAdded(new PluginFeatureEventArgs(feature));
|
||||
}
|
||||
|
||||
internal void RemoveFeature(PluginFeature feature)
|
||||
{
|
||||
_features.Remove(feature);
|
||||
feature.InternalDisable();
|
||||
feature.Dispose();
|
||||
|
||||
OnFeatureRemoved(new PluginFeatureEventArgs(feature));
|
||||
}
|
||||
|
||||
|
||||
internal void SetEnabled(bool enable)
|
||||
{
|
||||
if (IsEnabled == enable)
|
||||
return;
|
||||
|
||||
if (!enable && Features.Any(e => e.IsEnabled))
|
||||
throw new ArtemisCoreException("Cannot disable this plugin because it still has enabled features");
|
||||
|
||||
IsEnabled = enable;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
Bootstrapper?.Enable(this);
|
||||
OnEnabled();
|
||||
}
|
||||
else
|
||||
{
|
||||
Bootstrapper?.Disable(this);
|
||||
OnDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (PluginImplementation pluginImplementation in Implementations)
|
||||
pluginImplementation.Dispose();
|
||||
foreach (PluginFeature feature in Features)
|
||||
feature.Dispose();
|
||||
|
||||
Kernel?.Dispose();
|
||||
PluginLoader?.Dispose();
|
||||
|
||||
_features.Clear();
|
||||
SetEnabled(false);
|
||||
}
|
||||
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the plugin is enabled
|
||||
/// </summary>
|
||||
public event EventHandler? Enabled;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the plugin is disabled
|
||||
/// </summary>
|
||||
public event EventHandler? Disabled;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when an feature is loaded and added to the plugin
|
||||
/// </summary>
|
||||
public event EventHandler<PluginFeatureEventArgs>? FeatureAdded;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when an feature is disabled and removed from the plugin
|
||||
/// </summary>
|
||||
public event EventHandler<PluginFeatureEventArgs>? FeatureRemoved;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the Enabled event
|
||||
/// </summary>
|
||||
protected virtual void OnEnabled()
|
||||
{
|
||||
Enabled?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the Disabled event
|
||||
/// </summary>
|
||||
protected virtual void OnDisabled()
|
||||
{
|
||||
Disabled?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the FeatureAdded event
|
||||
/// </summary>
|
||||
protected virtual void OnFeatureAdded(PluginFeatureEventArgs e)
|
||||
{
|
||||
FeatureAdded?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the FeatureRemoved event
|
||||
/// </summary>
|
||||
protected virtual void OnFeatureRemoved(PluginFeatureEventArgs e)
|
||||
{
|
||||
FeatureRemoved?.Invoke(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,22 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Storage.Entities.Plugins;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an implementation of a certain type provided by a plugin
|
||||
/// Represents an feature of a certain type provided by a plugin
|
||||
/// </summary>
|
||||
public abstract class PluginImplementation : PropertyChangedBase, IDisposable
|
||||
public abstract class PluginFeature : CorePropertyChanged, IDisposable
|
||||
{
|
||||
private Exception? _loadException;
|
||||
private bool _isEnabled;
|
||||
private Exception? _loadException;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin that provides this implementation
|
||||
/// Gets the plugin that provides this feature
|
||||
/// </summary>
|
||||
public Plugin? Plugin { get; internal set; }
|
||||
public Plugin Plugin { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the plugin is enabled
|
||||
@ -38,15 +36,20 @@ namespace Artemis.Core
|
||||
internal set => SetAndNotify(ref _loadException, value);
|
||||
}
|
||||
|
||||
internal PluginImplementationEntity? Entity { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the identifier of this plugin feature
|
||||
/// </summary>
|
||||
public string Id => $"{GetType().FullName}-{Plugin.Guid.ToString().Substring(0, 8)}"; // Not as unique as a GUID but good enough and stays readable
|
||||
|
||||
internal PluginFeatureEntity Entity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the implementation is activated
|
||||
/// Called when the feature is activated
|
||||
/// </summary>
|
||||
public abstract void Enable();
|
||||
|
||||
/// <summary>
|
||||
/// Called when the implementation is deactivated or when Artemis shuts down
|
||||
/// Called when the feature is deactivated or when Artemis shuts down
|
||||
/// </summary>
|
||||
public abstract void Disable();
|
||||
|
||||
@ -56,12 +59,12 @@ namespace Artemis.Core
|
||||
return;
|
||||
|
||||
if (Plugin == null)
|
||||
throw new ArtemisCoreException("Cannot enable a plugin implementation that is not associated with a plugin");
|
||||
throw new ArtemisCoreException("Cannot enable a plugin feature that is not associated with a plugin");
|
||||
|
||||
lock (Plugin)
|
||||
{
|
||||
if (!Plugin.IsEnabled)
|
||||
throw new ArtemisCoreException("Cannot enable a plugin implementation of a disabled plugin");
|
||||
throw new ArtemisCoreException("Cannot enable a plugin feature of a disabled plugin");
|
||||
|
||||
if (!enable)
|
||||
{
|
||||
@ -72,7 +75,7 @@ namespace Artemis.Core
|
||||
OnDisabled();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
if (isAutoEnable && GetLockFileCreated())
|
||||
@ -89,19 +92,10 @@ namespace Artemis.Core
|
||||
|
||||
// Allow up to 15 seconds for plugins to activate.
|
||||
// This means plugins that need more time should do their long running tasks in a background thread, which is intentional
|
||||
ManualResetEvent wait = new ManualResetEvent(false);
|
||||
Thread work = new Thread(() =>
|
||||
{
|
||||
InternalEnable();
|
||||
wait.Set();
|
||||
});
|
||||
work.Start();
|
||||
wait.WaitOne(TimeSpan.FromSeconds(15));
|
||||
if (work.IsAlive)
|
||||
{
|
||||
work.Abort();
|
||||
// This would've been a perfect match for Thread.Abort but that didn't make it into .NET Core
|
||||
Task enableTask = Task.Run(InternalEnable);
|
||||
if (!enableTask.Wait(TimeSpan.FromSeconds(15)))
|
||||
throw new ArtemisPluginException(Plugin, "Plugin load timeout");
|
||||
}
|
||||
|
||||
LoadException = null;
|
||||
OnEnabled();
|
||||
@ -144,7 +138,7 @@ namespace Artemis.Core
|
||||
internal void CreateLockFile()
|
||||
{
|
||||
if (Plugin == null)
|
||||
throw new ArtemisCoreException("Cannot lock a plugin implementation that is not associated with a plugin");
|
||||
throw new ArtemisCoreException("Cannot lock a plugin feature that is not associated with a plugin");
|
||||
|
||||
File.Create(Plugin.ResolveRelativePath($"{GetType().FullName}.lock")).Close();
|
||||
}
|
||||
@ -152,7 +146,7 @@ namespace Artemis.Core
|
||||
internal void DeleteLockFile()
|
||||
{
|
||||
if (Plugin == null)
|
||||
throw new ArtemisCoreException("Cannot lock a plugin implementation that is not associated with a plugin");
|
||||
throw new ArtemisCoreException("Cannot lock a plugin feature that is not associated with a plugin");
|
||||
|
||||
if (GetLockFileCreated())
|
||||
File.Delete(Plugin.ResolveRelativePath($"{GetType().FullName}.lock"));
|
||||
@ -161,7 +155,7 @@ namespace Artemis.Core
|
||||
internal bool GetLockFileCreated()
|
||||
{
|
||||
if (Plugin == null)
|
||||
throw new ArtemisCoreException("Cannot lock a plugin implementation that is not associated with a plugin");
|
||||
throw new ArtemisCoreException("Cannot lock a plugin feature that is not associated with a plugin");
|
||||
|
||||
return File.Exists(Plugin.ResolveRelativePath($"{GetType().FullName}.lock"));
|
||||
}
|
||||
@ -171,17 +165,17 @@ namespace Artemis.Core
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the implementation is enabled
|
||||
/// Occurs when the feature is enabled
|
||||
/// </summary>
|
||||
public event EventHandler? Enabled;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the implementation is disabled
|
||||
/// Occurs when the feature is disabled
|
||||
/// </summary>
|
||||
public event EventHandler? Disabled;
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the PluginEnabled event
|
||||
/// Triggers the Enabled event
|
||||
/// </summary>
|
||||
protected virtual void OnEnabled()
|
||||
{
|
||||
@ -189,7 +183,7 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the PluginDisabled event
|
||||
/// Triggers the Disabled event
|
||||
/// </summary>
|
||||
protected virtual void OnDisabled()
|
||||
{
|
||||
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
@ -8,7 +7,7 @@ namespace Artemis.Core
|
||||
/// Represents basic info about a plugin and contains a reference to the instance of said plugin
|
||||
/// </summary>
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class PluginInfo : PropertyChangedBase
|
||||
public class PluginInfo : CorePropertyChanged
|
||||
{
|
||||
private string _description;
|
||||
private Guid _guid;
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
using Artemis.Storage.Entities.Plugins;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using Newtonsoft.Json;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
@ -10,17 +9,18 @@ namespace Artemis.Core
|
||||
/// Represents a setting tied to a plugin of type <typeparamref name="T" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The value type of the setting</typeparam>
|
||||
public class PluginSetting<T> : PropertyChangedBase
|
||||
public class PluginSetting<T> : CorePropertyChanged
|
||||
{
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
private readonly PluginInfo _pluginInfo;
|
||||
// TODO: Why? Should have included that...
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
private readonly Plugin _plugin;
|
||||
private readonly IPluginRepository _pluginRepository;
|
||||
private readonly PluginSettingEntity _pluginSettingEntity;
|
||||
private T _value;
|
||||
|
||||
internal PluginSetting(PluginInfo pluginInfo, IPluginRepository pluginRepository, PluginSettingEntity pluginSettingEntity)
|
||||
internal PluginSetting(Plugin plugin, IPluginRepository pluginRepository, PluginSettingEntity pluginSettingEntity)
|
||||
{
|
||||
_pluginInfo = pluginInfo;
|
||||
_plugin = plugin;
|
||||
_pluginRepository = pluginRepository;
|
||||
_pluginSettingEntity = pluginSettingEntity;
|
||||
|
||||
@ -52,7 +52,7 @@ namespace Artemis.Core
|
||||
|
||||
_value = value;
|
||||
OnSettingChanged();
|
||||
NotifyOfPropertyChange(nameof(Value));
|
||||
OnPropertyChanged(nameof(Value));
|
||||
|
||||
if (AutoSave)
|
||||
Save();
|
||||
|
||||
@ -14,17 +14,17 @@ namespace Artemis.Core
|
||||
private readonly IPluginRepository _pluginRepository;
|
||||
private readonly Dictionary<string, object> _settingEntities;
|
||||
|
||||
internal PluginSettings(PluginInfo pluginInfo, IPluginRepository pluginRepository)
|
||||
internal PluginSettings(Plugin plugin, IPluginRepository pluginRepository)
|
||||
{
|
||||
PluginInfo = pluginInfo;
|
||||
Plugin = plugin;
|
||||
_pluginRepository = pluginRepository;
|
||||
_settingEntities = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the info of the plugin this setting belongs to
|
||||
/// Gets the plugin these settings belong to
|
||||
/// </summary>
|
||||
public PluginInfo PluginInfo { get; }
|
||||
public Plugin Plugin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the setting with the provided name. If the setting does not exist yet, it is created.
|
||||
@ -41,15 +41,15 @@ namespace Artemis.Core
|
||||
if (_settingEntities.ContainsKey(name))
|
||||
return (PluginSetting<T>) _settingEntities[name];
|
||||
// Try to find in database
|
||||
PluginSettingEntity settingEntity = _pluginRepository.GetSettingByNameAndGuid(name, PluginInfo.Guid);
|
||||
PluginSettingEntity settingEntity = _pluginRepository.GetSettingByNameAndGuid(name, Plugin.Guid);
|
||||
// If not found, create a new one
|
||||
if (settingEntity == null)
|
||||
{
|
||||
settingEntity = new PluginSettingEntity {Name = name, PluginGuid = PluginInfo.Guid, Value = JsonConvert.SerializeObject(defaultValue)};
|
||||
settingEntity = new PluginSettingEntity {Name = name, PluginGuid = Plugin.Guid, Value = JsonConvert.SerializeObject(defaultValue)};
|
||||
_pluginRepository.AddSetting(settingEntity);
|
||||
}
|
||||
|
||||
PluginSetting<T> pluginSetting = new PluginSetting<T>(PluginInfo, _pluginRepository, settingEntity);
|
||||
PluginSetting<T> pluginSetting = new PluginSetting<T>(Plugin, _pluginRepository, settingEntity);
|
||||
|
||||
// This overrides null with the default value, I'm not sure if that's desirable because you
|
||||
// might expect something to go null and you might not
|
||||
|
||||
@ -8,40 +8,41 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Represents a registration for a timed plugin update
|
||||
/// </summary>
|
||||
public class TimedUpdateRegistration
|
||||
public class TimedUpdateRegistration : IDisposable
|
||||
{
|
||||
private DateTime _lastEvent;
|
||||
private Timer _timer;
|
||||
private bool _disposed;
|
||||
|
||||
internal TimedUpdateRegistration(PluginInfo pluginInfo, TimeSpan interval, Action<double> action)
|
||||
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Action<double> action)
|
||||
{
|
||||
PluginInfo = pluginInfo;
|
||||
Feature = feature;
|
||||
Interval = interval;
|
||||
Action = action;
|
||||
|
||||
PluginInfo.Plugin.Enabled += InstanceOnEnabled;
|
||||
PluginInfo.Plugin.Disabled += InstanceOnDisabled;
|
||||
if (PluginInfo.Plugin.IsEnabled)
|
||||
Feature.Enabled += FeatureOnEnabled;
|
||||
Feature.Disabled += FeatureOnDisabled;
|
||||
if (Feature.IsEnabled)
|
||||
Start();
|
||||
}
|
||||
|
||||
internal TimedUpdateRegistration(PluginInfo pluginInfo, TimeSpan interval, Func<double, Task> asyncAction)
|
||||
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Func<double, Task> asyncAction)
|
||||
{
|
||||
PluginInfo = pluginInfo;
|
||||
Feature = feature;
|
||||
Interval = interval;
|
||||
AsyncAction = asyncAction;
|
||||
|
||||
PluginInfo.Plugin.Enabled += InstanceOnEnabled;
|
||||
PluginInfo.Plugin.Disabled += InstanceOnDisabled;
|
||||
if (PluginInfo.Plugin.IsEnabled)
|
||||
|
||||
Feature.Enabled += FeatureOnEnabled;
|
||||
Feature.Disabled += FeatureOnDisabled;
|
||||
if (Feature.IsEnabled)
|
||||
Start();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin info of the plugin this registration is associated with
|
||||
/// Gets the plugin feature this registration is associated with
|
||||
/// </summary>
|
||||
public PluginInfo PluginInfo { get; }
|
||||
public PluginFeature Feature { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the interval at which the update should occur
|
||||
@ -64,10 +65,13 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("TimedUpdateRegistration");
|
||||
|
||||
lock (this)
|
||||
{
|
||||
if (!PluginInfo.Plugin.IsEnabled)
|
||||
throw new ArtemisPluginException("Cannot start a timed update for a disabled plugin");
|
||||
if (!Feature.IsEnabled)
|
||||
throw new ArtemisPluginException("Cannot start a timed update for a disabled plugin feature");
|
||||
|
||||
if (_timer != null)
|
||||
return;
|
||||
@ -85,6 +89,9 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("TimedUpdateRegistration");
|
||||
|
||||
lock (this)
|
||||
{
|
||||
if (_timer == null)
|
||||
@ -99,7 +106,7 @@ namespace Artemis.Core
|
||||
|
||||
private void TimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (!PluginInfo.Plugin.IsEnabled)
|
||||
if (!Feature.IsEnabled)
|
||||
return;
|
||||
|
||||
lock (this)
|
||||
@ -108,7 +115,7 @@ namespace Artemis.Core
|
||||
_lastEvent = DateTime.Now;
|
||||
|
||||
// Modules don't always want to update, honor that
|
||||
if (PluginInfo.Plugin is Module module && !module.IsUpdateAllowed)
|
||||
if (Feature is Module module && !module.IsUpdateAllowed)
|
||||
return;
|
||||
|
||||
if (Action != null)
|
||||
@ -121,14 +128,25 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
private void InstanceOnEnabled(object sender, EventArgs e)
|
||||
private void FeatureOnEnabled(object sender, EventArgs e)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
|
||||
private void InstanceOnDisabled(object sender, EventArgs e)
|
||||
private void FeatureOnDisabled(object sender, EventArgs e)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
|
||||
Feature.Enabled -= FeatureOnEnabled;
|
||||
Feature.Disabled -= FeatureOnDisabled;
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -40,7 +40,7 @@ namespace Artemis.Core.Services
|
||||
IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService, IModuleService moduleService)
|
||||
{
|
||||
Kernel = kernel;
|
||||
Constants.CorePluginInfo.Kernel = kernel;
|
||||
Constants.CorePlugin.Kernel = kernel;
|
||||
|
||||
_logger = logger;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
@ -133,8 +133,8 @@ namespace Artemis.Core.Services
|
||||
|
||||
private void UpdatePluginCache()
|
||||
{
|
||||
_modules = _pluginManagementService.GetPluginsOfType<Module>().Where(p => p.IsEnabled).ToList();
|
||||
_dataModelExpansions = _pluginManagementService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled).ToList();
|
||||
_modules = _pluginManagementService.GetFeaturesOfType<Module>().Where(p => p.IsEnabled).ToList();
|
||||
_dataModelExpansions = _pluginManagementService.GetFeaturesOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled).ToList();
|
||||
}
|
||||
|
||||
private void ConfigureJsonConvert()
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Artemis.Core.DeviceProviders;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace Artemis.Core.Services
|
||||
@ -33,69 +34,77 @@ namespace Artemis.Core.Services
|
||||
void UnloadPlugins();
|
||||
|
||||
/// <summary>
|
||||
/// Loads the plugin defined in the provided <see cref="PluginInfo" />
|
||||
/// Loads the plugin located in the provided <paramref name="directory" />
|
||||
/// </summary>
|
||||
/// <param name="pluginInfo">The plugin info defining the plugin to load</param>
|
||||
void LoadPlugin(DirectoryInfo pluginInfo);
|
||||
/// <param name="directory">The directory where the plugin is located</param>
|
||||
Plugin LoadPlugin(DirectoryInfo directory);
|
||||
|
||||
/// <summary>
|
||||
/// Unloads the plugin defined in the provided <see cref="PluginInfo" />
|
||||
/// Enables the provided <paramref name="plugin" />
|
||||
/// </summary>
|
||||
/// <param name="pluginInfo">The plugin info defining the plugin to unload</param>
|
||||
void UnloadPlugin(PluginInfo pluginInfo);
|
||||
/// <param name="plugin">The plugin to enable</param>
|
||||
void EnablePlugin(Plugin plugin, bool ignorePluginLock = false);
|
||||
|
||||
/// <summary>
|
||||
/// Enables the provided plugin
|
||||
/// Unloads the provided <paramref name="plugin" />
|
||||
/// </summary>
|
||||
/// <param name="pluginImplementation"></param>
|
||||
/// <param name="plugin">The plugin to unload</param>
|
||||
void UnloadPlugin(Plugin plugin);
|
||||
|
||||
/// <summary>
|
||||
/// Disables the provided <paramref name="plugin" />
|
||||
/// </summary>
|
||||
/// <param name="plugin">The plugin to disable</param>
|
||||
void DisablePlugin(Plugin plugin);
|
||||
|
||||
/// <summary>
|
||||
/// Enables the provided plugin feature
|
||||
/// </summary>
|
||||
/// <param name="pluginFeature"></param>
|
||||
/// <param name="isAutoEnable">If true, fails if there is a lock file present</param>
|
||||
void EnablePluginImplementation(PluginImplementation pluginImplementation, bool isAutoEnable = false);
|
||||
void EnablePluginFeature(PluginFeature pluginFeature, bool isAutoEnable = false);
|
||||
|
||||
/// <summary>
|
||||
/// Disables the provided plugin
|
||||
/// Disables the provided plugin feature
|
||||
/// </summary>
|
||||
/// <param name="pluginImplementation"></param>
|
||||
void DisablePluginImplementation(PluginImplementation pluginImplementation);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the plugin info related to the plugin
|
||||
/// </summary>
|
||||
/// <param name="pluginImplementation">The plugin you want to find the plugin info for</param>
|
||||
/// <returns>The plugins PluginInfo</returns>
|
||||
PluginInfo GetPluginInfo(PluginImplementation pluginImplementation);
|
||||
/// <param name="pluginFeature"></param>
|
||||
void DisablePluginFeature(PluginFeature pluginFeature);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin info of all loaded plugins
|
||||
/// </summary>
|
||||
/// <returns>A list containing all the plugin info</returns>
|
||||
List<PluginInfo> GetAllPluginInfo();
|
||||
List<Plugin> GetAllPlugins();
|
||||
|
||||
/// <summary>
|
||||
/// Finds all enabled <see cref="PluginImplementation" /> instances of <typeparamref name="T" />
|
||||
/// Finds all enabled <see cref="PluginFeature" /> instances of <typeparamref name="T" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Either <see cref="PluginImplementation" /> or a plugin type implementing <see cref="PluginImplementation" /></typeparam>
|
||||
/// <returns>Returns a list of plugin instances of <typeparamref name="T" /></returns>
|
||||
List<T> GetPluginsOfType<T>() where T : PluginImplementation;
|
||||
/// <typeparam name="T">
|
||||
/// Either <see cref="PluginFeature" /> or a plugin type implementing
|
||||
/// <see cref="PluginFeature" />
|
||||
/// </typeparam>
|
||||
/// <returns>Returns a list of feature instances of <typeparamref name="T" /></returns>
|
||||
List<T> GetFeaturesOfType<T>() where T : PluginFeature;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin that provided the specified assembly
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
PluginImplementation GetPluginByAssembly(Assembly assembly);
|
||||
Plugin GetPluginByAssembly(Assembly assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the plugin info of the current call stack
|
||||
/// </summary>
|
||||
/// <returns>If the current call stack contains a plugin, the plugin. Otherwise null</returns>
|
||||
Plugin? GetCallingPlugin();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin that defined the specified device
|
||||
/// </summary>
|
||||
/// <param name="device"></param>
|
||||
/// <returns></returns>
|
||||
PluginImplementation GetPluginByDevice(IRGBDevice device);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the plugin info of the current call stack
|
||||
/// </summary>
|
||||
/// <returns>If the current call stack contains a plugin, the plugin. Otherwise null</returns>
|
||||
PluginImplementation GetCallingPlugin();
|
||||
DeviceProvider GetDeviceProviderByDevice(IRGBDevice device);
|
||||
|
||||
#region Events
|
||||
|
||||
@ -134,6 +143,26 @@ namespace Artemis.Core.Services
|
||||
/// </summary>
|
||||
event EventHandler<PluginEventArgs> PluginDisabled;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a plugin feature is being enabled
|
||||
/// </summary>
|
||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureEnabling;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a plugin feature has been enabled
|
||||
/// </summary>
|
||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a plugin feature could not be enabled
|
||||
/// </summary>
|
||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureEnableFailed;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a plugin feature has been disabled
|
||||
/// </summary>
|
||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureDisabled;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -26,16 +26,129 @@ namespace Artemis.Core.Services
|
||||
_moduleRepository = moduleRepository;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_profileService = profileService;
|
||||
_pluginManagementService.PluginEnabled += PluginManagementServiceOnPluginManagementEnabled;
|
||||
_pluginManagementService.PluginFeatureEnabled += OnPluginFeatureEnabled;
|
||||
|
||||
Timer activationUpdateTimer = new Timer(2000);
|
||||
activationUpdateTimer.Start();
|
||||
activationUpdateTimer.Elapsed += ActivationUpdateTimerOnElapsed;
|
||||
|
||||
foreach (Module module in _pluginManagementService.GetPluginsOfType<Module>())
|
||||
foreach (Module module in _pluginManagementService.GetFeaturesOfType<Module>())
|
||||
InitialiseOrApplyPriority(module);
|
||||
}
|
||||
|
||||
private async void ActivationUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
await UpdateModuleActivation();
|
||||
}
|
||||
|
||||
private async Task ActivateModule(Module module)
|
||||
{
|
||||
try
|
||||
{
|
||||
module.Activate(false);
|
||||
|
||||
// If this is a profile module, activate the last active profile after module activation
|
||||
if (module is ProfileModule profileModule)
|
||||
await _profileService.ActivateLastProfileAnimated(profileModule);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(new ArtemisPluginFeatureException(
|
||||
module, "Failed to activate module and last profile.", e), "Failed to activate module and last profile"
|
||||
);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeactivateModule(Module module)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If this is a profile module, animate profile disable
|
||||
// module.Deactivate would do the same but without animation
|
||||
if (module.IsActivated && module is ProfileModule profileModule)
|
||||
await profileModule.ChangeActiveProfileAnimated(null, null);
|
||||
|
||||
module.Deactivate(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(new ArtemisPluginFeatureException(
|
||||
module, "Failed to deactivate module and last profile.", e), "Failed to deactivate module and last profile"
|
||||
);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void OverrideActivate(Module module)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (module.IsActivated)
|
||||
return;
|
||||
|
||||
// If activating while it should be deactivated, its an override
|
||||
bool shouldBeActivated = module.EvaluateActivationRequirements();
|
||||
module.Activate(!shouldBeActivated);
|
||||
|
||||
// If this is a profile module, activate the last active profile after module activation
|
||||
if (module is ProfileModule profileModule)
|
||||
_profileService.ActivateLastProfile(profileModule);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(new ArtemisPluginFeatureException(
|
||||
module, "Failed to activate module and last profile.", e), "Failed to activate module and last profile"
|
||||
);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void OverrideDeactivate(Module module, bool clearingOverride)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!module.IsActivated)
|
||||
return;
|
||||
|
||||
// If deactivating while it should be activated, its an override
|
||||
bool shouldBeActivated = module.EvaluateActivationRequirements();
|
||||
// No need to deactivate if it is not in an overridden state
|
||||
if (shouldBeActivated && !module.IsActivatedOverride && !clearingOverride)
|
||||
return;
|
||||
|
||||
module.Deactivate(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(new ArtemisPluginFeatureException(
|
||||
module, "Failed to deactivate module and last profile.", e), "Failed to deactivate module and last profile"
|
||||
);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPluginFeatureEnabled(object? sender, PluginFeatureEventArgs e)
|
||||
{
|
||||
if (e.PluginFeature is Module module)
|
||||
InitialiseOrApplyPriority(module);
|
||||
}
|
||||
|
||||
private void InitialiseOrApplyPriority(Module module)
|
||||
{
|
||||
ModulePriorityCategory category = module.DefaultPriorityCategory;
|
||||
int priority = 1;
|
||||
|
||||
module.Entity = _moduleRepository.GetByModuleId(module.Id);
|
||||
if (module.Entity != null)
|
||||
{
|
||||
category = (ModulePriorityCategory) module.Entity.PriorityCategory;
|
||||
priority = module.Entity.Priority;
|
||||
}
|
||||
|
||||
UpdateModulePriority(module, category, priority);
|
||||
}
|
||||
|
||||
public Module ActiveModuleOverride { get; private set; }
|
||||
|
||||
public async Task SetActiveModuleOverride(Module overrideModule)
|
||||
@ -46,17 +159,19 @@ namespace Artemis.Core.Services
|
||||
|
||||
if (ActiveModuleOverride == overrideModule)
|
||||
return;
|
||||
|
||||
|
||||
if (overrideModule != null)
|
||||
{
|
||||
OverrideActivate(overrideModule);
|
||||
_logger.Information($"Setting active module override to {overrideModule.DisplayName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Information("Clearing active module override");
|
||||
}
|
||||
|
||||
// Always deactivate all other modules whenever override is called
|
||||
List<Module> modules = _pluginManagementService.GetPluginsOfType<Module>().ToList();
|
||||
List<Module> modules = _pluginManagementService.GetFeaturesOfType<Module>().ToList();
|
||||
foreach (Module module in modules.Where(m => m != overrideModule))
|
||||
OverrideDeactivate(module, overrideModule != null);
|
||||
|
||||
@ -83,13 +198,8 @@ namespace Artemis.Core.Services
|
||||
// the principle is different for this service but not for the module
|
||||
bool shouldBeActivated = ActiveModuleOverride.EvaluateActivationRequirements();
|
||||
if (shouldBeActivated && ActiveModuleOverride.IsActivatedOverride)
|
||||
{
|
||||
ActiveModuleOverride.Reactivate(true, false);
|
||||
}
|
||||
else if (!shouldBeActivated && !ActiveModuleOverride.IsActivatedOverride)
|
||||
{
|
||||
ActiveModuleOverride.Reactivate(false, true);
|
||||
}
|
||||
else if (!shouldBeActivated && !ActiveModuleOverride.IsActivatedOverride) ActiveModuleOverride.Reactivate(false, true);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -97,10 +207,9 @@ namespace Artemis.Core.Services
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
List<Module> modules = _pluginManagementService.GetPluginsOfType<Module>().ToList();
|
||||
List<Module> modules = _pluginManagementService.GetFeaturesOfType<Module>().ToList();
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (Module module in modules)
|
||||
{
|
||||
lock (module)
|
||||
{
|
||||
bool shouldBeActivated = module.EvaluateActivationRequirements() && module.IsEnabled;
|
||||
@ -109,7 +218,6 @@ namespace Artemis.Core.Services
|
||||
else if (!shouldBeActivated && module.IsActivated)
|
||||
tasks.Add(DeactivateModule(module));
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
@ -128,7 +236,12 @@ namespace Artemis.Core.Services
|
||||
if (module.PriorityCategory == category && module.Priority == priority)
|
||||
return;
|
||||
|
||||
List<Module> modules = _pluginManagementService.GetPluginsOfType<Module>().Where(m => m.PriorityCategory == category).OrderBy(m => m.Priority).ToList();
|
||||
List<Module> modules = _pluginManagementService
|
||||
.GetFeaturesOfType<Module>()
|
||||
.Where(m => m.PriorityCategory == category)
|
||||
.OrderBy(m => m.Priority)
|
||||
.ToList();
|
||||
|
||||
if (modules.Contains(module))
|
||||
modules.Remove(module);
|
||||
|
||||
@ -149,110 +262,5 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void ActivationUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
await UpdateModuleActivation();
|
||||
}
|
||||
|
||||
private async Task ActivateModule(Module module)
|
||||
{
|
||||
try
|
||||
{
|
||||
module.Activate(false);
|
||||
|
||||
// If this is a profile module, activate the last active profile after module activation
|
||||
if (module is ProfileModule profileModule)
|
||||
await _profileService.ActivateLastProfileAnimated(profileModule);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(new ArtemisPluginException(module.PluginInfo, "Failed to activate module and last profile.", e), "Failed to activate module and last profile");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeactivateModule(Module module)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If this is a profile module, animate profile disable
|
||||
// module.Deactivate would do the same but without animation
|
||||
if (module.IsActivated && module is ProfileModule profileModule)
|
||||
await profileModule.ChangeActiveProfileAnimated(null, null);
|
||||
|
||||
module.Deactivate(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(new ArtemisPluginException(module.PluginInfo, "Failed to deactivate module and last profile.", e), "Failed to deactivate module and last profile");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void OverrideActivate(Module module)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (module.IsActivated)
|
||||
return;
|
||||
|
||||
// If activating while it should be deactivated, its an override
|
||||
bool shouldBeActivated = module.EvaluateActivationRequirements();
|
||||
module.Activate(!shouldBeActivated);
|
||||
|
||||
// If this is a profile module, activate the last active profile after module activation
|
||||
if (module is ProfileModule profileModule)
|
||||
_profileService.ActivateLastProfile(profileModule);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(new ArtemisPluginException(module.PluginInfo, "Failed to activate module and last profile.", e), "Failed to activate module and last profile");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void OverrideDeactivate(Module module, bool clearingOverride)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!module.IsActivated)
|
||||
return;
|
||||
|
||||
// If deactivating while it should be activated, its an override
|
||||
bool shouldBeActivated = module.EvaluateActivationRequirements();
|
||||
// No need to deactivate if it is not in an overridden state
|
||||
if (shouldBeActivated && !module.IsActivatedOverride && !clearingOverride)
|
||||
return;
|
||||
|
||||
module.Deactivate(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(new ArtemisPluginException(module.PluginInfo, "Failed to deactivate module and last profile.", e), "Failed to deactivate module and last profile");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void PluginManagementServiceOnPluginManagementEnabled(object sender, PluginEventArgs e)
|
||||
{
|
||||
if (e.PluginInfo.Plugin is Module module)
|
||||
InitialiseOrApplyPriority(module);
|
||||
}
|
||||
|
||||
private void InitialiseOrApplyPriority(Module module)
|
||||
{
|
||||
ModulePriorityCategory category = module.DefaultPriorityCategory;
|
||||
int priority = 1;
|
||||
|
||||
module.Entity = _moduleRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
||||
if (module.Entity != null)
|
||||
{
|
||||
category = (ModulePriorityCategory) module.Entity.PriorityCategory;
|
||||
priority = module.Entity.Priority;
|
||||
}
|
||||
|
||||
UpdateModulePriority(module, category, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -41,6 +41,21 @@ namespace Artemis.Core.Services
|
||||
Directory.CreateDirectory(Constants.DataFolder + "plugins");
|
||||
}
|
||||
|
||||
private void CopyBuiltInPlugin(FileInfo zipFileInfo, ZipArchive zipArchive)
|
||||
{
|
||||
DirectoryInfo pluginDirectory = new DirectoryInfo(Path.Combine(Constants.DataFolder, "plugins", Path.GetFileNameWithoutExtension(zipFileInfo.Name)));
|
||||
bool createLockFile = File.Exists(Path.Combine(pluginDirectory.FullName, "artemis.lock"));
|
||||
|
||||
// Remove the old directory if it exists
|
||||
if (Directory.Exists(pluginDirectory.FullName))
|
||||
pluginDirectory.DeleteRecursively();
|
||||
Directory.CreateDirectory(pluginDirectory.FullName);
|
||||
|
||||
zipArchive.ExtractToDirectory(pluginDirectory.FullName, true);
|
||||
if (createLockFile)
|
||||
File.Create(Path.Combine(pluginDirectory.FullName, "artemis.lock")).Close();
|
||||
}
|
||||
|
||||
public bool LoadingPlugins { get; private set; }
|
||||
|
||||
#region Built in plugins
|
||||
@ -72,7 +87,9 @@ namespace Artemis.Core.Services
|
||||
// Find the matching plugin in the plugin folder
|
||||
DirectoryInfo? match = pluginDirectory.EnumerateDirectories().FirstOrDefault(d => d.Name == Path.GetFileNameWithoutExtension(zipFile.Name));
|
||||
if (match == null)
|
||||
{
|
||||
CopyBuiltInPlugin(zipFile, archive);
|
||||
}
|
||||
else
|
||||
{
|
||||
string metadataFile = Path.Combine(match.FullName, "plugin.json");
|
||||
@ -105,6 +122,48 @@ namespace Artemis.Core.Services
|
||||
|
||||
#endregion
|
||||
|
||||
public List<Plugin> GetAllPlugins()
|
||||
{
|
||||
return new List<Plugin>(_plugins);
|
||||
}
|
||||
|
||||
public List<T> GetFeaturesOfType<T>() where T : PluginFeature
|
||||
{
|
||||
return _plugins.Where(p => p.IsEnabled).SelectMany(p => p.Features.Where(i => i.IsEnabled && i is T)).Cast<T>().ToList();
|
||||
}
|
||||
|
||||
public Plugin? GetPluginByAssembly(Assembly assembly)
|
||||
{
|
||||
return _plugins.FirstOrDefault(p => p.Assembly == assembly);
|
||||
}
|
||||
|
||||
// TODO: move to a more appropriate service
|
||||
public DeviceProvider GetDeviceProviderByDevice(IRGBDevice rgbDevice)
|
||||
{
|
||||
return GetFeaturesOfType<DeviceProvider>().First(d => d.RgbDeviceProvider.Devices != null && d.RgbDeviceProvider.Devices.Contains(rgbDevice));
|
||||
}
|
||||
|
||||
public Plugin? GetCallingPlugin()
|
||||
{
|
||||
StackTrace stackTrace = new StackTrace(); // get call stack
|
||||
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
||||
|
||||
foreach (StackFrame stackFrame in stackFrames)
|
||||
{
|
||||
Assembly assembly = stackFrame.GetMethod().DeclaringType.Assembly;
|
||||
Plugin plugin = GetPluginByAssembly(assembly);
|
||||
if (plugin != null)
|
||||
return plugin;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
UnloadPlugins();
|
||||
}
|
||||
|
||||
#region Plugins
|
||||
|
||||
public void LoadPlugins(bool ignorePluginLock)
|
||||
@ -125,7 +184,8 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadPlugin(subDirectory);
|
||||
Plugin plugin = LoadPlugin(subDirectory);
|
||||
EnablePlugin(plugin, ignorePluginLock);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -133,22 +193,6 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
// Activate plugins after they are all loaded
|
||||
foreach (Plugin plugin in _plugins.Where(p => p.Entity.IsEnabled))
|
||||
{
|
||||
foreach (PluginImplementation pluginImplementation in plugin.Implementations.Where(i => i.Entity.IsEnabled))
|
||||
{
|
||||
try
|
||||
{
|
||||
EnablePluginImplementation(pluginImplementation, !ignorePluginLock);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored, logged in EnablePlugin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadingPlugins = false;
|
||||
}
|
||||
}
|
||||
@ -165,29 +209,32 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadPlugin(DirectoryInfo pluginDirectory)
|
||||
public Plugin LoadPlugin(DirectoryInfo directory)
|
||||
{
|
||||
lock (_plugins)
|
||||
{
|
||||
_logger.Debug("Loading plugin from {directory}", pluginDirectory.FullName);
|
||||
_logger.Debug("Loading plugin from {directory}", directory.FullName);
|
||||
|
||||
// Load the metadata
|
||||
string metadataFile = Path.Combine(pluginDirectory.FullName, "plugin.json");
|
||||
string metadataFile = Path.Combine(directory.FullName, "plugin.json");
|
||||
if (!File.Exists(metadataFile))
|
||||
_logger.Warning(new ArtemisPluginException("Couldn't find the plugins metadata file at " + metadataFile), "Plugin exception");
|
||||
|
||||
// PluginInfo contains the ID which we need to move on
|
||||
PluginInfo pluginInfo = JsonConvert.DeserializeObject<PluginInfo>(File.ReadAllText(metadataFile));
|
||||
|
||||
if (pluginInfo.Guid == Constants.CorePluginInfo.Guid)
|
||||
throw new ArtemisPluginException($"Plugin cannot use reserved GUID {pluginInfo.Guid}");
|
||||
|
||||
// Ensure the plugin is not already loaded
|
||||
if (_plugins.Any(p => p.Guid == pluginInfo.Guid))
|
||||
throw new ArtemisCoreException("Cannot load a plugin that is already loaded");
|
||||
|
||||
Plugin plugin = new Plugin(pluginInfo, pluginDirectory);
|
||||
Plugin plugin = new Plugin(pluginInfo, directory);
|
||||
OnPluginLoading(new PluginEventArgs(plugin));
|
||||
|
||||
// Load the entity and fall back on creating a new one
|
||||
plugin.Entity = _pluginRepository.GetPluginByGuid(pluginInfo.Guid) ?? new PluginEntity { Id = plugin.Guid, IsEnabled = true };
|
||||
plugin.Entity = _pluginRepository.GetPluginByGuid(pluginInfo.Guid) ?? new PluginEntity {Id = plugin.Guid, IsEnabled = true};
|
||||
|
||||
// Locate the main assembly entry
|
||||
string? mainFile = plugin.ResolveRelativePath(plugin.Info.Main);
|
||||
@ -210,55 +257,94 @@ namespace Artemis.Core.Services
|
||||
throw new ArtemisPluginException(plugin, "Failed to load the plugins assembly", e);
|
||||
}
|
||||
|
||||
// Get the Plugin implementation from the main assembly and if there is only one, instantiate it
|
||||
List<Type> implementationTypes;
|
||||
try
|
||||
{
|
||||
implementationTypes = plugin.Assembly.GetTypes().Where(t => typeof(PluginImplementation).IsAssignableFrom(t)).ToList();
|
||||
}
|
||||
catch (ReflectionTypeLoadException e)
|
||||
{
|
||||
throw new ArtemisPluginException(plugin, "Failed to initialize the plugin assembly", new AggregateException(e.LoaderExceptions));
|
||||
}
|
||||
|
||||
// Create the Ninject child kernel and load the module
|
||||
plugin.Kernel = new ChildKernel(_kernel);
|
||||
plugin.Kernel.Load(new PluginModule(pluginInfo));
|
||||
|
||||
if (!implementationTypes.Any())
|
||||
_logger.Warning("Plugin {plugin} contains no implementations", plugin);
|
||||
|
||||
// Create instances of each implementation and add them to the plugin
|
||||
// Construction should be simple and not contain any logic so failure at this point means the entire plugin fails
|
||||
foreach (Type implementationType in implementationTypes)
|
||||
{
|
||||
try
|
||||
{
|
||||
PluginImplementation instance = (PluginImplementation)plugin.Kernel.Get(implementationType);
|
||||
plugin.AddImplementation(instance);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArtemisPluginException(plugin, "Failed to load instantiate implementation", e);
|
||||
}
|
||||
}
|
||||
List<Type> bootstrappers = plugin.Assembly.GetTypes().Where(t => typeof(IPluginBootstrapper).IsAssignableFrom(t)).ToList();
|
||||
if (bootstrappers.Count > 1)
|
||||
_logger.Warning($"{plugin} has more than one bootstrapper, only initializing {bootstrappers.First().FullName}");
|
||||
if (bootstrappers.Any())
|
||||
plugin.Bootstrapper = (IPluginBootstrapper?) Activator.CreateInstance(bootstrappers.First());
|
||||
|
||||
_plugins.Add(plugin);
|
||||
|
||||
OnPluginLoaded(new PluginEventArgs(plugin));
|
||||
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
|
||||
public void EnablePlugin(Plugin plugin, bool ignorePluginLock)
|
||||
{
|
||||
if (plugin.Assembly == null)
|
||||
throw new ArtemisPluginException(plugin, "Cannot enable a plugin that hasn't successfully been loaded");
|
||||
|
||||
// Create the Ninject child kernel and load the module
|
||||
plugin.Kernel = new ChildKernel(_kernel);
|
||||
plugin.Kernel.Bind<Plugin>().ToConstant(plugin);
|
||||
plugin.Kernel.Load(new PluginModule(plugin.Info));
|
||||
|
||||
plugin.SetEnabled(true);
|
||||
|
||||
// Get the Plugin feature from the main assembly and if there is only one, instantiate it
|
||||
List<Type> featureTypes;
|
||||
try
|
||||
{
|
||||
featureTypes = plugin.Assembly.GetTypes().Where(t => typeof(PluginFeature).IsAssignableFrom(t)).ToList();
|
||||
}
|
||||
catch (ReflectionTypeLoadException e)
|
||||
{
|
||||
throw new ArtemisPluginException(plugin, "Failed to initialize the plugin assembly", new AggregateException(e.LoaderExceptions));
|
||||
}
|
||||
|
||||
if (!featureTypes.Any())
|
||||
_logger.Warning("Plugin {plugin} contains no features", plugin);
|
||||
|
||||
// Create instances of each feature and add them to the plugin
|
||||
// Construction should be simple and not contain any logic so failure at this point means the entire plugin fails
|
||||
foreach (Type featureType in featureTypes)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Include Plugin as a parameter for the PluginSettingsProvider
|
||||
IParameter[] parameters = {new Parameter("Plugin", plugin, false)};
|
||||
PluginFeature instance = (PluginFeature) plugin.Kernel.Get(featureType, parameters);
|
||||
plugin.AddFeature(instance);
|
||||
|
||||
// Load the enabled state and if not found, default to true
|
||||
instance.Entity = plugin.Entity.Features.FirstOrDefault(i => i.Type == featureType.FullName) ??
|
||||
new PluginFeatureEntity {IsEnabled = true, Type = featureType.FullName};
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArtemisPluginException(plugin, "Failed to load instantiate feature", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Activate plugins after they are all loaded
|
||||
foreach (PluginFeature pluginFeature in plugin.Features.Where(i => i.Entity.IsEnabled))
|
||||
{
|
||||
try
|
||||
{
|
||||
EnablePluginFeature(pluginFeature, !ignorePluginLock);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored, logged in EnablePluginFeature
|
||||
}
|
||||
}
|
||||
|
||||
OnPluginEnabled(new PluginEventArgs(plugin));
|
||||
}
|
||||
|
||||
public void UnloadPlugin(Plugin plugin)
|
||||
{
|
||||
lock (_plugins)
|
||||
{
|
||||
try
|
||||
{
|
||||
plugin.SetEnabled(false);
|
||||
DisablePlugin(plugin);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO: Log these
|
||||
_logger.Warning(new ArtemisPluginException(plugin, "Exception during DisablePlugin call for UnloadPlugin", e), "Failed to unload plugin");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -267,38 +353,59 @@ namespace Artemis.Core.Services
|
||||
|
||||
plugin.Dispose();
|
||||
_plugins.Remove(plugin);
|
||||
|
||||
OnPluginUnloaded(new PluginEventArgs(plugin));
|
||||
}
|
||||
}
|
||||
|
||||
public void DisablePlugin(Plugin plugin)
|
||||
{
|
||||
if (!plugin.IsEnabled)
|
||||
return;
|
||||
|
||||
while (plugin.Features.Any())
|
||||
{
|
||||
PluginFeature feature = plugin.Features[0];
|
||||
plugin.RemoveFeature(feature);
|
||||
OnPluginFeatureDisabled(new PluginFeatureEventArgs(feature));
|
||||
}
|
||||
|
||||
plugin.SetEnabled(false);
|
||||
|
||||
plugin.Kernel.Dispose();
|
||||
plugin.Kernel = null;
|
||||
|
||||
OnPluginDisabled(new PluginEventArgs(plugin));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Features
|
||||
|
||||
#region Implementations
|
||||
|
||||
public void EnablePluginImplementation(PluginImplementation pluginImplementation, bool isAutoEnable = false)
|
||||
public void EnablePluginFeature(PluginFeature pluginFeature, bool isAutoEnable = false)
|
||||
{
|
||||
_logger.Debug("Enabling plugin implementation {implementation} - {plugin}", pluginImplementation, pluginImplementation.Plugin);
|
||||
_logger.Debug("Enabling plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
||||
|
||||
lock (_plugins)
|
||||
{
|
||||
OnPluginFeatureEnabling(new PluginFeatureEventArgs(pluginFeature));
|
||||
try
|
||||
{
|
||||
// A device provider may be queued for disable on next restart, this undoes that
|
||||
if (pluginImplementation is DeviceProvider && pluginImplementation.IsEnabled && !pluginImplementation.PluginInfo.IsEnabled)
|
||||
if (pluginFeature is DeviceProvider && pluginFeature.IsEnabled && !pluginFeature.Entity.IsEnabled)
|
||||
{
|
||||
pluginImplementation.PluginInfo.IsEnabled = true;
|
||||
pluginImplementation.PluginInfo.ApplyToEntity();
|
||||
_pluginRepository.SavePlugin(pluginImplementation.PluginInfo.PluginEntity);
|
||||
pluginFeature.Entity.IsEnabled = true;
|
||||
SavePlugin(pluginFeature.Plugin);
|
||||
return;
|
||||
}
|
||||
|
||||
pluginImplementation.SetEnabled(true, isAutoEnable);
|
||||
pluginFeature.SetEnabled(true, isAutoEnable);
|
||||
pluginFeature.Entity.IsEnabled = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Warning(new ArtemisPluginException(pluginImplementation.PluginInfo, "Exception during SetEnabled(true)", e), "Failed to enable plugin");
|
||||
_logger.Warning(
|
||||
new ArtemisPluginException(pluginFeature.Plugin, $"Exception during SetEnabled(true) on {pluginFeature}", e),
|
||||
"Failed to enable plugin"
|
||||
);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
@ -306,108 +413,83 @@ namespace Artemis.Core.Services
|
||||
// On an auto-enable, ensure PluginInfo.Enabled is true even if enable failed, that way a failure on auto-enable does
|
||||
// not affect the user's settings
|
||||
if (isAutoEnable)
|
||||
pluginImplementation.PluginInfo.IsEnabled = true;
|
||||
pluginFeature.Entity.IsEnabled = true;
|
||||
|
||||
pluginImplementation.PluginInfo.ApplyToEntity();
|
||||
_pluginRepository.SavePlugin(pluginImplementation.PluginInfo.PluginEntity);
|
||||
SavePlugin(pluginFeature.Plugin);
|
||||
|
||||
if (pluginImplementation.PluginInfo.IsEnabled)
|
||||
_logger.Debug("Successfully enabled plugin {pluginInfo}", pluginImplementation.PluginInfo);
|
||||
if (pluginFeature.IsEnabled)
|
||||
{
|
||||
_logger.Debug("Successfully enabled plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
||||
OnPluginFeatureEnabled(new PluginFeatureEventArgs(pluginFeature));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnPluginFeatureEnableFailed(new PluginFeatureEventArgs(pluginFeature));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OnPluginImplementationEnabled(new PluginImplementationEventArgs(pluginImplementation));
|
||||
}
|
||||
|
||||
public void DisablePluginImplementation(PluginImplementation pluginImplementation)
|
||||
public void DisablePluginFeature(PluginFeature pluginFeature)
|
||||
{
|
||||
lock (_plugins)
|
||||
{
|
||||
_logger.Debug("Disabling plugin {pluginInfo}", pluginImplementation.PluginInfo);
|
||||
|
||||
// Device providers cannot be disabled at runtime simply queue a disable for next restart
|
||||
if (pluginImplementation is DeviceProvider)
|
||||
try
|
||||
{
|
||||
// Don't call SetEnabled(false) but simply update enabled state and save it
|
||||
pluginImplementation.PluginInfo.IsEnabled = false;
|
||||
pluginImplementation.PluginInfo.ApplyToEntity();
|
||||
_pluginRepository.SavePlugin(pluginImplementation.PluginInfo.PluginEntity);
|
||||
return;
|
||||
_logger.Debug("Disabling plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
||||
|
||||
// Device providers cannot be disabled at runtime simply queue a disable for next restart
|
||||
if (pluginFeature is DeviceProvider)
|
||||
{
|
||||
// Don't call SetEnabled(false) but simply update enabled state and save it
|
||||
pluginFeature.Entity.IsEnabled = false;
|
||||
SavePlugin(pluginFeature.Plugin);
|
||||
return;
|
||||
}
|
||||
|
||||
pluginFeature.SetEnabled(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
pluginFeature.Entity.IsEnabled = false;
|
||||
SavePlugin(pluginFeature.Plugin);
|
||||
|
||||
pluginImplementation.SetEnabled(false);
|
||||
pluginImplementation.PluginInfo.ApplyToEntity();
|
||||
_pluginRepository.SavePlugin(pluginImplementation.PluginInfo.PluginEntity);
|
||||
|
||||
_logger.Debug("Successfully disabled plugin {pluginInfo}", pluginImplementation.PluginInfo);
|
||||
if (!pluginFeature.IsEnabled)
|
||||
{
|
||||
_logger.Debug("Successfully disabled plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
||||
OnPluginFeatureDisabled(new PluginFeatureEventArgs(pluginFeature));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OnPluginDisabled(new PluginEventArgs(pluginImplementation.PluginInfo));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Storage
|
||||
|
||||
public PluginInfo GetPluginInfo(PluginImplementation pluginImplementation)
|
||||
private void SavePlugin(Plugin plugin)
|
||||
{
|
||||
return _plugins.FirstOrDefault(p => p.Plugin == pluginImplementation);
|
||||
}
|
||||
|
||||
public List<PluginInfo> GetAllPluginInfo()
|
||||
{
|
||||
return new List<PluginInfo>(_plugins);
|
||||
}
|
||||
|
||||
public List<T> GetPluginsOfType<T>() where T : PluginImplementation
|
||||
{
|
||||
return _plugins.Where(p => p.IsEnabled && p.Plugin is T).Select(p => (T) p.Plugin).ToList();
|
||||
}
|
||||
|
||||
public PluginImplementation GetPluginByAssembly(Assembly assembly)
|
||||
{
|
||||
return _plugins.FirstOrDefault(p => p.Assembly == assembly)?.Plugin;
|
||||
}
|
||||
|
||||
public PluginImplementation GetPluginByDevice(IRGBDevice rgbDevice)
|
||||
{
|
||||
return GetPluginsOfType<DeviceProvider>().First(d => d.RgbDeviceProvider.Devices != null && d.RgbDeviceProvider.Devices.Contains(rgbDevice));
|
||||
}
|
||||
|
||||
public PluginImplementation GetCallingPlugin()
|
||||
{
|
||||
StackTrace stackTrace = new StackTrace(); // get call stack
|
||||
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
||||
|
||||
foreach (StackFrame stackFrame in stackFrames)
|
||||
foreach (PluginFeature pluginFeature in plugin.Features)
|
||||
{
|
||||
Assembly assembly = stackFrame.GetMethod().DeclaringType.Assembly;
|
||||
PluginImplementation pluginImplementation = GetPluginByAssembly(assembly);
|
||||
if (pluginImplementation != null)
|
||||
return pluginImplementation;
|
||||
if (plugin.Entity.Features.All(i => i.Type != pluginFeature.GetType().FullName))
|
||||
plugin.Entity.Features.Add(pluginFeature.Entity);
|
||||
}
|
||||
|
||||
return null;
|
||||
_pluginRepository.SavePlugin(plugin.Entity);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
private PluginFeatureEntity GetOrCreateFeatureEntity(PluginFeature feature)
|
||||
{
|
||||
UnloadPlugins();
|
||||
return feature.Plugin.Entity.Features.FirstOrDefault(i => i.Type == feature.GetType().FullName) ??
|
||||
new PluginFeatureEntity {IsEnabled = true, Type = feature.GetType().FullName};
|
||||
}
|
||||
|
||||
private void CopyBuiltInPlugin(FileInfo zipFileInfo, ZipArchive zipArchive)
|
||||
{
|
||||
DirectoryInfo pluginDirectory = new DirectoryInfo(Path.Combine(Constants.DataFolder, "plugins", Path.GetFileNameWithoutExtension(zipFileInfo.Name)));
|
||||
bool createLockFile = File.Exists(Path.Combine(pluginDirectory.FullName, "artemis.lock"));
|
||||
|
||||
// Remove the old directory if it exists
|
||||
if (Directory.Exists(pluginDirectory.FullName))
|
||||
pluginDirectory.DeleteRecursively();
|
||||
Directory.CreateDirectory(pluginDirectory.FullName);
|
||||
|
||||
zipArchive.ExtractToDirectory(pluginDirectory.FullName, true);
|
||||
if (createLockFile)
|
||||
File.Create(Path.Combine(pluginDirectory.FullName, "artemis.lock")).Close();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
@ -419,8 +501,10 @@ namespace Artemis.Core.Services
|
||||
public event EventHandler<PluginEventArgs> PluginEnabled;
|
||||
public event EventHandler<PluginEventArgs> PluginDisabled;
|
||||
|
||||
public event EventHandler<PluginImplementationEventArgs> PluginImplementationEnabled;
|
||||
public event EventHandler<PluginImplementationEventArgs> PluginImplementationDisabled;
|
||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureEnabling;
|
||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureEnabled;
|
||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureDisabled;
|
||||
public event EventHandler<PluginFeatureEventArgs> PluginFeatureEnableFailed;
|
||||
|
||||
protected virtual void OnCopyingBuildInPlugins()
|
||||
{
|
||||
@ -457,14 +541,24 @@ namespace Artemis.Core.Services
|
||||
PluginDisabled?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnPluginImplementationDisabled(PluginImplementationEventArgs e)
|
||||
protected virtual void OnPluginFeatureEnabling(PluginFeatureEventArgs e)
|
||||
{
|
||||
PluginImplementationDisabled?.Invoke(this, e);
|
||||
PluginFeatureEnabling?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnPluginImplementationEnabled(PluginImplementationEventArgs e)
|
||||
protected virtual void OnPluginFeatureEnabled(PluginFeatureEventArgs e)
|
||||
{
|
||||
PluginImplementationEnabled?.Invoke(this, e);
|
||||
PluginFeatureEnabled?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnPluginFeatureDisabled(PluginFeatureEventArgs e)
|
||||
{
|
||||
PluginFeatureDisabled?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnPluginFeatureEnableFailed(PluginFeatureEventArgs e)
|
||||
{
|
||||
PluginFeatureEnableFailed?.Invoke(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -12,14 +12,14 @@ namespace Artemis.Core.Services
|
||||
RegisterBuiltInConditionOperators();
|
||||
}
|
||||
|
||||
public ConditionOperatorRegistration RegisterConditionOperator(PluginInfo pluginInfo, BaseConditionOperator conditionOperator)
|
||||
public ConditionOperatorRegistration RegisterConditionOperator(Plugin plugin, BaseConditionOperator conditionOperator)
|
||||
{
|
||||
if (pluginInfo == null)
|
||||
throw new ArgumentNullException(nameof(pluginInfo));
|
||||
if (plugin == null)
|
||||
throw new ArgumentNullException(nameof(plugin));
|
||||
if (conditionOperator == null)
|
||||
throw new ArgumentNullException(nameof(conditionOperator));
|
||||
|
||||
conditionOperator.PluginInfo = pluginInfo;
|
||||
conditionOperator.Plugin = plugin;
|
||||
return ConditionOperatorStore.Add(conditionOperator);
|
||||
}
|
||||
|
||||
@ -43,30 +43,30 @@ namespace Artemis.Core.Services
|
||||
private void RegisterBuiltInConditionOperators()
|
||||
{
|
||||
// General usage for any type
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new EqualsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new NotEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new EqualsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new NotEqualConditionOperator());
|
||||
|
||||
// Numeric operators
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new NumberEqualsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new NumberNotEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new LessThanConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new GreaterThanConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new LessThanOrEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new GreaterThanOrEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new NumberEqualsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new NumberNotEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new LessThanConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new GreaterThanConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new LessThanOrEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new GreaterThanOrEqualConditionOperator());
|
||||
|
||||
// String operators
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringEqualsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringNotEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringContainsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringNotContainsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringStartsWithConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringEndsWithConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new StringMatchesRegexConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringEqualsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringNotEqualConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringContainsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringNotContainsConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringStartsWithConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringEndsWithConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new StringMatchesRegexConditionOperator());
|
||||
|
||||
// Null checks, at the bottom
|
||||
// TODO: Implement a priority mechanism
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new NullConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePluginInfo, new NotNullConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new NullConditionOperator());
|
||||
RegisterConditionOperator(Constants.CorePlugin, new NotNullConditionOperator());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,14 +12,14 @@ namespace Artemis.Core.Services
|
||||
RegisterBuiltInModifiers();
|
||||
}
|
||||
|
||||
public DataBindingModifierTypeRegistration RegisterModifierType(PluginInfo pluginInfo, BaseDataBindingModifierType dataBindingModifierType)
|
||||
public DataBindingModifierTypeRegistration RegisterModifierType(Plugin plugin, BaseDataBindingModifierType dataBindingModifierType)
|
||||
{
|
||||
if (pluginInfo == null)
|
||||
throw new ArgumentNullException(nameof(pluginInfo));
|
||||
if (plugin == null)
|
||||
throw new ArgumentNullException(nameof(plugin));
|
||||
if (dataBindingModifierType == null)
|
||||
throw new ArgumentNullException(nameof(dataBindingModifierType));
|
||||
|
||||
dataBindingModifierType.PluginInfo = pluginInfo;
|
||||
dataBindingModifierType.Plugin = plugin;
|
||||
return DataBindingModifierTypeStore.Add(dataBindingModifierType);
|
||||
}
|
||||
|
||||
@ -43,41 +43,41 @@ namespace Artemis.Core.Services
|
||||
private void RegisterBuiltInModifiers()
|
||||
{
|
||||
// Numbers - General
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SumModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SubtractModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new MultiplicationModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new DivideModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new PercentageOfModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SumModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SubtractModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new MultiplicationModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new DivideModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new PercentageOfModifierType());
|
||||
|
||||
// Numbers - Advanced
|
||||
RegisterModifierType(Constants.CorePluginInfo, new MaxModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new MinModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new ModuloModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new AbsoluteModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new PowerModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SquareRootModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new MaxModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new MinModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new ModuloModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new AbsoluteModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new PowerModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SquareRootModifierType());
|
||||
|
||||
// Numbers - Rounding
|
||||
RegisterModifierType(Constants.CorePluginInfo, new FloorModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new RoundModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new CeilingModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new FloorModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new RoundModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new CeilingModifierType());
|
||||
|
||||
// Numbers - Trigonometric
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SineModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new CosineModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new TangentModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new CotangentModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SecantModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new CosecantModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SineModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new CosineModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new TangentModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new CotangentModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SecantModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new CosecantModifierType());
|
||||
|
||||
// Colors
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SKColorSumModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SKColorSaturateModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SKColorDesaturateModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SKColorBrightenModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SKColorDarkenModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SKColorRotateHueModifierType());
|
||||
RegisterModifierType(Constants.CorePluginInfo, new SKColorInvertModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SKColorSumModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SKColorSaturateModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SKColorDesaturateModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SKColorBrightenModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SKColorDarkenModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SKColorRotateHueModifierType());
|
||||
RegisterModifierType(Constants.CorePlugin, new SKColorInvertModifierType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11,15 +11,16 @@ namespace Artemis.Core.Services
|
||||
public DataModelService(IPluginManagementService pluginManagementService)
|
||||
{
|
||||
// Add data models of already loaded plugins
|
||||
foreach (Module module in pluginManagementService.GetPluginsOfType<Module>().Where(p => p.IsEnabled))
|
||||
foreach (Module module in pluginManagementService.GetFeaturesOfType<Module>().Where(p => p.IsEnabled))
|
||||
AddModuleDataModel(module);
|
||||
foreach (BaseDataModelExpansion dataModelExpansion in pluginManagementService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled))
|
||||
foreach (BaseDataModelExpansion dataModelExpansion in pluginManagementService.GetFeaturesOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled))
|
||||
AddDataModelExpansionDataModel(dataModelExpansion);
|
||||
|
||||
// Add data models of new plugins when they get enabled
|
||||
pluginManagementService.PluginEnabled += PluginServiceOnPluginEnabled;
|
||||
pluginManagementService.PluginFeatureEnabled += OnPluginFeatureEnabled;
|
||||
}
|
||||
|
||||
|
||||
public DataModelRegistration RegisterDataModel(DataModel dataModel)
|
||||
{
|
||||
if (dataModel == null)
|
||||
@ -44,21 +45,16 @@ namespace Artemis.Core.Services
|
||||
return (T) DataModelStore.GetAll().FirstOrDefault(d => d.DataModel is T)?.DataModel;
|
||||
}
|
||||
|
||||
public DataModel GetPluginDataModel(PluginImplementation pluginImplementation)
|
||||
public DataModel? GetPluginDataModel(PluginFeature pluginFeature)
|
||||
{
|
||||
return DataModelStore.Get(pluginImplementation.PluginInfo.Guid)?.DataModel;
|
||||
return DataModelStore.Get(pluginFeature.Id)?.DataModel;
|
||||
}
|
||||
|
||||
public DataModel GetPluginDataModel(Guid pluginGuid)
|
||||
|
||||
private void OnPluginFeatureEnabled(object? sender, PluginFeatureEventArgs e)
|
||||
{
|
||||
return DataModelStore.Get(pluginGuid)?.DataModel;
|
||||
}
|
||||
|
||||
private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
|
||||
{
|
||||
if (e.PluginInfo.Plugin is Module module)
|
||||
if (e.PluginFeature is Module module)
|
||||
AddModuleDataModel(module);
|
||||
else if (e.PluginInfo.Plugin is BaseDataModelExpansion dataModelExpansion)
|
||||
else if (e.PluginFeature is BaseDataModelExpansion dataModelExpansion)
|
||||
AddDataModelExpansionDataModel(dataModelExpansion);
|
||||
}
|
||||
|
||||
@ -68,7 +64,7 @@ namespace Artemis.Core.Services
|
||||
return;
|
||||
|
||||
if (module.InternalDataModel.DataModelDescription == null)
|
||||
throw new ArtemisPluginException(module.PluginInfo, "Module overrides GetDataModelDescription but returned null");
|
||||
throw new ArtemisPluginFeatureException(module, "Module overrides GetDataModelDescription but returned null");
|
||||
|
||||
module.InternalDataModel.IsExpansion = module.InternalExpandsMainDataModel;
|
||||
RegisterDataModel(module.InternalDataModel);
|
||||
@ -77,7 +73,7 @@ namespace Artemis.Core.Services
|
||||
private void AddDataModelExpansionDataModel(BaseDataModelExpansion dataModelExpansion)
|
||||
{
|
||||
if (dataModelExpansion.InternalDataModel.DataModelDescription == null)
|
||||
throw new ArtemisPluginException(dataModelExpansion.PluginInfo, "Data model expansion overrides GetDataModelDescription but returned null");
|
||||
throw new ArtemisPluginFeatureException(dataModelExpansion, "Data model expansion overrides GetDataModelDescription but returned null");
|
||||
|
||||
dataModelExpansion.InternalDataModel.IsExpansion = true;
|
||||
RegisterDataModel(dataModelExpansion.InternalDataModel);
|
||||
|
||||
@ -12,9 +12,9 @@ namespace Artemis.Core.Services
|
||||
/// <summary>
|
||||
/// Registers a new condition operator for use in layer conditions
|
||||
/// </summary>
|
||||
/// <param name="pluginInfo">The PluginInfo of the plugin this condition operator belongs to</param>
|
||||
/// <param name="plugin">The plugin this condition operator belongs to</param>
|
||||
/// <param name="conditionOperator">The condition operator to register</param>
|
||||
ConditionOperatorRegistration RegisterConditionOperator([NotNull] PluginInfo pluginInfo, [NotNull] BaseConditionOperator conditionOperator);
|
||||
ConditionOperatorRegistration RegisterConditionOperator([NotNull] Plugin plugin, [NotNull] BaseConditionOperator conditionOperator);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a condition operator so it is no longer available for use in layer conditions
|
||||
|
||||
@ -12,9 +12,9 @@ namespace Artemis.Core.Services
|
||||
/// <summary>
|
||||
/// Registers a new modifier type for use in data bindings
|
||||
/// </summary>
|
||||
/// <param name="pluginInfo">The PluginInfo of the plugin this modifier type belongs to</param>
|
||||
/// <param name="plugin">The plugin this modifier type belongs to</param>
|
||||
/// <param name="dataBindingModifierType">The modifier type to register</param>
|
||||
DataBindingModifierTypeRegistration RegisterModifierType([NotNull] PluginInfo pluginInfo, [NotNull] BaseDataBindingModifierType dataBindingModifierType);
|
||||
DataBindingModifierTypeRegistration RegisterModifierType([NotNull] Plugin plugin, [NotNull] BaseDataBindingModifierType dataBindingModifierType);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a modifier type so it is no longer available for use in data bindings
|
||||
|
||||
@ -34,13 +34,7 @@ namespace Artemis.Core.Services
|
||||
/// <summary>
|
||||
/// If found, returns the data model of the provided plugin
|
||||
/// </summary>
|
||||
/// <param name="pluginImplementation">The plugin to find the data model of</param>
|
||||
DataModel GetPluginDataModel(PluginImplementation pluginImplementation);
|
||||
|
||||
/// <summary>
|
||||
/// If found, returns the data model of the provided plugin GUID
|
||||
/// </summary>
|
||||
/// <param name="pluginGuid">The GUID of the plugin to find the data model of</param>
|
||||
DataModel GetPluginDataModel(Guid pluginGuid);
|
||||
/// <param name="pluginFeature">The plugin to find the data model of</param>
|
||||
DataModel? GetPluginDataModel(PluginFeature pluginFeature);
|
||||
}
|
||||
}
|
||||
@ -38,11 +38,11 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
PluginSetting<LayerBrushReference> defaultReference = _settingsService.GetSetting("ProfileEditor.DefaultLayerBrushDescriptor", new LayerBrushReference
|
||||
{
|
||||
BrushPluginGuid = Guid.Parse("92a9d6ba-6f7a-4937-94d5-c1d715b4141a"),
|
||||
LayerBrushProviderId = "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba",
|
||||
BrushType = "ColorBrush"
|
||||
});
|
||||
|
||||
return LayerBrushStore.Get(defaultReference.Value.BrushPluginGuid, defaultReference.Value.BrushType)?.LayerBrushDescriptor;
|
||||
return LayerBrushStore.Get(defaultReference.Value.LayerBrushProviderId, defaultReference.Value.BrushType)?.LayerBrushDescriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ namespace Artemis.Core.Services
|
||||
|
||||
internal SettingsService(IPluginRepository pluginRepository)
|
||||
{
|
||||
_pluginSettings = new PluginSettings(Constants.CorePluginInfo, pluginRepository);
|
||||
_pluginSettings = new PluginSettings(Constants.CorePlugin, pluginRepository);
|
||||
}
|
||||
|
||||
public PluginSetting<T> GetSetting<T>(string name, T defaultValue = default)
|
||||
|
||||
@ -38,13 +38,13 @@ namespace Artemis.Core.Services
|
||||
|
||||
public List<ProfileDescriptor> GetProfileDescriptors(ProfileModule module)
|
||||
{
|
||||
List<ProfileEntity> profileEntities = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
||||
List<ProfileEntity> profileEntities = _profileRepository.GetByModuleId(module.Id);
|
||||
return profileEntities.Select(e => new ProfileDescriptor(module, e)).ToList();
|
||||
}
|
||||
|
||||
public ProfileDescriptor CreateProfileDescriptor(ProfileModule module, string name)
|
||||
{
|
||||
ProfileEntity profileEntity = new ProfileEntity {Id = Guid.NewGuid(), Name = name, PluginGuid = module.PluginInfo.Guid};
|
||||
ProfileEntity profileEntity = new ProfileEntity {Id = Guid.NewGuid(), Name = name, ModuleId = module.Id};
|
||||
_profileRepository.Add(profileEntity);
|
||||
|
||||
return new ProfileDescriptor(module, profileEntity);
|
||||
@ -258,7 +258,7 @@ namespace Artemis.Core.Services
|
||||
|
||||
public ProfileDescriptor GetLastActiveProfile(ProfileModule module)
|
||||
{
|
||||
List<ProfileEntity> moduleProfiles = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
||||
List<ProfileEntity> moduleProfiles = _profileRepository.GetByModuleId(module.Id);
|
||||
if (!moduleProfiles.Any())
|
||||
return CreateProfileDescriptor(module, "Default");
|
||||
|
||||
@ -271,7 +271,7 @@ namespace Artemis.Core.Services
|
||||
if (module.ActiveProfile == null)
|
||||
return;
|
||||
|
||||
List<ProfileEntity> profileEntities = _profileRepository.GetByPluginGuid(module.PluginInfo.Guid);
|
||||
List<ProfileEntity> profileEntities = _profileRepository.GetByModuleId(module.Id);
|
||||
foreach (ProfileEntity profileEntity in profileEntities)
|
||||
{
|
||||
profileEntity.IsActive = module.ActiveProfile.EntityId == profileEntity.Id;
|
||||
@ -285,7 +285,7 @@ namespace Artemis.Core.Services
|
||||
/// <param name="surface"></param>
|
||||
private void ActiveProfilesPopulateLeds(ArtemisSurface surface)
|
||||
{
|
||||
List<ProfileModule> profileModules = _pluginManagementService.GetPluginsOfType<ProfileModule>();
|
||||
List<ProfileModule> profileModules = _pluginManagementService.GetFeaturesOfType<ProfileModule>();
|
||||
foreach (ProfileModule profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList())
|
||||
profileModule.ActiveProfile.PopulateLeds(surface);
|
||||
}
|
||||
|
||||
@ -44,8 +44,8 @@ namespace Artemis.Core.Services
|
||||
// Add all current devices
|
||||
foreach (IRGBDevice rgbDevice in _rgbService.LoadedDevices)
|
||||
{
|
||||
PluginImplementation pluginImplementation = _pluginManagementService.GetPluginByDevice(rgbDevice);
|
||||
configuration.Devices.Add(new ArtemisDevice(rgbDevice, pluginImplementation, configuration));
|
||||
PluginFeature pluginFeature = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
|
||||
configuration.Devices.Add(new ArtemisDevice(rgbDevice, pluginFeature, configuration));
|
||||
}
|
||||
|
||||
lock (_surfaceConfigurations)
|
||||
@ -136,8 +136,8 @@ namespace Artemis.Core.Services
|
||||
IRGBDevice device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
|
||||
if (device != null)
|
||||
{
|
||||
PluginImplementation pluginImplementation = _pluginManagementService.GetPluginByDevice(device);
|
||||
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, pluginImplementation, surfaceConfiguration, position));
|
||||
PluginFeature pluginFeature = _pluginManagementService.GetDeviceProviderByDevice(device);
|
||||
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, pluginFeature, surfaceConfiguration, position));
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,8 +178,8 @@ namespace Artemis.Core.Services
|
||||
DeviceEntity existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
|
||||
if (existingDeviceConfig != null)
|
||||
{
|
||||
PluginImplementation pluginImplementation = _pluginManagementService.GetPluginByDevice(rgbDevice);
|
||||
device = new ArtemisDevice(rgbDevice, pluginImplementation, surface, existingDeviceConfig);
|
||||
PluginFeature pluginFeature = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
|
||||
device = new ArtemisDevice(rgbDevice, pluginFeature, surface, existingDeviceConfig);
|
||||
}
|
||||
// Fall back on creating a new device
|
||||
else
|
||||
@ -189,8 +189,8 @@ namespace Artemis.Core.Services
|
||||
rgbDevice.DeviceInfo,
|
||||
deviceIdentifier
|
||||
);
|
||||
PluginImplementation pluginImplementation = _pluginManagementService.GetPluginByDevice(rgbDevice);
|
||||
device = new ArtemisDevice(rgbDevice, pluginImplementation, surface);
|
||||
PluginFeature pluginFeature = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
|
||||
device = new ArtemisDevice(rgbDevice, pluginFeature, surface);
|
||||
}
|
||||
|
||||
surface.Devices.Add(device);
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Core
|
||||
if (Registrations.Any(r => r.ConditionOperator == conditionOperator))
|
||||
throw new ArtemisCoreException($"Condition operator store store already contains operator '{conditionOperator.Description}'");
|
||||
|
||||
registration = new ConditionOperatorRegistration(conditionOperator, conditionOperator.PluginInfo.Plugin) {IsInStore = true};
|
||||
registration = new ConditionOperatorRegistration(conditionOperator, conditionOperator.Plugin) {IsInStore = true};
|
||||
Registrations.Add(registration);
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ namespace Artemis.Core
|
||||
{
|
||||
lock (Registrations)
|
||||
{
|
||||
return Registrations.FirstOrDefault(r => r.PluginImplementation.PluginInfo.Guid == pluginGuid && r.ConditionOperator.GetType().Name == type);
|
||||
return Registrations.FirstOrDefault(r => r.Plugin.Guid == pluginGuid && r.ConditionOperator.GetType().Name == type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Core
|
||||
if (Registrations.Any(r => r.DataBindingModifierType == modifierType))
|
||||
throw new ArtemisCoreException($"Data binding modifier type store already contains modifier '{modifierType.Name}'");
|
||||
|
||||
typeRegistration = new DataBindingModifierTypeRegistration(modifierType, modifierType.PluginInfo.Plugin) { IsInStore = true };
|
||||
typeRegistration = new DataBindingModifierTypeRegistration(modifierType, modifierType.Plugin) { IsInStore = true };
|
||||
Registrations.Add(typeRegistration);
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ namespace Artemis.Core
|
||||
{
|
||||
lock (Registrations)
|
||||
{
|
||||
return Registrations.FirstOrDefault(r => r.PluginImplementation.PluginInfo.Guid == pluginGuid && r.DataBindingModifierType.GetType().Name == type);
|
||||
return Registrations.FirstOrDefault(r => r.Plugin.Guid == pluginGuid && r.DataBindingModifierType.GetType().Name == type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Core
|
||||
if (Registrations.Any(r => r.DataModel == dataModel))
|
||||
throw new ArtemisCoreException($"Data model store already contains data model '{dataModel.DataModelDescription}'");
|
||||
|
||||
registration = new DataModelRegistration(dataModel, dataModel.Implementation.Instance) {IsInStore = true};
|
||||
registration = new DataModelRegistration(dataModel, dataModel.Feature) {IsInStore = true};
|
||||
Registrations.Add(registration);
|
||||
}
|
||||
|
||||
@ -47,11 +47,11 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static DataModelRegistration Get(Guid pluginGuid)
|
||||
public static DataModelRegistration Get(string id)
|
||||
{
|
||||
lock (Registrations)
|
||||
{
|
||||
return Registrations.FirstOrDefault(d => d.PluginImplementation.PluginInfo.Guid == pluginGuid);
|
||||
return Registrations.FirstOrDefault(d => d.PluginFeature.Id == id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Core
|
||||
if (Registrations.Any(r => r.LayerBrushDescriptor == descriptor))
|
||||
throw new ArtemisCoreException($"Store already contains layer brush '{descriptor.DisplayName}'");
|
||||
|
||||
registration = new LayerBrushRegistration(descriptor, descriptor.LayerBrushProvider.PluginInfo.Plugin) {IsInStore = true};
|
||||
registration = new LayerBrushRegistration(descriptor, descriptor.Provider) {IsInStore = true};
|
||||
Registrations.Add(registration);
|
||||
}
|
||||
|
||||
@ -47,11 +47,11 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static LayerBrushRegistration Get(Guid pluginGuid, string typeName)
|
||||
public static LayerBrushRegistration? Get(string id, string typeName)
|
||||
{
|
||||
lock (Registrations)
|
||||
{
|
||||
return Registrations.FirstOrDefault(d => d.PluginImplementation.PluginInfo.Guid == pluginGuid &&
|
||||
return Registrations.FirstOrDefault(d => d.PluginFeature.Id == id &&
|
||||
d.LayerBrushDescriptor.LayerBrushType.Name == typeName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Core
|
||||
if (Registrations.Any(r => r.LayerEffectDescriptor == descriptor))
|
||||
throw new ArtemisCoreException($"Store already contains layer brush '{descriptor.DisplayName}'");
|
||||
|
||||
registration = new LayerEffectRegistration(descriptor, descriptor.LayerEffectProvider.PluginInfo.Plugin) { IsInStore = true };
|
||||
registration = new LayerEffectRegistration(descriptor, descriptor.Provider) { IsInStore = true };
|
||||
Registrations.Add(registration);
|
||||
}
|
||||
|
||||
@ -47,11 +47,11 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static LayerEffectRegistration Get(Guid pluginGuid, string typeName)
|
||||
public static LayerEffectRegistration? Get(string providerId, string typeName)
|
||||
{
|
||||
lock (Registrations)
|
||||
{
|
||||
return Registrations.FirstOrDefault(d => d.PluginImplementation.PluginInfo.Guid == pluginGuid && d.LayerEffectDescriptor.LayerEffectType.Name == typeName);
|
||||
return Registrations.FirstOrDefault(d => d.PluginFeature.Id == providerId && d.LayerEffectDescriptor.LayerEffectType.Name == typeName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,12 +7,12 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public class ConditionOperatorRegistration
|
||||
{
|
||||
internal ConditionOperatorRegistration(BaseConditionOperator conditionOperator, PluginImplementation pluginImplementation)
|
||||
internal ConditionOperatorRegistration(BaseConditionOperator conditionOperator, Plugin plugin)
|
||||
{
|
||||
ConditionOperator = conditionOperator;
|
||||
PluginImplementation = pluginImplementation;
|
||||
Plugin = plugin;
|
||||
|
||||
PluginImplementation.Disabled += OnDisabled;
|
||||
Plugin.Disabled += OnDisabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -23,7 +23,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the plugin the condition operator is associated with
|
||||
/// </summary>
|
||||
public PluginImplementation PluginImplementation { get; }
|
||||
public Plugin Plugin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||
@ -32,7 +32,7 @@ namespace Artemis.Core
|
||||
|
||||
private void OnDisabled(object sender, EventArgs e)
|
||||
{
|
||||
PluginImplementation.Disabled -= OnDisabled;
|
||||
Plugin.Disabled -= OnDisabled;
|
||||
if (IsInStore)
|
||||
ConditionOperatorStore.Remove(this);
|
||||
}
|
||||
|
||||
@ -7,12 +7,12 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public class DataBindingModifierTypeRegistration
|
||||
{
|
||||
internal DataBindingModifierTypeRegistration(BaseDataBindingModifierType dataBindingModifierType, PluginImplementation pluginImplementation)
|
||||
internal DataBindingModifierTypeRegistration(BaseDataBindingModifierType dataBindingModifierType, Plugin plugin)
|
||||
{
|
||||
DataBindingModifierType = dataBindingModifierType;
|
||||
PluginImplementation = pluginImplementation;
|
||||
Plugin = plugin;
|
||||
|
||||
PluginImplementation.Disabled += OnDisabled;
|
||||
Plugin.Disabled += OnDisabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -23,7 +23,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the plugin the data binding modifier is associated with
|
||||
/// </summary>
|
||||
public PluginImplementation PluginImplementation { get; }
|
||||
public Plugin Plugin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||
@ -32,7 +32,7 @@ namespace Artemis.Core
|
||||
|
||||
private void OnDisabled(object sender, EventArgs e)
|
||||
{
|
||||
PluginImplementation.Disabled -= OnDisabled;
|
||||
Plugin.Disabled -= OnDisabled;
|
||||
if (IsInStore)
|
||||
DataBindingModifierTypeStore.Remove(this);
|
||||
}
|
||||
|
||||
@ -8,12 +8,12 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public class DataModelRegistration
|
||||
{
|
||||
internal DataModelRegistration(DataModel dataModel, PluginImplementation pluginImplementation)
|
||||
internal DataModelRegistration(DataModel dataModel, PluginFeature pluginFeature)
|
||||
{
|
||||
DataModel = dataModel;
|
||||
PluginImplementation = pluginImplementation;
|
||||
PluginFeature = pluginFeature;
|
||||
|
||||
PluginImplementation.Disabled += OnDisabled;
|
||||
PluginFeature.Disabled += OnDisabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -24,7 +24,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the plugin the data model is associated with
|
||||
/// </summary>
|
||||
public PluginImplementation PluginImplementation { get; }
|
||||
public PluginFeature PluginFeature { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||
@ -33,7 +33,7 @@ namespace Artemis.Core
|
||||
|
||||
private void OnDisabled(object sender, EventArgs e)
|
||||
{
|
||||
PluginImplementation.Disabled -= OnDisabled;
|
||||
PluginFeature.Disabled -= OnDisabled;
|
||||
if (IsInStore)
|
||||
DataModelStore.Remove(this);
|
||||
}
|
||||
|
||||
@ -8,12 +8,12 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public class LayerBrushRegistration
|
||||
{
|
||||
internal LayerBrushRegistration(LayerBrushDescriptor descriptor, PluginImplementation pluginImplementation)
|
||||
internal LayerBrushRegistration(LayerBrushDescriptor descriptor, PluginFeature pluginFeature)
|
||||
{
|
||||
LayerBrushDescriptor = descriptor;
|
||||
PluginImplementation = pluginImplementation;
|
||||
PluginFeature = pluginFeature;
|
||||
|
||||
PluginImplementation.Disabled += OnDisabled;
|
||||
PluginFeature.Disabled += OnDisabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -24,7 +24,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the plugin the layer brush is associated with
|
||||
/// </summary>
|
||||
public PluginImplementation PluginImplementation { get; }
|
||||
public PluginFeature PluginFeature { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||
@ -33,7 +33,7 @@ namespace Artemis.Core
|
||||
|
||||
private void OnDisabled(object sender, EventArgs e)
|
||||
{
|
||||
PluginImplementation.Disabled -= OnDisabled;
|
||||
PluginFeature.Disabled -= OnDisabled;
|
||||
if (IsInStore)
|
||||
LayerBrushStore.Remove(this);
|
||||
}
|
||||
|
||||
@ -8,12 +8,12 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public class LayerEffectRegistration
|
||||
{
|
||||
internal LayerEffectRegistration(LayerEffectDescriptor descriptor, PluginImplementation pluginImplementation)
|
||||
internal LayerEffectRegistration(LayerEffectDescriptor descriptor, PluginFeature pluginFeature)
|
||||
{
|
||||
LayerEffectDescriptor = descriptor;
|
||||
PluginImplementation = pluginImplementation;
|
||||
PluginFeature = pluginFeature;
|
||||
|
||||
PluginImplementation.Disabled += OnDisabled;
|
||||
PluginFeature.Disabled += OnDisabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -24,7 +24,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the plugin the layer effect is associated with
|
||||
/// </summary>
|
||||
public PluginImplementation PluginImplementation { get; }
|
||||
public PluginFeature PluginFeature { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the registration is in the internal Core store
|
||||
@ -33,7 +33,7 @@ namespace Artemis.Core
|
||||
|
||||
private void OnDisabled(object sender, EventArgs e)
|
||||
{
|
||||
PluginImplementation.Disabled -= OnDisabled;
|
||||
PluginFeature.Disabled -= OnDisabled;
|
||||
if (IsInStore)
|
||||
LayerEffectStore.Remove(this);
|
||||
}
|
||||
|
||||
@ -3,13 +3,13 @@
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty plugin used by <see cref="Constants.CorePluginInfo"/>
|
||||
/// An empty data model plugin feature used by <see cref="Constants.CorePlugin" />
|
||||
/// </summary>
|
||||
internal class CorePluginImplementation : PluginImplementation
|
||||
internal class CorePluginFeature : DataModelPluginFeature
|
||||
{
|
||||
public CorePluginImplementation()
|
||||
public CorePluginFeature()
|
||||
{
|
||||
Constants.CorePluginInfo.Plugin = this;
|
||||
Constants.CorePlugin.AddFeature(this);
|
||||
IsEnabled = true;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
@ -37,8 +37,8 @@ namespace Artemis.Core
|
||||
if (!Debugger.IsAttached)
|
||||
Process.Start(info);
|
||||
|
||||
// Also attempt a graceful shutdown on the UI thread
|
||||
Execute.OnUIThread(() => Application.Current.Shutdown());
|
||||
// Request a graceful shutdown, whatever UI we're running can pick this up
|
||||
OnShutdownRequested();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -64,5 +64,18 @@ namespace Artemis.Core
|
||||
{
|
||||
return Process.GetCurrentProcess().MainModule.FileName;
|
||||
}
|
||||
|
||||
#region Events
|
||||
|
||||
public static event EventHandler ShutdownRequested;
|
||||
|
||||
private static void OnShutdownRequested()
|
||||
{
|
||||
ShutdownRequested?.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -121,15 +121,6 @@
|
||||
"System.Memory": "4.5.3"
|
||||
}
|
||||
},
|
||||
"Stylet": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.3.4, )",
|
||||
"resolved": "1.3.4",
|
||||
"contentHash": "bCEdA+AIi+TM9SQQGLYMsFRIfzZcDUDg2Mznyr72kOkcC/cdBj01/jel4/v2aoKwbFcxVjiqmpgnbsFgMEZ4zQ==",
|
||||
"dependencies": {
|
||||
"System.Drawing.Common": "4.6.0"
|
||||
}
|
||||
},
|
||||
"System.Buffers": {
|
||||
"type": "Direct",
|
||||
"requested": "[4.5.0, )",
|
||||
@ -192,8 +183,8 @@
|
||||
},
|
||||
"Microsoft.NETCore.Platforms": {
|
||||
"type": "Transitive",
|
||||
"resolved": "3.0.0",
|
||||
"contentHash": "TsETIgVJb/AKoYfSP+iCxkuly5d3inZjTdx/ItZLk2CxY85v8083OBS3uai84kK3/baLnS5/b5XGs6zR7SuuHQ=="
|
||||
"resolved": "1.1.0",
|
||||
"contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
|
||||
},
|
||||
"Microsoft.NETCore.Targets": {
|
||||
"type": "Transitive",
|
||||
@ -210,14 +201,6 @@
|
||||
"System.Runtime": "4.3.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Win32.SystemEvents": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.6.0",
|
||||
"contentHash": "Edg+pFW5C8WJb680Za2kTV8TqUi6Ahl/WldRVoOVJ23UQLpDHFspa+umgFjkWZw24ETsU99Cg+ErZz683M4chg==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "3.0.0"
|
||||
}
|
||||
},
|
||||
"NETStandard.Library": {
|
||||
"type": "Transitive",
|
||||
"resolved": "1.6.1",
|
||||
@ -557,15 +540,6 @@
|
||||
"System.Runtime": "4.3.0"
|
||||
}
|
||||
},
|
||||
"System.Drawing.Common": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.6.0",
|
||||
"contentHash": "2A3spjjoPZnvpVh/sDTzd+0H8ZqTdr+hH/6obB8MMfG81EJ85PmxCKDBxhBVQiA25PliKAZ1sKogDcq9mSnFEA==",
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "3.0.0",
|
||||
"Microsoft.Win32.SystemEvents": "4.6.0"
|
||||
}
|
||||
},
|
||||
"System.Dynamic.Runtime": {
|
||||
"type": "Transitive",
|
||||
"resolved": "4.3.0",
|
||||
|
||||
@ -10,7 +10,7 @@ namespace Artemis.Storage.Entities.Module
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
public Guid PluginGuid { get; set; }
|
||||
public string ModuleId { get; set; }
|
||||
public int PriorityCategory { get; set; }
|
||||
public int Priority { get; set; }
|
||||
}
|
||||
|
||||
@ -8,16 +8,21 @@ namespace Artemis.Storage.Entities.Plugins
|
||||
/// </summary>
|
||||
public class PluginEntity
|
||||
{
|
||||
public PluginEntity()
|
||||
{
|
||||
Features = new List<PluginFeatureEntity>();
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public List<PluginImplementationEntity> Implementations { get; set; }
|
||||
public List<PluginFeatureEntity> Features { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the configuration of a plugin implementation, each implementation has one configuration
|
||||
/// Represents the configuration of a plugin feature, each feature has one configuration
|
||||
/// </summary>
|
||||
public class PluginImplementationEntity
|
||||
public class PluginFeatureEntity
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
@ -5,7 +5,7 @@ namespace Artemis.Storage.Entities.Profile
|
||||
public class DataModelPathEntity
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public Guid? DataModelGuid { get; set; }
|
||||
public string DataModelId { get; set; }
|
||||
|
||||
public PathWrapperType WrapperType { get; set; }
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ namespace Artemis.Storage.Entities.Profile
|
||||
public class LayerEffectEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid PluginGuid { get; set; }
|
||||
public string ProviderId { get; set; }
|
||||
public string EffectType { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
@ -13,7 +13,7 @@ namespace Artemis.Storage.Entities.Profile
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
public Guid PluginGuid { get; set; }
|
||||
public string ModuleId { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Storage.Entities.Profile.DataBindings;
|
||||
|
||||
namespace Artemis.Storage.Entities.Profile
|
||||
@ -12,7 +11,7 @@ namespace Artemis.Storage.Entities.Profile
|
||||
DataBindingEntities = new List<DataBindingEntity>();
|
||||
}
|
||||
|
||||
public Guid PluginGuid { get; set; }
|
||||
public string FeatureId { get; set; }
|
||||
public string Path { get; set; }
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Storage.Entities.Module;
|
||||
|
||||
namespace Artemis.Storage.Repositories.Interfaces
|
||||
@ -7,7 +6,7 @@ namespace Artemis.Storage.Repositories.Interfaces
|
||||
public interface IModuleRepository : IRepository
|
||||
{
|
||||
void Add(ModuleSettingsEntity moduleSettingsEntity);
|
||||
ModuleSettingsEntity GetByPluginGuid(Guid guid);
|
||||
ModuleSettingsEntity GetByModuleId(string moduleId);
|
||||
List<ModuleSettingsEntity> GetAll();
|
||||
List<ModuleSettingsEntity> GetByCategory(int category);
|
||||
void Save(ModuleSettingsEntity moduleSettingsEntity);
|
||||
|
||||
@ -10,7 +10,7 @@ namespace Artemis.Storage.Repositories.Interfaces
|
||||
void Remove(ProfileEntity profileEntity);
|
||||
List<ProfileEntity> GetAll();
|
||||
ProfileEntity Get(Guid id);
|
||||
List<ProfileEntity> GetByPluginGuid(Guid pluginGuid);
|
||||
List<ProfileEntity> GetByModuleId(string moduleId);
|
||||
void Save(ProfileEntity profileEntity);
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,7 @@ namespace Artemis.Storage.Repositories
|
||||
internal ModuleRepository(LiteRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
_repository.Database.GetCollection<ModuleSettingsEntity>().EnsureIndex(s => s.PluginGuid, true);
|
||||
_repository.Database.GetCollection<ModuleSettingsEntity>().EnsureIndex(s => s.ModuleId, true);
|
||||
}
|
||||
|
||||
public void Add(ModuleSettingsEntity moduleSettingsEntity)
|
||||
@ -21,9 +21,9 @@ namespace Artemis.Storage.Repositories
|
||||
_repository.Insert(moduleSettingsEntity);
|
||||
}
|
||||
|
||||
public ModuleSettingsEntity GetByPluginGuid(Guid guid)
|
||||
public ModuleSettingsEntity GetByModuleId(string moduleId)
|
||||
{
|
||||
return _repository.FirstOrDefault<ModuleSettingsEntity>(s => s.PluginGuid == guid);
|
||||
return _repository.FirstOrDefault<ModuleSettingsEntity>(s => s.ModuleId == moduleId);
|
||||
}
|
||||
|
||||
public List<ModuleSettingsEntity> GetAll()
|
||||
|
||||
@ -36,12 +36,12 @@ namespace Artemis.Storage.Repositories
|
||||
return _repository.FirstOrDefault<ProfileEntity>(p => p.Id == id);
|
||||
}
|
||||
|
||||
public List<ProfileEntity> GetByPluginGuid(Guid pluginGuid)
|
||||
public List<ProfileEntity> GetByModuleId(string moduleId)
|
||||
{
|
||||
return _repository.Query<ProfileEntity>()
|
||||
.Include(p => p.Folders)
|
||||
.Include(p => p.Layers)
|
||||
.Where(s => s.PluginGuid == pluginGuid)
|
||||
.Where(s => s.ModuleId == moduleId)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=exceptions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=extensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=propertyinput/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cdatamodelvisualization/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cdialog/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@ -11,22 +11,22 @@ namespace Artemis.UI.Shared
|
||||
|
||||
public DataModelVisualizationRegistration(IDataModelUIService dataModelUIService,
|
||||
RegistrationType registrationType,
|
||||
PluginInfo pluginInfo,
|
||||
Plugin plugin,
|
||||
Type supportedType,
|
||||
Type viewModelType)
|
||||
{
|
||||
_dataModelUIService = dataModelUIService;
|
||||
RegistrationType = registrationType;
|
||||
PluginInfo = pluginInfo;
|
||||
Plugin = plugin;
|
||||
SupportedType = supportedType;
|
||||
ViewModelType = viewModelType;
|
||||
|
||||
if (PluginInfo != Constants.CorePluginInfo)
|
||||
PluginInfo.Plugin.Disabled += InstanceOnDisabled;
|
||||
if (Plugin != Constants.CorePlugin)
|
||||
Plugin.Disabled += InstanceOnDisabled;
|
||||
}
|
||||
|
||||
public RegistrationType RegistrationType { get; }
|
||||
public PluginInfo PluginInfo { get; }
|
||||
public Plugin Plugin { get; }
|
||||
public Type SupportedType { get; }
|
||||
public Type ViewModelType { get; }
|
||||
|
||||
@ -34,8 +34,8 @@ namespace Artemis.UI.Shared
|
||||
|
||||
internal void Unsubscribe()
|
||||
{
|
||||
if (PluginInfo != Constants.CorePluginInfo)
|
||||
PluginInfo.Plugin.Disabled -= InstanceOnDisabled;
|
||||
if (Plugin != Constants.CorePlugin)
|
||||
Plugin.Disabled -= InstanceOnDisabled;
|
||||
}
|
||||
|
||||
private void InstanceOnDisabled(object sender, EventArgs e)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using Stylet;
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core.LayerBrushes
|
||||
namespace Artemis.UI.Shared.LayerBrushes
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a view model for a brush configuration window
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using Artemis.Core.LayerBrushes;
|
||||
|
||||
namespace Artemis.Core.LayerBrushes
|
||||
namespace Artemis.UI.Shared.LayerBrushes
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class LayerBrushConfigurationDialog<T> : LayerBrushConfigurationDialog where T : BrushConfigurationViewModel
|
||||
@ -12,7 +13,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
/// <summary>
|
||||
/// Describes a UI tab for a layer brush
|
||||
/// </summary>
|
||||
public abstract class LayerBrushConfigurationDialog
|
||||
public abstract class LayerBrushConfigurationDialog : ILayerBrushConfigurationDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// The layer brush this dialog belongs to
|
||||
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