1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-14 15:57:24 +08:00

Refactor storyboard timeline to reduce GC / fix crashes (#7270)

Refactor storyboard timeline to reduce GC / fix crashes

Co-authored-by: Dean Herbert <pe@ppy.sh>
This commit is contained in:
Dean Herbert 2019-12-19 12:02:08 +09:00 committed by GitHub
commit fd7309551c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 25 deletions

View File

@ -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 osu.Framework.Caching;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -12,27 +11,35 @@ namespace osu.Game.Storyboards
public class CommandTimeline<T> : ICommandTimeline public class CommandTimeline<T> : ICommandTimeline
{ {
private readonly List<TypedCommand> commands = new List<TypedCommand>(); private readonly List<TypedCommand> commands = new List<TypedCommand>();
public IEnumerable<TypedCommand> Commands => commands.OrderBy(c => c.StartTime); public IEnumerable<TypedCommand> Commands => commands.OrderBy(c => c.StartTime);
public bool HasCommands => commands.Count > 0; public bool HasCommands => commands.Count > 0;
private readonly Cached<double> startTimeBacking = new Cached<double>(); public double StartTime { get; private set; } = double.MaxValue;
public double StartTime => startTimeBacking.IsValid ? startTimeBacking : startTimeBacking.Value = HasCommands ? commands.Min(c => c.StartTime) : double.MinValue; public double EndTime { get; private set; } = double.MinValue;
private readonly Cached<double> endTimeBacking = new Cached<double>(); public T StartValue { get; private set; }
public double EndTime => endTimeBacking.IsValid ? endTimeBacking : endTimeBacking.Value = HasCommands ? commands.Max(c => c.EndTime) : double.MaxValue; public T EndValue { get; private set; }
public T StartValue => HasCommands ? commands.OrderBy(c => c.StartTime).First().StartValue : default;
public T EndValue => HasCommands ? commands.OrderByDescending(c => c.EndTime).First().EndValue : default;
public void Add(Easing easing, double startTime, double endTime, T startValue, T endValue) public void Add(Easing easing, double startTime, double endTime, T startValue, T endValue)
{ {
if (endTime < startTime) if (endTime < startTime)
return; return;
commands.Add(new TypedCommand { Easing = easing, StartTime = startTime, EndTime = endTime, StartValue = startValue, EndValue = endValue, }); commands.Add(new TypedCommand { Easing = easing, StartTime = startTime, EndTime = endTime, StartValue = startValue, EndValue = endValue });
startTimeBacking.Invalidate(); if (startTime < StartTime)
endTimeBacking.Invalidate(); {
StartValue = startValue;
StartTime = startTime;
}
if (endTime > EndTime)
{
EndValue = endValue;
EndTime = endTime;
}
} }
public override string ToString() public override string ToString()

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;
@ -25,28 +26,52 @@ namespace osu.Game.Storyboards
public CommandTimeline<bool> FlipH = new CommandTimeline<bool>(); public CommandTimeline<bool> FlipH = new CommandTimeline<bool>();
public CommandTimeline<bool> FlipV = new CommandTimeline<bool>(); public CommandTimeline<bool> FlipV = new CommandTimeline<bool>();
private readonly ICommandTimeline[] timelines;
public CommandTimelineGroup()
{
timelines = new ICommandTimeline[]
{
X,
Y,
Scale,
VectorScale,
Rotation,
Colour,
Alpha,
BlendingParameters,
FlipH,
FlipV
};
}
[JsonIgnore] [JsonIgnore]
public IEnumerable<ICommandTimeline> Timelines public double CommandsStartTime
{ {
get get
{ {
yield return X; double min = double.MaxValue;
yield return Y;
yield return Scale; for (int i = 0; i < timelines.Length; i++)
yield return Rotation; min = Math.Min(min, timelines[i].StartTime);
yield return Colour;
yield return Alpha; return min;
yield return BlendingParameters;
yield return FlipH;
yield return FlipV;
} }
} }
[JsonIgnore] [JsonIgnore]
public double CommandsStartTime => Timelines.Where(t => t.HasCommands).Min(t => t.StartTime); public double CommandsEndTime
{
get
{
double max = double.MinValue;
[JsonIgnore] for (int i = 0; i < timelines.Length; i++)
public double CommandsEndTime => Timelines.Where(t => t.HasCommands).Max(t => t.EndTime); max = Math.Max(max, timelines[i].EndTime);
return max;
}
}
[JsonIgnore] [JsonIgnore]
public double CommandsDuration => CommandsEndTime - CommandsStartTime; public double CommandsDuration => CommandsEndTime - CommandsStartTime;
@ -61,7 +86,19 @@ namespace osu.Game.Storyboards
public double Duration => EndTime - StartTime; public double Duration => EndTime - StartTime;
[JsonIgnore] [JsonIgnore]
public bool HasCommands => Timelines.Any(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)
{ {