mirror of
https://github.com/ppy/osu.git
synced 2025-02-15 19:55:45 +08:00
Optimise fallback logic to reduce lookups to bare minimum
This commit is contained in:
parent
6aa894e55e
commit
4a294d4de4
@ -44,32 +44,44 @@ namespace osu.Game.Rulesets.UI
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISampleInfo[] playableSampleInfo;
|
private HitObject fallbackObject;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Play the most appropriate hit sound for the current point in time.
|
/// Play the most appropriate hit sound for the current point in time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Play()
|
public void Play()
|
||||||
{
|
{
|
||||||
var nextObject =
|
var nextObject = hitObjectContainer.AliveObjects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current)?.HitObject;
|
||||||
hitObjectContainer.AliveObjects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current)?.HitObject ??
|
|
||||||
// fallback to non-alive objects to find next off-screen object
|
if (nextObject == null)
|
||||||
// TODO: make lookup more efficient?
|
{
|
||||||
drawableRuleset.Objects.FirstOrDefault(h => h.StartTime > Time.Current) ??
|
if (fallbackObject == null || fallbackObject.StartTime < Time.Current)
|
||||||
drawableRuleset.Objects.LastOrDefault();
|
{
|
||||||
|
// in the case a next object isn't available in drawable form, we need to do a somewhat expensive traversal to get a valid sound to play.
|
||||||
|
// note that we don't want to cache the object if it is an alive object, as once it is hit we don't want to continue playing its sound.
|
||||||
|
// check whether we can use the previous computed sample.
|
||||||
|
|
||||||
|
// fallback to non-alive objects to find next off-screen object
|
||||||
|
// TODO: make lookup more efficient?
|
||||||
|
fallbackObject = hitObjectContainer.Entries
|
||||||
|
.Where(e => e.Result?.HasResult != true && e.HitObject.StartTime > Time.Current)?
|
||||||
|
.OrderBy(e => e.HitObject.StartTime)
|
||||||
|
.FirstOrDefault()?.HitObject ?? hitObjectContainer.Entries.FirstOrDefault()?.HitObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextObject = fallbackObject;
|
||||||
|
}
|
||||||
|
|
||||||
if (nextObject != null)
|
if (nextObject != null)
|
||||||
{
|
{
|
||||||
var hitSound = getNextSample();
|
var hitSound = getNextSample();
|
||||||
playableSampleInfo = GetPlayableSampleInfo(nextObject);
|
hitSound.Samples = GetPlayableSampleInfo(nextObject).Select(s => nextObject.SampleControlPoint.ApplyTo(s)).Cast<ISampleInfo>().ToArray();
|
||||||
hitSound.Samples = playableSampleInfo;
|
|
||||||
hitSound.Play();
|
hitSound.Play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual ISampleInfo[] GetPlayableSampleInfo(HitObject nextObject) =>
|
protected virtual HitSampleInfo[] GetPlayableSampleInfo(HitObject nextObject) =>
|
||||||
// TODO: avoid cast somehow?
|
nextObject.Samples.ToArray();
|
||||||
nextObject.Samples.Cast<ISampleInfo>().ToArray();
|
|
||||||
|
|
||||||
private SkinnableSound getNextSample()
|
private SkinnableSound getNextSample()
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user