mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 11:37:28 +08:00
Improve sb sprite end time guessing
This commit is contained in:
parent
9a1403d22a
commit
77b3055978
@ -1,7 +1,6 @@
|
|||||||
// 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;
|
||||||
@ -46,32 +45,10 @@ namespace osu.Game.Storyboards
|
|||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public double CommandsStartTime
|
public double CommandsStartTime => timelines.Min(static t => t.StartTime);
|
||||||
{
|
|
||||||
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
|
public double CommandsEndTime => timelines.Max(static t => t.EndTime);
|
||||||
{
|
|
||||||
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;
|
||||||
@ -83,19 +60,7 @@ namespace osu.Game.Storyboards
|
|||||||
public virtual double EndTime => CommandsEndTime;
|
public virtual double EndTime => CommandsEndTime;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public bool HasCommands
|
public bool HasCommands => timelines.Any(static t => t.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)
|
||||||
{
|
{
|
||||||
|
@ -85,12 +85,56 @@ namespace osu.Game.Storyboards
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
double latestEndTime = TimelineGroup.EndTime;
|
double latestEndTime = double.MaxValue;
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
deathTimes[0] = alphaCommand.EndValue == 0
|
||||||
|
? Math.Min(alphaCommand.EndTime, deathTimes[0]) // commands are ordered by the start time, however end time may vary. Save the earliest.
|
||||||
|
: double.MaxValue; // If value isn't 0 (sprite becomes visible again), revert the saved state.
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take the minimum time of all the potential "death" reasons.
|
||||||
|
latestEndTime = deathTimes.Min();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
latestEndTime = Math.Max(latestEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations);
|
conservativeEndTime = Math.Max(conservativeEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations);
|
||||||
|
|
||||||
return latestEndTime;
|
return Math.Min(latestEndTime, conservativeEndTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user