1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

UI VM factories - Shortened names for readibility

Layer properties - Ensure only LayerBrushes can add properties and make sure that method instantiates a keyframe engine
Layer properties UI - Respond to properties being added/removed
This commit is contained in:
Robert 2020-02-12 21:18:00 +01:00
parent 4f66d09755
commit 51a21b7a8a
29 changed files with 417 additions and 303 deletions

View File

@ -428,7 +428,7 @@ namespace Artemis.Core.Models.Profile
/// <typeparam name="T">The type of value of the layer property</typeparam> /// <typeparam name="T">The type of value of the layer property</typeparam>
/// <param name="layerProperty">The property to apply to the layer</param> /// <param name="layerProperty">The property to apply to the layer</param>
/// <returns>True if an existing value was found and applied, otherwise false.</returns> /// <returns>True if an existing value was found and applied, otherwise false.</returns>
public bool RegisterLayerProperty<T>(LayerProperty<T> layerProperty) internal bool RegisterLayerProperty<T>(LayerProperty<T> layerProperty)
{ {
return RegisterLayerProperty((BaseLayerProperty) layerProperty); return RegisterLayerProperty((BaseLayerProperty) layerProperty);
} }
@ -439,7 +439,7 @@ namespace Artemis.Core.Models.Profile
/// </summary> /// </summary>
/// <param name="layerProperty">The property to apply to the layer</param> /// <param name="layerProperty">The property to apply to the layer</param>
/// <returns>True if an existing value was found and applied, otherwise false.</returns> /// <returns>True if an existing value was found and applied, otherwise false.</returns>
public bool RegisterLayerProperty(BaseLayerProperty layerProperty) internal bool RegisterLayerProperty(BaseLayerProperty layerProperty)
{ {
if (_properties.ContainsKey((layerProperty.PluginInfo.Guid, layerProperty.Id))) if (_properties.ContainsKey((layerProperty.PluginInfo.Guid, layerProperty.Id)))
throw new ArtemisCoreException($"Duplicate property ID detected. Layer already contains a property with ID {layerProperty.Id}."); throw new ArtemisCoreException($"Duplicate property ID detected. Layer already contains a property with ID {layerProperty.Id}.");

View File

@ -108,9 +108,9 @@ namespace Artemis.Core.Models.Profile.LayerProperties
public IReadOnlyCollection<BaseKeyframe> UntypedKeyframes => BaseKeyframes.AsReadOnly(); public IReadOnlyCollection<BaseKeyframe> UntypedKeyframes => BaseKeyframes.AsReadOnly();
/// <summary> /// <summary>
/// Gets or sets the keyframe engine instance of this property /// Gets the keyframe engine instance of this property
/// </summary> /// </summary>
public KeyframeEngine KeyframeEngine { get; set; } public KeyframeEngine KeyframeEngine { get; internal set; }
protected List<BaseKeyframe> BaseKeyframes { get; set; } protected List<BaseKeyframe> BaseKeyframes { get; set; }
@ -129,50 +129,6 @@ namespace Artemis.Core.Models.Profile.LayerProperties
} }
} }
internal void ApplyToEntity()
{
var propertyEntity = Layer.LayerEntity.PropertyEntities.FirstOrDefault(p => p.Id == Id);
if (propertyEntity == null)
{
propertyEntity = new PropertyEntity {Id = Id};
Layer.LayerEntity.PropertyEntities.Add(propertyEntity);
}
propertyEntity.ValueType = Type.Name;
propertyEntity.Value = JsonConvert.SerializeObject(BaseValue);
propertyEntity.IsUsingKeyframes = IsUsingKeyframes;
propertyEntity.KeyframeEntities.Clear();
foreach (var baseKeyframe in BaseKeyframes)
{
propertyEntity.KeyframeEntities.Add(new KeyframeEntity
{
Position = baseKeyframe.Position,
Value = JsonConvert.SerializeObject(baseKeyframe.BaseValue),
EasingFunction = (int) baseKeyframe.EasingFunction
});
}
}
internal void ApplyToProperty(PropertyEntity propertyEntity)
{
BaseValue = DeserializePropertyValue(propertyEntity.Value);
IsUsingKeyframes = propertyEntity.IsUsingKeyframes;
BaseKeyframes.Clear();
foreach (var keyframeEntity in propertyEntity.KeyframeEntities.OrderBy(e => e.Position))
{
// Create a strongly typed keyframe or else it cannot be cast later on
var keyframeType = typeof(Keyframe<>);
var keyframe = (BaseKeyframe) Activator.CreateInstance(keyframeType.MakeGenericType(Type), Layer, this);
keyframe.Position = keyframeEntity.Position;
keyframe.BaseValue = DeserializePropertyValue(keyframeEntity.Value);
keyframe.EasingFunction = (Easings.Functions) keyframeEntity.EasingFunction;
BaseKeyframes.Add(keyframe);
}
}
/// <summary> /// <summary>
/// Creates a new keyframe for this base property without knowing the type /// Creates a new keyframe for this base property without knowing the type
/// </summary> /// </summary>
@ -261,9 +217,29 @@ namespace Artemis.Core.Models.Profile.LayerProperties
SortKeyframes(); SortKeyframes();
} }
internal void SortKeyframes() /// <summary>
/// Returns the flattened index of this property on the layer
/// </summary>
/// <returns></returns>
public int GetFlattenedIndex()
{ {
BaseKeyframes = BaseKeyframes.OrderBy(k => k.Position).ToList(); if (Parent == null)
return Layer.Properties.IndexOf(this);
// Create a flattened list of all properties in their order as defined by the parent/child hierarchy
var properties = new List<BaseLayerProperty>();
// Iterate root properties (those with children)
foreach (var baseLayerProperty in Layer.Properties)
{
// First add self, then add all children
if (baseLayerProperty.Children.Any())
{
properties.Add(baseLayerProperty);
properties.AddRange(baseLayerProperty.GetAllChildren());
}
}
return properties.IndexOf(this);
} }
public override string ToString() public override string ToString()
@ -271,6 +247,65 @@ namespace Artemis.Core.Models.Profile.LayerProperties
return $"{nameof(Id)}: {Id}, {nameof(Name)}: {Name}, {nameof(Description)}: {Description}"; return $"{nameof(Id)}: {Id}, {nameof(Name)}: {Name}, {nameof(Description)}: {Description}";
} }
internal void ApplyToEntity()
{
var propertyEntity = Layer.LayerEntity.PropertyEntities.FirstOrDefault(p => p.Id == Id);
if (propertyEntity == null)
{
propertyEntity = new PropertyEntity {Id = Id};
Layer.LayerEntity.PropertyEntities.Add(propertyEntity);
}
propertyEntity.ValueType = Type.Name;
propertyEntity.Value = JsonConvert.SerializeObject(BaseValue);
propertyEntity.IsUsingKeyframes = IsUsingKeyframes;
propertyEntity.KeyframeEntities.Clear();
foreach (var baseKeyframe in BaseKeyframes)
{
propertyEntity.KeyframeEntities.Add(new KeyframeEntity
{
Position = baseKeyframe.Position,
Value = JsonConvert.SerializeObject(baseKeyframe.BaseValue),
EasingFunction = (int) baseKeyframe.EasingFunction
});
}
}
internal void ApplyToProperty(PropertyEntity propertyEntity)
{
BaseValue = DeserializePropertyValue(propertyEntity.Value);
IsUsingKeyframes = propertyEntity.IsUsingKeyframes;
BaseKeyframes.Clear();
foreach (var keyframeEntity in propertyEntity.KeyframeEntities.OrderBy(e => e.Position))
{
// Create a strongly typed keyframe or else it cannot be cast later on
var keyframeType = typeof(Keyframe<>);
var keyframe = (BaseKeyframe) Activator.CreateInstance(keyframeType.MakeGenericType(Type), Layer, this);
keyframe.Position = keyframeEntity.Position;
keyframe.BaseValue = DeserializePropertyValue(keyframeEntity.Value);
keyframe.EasingFunction = (Easings.Functions) keyframeEntity.EasingFunction;
BaseKeyframes.Add(keyframe);
}
}
internal void SortKeyframes()
{
BaseKeyframes = BaseKeyframes.OrderBy(k => k.Position).ToList();
}
internal IEnumerable<BaseLayerProperty> GetAllChildren()
{
var children = new List<BaseLayerProperty>();
children.AddRange(Children);
foreach (var layerPropertyViewModel in Children)
children.AddRange(layerPropertyViewModel.GetAllChildren());
return children;
}
private object DeserializePropertyValue(string value) private object DeserializePropertyValue(string value)
{ {
if (value == "null") if (value == "null")

View File

@ -1,71 +1,31 @@
using System; using System.Collections.ObjectModel;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Artemis.Core.Plugins.LayerBrush;
using Artemis.Core.Plugins.Models; using Artemis.Core.Plugins.Models;
namespace Artemis.Core.Models.Profile.LayerProperties namespace Artemis.Core.Models.Profile.LayerProperties
{ {
/// <summary> /// <summary>
/// Represents a property on the layer. This property is visible in the profile editor and can be key-framed (unless /// Represents a property on the layer. This property is visible in the profile editor and can be key-framed (unless
/// opted out) /// opted out).
/// <para>To create and register a new LayerProperty use <see cref="LayerBrush.RegisterLayerProperty" /></para>
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public class LayerProperty<T> : BaseLayerProperty public class LayerProperty<T> : BaseLayerProperty
{ {
internal LayerProperty(Layer layer, BaseLayerProperty parent, string id, string name, string description) : base(layer, null, parent, id, name, description, typeof(T)) internal LayerProperty(Layer layer, BaseLayerProperty parent, string id, string name, string description)
: base(layer, null, parent, id, name, description, typeof(T))
{ {
} }
internal LayerProperty(Layer layer, string id, string name, string description) : base(layer, null, null, id, name, description, typeof(T)) internal LayerProperty(Layer layer, string id, string name, string description)
: base(layer, null, null, id, name, description, typeof(T))
{ {
} }
/// <summary> internal LayerProperty(Layer layer, PluginInfo pluginInfo, BaseLayerProperty parent, string id, string name, string description)
/// Represents a property on the layer. This property is visible in the profile editor and can be key-framed (unless : base(layer, pluginInfo, parent, id, name, description, typeof(T))
/// opted out)
/// <para>
/// Note: The value and keyframes of the property are stored using the ID, after adding the property to the layer
/// these are restored.
/// </para>
/// </summary>
/// <param name="layer">The layer the property is applied to</param>
/// <param name="pluginInfo">The plugin to create this property for</param>
/// <param name="parent">The parent of this property, use this to create a tree-hierarchy in the editor</param>
/// <param name="id">A and ID identifying your property, must be unique within your plugin</param>
/// <param name="name">A name for your property, this is visible in the editor</param>
/// <param name="description">A description for your property, this is visible in the editor</param>
public LayerProperty(Layer layer, PluginInfo pluginInfo, BaseLayerProperty parent, string id, string name, string description) : base(layer, pluginInfo, parent, id, name, description,
typeof(T))
{ {
if (layer == null)
throw new ArgumentNullException(nameof(layer));
if (pluginInfo == null)
throw new ArgumentNullException(nameof(pluginInfo));
if (id == null)
throw new ArgumentNullException(nameof(id));
}
/// <summary>
/// Represents a property on the layer. This property is visible in the profile editor and can be key-framed (unless
/// opted out)
/// <para>
/// Note: The value and keyframes of the property are stored using the ID, after adding the property to the layer
/// these are restored.
/// </para>
/// </summary>
/// <param name="layer">The layer the property is applied to</param>
/// <param name="pluginInfo">The plugin to create this property for</param>
/// <param name="id">A and ID identifying your property, must be unique within your plugin</param>
/// <param name="name">A name for your property, this is visible in the editor</param>
/// <param name="description">A description for your property, this is visible in the editor</param>
public LayerProperty(Layer layer, PluginInfo pluginInfo, string id, string name, string description) : base(layer, pluginInfo, null, id, name, description, typeof(T))
{
if (layer == null)
throw new ArgumentNullException(nameof(layer));
if (pluginInfo == null)
throw new ArgumentNullException(nameof(pluginInfo));
if (id == null)
throw new ArgumentNullException(nameof(id));
} }
/// <summary> /// <summary>

View File

@ -1,12 +1,16 @@
using System; using System;
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.Services;
using Artemis.Core.Services.Interfaces;
using SkiaSharp; using SkiaSharp;
namespace Artemis.Core.Plugins.LayerBrush namespace Artemis.Core.Plugins.LayerBrush
{ {
public abstract class LayerBrush : IDisposable public abstract class LayerBrush : IDisposable
{ {
private ILayerService _layerService;
protected LayerBrush(Layer layer, LayerBrushDescriptor descriptor) protected LayerBrush(Layer layer, LayerBrushDescriptor descriptor)
{ {
Layer = layer; Layer = layer;
@ -54,6 +58,8 @@ namespace Artemis.Core.Plugins.LayerBrush
{ {
var property = new LayerProperty<T>(Layer, Descriptor.LayerBrushProvider.PluginInfo, parent, id, name, description); var property = new LayerProperty<T>(Layer, Descriptor.LayerBrushProvider.PluginInfo, parent, id, name, description);
Layer.RegisterLayerProperty(property); Layer.RegisterLayerProperty(property);
// It's fine if this is null, it'll be picked up by SetLayerService later
_layerService?.InstantiateKeyframeEngine(property);
return property; return property;
} }
@ -68,9 +74,20 @@ namespace Artemis.Core.Plugins.LayerBrush
/// <returns>The layer property</returns> /// <returns>The layer property</returns>
protected LayerProperty<T> RegisterLayerProperty<T>(string id, string name, string description) protected LayerProperty<T> RegisterLayerProperty<T>(string id, string name, string description)
{ {
var property = new LayerProperty<T>(Layer, Descriptor.LayerBrushProvider.PluginInfo, Layer.BrushReferenceProperty.Parent, id, name, description); var property = new LayerProperty<T>(
Layer, Descriptor.LayerBrushProvider.PluginInfo, Layer.BrushReferenceProperty.Parent, id, name, description
);
Layer.RegisterLayerProperty(property); Layer.RegisterLayerProperty(property);
// It's fine if this is null, it'll be picked up by SetLayerService later
_layerService?.InstantiateKeyframeEngine(property);
return property; return property;
} }
internal void SetLayerService(ILayerService layerService)
{
_layerService = layerService;
foreach (var baseLayerProperty in Layer.Properties)
_layerService.InstantiateKeyframeEngine(baseLayerProperty);
}
} }
} }

View File

@ -8,15 +8,16 @@ namespace Artemis.Core.Services.Interfaces
public interface ILayerService : IArtemisService public interface ILayerService : IArtemisService
{ {
/// <summary> /// <summary>
/// Instantiates and adds the <see cref="LayerBrush" /> described by the provided /// Instantiates and adds the <see cref="LayerBrush" /> described by the provided <see cref="LayerBrushDescriptor" />
/// <see cref="LayerBrushDescriptor" /> to the provided <see cref="Layer" />. /// to the <see cref="Layer" />.
/// </summary> /// </summary>
/// <param name="layer">The layer to add the new layer element to</param> /// <param name="layer">The layer to instantiate the brush for</param>
/// <returns></returns> /// <returns></returns>
LayerBrush InstantiateLayerBrush(Layer layer); LayerBrush InstantiateLayerBrush(Layer layer);
/// <summary> /// <summary>
/// Instantiates and adds a compatible <see cref="KeyframeEngine" /> to the provided <see cref="LayerProperty{T}" /> /// Instantiates and adds a compatible <see cref="KeyframeEngine" /> to the provided <see cref="LayerProperty{T}" />.
/// If the property already has a compatible keyframe engine, nothing happens.
/// </summary> /// </summary>
/// <param name="layerProperty">The layer property to apply the keyframe engine to.</param> /// <param name="layerProperty">The layer property to apply the keyframe engine to.</param>
/// <returns>The resulting keyframe engine, if a compatible engine was found.</returns> /// <returns>The resulting keyframe engine, if a compatible engine was found.</returns>
@ -24,6 +25,7 @@ namespace Artemis.Core.Services.Interfaces
/// <summary> /// <summary>
/// Instantiates and adds a compatible <see cref="KeyframeEngine" /> to the provided <see cref="BaseLayerProperty" />. /// Instantiates and adds a compatible <see cref="KeyframeEngine" /> to the provided <see cref="BaseLayerProperty" />.
/// If the property already has a compatible keyframe engine, nothing happens.
/// </summary> /// </summary>
/// <param name="layerProperty">The layer property to apply the keyframe engine to.</param> /// <param name="layerProperty">The layer property to apply the keyframe engine to.</param>
/// <returns>The resulting keyframe engine, if a compatible engine was found.</returns> /// <returns>The resulting keyframe engine, if a compatible engine was found.</returns>

View File

@ -46,10 +46,13 @@ namespace Artemis.Core.Services
new ConstructorArgument("layer", layer), new ConstructorArgument("layer", layer),
new ConstructorArgument("descriptor", descriptor) new ConstructorArgument("descriptor", descriptor)
}; };
var layerElement = (LayerBrush) _kernel.Get(descriptor.LayerBrushType, arguments); var layerBrush = (LayerBrush) _kernel.Get(descriptor.LayerBrushType, arguments);
layer.LayerBrush = layerElement; // Set the layer service after the brush was created to avoid constructor clutter, SetLayerService will play catch-up for us.
// If layer brush implementations need the LayerService they can inject it themselves, but don't require it by default
layerBrush.SetLayerService(this);
layer.LayerBrush = layerBrush;
return layerElement; return layerBrush;
} }
public KeyframeEngine InstantiateKeyframeEngine<T>(LayerProperty<T> layerProperty) public KeyframeEngine InstantiateKeyframeEngine<T>(LayerProperty<T> layerProperty)
@ -59,6 +62,9 @@ namespace Artemis.Core.Services
public KeyframeEngine InstantiateKeyframeEngine(BaseLayerProperty layerProperty) public KeyframeEngine InstantiateKeyframeEngine(BaseLayerProperty layerProperty)
{ {
if (layerProperty.KeyframeEngine != null && layerProperty.KeyframeEngine.CompatibleTypes.Contains(layerProperty.Type))
return layerProperty.KeyframeEngine;
// This creates an instance of each keyframe engine, which is pretty cheap since all the expensive stuff is done during // This creates an instance of each keyframe engine, which is pretty cheap since all the expensive stuff is done during
// Initialize() call but it's not ideal // Initialize() call but it's not ideal
var keyframeEngines = _kernel.Get<List<KeyframeEngine>>(); var keyframeEngines = _kernel.Get<List<KeyframeEngine>>();

View File

@ -17,7 +17,7 @@ namespace Artemis.Plugins.LayerBrushes.Color
public ColorBrush(Layer layer, LayerBrushDescriptor descriptor) : base(layer, descriptor) public ColorBrush(Layer layer, LayerBrushDescriptor descriptor) : base(layer, descriptor)
{ {
ColorProperty = RegisterLayerProperty<SKColor>("Brush.Color", "Main color", "The color of the brush."); ColorProperty = RegisterLayerProperty<SKColor>("Brush.Color", "Color", "The color of the brush.");
GradientTypeProperty = RegisterLayerProperty<GradientType>("Brush.GradientType", "Gradient type", "The scale of the noise."); GradientTypeProperty = RegisterLayerProperty<GradientType>("Brush.GradientType", "Gradient type", "The scale of the noise.");
GradientTypeProperty.CanUseKeyframes = false; GradientTypeProperty.CanUseKeyframes = false;

View File

@ -155,6 +155,7 @@
<Compile Include="Converters\NullToVisibilityConverter.cs" /> <Compile Include="Converters\NullToVisibilityConverter.cs" />
<Compile Include="Events\MainWindowFocusChangedEvent.cs" /> <Compile Include="Events\MainWindowFocusChangedEvent.cs" />
<Compile Include="Events\MainWindowKeyEvent.cs" /> <Compile Include="Events\MainWindowKeyEvent.cs" />
<Compile Include="Events\ProfileElementEventArgs.cs" />
<Compile Include="Events\ShapeControlEventArgs.cs" /> <Compile Include="Events\ShapeControlEventArgs.cs" />
<Compile Include="Events\WindowsThemeEventArgs.cs" /> <Compile Include="Events\WindowsThemeEventArgs.cs" />
<Compile Include="Extensions\TreeViewItemExtensions.cs" /> <Compile Include="Extensions\TreeViewItemExtensions.cs" />
@ -232,7 +233,7 @@
<Compile Include="Exceptions\ArtemisCoreException.cs" /> <Compile Include="Exceptions\ArtemisCoreException.cs" />
<Compile Include="Extensions\RgbColorExtensions.cs" /> <Compile Include="Extensions\RgbColorExtensions.cs" />
<Compile Include="Extensions\RgbRectangleExtensions.cs" /> <Compile Include="Extensions\RgbRectangleExtensions.cs" />
<Compile Include="Ninject\Factories\IViewModelFactory.cs" /> <Compile Include="Ninject\Factories\IVmFactory.cs" />
<Compile Include="Ninject\UIModule.cs" /> <Compile Include="Ninject\UIModule.cs" />
<Compile Include="Utilities\SizeObserver.cs" /> <Compile Include="Utilities\SizeObserver.cs" />
<Compile Include="Screens\Module\ProfileEditor\Dialogs\ProfileCreateViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\Dialogs\ProfileCreateViewModel.cs" />

View File

@ -0,0 +1,22 @@
using System;
using Artemis.Core.Models.Profile;
namespace Artemis.UI.Events
{
public class ProfileElementEventArgs : EventArgs
{
public ProfileElementEventArgs(ProfileElement profileElement)
{
ProfileElement = profileElement;
}
public ProfileElementEventArgs(ProfileElement profileElement, ProfileElement previousProfileElement)
{
ProfileElement = profileElement;
PreviousProfileElement = previousProfileElement;
}
public ProfileElement ProfileElement { get; }
public ProfileElement PreviousProfileElement { get; }
}
}

View File

@ -13,62 +13,62 @@ using Artemis.UI.Screens.Settings.Tabs.Devices;
namespace Artemis.UI.Ninject.Factories namespace Artemis.UI.Ninject.Factories
{ {
public interface IViewModelFactory public interface IVmFactory
{ {
} }
public interface IModuleViewModelFactory : IViewModelFactory public interface IModuleVmFactory : IVmFactory
{ {
ModuleRootViewModel Create(Module module); ModuleRootViewModel Create(Module module);
} }
public interface IDeviceSettingsViewModelFactory : IViewModelFactory public interface IDeviceSettingsVmFactory : IVmFactory
{ {
DeviceSettingsViewModel Create(ArtemisDevice device); DeviceSettingsViewModel Create(ArtemisDevice device);
} }
public interface IProfileEditorViewModelFactory : IViewModelFactory public interface IProfileEditorVmFactory : IVmFactory
{ {
ProfileEditorViewModel Create(ProfileModule module); ProfileEditorViewModel Create(ProfileModule module);
} }
public interface IFolderViewModelFactory : IViewModelFactory public interface IFolderVmFactory : IVmFactory
{ {
FolderViewModel Create(ProfileElement folder); FolderViewModel Create(ProfileElement folder);
FolderViewModel Create(TreeItemViewModel parent, ProfileElement folder); FolderViewModel Create(TreeItemViewModel parent, ProfileElement folder);
} }
public interface ILayerViewModelFactory : IViewModelFactory public interface ILayerVmFactory : IVmFactory
{ {
LayerViewModel Create(TreeItemViewModel parent, ProfileElement folder); LayerViewModel Create(TreeItemViewModel parent, ProfileElement folder);
} }
public interface IProfileLayerViewModelFactory : IViewModelFactory public interface IProfileLayerVmFactory : IVmFactory
{ {
ProfileLayerViewModel Create(Layer layer); ProfileLayerViewModel Create(Layer layer);
} }
public interface ILayerPropertyViewModelFactory : IViewModelFactory public interface ILayerPropertyVmFactory : IVmFactory
{ {
LayerPropertyViewModel Create(BaseLayerProperty layerProperty, LayerPropertyViewModel parent); LayerPropertyViewModel Create(BaseLayerProperty layerProperty, LayerPropertyViewModel parent);
} }
public interface IPropertyTreeViewModelFactory : IViewModelFactory public interface IPropertyTreeVmFactory : IVmFactory
{ {
PropertyTreeViewModel Create(LayerPropertiesViewModel layerPropertiesViewModel); PropertyTreeViewModel Create(LayerPropertiesViewModel layerPropertiesViewModel);
} }
public interface IPropertyTimelineViewModelFactory : IViewModelFactory public interface IPropertyTimelineVmFactory : IVmFactory
{ {
PropertyTimelineViewModel Create(LayerPropertiesViewModel layerPropertiesViewModel); PropertyTimelineViewModel Create(LayerPropertiesViewModel layerPropertiesViewModel);
} }
public interface IPropertyTrackViewModelFactory : IViewModelFactory public interface IPropertyTrackVmFactory : IVmFactory
{ {
PropertyTrackViewModel Create(PropertyTimelineViewModel propertyTimelineViewModel, LayerPropertyViewModel layerPropertyViewModel); PropertyTrackViewModel Create(PropertyTimelineViewModel propertyTimelineViewModel, LayerPropertyViewModel layerPropertyViewModel);
} }
public interface IPropertyTrackKeyframeViewModelFactory : IViewModelFactory public interface IPropertyTrackKeyframeVmFactory : IVmFactory
{ {
PropertyTrackKeyframeViewModel Create(PropertyTrackViewModel propertyTrackViewModel, BaseKeyframe keyframe); PropertyTrackKeyframeViewModel Create(PropertyTrackViewModel propertyTrackViewModel, BaseKeyframe keyframe);
} }

View File

@ -45,7 +45,7 @@ namespace Artemis.UI.Ninject
{ {
x.FromThisAssembly() x.FromThisAssembly()
.SelectAllInterfaces() .SelectAllInterfaces()
.InheritedFrom<IViewModelFactory>() .InheritedFrom<IVmFactory>()
.BindToFactory(); .BindToFactory();
}); });

View File

@ -8,14 +8,14 @@ namespace Artemis.UI.Screens.Module
{ {
public class ModuleRootViewModel : Conductor<Screen>.Collection.OneActive public class ModuleRootViewModel : Conductor<Screen>.Collection.OneActive
{ {
private readonly IProfileEditorViewModelFactory _profileEditorViewModelFactory; private readonly IProfileEditorVmFactory _profileEditorVmFactory;
public ModuleRootViewModel(Core.Plugins.Abstract.Module module, IProfileEditorViewModelFactory profileEditorViewModelFactory) public ModuleRootViewModel(Core.Plugins.Abstract.Module module, IProfileEditorVmFactory profileEditorVmFactory)
{ {
DisplayName = module?.DisplayName; DisplayName = module?.DisplayName;
Module = module; Module = module;
_profileEditorViewModelFactory = profileEditorViewModelFactory; _profileEditorVmFactory = profileEditorVmFactory;
Task.Run(AddTabsAsync); Task.Run(AddTabsAsync);
} }
@ -30,7 +30,7 @@ namespace Artemis.UI.Screens.Module
// Create the profile editor and module VMs // Create the profile editor and module VMs
if (Module is ProfileModule profileModule) if (Module is ProfileModule profileModule)
{ {
var profileEditor = _profileEditorViewModelFactory.Create(profileModule); var profileEditor = _profileEditorVmFactory.Create(profileModule);
Items.Add(profileEditor); Items.Add(profileEditor);
} }

View File

@ -1,10 +1,12 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; 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.Services; using Artemis.Core.Services;
using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Interfaces;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
@ -18,30 +20,32 @@ 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 ILayerPropertyViewModelFactory _layerPropertyViewModelFactory; private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private readonly ISettingsService _settingsService; private readonly ISettingsService _settingsService;
private readonly List<LayerPropertyViewModel> _layerPropertyViewModels;
public LayerPropertiesViewModel(IProfileEditorService profileEditorService, public LayerPropertiesViewModel(IProfileEditorService profileEditorService,
ICoreService coreService, ICoreService coreService,
ISettingsService settingsService, ISettingsService settingsService,
ILayerPropertyViewModelFactory layerPropertyViewModelFactory, ILayerPropertyVmFactory layerPropertyVmFactory,
IPropertyTreeViewModelFactory propertyTreeViewModelFactory, IPropertyTreeVmFactory propertyTreeVmFactory,
IPropertyTimelineViewModelFactory propertyTimelineViewModelFactory) IPropertyTimelineVmFactory propertyTimelineVmFactory)
{ {
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_coreService = coreService; _coreService = coreService;
_settingsService = settingsService; _settingsService = settingsService;
_layerPropertyViewModelFactory = layerPropertyViewModelFactory; _layerPropertyVmFactory = layerPropertyVmFactory;
PixelsPerSecond = 31; PixelsPerSecond = 31;
PropertyTree = propertyTreeViewModelFactory.Create(this); PropertyTree = propertyTreeVmFactory.Create(this);
PropertyTimeline = propertyTimelineViewModelFactory.Create(this); PropertyTimeline = propertyTimelineVmFactory.Create(this);
PopulateProperties(); PopulateProperties(_profileEditorService.SelectedProfileElement, null);
_profileEditorService.SelectedProfileElementChanged += (sender, args) => PopulateProperties(); _layerPropertyViewModels = new List<LayerPropertyViewModel>();
_profileEditorService.SelectedProfileChanged += (sender, args) => PopulateProperties(); _profileEditorService.SelectedProfileElementChanged += (sender, args) => PopulateProperties(args.ProfileElement, args.PreviousProfileElement);
_profileEditorService.SelectedProfileChanged += (sender, args) => PopulateProperties(_profileEditorService.SelectedProfileElement, null);
_profileEditorService.CurrentTimeChanged += ProfileEditorServiceOnCurrentTimeChanged; _profileEditorService.CurrentTimeChanged += ProfileEditorServiceOnCurrentTimeChanged;
} }
@ -68,26 +72,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
public PropertyTreeViewModel PropertyTree { get; set; } public PropertyTreeViewModel PropertyTree { get; set; }
public PropertyTimelineViewModel PropertyTimeline { get; set; } public PropertyTimelineViewModel PropertyTimeline { get; set; }
private void PopulateProperties()
{
if (_profileEditorService.SelectedProfileElement is Layer selectedLayer)
{
// Only create VMs for top-level parents, let parents populate their own children recursively
var propertyViewModels = selectedLayer.Properties
.Where(p => p.Children.Any())
.Select(p => _layerPropertyViewModelFactory.Create(p, null))
.ToList();
PropertyTree.PopulateProperties(propertyViewModels);
PropertyTimeline.PopulateProperties(propertyViewModels);
}
else
{
PropertyTree.ClearProperties();
PropertyTimeline.ClearProperties();
}
}
private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e) private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e)
{ {
NotifyOfPropertyChange(() => FormattedCurrentTime); NotifyOfPropertyChange(() => FormattedCurrentTime);
@ -100,6 +84,77 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
base.OnDeactivate(); base.OnDeactivate();
} }
#region View model managament
private void PopulateProperties(ProfileElement profileElement, ProfileElement previousProfileElement)
{
if (previousProfileElement is Layer previousLayer)
{
previousLayer.LayerPropertyRegistered -= LayerOnPropertyRegistered;
previousLayer.LayerPropertyRemoved -= LayerOnPropertyRemoved;
}
if (profileElement is Layer layer)
{
// Create VMs for missing properties
foreach (var baseLayerProperty in layer.Properties)
{
if (_layerPropertyViewModels.All(vm => vm.LayerProperty != baseLayerProperty))
CreatePropertyViewModel(baseLayerProperty);
}
// Remove VMs for extra properties
foreach (var layerPropertyViewModel in _layerPropertyViewModels.ToList())
{
if (layer.Properties.All(p => p != layerPropertyViewModel.LayerProperty))
RemovePropertyViewModel(layerPropertyViewModel);
}
layer.LayerPropertyRegistered += LayerOnPropertyRegistered;
layer.LayerPropertyRemoved += LayerOnPropertyRemoved;
}
}
private void LayerOnPropertyRegistered(object sender, LayerPropertyEventArgs e)
{
Console.WriteLine("LayerOnPropertyRegistered");
PopulateProperties(e.LayerProperty.Layer, e.LayerProperty.Layer);
}
private void LayerOnPropertyRemoved(object sender, LayerPropertyEventArgs e)
{
Console.WriteLine("LayerOnPropertyRemoved");
PopulateProperties(e.LayerProperty.Layer, 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
#region Controls #region Controls
public void PlayFromStart() public void PlayFromStart()

View File

@ -16,8 +16,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private bool _keyframesEnabled; private bool _keyframesEnabled;
public LayerPropertyViewModel(BaseLayerProperty layerProperty, LayerPropertyViewModel parent, ILayerPropertyViewModelFactory layerPropertyViewModelFactory, IKernel kernel, public LayerPropertyViewModel(BaseLayerProperty layerProperty, LayerPropertyViewModel parent, IKernel kernel, IProfileEditorService profileEditorService)
IProfileEditorService profileEditorService)
{ {
_kernel = kernel; _kernel = kernel;
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
@ -28,8 +27,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
Children = new List<LayerPropertyViewModel>(); Children = new List<LayerPropertyViewModel>();
IsExpanded = layerProperty.ExpandByDefault; IsExpanded = layerProperty.ExpandByDefault;
foreach (var child in layerProperty.Children) Parent?.Children.Add(this);
Children.Add(layerPropertyViewModelFactory.Create(child, this));
} }
public BaseLayerProperty LayerProperty { get; } public BaseLayerProperty LayerProperty { get; }
@ -78,15 +76,5 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
match.Initialize(this); match.Initialize(this);
return match; return match;
} }
public IEnumerable<LayerPropertyViewModel> GetAllChildren()
{
var children = new List<LayerPropertyViewModel>();
children.AddRange(Children);
foreach (var layerPropertyViewModel in children)
children.AddRange(layerPropertyViewModel.GetAllChildren());
return children;
}
} }
} }

View File

@ -22,5 +22,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
PropertyInputViewModel?.Update(); PropertyInputViewModel?.Update();
} }
} }
public override void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel)
{
}
public override void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel)
{
}
} }
} }

