Re-implement legacy hit object conversion.

This commit is contained in:
smoogipooo 2017-04-17 17:23:11 +09:00
parent 2767fbd81a
commit 09208adf81
28 changed files with 467 additions and 67 deletions

View File

@ -36,6 +36,10 @@ private List<OsuHitObject> convertHitObjects(List<HitObject> hitObjects, float s
private OsuHitObject convertHitObject(HitObject original)
{
OsuHitObject originalOsu = original as OsuHitObject;
if (originalOsu != null)
return originalOsu;
IHasCurve curveData = original as IHasCurve;
IHasEndTime endTimeData = original as IHasEndTime;
IHasPosition positionData = original as IHasPosition;

View File

@ -8,6 +8,7 @@
using OpenTK.Graphics;
using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
using System;
namespace osu.Game.Modes.Osu.Objects
{
@ -21,6 +22,8 @@ public abstract class OsuHitObject : HitObject, IHasCombo, IHasPosition
private const double hit_window_300 = 30;
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
public Vector2 StackedPosition => Position + StackOffset;

View File

@ -10,6 +10,8 @@
using osu.Game.Modes.Objects.Legacy;
using System.Linq;
using osu.Game.Audio;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Tests.Beatmaps.Formats
{
@ -130,16 +132,22 @@ public void TestDecodeHitObjects()
using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
{
var beatmap = decoder.Decode(new StreamReader(stream));
var slider = beatmap.HitObjects[0] as LegacySlider;
Assert.IsNotNull(slider);
Assert.AreEqual(new Vector2(192, 168), slider.Position);
Assert.AreEqual(956, slider.StartTime);
Assert.IsTrue(slider.Samples.Any(s => s.Name == SampleInfo.HIT_NORMAL));
var hit = beatmap.HitObjects[1] as LegacyHit;
Assert.IsNotNull(hit);
Assert.AreEqual(new Vector2(304, 56), hit.Position);
Assert.AreEqual(1285, hit.StartTime);
Assert.IsTrue(hit.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP));
var curveData = beatmap.HitObjects[0] as IHasCurve;
var positionData = beatmap.HitObjects[0] as IHasPosition;
Assert.IsNotNull(positionData);
Assert.IsNotNull(curveData);
Assert.AreEqual(new Vector2(192, 168), positionData.Position);
Assert.AreEqual(956, beatmap.HitObjects[0].StartTime);
Assert.IsTrue(beatmap.HitObjects[0].Samples.Any(s => s.Name == SampleInfo.HIT_NORMAL));
positionData = beatmap.HitObjects[1] as IHasPosition;
Assert.IsNotNull(positionData);
Assert.AreEqual(new Vector2(304, 56), positionData.Position);
Assert.AreEqual(1285, beatmap.HitObjects[1].StartTime);
Assert.IsTrue(beatmap.HitObjects[1].Samples.Any(s => s.Name == SampleInfo.HIT_CLAP));
}
}
}

View File

@ -7,8 +7,8 @@
using OpenTK.Graphics;
using osu.Game.Beatmaps.Events;
using osu.Game.Beatmaps.Timing;
using osu.Game.Modes.Objects;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Modes.Objects.Legacy;
namespace osu.Game.Beatmaps.Formats
{
@ -29,6 +29,8 @@ public static void Register()
// TODO: Not sure how far back to go, or differences between versions
}
private HitObjectParser parser;
private LegacySampleBank defaultSampleBank;
private int defaultSampleVolume = 100;
@ -84,6 +86,22 @@ private void handleGeneral(Beatmap beatmap, string key, string val)
break;
case @"Mode":
beatmap.BeatmapInfo.RulesetID = int.Parse(val);
switch (beatmap.BeatmapInfo.Mode)
{
case 0:
parser = new Modes.Objects.Legacy.Osu.HitObjectParser();
break;
case 1:
parser = new Modes.Objects.Legacy.Taiko.HitObjectParser();
break;
case 2:
parser = new Modes.Objects.Legacy.Catch.HitObjectParser();
break;
case 3:
parser = new Modes.Objects.Legacy.Mania.HitObjectParser();
break;
}
break;
case @"LetterboxInBreaks":
beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(val) == 1;
@ -303,8 +321,6 @@ protected override void ParseFile(StreamReader stream, Beatmap beatmap)
{
beatmap.BeatmapInfo.BeatmapVersion = beatmapVersion;
HitObjectParser parser = new LegacyHitObjectParser();
Section section = Section.None;
bool hasCustomColours = false;

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Catch
{
/// <summary>
/// Legacy Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasCombo, IHasXPosition
{
public float X { get; set; }
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,42 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using OpenTK;
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Catch
{
internal class HitObjectParser : Legacy.HitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
{
X = position.X,
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
{
return new Slider
{
X = position.X,
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
{
EndTime = endTime
};
}
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Catch
{
/// <summary>
/// Legacy Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasXPosition, IHasCombo
{
public float X { get; set; }
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Catch
{
/// <summary>
/// Legacy Spinner-type, used for parsing Beatmaps.
/// </summary>
internal class Spinner : HitObject, IHasEndTime
{
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
}
}

View File

@ -6,20 +6,19 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using osu.Game.Modes.Objects.Legacy;
using osu.Game.Beatmaps.Formats;
using osu.Game.Audio;
namespace osu.Game.Modes.Objects
namespace osu.Game.Modes.Objects.Legacy
{
internal class LegacyHitObjectParser : HitObjectParser
internal abstract class HitObjectParser : Objects.HitObjectParser
{
public override HitObject Parse(string text)
{
string[] split = text.Split(',');
var type = (LegacyHitObjectType)int.Parse(split[3]) & ~LegacyHitObjectType.ColourHax;
bool combo = type.HasFlag(LegacyHitObjectType.NewCombo);
type &= ~LegacyHitObjectType.NewCombo;
var type = (HitObjectType)int.Parse(split[3]) & ~HitObjectType.ColourHax;
bool combo = type.HasFlag(HitObjectType.NewCombo);
type &= ~HitObjectType.NewCombo;
int sampleVolume = 0;
string normalSampleBank = null;
@ -27,22 +26,18 @@ public override HitObject Parse(string text)
HitObject result;
if ((type & LegacyHitObjectType.Circle) > 0)
if ((type & HitObjectType.Circle) > 0)
{
result = new LegacyHit
{
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
NewCombo = combo
};
result = CreateHit(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo);
if (split.Length > 5)
readCustomSampleBanks(split[5], ref normalSampleBank, ref addSampleBank, ref sampleVolume);
}
else if ((type & LegacyHitObjectType.Slider) > 0)
else if ((type & HitObjectType.Slider) > 0)
{
CurveType curveType = CurveType.Catmull;
double length = 0;
List<Vector2> points = new List<Vector2> { new Vector2(int.Parse(split[0]), int.Parse(split[1])) };
var points = new List<Vector2> { new Vector2(int.Parse(split[0]), int.Parse(split[1])) };
string[] pointsplit = split[5].Split('|');
foreach (string t in pointsplit)
@ -68,11 +63,7 @@ public override HitObject Parse(string text)
}
string[] temp = t.Split(':');
Vector2 v = new Vector2(
(int)Convert.ToDouble(temp[0], CultureInfo.InvariantCulture),
(int)Convert.ToDouble(temp[1], CultureInfo.InvariantCulture)
);
points.Add(v);
points.Add(new Vector2((int)Convert.ToDouble(temp[0], CultureInfo.InvariantCulture), (int)Convert.ToDouble(temp[1], CultureInfo.InvariantCulture)));
}
int repeatCount = Convert.ToInt32(split[6], CultureInfo.InvariantCulture);
@ -83,38 +74,26 @@ public override HitObject Parse(string text)
if (split.Length > 7)
length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture);
result = new LegacySlider
{
ControlPoints = points,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount,
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
NewCombo = combo
};
result = CreateSlider(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo, points, length, curveType, repeatCount);
if (split.Length > 10)
readCustomSampleBanks(split[10], ref normalSampleBank, ref addSampleBank, ref sampleVolume);
}
else if ((type & LegacyHitObjectType.Spinner) > 0)
else if ((type & HitObjectType.Spinner) > 0)
{
result = new LegacySpinner
{
Position = new Vector2(512, 384) / 2,
EndTime = Convert.ToDouble(split[5], CultureInfo.InvariantCulture)
};
result = CreateSpinner(new Vector2(512, 384) / 2, Convert.ToDouble(split[5], CultureInfo.InvariantCulture));
if (split.Length > 6)
readCustomSampleBanks(split[6], ref normalSampleBank, ref addSampleBank, ref sampleVolume);
}
else if ((type & LegacyHitObjectType.Hold) > 0)
else if ((type & HitObjectType.Hold) > 0)
{
// Note: Hold is generated by BMS converts
// Todo: Apparently end time is determined by samples??
// Shouldn't need implementation until mania
result = new LegacyHold
result = new Hold
{
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
NewCombo = combo
@ -167,6 +146,10 @@ public override HitObject Parse(string text)
return result;
}
protected abstract HitObject CreateHit(Vector2 position, bool newCombo);
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount);
protected abstract HitObject CreateSpinner(Vector2 position, double endTime);
private void readCustomSampleBanks(string str, ref string normalSampleBank, ref string addSampleBank, ref int sampleVolume)
{
if (string.IsNullOrEmpty(str))

View File

@ -6,7 +6,7 @@
namespace osu.Game.Modes.Objects.Legacy
{
[Flags]
public enum LegacyHitObjectType
public enum HitObjectType
{
Circle = 1 << 0,
Slider = 1 << 1,

View File

@ -9,10 +9,14 @@ namespace osu.Game.Modes.Objects.Legacy
/// <summary>
/// Legacy Hold-type, used for parsing "specials" in beatmaps.
/// </summary>
public sealed class LegacyHold : HitObject, IHasPosition, IHasCombo, IHasHold
internal sealed class Hold : HitObject, IHasPosition, IHasCombo, IHasHold
{
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Mania
{
/// <summary>
/// Legacy Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasColumn, IHasCombo
{
public int Column { get; set; }
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,40 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using OpenTK;
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Mania
{
internal class HitObjectParser : Legacy.HitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
{
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
{
return new Slider
{
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
{
EndTime = endTime
};
}
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Mania
{
/// <summary>
/// Legacy Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasColumn, IHasCombo
{
public int Column { get; set; }
public bool NewCombo { get; set; }
}
}

View File

@ -1,20 +1,19 @@
using OpenTK;
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy
namespace osu.Game.Modes.Objects.Legacy.Mania
{
/// <summary>
/// Legacy Spinner-type, used for parsing Beatmaps.
/// </summary>
internal class LegacySpinner : HitObject, IHasEndTime, IHasPosition
internal class Spinner : HitObject, IHasEndTime, IHasColumn
{
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
public Vector2 Position { get; set; }
public int Column { get; set; }
}
}

View File

@ -4,15 +4,19 @@
using osu.Game.Modes.Objects.Types;
using OpenTK;
namespace osu.Game.Modes.Objects.Legacy
namespace osu.Game.Modes.Objects.Legacy.Osu
{
/// <summary>
/// Legacy Hit-type, used for parsing Beatmaps.
/// </summary>
public sealed class LegacyHit : HitObject, IHasPosition, IHasCombo
internal sealed class Hit : HitObject, IHasPosition, IHasCombo
{
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,43 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Modes.Objects.Types;
using System.Collections.Generic;
namespace osu.Game.Modes.Objects.Legacy.Osu
{
internal class HitObjectParser : Legacy.HitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
{
Position = position,
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
{
return new Slider
{
Position = position,
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
{
Position = position,
EndTime = endTime
};
}
}
}

View File

@ -4,15 +4,19 @@
using osu.Game.Modes.Objects.Types;
using OpenTK;
namespace osu.Game.Modes.Objects.Legacy
namespace osu.Game.Modes.Objects.Legacy.Osu
{
/// <summary>
/// Legacy Slider-type, used for parsing Beatmaps.
/// </summary>
public sealed class LegacySlider : CurvedHitObject, IHasPosition, IHasCombo
internal sealed class Slider : CurvedHitObject, IHasPosition, IHasCombo
{
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
using OpenTK;
namespace osu.Game.Modes.Objects.Legacy.Osu
{
/// <summary>
/// Legacy Spinner-type, used for parsing Beatmaps.
/// </summary>
internal class Spinner : HitObject, IHasEndTime, IHasPosition
{
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Taiko
{
/// <summary>
/// Legacy Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasCombo
{
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,40 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Modes.Objects.Types;
using System.Collections.Generic;
namespace osu.Game.Modes.Objects.Legacy.Taiko
{
internal class HitObjectParser : Legacy.HitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
{
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
{
return new Slider
{
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
{
EndTime = endTime
};
}
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Taiko
{
/// <summary>
/// Legacy Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasCombo
{
public bool NewCombo { get; set; }
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Modes.Objects.Types;
namespace osu.Game.Modes.Objects.Legacy.Taiko
{
/// <summary>
/// Legacy Spinner-type, used for parsing Beatmaps.
/// </summary>
internal class Spinner : HitObject, IHasEndTime
{
public double EndTime { get; set; }
public double Duration => EndTime - StartTime;
}
}

View File

@ -0,0 +1,10 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Types
{
public interface IHasColumn
{
int Column { get; }
}
}

View File

@ -8,7 +8,7 @@ namespace osu.Game.Modes.Objects.Types
/// <summary>
/// A HitObject that has a starting position.
/// </summary>
public interface IHasPosition
public interface IHasPosition : IHasXPosition, IHasYPosition
{
/// <summary>
/// The starting position of the HitObject.

View File

@ -0,0 +1,14 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Types
{
/// <summary>
/// A HitObject that has a starting X-position.
/// </summary>
public interface IHasXPosition
{
float X { get; }
}
}

View File

@ -0,0 +1,14 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Modes.Objects.Types
{
/// <summary>
/// A HitObject that has a starting Y-position.
/// </summary>
public interface IHasYPosition
{
float Y { get; }
}
}

View File

@ -104,6 +104,22 @@
<Compile Include="IO\Serialization\IJsonSerializable.cs" />
<Compile Include="IPC\ScoreIPCChannel.cs" />
<Compile Include="Modes\BeatmapStatistic.cs" />
<Compile Include="Modes\Objects\Legacy\Catch\Hit.cs" />
<Compile Include="Modes\Objects\Legacy\Catch\HitObjectParser.cs" />
<Compile Include="Modes\Objects\Legacy\Catch\Slider.cs" />
<Compile Include="Modes\Objects\Legacy\Catch\Spinner.cs" />
<Compile Include="Modes\Objects\Legacy\Mania\Hit.cs" />
<Compile Include="Modes\Objects\Legacy\Mania\HitObjectParser.cs" />
<Compile Include="Modes\Objects\Legacy\Mania\Slider.cs" />
<Compile Include="Modes\Objects\Legacy\Mania\Spinner.cs" />
<Compile Include="Modes\Objects\Legacy\Osu\HitObjectParser.cs" />
<Compile Include="Modes\Objects\Legacy\Taiko\Hit.cs" />
<Compile Include="Modes\Objects\Legacy\Taiko\HitObjectParser.cs" />
<Compile Include="Modes\Objects\Legacy\Taiko\Slider.cs" />
<Compile Include="Modes\Objects\Legacy\Taiko\Spinner.cs" />
<Compile Include="Modes\Objects\Types\IHasColumn.cs" />
<Compile Include="Modes\Objects\Types\IHasXPosition.cs" />
<Compile Include="Modes\Objects\Types\IHasYPosition.cs" />
<Compile Include="Modes\Replays\Replay.cs" />
<Compile Include="Modes\Judgements\DrawableJudgement.cs" />
<Compile Include="Modes\Judgements\IPartialJudgement.cs" />
@ -115,11 +131,11 @@
<Compile Include="Modes\Objects\BezierApproximator.cs" />
<Compile Include="Modes\Objects\CircularArcApproximator.cs" />
<Compile Include="Modes\Objects\CurvedHitObject.cs" />
<Compile Include="Modes\Objects\Legacy\LegacyHit.cs" />
<Compile Include="Modes\Objects\LegacyHitObjectParser.cs" />
<Compile Include="Modes\Objects\Legacy\LegacyHold.cs" />
<Compile Include="Modes\Objects\Legacy\LegacySlider.cs" />
<Compile Include="Modes\Objects\Legacy\LegacySpinner.cs" />
<Compile Include="Modes\Objects\Legacy\Osu\Hit.cs" />
<Compile Include="Modes\Objects\Legacy\HitObjectParser.cs" />
<Compile Include="Modes\Objects\Legacy\Hold.cs" />
<Compile Include="Modes\Objects\Legacy\Osu\Slider.cs" />
<Compile Include="Modes\Objects\Legacy\Osu\Spinner.cs" />
<Compile Include="Modes\Objects\SliderCurve.cs" />
<Compile Include="Modes\Objects\Types\CurveType.cs" />
<Compile Include="Modes\Objects\Drawables\IDrawableHitObjectWithProxiedApproach.cs" />
@ -132,7 +148,7 @@
<Compile Include="Modes\Objects\Types\IHasRepeats.cs" />
<Compile Include="Modes\Objects\Types\IHasPosition.cs" />
<Compile Include="Modes\Objects\Types\IHasHold.cs" />
<Compile Include="Modes\Objects\Legacy\LegacyHitObjectType.cs" />
<Compile Include="Modes\Objects\Legacy\HitObjectType.cs" />
<Compile Include="Modes\Replays\ReplayButtonState.cs" />
<Compile Include="Modes\Replays\ReplayFrame.cs" />
<Compile Include="Database\RulesetDatabase.cs" />