Refactor WorkingBeatmap

Gets ArchiveReader out of WorkingBeatmap and delegates extracting stuff
from it to subclasses. Should enable us to make an OnlineWorkingBeatmap
or so.
This commit is contained in:
Drew DeVault
2017-03-22 05:54:07 -04:00
parent b349c7d7fd
commit cc2b4c5c5b
8 changed files with 176 additions and 152 deletions

View File

@ -0,0 +1,32 @@
using System;
using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.IO;
namespace osu.Desktop.VisualTests.Beatmaps
{
public class TestWorkingBeatmap : WorkingBeatmap
{
public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
{
this.beatmap = beatmap;
}
private Beatmap beatmap;
public override Beatmap Beatmap => beatmap;
public override Texture Background => null;
public override Track Track => null;
public override void Dispose()
{
// This space intentionally left blank
}
public override void TransferTo(WorkingBeatmap other)
{
// This space intentionally left blank
}
}
}

View File

@ -17,6 +17,8 @@ using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI; using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.Taiko.UI; using osu.Game.Modes.Taiko.UI;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Graphics.Textures;
using osu.Desktop.VisualTests.Beatmaps;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
@ -95,16 +97,5 @@ namespace osu.Desktop.VisualTests.Tests
} }
}); });
} }
private class TestWorkingBeatmap : WorkingBeatmap
{
public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
{
Beatmap = beatmap;
}
protected override ArchiveReader GetReader() => null;
}
} }
} }

View File

@ -15,6 +15,7 @@ using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects; using osu.Game.Modes.Osu.Objects;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Desktop.VisualTests.Beatmaps;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
@ -97,16 +98,5 @@ namespace osu.Desktop.VisualTests.Tests
Beatmap = beatmap Beatmap = beatmap
}; };
} }
private class TestWorkingBeatmap : WorkingBeatmap
{
public TestWorkingBeatmap(Beatmap beatmap)
: base(beatmap.BeatmapInfo, beatmap.BeatmapInfo.BeatmapSet)
{
Beatmap = beatmap;
}
protected override ArchiveReader GetReader() => null;
}
} }
} }

View File

@ -205,9 +205,13 @@
<Compile Include="Tests\TestCaseDialogOverlay.cs" /> <Compile Include="Tests\TestCaseDialogOverlay.cs" />
<Compile Include="Tests\TestCaseBeatmapOptionsOverlay.cs" /> <Compile Include="Tests\TestCaseBeatmapOptionsOverlay.cs" />
<Compile Include="Tests\TestCaseLeaderboard.cs" /> <Compile Include="Tests\TestCaseLeaderboard.cs" />
<Compile Include="Beatmaps\TestWorkingBeatmap.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<ItemGroup /> <ItemGroup />
<ItemGroup>
<Folder Include="Beatmaps\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -4,14 +4,11 @@
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.IO;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Modes; using osu.Game.Modes;
using osu.Game.Modes.Mods; using osu.Game.Modes.Mods;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
@ -27,14 +24,12 @@ namespace osu.Game.Beatmaps
/// </summary> /// </summary>
public PlayMode? PreferredPlayMode; public PlayMode? PreferredPlayMode;
public PlayMode PlayMode => beatmap?.BeatmapInfo?.Mode > PlayMode.Osu ? beatmap.BeatmapInfo.Mode : PreferredPlayMode ?? PlayMode.Osu; public PlayMode PlayMode => Beatmap?.BeatmapInfo?.Mode > PlayMode.Osu ? Beatmap.BeatmapInfo.Mode : PreferredPlayMode ?? PlayMode.Osu;
public readonly Bindable<IEnumerable<Mod>> Mods = new Bindable<IEnumerable<Mod>>(); public readonly Bindable<IEnumerable<Mod>> Mods = new Bindable<IEnumerable<Mod>>();
public readonly bool WithStoryboard; public readonly bool WithStoryboard;
protected abstract ArchiveReader GetReader();
protected WorkingBeatmap(BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false) protected WorkingBeatmap(BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false)
{ {
BeatmapInfo = beatmapInfo; BeatmapInfo = beatmapInfo;
@ -42,116 +37,13 @@ namespace osu.Game.Beatmaps
WithStoryboard = withStoryboard; WithStoryboard = withStoryboard;
} }
private Texture background; public abstract Beatmap Beatmap { get; }
private object backgroundLock = new object(); public abstract Texture Background { get; }
public Texture Background public abstract Track Track { get; }
{
get
{
lock (backgroundLock)
{
if (background != null) return background;
if (BeatmapInfo?.Metadata?.BackgroundFile == null) return null; public abstract void TransferTo(WorkingBeatmap other);
public abstract void Dispose();
try public virtual bool TrackLoaded => Track != null;
{
using (var reader = GetReader())
background = new TextureStore(new RawTextureLoaderStore(reader), false).Get(BeatmapInfo.Metadata.BackgroundFile);
}
catch { }
return background;
}
}
set { lock (backgroundLock) background = value; }
}
private Beatmap beatmap;
private object beatmapLock = new object();
public Beatmap Beatmap
{
get
{
lock (beatmapLock)
{
if (beatmap != null) return beatmap;
try
{
using (var reader = GetReader())
{
BeatmapDecoder decoder;
using (var stream = new StreamReader(reader.GetStream(BeatmapInfo.Path)))
{
decoder = BeatmapDecoder.GetDecoder(stream);
beatmap = decoder?.Decode(stream);
}
if (WithStoryboard && beatmap != null && BeatmapSetInfo.StoryboardFile != null)
using (var stream = new StreamReader(reader.GetStream(BeatmapSetInfo.StoryboardFile)))
decoder?.Decode(stream, beatmap);
}
}
catch { }
return beatmap;
}
}
set { lock (beatmapLock) beatmap = value; }
}
private ArchiveReader trackReader;
private Track track;
private object trackLock = new object();
public Track Track
{
get
{
lock (trackLock)
{
if (track != null) return track;
try
{
//store a reference to the reader as we may continue accessing the stream in the background.
trackReader = GetReader();
var trackData = trackReader?.GetStream(BeatmapInfo.Metadata.AudioFile);
if (trackData != null)
track = new TrackBass(trackData);
}
catch { }
return track;
}
}
set { lock (trackLock) track = value; }
}
public bool TrackLoaded => track != null;
private bool isDisposed;
protected virtual void Dispose(bool disposing)
{
if (!isDisposed)
{
track?.Dispose();
background?.Dispose();
isDisposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void TransferTo(WorkingBeatmap working)
{
if (track != null && BeatmapInfo.AudioEquals(working.BeatmapInfo))
working.track = track;
}
} }
} }

