mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 11:26:27 +00:00
Plugins - Implemented features
Core - Removed Stylet dependency for #500
This commit is contained in:
1 parent
b56966c585
commit
e812929215
139 files changed
+1635
-1106
No files matched your search
@@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public interface IPluginConfigurationDialog
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a view model for a plugin configuration window
|
||||
/// </summary>
|
||||
public interface IPluginConfigurationViewModel
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core.LayerBrushes
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a view model for a brush configuration window
|
||||
/// </summary>
|
||||
public abstract class BrushConfigurationViewModel : Screen
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="BrushConfigurationViewModel" /> class
|
||||
/// </summary>
|
||||
/// <param name="layerBrush"></param>
|
||||
protected BrushConfigurationViewModel(BaseLayerBrush layerBrush)
|
||||
{
|
||||
LayerBrush = layerBrush;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="BrushConfigurationViewModel" /> class with a validator
|
||||
/// </summary>
|
||||
/// <param name="layerBrush"></param>
|
||||
/// <param name="validator"></param>
|
||||
protected BrushConfigurationViewModel(BaseLayerBrush layerBrush, IModelValidator validator) : base(validator)
|
||||
{
|
||||
LayerBrush = layerBrush;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the layer brush this view model is associated with
|
||||
/// </summary>
|
||||
public BaseLayerBrush LayerBrush { get; }
|
||||
}
|
||||
}
|
||||
@@ -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,27 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core.LayerBrushes
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class LayerBrushConfigurationDialog<T> : LayerBrushConfigurationDialog where T : BrushConfigurationViewModel
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override Type Type => typeof(T);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes a UI tab for a layer brush
|
||||
/// </summary>
|
||||
public abstract class LayerBrushConfigurationDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// The layer brush this dialog belongs to
|
||||
/// </summary>
|
||||
internal BaseLayerBrush LayerBrush { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of view model the tab contains
|
||||
/// </summary>
|
||||
public abstract Type Type { get; }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core.LayerEffects
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a view model for an effect configuration window
|
||||
/// </summary>
|
||||
public abstract class EffectConfigurationViewModel : Screen
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="EffectConfigurationViewModel" /> class
|
||||
/// </summary>
|
||||
/// <param name="layerEffect"></param>
|
||||
protected EffectConfigurationViewModel(BaseLayerEffect layerEffect)
|
||||
{
|
||||
LayerEffect = layerEffect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="EffectConfigurationViewModel" /> class with a validator
|
||||
/// </summary>
|
||||
/// <param name="layerEffect"></param>
|
||||
/// <param name="validator"></param>
|
||||
protected EffectConfigurationViewModel(BaseLayerEffect layerEffect, IModelValidator validator) : base(validator)
|
||||
{
|
||||
LayerEffect = layerEffect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the layer effect this view model is associated with
|
||||
/// </summary>
|
||||
public BaseLayerEffect LayerEffect { get; }
|
||||
}
|
||||
}
|
||||
@@ -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,27 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core.LayerEffects
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class LayerEffectConfigurationDialog<T> : LayerEffectConfigurationDialog where T : EffectConfigurationViewModel
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override Type Type => typeof(T);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes a UI tab for a specific layer effect
|
||||
/// </summary>
|
||||
public abstract class LayerEffectConfigurationDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// The layer effect this dialog belongs to
|
||||
/// </summary>
|
||||
internal BaseLayerEffect LayerEffect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of view model the tab contains
|
||||
/// </summary>
|
||||
public abstract Type Type { get; }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
+3
-5
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core.Modules
|
||||
{
|
||||
/// <summary>
|
||||
/// The base class for any view model that belongs to a module
|
||||
/// </summary>
|
||||
public abstract class ModuleViewModel : Screen
|
||||
{
|
||||
/// <summary>
|
||||
/// The base class for any view model that belongs to a module
|
||||
/// </summary>
|
||||
/// <param name="module">The module this view model belongs to</param>
|
||||
/// <param name="displayName">The name of the tab that's shown on the modules UI page</param>
|
||||
protected ModuleViewModel(Module module, string displayName)
|
||||
{
|
||||
Module = module;
|
||||
DisplayName = displayName.ToUpper();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the module this view model belongs to
|
||||
/// </summary>
|
||||
public Module Module { get; }
|
||||
}
|
||||
}
|
||||
@@ -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,27 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class PluginConfigurationDialog<T> : PluginConfigurationDialog where T : PluginConfigurationViewModel
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override Type Type => typeof(T);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes a configuration dialog for a specific plugin
|
||||
/// </summary>
|
||||
public abstract class PluginConfigurationDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// The layer brush this dialog belongs to
|
||||
/// </summary>
|
||||
internal PluginImplementation PluginImplementation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of view model the tab contains
|
||||
/// </summary>
|
||||
public abstract Type Type { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a view model for a plugin configuration window
|
||||
/// </summary>
|
||||
public abstract class PluginConfigurationViewModel : Screen
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="PluginConfigurationViewModel" /> class
|
||||
/// </summary>
|
||||
/// <param name="pluginImplementation"></param>
|
||||
protected PluginConfigurationViewModel(PluginImplementation pluginImplementation)
|
||||
{
|
||||
PluginImplementation = pluginImplementation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="PluginConfigurationViewModel" /> class with a validator
|
||||
/// </summary>
|
||||
/// <param name="pluginImplementation"></param>
|
||||
/// <param name="validator"></param>
|
||||
protected PluginConfigurationViewModel(PluginImplementation pluginImplementation, IModelValidator validator) : base(validator)
|
||||
{
|
||||
PluginImplementation = pluginImplementation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin this configuration view model is associated with
|
||||
/// </summary>
|
||||
public PluginImplementation PluginImplementation { get; }
|
||||
}
|
||||
}
|
||||
+26
-32
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user