From 54081b591bafe5688a9b6fb4732883e4af1ea9d6 Mon Sep 17 00:00:00 2001 From: Robert Date: Fri, 1 May 2020 23:07:21 +0200 Subject: [PATCH] UI - Restructured layer property VMs --- src/Artemis.Core/Models/Profile/Layer.cs | 10 +- .../LayerProperties/BaseLayerProperty.cs | 10 +- .../Profile/LayerProperties/LayerProperty.cs | 2 +- .../Models/Profile/LayerPropertyGroup.cs | 21 +-- .../Plugins/LayerBrush/BaseLayerBrush.cs | 21 +-- .../Plugins/LayerBrush/LayerBrush.cs | 13 +- src/Artemis.Core/Services/LayerService.cs | 5 - .../Abstract/LayerPropertyBaseViewModel.cs | 11 ++ .../LayerPropertiesViewModel.cs | 136 ++++++------------ .../LayerPropertyGroupViewModel.cs | 67 +++++++++ .../LayerProperties/LayerPropertyViewModel.cs | 101 ++----------- 11 files changed, 163 insertions(+), 234 deletions(-) create mode 100644 src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs create mode 100644 src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 45b6bc8b3..3f9dd807a 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -125,7 +125,7 @@ namespace Artemis.Core.Models.Profile General.ApplyToEntity(); Transform.ApplyToEntity(); - LayerBrush.ApplyToEntity(); + LayerBrush.BaseProperties.ApplyToEntity(); // LEDs LayerEntity.Leds.Clear(); @@ -187,7 +187,7 @@ namespace Artemis.Core.Models.Profile var properties = new List(General.GetAllLayerProperties()); properties.AddRange(Transform.GetAllLayerProperties()); - properties.AddRange(LayerBrush.GetAllLayerProperties()); + properties.AddRange(LayerBrush.BaseProperties.GetAllLayerProperties()); // For now, reset all keyframe engines after the last keyframe was hit // This is a placeholder method of repeating the animation until repeat modes are implemented @@ -196,13 +196,13 @@ namespace Artemis.Core.Models.Profile { General.Override(TimeSpan.Zero); Transform.Override(TimeSpan.Zero); - LayerBrush.OverrideProperties(TimeSpan.Zero); + LayerBrush.BaseProperties.Override(TimeSpan.Zero); } else { General.Update(deltaTime); Transform.Update(deltaTime); - LayerBrush.UpdateProperties(deltaTime); + LayerBrush.BaseProperties.Update(deltaTime); } LayerBrush.Update(deltaTime); @@ -212,7 +212,7 @@ namespace Artemis.Core.Models.Profile { General.Override(timeOverride); Transform.Override(timeOverride); - LayerBrush.OverrideProperties(timeOverride); + LayerBrush.BaseProperties.Override(timeOverride); } /// diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs index 9863661da..af9a7d590 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs @@ -5,7 +5,7 @@ using Artemis.Storage.Entities.Profile; namespace Artemis.Core.Models.Profile.LayerProperties { /// - /// For internal use only, to implement your own layer property type, extend instead. + /// For internal use only, to implement your own layer property type, extend instead. /// public abstract class BaseLayerProperty { @@ -42,11 +42,15 @@ namespace Artemis.Core.Models.Profile.LayerProperties /// /// Used to declare that this property doesn't belong to a plugin and should use the core plugin GUID /// - internal bool IsCoreProperty { get; set; } + public bool IsCoreProperty { get; internal set; } + + /// + /// Gets a list of all the keyframes in their non-generic base form, without their values being available + /// + public abstract IReadOnlyList BaseKeyframes { get; } internal PropertyEntity PropertyEntity { get; set; } internal LayerPropertyGroup LayerPropertyGroup { get; set; } - internal abstract IReadOnlyList BaseKeyframes { get; } /// /// Applies the provided property entity to the layer property by deserializing the JSON base value and keyframe values diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index a9b0a397a..66d55132d 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -70,7 +70,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties /// public LayerPropertyKeyframe NextKeyframe { get; protected set; } - internal override IReadOnlyList BaseKeyframes => _keyframes.Cast().ToList().AsReadOnly(); + public override IReadOnlyList BaseKeyframes => _keyframes.Cast().ToList().AsReadOnly(); /// /// Adds a keyframe to the layer property diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs index 486b36aa2..f9057d67d 100644 --- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs +++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs @@ -14,29 +14,34 @@ namespace Artemis.Core.Models.Profile public class LayerPropertyGroup { private ReadOnlyCollection _allLayerProperties; + private readonly List _layerProperties; + private readonly List _layerPropertyGroups; protected LayerPropertyGroup() { - LayerProperties = new List(); - LayerPropertyGroups = new List(); + _layerProperties = new List(); + _layerPropertyGroups = new List(); } + /// + /// Gets whether this property group's properties are all initialized + /// public bool PropertiesInitialized { get; private set; } /// /// Used to declare that this property group doesn't belong to a plugin and should use the core plugin GUID /// - internal bool IsCorePropertyGroup { get; set; } + public bool IsCorePropertyGroup { get; internal set; } /// /// A list of all layer properties in this group /// - internal List LayerProperties { get; set; } + public ReadOnlyCollection LayerProperties => _layerProperties.AsReadOnly(); /// /// A list of al child groups in this group /// - internal List LayerPropertyGroups { get; set; } + public ReadOnlyCollection LayerPropertyGroups => _layerPropertyGroups.AsReadOnly(); /// /// Called when all layer properties in this property group have been initialized @@ -63,7 +68,7 @@ namespace Artemis.Core.Models.Profile var instance = (BaseLayerProperty) Activator.CreateInstance(propertyInfo.PropertyType); InitializeProperty(layer, path, instance); propertyInfo.SetValue(this, instance); - LayerProperties.Add(instance); + _layerProperties.Add(instance); } else { @@ -76,7 +81,7 @@ namespace Artemis.Core.Models.Profile var instance = (LayerPropertyGroup) Activator.CreateInstance(propertyInfo.PropertyType); instance.InitializeProperties(layerService, layer, $"{path}{propertyInfo.Name}."); propertyInfo.SetValue(this, instance); - LayerPropertyGroups.Add(instance); + _layerPropertyGroups.Add(instance); } } } @@ -121,7 +126,7 @@ namespace Artemis.Core.Models.Profile /// Recursively gets all layer properties on this group and any subgroups /// /// - internal IReadOnlyCollection GetAllLayerProperties() + public IReadOnlyCollection GetAllLayerProperties() { if (!PropertiesInitialized) return new List(); diff --git a/src/Artemis.Core/Plugins/LayerBrush/BaseLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrush/BaseLayerBrush.cs index beecad9b4..5a06297f8 100644 --- a/src/Artemis.Core/Plugins/LayerBrush/BaseLayerBrush.cs +++ b/src/Artemis.Core/Plugins/LayerBrush/BaseLayerBrush.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using Artemis.Core.Models.Profile; -using Artemis.Core.Models.Profile.LayerProperties; using Artemis.Core.Plugins.Models; using Artemis.Core.Services.Interfaces; using SkiaSharp; @@ -29,7 +27,7 @@ namespace Artemis.Core.Plugins.LayerBrush /// public PluginInfo PluginInfo => Descriptor.LayerBrushProvider.PluginInfo; - internal virtual LayerPropertyGroup BaseProperties => null; + public virtual LayerPropertyGroup BaseProperties => null; /// /// Called when the brush is being removed from the layer @@ -62,22 +60,5 @@ namespace Artemis.Core.Plugins.LayerBrush internal virtual void InitializeProperties(ILayerService layerService, string path) { } - - internal virtual void ApplyToEntity() - { - } - - internal virtual void UpdateProperties(double deltaTime) - { - } - - internal virtual void OverrideProperties(TimeSpan overrideTime) - { - } - - internal virtual IReadOnlyCollection GetAllLayerProperties() - { - return new List(); - } } } \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs index b3807f239..a27fcdb19 100644 --- a/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs +++ b/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs @@ -47,7 +47,7 @@ namespace Artemis.Core.Plugins.LayerBrush } /// - internal override LayerPropertyGroup BaseProperties => Properties; + public override LayerPropertyGroup BaseProperties => Properties; internal override void InitializeProperties(ILayerService layerService, string path) { @@ -56,22 +56,17 @@ namespace Artemis.Core.Plugins.LayerBrush PropertiesInitialized = true; } - internal override void ApplyToEntity() + internal virtual void ApplyToEntity() { Properties.ApplyToEntity(); } - internal override void UpdateProperties(double deltaTime) - { - Properties.Update(deltaTime); - } - - internal override void OverrideProperties(TimeSpan overrideTime) + internal virtual void OverrideProperties(TimeSpan overrideTime) { Properties.Override(overrideTime); } - internal override IReadOnlyCollection GetAllLayerProperties() + internal virtual IReadOnlyCollection GetAllLayerProperties() { return Properties.GetAllLayerProperties(); } diff --git a/src/Artemis.Core/Services/LayerService.cs b/src/Artemis.Core/Services/LayerService.cs index a1cd47f46..6a1c344e3 100644 --- a/src/Artemis.Core/Services/LayerService.cs +++ b/src/Artemis.Core/Services/LayerService.cs @@ -76,10 +76,5 @@ namespace Artemis.Core.Services layer.LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == brush.PluginInfo.Guid); } - - public void GetLayerPropertyGroups(Layer layer) - { - var groups = new List {layer.General, layer.Transform, layer.LayerBrush.BrushProperties}; - } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs new file mode 100644 index 000000000..694dc9480 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Artemis.Core.Models.Profile.LayerProperties; +using Stylet; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract +{ + public abstract class LayerPropertyBaseViewModel : PropertyChangedBase + { + public abstract List GetKeyframes(bool visibleOnly); + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs index cc4ef6b8f..4844e8619 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs @@ -7,6 +7,7 @@ using System.Windows.Media; using Artemis.Core.Events; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.LayerProperties; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; using Artemis.Core.Services; using Artemis.Core.Services.Interfaces; using Artemis.UI.Events; @@ -21,28 +22,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties public class LayerPropertiesViewModel : ProfileEditorPanelViewModel { private readonly ICoreService _coreService; - private readonly List _layerPropertyViewModels; - private readonly ILayerPropertyVmFactory _layerPropertyVmFactory; private readonly IPropertyTreeVmFactory _propertyTreeVmFactory; private readonly IPropertyTimelineVmFactory _propertyTimelineVmFactory; private readonly IProfileEditorService _profileEditorService; private readonly ISettingsService _settingsService; - private Layer _lastSelectedLayer; public LayerPropertiesViewModel(IProfileEditorService profileEditorService, ICoreService coreService, ISettingsService settingsService, - ILayerPropertyVmFactory layerPropertyVmFactory, IPropertyTreeVmFactory propertyTreeVmFactory, IPropertyTimelineVmFactory propertyTimelineVmFactory) { _profileEditorService = profileEditorService; _coreService = coreService; _settingsService = settingsService; - _layerPropertyVmFactory = layerPropertyVmFactory; _propertyTreeVmFactory = propertyTreeVmFactory; _propertyTimelineVmFactory = propertyTimelineVmFactory; - _layerPropertyViewModels = new List(); PixelsPerSecond = 31; } @@ -67,6 +62,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties set => _profileEditorService.CurrentTime = TimeSpan.FromSeconds(value.Left / PixelsPerSecond); } + public BindableCollection LayerPropertyGroups { get; set; } public PropertyTreeViewModel PropertyTree { get; set; } public PropertyTimelineViewModel PropertyTimeline { get; set; } @@ -88,12 +84,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties _profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected; _profileEditorService.CurrentTimeChanged -= ProfileEditorServiceOnCurrentTimeChanged; - if (_lastSelectedLayer != null) - { - _lastSelectedLayer.Properties.LayerPropertyRegistered -= LayerOnPropertyRegistered; - _lastSelectedLayer.Properties.LayerPropertyRemoved -= LayerOnPropertyRemoved; - } - PropertyTree?.Dispose(); PropertyTimeline?.Dispose(); PropertyTree = null; @@ -122,78 +112,30 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties private void PopulateProperties(ProfileElement profileElement) { - if (_lastSelectedLayer != null) - { - _lastSelectedLayer.Properties.LayerPropertyRegistered -= LayerOnPropertyRegistered; - _lastSelectedLayer.Properties.LayerPropertyRemoved -= LayerOnPropertyRemoved; - } - + LayerPropertyGroups.Clear(); if (profileElement is Layer layer) { - // Create VMs for missing properties - foreach (var baseLayerProperty in layer.Properties) + // Add the built-in root groups of the layer + var generalAttribute = Attribute.GetCustomAttribute( + layer.GetType().GetProperty(nameof(layer.General)), + typeof(PropertyGroupDescriptionAttribute) + ); + var transformAttribute = Attribute.GetCustomAttribute( + layer.GetType().GetProperty(nameof(layer.Transform)), + typeof(PropertyGroupDescriptionAttribute) + ); + LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(layer.General, (PropertyGroupDescriptionAttribute) generalAttribute)); + LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(layer.Transform, (PropertyGroupDescriptionAttribute) transformAttribute)); + + // Add the rout group of the brush + // The root group of the brush has no attribute so let's pull one out of our sleeve + var brushDescription = new PropertyGroupDescriptionAttribute { - if (_layerPropertyViewModels.All(vm => vm.LayerProperty != baseLayerProperty)) - CreatePropertyViewModel(baseLayerProperty); - } - - // Remove VMs for extra properties - foreach (var layerPropertyViewModel in _layerPropertyViewModels.ToList()) - { - if (layer.Properties.All(p => p != layerPropertyViewModel.LayerProperty)) - RemovePropertyViewModel(layerPropertyViewModel); - } - - _lastSelectedLayer = layer; - layer.Properties.LayerPropertyRegistered += LayerOnPropertyRegistered; - layer.Properties.LayerPropertyRemoved += LayerOnPropertyRemoved; + Name = layer.LayerBrush.Descriptor.DisplayName, + Description = layer.LayerBrush.Descriptor.Description + }; + LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(layer.LayerBrush.BaseProperties, brushDescription)); } - else - { - foreach (var layerPropertyViewModel in _layerPropertyViewModels.ToList()) - RemovePropertyViewModel(layerPropertyViewModel); - - _lastSelectedLayer = null; - } - } - - private void LayerOnPropertyRegistered(object sender, LayerPropertyEventArgs e) - { - Console.WriteLine("LayerOnPropertyRegistered"); - PopulateProperties(e.LayerProperty.Layer); - } - - private void LayerOnPropertyRemoved(object sender, LayerPropertyEventArgs e) - { - Console.WriteLine("LayerOnPropertyRemoved"); - PopulateProperties(e.LayerProperty.Layer); - } - - private LayerPropertyViewModel CreatePropertyViewModel(BaseLayerProperty layerProperty) - { - LayerPropertyViewModel parent = null; - // If the property has a parent, find it's VM - if (layerProperty.Parent != null) - { - parent = _layerPropertyViewModels.FirstOrDefault(vm => vm.LayerProperty == layerProperty.Parent); - // If no VM is found, create it - if (parent == null) - parent = CreatePropertyViewModel(layerProperty.Parent); - } - - var createdViewModel = _layerPropertyVmFactory.Create(layerProperty, parent); - _layerPropertyViewModels.Add(createdViewModel); - PropertyTree.AddLayerProperty(createdViewModel); - PropertyTimeline.AddLayerProperty(createdViewModel); - - return createdViewModel; - } - - private void RemovePropertyViewModel(LayerPropertyViewModel layerPropertyViewModel) - { - PropertyTree.RemoveLayerProperty(layerPropertyViewModel); - PropertyTimeline.RemoveLayerProperty(layerPropertyViewModel); - _layerPropertyViewModels.Remove(layerPropertyViewModel); } #endregion @@ -259,9 +201,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties private TimeSpan CalculateEndTime() { - // End time is the last keyframe + 10 sec - var lastKeyFrame = PropertyTimeline.PropertyTrackViewModels.SelectMany(r => r.KeyframeViewModels).OrderByDescending(t => t.Keyframe.Position).FirstOrDefault(); - return lastKeyFrame?.Keyframe.Position.Add(new TimeSpan(0, 0, 0, 10)) ?? TimeSpan.MaxValue; + if (!(_profileEditorService.SelectedProfileElement is Layer layer)) + return TimeSpan.MaxValue; + + var keyframes = GetKeyframes(false); + + // If there are no keyframes, don't stop at all + if (!keyframes.Any()) + return TimeSpan.MaxValue; + // If there are keyframes, stop after the last keyframe + 10 sec + return keyframes.Max(k => k.Position).Add(TimeSpan.FromSeconds(10)); } private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e) @@ -323,19 +272,24 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties return; } - // If shift is held, snap to closest keyframe - var visibleKeyframes = PropertyTimeline.PropertyTrackViewModels - .Where(t => t.LayerPropertyViewModel.Parent != null && t.LayerPropertyViewModel.Parent.IsExpanded) - .SelectMany(t => t.KeyframeViewModels); + var visibleKeyframes = GetKeyframes(true); + // Take a tolerance of 5 pixels (half a keyframe width) var tolerance = 1000f / PixelsPerSecond * 5; - var closeKeyframe = visibleKeyframes.FirstOrDefault( - kf => Math.Abs(kf.Keyframe.Position.TotalMilliseconds - newTime.TotalMilliseconds) < tolerance - ); - _profileEditorService.CurrentTime = closeKeyframe?.Keyframe.Position ?? newTime; + var closeKeyframe = visibleKeyframes.FirstOrDefault(k => Math.Abs(k.Position.TotalMilliseconds - newTime.TotalMilliseconds) < tolerance); + _profileEditorService.CurrentTime = closeKeyframe?.Position ?? newTime; } } + private List GetKeyframes(bool visibleOnly) + { + var result = new List(); + foreach (var layerPropertyGroupViewModel in LayerPropertyGroups) + result.AddRange(layerPropertyGroupViewModel.GetKeyframes(visibleOnly)); + + return result; + } + #endregion #region Events diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs new file mode 100644 index 000000000..2c3e0190d --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties +{ + public class LayerPropertyGroupViewModel : LayerPropertyBaseViewModel + { + public LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription) + { + LayerPropertyGroup = layerPropertyGroup; + PropertyGroupDescription = propertyGroupDescription; + + IsExpanded = PropertyGroupDescription.ExpandByDefault; + + Children = new List(); + PopulateChildren(); + } + + public LayerPropertyGroup LayerPropertyGroup { get; } + public PropertyGroupDescriptionAttribute PropertyGroupDescription { get; } + public bool IsExpanded { get; set; } + + public List Children { get; set; } + + private void PopulateChildren() + { + // Get all properties and property groups and create VMs for them + foreach (var propertyInfo in LayerPropertyGroup.GetType().GetProperties()) + { + var propertyAttribute = (PropertyDescriptionAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyDescriptionAttribute)); + var groupAttribute = (PropertyGroupDescriptionAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyGroupDescriptionAttribute)); + var value = propertyInfo.GetValue(LayerPropertyGroup); + + // Create VMs for properties on the group + if (propertyAttribute != null && value is BaseLayerProperty) + { + // Go through the pain of instantiating a generic type VM now via reflection to make things a lot simpler down the line + var genericType = propertyInfo.PropertyType.GetGenericArguments()[0]; + var genericViewModel = typeof(LayerPropertyViewModel<>).MakeGenericType(genericType); + var instance = Activator.CreateInstance(genericViewModel, value, propertyAttribute); + Children.Add((LayerPropertyBaseViewModel) instance); + } + // Create VMs for child groups on this group, resulting in a nested structure + else if (groupAttribute != null && value is LayerPropertyGroup layerPropertyGroup) + { + Children.Add(new LayerPropertyGroupViewModel(layerPropertyGroup, groupAttribute)); + } + } + } + + public override List GetKeyframes(bool visibleOnly) + { + var result = new List(); + if (!IsExpanded) + return result; + + foreach (var layerPropertyBaseViewModel in Children) + result.AddRange(layerPropertyBaseViewModel.GetKeyframes(visibleOnly)); + + return result; + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs index 2c3572a5f..699c0f0a9 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs @@ -1,108 +1,25 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Artemis.Core.Models.Profile.LayerProperties; -using Artemis.Core.Utilities; -using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput; -using Artemis.UI.Services.Interfaces; -using Ninject; -using Stylet; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties { - public class LayerPropertyViewModel : LayerPropertyViewModel + public class LayerPropertyViewModel : LayerPropertyBaseViewModel { - private readonly IKernel _kernel; - private readonly IProfileEditorService _profileEditorService; - private bool _keyframesEnabled; - private bool _isExpanded; - - public LayerPropertyViewModel(LayerProperty layerProperty, LayerPropertyViewModel parent, IKernel kernel, IProfileEditorService profileEditorService) + public LayerPropertyViewModel(LayerProperty layerProperty, PropertyDescriptionAttribute propertyDescription) { - _kernel = kernel; - _profileEditorService = profileEditorService; - _keyframesEnabled = layerProperty.KeyframesEnabled; - LayerProperty = layerProperty; - Parent = parent; - Children = new List(); - - // TODO: Get from attribute - IsExpanded = false; - - Parent?.Children.Add(this); + PropertyDescription = propertyDescription; } public LayerProperty LayerProperty { get; } + public PropertyDescriptionAttribute PropertyDescription { get; } - public bool IsExpanded + public override List GetKeyframes(bool visibleOnly) { - get => _isExpanded; - set - { - _isExpanded = value; - OnExpandedStateChanged(); - } + return LayerProperty.BaseKeyframes.ToList(); } - - public bool KeyframesEnabled - { - get => _keyframesEnabled; - set - { - _keyframesEnabled = value; - UpdateKeyframes(); - } - } - - public PropertyInputViewModel GetPropertyInputViewModel() - { - // If the type is an enum type, search for Enum instead. - var type = typeof(T); - if (type.IsEnum) - type = typeof(Enum); - - var match = _kernel.Get>().FirstOrDefault(p => p.CompatibleTypes.Contains(type)); - if (match == null) - return null; - - match.Initialize(this); - return match; - } - - private void UpdateKeyframes() - { - - // Either create a new first keyframe or clear all the keyframes - if (_keyframesEnabled) - LayerProperty.AddKeyframe(new LayerPropertyKeyframe(LayerProperty.CurrentValue, _profileEditorService.CurrentTime, Easings.Functions.Linear)); - else - LayerProperty.ClearKeyframes(); - - // Force the keyframe engine to update, the new keyframe is the current keyframe - LayerProperty.KeyframesEnabled = _keyframesEnabled; - LayerProperty.Update(0); - - _profileEditorService.UpdateSelectedProfileElement(); - } - - #region Events - - public event EventHandler ExpandedStateChanged; - - protected virtual void OnExpandedStateChanged() - { - ExpandedStateChanged?.Invoke(this, EventArgs.Empty); - foreach (var layerPropertyViewModel in Children) - layerPropertyViewModel.OnExpandedStateChanged(); - } - - #endregion - } - - public class LayerPropertyViewModel : PropertyChangedBase - { - public LayerPropertyViewModel Parent { get; protected set; } - public List Children { get; protected set; } } } \ No newline at end of file