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(); CreateEasingViewModels(); } public bool IsSelected { get; set; } public PropertyTrackViewModel PropertyTrackViewModel { get; } public BaseKeyframe Keyframe { get; } public BindableCollection 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 } }