1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 22:47:24 +08:00

Merge pull request #27797 from smoogipoo/revert-storyboard-optimisation

Revert recent storyboard optimisations
This commit is contained in:
Dean Herbert 2024-04-05 14:56:44 +08:00 committed by GitHub
commit 6093b50641
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 58 deletions

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -45,10 +46,32 @@ namespace osu.Game.Storyboards
} }
[JsonIgnore] [JsonIgnore]
public double CommandsStartTime => timelines.Min(static t => t.StartTime); public double CommandsStartTime
{
get
{
double min = double.MaxValue;
for (int i = 0; i < timelines.Length; i++)
min = Math.Min(min, timelines[i].StartTime);
return min;
}
}
[JsonIgnore] [JsonIgnore]
public double CommandsEndTime => timelines.Max(static t => t.EndTime); public double CommandsEndTime
{
get
{
double max = double.MinValue;
for (int i = 0; i < timelines.Length; i++)
max = Math.Max(max, timelines[i].EndTime);
return max;
}
}
[JsonIgnore] [JsonIgnore]
public double CommandsDuration => CommandsEndTime - CommandsStartTime; public double CommandsDuration => CommandsEndTime - CommandsStartTime;
@ -60,7 +83,19 @@ namespace osu.Game.Storyboards
public virtual double EndTime => CommandsEndTime; public virtual double EndTime => CommandsEndTime;
[JsonIgnore] [JsonIgnore]
public bool HasCommands => timelines.Any(static t => t.HasCommands); public bool HasCommands
{
get
{
for (int i = 0; i < timelines.Length; i++)
{
if (timelines[i].HasCommands)
return true;
}
return false;
}
}
public virtual IEnumerable<CommandTimeline<T>.TypedCommand> GetCommands<T>(CommandTimelineSelector<T> timelineSelector, double offset = 0) public virtual IEnumerable<CommandTimeline<T>.TypedCommand> GetCommands<T>(CommandTimelineSelector<T> timelineSelector, double offset = 0)
{ {

View File

@ -85,23 +85,12 @@ namespace osu.Game.Storyboards
{ {
get get
{ {
double latestEndTime = double.MaxValue; double latestEndTime = TimelineGroup.EndTime;
// Ignore the whole setup if there are loops. In theory they can be handled here too, however the logic will be overly complex.
if (loops.Count == 0)
{
// Take the minimum time of all the potential "death" reasons.
latestEndTime = calculateOptimisedEndTime(TimelineGroup);
}
// If the logic above fails to find anything or discarded by the fact that there are loops present, latestEndTime will be double.MaxValue
// and thus conservativeEndTime will be used.
double conservativeEndTime = TimelineGroup.EndTime;
foreach (var l in loops) foreach (var l in loops)
conservativeEndTime = Math.Max(conservativeEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations); latestEndTime = Math.Max(latestEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations);
return Math.Min(latestEndTime, conservativeEndTime); return latestEndTime;
} }
} }
@ -205,47 +194,6 @@ namespace osu.Game.Storyboards
return commands; return commands;
} }
private static double calculateOptimisedEndTime(CommandTimelineGroup timelineGroup)
{
// Here we are starting from maximum value and trying to minimise the end time on each step.
// There are few solid guesses we can make using which sprite's end time can be minimised: alpha = 0, scale = 0, colour.a = 0.
double[] deathTimes =
{
double.MaxValue, // alpha
double.MaxValue, // colour alpha
double.MaxValue, // scale
double.MaxValue, // scale x
double.MaxValue, // scale y
};
// The loops below are following the same pattern.
// We could be using TimelineGroup.EndValue here, however it's possible to have multiple commands with 0 value in a row
// so we are saving the earliest of them.
foreach (var alphaCommand in timelineGroup.Alpha.Commands)
{
if (alphaCommand.EndValue == 0)
// commands are ordered by the start time, however end time may vary. Save the earliest.
deathTimes[0] = Math.Min(alphaCommand.EndTime, deathTimes[0]);
else
// If value isn't 0 (sprite becomes visible again), revert the saved state.
deathTimes[0] = double.MaxValue;
}
foreach (var colourCommand in timelineGroup.Colour.Commands)
deathTimes[1] = colourCommand.EndValue.A == 0 ? Math.Min(colourCommand.EndTime, deathTimes[1]) : double.MaxValue;
foreach (var scaleCommand in timelineGroup.Scale.Commands)
deathTimes[2] = scaleCommand.EndValue == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[2]) : double.MaxValue;
foreach (var scaleCommand in timelineGroup.VectorScale.Commands)
{
deathTimes[3] = scaleCommand.EndValue.X == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[3]) : double.MaxValue;
deathTimes[4] = scaleCommand.EndValue.Y == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[4]) : double.MaxValue;
}
return deathTimes.Min();
}
public override string ToString() public override string ToString()
=> $"{Path}, {Origin}, {InitialPosition}"; => $"{Path}, {Origin}, {InitialPosition}";