private void ScaleKeyframes() { var boundaries = GridSelection.GetSelectionBoundaries(); if (boundaries.HasValue || Scale < Mathf.ZeroTolerance) { var saved = new List <IKeyframe>(); for (int i = boundaries.Value.Top; i <= boundaries.Value.Bottom; ++i) { if (!(Document.Current.Rows[i].Components.Get <NodeRow>()?.Node is IAnimationHost animable)) { continue; } foreach (var animator in animable.Animators.ToList()) { saved.Clear(); IEnumerable <IKeyframe> keys = animator.ReadonlyKeys.Where(k => k.Frame >= boundaries.Value.Left && k.Frame < boundaries.Value.Right ).ToList(); if (Scale < 1) { keys = keys.Reverse().ToList(); } foreach (var key in keys) { saved.Add(key); RemoveKeyframe.Perform(animator, key.Frame); } foreach (var key in saved) { // The formula should behave similiar to stretching animation with mouse int newFrame = (int)( boundaries.Value.Left + (key.Frame - boundaries.Value.Left) * (1 + (boundaries.Value.Left - boundaries.Value.Right) * Scale) / (1 + boundaries.Value.Left - boundaries.Value.Right) ); var newKey = key.Clone(); newKey.Frame = newFrame; SetAnimableProperty.Perform( animable, animator.TargetPropertyPath, newKey.Value, createAnimatorIfNeeded: true, createInitialKeyframeForNewAnimator: false, newKey.Frame ); SetKeyframe.Perform(animable, animator.TargetPropertyPath, Document.Current.AnimationId, newKey); } } } ClearGridSelection.Perform(); for (int i = boundaries.Value.Top; i <= boundaries.Value.Bottom; ++i) { SelectGridSpan.Perform(i, boundaries.Value.Left, (int)(boundaries.Value.Left + (boundaries.Value.Right - boundaries.Value.Left) * Scale)); } } else { Document.Current.History.RollbackTransaction(); } }
private void ScaleKeyframes() { if (GridSelection.GetSelectionBoundaries(out var boundaries) && Scale > Mathf.ZeroTolerance) { var processed = new HashSet <IAnimator>(); var saved = new List <IKeyframe>(); foreach (var animable in GridSelection.EnumerateAnimators(boundaries)) { foreach (var animator in animable.Animators) { if (animator.AnimationId != Document.Current.AnimationId || processed.Contains(animator)) { continue; } processed.Add(animator); saved.Clear(); IEnumerable <IKeyframe> keys = animator.ReadonlyKeys.Where(k => k.Frame >= boundaries.Left && k.Frame < boundaries.Right ).ToList(); if (Scale < 1) { keys = keys.Reverse().ToList(); } foreach (var key in keys) { saved.Add(key); RemoveKeyframe.Perform(animator, key.Frame); } foreach (var key in saved) { // The formula should behave similiar to stretching animation with mouse int newFrame = (int)( boundaries.Left + (key.Frame - boundaries.Left) * (1 + (boundaries.Left - boundaries.Right) * Scale) / (1 + boundaries.Left - boundaries.Right) ); var newKey = key.Clone(); newKey.Frame = newFrame; SetAnimableProperty.Perform( animable.Host, animator.TargetPropertyPath, newKey.Value, createAnimatorIfNeeded: true, createInitialKeyframeForNewAnimator: false, newKey.Frame ); SetKeyframe.Perform(animable.Host, animator.TargetPropertyPath, Document.Current.AnimationId, newKey); } } } ClearGridSelection.Perform(); for (int i = boundaries.Top; i <= boundaries.Bottom; ++i) { SelectGridSpan.Perform(i, boundaries.Left, (int)(boundaries.Left + (boundaries.Right - boundaries.Left) * Scale)); } }
public IEnumerator <object> Task() { while (true) { if (!TimelineUserPreferences.Instance.AnimationStretchMode) { yield return(null); continue; } var boundaries = GridSelection.GetSelectionBoundaries(); if (boundaries == null || boundaries.Value.Right - boundaries.Value.Left < 2) { yield return(null); continue; } var topLeft = grid.CellToGridCoordinates(boundaries.Value.Top, boundaries.Value.Left); var bottomRight = grid.CellToGridCoordinates(boundaries.Value.Bottom + 1, boundaries.Value.Right); var mousePosition = grid.ContentWidget.LocalMousePosition(); if (mousePosition.Y < topLeft.Y || mousePosition.Y > bottomRight.Y) { yield return(null); continue; } if (mousePosition.X - topLeft.X < 0 && mousePosition.X - topLeft.X > -10) { Utils.ChangeCursorIfDefault(MouseCursor.SizeWE); if (input.ConsumeKeyPress(Key.Mouse0)) { yield return(Drag(boundaries.Value, DragSide.Left)); } } else if (mousePosition.X - bottomRight.X > 0 && mousePosition.X - bottomRight.X < 10) { Utils.ChangeCursorIfDefault(MouseCursor.SizeWE); if (input.ConsumeKeyPress(Key.Mouse0)) { yield return(Drag(boundaries.Value, DragSide.Right)); } } yield return(null); } }
private void Save(IntRectangle boundaries) { savedPositions.Clear(); savedKeyframes.Clear(); savedMarkerPositions.Clear(); savedMarkers.Clear(); var length = boundaries.Right - boundaries.Left - 1; foreach (var animable in GridSelection.EnumerateAnimators(boundaries)) { foreach (var animator in animable.Animators) { if (animator.AnimationId != Document.Current.AnimationId) { continue; } savedKeyframes.Add(animator, new List <IKeyframe>()); var keys = animator.Keys.Where(k => boundaries.Left <= k.Frame && k.Frame < boundaries.Right ); foreach (var key in keys) { savedPositions.Add(key, ((double)key.Frame - boundaries.Left) / length); savedKeyframes[animator].Add(key); } } } var markers = Document.Current.Animation.Markers.Where(k => boundaries.Left <= k.Frame && k.Frame < boundaries.Right); foreach (var marker in markers) { savedMarkerPositions.Add(marker, ((double)marker.Frame - boundaries.Left) / length); savedMarkers.Add(marker); } }
public void Show() { var menu = new Menu(); var frameUnderMouse = Timeline.Instance.Grid.CellUnderMouse().X; var marker = Document.Current.Animation.Markers.GetByFrame(frameUnderMouse); menu.Add(new Command(marker == null ? "Add Marker" : "Edit Marker", () => ShowMarkerDialog(frameUnderMouse))); menu.Add(new Command("Copy Marker", () => CopyMarker(marker)) { Enabled = marker != null }); menu.Add(new Command("Paste Marker", () => PasteMarker(frameUnderMouse)) { Enabled = CanParseMarkerFromClipboard() }); menu.Add(new Command("Delete Marker", () => DeleteMarker(marker)) { Enabled = marker != null }); menu.Add(Command.MenuSeparator); menu.Add(new Command(TimelineCommands.CopyMarkers.Text, CopyMarkers) { Enabled = Document.Current.Animation.Markers.Count > 0 }); menu.Add(new Command(TimelineCommands.PasteMarkers.Text, PasteMarkers) { Enabled = CanParseMarkersFromClipboard() }); menu.Add(new Command(TimelineCommands.DeleteMarkers.Text, DeleteMarkers) { Enabled = Document.Current.Animation.Markers.Count > 0 }); menu.Add(new Command(TimelineCommands.DeleteMarkersInRange.Text, DeleteMarkersInRange) { Enabled = GridSelection.GetSelectionBoundaries(out _) && Document.Current.Animation.Markers.Count > 0 }); menu.Popup(); }
private void Stretch(IntRectangle boundaries, DragSide side, int newPos, bool stretchMarkers) { int length; if (side == DragSide.Left) { length = boundaries.Right - newPos - 1; } else { length = newPos - boundaries.Left - 1; } int oldLength = boundaries.Right - boundaries.Left - 1; var processed = new HashSet <IAnimator>(); foreach (var animable in GridSelection.EnumerateAnimators(boundaries)) { foreach (var animator in animable.Animators) { if (animator.AnimationId != Document.Current.AnimationId || processed.Contains(animator) || !savedKeyframes.ContainsKey(animator)) { continue; } processed.Add(animator); IEnumerable <IKeyframe> saved = savedKeyframes[animator]; if ( side == DragSide.Left && length < oldLength || side == DragSide.Right && length > oldLength ) { saved = saved.Reverse(); } foreach (var key in saved) { RemoveKeyframe.Perform(animator, key.Frame); } foreach (var key in saved) { double relpos = savedPositions[key]; int newFrame; if (side == DragSide.Left) { newFrame = (int)Math.Round(newPos + relpos * length); } else { newFrame = (int)Math.Round(boundaries.Left + relpos * length); } var newKey = key.Clone(); newKey.Frame = newFrame; SetAnimableProperty.Perform( animable.Host, animator.TargetPropertyPath, newKey.Value, createAnimatorIfNeeded: true, createInitialKeyframeForNewAnimator: false, newKey.Frame ); SetKeyframe.Perform(animable.Host, animator.TargetPropertyPath, Document.Current.AnimationId, newKey); } } } if (stretchMarkers) { foreach (var marker in savedMarkers) { DeleteMarker.Perform(marker, removeDependencies: false); } foreach (var marker in savedMarkers) { double relpos = savedMarkerPositions[marker]; int newFrame; if (side == DragSide.Left) { newFrame = (int)Math.Round(newPos + relpos * length); } else { newFrame = (int)Math.Round(boundaries.Left + relpos * length); } var newMarker = marker.Clone(); newMarker.Frame = newFrame; SetMarker.Perform(newMarker, removeDependencies: false); } } }