reverted split at Decoder, moved logic down

I'm done experimenting, sorry
- `Decoder` only returns a "Beatmap"`Decoder` now
- "Storyboard"`Decoder` is retrieved from a "Beatmap"`Decoder`
- moved parse methods down in the hierarchy where I forgot to do that
- renamed `OsuLegacyDecoderTest` to `LegacyDecoderTest`
This commit is contained in:
Aergwyn
2017-12-01 22:05:01 +01:00
parent a49f3479a2
commit c466296b14
9 changed files with 115 additions and 143 deletions

View File

@ -14,7 +14,7 @@ using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Tests.Beatmaps.Formats namespace osu.Game.Tests.Beatmaps.Formats
{ {
[TestFixture] [TestFixture]
public class OsuLegacyDecoderTest public class LegacyDecoderTest
{ {
[Test] [Test]
public void TestDecodeMetadata() public void TestDecodeMetadata()

View File

@ -50,7 +50,7 @@ namespace osu.Game.Tests.Beatmaps.IO
BeatmapMetadata meta; BeatmapMetadata meta;
using (var stream = new StreamReader(reader.GetStream("Soleily - Renatus (Deif) [Platter].osu"))) using (var stream = new StreamReader(reader.GetStream("Soleily - Renatus (Deif) [Platter].osu")))
meta = Decoder.GetBeatmapDecoder(stream).DecodeBeatmap(stream).Metadata; meta = Decoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata;
Assert.AreEqual(241526, meta.OnlineBeatmapSetID); Assert.AreEqual(241526, meta.OnlineBeatmapSetID);
Assert.AreEqual("Soleily", meta.Artist); Assert.AreEqual("Soleily", meta.Artist);

View File

@ -89,7 +89,7 @@
<Compile Include="Beatmaps\IO\OszArchiveReaderTest.cs" /> <Compile Include="Beatmaps\IO\OszArchiveReaderTest.cs" />
<Compile Include="Beatmaps\IO\ImportBeatmapTest.cs" /> <Compile Include="Beatmaps\IO\ImportBeatmapTest.cs" />
<Compile Include="Resources\Resource.cs" /> <Compile Include="Resources\Resource.cs" />
<Compile Include="Beatmaps\Formats\OsuLegacyDecoderTest.cs" /> <Compile Include="Beatmaps\Formats\LegacyDecoderTest.cs" />
<Compile Include="Visual\TestCaseBeatmapDetailArea.cs" /> <Compile Include="Visual\TestCaseBeatmapDetailArea.cs" />
<Compile Include="Visual\TestCaseBeatmapDetails.cs" /> <Compile Include="Visual\TestCaseBeatmapDetails.cs" />
<Compile Include="Visual\TestCaseBeatmapOptionsOverlay.cs" /> <Compile Include="Visual\TestCaseBeatmapOptionsOverlay.cs" />

View File

@ -495,7 +495,7 @@ namespace osu.Game.Beatmaps
BeatmapMetadata metadata; BeatmapMetadata metadata;
using (var stream = new StreamReader(reader.GetStream(mapName))) using (var stream = new StreamReader(reader.GetStream(mapName)))
metadata = Decoder.GetBeatmapDecoder(stream).DecodeBeatmap(stream).Metadata; metadata = Decoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata;
// check if a set already exists with the same online id. // check if a set already exists with the same online id.
beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == metadata.OnlineBeatmapSetID) ?? new BeatmapSetInfo beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == metadata.OnlineBeatmapSetID) ?? new BeatmapSetInfo
@ -518,7 +518,7 @@ namespace osu.Game.Beatmaps
raw.CopyTo(ms); raw.CopyTo(ms);
ms.Position = 0; ms.Position = 0;
var decoder = Decoder.GetBeatmapDecoder(sr); var decoder = Decoder.GetDecoder(sr);
Beatmap beatmap = decoder.DecodeBeatmap(sr); Beatmap beatmap = decoder.DecodeBeatmap(sr);
beatmap.BeatmapInfo.Path = name; beatmap.BeatmapInfo.Path = name;
@ -571,7 +571,7 @@ namespace osu.Game.Beatmaps
{ {
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
{ {
Decoder decoder = Decoder.GetBeatmapDecoder(stream); Decoder decoder = Decoder.GetDecoder(stream);
return decoder.DecodeBeatmap(stream); return decoder.DecodeBeatmap(stream);
} }
} }
@ -622,10 +622,10 @@ namespace osu.Game.Beatmaps
{ {
Decoder decoder; Decoder decoder;
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
decoder = Decoder.GetStoryboardDecoder(stream); decoder = Decoder.GetDecoder(stream);
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile)))) using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile))))
return decoder.DecodeStoryboard(stream); return decoder.GetStoryboardDecoder().DecodeStoryboard(stream);
} }
catch catch
{ {

View File

@ -10,8 +10,7 @@ namespace osu.Game.Beatmaps.Formats
{ {
public abstract class Decoder public abstract class Decoder
{ {
private static readonly Dictionary<string, Type> beatmapDecoders = new Dictionary<string, Type>(); private static readonly Dictionary<string, Type> decoders = new Dictionary<string, Type>();
private static readonly Dictionary<string, Type> storyboardDecoders = new Dictionary<string, Type>();
static Decoder() static Decoder()
{ {
@ -19,32 +18,10 @@ namespace osu.Game.Beatmaps.Formats
} }
/// <summary> /// <summary>
/// Retrieves a <see cref="Decoder"/> to parse <see cref="Beatmap"/>s. /// Retrieves a <see cref="Decoder"/> to parse a <see cref="Beatmap"/>.
/// </summary> /// </summary>
/// <param name="stream">A stream pointing to the <see cref="Beatmap"/> to retrieve the version from.</param> /// <param name="stream">A stream pointing to the <see cref="Beatmap"/>.</param>
public static Decoder GetBeatmapDecoder(StreamReader stream) public static Decoder GetDecoder(StreamReader stream)
{
string line = readFirstLine(stream);
if (line == null || !beatmapDecoders.ContainsKey(line))
throw new IOException(@"Unknown file format");
return (Decoder)Activator.CreateInstance(beatmapDecoders[line], line);
}
/// <summary>
/// Retrieves a <see cref="Decoder"/> to parse <see cref="Storyboard"/>s.
/// </summary>
/// <param name="stream">A stream pointing to the <see cref="Beatmap"/> to retrieve the version from.</param>
public static Decoder GetStoryboardDecoder(StreamReader stream)
{
string line = readFirstLine(stream);
if (line == null || !storyboardDecoders.ContainsKey(line))
throw new IOException(@"Unknown file format");
return (Decoder)Activator.CreateInstance(storyboardDecoders[line], line);
}
private static string readFirstLine(StreamReader stream)
{ {
if (stream == null) if (stream == null)
throw new ArgumentNullException(nameof(stream)); throw new ArgumentNullException(nameof(stream));
@ -54,44 +31,27 @@ namespace osu.Game.Beatmaps.Formats
{ line = stream.ReadLine()?.Trim(); } { line = stream.ReadLine()?.Trim(); }
while (line != null && line.Length == 0); while (line != null && line.Length == 0);
return line; if (line == null || !decoders.ContainsKey(line))
throw new IOException(@"Unknown file format");
return (Decoder)Activator.CreateInstance(decoders[line], line);
} }
/// <summary> /// <summary>
/// Adds the <see cref="Decoder"/> to the list of <see cref="Beatmap"/> and <see cref="Storyboard"/> decoder. /// Adds the <see cref="Decoder"/> to the list of <see cref="Beatmap"/> and <see cref="Storyboard"/> decoder.
/// </summary> /// </summary>
/// <typeparam name="A">Type to decode a <see cref="Beatmap"/> with.</typeparam>
/// /// <typeparam name="B">Type to decode a <see cref="Storyboard"/> with.</typeparam>
/// <param name="version">A string representation of the version.</param>
protected static void AddDecoder<A, B>(string version) where A : Decoder where B : Decoder
{
beatmapDecoders[version] = typeof(A);
storyboardDecoders[version] = typeof(B);
}
/// <summary>
/// Adds the <see cref="Decoder"/> to the list of <see cref="Beatmap"/> decoder.
/// </summary>
/// <typeparam name="T">Type to decode a <see cref="Beatmap"/> with.</typeparam> /// <typeparam name="T">Type to decode a <see cref="Beatmap"/> with.</typeparam>
/// <param name="version">A string representation of the version.</param> /// <param name="version">A string representation of the version.</param>
protected static void AddBeatmapDecoder<T>(string version) where T : Decoder protected static void AddDecoder<T>(string version) where T : Decoder
{ {
beatmapDecoders[version] = typeof(T); decoders[version] = typeof(T);
} }
/// <summary> /// <summary>
/// Adds the <see cref="Decoder"/> to the list of <see cref="Storyboard"/> decoder. /// Retrieves a <see cref="Decoder"/> to parse a <see cref="Storyboard"/>
/// </summary> /// </summary>
/// <typeparam name="T">Type to decode a <see cref="Storyboard"/> with.</typeparam> public abstract Decoder GetStoryboardDecoder();
/// <param name="version">A string representation of the version.</param>
protected static void AddStoryboardDecoder<T>(string version) where T : Decoder
{
storyboardDecoders[version] = typeof(T);
}
public virtual Beatmap DecodeBeatmap(StreamReader stream) => ParseBeatmap(stream); public virtual Beatmap DecodeBeatmap(StreamReader stream)
protected virtual Beatmap ParseBeatmap(StreamReader stream)
{ {
var beatmap = new Beatmap var beatmap = new Beatmap
{ {

View File

@ -2,18 +2,20 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Rulesets.Objects.Legacy;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using System.Collections.Generic;
namespace osu.Game.Beatmaps.Formats namespace osu.Game.Beatmaps.Formats
{ {
public class LegacyBeatmapDecoder : LegacyDecoder public class LegacyBeatmapDecoder : LegacyDecoder
{ {
private Beatmap beatmap;
private bool hasCustomColours; private bool hasCustomColours;
private ConvertHitObjectParser parser; private ConvertHitObjectParser parser;
@ -29,6 +31,22 @@ namespace osu.Game.Beatmaps.Formats
BeatmapVersion = int.Parse(header.Substring(17)); BeatmapVersion = int.Parse(header.Substring(17));
} }
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
{
if (stream == null)
throw new ArgumentNullException(nameof(stream));
if (beatmap == null)
throw new ArgumentNullException(nameof(beatmap));
this.beatmap = beatmap;
this.beatmap.BeatmapInfo.BeatmapVersion = BeatmapVersion;
ParseContent(stream);
foreach (var hitObject in this.beatmap.HitObjects)
hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.BeatmapInfo.BaseDifficulty);
}
protected override void ProcessSection(Section section, string line) protected override void ProcessSection(Section section, string line)
{ {
switch (section) switch (section)
@ -67,20 +85,20 @@ namespace osu.Game.Beatmaps.Formats
{ {
var pair = splitKeyVal(line, ':'); var pair = splitKeyVal(line, ':');
var metadata = Beatmap.BeatmapInfo.Metadata; var metadata = beatmap.BeatmapInfo.Metadata;
switch (pair.Key) switch (pair.Key)
{ {
case @"AudioFilename": case @"AudioFilename":
metadata.AudioFile = pair.Value; metadata.AudioFile = pair.Value;
break; break;
case @"AudioLeadIn": case @"AudioLeadIn":
Beatmap.BeatmapInfo.AudioLeadIn = int.Parse(pair.Value); beatmap.BeatmapInfo.AudioLeadIn = int.Parse(pair.Value);
break; break;
case @"PreviewTime": case @"PreviewTime":
metadata.PreviewTime = int.Parse(pair.Value); metadata.PreviewTime = int.Parse(pair.Value);
break; break;
case @"Countdown": case @"Countdown":
Beatmap.BeatmapInfo.Countdown = int.Parse(pair.Value) == 1; beatmap.BeatmapInfo.Countdown = int.Parse(pair.Value) == 1;
break; break;
case @"SampleSet": case @"SampleSet":
defaultSampleBank = (LegacySampleBank)Enum.Parse(typeof(LegacySampleBank), pair.Value); defaultSampleBank = (LegacySampleBank)Enum.Parse(typeof(LegacySampleBank), pair.Value);
@ -89,12 +107,12 @@ namespace osu.Game.Beatmaps.Formats
defaultSampleVolume = int.Parse(pair.Value); defaultSampleVolume = int.Parse(pair.Value);
break; break;
case @"StackLeniency": case @"StackLeniency":
Beatmap.BeatmapInfo.StackLeniency = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo); beatmap.BeatmapInfo.StackLeniency = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo);
break; break;
case @"Mode": case @"Mode":
Beatmap.BeatmapInfo.RulesetID = int.Parse(pair.Value); beatmap.BeatmapInfo.RulesetID = int.Parse(pair.Value);
switch (Beatmap.BeatmapInfo.RulesetID) switch (beatmap.BeatmapInfo.RulesetID)
{ {
case 0: case 0:
parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser(); parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser();
@ -111,13 +129,13 @@ namespace osu.Game.Beatmaps.Formats
} }
break; break;
case @"LetterboxInBreaks": case @"LetterboxInBreaks":
Beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(pair.Value) == 1; beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(pair.Value) == 1;
break; break;
case @"SpecialStyle": case @"SpecialStyle":
Beatmap.BeatmapInfo.SpecialStyle = int.Parse(pair.Value) == 1; beatmap.BeatmapInfo.SpecialStyle = int.Parse(pair.Value) == 1;
break; break;
case @"WidescreenStoryboard": case @"WidescreenStoryboard":
Beatmap.BeatmapInfo.WidescreenStoryboard = int.Parse(pair.Value) == 1; beatmap.BeatmapInfo.WidescreenStoryboard = int.Parse(pair.Value) == 1;
break; break;
} }
} }
@ -129,19 +147,19 @@ namespace osu.Game.Beatmaps.Formats
switch (pair.Key) switch (pair.Key)
{ {
case @"Bookmarks": case @"Bookmarks":
Beatmap.BeatmapInfo.StoredBookmarks = pair.Value; beatmap.BeatmapInfo.StoredBookmarks = pair.Value;
break; break;
case @"DistanceSpacing": case @"DistanceSpacing":
Beatmap.BeatmapInfo.DistanceSpacing = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo); beatmap.BeatmapInfo.DistanceSpacing = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo);
break; break;
case @"BeatDivisor": case @"BeatDivisor":
Beatmap.BeatmapInfo.BeatDivisor = int.Parse(pair.Value); beatmap.BeatmapInfo.BeatDivisor = int.Parse(pair.Value);
break; break;
case @"GridSize": case @"GridSize":
Beatmap.BeatmapInfo.GridSize = int.Parse(pair.Value); beatmap.BeatmapInfo.GridSize = int.Parse(pair.Value);
break; break;
case @"TimelineZoom": case @"TimelineZoom":
Beatmap.BeatmapInfo.TimelineZoom = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo); beatmap.BeatmapInfo.TimelineZoom = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo);
break; break;
} }
} }
@ -150,7 +168,7 @@ namespace osu.Game.Beatmaps.Formats
{ {
var pair = splitKeyVal(line, ':'); var pair = splitKeyVal(line, ':');
var metadata = Beatmap.BeatmapInfo.Metadata; var metadata = beatmap.BeatmapInfo.Metadata;
switch (pair.Key) switch (pair.Key)
{ {
case @"Title": case @"Title":
@ -169,19 +187,19 @@ namespace osu.Game.Beatmaps.Formats
metadata.AuthorString = pair.Value; metadata.AuthorString = pair.Value;
break; break;
case @"Version": case @"Version":
Beatmap.BeatmapInfo.Version = pair.Value; beatmap.BeatmapInfo.Version = pair.Value;
break; break;
case @"Source": case @"Source":
Beatmap.BeatmapInfo.Metadata.Source = pair.Value; beatmap.BeatmapInfo.Metadata.Source = pair.Value;
break; break;
case @"Tags": case @"Tags":
Beatmap.BeatmapInfo.Metadata.Tags = pair.Value; beatmap.BeatmapInfo.Metadata.Tags = pair.Value;
break; break;
case @"BeatmapID": case @"BeatmapID":
Beatmap.BeatmapInfo.OnlineBeatmapID = int.Parse(pair.Value); beatmap.BeatmapInfo.OnlineBeatmapID = int.Parse(pair.Value);
break; break;
case @"BeatmapSetID": case @"BeatmapSetID":
Beatmap.BeatmapInfo.OnlineBeatmapSetID = int.Parse(pair.Value); beatmap.BeatmapInfo.OnlineBeatmapSetID = int.Parse(pair.Value);
metadata.OnlineBeatmapSetID = int.Parse(pair.Value); metadata.OnlineBeatmapSetID = int.Parse(pair.Value);
break; break;
} }
@ -191,7 +209,7 @@ namespace osu.Game.Beatmaps.Formats
{ {
var pair = splitKeyVal(line, ':'); var pair = splitKeyVal(line, ':');
var difficulty = Beatmap.BeatmapInfo.BaseDifficulty; var difficulty = beatmap.BeatmapInfo.BaseDifficulty;
switch (pair.Key) switch (pair.Key)
{ {
case @"HPDrainRate": case @"HPDrainRate":
@ -229,7 +247,7 @@ namespace osu.Game.Beatmaps.Formats
{ {
case EventType.Background: case EventType.Background:
string filename = split[2].Trim('"'); string filename = split[2].Trim('"');
Beatmap.BeatmapInfo.Metadata.BackgroundFile = filename; beatmap.BeatmapInfo.Metadata.BackgroundFile = filename;
break; break;
case EventType.Break: case EventType.Break:
var breakEvent = new BreakPeriod var breakEvent = new BreakPeriod
@ -241,7 +259,7 @@ namespace osu.Game.Beatmaps.Formats
if (!breakEvent.HasEffect) if (!breakEvent.HasEffect)
return; return;
Beatmap.Breaks.Add(breakEvent); beatmap.Breaks.Add(breakEvent);
break; break;
} }
} }
@ -287,13 +305,13 @@ namespace osu.Game.Beatmaps.Formats
if (stringSampleSet == @"none") if (stringSampleSet == @"none")
stringSampleSet = @"normal"; stringSampleSet = @"normal";
DifficultyControlPoint difficultyPoint = Beatmap.ControlPointInfo.DifficultyPointAt(time); DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(time);
SoundControlPoint soundPoint = Beatmap.ControlPointInfo.SoundPointAt(time); SoundControlPoint soundPoint = beatmap.ControlPointInfo.SoundPointAt(time);
EffectControlPoint effectPoint = Beatmap.ControlPointInfo.EffectPointAt(time); EffectControlPoint effectPoint = beatmap.ControlPointInfo.EffectPointAt(time);
if (timingChange) if (timingChange)
{ {
Beatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint beatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint
{ {
Time = time, Time = time,
BeatLength = beatLength, BeatLength = beatLength,
@ -303,8 +321,8 @@ namespace osu.Game.Beatmaps.Formats
if (speedMultiplier != difficultyPoint.SpeedMultiplier) if (speedMultiplier != difficultyPoint.SpeedMultiplier)
{ {
Beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == time); beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == time);
Beatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint beatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint
{ {
Time = time, Time = time,
SpeedMultiplier = speedMultiplier SpeedMultiplier = speedMultiplier
@ -313,7 +331,7 @@ namespace osu.Game.Beatmaps.Formats
if (stringSampleSet != soundPoint.SampleBank || sampleVolume != soundPoint.SampleVolume) if (stringSampleSet != soundPoint.SampleBank || sampleVolume != soundPoint.SampleVolume)
{ {
Beatmap.ControlPointInfo.SoundPoints.Add(new SoundControlPoint beatmap.ControlPointInfo.SoundPoints.Add(new SoundControlPoint
{ {
Time = time, Time = time,
SampleBank = stringSampleSet, SampleBank = stringSampleSet,
@ -323,7 +341,7 @@ namespace osu.Game.Beatmaps.Formats
if (kiaiMode != effectPoint.KiaiMode || omitFirstBarSignature != effectPoint.OmitFirstBarLine) if (kiaiMode != effectPoint.KiaiMode || omitFirstBarSignature != effectPoint.OmitFirstBarLine)
{ {
Beatmap.ControlPointInfo.EffectPoints.Add(new EffectControlPoint beatmap.ControlPointInfo.EffectPoints.Add(new EffectControlPoint
{ {
Time = time, Time = time,
KiaiMode = kiaiMode, KiaiMode = kiaiMode,
@ -347,14 +365,14 @@ namespace osu.Game.Beatmaps.Formats
if (!hasCustomColours) if (!hasCustomColours)
{ {
Beatmap.ComboColors.Clear(); beatmap.ComboColors.Clear();
hasCustomColours = true; hasCustomColours = true;
} }
// Note: the combo index specified in the beatmap is discarded // Note: the combo index specified in the beatmap is discarded
if (pair.Key.StartsWith(@"Combo")) if (pair.Key.StartsWith(@"Combo"))
{ {
Beatmap.ComboColors.Add(new Color4 beatmap.ComboColors.Add(new Color4
{ {
R = r / 255f, R = r / 255f,
G = g / 255f, G = g / 255f,
@ -373,7 +391,7 @@ namespace osu.Game.Beatmaps.Formats
var obj = parser.Parse(line); var obj = parser.Parse(line);
if (obj != null) if (obj != null)
Beatmap.HitObjects.Add(obj); beatmap.HitObjects.Add(obj);
} }
private void handleVariables(string line) private void handleVariables(string line)

View File

@ -13,57 +13,36 @@ namespace osu.Game.Beatmaps.Formats
{ {
public static void Register() public static void Register()
{ {
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v14"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v14");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v13"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v13");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v12"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v12");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v11"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v11");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v10"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v10");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v9"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v9");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v8"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v8");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v7"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v7");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v6"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v6");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v5"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v5");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v4"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v4");
AddDecoder<LegacyBeatmapDecoder, LegacyStoryboardDecoder>(@"osu file format v3"); AddDecoder<LegacyBeatmapDecoder>(@"osu file format v3");
// TODO: differences between versions // TODO: differences between versions
} }
protected Beatmap Beatmap;
protected Storyboard Storyboard;
protected int BeatmapVersion; protected int BeatmapVersion;
protected readonly Dictionary<string, string> Variables = new Dictionary<string, string>(); protected readonly Dictionary<string, string> Variables = new Dictionary<string, string>();
public override Beatmap DecodeBeatmap(StreamReader stream) => new LegacyBeatmap(base.DecodeBeatmap(stream)); public override Decoder GetStoryboardDecoder() => new LegacyStoryboardDecoder(BeatmapVersion);
protected override Beatmap ParseBeatmap(StreamReader stream) => new LegacyBeatmap(base.ParseBeatmap(stream)); public override Beatmap DecodeBeatmap(StreamReader stream) => new LegacyBeatmap(base.DecodeBeatmap(stream));
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap) protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
{ {
if (stream == null) throw new NotImplementedException();
throw new ArgumentNullException(nameof(stream));
if (beatmap == null)
throw new ArgumentNullException(nameof(beatmap));
Beatmap = beatmap;
Beatmap.BeatmapInfo.BeatmapVersion = BeatmapVersion;
ParseContent(stream);
foreach (var hitObject in Beatmap.HitObjects)
hitObject.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty);
} }
protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard) protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard)
{ {
if (stream == null) throw new NotImplementedException();
throw new ArgumentNullException(nameof(stream));
if (storyboard == null)
throw new ArgumentNullException(nameof(storyboard));
Storyboard = storyboard;
ParseContent(stream);
} }
protected void ParseContent(StreamReader stream) protected void ParseContent(StreamReader stream)
@ -79,11 +58,12 @@ namespace osu.Game.Beatmaps.Formats
if (line.StartsWith("//")) if (line.StartsWith("//"))
continue; continue;
if (line.StartsWith(@"osu file format v")) // It's already set in ParseBeatmap... why do it again?
{ //if (line.StartsWith(@"osu file format v"))
Beatmap.BeatmapInfo.BeatmapVersion = int.Parse(line.Substring(17)); //{
continue; // Beatmap.BeatmapInfo.BeatmapVersion = int.Parse(line.Substring(17));
} // continue;
//}
if (line.StartsWith(@"[") && line.EndsWith(@"]")) if (line.StartsWith(@"[") && line.EndsWith(@"]"))
{ {

View File

@ -14,6 +14,8 @@ namespace osu.Game.Beatmaps.Formats
{ {
public class LegacyStoryboardDecoder : LegacyDecoder public class LegacyStoryboardDecoder : LegacyDecoder
{ {
private Storyboard storyboard;
private StoryboardSprite storyboardSprite; private StoryboardSprite storyboardSprite;
private CommandTimelineGroup timelineGroup; private CommandTimelineGroup timelineGroup;
@ -21,9 +23,21 @@ namespace osu.Game.Beatmaps.Formats
{ {
} }
public LegacyStoryboardDecoder(string header) public LegacyStoryboardDecoder(int beatmapVersion)
{ {
BeatmapVersion = int.Parse(header.Substring(17)); BeatmapVersion = beatmapVersion;
}
protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard)
{
if (stream == null)
throw new ArgumentNullException(nameof(stream));
if (storyboard == null)
throw new ArgumentNullException(nameof(storyboard));
this.storyboard = storyboard;
ParseContent(stream);
} }
protected override void ProcessSection(Section section, string line) protected override void ProcessSection(Section section, string line)
@ -67,7 +81,7 @@ namespace osu.Game.Beatmaps.Formats
var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo); var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo);
var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo);
storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y)); storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y));
Storyboard.GetLayer(layer).Add(storyboardSprite); storyboard.GetLayer(layer).Add(storyboardSprite);
} }
break; break;
case EventType.Animation: case EventType.Animation:
@ -81,7 +95,7 @@ namespace osu.Game.Beatmaps.Formats
var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo); var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo);
var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever; var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever;
storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType); storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType);
Storyboard.GetLayer(layer).Add(storyboardSprite); storyboard.GetLayer(layer).Add(storyboardSprite);
} }
break; break;
case EventType.Sample: case EventType.Sample:
@ -90,7 +104,7 @@ namespace osu.Game.Beatmaps.Formats
var layer = parseLayer(split[2]); var layer = parseLayer(split[2]);
var path = cleanFilename(split[3]); var path = cleanFilename(split[3]);
var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100; var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100;
Storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume)); storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume));
} }
break; break;
} }

View File

@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data))) using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(test_beatmap_data)))
using (var reader = new StreamReader(stream)) using (var reader = new StreamReader(stream))
beatmap = Game.Beatmaps.Formats.Decoder.GetBeatmapDecoder(reader).DecodeBeatmap(reader); beatmap = Game.Beatmaps.Formats.Decoder.GetDecoder(reader).DecodeBeatmap(reader);
return beatmap; return beatmap;
} }