Implemented basic keyframes

This commit is contained in:
Robert committed 2020-01-09 16:56:46 +01:00
1 parent b734fa2f8f
commit 8a1759a575
41 files changed
+951 -123

No files matched your search

@@ -15,29 +15,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
private readonly ILayerPropertyViewModelFactory _layerPropertyViewModelFactory;
private readonly IProfileEditorService _profileEditorService;
public LayerPropertiesViewModel(IProfileEditorService profileEditorService, ILayerPropertyViewModelFactory layerPropertyViewModelFactory)
public LayerPropertiesViewModel(IProfileEditorService profileEditorService,
ILayerPropertyViewModelFactory layerPropertyViewModelFactory,
IPropertyTreeViewModelFactory propertyTreeViewModelFactory,
IPropertyTimelineViewModelFactory propertyTimelineViewModelFactory)
{
_profileEditorService = profileEditorService;
_layerPropertyViewModelFactory = layerPropertyViewModelFactory;
CurrentTime = TimeSpan.Zero;
PixelsPerSecond = 1;
PropertyTree = new PropertyTreeViewModel(this);
PropertyTimeline = new PropertyTimelineViewModel(this);
PropertyTree = propertyTreeViewModelFactory.Create(this);
PropertyTimeline = propertyTimelineViewModelFactory.Create(this);
PopulateProperties();
_profileEditorService.SelectedProfileElementChanged += (sender, args) => PopulateProperties();
}
public TimeSpan CurrentTime
{
get => _currentTime;
set
{
_currentTime = value;
OnCurrentTimeChanged();
}
_profileEditorService.CurrentTimeChanged += ProfileEditorServiceOnCurrentTimeChanged;
}
public string FormattedCurrentTime
@@ -45,10 +38,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
get
{
if (PixelsPerSecond > 200)
return $"{Math.Floor(CurrentTime.TotalSeconds):00}.{CurrentTime.Milliseconds:000}";
return $"{Math.Floor(_profileEditorService.CurrentTime.TotalSeconds):00}.{_profileEditorService.CurrentTime.Milliseconds:000}";
if (PixelsPerSecond > 60)
return $"{Math.Floor(CurrentTime.TotalSeconds):00}.{CurrentTime.Milliseconds:000}";
return $"{Math.Floor(CurrentTime.TotalMinutes):0}:{CurrentTime.Seconds:00}";
return $"{Math.Floor(_profileEditorService.CurrentTime.TotalSeconds):00}.{_profileEditorService.CurrentTime.Milliseconds:000}";
return $"{Math.Floor(_profileEditorService.CurrentTime.TotalMinutes):0}:{_profileEditorService.CurrentTime.Seconds:00}";
}
}
@@ -64,8 +57,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
public Thickness TimeCaretPosition
{
get => new Thickness(CurrentTime.TotalSeconds * PixelsPerSecond, 0, 0, 0);
set => CurrentTime = TimeSpan.FromSeconds(value.Left / PixelsPerSecond);
get => new Thickness(_profileEditorService.CurrentTime.TotalSeconds * PixelsPerSecond, 0, 0, 0);
set => _profileEditorService.CurrentTime = TimeSpan.FromSeconds(value.Left / PixelsPerSecond);
}
public PropertyTreeViewModel PropertyTree { get; set; }
@@ -91,15 +84,21 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
}
}
private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e)
{
NotifyOfPropertyChange(() => FormattedCurrentTime);
NotifyOfPropertyChange(() => TimeCaretPosition);
}
#region Caret movement
private double _caretStartMouseStartOffset;
private bool _mouseOverCaret;
private int _pixelsPerSecond;
private TimeSpan _currentTime;
public void RightGridMouseDown(object sender, MouseButtonEventArgs e)
{
// TODO Preserve mouse offset
_caretStartMouseStartOffset = e.GetPosition((IInputElement) sender).X - TimeCaretPosition.Left;
}
@@ -124,14 +123,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
#region Events
public event EventHandler CurrentTimeChanged;
public event EventHandler PixelsPerSecondChanged;
protected virtual void OnCurrentTimeChanged()
{
CurrentTimeChanged?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnPixelsPerSecondChanged()
{
PixelsPerSecondChanged?.Invoke(this, EventArgs.Empty);
@@ -3,6 +3,7 @@ using System.Linq;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput;
using Artemis.UI.Services.Interfaces;
using Ninject;
using Stylet;
@@ -11,11 +12,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
public class LayerPropertyViewModel : PropertyChangedBase
{
private readonly IKernel _kernel;
private readonly IProfileEditorService _profileEditorService;
private bool _keyframesEnabled;
public LayerPropertyViewModel(BaseLayerProperty layerProperty, LayerPropertyViewModel parent, ILayerPropertyViewModelFactory layerPropertyViewModelFactory, IKernel kernel)
public LayerPropertyViewModel(BaseLayerProperty layerProperty, LayerPropertyViewModel parent, ILayerPropertyViewModelFactory layerPropertyViewModelFactory, IKernel kernel, IProfileEditorService profileEditorService)
{
_kernel = kernel;
_profileEditorService = profileEditorService;
_keyframesEnabled = layerProperty.UntypedKeyframes.Any();
LayerProperty = layerProperty;
Parent = parent;
@@ -44,6 +48,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
private void UpdateKeyframes()
{
// Either create a new first keyframe or clear all the keyframes
if (_keyframesEnabled)
LayerProperty.CreateNewKeyframe(_profileEditorService.CurrentTime);
else
LayerProperty.ClearKeyframes();
// Force the keyframe engine to update, the new keyframe is the current keyframe
LayerProperty.KeyframeEngine.Update(0);
_profileEditorService.UpdateSelectedProfileElement();
}
public PropertyInputViewModel GetPropertyInputViewModel()
@@ -15,6 +15,7 @@
Padding="0 -1"
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
Text="{Binding FloatInputValue}"
Cursor="/Resources/aero_drag_ew.cur" />
<TextBlock Margin="5 0 0 0" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.LayerProperty.InputAffix}" />
</StackPanel>
@@ -1,26 +1,39 @@
using System;
using System.Collections.Generic;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput
{
public class FloatPropertyInputViewModel : PropertyInputViewModel
{
public FloatPropertyInputViewModel(IProfileEditorService profileEditorService) : base(profileEditorService)
{
}
public sealed override List<Type> CompatibleTypes { get; } = new List<Type> {typeof(float)};
public float FloatInputValue
{
get => (float) InputValue;
set => InputValue = value;
}
public override void Update()
{
NotifyOfPropertyChange(() => FloatInputValue);
}
protected override void UpdateBaseValue(object value)
{
throw new NotImplementedException();
var layerProperty = (LayerProperty<float>) LayerPropertyViewModel.LayerProperty;
layerProperty.Value = (float) value;
}
protected override void UpdateKeyframeValue(BaseKeyframe keyframe, object value)
protected override void UpdateKeyframeValue(BaseKeyframe baseKeyframe, object value)
{
throw new NotImplementedException();
}
protected override void CreateKeyframeForValue(object value)
{
throw new NotImplementedException();
var keyframe = (Keyframe<float>) baseKeyframe;
keyframe.Value = (float) value;
}
}
}
@@ -15,6 +15,7 @@
Padding="0 -1"
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
Text="{Binding IntInputValue}"
Cursor="/Resources/aero_drag_ew.cur" />
<TextBlock Margin="5 0 0 0" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.LayerProperty.InputAffix}" />
</StackPanel>
@@ -1,26 +1,39 @@
using System;
using System.Collections.Generic;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput
{
public class IntPropertyInputViewModel : PropertyInputViewModel
{
public IntPropertyInputViewModel(IProfileEditorService profileEditorService) : base(profileEditorService)
{
}
public sealed override List<Type> CompatibleTypes { get; } = new List<Type> {typeof(int)};
public int IntInputValue
{
get => (int) InputValue;
set => InputValue = value;
}
public override void Update()
{
NotifyOfPropertyChange(() => IntInputValue);
}
protected override void UpdateBaseValue(object value)
{
throw new NotImplementedException();
var layerProperty = (LayerProperty<int>) LayerPropertyViewModel.LayerProperty;
layerProperty.Value = (int) value;
}
protected override void UpdateKeyframeValue(BaseKeyframe keyframe, object value)
protected override void UpdateKeyframeValue(BaseKeyframe baseKeyframe, object value)
{
throw new NotImplementedException();
}
protected override void CreateKeyframeForValue(object value)
{
throw new NotImplementedException();
var keyframe = (Keyframe<int>) baseKeyframe;
keyframe.Value = (int) value;
}
}
}
@@ -3,18 +3,26 @@ using System.Collections.Generic;
using System.Linq;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Exceptions;
using Artemis.UI.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput
{
public abstract class PropertyInputViewModel : PropertyChangedBase
{
protected PropertyInputViewModel(IProfileEditorService profileEditorService)
{
ProfileEditorService = profileEditorService;
}
protected IProfileEditorService ProfileEditorService { get; set; }
public bool Initialized { get; private set; }
public abstract List<Type> CompatibleTypes { get; }
public LayerPropertyViewModel LayerPropertyViewModel { get; private set; }
public object InputValue
protected object InputValue
{
get => LayerPropertyViewModel.LayerProperty.KeyframeEngine.GetCurrentValue();
set => UpdateInputValue(value);
@@ -33,11 +41,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
Initialized = true;
}
public void Update()
{
NotifyOfPropertyChange(() => InputValue);
}
private void UpdateInputValue(object value)
{
// If keyframes are disabled, update the base value
@@ -47,13 +50,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
return;
}
// If on a keyframe, update the keyframe TODO: Make decisions..
// var currentKeyframe = LayerPropertyViewModel.LayerProperty.UntypedKeyframes.FirstOrDefault(k => k.Position == LayerPropertyViewModel.)
// Otherwise, add a new keyframe at the current position
// If on a keyframe, update the keyframe
var currentKeyframe = LayerPropertyViewModel.LayerProperty.UntypedKeyframes.FirstOrDefault(k => k.Position == ProfileEditorService.CurrentTime);
// Create a new keyframe if none found
if (currentKeyframe == null)
currentKeyframe = LayerPropertyViewModel.LayerProperty.CreateNewKeyframe(ProfileEditorService.CurrentTime);
UpdateKeyframeValue(currentKeyframe, value);
// Force the keyframe engine to update, the edited keyframe might affect the current keyframe progress
LayerPropertyViewModel.LayerProperty.KeyframeEngine.Update(0);
ProfileEditorService.UpdateSelectedProfileElement();
}
public abstract void Update();
protected abstract void UpdateBaseValue(object value);
protected abstract void UpdateKeyframeValue(BaseKeyframe keyframe, object value);
protected abstract void CreateKeyframeForValue(object value);
protected abstract void UpdateKeyframeValue(BaseKeyframe baseKeyframe, object value);
}
}
@@ -8,7 +8,7 @@
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:SKPointPropertyInputViewModel}">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal" KeyboardNavigation.IsTabStop="True">
<TextBlock Margin="0 0 5 0" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.LayerProperty.InputPrefix}" />
<TextBox Width="60"
Margin="0 2"
@@ -16,7 +16,8 @@
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
ToolTip="X-coordinate (horizontal)"
Cursor="/Resources/aero_drag_ew.cur" />
Text="{Binding X}"
Cursor="/Resources/aero_drag_ew.cur" KeyboardNavigation.IsTabStop="True" TabIndex="1" />
<TextBlock Margin="5 0" VerticalAlignment="Bottom">,</TextBlock>
<TextBox Width="60"
Margin="0 2"
@@ -24,7 +25,8 @@
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
ToolTip="Y-coordinate (vertical)"
Cursor="/Resources/aero_drag_ew.cur" />
Text="{Binding Y}"
Cursor="/Resources/aero_drag_ew.cur" KeyboardNavigation.IsTabStop="True" TabIndex="2" />
<TextBlock Margin="5 0 0 0" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.LayerProperty.InputAffix}" />
</StackPanel>
</UserControl>
@@ -1,27 +1,51 @@
using System;
using System.Collections.Generic;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Services.Interfaces;
using PropertyChanged;
using SkiaSharp;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput
{
public class SKPointPropertyInputViewModel : PropertyInputViewModel
{
public SKPointPropertyInputViewModel(IProfileEditorService profileEditorService) : base(profileEditorService)
{
}
public sealed override List<Type> CompatibleTypes { get; } = new List<Type> {typeof(SKPoint)};
// Since SKPoint is immutable we need to create properties that replace the SKPoint entirely
[DependsOn(nameof(InputValue))]
public float X
{
get => ((SKPoint) InputValue).X;
set => InputValue = new SKPoint(value, Y);
}
[DependsOn(nameof(InputValue))]
public float Y
{
get => ((SKPoint) InputValue).Y;
set => InputValue = new SKPoint(X, value);
}
public override void Update()
{
NotifyOfPropertyChange(() => X);
NotifyOfPropertyChange(() => Y);
}
protected override void UpdateBaseValue(object value)
{
throw new NotImplementedException();
var layerProperty = (LayerProperty<SKPoint>) LayerPropertyViewModel.LayerProperty;
layerProperty.Value = (SKPoint) value;
}
protected override void UpdateKeyframeValue(BaseKeyframe keyframe, object value)
protected override void UpdateKeyframeValue(BaseKeyframe baseKeyframe, object value)
{
throw new NotImplementedException();
}
protected override void CreateKeyframeForValue(object value)
{
throw new NotImplementedException();
var keyframe = (Keyframe<SKPoint>) baseKeyframe;
keyframe.Value = (SKPoint) value;
}
}
}
@@ -16,6 +16,7 @@
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
ToolTip="Height"
Text="{Binding Height}"
Cursor="/Resources/aero_drag_ew.cur" />
<TextBlock Margin="5 0" VerticalAlignment="Bottom">,</TextBlock>
<TextBox Width="60"
@@ -24,6 +25,7 @@
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
ToolTip="Width"
Text="{Binding Width}"
Cursor="/Resources/aero_drag_ew.cur" />
<TextBlock Margin="5 0 0 0" Width="10" VerticalAlignment="Bottom" Text="{Binding LayerPropertyViewModel.LayerProperty.InputAffix}" />
</StackPanel>
@@ -1,27 +1,51 @@
using System;
using System.Collections.Generic;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Services.Interfaces;
using PropertyChanged;
using SkiaSharp;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput
{
public class SKSizePropertyInputViewModel : PropertyInputViewModel
{
public SKSizePropertyInputViewModel(IProfileEditorService profileEditorService) : base(profileEditorService)
{
}
public sealed override List<Type> CompatibleTypes { get; } = new List<Type> {typeof(SKSize)};
// Since SKSize is immutable we need to create properties that replace the SKPoint entirely
[DependsOn(nameof(InputValue))]
public float Width
{
get => ((SKSize) InputValue).Width;
set => InputValue = new SKSize(value, Height);
}
[DependsOn(nameof(InputValue))]
public float Height
{
get => ((SKSize) InputValue).Height;
set => InputValue = new SKSize(Width, value);
}
public override void Update()
{
NotifyOfPropertyChange(() => Width);
NotifyOfPropertyChange(() => Height);
}
protected override void UpdateBaseValue(object value)
{
throw new NotImplementedException();
var layerProperty = (LayerProperty<SKSize>) LayerPropertyViewModel.LayerProperty;
layerProperty.Value = (SKSize) value;
}
protected override void UpdateKeyframeValue(BaseKeyframe keyframe, object value)
protected override void UpdateKeyframeValue(BaseKeyframe baseKeyframe, object value)
{
throw new NotImplementedException();
}
protected override void CreateKeyframeForValue(object value)
{
throw new NotImplementedException();
var keyframe = (Keyframe<SKSize>) baseKeyframe;
keyframe.Value = (SKSize) value;
}
}
}
@@ -22,7 +22,7 @@
ToolTip="Toggle key-framing"
Width="18"
Height="18"
IsChecked="{Binding KeyframesEnabled}"
IsChecked="{Binding LayerPropertyViewModel.KeyframesEnabled}"
VerticalAlignment="Center" Padding="-25">
<materialDesign:PackIcon Kind="Stopwatch" Height="13" Width="13" />
</ToggleButton>
@@ -12,5 +12,17 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
public LayerPropertyViewModel LayerPropertyViewModel { get; }
public PropertyInputViewModel PropertyInputViewModel { get; set; }
public override void Update(bool forceUpdate)
{
if (forceUpdate)
PropertyInputViewModel.Update();
else
{
// Only update if visible and if keyframes are enabled
if (LayerPropertyViewModel.Parent.IsExpanded && LayerPropertyViewModel.KeyframesEnabled)
PropertyInputViewModel.Update();
}
}
}
}
@@ -2,7 +2,12 @@
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
public class PropertyTreeItemViewModel : PropertyChangedBase
public abstract class PropertyTreeItemViewModel : PropertyChangedBase
{
/// <summary>
/// Updates the tree item's input if it is visible and has keyframes enabled
/// </summary>
/// <param name="forceUpdate">Force update regardless of visibility and keyframes</param>
public abstract void Update(bool forceUpdate);
}
}
@@ -21,5 +21,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
public LayerPropertyViewModel LayerPropertyViewModel { get; }
public BindableCollection<PropertyTreeItemViewModel> Children { get; set; }
public override void Update(bool forceUpdate)
{
foreach (var child in Children)
child.Update(forceUpdate);
}
}
}
@@ -1,15 +1,24 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.UI.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
public class PropertyTreeViewModel : PropertyChangedBase
{
public PropertyTreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel)
private readonly IProfileEditorService _profileEditorService;
public PropertyTreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IProfileEditorService profileEditorService)
{
_profileEditorService = profileEditorService;
LayerPropertiesViewModel = layerPropertiesViewModel;
PropertyTreeItemViewModels = new BindableCollection<PropertyTreeItemViewModel>();
_profileEditorService.CurrentTimeChanged += (sender, args) => Update(false);
_profileEditorService.SelectedProfileElementUpdated += (sender, args) => Update(true);
}
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
@@ -31,5 +40,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
PropertyTreeItemViewModels.Clear();
}
/// <summary>
/// Updates the tree item's input if it is visible and has keyframes enabled
/// </summary>
/// <param name="forceUpdate">Force update regardless of visibility and keyframes</param>
public void Update(bool forceUpdate)
{
foreach (var viewModel in PropertyTreeItemViewModels)
viewModel.Update(forceUpdate);
}
}
}
@@ -16,7 +16,7 @@
HorizontalAlignment="Left">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
@@ -1,16 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Artemis.UI.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class PropertyTimelineViewModel : PropertyChangedBase
{
public PropertyTimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel)
private readonly IProfileEditorService _profileEditorService;
public PropertyTimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IProfileEditorService profileEditorService)
{
_profileEditorService = profileEditorService;
LayerPropertiesViewModel = layerPropertiesViewModel;
PropertyTrackViewModels = new BindableCollection<PropertyTrackViewModel>();
_profileEditorService.SelectedProfileElementUpdated += (sender, args) => Update();
LayerPropertiesViewModel.PixelsPerSecondChanged += (sender, args) => UpdateKeyframePositions();
}
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
@@ -27,8 +35,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
Width = endTime.TotalSeconds * LayerPropertiesViewModel.PixelsPerSecond;
// Ensure the caret isn't outside the end time
if (LayerPropertiesViewModel.CurrentTime > endTime)
LayerPropertiesViewModel.CurrentTime = endTime;
if (_profileEditorService.CurrentTime > endTime)
_profileEditorService.CurrentTime = endTime;
}
public void PopulateProperties(List<LayerPropertyViewModel> properties)
@@ -51,5 +59,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
PropertyTrackViewModels.Clear();
}
public void UpdateKeyframePositions()
{
foreach (var viewModel in PropertyTrackViewModels)
viewModel.UpdateKeyframes(LayerPropertiesViewModel.PixelsPerSecond);
}
/// <summary>
/// Updates the time line's keyframes
/// </summary>
public void Update()
{
foreach (var viewModel in PropertyTrackViewModels)
viewModel.PopulateKeyframes();
UpdateEndTime();
}
}
}
@@ -12,7 +12,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
KeyframeViewModels = new BindableCollection<PropertyTrackKeyframeViewModel>();
PopulateKeyframes();
UpdateKeyframes(propertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond);
UpdateKeyframes(PropertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond);
}
public PropertyTimelineViewModel PropertyTimelineViewModel { get; }
@@ -21,12 +21,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
public void PopulateKeyframes()
{
// Remove old keyframes
foreach (var viewModel in KeyframeViewModels.ToList())
{
if (!LayerPropertyViewModel.LayerProperty.UntypedKeyframes.Contains(viewModel.Keyframe))
KeyframeViewModels.Remove(viewModel);
}
// Add new keyframes
foreach (var keyframe in LayerPropertyViewModel.LayerProperty.UntypedKeyframes)
{
if (KeyframeViewModels.Any(k => k.Keyframe == keyframe))
continue;
KeyframeViewModels.Add(new PropertyTrackKeyframeViewModel(keyframe));
}
UpdateKeyframes(PropertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond);
}
public void UpdateKeyframes(int pixelsPerSecond)
@@ -42,7 +42,7 @@
<!-- The part of the layer's shape that is inside the layer -->
<Path Data="{Binding ShapeGeometry, Mode=OneWay}">
<Path.Fill>
<SolidColorBrush Color="{StaticResource Accent700}" Opacity="0.35" />
<SolidColorBrush Color="{StaticResource Accent700}" Opacity="0.25" />
</Path.Fill>
<Path.Stroke>
<SolidColorBrush Color="{StaticResource Accent700}" />
@@ -24,8 +24,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
Update();
Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated;
_profileEditorService.SelectedProfileElementChanged += OnSelectedProfileElementChanged;
_profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated;
_profileEditorService.CurrentTimeChanged += ProfileEditorServiceOnCurrentTimeChanged;
}
public Layer Layer { get; }
public Geometry LayerGeometry { get; set; }
@@ -119,8 +121,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
shapeGeometry.Freeze();
ShapeGeometry = shapeGeometry;
}
private void CreateViewportRectangle()
{
if (!Layer.Leds.Any() || Layer.LayerShape == null)
@@ -190,6 +191,20 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
IsSelected = _profileEditorService.SelectedProfileElement == Layer;
}
private void OnSelectedProfileElementUpdated(object sender, EventArgs e)
{
if (IsSelected)
Update();
}
private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e)
{
if (!IsSelected)
return;
CreateShapeGeometry();
CreateViewportRectangle();
}
public void Dispose()
{
Layer.RenderPropertiesUpdated -= LayerOnRenderPropertiesUpdated;