diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index 66d55132d..c33897687 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -72,6 +72,33 @@ namespace Artemis.Core.Models.Profile.LayerProperties public override IReadOnlyList BaseKeyframes => _keyframes.Cast().ToList().AsReadOnly(); + /// + /// Sets the current value, using either keyframes if enabled or the base value. + /// + /// The value to set. + /// + /// An optional time to set the value add, if provided and property is using keyframes the value will be set to an new + /// or existing keyframe. + /// + public void SetCurrentValue(T value, TimeSpan? time) + { + if (time == null || !KeyframesEnabled || !KeyframesSupported) + BaseValue = value; + else + { + // If on a keyframe, update the keyframe + var currentKeyframe = Keyframes.FirstOrDefault(k => k.Position == time.Value); + // Create a new keyframe if none found + if (currentKeyframe == null) + AddKeyframe(new LayerPropertyKeyframe(value, time.Value, Easings.Functions.Linear)); + else + currentKeyframe.Value = value; + + // Update the property so that the new keyframe is reflected on the current value + Update(0); + } + } + /// /// Adds a keyframe to the layer property /// @@ -220,9 +247,24 @@ namespace Artemis.Core.Models.Profile.LayerProperties #region Events + /// + /// Occurs once every frame when the layer property is updated + /// public event EventHandler Updated; + + /// + /// Occurs when the base value of the layer property was updated + /// public event EventHandler BaseValueChanged; + + /// + /// Occurs when a new keyframe was added to the layer property + /// public event EventHandler KeyframeAdded; + + /// + /// Occurs when a keyframe was removed from the layer property + /// public event EventHandler KeyframeRemoved; protected virtual void OnUpdated() diff --git a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs index f9057d67d..c06c94647 100644 --- a/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs +++ b/src/Artemis.Core/Models/Profile/LayerPropertyGroup.cs @@ -33,6 +33,11 @@ namespace Artemis.Core.Models.Profile /// public bool IsCorePropertyGroup { get; internal set; } + /// + /// Gets or sets whether the property is hidden in the UI + /// + public bool IsHidden { get; set; } + /// /// A list of all layer properties in this group /// diff --git a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs index a783c2876..5e96cd8b1 100644 --- a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs +++ b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs @@ -47,29 +47,4 @@ namespace Artemis.UI.Ninject.Factories { ProfileLayerViewModel Create(Layer layer); } - - public interface ILayerPropertyVmFactory : IVmFactory - { - LayerPropertyViewModel Create(BaseLayerProperty layerProperty, LayerPropertyViewModel parent); - } - - public interface IPropertyTreeVmFactory : IVmFactory - { - PropertyTreeViewModel Create(LayerPropertiesViewModel layerPropertiesViewModel); - } - - public interface IPropertyTimelineVmFactory : IVmFactory - { - PropertyTimelineViewModel Create(LayerPropertiesViewModel layerPropertiesViewModel); - } - - public interface IPropertyTrackVmFactory : IVmFactory - { - PropertyTrackViewModel Create(PropertyTimelineViewModel propertyTimelineViewModel, LayerPropertyViewModel layerPropertyViewModel); - } - - public interface IPropertyTrackKeyframeVmFactory : IVmFactory - { - PropertyTrackKeyframeViewModel Create(PropertyTrackViewModel propertyTrackViewModel, LayerPropertyKeyframe keyframe); - } } \ 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 index 694dc9480..3a4364209 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs @@ -1,11 +1,23 @@ -using System.Collections.Generic; +using System; +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 class LayerPropertyBaseViewModel : PropertyChangedBase, IDisposable { + protected LayerPropertyBaseViewModel() + { + Children = new List(); + } + + public bool IsExpanded { get; set; } + public abstract bool IsVisible { get; } + + public List Children { get; set; } + public abstract List GetKeyframes(bool visibleOnly); + public abstract void Dispose(); } } \ 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 4844e8619..9114231c4 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs @@ -11,9 +11,8 @@ using Artemis.Core.Models.Profile.LayerProperties.Attributes; using Artemis.Core.Services; using Artemis.Core.Services.Interfaces; using Artemis.UI.Events; -using Artemis.UI.Ninject.Factories; -using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree; using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree; using Artemis.UI.Services.Interfaces; using Stylet; @@ -22,22 +21,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties public class LayerPropertiesViewModel : ProfileEditorPanelViewModel { private readonly ICoreService _coreService; - private readonly IPropertyTreeVmFactory _propertyTreeVmFactory; - private readonly IPropertyTimelineVmFactory _propertyTimelineVmFactory; private readonly IProfileEditorService _profileEditorService; private readonly ISettingsService _settingsService; - public LayerPropertiesViewModel(IProfileEditorService profileEditorService, - ICoreService coreService, - ISettingsService settingsService, - IPropertyTreeVmFactory propertyTreeVmFactory, - IPropertyTimelineVmFactory propertyTimelineVmFactory) + public LayerPropertiesViewModel(IProfileEditorService profileEditorService, ICoreService coreService, ISettingsService settingsService) { _profileEditorService = profileEditorService; _coreService = coreService; _settingsService = settingsService; - _propertyTreeVmFactory = propertyTreeVmFactory; - _propertyTimelineVmFactory = propertyTimelineVmFactory; PixelsPerSecond = 31; } @@ -63,13 +54,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties } public BindableCollection LayerPropertyGroups { get; set; } - public PropertyTreeViewModel PropertyTree { get; set; } - public PropertyTimelineViewModel PropertyTimeline { get; set; } + public TreeViewModel TreeViewModel { get; set; } + public TimelineViewModel TimelineViewModel { get; set; } protected override void OnInitialActivate() { - PropertyTree = _propertyTreeVmFactory.Create(this); - PropertyTimeline = _propertyTimelineVmFactory.Create(this); + TreeViewModel = new TreeViewModel(LayerPropertyGroups); + TimelineViewModel = new TimelineViewModel(LayerPropertyGroups); PopulateProperties(_profileEditorService.SelectedProfileElement); @@ -84,10 +75,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties _profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected; _profileEditorService.CurrentTimeChanged -= ProfileEditorServiceOnCurrentTimeChanged; - PropertyTree?.Dispose(); - PropertyTimeline?.Dispose(); - PropertyTree = null; - PropertyTimeline = null; base.OnClose(); } @@ -124,8 +111,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties layer.GetType().GetProperty(nameof(layer.Transform)), typeof(PropertyGroupDescriptionAttribute) ); - LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(layer.General, (PropertyGroupDescriptionAttribute) generalAttribute)); - LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(layer.Transform, (PropertyGroupDescriptionAttribute) transformAttribute)); + LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(_profileEditorService, layer.General, (PropertyGroupDescriptionAttribute) generalAttribute)); + LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(_profileEditorService, 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 @@ -134,7 +121,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties Name = layer.LayerBrush.Descriptor.DisplayName, Description = layer.LayerBrush.Descriptor.Description }; - LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(layer.LayerBrush.BaseProperties, brushDescription)); + LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(_profileEditorService, layer.LayerBrush.BaseProperties, brushDescription)); } } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs index 2c3e0190d..aef93f5c0 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs @@ -4,27 +4,37 @@ 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; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree; +using Artemis.UI.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties { public class LayerPropertyGroupViewModel : LayerPropertyBaseViewModel { - public LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription) + public LayerPropertyGroupViewModel(IProfileEditorService profileEditorService, LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription) { + ProfileEditorService = profileEditorService; + LayerPropertyGroup = layerPropertyGroup; PropertyGroupDescription = propertyGroupDescription; - IsExpanded = PropertyGroupDescription.ExpandByDefault; - Children = new List(); + TreePropertyGroupViewModel = new TreePropertyGroupViewModel(this); + TimelinePropertyGroupViewModel = new TimelinePropertyGroupViewModel(this); + PopulateChildren(); } + public override bool IsVisible => !LayerPropertyGroup.IsHidden; + + public IProfileEditorService ProfileEditorService { get; } + public LayerPropertyGroup LayerPropertyGroup { get; } public PropertyGroupDescriptionAttribute PropertyGroupDescription { get; } - public bool IsExpanded { get; set; } - public List Children { get; set; } + public TreePropertyGroupViewModel TreePropertyGroupViewModel { get; set; } + public TimelinePropertyGroupViewModel TimelinePropertyGroupViewModel { get; set; } private void PopulateChildren() { @@ -36,18 +46,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties var value = propertyInfo.GetValue(LayerPropertyGroup); // Create VMs for properties on the group - if (propertyAttribute != null && value is BaseLayerProperty) + if (propertyAttribute != null && value is BaseLayerProperty 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); + var viewModel = ProfileEditorService.CreateLayerPropertyViewModel(baseLayerProperty, propertyAttribute); + if (viewModel != null) + Children.Add(viewModel); } // 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)); + Children.Add(new LayerPropertyGroupViewModel(ProfileEditorService, layerPropertyGroup, groupAttribute)); } } } @@ -63,5 +71,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties return result; } + + public override void Dispose() + { + foreach (var layerPropertyBaseViewModel in Children) + layerPropertyBaseViewModel.Dispose(); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyKeyframeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyKeyframeViewModel.cs new file mode 100644 index 000000000..bb60f1d4f --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyKeyframeViewModel.cs @@ -0,0 +1,14 @@ +using Artemis.Core.Models.Profile.LayerProperties; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties +{ + public class LayerKeyframeViewModel + { + public LayerKeyframeViewModel(LayerPropertyKeyframe keyframe) + { + Keyframe = keyframe; + } + + public LayerPropertyKeyframe Keyframe { get; } + } +} \ 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 699c0f0a9..6b76b8672 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs @@ -3,23 +3,68 @@ using System.Linq; using Artemis.Core.Models.Profile.LayerProperties; using Artemis.Core.Models.Profile.LayerProperties.Attributes; using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree; +using Artemis.UI.Services.Interfaces; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties { - public class LayerPropertyViewModel : LayerPropertyBaseViewModel + public class LayerPropertyViewModel : LayerPropertyViewModel { - public LayerPropertyViewModel(LayerProperty layerProperty, PropertyDescriptionAttribute propertyDescription) + public LayerPropertyViewModel(IProfileEditorService profileEditorService, LayerProperty layerProperty, PropertyDescriptionAttribute propertyDescription) + : base(profileEditorService, layerProperty) { LayerProperty = layerProperty; PropertyDescription = propertyDescription; + + TreePropertyViewModel = new TreePropertyViewModel(this); + TimelinePropertyViewModel = new TimelinePropertyViewModel(this); + + TreePropertyBaseViewModel = TreePropertyViewModel; + TimelinePropertyBaseViewModel = TimelinePropertyViewModel; } + public override bool IsVisible => !LayerProperty.IsHidden; + public LayerProperty LayerProperty { get; } - public PropertyDescriptionAttribute PropertyDescription { get; } + + public TreePropertyViewModel TreePropertyViewModel { get; set; } + public TimelinePropertyViewModel TimelinePropertyViewModel { get; set; } public override List GetKeyframes(bool visibleOnly) { return LayerProperty.BaseKeyframes.ToList(); } + + public override void Dispose() + { + TreePropertyViewModel.Dispose(); + TimelinePropertyViewModel.Dispose(); + } + + public void SetCurrentValue(T value, bool saveChanges) + { + LayerProperty.SetCurrentValue(value, ProfileEditorService.CurrentTime); + if (saveChanges) + ProfileEditorService.UpdateSelectedProfileElement(); + else + ProfileEditorService.UpdateProfilePreview(); + } + } + + public abstract class LayerPropertyViewModel : LayerPropertyBaseViewModel + { + public IProfileEditorService ProfileEditorService { get; } + public BaseLayerProperty BaseLayerProperty { get; } + + protected LayerPropertyViewModel(IProfileEditorService profileEditorService, BaseLayerProperty baseLayerProperty) + { + ProfileEditorService = profileEditorService; + BaseLayerProperty = baseLayerProperty; + } + + public PropertyDescriptionAttribute PropertyDescription { get; protected set; } + public TreePropertyViewModel TreePropertyBaseViewModel { get; set; } + public TimelinePropertyViewModel TimelinePropertyBaseViewModel { get; set; } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs deleted file mode 100644 index 42b6e9678..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/PropertyInputViewModel.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Collections.Generic; -using Artemis.UI.Exceptions; -using Artemis.UI.Services.Interfaces; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput -{ - public abstract class PropertyInputViewModel : PropertyChangedBase, IDisposable - { - protected PropertyInputViewModel(IProfileEditorService profileEditorService) - { - ProfileEditorService = profileEditorService; - } - - protected IProfileEditorService ProfileEditorService { get; } - public abstract List CompatibleTypes { get; } - - public bool Initialized { get; private set; } - public bool InputDragging { get; private set; } - public LayerPropertyViewModel LayerPropertyViewModel { get; private set; } - - protected object InputValue - { - get => LayerPropertyViewModel.LayerProperty.GetCurrentValue(); - set => UpdateInputValue(value); - } - - public void Initialize(LayerPropertyViewModel layerPropertyViewModel) - { - var type = layerPropertyViewModel.LayerProperty.Type; - if (type.IsEnum) - type = typeof(Enum); - if (Initialized) - throw new ArtemisUIException("Cannot initialize the same property input VM twice"); - if (!CompatibleTypes.Contains(type)) - throw new ArtemisUIException($"This input VM does not support the provided type {type.Name}"); - - LayerPropertyViewModel = layerPropertyViewModel; - LayerPropertyViewModel.LayerProperty.ValueChanged += LayerPropertyOnValueChanged; - Update(); - - Initialized = true; - - OnInitialized(); - } - - public abstract void Update(); - - protected virtual void OnInitialized() - { - } - - private void LayerPropertyOnValueChanged(object sender, EventArgs e) - { - Update(); - } - - private void UpdateInputValue(object value) - { - LayerPropertyViewModel.LayerProperty.SetCurrentValue(value, ProfileEditorService.CurrentTime); - // Force the keyframe engine to update, the edited keyframe might affect the current keyframe progress - LayerPropertyViewModel.LayerProperty.KeyframeEngine?.Update(0); - - if (!InputDragging) - ProfileEditorService.UpdateSelectedProfileElement(); - else - ProfileEditorService.UpdateProfilePreview(); - } - - #region Event handlers - - public void InputDragStarted(object sender, EventArgs e) - { - InputDragging = true; - } - - public void InputDragEnded(object sender, EventArgs e) - { - InputDragging = false; - ProfileEditorService.UpdateSelectedProfileElement(); - } - - #endregion - - public virtual void Dispose() - { - if (LayerPropertyViewModel != null) - LayerPropertyViewModel.LayerProperty.ValueChanged -= LayerPropertyOnValueChanged; - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildView.xaml deleted file mode 100644 index 4f4fec459..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildView.xaml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildViewModel.cs deleted file mode 100644 index 3d32a21f2..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildViewModel.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree -{ - public class PropertyTreeChildViewModel : PropertyTreeItemViewModel - { - public PropertyTreeChildViewModel(LayerPropertyViewModel layerPropertyViewModel) : base(layerPropertyViewModel) - { - PropertyInputViewModel = layerPropertyViewModel.GetPropertyInputViewModel(); - } - - public PropertyInputViewModel PropertyInputViewModel { get; set; } - - public override void Update(bool forceUpdate) - { - if (forceUpdate) - PropertyInputViewModel?.Update(); - else - { - // Only update if visible and if keyframes are enabled - if (LayerPropertyViewModel.Parent.IsExpanded && LayerPropertyViewModel.KeyframesEnabled) - PropertyInputViewModel?.Update(); - } - } - - public override void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel) - { - } - - public override void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel) - { - } - - public override void Dispose() - { - PropertyInputViewModel?.Dispose(); - PropertyInputViewModel = null; - - base.Dispose(); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeItemViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeItemViewModel.cs deleted file mode 100644 index bae2fe5dd..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeItemViewModel.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree -{ - public abstract class PropertyTreeItemViewModel : PropertyChangedBase, IDisposable - { - protected PropertyTreeItemViewModel(LayerPropertyViewModel layerPropertyViewModel) - { - LayerPropertyViewModel = layerPropertyViewModel; - } - - public LayerPropertyViewModel LayerPropertyViewModel { get; } - - /// - /// Updates the tree item's input if it is visible and has keyframes enabled - /// - /// Force update regardless of visibility and keyframes - public abstract void Update(bool forceUpdate); - - /// - /// Removes the layer property recursively - /// - /// - public abstract void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel); - - /// - /// Adds the layer property recursively - /// - /// - public abstract void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel); - - public virtual void Dispose() - { - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeParentViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeParentViewModel.cs deleted file mode 100644 index aa88002a8..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeParentViewModel.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Linq; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree -{ - public class PropertyTreeParentViewModel : PropertyTreeItemViewModel - { - public PropertyTreeParentViewModel(LayerPropertyViewModel layerPropertyViewModel) : base(layerPropertyViewModel) - { - Children = new BindableCollection(); - } - - public BindableCollection Children { get; set; } - - public override void Update(bool forceUpdate) - { - foreach (var child in Children) - child.Update(forceUpdate); - } - - // TODO: Change this to not add one by one, this raises far too many events - public override void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel) - { - if (layerPropertyViewModel.Parent == LayerPropertyViewModel) - { - lock (Children) - { - var index = layerPropertyViewModel.LayerProperty.Parent.Children.IndexOf(layerPropertyViewModel.LayerProperty); - if (index > Children.Count) - index = Children.Count; - if (layerPropertyViewModel.Children.Any()) - Children.Insert(index, new PropertyTreeParentViewModel(layerPropertyViewModel)); - else - Children.Insert(index, new PropertyTreeChildViewModel(layerPropertyViewModel)); - } - } - else - { - foreach (var propertyTreeItemViewModel in Children) - propertyTreeItemViewModel.AddLayerProperty(layerPropertyViewModel); - } - } - - // TODO: Change this to not remove one by one, this raises far too many events - public override void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel) - { - foreach (var child in Children.ToList()) - { - if (child.LayerPropertyViewModel == layerPropertyViewModel) - { - Children.Remove(child); - child.Dispose(); - } - else - child.RemoveLayerProperty(layerPropertyViewModel); - } - } - - public override void Dispose() - { - foreach (var child in Children.ToList()) - child.Dispose(); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeViewModel.cs deleted file mode 100644 index 54f28e915..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeViewModel.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using Artemis.UI.Events; -using Artemis.UI.Services.Interfaces; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree -{ - public class PropertyTreeViewModel : PropertyChangedBase, IDisposable - { - private readonly IProfileEditorService _profileEditorService; - - public PropertyTreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IProfileEditorService profileEditorService) - { - _profileEditorService = profileEditorService; - - LayerPropertiesViewModel = layerPropertiesViewModel; - PropertyTreeItemViewModels = new BindableCollection(); - - _profileEditorService.CurrentTimeChanged += OnCurrentTimeChanged; - _profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated; - } - - public LayerPropertiesViewModel LayerPropertiesViewModel { get; } - public BindableCollection PropertyTreeItemViewModels { get; set; } - - public void Dispose() - { - _profileEditorService.CurrentTimeChanged -= OnCurrentTimeChanged; - _profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated; - - foreach (var propertyTreeItemViewModel in PropertyTreeItemViewModels) - propertyTreeItemViewModel.Dispose(); - } - - // TODO: Change this to not add one by one, this raises far too many events - public void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel) - { - // Add as a root VM - if (layerPropertyViewModel.Parent == null) - PropertyTreeItemViewModels.Add(new PropertyTreeParentViewModel(layerPropertyViewModel)); - // Add recursively to one of the child VMs - else - { - foreach (var propertyTreeItemViewModel in PropertyTreeItemViewModels) - propertyTreeItemViewModel.AddLayerProperty(layerPropertyViewModel); - } - } - - // TODO: Change this to not remove one by one, this raises far too many events - public void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel) - { - // Remove a root VM - var rootVm = PropertyTreeItemViewModels.FirstOrDefault(vm => vm.LayerPropertyViewModel == layerPropertyViewModel); - if (rootVm != null) - PropertyTreeItemViewModels.Remove(rootVm); - // Remove recursively from one of the child VMs - else - { - foreach (var propertyTreeItemViewModel in PropertyTreeItemViewModels) - propertyTreeItemViewModel.RemoveLayerProperty(layerPropertyViewModel); - } - } - - /// - /// Updates the tree item's input if it is visible and has keyframes enabled - /// - /// Force update regardless of visibility and keyframes - public void Update(bool forceUpdate) - { - foreach (var viewModel in PropertyTreeItemViewModels) - viewModel.Update(forceUpdate); - } - - public void PropertyTreePreviewMouseWheel(object sender, MouseWheelEventArgs e) - { - if (e.Handled || !(sender is TreeView)) - return; - - e.Handled = true; - var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) - { - RoutedEvent = UIElement.MouseWheelEvent, - Source = sender - }; - var parent = ((Control) sender).Parent as UIElement; - parent?.RaiseEvent(eventArg); - } - - private void OnCurrentTimeChanged(object sender, EventArgs e) - { - Update(false); - } - - private void OnSelectedProfileElementUpdated(object sender, ProfileElementEventArgs e) - { - Update(true); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineHeader.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/Controls/PropertyTimelineHeader.cs similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineHeader.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/Controls/PropertyTimelineHeader.cs diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineView.xaml deleted file mode 100644 index 239fafe15..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineView.xaml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs deleted file mode 100644 index 655c0e007..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs +++ /dev/null @@ -1,245 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using System.Windows.Input; -using System.Windows.Media; -using Artemis.UI.Events; -using Artemis.UI.Ninject.Factories; -using Artemis.UI.Services.Interfaces; -using Artemis.UI.Shared.Utilities; -using Artemis.UI.Utilities; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline -{ - public class PropertyTimelineViewModel : PropertyChangedBase, IDisposable - { - private readonly IProfileEditorService _profileEditorService; - private readonly IPropertyTrackVmFactory _propertyTrackVmFactory; - - public PropertyTimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, - IProfileEditorService profileEditorService, - IPropertyTrackVmFactory propertyTrackVmFactory) - { - _profileEditorService = profileEditorService; - _propertyTrackVmFactory = propertyTrackVmFactory; - - LayerPropertiesViewModel = layerPropertiesViewModel; - PropertyTrackViewModels = new BindableCollection(); - - _profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated; - LayerPropertiesViewModel.PixelsPerSecondChanged += OnPixelsPerSecondChanged; - - Execute.PostToUIThread(() => SelectionRectangle = new RectangleGeometry()); - } - - public LayerPropertiesViewModel LayerPropertiesViewModel { get; } - - public double Width { get; set; } - public BindableCollection PropertyTrackViewModels { get; set; } - public RectangleGeometry SelectionRectangle { get; set; } - - public void Dispose() - { - _profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated; - LayerPropertiesViewModel.PixelsPerSecondChanged -= OnPixelsPerSecondChanged; - } - - public void UpdateEndTime() - { - // End time is the last keyframe + 10 sec - var lastKeyFrame = PropertyTrackViewModels.SelectMany(r => r.KeyframeViewModels).OrderByDescending(t => t.Keyframe.Position).FirstOrDefault(); - var endTime = lastKeyFrame?.Keyframe.Position.Add(new TimeSpan(0, 0, 0, 10)) ?? TimeSpan.FromSeconds(10); - - Width = endTime.TotalSeconds * LayerPropertiesViewModel.PixelsPerSecond; - - // Ensure the caret isn't outside the end time - if (_profileEditorService.CurrentTime > endTime) - _profileEditorService.CurrentTime = endTime; - } - - public void PopulateProperties(List properties) - { - var newViewModels = new List(); - foreach (var property in properties) - newViewModels.AddRange(CreateViewModels(property)); - - PropertyTrackViewModels.Clear(); - PropertyTrackViewModels.AddRange(newViewModels); - UpdateEndTime(); - } - - public void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel) - { - // Determine the index by flattening all the layer's properties - var index = layerPropertyViewModel.LayerProperty.GetFlattenedIndex(); - if (index > PropertyTrackViewModels.Count) - index = PropertyTrackViewModels.Count; - PropertyTrackViewModels.Insert(index, _propertyTrackVmFactory.Create(this, layerPropertyViewModel)); - } - - public void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel) - { - var vm = PropertyTrackViewModels.FirstOrDefault(v => v.LayerPropertyViewModel == layerPropertyViewModel); - if (vm != null) - PropertyTrackViewModels.Remove(vm); - } - - public void UpdateKeyframePositions() - { - foreach (var viewModel in PropertyTrackViewModels) - viewModel.UpdateKeyframes(LayerPropertiesViewModel.PixelsPerSecond); - - UpdateEndTime(); - } - - /// - /// Updates the time line's keyframes - /// - public void Update() - { - foreach (var viewModel in PropertyTrackViewModels) - viewModel.PopulateKeyframes(); - - UpdateEndTime(); - } - - private void OnSelectedProfileElementUpdated(object sender, ProfileElementEventArgs e) - { - Update(); - } - - private void OnPixelsPerSecondChanged(object sender, EventArgs e) - { - UpdateKeyframePositions(); - } - - private List CreateViewModels(LayerPropertyViewModel property) - { - var result = new List {_propertyTrackVmFactory.Create(this, property)}; - foreach (var child in property.Children) - result.AddRange(CreateViewModels(child)); - - return result; - } - - #region Keyframe movement - - public void MoveSelectedKeyframes(TimeSpan cursorTime) - { - // Ensure the selection rectangle doesn't show, the view isn't aware of different types of dragging - SelectionRectangle.Rect = new Rect(); - - var keyframeViewModels = PropertyTrackViewModels.SelectMany(t => t.KeyframeViewModels.OrderBy(k => k.Keyframe.Position)).ToList(); - foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected)) - keyframeViewModel.ApplyMovement(cursorTime); - - _profileEditorService.UpdateProfilePreview(); - } - - - public void ReleaseSelectedKeyframes() - { - var keyframeViewModels = PropertyTrackViewModels.SelectMany(t => t.KeyframeViewModels.OrderBy(k => k.Keyframe.Position)).ToList(); - foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected)) - keyframeViewModel.ReleaseMovement(); - } - - #endregion - - #region Keyframe selection - - private Point _mouseDragStartPoint; - private bool _mouseDragging; - - // ReSharper disable once UnusedMember.Global - Called from view - public void TimelineCanvasMouseDown(object sender, MouseButtonEventArgs e) - { - if (e.LeftButton == MouseButtonState.Released) - return; - - ((IInputElement) sender).CaptureMouse(); - - SelectionRectangle.Rect = new Rect(); - _mouseDragStartPoint = e.GetPosition((IInputElement) sender); - _mouseDragging = true; - e.Handled = true; - } - - // ReSharper disable once UnusedMember.Global - Called from view - public void TimelineCanvasMouseUp(object sender, MouseEventArgs e) - { - if (!_mouseDragging) - return; - - var position = e.GetPosition((IInputElement) sender); - var selectedRect = new Rect(_mouseDragStartPoint, position); - SelectionRectangle.Rect = selectedRect; - - var selectedKeyframes = HitTestUtilities.GetHitViewModels((Visual) sender, SelectionRectangle); - var keyframeViewModels = PropertyTrackViewModels.SelectMany(t => t.KeyframeViewModels.OrderBy(k => k.Keyframe.Position)).ToList(); - foreach (var keyframeViewModel in keyframeViewModels) - keyframeViewModel.IsSelected = selectedKeyframes.Contains(keyframeViewModel); - - _mouseDragging = false; - e.Handled = true; - ((IInputElement) sender).ReleaseMouseCapture(); - } - - public void TimelineCanvasMouseMove(object sender, MouseEventArgs e) - { - if (_mouseDragging && e.LeftButton == MouseButtonState.Pressed) - { - var position = e.GetPosition((IInputElement) sender); - var selectedRect = new Rect(_mouseDragStartPoint, position); - SelectionRectangle.Rect = selectedRect; - e.Handled = true; - } - } - - public void SelectKeyframe(PropertyTrackKeyframeViewModel clicked, bool selectBetween, bool toggle) - { - var keyframeViewModels = PropertyTrackViewModels.SelectMany(t => t.KeyframeViewModels.OrderBy(k => k.Keyframe.Position)).ToList(); - if (selectBetween) - { - var selectedIndex = keyframeViewModels.FindIndex(k => k.IsSelected); - // If nothing is selected, select only the clicked - if (selectedIndex == -1) - { - clicked.IsSelected = true; - return; - } - - foreach (var keyframeViewModel in keyframeViewModels) - keyframeViewModel.IsSelected = false; - - var clickedIndex = keyframeViewModels.IndexOf(clicked); - if (clickedIndex < selectedIndex) - { - foreach (var keyframeViewModel in keyframeViewModels.Skip(clickedIndex).Take(selectedIndex - clickedIndex + 1)) - keyframeViewModel.IsSelected = true; - } - else - { - foreach (var keyframeViewModel in keyframeViewModels.Skip(selectedIndex).Take(clickedIndex - selectedIndex + 1)) - keyframeViewModel.IsSelected = true; - } - } - else if (toggle) - { - // Toggle only the clicked keyframe, leave others alone - clicked.IsSelected = !clicked.IsSelected; - } - else - { - // Only select the clicked keyframe - foreach (var keyframeViewModel in keyframeViewModels) - keyframeViewModel.IsSelected = false; - clicked.IsSelected = true; - } - } - - #endregion - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackEasingViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackEasingViewModel.cs deleted file mode 100644 index c1fcebd0e..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackEasingViewModel.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Windows; -using System.Windows.Media; -using Artemis.Core.Utilities; -using Humanizer; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline -{ - public class PropertyTrackEasingViewModel : PropertyChangedBase - { - private readonly PropertyTrackKeyframeViewModel _keyframeViewModel; - private bool _isEasingModeSelected; - - public PropertyTrackEasingViewModel(PropertyTrackKeyframeViewModel keyframeViewModel, Easings.Functions easingFunction) - { - _keyframeViewModel = keyframeViewModel; - _isEasingModeSelected = keyframeViewModel.Keyframe.EasingFunction == easingFunction; - - EasingFunction = easingFunction; - Description = easingFunction.Humanize(); - - CreateGeometry(); - } - - public Easings.Functions EasingFunction { get; } - public PointCollection EasingPoints { get; set; } - public string Description { get; set; } - - public bool IsEasingModeSelected - { - get => _isEasingModeSelected; - set - { - _isEasingModeSelected = value; - if (_isEasingModeSelected) - _keyframeViewModel.SelectEasingMode(this); - } - } - - private void CreateGeometry() - { - EasingPoints = new PointCollection(); - for (var i = 1; i <= 10; i++) - { - var x = i; - var y = Easings.Interpolate(i / 10.0, EasingFunction) * 10; - EasingPoints.Add(new Point(x, y)); - } - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackKeyframeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackKeyframeViewModel.cs deleted file mode 100644 index a4f0d692c..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackKeyframeViewModel.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.Linq; -using System.Windows; -using System.Windows.Input; -using Artemis.Core.Models.Profile.LayerProperties; -using Artemis.Core.Utilities; -using Artemis.UI.Services.Interfaces; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline -{ - public class PropertyTrackKeyframeViewModel : PropertyTrackKeyframeViewModel - { - private readonly IProfileEditorService _profileEditorService; - private int _pixelsPerSecond; - - public PropertyTrackKeyframeViewModel(PropertyTrackViewModel propertyTrackViewModel, LayerPropertyKeyframe keyframe, IProfileEditorService profileEditorService) - { - _profileEditorService = profileEditorService; - - PropertyTrackViewModel = propertyTrackViewModel; - Keyframe = keyframe; - EasingViewModels = new BindableCollection(); - CreateEasingViewModels(); - } - - public bool IsSelected { get; set; } - public PropertyTrackViewModel PropertyTrackViewModel { get; } - public LayerPropertyKeyframe Keyframe { get; } - public BindableCollection EasingViewModels { get; set; } - public double X { get; set; } - public string Timestamp { get; set; } - - public UIElement ParentView { get; set; } - - - public void Update(int pixelsPerSecond) - { - _pixelsPerSecond = pixelsPerSecond; - - X = pixelsPerSecond * Keyframe.Position.TotalSeconds; - Timestamp = $"{Math.Floor(Keyframe.Position.TotalSeconds):00}.{Keyframe.Position.Milliseconds:000}"; - } - - #region Keyframe movement - - public void KeyframeMouseDown(object sender, MouseButtonEventArgs e) - { - if (e.LeftButton == MouseButtonState.Released) - return; - - ((IInputElement) sender).CaptureMouse(); - if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift) && !IsSelected) - PropertyTrackViewModel.PropertyTimelineViewModel.SelectKeyframe(this, true, false); - else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) - PropertyTrackViewModel.PropertyTimelineViewModel.SelectKeyframe(this, false, true); - else if (!IsSelected) - PropertyTrackViewModel.PropertyTimelineViewModel.SelectKeyframe(this, false, false); - - e.Handled = true; - } - - public void KeyframeMouseUp(object sender, MouseButtonEventArgs e) - { - _profileEditorService.UpdateSelectedProfileElement(); - PropertyTrackViewModel.PropertyTimelineViewModel.ReleaseSelectedKeyframes(); - - ((IInputElement) sender).ReleaseMouseCapture(); - } - - public void KeyframeMouseMove(object sender, MouseEventArgs e) - { - if (e.LeftButton == MouseButtonState.Pressed) - PropertyTrackViewModel.PropertyTimelineViewModel.MoveSelectedKeyframes(GetCursorTime(e.GetPosition(ParentView))); - - e.Handled = true; - } - - private TimeSpan GetCursorTime(Point position) - { - // Get the parent grid, need that for our position - var x = Math.Max(0, position.X); - var time = TimeSpan.FromSeconds(x / _pixelsPerSecond); - - // Round the time to something that fits the current zoom level - if (_pixelsPerSecond < 200) - time = TimeSpan.FromMilliseconds(Math.Round(time.TotalMilliseconds / 5.0) * 5.0); - else if (_pixelsPerSecond < 500) - time = TimeSpan.FromMilliseconds(Math.Round(time.TotalMilliseconds / 2.0) * 2.0); - else - time = TimeSpan.FromMilliseconds(Math.Round(time.TotalMilliseconds)); - - // If shift is held, snap to the current time - // Take a tolerance of 5 pixels (half a keyframe width) - if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) - { - var tolerance = 1000f / _pixelsPerSecond * 5; - if (Math.Abs(_profileEditorService.CurrentTime.TotalMilliseconds - time.TotalMilliseconds) < tolerance) - time = _profileEditorService.CurrentTime; - } - - return time; - } - - #endregion - - #region Context menu actions - - public void Copy() - { - var keyframe = PropertyTrackViewModel.LayerPropertyViewModel.LayerProperty.CreateNewKeyframe(Keyframe.Position, Keyframe.BaseValue); - keyframe.EasingFunction = Keyframe.EasingFunction; - _profileEditorService.UpdateSelectedProfileElement(); - } - - public void Delete() - { - PropertyTrackViewModel.LayerPropertyViewModel.LayerProperty.RemoveKeyframe(Keyframe); - _profileEditorService.UpdateSelectedProfileElement(); - } - - #endregion - - #region Easing - - private void CreateEasingViewModels() - { - EasingViewModels.AddRange(Enum.GetValues(typeof(Easings.Functions)).Cast().Select(v => new PropertyTrackEasingViewModel(this, v))); - } - - public void SelectEasingMode(PropertyTrackEasingViewModel easingViewModel) - { - Keyframe.EasingFunction = easingViewModel.EasingFunction; - // Set every selection to false except on the VM that made the change - foreach (var propertyTrackEasingViewModel in EasingViewModels.Where(vm => vm != easingViewModel)) - propertyTrackEasingViewModel.IsEasingModeSelected = false; - - _profileEditorService.UpdateSelectedProfileElement(); - } - - #endregion - - #region Movement - - private bool _movementReleased = true; - private TimeSpan _startOffset; - - public void ApplyMovement(TimeSpan cursorTime) - { - if (_movementReleased) - { - _movementReleased = false; - _startOffset = cursorTime - Keyframe.Position; - } - else - { - Keyframe.Position = cursorTime - _startOffset; - if (Keyframe.Position < TimeSpan.Zero) - Keyframe.Position = TimeSpan.Zero; - - Update(_pixelsPerSecond); - } - } - - public void ReleaseMovement() - { - _movementReleased = true; - } - - #endregion - } - - public abstract class PropertyTrackKeyframeViewModel : PropertyChangedBase - { - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackView.xaml deleted file mode 100644 index 497e47dff..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackView.xaml +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackViewModel.cs deleted file mode 100644 index 5c62a5cb5..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackViewModel.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Artemis.UI.Ninject.Factories; -using Stylet; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline -{ - public class PropertyTrackViewModel : Screen - { - private readonly IPropertyTrackKeyframeVmFactory _propertyTrackKeyframeVmFactory; - - public PropertyTrackViewModel(PropertyTimelineViewModel propertyTimelineViewModel, LayerPropertyViewModel layerPropertyViewModel, - IPropertyTrackKeyframeVmFactory propertyTrackKeyframeVmFactory) - { - _propertyTrackKeyframeVmFactory = propertyTrackKeyframeVmFactory; - PropertyTimelineViewModel = propertyTimelineViewModel; - LayerPropertyViewModel = layerPropertyViewModel; - KeyframeViewModels = new BindableCollection(); - - PopulateKeyframes(); - UpdateKeyframes(PropertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond); - - LayerPropertyViewModel.ExpandedStateChanged += (sender, args) => UpdateMustDisplay(); - LayerPropertyViewModel.LayerProperty.VisibilityChanged += (sender, args) => UpdateMustDisplay(); - UpdateMustDisplay(); - } - - - public PropertyTimelineViewModel PropertyTimelineViewModel { get; } - public LayerPropertyViewModel LayerPropertyViewModel { get; } - public BindableCollection KeyframeViewModels { get; set; } - public bool MustDisplay { get; set; } - - private void UpdateMustDisplay() - { - var expandedTest = LayerPropertyViewModel.Parent; - while (expandedTest != null) - { - if (!expandedTest.IsExpanded) - { - MustDisplay = false; - return; - } - expandedTest = expandedTest.Parent; - } - - var visibilityTest = LayerPropertyViewModel.LayerProperty; - while (visibilityTest != null) - { - if (visibilityTest.IsHidden) - { - MustDisplay = false; - return; - } - visibilityTest = visibilityTest.Parent; - } - - MustDisplay = true; - } - - public void PopulateKeyframes() - { - // Remove old keyframes - KeyframeViewModels.RemoveRange(KeyframeViewModels.ToList().Where(vm => !LayerPropertyViewModel.LayerProperty.UntypedKeyframes.Contains(vm.Keyframe))); - - // Add new keyframes - KeyframeViewModels.AddRange( - LayerPropertyViewModel.LayerProperty.UntypedKeyframes - .Where(k => KeyframeViewModels.All(vm => vm.Keyframe != k)) - .Select(k => _propertyTrackKeyframeVmFactory.Create(this, k)) - ); - UpdateKeyframes(PropertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond); - } - - public void UpdateKeyframes(int pixelsPerSecond) - { - foreach (var keyframeViewModel in KeyframeViewModels) - { - keyframeViewModel.ParentView = View; - keyframeViewModel.Update(pixelsPerSecond); - } - } - - protected override void OnViewLoaded() - { - foreach (var keyframeViewModel in KeyframeViewModels) - keyframeViewModel.ParentView = View; - base.OnViewLoaded(); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyGroupViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyGroupViewModel.cs new file mode 100644 index 000000000..69994652f --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyGroupViewModel.cs @@ -0,0 +1,14 @@ +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline +{ + public class TimelinePropertyGroupViewModel + { + public TimelinePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel) + { + LayerPropertyGroupViewModel = (LayerPropertyGroupViewModel) layerPropertyBaseViewModel; + } + + public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs new file mode 100644 index 000000000..b675b107d --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs @@ -0,0 +1,30 @@ +using System; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline +{ + public class TimelinePropertyViewModel : TimelinePropertyViewModel + { + public TimelinePropertyViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel) : base(layerPropertyBaseViewModel) + { + LayerPropertyViewModel = (LayerPropertyViewModel) layerPropertyBaseViewModel; + } + + public LayerPropertyViewModel LayerPropertyViewModel { get; } + + public override void Dispose() + { + } + } + + public abstract class TimelinePropertyViewModel : IDisposable + { + protected TimelinePropertyViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel) + { + LayerPropertyBaseViewModel = layerPropertyBaseViewModel; + } + + public LayerPropertyBaseViewModel LayerPropertyBaseViewModel { get; } + public abstract void Dispose(); + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs new file mode 100644 index 000000000..865d49a00 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs @@ -0,0 +1,14 @@ +using Stylet; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline +{ + public class TimelineViewModel + { + public TimelineViewModel(BindableCollection layerPropertyGroups) + { + LayerPropertyGroups = layerPropertyGroups; + } + + public BindableCollection LayerPropertyGroups { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/BrushPropertyInputView.xaml similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/BrushPropertyInputView.xaml diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/BrushPropertyInputViewModel.cs similarity index 89% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputViewModel.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/BrushPropertyInputViewModel.cs index 79c472350..2eb194bb1 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/BrushPropertyInputViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/BrushPropertyInputViewModel.cs @@ -5,18 +5,20 @@ using Artemis.Core.Events; using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Services.Interfaces; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput; using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Utilities; using Stylet; namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput { - public class BrushPropertyInputViewModel : PropertyInputViewModel + public class BrushPropertyInputViewModel : PropertyInputViewModel { private readonly ILayerService _layerService; private readonly IPluginService _pluginService; - public BrushPropertyInputViewModel(IProfileEditorService profileEditorService, ILayerService layerService, IPluginService pluginService) : base(profileEditorService) + public BrushPropertyInputViewModel(LayerPropertyViewModel layerPropertyViewModel, ILayerService layerService, IPluginService pluginService) + : base(layerPropertyViewModel) { _layerService = layerService; _pluginService = pluginService; @@ -26,9 +28,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P } public BindableCollection EnumValues { get; } - - public sealed override List CompatibleTypes { get; } = new List {typeof(LayerBrushReference)}; - + public LayerBrushReference BrushInputValue { get => (LayerBrushReference) InputValue; diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/ColorGradientPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/ColorGradientPropertyInputView.xaml similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/ColorGradientPropertyInputView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/ColorGradientPropertyInputView.xaml diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/ColorGradientPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/ColorGradientPropertyInputViewModel.cs similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/ColorGradientPropertyInputViewModel.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/ColorGradientPropertyInputViewModel.cs diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/EnumPropertyInputView.xaml similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/EnumPropertyInputView.xaml diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/EnumPropertyInputViewModel.cs similarity index 76% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputViewModel.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/EnumPropertyInputViewModel.cs index f1e1d7932..2134ab5ea 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/EnumPropertyInputViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/EnumPropertyInputViewModel.cs @@ -18,7 +18,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P public object EnumInputValue { - get => InputValue ?? Enum.GetValues(LayerPropertyViewModel.LayerProperty.Type).Cast().First(); + get => InputValue ?? Enum.GetValues(GetLayerPropertyEnumType()).Cast().First(); set => InputValue = value; } @@ -29,7 +29,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P protected override void OnInitialized() { - EnumValues = EnumUtilities.GetAllValuesAndDescriptions(LayerPropertyViewModel.LayerProperty.Type); + EnumValues = EnumUtilities.GetAllValuesAndDescriptions(GetLayerPropertyEnumType()); + } + + + private Type GetLayerPropertyEnumType() + { + return LayerPropertyViewModel.BaseLayerProperty.GetType().GetGenericTypeDefinition(); } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/FloatPropertyInputView.xaml similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/FloatPropertyInputView.xaml diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/FloatPropertyInputViewModel.cs similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/FloatPropertyInputViewModel.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/FloatPropertyInputViewModel.cs diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/IntPropertyInputView.xaml similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/IntPropertyInputView.xaml diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/IntPropertyInputViewModel.cs similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/IntPropertyInputViewModel.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/IntPropertyInputViewModel.cs diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/PropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/PropertyInputViewModel.cs new file mode 100644 index 000000000..b24885717 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/PropertyInputViewModel.cs @@ -0,0 +1,51 @@ +using System; +using Stylet; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput +{ + public abstract class PropertyInputViewModel : PropertyChangedBase, IDisposable + { + protected PropertyInputViewModel(LayerPropertyViewModel layerPropertyViewModel) + { + LayerPropertyViewModel = layerPropertyViewModel; + LayerPropertyViewModel.LayerProperty.Updated += LayerPropertyOnUpdated; + } + + public LayerPropertyViewModel LayerPropertyViewModel { get; } + + public bool InputDragging { get; private set; } + + protected T InputValue + { + get => LayerPropertyViewModel.LayerProperty.CurrentValue; + set => LayerPropertyViewModel.SetCurrentValue(value, !InputDragging); + } + + public abstract void Update(); + + private void LayerPropertyOnUpdated(object? sender, EventArgs e) + { + Update(); + } + + #region Event handlers + + public void InputDragStarted(object sender, EventArgs e) + { + InputDragging = true; + } + + public void InputDragEnded(object sender, EventArgs e) + { + InputDragging = false; + LayerPropertyViewModel.ProfileEditorService.UpdateSelectedProfileElement(); + } + + #endregion + + public void Dispose() + { + LayerPropertyViewModel.LayerProperty.Updated -= LayerPropertyOnUpdated; + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKColorPropertyInputView.xaml similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKColorPropertyInputView.xaml diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKColorPropertyInputViewModel.cs similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKColorPropertyInputViewModel.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKColorPropertyInputViewModel.cs diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKPointPropertyInputView.xaml similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKPointPropertyInputView.xaml diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKPointPropertyInputViewModel.cs similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKPointPropertyInputViewModel.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKPointPropertyInputViewModel.cs diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKSizePropertyInputView.xaml similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKSizePropertyInputView.xaml diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKSizePropertyInputViewModel.cs similarity index 100% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyInput/SKSizePropertyInputViewModel.cs rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/PropertyInput/SKSizePropertyInputViewModel.cs diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs new file mode 100644 index 000000000..fcf625ceb --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs @@ -0,0 +1,14 @@ +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree +{ + public class TreePropertyGroupViewModel + { + public TreePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel) + { + LayerPropertyGroupViewModel = (LayerPropertyGroupViewModel)layerPropertyBaseViewModel; + } + + public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyViewModel.cs new file mode 100644 index 000000000..fc791154a --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreePropertyViewModel.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Artemis.Core.Models.Profile; +using Artemis.UI.Exceptions; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree.PropertyInput; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree +{ + public class TreePropertyViewModel : TreePropertyViewModel + { + public TreePropertyViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel) : base(layerPropertyBaseViewModel) + { + LayerPropertyViewModel = (LayerPropertyViewModel) layerPropertyBaseViewModel; + PropertyInputViewModel = CreatePropertyInputViewModel(); + } + + public LayerPropertyViewModel LayerPropertyViewModel { get; } + public PropertyInputViewModel PropertyInputViewModel { get; set; } + + public override void Dispose() + { + PropertyInputViewModel.Dispose(); + } + + private PropertyInputViewModel CreatePropertyInputViewModel() + { + if (!IsPropertySupported(typeof(T))) + throw new ArtemisUIException($"Failed to create a property input view model, type {typeof(T).Name} is not supported."); + + return (PropertyInputViewModel) Activator.CreateInstance(SupportedTypes[typeof(T)], this); + } + } + + public abstract class TreePropertyViewModel : IDisposable + { + public static ReadOnlyDictionary SupportedTypes = new ReadOnlyDictionary(new Dictionary + { + {typeof(LayerBrushReference), typeof(BrushPropertyInputViewModel)}, + {typeof(LayerBrushReference), typeof(BrushPropertyInputViewModel)}, + {typeof(LayerBrushReference), typeof(BrushPropertyInputViewModel)}, + {typeof(LayerBrushReference), typeof(BrushPropertyInputViewModel)} + }); + + public static void RegisterPropertyInputViewModel() + { + + } + + public static bool IsPropertySupported(Type type) + { + return SupportedTypes.ContainsKey(type); + } + + protected TreePropertyViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel) + { + LayerPropertyBaseViewModel = layerPropertyBaseViewModel; + } + + public LayerPropertyBaseViewModel LayerPropertyBaseViewModel { get; } + public abstract void Dispose(); + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeView.xaml similarity index 78% rename from src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeView.xaml rename to src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeView.xaml index cfb33f63b..41bb9c831 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeView.xaml @@ -1,14 +1,16 @@ - + d:DesignHeight="450" d:DesignWidth="800" + d:DataContext="{d:DesignInstance {x:Type local:TreeViewModel}}"> - - - + - - - - + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs new file mode 100644 index 000000000..14723722e --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs @@ -0,0 +1,14 @@ +using Stylet; + +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree +{ + public class TreeViewModel + { + public TreeViewModel(BindableCollection layerPropertyGroups) + { + LayerPropertyGroups = layerPropertyGroups; + } + + public BindableCollection LayerPropertyGroups { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeView.xaml index 7bc5e82cc..cfb383c9a 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeView.xaml @@ -25,7 +25,7 @@ - + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs index b023d3cad..7138ecdc9 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs @@ -122,9 +122,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem if (!SupportsChildren) throw new ArtemisUIException("Cannot add a layer to a profile element of type " + ProfileElement.GetType().Name); - var layer = new Layer(ProfileElement.Profile, ProfileElement, "New layer"); - foreach (var baseLayerProperty in layer.Properties) - _layerService.InstantiateKeyframeEngine(baseLayerProperty); + var layer = _layerService.CreateLayer(ProfileElement.Profile, ProfileElement, "New layer"); ProfileElement.AddChild(layer); UpdateProfileElements(); _profileEditorService.UpdateSelectedProfile(); @@ -174,7 +172,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem } // Ensure every child element has an up-to-date VM - if (ProfileElement.Children == null) + if (ProfileElement.Children == null) return; var newChildren = new List(); @@ -192,7 +190,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem } } - if (!newChildren.Any()) + if (!newChildren.Any()) return; // Add the new children in one call, prevent extra UI events diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs index 2994814ce..66eaaec3e 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/Tools/EditToolViewModel.cs @@ -94,15 +94,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools difference += 360; else if (difference > 350) difference -= 360; - newRotation = layer.Properties.Rotation.CurrentValue + difference; + + newRotation = layer.Transform.Rotation.CurrentValue + difference; // Round the end-result to increments of 5 as well, to avoid staying on an offset if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) newRotation = (float) Math.Round(newRotation / 5f) * 5f; else newRotation = (float) Math.Round(newRotation, 2, MidpointRounding.AwayFromZero); - - layer.Properties.Rotation.SetCurrentValue(newRotation, ProfileEditorService.CurrentTime); + layer.Transform.Rotation.SetCurrentValue(newRotation, ProfileEditorService.CurrentTime); ProfileEditorService.UpdateProfilePreview(); } @@ -121,7 +121,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools var dragStart = GetRelativePosition(sender, e.MouseEventArgs).ToSKPoint(); _dragOffset = _layerEditorService.GetDragOffset(layer, dragStart); _dragStart = dragStart + _dragOffset; - _dragStartScale = layer.Properties.Scale.CurrentValue; + _dragStartScale = layer.Transform.Scale.CurrentValue; _isResizing = true; } @@ -159,19 +159,19 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools break; case ShapeControlPoint.TopCenter: height = VerticalResize(layer, position, ResizeOrigin.Top); - width = layer.Properties.Scale.CurrentValue.Width; + width = layer.Transform.Scale.CurrentValue.Width; break; case ShapeControlPoint.RightCenter: width = HorizontalResize(layer, position, ResizeOrigin.Right); - height = layer.Properties.Scale.CurrentValue.Height; + height = layer.Transform.Scale.CurrentValue.Height; break; case ShapeControlPoint.BottomCenter: - width = layer.Properties.Scale.CurrentValue.Width; + width = layer.Transform.Scale.CurrentValue.Width; height = VerticalResize(layer, position, ResizeOrigin.Bottom); break; case ShapeControlPoint.LeftCenter: width = HorizontalResize(layer, position, ResizeOrigin.Left); - height = layer.Properties.Scale.CurrentValue.Height; + height = layer.Transform.Scale.CurrentValue.Height; break; default: throw new ArgumentOutOfRangeException(); @@ -186,7 +186,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools height = (float) Math.Round(1.0 / bounds.Height * smallestSide, 2, MidpointRounding.AwayFromZero); } - layer.Properties.Scale.SetCurrentValue(new SKSize(width, height), ProfileEditorService.CurrentTime); + layer.Transform.Scale.SetCurrentValue(new SKSize(width, height), ProfileEditorService.CurrentTime); ProfileEditorService.UpdateProfilePreview(); } @@ -319,7 +319,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools // Scale down the resulting position and make it relative var scaled = _layerEditorService.GetScaledPoint(layer, position, true); // Round and update the position property - layer.Properties.Position.SetCurrentValue(RoundPoint(scaled, 3), ProfileEditorService.CurrentTime); + layer.Transform.Position.SetCurrentValue(RoundPoint(scaled, 3), ProfileEditorService.CurrentTime); ProfileEditorService.UpdateProfilePreview(); } @@ -338,13 +338,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools var scaled = _layerEditorService.GetScaledPoint(layer, countered[1], false); // Update the anchor point, this causes the shape to move - layer.Properties.AnchorPoint.SetCurrentValue(RoundPoint(scaled, 3), ProfileEditorService.CurrentTime); + layer.Transform.AnchorPoint.SetCurrentValue(RoundPoint(scaled, 3), ProfileEditorService.CurrentTime); // TopLeft is not updated yet and acts as a snapshot of the top-left before changing the anchor var path = _layerEditorService.GetLayerPath(layer, true, true, true); // Calculate the (scaled) difference between the old and now position var difference = _layerEditorService.GetScaledPoint(layer, _topLeft - path.Points[0], false); // Apply the difference so that the shape effectively stays in place - layer.Properties.Position.SetCurrentValue(RoundPoint(layer.Properties.Position.CurrentValue + difference, 3), ProfileEditorService.CurrentTime); + layer.Transform.Position.SetCurrentValue(RoundPoint(layer.Transform.Position.CurrentValue + difference, 3), ProfileEditorService.CurrentTime); ProfileEditorService.UpdateProfilePreview(); } @@ -362,9 +362,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools { var counterRotatePath = new SKPath(); counterRotatePath.AddPoly(skPoints, false); - counterRotatePath.Transform(SKMatrix.MakeRotationDegrees(layer.Properties.Rotation.CurrentValue * -1, pivot.X, pivot.Y)); + counterRotatePath.Transform(SKMatrix.MakeRotationDegrees(layer.Transform.Rotation.CurrentValue * -1, pivot.X, pivot.Y)); if (includeScale) - counterRotatePath.Transform(SKMatrix.MakeScale(1f / (layer.Properties.Scale.CurrentValue.Width / 100f), 1f / (layer.Properties.Scale.CurrentValue.Height / 100f))); + counterRotatePath.Transform(SKMatrix.MakeScale(1f / (layer.Transform.Scale.CurrentValue.Width / 100f), 1f / (layer.Transform.Scale.CurrentValue.Height / 100f))); return counterRotatePath.Points; } diff --git a/src/Artemis.UI/Services/Interfaces/IProfileEditorService.cs b/src/Artemis.UI/Services/Interfaces/IProfileEditorService.cs index 453979079..585276011 100644 --- a/src/Artemis.UI/Services/Interfaces/IProfileEditorService.cs +++ b/src/Artemis.UI/Services/Interfaces/IProfileEditorService.cs @@ -1,7 +1,10 @@ using System; using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; using Artemis.Core.Plugins.Abstract; using Artemis.UI.Events; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; namespace Artemis.UI.Services.Interfaces { @@ -11,6 +14,7 @@ namespace Artemis.UI.Services.Interfaces ProfileElement SelectedProfileElement { get; } TimeSpan CurrentTime { get; set; } + LayerPropertyBaseViewModel CreateLayerPropertyViewModel(BaseLayerProperty baseLayerProperty, PropertyDescriptionAttribute propertyDescription); void ChangeSelectedProfile(Profile profile); void UpdateSelectedProfile(); void ChangeSelectedProfileElement(ProfileElement profileElement); @@ -18,6 +22,8 @@ namespace Artemis.UI.Services.Interfaces void UpdateProfilePreview(); void UndoUpdateProfile(ProfileModule module); void RedoUpdateProfile(ProfileModule module); + void StopRegularRender(); + void ResumeRegularRender(); /// /// Occurs when a new profile is selected @@ -48,8 +54,5 @@ namespace Artemis.UI.Services.Interfaces /// Occurs when the profile preview has been updated /// event EventHandler ProfilePreviewUpdated; - - void StopRegularRender(); - void ResumeRegularRender(); } } \ No newline at end of file diff --git a/src/Artemis.UI/Services/LayerEditorService.cs b/src/Artemis.UI/Services/LayerEditorService.cs index 83c654db3..57a405fd5 100644 --- a/src/Artemis.UI/Services/LayerEditorService.cs +++ b/src/Artemis.UI/Services/LayerEditorService.cs @@ -35,7 +35,7 @@ namespace Artemis.UI.Services public Point GetLayerAnchorPosition(Layer layer, SKPoint? positionOverride = null) { var layerBounds = GetLayerBounds(layer).ToSKRect(); - var positionProperty = layer.Properties.Position.CurrentValue; + var positionProperty = layer.Transform.Position.CurrentValue; if (positionOverride != null) positionProperty = positionOverride.Value; @@ -59,7 +59,7 @@ namespace Artemis.UI.Services // the layer using the structure of the XAML while the Core has to deal with that by applying the layer // position to the translation var anchorPosition = GetLayerAnchorPosition(layer); - var anchorProperty = layer.Properties.AnchorPoint.CurrentValue; + var anchorProperty = layer.Transform.AnchorPoint.CurrentValue; // Translation originates from the unscaled center of the shape and is tied to the anchor var x = anchorPosition.X - layerBounds.MidX - anchorProperty.X * layerBounds.Width; @@ -67,8 +67,8 @@ namespace Artemis.UI.Services var transformGroup = new TransformGroup(); transformGroup.Children.Add(new TranslateTransform(x, y)); - transformGroup.Children.Add(new ScaleTransform(layer.Properties.Scale.CurrentValue.Width / 100f, layer.Properties.Scale.CurrentValue.Height / 100f, anchorPosition.X, anchorPosition.Y)); - transformGroup.Children.Add(new RotateTransform(layer.Properties.Rotation.CurrentValue, anchorPosition.X, anchorPosition.Y)); + transformGroup.Children.Add(new ScaleTransform(layer.Transform.Scale.CurrentValue.Width / 100f, layer.Transform.Scale.CurrentValue.Height / 100f, anchorPosition.X, anchorPosition.Y)); + transformGroup.Children.Add(new RotateTransform(layer.Transform.Rotation.CurrentValue, anchorPosition.X, anchorPosition.Y)); return transformGroup; } @@ -83,7 +83,7 @@ namespace Artemis.UI.Services if (anchorOverride != null) anchorPosition = anchorOverride.Value; - var anchorProperty = layer.Properties.AnchorPoint.CurrentValue; + var anchorProperty = layer.Transform.AnchorPoint.CurrentValue; // Translation originates from the unscaled center of the shape and is tied to the anchor var x = anchorPosition.X - layerBounds.MidX - anchorProperty.X * layerBounds.Width; @@ -94,9 +94,9 @@ namespace Artemis.UI.Services if (includeTranslation) path.Transform(SKMatrix.MakeTranslation(x, y)); if (includeScale) - path.Transform(SKMatrix.MakeScale(layer.Properties.Scale.CurrentValue.Width / 100f, layer.Properties.Scale.CurrentValue.Height / 100f, anchorPosition.X, anchorPosition.Y)); + path.Transform(SKMatrix.MakeScale(layer.Transform.Scale.CurrentValue.Width / 100f, layer.Transform.Scale.CurrentValue.Height / 100f, anchorPosition.X, anchorPosition.Y)); if (includeRotation) - path.Transform(SKMatrix.MakeRotationDegrees(layer.Properties.Rotation.CurrentValue, anchorPosition.X, anchorPosition.Y)); + path.Transform(SKMatrix.MakeRotationDegrees(layer.Transform.Rotation.CurrentValue, anchorPosition.X, anchorPosition.Y)); return path; } diff --git a/src/Artemis.UI/Services/ProfileEditorService.cs b/src/Artemis.UI/Services/ProfileEditorService.cs index 19c497b38..fe3e7a871 100644 --- a/src/Artemis.UI/Services/ProfileEditorService.cs +++ b/src/Artemis.UI/Services/ProfileEditorService.cs @@ -1,11 +1,20 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties; +using Artemis.Core.Models.Profile.LayerProperties.Attributes; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Storage.Interfaces; using Artemis.UI.Events; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract; +using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Tree; using Artemis.UI.Services.Interfaces; +using Ninject; +using Ninject.Parameters; namespace Artemis.UI.Services { @@ -13,15 +22,21 @@ namespace Artemis.UI.Services { private readonly ICoreService _coreService; private readonly IProfileService _profileService; + private readonly IKernel _kernel; + private readonly List _registeredProfileEditors; private TimeSpan _currentTime; private TimeSpan _lastUpdateTime; - public ProfileEditorService(ICoreService coreService, IProfileService profileService) + public ProfileEditorService(ICoreService coreService, IProfileService profileService, IKernel kernel) { _coreService = coreService; _profileService = profileService; + _kernel = kernel; + _registeredProfileEditors = new List(); } + public ReadOnlyCollection RegisteredPropertyEditors => _registeredProfileEditors.AsReadOnly(); + public Profile SelectedProfile { get; private set; } public ProfileElement SelectedProfileElement { get; private set; } @@ -38,6 +53,23 @@ namespace Artemis.UI.Services } } + public LayerPropertyBaseViewModel CreateLayerPropertyViewModel(BaseLayerProperty baseLayerProperty, PropertyDescriptionAttribute propertyDescription) + { + // Go through the pain of instantiating a generic type VM now via reflection to make things a lot simpler down the line + var genericType = baseLayerProperty.GetType().GetGenericArguments()[0]; + // Only create entries for types supported by a tree input VM + if (!TreePropertyViewModel.IsPropertySupported(genericType)) + return null; + var genericViewModel = typeof(LayerPropertyViewModel<>).MakeGenericType(genericType); + var parameters = new IParameter[] + { + new ConstructorArgument("layerProperty", baseLayerProperty), + new ConstructorArgument("propertyDescription", propertyDescription) + }; + + return (LayerPropertyBaseViewModel) _kernel.Get(genericViewModel, parameters); + } + public void ChangeSelectedProfile(Profile profile) { ChangeSelectedProfileElement(null); diff --git a/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrushProperties.cs b/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrushProperties.cs index c76fd5bbe..0dca4b77e 100644 --- a/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrushProperties.cs +++ b/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrushProperties.cs @@ -35,7 +35,7 @@ namespace Artemis.Plugins.LayerBrushes.Color GradientType.BaseValueChanged += GradientTypeOnBaseValueChanged; } - private void GradientTypeOnBaseValueChanged(object? sender, EventArgs e) + private void GradientTypeOnBaseValueChanged(object sender, EventArgs e) { Color.IsHidden = GradientType.BaseValue != LayerBrushes.Color.GradientType.Solid; Gradient.IsHidden = GradientType.BaseValue == LayerBrushes.Color.GradientType.Solid; diff --git a/src/Plugins/Artemis.Plugins.LayerBrushes.Noise/NoiseBrushProperties.cs b/src/Plugins/Artemis.Plugins.LayerBrushes.Noise/NoiseBrushProperties.cs index 89f5f6790..d01cfa509 100644 --- a/src/Plugins/Artemis.Plugins.LayerBrushes.Noise/NoiseBrushProperties.cs +++ b/src/Plugins/Artemis.Plugins.LayerBrushes.Noise/NoiseBrushProperties.cs @@ -57,7 +57,7 @@ namespace Artemis.Plugins.LayerBrushes.Noise ColorType.BaseValueChanged += ColorTypeOnBaseValueChanged; } - private void ColorTypeOnBaseValueChanged(object? sender, EventArgs e) + private void ColorTypeOnBaseValueChanged(object sender, EventArgs e) { GradientColor.IsHidden = ColorType.BaseValue != ColorMappingType.Gradient; MainColor.IsHidden = ColorType.BaseValue != ColorMappingType.Simple;