1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 23:12:56 +08:00

Fix storyboard vectorscale and scale cross-polluting each other (#7259)

Fix storyboard vectorscale and scale cross-polluting each other
This commit is contained in:
Dean Herbert 2019-12-18 17:41:55 +09:00 committed by GitHub
commit 53d6693c89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 94 additions and 16 deletions

View File

@ -176,7 +176,7 @@ namespace osu.Game.Beatmaps.Formats
{ {
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; 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; break;
} }
@ -186,7 +186,7 @@ namespace osu.Game.Beatmaps.Formats
var startY = float.Parse(split[5], CultureInfo.InvariantCulture); var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; 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; break;
} }

View File

@ -16,7 +16,8 @@ namespace osu.Game.Storyboards
{ {
public CommandTimeline<float> X = new CommandTimeline<float>(); public CommandTimeline<float> X = new CommandTimeline<float>();
public CommandTimeline<float> Y = new CommandTimeline<float>(); public CommandTimeline<float> Y = new CommandTimeline<float>();
public CommandTimeline<Vector2> Scale = new CommandTimeline<Vector2>(); public CommandTimeline<float> Scale = new CommandTimeline<float>();
public CommandTimeline<Vector2> VectorScale = new CommandTimeline<Vector2>();
public CommandTimeline<float> Rotation = new CommandTimeline<float>(); public CommandTimeline<float> Rotation = new CommandTimeline<float>();
public CommandTimeline<Color4> Colour = new CommandTimeline<Color4>(); public CommandTimeline<Color4> Colour = new CommandTimeline<Color4>();
public CommandTimeline<float> Alpha = new CommandTimeline<float>(); public CommandTimeline<float> Alpha = new CommandTimeline<float>();

View File

@ -8,21 +8,44 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Animations;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
namespace osu.Game.Storyboards.Drawables namespace osu.Game.Storyboards.Drawables
{ {
public class DrawableStoryboardAnimation : TextureAnimation, IFlippable public class DrawableStoryboardAnimation : TextureAnimation, IFlippable, IVectorScalable
{ {
public StoryboardAnimation Animation { get; private set; } public StoryboardAnimation Animation { get; private set; }
public bool FlipH { get; set; } public bool FlipH { get; set; }
public bool FlipV { 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; public override bool RemoveWhenNotAlive => false;
protected override Vector2 DrawScale 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 public override Anchor Origin
{ {

View File

@ -8,21 +8,44 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
namespace osu.Game.Storyboards.Drawables namespace osu.Game.Storyboards.Drawables
{ {
public class DrawableStoryboardSprite : Sprite, IFlippable public class DrawableStoryboardSprite : Sprite, IFlippable, IVectorScalable
{ {
public StoryboardSprite Sprite { get; private set; } public StoryboardSprite Sprite { get; private set; }
public bool FlipH { get; set; } public bool FlipH { get; set; }
public bool FlipV { 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; public override bool RemoveWhenNotAlive => false;
protected override Vector2 DrawScale 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 public override Anchor Origin
{ {

View File

@ -6,13 +6,13 @@ using osu.Framework.Graphics.Transforms;
namespace osu.Game.Storyboards.Drawables namespace osu.Game.Storyboards.Drawables
{ {
public interface IFlippable : ITransformable internal interface IFlippable : ITransformable
{ {
bool FlipH { get; set; } bool FlipH { get; set; }
bool FlipV { get; set; } bool FlipV { get; set; }
} }
public class TransformFlipH : Transform<bool, IFlippable> internal class TransformFlipH : Transform<bool, IFlippable>
{ {
private bool valueAt(double time) private bool valueAt(double time)
=> time < EndTime ? StartValue : EndValue; => time < EndTime ? StartValue : EndValue;
@ -23,7 +23,7 @@ namespace osu.Game.Storyboards.Drawables
protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipH; protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipH;
} }
public class TransformFlipV : Transform<bool, IFlippable> internal class TransformFlipV : Transform<bool, IFlippable>
{ {
private bool valueAt(double time) private bool valueAt(double time)
=> time < EndTime ? StartValue : EndValue; => time < EndTime ? StartValue : EndValue;
@ -34,7 +34,7 @@ namespace osu.Game.Storyboards.Drawables
protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipV; protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipV;
} }
public static class FlippableExtensions internal static class FlippableExtensions
{ {
/// <summary> /// <summary>
/// Adjusts <see cref="IFlippable.FlipH"/> after a delay. /// Adjusts <see cref="IFlippable.FlipH"/> after a delay.

View File

@ -0,0 +1,21 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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<T> VectorScaleTo<T>(this T target, Vector2 newVectorScale, double duration = 0, Easing easing = Easing.None)
where T : class, IVectorScalable
=> target.TransformTo(nameof(IVectorScalable.VectorScale), newVectorScale, duration, easing);
}
}

View File

@ -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.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.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.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.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.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) 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.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration),
applyCommands(drawable, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false); 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<T>(Drawable drawable, IEnumerable<CommandTimeline<T>.TypedCommand> commands, DrawablePropertyInitializer<T> initializeProperty, DrawableTransformer<T> transform, bool alwaysInitialize = true) private void applyCommands<T>(Drawable drawable, IEnumerable<CommandTimeline<T>.TypedCommand> commands, DrawablePropertyInitializer<T> initializeProperty, DrawableTransformer<T> transform,
bool alwaysInitialize = true)
where T : struct where T : struct
{ {
var initialized = false; var initialized = false;