mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 16:32:54 +08:00
Merge branch 'master' into mania-difficulty
This commit is contained in:
commit
8cbcdeb665
@ -24,7 +24,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var beatmap = decoder.DecodeBeatmap(stream);
|
var beatmap = decoder.Decode(stream);
|
||||||
var beatmapInfo = beatmap.BeatmapInfo;
|
var beatmapInfo = beatmap.BeatmapInfo;
|
||||||
var metadata = beatmap.Metadata;
|
var metadata = beatmap.Metadata;
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var beatmapInfo = decoder.DecodeBeatmap(stream).BeatmapInfo;
|
var beatmapInfo = decoder.Decode(stream).BeatmapInfo;
|
||||||
|
|
||||||
int[] expectedBookmarks =
|
int[] expectedBookmarks =
|
||||||
{
|
{
|
||||||
@ -72,7 +72,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var beatmap = decoder.DecodeBeatmap(stream);
|
var beatmap = decoder.Decode(stream);
|
||||||
var beatmapInfo = beatmap.BeatmapInfo;
|
var beatmapInfo = beatmap.BeatmapInfo;
|
||||||
var metadata = beatmap.Metadata;
|
var metadata = beatmap.Metadata;
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var difficulty = decoder.DecodeBeatmap(stream).BeatmapInfo.BaseDifficulty;
|
var difficulty = decoder.Decode(stream).BeatmapInfo.BaseDifficulty;
|
||||||
|
|
||||||
Assert.AreEqual(6.5f, difficulty.DrainRate);
|
Assert.AreEqual(6.5f, difficulty.DrainRate);
|
||||||
Assert.AreEqual(4, difficulty.CircleSize);
|
Assert.AreEqual(4, difficulty.CircleSize);
|
||||||
@ -114,7 +114,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var beatmap = decoder.DecodeBeatmap(stream);
|
var beatmap = decoder.Decode(stream);
|
||||||
var metadata = beatmap.Metadata;
|
var metadata = beatmap.Metadata;
|
||||||
var breakPoint = beatmap.Breaks[0];
|
var breakPoint = beatmap.Breaks[0];
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var beatmap = decoder.DecodeBeatmap(stream);
|
var beatmap = decoder.Decode(stream);
|
||||||
var controlPoints = beatmap.ControlPointInfo;
|
var controlPoints = beatmap.ControlPointInfo;
|
||||||
|
|
||||||
Assert.AreEqual(4, controlPoints.TimingPoints.Count);
|
Assert.AreEqual(4, controlPoints.TimingPoints.Count);
|
||||||
@ -167,7 +167,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var comboColors = decoder.DecodeBeatmap(stream).ComboColors;
|
var comboColors = decoder.Decode(stream).ComboColors;
|
||||||
|
|
||||||
Color4[] expectedColors =
|
Color4[] expectedColors =
|
||||||
{
|
{
|
||||||
@ -191,7 +191,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var hitObjects = decoder.DecodeBeatmap(stream).HitObjects;
|
var hitObjects = decoder.Decode(stream).HitObjects;
|
||||||
|
|
||||||
var curveData = hitObjects[0] as IHasCurve;
|
var curveData = hitObjects[0] as IHasCurve;
|
||||||
var positionData = hitObjects[0] as IHasPosition;
|
var positionData = hitObjects[0] as IHasPosition;
|
||||||
|
@ -18,11 +18,11 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestDecodeStoryboardEvents()
|
public void TestDecodeStoryboardEvents()
|
||||||
{
|
{
|
||||||
var decoder = new LegacyBeatmapDecoder();
|
var decoder = new LegacyStoryboardDecoder();
|
||||||
using (var resStream = Resource.OpenResource("Himeringo - Yotsuya-san ni Yoroshiku (RLC) [Winber1's Extreme].osu"))
|
using (var resStream = Resource.OpenResource("Himeringo - Yotsuya-san ni Yoroshiku (RLC) [Winber1's Extreme].osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var storyboard = decoder.GetStoryboardDecoder().DecodeStoryboard(stream);
|
var storyboard = decoder.Decode(stream);
|
||||||
|
|
||||||
Assert.IsTrue(storyboard.HasDrawable);
|
Assert.IsTrue(storyboard.HasDrawable);
|
||||||
Assert.AreEqual(4, storyboard.Layers.Count());
|
Assert.AreEqual(4, storyboard.Layers.Count());
|
||||||
|
@ -159,7 +159,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var sr = new StreamReader(stream))
|
using (var sr = new StreamReader(stream))
|
||||||
{
|
{
|
||||||
|
|
||||||
var legacyDecoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.DecodeBeatmap(sr);
|
var legacyDecoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.Decode(sr);
|
||||||
using (var ms = new MemoryStream())
|
using (var ms = new MemoryStream())
|
||||||
using (var sw = new StreamWriter(ms))
|
using (var sw = new StreamWriter(ms))
|
||||||
using (var sr2 = new StreamReader(ms))
|
using (var sr2 = new StreamReader(ms))
|
||||||
@ -168,7 +168,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
sw.Flush();
|
sw.Flush();
|
||||||
|
|
||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
return (legacyDecoded, new JsonBeatmapDecoder().DecodeBeatmap(sr2));
|
return (legacyDecoded, new JsonBeatmapDecoder().Decode(sr2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.GetDecoder(stream).DecodeBeatmap(stream).Metadata;
|
meta = Decoder.GetDecoder<Beatmap>(stream).Decode(stream).Metadata;
|
||||||
|
|
||||||
Assert.AreEqual(241526, meta.OnlineBeatmapSetID);
|
Assert.AreEqual(241526, meta.OnlineBeatmapSetID);
|
||||||
Assert.AreEqual("Soleily", meta.Artist);
|
Assert.AreEqual("Soleily", meta.Artist);
|
||||||
|
@ -22,6 +22,7 @@ namespace osu.Game.Beatmaps
|
|||||||
public BeatmapInfo BeatmapInfo = new BeatmapInfo();
|
public BeatmapInfo BeatmapInfo = new BeatmapInfo();
|
||||||
public ControlPointInfo ControlPointInfo = new ControlPointInfo();
|
public ControlPointInfo ControlPointInfo = new ControlPointInfo();
|
||||||
public List<BreakPeriod> Breaks = new List<BreakPeriod>();
|
public List<BreakPeriod> Breaks = new List<BreakPeriod>();
|
||||||
|
|
||||||
public List<Color4> ComboColors = new List<Color4>
|
public List<Color4> ComboColors = new List<Color4>
|
||||||
{
|
{
|
||||||
new Color4(17, 136, 170, 255),
|
new Color4(17, 136, 170, 255),
|
||||||
@ -85,9 +86,13 @@ namespace osu.Game.Beatmaps
|
|||||||
/// Constructs a new beatmap.
|
/// Constructs a new beatmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="original">The original beatmap to use the parameters of.</param>
|
/// <param name="original">The original beatmap to use the parameters of.</param>
|
||||||
public Beatmap(Beatmap original = null)
|
public Beatmap(Beatmap original)
|
||||||
: base(original)
|
: base(original)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Beatmap()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,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.GetDecoder(stream).DecodeBeatmap(stream).Metadata;
|
metadata = Decoder.GetDecoder<Beatmap>(stream).Decode(stream).Metadata;
|
||||||
|
|
||||||
return new BeatmapSetInfo
|
return new BeatmapSetInfo
|
||||||
{
|
{
|
||||||
@ -328,8 +328,8 @@ namespace osu.Game.Beatmaps
|
|||||||
raw.CopyTo(ms);
|
raw.CopyTo(ms);
|
||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
|
|
||||||
var decoder = Decoder.GetDecoder(sr);
|
var decoder = Decoder.GetDecoder<Beatmap>(sr);
|
||||||
Beatmap beatmap = decoder.DecodeBeatmap(sr);
|
Beatmap beatmap = decoder.Decode(sr);
|
||||||
|
|
||||||
beatmap.BeatmapInfo.Path = name;
|
beatmap.BeatmapInfo.Path = name;
|
||||||
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
|
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Beatmaps.Formats;
|
using osu.Game.Beatmaps.Formats;
|
||||||
using osu.Game.Graphics.Textures;
|
using osu.Game.Graphics.Textures;
|
||||||
using osu.Game.Storyboards;
|
using osu.Game.Storyboards;
|
||||||
@ -30,10 +31,7 @@ namespace osu.Game.Beatmaps
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
|
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
|
||||||
{
|
return Decoder.GetDecoder<Beatmap>(stream).Decode(stream);
|
||||||
Decoder decoder = Decoder.GetDecoder(stream);
|
|
||||||
return decoder.DecodeBeatmap(stream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -78,23 +76,23 @@ namespace osu.Game.Beatmaps
|
|||||||
Storyboard storyboard;
|
Storyboard storyboard;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var beatmap = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
|
using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path))))
|
||||||
{
|
{
|
||||||
Decoder decoder = Decoder.GetDecoder(beatmap);
|
var decoder = Decoder.GetDecoder<Storyboard>(stream);
|
||||||
|
|
||||||
// todo: support loading from both set-wide storyboard *and* beatmap specific.
|
// todo: support loading from both set-wide storyboard *and* beatmap specific.
|
||||||
|
|
||||||
if (BeatmapSetInfo?.StoryboardFile == null)
|
if (BeatmapSetInfo?.StoryboardFile == null)
|
||||||
storyboard = decoder.GetStoryboardDecoder().DecodeStoryboard(beatmap);
|
storyboard = decoder.Decode(stream);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using (var reader = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile))))
|
using (var secondaryStream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile))))
|
||||||
storyboard = decoder.GetStoryboardDecoder().DecodeStoryboard(beatmap, reader);
|
storyboard = decoder.Decode(stream, secondaryStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
Logger.Error(e, "Storyboard failed to load");
|
||||||
storyboard = new Storyboard();
|
storyboard = new Storyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,38 +4,64 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using osu.Game.Storyboards;
|
using System.Linq;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Formats
|
namespace osu.Game.Beatmaps.Formats
|
||||||
{
|
{
|
||||||
|
public abstract class Decoder<TOutput> : Decoder
|
||||||
|
where TOutput : new()
|
||||||
|
{
|
||||||
|
protected virtual TOutput CreateTemplateObject() => new TOutput();
|
||||||
|
|
||||||
|
public TOutput Decode(StreamReader primaryStream, params StreamReader[] otherStreams)
|
||||||
|
{
|
||||||
|
var output = CreateTemplateObject();
|
||||||
|
foreach (StreamReader stream in new[] { primaryStream }.Concat(otherStreams))
|
||||||
|
ParseStreamInto(stream, output);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void ParseStreamInto(StreamReader stream, TOutput beatmap);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class Decoder
|
public abstract class Decoder
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, Func<string, Decoder>> decoders = new Dictionary<string, Func<string, Decoder>>();
|
private static readonly Dictionary<Type, Dictionary<string, Func<string, Decoder>>> decoders = new Dictionary<Type, Dictionary<string, Func<string, Decoder>>>();
|
||||||
|
|
||||||
static Decoder()
|
static Decoder()
|
||||||
{
|
{
|
||||||
LegacyDecoder.Register();
|
LegacyBeatmapDecoder.Register();
|
||||||
JsonBeatmapDecoder.Register();
|
JsonBeatmapDecoder.Register();
|
||||||
|
LegacyStoryboardDecoder.Register();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves a <see cref="Decoder"/> to parse a <see cref="Beatmap"/>.
|
/// Retrieves a <see cref="Decoder"/> to parse a <see cref="Beatmap"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stream">A stream pointing to the <see cref="Beatmap"/>.</param>
|
/// <param name="stream">A stream pointing to the <see cref="Beatmap"/>.</param>
|
||||||
public static Decoder GetDecoder(StreamReader stream)
|
public static Decoder<T> GetDecoder<T>(StreamReader stream)
|
||||||
|
where T : new()
|
||||||
{
|
{
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
throw new ArgumentNullException(nameof(stream));
|
throw new ArgumentNullException(nameof(stream));
|
||||||
|
|
||||||
|
if (!decoders.TryGetValue(typeof(T), out var typedDecoders))
|
||||||
|
throw new IOException(@"Unknown decoder type");
|
||||||
|
|
||||||
string line;
|
string line;
|
||||||
do
|
do
|
||||||
{ line = stream.ReadLine()?.Trim(); }
|
{
|
||||||
while (line != null && line.Length == 0);
|
line = stream.ReadLine()?.Trim();
|
||||||
|
} while (line != null && line.Length == 0);
|
||||||
|
|
||||||
if (line == null || !decoders.ContainsKey(line))
|
if (line == null)
|
||||||
throw new IOException(@"Unknown file format");
|
throw new IOException(@"Unknown file format");
|
||||||
|
|
||||||
return decoders[line](line);
|
var decoder = typedDecoders.Select(d => line.StartsWith(d.Key) ? d.Value : null).FirstOrDefault();
|
||||||
|
if (decoder == null)
|
||||||
|
throw new IOException(@"Unknown file format");
|
||||||
|
|
||||||
|
return (Decoder<T>)decoder.Invoke(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -43,41 +69,12 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="magic">A string in the file which triggers this decoder to be used.</param>
|
/// <param name="magic">A string in the file which triggers this decoder to be used.</param>
|
||||||
/// <param name="constructor">A function which constructs the <see cref="Decoder"/> given <paramref name="magic"/>.</param>
|
/// <param name="constructor">A function which constructs the <see cref="Decoder"/> given <paramref name="magic"/>.</param>
|
||||||
protected static void AddDecoder(string magic, Func<string, Decoder> constructor)
|
protected static void AddDecoder<T>(string magic, Func<string, Decoder> constructor)
|
||||||
{
|
{
|
||||||
decoders[magic] = constructor;
|
if (!decoders.TryGetValue(typeof(T), out var typedDecoders))
|
||||||
|
decoders.Add(typeof(T), typedDecoders = new Dictionary<string, Func<string, Decoder>>());
|
||||||
|
|
||||||
|
typedDecoders[magic] = constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves a <see cref="Decoder"/> to parse a <see cref="Storyboard"/>
|
|
||||||
/// </summary>
|
|
||||||
public abstract Decoder GetStoryboardDecoder();
|
|
||||||
|
|
||||||
public virtual Beatmap DecodeBeatmap(StreamReader stream)
|
|
||||||
{
|
|
||||||
var beatmap = new Beatmap
|
|
||||||
{
|
|
||||||
BeatmapInfo = new BeatmapInfo
|
|
||||||
{
|
|
||||||
Metadata = new BeatmapMetadata(),
|
|
||||||
BaseDifficulty = new BeatmapDifficulty(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
ParseBeatmap(stream, beatmap);
|
|
||||||
return beatmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void ParseBeatmap(StreamReader stream, Beatmap beatmap);
|
|
||||||
|
|
||||||
public virtual Storyboard DecodeStoryboard(params StreamReader[] streams)
|
|
||||||
{
|
|
||||||
var storyboard = new Storyboard();
|
|
||||||
foreach (StreamReader stream in streams)
|
|
||||||
ParseStoryboard(stream, storyboard);
|
|
||||||
return storyboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void ParseStoryboard(StreamReader stream, Storyboard storyboard);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,17 @@
|
|||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using osu.Game.IO.Serialization;
|
using osu.Game.IO.Serialization;
|
||||||
using osu.Game.Storyboards;
|
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Formats
|
namespace osu.Game.Beatmaps.Formats
|
||||||
{
|
{
|
||||||
public class JsonBeatmapDecoder : Decoder
|
public class JsonBeatmapDecoder : Decoder<Beatmap>
|
||||||
{
|
{
|
||||||
public static void Register()
|
public static void Register()
|
||||||
{
|
{
|
||||||
AddDecoder("{", m => new JsonBeatmapDecoder());
|
AddDecoder<Beatmap>("{", m => new JsonBeatmapDecoder());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Decoder GetStoryboardDecoder() => this;
|
protected override void ParseStreamInto(StreamReader stream, Beatmap beatmap)
|
||||||
|
|
||||||
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
|
|
||||||
{
|
{
|
||||||
stream.BaseStream.Position = 0;
|
stream.BaseStream.Position = 0;
|
||||||
stream.DiscardBufferedData();
|
stream.DiscardBufferedData();
|
||||||
@ -26,10 +23,5 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
foreach (var hitObject in beatmap.HitObjects)
|
foreach (var hitObject in beatmap.HitObjects)
|
||||||
hitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty);
|
hitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard)
|
|
||||||
{
|
|
||||||
// throw new System.NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
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;
|
||||||
@ -12,8 +13,10 @@ using osu.Framework;
|
|||||||
|
|
||||||
namespace osu.Game.Beatmaps.Formats
|
namespace osu.Game.Beatmaps.Formats
|
||||||
{
|
{
|
||||||
public class LegacyBeatmapDecoder : LegacyDecoder
|
public class LegacyBeatmapDecoder : LegacyDecoder<Beatmap>
|
||||||
{
|
{
|
||||||
|
public const int LATEST_VERSION = 14;
|
||||||
|
|
||||||
private Beatmap beatmap;
|
private Beatmap beatmap;
|
||||||
|
|
||||||
private bool hasCustomColours;
|
private bool hasCustomColours;
|
||||||
@ -22,6 +25,11 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
private LegacySampleBank defaultSampleBank;
|
private LegacySampleBank defaultSampleBank;
|
||||||
private int defaultSampleVolume = 100;
|
private int defaultSampleVolume = 100;
|
||||||
|
|
||||||
|
public static void Register()
|
||||||
|
{
|
||||||
|
AddDecoder<Beatmap>(@"osu file format v", m => new LegacyBeatmapDecoder(int.Parse(m.Split('v').Last())));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// lazer's audio timings in general doesn't match stable. this is the result of user testing, albeit limited.
|
/// lazer's audio timings in general doesn't match stable. this is the result of user testing, albeit limited.
|
||||||
/// This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
|
/// This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
|
||||||
@ -35,29 +43,18 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
private readonly int offset = UniversalOffset;
|
private readonly int offset = UniversalOffset;
|
||||||
|
|
||||||
public LegacyBeatmapDecoder()
|
public LegacyBeatmapDecoder(int version = LATEST_VERSION) : base(version)
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
public LegacyBeatmapDecoder(string header)
|
|
||||||
{
|
|
||||||
BeatmapVersion = int.Parse(header.Substring(17));
|
|
||||||
|
|
||||||
// BeatmapVersion 4 and lower had an incorrect offset (stable has this set as 24ms off)
|
// BeatmapVersion 4 and lower had an incorrect offset (stable has this set as 24ms off)
|
||||||
offset += BeatmapVersion < 5 ? 24 : 0;
|
offset += FormatVersion < 5 ? 24 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
|
protected override void ParseStreamInto(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 = beatmap;
|
||||||
this.beatmap.BeatmapInfo.BeatmapVersion = BeatmapVersion;
|
this.beatmap.BeatmapInfo.BeatmapVersion = FormatVersion;
|
||||||
|
|
||||||
ParseContent(stream);
|
base.ParseStreamInto(stream, beatmap);
|
||||||
|
|
||||||
// objects may be out of order *only* if a user has manually edited an .osu file.
|
// objects may be out of order *only* if a user has manually edited an .osu file.
|
||||||
// unfortunately there are ranked maps in this state (example: https://osu.ppy.sh/s/594828).
|
// unfortunately there are ranked maps in this state (example: https://osu.ppy.sh/s/594828).
|
||||||
@ -67,14 +64,9 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.BeatmapInfo.BaseDifficulty);
|
hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.BeatmapInfo.BaseDifficulty);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool ShouldSkipLine(string line)
|
protected override bool ShouldSkipLine(string line) => base.ShouldSkipLine(line) || line.StartsWith(" ") || line.StartsWith("_");
|
||||||
{
|
|
||||||
if (base.ShouldSkipLine(line) || line.StartsWith(" ") || line.StartsWith("_"))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ProcessSection(Section section, string line)
|
protected override void ParseLine(Beatmap beatmap, Section section, string line)
|
||||||
{
|
{
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
|
@ -4,47 +4,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using osu.Game.Beatmaps.Legacy;
|
|
||||||
using osu.Game.Storyboards;
|
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps.Formats
|
namespace osu.Game.Beatmaps.Formats
|
||||||
{
|
{
|
||||||
public abstract class LegacyDecoder : Decoder
|
public abstract class LegacyDecoder<T> : Decoder<T>
|
||||||
|
where T : new()
|
||||||
{
|
{
|
||||||
public static void Register()
|
protected readonly int FormatVersion;
|
||||||
|
|
||||||
|
protected LegacyDecoder(int version)
|
||||||
{
|
{
|
||||||
AddDecoder(@"osu file format v14", m => new LegacyBeatmapDecoder(m));
|
FormatVersion = version;
|
||||||
AddDecoder(@"osu file format v13", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v12", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v11", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v10", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v9", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v8", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v7", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v6", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v5", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v4", m => new LegacyBeatmapDecoder(m));
|
|
||||||
AddDecoder(@"osu file format v3", m => new LegacyBeatmapDecoder(m));
|
|
||||||
// TODO: differences between versions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int BeatmapVersion;
|
protected override void ParseStreamInto(StreamReader stream, T beatmap)
|
||||||
|
|
||||||
public override Decoder GetStoryboardDecoder() => new LegacyStoryboardDecoder(BeatmapVersion);
|
|
||||||
|
|
||||||
public override Beatmap DecodeBeatmap(StreamReader stream) => new LegacyBeatmap(base.DecodeBeatmap(stream));
|
|
||||||
|
|
||||||
protected override void ParseBeatmap(StreamReader stream, Beatmap beatmap)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void ParseContent(StreamReader stream)
|
|
||||||
{
|
{
|
||||||
Section section = Section.None;
|
Section section = Section.None;
|
||||||
|
|
||||||
@ -54,13 +27,6 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
if (ShouldSkipLine(line))
|
if (ShouldSkipLine(line))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 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;
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (line.StartsWith(@"[") && line.EndsWith(@"]"))
|
if (line.StartsWith(@"[") && line.EndsWith(@"]"))
|
||||||
{
|
{
|
||||||
if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section))
|
if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section))
|
||||||
@ -68,18 +34,13 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessSection(section, line);
|
ParseLine(beatmap, section, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool ShouldSkipLine(string line)
|
protected virtual bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.StartsWith("//");
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(line) || line.StartsWith("//"))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void ProcessSection(Section section, string line);
|
protected abstract void ParseLine(T output, Section section, string line);
|
||||||
|
|
||||||
protected KeyValuePair<string, string> SplitKeyVal(string line, char separator)
|
protected KeyValuePair<string, string> SplitKeyVal(string line, char separator)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
@ -13,37 +13,34 @@ using osu.Game.Storyboards;
|
|||||||
|
|
||||||
namespace osu.Game.Beatmaps.Formats
|
namespace osu.Game.Beatmaps.Formats
|
||||||
{
|
{
|
||||||
public class LegacyStoryboardDecoder : LegacyDecoder
|
public class LegacyStoryboardDecoder : LegacyDecoder<Storyboard>
|
||||||
{
|
{
|
||||||
private Storyboard storyboard;
|
|
||||||
|
|
||||||
private StoryboardSprite storyboardSprite;
|
private StoryboardSprite storyboardSprite;
|
||||||
private CommandTimelineGroup timelineGroup;
|
private CommandTimelineGroup timelineGroup;
|
||||||
|
|
||||||
|
private Storyboard storyboard;
|
||||||
|
|
||||||
private readonly Dictionary<string, string> variables = new Dictionary<string, string>();
|
private readonly Dictionary<string, string> variables = new Dictionary<string, string>();
|
||||||
|
|
||||||
public LegacyStoryboardDecoder()
|
public LegacyStoryboardDecoder()
|
||||||
|
: base(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public LegacyStoryboardDecoder(int beatmapVersion)
|
public static void Register()
|
||||||
{
|
{
|
||||||
BeatmapVersion = beatmapVersion;
|
// note that this isn't completely correct
|
||||||
|
AddDecoder<Storyboard>(@"osu file format v", m => new LegacyStoryboardDecoder());
|
||||||
|
AddDecoder<Storyboard>(@"[Events]", m => new LegacyStoryboardDecoder());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ParseStoryboard(StreamReader stream, Storyboard storyboard)
|
protected override void ParseStreamInto(StreamReader stream, Storyboard storyboard)
|
||||||
{
|
{
|
||||||
if (stream == null)
|
|
||||||
throw new ArgumentNullException(nameof(stream));
|
|
||||||
if (storyboard == null)
|
|
||||||
throw new ArgumentNullException(nameof(storyboard));
|
|
||||||
|
|
||||||
this.storyboard = storyboard;
|
this.storyboard = storyboard;
|
||||||
|
base.ParseStreamInto(stream, storyboard);
|
||||||
ParseContent(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessSection(Section section, string line)
|
protected override void ParseLine(Storyboard storyboard, Section section, string line)
|
||||||
{
|
{
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
@ -80,38 +77,38 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case EventType.Sprite:
|
case EventType.Sprite:
|
||||||
{
|
{
|
||||||
var layer = parseLayer(split[1]);
|
var layer = parseLayer(split[1]);
|
||||||
var origin = parseOrigin(split[2]);
|
var origin = parseOrigin(split[2]);
|
||||||
var path = cleanFilename(split[3]);
|
var path = cleanFilename(split[3]);
|
||||||
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:
|
||||||
{
|
{
|
||||||
var layer = parseLayer(split[1]);
|
var layer = parseLayer(split[1]);
|
||||||
var origin = parseOrigin(split[2]);
|
var origin = parseOrigin(split[2]);
|
||||||
var path = cleanFilename(split[3]);
|
var path = cleanFilename(split[3]);
|
||||||
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);
|
||||||
var frameCount = int.Parse(split[6]);
|
var frameCount = int.Parse(split[6]);
|
||||||
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:
|
||||||
{
|
{
|
||||||
var time = double.Parse(split[1], CultureInfo.InvariantCulture);
|
var time = double.Parse(split[1], CultureInfo.InvariantCulture);
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,120 +121,120 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
switch (commandType)
|
switch (commandType)
|
||||||
{
|
{
|
||||||
case "T":
|
case "T":
|
||||||
{
|
{
|
||||||
var triggerName = split[1];
|
var triggerName = split[1];
|
||||||
var startTime = split.Length > 2 ? double.Parse(split[2], CultureInfo.InvariantCulture) : double.MinValue;
|
var startTime = split.Length > 2 ? double.Parse(split[2], CultureInfo.InvariantCulture) : double.MinValue;
|
||||||
var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue;
|
var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue;
|
||||||
var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0;
|
var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0;
|
||||||
timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber);
|
timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "L":
|
case "L":
|
||||||
{
|
{
|
||||||
var startTime = double.Parse(split[1], CultureInfo.InvariantCulture);
|
var startTime = double.Parse(split[1], CultureInfo.InvariantCulture);
|
||||||
var loopCount = int.Parse(split[2]);
|
var loopCount = int.Parse(split[2]);
|
||||||
timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount);
|
timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(split[3]))
|
||||||
|
split[3] = split[2];
|
||||||
|
|
||||||
|
var easing = (Easing)int.Parse(split[1]);
|
||||||
|
var startTime = double.Parse(split[2], CultureInfo.InvariantCulture);
|
||||||
|
var endTime = double.Parse(split[3], CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
switch (commandType)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(split[3]))
|
case "F":
|
||||||
split[3] = split[2];
|
|
||||||
|
|
||||||
var easing = (Easing)int.Parse(split[1]);
|
|
||||||
var startTime = double.Parse(split[2], CultureInfo.InvariantCulture);
|
|
||||||
var endTime = double.Parse(split[3], CultureInfo.InvariantCulture);
|
|
||||||
|
|
||||||
switch (commandType)
|
|
||||||
{
|
{
|
||||||
case "F":
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
{
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue);
|
||||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
|
||||||
timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "S":
|
|
||||||
{
|
|
||||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
|
||||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
|
||||||
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "V":
|
|
||||||
{
|
|
||||||
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
|
||||||
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
|
||||||
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
|
||||||
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
|
||||||
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "R":
|
|
||||||
{
|
|
||||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
|
||||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
|
||||||
timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "M":
|
|
||||||
{
|
|
||||||
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
|
||||||
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
|
||||||
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
|
||||||
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
|
||||||
timelineGroup?.X.Add(easing, startTime, endTime, startX, endX);
|
|
||||||
timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "MX":
|
|
||||||
{
|
|
||||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
|
||||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
|
||||||
timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "MY":
|
|
||||||
{
|
|
||||||
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
|
||||||
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
|
||||||
timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "C":
|
|
||||||
{
|
|
||||||
var startRed = float.Parse(split[4], CultureInfo.InvariantCulture);
|
|
||||||
var startGreen = float.Parse(split[5], CultureInfo.InvariantCulture);
|
|
||||||
var startBlue = float.Parse(split[6], CultureInfo.InvariantCulture);
|
|
||||||
var endRed = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startRed;
|
|
||||||
var endGreen = split.Length > 8 ? float.Parse(split[8], CultureInfo.InvariantCulture) : startGreen;
|
|
||||||
var endBlue = split.Length > 9 ? float.Parse(split[9], CultureInfo.InvariantCulture) : startBlue;
|
|
||||||
timelineGroup?.Colour.Add(easing, startTime, endTime,
|
|
||||||
new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1),
|
|
||||||
new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "P":
|
|
||||||
{
|
|
||||||
var type = split[4];
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case "A":
|
|
||||||
timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit);
|
|
||||||
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;
|
|
||||||
default:
|
|
||||||
throw new InvalidDataException($@"Unknown command type: {commandType}");
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case "S":
|
||||||
|
{
|
||||||
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
|
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "V":
|
||||||
|
{
|
||||||
|
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||||
|
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
||||||
|
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||||
|
timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "R":
|
||||||
|
{
|
||||||
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
|
timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "M":
|
||||||
|
{
|
||||||
|
var startX = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var startY = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||||
|
var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX;
|
||||||
|
var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY;
|
||||||
|
timelineGroup?.X.Add(easing, startTime, endTime, startX, endX);
|
||||||
|
timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "MX":
|
||||||
|
{
|
||||||
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
|
timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "MY":
|
||||||
|
{
|
||||||
|
var startValue = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue;
|
||||||
|
timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "C":
|
||||||
|
{
|
||||||
|
var startRed = float.Parse(split[4], CultureInfo.InvariantCulture);
|
||||||
|
var startGreen = float.Parse(split[5], CultureInfo.InvariantCulture);
|
||||||
|
var startBlue = float.Parse(split[6], CultureInfo.InvariantCulture);
|
||||||
|
var endRed = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startRed;
|
||||||
|
var endGreen = split.Length > 8 ? float.Parse(split[8], CultureInfo.InvariantCulture) : startGreen;
|
||||||
|
var endBlue = split.Length > 9 ? float.Parse(split[9], CultureInfo.InvariantCulture) : startBlue;
|
||||||
|
timelineGroup?.Colour.Add(easing, startTime, endTime,
|
||||||
|
new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1),
|
||||||
|
new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "P":
|
||||||
|
{
|
||||||
|
var type = split[4];
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case "A":
|
||||||
|
timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit);
|
||||||
|
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;
|
||||||
|
default:
|
||||||
|
throw new InvalidDataException($@"Unknown command type: {commandType}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,6 +266,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
case LegacyOrigins.BottomRight:
|
case LegacyOrigins.BottomRight:
|
||||||
return Anchor.BottomRight;
|
return Anchor.BottomRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new InvalidDataException($@"Unknown origin: {value}");
|
throw new InvalidDataException($@"Unknown origin: {value}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,8 +188,8 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
string[] split = str.Split(':');
|
string[] split = str.Split(':');
|
||||||
|
|
||||||
var bank = (LegacyDecoder.LegacySampleBank)Convert.ToInt32(split[0]);
|
var bank = (LegacyBeatmapDecoder.LegacySampleBank)Convert.ToInt32(split[0]);
|
||||||
var addbank = (LegacyDecoder.LegacySampleBank)Convert.ToInt32(split[1]);
|
var addbank = (LegacyBeatmapDecoder.LegacySampleBank)Convert.ToInt32(split[1]);
|
||||||
|
|
||||||
// Let's not implement this for now, because this doesn't fit nicely into the bank structure
|
// Let's not implement this for now, because this doesn't fit nicely into the bank structure
|
||||||
//string sampleFile = split2.Length > 4 ? split2[4] : string.Empty;
|
//string sampleFile = split2.Length > 4 ? split2[4] : string.Empty;
|
||||||
|
@ -112,9 +112,9 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
using (var resStream = openResource($"{resource_namespace}.{name}.osu"))
|
using (var resStream = openResource($"{resource_namespace}.{name}.osu"))
|
||||||
using (var stream = new StreamReader(resStream))
|
using (var stream = new StreamReader(resStream))
|
||||||
{
|
{
|
||||||
var decoder = Decoder.GetDecoder(stream);
|
var decoder = Decoder.GetDecoder<Beatmap>(stream);
|
||||||
((LegacyBeatmapDecoder)decoder).ApplyOffsets = false;
|
((LegacyBeatmapDecoder)decoder).ApplyOffsets = false;
|
||||||
return decoder.DecodeBeatmap(stream);
|
return decoder.Decode(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,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.GetDecoder(reader).DecodeBeatmap(reader);
|
beatmap = Game.Beatmaps.Formats.Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||||
|
|
||||||
return beatmap;
|
return beatmap;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user