View File

@ -16,5 +16,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
/// </summary> /// </summary>
/// <param name="forceUpdate">Force update regardless of visibility and keyframes</param> /// <param name="forceUpdate">Force update regardless of visibility and keyframes</param>
public abstract void Update(bool forceUpdate); public abstract void Update(bool forceUpdate);
/// <summary>
/// Removes the layer property recursively
/// </summary>
/// <param name="layerPropertyViewModel"></param>
public abstract void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel);
/// <summary>
/// Adds the layer property recursively
/// </summary>
/// <param name="layerPropertyViewModel"></param>
public abstract void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel);
} }
} }

View File

@ -9,43 +9,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
public PropertyTreeParentViewModel(LayerPropertyViewModel layerPropertyViewModel) : base(layerPropertyViewModel) public PropertyTreeParentViewModel(LayerPropertyViewModel layerPropertyViewModel) : base(layerPropertyViewModel)
{ {
Children = new BindableCollection<PropertyTreeItemViewModel>(); Children = new BindableCollection<PropertyTreeItemViewModel>();
foreach (var childProperty in layerPropertyViewModel.Children)
{
if (childProperty.Children.Any())
Children.Add(new PropertyTreeParentViewModel(childProperty));
else
Children.Add(new PropertyTreeChildViewModel(childProperty));
}
LayerPropertyViewModel.LayerProperty.Layer.LayerPropertyRegistered += LayerOnLayerPropertyRegistered;
LayerPropertyViewModel.LayerProperty.Layer.LayerPropertyRemoved += LayerOnLayerPropertyRemoved;
}
private void LayerOnLayerPropertyRegistered(object sender, LayerPropertyEventArgs e)
{
if (e.LayerProperty.Parent == LayerPropertyViewModel.LayerProperty)
{
// Problem is we don't have a LayerPropertyViewModel here..
}
}
private void LayerOnLayerPropertyRemoved(object sender, LayerPropertyEventArgs e)
{
// Remove self
if (e.LayerProperty == LayerPropertyViewModel.LayerProperty)
{
LayerPropertyViewModel.LayerProperty.Layer.LayerPropertyRemoved -= LayerOnLayerPropertyRegistered;
LayerPropertyViewModel.LayerProperty.Layer.LayerPropertyRemoved -= LayerOnLayerPropertyRemoved;
}
// Remove child
if (e.LayerProperty.Parent == LayerPropertyViewModel.LayerProperty)
{
var child = Children.FirstOrDefault(c => c.LayerPropertyViewModel.LayerProperty == e.LayerProperty);
if (child != null)
Children.Remove(child);
}
} }
public BindableCollection<PropertyTreeItemViewModel> Children { get; set; } public BindableCollection<PropertyTreeItemViewModel> Children { get; set; }
@ -55,5 +18,38 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
foreach (var child in Children) foreach (var child in Children)
child.Update(forceUpdate); child.Update(forceUpdate);
} }
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);
}
}
public override void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel)
{
foreach (var child in Children.ToList())
{
if (child.LayerPropertyViewModel == layerPropertyViewModel)
Children.Remove(child);
else
child.RemoveLayerProperty(layerPropertyViewModel);
}
}
} }
} }

