mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 14:03:21 +08:00
split parsing a beatmap and parsing a storyboard
This commit is contained in:
parent
016057ab01
commit
c16925059c
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user