diff --git a/src/Artemis.Core/Models/Profile/Conditions/Abstract/DataModelConditionPart.cs b/src/Artemis.Core/Models/Profile/Conditions/Abstract/DataModelConditionPart.cs index abbdfb519..d86df56a0 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/Abstract/DataModelConditionPart.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/Abstract/DataModelConditionPart.cs @@ -13,6 +13,11 @@ namespace Artemis.Core { private readonly List _children = new(); + protected DataModelConditionPart() + { + Children = new(_children); + } + /// /// Gets the parent of this part /// @@ -21,7 +26,7 @@ namespace Artemis.Core /// /// Gets the children of this part /// - public ReadOnlyCollection Children => _children.AsReadOnly(); + public ReadOnlyCollection Children { get; } /// /// Adds a child to the display condition part's collection diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Modes/Conditional/ConditionalDataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/Modes/Conditional/ConditionalDataBinding.cs index 96a8a5450..d5d50125d 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/Modes/Conditional/ConditionalDataBinding.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/Modes/Conditional/ConditionalDataBinding.cs @@ -18,13 +18,14 @@ namespace Artemis.Core { DataBinding = dataBinding; Entity = entity; + Conditions = new(_conditions); Load(); } /// /// Gets a list of conditions applied to this data binding /// - public ReadOnlyCollection> Conditions => _conditions.AsReadOnly(); + public ReadOnlyCollection> Conditions { get; } internal ConditionalDataBindingEntity Entity { get; } diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Modes/DirectDataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/Modes/DirectDataBinding.cs index 0dba4bd45..5ed0c6d67 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/Modes/DirectDataBinding.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/Modes/DirectDataBinding.cs @@ -17,7 +17,7 @@ namespace Artemis.Core { DataBinding = dataBinding; Entity = entity; - + Modifiers = new(_modifiers); Load(); } @@ -29,7 +29,7 @@ namespace Artemis.Core /// /// Gets a list of modifiers applied to this data binding /// - public ReadOnlyCollection> Modifiers => _modifiers.AsReadOnly(); + public ReadOnlyCollection> Modifiers { get; } internal DirectDataBindingEntity Entity { get; } diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index c28e9ea00..7ef74f1d1 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -306,7 +306,7 @@ namespace Artemis.Core ChildrenList.Add(new Layer(Profile, this, childLayer)); // Ensure order integrity, should be unnecessary but no one is perfect specially me - ChildrenList = ChildrenList.OrderBy(c => c.Order).ToList(); + ChildrenList.Sort((a,b) => a.Order.CompareTo(b.Order)); for (int index = 0; index < ChildrenList.Count; index++) ChildrenList[index].Order = index + 1; diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 8b6cde56e..dfb0a68dc 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -43,6 +43,7 @@ namespace Artemis.Core _transform = new LayerTransformProperties(); _leds = new List(); + Leds = new ReadOnlyCollection(_leds); Adapter = new LayerAdapter(this); Initialize(); @@ -67,6 +68,7 @@ namespace Artemis.Core _transform = new LayerTransformProperties(); _leds = new List(); + Leds = new ReadOnlyCollection(_leds); Adapter = new LayerAdapter(this); Load(); @@ -76,7 +78,7 @@ namespace Artemis.Core /// /// A collection of all the LEDs this layer is assigned to. /// - public ReadOnlyCollection Leds => _leds.AsReadOnly(); + public ReadOnlyCollection Leds { get; private set; } /// /// Defines the shape that is rendered by the . @@ -679,6 +681,7 @@ namespace Artemis.Core } _leds = leds; + Leds = new ReadOnlyCollection(_leds); CalculateRenderProperties(); } diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index 3d83ce37b..6bcf8f8b2 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -44,6 +44,7 @@ namespace Artemis.Core _baseValue = default!; _keyframes = new List>(); + Keyframes = new(_keyframes); } /// @@ -337,7 +338,7 @@ namespace Artemis.Core #region Keyframes private bool _keyframesEnabled; - private List> _keyframes; + private readonly List> _keyframes; /// /// Gets whether keyframes are supported on this type of property @@ -363,7 +364,7 @@ namespace Artemis.Core /// /// Gets a read-only list of all the keyframes on this layer property /// - public ReadOnlyCollection> Keyframes => _keyframes.AsReadOnly(); + public ReadOnlyCollection> Keyframes { get; } /// /// Gets the current keyframe in the timeline according to the current progress @@ -436,7 +437,7 @@ namespace Artemis.Core /// internal void SortKeyframes() { - _keyframes = _keyframes.OrderBy(k => k.Position).ToList(); + _keyframes.Sort((a, b) => a.Position.CompareTo(b.Position)); } private void UpdateKeyframes(Timeline timeline) diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs index 7483733a9..00658528d 100644 --- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs +++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs @@ -37,6 +37,9 @@ namespace Artemis.Core _layerProperties = new List(); _layerPropertyGroups = new List(); + + LayerProperties = new(_layerProperties); + LayerPropertyGroups = new(_layerPropertyGroups); } /// @@ -96,12 +99,12 @@ namespace Artemis.Core /// /// A list of all layer properties in this group /// - public ReadOnlyCollection LayerProperties => _layerProperties.AsReadOnly(); + public ReadOnlyCollection LayerProperties { get; } /// /// A list of al child groups in this group /// - public ReadOnlyCollection LayerPropertyGroups => _layerPropertyGroups.AsReadOnly(); + public ReadOnlyCollection LayerPropertyGroups { get; } /// /// Recursively gets all layer properties on this group and any subgroups diff --git a/src/Artemis.Core/Models/Profile/ProfileCategory.cs b/src/Artemis.Core/Models/Profile/ProfileCategory.cs index c53e36129..c00671f56 100644 --- a/src/Artemis.Core/Models/Profile/ProfileCategory.cs +++ b/src/Artemis.Core/Models/Profile/ProfileCategory.cs @@ -24,12 +24,15 @@ namespace Artemis.Core { _name = name; Entity = new ProfileCategoryEntity(); + ProfileConfigurations = new(_profileConfigurations); } internal ProfileCategory(ProfileCategoryEntity entity) { _name = null!; Entity = entity; + ProfileConfigurations = new(_profileConfigurations); + Load(); } @@ -73,7 +76,7 @@ namespace Artemis.Core /// /// Gets a read only collection of the profiles inside this category /// - public ReadOnlyCollection ProfileConfigurations => _profileConfigurations.AsReadOnly(); + public ReadOnlyCollection ProfileConfigurations { get; } /// /// Gets the unique ID of this category diff --git a/src/Artemis.Core/Models/Profile/ProfileElement.cs b/src/Artemis.Core/Models/Profile/ProfileElement.cs index 81537b0ba..74bbfc0af 100644 --- a/src/Artemis.Core/Models/Profile/ProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/ProfileElement.cs @@ -18,12 +18,13 @@ namespace Artemis.Core private Profile _profile; private bool _suspended; - internal List ChildrenList; + internal readonly List ChildrenList; internal ProfileElement(Profile profile) { _profile = profile; ChildrenList = new List(); + Children = new(ChildrenList); } /// @@ -56,16 +57,7 @@ namespace Artemis.Core /// /// The element's children /// - public ReadOnlyCollection Children - { - get - { - lock (ChildrenList) - { - return ChildrenList.AsReadOnly(); - } - } - } + public ReadOnlyCollection Children { get; } /// /// The order in which this element appears in the update loop and editor diff --git a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs index bd4b4994a..6d70fa31a 100644 --- a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs @@ -24,6 +24,7 @@ namespace Artemis.Core Timeline = new Timeline(); ExpandedPropertyGroups = new List(); LayerEffectsList = new List(); + LayerEffects = new(LayerEffectsList); LayerEffectStore.LayerEffectAdded += LayerEffectStoreOnLayerEffectAdded; LayerEffectStore.LayerEffectRemoved += LayerEffectStoreOnLayerEffectRemoved; @@ -223,12 +224,12 @@ namespace Artemis.Core #region Effect management - internal List LayerEffectsList; + internal readonly List LayerEffectsList; /// /// Gets a read-only collection of the layer effects on this entity /// - public ReadOnlyCollection LayerEffects => LayerEffectsList.AsReadOnly(); + public ReadOnlyCollection LayerEffects { get; } /// /// Adds a the layer effect described inthe provided diff --git a/src/Artemis.Core/Models/Profile/Timeline.cs b/src/Artemis.Core/Models/Profile/Timeline.cs index a01b9d232..5e29dc86e 100644 --- a/src/Artemis.Core/Models/Profile/Timeline.cs +++ b/src/Artemis.Core/Models/Profile/Timeline.cs @@ -24,6 +24,7 @@ namespace Artemis.Core MainSegmentLength = TimeSpan.FromSeconds(5); _extraTimelines = new List(); + ExtraTimelines = new(_extraTimelines); Save(); } @@ -32,6 +33,7 @@ namespace Artemis.Core { Entity = entity; _extraTimelines = new List(); + ExtraTimelines = new(_extraTimelines); Load(); } @@ -45,6 +47,7 @@ namespace Artemis.Core EndSegmentLength = Parent.EndSegmentLength; _extraTimelines = new List(); + ExtraTimelines = new(_extraTimelines); } /// @@ -150,7 +153,7 @@ namespace Artemis.Core /// /// Gets a list of extra copies of the timeline applied to this timeline /// - public ReadOnlyCollection ExtraTimelines => _extraTimelines.AsReadOnly(); + public ReadOnlyCollection ExtraTimelines { get; } /// /// Gets a boolean indicating whether the timeline has finished its run diff --git a/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushProvider.cs b/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushProvider.cs index c2cea1742..25f72b7ac 100644 --- a/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushProvider.cs +++ b/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushProvider.cs @@ -17,13 +17,14 @@ namespace Artemis.Core.LayerBrushes protected LayerBrushProvider() { _layerBrushDescriptors = new List(); + LayerBrushDescriptors = new(_layerBrushDescriptors); Disabled += OnDisabled; } /// /// A read-only collection of all layer brushes added with /// - public ReadOnlyCollection LayerBrushDescriptors => _layerBrushDescriptors.AsReadOnly(); + public ReadOnlyCollection LayerBrushDescriptors { get; } /// /// Registers a layer brush descriptor for a given layer brush, so that it appears in the UI. diff --git a/src/Artemis.Core/Plugins/LayerEffects/LayerEffectProvider.cs b/src/Artemis.Core/Plugins/LayerEffects/LayerEffectProvider.cs index b457bb90e..a35eb156f 100644 --- a/src/Artemis.Core/Plugins/LayerEffects/LayerEffectProvider.cs +++ b/src/Artemis.Core/Plugins/LayerEffects/LayerEffectProvider.cs @@ -18,13 +18,14 @@ namespace Artemis.Core.LayerEffects protected LayerEffectProvider() { _layerEffectDescriptors = new List(); + LayerEffectDescriptors = new(_layerEffectDescriptors); Disabled += OnDisabled; } /// /// A read-only collection of all layer effects added with /// - public ReadOnlyCollection LayerEffectDescriptors => _layerEffectDescriptors.AsReadOnly(); + public ReadOnlyCollection LayerEffectDescriptors { get; } /// /// Adds a layer effect descriptor for a given layer effect, so that it appears in the UI. diff --git a/src/Artemis.Core/Plugins/Modules/DataModel.cs b/src/Artemis.Core/Plugins/Modules/DataModel.cs index c2eb187c9..4587c996a 100644 --- a/src/Artemis.Core/Plugins/Modules/DataModel.cs +++ b/src/Artemis.Core/Plugins/Modules/DataModel.cs @@ -26,6 +26,9 @@ namespace Artemis.Core.Modules // These are both set right after construction to keep the constructor of inherited classes clean Module = null!; DataModelDescription = null!; + + ActivePaths = new(_activePaths); + DynamicChildren = new(_dynamicChildren); } /// @@ -52,13 +55,13 @@ namespace Artemis.Core.Modules /// Gets an read-only dictionary of all dynamic children /// [DataModelIgnore] - public ReadOnlyDictionary DynamicChildren => new(_dynamicChildren); + public ReadOnlyDictionary DynamicChildren { get; } /// /// Gets a read-only list of s targeting this data model /// [DataModelIgnore] - public ReadOnlyCollection ActivePaths => _activePaths.AsReadOnly(); + public ReadOnlyCollection ActivePaths { get; } /// /// Returns a read-only collection of all properties in this datamodel that are to be ignored diff --git a/src/Artemis.Core/Plugins/Modules/Module.cs b/src/Artemis.Core/Plugins/Modules/Module.cs index aa2d84691..2874355f9 100644 --- a/src/Artemis.Core/Plugins/Modules/Module.cs +++ b/src/Artemis.Core/Plugins/Modules/Module.cs @@ -114,6 +114,12 @@ namespace Artemis.Core.Modules private readonly List<(DefaultCategoryName, string)> _defaultProfilePaths = new(); private readonly List<(DefaultCategoryName, string)> _pendingDefaultProfilePaths = new(); + public Module() + { + DefaultProfilePaths = new ReadOnlyCollection<(DefaultCategoryName, string)>(_defaultProfilePaths); + HiddenProperties = new(HiddenPropertiesList); + } + /// /// Gets a list of all properties ignored at runtime using IgnoreProperty(x => x.y) /// @@ -122,7 +128,7 @@ namespace Artemis.Core.Modules /// /// Gets a read only collection of default profile paths /// - public IReadOnlyCollection<(DefaultCategoryName, string)> DefaultProfilePaths => _defaultProfilePaths.AsReadOnly(); + public IReadOnlyCollection<(DefaultCategoryName, string)> DefaultProfilePaths { get; } /// /// A list of activation requirements @@ -176,7 +182,7 @@ namespace Artemis.Core.Modules /// /// Gets a list of all properties ignored at runtime using IgnoreProperty(x => x.y) /// - public ReadOnlyCollection HiddenProperties => HiddenPropertiesList.AsReadOnly(); + public ReadOnlyCollection HiddenProperties { get; } internal DataModel? InternalDataModel { get; set; } diff --git a/src/Artemis.Core/Plugins/Plugin.cs b/src/Artemis.Core/Plugins/Plugin.cs index 49f67ed78..c82eab146 100644 --- a/src/Artemis.Core/Plugins/Plugin.cs +++ b/src/Artemis.Core/Plugins/Plugin.cs @@ -30,6 +30,9 @@ namespace Artemis.Core _features = new List(); _profilers = new List(); + + Features = new(_features); + Profilers = new(_profilers); } /// @@ -64,12 +67,12 @@ namespace Artemis.Core /// /// Gets a read-only collection of all features this plugin provides /// - public ReadOnlyCollection Features => _features.AsReadOnly(); + public ReadOnlyCollection Features { get; } /// /// Gets a read-only collection of profiles running on the plugin /// - public ReadOnlyCollection Profilers => _profilers.AsReadOnly(); + public ReadOnlyCollection Profilers { get; } /// /// The assembly the plugin code lives in diff --git a/src/Artemis.Core/Plugins/ScriptingProviders/ScriptingProvider.cs b/src/Artemis.Core/Plugins/ScriptingProviders/ScriptingProvider.cs index 08568f78e..0ae720943 100644 --- a/src/Artemis.Core/Plugins/ScriptingProviders/ScriptingProvider.cs +++ b/src/Artemis.Core/Plugins/ScriptingProviders/ScriptingProvider.cs @@ -44,6 +44,11 @@ namespace Artemis.Core.ScriptingProviders /// public abstract class ScriptingProvider : PluginFeature { + protected ScriptingProvider() + { + Scripts = new(InternalScripts); + } + /// /// Gets the name of the scripting language this provider provides /// @@ -52,7 +57,7 @@ namespace Artemis.Core.ScriptingProviders /// /// Gets a list of all active scripts belonging to this scripting provider /// - public ReadOnlyCollection