View File

@ -1,9 +1,7 @@
using System.Collections.Generic; using System.Linq;
using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Services.Interfaces; using Artemis.UI.Services.Interfaces;
using Stylet; using Stylet;
@ -27,26 +25,31 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
public LayerPropertiesViewModel LayerPropertiesViewModel { get; } public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
public BindableCollection<PropertyTreeItemViewModel> PropertyTreeItemViewModels { get; set; } public BindableCollection<PropertyTreeItemViewModel> PropertyTreeItemViewModels { get; set; }
public void PopulateProperties(List<LayerPropertyViewModel> properties) public void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel)
{ {
PropertyTreeItemViewModels.Clear(); // Add as a root VM
if (layerPropertyViewModel.Parent == null)
// Only put parents on the top-level, let parents populate their own children recursively PropertyTreeItemViewModels.Add(new PropertyTreeParentViewModel(layerPropertyViewModel));
foreach (var property in properties) // Add recursively to one of the child VMs
else
{ {
if (property.Children.Any()) foreach (var propertyTreeItemViewModel in PropertyTreeItemViewModels)
PropertyTreeItemViewModels.Add(new PropertyTreeParentViewModel(property)); propertyTreeItemViewModel.AddLayerProperty(layerPropertyViewModel);
} }
} }
public void ClearProperties() public void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel)
{ {
PropertyTreeItemViewModels.Clear(); // Remove a root VM
} var rootVm = PropertyTreeItemViewModels.FirstOrDefault(vm => vm.LayerPropertyViewModel == layerPropertyViewModel);
if (rootVm != null)
public void AddLayerProperty(BaseLayerProperty layerProperty) PropertyTreeItemViewModels.Remove(rootVm);
{ // Remove recursively from one of the child VMs
else
{
foreach (var propertyTreeItemViewModel in PropertyTreeItemViewModels)
propertyTreeItemViewModel.RemoveLayerProperty(layerPropertyViewModel);
}
} }
/// <summary> /// <summary>