View File

@ -18,7 +18,7 @@ using SQLiteNetExtensions.Extensions;
namespace osu.Game.Database namespace osu.Game.Database
{ {
public class BeatmapDatabase public partial class BeatmapDatabase
{ {
private SQLiteConnection connection { get; } private SQLiteConnection connection { get; }
private Storage storage; private Storage storage;
@ -342,18 +342,5 @@ namespace osu.Game.Database
} }
public bool Exists(BeatmapSetInfo beatmapSet) => storage.Exists(beatmapSet.Path); public bool Exists(BeatmapSetInfo beatmapSet) => storage.Exists(beatmapSet.Path);
private class DatabaseWorkingBeatmap : WorkingBeatmap
{
private readonly BeatmapDatabase database;
public DatabaseWorkingBeatmap(BeatmapDatabase database, BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false)
: base(beatmapInfo, beatmapSetInfo, withStoryboard)
{
this.database = database;
}
protected override ArchiveReader GetReader() => database?.GetReader(BeatmapSetInfo);
}
} }
} }

View File

@ -0,0 +1,127 @@
using System.IO;
using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.IO;
namespace osu.Game.Database
{
public partial class BeatmapDatabase
{
private class DatabaseWorkingBeatmap : WorkingBeatmap
{
private readonly BeatmapDatabase database;
public DatabaseWorkingBeatmap(BeatmapDatabase database, BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, bool withStoryboard = false)
: base(beatmapInfo, beatmapSetInfo, withStoryboard)
{
this.database = database;
}
private ArchiveReader GetReader() => database?.GetReader(BeatmapSetInfo);
private Beatmap beatmap;
private object beatmapLock = new object();
public override Beatmap Beatmap
{
get
{
lock (beatmapLock)
{
if (beatmap != null) return beatmap;
try
{
using (var reader = GetReader())
{
BeatmapDecoder decoder;
using (var stream = new StreamReader(reader.GetStream(BeatmapInfo.Path)))
{
decoder = BeatmapDecoder.GetDecoder(stream);
beatmap = decoder?.Decode(stream);
}
if (WithStoryboard && beatmap != null && BeatmapSetInfo.StoryboardFile != null)
using (var stream = new StreamReader(reader.GetStream(BeatmapSetInfo.StoryboardFile)))
decoder?.Decode(stream, beatmap);
}
}
catch { return null; }
return beatmap;
}
}
}
private object backgroundLock = new object();
private Texture background;
public override Texture Background
{
get
{
lock (backgroundLock)
{
if (background != null) return background;
if (BeatmapInfo?.Metadata?.BackgroundFile == null) return null;
try
{
using (var reader = GetReader())
{
background = new TextureStore(
new RawTextureLoaderStore(reader),
false).Get(BeatmapInfo.Metadata.BackgroundFile);
}
}
catch { return null; }
return background;
}
}
}
private ArchiveReader trackReader;
private Track track;
private object trackLock = new object();
public override Track Track
{
get
{
lock (trackLock)
{
if (track != null) return track;
try
{
//store a reference to the reader as we may continue accessing the stream in the background.
trackReader = GetReader();
var trackData = trackReader?.GetStream(BeatmapInfo.Metadata.AudioFile);
if (trackData != null)
track = new TrackBass(trackData);
}
catch { return null; }
return track;
}
}
}
public override bool TrackLoaded => track != null;
public override void TransferTo(WorkingBeatmap other)
{
var _other = (DatabaseWorkingBeatmap)other;
if (track != null && BeatmapInfo.AudioEquals(_other.BeatmapInfo))
_other.track = track;
}
public override void Dispose()
{
background?.Dispose();
background = null;
}
}
}
}

View File

@ -363,6 +363,7 @@
<Compile Include="Screens\Select\Leaderboards\DrawableRank.cs" /> <Compile Include="Screens\Select\Leaderboards\DrawableRank.cs" />
<Compile Include="Graphics\UserInterface\OsuTabControl.cs" /> <Compile Include="Graphics\UserInterface\OsuTabControl.cs" />
<Compile Include="Graphics\UserInterface\OsuTabItem.cs" /> <Compile Include="Graphics\UserInterface\OsuTabItem.cs" />
<Compile Include="Database\DatabaseWorkingBeatmap.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="$(SolutionDir)\osu-framework\osu.Framework\osu.Framework.csproj"> <ProjectReference Include="$(SolutionDir)\osu-framework\osu.Framework\osu.Framework.csproj">