diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerPropertyKeyframe.cs b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerPropertyKeyframe.cs
index d0537d8b1..e90536c18 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerPropertyKeyframe.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerPropertyKeyframe.cs
@@ -1,12 +1,13 @@
using System;
using Artemis.Core.Utilities;
+using Stylet;
namespace Artemis.Core.Models.Profile.LayerProperties
{
///
/// For internal use only, use instead.
///
- public abstract class BaseLayerPropertyKeyframe
+ public abstract class BaseLayerPropertyKeyframe : PropertyChangedBase
{
internal BaseLayerPropertyKeyframe(BaseLayerProperty baseLayerProperty)
{
@@ -27,5 +28,10 @@ namespace Artemis.Core.Models.Profile.LayerProperties
/// The easing function applied on the value of the keyframe
///
public Easings.Functions EasingFunction { get; set; }
+
+ ///
+ /// Removes the keyframe from the layer property
+ ///
+ public abstract void Remove();
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerPropertyKeyFrame.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerPropertyKeyFrame.cs
index af37209aa..a2257cefe 100644
--- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerPropertyKeyFrame.cs
+++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerPropertyKeyFrame.cs
@@ -6,6 +6,8 @@ namespace Artemis.Core.Models.Profile.LayerProperties
public class LayerPropertyKeyframe : BaseLayerPropertyKeyframe
{
private TimeSpan _position;
+ private T _value;
+ private LayerProperty _layerProperty;
public LayerPropertyKeyframe(T value, TimeSpan position, Easings.Functions easingFunction, LayerProperty layerProperty) : base(layerProperty)
{
@@ -18,12 +20,20 @@ namespace Artemis.Core.Models.Profile.LayerProperties
///
/// The layer property this keyframe is applied to
///
- public LayerProperty LayerProperty { get; internal set; }
+ public LayerProperty LayerProperty
+ {
+ get => _layerProperty;
+ internal set => SetAndNotify(ref _layerProperty, value);
+ }
///
/// The value of this keyframe
///
- public T Value { get; set; }
+ public T Value
+ {
+ get => _value;
+ set => SetAndNotify(ref _value, value);
+ }
///
public override TimeSpan Position
@@ -31,9 +41,15 @@ namespace Artemis.Core.Models.Profile.LayerProperties
get => _position;
set
{
- _position = value;
+ SetAndNotify(ref _position, value);
LayerProperty.SortKeyframes();
}
}
+
+ ///
+ public override void Remove()
+ {
+ LayerProperty.RemoveKeyframe(this);
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/Abstract/DisplayConditionViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/Abstract/DisplayConditionViewModel.cs
index 2c866f348..3c7c92ab2 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/Abstract/DisplayConditionViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/Abstract/DisplayConditionViewModel.cs
@@ -19,7 +19,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions.Abstract
public abstract void Update();
- public void Delete()
+ public virtual void Delete()
{
Model.Parent.RemoveChild(Model);
Parent.Update();
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateViewModel.cs
index a2f8034b2..c6770f62d 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateViewModel.cs
@@ -23,6 +23,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
private readonly IDataModelVisualizationService _dataModelVisualizationService;
private readonly IEventAggregator _eventAggregator;
private readonly IProfileEditorService _profileEditorService;
+ private bool _isInitialized;
private DataModelPropertiesViewModel _leftSideDataModel;
private List _operators;
private DataModelPropertiesViewModel _rightSideDataModel;
@@ -34,7 +35,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
private DataModelVisualizationViewModel _selectedRightSideProperty;
private List _supportedInputTypes;
- private bool _isInitialized;
public DisplayConditionPredicateViewModel(DisplayConditionPredicate displayConditionPredicate, DisplayConditionViewModel parent, IProfileEditorService profileEditorService,
IDataModelVisualizationService dataModelVisualizationService, IDataModelService dataModelService, IEventAggregator eventAggregator)
@@ -145,6 +145,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
RightSideInputViewModel.Submit();
}
+ public override void Delete()
+ {
+ base.Delete();
+ _profileEditorService.UpdateSelectedProfileElement();
+ }
+
public void Initialize()
{
// Get the data models
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs
index 226c88150..e18cc0520 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.ComponentModel;
using System.Linq;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Utilities;
@@ -43,7 +44,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
#endregion
}
- public abstract class TimelineKeyframeViewModel : PropertyChangedBase
+ public abstract class TimelineKeyframeViewModel : PropertyChangedBase, IDisposable
{
private readonly IProfileEditorService _profileEditorService;
private BindableCollection _easingViewModels;
@@ -57,6 +58,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
_profileEditorService = profileEditorService;
BaseLayerPropertyKeyframe = baseLayerPropertyKeyframe;
EasingViewModels = new BindableCollection();
+
+ BaseLayerPropertyKeyframe.PropertyChanged += BaseLayerPropertyKeyframeOnPropertyChanged;
}
public BaseLayerPropertyKeyframe BaseLayerPropertyKeyframe { get; }
@@ -97,6 +100,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
public abstract void Delete();
+ private void BaseLayerPropertyKeyframeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(BaseLayerPropertyKeyframe.Position))
+ Update(_pixelsPerSecond);
+ }
+
#region Easing
public void CreateEasingViewModels()
@@ -121,12 +130,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
private TimeSpan? _offset;
- public void ApplyMovement(TimeSpan cursorTime)
- {
- UpdatePosition(cursorTime);
- Update(_pixelsPerSecond);
- }
-
public void ReleaseMovement()
{
_offset = null;
@@ -154,7 +157,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
UpdatePosition(keyframeViewModel.BaseLayerPropertyKeyframe.Position + _offset.Value);
}
- private void UpdatePosition(TimeSpan position)
+ public void UpdatePosition(TimeSpan position)
{
if (position < TimeSpan.Zero)
BaseLayerPropertyKeyframe.Position = TimeSpan.Zero;
@@ -167,5 +170,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
}
#endregion
+
+ public void Dispose()
+ {
+ BaseLayerPropertyKeyframe.PropertyChanged -= BaseLayerPropertyKeyframeOnPropertyChanged;
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs
index 2046a9e35..a5e423c2e 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs
@@ -30,14 +30,17 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
var keyframes = LayerPropertyViewModel.LayerProperty.Keyframes.ToList();
var toRemove = TimelineKeyframeViewModels.Where(t => !keyframes.Contains(t.BaseLayerPropertyKeyframe)).ToList();
+ foreach (var timelineKeyframeViewModel in toRemove)
+ timelineKeyframeViewModel.Dispose();
+
TimelineKeyframeViewModels.RemoveRange(toRemove);
- TimelineKeyframeViewModels.AddRange(
- keyframes.Where(k => TimelineKeyframeViewModels.All(t => t.BaseLayerPropertyKeyframe != k))
- .Select(k => new TimelineKeyframeViewModel(_profileEditorService, k))
+ TimelineKeyframeViewModels.AddRange(keyframes
+ .Where(k => TimelineKeyframeViewModels.All(t => t.BaseLayerPropertyKeyframe != k))
+ .Select(k => new TimelineKeyframeViewModel(_profileEditorService, k))
);
}
else
- TimelineKeyframeViewModels.Clear();
+ DisposeKeyframeViewModels();
foreach (var timelineKeyframeViewModel in TimelineKeyframeViewModels)
timelineKeyframeViewModel.Update(_profileEditorService.PixelsPerSecond);
@@ -49,6 +52,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
LayerPropertyViewModel.LayerProperty.KeyframeAdded -= LayerPropertyOnKeyframeModified;
LayerPropertyViewModel.LayerProperty.KeyframeRemoved -= LayerPropertyOnKeyframeModified;
LayerPropertyViewModel.LayerProperty.KeyframesToggled -= LayerPropertyOnKeyframeModified;
+ DisposeKeyframeViewModels();
+ }
+
+ private void DisposeKeyframeViewModels()
+ {
+ foreach (var timelineKeyframeViewModel in TimelineKeyframeViewModels)
+ timelineKeyframeViewModel.Dispose();
+ TimelineKeyframeViewModels.Clear();
}
private void LayerPropertyOnKeyframeModified(object sender, EventArgs e)
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs
index 9175f2b64..cf9aad4ad 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
@@ -130,44 +131,66 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
public void DisableSegment()
{
- switch (Segment)
+ var keyframes = SelectedProfileElement.GetAllKeyframes();
+ var startSegmentEnd = SelectedProfileElement.StartSegmentLength;
+ var mainSegmentEnd = SelectedProfileElement.StartSegmentLength + SelectedProfileElement.MainSegmentLength;
+
+ var oldSegmentLength = SegmentLength;
+
+ if (Segment == SegmentViewModelType.Start)
{
- case SegmentViewModelType.Start:
- SelectedProfileElement.StartSegmentLength = TimeSpan.Zero;
- break;
- case SegmentViewModelType.Main:
- SelectedProfileElement.MainSegmentLength = TimeSpan.Zero;
- break;
- case SegmentViewModelType.End:
- SelectedProfileElement.EndSegmentLength = TimeSpan.Zero;
- break;
- default:
- throw new ArgumentOutOfRangeException();
+ // Remove keyframes that fall in this segment
+ foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position < startSegmentEnd))
+ baseLayerPropertyKeyframe.Remove();
+ SelectedProfileElement.StartSegmentLength = TimeSpan.Zero;
+ }
+ else if (Segment == SegmentViewModelType.Main)
+ {
+ // Remove keyframes that fall in this segment
+ foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position > startSegmentEnd && k.Position < mainSegmentEnd))
+ baseLayerPropertyKeyframe.Remove();
+ SelectedProfileElement.MainSegmentLength = TimeSpan.Zero;
+ }
+ else if (Segment == SegmentViewModelType.End)
+ {
+ // Remove keyframes that fall in this segment
+ foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position > mainSegmentEnd))
+ baseLayerPropertyKeyframe.Remove();
+ SelectedProfileElement.EndSegmentLength = TimeSpan.Zero;
}
NotifyOfPropertyChange(nameof(SegmentEnabled));
+ ShiftNextSegment(SegmentLength - oldSegmentLength);
ProfileEditorService.UpdateSelectedProfileElement();
}
public void EnableSegment()
{
- switch (Segment)
- {
- case SegmentViewModelType.Start:
- SelectedProfileElement.StartSegmentLength = TimeSpan.FromSeconds(1);
- break;
- case SegmentViewModelType.Main:
- SelectedProfileElement.MainSegmentLength = TimeSpan.FromSeconds(1);
- break;
- case SegmentViewModelType.End:
- SelectedProfileElement.EndSegmentLength = TimeSpan.FromSeconds(1);
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
+ ShiftNextSegment(TimeSpan.FromSeconds(1));
+ if (Segment == SegmentViewModelType.Start)
+ SelectedProfileElement.StartSegmentLength = TimeSpan.FromSeconds(1);
+ else if (Segment == SegmentViewModelType.Main)
+ SelectedProfileElement.MainSegmentLength = TimeSpan.FromSeconds(1);
+ else if (Segment == SegmentViewModelType.End)
+ SelectedProfileElement.EndSegmentLength = TimeSpan.FromSeconds(1);
NotifyOfPropertyChange(nameof(SegmentEnabled));
ProfileEditorService.UpdateSelectedProfileElement();
+ UpdateDisplay();
+ }
+
+ public void ShiftNextSegment(TimeSpan amount)
+ {
+ var segmentEnd = TimeSpan.Zero;
+ if (Segment == SegmentViewModelType.Start)
+ segmentEnd = SelectedProfileElement.StartSegmentLength;
+ else if (Segment == SegmentViewModelType.Main)
+ segmentEnd = SelectedProfileElement.StartSegmentLength + SelectedProfileElement.MainSegmentLength;
+ else if (Segment == SegmentViewModelType.End)
+ segmentEnd = SelectedProfileElement.TimelineLength;
+
+ foreach (var baseLayerPropertyKeyframe in SelectedProfileElement.GetAllKeyframes().Where(k => k.Position >= segmentEnd))
+ baseLayerPropertyKeyframe.Position += amount;
}
public void SegmentMouseDown(object sender, MouseButtonEventArgs e)
@@ -180,6 +203,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
((IInputElement) sender).ReleaseMouseCapture();
_draggingSegment = false;
+
+ ProfileEditorService.UpdateSelectedProfileElement();
}
public void SegmentMouseMove(object sender, MouseEventArgs e)
@@ -189,7 +214,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
// Get the parent scroll viewer, need that for our position
var parent = VisualTreeUtilities.FindParent((DependencyObject) sender, "TimelineHeaderScrollViewer");
-
+
var x = Math.Max(0, e.GetPosition(parent).X);
var newTime = TimeSpan.FromSeconds(x / ProfileEditorService.PixelsPerSecond);
@@ -208,7 +233,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
newTime = TimeSpan.FromMilliseconds(Math.Round(newTime.TotalMilliseconds / 50.0) * 50.0);
-
+ var oldSegmentLength = SegmentLength;
if (Segment == SegmentViewModelType.Start)
{
if (newTime < TimeSpan.FromMilliseconds(100))
@@ -231,12 +256,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
NotifyOfPropertyChange(nameof(SegmentLength));
NotifyOfPropertyChange(nameof(SegmentWidth));
+ ShiftNextSegment(SegmentLength - oldSegmentLength);
UpdateDisplay();
}
private void SelectedProfileElementOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
- if (e.PropertyName == nameof(RenderProfileElement.StartSegmentLength) ||
+ if (e.PropertyName == nameof(RenderProfileElement.StartSegmentLength) ||
e.PropertyName == nameof(RenderProfileElement.MainSegmentLength) ||
e.PropertyName == nameof(RenderProfileElement.EndSegmentLength))
{
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs
index e76eba964..dc7d0d17c 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs
@@ -220,7 +220,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected))
keyframeViewModel.SaveOffsetToKeyframe(sourceKeyframeViewModel);
- sourceKeyframeViewModel.ApplyMovement(cursorTime);
+ sourceKeyframeViewModel.UpdatePosition(cursorTime);
foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected))
keyframeViewModel.ApplyOffsetToKeyframe(sourceKeyframeViewModel);