diff --git a/src/.idea/.idea.Artemis/.idea/avalonia.xml b/src/.idea/.idea.Artemis/.idea/avalonia.xml
index 5d5fcf5ff..b11284c50 100644
--- a/src/.idea/.idea.Artemis/.idea/avalonia.xml
+++ b/src/.idea/.idea.Artemis/.idea/avalonia.xml
@@ -34,12 +34,14 @@
+
+
@@ -47,6 +49,8 @@
+
+
diff --git a/src/Artemis.Core/Events/Profiles/LayerPropertyKeyframeEventArgs.cs b/src/Artemis.Core/Events/Profiles/LayerPropertyKeyframeEventArgs.cs
new file mode 100644
index 000000000..962240239
--- /dev/null
+++ b/src/Artemis.Core/Events/Profiles/LayerPropertyKeyframeEventArgs.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Artemis.Core
+{
+ ///
+ /// Provides data for layer property events.
+ ///
+ public class LayerPropertyKeyframeEventArgs : EventArgs
+ {
+ internal LayerPropertyKeyframeEventArgs(ILayerPropertyKeyframe keyframe)
+ {
+ Keyframe = keyframe;
+ }
+
+ ///
+ /// Gets the keyframe this event is related to
+ ///
+ public ILayerPropertyKeyframe Keyframe { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs
index 13e3ada28..009852cec 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs
@@ -144,11 +144,11 @@ namespace Artemis.Core
///
/// Occurs when a new keyframe was added to the layer property
///
- public event EventHandler? KeyframeAdded;
+ public event EventHandler? KeyframeAdded;
///
/// Occurs when a keyframe was removed from the layer property
///
- public event EventHandler? KeyframeRemoved;
+ public event EventHandler? KeyframeRemoved;
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
index fa1e96f0e..28e2d5db4 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs
@@ -322,7 +322,7 @@ namespace Artemis.Core
SortKeyframes();
ReapplyUpdate();
- OnKeyframeAdded();
+ OnKeyframeAdded(keyframe);
}
///
@@ -357,7 +357,7 @@ namespace Artemis.Core
SortKeyframes();
ReapplyUpdate();
- OnKeyframeRemoved();
+ OnKeyframeRemoved(keyframe);
}
///
@@ -604,10 +604,10 @@ namespace Artemis.Core
public event EventHandler? KeyframesToggled;
///
- public event EventHandler? KeyframeAdded;
+ public event EventHandler? KeyframeAdded;
///
- public event EventHandler? KeyframeRemoved;
+ public event EventHandler? KeyframeRemoved;
///
/// Invokes the event
@@ -645,17 +645,19 @@ namespace Artemis.Core
///
/// Invokes the event
///
- protected virtual void OnKeyframeAdded()
+ ///
+ protected virtual void OnKeyframeAdded(ILayerPropertyKeyframe keyframe)
{
- KeyframeAdded?.Invoke(this, new LayerPropertyEventArgs(this));
+ KeyframeAdded?.Invoke(this, new LayerPropertyKeyframeEventArgs(keyframe));
}
///
/// Invokes the event
///
- protected virtual void OnKeyframeRemoved()
+ ///
+ protected virtual void OnKeyframeRemoved(ILayerPropertyKeyframe keyframe)
{
- KeyframeRemoved?.Invoke(this, new LayerPropertyEventArgs(this));
+ KeyframeRemoved?.Invoke(this, new LayerPropertyKeyframeEventArgs(keyframe));
}
#endregion
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyGroupViewModel.cs
index faa1e3841..85ca45af1 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyGroupViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyGroupViewModel.cs
@@ -12,29 +12,32 @@ using Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
using Artemis.UI.Screens.ProfileEditor.Properties.Tree;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.PropertyInput;
+using DynamicData;
+using DynamicData.Binding;
namespace Artemis.UI.Screens.ProfileEditor.Properties;
-public class PropertyGroupViewModel : ViewModelBase, IDisposable
+public class PropertyGroupViewModel : PropertyViewModelBase, IDisposable
{
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
private readonly IPropertyInputService _propertyInputService;
private bool _hasChildren;
private bool _isExpanded;
private bool _isVisible;
+ private ReadOnlyObservableCollection _keyframes = null!;
+ private IDisposable _keyframeSubscription = null!;
public PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, ILayerPropertyVmFactory layerPropertyVmFactory, IPropertyInputService propertyInputService)
{
_layerPropertyVmFactory = layerPropertyVmFactory;
_propertyInputService = propertyInputService;
- Children = new ObservableCollection();
LayerPropertyGroup = layerPropertyGroup;
TreeGroupViewModel = layerPropertyVmFactory.TreeGroupViewModel(this);
TimelineGroupViewModel = layerPropertyVmFactory.TimelineGroupViewModel(this);
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
_isVisible = !LayerPropertyGroup.IsHidden;
-
+
PopulateChildren();
}
@@ -43,14 +46,13 @@ public class PropertyGroupViewModel : ViewModelBase, IDisposable
_layerPropertyVmFactory = layerPropertyVmFactory;
_propertyInputService = propertyInputService;
LayerBrush = layerBrush;
- Children = new ObservableCollection();
LayerPropertyGroup = layerPropertyGroup;
TreeGroupViewModel = layerPropertyVmFactory.TreeGroupViewModel(this);
TimelineGroupViewModel = layerPropertyVmFactory.TimelineGroupViewModel(this);
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
_isVisible = !LayerPropertyGroup.IsHidden;
-
+
PopulateChildren();
}
@@ -59,18 +61,17 @@ public class PropertyGroupViewModel : ViewModelBase, IDisposable
_layerPropertyVmFactory = layerPropertyVmFactory;
_propertyInputService = propertyInputService;
LayerEffect = layerEffect;
- Children = new ObservableCollection();
LayerPropertyGroup = layerPropertyGroup;
TreeGroupViewModel = layerPropertyVmFactory.TreeGroupViewModel(this);
TimelineGroupViewModel = layerPropertyVmFactory.TimelineGroupViewModel(this);
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
_isVisible = !LayerPropertyGroup.IsHidden;
-
+
PopulateChildren();
}
- public ObservableCollection Children { get; }
+ public ObservableCollection Children { get; private set; } = null!;
public LayerPropertyGroup LayerPropertyGroup { get; }
public BaseLayerBrush? LayerBrush { get; }
public BaseLayerEffect? LayerEffect { get; }
@@ -96,13 +97,32 @@ public class PropertyGroupViewModel : ViewModelBase, IDisposable
set => RaiseAndSetIfChanged(ref _hasChildren, value);
}
+ public override ReadOnlyObservableCollection Keyframes => _keyframes;
+
+ public List GetAllKeyframes(bool expandedOnly)
+ {
+ List result = new();
+ if (expandedOnly && !IsExpanded)
+ return result;
+
+ foreach (PropertyViewModelBase child in Children)
+ {
+ if (child is PropertyViewModel profileElementPropertyViewModel)
+ result.AddRange(profileElementPropertyViewModel.TimelinePropertyViewModel.GetAllKeyframes());
+ else if (child is PropertyGroupViewModel profileElementPropertyGroupViewModel)
+ result.AddRange(profileElementPropertyGroupViewModel.GetAllKeyframes(expandedOnly));
+ }
+
+ return result;
+ }
+
public List GetAllKeyframeViewModels(bool expandedOnly)
{
List result = new();
if (expandedOnly && !IsExpanded)
return result;
- foreach (ViewModelBase child in Children)
+ foreach (PropertyViewModelBase child in Children)
{
if (child is PropertyViewModel profileElementPropertyViewModel)
result.AddRange(profileElementPropertyViewModel.TimelinePropertyViewModel.GetAllKeyframeViewModels());
@@ -115,6 +135,8 @@ public class PropertyGroupViewModel : ViewModelBase, IDisposable
private void PopulateChildren()
{
+ Children = new ObservableCollection();
+
// Get all properties and property groups and create VMs for them
// The group has methods for getting this without reflection but then we lose the order of the properties as they are defined on the group
// Sorting is done to ensure properties defined by the Core (such as on layers) are always on top.
@@ -138,7 +160,14 @@ public class PropertyGroupViewModel : ViewModelBase, IDisposable
}
}
- HasChildren = Children.Any(i => i is PropertyViewModel {IsVisible: true} || i is PropertyGroupViewModel {IsVisible: true});
+ HasChildren = Children.Any(i => i is PropertyViewModel {IsVisible: true} or PropertyGroupViewModel {IsVisible: true});
+ _keyframeSubscription = Children
+ .ToObservableChangeSet()
+ .TransformMany(c => c.Keyframes)
+ .Bind(out ReadOnlyObservableCollection keyframes)
+ .Subscribe();
+
+ _keyframes = keyframes;
}
private void LayerPropertyGroupOnVisibilityChanged(object? sender, EventArgs e)
@@ -155,5 +184,7 @@ public class PropertyGroupViewModel : ViewModelBase, IDisposable
if (viewModelBase is IDisposable disposable)
disposable.Dispose();
}
+
+ _keyframeSubscription.Dispose();
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyViewModel.cs
index 0dfa5ad45..988876941 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyViewModel.cs
@@ -1,17 +1,20 @@
using System;
+using System.Collections.ObjectModel;
using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
using Artemis.UI.Screens.ProfileEditor.Properties.Tree;
using Artemis.UI.Shared;
+using DynamicData;
namespace Artemis.UI.Screens.ProfileEditor.Properties;
-public class PropertyViewModel : ViewModelBase, IDisposable
+public class PropertyViewModel : PropertyViewModelBase, IDisposable
{
private bool _isExpanded;
private bool _isHighlighted;
private bool _isVisible;
+ private readonly SourceList _keyframes;
public PropertyViewModel(ILayerProperty layerProperty, IPropertyVmFactory propertyVmFactory)
{
@@ -19,13 +22,22 @@ public class PropertyViewModel : ViewModelBase, IDisposable
TreePropertyViewModel = propertyVmFactory.TreePropertyViewModel(LayerProperty, this);
TimelinePropertyViewModel = propertyVmFactory.TimelinePropertyViewModel(LayerProperty, this);
- LayerProperty.VisibilityChanged += LayerPropertyOnVisibilityChanged;
_isVisible = !LayerProperty.IsHidden;
+ _keyframes = new SourceList();
+ _keyframes.Edit(k => k.AddRange(LayerProperty.UntypedKeyframes));
+ _keyframes.Connect().Bind(out ReadOnlyObservableCollection keyframes).Subscribe();
+
+ Keyframes = keyframes;
+
+ LayerProperty.VisibilityChanged += LayerPropertyOnVisibilityChanged;
+ LayerProperty.KeyframeAdded += LayerPropertyOnKeyframeAdded;
+ LayerProperty.KeyframeRemoved += LayerPropertyOnKeyframeRemoved;
}
public ILayerProperty LayerProperty { get; }
public ITreePropertyViewModel TreePropertyViewModel { get; }
public ITimelinePropertyViewModel TimelinePropertyViewModel { get; }
+ public override ReadOnlyObservableCollection Keyframes { get; }
public bool IsVisible
{
@@ -50,9 +62,21 @@ public class PropertyViewModel : ViewModelBase, IDisposable
IsVisible = !LayerProperty.IsHidden;
}
+ private void LayerPropertyOnKeyframeAdded(object? sender, LayerPropertyKeyframeEventArgs e)
+ {
+ _keyframes.Add(e.Keyframe);
+ }
+
+ private void LayerPropertyOnKeyframeRemoved(object? sender, LayerPropertyKeyframeEventArgs e)
+ {
+ _keyframes.Remove(e.Keyframe);
+ }
+
///
public void Dispose()
{
LayerProperty.VisibilityChanged -= LayerPropertyOnVisibilityChanged;
+ LayerProperty.KeyframeAdded -= LayerPropertyOnKeyframeAdded;
+ LayerProperty.KeyframeRemoved -= LayerPropertyOnKeyframeRemoved;
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyViewModelBase.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyViewModelBase.cs
new file mode 100644
index 000000000..0aca9b1d7
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyViewModelBase.cs
@@ -0,0 +1,10 @@
+using System.Collections.ObjectModel;
+using Artemis.Core;
+using Artemis.UI.Shared;
+
+namespace Artemis.UI.Screens.ProfileEditor.Properties;
+
+public abstract class PropertyViewModelBase : ViewModelBase
+{
+ public abstract ReadOnlyObservableCollection Keyframes { get; }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/ITimelinePropertyViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/ITimelinePropertyViewModel.cs
index 4770f4cf9..786773223 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/ITimelinePropertyViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/ITimelinePropertyViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using Artemis.Core;
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
using ReactiveUI;
@@ -7,6 +8,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
public interface ITimelinePropertyViewModel : IReactiveObject
{
+ List GetAllKeyframes();
List GetAllKeyframeViewModels();
void WipeKeyframes(TimeSpan? start, TimeSpan? end);
void ShiftKeyframes(TimeSpan? start, TimeSpan? end, TimeSpan amount);
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/Keyframes/TimelineKeyframeViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/Keyframes/TimelineKeyframeViewModel.cs
index 245cdc103..7a6e2618a 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/Keyframes/TimelineKeyframeViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/Keyframes/TimelineKeyframeViewModel.cs
@@ -29,14 +29,14 @@ public class TimelineKeyframeViewModel : ActivatableViewModelBase, ITimelineK
this.WhenActivated(d =>
{
- _isSelected = profileEditorService.ConnectToKeyframes().ToCollection().Select(keyframes => keyframes.Contains(LayerPropertyKeyframe)).ToProperty(this, vm => vm.IsSelected).DisposeWith(d);
+ _isSelected = profileEditorService.ConnectToKeyframes()
+ .ToCollection()
+ .Select(keyframes => keyframes.Contains(LayerPropertyKeyframe))
+ .ToProperty(this, vm => vm.IsSelected)
+ .DisposeWith(d);
profileEditorService.ConnectToKeyframes();
- profileEditorService.PixelsPerSecond.Subscribe(p =>
- {
- _pixelsPerSecond = p;
- profileEditorService.PixelsPerSecond.Subscribe(_ => Update()).DisposeWith(d);
- }).DisposeWith(d);
-
+ profileEditorService.PixelsPerSecond.Subscribe(p => _pixelsPerSecond = p).DisposeWith(d);
+ profileEditorService.PixelsPerSecond.Subscribe(_ => Update()).DisposeWith(d);
this.WhenAnyValue(vm => vm.LayerPropertyKeyframe.Position).Subscribe(_ => Update()).DisposeWith(d);
});
}
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupViewModel.cs
index a8f8f35fc..62b39efe0 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelineGroupViewModel.cs
@@ -1,48 +1,47 @@
using System;
using System.Collections.ObjectModel;
-using System.Linq;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.ProfileEditor;
using Avalonia.Controls.Mixins;
+using DynamicData;
+using DynamicData.Binding;
using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
public class TimelineGroupViewModel : ActivatableViewModelBase
{
- private ObservableCollection? _keyframePositions;
- private ObservableAsPropertyHelper? _pixelsPerSecond;
+ private ReadOnlyObservableCollection _keyframePositions;
+ private int _pixelsPerSecond;
public TimelineGroupViewModel(PropertyGroupViewModel propertyGroupViewModel, IProfileEditorService profileEditorService)
{
PropertyGroupViewModel = propertyGroupViewModel;
+ _keyframePositions = new ReadOnlyObservableCollection(new ObservableCollection());
this.WhenActivated(d =>
{
- _pixelsPerSecond = profileEditorService.PixelsPerSecond.ToProperty(this, vm => vm.PixelsPerSecond).DisposeWith(d);
- profileEditorService.PixelsPerSecond.Subscribe(p => UpdateKeyframePositions()).DisposeWith(d);
+ profileEditorService.PixelsPerSecond.Subscribe(p => _pixelsPerSecond = p).DisposeWith(d);
+
PropertyGroupViewModel.WhenAnyValue(vm => vm.IsExpanded).Subscribe(_ => this.RaisePropertyChanged(nameof(Children))).DisposeWith(d);
- PropertyGroupViewModel.WhenAnyValue(vm => vm.IsExpanded).Subscribe(_ => UpdateKeyframePositions()).DisposeWith(d);
- this.WhenAnyValue(vm => vm.PixelsPerSecond).Subscribe(_ => UpdateKeyframePositions()).DisposeWith(d);
- UpdateKeyframePositions();
+ PropertyGroupViewModel.Keyframes
+ .ToObservableChangeSet()
+ .AutoRefreshOnObservable(_ => profileEditorService.PixelsPerSecond)
+ .Transform(k => k.Position.TotalSeconds * _pixelsPerSecond, true)
+ .Bind(out ReadOnlyObservableCollection keyframePositions)
+ .Subscribe()
+ .DisposeWith(d);
+ KeyframePositions = keyframePositions;
});
}
- public int PixelsPerSecond => _pixelsPerSecond?.Value ?? 0;
public PropertyGroupViewModel PropertyGroupViewModel { get; }
- public ObservableCollection? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null;
+ public ObservableCollection? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null;
- public ObservableCollection? KeyframePositions
+ public ReadOnlyObservableCollection KeyframePositions
{
get => _keyframePositions;
set => RaiseAndSetIfChanged(ref _keyframePositions, value);
}
-
- private void UpdateKeyframePositions()
- {
- KeyframePositions = new ObservableCollection(PropertyGroupViewModel
- .GetAllKeyframeViewModels(false)
- .Select(p => p.Position.TotalSeconds * PixelsPerSecond));
- }
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelinePropertyViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelinePropertyViewModel.cs
index 354b7c30b..a3f52aa3b 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelinePropertyViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Timeline/TimelinePropertyViewModel.cs
@@ -8,6 +8,7 @@ using Artemis.UI.Screens.ProfileEditor.Properties.Timeline.Keyframes;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.ProfileEditor;
using Avalonia.Controls.Mixins;
+using DynamicData;
using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
@@ -15,60 +16,61 @@ namespace Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
public class TimelinePropertyViewModel : ActivatableViewModelBase, ITimelinePropertyViewModel
{
private readonly IProfileEditorService _profileEditorService;
+ private readonly SourceList> _keyframes;
+ private ObservableAsPropertyHelper? _keyframesEnabled;
public TimelinePropertyViewModel(LayerProperty layerProperty, PropertyViewModel propertyViewModel, IProfileEditorService profileEditorService)
{
_profileEditorService = profileEditorService;
LayerProperty = layerProperty;
PropertyViewModel = propertyViewModel;
- KeyframeViewModels = new ObservableCollection>();
+
+ _keyframes = new SourceList>();
+
+ _keyframes.Connect()
+ // Only show items when keyframes are enabled
+ .Filter(this.WhenAnyValue(vm => vm.KeyframesEnabled).Select(b => new Func, bool>(_ => b)))
+ .Transform(k => new TimelineKeyframeViewModel(k, _profileEditorService))
+ .Bind(out ReadOnlyObservableCollection> keyframeViewModels)
+ .Subscribe();
+ KeyframeViewModels = keyframeViewModels;
this.WhenActivated(d =>
{
- Observable.FromEventPattern(x => LayerProperty.KeyframesToggled += x, x => LayerProperty.KeyframesToggled -= x)
- .Subscribe(_ => UpdateKeyframes())
+ _keyframesEnabled = LayerProperty.WhenAnyValue(p => p.KeyframesEnabled).ToProperty(this, vm => vm.KeyframesEnabled).DisposeWith(d);
+ Observable.FromEventPattern(x => LayerProperty.KeyframeAdded += x, x => LayerProperty.KeyframeAdded -= x)
+ .Subscribe(e => _keyframes.Add((LayerPropertyKeyframe) e.EventArgs.Keyframe))
.DisposeWith(d);
- Observable.FromEventPattern(x => LayerProperty.KeyframeAdded += x, x => LayerProperty.KeyframeAdded -= x)
- .Subscribe(_ => UpdateKeyframes())
- .DisposeWith(d);
- Observable.FromEventPattern(x => LayerProperty.KeyframeRemoved += x, x => LayerProperty.KeyframeRemoved -= x)
- .Subscribe(_ => UpdateKeyframes())
+ Observable.FromEventPattern(x => LayerProperty.KeyframeRemoved += x, x => LayerProperty.KeyframeRemoved -= x)
+ .Subscribe(e => _keyframes.Remove((LayerPropertyKeyframe) e.EventArgs.Keyframe))
.DisposeWith(d);
- UpdateKeyframes();
+ _keyframes.Edit(k =>
+ {
+ k.Clear();
+ k.AddRange(LayerProperty.Keyframes);
+ });
});
}
public LayerProperty LayerProperty { get; }
public PropertyViewModel PropertyViewModel { get; }
- public ObservableCollection> KeyframeViewModels { get; }
+ public ReadOnlyObservableCollection> KeyframeViewModels { get; }
+ public bool KeyframesEnabled => _keyframesEnabled?.Value ?? false;
private void UpdateKeyframes()
{
- // Only show keyframes if they are enabled
- if (LayerProperty.KeyframesEnabled)
- {
- List> keyframes = LayerProperty.Keyframes.ToList();
-
- List> toRemove = KeyframeViewModels.Where(t => !keyframes.Contains(t.LayerPropertyKeyframe)).ToList();
- foreach (TimelineKeyframeViewModel timelineKeyframeViewModel in toRemove)
- KeyframeViewModels.Remove(timelineKeyframeViewModel);
- List> toAdd = keyframes.Where(k => KeyframeViewModels.All(t => t.LayerPropertyKeyframe != k))
- .Select(k => new TimelineKeyframeViewModel(k, _profileEditorService)).ToList();
- foreach (TimelineKeyframeViewModel timelineKeyframeViewModel in toAdd)
- KeyframeViewModels.Add(timelineKeyframeViewModel);
- }
- else
- {
- KeyframeViewModels.Clear();
- }
-
foreach (TimelineKeyframeViewModel timelineKeyframeViewModel in KeyframeViewModels)
timelineKeyframeViewModel.Update();
}
#region Implementation of ITimelinePropertyViewModel
+ public List GetAllKeyframes()
+ {
+ return LayerProperty.KeyframesEnabled ? new List(LayerProperty.Keyframes) : new List();
+ }
+
public List GetAllKeyframeViewModels()
{
return KeyframeViewModels.Cast().ToList();
@@ -79,7 +81,6 @@ public class TimelinePropertyViewModel : ActivatableViewModelBase, ITimelineP
start ??= TimeSpan.Zero;
end ??= TimeSpan.MaxValue;
-
List> toShift = LayerProperty.Keyframes.Where(k => k.Position >= start && k.Position < end).ToList();
foreach (LayerPropertyKeyframe keyframe in toShift)
LayerProperty.RemoveKeyframe(keyframe);
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupViewModel.cs
index f626de8d8..c870e291b 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupViewModel.cs
@@ -56,7 +56,7 @@ public class TreeGroupViewModel : ActivatableViewModelBase
public BaseLayerBrush? LayerBrush => PropertyGroupViewModel.LayerBrush;
public BaseLayerEffect? LayerEffect => PropertyGroupViewModel.LayerEffect;
public LayerPropertyGroupType GroupType { get; private set; }
- public ObservableCollection? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null;
+ public ObservableCollection? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null;
public ReactiveCommand OpenBrushSettings { get; }
public ReactiveCommand OpenEffectSettings { get; }