diff --git a/src/Artemis.Core/Constants.cs b/src/Artemis.Core/Constants.cs
index 36f32cada..9a0ba95c4 100644
--- a/src/Artemis.Core/Constants.cs
+++ b/src/Artemis.Core/Constants.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using Artemis.Storage.Entities.Plugins;
namespace Artemis.Core
{
@@ -34,13 +35,13 @@ namespace Artemis.Core
///
public static readonly PluginInfo CorePluginInfo = new PluginInfo
{
- Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core"
+ Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core", Version = new Version(2,0)
};
///
/// The plugin used by core components of Artemis
///
- public static readonly Plugin CorePlugin = new Plugin(CorePluginInfo, new DirectoryInfo(ApplicationFolder));
+ public static readonly Plugin CorePlugin = new Plugin(CorePluginInfo, new DirectoryInfo(ApplicationFolder), null);
internal static readonly CorePluginFeature CorePluginFeature = new CorePluginFeature {Plugin = CorePlugin};
internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new EffectPlaceholderPlugin {Plugin = CorePlugin};
diff --git a/src/Artemis.Core/Extensions/ProcessExtensions.cs b/src/Artemis.Core/Extensions/ProcessExtensions.cs
index eb02a3c75..28685d781 100644
--- a/src/Artemis.Core/Extensions/ProcessExtensions.cs
+++ b/src/Artemis.Core/Extensions/ProcessExtensions.cs
@@ -8,6 +8,7 @@ namespace Artemis.Core
///
/// A static class providing extensions
///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1060:Move pinvokes to native methods class", Justification = "I don't care, piss off")]
public static class ProcessExtensions
{
///
diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs
index f764ca544..5b2c695d3 100644
--- a/src/Artemis.Core/Models/Profile/Folder.cs
+++ b/src/Artemis.Core/Models/Profile/Folder.cs
@@ -20,7 +20,7 @@ namespace Artemis.Core
///
/// The parent of the folder
/// The name of the folder
- public Folder(ProfileElement parent, string name)
+ public Folder(ProfileElement parent, string name) : base(parent.Profile)
{
FolderEntity = new FolderEntity();
EntityId = Guid.NewGuid();
@@ -29,14 +29,11 @@ namespace Artemis.Core
Profile = Parent.Profile;
Name = name;
Enabled = true;
-
- LayerEffectsList = new List();
- ExpandedPropertyGroups = new List();
-
+
Parent.AddChild(this);
}
- internal Folder(Profile profile, ProfileElement parent, FolderEntity folderEntity)
+ internal Folder(Profile profile, ProfileElement parent, FolderEntity folderEntity) : base(parent.Profile)
{
FolderEntity = folderEntity;
EntityId = folderEntity.Id;
@@ -46,10 +43,7 @@ namespace Artemis.Core
Name = folderEntity.Name;
Enabled = folderEntity.Enabled;
Order = folderEntity.Order;
-
- LayerEffectsList = new List();
- ExpandedPropertyGroups = new List();
-
+
Load();
}
diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs
index 89c91cf3e..259a13e03 100644
--- a/src/Artemis.Core/Models/Profile/Layer.cs
+++ b/src/Artemis.Core/Models/Profile/Layer.cs
@@ -28,7 +28,7 @@ namespace Artemis.Core
///
/// The parent of the layer
/// The name of the layer
- public Layer(ProfileElement parent, string name)
+ public Layer(ProfileElement parent, string name) : base(parent.Profile)
{
LayerEntity = new LayerEntity();
EntityId = Guid.NewGuid();
@@ -39,16 +39,14 @@ namespace Artemis.Core
Enabled = true;
_general = new LayerGeneralProperties();
_transform = new LayerTransformProperties();
-
- LayerEffectsList = new List();
+
_leds = new List();
- ExpandedPropertyGroups = new List();
-
+
Initialize();
Parent.AddChild(this);
}
- internal Layer(Profile profile, ProfileElement parent, LayerEntity layerEntity)
+ internal Layer(Profile profile, ProfileElement parent, LayerEntity layerEntity) : base(parent.Profile)
{
LayerEntity = layerEntity;
EntityId = layerEntity.Id;
@@ -57,10 +55,8 @@ namespace Artemis.Core
Parent = parent;
_general = new LayerGeneralProperties();
_transform = new LayerTransformProperties();
-
- LayerEffectsList = new List();
+
_leds = new List();
- ExpandedPropertyGroups = new List();
Load();
Initialize();
@@ -263,17 +259,12 @@ namespace Artemis.Core
private void ApplyShapeType()
{
- switch (General.ShapeType.CurrentValue)
+ LayerShape = General.ShapeType.CurrentValue switch
{
- case LayerShapeType.Ellipse:
- LayerShape = new EllipseShape(this);
- break;
- case LayerShapeType.Rectangle:
- LayerShape = new RectangleShape(this);
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
+ LayerShapeType.Ellipse => new EllipseShape(this),
+ LayerShapeType.Rectangle => new RectangleShape(this),
+ _ => throw new ArgumentOutOfRangeException()
+ };
}
#endregion
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
index 12edfed9c..67d653575 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
@@ -25,7 +25,13 @@ namespace Artemis.Core
///
protected LayerProperty()
{
- // Cant define generic types as nullable ¯\_(ツ)_/¯
+ // These are set right after construction to keep the constructor (and inherited constructs) clean
+ ProfileElement = null!;
+ LayerPropertyGroup = null!;
+ Path = null!;
+ Entity = null!;
+ PropertyDescription = null!;
+
CurrentValue = default!;
DefaultValue = default!;
diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs
index 2e39f756c..b82052a89 100644
--- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs
+++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs
@@ -5,7 +5,6 @@ using System.Linq;
using System.Reflection;
using Artemis.Core.LayerBrushes;
using Artemis.Core.LayerEffects;
-using Artemis.Core.Properties;
using Artemis.Storage.Entities.Profile;
using Humanizer;
@@ -30,6 +29,12 @@ namespace Artemis.Core
///
protected LayerPropertyGroup()
{
+ // These are set right after construction to keep the constructor (and inherited constructs) clean
+ GroupDescription = null!;
+ Feature = null!;
+ ProfileElement = null!;
+ Path = null!;
+
_layerProperties = new List();
_layerPropertyGroups = new List();
}
@@ -52,7 +57,7 @@ namespace Artemis.Core
///
/// The parent group of this group
///
- public LayerPropertyGroup Parent { get; internal set; }
+ public LayerPropertyGroup? Parent { get; internal set; }
///
/// The path of this property group
@@ -67,12 +72,12 @@ namespace Artemis.Core
///
/// The layer brush this property group belongs to
///
- public BaseLayerBrush LayerBrush { get; internal set; }
+ public BaseLayerBrush? LayerBrush { get; internal set; }
///
/// The layer effect this property group belongs to
///
- public BaseLayerEffect LayerEffect { get; internal set; }
+ public BaseLayerEffect? LayerEffect { get; internal set; }
///
/// Gets or sets whether the property is hidden in the UI
@@ -139,19 +144,16 @@ namespace Artemis.Core
PropertyGroupInitialized?.Invoke(this, EventArgs.Empty);
}
- internal void Initialize(RenderProfileElement profileElement, [NotNull] string path, PluginFeature feature)
+ internal void Initialize(RenderProfileElement profileElement, string path, PluginFeature feature)
{
- if (path == null)
- throw new ArgumentNullException(nameof(path));
- if (feature == null)
- throw new ArgumentNullException(nameof(feature));
+ if (path == null) throw new ArgumentNullException(nameof(path));
// Doubt this will happen but let's make sure
if (PropertiesInitialized)
throw new ArtemisCoreException("Layer property group already initialized, wut");
- Feature = feature;
- ProfileElement = profileElement;
+ Feature = feature ?? throw new ArgumentNullException(nameof(feature));
+ ProfileElement = profileElement ?? throw new ArgumentNullException(nameof(profileElement));
Path = path.TrimEnd('.');
// Get all properties with a PropertyDescriptionAttribute
@@ -209,8 +211,7 @@ namespace Artemis.Core
if (!typeof(ILayerProperty).IsAssignableFrom(propertyInfo.PropertyType))
throw new ArtemisPluginException($"Layer property with PropertyDescription attribute must be of type LayerProperty at {path}");
- ILayerProperty instance = (ILayerProperty) Activator.CreateInstance(propertyInfo.PropertyType, true);
- if (instance == null)
+ if (!(Activator.CreateInstance(propertyInfo.PropertyType, true) is ILayerProperty instance))
throw new ArtemisPluginException($"Failed to create instance of layer property at {path}");
// Ensure the description has a name, if not this is a good point to set it based on the property info
@@ -230,8 +231,7 @@ namespace Artemis.Core
if (!typeof(LayerPropertyGroup).IsAssignableFrom(propertyInfo.PropertyType))
throw new ArtemisPluginException("Layer property with PropertyGroupDescription attribute must be of type LayerPropertyGroup");
- LayerPropertyGroup instance = (LayerPropertyGroup) Activator.CreateInstance(propertyInfo.PropertyType);
- if (instance == null)
+ if (!(Activator.CreateInstance(propertyInfo.PropertyType) is LayerPropertyGroup instance))
throw new ArtemisPluginException($"Failed to create instance of layer property group at {path + propertyInfo.Name}");
// Ensure the description has a name, if not this is a good point to set it based on the property info
@@ -250,7 +250,7 @@ namespace Artemis.Core
private PropertyEntity GetPropertyEntity(RenderProfileElement profileElement, string path, out bool fromStorage)
{
- PropertyEntity entity = profileElement.RenderElementEntity.PropertyEntities.FirstOrDefault(p => p.FeatureId == Feature.Id && p.Path == path);
+ PropertyEntity? entity = profileElement.RenderElementEntity.PropertyEntities.FirstOrDefault(p => p.FeatureId == Feature.Id && p.Path == path);
fromStorage = entity != null;
if (entity == null)
{
@@ -298,18 +298,18 @@ namespace Artemis.Core
///
/// Occurs when the property group has initialized all its children
///
- public event EventHandler PropertyGroupInitialized;
+ public event EventHandler? PropertyGroupInitialized;
///
/// Occurs when one of the current value of one of the layer properties in this group changes by some form of input
/// Note: Will not trigger on properties in child groups
///
- public event EventHandler LayerPropertyOnCurrentValueSet;
+ public event EventHandler? LayerPropertyOnCurrentValueSet;
///
/// Occurs when the value of the layer property was updated
///
- public event EventHandler VisibilityChanged;
+ public event EventHandler? VisibilityChanged;
internal virtual void OnVisibilityChanged()
{
diff --git a/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs b/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs
index d9d6f7873..6b5f4e825 100644
--- a/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs
+++ b/src/Artemis.Core/Models/Profile/LayerShapes/LayerShape.cs
@@ -20,7 +20,7 @@ namespace Artemis.Core
///
/// Gets a the path outlining the shape
///
- public SKPath Path { get; protected set; }
+ public SKPath? Path { get; protected set; }
///
/// Calculates the
diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs
index abadbc421..a8e21ce76 100644
--- a/src/Artemis.Core/Models/Profile/Profile.cs
+++ b/src/Artemis.Core/Models/Profile/Profile.cs
@@ -15,7 +15,7 @@ namespace Artemis.Core
private bool _isActivated;
private readonly object _lock = new object();
- internal Profile(ProfileModule module, string name)
+ internal Profile(ProfileModule module, string name) : base(null!)
{
ProfileEntity = new ProfileEntity();
EntityId = Guid.NewGuid();
@@ -30,7 +30,7 @@ namespace Artemis.Core
Save();
}
- internal Profile(ProfileModule module, ProfileEntity profileEntity)
+ internal Profile(ProfileModule module, ProfileEntity profileEntity) : base(null!)
{
Profile = this;
ProfileEntity = profileEntity;
@@ -149,7 +149,7 @@ namespace Artemis.Core
ChildrenList.Clear();
// Populate the profile starting at the root, the rest is populated recursively
- FolderEntity rootFolder = ProfileEntity.Folders.FirstOrDefault(f => f.ParentId == EntityId);
+ FolderEntity? rootFolder = ProfileEntity.Folders.FirstOrDefault(f => f.ParentId == EntityId);
if (rootFolder == null)
{
Folder _ = new Folder(this, "Root folder");
diff --git a/src/Artemis.Core/Models/Profile/ProfileElement.cs b/src/Artemis.Core/Models/Profile/ProfileElement.cs
index 29183378c..b9ee1b524 100644
--- a/src/Artemis.Core/Models/Profile/ProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/ProfileElement.cs
@@ -13,7 +13,7 @@ namespace Artemis.Core
{
private bool _enabled;
private Guid _entityId;
- private string _name;
+ private string? _name;
private int _order;
private ProfileElement? _parent;
private Profile _profile;
@@ -21,8 +21,9 @@ namespace Artemis.Core
internal List ChildrenList;
internal bool Disposed;
- internal ProfileElement()
+ internal ProfileElement(Profile profile)
{
+ _profile = profile;
ChildrenList = new List();
}
@@ -56,7 +57,16 @@ namespace Artemis.Core
///
/// The element's children
///
- public ReadOnlyCollection Children => ChildrenList.AsReadOnly();
+ public ReadOnlyCollection Children
+ {
+ get
+ {
+ lock (ChildrenList)
+ {
+ return ChildrenList.AsReadOnly();
+ }
+ }
+ }
///
/// The order in which this element appears in the update loop and editor
@@ -70,7 +80,7 @@ namespace Artemis.Core
///
/// The name which appears in the editor
///
- public string Name
+ public string? Name
{
get => _name;
set => SetAndNotify(ref _name, value);
diff --git a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
index 53b4cc9b6..9fc045777 100644
--- a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
@@ -16,10 +16,12 @@ namespace Artemis.Core
///
public abstract class RenderProfileElement : ProfileElement
{
- internal RenderProfileElement()
+ internal RenderProfileElement(Profile profile) : base(profile)
{
Timeline = new Timeline();
Renderer = new Renderer();
+ ExpandedPropertyGroups = new List();
+ LayerEffectsList = new List();
LayerEffectStore.LayerEffectAdded += LayerEffectStoreOnLayerEffectAdded;
LayerEffectStore.LayerEffectRemoved += LayerEffectStoreOnLayerEffectRemoved;
@@ -68,7 +70,7 @@ namespace Artemis.Core
LayerEffectEntity layerEffectEntity = new LayerEffectEntity
{
Id = layerEffect.EntityId,
- ProviderId = layerEffect.Descriptor.PlaceholderFor ?? layerEffect.ProviderId,
+ ProviderId = layerEffect.Descriptor?.PlaceholderFor ?? layerEffect.ProviderId,
EffectType = layerEffect.GetEffectTypeName(),
Name = layerEffect.Name,
Enabled = layerEffect.Enabled,
@@ -76,7 +78,7 @@ namespace Artemis.Core
Order = layerEffect.Order
};
RenderElementEntity.LayerEffects.Add(layerEffectEntity);
- layerEffect.BaseProperties.ApplyToEntity();
+ layerEffect.BaseProperties?.ApplyToEntity();
}
// Conditions
@@ -290,8 +292,7 @@ namespace Artemis.Core
private void LayerEffectStoreOnLayerEffectRemoved(object? sender, LayerEffectStoreEvent e)
{
// If effects provided by the plugin are on the element, replace them with placeholders
- List pluginEffects = LayerEffectsList.Where(ef => ef.Descriptor.Provider != null &&
- ef.ProviderId == e.Registration.PluginFeature.Id).ToList();
+ List pluginEffects = LayerEffectsList.Where(ef => ef.ProviderId == e.Registration.PluginFeature.Id).ToList();
foreach (BaseLayerEffect pluginEffect in pluginEffects)
{
LayerEffectEntity entity = RenderElementEntity.LayerEffects.First(en => en.Id == pluginEffect.EntityId);
@@ -323,13 +324,13 @@ namespace Artemis.Core
protected set => SetAndNotify(ref _displayConditionMet, value);
}
- private DataModelConditionGroup _displayCondition;
+ private DataModelConditionGroup? _displayCondition;
private bool _displayConditionMet;
///
/// Gets or sets the root display condition group
///
- public DataModelConditionGroup DisplayCondition
+ public DataModelConditionGroup? DisplayCondition
{
get => _displayCondition;
set => SetAndNotify(ref _displayCondition, value);
diff --git a/src/Artemis.Core/Models/Profile/Renderer.cs b/src/Artemis.Core/Models/Profile/Renderer.cs
index 03b4e1fb7..110974d05 100644
--- a/src/Artemis.Core/Models/Profile/Renderer.cs
+++ b/src/Artemis.Core/Models/Profile/Renderer.cs
@@ -26,7 +26,7 @@ namespace Artemis.Core
if (IsOpen)
throw new ArtemisCoreException("Cannot open render context because it is already open");
- if (!_valid)
+ if (!_valid || Canvas == null)
{
SKRect pathBounds = path.Bounds;
int width = (int) pathBounds.Width;
@@ -59,7 +59,7 @@ namespace Artemis.Core
if (_disposed)
throw new ObjectDisposedException("Renderer");
- Canvas.Restore();
+ Canvas?.Restore();
Paint?.Dispose();
Paint = null;
diff --git a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs
index f99b35771..1bcb14540 100644
--- a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs
+++ b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs
@@ -14,7 +14,7 @@ namespace Artemis.Core
public class ArtemisDevice : CorePropertyChanged
{
private ReadOnlyCollection _leds;
- private SKPath _renderPath;
+ private SKPath? _renderPath;
private SKRect _renderRectangle;
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, ArtemisSurface surface)
@@ -23,7 +23,7 @@ namespace Artemis.Core
DeviceProvider = deviceProvider;
Surface = surface;
DeviceEntity = new DeviceEntity();
- Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
+ _leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
Rotation = 0;
Scale = 1;
@@ -39,7 +39,7 @@ namespace Artemis.Core
DeviceProvider = deviceProvider;
Surface = surface;
DeviceEntity = deviceEntity;
- Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
+ _leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
}
///
@@ -54,7 +54,7 @@ namespace Artemis.Core
///
/// Gets the path surrounding the device, sized to match the render scale
///
- public SKPath RenderPath
+ public SKPath? RenderPath
{
get => _renderPath;
private set => SetAndNotify(ref _renderPath, value);
diff --git a/src/Artemis.Core/Ninject/LoggerProvider.cs b/src/Artemis.Core/Ninject/LoggerProvider.cs
index 9d1107b2d..e39a4a434 100644
--- a/src/Artemis.Core/Ninject/LoggerProvider.cs
+++ b/src/Artemis.Core/Ninject/LoggerProvider.cs
@@ -22,7 +22,7 @@ namespace Artemis.Core.Ninject
protected override ILogger CreateInstance(IContext context)
{
- Type requestingType = context.Request.ParentContext?.Plan?.Type;
+ Type? requestingType = context.Request.ParentContext?.Plan?.Type;
if (requestingType != null)
return Logger.ForContext(requestingType);
return Logger;
diff --git a/src/Artemis.Core/Plugins/DataModelExpansions/Attributes/DataModelProperty.cs b/src/Artemis.Core/Plugins/DataModelExpansions/Attributes/DataModelProperty.cs
index 6eae6b89b..3f6ee745a 100644
--- a/src/Artemis.Core/Plugins/DataModelExpansions/Attributes/DataModelProperty.cs
+++ b/src/Artemis.Core/Plugins/DataModelExpansions/Attributes/DataModelProperty.cs
@@ -11,32 +11,32 @@ namespace Artemis.Core.DataModelExpansions
///
/// Gets or sets the user-friendly name for this property, shown in the UI.
///
- public string Name { get; set; }
+ public string? Name { get; set; }
///
/// Gets or sets the user-friendly description for this property, shown in the UI.
///
- public string Description { get; set; }
+ public string? Description { get; set; }
///
/// Gets or sets the an optional prefix to show before displaying elements in the UI.
///
- public string Prefix { get; set; }
+ public string? Prefix { get; set; }
///
/// Gets or sets an optional affix to show behind displaying elements in the UI.
///
- public string Affix { get; set; }
+ public string? Affix { get; set; }
///
/// Gets or sets an optional maximum value, this value is not enforced but used for percentage calculations.
///
- public object MaxValue { get; set; }
+ public object? MaxValue { get; set; }
///
/// Gets or sets an optional minimum value, this value is not enforced but used for percentage calculations.
///
- public object MinValue { get; set; }
+ public object? MinValue { get; set; }
///
/// Gets or sets whether this property resets the max depth of the data model, defaults to true
diff --git a/src/Artemis.Core/Plugins/DataModelExpansions/DataModel.cs b/src/Artemis.Core/Plugins/DataModelExpansions/DataModel.cs
index fd57053cb..3377bb081 100644
--- a/src/Artemis.Core/Plugins/DataModelExpansions/DataModel.cs
+++ b/src/Artemis.Core/Plugins/DataModelExpansions/DataModel.cs
@@ -15,6 +15,16 @@ namespace Artemis.Core.DataModelExpansions
{
private readonly Dictionary _dynamicDataModels = new Dictionary();
+ ///
+ /// Creates a new instance of the class
+ ///
+ protected DataModel()
+ {
+ // These are both set right after construction to keep the constructor of inherited classes clean
+ Feature = null!;
+ DataModelDescription = null!;
+ }
+
///
/// Gets the plugin feature this data model belongs to
///
@@ -60,7 +70,7 @@ namespace Artemis.Core.DataModelExpansions
/// The key of the child, must be unique to this data model
/// An optional name, if not provided the key will be used in a humanized form
/// An optional description
- public T AddDynamicChild(T dynamicDataModel, string key, string name = null, string description = null) where T : DataModel
+ public T AddDynamicChild(T dynamicDataModel, string key, string? name = null, string? description = null) where T : DataModel
{
if (dynamicDataModel == null)
throw new ArgumentNullException(nameof(dynamicDataModel));
@@ -140,7 +150,7 @@ namespace Artemis.Core.DataModelExpansions
/// If found, the dynamic data model otherwise null
public T? DynamicChild(string key) where T : DataModel
{
- _dynamicDataModels.TryGetValue(key, out DataModel value);
+ _dynamicDataModels.TryGetValue(key, out DataModel? value);
return value as T;
}
diff --git a/src/Artemis.Core/Plugins/DataModelExpansions/DataModelExpansion.cs b/src/Artemis.Core/Plugins/DataModelExpansions/DataModelExpansion.cs
index eca795b81..a0dd6b998 100644
--- a/src/Artemis.Core/Plugins/DataModelExpansions/DataModelExpansion.cs
+++ b/src/Artemis.Core/Plugins/DataModelExpansions/DataModelExpansion.cs
@@ -16,7 +16,7 @@ namespace Artemis.Core.DataModelExpansions
///
public T DataModel
{
- get => (T) InternalDataModel;
+ get => InternalDataModel as T ?? throw new InvalidOperationException("Internal datamodel does not match the type of the data model");
internal set => InternalDataModel = value;
}
@@ -49,11 +49,5 @@ namespace Artemis.Core.DataModelExpansions
DataModel.DataModelDescription = GetDataModelDescription();
base.InternalEnable();
}
-
- internal override void InternalDisable()
- {
- DataModel = null;
- base.InternalDisable();
- }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Plugins/DeviceProviders/DeviceProvider.cs b/src/Artemis.Core/Plugins/DeviceProviders/DeviceProvider.cs
index c59446c14..bfc020c52 100644
--- a/src/Artemis.Core/Plugins/DeviceProviders/DeviceProvider.cs
+++ b/src/Artemis.Core/Plugins/DeviceProviders/DeviceProvider.cs
@@ -31,7 +31,7 @@ namespace Artemis.Core.DeviceProviders
/// A logger used by the device provider internally, ignore this
///
[Inject]
- public ILogger Logger { get; set; }
+ public ILogger? Logger { get; set; }
///
public override void Disable()
diff --git a/src/Artemis.Core/Plugins/LayerBrushes/Internal/BaseLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrushes/Internal/BaseLayerBrush.cs
index 837f32142..c452384e3 100644
--- a/src/Artemis.Core/Plugins/LayerBrushes/Internal/BaseLayerBrush.cs
+++ b/src/Artemis.Core/Plugins/LayerBrushes/Internal/BaseLayerBrush.cs
@@ -10,10 +10,20 @@ namespace Artemis.Core.LayerBrushes
{
private LayerBrushType _brushType;
private ILayerBrushConfigurationDialog? _configurationDialog;
- private LayerBrushDescriptor? _descriptor;
+ private LayerBrushDescriptor _descriptor;
private Layer _layer;
private bool _supportsTransformation = true;
+ ///
+ /// Creates a new instance of the class
+ ///
+ protected BaseLayerBrush()
+ {
+ // Both are set right after construction to keep the constructor of inherited classes clean
+ _layer = null!;
+ _descriptor = null!;
+ }
+
///
/// Gets the layer this brush is applied to
///
@@ -26,7 +36,7 @@ namespace Artemis.Core.LayerBrushes
///
/// Gets the descriptor of this brush
///
- public LayerBrushDescriptor? Descriptor
+ public LayerBrushDescriptor Descriptor
{
get => _descriptor;
internal set => SetAndNotify(ref _descriptor, value);
diff --git a/src/Artemis.Core/Plugins/LayerBrushes/Internal/PropertiesLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrushes/Internal/PropertiesLayerBrush.cs
index d8ede59ee..5b12849b8 100644
--- a/src/Artemis.Core/Plugins/LayerBrushes/Internal/PropertiesLayerBrush.cs
+++ b/src/Artemis.Core/Plugins/LayerBrushes/Internal/PropertiesLayerBrush.cs
@@ -7,7 +7,7 @@ namespace Artemis.Core.LayerBrushes
///
public abstract class PropertiesLayerBrush : BaseLayerBrush where T : LayerPropertyGroup
{
- private T _properties;
+ private T _properties = null!;
///
/// Gets whether all properties on this brush are initialized
@@ -35,7 +35,7 @@ namespace Artemis.Core.LayerBrushes
internal void InitializeProperties()
{
Properties = Activator.CreateInstance();
- Properties.GroupDescription ??= new PropertyGroupDescriptionAttribute {Name = Descriptor.DisplayName, Description = Descriptor.Description};
+ Properties.GroupDescription = new PropertyGroupDescriptionAttribute {Name = Descriptor.DisplayName, Description = Descriptor.Description};
Properties.LayerBrush = this;
Properties.Initialize(Layer, "LayerBrush.", Descriptor.Provider);
PropertiesInitialized = true;
diff --git a/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushDescriptor.cs b/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushDescriptor.cs
index b8673a261..2f70a6d54 100644
--- a/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushDescriptor.cs
+++ b/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushDescriptor.cs
@@ -59,6 +59,7 @@ namespace Artemis.Core.LayerBrushes
///
internal void CreateInstance(Layer layer)
{
+ if (layer == null) throw new ArgumentNullException(nameof(layer));
if (layer.LayerBrush != null)
throw new ArtemisCoreException("Layer already has an instantiated layer brush");
diff --git a/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs
index c106a1c15..4028228a7 100644
--- a/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs
+++ b/src/Artemis.Core/Plugins/LayerBrushes/RgbNetLayerBrush.cs
@@ -20,6 +20,7 @@ namespace Artemis.Core.LayerBrushes
///
protected RgbNetLayerBrush()
{
+ LedGroup = new ListLedGroup();
BrushType = LayerBrushType.RgbNet;
SupportsTransformation = false;
}
@@ -75,7 +76,7 @@ namespace Artemis.Core.LayerBrushes
// Not used in this effect type
internal override void InternalRender(SKCanvas canvas, SKRect bounds, SKPaint paint)
{
- throw new NotImplementedException("RGB.NET layer effectes do not implement InternalRender");
+ throw new NotImplementedException("RGB.NET layer effects do not implement InternalRender");
}
private void LayerOnRenderPropertiesUpdated(object? sender, EventArgs e)
diff --git a/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs b/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs
index f76014daf..87a10811d 100644
--- a/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs
+++ b/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs
@@ -9,7 +9,7 @@ namespace Artemis.Core.LayerEffects
///
public abstract class BaseLayerEffect : CorePropertyChanged, IDisposable
{
- private ILayerEffectConfigurationDialog _configurationDialog;
+ private ILayerEffectConfigurationDialog? _configurationDialog;
private LayerEffectDescriptor _descriptor;
private bool _enabled;
private Guid _entityId;
@@ -18,6 +18,15 @@ namespace Artemis.Core.LayerEffects
private int _order;
private RenderProfileElement _profileElement;
+ ///
+ protected BaseLayerEffect()
+ {
+ // These are set right after construction to keep the constructor of inherited classes clean
+ _profileElement = null!;
+ _descriptor = null!;
+ _name = null!;
+ }
+
///
/// Gets the unique ID of this effect
///
@@ -76,7 +85,7 @@ namespace Artemis.Core.LayerEffects
///
/// Gets the that registered this effect
///
- public LayerEffectDescriptor? Descriptor
+ public LayerEffectDescriptor Descriptor
{
get => _descriptor;
internal set => SetAndNotify(ref _descriptor, value);
@@ -85,7 +94,7 @@ namespace Artemis.Core.LayerEffects
///
/// Gets or sets a configuration dialog complementing the regular properties
///
- public ILayerEffectConfigurationDialog ConfigurationDialog
+ public ILayerEffectConfigurationDialog? ConfigurationDialog
{
get => _configurationDialog;
protected set => SetAndNotify(ref _configurationDialog, value);
@@ -94,12 +103,12 @@ namespace Artemis.Core.LayerEffects
///
/// Gets the ID of the that provided this effect
///
- public string ProviderId => Descriptor?.Provider?.Id;
+ public string ProviderId => Descriptor.Provider.Id;
///
/// Gets a reference to the layer property group without knowing it's type
///
- public virtual LayerPropertyGroup BaseProperties => null;
+ public virtual LayerPropertyGroup? BaseProperties => null;
internal string PropertyRootPath => $"LayerEffect.{EntityId}.{GetType().Name}.";
diff --git a/src/Artemis.Core/Plugins/LayerEffects/LayerEffect.cs b/src/Artemis.Core/Plugins/LayerEffects/LayerEffect.cs
index 585fb8463..3a1b03e62 100644
--- a/src/Artemis.Core/Plugins/LayerEffects/LayerEffect.cs
+++ b/src/Artemis.Core/Plugins/LayerEffects/LayerEffect.cs
@@ -8,7 +8,7 @@ namespace Artemis.Core.LayerEffects
///
public abstract class LayerEffect : BaseLayerEffect where T : LayerPropertyGroup
{
- private T _properties;
+ private T _properties = null!;
///
/// Gets whether all properties on this effect are initialized
diff --git a/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs b/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs
index 33fafb542..0b742742a 100644
--- a/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs
+++ b/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs
@@ -11,7 +11,7 @@ namespace Artemis.Core.LayerEffects
///
public class LayerEffectDescriptor
{
- internal LayerEffectDescriptor(string displayName, string description, string icon, Type layerEffectType, LayerEffectProvider provider)
+ internal LayerEffectDescriptor(string displayName, string description, string icon, Type? layerEffectType, LayerEffectProvider provider)
{
DisplayName = displayName;
Description = description;
@@ -39,12 +39,12 @@ namespace Artemis.Core.LayerEffects
///
/// The type of the layer effect
///
- public Type LayerEffectType { get; }
+ public Type? LayerEffectType { get; }
///
/// The plugin that provided this
///
- public LayerEffectProvider? Provider { get; }
+ public LayerEffectProvider Provider { get; }
///
/// Gets the GUID this descriptor is acting as a placeholder for. If null, this descriptor is not a placeholder
@@ -66,8 +66,8 @@ namespace Artemis.Core.LayerEffects
return;
}
- 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");
+ if (LayerEffectType == null)
+ throw new ArtemisCoreException("Cannot create an instance of a layer effect because this descriptor is not a placeholder but is still missing its LayerEffectType");
BaseLayerEffect effect = (BaseLayerEffect) Provider.Plugin.Kernel!.Get(LayerEffectType);
effect.ProfileElement = renderElement;
@@ -85,7 +85,13 @@ namespace Artemis.Core.LayerEffects
private void CreatePlaceHolderInstance(RenderProfileElement renderElement, LayerEffectEntity entity)
{
- PlaceholderLayerEffect effect = new PlaceholderLayerEffect(entity, PlaceholderFor) {ProfileElement = renderElement, Descriptor = this};
+ if (PlaceholderFor == null)
+ throw new ArtemisCoreException("Cannot create a placeholder instance using a layer effect descriptor that is not a placeholder for anything");
+ PlaceholderLayerEffect effect = new PlaceholderLayerEffect(entity, PlaceholderFor)
+ {
+ ProfileElement = renderElement,
+ Descriptor = this
+ };
effect.Initialize();
renderElement.ActivateLayerEffect(effect);
}
diff --git a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs
index 51c471b0a..cd43a0c9a 100644
--- a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs
+++ b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs
@@ -16,7 +16,7 @@ namespace Artemis.Core.Modules
///
/// The name of the process that must run
/// The location of where the process must be running from (optional)
- public ProcessActivationRequirement(string processName, string location = null)
+ public ProcessActivationRequirement(string? processName, string? location = null)
{
ProcessName = processName;
Location = location;
@@ -25,12 +25,12 @@ namespace Artemis.Core.Modules
///
/// The name of the process that must run
///
- public string ProcessName { get; set; }
+ public string? ProcessName { get; set; }
///
/// The location of where the process must be running from
///
- public string Location { get; set; }
+ public string? Location { get; set; }
///
public bool Evaluate()
diff --git a/src/Artemis.Core/Plugins/Modules/Module.cs b/src/Artemis.Core/Plugins/Modules/Module.cs
index 89698c176..88a194349 100644
--- a/src/Artemis.Core/Plugins/Modules/Module.cs
+++ b/src/Artemis.Core/Plugins/Modules/Module.cs
@@ -18,7 +18,7 @@ namespace Artemis.Core.Modules
///
public T DataModel
{
- get => (T) InternalDataModel;
+ get => InternalDataModel as T ?? throw new InvalidOperationException("Internal datamodel does not match the type of the data model");
internal set => InternalDataModel = value;
}
@@ -52,12 +52,6 @@ namespace Artemis.Core.Modules
DataModel.DataModelDescription = GetDataModelDescription();
base.InternalEnable();
}
-
- internal override void InternalDisable()
- {
- DataModel = null;
- base.InternalDisable();
- }
}
diff --git a/src/Artemis.Core/Plugins/Modules/ModuleTab.cs b/src/Artemis.Core/Plugins/Modules/ModuleTab.cs
index 1c017964c..01c11411e 100644
--- a/src/Artemis.Core/Plugins/Modules/ModuleTab.cs
+++ b/src/Artemis.Core/Plugins/Modules/ModuleTab.cs
@@ -6,12 +6,11 @@ namespace Artemis.Core.Modules
public class ModuleTab : ModuleTab where T : IModuleViewModel
{
///
- /// Initializes a new instance of the class
+ /// Creates a new instance of the class
///
/// The title of the tab
- public ModuleTab(string title)
+ public ModuleTab(string title) : base(title)
{
- Title = title;
}
///
@@ -24,9 +23,13 @@ namespace Artemis.Core.Modules
public abstract class ModuleTab
{
///
- /// The module this tab belongs to
+ /// Creates a new instance of the class
///
- internal Module Module { get; set; }
+ /// The title of the tab
+ protected ModuleTab(string title)
+ {
+ Title = title;
+ }
///
/// The title of the tab
diff --git a/src/Artemis.Core/Plugins/Modules/ProfileModule.cs b/src/Artemis.Core/Plugins/Modules/ProfileModule.cs
index a5b45926c..945521491 100644
--- a/src/Artemis.Core/Plugins/Modules/ProfileModule.cs
+++ b/src/Artemis.Core/Plugins/Modules/ProfileModule.cs
@@ -22,7 +22,7 @@ namespace Artemis.Core.Modules
///
public T DataModel
{
- get => (T) InternalDataModel;
+ get => InternalDataModel as T ?? throw new InvalidOperationException("Internal datamodel does not match the type of the data model");
internal set => InternalDataModel = value;
}
@@ -83,7 +83,6 @@ namespace Artemis.Core.Modules
{
Deactivate(true);
base.InternalDisable();
- DataModel = null;
}
}
@@ -182,7 +181,7 @@ namespace Artemis.Core.Modules
ProfileRendered(deltaTime, surface, canvas, canvasInfo);
}
- internal async Task ChangeActiveProfileAnimated(Profile profile, ArtemisSurface surface)
+ 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 {this}.");
@@ -204,12 +203,14 @@ namespace Artemis.Core.Modules
await Task.Delay(50);
}
- internal void ChangeActiveProfile(Profile profile, ArtemisSurface surface)
+ 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 {this}.");
if (!IsActivated)
throw new ArtemisCoreException("Cannot activate a profile on a deactivated module");
+ if (profile != null && surface == null)
+ throw new ArtemisCoreException("If changing the active profile to a non-null profile, a surface is required");
lock (_lock)
{
@@ -219,7 +220,7 @@ namespace Artemis.Core.Modules
ActiveProfile?.Dispose();
ActiveProfile = profile;
- ActiveProfile?.Activate(surface);
+ ActiveProfile?.Activate(surface!);
}
OnActiveProfileChanged();
@@ -229,7 +230,7 @@ namespace Artemis.Core.Modules
{
base.Deactivate(isOverride);
- Profile profile = ActiveProfile;
+ Profile? profile = ActiveProfile;
ActiveProfile = null;
profile?.Dispose();
}
@@ -249,7 +250,7 @@ namespace Artemis.Core.Modules
///
/// Occurs when the has changed
///
- public event EventHandler ActiveProfileChanged;
+ public event EventHandler? ActiveProfileChanged;
///
/// Invokes the event
diff --git a/src/Artemis.Core/Plugins/Plugin.cs b/src/Artemis.Core/Plugins/Plugin.cs
index 2eb977b9d..853649b0b 100644
--- a/src/Artemis.Core/Plugins/Plugin.cs
+++ b/src/Artemis.Core/Plugins/Plugin.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -19,10 +20,11 @@ namespace Artemis.Core
private bool _isEnabled;
- internal Plugin(PluginInfo info, DirectoryInfo directory)
+ internal Plugin(PluginInfo info, DirectoryInfo directory, PluginEntity? pluginEntity)
{
Info = info;
Directory = directory;
+ Entity = pluginEntity ?? new PluginEntity {Id = Guid, IsEnabled = true};
_features = new List();
}
@@ -42,6 +44,7 @@ namespace Artemis.Core
///
public DirectoryInfo Directory { get; }
+
///
/// Gets or sets a configuration dialog for this plugin that is accessible in the UI under Settings > Plugins
///
@@ -91,7 +94,8 @@ namespace Artemis.Core
///
/// The path to resolve
/// An absolute path pointing to the provided relative path
- public string? ResolveRelativePath(string path)
+ [return: NotNullIfNotNull("path")]
+ public string? ResolveRelativePath(string? path)
{
return path == null ? null : Path.Combine(Directory.FullName, path);
}
diff --git a/src/Artemis.Core/Plugins/PluginFeature.cs b/src/Artemis.Core/Plugins/PluginFeature.cs
index 3cc20c092..733c3ee9b 100644
--- a/src/Artemis.Core/Plugins/PluginFeature.cs
+++ b/src/Artemis.Core/Plugins/PluginFeature.cs
@@ -16,7 +16,7 @@ namespace Artemis.Core
///
/// Gets the plugin that provides this feature
///
- public Plugin Plugin { get; internal set; }
+ public Plugin Plugin { get; internal set; } = null!; // Will be set right after construction
///
/// Gets whether the plugin is enabled
@@ -41,7 +41,7 @@ namespace Artemis.Core
///
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; }
+ internal PluginFeatureEntity Entity { get; set; } = null!; // Will be set right after construction
///
/// Called when the feature is activated
diff --git a/src/Artemis.Core/Plugins/PluginInfo.cs b/src/Artemis.Core/Plugins/PluginInfo.cs
index 26a3b7e1f..4323b2764 100644
--- a/src/Artemis.Core/Plugins/PluginInfo.cs
+++ b/src/Artemis.Core/Plugins/PluginInfo.cs
@@ -9,13 +9,13 @@ namespace Artemis.Core
[JsonObject(MemberSerialization.OptIn)]
public class PluginInfo : CorePropertyChanged
{
- private string _description;
+ private string? _description;
private Guid _guid;
- private string _icon;
- private string _main;
- private string _name;
- private Plugin _plugin;
- private Version _version;
+ private string? _icon;
+ private string _main = null!;
+ private string _name = null!;
+ private Plugin _plugin = null!;
+ private Version _version = null!;
internal PluginInfo()
{
@@ -45,7 +45,7 @@ namespace Artemis.Core
/// A short description of the plugin
///
[JsonProperty]
- public string Description
+ public string? Description
{
get => _description;
set => SetAndNotify(ref _description, value);
@@ -57,7 +57,7 @@ namespace Artemis.Core
/// icons
///
[JsonProperty]
- public string Icon
+ public string? Icon
{
get => _icon;
set => SetAndNotify(ref _icon, value);
diff --git a/src/Artemis.Core/Plugins/Settings/PluginSetting.cs b/src/Artemis.Core/Plugins/Settings/PluginSetting.cs
index d8738dd70..02508f220 100644
--- a/src/Artemis.Core/Plugins/Settings/PluginSetting.cs
+++ b/src/Artemis.Core/Plugins/Settings/PluginSetting.cs
@@ -1,4 +1,6 @@
using System;
+using System.Diagnostics.CodeAnalysis;
+using Artemis.Core.Properties;
using Artemis.Storage.Entities.Plugins;
using Artemis.Storage.Repositories.Interfaces;
using Newtonsoft.Json;
@@ -27,11 +29,11 @@ namespace Artemis.Core
Name = pluginSettingEntity.Name;
try
{
- Value = JsonConvert.DeserializeObject(pluginSettingEntity.Value);
+ _value = JsonConvert.DeserializeObject(pluginSettingEntity.Value);
}
catch (JsonReaderException)
{
- Value = default;
+ _value = default!;
}
}
@@ -43,6 +45,8 @@ namespace Artemis.Core
///
/// The value of the setting
///
+ [AllowNull]
+ [CanBeNull]
public T Value
{
get => _value;
@@ -50,7 +54,7 @@ namespace Artemis.Core
{
if (Equals(_value, value)) return;
- _value = value;
+ _value = value!;
OnSettingChanged();
OnPropertyChanged(nameof(Value));
@@ -94,12 +98,12 @@ namespace Artemis.Core
///
/// Occurs when the value of the setting has been changed
///
- public event EventHandler SettingChanged;
+ public event EventHandler? SettingChanged;
///
/// Occurs when the value of the setting has been saved
///
- public event EventHandler SettingSaved;
+ public event EventHandler? SettingSaved;
///
public override string ToString()
diff --git a/src/Artemis.Core/Plugins/TimedUpdateRegistration.cs b/src/Artemis.Core/Plugins/TimedUpdateRegistration.cs
index cc77111b7..1297f6a71 100644
--- a/src/Artemis.Core/Plugins/TimedUpdateRegistration.cs
+++ b/src/Artemis.Core/Plugins/TimedUpdateRegistration.cs
@@ -11,7 +11,7 @@ namespace Artemis.Core
public class TimedUpdateRegistration : IDisposable
{
private DateTime _lastEvent;
- private Timer _timer;
+ private Timer? _timer;
private bool _disposed;
private readonly object _lock = new object();
@@ -53,12 +53,12 @@ namespace Artemis.Core
///
/// Gets the action that gets called each time the update event fires
///
- public Action Action { get; }
+ public Action? Action { get; }
///
/// Gets the task that gets called each time the update event fires
///
- public Func AsyncAction { get; }
+ public Func? AsyncAction { get; }
///
/// Starts calling the or at the configured
diff --git a/src/Artemis.Core/Properties/Annotations.cs b/src/Artemis.Core/Properties/Annotations.cs
index 74ad7d4bc..8e036ce4e 100644
--- a/src/Artemis.Core/Properties/Annotations.cs
+++ b/src/Artemis.Core/Properties/Annotations.cs
@@ -22,9 +22,10 @@ SOFTWARE. */
using System;
-// ReSharper disable InheritdocConsiderUsage
-
#pragma warning disable 1591
+#pragma warning disable 8618
+
+// ReSharper disable InheritdocConsiderUsage
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedAutoPropertyAccessor.Global
diff --git a/src/Artemis.Core/RGB.NET/BitmapBrush.cs b/src/Artemis.Core/RGB.NET/BitmapBrush.cs
index 1ac02169d..a7d4a656b 100644
--- a/src/Artemis.Core/RGB.NET/BitmapBrush.cs
+++ b/src/Artemis.Core/RGB.NET/BitmapBrush.cs
@@ -60,7 +60,7 @@ namespace Artemis.Core
///
/// Gets the bitmap used to sample the brush
///
- public SKBitmap Bitmap { get; private set; }
+ public SKBitmap? Bitmap { get; private set; }
#endregion
@@ -94,6 +94,9 @@ namespace Artemis.Core
private void TakeCenter(IEnumerable renderTargets)
{
+ if (Bitmap == null)
+ return;
+
foreach (BrushRenderTarget renderTarget in renderTargets)
{
Point scaledLocation = renderTarget.Point * Scale;
@@ -104,6 +107,9 @@ namespace Artemis.Core
private void TakeSamples(IEnumerable renderTargets)
{
+ if (Bitmap == null)
+ return;
+
int sampleSize = _sampleSizeSetting.Value;
int sampleDepth = Math.Sqrt(sampleSize).RoundToInt();
diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs
index 4842b6880..782b83589 100644
--- a/src/Artemis.Core/Services/CoreService.cs
+++ b/src/Artemis.Core/Services/CoreService.cs
@@ -23,7 +23,7 @@ namespace Artemis.Core.Services
///
internal class CoreService : ICoreService
{
- internal static IKernel Kernel;
+ internal static IKernel Kernel = null!;
private readonly Stopwatch _frameStopWatch;
private readonly ILogger _logger;
@@ -32,10 +32,10 @@ namespace Artemis.Core.Services
private readonly IProfileService _profileService;
private readonly IRgbService _rgbService;
private readonly ISurfaceService _surfaceService;
- private List _dataModelExpansions;
- private List _modules;
+ private List _dataModelExpansions = new List();
+ private List _modules = new List();
- // ReSharper disable once UnusedParameter.Local - Storage migration service is injected early to ensure it runs before anything else
+ // ReSharper disable UnusedParameter.Local - Storage migration and module service are injected early to ensure it runs before anything else
public CoreService(IKernel kernel, ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginManagementService pluginManagementService,
IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService, IModuleService moduleService)
{
@@ -60,10 +60,11 @@ namespace Artemis.Core.Services
_pluginManagementService.PluginEnabled += (sender, args) => UpdatePluginCache();
_pluginManagementService.PluginDisabled += (sender, args) => UpdatePluginCache();
}
+ // ReSharper restore UnusedParameter.Local
public TimeSpan FrameTime { get; private set; }
public bool ModuleRenderingDisabled { get; set; }
- public List StartupArguments { get; set; }
+ public List? StartupArguments { get; set; }
public void Dispose()
{
@@ -86,13 +87,10 @@ namespace Artemis.Core.Services
// Initialize the services
_pluginManagementService.CopyBuiltInPlugins();
- _pluginManagementService.LoadPlugins(StartupArguments.Contains("--ignore-plugin-lock"));
+ _pluginManagementService.LoadPlugins(StartupArguments != null && StartupArguments.Contains("--ignore-plugin-lock"));
ArtemisSurface surfaceConfig = _surfaceService.ActiveSurface;
- if (surfaceConfig != null)
- _logger.Information("Initialized with active surface entity {surfaceConfig}-{guid}", surfaceConfig.Name, surfaceConfig.EntityId);
- else
- _logger.Information("Initialized without an active surface entity");
+ _logger.Information("Initialized with active surface entity {surfaceConfig}-{guid}", surfaceConfig.Name, surfaceConfig.EntityId);
PlayIntroAnimation();
OnInitialized();
@@ -121,7 +119,7 @@ namespace Artemis.Core.Services
FrameRendering += DrawOverlay;
// Stop rendering after the profile finishes (take 1 second extra in case of slow updates)
- TimeSpan introLength = intro.AnimationProfile.GetAllLayers().Max(l => l.Timeline.Length);
+ TimeSpan introLength = intro.AnimationProfile.GetAllLayers().Max(l => l.Timeline.Length)!;
Task.Run(async () =>
{
await Task.Delay(introLength.Add(TimeSpan.FromSeconds(1)));
@@ -217,14 +215,14 @@ namespace Artemis.Core.Services
if (_rgbService.IsRenderPaused)
return;
- OnFrameRendered(new FrameRenderedEventArgs(_rgbService.BitmapBrush, _rgbService.Surface));
+ OnFrameRendered(new FrameRenderedEventArgs(_rgbService.BitmapBrush!, _rgbService.Surface));
}
#region Events
- public event EventHandler Initialized;
- public event EventHandler FrameRendering;
- public event EventHandler FrameRendered;
+ public event EventHandler? Initialized;
+ public event EventHandler? FrameRendering;
+ public event EventHandler? FrameRendered;
private void OnInitialized()
{
diff --git a/src/Artemis.Core/Services/Interfaces/ICoreService.cs b/src/Artemis.Core/Services/Interfaces/ICoreService.cs
index b506f18ac..cc99e4fc7 100644
--- a/src/Artemis.Core/Services/Interfaces/ICoreService.cs
+++ b/src/Artemis.Core/Services/Interfaces/ICoreService.cs
@@ -26,7 +26,7 @@ namespace Artemis.Core.Services
///
/// Gets or sets a list of startup arguments
///
- List StartupArguments { get; set; }
+ List? StartupArguments { get; set; }
///
/// Initializes the core, only call once
diff --git a/src/Artemis.Core/Services/Interfaces/IModuleService.cs b/src/Artemis.Core/Services/Interfaces/IModuleService.cs
index aa61cd25c..e4748174a 100644
--- a/src/Artemis.Core/Services/Interfaces/IModuleService.cs
+++ b/src/Artemis.Core/Services/Interfaces/IModuleService.cs
@@ -12,13 +12,13 @@ namespace Artemis.Core.Services
/// Gets the current active module override. If set, all other modules are deactivated and only the
/// is active.
///
- Module ActiveModuleOverride { get; }
+ Module? ActiveModuleOverride { get; }
///
/// Changes the current and deactivates all other modules
///
///
- Task SetActiveModuleOverride(Module overrideModule);
+ Task SetActiveModuleOverride(Module? overrideModule);
///
/// Evaluates every enabled module's activation requirements and activates/deactivates modules accordingly
diff --git a/src/Artemis.Core/Services/Interfaces/IRgbService.cs b/src/Artemis.Core/Services/Interfaces/IRgbService.cs
index e5cd0c213..ad1d51644 100644
--- a/src/Artemis.Core/Services/Interfaces/IRgbService.cs
+++ b/src/Artemis.Core/Services/Interfaces/IRgbService.cs
@@ -17,7 +17,7 @@ namespace Artemis.Core.Services
///
/// Gets the bitmap brush used to convert the rendered frame to LED-colors
///
- BitmapBrush BitmapBrush { get; }
+ BitmapBrush? BitmapBrush { get; }
///
/// Gets the scale the frames are rendered on, a scale of 1.0 means 1 pixel = 1mm
diff --git a/src/Artemis.Core/Services/ModuleService.cs b/src/Artemis.Core/Services/ModuleService.cs
index d5c543d82..68dd9d203 100644
--- a/src/Artemis.Core/Services/ModuleService.cs
+++ b/src/Artemis.Core/Services/ModuleService.cs
@@ -149,9 +149,9 @@ namespace Artemis.Core.Services
UpdateModulePriority(module, category, priority);
}
- public Module ActiveModuleOverride { get; private set; }
+ public Module? ActiveModuleOverride { get; private set; }
- public async Task SetActiveModuleOverride(Module overrideModule)
+ public async Task SetActiveModuleOverride(Module? overrideModule)
{
try
{
diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs
index 8817ae644..e9b401081 100644
--- a/src/Artemis.Core/Services/PluginManagementService.cs
+++ b/src/Artemis.Core/Services/PluginManagementService.cs
@@ -242,12 +242,10 @@ namespace Artemis.Core.Services
throw new ArtemisCoreException("Cannot load a plugin that is already loaded");
}
- Plugin plugin = new Plugin(pluginInfo, directory);
- OnPluginLoading(new PluginEventArgs(plugin));
-
// Load the entity and fall back on creating a new one
- plugin.Entity = _pluginRepository.GetPluginByGuid(pluginInfo.Guid) ?? new PluginEntity {Id = plugin.Guid, IsEnabled = true};
-
+ Plugin plugin = new Plugin(pluginInfo, directory, _pluginRepository.GetPluginByGuid(pluginInfo.Guid));
+ OnPluginLoading(new PluginEventArgs(plugin));
+
// Locate the main assembly entry
string? mainFile = plugin.ResolveRelativePath(plugin.Info.Main);
if (!File.Exists(mainFile))
diff --git a/src/Artemis.Core/Services/Registration/ConditionOperatorService.cs b/src/Artemis.Core/Services/Registration/ConditionOperatorService.cs
index bc3664a4a..f14a0d0af 100644
--- a/src/Artemis.Core/Services/Registration/ConditionOperatorService.cs
+++ b/src/Artemis.Core/Services/Registration/ConditionOperatorService.cs
@@ -34,7 +34,7 @@ namespace Artemis.Core.Services
return ConditionOperatorStore.GetForType(type, side).Select(r => r.ConditionOperator).ToList();
}
- public BaseConditionOperator GetConditionOperator(Guid operatorPluginGuid, string operatorType)
+ public BaseConditionOperator? GetConditionOperator(Guid operatorPluginGuid, string operatorType)
{
return ConditionOperatorStore.Get(operatorPluginGuid, operatorType)?.ConditionOperator;
}
diff --git a/src/Artemis.Core/Services/Registration/DataBindingService.cs b/src/Artemis.Core/Services/Registration/DataBindingService.cs
index b800a528c..6cf789fbc 100644
--- a/src/Artemis.Core/Services/Registration/DataBindingService.cs
+++ b/src/Artemis.Core/Services/Registration/DataBindingService.cs
@@ -34,7 +34,7 @@ namespace Artemis.Core.Services
return DataBindingModifierTypeStore.GetForType(type, part).Select(r => r.DataBindingModifierType).ToList();
}
- public BaseDataBindingModifierType GetModifierType(Guid modifierTypePluginGuid, string modifierType)
+ public BaseDataBindingModifierType? GetModifierType(Guid modifierTypePluginGuid, string modifierType)
{
return DataBindingModifierTypeStore.Get(modifierTypePluginGuid, modifierType)?.DataBindingModifierType;
}
diff --git a/src/Artemis.Core/Services/Registration/DataModelService.cs b/src/Artemis.Core/Services/Registration/DataModelService.cs
index b583439be..c0fcc3a02 100644
--- a/src/Artemis.Core/Services/Registration/DataModelService.cs
+++ b/src/Artemis.Core/Services/Registration/DataModelService.cs
@@ -11,7 +11,7 @@ namespace Artemis.Core.Services
public DataModelService(IPluginManagementService pluginManagementService)
{
// Add data models of already loaded plugins
- foreach (Module module in pluginManagementService.GetFeaturesOfType().Where(p => p.IsEnabled))
+ foreach (Module module in pluginManagementService.GetFeaturesOfType().Where(p => p.IsEnabled && p.InternalDataModel != null))
AddModuleDataModel(module);
foreach (BaseDataModelExpansion dataModelExpansion in pluginManagementService.GetFeaturesOfType().Where(p => p.IsEnabled))
AddDataModelExpansionDataModel(dataModelExpansion);
@@ -40,9 +40,9 @@ namespace Artemis.Core.Services
return DataModelStore.GetAll().Select(d => d.DataModel).ToList();
}
- public T GetDataModel() where T : DataModel
+ public T? GetDataModel() where T : DataModel
{
- return (T) DataModelStore.GetAll().FirstOrDefault(d => d.DataModel is T)?.DataModel;
+ return (T?) DataModelStore.GetAll().FirstOrDefault(d => d.DataModel is T)?.DataModel;
}
public DataModel? GetPluginDataModel(PluginFeature pluginFeature)
@@ -61,8 +61,7 @@ namespace Artemis.Core.Services
private void AddModuleDataModel(Module module)
{
if (module.InternalDataModel == null)
- return;
-
+ throw new ArtemisCoreException("Cannot add module data model that is not enabled");
if (module.InternalDataModel.DataModelDescription == null)
throw new ArtemisPluginFeatureException(module, "Module overrides GetDataModelDescription but returned null");
@@ -72,6 +71,8 @@ namespace Artemis.Core.Services
private void AddDataModelExpansionDataModel(BaseDataModelExpansion dataModelExpansion)
{
+ if (dataModelExpansion.InternalDataModel == null)
+ throw new ArtemisCoreException("Cannot add data model expansion that is not enabled");
if (dataModelExpansion.InternalDataModel.DataModelDescription == null)
throw new ArtemisPluginFeatureException(dataModelExpansion, "Data model expansion overrides GetDataModelDescription but returned null");
diff --git a/src/Artemis.Core/Services/Registration/Interfaces/IConditionOperatorService.cs b/src/Artemis.Core/Services/Registration/Interfaces/IConditionOperatorService.cs
index 359fec8d9..9b32ecc3f 100644
--- a/src/Artemis.Core/Services/Registration/Interfaces/IConditionOperatorService.cs
+++ b/src/Artemis.Core/Services/Registration/Interfaces/IConditionOperatorService.cs
@@ -32,6 +32,6 @@ namespace Artemis.Core.Services
///
/// The operator's plugin GUID
/// The type name of the operator
- BaseConditionOperator GetConditionOperator(Guid operatorPluginGuid, string operatorType);
+ BaseConditionOperator? GetConditionOperator(Guid operatorPluginGuid, string operatorType);
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/Registration/Interfaces/IDataBindingService.cs b/src/Artemis.Core/Services/Registration/Interfaces/IDataBindingService.cs
index 27ca01ab3..36b73dcaf 100644
--- a/src/Artemis.Core/Services/Registration/Interfaces/IDataBindingService.cs
+++ b/src/Artemis.Core/Services/Registration/Interfaces/IDataBindingService.cs
@@ -33,6 +33,6 @@ namespace Artemis.Core.Services
/// The modifier type's plugin GUID
/// The type name of the modifier type
///
- BaseDataBindingModifierType GetModifierType(Guid modifierTypePluginGuid, string modifierType);
+ BaseDataBindingModifierType? GetModifierType(Guid modifierTypePluginGuid, string modifierType);
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/Registration/Interfaces/IDataModelService.cs b/src/Artemis.Core/Services/Registration/Interfaces/IDataModelService.cs
index 2f07006b6..072c68601 100644
--- a/src/Artemis.Core/Services/Registration/Interfaces/IDataModelService.cs
+++ b/src/Artemis.Core/Services/Registration/Interfaces/IDataModelService.cs
@@ -29,7 +29,7 @@ namespace Artemis.Core.Services
/// If found, returns the registered data model of type
///
/// The type of the data model to find
- T GetDataModel() where T : DataModel;
+ T? GetDataModel() where T : DataModel;
///
/// If found, returns the data model of the provided plugin
diff --git a/src/Artemis.Core/Services/Registration/LayerBrushService.cs b/src/Artemis.Core/Services/Registration/LayerBrushService.cs
index de738d6c4..667ecde87 100644
--- a/src/Artemis.Core/Services/Registration/LayerBrushService.cs
+++ b/src/Artemis.Core/Services/Registration/LayerBrushService.cs
@@ -34,7 +34,7 @@ namespace Artemis.Core.Services
return LayerBrushStore.GetAll().Select(r => r.LayerBrushDescriptor).ToList();
}
- public LayerBrushDescriptor GetDefaultLayerBrush()
+ public LayerBrushDescriptor? GetDefaultLayerBrush()
{
PluginSetting defaultReference = _settingsService.GetSetting("ProfileEditor.DefaultLayerBrushDescriptor", new LayerBrushReference
{
@@ -42,6 +42,8 @@ namespace Artemis.Core.Services
BrushType = "ColorBrush"
});
+ defaultReference.Value.LayerBrushProviderId ??= "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba";
+ defaultReference.Value.BrushType ??= "ColorBrush";
return LayerBrushStore.Get(defaultReference.Value.LayerBrushProviderId, defaultReference.Value.BrushType)?.LayerBrushDescriptor;
}
}
diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs
index 9091dbdd2..81031d862 100644
--- a/src/Artemis.Core/Services/RgbService.cs
+++ b/src/Artemis.Core/Services/RgbService.cs
@@ -17,7 +17,7 @@ namespace Artemis.Core.Services
private readonly PluginSetting _renderScaleSetting;
private readonly PluginSetting _sampleSizeSetting;
private readonly PluginSetting _targetFrameRateSetting;
- private ListLedGroup _surfaceLedGroup;
+ private ListLedGroup? _surfaceLedGroup;
public RgbService(ILogger logger, ISettingsService settingsService)
{
@@ -41,7 +41,7 @@ namespace Artemis.Core.Services
public RGBSurface Surface { get; set; }
public TimerUpdateTrigger UpdateTrigger { get; }
- public BitmapBrush BitmapBrush { get; private set; }
+ public BitmapBrush? BitmapBrush { get; private set; }
public IReadOnlyCollection LoadedDevices => _loadedDevices.AsReadOnly();
public double RenderScale => _renderScaleSetting.Value;
public bool IsRenderPaused { get; set; }
@@ -109,7 +109,7 @@ namespace Artemis.Core.Services
public void UpdateSurfaceLedGroup()
{
- if (_surfaceLedGroup == null)
+ if (_surfaceLedGroup == null || BitmapBrush == null)
{
// Apply the application wide brush and decorator
BitmapBrush = new BitmapBrush(new Scale(_renderScaleSetting.Value), _sampleSizeSetting);
@@ -126,10 +126,6 @@ namespace Artemis.Core.Services
BitmapBrush.Scale = new Scale(_renderScaleSetting.Value);
_surfaceLedGroup = new ListLedGroup(Surface.Leds) {Brush = BitmapBrush};
}
-
- lock (BitmapBrush)
- {
- }
}
private void OnDeviceLoaded(DeviceEventArgs e)
diff --git a/src/Artemis.Core/Services/SettingsService.cs b/src/Artemis.Core/Services/SettingsService.cs
index a5ca7d658..d58124c03 100644
--- a/src/Artemis.Core/Services/SettingsService.cs
+++ b/src/Artemis.Core/Services/SettingsService.cs
@@ -14,7 +14,7 @@ namespace Artemis.Core.Services
public PluginSetting GetSetting(string name, T defaultValue = default)
{
- return _pluginSettings.GetSetting(name, defaultValue);
+ return _pluginSettings.GetSetting(name, defaultValue!);
}
}
diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs
index c1c556618..098812196 100644
--- a/src/Artemis.Core/Services/Storage/ProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/ProfileService.cs
@@ -36,6 +36,40 @@ namespace Artemis.Core.Services
public JsonSerializerSettings MementoSettings { get; set; } = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All};
public JsonSerializerSettings ExportSettings { get; set; } = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All, Formatting = Formatting.Indented};
+ public ProfileDescriptor? GetLastActiveProfile(ProfileModule module)
+ {
+ List moduleProfiles = _profileRepository.GetByModuleId(module.Id);
+ if (!moduleProfiles.Any())
+ return CreateProfileDescriptor(module, "Default");
+
+ ProfileEntity? profileEntity = moduleProfiles.FirstOrDefault(p => p.IsActive) ?? moduleProfiles.FirstOrDefault();
+ return profileEntity == null ? null : new ProfileDescriptor(module, profileEntity);
+ }
+
+ private void SaveActiveProfile(ProfileModule module)
+ {
+ if (module.ActiveProfile == null)
+ return;
+
+ List profileEntities = _profileRepository.GetByModuleId(module.Id);
+ foreach (ProfileEntity profileEntity in profileEntities)
+ {
+ profileEntity.IsActive = module.ActiveProfile.EntityId == profileEntity.Id;
+ _profileRepository.Save(profileEntity);
+ }
+ }
+
+ ///
+ /// Populates all missing LEDs on all currently active profiles
+ ///
+ ///
+ private void ActiveProfilesPopulateLeds(ArtemisSurface surface)
+ {
+ List profileModules = _pluginManagementService.GetFeaturesOfType();
+ foreach (ProfileModule profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList())
+ profileModule.ActiveProfile?.PopulateLeds(surface); // Avoid race condition
+ }
+
public List GetProfileDescriptors(ProfileModule module)
{
List profileEntities = _profileRepository.GetByModuleId(module.Id);
@@ -52,14 +86,14 @@ namespace Artemis.Core.Services
public void ActivateLastProfile(ProfileModule profileModule)
{
- ProfileDescriptor activeProfile = GetLastActiveProfile(profileModule);
+ ProfileDescriptor? activeProfile = GetLastActiveProfile(profileModule);
if (activeProfile != null)
ActivateProfile(activeProfile);
}
public async Task ActivateLastProfileAnimated(ProfileModule profileModule)
{
- ProfileDescriptor activeProfile = GetLastActiveProfile(profileModule);
+ ProfileDescriptor? activeProfile = GetLastActiveProfile(profileModule);
if (activeProfile != null)
await ActivateProfileAnimated(activeProfile);
}
@@ -196,7 +230,8 @@ namespace Artemis.Core.Services
string top = profile.UndoStack.Pop();
string memento = JsonConvert.SerializeObject(profile.ProfileEntity, MementoSettings);
profile.RedoStack.Push(memento);
- profile.ProfileEntity = JsonConvert.DeserializeObject(top, MementoSettings);
+ profile.ProfileEntity = JsonConvert.DeserializeObject(top, MementoSettings)
+ ?? throw new InvalidOperationException("Failed to deserialize memento");
profile.Load();
InstantiateProfile(profile);
@@ -220,7 +255,8 @@ namespace Artemis.Core.Services
string top = profile.RedoStack.Pop();
string memento = JsonConvert.SerializeObject(profile.ProfileEntity, MementoSettings);
profile.UndoStack.Push(memento);
- profile.ProfileEntity = JsonConvert.DeserializeObject(top, MementoSettings);
+ profile.ProfileEntity = JsonConvert.DeserializeObject(top, MementoSettings)
+ ?? throw new InvalidOperationException("Failed to deserialize memento");
profile.Load();
InstantiateProfile(profile);
@@ -246,7 +282,9 @@ namespace Artemis.Core.Services
public ProfileDescriptor ImportProfile(string json, ProfileModule profileModule)
{
- ProfileEntity profileEntity = JsonConvert.DeserializeObject(json, ExportSettings);
+ ProfileEntity? profileEntity = JsonConvert.DeserializeObject(json, ExportSettings);
+ if (profileEntity == null)
+ throw new ArtemisCoreException("Failed to import profile but JSON.NET threw no error :(");
// Assign a new GUID to make sure it is unique in case of a previous import of the same content
profileEntity.UpdateGuid(Guid.NewGuid());
@@ -256,40 +294,6 @@ namespace Artemis.Core.Services
return new ProfileDescriptor(profileModule, profileEntity);
}
- public ProfileDescriptor GetLastActiveProfile(ProfileModule module)
- {
- List moduleProfiles = _profileRepository.GetByModuleId(module.Id);
- if (!moduleProfiles.Any())
- return CreateProfileDescriptor(module, "Default");
-
- ProfileEntity profileEntity = moduleProfiles.FirstOrDefault(p => p.IsActive) ?? moduleProfiles.FirstOrDefault();
- return profileEntity == null ? null : new ProfileDescriptor(module, profileEntity);
- }
-
- private void SaveActiveProfile(ProfileModule module)
- {
- if (module.ActiveProfile == null)
- return;
-
- List profileEntities = _profileRepository.GetByModuleId(module.Id);
- foreach (ProfileEntity profileEntity in profileEntities)
- {
- profileEntity.IsActive = module.ActiveProfile.EntityId == profileEntity.Id;
- _profileRepository.Save(profileEntity);
- }
- }
-
- ///
- /// Populates all missing LEDs on all currently active profiles
- ///
- ///
- private void ActiveProfilesPopulateLeds(ArtemisSurface surface)
- {
- List profileModules = _pluginManagementService.GetFeaturesOfType();
- foreach (ProfileModule profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList())
- profileModule.ActiveProfile.PopulateLeds(surface);
- }
-
#region Event handlers
private void OnActiveSurfaceConfigurationSelected(object? sender, SurfaceConfigurationEventArgs e)
diff --git a/src/Artemis.Core/Services/Storage/SurfaceService.cs b/src/Artemis.Core/Services/Storage/SurfaceService.cs
index af1b2a349..b7340bd56 100644
--- a/src/Artemis.Core/Services/Storage/SurfaceService.cs
+++ b/src/Artemis.Core/Services/Storage/SurfaceService.cs
@@ -28,6 +28,8 @@ namespace Artemis.Core.Services
_surfaceConfigurations = new List();
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.5);
+ // LoadFromRepository is guaranteed to set the ActiveSurface
+ ActiveSurface = null!;
LoadFromRepository();
_rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded;
@@ -61,6 +63,7 @@ namespace Artemis.Core.Services
public void SetActiveSurfaceConfiguration(ArtemisSurface surface)
{
+ if (surface == null) throw new ArgumentNullException(nameof(surface));
if (ActiveSurface == surface)
return;
@@ -81,11 +84,8 @@ namespace Artemis.Core.Services
}
// Apply the active surface entity to the devices
- if (ActiveSurface != null)
- {
- foreach (ArtemisDevice device in ActiveSurface.Devices)
- device.ApplyToRgbDevice();
- }
+ foreach (ArtemisDevice device in ActiveSurface.Devices)
+ device.ApplyToRgbDevice();
// Update the RGB service's graphics decorator to work with the new surface entity
_rgbService.UpdateSurfaceLedGroup();
@@ -134,7 +134,7 @@ namespace Artemis.Core.Services
ArtemisSurface surfaceConfiguration = new ArtemisSurface(_rgbService.Surface, surfaceEntity, _renderScaleSetting.Value);
foreach (DeviceEntity position in surfaceEntity.DeviceEntities)
{
- IRGBDevice device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
+ IRGBDevice? device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
if (device != null)
{
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(device);
@@ -150,7 +150,7 @@ namespace Artemis.Core.Services
}
// When all surface configs are loaded, apply the active surface config
- ArtemisSurface active = SurfaceConfigurations.FirstOrDefault(c => c.IsActive);
+ ArtemisSurface? active = SurfaceConfigurations.FirstOrDefault(c => c.IsActive);
if (active != null)
SetActiveSurfaceConfiguration(active);
else
@@ -170,13 +170,13 @@ namespace Artemis.Core.Services
private void AddDeviceIfMissing(IRGBDevice rgbDevice, ArtemisSurface surface)
{
string deviceIdentifier = rgbDevice.GetDeviceIdentifier();
- ArtemisDevice device = surface.Devices.FirstOrDefault(d => d.DeviceEntity.DeviceIdentifier == deviceIdentifier);
+ ArtemisDevice? device = surface.Devices.FirstOrDefault(d => d.DeviceEntity.DeviceIdentifier == deviceIdentifier);
if (device != null)
return;
// Find an existing device config and use that
- DeviceEntity existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
+ DeviceEntity? existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
if (existingDeviceConfig != null)
{
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
@@ -225,8 +225,8 @@ namespace Artemis.Core.Services
#region Events
- public event EventHandler ActiveSurfaceConfigurationSelected;
- public event EventHandler SurfaceConfigurationUpdated;
+ public event EventHandler? ActiveSurfaceConfigurationSelected;
+ public event EventHandler? SurfaceConfigurationUpdated;
protected virtual void OnActiveSurfaceConfigurationChanged(SurfaceConfigurationEventArgs e)
{
diff --git a/src/Artemis.Core/Stores/ConditionOperatorStore.cs b/src/Artemis.Core/Stores/ConditionOperatorStore.cs
index 67edee873..ae1437079 100644
--- a/src/Artemis.Core/Stores/ConditionOperatorStore.cs
+++ b/src/Artemis.Core/Stores/ConditionOperatorStore.cs
@@ -10,6 +10,9 @@ namespace Artemis.Core
public static ConditionOperatorRegistration Add(BaseConditionOperator conditionOperator)
{
+ if (conditionOperator.Plugin == null)
+ throw new ArtemisCoreException("Cannot add a condition operator to the store that is not related to a plugin");
+
ConditionOperatorRegistration registration;
lock (Registrations)
{
@@ -74,8 +77,8 @@ namespace Artemis.Core
#region Events
- public static event EventHandler ConditionOperatorAdded;
- public static event EventHandler ConditionOperatorRemoved;
+ public static event EventHandler? ConditionOperatorAdded;
+ public static event EventHandler? ConditionOperatorRemoved;
private static void OnConditionOperatorAdded(ConditionOperatorStoreEvent e)
{
diff --git a/src/Artemis.Core/Stores/DataModelStore.cs b/src/Artemis.Core/Stores/DataModelStore.cs
index 02e7a9603..7a6e14d03 100644
--- a/src/Artemis.Core/Stores/DataModelStore.cs
+++ b/src/Artemis.Core/Stores/DataModelStore.cs
@@ -57,8 +57,8 @@ namespace Artemis.Core
#region Events
- public static event EventHandler DataModelAdded;
- public static event EventHandler DataModelRemoved;
+ public static event EventHandler? DataModelAdded;
+ public static event EventHandler? DataModelRemoved;
private static void OnDataModelAdded(DataModelStoreEvent e)
{
diff --git a/src/Artemis.Core/Stores/LayerBrushStore.cs b/src/Artemis.Core/Stores/LayerBrushStore.cs
index fb05da802..b0897fdd8 100644
--- a/src/Artemis.Core/Stores/LayerBrushStore.cs
+++ b/src/Artemis.Core/Stores/LayerBrushStore.cs
@@ -58,8 +58,8 @@ namespace Artemis.Core
#region Events
- public static event EventHandler LayerBrushAdded;
- public static event EventHandler LayerBrushRemoved;
+ public static event EventHandler? LayerBrushAdded;
+ public static event EventHandler? LayerBrushRemoved;
private static void OnLayerBrushAdded(LayerBrushStoreEvent e)
{
diff --git a/src/Artemis.Core/Stores/LayerEffectStore.cs b/src/Artemis.Core/Stores/LayerEffectStore.cs
index ac3060bd9..65f2b1289 100644
--- a/src/Artemis.Core/Stores/LayerEffectStore.cs
+++ b/src/Artemis.Core/Stores/LayerEffectStore.cs
@@ -51,14 +51,14 @@ namespace Artemis.Core
{
lock (Registrations)
{
- return Registrations.FirstOrDefault(d => d.PluginFeature.Id == providerId && d.LayerEffectDescriptor.LayerEffectType.Name == typeName);
+ return Registrations.FirstOrDefault(d => d.PluginFeature.Id == providerId && d.LayerEffectDescriptor.LayerEffectType?.Name == typeName);
}
}
#region Events
- public static event EventHandler LayerEffectAdded;
- public static event EventHandler LayerEffectRemoved;
+ public static event EventHandler? LayerEffectAdded;
+ public static event EventHandler? LayerEffectRemoved;
private static void OnLayerEffectAdded(LayerEffectStoreEvent e)
{
diff --git a/src/Artemis.Core/Utilities/CurrentProcessUtilities.cs b/src/Artemis.Core/Utilities/CurrentProcessUtilities.cs
index e04096b22..99aa6a3d0 100644
--- a/src/Artemis.Core/Utilities/CurrentProcessUtilities.cs
+++ b/src/Artemis.Core/Utilities/CurrentProcessUtilities.cs
@@ -23,7 +23,7 @@ namespace Artemis.Core
string arguments = "-Command \"& {Start-Sleep -s " + delay + "; (Get-Process 'Artemis.UI').kill()}";
// If restart is required, start the executable again after the process was killed
if (restart)
- arguments = "-Command \"& {Start-Sleep -s " + delay + "; (Get-Process 'Artemis.UI').kill(); Start-Process -FilePath '" + Process.GetCurrentProcess().MainModule.FileName + "'}\"";
+ arguments = "-Command \"& {Start-Sleep -s " + delay + "; (Get-Process 'Artemis.UI').kill(); Start-Process -FilePath '" + Process.GetCurrentProcess().MainModule!.FileName + "'}\"";
ProcessStartInfo info = new ProcessStartInfo
{
@@ -45,7 +45,7 @@ namespace Artemis.Core
///
/// The URL to open
/// The process created to open the URL
- public static Process OpenUrl(string url)
+ public static Process? OpenUrl(string url)
{
ProcessStartInfo processInfo = new ProcessStartInfo
{
@@ -61,7 +61,7 @@ namespace Artemis.Core
///
internal static string GetCurrentLocation()
{
- return Process.GetCurrentProcess().MainModule.FileName;
+ return Process.GetCurrentProcess().MainModule!.FileName!;
}
#region Events
diff --git a/src/Artemis.Core/Utilities/DeserializationLogger.cs b/src/Artemis.Core/Utilities/DeserializationLogger.cs
index de4424def..f75542c87 100644
--- a/src/Artemis.Core/Utilities/DeserializationLogger.cs
+++ b/src/Artemis.Core/Utilities/DeserializationLogger.cs
@@ -6,7 +6,7 @@ namespace Artemis.Core
{
internal static class DeserializationLogger
{
- private static ILogger _logger;
+ private static ILogger? _logger;
public static void Initialize(IKernel kernel)
{
@@ -15,7 +15,7 @@ namespace Artemis.Core
public static void LogPredicateDeserializationFailure(DataModelConditionPredicate dataModelConditionPredicate, JsonException exception)
{
- _logger.Warning(
+ _logger?.Warning(
exception,
"Failed to deserialize display condition predicate {left} {operator} {right}",
dataModelConditionPredicate.Entity.LeftPath?.Path,
@@ -26,7 +26,7 @@ namespace Artemis.Core
public static void LogModifierDeserializationFailure(string modifierName, JsonSerializationException exception)
{
- _logger.Warning(exception, "Failed to deserialize static parameter for modifier {modifierName}", modifierName);
+ _logger?.Warning(exception, "Failed to deserialize static parameter for modifier {modifierName}", modifierName);
}
}
}
diff --git a/src/Artemis.Core/Utilities/ExpressionUtilities.cs b/src/Artemis.Core/Utilities/ExpressionUtilities.cs
index 12a0a31a8..4db041961 100644
--- a/src/Artemis.Core/Utilities/ExpressionUtilities.cs
+++ b/src/Artemis.Core/Utilities/ExpressionUtilities.cs
@@ -19,7 +19,7 @@ namespace Artemis.Core
{
// Create an expression that checks every part of the path for null
// In the same iteration, create the accessor
- Expression condition = null;
+ Expression? condition = null;
foreach (string memberName in path.Split('.'))
{
BinaryExpression notNull = Expression.NotEqual(source, Expression.Constant(null));
diff --git a/src/Artemis.Core/Utilities/IntroAnimation.cs b/src/Artemis.Core/Utilities/IntroAnimation.cs
index 8030b10fb..604191a94 100644
--- a/src/Artemis.Core/Utilities/IntroAnimation.cs
+++ b/src/Artemis.Core/Utilities/IntroAnimation.cs
@@ -21,21 +21,19 @@ namespace Artemis.Core
_logger = logger;
_profileService = profileService;
_surfaceService = surfaceService;
- CreateIntroProfile();
+
+ AnimationProfile = CreateIntroProfile();
}
public Profile AnimationProfile { get; set; }
public void Render(double deltaTime, SKCanvas canvas)
{
- if (AnimationProfile == null)
- return;
-
AnimationProfile.Update(deltaTime);
AnimationProfile.Render(canvas);
}
- private void CreateIntroProfile()
+ private Profile CreateIntroProfile()
{
try
{
@@ -44,24 +42,24 @@ namespace Artemis.Core
ProfileEntity profileEntity = JsonConvert.DeserializeObject(json);
// Inject every LED on the surface into each layer
foreach (LayerEntity profileEntityLayer in profileEntity.Layers)
- {
profileEntityLayer.Leds.AddRange(_surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds).Select(l => new LedEntity
{
DeviceIdentifier = l.Device.RgbDevice.GetDeviceIdentifier(),
LedName = l.RgbLed.Id.ToString()
}));
- }
Profile profile = new Profile(new DummyModule(), profileEntity);
profile.Activate(_surfaceService.ActiveSurface);
_profileService.InstantiateProfile(profile);
- AnimationProfile = profile;
+ return profile;
}
catch (Exception e)
{
_logger.Warning(e, "Failed to load intro profile");
}
+
+ return new Profile(new DummyModule(), "Intro");
}
}
diff --git a/src/Artemis.Core/Utilities/ReflectionUtilities.cs b/src/Artemis.Core/Utilities/ReflectionUtilities.cs
index 7816f36bb..8b914996d 100644
--- a/src/Artemis.Core/Utilities/ReflectionUtilities.cs
+++ b/src/Artemis.Core/Utilities/ReflectionUtilities.cs
@@ -10,11 +10,11 @@ namespace Artemis.Core
{
Type type = typeof(TSource);
- MemberExpression member = propertyLambda.Body as MemberExpression;
+ MemberExpression? member = propertyLambda.Body as MemberExpression;
if (member == null)
throw new ArgumentException(string.Format("Expression '{0}' refers to a method, not a property.", propertyLambda));
- PropertyInfo propInfo = member.Member as PropertyInfo;
+ PropertyInfo? propInfo = member.Member as PropertyInfo;
if (propInfo == null)
throw new ArgumentException(string.Format("Expression '{0}' refers to a field, not a property.", propertyLambda));