Core - Added stores for the different register-able types

Profiles - Refactored large parts of the profile structure to use these stores
This commit is contained in:
Robert authored and SpoinkyNL committed 2020-09-09 19:56:06 +02:00
1 parent 4cfe71796c
commit 11de30318e
75 files changed
+1526 -934

No files matched your search

+7 -2
View File
@@ -9,6 +9,7 @@ using Artemis.Core.JsonConverters;
using Artemis.Core.Ninject;
using Artemis.Storage;
using Newtonsoft.Json;
using Ninject;
using RGB.NET.Core;
using Serilog;
using Serilog.Events;
@@ -23,6 +24,7 @@ namespace Artemis.Core.Services
internal class CoreService : ICoreService
{
private readonly Stopwatch _frameStopWatch;
private readonly IKernel _kernel;
private readonly ILogger _logger;
private readonly PluginSetting<LogEventLevel> _loggingLevel;
private readonly IPluginService _pluginService;
@@ -34,9 +36,10 @@ namespace Artemis.Core.Services
private List<Module> _modules;
// ReSharper disable once UnusedParameter.Local - Storage migration service is injected early to ensure it runs before anything else
public CoreService(ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginService pluginService,
IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService, IModuleService moduleService)
public CoreService(IKernel kernel, ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginService pluginService,
IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService)
{
_kernel = kernel;
_logger = logger;
_pluginService = pluginService;
_rgbService = rgbService;
@@ -77,6 +80,8 @@ namespace Artemis.Core.Services
_logger.Information("Initializing Artemis Core version {version}", versionAttribute?.InformationalVersion);
ApplyLoggingLevel();
DeserializationLogger.Initialize(_kernel);
// Initialize the services
_pluginService.CopyBuiltInPlugins();
_pluginService.LoadPlugins(StartupArguments.Contains("--ignore-plugin-lock"));
@@ -1,106 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Serilog;
namespace Artemis.Core.Services
{
internal class DataBindingService : IDataBindingService
{
private readonly ILogger _logger;
private readonly List<DataBindingModifierType> _registeredDataBindingModifierTypes;
public DataBindingService(ILogger logger)
{
_logger = logger;
_registeredDataBindingModifierTypes = new List<DataBindingModifierType>();
RegisterBuiltInModifiers();
}
public IReadOnlyCollection<DataBindingModifierType> RegisteredDataBindingModifierTypes
{
get
{
lock (_registeredDataBindingModifierTypes)
{
return _registeredDataBindingModifierTypes.AsReadOnly();
}
}
}
public void RegisterModifierType(PluginInfo pluginInfo, DataBindingModifierType dataBindingModifierType)
{
if (pluginInfo == null)
throw new ArgumentNullException(nameof(pluginInfo));
if (dataBindingModifierType == null)
throw new ArgumentNullException(nameof(dataBindingModifierType));
lock (_registeredDataBindingModifierTypes)
{
if (_registeredDataBindingModifierTypes.Contains(dataBindingModifierType))
return;
dataBindingModifierType.Register(pluginInfo, this);
_registeredDataBindingModifierTypes.Add(dataBindingModifierType);
}
}
public void RemoveModifierType(DataBindingModifierType dataBindingModifierType)
{
if (dataBindingModifierType == null)
throw new ArgumentNullException(nameof(dataBindingModifierType));
lock (_registeredDataBindingModifierTypes)
{
if (!_registeredDataBindingModifierTypes.Contains(dataBindingModifierType))
return;
dataBindingModifierType.Unsubscribe();
_registeredDataBindingModifierTypes.Remove(dataBindingModifierType);
}
}
public List<DataBindingModifierType> GetCompatibleModifierTypes(Type type)
{
lock (_registeredDataBindingModifierTypes)
{
if (type == null)
return new List<DataBindingModifierType>(_registeredDataBindingModifierTypes);
var candidates = _registeredDataBindingModifierTypes.Where(c => c.CompatibleTypes.Any(t => t.IsCastableFrom(type))).ToList();
// If there are multiple modifier types with the same description, use the closest match
foreach (var dataBindingModifierTypes in candidates.GroupBy(c => c.Description).Where(g => g.Count() > 1).ToList())
{
var bestCandidate = dataBindingModifierTypes.OrderByDescending(c => c.CompatibleTypes.Contains(type)).FirstOrDefault();
foreach (var dataBindingModifierType in dataBindingModifierTypes)
{
if (dataBindingModifierType != bestCandidate)
candidates.Remove(dataBindingModifierType);
}
}
return candidates;
}
}
public DataBindingModifierType GetModifierType(Guid modifierTypePluginGuid, string modifierType)
{
return RegisteredDataBindingModifierTypes.FirstOrDefault(o => o.PluginInfo.Guid == modifierTypePluginGuid && o.GetType().Name == modifierType);
}
public void LogModifierDeserializationFailure(string modifierName, JsonSerializationException exception)
{
_logger.Warning(exception, "Failed to deserialize static parameter for modifier {modifierName}", modifierName);
}
private void RegisterBuiltInModifiers()
{
RegisterModifierType(Constants.CorePluginInfo, new MultiplicationModifierType());
RegisterModifierType(Constants.CorePluginInfo, new DivideModifierType());
RegisterModifierType(Constants.CorePluginInfo, new FloorModifierType());
}
}
}
@@ -1,252 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using Newtonsoft.Json;
using Serilog;
namespace Artemis.Core.Services
{
/// <summary>
/// Provides access to the main data model
/// </summary>
internal class DataModelService : IDataModelService
{
private readonly List<DataModel> _dataModelExpansions;
private readonly ILogger _logger;
private readonly IPluginService _pluginService;
private readonly List<DisplayConditionOperator> _registeredConditionOperators;
public DataModelService(IPluginService pluginService, ILogger logger)
{
_pluginService = pluginService;
_logger = logger;
_dataModelExpansions = new List<DataModel>();
_registeredConditionOperators = new List<DisplayConditionOperator>();
_pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
_pluginService.PluginDisabled += PluginServiceOnPluginDisabled;
RegisterBuiltInConditionOperators();
foreach (var module in _pluginService.GetPluginsOfType<Module>().Where(m => m.InternalExpandsMainDataModel))
AddModuleDataModel(module);
foreach (var dataModelExpansion in _pluginService.GetPluginsOfType<BaseDataModelExpansion>())
AddDataModelExpansionDataModel(dataModelExpansion);
}
public IReadOnlyCollection<DisplayConditionOperator> RegisteredConditionOperators
{
get
{
lock (_registeredConditionOperators)
{
return _registeredConditionOperators.AsReadOnly();
}
}
}
public IReadOnlyCollection<DataModel> DataModelExpansions
{
get
{
lock (_dataModelExpansions)
{
return new List<DataModel>(_dataModelExpansions).AsReadOnly();
}
}
}
public void AddExpansion(DataModel dataModelExpansion)
{
lock (_dataModelExpansions)
{
_dataModelExpansions.Add(dataModelExpansion);
// TODO SpoinkyNL 3-3-2018: Initialize the expansion and fire an event
}
}
public void RemoveExpansion(DataModel dataModelExpansion)
{
lock (_dataModelExpansions)
{
if (!_dataModelExpansions.Contains(dataModelExpansion))
throw new ArtemisCoreException("Cannot remove a data model expansion that wasn't previously added.");
// TODO SpoinkyNL 3-3-2018: Dispose the expansion and fire an event
_dataModelExpansions.Remove(dataModelExpansion);
}
}
public DataModel GetPluginDataModel(Plugin plugin)
{
if (plugin is Module module)
return module.InternalDataModel;
if (plugin is BaseDataModelExpansion dataModelExpansion)
return dataModelExpansion.InternalDataModel;
return null;
}
public DataModel GetPluginDataModelByGuid(Guid pluginGuid)
{
var pluginInfo = _pluginService.GetAllPluginInfo().FirstOrDefault(i => i.Guid == pluginGuid);
if (pluginInfo == null || !pluginInfo.Enabled)
return null;
return GetPluginDataModel(pluginInfo.Instance);
}
public bool GetPluginExtendsDataModel(Plugin plugin)
{
if (plugin is Module module)
return module.InternalExpandsMainDataModel;
if (plugin is BaseDataModelExpansion)
return true;
return false;
}
public void RegisterConditionOperator(PluginInfo pluginInfo, DisplayConditionOperator displayConditionOperator)
{
if (pluginInfo == null)
throw new ArgumentNullException(nameof(pluginInfo));
if (displayConditionOperator == null)
throw new ArgumentNullException(nameof(displayConditionOperator));
lock (_registeredConditionOperators)
{
if (_registeredConditionOperators.Contains(displayConditionOperator))
return;
displayConditionOperator.Register(pluginInfo, this);
_registeredConditionOperators.Add(displayConditionOperator);
}
}
public void RemoveConditionOperator(DisplayConditionOperator displayConditionOperator)
{
if (displayConditionOperator == null)
throw new ArgumentNullException(nameof(displayConditionOperator));
lock (_registeredConditionOperators)
{
if (!_registeredConditionOperators.Contains(displayConditionOperator))
return;
displayConditionOperator.Unsubscribe();
_registeredConditionOperators.Remove(displayConditionOperator);
}
}
public List<DisplayConditionOperator> GetCompatibleConditionOperators(Type type)
{
lock (_registeredConditionOperators)
{
if (type == null)
return new List<DisplayConditionOperator>(_registeredConditionOperators);
var candidates = _registeredConditionOperators.Where(c => c.CompatibleTypes.Any(t => t.IsCastableFrom(type))).ToList();
// If there are multiple operators with the same description, use the closest match
foreach (var displayConditionOperators in candidates.GroupBy(c => c.Description).Where(g => g.Count() > 1).ToList())
{
var bestCandidate = displayConditionOperators.OrderByDescending(c => c.CompatibleTypes.Contains(type)).FirstOrDefault();
foreach (var displayConditionOperator in displayConditionOperators)
{
if (displayConditionOperator != bestCandidate)
candidates.Remove(displayConditionOperator);
}
}
return candidates;
}
}
public DisplayConditionOperator GetConditionOperator(Guid operatorPluginGuid, string operatorType)
{
return RegisteredConditionOperators.FirstOrDefault(o => o.PluginInfo.Guid == operatorPluginGuid && o.GetType().Name == operatorType);
}
public void LogPredicateDeserializationFailure(DisplayConditionPredicate displayConditionPredicate, JsonException exception)
{
_logger.Warning(
exception,
"Failed to deserialize display condition predicate {left} {operator} {right}",
displayConditionPredicate.Entity.LeftPropertyPath,
displayConditionPredicate.Entity.OperatorType,
displayConditionPredicate.Entity.RightPropertyPath
);
}
public void LogListPredicateDeserializationFailure(DisplayConditionListPredicate displayConditionPredicate, JsonException exception)
{
_logger.Warning(
exception,
"Failed to deserialize display condition list predicate {list} => {left} {operator} {right}",
displayConditionPredicate.Entity.ListPropertyPath,
displayConditionPredicate.Entity.LeftPropertyPath,
displayConditionPredicate.Entity.OperatorType,
displayConditionPredicate.Entity.RightPropertyPath
);
}
private void RegisterBuiltInConditionOperators()
{
// General usage for any type
RegisterConditionOperator(Constants.CorePluginInfo, new EqualsConditionOperator());
RegisterConditionOperator(Constants.CorePluginInfo, new NotEqualConditionOperator());
// Numeric operators
RegisterConditionOperator(Constants.CorePluginInfo, new LessThanConditionOperator());
RegisterConditionOperator(Constants.CorePluginInfo, new GreaterThanConditionOperator());
RegisterConditionOperator(Constants.CorePluginInfo, new LessThanOrEqualConditionOperator());
RegisterConditionOperator(Constants.CorePluginInfo, 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 StringNullConditionOperator());
}
private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
{
if (e.PluginInfo.Instance is Module module && module.InternalExpandsMainDataModel)
AddModuleDataModel(module);
else if (e.PluginInfo.Instance is BaseDataModelExpansion dataModelExpansion)
AddDataModelExpansionDataModel(dataModelExpansion);
}
private void AddDataModelExpansionDataModel(BaseDataModelExpansion dataModelExpansion)
{
if (dataModelExpansion.InternalDataModel.DataModelDescription == null)
throw new ArtemisPluginException(dataModelExpansion.PluginInfo, "Data model expansion overrides GetDataModelDescription but returned null");
AddExpansion(dataModelExpansion.InternalDataModel);
}
private void AddModuleDataModel(Module module)
{
if (module.InternalDataModel.DataModelDescription == null)
throw new ArtemisPluginException(module.PluginInfo, "Module overrides GetDataModelDescription but returned null");
AddExpansion(module.InternalDataModel);
}
private void PluginServiceOnPluginDisabled(object sender, PluginEventArgs e)
{
// Remove all data models related to the plugin
lock (_dataModelExpansions)
{
var toRemove = _dataModelExpansions.Where(d => d.PluginInfo == e.PluginInfo).ToList();
foreach (var dataModel in toRemove)
_dataModelExpansions.Remove(dataModel);
}
}
}
}
@@ -3,6 +3,9 @@ using System.Collections.Generic;
namespace Artemis.Core.Services
{
/// <summary>
/// A service that initializes the Core and manages the render loop
/// </summary>
public interface ICoreService : IArtemisService, IDisposable
{
/// <summary>
@@ -1,91 +0,0 @@
using System;
using System.Collections.Generic;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Properties;
using Newtonsoft.Json;
namespace Artemis.Core.Services
{
public interface IDataModelService : IArtemisService
{
/// <summary>
/// Gets a read-only collection of all registered condition operators
/// </summary>
IReadOnlyCollection<DisplayConditionOperator> RegisteredConditionOperators { get; }
/// <summary>
/// Gets a read-only collection of all registered data model expansions
/// </summary>
IReadOnlyCollection<DataModel> DataModelExpansions { get; }
/// <summary>
/// Add an expansion to the datamodel to be available for use after the next update
/// </summary>
/// <param name="baseDataModelExpansion"></param>
void AddExpansion(DataModel baseDataModelExpansion);
/// <summary>
/// Remove a previously added expansion so that it is no longer available and updated
/// </summary>
/// <param name="baseDataModelExpansion"></param>
void RemoveExpansion(DataModel baseDataModelExpansion);
/// <summary>
/// If found, returns the data model of the provided plugin
/// </summary>
/// <param name="plugin">Should be a module with a data model or a data model expansion</param>
DataModel GetPluginDataModel(Plugin plugin);
/// <summary>
/// If found, returns the data model of the provided plugin
/// </summary>
/// <param name="pluginGuid">Should be a module with a data model or a data model expansion</param>
DataModel GetPluginDataModelByGuid(Guid pluginGuid);
/// <summary>
/// Determines whether the given plugin expands the main data model
/// </summary>
/// <param name="plugin"></param>
/// <returns></returns>
bool GetPluginExtendsDataModel(Plugin plugin);
/// <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="displayConditionOperator">The condition operator to register</param>
void RegisterConditionOperator([NotNull] PluginInfo pluginInfo, [NotNull] DisplayConditionOperator displayConditionOperator);
/// <summary>
/// Removes a condition operator so it is no longer available for use in layer conditions
/// </summary>
/// <param name="displayConditionOperator">The layer condition operator to remove</param>
void RemoveConditionOperator([NotNull] DisplayConditionOperator displayConditionOperator);
/// <summary>
/// Returns all the display condition operators compatible with the provided type
/// </summary>
List<DisplayConditionOperator> GetCompatibleConditionOperators(Type type);
/// <summary>
/// Gets a condition operator by its plugin GUID and type name
/// </summary>
/// <param name="operatorPluginGuid">The operator's plugin GUID</param>
/// <param name="operatorType">The type name of the operator</param>
DisplayConditionOperator GetConditionOperator(Guid operatorPluginGuid, string operatorType);
/// <summary>
/// Logs a predicate deserialization failure
/// </summary>
/// <param name="displayConditionPredicate">The predicate that failed to deserialize</param>
/// <param name="exception">The JSON exception that occurred</param>
void LogPredicateDeserializationFailure(DisplayConditionPredicate displayConditionPredicate, JsonException exception);
/// <summary>
/// Logs a list predicate deserialization failure
/// </summary>
/// <param name="displayConditionListPredicate">The list predicate that failed to deserialize</param>
/// <param name="exception">The JSON exception that occurred</param>
void LogListPredicateDeserializationFailure(DisplayConditionListPredicate displayConditionListPredicate, JsonException exception);
}
}
@@ -1,5 +1,8 @@
namespace Artemis.Core.Services
{
/// <summary>
/// A service that allows you manage an <see cref="ArtemisDevice"/>
/// </summary>
public interface IDeviceService : IArtemisService
{
/// <summary>
@@ -1,59 +0,0 @@
using Artemis.Core.LayerBrushes;
using Artemis.Core.LayerEffects;
namespace Artemis.Core.Services
{
public interface IRenderElementService : IArtemisService
{
/// <summary>
/// Creates a new layer
/// </summary>
/// <param name="profile"></param>
/// <param name="parent"></param>
/// <param name="name"></param>
/// <returns></returns>
Layer CreateLayer(Profile profile, ProfileElement parent, string name);
/// <summary>
/// Removes the currently active layer brush from the <see cref="Layer" /> and deletes any settings
/// </summary>
/// <param name="layer">The layer to remove the active brush from</param>
void RemoveLayerBrush(Layer layer);
/// <summary>
/// Deactivates the currently active layer brush from the <see cref="Layer" /> but keeps all settings
/// </summary>
/// <param name="layer">The layer to deactivate the active brush on</param>
void DeactivateLayerBrush(Layer layer);
/// <summary>
/// Instantiates and adds the <see cref="BaseLayerBrush" /> described by the provided
/// <see cref="LayerBrushDescriptor" />
/// to the <see cref="Layer" />.
/// </summary>
/// <param name="layer">The layer to instantiate the brush for</param>
/// <returns></returns>
BaseLayerBrush InstantiateLayerBrush(Layer layer);
/// <summary>
/// Instantiates and adds the <see cref="BaseLayerEffect" /> described by the provided
/// <see cref="LayerEffectDescriptor" /> to the <see cref="Layer" />.
/// </summary>
/// <param name="renderProfileElement">The layer/folder to instantiate the effect for</param>
void InstantiateLayerEffects(RenderProfileElement renderProfileElement);
/// <summary>
/// Adds the <see cref="BaseLayerEffect" /> described by the provided <see cref="LayerEffectDescriptor" /> to the
/// <see cref="Layer" />.
/// </summary>
/// <param name="renderProfileElement">The layer/folder to instantiate the effect for</param>
/// <param name="layerEffectDescriptor"></param>
/// <returns></returns>
BaseLayerEffect AddLayerEffect(RenderProfileElement renderProfileElement, LayerEffectDescriptor layerEffectDescriptor);
void RemoveLayerEffect(BaseLayerEffect layerEffect);
void InstantiateDisplayConditions(RenderProfileElement renderElement);
void InstantiateDataBindings(RenderProfileElement renderElement);
}
}
@@ -4,7 +4,10 @@ using RGB.NET.Core;
namespace Artemis.Core.Services
{
public interface IRgbService : IArtemisService
/// <summary>
/// A service that allows you to manage the <see cref="RGBSurface" /> and its contents
/// </summary>
public interface IRgbService : IArtemisService, IDisposable
{
/// <summary>
/// Gets or sets the RGB surface rendering is performed on
@@ -26,7 +29,14 @@ namespace Artemis.Core.Services
/// </summary>
IReadOnlyCollection<IRGBDevice> LoadedDevices { get; }
/// <summary>
/// Gets the update trigger that drives the render loop
/// </summary>
TimerUpdateTrigger UpdateTrigger { get; }
/// <summary>
/// Gets or sets whether rendering should be paused
/// </summary>
bool IsRenderPaused { get; set; }
/// <summary>
@@ -35,8 +45,6 @@ namespace Artemis.Core.Services
/// <param name="deviceProvider"></param>
void AddDeviceProvider(IRGBDeviceProvider deviceProvider);
void Dispose();
/// <summary>
/// Occurs when a single device has loaded
/// </summary>
@@ -47,6 +55,9 @@ namespace Artemis.Core.Services
/// </summary>
event EventHandler<DeviceEventArgs> DeviceReloaded;
/// <summary>
/// Recalculates the LED group used by the <see cref="BitmapBrush" />
/// </summary>
void UpdateSurfaceLedGroup();
}
}
@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Artemis.Core.Services
{
internal class ConditionOperatorService : IConditionOperatorService
{
public ConditionOperatorService()
{
RegisterBuiltInConditionOperators();
}
public ConditionOperatorRegistration RegisterConditionOperator(PluginInfo pluginInfo, ConditionOperator conditionOperator)
{
if (pluginInfo == null)
throw new ArgumentNullException(nameof(pluginInfo));
if (conditionOperator == null)
throw new ArgumentNullException(nameof(conditionOperator));
conditionOperator.PluginInfo = pluginInfo;
return ConditionOperatorStore.Add(conditionOperator);
}
public void RemoveConditionOperator(ConditionOperatorRegistration registration)
{
if (registration == null)
throw new ArgumentNullException(nameof(registration));
ConditionOperatorStore.Remove(registration);
}
public List<ConditionOperator> GetConditionOperatorsForType(Type type)
{
return ConditionOperatorStore.GetForType(type).Select(r => r.ConditionOperator).ToList();
}
public ConditionOperator GetConditionOperator(Guid operatorPluginGuid, string operatorType)
{
return ConditionOperatorStore.Get(operatorPluginGuid, operatorType)?.ConditionOperator;
}
private void RegisterBuiltInConditionOperators()
{
// General usage for any type
RegisterConditionOperator(Constants.CorePluginInfo, new EqualsConditionOperator());
RegisterConditionOperator(Constants.CorePluginInfo, new NotEqualConditionOperator());
// Numeric operators
RegisterConditionOperator(Constants.CorePluginInfo, new LessThanConditionOperator());
RegisterConditionOperator(Constants.CorePluginInfo, new GreaterThanConditionOperator());
RegisterConditionOperator(Constants.CorePluginInfo, new LessThanOrEqualConditionOperator());
RegisterConditionOperator(Constants.CorePluginInfo, 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 StringNullConditionOperator());
}
}
}
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Artemis.Core.Services
{
internal class DataBindingService : IDataBindingService
{
public DataBindingService()
{
RegisterBuiltInModifiers();
}
public DataBindingModifierTypeRegistration RegisterModifierType(PluginInfo pluginInfo, DataBindingModifierType dataBindingModifierType)
{
if (pluginInfo == null)
throw new ArgumentNullException(nameof(pluginInfo));
if (dataBindingModifierType == null)
throw new ArgumentNullException(nameof(dataBindingModifierType));
dataBindingModifierType.PluginInfo = pluginInfo;
return DataBindingModifierTypeStore.Add(dataBindingModifierType);
}
public void RemoveModifierType(DataBindingModifierTypeRegistration registration)
{
if (registration == null)
throw new ArgumentNullException(nameof(registration));
DataBindingModifierTypeStore.Remove(registration);
}
public List<DataBindingModifierType> GetCompatibleModifierTypes(Type type)
{
return DataBindingModifierTypeStore.GetForType(type).Select(r => r.DataBindingModifierType).ToList();
}
public DataBindingModifierType GetModifierType(Guid modifierTypePluginGuid, string modifierType)
{
return DataBindingModifierTypeStore.Get(modifierTypePluginGuid, modifierType)?.DataBindingModifierType;
}
private void RegisterBuiltInModifiers()
{
RegisterModifierType(Constants.CorePluginInfo, new MultiplicationModifierType());
RegisterModifierType(Constants.CorePluginInfo, new DivideModifierType());
RegisterModifierType(Constants.CorePluginInfo, new FloorModifierType());
}
}
}
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
namespace Artemis.Core.Services
{
internal class DataModelService : IDataModelService
{
public DataModelService(IPluginService pluginService)
{
// Add data models of already loaded plugins
foreach (var module in pluginService.GetPluginsOfType<Module>())
AddModuleDataModel(module);
foreach (var dataModelExpansion in pluginService.GetPluginsOfType<BaseDataModelExpansion>())
AddDataModelExpansionDataModel(dataModelExpansion);
// Add data models of new plugins when they get enabled
pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
}
public DataModelRegistration RegisterDataModel(DataModel dataModel)
{
if (dataModel == null)
throw new ArgumentNullException(nameof(dataModel));
return DataModelStore.Add(dataModel);
}
public void RemoveDataModel(DataModelRegistration registration)
{
if (registration == null)
throw new ArgumentNullException(nameof(registration));
DataModelStore.Remove(registration);
}
public List<DataModel> GetDataModels()
{
return DataModelStore.GetAll().Select(d => d.DataModel).ToList();
}
public T GetDataModel<T>() where T : DataModel
{
return (T) DataModelStore.GetAll().FirstOrDefault(d => d.DataModel is T)?.DataModel;
}
public DataModel GetPluginDataModel(Plugin plugin)
{
return DataModelStore.Get(plugin.PluginInfo.Guid)?.DataModel;
}
public DataModel GetPluginDataModel(Guid pluginGuid)
{
return DataModelStore.Get(pluginGuid)?.DataModel;
}
private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
{
if (e.PluginInfo.Instance is Module module)
AddModuleDataModel(module);
else if (e.PluginInfo.Instance is BaseDataModelExpansion dataModelExpansion)
AddDataModelExpansionDataModel(dataModelExpansion);
}
private void AddModuleDataModel(Module module)
{
if (module.InternalDataModel == null)
return;
if (module.InternalDataModel.DataModelDescription == null)
throw new ArtemisPluginException(module.PluginInfo, "Module overrides GetDataModelDescription but returned null");
module.InternalDataModel.IsExpansion = module.InternalExpandsMainDataModel;
RegisterDataModel(module.InternalDataModel);
}
private void AddDataModelExpansionDataModel(BaseDataModelExpansion dataModelExpansion)
{
if (dataModelExpansion.InternalDataModel.DataModelDescription == null)
throw new ArtemisPluginException(dataModelExpansion.PluginInfo, "Data model expansion overrides GetDataModelDescription but returned null");
dataModelExpansion.InternalDataModel.IsExpansion = true;
RegisterDataModel(dataModelExpansion.InternalDataModel);
}
}
}
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using Artemis.Core.Properties;
namespace Artemis.Core.Services
{
/// <summary>
/// A service that allows you to register and retrieve conditions operators used by display conditions
/// </summary>
public interface IConditionOperatorService : IArtemisService
{
/// <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="conditionOperator">The condition operator to register</param>
ConditionOperatorRegistration RegisterConditionOperator([NotNull] PluginInfo pluginInfo, [NotNull] ConditionOperator conditionOperator);
/// <summary>
/// Removes a condition operator so it is no longer available for use in layer conditions
/// </summary>
/// <param name="registration">The registration of the condition operator to remove</param>
void RemoveConditionOperator([NotNull] ConditionOperatorRegistration registration);
/// <summary>
/// Returns all the condition operators compatible with the provided type
/// </summary>
List<ConditionOperator> GetConditionOperatorsForType(Type type);
/// <summary>
/// Gets a condition operator by its plugin GUID and type name
/// </summary>
/// <param name="operatorPluginGuid">The operator's plugin GUID</param>
/// <param name="operatorType">The type name of the operator</param>
ConditionOperator GetConditionOperator(Guid operatorPluginGuid, string operatorType);
}
}
@@ -1,29 +1,26 @@
using System;
using System.Collections.Generic;
using Artemis.Core.Properties;
using Newtonsoft.Json;
namespace Artemis.Core.Services
{
/// <summary>
/// A service that allows you to register and retrieve data binding modifiers used by the data bindings system
/// </summary>
public interface IDataBindingService : IArtemisService
{
/// <summary>
/// Gets a read-only collection of all registered modifier types
/// </summary>
IReadOnlyCollection<DataBindingModifierType> RegisteredDataBindingModifierTypes { get; }
/// <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="dataBindingModifierType">The modifier type to register</param>
void RegisterModifierType([NotNull] PluginInfo pluginInfo, [NotNull] DataBindingModifierType dataBindingModifierType);
DataBindingModifierTypeRegistration RegisterModifierType([NotNull] PluginInfo pluginInfo, [NotNull] DataBindingModifierType dataBindingModifierType);
/// <summary>
/// Removes a modifier type so it is no longer available for use in data bindings
/// </summary>
/// <param name="dataBindingModifierType">The modifier type to remove</param>
void RemoveModifierType([NotNull] DataBindingModifierType dataBindingModifierType);
/// <param name="dataBindingModifierType">The registration of the modifier type to remove</param>
void RemoveModifierType([NotNull] DataBindingModifierTypeRegistration dataBindingModifierType);
/// <summary>
/// Returns all the data binding modifier types compatible with the provided type
@@ -37,12 +34,5 @@ namespace Artemis.Core.Services
/// <param name="modifierType">The type name of the modifier type</param>
/// <returns></returns>
DataBindingModifierType GetModifierType(Guid modifierTypePluginGuid, string modifierType);
/// <summary>
/// Logs a modifier deserialization failure
/// </summary>
/// <param name="modifierName">The modifier that failed to deserialize</param>
/// <param name="exception">The JSON exception that occurred</param>
void LogModifierDeserializationFailure(string modifierName, JsonSerializationException exception);
}
}
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using Artemis.Core.DataModelExpansions;
namespace Artemis.Core.Services
{
/// <summary>
/// A service that allows you to register and retrieve data models
/// </summary>
public interface IDataModelService : IArtemisService
{
/// <summary>
/// Add a data model to so that it is available to conditions and data bindings
/// </summary>
/// <param name="dataModel"></param>
DataModelRegistration RegisterDataModel(DataModel dataModel);
/// <summary>
/// Remove a previously added data model so that it is no longer available
/// </summary>
void RemoveDataModel(DataModelRegistration registration);
/// <summary>
/// Returns a list of all registered data models
/// </summary>
List<DataModel> GetDataModels();
/// <summary>
/// If found, returns the registered data model of type <typeparamref name="T" />
/// </summary>
/// <typeparam name="T">The type of the data model to find</typeparam>
T GetDataModel<T>() where T : DataModel;
/// <summary>
/// If found, returns the data model of the provided plugin
/// </summary>
/// <param name="plugin">The plugin to find the data model of</param>
DataModel GetPluginDataModel(Plugin plugin);
/// <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);
}
}
@@ -0,0 +1,26 @@
using System.Collections.Generic;
using Artemis.Core.LayerBrushes;
namespace Artemis.Core.Services
{
/// <summary>
/// A service that allows you to register and retrieve layer brushes
/// </summary>
public interface ILayerBrushService : IArtemisService
{
/// <summary>
/// Add a layer brush descriptor so that it is available to layers
/// </summary>
LayerBrushRegistration RegisterLayerBrush(LayerBrushDescriptor descriptor);
/// <summary>
/// Remove a previously added layer brush descriptor so that it is no longer available
/// </summary>
void RemoveLayerBrush(LayerBrushRegistration registration);
/// <summary>
/// Returns a list of all registered layer brush descriptors
/// </summary>
List<LayerBrushDescriptor> GetLayerBrushes();
}
}
@@ -0,0 +1,27 @@
using System.Collections.Generic;
using Artemis.Core.LayerBrushes;
using Artemis.Core.LayerEffects;
namespace Artemis.Core.Services
{
/// <summary>
/// A service that allows you to register and retrieve layer brushes
/// </summary>
public interface ILayerEffectService : IArtemisService
{
/// <summary>
/// Add an effect descriptor so that it is available to profile elements
/// </summary>
LayerEffectRegistration RegisterLayerEffect(LayerEffectDescriptor descriptor);
/// <summary>
/// Remove a previously added layer effect descriptor so that it is no longer available
/// </summary>
void RemoveLayerEffect(LayerEffectRegistration registration);
/// <summary>
/// Returns a list of all registered layer effect descriptors
/// </summary>
List<LayerEffectDescriptor> GetLayerEffects();
}
}
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.LayerBrushes;
using Ninject;
namespace Artemis.Core.Services
{
internal class LayerBrushService : ILayerBrushService
{
private readonly IKernel _kernel;
public LayerBrushService(IKernel kernel)
{
_kernel = kernel;
}
public LayerBrushRegistration RegisterLayerBrush(LayerBrushDescriptor descriptor)
{
if (descriptor == null)
throw new ArgumentNullException(nameof(descriptor));
descriptor.Kernel = _kernel;
return LayerBrushStore.Add(descriptor);
}
public void RemoveLayerBrush(LayerBrushRegistration registration)
{
if (registration == null)
throw new ArgumentNullException(nameof(registration));
LayerBrushStore.Remove(registration);
}
public List<LayerBrushDescriptor> GetLayerBrushes()
{
return LayerBrushStore.GetAll().Select(r => r.LayerBrushDescriptor).ToList();
}
}
}
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core.LayerEffects;
using Ninject;
namespace Artemis.Core.Services
{
internal class LayerEffectService : ILayerEffectService
{
private readonly IKernel _kernel;
public LayerEffectService(IKernel kernel)
{
_kernel = kernel;
}
public LayerEffectRegistration RegisterLayerEffect(LayerEffectDescriptor descriptor)
{
if (descriptor == null)
throw new ArgumentNullException(nameof(descriptor));
descriptor.Kernel = _kernel;
return LayerEffectStore.Add(descriptor);
}
public void RemoveLayerEffect(LayerEffectRegistration registration)
{
if (registration == null)
throw new ArgumentNullException(nameof(registration));
LayerEffectStore.Remove(registration);
}
public List<LayerEffectDescriptor> GetLayerEffects()
{
return LayerEffectStore.GetAll().Select(r => r.LayerEffectDescriptor).ToList();
}
}
}
@@ -1,168 +0,0 @@
using System;
using System.Linq;
using Artemis.Core.LayerBrushes;
using Artemis.Core.LayerEffects;
using Ninject;
using Serilog;
namespace Artemis.Core.Services
{
internal class RenderElementService : IRenderElementService
{
private readonly IDataModelService _dataModelService;
private readonly IDataBindingService _dataBindingService;
private readonly IKernel _kernel;
private readonly ILogger _logger;
private readonly IPluginService _pluginService;
public RenderElementService(IKernel kernel, ILogger logger, IPluginService pluginService, IDataModelService dataModelService, IDataBindingService dataBindingService)
{
_kernel = kernel;
_logger = logger;
_pluginService = pluginService;
_dataModelService = dataModelService;
_dataBindingService = dataBindingService;
}
public Layer CreateLayer(Profile profile, ProfileElement parent, string name)
{
var layer = new Layer(profile, parent, name);
parent.AddChild(layer);
// Layers have two hardcoded property groups, instantiate them
layer.General.Initialize(layer, "General.", Constants.CorePluginInfo);
layer.Transform.Initialize(layer, "Transform.", Constants.CorePluginInfo);
// With the properties loaded, the layer brush and effect can be instantiated
InstantiateLayerBrush(layer);
InstantiateLayerEffects(layer);
InstantiateDisplayConditions(layer);
InstantiateDataBindings(layer);
return layer;
}
public void RemoveLayerBrush(Layer layer)
{
layer.RemoveLayerBrush();
layer.OnLayerBrushUpdated();
}
public void DeactivateLayerBrush(Layer layer)
{
layer.DeactivateLayerBrush();
layer.OnLayerBrushUpdated();
}
public BaseLayerBrush InstantiateLayerBrush(Layer layer)
{
if (layer.LayerBrush != null)
throw new ArtemisCoreException("Layer already has an instantiated layer brush");
var descriptorReference = layer.General.BrushReference?.CurrentValue;
if (descriptorReference == null)
return null;
// Get a matching descriptor
var layerBrushProviders = _pluginService.GetPluginsOfType<LayerBrushProvider>();
var descriptors = layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors).ToList();
var descriptor = descriptors.FirstOrDefault(d => d.LayerBrushProvider.PluginInfo.Guid == descriptorReference.BrushPluginGuid &&
d.LayerBrushType.Name == descriptorReference.BrushType);
if (descriptor == null)
return null;
var brush = (BaseLayerBrush) _kernel.Get(descriptor.LayerBrushType);
brush.Layer = layer;
brush.Descriptor = descriptor;
brush.Initialize();
brush.Update(0);
layer.LayerBrush = brush;
layer.OnLayerBrushUpdated();
return brush;
}
public BaseLayerEffect AddLayerEffect(RenderProfileElement renderElement, LayerEffectDescriptor layerEffectDescriptor)
{
// Create the effect with dependency injection
var effect = (BaseLayerEffect) _kernel.Get(layerEffectDescriptor.LayerEffectType);
effect.ProfileElement = renderElement;
effect.EntityId = Guid.NewGuid();
effect.Enabled = true;
effect.Order = renderElement.LayerEffects.Count + 1;
effect.Descriptor = layerEffectDescriptor;
effect.Initialize();
effect.Update(0);
renderElement.AddLayerEffect(effect);
_logger.Debug("Added layer effect with root path {rootPath}", effect.PropertyRootPath);
return effect;
}
public void RemoveLayerEffect(BaseLayerEffect layerEffect)
{
layerEffect.ProfileElement.RemoveLayerEffect(layerEffect);
}
public void InstantiateLayerEffects(RenderProfileElement renderElement)
{
var layerEffectProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>();
var descriptors = layerEffectProviders.SelectMany(l => l.LayerEffectDescriptors).ToList();
var entities = renderElement.RenderElementEntity.LayerEffects.OrderByDescending(e => e.Order).ToList();
foreach (var layerEffectEntity in entities)
{
// Skip effects already on the element
if (renderElement.LayerEffects.Any(e => e.EntityId == layerEffectEntity.Id))
continue;
// Get a matching descriptor
var descriptor = descriptors.FirstOrDefault(d => d.LayerEffectProvider.PluginInfo.Guid == layerEffectEntity.PluginGuid &&
d.LayerEffectType.Name == layerEffectEntity.EffectType);
if (descriptor == null)
continue;
// Create the effect with dependency injection
var effect = (BaseLayerEffect) _kernel.Get(descriptor.LayerEffectType);
effect.ProfileElement = renderElement;
effect.EntityId = layerEffectEntity.Id;
effect.Order = layerEffectEntity.Order;
effect.Name = layerEffectEntity.Name;
effect.Enabled = layerEffectEntity.Enabled;
effect.Descriptor = descriptor;
effect.Initialize();
effect.Update(0);
renderElement.AddLayerEffect(effect);
_logger.Debug("Instantiated layer effect with root path {rootPath}", effect.PropertyRootPath);
}
}
public void InstantiateDisplayConditions(RenderProfileElement renderElement)
{
var displayCondition = renderElement.RenderElementEntity.RootDisplayCondition != null
? new DisplayConditionGroup(null, renderElement.RenderElementEntity.RootDisplayCondition)
: new DisplayConditionGroup(null);
try
{
displayCondition.Initialize(_dataModelService);
renderElement.DisplayConditionGroup = displayCondition;
}
catch (Exception e)
{
_logger.Warning(e, $"Failed to init display conditions for {renderElement}");
}
}
public void InstantiateDataBindings(RenderProfileElement renderElement)
{
renderElement.InitializeDataBindings(_dataBindingService, _dataModelService);
}
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ namespace Artemis.Core.Services
/// <summary>
/// Provides wrapped access the RGB.NET
/// </summary>
internal class RgbService : IRgbService, IDisposable
internal class RgbService : IRgbService
{
private readonly List<IRGBDevice> _loadedDevices;
private readonly ILogger _logger;
@@ -158,13 +158,13 @@ namespace Artemis.Core.Services
profile.RedoStack.Clear();
profile.UndoStack.Push(memento);
profile.ApplyToEntity();
profile.Save();
if (includeChildren)
{
foreach (var folder in profile.GetAllFolders())
folder.ApplyToEntity();
folder.Save();
foreach (var layer in profile.GetAllLayers())
layer.ApplyToEntity();
layer.Save();
}
_profileRepository.Save(profile.ProfileEntity);