mirror of
https://github.com/ppy/osu
synced 2025-01-02 04:12:13 +00:00
Fix storyboard commands occurring before the earliest point of visibility delaying gameplay
In osu-stable, storyboard intros start from the first command, but in the case of storyboard drawables which have an initial hidden state, all commands before the time at which they become visible (ie. the first command where `Alpha` increases to a non-zero value) are ignored. This brings lazer in line with that behaviour. It also removes several unnecessary LINQ calls. Note that the alpha check being done in its own pass is important, as it must be the "minimum present alpha across all command groups, including loops". This is what makes the implementation slightly complex. Closes #11981.
This commit is contained in:
parent
a5b3ac7ef8
commit
8aaba32431
@ -45,11 +45,30 @@ namespace osu.Game.Storyboards
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the earliest visible time. Will be null unless this group has an <see cref="Alpha"/> command with a start value of zero.
|
||||
/// </summary>
|
||||
public double? EarliestDisplayedTime
|
||||
{
|
||||
get
|
||||
{
|
||||
var first = Alpha.Commands.FirstOrDefault();
|
||||
|
||||
return first?.StartValue == 0 ? first.StartTime : (double?)null;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public double CommandsStartTime
|
||||
{
|
||||
get
|
||||
{
|
||||
// if the first alpha command starts at zero it should be given priority over anything else.
|
||||
// this is due to it creating a state where the target is not present before that time, causing any other events to not be visible.
|
||||
var earliestDisplay = EarliestDisplayedTime;
|
||||
if (earliestDisplay != null)
|
||||
return earliestDisplay.Value;
|
||||
|
||||
double min = double.MaxValue;
|
||||
|
||||
for (int i = 0; i < timelines.Length; i++)
|
||||
|
@ -24,13 +24,46 @@ namespace osu.Game.Storyboards
|
||||
|
||||
public readonly CommandTimelineGroup TimelineGroup = new CommandTimelineGroup();
|
||||
|
||||
public double StartTime => Math.Min(
|
||||
TimelineGroup.HasCommands ? TimelineGroup.CommandsStartTime : double.MaxValue,
|
||||
loops.Any(l => l.HasCommands) ? loops.Where(l => l.HasCommands).Min(l => l.StartTime) : double.MaxValue);
|
||||
public double StartTime
|
||||
{
|
||||
get
|
||||
{
|
||||
// check for presence affecting commands as an initial pass.
|
||||
double earliestStartTime = TimelineGroup.EarliestDisplayedTime ?? double.MaxValue;
|
||||
|
||||
public double EndTime => Math.Max(
|
||||
TimelineGroup.HasCommands ? TimelineGroup.CommandsEndTime : double.MinValue,
|
||||
loops.Any(l => l.HasCommands) ? loops.Where(l => l.HasCommands).Max(l => l.EndTime) : double.MinValue);
|
||||
foreach (var l in loops)
|
||||
{
|
||||
if (!(l.EarliestDisplayedTime is double lEarliest))
|
||||
continue;
|
||||
|
||||
earliestStartTime = Math.Min(earliestStartTime, lEarliest);
|
||||
}
|
||||
|
||||
if (earliestStartTime < double.MaxValue)
|
||||
return earliestStartTime;
|
||||
|
||||
// if an alpha-affecting command was not found, use the earliest of any command.
|
||||
earliestStartTime = TimelineGroup.StartTime;
|
||||
|
||||
foreach (var l in loops)
|
||||
earliestStartTime = Math.Min(earliestStartTime, l.StartTime);
|
||||
|
||||
return earliestStartTime;
|
||||
}
|
||||
}
|
||||
|
||||
public double EndTime
|
||||
{
|
||||
get
|
||||
{
|
||||
double latestEndTime = TimelineGroup.EndTime;
|
||||
|
||||
foreach (var l in loops)
|
||||
latestEndTime = Math.Max(latestEndTime, l.EndTime);
|
||||
|
||||
return latestEndTime;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCommands => TimelineGroup.HasCommands || loops.Any(l => l.HasCommands);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user