mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-01-01 02:03:32 +00:00
UI - Restructured layer property VMs
This commit is contained in:
parent
41b3c77210
commit
54081b591b
@ -125,7 +125,7 @@ namespace Artemis.Core.Models.Profile
|
|||||||
|
|
||||||
General.ApplyToEntity();
|
General.ApplyToEntity();
|
||||||
Transform.ApplyToEntity();
|
Transform.ApplyToEntity();
|
||||||
LayerBrush.ApplyToEntity();
|
LayerBrush.BaseProperties.ApplyToEntity();
|
||||||
|
|
||||||
// LEDs
|
// LEDs
|
||||||
LayerEntity.Leds.Clear();
|
LayerEntity.Leds.Clear();
|
||||||
@ -187,7 +187,7 @@ namespace Artemis.Core.Models.Profile
|
|||||||
|
|
||||||
var properties = new List<BaseLayerProperty>(General.GetAllLayerProperties());
|
var properties = new List<BaseLayerProperty>(General.GetAllLayerProperties());
|
||||||
properties.AddRange(Transform.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
|
// 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
|
// 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);
|
General.Override(TimeSpan.Zero);
|
||||||
Transform.Override(TimeSpan.Zero);
|
Transform.Override(TimeSpan.Zero);
|
||||||
LayerBrush.OverrideProperties(TimeSpan.Zero);
|
LayerBrush.BaseProperties.Override(TimeSpan.Zero);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
General.Update(deltaTime);
|
General.Update(deltaTime);
|
||||||
Transform.Update(deltaTime);
|
Transform.Update(deltaTime);
|
||||||
LayerBrush.UpdateProperties(deltaTime);
|
LayerBrush.BaseProperties.Update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerBrush.Update(deltaTime);
|
LayerBrush.Update(deltaTime);
|
||||||
@ -212,7 +212,7 @@ namespace Artemis.Core.Models.Profile
|
|||||||
{
|
{
|
||||||
General.Override(timeOverride);
|
General.Override(timeOverride);
|
||||||
Transform.Override(timeOverride);
|
Transform.Override(timeOverride);
|
||||||
LayerBrush.OverrideProperties(timeOverride);
|
LayerBrush.BaseProperties.Override(timeOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@ -5,7 +5,7 @@ using Artemis.Storage.Entities.Profile;
|
|||||||
namespace Artemis.Core.Models.Profile.LayerProperties
|
namespace Artemis.Core.Models.Profile.LayerProperties
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For internal use only, to implement your own layer property type, extend <see cref="LayerProperty{T}"/> instead.
|
/// For internal use only, to implement your own layer property type, extend <see cref="LayerProperty{T}" /> instead.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BaseLayerProperty
|
public abstract class BaseLayerProperty
|
||||||
{
|
{
|
||||||
@ -42,11 +42,15 @@ namespace Artemis.Core.Models.Profile.LayerProperties
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to declare that this property doesn't belong to a plugin and should use the core plugin GUID
|
/// Used to declare that this property doesn't belong to a plugin and should use the core plugin GUID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal bool IsCoreProperty { get; set; }
|
public bool IsCoreProperty { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of all the keyframes in their non-generic base form, without their values being available
|
||||||
|
/// </summary>
|
||||||
|
public abstract IReadOnlyList<BaseLayerPropertyKeyframe> BaseKeyframes { get; }
|
||||||
|
|
||||||
internal PropertyEntity PropertyEntity { get; set; }
|
internal PropertyEntity PropertyEntity { get; set; }
|
||||||
internal LayerPropertyGroup LayerPropertyGroup { get; set; }
|
internal LayerPropertyGroup LayerPropertyGroup { get; set; }
|
||||||
internal abstract IReadOnlyList<BaseLayerPropertyKeyframe> BaseKeyframes { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies the provided property entity to the layer property by deserializing the JSON base value and keyframe values
|
/// Applies the provided property entity to the layer property by deserializing the JSON base value and keyframe values
|
||||||
|
|||||||
@ -70,7 +70,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public LayerPropertyKeyframe<T> NextKeyframe { get; protected set; }
|
public LayerPropertyKeyframe<T> NextKeyframe { get; protected set; }
|
||||||
|
|
||||||
internal override IReadOnlyList<BaseLayerPropertyKeyframe> BaseKeyframes => _keyframes.Cast<BaseLayerPropertyKeyframe>().ToList().AsReadOnly();
|
public override IReadOnlyList<BaseLayerPropertyKeyframe> BaseKeyframes => _keyframes.Cast<BaseLayerPropertyKeyframe>().ToList().AsReadOnly();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a keyframe to the layer property
|
/// Adds a keyframe to the layer property
|
||||||
|
|||||||
@ -14,29 +14,34 @@ namespace Artemis.Core.Models.Profile
|
|||||||
public class LayerPropertyGroup
|
public class LayerPropertyGroup
|
||||||
{
|
{
|
||||||
private ReadOnlyCollection<BaseLayerProperty> _allLayerProperties;
|
private ReadOnlyCollection<BaseLayerProperty> _allLayerProperties;
|
||||||
|
private readonly List<BaseLayerProperty> _layerProperties;
|
||||||
|
private readonly List<LayerPropertyGroup> _layerPropertyGroups;
|
||||||
|
|
||||||
protected LayerPropertyGroup()
|
protected LayerPropertyGroup()
|
||||||
{
|
{
|
||||||
LayerProperties = new List<BaseLayerProperty>();
|
_layerProperties = new List<BaseLayerProperty>();
|
||||||
LayerPropertyGroups = new List<LayerPropertyGroup>();
|
_layerPropertyGroups = new List<LayerPropertyGroup>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether this property group's properties are all initialized
|
||||||
|
/// </summary>
|
||||||
public bool PropertiesInitialized { get; private set; }
|
public bool PropertiesInitialized { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to declare that this property group doesn't belong to a plugin and should use the core plugin GUID
|
/// Used to declare that this property group doesn't belong to a plugin and should use the core plugin GUID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal bool IsCorePropertyGroup { get; set; }
|
public bool IsCorePropertyGroup { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of all layer properties in this group
|
/// A list of all layer properties in this group
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal List<BaseLayerProperty> LayerProperties { get; set; }
|
public ReadOnlyCollection<BaseLayerProperty> LayerProperties => _layerProperties.AsReadOnly();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of al child groups in this group
|
/// A list of al child groups in this group
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal List<LayerPropertyGroup> LayerPropertyGroups { get; set; }
|
public ReadOnlyCollection<LayerPropertyGroup> LayerPropertyGroups => _layerPropertyGroups.AsReadOnly();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when all layer properties in this property group have been initialized
|
/// 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);
|
var instance = (BaseLayerProperty) Activator.CreateInstance(propertyInfo.PropertyType);
|
||||||
InitializeProperty(layer, path, instance);
|
InitializeProperty(layer, path, instance);
|
||||||
propertyInfo.SetValue(this, instance);
|
propertyInfo.SetValue(this, instance);
|
||||||
LayerProperties.Add(instance);
|
_layerProperties.Add(instance);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -76,7 +81,7 @@ namespace Artemis.Core.Models.Profile
|
|||||||
var instance = (LayerPropertyGroup) Activator.CreateInstance(propertyInfo.PropertyType);
|
var instance = (LayerPropertyGroup) Activator.CreateInstance(propertyInfo.PropertyType);
|
||||||
instance.InitializeProperties(layerService, layer, $"{path}{propertyInfo.Name}.");
|
instance.InitializeProperties(layerService, layer, $"{path}{propertyInfo.Name}.");
|
||||||
propertyInfo.SetValue(this, instance);
|
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
|
/// Recursively gets all layer properties on this group and any subgroups
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal IReadOnlyCollection<BaseLayerProperty> GetAllLayerProperties()
|
public IReadOnlyCollection<BaseLayerProperty> GetAllLayerProperties()
|
||||||
{
|
{
|
||||||
if (!PropertiesInitialized)
|
if (!PropertiesInitialized)
|
||||||
return new List<BaseLayerProperty>();
|
return new List<BaseLayerProperty>();
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Artemis.Core.Models.Profile;
|
using Artemis.Core.Models.Profile;
|
||||||
using Artemis.Core.Models.Profile.LayerProperties;
|
|
||||||
using Artemis.Core.Plugins.Models;
|
using Artemis.Core.Plugins.Models;
|
||||||
using Artemis.Core.Services.Interfaces;
|
using Artemis.Core.Services.Interfaces;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
@ -29,7 +27,7 @@ namespace Artemis.Core.Plugins.LayerBrush
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public PluginInfo PluginInfo => Descriptor.LayerBrushProvider.PluginInfo;
|
public PluginInfo PluginInfo => Descriptor.LayerBrushProvider.PluginInfo;
|
||||||
|
|
||||||
internal virtual LayerPropertyGroup BaseProperties => null;
|
public virtual LayerPropertyGroup BaseProperties => null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the brush is being removed from the layer
|
/// 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 InitializeProperties(ILayerService layerService, string path)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void ApplyToEntity()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
internal virtual void UpdateProperties(double deltaTime)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
internal virtual void OverrideProperties(TimeSpan overrideTime)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
internal virtual IReadOnlyCollection<BaseLayerProperty> GetAllLayerProperties()
|
|
||||||
{
|
|
||||||
return new List<BaseLayerProperty>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ namespace Artemis.Core.Plugins.LayerBrush
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
internal override LayerPropertyGroup BaseProperties => Properties;
|
public override LayerPropertyGroup BaseProperties => Properties;
|
||||||
|
|
||||||
internal override void InitializeProperties(ILayerService layerService, string path)
|
internal override void InitializeProperties(ILayerService layerService, string path)
|
||||||
{
|
{
|
||||||
@ -56,22 +56,17 @@ namespace Artemis.Core.Plugins.LayerBrush
|
|||||||
PropertiesInitialized = true;
|
PropertiesInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void ApplyToEntity()
|
internal virtual void ApplyToEntity()
|
||||||
{
|
{
|
||||||
Properties.ApplyToEntity();
|
Properties.ApplyToEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void UpdateProperties(double deltaTime)
|
internal virtual void OverrideProperties(TimeSpan overrideTime)
|
||||||
{
|
|
||||||
Properties.Update(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void OverrideProperties(TimeSpan overrideTime)
|
|
||||||
{
|
{
|
||||||
Properties.Override(overrideTime);
|
Properties.Override(overrideTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override IReadOnlyCollection<BaseLayerProperty> GetAllLayerProperties()
|
internal virtual IReadOnlyCollection<BaseLayerProperty> GetAllLayerProperties()
|
||||||
{
|
{
|
||||||
return Properties.GetAllLayerProperties();
|
return Properties.GetAllLayerProperties();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,10 +76,5 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
layer.LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == brush.PluginInfo.Guid);
|
layer.LayerEntity.PropertyEntities.RemoveAll(p => p.PluginGuid == brush.PluginInfo.Guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetLayerPropertyGroups(Layer layer)
|
|
||||||
{
|
|
||||||
var groups = new List<LayerPropertyGroup> {layer.General, layer.Transform, layer.LayerBrush.BrushProperties};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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<BaseLayerPropertyKeyframe> GetKeyframes(bool visibleOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ using System.Windows.Media;
|
|||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
using Artemis.Core.Models.Profile;
|
using Artemis.Core.Models.Profile;
|
||||||
using Artemis.Core.Models.Profile.LayerProperties;
|
using Artemis.Core.Models.Profile.LayerProperties;
|
||||||
|
using Artemis.Core.Models.Profile.LayerProperties.Attributes;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.Core.Services.Interfaces;
|
using Artemis.Core.Services.Interfaces;
|
||||||
using Artemis.UI.Events;
|
using Artemis.UI.Events;
|
||||||
@ -21,28 +22,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
|
|||||||
public class LayerPropertiesViewModel : ProfileEditorPanelViewModel
|
public class LayerPropertiesViewModel : ProfileEditorPanelViewModel
|
||||||
{
|
{
|
||||||
private readonly ICoreService _coreService;
|
private readonly ICoreService _coreService;
|
||||||
private readonly List<LayerPropertyViewModel> _layerPropertyViewModels;
|
|
||||||
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
|
|
||||||
private readonly IPropertyTreeVmFactory _propertyTreeVmFactory;
|
private readonly IPropertyTreeVmFactory _propertyTreeVmFactory;
|
||||||
private readonly IPropertyTimelineVmFactory _propertyTimelineVmFactory;
|
private readonly IPropertyTimelineVmFactory _propertyTimelineVmFactory;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
private Layer _lastSelectedLayer;
|
|
||||||
|
|
||||||
public LayerPropertiesViewModel(IProfileEditorService profileEditorService,
|
public LayerPropertiesViewModel(IProfileEditorService profileEditorService,
|
||||||
ICoreService coreService,
|
ICoreService coreService,
|
||||||
ISettingsService settingsService,
|
ISettingsService settingsService,
|
||||||
ILayerPropertyVmFactory layerPropertyVmFactory,
|
|
||||||
IPropertyTreeVmFactory propertyTreeVmFactory,
|
IPropertyTreeVmFactory propertyTreeVmFactory,
|
||||||
IPropertyTimelineVmFactory propertyTimelineVmFactory)
|
IPropertyTimelineVmFactory propertyTimelineVmFactory)
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_coreService = coreService;
|
_coreService = coreService;
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
_layerPropertyVmFactory = layerPropertyVmFactory;
|
|
||||||
_propertyTreeVmFactory = propertyTreeVmFactory;
|
_propertyTreeVmFactory = propertyTreeVmFactory;
|
||||||
_propertyTimelineVmFactory = propertyTimelineVmFactory;
|
_propertyTimelineVmFactory = propertyTimelineVmFactory;
|
||||||
_layerPropertyViewModels = new List<LayerPropertyViewModel>();
|
|
||||||
|
|
||||||
PixelsPerSecond = 31;
|
PixelsPerSecond = 31;
|
||||||
}
|
}
|
||||||
@ -67,6 +62,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
|
|||||||
set => _profileEditorService.CurrentTime = TimeSpan.FromSeconds(value.Left / PixelsPerSecond);
|
set => _profileEditorService.CurrentTime = TimeSpan.FromSeconds(value.Left / PixelsPerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BindableCollection<LayerPropertyGroupViewModel> LayerPropertyGroups { get; set; }
|
||||||
public PropertyTreeViewModel PropertyTree { get; set; }
|
public PropertyTreeViewModel PropertyTree { get; set; }
|
||||||
public PropertyTimelineViewModel PropertyTimeline { get; set; }
|
public PropertyTimelineViewModel PropertyTimeline { get; set; }
|
||||||
|
|
||||||
@ -88,12 +84,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
|
|||||||
_profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
|
_profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
|
||||||
_profileEditorService.CurrentTimeChanged -= ProfileEditorServiceOnCurrentTimeChanged;
|
_profileEditorService.CurrentTimeChanged -= ProfileEditorServiceOnCurrentTimeChanged;
|
||||||
|
|
||||||
if (_lastSelectedLayer != null)
|
|
||||||
{
|
|
||||||
_lastSelectedLayer.Properties.LayerPropertyRegistered -= LayerOnPropertyRegistered;
|
|
||||||
_lastSelectedLayer.Properties.LayerPropertyRemoved -= LayerOnPropertyRemoved;
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertyTree?.Dispose();
|
PropertyTree?.Dispose();
|
||||||
PropertyTimeline?.Dispose();
|
PropertyTimeline?.Dispose();
|
||||||
PropertyTree = null;
|
PropertyTree = null;
|
||||||
@ -122,78 +112,30 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
|
|||||||
|
|
||||||
private void PopulateProperties(ProfileElement profileElement)
|
private void PopulateProperties(ProfileElement profileElement)
|
||||||
{
|
{
|
||||||
if (_lastSelectedLayer != null)
|
LayerPropertyGroups.Clear();
|
||||||
{
|
|
||||||
_lastSelectedLayer.Properties.LayerPropertyRegistered -= LayerOnPropertyRegistered;
|
|
||||||
_lastSelectedLayer.Properties.LayerPropertyRemoved -= LayerOnPropertyRemoved;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (profileElement is Layer layer)
|
if (profileElement is Layer layer)
|
||||||
{
|
{
|
||||||
// Create VMs for missing properties
|
// Add the built-in root groups of the layer
|
||||||
foreach (var baseLayerProperty in layer.Properties)
|
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))
|
Name = layer.LayerBrush.Descriptor.DisplayName,
|
||||||
CreatePropertyViewModel(baseLayerProperty);
|
Description = layer.LayerBrush.Descriptor.Description
|
||||||
}
|
};
|
||||||
|
LayerPropertyGroups.Add(new LayerPropertyGroupViewModel(layer.LayerBrush.BaseProperties, brushDescription));
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
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
|
#endregion
|
||||||
@ -259,9 +201,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
|
|||||||
|
|
||||||
private TimeSpan CalculateEndTime()
|
private TimeSpan CalculateEndTime()
|
||||||
{
|
{
|
||||||
// End time is the last keyframe + 10 sec
|
if (!(_profileEditorService.SelectedProfileElement is Layer layer))
|
||||||
var lastKeyFrame = PropertyTimeline.PropertyTrackViewModels.SelectMany(r => r.KeyframeViewModels).OrderByDescending(t => t.Keyframe.Position).FirstOrDefault();
|
return TimeSpan.MaxValue;
|
||||||
return lastKeyFrame?.Keyframe.Position.Add(new TimeSpan(0, 0, 0, 10)) ?? 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)
|
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
|
||||||
@ -323,19 +272,24 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If shift is held, snap to closest keyframe
|
var visibleKeyframes = GetKeyframes(true);
|
||||||
var visibleKeyframes = PropertyTimeline.PropertyTrackViewModels
|
|
||||||
.Where(t => t.LayerPropertyViewModel.Parent != null && t.LayerPropertyViewModel.Parent.IsExpanded)
|
|
||||||
.SelectMany(t => t.KeyframeViewModels);
|
|
||||||
// Take a tolerance of 5 pixels (half a keyframe width)
|
// Take a tolerance of 5 pixels (half a keyframe width)
|
||||||
var tolerance = 1000f / PixelsPerSecond * 5;
|
var tolerance = 1000f / PixelsPerSecond * 5;
|
||||||
var closeKeyframe = visibleKeyframes.FirstOrDefault(
|
var closeKeyframe = visibleKeyframes.FirstOrDefault(k => Math.Abs(k.Position.TotalMilliseconds - newTime.TotalMilliseconds) < tolerance);
|
||||||
kf => Math.Abs(kf.Keyframe.Position.TotalMilliseconds - newTime.TotalMilliseconds) < tolerance
|
_profileEditorService.CurrentTime = closeKeyframe?.Position ?? newTime;
|
||||||
);
|
|
||||||
_profileEditorService.CurrentTime = closeKeyframe?.Keyframe.Position ?? newTime;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<BaseLayerPropertyKeyframe> GetKeyframes(bool visibleOnly)
|
||||||
|
{
|
||||||
|
var result = new List<BaseLayerPropertyKeyframe>();
|
||||||
|
foreach (var layerPropertyGroupViewModel in LayerPropertyGroups)
|
||||||
|
result.AddRange(layerPropertyGroupViewModel.GetKeyframes(visibleOnly));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
|
|||||||
@ -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<LayerPropertyBaseViewModel>();
|
||||||
|
PopulateChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayerPropertyGroup LayerPropertyGroup { get; }
|
||||||
|
public PropertyGroupDescriptionAttribute PropertyGroupDescription { get; }
|
||||||
|
public bool IsExpanded { get; set; }
|
||||||
|
|
||||||
|
public List<LayerPropertyBaseViewModel> 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<BaseLayerPropertyKeyframe> GetKeyframes(bool visibleOnly)
|
||||||
|
{
|
||||||
|
var result = new List<BaseLayerPropertyKeyframe>();
|
||||||
|
if (!IsExpanded)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
foreach (var layerPropertyBaseViewModel in Children)
|
||||||
|
result.AddRange(layerPropertyBaseViewModel.GetKeyframes(visibleOnly));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,108 +1,25 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.Models.Profile.LayerProperties;
|
using Artemis.Core.Models.Profile.LayerProperties;
|
||||||
using Artemis.Core.Utilities;
|
using Artemis.Core.Models.Profile.LayerProperties.Attributes;
|
||||||
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput;
|
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract;
|
||||||
using Artemis.UI.Services.Interfaces;
|
|
||||||
using Ninject;
|
|
||||||
using Stylet;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
|
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
|
||||||
{
|
{
|
||||||
public class LayerPropertyViewModel<T> : LayerPropertyViewModel
|
public class LayerPropertyViewModel<T> : LayerPropertyBaseViewModel
|
||||||
{
|
{
|
||||||
private readonly IKernel _kernel;
|
public LayerPropertyViewModel(LayerProperty<T> layerProperty, PropertyDescriptionAttribute propertyDescription)
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
|
||||||
private bool _keyframesEnabled;
|
|
||||||
private bool _isExpanded;
|
|
||||||
|
|
||||||
public LayerPropertyViewModel(LayerProperty<T> layerProperty, LayerPropertyViewModel parent, IKernel kernel, IProfileEditorService profileEditorService)
|
|
||||||
{
|
{
|
||||||
_kernel = kernel;
|
|
||||||
_profileEditorService = profileEditorService;
|
|
||||||
_keyframesEnabled = layerProperty.KeyframesEnabled;
|
|
||||||
|
|
||||||
LayerProperty = layerProperty;
|
LayerProperty = layerProperty;
|
||||||
Parent = parent;
|
PropertyDescription = propertyDescription;
|
||||||
Children = new List<LayerPropertyViewModel>();
|
|
||||||
|
|
||||||
// TODO: Get from attribute
|
|
||||||
IsExpanded = false;
|
|
||||||
|
|
||||||
Parent?.Children.Add(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LayerProperty<T> LayerProperty { get; }
|
public LayerProperty<T> LayerProperty { get; }
|
||||||
|
public PropertyDescriptionAttribute PropertyDescription { get; }
|
||||||
|
|
||||||
public bool IsExpanded
|
public override List<BaseLayerPropertyKeyframe> GetKeyframes(bool visibleOnly)
|
||||||
{
|
{
|
||||||
get => _isExpanded;
|
return LayerProperty.BaseKeyframes.ToList();
|
||||||
set
|
|
||||||
{
|
|
||||||
_isExpanded = value;
|
|
||||||
OnExpandedStateChanged();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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<List<PropertyInputViewModel>>().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<T>(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<EventArgs> 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<LayerPropertyViewModel> Children { get; protected set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user