diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs
index 17e94a8b5f..f78825ffb1 100644
--- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs
+++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs
@@ -110,7 +110,9 @@ namespace osu.Game.Tests.Beatmaps.Formats
Assert.AreEqual(2000, background.Elements[0].StartTime);
Assert.AreEqual(2000, (background.Elements[0] as StoryboardAnimation)?.EarliestTransformTime);
- Assert.AreEqual(12000, (background.Elements[0] as StoryboardAnimation)?.GetEndTime());
+
+ Assert.AreEqual(3000, (background.Elements[0] as StoryboardAnimation)?.GetEndTime());
+ Assert.AreEqual(12000, (background.Elements[0] as StoryboardAnimation)?.EndTimeForDisplay);
}
}
diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
index fbdaad1cd8..8f4250799e 100644
--- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
+++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
@@ -311,6 +311,7 @@ namespace osu.Game.Tests.Visual.Background
public bool IsDrawable => true;
public double StartTime => double.MinValue;
public double EndTime => double.MaxValue;
+ public double EndTimeForDisplay => double.MaxValue;
public Drawable CreateDrawable() => new DrawableTestStoryboardElement();
}
diff --git a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs
index c8daeb3b3d..9eed139ad4 100644
--- a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs
+++ b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs
@@ -12,9 +12,17 @@ namespace osu.Game.Storyboards
{
///
/// The time at which the ends.
+ /// This is consumed to extend the length of a storyboard to ensure all visuals are played to completion.
///
double EndTime { get; }
+ ///
+ /// The time this element displays until.
+ /// This is used for lifetime purposes, and includes long playing animations which don't necessarily extend
+ /// a storyboard's play time.
+ ///
+ double EndTimeForDisplay { get; }
+
///
/// The duration of the StoryboardElement.
///
diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs
index 0c28d7bce1..982185d51b 100644
--- a/osu.Game/Storyboards/StoryboardSprite.cs
+++ b/osu.Game/Storyboards/StoryboardSprite.cs
@@ -81,6 +81,19 @@ namespace osu.Game.Storyboards
}
}
+ public double EndTimeForDisplay
+ {
+ get
+ {
+ double latestEndTime = TimelineGroup.EndTime;
+
+ foreach (var l in loops)
+ latestEndTime = Math.Max(latestEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations);
+
+ return latestEndTime;
+ }
+ }
+
public bool HasCommands => TimelineGroup.HasCommands || loops.Any(l => l.HasCommands);
private delegate void DrawablePropertyInitializer(Drawable drawable, T value);