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)); } }
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); } }
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); } } }