From 602ce698d5633a3b655682a1b94d952a4adc99ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 18 Dec 2019 17:21:38 +0900 Subject: [PATCH] Fix storyboard vectorscale and scale cross-pollution --- .../Formats/LegacyStoryboardDecoder.cs | 4 +-- osu.Game/Storyboards/CommandTimelineGroup.cs | 3 ++- .../Drawables/DrawableStoryboardAnimation.cs | 27 +++++++++++++++++-- .../Drawables/DrawableStoryboardSprite.cs | 27 +++++++++++++++++-- osu.Game/Storyboards/Drawables/IFlippable.cs | 8 +++--- .../Storyboards/Drawables/IVectorScalable.cs | 21 +++++++++++++++ osu.Game/Storyboards/StoryboardSprite.cs | 20 ++++++++++---- 7 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 osu.Game/Storyboards/Drawables/IVectorScalable.cs diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index ccd46ab559..756aa45eed 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -176,7 +176,7 @@ namespace osu.Game.Beatmaps.Formats { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; - timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue)); + timelineGroup?.Scale.Add(easing, startTime, endTime, startValue, endValue); break; } @@ -186,7 +186,7 @@ namespace osu.Game.Beatmaps.Formats var startY = float.Parse(split[5], CultureInfo.InvariantCulture); var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; - timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); + timelineGroup?.VectorScale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); break; } diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index 364c971874..7b6e667d4f 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -16,7 +16,8 @@ namespace osu.Game.Storyboards { public CommandTimeline X = new CommandTimeline(); public CommandTimeline Y = new CommandTimeline(); - public CommandTimeline Scale = new CommandTimeline(); + public CommandTimeline Scale = new CommandTimeline(); + public CommandTimeline VectorScale = new CommandTimeline(); public CommandTimeline Rotation = new CommandTimeline(); public CommandTimeline Colour = new CommandTimeline(); public CommandTimeline Alpha = new CommandTimeline(); diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index 4f8e39fa1b..a452c7540d 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -8,21 +8,44 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Textures; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardAnimation : TextureAnimation, IFlippable + public class DrawableStoryboardAnimation : TextureAnimation, IFlippable, IVectorScalable { public StoryboardAnimation Animation { get; private set; } public bool FlipH { get; set; } public bool FlipV { get; set; } + private Vector2 vectorScale = Vector2.One; + + public Vector2 VectorScale + { + get => vectorScale; + set + { + if (Math.Abs(value.X) < Precision.FLOAT_EPSILON) + value.X = Precision.FLOAT_EPSILON; + if (Math.Abs(value.Y) < Precision.FLOAT_EPSILON) + value.Y = Precision.FLOAT_EPSILON; + + if (vectorScale == value) + return; + + if (!Validation.IsFinite(value)) throw new ArgumentException($@"{nameof(VectorScale)} must be finite, but is {value}."); + + vectorScale = value; + Invalidate(Invalidation.MiscGeometry); + } + } + public override bool RemoveWhenNotAlive => false; protected override Vector2 DrawScale - => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y) * VectorScale; public override Anchor Origin { diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index ff48dab7e5..42c7cfacb2 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -8,21 +8,44 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardSprite : Sprite, IFlippable + public class DrawableStoryboardSprite : Sprite, IFlippable, IVectorScalable { public StoryboardSprite Sprite { get; private set; } public bool FlipH { get; set; } public bool FlipV { get; set; } + private Vector2 vectorScale = Vector2.One; + + public Vector2 VectorScale + { + get => vectorScale; + set + { + if (Math.Abs(value.X) < Precision.FLOAT_EPSILON) + value.X = Precision.FLOAT_EPSILON; + if (Math.Abs(value.Y) < Precision.FLOAT_EPSILON) + value.Y = Precision.FLOAT_EPSILON; + + if (vectorScale == value) + return; + + if (!Validation.IsFinite(value)) throw new ArgumentException($@"{nameof(VectorScale)} must be finite, but is {value}."); + + vectorScale = value; + Invalidate(Invalidation.MiscGeometry); + } + } + public override bool RemoveWhenNotAlive => false; protected override Vector2 DrawScale - => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y) * VectorScale; public override Anchor Origin { diff --git a/osu.Game/Storyboards/Drawables/IFlippable.cs b/osu.Game/Storyboards/Drawables/IFlippable.cs index 1c4cdde22d..165b3d97cc 100644 --- a/osu.Game/Storyboards/Drawables/IFlippable.cs +++ b/osu.Game/Storyboards/Drawables/IFlippable.cs @@ -6,13 +6,13 @@ using osu.Framework.Graphics.Transforms; namespace osu.Game.Storyboards.Drawables { - public interface IFlippable : ITransformable + internal interface IFlippable : ITransformable { bool FlipH { get; set; } bool FlipV { get; set; } } - public class TransformFlipH : Transform + internal class TransformFlipH : Transform { private bool valueAt(double time) => time < EndTime ? StartValue : EndValue; @@ -23,7 +23,7 @@ namespace osu.Game.Storyboards.Drawables protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipH; } - public class TransformFlipV : Transform + internal class TransformFlipV : Transform { private bool valueAt(double time) => time < EndTime ? StartValue : EndValue; @@ -34,7 +34,7 @@ namespace osu.Game.Storyboards.Drawables protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipV; } - public static class FlippableExtensions + internal static class FlippableExtensions { /// /// Adjusts after a delay. diff --git a/osu.Game/Storyboards/Drawables/IVectorScalable.cs b/osu.Game/Storyboards/Drawables/IVectorScalable.cs new file mode 100644 index 0000000000..fcc407d460 --- /dev/null +++ b/osu.Game/Storyboards/Drawables/IVectorScalable.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; +using osuTK; + +namespace osu.Game.Storyboards.Drawables +{ + internal interface IVectorScalable : ITransformable + { + Vector2 VectorScale { get; set; } + } + + internal static class VectorScalableExtensions + { + public static TransformSequence VectorScaleTo(this T target, Vector2 newVectorScale, double duration = 0, Easing easing = Easing.None) + where T : class, IVectorScalable + => target.TransformTo(nameof(IVectorScalable.VectorScale), newVectorScale, duration, easing); + } +} diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index d5e69fd103..abf9f58804 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -65,20 +65,30 @@ namespace osu.Game.Storyboards { applyCommands(drawable, getCommands(g => g.X, triggeredGroups), (d, value) => d.X = value, (d, value, duration, easing) => d.MoveToX(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Y, triggeredGroups), (d, value) => d.Y = value, (d, value, duration, easing) => d.MoveToY(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.Scale, triggeredGroups), (d, value) => d.Scale = value, (d, value, duration, easing) => d.ScaleTo(value, duration, easing)); + applyCommands(drawable, getCommands(g => g.Scale, triggeredGroups), (d, value) => d.Scale = new Vector2(value), (d, value, duration, easing) => d.ScaleTo(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Rotation, triggeredGroups), (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Colour, triggeredGroups), (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); applyCommands(drawable, getCommands(g => g.Alpha, triggeredGroups), (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); - applyCommands(drawable, getCommands(g => g.BlendingParameters, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); + applyCommands(drawable, getCommands(g => g.BlendingParameters, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), + false); + + if (drawable is IVectorScalable vectorScalable) + { + applyCommands(drawable, getCommands(g => g.VectorScale, triggeredGroups), (d, value) => vectorScalable.VectorScale = value, + (d, value, duration, easing) => vectorScalable.VectorScaleTo(value, duration, easing)); + } if (drawable is IFlippable flippable) { - applyCommands(drawable, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), false); - applyCommands(drawable, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false); + applyCommands(drawable, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), + false); + applyCommands(drawable, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), + false); } } - private void applyCommands(Drawable drawable, IEnumerable.TypedCommand> commands, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, bool alwaysInitialize = true) + private void applyCommands(Drawable drawable, IEnumerable.TypedCommand> commands, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, + bool alwaysInitialize = true) where T : struct { var initialized = false;