View File

@ -11,14 +11,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
public class PropertyTimelineViewModel : PropertyChangedBase public class PropertyTimelineViewModel : PropertyChangedBase
{ {
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private readonly IPropertyTrackViewModelFactory _propertyTrackViewModelFactory; private readonly IPropertyTrackVmFactory _propertyTrackVmFactory;
public PropertyTimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, public PropertyTimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel,
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IPropertyTrackViewModelFactory propertyTrackViewModelFactory) IPropertyTrackVmFactory propertyTrackVmFactory)
{ {
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_propertyTrackViewModelFactory = propertyTrackViewModelFactory; _propertyTrackVmFactory = propertyTrackVmFactory;
LayerPropertiesViewModel = layerPropertiesViewModel; LayerPropertiesViewModel = layerPropertiesViewModel;
PropertyTrackViewModels = new BindableCollection<PropertyTrackViewModel>(); PropertyTrackViewModels = new BindableCollection<PropertyTrackViewModel>();
@ -54,23 +54,29 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
UpdateEndTime(); 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);
}
private void CreateViewModels(LayerPropertyViewModel property) private void CreateViewModels(LayerPropertyViewModel property)
{ {
PropertyTrackViewModels.Add(_propertyTrackViewModelFactory.Create(this, property)); PropertyTrackViewModels.Add(_propertyTrackVmFactory.Create(this, property));
foreach (var child in property.Children) foreach (var child in property.Children)
CreateViewModels(child); CreateViewModels(child);
} }
public void AddLayerProperty(BaseLayerProperty layerProperty)
{
throw new NotImplementedException();
}
public void ClearProperties()
{
PropertyTrackViewModels.Clear();
}
public void UpdateKeyframePositions() public void UpdateKeyframePositions()
{ {
foreach (var viewModel in PropertyTrackViewModels) foreach (var viewModel in PropertyTrackViewModels)

View File

@ -7,13 +7,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{ {
public class PropertyTrackViewModel : Screen public class PropertyTrackViewModel : Screen
{ {
private readonly IPropertyTrackKeyframeViewModelFactory _propertyTrackKeyframeViewModelFactory; private readonly IPropertyTrackKeyframeVmFactory _propertyTrackKeyframeVmFactory;
public PropertyTrackViewModel(PropertyTimelineViewModel propertyTimelineViewModel, public PropertyTrackViewModel(PropertyTimelineViewModel propertyTimelineViewModel, LayerPropertyViewModel layerPropertyViewModel, IPropertyTrackKeyframeVmFactory propertyTrackKeyframeVmFactory)
LayerPropertyViewModel layerPropertyViewModel,
IPropertyTrackKeyframeViewModelFactory propertyTrackKeyframeViewModelFactory)
{ {
_propertyTrackKeyframeViewModelFactory = propertyTrackKeyframeViewModelFactory; _propertyTrackKeyframeVmFactory = propertyTrackKeyframeVmFactory;
PropertyTimelineViewModel = propertyTimelineViewModel; PropertyTimelineViewModel = propertyTimelineViewModel;
LayerPropertyViewModel = layerPropertyViewModel; LayerPropertyViewModel = layerPropertyViewModel;
KeyframeViewModels = new BindableCollection<PropertyTrackKeyframeViewModel>(); KeyframeViewModels = new BindableCollection<PropertyTrackKeyframeViewModel>();
@ -41,7 +39,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{ {
if (KeyframeViewModels.Any(k => k.Keyframe == keyframe)) if (KeyframeViewModels.Any(k => k.Keyframe == keyframe))
continue; continue;
KeyframeViewModels.Add(_propertyTrackKeyframeViewModelFactory.Create(this, keyframe)); KeyframeViewModels.Add(_propertyTrackKeyframeVmFactory.Create(this, keyframe));
} }
UpdateKeyframes(PropertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond); UpdateKeyframes(PropertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond);

View File

@ -11,18 +11,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
{ {
public class ProfileTreeViewModel : ProfileEditorPanelViewModel, IDropTarget public class ProfileTreeViewModel : ProfileEditorPanelViewModel, IDropTarget
{ {
private readonly IFolderViewModelFactory _folderViewModelFactory; private readonly IFolderVmFactory _folderVmFactory;
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private TreeItemViewModel _selectedTreeItem; private TreeItemViewModel _selectedTreeItem;
private bool _updatingTree; private bool _updatingTree;
public ProfileTreeViewModel(IProfileEditorService profileEditorService, public ProfileTreeViewModel(IProfileEditorService profileEditorService,
IFolderViewModelFactory folderViewModelFactory, IFolderVmFactory folderVmFactory,
ILayerViewModelFactory layerViewModelFactory) ILayerVmFactory layerVmFactory)
{ {
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_folderViewModelFactory = folderViewModelFactory; _folderVmFactory = folderVmFactory;
CreateRootFolderViewModel(); CreateRootFolderViewModel();
_profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged; _profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged;
@ -105,7 +105,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
return; return;
} }
RootFolder = _folderViewModelFactory.Create(folder); RootFolder = _folderVmFactory.Create(folder);
_updatingTree = false; _updatingTree = false;
} }

View File

@ -12,9 +12,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IDialogService dialogService, IDialogService dialogService,
ILayerService layerService, ILayerService layerService,
IFolderViewModelFactory folderViewModelFactory, IFolderVmFactory folderVmFactory,
ILayerViewModelFactory layerViewModelFactory) : ILayerVmFactory layerVmFactory) :
base(null, folder, profileEditorService, dialogService, layerService, folderViewModelFactory, layerViewModelFactory) base(null, folder, profileEditorService, dialogService, layerService, folderVmFactory, layerVmFactory)
{ {
} }
@ -23,9 +23,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IDialogService dialogService, IDialogService dialogService,
ILayerService layerService, ILayerService layerService,
IFolderViewModelFactory folderViewModelFactory, IFolderVmFactory folderVmFactory,
ILayerViewModelFactory layerViewModelFactory) : ILayerVmFactory layerVmFactory) :
base(parent, folder, profileEditorService, dialogService, layerService, folderViewModelFactory, layerViewModelFactory) base(parent, folder, profileEditorService, dialogService, layerService, folderVmFactory, layerVmFactory)
{ {
} }

View File

@ -12,9 +12,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IDialogService dialogService, IDialogService dialogService,
ILayerService layerService, ILayerService layerService,
IFolderViewModelFactory folderViewModelFactory, IFolderVmFactory folderVmFactory,
ILayerViewModelFactory layerViewModelFactory) : ILayerVmFactory layerVmFactory) :
base(parent, folder, profileEditorService, dialogService, layerService, folderViewModelFactory, layerViewModelFactory) base(parent, folder, profileEditorService, dialogService, layerService, folderVmFactory, layerVmFactory)
{ {
} }

View File

@ -14,9 +14,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
public abstract class TreeItemViewModel : PropertyChangedBase public abstract class TreeItemViewModel : PropertyChangedBase
{ {
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly IFolderViewModelFactory _folderViewModelFactory; private readonly IFolderVmFactory _folderVmFactory;
private readonly ILayerService _layerService; private readonly ILayerService _layerService;
private readonly ILayerViewModelFactory _layerViewModelFactory; private readonly ILayerVmFactory _layerVmFactory;
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
protected TreeItemViewModel(TreeItemViewModel parent, protected TreeItemViewModel(TreeItemViewModel parent,
@ -24,14 +24,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IDialogService dialogService, IDialogService dialogService,
ILayerService layerService, ILayerService layerService,
IFolderViewModelFactory folderViewModelFactory, IFolderVmFactory folderVmFactory,
ILayerViewModelFactory layerViewModelFactory) ILayerVmFactory layerVmFactory)
{ {
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_dialogService = dialogService; _dialogService = dialogService;
_layerService = layerService; _layerService = layerService;
_folderViewModelFactory = folderViewModelFactory; _folderVmFactory = folderVmFactory;
_layerViewModelFactory = layerViewModelFactory; _layerVmFactory = layerVmFactory;
Parent = parent; Parent = parent;
ProfileElement = profileElement; ProfileElement = profileElement;
@ -182,13 +182,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{ {
existing = Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder); existing = Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder);
if (existing == null) if (existing == null)
Children.Add(_folderViewModelFactory.Create((FolderViewModel) this, folder)); Children.Add(_folderVmFactory.Create((FolderViewModel) this, folder));
} }
else if (profileElement is Layer layer) else if (profileElement is Layer layer)
{ {
existing = Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer); existing = Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer);
if (existing == null) if (existing == null)
Children.Add(_layerViewModelFactory.Create((FolderViewModel) this, layer)); Children.Add(_layerVmFactory.Create((FolderViewModel) this, layer));
} }
existing?.UpdateProfileElements(); existing?.UpdateProfileElements();

View File

@ -24,7 +24,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{ {
private readonly ILayerEditorService _layerEditorService; private readonly ILayerEditorService _layerEditorService;
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private readonly IProfileLayerViewModelFactory _profileLayerViewModelFactory; private readonly IProfileLayerVmFactory _profileLayerVmFactory;
private readonly ISettingsService _settingsService; private readonly ISettingsService _settingsService;
private readonly ISurfaceService _surfaceService; private readonly ISurfaceService _surfaceService;
private int _activeToolIndex; private int _activeToolIndex;
@ -37,13 +37,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
ISurfaceService surfaceService, ISurfaceService surfaceService,
ISettingsService settingsService, ISettingsService settingsService,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IProfileLayerViewModelFactory profileLayerViewModelFactory) IProfileLayerVmFactory profileLayerVmFactory)
{ {
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_layerEditorService = layerEditorService; _layerEditorService = layerEditorService;
_surfaceService = surfaceService; _surfaceService = surfaceService;
_settingsService = settingsService; _settingsService = settingsService;
_profileLayerViewModelFactory = profileLayerViewModelFactory; _profileLayerVmFactory = profileLayerVmFactory;
Execute.OnUIThreadSync(() => Execute.OnUIThreadSync(() =>
{ {
@ -144,7 +144,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
foreach (var layer in layers) foreach (var layer in layers)
{ {
if (layerViewModels.All(vm => vm.Layer != layer)) if (layerViewModels.All(vm => vm.Layer != layer))
CanvasViewModels.Add(_profileLayerViewModelFactory.Create(layer)); CanvasViewModels.Add(_profileLayerVmFactory.Create(layer));
} }
// Remove layers that no longer exist // Remove layers that no longer exist

View File

@ -20,7 +20,7 @@ namespace Artemis.UI.Screens.Settings
{ {
public class SettingsViewModel : MainScreenViewModel public class SettingsViewModel : MainScreenViewModel
{ {
private readonly IDeviceSettingsViewModelFactory _deviceSettingsViewModelFactory; private readonly IDeviceSettingsVmFactory _deviceSettingsVmFactory;
private readonly IKernel _kernel; private readonly IKernel _kernel;
private readonly IPluginService _pluginService; private readonly IPluginService _pluginService;
private readonly ISettingsService _settingsService; private readonly ISettingsService _settingsService;
@ -32,7 +32,7 @@ namespace Artemis.UI.Screens.Settings
IPluginService pluginService, IPluginService pluginService,
IWindowManager windowManager, IWindowManager windowManager,
ISettingsService settingsService, ISettingsService settingsService,
IDeviceSettingsViewModelFactory deviceSettingsViewModelFactory) IDeviceSettingsVmFactory deviceSettingsVmFactory)
{ {
DisplayName = "Settings"; DisplayName = "Settings";
DisplayIcon = PackIconKind.Settings; DisplayIcon = PackIconKind.Settings;
@ -43,7 +43,7 @@ namespace Artemis.UI.Screens.Settings
_pluginService = pluginService; _pluginService = pluginService;
_windowManager = windowManager; _windowManager = windowManager;
_settingsService = settingsService; _settingsService = settingsService;
_deviceSettingsViewModelFactory = deviceSettingsViewModelFactory; _deviceSettingsVmFactory = deviceSettingsVmFactory;
DeviceSettingsViewModels = new BindableCollection<DeviceSettingsViewModel>(); DeviceSettingsViewModels = new BindableCollection<DeviceSettingsViewModel>();
Plugins = new BindableCollection<PluginSettingsViewModel>(); Plugins = new BindableCollection<PluginSettingsViewModel>();
@ -112,7 +112,7 @@ namespace Artemis.UI.Screens.Settings
{ {
DeviceSettingsViewModels.Clear(); DeviceSettingsViewModels.Clear();
foreach (var device in _surfaceService.ActiveSurface.Devices) foreach (var device in _surfaceService.ActiveSurface.Devices)
DeviceSettingsViewModels.Add(_deviceSettingsViewModelFactory.Create(device)); DeviceSettingsViewModels.Add(_deviceSettingsVmFactory.Create(device));
// TODO: GetPluginsOfType isn't ideal here as it doesn't include disabled plugins // TODO: GetPluginsOfType isn't ideal here as it doesn't include disabled plugins
Plugins.Clear(); Plugins.Clear();

View File

@ -13,12 +13,12 @@ namespace Artemis.UI.Screens.Sidebar
{ {
public class SidebarViewModel : PropertyChangedBase public class SidebarViewModel : PropertyChangedBase
{ {
private readonly IModuleViewModelFactory _moduleViewModelFactory; private readonly IModuleVmFactory _moduleVmFactory;
private readonly IPluginService _pluginService; private readonly IPluginService _pluginService;
public SidebarViewModel(List<MainScreenViewModel> defaultSidebarItems, IModuleViewModelFactory moduleViewModelFactory, IPluginService pluginService) public SidebarViewModel(List<MainScreenViewModel> defaultSidebarItems, IModuleVmFactory moduleVmFactory, IPluginService pluginService)
{ {
_moduleViewModelFactory = moduleViewModelFactory; _moduleVmFactory = moduleVmFactory;
_pluginService = pluginService; _pluginService = pluginService;
DefaultSidebarItems = defaultSidebarItems; DefaultSidebarItems = defaultSidebarItems;
@ -76,7 +76,7 @@ namespace Artemis.UI.Screens.Sidebar
SelectedItem = screen; SelectedItem = screen;
// Modules have a VM that must be created, use a factory and set the result as the selected item // Modules have a VM that must be created, use a factory and set the result as the selected item
else if (sidebarItemObject is Core.Plugins.Abstract.Module module) else if (sidebarItemObject is Core.Plugins.Abstract.Module module)
SelectedItem = _moduleViewModelFactory.Create(module); SelectedItem = _moduleVmFactory.Create(module);
} }
public void AddModule(Core.Plugins.Abstract.Module module) public void AddModule(Core.Plugins.Abstract.Module module)

View File

@ -1,6 +1,7 @@
using System; using System;
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Abstract;
using Artemis.UI.Events;
namespace Artemis.UI.Services.Interfaces namespace Artemis.UI.Services.Interfaces
{ {
@ -21,22 +22,22 @@ namespace Artemis.UI.Services.Interfaces
/// <summary> /// <summary>
/// Occurs when a new profile is selected /// Occurs when a new profile is selected
/// </summary> /// </summary>
event EventHandler SelectedProfileChanged; event EventHandler<ProfileElementEventArgs> SelectedProfileChanged;
/// <summary> /// <summary>
/// Occurs then the currently selected profile is updated /// Occurs then the currently selected profile is updated
/// </summary> /// </summary>
event EventHandler SelectedProfileUpdated; event EventHandler<ProfileElementEventArgs> SelectedProfileUpdated;
/// <summary> /// <summary>
/// Occurs when a new profile element is selected /// Occurs when a new profile element is selected
/// </summary> /// </summary>
event EventHandler SelectedProfileElementChanged; event EventHandler<ProfileElementEventArgs> SelectedProfileElementChanged;
/// <summary> /// <summary>
/// Occurs when the currently selected profile element is updated /// Occurs when the currently selected profile element is updated
/// </summary> /// </summary>
event EventHandler SelectedProfileElementUpdated; event EventHandler<ProfileElementEventArgs> SelectedProfileElementUpdated;
/// <summary> /// <summary>
/// Occurs when the current editor time is changed /// Occurs when the current editor time is changed

View File

@ -4,6 +4,7 @@ using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Interfaces;
using Artemis.Core.Services.Storage.Interfaces; using Artemis.Core.Services.Storage.Interfaces;
using Artemis.UI.Events;
using Artemis.UI.Services.Interfaces; using Artemis.UI.Services.Interfaces;
namespace Artemis.UI.Services namespace Artemis.UI.Services
@ -39,29 +40,31 @@ namespace Artemis.UI.Services
public void ChangeSelectedProfile(Profile profile) public void ChangeSelectedProfile(Profile profile)
{ {
var profileElementEvent = new ProfileElementEventArgs(profile, SelectedProfile);
SelectedProfile = profile; SelectedProfile = profile;
UpdateProfilePreview(); UpdateProfilePreview();
OnSelectedProfileChanged(); OnSelectedProfileChanged(profileElementEvent);
} }
public void UpdateSelectedProfile() public void UpdateSelectedProfile()
{ {
_profileService.UpdateProfile(SelectedProfile, false); _profileService.UpdateProfile(SelectedProfile, false);
UpdateProfilePreview(); UpdateProfilePreview();
OnSelectedProfileElementUpdated(); OnSelectedProfileElementUpdated(new ProfileElementEventArgs(SelectedProfile));
} }
public void ChangeSelectedProfileElement(ProfileElement profileElement) public void ChangeSelectedProfileElement(ProfileElement profileElement)
{ {
var profileElementEvent = new ProfileElementEventArgs(profileElement, SelectedProfileElement);
SelectedProfileElement = profileElement; SelectedProfileElement = profileElement;
OnSelectedProfileElementChanged(); OnSelectedProfileElementChanged(profileElementEvent);
} }
public void UpdateSelectedProfileElement() public void UpdateSelectedProfileElement()
{ {
_profileService.UpdateProfile(SelectedProfile, true); _profileService.UpdateProfile(SelectedProfile, true);
UpdateProfilePreview(); UpdateProfilePreview();
OnSelectedProfileElementUpdated(); OnSelectedProfileElementUpdated(new ProfileElementEventArgs(SelectedProfileElement));
} }
@ -91,7 +94,7 @@ namespace Artemis.UI.Services
public void UndoUpdateProfile(ProfileModule module) public void UndoUpdateProfile(ProfileModule module)
{ {
_profileService.UndoUpdateProfile(SelectedProfile, module); _profileService.UndoUpdateProfile(SelectedProfile, module);
OnSelectedProfileChanged(); OnSelectedProfileChanged(new ProfileElementEventArgs(SelectedProfile, SelectedProfile));
if (SelectedProfileElement != null) if (SelectedProfileElement != null)
{ {
@ -107,7 +110,7 @@ namespace Artemis.UI.Services
public void RedoUpdateProfile(ProfileModule module) public void RedoUpdateProfile(ProfileModule module)
{ {
_profileService.RedoUpdateProfile(SelectedProfile, module); _profileService.RedoUpdateProfile(SelectedProfile, module);
OnSelectedProfileChanged(); OnSelectedProfileChanged(new ProfileElementEventArgs(SelectedProfile, SelectedProfile));
if (SelectedProfileElement != null) if (SelectedProfileElement != null)
{ {
@ -120,10 +123,10 @@ namespace Artemis.UI.Services
UpdateProfilePreview(); UpdateProfilePreview();
} }
public event EventHandler SelectedProfileChanged; public event EventHandler<ProfileElementEventArgs> SelectedProfileChanged;
public event EventHandler SelectedProfileUpdated; public event EventHandler<ProfileElementEventArgs> SelectedProfileUpdated;
public event EventHandler SelectedProfileElementChanged; public event EventHandler<ProfileElementEventArgs> SelectedProfileElementChanged;
public event EventHandler SelectedProfileElementUpdated; public event EventHandler<ProfileElementEventArgs> SelectedProfileElementUpdated;
public event EventHandler CurrentTimeChanged; public event EventHandler CurrentTimeChanged;
public event EventHandler ProfilePreviewUpdated; public event EventHandler ProfilePreviewUpdated;
@ -137,24 +140,24 @@ namespace Artemis.UI.Services
_coreService.ModuleUpdatingDisabled = false; _coreService.ModuleUpdatingDisabled = false;
} }
protected virtual void OnSelectedProfileElementUpdated() protected virtual void OnSelectedProfileChanged(ProfileElementEventArgs e)
{ {
SelectedProfileElementUpdated?.Invoke(this, EventArgs.Empty); SelectedProfileChanged?.Invoke(this, e);
} }
protected virtual void OnSelectedProfileElementChanged() protected virtual void OnSelectedProfileUpdated(ProfileElementEventArgs e)
{ {
SelectedProfileElementChanged?.Invoke(this, EventArgs.Empty); SelectedProfileUpdated?.Invoke(this, e);
} }
protected virtual void OnSelectedProfileUpdated() protected virtual void OnSelectedProfileElementChanged(ProfileElementEventArgs e)
{ {
SelectedProfileUpdated?.Invoke(this, EventArgs.Empty); SelectedProfileElementChanged?.Invoke(this, e);
} }
protected virtual void OnSelectedProfileChanged() protected virtual void OnSelectedProfileElementUpdated(ProfileElementEventArgs e)
{ {
SelectedProfileChanged?.Invoke(this, EventArgs.Empty); SelectedProfileElementUpdated?.Invoke(this, e);
} }
protected virtual void OnCurrentTimeChanged() protected virtual void OnCurrentTimeChanged()