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

split parsing a beatmap and parsing a storyboard

This commit is contained in:
Aergwyn 2017-11-30 19:16:13 +01:00
parent 016057ab01
commit c16925059c
8 changed files with 262 additions and 203 deletions

View File

@ -22,7 +22,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
var decoder = new OsuLegacyDecoder(); var decoder = new OsuLegacyDecoder();
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
{ {
var beatmap = decoder.Decode(new StreamReader(stream)); var beatmap = decoder.DecodeBeatmap(new StreamReader(stream));
var meta = beatmap.BeatmapInfo.Metadata; var meta = beatmap.BeatmapInfo.Metadata;
Assert.AreEqual(241526, meta.OnlineBeatmapSetID); Assert.AreEqual(241526, meta.OnlineBeatmapSetID);
Assert.AreEqual("Soleily", meta.Artist); Assert.AreEqual("Soleily", meta.Artist);
@ -44,7 +44,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
var decoder = new OsuLegacyDecoder(); var decoder = new OsuLegacyDecoder();
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
{ {
var beatmapInfo = decoder.Decode(new StreamReader(stream)).BeatmapInfo; var beatmapInfo = decoder.DecodeBeatmap(new StreamReader(stream)).BeatmapInfo;
Assert.AreEqual(0, beatmapInfo.AudioLeadIn); Assert.AreEqual(0, beatmapInfo.AudioLeadIn);
Assert.AreEqual(false, beatmapInfo.Countdown); Assert.AreEqual(false, beatmapInfo.Countdown);
Assert.AreEqual(0.7f, beatmapInfo.StackLeniency); Assert.AreEqual(0.7f, beatmapInfo.StackLeniency);
@ -61,7 +61,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
var decoder = new OsuLegacyDecoder(); var decoder = new OsuLegacyDecoder();
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
{ {
var beatmap = decoder.Decode(new StreamReader(stream)).BeatmapInfo; var beatmap = decoder.DecodeBeatmap(new StreamReader(stream)).BeatmapInfo;
int[] expectedBookmarks = int[] expectedBookmarks =
{ {
11505, 22054, 32604, 43153, 53703, 64252, 74802, 85351, 11505, 22054, 32604, 43153, 53703, 64252, 74802, 85351,
@ -84,7 +84,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
var decoder = new OsuLegacyDecoder(); var decoder = new OsuLegacyDecoder();
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
{ {
var beatmap = decoder.Decode(new StreamReader(stream)); var beatmap = decoder.DecodeBeatmap(new StreamReader(stream));
var difficulty = beatmap.BeatmapInfo.BaseDifficulty; var difficulty = beatmap.BeatmapInfo.BaseDifficulty;
Assert.AreEqual(6.5f, difficulty.DrainRate); Assert.AreEqual(6.5f, difficulty.DrainRate);
Assert.AreEqual(4, difficulty.CircleSize); Assert.AreEqual(4, difficulty.CircleSize);
@ -101,7 +101,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
var decoder = new OsuLegacyDecoder(); var decoder = new OsuLegacyDecoder();
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
{ {
var beatmap = decoder.Decode(new StreamReader(stream)); var beatmap = decoder.DecodeBeatmap(new StreamReader(stream));
Color4[] expected = Color4[] expected =
{ {
new Color4(142, 199, 255, 255), new Color4(142, 199, 255, 255),
@ -123,7 +123,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
var decoder = new OsuLegacyDecoder(); var decoder = new OsuLegacyDecoder();
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
{ {
var beatmap = decoder.Decode(new StreamReader(stream)); var beatmap = decoder.DecodeBeatmap(new StreamReader(stream));
var curveData = beatmap.HitObjects[0] as IHasCurve; var curveData = beatmap.HitObjects[0] as IHasCurve;
var positionData = beatmap.HitObjects[0] as IHasPosition; var positionData = beatmap.HitObjects[0] as IHasPosition;

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 = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata; meta = BeatmapDecoder.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

@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual
var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true }; var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true };
storyboardContainer.Clock = decoupledClock; storyboardContainer.Clock = decoupledClock;
storyboard = working.Beatmap.Storyboard.CreateDrawable(beatmapBacking); storyboard = working.Storyboard.CreateDrawable(beatmapBacking);
storyboard.Passing = false; storyboard.Passing = false;
storyboardContainer.Add(storyboard); storyboardContainer.Add(storyboard);

View File

@ -41,11 +41,6 @@ namespace osu.Game.Beatmaps
/// </summary> /// </summary>
public double TotalBreakTime => Breaks.Sum(b => b.Duration); public double TotalBreakTime => Breaks.Sum(b => b.Duration);
/// <summary>
/// The Beatmap's Storyboard.
/// </summary>
public Storyboard Storyboard = new Storyboard();
/// <summary> /// <summary>
/// Constructs a new beatmap. /// Constructs a new beatmap.
/// </summary> /// </summary>
@ -57,7 +52,6 @@ namespace osu.Game.Beatmaps
Breaks = original?.Breaks ?? Breaks; Breaks = original?.Breaks ?? Breaks;
ComboColors = original?.ComboColors ?? ComboColors; ComboColors = original?.ComboColors ?? ComboColors;
HitObjects = original?.HitObjects ?? HitObjects; HitObjects = original?.HitObjects ?? HitObjects;
Storyboard = original?.Storyboard ?? Storyboard;
if (original == null && Metadata == null) if (original == null && Metadata == null)
{ {

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 = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata; metadata = BeatmapDecoder.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
@ -519,7 +519,7 @@ namespace osu.Game.Beatmaps
ms.Position = 0; ms.Position = 0;
var decoder = BeatmapDecoder.GetDecoder(sr); var decoder = BeatmapDecoder.GetDecoder(sr);
Beatmap beatmap = decoder.Decode(sr); Beatmap beatmap = decoder.DecodeBeatmap(sr);
beatmap.BeatmapInfo.Path = name; beatmap.BeatmapInfo.Path = name;
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
@ -572,7 +572,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))))
{ {
BeatmapDecoder decoder = BeatmapDecoder.GetDecoder(stream); BeatmapDecoder decoder = BeatmapDecoder.GetDecoder(stream);
return decoder.Decode(stream); return decoder.DecodeBeatmap(stream);
} }
} }
catch catch
@ -615,19 +615,17 @@ namespace osu.Game.Beatmaps
protected override Storyboard GetStoryboard() protected override Storyboard GetStoryboard()
{ {
if (BeatmapSetInfo?.StoryboardFile == null)
return new Storyboard();
try try
{ {
if (Beatmap == null || BeatmapSetInfo.StoryboardFile == null)
return new Storyboard();
BeatmapDecoder decoder; BeatmapDecoder decoder;
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
decoder = BeatmapDecoder.GetDecoder(stream); decoder = BeatmapDecoder.GetDecoder(stream);
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile)))) using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile))))
decoder.Decode(stream, Beatmap); return decoder.DecodeStoryboard(stream);
return Beatmap.Storyboard;
} }
catch catch
{ {

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using osu.Game.Storyboards;
namespace osu.Game.Beatmaps.Formats namespace osu.Game.Beatmaps.Formats
{ {
@ -35,17 +36,12 @@ namespace osu.Game.Beatmaps.Formats
decoders[magic] = typeof(T); decoders[magic] = typeof(T);
} }
public virtual Beatmap Decode(StreamReader stream) public virtual Beatmap DecodeBeatmap(StreamReader stream)
{ {
return ParseFile(stream); return ParseBeatmap(stream);
} }
public virtual void Decode(StreamReader stream, Beatmap beatmap) protected virtual Beatmap ParseBeatmap(StreamReader stream)
{
ParseFile(stream, beatmap);
}
protected virtual Beatmap ParseFile(StreamReader stream)
{ {
var beatmap = new Beatmap var beatmap = new Beatmap
{ {
@ -56,10 +52,19 @@ namespace osu.Game.Beatmaps.Formats
}, },
}; };
ParseFile(stream, beatmap); ParseBeatmap(stream, beatmap);
return beatmap; return beatmap;
} }
protected abstract void ParseFile(StreamReader stream, Beatmap beatmap); protected abstract void ParseBeatmap(StreamReader stream, Beatmap beatmap);
public virtual Storyboard DecodeStoryboard(StreamReader stream)
{
var storyboard = new Storyboard();
ParseStoryboard(stream, storyboard);
return storyboard;
}
protected abstract void ParseStoryboard(StreamReader stream, Storyboard storyboard);
} }
} }

