mirror of
https://github.com/ppy/osu
synced 2025-01-09 23:59:44 +00:00
Apply NRT to WorkingBeatmap
This commit is contained in:
parent
53c0a6708f
commit
9e17d7d4e3
@ -37,12 +37,12 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the <see cref="IBeatmap"/> which this <see cref="IWorkingBeatmap"/> represents.
|
/// Retrieves the <see cref="IBeatmap"/> which this <see cref="IWorkingBeatmap"/> represents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IBeatmap Beatmap { get; }
|
IBeatmap? Beatmap { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the background for this <see cref="IWorkingBeatmap"/>.
|
/// Retrieves the background for this <see cref="IWorkingBeatmap"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Texture Background { get; }
|
Texture? Background { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the <see cref="Waveform"/> for the <see cref="Track"/> of this <see cref="IWorkingBeatmap"/>.
|
/// Retrieves the <see cref="Waveform"/> for the <see cref="Track"/> of this <see cref="IWorkingBeatmap"/>.
|
||||||
@ -57,12 +57,12 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the <see cref="Skin"/> which this <see cref="IWorkingBeatmap"/> provides.
|
/// Retrieves the <see cref="Skin"/> which this <see cref="IWorkingBeatmap"/> provides.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISkin Skin { get; }
|
ISkin? Skin { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the <see cref="Track"/> which this <see cref="IWorkingBeatmap"/> has loaded.
|
/// Retrieves the <see cref="Track"/> which this <see cref="IWorkingBeatmap"/> has loaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Track Track { get; }
|
Track? Track { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a playable <see cref="IBeatmap"/> from <see cref="Beatmap"/> using the applicable converters for a specific <see cref="RulesetInfo"/>.
|
/// Constructs a playable <see cref="IBeatmap"/> from <see cref="Beatmap"/> using the applicable converters for a specific <see cref="RulesetInfo"/>.
|
||||||
@ -114,7 +114,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// Returns the stream of the file from the given storage path.
|
/// Returns the stream of the file from the given storage path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="storagePath">The storage path to the file.</param>
|
/// <param name="storagePath">The storage path to the file.</param>
|
||||||
Stream GetStream(string storagePath);
|
Stream? GetStream(string storagePath);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Beings loading the contents of this <see cref="IWorkingBeatmap"/> asynchronously.
|
/// Beings loading the contents of this <see cref="IWorkingBeatmap"/> asynchronously.
|
||||||
|
@ -8,7 +8,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
@ -21,6 +20,8 @@ using osu.Game.Rulesets.UI;
|
|||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Storyboards;
|
using osu.Game.Storyboards;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps
|
namespace osu.Game.Beatmaps
|
||||||
{
|
{
|
||||||
[ExcludeFromDynamicCompile]
|
[ExcludeFromDynamicCompile]
|
||||||
@ -30,28 +31,28 @@ namespace osu.Game.Beatmaps
|
|||||||
public readonly BeatmapSetInfo BeatmapSetInfo;
|
public readonly BeatmapSetInfo BeatmapSetInfo;
|
||||||
|
|
||||||
// TODO: remove once the fallback lookup is not required (and access via `working.BeatmapInfo.Metadata` directly).
|
// TODO: remove once the fallback lookup is not required (and access via `working.BeatmapInfo.Metadata` directly).
|
||||||
public BeatmapMetadata Metadata => BeatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata();
|
public BeatmapMetadata Metadata => BeatmapInfo.Metadata ?? BeatmapSetInfo.Metadata;
|
||||||
|
|
||||||
public Waveform Waveform => waveform.Value;
|
public Waveform Waveform => waveform.Value;
|
||||||
|
|
||||||
public Storyboard Storyboard => storyboard.Value;
|
public Storyboard Storyboard => storyboard.Value;
|
||||||
|
|
||||||
public Texture Background => GetBackground(); // Texture uses ref counting, so we want to return a new instance every usage.
|
public Texture? Background => GetBackground(); // Texture uses ref counting, so we want to return a new instance every usage.
|
||||||
|
|
||||||
public ISkin Skin => skin.Value;
|
public ISkin? Skin => skin.Value;
|
||||||
|
|
||||||
private AudioManager audioManager { get; }
|
private AudioManager? audioManager { get; }
|
||||||
|
|
||||||
private CancellationTokenSource loadCancellationSource = new CancellationTokenSource();
|
private CancellationTokenSource? loadCancellationSource;
|
||||||
|
|
||||||
private readonly object beatmapFetchLock = new object();
|
private readonly object beatmapFetchLock = new object();
|
||||||
|
|
||||||
private readonly Lazy<Waveform> waveform;
|
private readonly Lazy<Waveform> waveform;
|
||||||
private readonly Lazy<Storyboard> storyboard;
|
private readonly Lazy<Storyboard> storyboard;
|
||||||
private readonly Lazy<ISkin> skin;
|
private readonly Lazy<ISkin?> skin;
|
||||||
private Track track; // track is not Lazy as we allow transferring and loading multiple times.
|
private Track? track; // track is not Lazy as we allow transferring and loading multiple times.
|
||||||
|
|
||||||
protected WorkingBeatmap(BeatmapInfo beatmapInfo, AudioManager audioManager)
|
protected WorkingBeatmap(BeatmapInfo beatmapInfo, AudioManager? audioManager)
|
||||||
{
|
{
|
||||||
this.audioManager = audioManager;
|
this.audioManager = audioManager;
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
waveform = new Lazy<Waveform>(GetWaveform);
|
waveform = new Lazy<Waveform>(GetWaveform);
|
||||||
storyboard = new Lazy<Storyboard>(GetStoryboard);
|
storyboard = new Lazy<Storyboard>(GetStoryboard);
|
||||||
skin = new Lazy<ISkin>(GetSkin);
|
skin = new Lazy<ISkin?>(GetSkin);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Resource getters
|
#region Resource getters
|
||||||
@ -68,9 +69,9 @@ namespace osu.Game.Beatmaps
|
|||||||
protected virtual Waveform GetWaveform() => new Waveform(null);
|
protected virtual Waveform GetWaveform() => new Waveform(null);
|
||||||
protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo };
|
protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo };
|
||||||
|
|
||||||
protected abstract IBeatmap GetBeatmap();
|
protected abstract IBeatmap? GetBeatmap();
|
||||||
protected abstract Texture GetBackground();
|
protected abstract Texture? GetBackground();
|
||||||
protected abstract Track GetBeatmapTrack();
|
protected abstract Track? GetBeatmapTrack();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new skin instance for this beatmap.
|
/// Creates a new skin instance for this beatmap.
|
||||||
@ -80,7 +81,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// (e.g. for editing purposes, to avoid state pollution).
|
/// (e.g. for editing purposes, to avoid state pollution).
|
||||||
/// For standard reading purposes, <see cref="Skin"/> should always be used directly.
|
/// For standard reading purposes, <see cref="Skin"/> should always be used directly.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected internal abstract ISkin GetSkin();
|
protected internal abstract ISkin? GetSkin();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -93,7 +94,6 @@ namespace osu.Game.Beatmaps
|
|||||||
lock (beatmapFetchLock)
|
lock (beatmapFetchLock)
|
||||||
{
|
{
|
||||||
loadCancellationSource?.Cancel();
|
loadCancellationSource?.Cancel();
|
||||||
loadCancellationSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
if (beatmapLoadTask?.IsCompleted != true)
|
if (beatmapLoadTask?.IsCompleted != true)
|
||||||
beatmapLoadTask = null;
|
beatmapLoadTask = null;
|
||||||
@ -130,7 +130,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// across difficulties in the same beatmap set.
|
/// across difficulties in the same beatmap set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="track">The track to transfer.</param>
|
/// <param name="track">The track to transfer.</param>
|
||||||
public void TransferTrack([NotNull] Track track) => this.track = track ?? throw new ArgumentNullException(nameof(track));
|
public void TransferTrack(Track track) => this.track = track ?? throw new ArgumentNullException(nameof(track));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the loaded audio track instance. <see cref="LoadTrack"/> must have first been called.
|
/// Get the loaded audio track instance. <see cref="LoadTrack"/> must have first been called.
|
||||||
@ -143,6 +143,9 @@ namespace osu.Game.Beatmaps
|
|||||||
if (!TrackLoaded)
|
if (!TrackLoaded)
|
||||||
throw new InvalidOperationException($"Cannot access {nameof(Track)} without first calling {nameof(LoadTrack)}.");
|
throw new InvalidOperationException($"Cannot access {nameof(Track)} without first calling {nameof(LoadTrack)}.");
|
||||||
|
|
||||||
|
// Covered by TrackLoaded call above.
|
||||||
|
Debug.Assert(track != null);
|
||||||
|
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +173,7 @@ namespace osu.Game.Beatmaps
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return audioManager.Tracks.GetVirtual(length);
|
return audioManager?.Tracks.GetVirtual(length) ?? throw new InvalidOperationException($"Attempted to get virtual track without providing an {nameof(AudioManager)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -179,7 +182,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public virtual bool BeatmapLoaded => beatmapLoadTask?.IsCompleted ?? false;
|
public virtual bool BeatmapLoaded => beatmapLoadTask?.IsCompleted ?? false;
|
||||||
|
|
||||||
public IBeatmap Beatmap
|
public IBeatmap? Beatmap
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@ -204,7 +207,7 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<IBeatmap> beatmapLoadTask;
|
private Task<IBeatmap>? beatmapLoadTask;
|
||||||
|
|
||||||
private Task<IBeatmap> loadBeatmapAsync()
|
private Task<IBeatmap> loadBeatmapAsync()
|
||||||
{
|
{
|
||||||
@ -222,7 +225,7 @@ namespace osu.Game.Beatmaps
|
|||||||
b.BeatmapInfo = BeatmapInfo;
|
b.BeatmapInfo = BeatmapInfo;
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
}, loadCancellationSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
}, (loadCancellationSource = new CancellationTokenSource()).Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +233,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
#region Playable beatmap
|
#region Playable beatmap
|
||||||
|
|
||||||
public IBeatmap GetPlayableBeatmap(IRulesetInfo ruleset, IReadOnlyList<Mod> mods = null)
|
public IBeatmap GetPlayableBeatmap(IRulesetInfo ruleset, IReadOnlyList<Mod>? mods = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -253,6 +256,9 @@ namespace osu.Game.Beatmaps
|
|||||||
if (rulesetInstance == null)
|
if (rulesetInstance == null)
|
||||||
throw new RulesetLoadException("Creating ruleset instance failed when attempting to create playable beatmap.");
|
throw new RulesetLoadException("Creating ruleset instance failed when attempting to create playable beatmap.");
|
||||||
|
|
||||||
|
if (Beatmap == null)
|
||||||
|
throw new InvalidOperationException("Beatmap could not be loaded.");
|
||||||
|
|
||||||
IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance);
|
IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance);
|
||||||
|
|
||||||
// Check if the beatmap can be converted
|
// Check if the beatmap can be converted
|
||||||
@ -332,7 +338,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public override string ToString() => BeatmapInfo.ToString();
|
public override string ToString() => BeatmapInfo.ToString();
|
||||||
|
|
||||||
public abstract Stream GetStream(string storagePath);
|
public abstract Stream? GetStream(string storagePath);
|
||||||
|
|
||||||
IBeatmapInfo IWorkingBeatmap.BeatmapInfo => BeatmapInfo;
|
IBeatmapInfo IWorkingBeatmap.BeatmapInfo => BeatmapInfo;
|
||||||
|
|
||||||
|
@ -180,17 +180,17 @@ namespace osu.Game.Beatmaps
|
|||||||
protected override Waveform GetWaveform()
|
protected override Waveform GetWaveform()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(Metadata?.AudioFile))
|
if (string.IsNullOrEmpty(Metadata?.AudioFile))
|
||||||
return null;
|
return base.GetWaveform();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var trackData = GetStream(BeatmapSetInfo.GetPathForFile(Metadata.AudioFile));
|
var trackData = GetStream(BeatmapSetInfo.GetPathForFile(Metadata.AudioFile));
|
||||||
return trackData == null ? null : new Waveform(trackData);
|
return trackData == null ? base.GetWaveform() : new Waveform(trackData);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Error(e, "Waveform failed to load");
|
Logger.Error(e, "Waveform failed to load");
|
||||||
return null;
|
return base.GetWaveform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ namespace osu.Game.Stores
|
|||||||
|
|
||||||
protected override IBeatmap GetBeatmap() => beatmap;
|
protected override IBeatmap GetBeatmap() => beatmap;
|
||||||
protected override Texture? GetBackground() => null;
|
protected override Texture? GetBackground() => null;
|
||||||
protected override Track? GetBeatmapTrack() => null;
|
protected override Track GetBeatmapTrack() => null!;
|
||||||
protected internal override ISkin? GetSkin() => null;
|
protected internal override ISkin? GetSkin() => null;
|
||||||
public override Stream? GetStream(string storagePath) => null;
|
public override Stream? GetStream(string storagePath) => null;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user