From fea454ad12758dd7abb3953abfa9e6d7a69e3b91 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Mon, 14 Sep 2020 01:24:07 +0200 Subject: [PATCH] Profile editor - Finished most of the refactor except databindings --- .../Artemis.Core.csproj.DotSettings | 1 + src/Artemis.Core/Constants.cs | 8 +- .../Converters/FloatDataBindingConverter.cs | 14 +- .../Converters/GeneralDataBindingConverter.cs | 2 +- .../Converters/IntDataBindingConverter.cs | 2 +- .../Profile/DataBindings/DataBinding.cs | 46 ++-- .../DataBindings/DataBindingConverter.cs | 30 ++- .../DataBindings/DataBindingModifier.cs | 6 +- .../DataBindings/DataBindingRegistration.cs | 18 +- src/Artemis.Core/Models/Profile/Folder.cs | 12 +- src/Artemis.Core/Models/Profile/Layer.cs | 24 +- .../Models/Profile/LayerBrushReference.cs | 10 + .../Profile/LayerProperties/ILayerProperty.cs | 5 - .../Profile/LayerProperties/LayerProperty.cs | 8 +- .../Models/Profile/LayerPropertyGroup.cs | 4 + .../Models/Profile/RenderProfileElement.cs | 68 ++++-- .../LayerBrushes/LayerBrushDescriptor.cs | 7 + .../LayerEffects/Internal/BaseLayerEffect.cs | 4 +- .../LayerEffects/LayerEffectDescriptor.cs | 10 +- .../Placeholder/PlaceholderLayerEffect.cs | 29 ++- .../PlaceholderLayerEffectDescriptor.cs | 12 +- src/Artemis.Core/Plugins/Plugin.cs | 2 +- .../Interfaces/ILayerBrushService.cs | 5 + .../Registration/LayerBrushService.cs | 18 ++ .../Services/Storage/ProfileService.cs | 15 +- src/Artemis.Core/Utilities/CorePlugin.cs | 40 ++++ .../Profile/DataBindings/DataBindingEntity.cs | 2 +- .../Ninject/Factories/IVMFactory.cs | 12 +- .../DataBindingsViewModelInstanceProvider.cs | 14 +- src/Artemis.UI/Ninject/UiModule.cs | 1 + .../PropertyInput/BrushPropertyInputView.xaml | 31 +-- .../BrushPropertyInputViewModel.cs | 15 +- .../LayerBrushDescriptors.xaml | 27 +++ .../DisplayConditionsViewModel.cs | 17 +- .../DataBindings/DataBindingView.xaml | 6 +- .../DataBindings/DataBindingViewModel.cs | 22 +- .../DataBindings/DataBindingsView.xaml | 2 +- .../DataBindings/DataBindingsViewModel.cs | 9 + .../LayerEffects/EffectsView.xaml | 2 +- .../LayerPropertiesViewModel.cs | 2 +- .../LayerPropertyGroupViewModel.cs | 153 +++++++------ .../LayerProperties/LayerPropertyViewModel.cs | 12 +- .../Timeline/TimelineGroupViewModel.cs | 39 +++- .../Timeline/TimelineKeyframeViewModel.cs | 38 ++-- .../Timeline/TimelinePropertyView.xaml | 2 +- .../Timeline/TimelinePropertyViewModel.cs | 28 ++- .../Timeline/TimelineSegmentViewModel.cs | 209 ++++++++++-------- .../Timeline/TimelineView.xaml | 4 +- .../Timeline/TimelineViewModel.cs | 142 +++++++----- .../Tree/TreePropertyViewModel.cs | 9 + .../ProfileTree/TreeItem/FolderViewModel.cs | 7 +- .../ProfileTree/TreeItem/LayerViewModel.cs | 7 +- .../ProfileTree/TreeItem/TreeItemViewModel.cs | 15 +- .../Tools/SelectionToolViewModel.cs | 31 ++- .../Tabs/General/GeneralSettingsTabView.xaml | 41 ++++ .../General/GeneralSettingsTabViewModel.cs | 26 ++- 56 files changed, 866 insertions(+), 459 deletions(-) create mode 100644 src/Artemis.Core/Utilities/CorePlugin.cs create mode 100644 src/Artemis.UI/ResourceDictionaries/LayerBrushDescriptors.xaml diff --git a/src/Artemis.Core/Artemis.Core.csproj.DotSettings b/src/Artemis.Core/Artemis.Core.csproj.DotSettings index 7f651acb6..abb086d59 100644 --- a/src/Artemis.Core/Artemis.Core.csproj.DotSettings +++ b/src/Artemis.Core/Artemis.Core.csproj.DotSettings @@ -23,6 +23,7 @@ True True True + True True True True diff --git a/src/Artemis.Core/Constants.cs b/src/Artemis.Core/Constants.cs index 0fa81409d..267ec0b76 100644 --- a/src/Artemis.Core/Constants.cs +++ b/src/Artemis.Core/Constants.cs @@ -32,7 +32,13 @@ namespace Artemis.Core /// /// The plugin info used by core components of Artemis /// - public static readonly PluginInfo CorePluginInfo = new PluginInfo {Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core"}; + public static readonly PluginInfo CorePluginInfo = new PluginInfo + { + Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core", Enabled = true + }; + + internal static readonly CorePlugin CorePlugin = new CorePlugin {PluginInfo = CorePluginInfo}; + internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new EffectPlaceholderPlugin {PluginInfo = CorePluginInfo}; /// /// A read-only collection containing all primitive numeric types diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs index bd061eaa4..7a0c3d0a8 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/Converters/FloatDataBindingConverter.cs @@ -1,4 +1,5 @@ using System; +using SkiaSharp; namespace Artemis.Core { @@ -36,12 +37,23 @@ namespace Artemis.Core /// public override void ApplyValue(float value) { + if (SetExpression == null) + return; + if (DataBinding.LayerProperty.PropertyDescription.MaxInputValue is float max) value = Math.Min(value, max); if (DataBinding.LayerProperty.PropertyDescription.MinInputValue is float min) value = Math.Max(value, min); - SetExpression?.Invoke(value); + var test = new SKSize(5,5); + test.Width = 10; + + SetExpression(DataBinding.LayerProperty.CurrentValue, value); + } + + private void Mehtest(ref SKSize test) + { + test.Width = 20; } /// diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Converters/GeneralDataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/Converters/GeneralDataBindingConverter.cs index 5d5ec636c..bb94f06ac 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/Converters/GeneralDataBindingConverter.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/Converters/GeneralDataBindingConverter.cs @@ -26,7 +26,7 @@ namespace Artemis.Core /// public override void ApplyValue(object value) { - SetExpression?.Invoke(value); + SetExpression?.Invoke(DataBinding.LayerProperty.CurrentValue, value); } /// diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Converters/IntDataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/Converters/IntDataBindingConverter.cs index 2bd6bd483..70daff304 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/Converters/IntDataBindingConverter.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/Converters/IntDataBindingConverter.cs @@ -41,7 +41,7 @@ namespace Artemis.Core /// public override void ApplyValue(int value) { - SetExpression?.Invoke(value); + SetExpression?.Invoke(DataBinding.LayerProperty.CurrentValue, value); } /// diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs index 7e5240820..d584a802a 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Reflection; using Artemis.Core.DataModelExpansions; using Artemis.Storage.Entities.Profile.DataBindings; @@ -14,9 +13,9 @@ namespace Artemis.Core private readonly List> _modifiers = new List>(); private TProperty _currentValue; + private bool _disposed; private TimeSpan _easingProgress; private TProperty _previousValue; - private bool _disposed; internal DataBinding(DataBindingRegistration dataBindingRegistration) { @@ -53,11 +52,6 @@ namespace Artemis.Core /// public DataBindingConverter Converter { get; private set; } - /// - /// Gets the property on the this data binding targets - /// - public PropertyInfo TargetProperty { get; private set; } - /// /// Gets the currently used instance of the data model that contains the source of the data binding /// @@ -118,8 +112,21 @@ namespace Artemis.Core if (Converter == null) return; - var value = GetValue(Converter.GetValue()); - Converter.ApplyValue(GetValue(value)); + var converterValue = Converter.GetValue(); + var value = GetValue(converterValue); + Converter.ApplyValue(value); + } + + /// + public void Dispose() + { + _disposed = true; + + DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded; + DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved; + + foreach (var dataBindingModifier in Modifiers) + dataBindingModifier.Dispose(); } /// @@ -218,7 +225,7 @@ namespace Artemis.Core /// public Type GetTargetType() { - return TargetProperty.PropertyType; + return Registration.PropertyExpression.ReturnType; } /// @@ -257,7 +264,6 @@ namespace Artemis.Core Converter = dataBindingRegistration?.Converter; Registration = dataBindingRegistration; - TargetProperty = dataBindingRegistration?.Property; if (GetTargetType().IsValueType) { @@ -305,7 +311,7 @@ namespace Artemis.Core if (_disposed) throw new ObjectDisposedException("DataBinding"); // General - var registration = LayerProperty.GetDataBindingRegistration(Entity.TargetProperty); + var registration = LayerProperty.GetDataBindingRegistration(Entity.TargetExpression); ApplyRegistration(registration); Mode = (DataBindingMode) Entity.DataBindingMode; @@ -329,7 +335,7 @@ namespace Artemis.Core LayerProperty.Entity.DataBindingEntities.Add(Entity); // General - Entity.TargetProperty = TargetProperty?.Name; + Entity.TargetExpression = Registration.PropertyExpression.ToString(); Entity.DataBindingMode = (int) Mode; Entity.EasingTime = EasingTime; Entity.EasingFunction = (int) EasingFunction; @@ -340,7 +346,7 @@ namespace Artemis.Core Entity.SourceDataModelGuid = SourceDataModel.PluginInfo.Guid; Entity.SourcePropertyPath = SourcePropertyPath; } - + // Modifiers Entity.Modifiers.Clear(); foreach (var dataBindingModifier in Modifiers) @@ -381,18 +387,6 @@ namespace Artemis.Core } #endregion - - /// - public void Dispose() - { - _disposed = true; - - DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded; - DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved; - - foreach (var dataBindingModifier in Modifiers) - dataBindingModifier.Dispose(); - } } /// diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs index e5d3f3b13..fbe7642fc 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingConverter.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Linq.Expressions; +using System.Reflection; namespace Artemis.Core { @@ -18,7 +19,7 @@ namespace Artemis.Core /// /// A dynamically compiled setter pointing to the data bound property /// - public Action SetExpression { get; private set; } + public Action SetExpression { get; private set; } /// /// Gets the data binding this converter is applied to @@ -81,19 +82,34 @@ namespace Artemis.Core OnInitialized(); } - private Action CreateValueSetter() + private Action CreateValueSetter() { - if (DataBinding.TargetProperty?.DeclaringType == null) - return null; + MethodInfo setterMethod = null; + + if (DataBinding.Registration.Member != null) + { + if (DataBinding.Registration.Member is PropertyInfo propertyInfo) + setterMethod = propertyInfo.GetSetMethod(); + } - var setterMethod = DataBinding.TargetProperty.GetSetMethod(); if (setterMethod == null) return null; + var parameter = Expression.Parameter(typeof(TLayerProperty), "currentValue"); var propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue"); - var body = DataBinding.Registration.PropertyExpression; - var lambda = Expression.Lambda>(body, propertyValue); + + var memberAccess = Expression.MakeMemberAccess(parameter, DataBinding.Registration.Member); + var assignment = Expression.Assign(memberAccess, propertyValue); + var lambda = Expression.Lambda>(assignment, parameter, propertyValue); + + if (typeof(TLayerProperty).IsValueType) + { + // var layerProperty = Expression.Constant(DataBinding.LayerProperty); + // var layerPropertyMemberAccess = Expression.MakeMemberAccess(layerProperty, DataBinding.LayerProperty.GetType().GetMember(nameof(DataBinding.LayerProperty.CurrentValue))[0]); + // var assingment = Expression.Assign() + } + return lambda.Compile(); } } diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs index bd25a62cf..05e126771 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs @@ -175,7 +175,7 @@ namespace Artemis.Core return; } - var targetType = DataBinding.TargetProperty.PropertyType; + var targetType = DataBinding.GetTargetType(); if (!modifierType.SupportsType(targetType)) { throw new ArtemisCoreException($"Cannot apply modifier type {modifierType.GetType().Name} to this modifier because " + @@ -227,7 +227,7 @@ namespace Artemis.Core ParameterDataModel = null; ParameterPropertyPath = null; - var targetType = DataBinding.TargetProperty.PropertyType; + var targetType = DataBinding.GetTargetType(); // If not null ensure the types match and if not, convert it if (staticValue != null && staticValue.GetType() == targetType) @@ -269,7 +269,7 @@ namespace Artemis.Core else if (ParameterType == ProfileRightSideType.Static && Entity.ParameterStaticValue != null && ParameterStaticValue == null) { // Use the target type so JSON.NET has a better idea what to do - var targetType = DataBinding.TargetProperty.PropertyType; + var targetType = DataBinding.GetTargetType(); object staticValue; try diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingRegistration.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingRegistration.cs index dba41727f..d7366ca63 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingRegistration.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingRegistration.cs @@ -8,13 +8,16 @@ namespace Artemis.Core /// public class DataBindingRegistration : IDataBindingRegistration { - internal DataBindingRegistration(LayerProperty layerProperty, - DataBindingConverter converter, + internal DataBindingRegistration(LayerProperty layerProperty, + DataBindingConverter converter, Expression> propertyExpression) { LayerProperty = layerProperty ?? throw new ArgumentNullException(nameof(layerProperty)); Converter = converter ?? throw new ArgumentNullException(nameof(converter)); PropertyExpression = propertyExpression ?? throw new ArgumentNullException(nameof(propertyExpression)); + + if (propertyExpression.Body is MemberExpression memberExpression) + Member = memberExpression.Member; } /// @@ -28,15 +31,16 @@ namespace Artemis.Core public DataBindingConverter Converter { get; } /// - /// Gets the expression that that accesses the property + /// Gets the expression that that accesses the property /// public Expression> PropertyExpression { get; } /// - /// Gets the registered property + /// Gets the member the targets + /// null if the is not a member expression /// - public PropertyInfo Property { get; } - + public MemberInfo Member { get; } + /// /// Gets the data binding created using this registration /// @@ -48,7 +52,7 @@ namespace Artemis.Core if (DataBinding != null) return DataBinding; - var dataBinding = LayerProperty.Entity.DataBindingEntities.FirstOrDefault(e => e.TargetProperty == PropertyExpression.ToString()); + var dataBinding = LayerProperty.Entity.DataBindingEntities.FirstOrDefault(e => e.TargetExpression == PropertyExpression.ToString()); if (dataBinding == null) return null; diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index 4491b8143..cb495ca70 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -193,7 +193,7 @@ namespace Artemis.Core canvas.Restore(); } - + /// public override void AddChild(ProfileElement child, int? order = null) { @@ -242,17 +242,13 @@ namespace Artemis.Core protected override void Dispose(bool disposing) { - if (!disposing) - return; - _disposed = true; - foreach (var baseLayerEffect in LayerEffects) - baseLayerEffect.Dispose(); foreach (var profileElement in Children) profileElement.Dispose(); _folderBitmap?.Dispose(); + base.Dispose(disposing); } internal override void Load() @@ -290,10 +286,6 @@ namespace Artemis.Core FolderEntity.ExpandedPropertyGroups.Clear(); FolderEntity.ExpandedPropertyGroups.AddRange(_expandedPropertyGroups); - // Conditions - RenderElementEntity.RootDisplayCondition = DisplayConditionGroup?.Entity; - DisplayConditionGroup?.Save(); - SaveRenderElement(); } diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index ac2c141fc..7fdad81f5 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -124,20 +124,16 @@ namespace Artemis.Core /// protected override void Dispose(bool disposing) { - if (!disposing) - return; - _disposed = true; // Brush first in case it depends on any of the other disposables during it's own disposal _layerBrush?.Dispose(); - foreach (var baseLayerEffect in LayerEffects) - baseLayerEffect.Dispose(); - _general?.Dispose(); _layerBitmap?.Dispose(); _transform?.Dispose(); + + base.Dispose(disposing); } #endregion @@ -210,10 +206,6 @@ namespace Artemis.Core LayerEntity.Leds.Add(ledEntity); } - // Conditions - RenderElementEntity.RootDisplayCondition = DisplayConditionGroup?.Entity; - DisplayConditionGroup?.Save(); - SaveRenderElement(); } @@ -691,14 +683,8 @@ namespace Artemis.Core // Ensure the brush reference matches the brush var current = General.BrushReference.CurrentValue; - if (current.BrushPluginGuid != descriptor.LayerBrushProvider.PluginInfo.Guid || current.BrushType != descriptor.LayerBrushType.Name) - { - General.BrushReference.CurrentValue = new LayerBrushReference - { - BrushPluginGuid = descriptor.LayerBrushProvider.PluginInfo.Guid, - BrushType = descriptor.LayerBrushType.Name - }; - } + if (!descriptor.MatchesLayerBrushReference(current)) + General.BrushReference.CurrentValue = new LayerBrushReference(descriptor); ActivateLayerBrush(); } @@ -746,7 +732,7 @@ namespace Artemis.Core private void LayerBrushStoreOnLayerBrushRemoved(object sender, LayerBrushStoreEvent e) { - if (LayerBrush.Descriptor == e.Registration.LayerBrushDescriptor) + if (LayerBrush?.Descriptor == e.Registration.LayerBrushDescriptor) DeactivateLayerBrush(); } diff --git a/src/Artemis.Core/Models/Profile/LayerBrushReference.cs b/src/Artemis.Core/Models/Profile/LayerBrushReference.cs index 588fac723..bcad54663 100644 --- a/src/Artemis.Core/Models/Profile/LayerBrushReference.cs +++ b/src/Artemis.Core/Models/Profile/LayerBrushReference.cs @@ -17,5 +17,15 @@ namespace Artemis.Core /// The full type name of the brush descriptor /// public string BrushType { get; set; } + + public LayerBrushReference() + { + } + + public LayerBrushReference(LayerBrushDescriptor descriptor) + { + BrushPluginGuid = descriptor.LayerBrushProvider.PluginInfo.Guid; + BrushType = descriptor.LayerBrushType.Name; + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs index 9624bd576..909255cb5 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs @@ -26,10 +26,5 @@ namespace Artemis.Core /// Returns a list off all data binding registrations /// List GetAllDataBindingRegistrations(); - - /// - /// Gets or sets whether the property is hidden in the UI - /// - bool IsHidden { get; set; } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index 2737daf91..01ccfc4c7 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -61,7 +61,9 @@ namespace Artemis.Core private bool _isHidden; - /// + /// + /// Gets or sets whether the property is hidden in the UI + /// public bool IsHidden { get => _isHidden; @@ -318,13 +320,13 @@ namespace Artemis.Core /// public bool DataBindingsSupported { get; protected internal set; } = true; - public DataBindingRegistration GetDataBindingRegistration(string propertyName) + public DataBindingRegistration GetDataBindingRegistration(string expression) { if (_disposed) throw new ObjectDisposedException("LayerProperty"); var match = _dataBindingRegistrations.FirstOrDefault(r => r is DataBindingRegistration registration && - registration.Property.Name == propertyName); + registration.PropertyExpression.ToString() == expression); return (DataBindingRegistration) match; } diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs index 1b4951458..a355747ce 100644 --- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs +++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs @@ -237,6 +237,10 @@ namespace Artemis.Core if (instance == null) 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 + if (string.IsNullOrWhiteSpace(propertyGroupDescription.Name)) + propertyGroupDescription.Name = propertyInfo.Name.Humanize(); + instance.Parent = this; instance.GroupDescription = propertyGroupDescription; instance.LayerBrush = LayerBrush; diff --git a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs index 4c735e94d..e225f6b57 100644 --- a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs @@ -32,6 +32,10 @@ namespace Artemis.Core DisplayContinuously = RenderElementEntity.DisplayContinuously; AlwaysFinishTimeline = RenderElementEntity.AlwaysFinishTimeline; + DisplayConditionGroup = RenderElementEntity.RootDisplayCondition != null + ? new DisplayConditionGroup(null, RenderElementEntity.RootDisplayCondition) + : new DisplayConditionGroup(null); + ActivateEffects(); } @@ -49,7 +53,7 @@ namespace Artemis.Core var layerEffectEntity = new LayerEffectEntity { Id = layerEffect.EntityId, - PluginGuid = layerEffect.PluginInfo.Guid, + PluginGuid = layerEffect.Descriptor.PlaceholderFor ?? layerEffect.PluginInfo.Guid, EffectType = layerEffect.GetEffectTypeName(), Name = layerEffect.Name, Enabled = layerEffect.Enabled, @@ -59,6 +63,10 @@ namespace Artemis.Core RenderElementEntity.LayerEffects.Add(layerEffectEntity); layerEffect.BaseProperties.ApplyToEntity(); } + + // Conditions + RenderElementEntity.RootDisplayCondition = DisplayConditionGroup?.Entity; + DisplayConditionGroup?.Save(); } #region Properties @@ -204,7 +212,7 @@ namespace Artemis.Core return (TimelinePosition - oldPosition).TotalSeconds; } - + /// /// Overrides the progress of the element /// @@ -238,6 +246,8 @@ namespace Artemis.Core Order = LayerEffects.Count + 1 }; descriptor.CreateInstance(this, entity); + + OrderEffects(); OnLayerEffectsUpdated(); } @@ -254,6 +264,12 @@ namespace Artemis.Core effect.Dispose(); // Update the order on the remaining effects + OrderEffects(); + OnLayerEffectsUpdated(); + } + + private void OrderEffects() + { var index = 0; foreach (var baseLayerEffect in LayerEffects.OrderBy(e => e.Order)) { @@ -261,7 +277,7 @@ namespace Artemis.Core index++; } - OnLayerEffectsUpdated(); + _layerEffects.Sort((a, b) => a.Order.CompareTo(b.Order)); } internal void ActivateEffects() @@ -270,7 +286,7 @@ namespace Artemis.Core { // If there is a non-placeholder existing effect, skip this entity var existing = _layerEffects.FirstOrDefault(e => e.EntityId == layerEffectEntity.Id); - if (existing != null && !existing.Descriptor.IsPlaceHolder) + if (existing != null && existing.Descriptor.PlaceholderFor == null) continue; var descriptor = LayerEffectStore.Get(layerEffectEntity.PluginGuid, layerEffectEntity.EffectType)?.LayerEffectDescriptor; @@ -282,37 +298,42 @@ namespace Artemis.Core _layerEffects.Remove(existing); existing.Dispose(); } + // Create an instance with the descriptor descriptor.CreateInstance(this, layerEffectEntity); } else if (existing == null) { // If no descriptor was found and there was no existing placeholder, create a placeholder - descriptor = PlaceholderLayerEffectDescriptor.Create(); + descriptor = PlaceholderLayerEffectDescriptor.Create(layerEffectEntity.PluginGuid); descriptor.CreateInstance(this, layerEffectEntity); } } + + OrderEffects(); } internal void ActivateLayerEffect(BaseLayerEffect layerEffect) { _layerEffects.Add(layerEffect); - - // Update the order on the effects - var index = 0; - foreach (var baseLayerEffect in LayerEffects.OrderBy(e => e.Order)) - { - baseLayerEffect.Order = Order = index + 1; - index++; - } - OnLayerEffectsUpdated(); } - private void LayerEffectStoreOnLayerEffectRemoved(object? sender, LayerEffectStoreEvent e) + private void LayerEffectStoreOnLayerEffectRemoved(object sender, LayerEffectStoreEvent e) { - throw new NotImplementedException(); + // If effects provided by the plugin are on the element, replace them with placeholders + var pluginEffects = _layerEffects.Where(ef => ef.Descriptor.LayerEffectProvider != null && + ef.PluginInfo.Guid == e.Registration.Plugin.PluginInfo.Guid).ToList(); + foreach (var pluginEffect in pluginEffects) + { + var entity = RenderElementEntity.LayerEffects.First(en => en.Id == pluginEffect.EntityId); + _layerEffects.Remove(pluginEffect); + pluginEffect.Dispose(); + + var descriptor = PlaceholderLayerEffectDescriptor.Create(pluginEffect.PluginInfo.Guid); + descriptor.CreateInstance(this, entity); + } } private void LayerEffectStoreOnLayerEffectAdded(object sender, LayerEffectStoreEvent e) @@ -359,6 +380,21 @@ namespace Artemis.Core #endregion + #region IDisposable + + protected override void Dispose(bool disposing) + { + LayerEffectStore.LayerEffectAdded -= LayerEffectStoreOnLayerEffectAdded; + LayerEffectStore.LayerEffectRemoved -= LayerEffectStoreOnLayerEffectRemoved; + + foreach (var baseLayerEffect in LayerEffects) + baseLayerEffect.Dispose(); + + base.Dispose(disposing); + } + + #endregion + #region Events public event EventHandler LayerEffectsUpdated; diff --git a/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushDescriptor.cs b/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushDescriptor.cs index f0fd29539..c03948109 100644 --- a/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushDescriptor.cs +++ b/src/Artemis.Core/Plugins/LayerBrushes/LayerBrushDescriptor.cs @@ -61,5 +61,12 @@ namespace Artemis.Core.LayerBrushes layer.LayerBrush = brush; layer.OnLayerBrushUpdated(); } + + public bool MatchesLayerBrushReference(LayerBrushReference reference) + { + if (reference == null) + return false; + return LayerBrushProvider.PluginInfo.Guid == reference.BrushPluginGuid && LayerBrushType.Name == reference.BrushType; + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs b/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs index 0607a7f24..e4ec96c9e 100644 --- a/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs +++ b/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs @@ -95,7 +95,7 @@ namespace Artemis.Core.LayerEffects /// /// Gets the plugin info that defined this effect /// - public PluginInfo PluginInfo => Descriptor.LayerEffectProvider.PluginInfo; + public PluginInfo PluginInfo => Descriptor.LayerEffectProvider?.PluginInfo; /// /// Gets a reference to the layer property group without knowing it's type @@ -108,7 +108,7 @@ namespace Artemis.Core.LayerEffects public void Dispose() { DisableLayerEffect(); - BaseProperties.Dispose(); + BaseProperties?.Dispose(); } /// diff --git a/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs b/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs index 21cb29d7d..50ffaa310 100644 --- a/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs +++ b/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Artemis.Core.LayerEffects.Placeholder; using Artemis.Core.Services; using Artemis.Storage.Entities.Profile; using Ninject; @@ -47,9 +48,9 @@ namespace Artemis.Core.LayerEffects public LayerEffectProvider LayerEffectProvider { get; } /// - /// Gets a boolean indicating if this descriptor is a placeholder for a missing plugin + /// Gets the GUID this descriptor is acting as a placeholder for. If null, this descriptor is not a placeholder /// - public bool IsPlaceHolder { get; internal set; } + public Guid? PlaceholderFor { get; internal set; } /// /// Creates an instance of the described effect and applies it to the render element @@ -60,7 +61,7 @@ namespace Artemis.Core.LayerEffects if (renderElement.LayerEffects.Any(e => e.EntityId == entity.Id)) return; - if (IsPlaceHolder) + if (PlaceholderFor != null) { CreatePlaceHolderInstance(renderElement, entity); return; @@ -82,7 +83,8 @@ namespace Artemis.Core.LayerEffects private void CreatePlaceHolderInstance(RenderProfileElement renderElement, LayerEffectEntity entity) { - var effect = new PlaceholderLayerEffect(entity) {ProfileElement = renderElement, Descriptor = this}; + var effect = new PlaceholderLayerEffect(entity, PlaceholderFor.Value) {ProfileElement = renderElement, Descriptor = this}; + effect.Initialize(); renderElement.ActivateLayerEffect(effect); } } diff --git a/src/Artemis.Core/Plugins/LayerEffects/Placeholder/PlaceholderLayerEffect.cs b/src/Artemis.Core/Plugins/LayerEffects/Placeholder/PlaceholderLayerEffect.cs index 067417d0d..995b244e9 100644 --- a/src/Artemis.Core/Plugins/LayerEffects/Placeholder/PlaceholderLayerEffect.cs +++ b/src/Artemis.Core/Plugins/LayerEffects/Placeholder/PlaceholderLayerEffect.cs @@ -1,17 +1,19 @@ -using Artemis.Storage.Entities.Profile; +using System; +using Artemis.Storage.Entities.Profile; using SkiaSharp; -namespace Artemis.Core.LayerEffects +namespace Artemis.Core.LayerEffects.Placeholder { /// /// Represents a layer effect that could not be loaded due to a missing plugin /// - public class PlaceholderLayerEffect : BaseLayerEffect + internal class PlaceholderLayerEffect : LayerEffect { - internal PlaceholderLayerEffect(LayerEffectEntity originalEntity) + internal PlaceholderLayerEffect(LayerEffectEntity originalEntity, Guid placeholderFor) { OriginalEntity = originalEntity; - + PlaceholderFor = placeholderFor; + EntityId = OriginalEntity.Id; Order = OriginalEntity.Order; Name = OriginalEntity.Name; @@ -20,6 +22,7 @@ namespace Artemis.Core.LayerEffects } internal LayerEffectEntity OriginalEntity { get; } + public Guid PlaceholderFor { get; } /// public override void EnableLayerEffect() @@ -50,8 +53,22 @@ namespace Artemis.Core.LayerEffects { return OriginalEntity.EffectType; } + } - internal override void Initialize() + /// + /// This is in place so that the UI has something to show + /// + internal class PlaceholderProperties : LayerPropertyGroup + { + protected override void PopulateDefaults() + { + } + + protected override void EnableProperties() + { + } + + protected override void DisableProperties() { } } diff --git a/src/Artemis.Core/Plugins/LayerEffects/Placeholder/PlaceholderLayerEffectDescriptor.cs b/src/Artemis.Core/Plugins/LayerEffects/Placeholder/PlaceholderLayerEffectDescriptor.cs index b34583a0f..63e738c37 100644 --- a/src/Artemis.Core/Plugins/LayerEffects/Placeholder/PlaceholderLayerEffectDescriptor.cs +++ b/src/Artemis.Core/Plugins/LayerEffects/Placeholder/PlaceholderLayerEffectDescriptor.cs @@ -1,10 +1,16 @@ -namespace Artemis.Core.LayerEffects.Placeholder +using System; + +namespace Artemis.Core.LayerEffects.Placeholder { internal static class PlaceholderLayerEffectDescriptor { - public static LayerEffectDescriptor Create() + public static LayerEffectDescriptor Create(Guid missingPluginGuid) { - var descriptor = new LayerEffectDescriptor("Missing effect", "This effect could not be loaded", "FileQuestion", null, null) {IsPlaceHolder = true}; + var descriptor = new LayerEffectDescriptor("Missing effect", "This effect could not be loaded", "FileQuestion", null, Constants.EffectPlaceholderPlugin) + { + PlaceholderFor = missingPluginGuid + }; + return descriptor; } } diff --git a/src/Artemis.Core/Plugins/Plugin.cs b/src/Artemis.Core/Plugins/Plugin.cs index d8f260b1b..dd6c0542f 100644 --- a/src/Artemis.Core/Plugins/Plugin.cs +++ b/src/Artemis.Core/Plugins/Plugin.cs @@ -16,7 +16,7 @@ namespace Artemis.Core /// /// Gets whether the plugin is enabled /// - public bool Enabled { get; private set; } + public bool Enabled { get; internal set; } /// /// Gets or sets a configuration dialog for this plugin that is accessible in the UI under Settings > Plugins diff --git a/src/Artemis.Core/Services/Registration/Interfaces/ILayerBrushService.cs b/src/Artemis.Core/Services/Registration/Interfaces/ILayerBrushService.cs index 8bc6a62e0..a8e576312 100644 --- a/src/Artemis.Core/Services/Registration/Interfaces/ILayerBrushService.cs +++ b/src/Artemis.Core/Services/Registration/Interfaces/ILayerBrushService.cs @@ -22,5 +22,10 @@ namespace Artemis.Core.Services /// Returns a list of all registered layer brush descriptors /// List GetLayerBrushes(); + + /// + /// Returns the descriptor of the default layer brush + /// + LayerBrushDescriptor GetDefaultLayerBrush(); } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/Registration/LayerBrushService.cs b/src/Artemis.Core/Services/Registration/LayerBrushService.cs index b46d24143..8a3a69e55 100644 --- a/src/Artemis.Core/Services/Registration/LayerBrushService.cs +++ b/src/Artemis.Core/Services/Registration/LayerBrushService.cs @@ -7,6 +7,13 @@ namespace Artemis.Core.Services { internal class LayerBrushService : ILayerBrushService { + private readonly ISettingsService _settingsService; + + public LayerBrushService(ISettingsService settingsService) + { + _settingsService = settingsService; + } + public LayerBrushRegistration RegisterLayerBrush(LayerBrushDescriptor descriptor) { if (descriptor == null) @@ -26,5 +33,16 @@ namespace Artemis.Core.Services { return LayerBrushStore.GetAll().Select(r => r.LayerBrushDescriptor).ToList(); } + + public LayerBrushDescriptor GetDefaultLayerBrush() + { + var defaultReference = _settingsService.GetSetting("ProfileEditor.DefaultLayerBrushDescriptor", new LayerBrushReference + { + BrushPluginGuid = Guid.Parse("92a9d6ba-6f7a-4937-94d5-c1d715b4141a"), + BrushType = "ColorBrush" + }); + + return LayerBrushStore.Get(defaultReference.Value.BrushPluginGuid, defaultReference.Value.BrushType)?.LayerBrushDescriptor; + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index f51c51a69..f31724d93 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Artemis.Core.LayerBrushes; -using Artemis.Core.LayerEffects; using Artemis.Core.Modules; using Artemis.Storage.Entities.Profile; using Artemis.Storage.Repositories.Interfaces; @@ -19,7 +17,12 @@ namespace Artemis.Core.Services private readonly IProfileRepository _profileRepository; private readonly ISurfaceService _surfaceService; - internal ProfileService(ILogger logger, IPluginService pluginService, ISurfaceService surfaceService, IProfileRepository profileRepository) + internal ProfileService(ILogger logger, + IPluginService pluginService, + ISurfaceService surfaceService, + IConditionOperatorService conditionOperatorService, + IDataBindingService dataBindingService, + IProfileRepository profileRepository) { _logger = logger; _pluginService = pluginService; @@ -261,7 +264,7 @@ namespace Artemis.Core.Services _profileRepository.Save(profileEntity); } } - + /// /// Populates all missing LEDs on all currently active profiles /// @@ -272,7 +275,7 @@ namespace Artemis.Core.Services foreach (var profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList()) profileModule.ActiveProfile.PopulateLeds(surface); } - + #region Event handlers private void OnActiveSurfaceConfigurationSelected(object sender, SurfaceConfigurationEventArgs e) @@ -285,7 +288,7 @@ namespace Artemis.Core.Services if (e.Surface.IsActive) ActiveProfilesPopulateLeds(e.Surface); } - + #endregion } } \ No newline at end of file diff --git a/src/Artemis.Core/Utilities/CorePlugin.cs b/src/Artemis.Core/Utilities/CorePlugin.cs new file mode 100644 index 000000000..8a87a9028 --- /dev/null +++ b/src/Artemis.Core/Utilities/CorePlugin.cs @@ -0,0 +1,40 @@ +using Artemis.Core.LayerEffects; + +namespace Artemis.Core +{ + /// + /// An empty plugin used by + /// + internal class CorePlugin : Plugin + { + public CorePlugin() + { + Constants.CorePluginInfo.Instance = this; + Enabled = true; + } + + public override void EnablePlugin() + { + } + + public override void DisablePlugin() + { + } + } + + internal class EffectPlaceholderPlugin : LayerEffectProvider + { + public EffectPlaceholderPlugin() + { + Enabled = true; + } + + public override void EnablePlugin() + { + } + + public override void DisablePlugin() + { + } + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingEntity.cs b/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingEntity.cs index 761acbeee..14011e683 100644 --- a/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingEntity.cs @@ -10,7 +10,7 @@ namespace Artemis.Storage.Entities.Profile.DataBindings Modifiers = new List(); } - public string TargetProperty { get; set; } + public string TargetExpression { get; set; } public Guid? SourceDataModelGuid { get; set; } public string SourcePropertyPath { get; set; } public int DataBindingMode { get; set; } diff --git a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs index 7fbb05c43..cd50678b0 100644 --- a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs +++ b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs @@ -69,12 +69,6 @@ namespace Artemis.UI.Ninject.Factories DisplayConditionListPredicateViewModel DisplayConditionListPredicateViewModel(DisplayConditionListPredicate displayConditionListPredicate); } - public interface IDataBindingsVmFactory : IVmFactory - { - IDataBindingViewModel DataBindingViewModel(IDataBindingRegistration registration); - DataBindingModifierViewModel DataBindingModifierViewModel(DataBindingModifier modifier); - } - public interface ILayerPropertyVmFactory : IVmFactory { LayerPropertyViewModel LayerPropertyViewModel(ILayerProperty layerProperty); @@ -89,6 +83,12 @@ namespace Artemis.UI.Ninject.Factories TimelineSegmentViewModel TimelineSegmentViewModel(SegmentViewModelType segment, BindableCollection layerPropertyGroups); } + public interface IDataBindingsVmFactory + { + IDataBindingViewModel DataBindingViewModel(IDataBindingRegistration registration); + DataBindingModifierViewModel DataBindingModifierViewModel(DataBindingModifier modifier); + } + public interface IPropertyVmFactory { ITreePropertyViewModel TreePropertyViewModel(ILayerProperty layerProperty, LayerPropertyViewModel layerPropertyViewModel); diff --git a/src/Artemis.UI/Ninject/InstanceProviders/DataBindingsViewModelInstanceProvider.cs b/src/Artemis.UI/Ninject/InstanceProviders/DataBindingsViewModelInstanceProvider.cs index 5df778f89..8a8e829fe 100644 --- a/src/Artemis.UI/Ninject/InstanceProviders/DataBindingsViewModelInstanceProvider.cs +++ b/src/Artemis.UI/Ninject/InstanceProviders/DataBindingsViewModelInstanceProvider.cs @@ -1,5 +1,7 @@ using System; using System.Reflection; +using Artemis.Core; +using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings; using Ninject.Extensions.Factory; namespace Artemis.UI.Ninject.InstanceProviders @@ -8,7 +10,17 @@ namespace Artemis.UI.Ninject.InstanceProviders { protected override Type GetType(MethodInfo methodInfo, object[] arguments) { - return base.GetType(methodInfo, arguments); + if (methodInfo.ReturnType != typeof(IDataBindingViewModel)) + return base.GetType(methodInfo, arguments); + + // Find LayerProperty type + var descriptionPropertyType = arguments[0].GetType(); + while (descriptionPropertyType != null && (!descriptionPropertyType.IsGenericType || descriptionPropertyType.GetGenericTypeDefinition() != typeof(DataBindingRegistration<,>))) + descriptionPropertyType = descriptionPropertyType.BaseType; + if (descriptionPropertyType == null) + return base.GetType(methodInfo, arguments); + + return typeof(DataBindingViewModel<,>).MakeGenericType(descriptionPropertyType.GetGenericArguments()); } } } \ No newline at end of file diff --git a/src/Artemis.UI/Ninject/UiModule.cs b/src/Artemis.UI/Ninject/UiModule.cs index 1da66b61c..3d807d1d9 100644 --- a/src/Artemis.UI/Ninject/UiModule.cs +++ b/src/Artemis.UI/Ninject/UiModule.cs @@ -50,6 +50,7 @@ namespace Artemis.UI.Ninject .BindToFactory(); }); + Kernel.Bind().ToFactory(() => new DataBindingsViewModelInstanceProvider()); Kernel.Bind().ToFactory(() => new LayerPropertyViewModelInstanceProvider()); // Bind profile editor VMs diff --git a/src/Artemis.UI/PropertyInput/BrushPropertyInputView.xaml b/src/Artemis.UI/PropertyInput/BrushPropertyInputView.xaml index c698304b8..820bbbdc4 100644 --- a/src/Artemis.UI/PropertyInput/BrushPropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/BrushPropertyInputView.xaml @@ -11,28 +11,11 @@ d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance {x:Type propertyInput:BrushPropertyInputViewModel}}"> - - - - - - - - - - - - - - - - - - - - - - + + + + + @@ -46,8 +29,8 @@ ItemsSource="{Binding Path=Descriptors}" SelectedValue="{Binding Path=SelectedDescriptor}" ItemTemplateSelector="{dataTemplateSelectors:ComboBoxTemplateSelector - SelectedItemTemplate={StaticResource SimpleTemplate}, - DropdownItemsTemplate={StaticResource ExtendedTemplate}}" /> + SelectedItemTemplate={StaticResource SimpleLayerBrushDescriptorTemplate}, + DropdownItemsTemplate={StaticResource ExtendedLayerBrushDescriptorTemplate}}" /> \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/BrushPropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/BrushPropertyInputViewModel.cs index 2222ecf81..61c512175 100644 --- a/src/Artemis.UI/PropertyInput/BrushPropertyInputViewModel.cs +++ b/src/Artemis.UI/PropertyInput/BrushPropertyInputViewModel.cs @@ -5,16 +5,17 @@ using Artemis.Core.LayerBrushes; using Artemis.Core.Services; using Artemis.UI.Shared; using Artemis.UI.Shared.Services; +using Stylet; namespace Artemis.UI.PropertyInput { public class BrushPropertyInputViewModel : PropertyInputViewModel { private readonly IPluginService _pluginService; - private List _descriptors; + private BindableCollection _descriptors; public BrushPropertyInputViewModel(LayerProperty layerProperty, - IProfileEditorService profileEditorService, + IProfileEditorService profileEditorService, IPluginService pluginService) : base(layerProperty, profileEditorService) { _pluginService = pluginService; @@ -24,7 +25,7 @@ namespace Artemis.UI.PropertyInput UpdateEnumValues(); } - public List Descriptors + public BindableCollection Descriptors { get => _descriptors; set => SetAndNotify(ref _descriptors, value); @@ -32,14 +33,14 @@ namespace Artemis.UI.PropertyInput public LayerBrushDescriptor SelectedDescriptor { - get => Descriptors.FirstOrDefault(d => d.LayerBrushProvider.PluginInfo.Guid == InputValue?.BrushPluginGuid && d.LayerBrushType.Name == InputValue?.BrushType); + get => Descriptors.FirstOrDefault(d => d.MatchesLayerBrushReference(InputValue)); set => SetBrushByDescriptor(value); } public void UpdateEnumValues() { var layerBrushProviders = _pluginService.GetPluginsOfType(); - Descriptors = layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors).ToList(); + Descriptors = new BindableCollection(layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors)); NotifyOfPropertyChange(nameof(SelectedDescriptor)); } @@ -53,13 +54,13 @@ namespace Artemis.UI.PropertyInput protected override void OnInputValueApplied() { - if (LayerProperty.ProfileElement is Layer layer) + if (LayerProperty.ProfileElement is Layer layer) layer.ChangeLayerBrush(SelectedDescriptor); } private void SetBrushByDescriptor(LayerBrushDescriptor value) { - InputValue = new LayerBrushReference {BrushPluginGuid = value.LayerBrushProvider.PluginInfo.Guid, BrushType = value.LayerBrushType.Name}; + InputValue = new LayerBrushReference(value); } private void PluginServiceOnPluginLoaded(object sender, PluginEventArgs e) diff --git a/src/Artemis.UI/ResourceDictionaries/LayerBrushDescriptors.xaml b/src/Artemis.UI/ResourceDictionaries/LayerBrushDescriptors.xaml new file mode 100644 index 000000000..059b43857 --- /dev/null +++ b/src/Artemis.UI/ResourceDictionaries/LayerBrushDescriptors.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs index e2d3a7a04..5392d0f52 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs @@ -11,8 +11,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions { private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory; private readonly IProfileEditorService _profileEditorService; - private bool _alwaysFinishTimeline; - private bool _displayContinuously; private RenderProfileElement _renderProfileElement; private int _transitionerIndex; @@ -37,20 +35,22 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions public bool DisplayContinuously { - get => _displayContinuously; + get => RenderProfileElement?.DisplayContinuously ?? false; set { - if (!SetAndNotify(ref _displayContinuously, value)) return; + if (RenderProfileElement == null || RenderProfileElement.DisplayContinuously == value) return; + RenderProfileElement.DisplayContinuously = value; _profileEditorService.UpdateSelectedProfileElement(); } } public bool AlwaysFinishTimeline { - get => _alwaysFinishTimeline; + get => RenderProfileElement?.AlwaysFinishTimeline ?? false; set { - if (!SetAndNotify(ref _alwaysFinishTimeline, value)) return; + if (RenderProfileElement == null || RenderProfileElement.AlwaysFinishTimeline == value) return; + RenderProfileElement.AlwaysFinishTimeline = value; _profileEditorService.UpdateSelectedProfileElement(); } } @@ -70,12 +70,9 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e) { RenderProfileElement = e.RenderProfileElement; - NotifyOfPropertyChange(nameof(ConditionBehaviourEnabled)); - - _displayContinuously = RenderProfileElement?.DisplayContinuously ?? false; NotifyOfPropertyChange(nameof(DisplayContinuously)); - _alwaysFinishTimeline = RenderProfileElement?.AlwaysFinishTimeline ?? false; NotifyOfPropertyChange(nameof(AlwaysFinishTimeline)); + NotifyOfPropertyChange(nameof(ConditionBehaviourEnabled)); if (e.RenderProfileElement == null) { diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml index 0afdbd491..779744f82 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml @@ -4,14 +4,10 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" - xmlns:converters="clr-namespace:Artemis.UI.Converters" - xmlns:utilities="clr-namespace:Artemis.UI.Utilities" xmlns:dd="urn:gong-wpf-dragdrop" xmlns:s="https://github.com/canton7/Stylet" - xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings" mc:Ignorable="d" - d:DesignHeight="450" d:DesignWidth="800" - d:DataContext="{d:DesignInstance local:DataBindingViewModel}"> + d:DesignHeight="450" d:DesignWidth="800"> diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs index dc89d11a1..0cee22ffa 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs @@ -36,7 +36,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings _dataModelUIService = dataModelUIService; _dataBindingsVmFactory = dataBindingsVmFactory; - DisplayName = Registration.Property.Name.ToUpper(); + if (Registration.Member != null) + DisplayName = Registration.Member.Name.ToUpper(); + else + DisplayName = Registration.LayerProperty.PropertyDescription.Name.ToUpper(); DataBindingModes = new BindableCollection(EnumUtilities.GetAllValuesAndDescriptions(typeof(DataBindingMode))); EasingViewModels = new BindableCollection(); @@ -203,7 +206,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings TargetSelectionViewModel.IsEnabled = true; TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataBinding.SourceDataModel, DataBinding.SourcePropertyPath); - TargetSelectionViewModel.FilterTypes = new[] {DataBinding.TargetProperty.PropertyType}; + TargetSelectionViewModel.FilterTypes = new[] {DataBinding.GetTargetType()}; UpdateModifierViewModels(); @@ -225,11 +228,18 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings private void UpdateTestResult() { + if (DataBinding == null) + { + TestInputValue = default; + TestResultValue = default; + return; + } + var currentValue = TargetSelectionViewModel.SelectedPropertyViewModel?.GetCurrentValue(); - if (currentValue == null && Registration.Property.PropertyType.IsValueType) - currentValue = Activator.CreateInstance(Registration.Property.PropertyType); - - TestInputValue = currentValue is TProperty testInputValue ? testInputValue : default; + if (currentValue == null) + currentValue = default(TProperty); + + TestInputValue = (TProperty) Convert.ChangeType(currentValue, typeof(TProperty)); if (DataBinding != null) TestResultValue = DataBinding.GetValue(TestInputValue); else diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsView.xaml index 85def1ef5..35e1c740c 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsView.xaml @@ -6,7 +6,7 @@ xmlns:s="https://github.com/canton7/Stylet" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> - + diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs index badbda92c..b9b454236 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs @@ -9,6 +9,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings { private readonly IDataBindingsVmFactory _dataBindingsVmFactory; private readonly IProfileEditorService _profileEditorService; + private int _selectedItemIndex; public DataBindingsViewModel(IProfileEditorService profileEditorService, IDataBindingsVmFactory dataBindingsVmFactory) { @@ -19,6 +20,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings CreateDataBindingViewModels(); } + public int SelectedItemIndex + { + get => _selectedItemIndex; + set => SetAndNotify(ref _selectedItemIndex, value); + } + private void CreateDataBindingViewModels() { Items.Clear(); @@ -33,6 +40,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings // and creating the actual data bindings foreach (var registration in registrations) ActivateItem(_dataBindingsVmFactory.DataBindingViewModel(registration)); + + SelectedItemIndex = 0; } protected override void OnClose() diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml index 792b2a58a..2e8460ced 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerEffects/EffectsView.xaml @@ -23,7 +23,7 @@ Think of things like blur, black & white but also audio visualization etc. -