View File

@ -54,20 +54,135 @@ namespace osu.Game.Beatmaps.Formats
beatmapVersion = int.Parse(header.Substring(17)); beatmapVersion = int.Parse(header.Substring(17));
} }
private enum Section //
protected override Beatmap ParseBeatmap(StreamReader stream)
{ {
None, return new LegacyBeatmap(base.ParseBeatmap(stream));
General,
Editor,
Metadata,
Difficulty,
Events,
TimingPoints,
Colours,
HitObjects,
Variables,
} }
public override Beatmap DecodeBeatmap(StreamReader stream)
{
return new LegacyBeatmap(base.DecodeBeatmap(stream));
}
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
{
if (beatmap == null)
throw new ArgumentNullException(nameof(beatmap));
if (stream == null)
throw new ArgumentNullException(nameof(stream));
beatmap.BeatmapInfo.BeatmapVersion = beatmapVersion;
Section section = Section.None;
bool hasCustomColours = false;
string line;
while ((line = stream.ReadLine()) != null)
{
if (string.IsNullOrWhiteSpace(line))
continue;
if (line.StartsWith("//"))
continue;
if (line.StartsWith(@"osu file format v"))
{
beatmap.BeatmapInfo.BeatmapVersion = int.Parse(line.Substring(17));
continue;
}
if (line.StartsWith(@"[") && line.EndsWith(@"]"))
{
if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section))
throw new InvalidDataException($@"Unknown osu section {line}");
continue;
}
switch (section)
{
case Section.General:
handleGeneral(beatmap, line);
break;
case Section.Editor:
handleEditor(beatmap, line);
break;
case Section.Metadata:
handleMetadata(beatmap, line);
break;
case Section.Difficulty:
handleDifficulty(beatmap, line);
break;
case Section.Events:
handleEvents(beatmap, line);
break;
case Section.TimingPoints:
handleTimingPoints(beatmap, line);
break;
case Section.Colours:
handleColours(beatmap, line, ref hasCustomColours);
break;
case Section.HitObjects:
// If the ruleset wasn't specified, assume the osu!standard ruleset.
if (parser == null)
parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser();
var obj = parser.Parse(line);
if (obj != null)
beatmap.HitObjects.Add(obj);
break;
case Section.Variables:
handleVariables(line);
break;
}
}
foreach (var hitObject in beatmap.HitObjects)
hitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty);
}
protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard)
{
if (storyboard == null)
throw new ArgumentNullException(nameof(storyboard));
if (stream == null)
throw new ArgumentNullException(nameof(stream));
Section section = Section.None;
StoryboardSprite storyboardSprite = null;
CommandTimelineGroup timelineGroup = null;
string line;
while ((line = stream.ReadLine()) != null)
{
if (string.IsNullOrWhiteSpace(line))
continue;
if (line.StartsWith("//"))
continue;
if (line.StartsWith(@"[") && line.EndsWith(@"]"))
{
if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section))
throw new InvalidDataException($@"Unknown osu section {line}");
continue;
}
switch (section)
{
case Section.Events:
handleEvents(storyboard, line, ref storyboardSprite, ref timelineGroup);
break;
}
}
}
//
private void handleGeneral(Beatmap beatmap, string line) private void handleGeneral(Beatmap beatmap, string line)
{ {
if (beatmap == null) if (beatmap == null)
@ -240,38 +355,49 @@ namespace osu.Game.Beatmaps.Formats
} }
} }
/// <summary> private void handleEvents(Beatmap beatmap, string line)
/// Decodes any beatmap variables present in a line into their real values.
/// </summary>
/// <param name="line">The line which may contains variables.</param>
private void decodeVariables(ref string line)
{
if (line == null)
throw new ArgumentNullException(nameof(line));
while (line.IndexOf('$') >= 0)
{
string origLine = line;
string[] split = line.Split(',');
for (int i = 0; i < split.Length; i++)
{
var item = split[i];
if (item.StartsWith("$") && variables.ContainsKey(item))
split[i] = variables[item];
}
line = string.Join(",", split);
if (line == origLine) break;
}
}
private void handleEvents(Beatmap beatmap, string line, ref StoryboardSprite storyboardSprite, ref CommandTimelineGroup timelineGroup)
{ {
if (line == null) if (line == null)
throw new ArgumentNullException(nameof(line)); throw new ArgumentNullException(nameof(line));
if (beatmap == null) if (beatmap == null)
throw new ArgumentNullException(nameof(beatmap)); throw new ArgumentNullException(nameof(beatmap));
decodeVariables(ref line);
string[] split = line.Split(',');
EventType type;
if (!Enum.TryParse(split[0], out type))
throw new InvalidDataException($@"Unknown event type {split[0]}");
switch (type)
{
case EventType.Background:
string filename = split[2].Trim('"');
beatmap.BeatmapInfo.Metadata.BackgroundFile = filename;
break;
case EventType.Break:
var breakEvent = new BreakPeriod
{
StartTime = double.Parse(split[1], NumberFormatInfo.InvariantInfo),
EndTime = double.Parse(split[2], NumberFormatInfo.InvariantInfo)
};
if (!breakEvent.HasEffect)
return;
beatmap.Breaks.Add(breakEvent);
break;
}
}
private void handleEvents(Storyboard storyboard, string line, ref StoryboardSprite storyboardSprite, ref CommandTimelineGroup timelineGroup)
{
if (line == null)
throw new ArgumentNullException(nameof(line));
if (storyboard == null)
throw new ArgumentNullException(nameof(storyboard));
var depth = 0; var depth = 0;
while (line.StartsWith(" ") || line.StartsWith("_")) while (line.StartsWith(" ") || line.StartsWith("_"))
{ {
@ -293,26 +419,6 @@ namespace osu.Game.Beatmaps.Formats
switch (type) switch (type)
{ {
case EventType.Video:
case EventType.Background:
string filename = split[2].Trim('"');
if (type == EventType.Background)
beatmap.BeatmapInfo.Metadata.BackgroundFile = filename;
break;
case EventType.Break:
var breakEvent = new BreakPeriod
{
StartTime = double.Parse(split[1], NumberFormatInfo.InvariantInfo),
EndTime = double.Parse(split[2], NumberFormatInfo.InvariantInfo)
};
if (!breakEvent.HasEffect)
return;
beatmap.Breaks.Add(breakEvent);
break;
case EventType.Sprite: case EventType.Sprite:
{ {
var layer = parseLayer(split[1]); var layer = parseLayer(split[1]);
@ -321,7 +427,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));
beatmap.Storyboard.GetLayer(layer).Add(storyboardSprite); storyboard.GetLayer(layer).Add(storyboardSprite);
} }
break; break;
case EventType.Animation: case EventType.Animation:
@ -335,7 +441,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);
beatmap.Storyboard.GetLayer(layer).Add(storyboardSprite); storyboard.GetLayer(layer).Add(storyboardSprite);
} }
break; break;
case EventType.Sample: case EventType.Sample:
@ -344,7 +450,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;
beatmap.Storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume)); storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume));
} }
break; break;
} }
@ -456,9 +562,15 @@ namespace osu.Game.Beatmaps.Formats
var type = split[4]; var type = split[4];
switch (type) switch (type)
{ {
case "A": timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit); break; case "A":
case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime); break; timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit);
case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime); break; break;
case "H":
timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime);
break;
case "V":
timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime);
break;
} }
} }
break; break;
@ -471,30 +583,6 @@ namespace osu.Game.Beatmaps.Formats
} }
} }
private static string cleanFilename(string path)
=> FileSafety.PathStandardise(path.Trim('\"'));
private static Anchor parseOrigin(string value)
{
var origin = (LegacyOrigins)Enum.Parse(typeof(LegacyOrigins), value);
switch (origin)
{
case LegacyOrigins.TopLeft: return Anchor.TopLeft;
case LegacyOrigins.TopCentre: return Anchor.TopCentre;
case LegacyOrigins.TopRight: return Anchor.TopRight;
case LegacyOrigins.CentreLeft: return Anchor.CentreLeft;
case LegacyOrigins.Centre: return Anchor.Centre;
case LegacyOrigins.CentreRight: return Anchor.CentreRight;
case LegacyOrigins.BottomLeft: return Anchor.BottomLeft;
case LegacyOrigins.BottomCentre: return Anchor.BottomCentre;
case LegacyOrigins.BottomRight: return Anchor.BottomRight;
}
throw new InvalidDataException($@"Unknown origin: {value}");
}
private static string parseLayer(string value)
=> Enum.Parse(typeof(StoryLayer), value).ToString();
private void handleTimingPoints(Beatmap beatmap, string line) private void handleTimingPoints(Beatmap beatmap, string line)
{ {
if (beatmap == null) if (beatmap == null)
@ -632,97 +720,57 @@ namespace osu.Game.Beatmaps.Formats
variables[pair.Key] = pair.Value; variables[pair.Key] = pair.Value;
} }
protected override Beatmap ParseFile(StreamReader stream) //
/// <summary>
/// Decodes any beatmap variables present in a line into their real values.
/// </summary>
/// <param name="line">The line which may contains variables.</param>
private void decodeVariables(ref string line)
{ {
return new LegacyBeatmap(base.ParseFile(stream)); if (line == null)
} throw new ArgumentNullException(nameof(line));
public override Beatmap Decode(StreamReader stream) while (line.IndexOf('$') >= 0)
{
return new LegacyBeatmap(base.Decode(stream));
}
protected override void ParseFile(StreamReader stream, Beatmap beatmap)
{
if (beatmap == null)
throw new ArgumentNullException(nameof(beatmap));
if (stream == null)
throw new ArgumentNullException(nameof(stream));
beatmap.BeatmapInfo.BeatmapVersion = beatmapVersion;
Section section = Section.None;
bool hasCustomColours = false;
StoryboardSprite storyboardSprite = null;
CommandTimelineGroup timelineGroup = null;
string line;
while ((line = stream.ReadLine()) != null)
{ {
if (string.IsNullOrWhiteSpace(line)) string origLine = line;
continue; string[] split = line.Split(',');
for (int i = 0; i < split.Length; i++)
if (line.StartsWith("//"))
continue;
if (line.StartsWith(@"osu file format v"))
{ {
beatmap.BeatmapInfo.BeatmapVersion = int.Parse(line.Substring(17)); var item = split[i];
continue; if (item.StartsWith("$") && variables.ContainsKey(item))
split[i] = variables[item];
} }
if (line.StartsWith(@"[") && line.EndsWith(@"]")) line = string.Join(",", split);
{ if (line == origLine) break;
if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section))
throw new InvalidDataException($@"Unknown osu section {line}");
continue;
}
switch (section)
{
case Section.General:
handleGeneral(beatmap, line);
break;
case Section.Editor:
handleEditor(beatmap, line);
break;
case Section.Metadata:
handleMetadata(beatmap, line);
break;
case Section.Difficulty:
handleDifficulty(beatmap, line);
break;
case Section.Events:
handleEvents(beatmap, line, ref storyboardSprite, ref timelineGroup);
break;
case Section.TimingPoints:
handleTimingPoints(beatmap, line);
break;
case Section.Colours:
handleColours(beatmap, line, ref hasCustomColours);
break;
case Section.HitObjects:
// If the ruleset wasn't specified, assume the osu!standard ruleset.
if (parser == null)
parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser();
var obj = parser.Parse(line);
if (obj != null)
beatmap.HitObjects.Add(obj);
break;
case Section.Variables:
handleVariables(line);
break;
}
} }
foreach (var hitObject in beatmap.HitObjects)
hitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty);
} }
private static string cleanFilename(string path)
=> FileSafety.PathStandardise(path.Trim('\"'));
private static Anchor parseOrigin(string value)
{
var origin = (LegacyOrigins)Enum.Parse(typeof(LegacyOrigins), value);
switch (origin)
{
case LegacyOrigins.TopLeft: return Anchor.TopLeft;
case LegacyOrigins.TopCentre: return Anchor.TopCentre;
case LegacyOrigins.TopRight: return Anchor.TopRight;
case LegacyOrigins.CentreLeft: return Anchor.CentreLeft;
case LegacyOrigins.Centre: return Anchor.Centre;
case LegacyOrigins.CentreRight: return Anchor.CentreRight;
case LegacyOrigins.BottomLeft: return Anchor.BottomLeft;
case LegacyOrigins.BottomCentre: return Anchor.BottomCentre;
case LegacyOrigins.BottomRight: return Anchor.BottomRight;
}
throw new InvalidDataException($@"Unknown origin: {value}");
}
private static string parseLayer(string value)
=> Enum.Parse(typeof(StoryLayer), value).ToString();
private KeyValuePair<string, string> splitKeyVal(string line, char separator) private KeyValuePair<string, string> splitKeyVal(string line, char separator)
{ {
if (line == null) if (line == null)
@ -737,6 +785,20 @@ namespace osu.Game.Beatmaps.Formats
); );
} }
private enum Section
{
None,
General,
Editor,
Metadata,
Difficulty,
Events,
TimingPoints,
Colours,
HitObjects,
Variables,
}
internal enum LegacySampleBank internal enum LegacySampleBank
{ {
None = 0, None = 0,

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 = BeatmapDecoder.GetDecoder(reader).Decode(reader); beatmap = BeatmapDecoder.GetDecoder(reader).DecodeBeatmap(reader);
return beatmap; return beatmap;
} }