diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 6fde7263da..d538960a37 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -428,9 +428,9 @@ namespace osu.Game.Beatmaps.Formats var type = split[4]; switch (type) { - case "A": timelineGroup?.Additive.Add(easing, startTime, endTime, true, true); break; - case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, true); break; - case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, true); break; + case "A": timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit); break; + case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime); break; + case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime); break; } } break; diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index a42aca7c28..332a6f79cb 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -3,6 +3,7 @@ using OpenTK; using OpenTK.Graphics; +using osu.Framework.Graphics; using System.Collections.Generic; using System.Linq; @@ -18,7 +19,7 @@ namespace osu.Game.Storyboards public CommandTimeline Rotation = new CommandTimeline(); public CommandTimeline Colour = new CommandTimeline(); public CommandTimeline Alpha = new CommandTimeline(); - public CommandTimeline Additive = new CommandTimeline(); + public CommandTimeline BlendingMode = new CommandTimeline(); public CommandTimeline FlipH = new CommandTimeline(); public CommandTimeline FlipV = new CommandTimeline(); @@ -32,7 +33,7 @@ namespace osu.Game.Storyboards yield return Rotation; yield return Colour; yield return Alpha; - yield return Additive; + yield return BlendingMode; yield return FlipH; yield return FlipV; } diff --git a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs new file mode 100644 index 0000000000..436b4aafeb --- /dev/null +++ b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs @@ -0,0 +1,27 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; + +namespace osu.Game.Storyboards.Drawables +{ + public static class DrawablesExtensions + { + /// + /// Adjusts after a delay. + /// + /// A to which further transforms can be added. + public static TransformSequence TransformBlendingMode(this T drawable, BlendingMode newValue, double delay = 0) + where T : Drawable + => drawable.TransformTo(drawable.PopulateTransform(new TransformBlendingMode(), newValue, delay)); + } + + public class TransformBlendingMode : Transform + { + private BlendingMode valueAt(double time) + => time < EndTime ? StartValue : EndValue; + + public override string TargetMember => nameof(Drawable.BlendingMode); + + protected override void Apply(Drawable d, double time) => d.BlendingMode = valueAt(time); + protected override void ReadIntoStartValue(Drawable d) => StartValue = d.BlendingMode; + } +} diff --git a/osu.Game/Storyboards/Drawables/IFlippable.cs b/osu.Game/Storyboards/Drawables/IFlippable.cs index a1899d1411..4d21c9d140 100644 --- a/osu.Game/Storyboards/Drawables/IFlippable.cs +++ b/osu.Game/Storyboards/Drawables/IFlippable.cs @@ -1,11 +1,55 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; + namespace osu.Game.Storyboards.Drawables { - public interface IFlippable + public interface IFlippable : ITransformable { bool FlipH { get; set; } bool FlipV { get; set; } } + + public class TransformFlipH : Transform + { + private bool valueAt(double time) + => time < EndTime ? StartValue : EndValue; + + public override string TargetMember => nameof(IFlippable.FlipH); + + protected override void Apply(IFlippable d, double time) => d.FlipH = valueAt(time); + protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipH; + } + + public class TransformFlipV : Transform + { + private bool valueAt(double time) + => time < EndTime ? StartValue : EndValue; + + public override string TargetMember => nameof(IFlippable.FlipV); + + protected override void Apply(IFlippable d, double time) => d.FlipV = valueAt(time); + protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipV; + } + + public static class FlippableExtensions + { + /// + /// Adjusts after a delay. + /// + /// A to which further transforms can be added. + public static TransformSequence TransformFlipH(this T flippable, bool newValue, double delay = 0) + where T : IFlippable + => flippable.TransformTo(flippable.PopulateTransform(new TransformFlipH(), newValue, delay)); + + /// + /// Adjusts after a delay. + /// + /// A to which further transforms can be added. + public static TransformSequence TransformFlipV(this T flippable, bool newValue, double delay = 0) + where T : IFlippable + => flippable.TransformTo(flippable.PopulateTransform(new TransformFlipV(), newValue, delay)); + } } diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/SpriteDefinition.cs index a4697aabfb..c410fd8807 100644 --- a/osu.Game/Storyboards/SpriteDefinition.cs +++ b/osu.Game/Storyboards/SpriteDefinition.cs @@ -62,27 +62,27 @@ namespace osu.Game.Storyboards applyCommands(drawable, triggeredGroups, g => g.Rotation, (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); applyCommands(drawable, triggeredGroups, g => g.Colour, (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); applyCommands(drawable, triggeredGroups, g => g.Alpha, (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); - - if (getAggregatedCommands(g => g.Additive, triggeredGroups).Any()) - drawable.BlendingMode = BlendingMode.Additive; + applyCommands(drawable, triggeredGroups, g => g.BlendingMode, (d, value) => d.BlendingMode = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); var flippable = drawable as IFlippable; if (flippable != null) { - flippable.FlipH = getAggregatedCommands(g => g.FlipH, triggeredGroups).Any(); - flippable.FlipV = getAggregatedCommands(g => g.FlipV, triggeredGroups).Any(); + applyCommands(drawable, triggeredGroups, g => g.FlipH, (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), false); + applyCommands(drawable, triggeredGroups, g => g.FlipV, (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false); } } private void applyCommands(Drawable drawable, IEnumerable> triggeredGroups, - CommandTimelineSelector timelineSelector, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform) + CommandTimelineSelector timelineSelector, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, bool alwaysInitialize = true) + where T : struct { var initialized = false; foreach (var command in getAggregatedCommands(timelineSelector, triggeredGroups).OrderBy(l => l)) { if (!initialized) { - initializeProperty(drawable, command.StartValue); + if (alwaysInitialize || command.StartTime == command.EndTime) + initializeProperty.Invoke(drawable, command.StartValue); initialized = true; } using (drawable.BeginAbsoluteSequence(command.StartTime)) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8c91a9e80a..7e068979bf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -86,6 +86,7 @@ +