Files
Artemis/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackKeyframeViewModel.cs
T

133 lines
5.4 KiB
C#

using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.Core.Utilities;
using Artemis.UI.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class PropertyTrackKeyframeViewModel : PropertyChangedBase
{
private readonly IProfileEditorService _profileEditorService;
private int _pixelsPerSecond;
public PropertyTrackKeyframeViewModel(PropertyTrackViewModel propertyTrackViewModel, BaseKeyframe keyframe, IProfileEditorService profileEditorService)
{
_profileEditorService = profileEditorService;
PropertyTrackViewModel = propertyTrackViewModel;
Keyframe = keyframe;
EasingViewModels = new BindableCollection<PropertyTrackEasingViewModel>();
CreateEasingViewModels();
}
public bool IsSelected { get; set; }
public PropertyTrackViewModel PropertyTrackViewModel { get; }
public BaseKeyframe Keyframe { get; }
public BindableCollection<PropertyTrackEasingViewModel> EasingViewModels { get; set; }
public double X { get; set; }
public string Timestamp { get; set; }
public UIElement ParentView { get; set; }
public void Update(int pixelsPerSecond)
{
_pixelsPerSecond = pixelsPerSecond;
X = pixelsPerSecond * Keyframe.Position.TotalSeconds;
Timestamp = $"{Math.Floor(Keyframe.Position.TotalSeconds):00}.{Keyframe.Position.Milliseconds:000}";
}
#region Keyframe movement
public void KeyframeMouseDown(object sender, MouseButtonEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift) && !IsSelected)
PropertyTrackViewModel.PropertyTimelineViewModel.SelectKeyframe(this, true, false);
else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
PropertyTrackViewModel.PropertyTimelineViewModel.SelectKeyframe(this, false, true);
else if (!IsSelected)
PropertyTrackViewModel.PropertyTimelineViewModel.SelectKeyframe(this, false, false);
((IInputElement) sender).CaptureMouse();
}
public void KeyframeMouseUp(object sender, MouseButtonEventArgs e)
{
((IInputElement) sender).ReleaseMouseCapture();
_profileEditorService.UpdateSelectedProfileElement();
}
public void KeyframeMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
// Get the parent grid, need that for our position
var x = Math.Max(0, e.GetPosition(ParentView).X);
var newTime = TimeSpan.FromSeconds(x / _pixelsPerSecond);
// Round the time to something that fits the current zoom level
if (_pixelsPerSecond < 200)
newTime = TimeSpan.FromMilliseconds(Math.Round(newTime.TotalMilliseconds / 5.0) * 5.0);
else if (_pixelsPerSecond < 500)
newTime = TimeSpan.FromMilliseconds(Math.Round(newTime.TotalMilliseconds / 2.0) * 2.0);
else
newTime = TimeSpan.FromMilliseconds(Math.Round(newTime.TotalMilliseconds));
// If shift is held, snap to the current time
// Take a tolerance of 5 pixels (half a keyframe width)
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
{
var tolerance = 1000f / _pixelsPerSecond * 5;
if (Math.Abs(_profileEditorService.CurrentTime.TotalMilliseconds - newTime.TotalMilliseconds) < tolerance)
newTime = _profileEditorService.CurrentTime;
}
PropertyTrackViewModel.PropertyTimelineViewModel.MoveSelectedKeyframes(newTime - Keyframe.Position);
}
}
#endregion
#region Context menu actions
public void Copy()
{
var keyframe = PropertyTrackViewModel.LayerPropertyViewModel.LayerProperty.CreateNewKeyframe(Keyframe.Position, Keyframe.BaseValue);
keyframe.EasingFunction = Keyframe.EasingFunction;
_profileEditorService.UpdateSelectedProfileElement();
}
public void Delete()
{
PropertyTrackViewModel.LayerPropertyViewModel.LayerProperty.RemoveKeyframe(Keyframe);
_profileEditorService.UpdateSelectedProfileElement();
}
#endregion
#region Easing
private void CreateEasingViewModels()
{
foreach (Easings.Functions value in Enum.GetValues(typeof(Easings.Functions)))
EasingViewModels.Add(new PropertyTrackEasingViewModel(this, value));
}
public void SelectEasingMode(PropertyTrackEasingViewModel easingViewModel)
{
Keyframe.EasingFunction = easingViewModel.EasingFunction;
// Set every selection to false except on the VM that made the change
foreach (var propertyTrackEasingViewModel in EasingViewModels.Where(vm => vm != easingViewModel))
propertyTrackEasingViewModel.IsEasingModeSelected = false;
_profileEditorService.UpdateSelectedProfileElement();
}
#endregion
}
}