mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 23:24:04 +09:00
Rework/rewrite beatmap parsing to parse to base hit objects, which mode-specific beatmap converters can then use.
This commit is contained in:
@ -11,6 +11,7 @@ using osu.Framework.Audio.Sample;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using OpenTK;
|
||||
using Container = osu.Framework.Graphics.Containers.Container;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Drawables
|
||||
{
|
||||
@ -67,14 +68,14 @@ namespace osu.Game.Modes.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class DrawableHitObject<HitObjectType> : DrawableHitObject
|
||||
where HitObjectType : HitObject
|
||||
public abstract class DrawableHitObject<TObject> : DrawableHitObject
|
||||
where TObject : HitObject
|
||||
{
|
||||
public event Action<DrawableHitObject<HitObjectType>, JudgementInfo> OnJudgement;
|
||||
public event Action<DrawableHitObject<TObject>, JudgementInfo> OnJudgement;
|
||||
|
||||
public HitObjectType HitObject;
|
||||
public TObject HitObject;
|
||||
|
||||
protected DrawableHitObject(HitObjectType hitObject)
|
||||
protected DrawableHitObject(TObject hitObject)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
}
|
||||
@ -88,7 +89,9 @@ namespace osu.Game.Modes.Objects.Drawables
|
||||
if (Judgement.Result != null)
|
||||
return false;
|
||||
|
||||
Judgement.TimeOffset = Time.Current - HitObject.EndTime;
|
||||
double endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
|
||||
|
||||
Judgement.TimeOffset = Time.Current - endTime;
|
||||
|
||||
CheckJudgement(userTriggered);
|
||||
|
||||
@ -138,14 +141,14 @@ namespace osu.Game.Modes.Objects.Drawables
|
||||
Sample = audio.Sample.Get($@"Gameplay/{sampleSet.ToString().ToLower()}-hit{type.ToString().ToLower()}");
|
||||
}
|
||||
|
||||
private List<DrawableHitObject<HitObjectType>> nestedHitObjects;
|
||||
private List<DrawableHitObject<TObject>> nestedHitObjects;
|
||||
|
||||
protected IEnumerable<DrawableHitObject<HitObjectType>> NestedHitObjects => nestedHitObjects;
|
||||
protected IEnumerable<DrawableHitObject<TObject>> NestedHitObjects => nestedHitObjects;
|
||||
|
||||
protected void AddNested(DrawableHitObject<HitObjectType> h)
|
||||
protected void AddNested(DrawableHitObject<TObject> h)
|
||||
{
|
||||
if (nestedHitObjects == null)
|
||||
nestedHitObjects = new List<DrawableHitObject<HitObjectType>>();
|
||||
nestedHitObjects = new List<DrawableHitObject<TObject>>();
|
||||
|
||||
h.OnJudgement += (d, j) => { OnJudgement?.Invoke(d, j); } ;
|
||||
nestedHitObjects.Add(h);
|
||||
|
15
osu.Game/Modes/Objects/Hit.cs
Normal file
15
osu.Game/Modes/Objects/Hit.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
internal class Hit : HitObject, IHasPosition, IHasCombo
|
||||
{
|
||||
public Vector2 Position { get; set; }
|
||||
public Color4 ComboColour { get; set; }
|
||||
|
||||
public bool NewCombo { get; set; }
|
||||
public int ComboIndex { get; set; }
|
||||
}
|
||||
}
|
@ -3,28 +3,31 @@
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// A hitobject describes a point in a beatmap
|
||||
/// A HitObject describes an object in a Beatmap.
|
||||
/// <para>
|
||||
/// HitObjects may contain more properties for which you should be checking through the IHas* types.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public abstract class HitObject
|
||||
public class HitObject
|
||||
{
|
||||
public double StartTime;
|
||||
public virtual double EndTime => StartTime;
|
||||
/// <summary>
|
||||
/// The time at which the HitObject starts.
|
||||
/// </summary>
|
||||
public double StartTime { get; set; }
|
||||
|
||||
public bool NewCombo { get; set; }
|
||||
|
||||
public Color4 Colour = new Color4(17, 136, 170, 255);
|
||||
|
||||
public double Duration => EndTime - StartTime;
|
||||
|
||||
public HitSampleInfo Sample;
|
||||
|
||||
public int ComboIndex;
|
||||
/// <summary>
|
||||
/// The sample to be played when this HitObject is hit.
|
||||
/// </summary>
|
||||
public HitSampleInfo Sample { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets default parameters from a beatmap.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to set from.</param>
|
||||
public virtual void SetDefaultsFromBeatmap(Beatmap beatmap) { }
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
// 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.Beatmaps;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
public abstract class HitObjectConverter<T>
|
||||
where T : HitObject
|
||||
{
|
||||
public abstract List<T> Convert(Beatmap beatmap);
|
||||
}
|
||||
|
||||
public class HitObjectConvertException : Exception
|
||||
{
|
||||
public HitObject Input { get; }
|
||||
public HitObjectConvertException(string modeName, HitObject input)
|
||||
: base($@"Can't convert from {input.GetType().Name} to {modeName} HitObject!")
|
||||
{
|
||||
Input = input;
|
||||
}
|
||||
}
|
||||
}
|
17
osu.Game/Modes/Objects/IHitObjectConverter.cs
Normal file
17
osu.Game/Modes/Objects/IHitObjectConverter.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts HitObjects to another mode.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of HitObject to be converted to.</typeparam>
|
||||
public interface IHitObjectConverter<T>
|
||||
where T : HitObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a <see cref="HitObject"/> to another mode.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The base HitObject to convert.</param>
|
||||
/// <returns>The converted HitObject.</returns>
|
||||
T Convert(HitObject hitObject);
|
||||
}
|
||||
}
|
105
osu.Game/Modes/Objects/LegacyHitObjectParser.cs
Normal file
105
osu.Game/Modes/Objects/LegacyHitObjectParser.cs
Normal file
@ -0,0 +1,105 @@
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps.Samples;
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
internal class LegacyHitObjectParser : HitObjectParser
|
||||
{
|
||||
public override HitObject Parse(string text)
|
||||
{
|
||||
string[] split = text.Split(',');
|
||||
var type = (HitObjectType)int.Parse(split[3]);
|
||||
bool combo = type.HasFlag(HitObjectType.NewCombo);
|
||||
type &= (HitObjectType)0xF;
|
||||
type &= ~HitObjectType.NewCombo;
|
||||
|
||||
HitObject result;
|
||||
switch (type)
|
||||
{
|
||||
case HitObjectType.Circle:
|
||||
result = new Hit
|
||||
{
|
||||
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
|
||||
NewCombo = combo
|
||||
};
|
||||
break;
|
||||
case HitObjectType.Slider:
|
||||
CurveType curveType = CurveType.Catmull;
|
||||
double length = 0;
|
||||
List<Vector2> points = new List<Vector2> { new Vector2(int.Parse(split[0]), int.Parse(split[1])) };
|
||||
|
||||
string[] pointsplit = split[5].Split('|');
|
||||
foreach (string t in pointsplit)
|
||||
{
|
||||
if (t.Length == 1)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case @"C":
|
||||
curveType = CurveType.Catmull;
|
||||
break;
|
||||
case @"B":
|
||||
curveType = CurveType.Bezier;
|
||||
break;
|
||||
case @"L":
|
||||
curveType = CurveType.Linear;
|
||||
break;
|
||||
case @"P":
|
||||
curveType = CurveType.PerfectCurve;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int repeatCount = Convert.ToInt32(split[6], CultureInfo.InvariantCulture);
|
||||
|
||||
if (repeatCount > 9000)
|
||||
throw new ArgumentOutOfRangeException(nameof(repeatCount), @"Repeat count is way too high");
|
||||
|
||||
if (split.Length > 7)
|
||||
length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture);
|
||||
|
||||
result = new Slider
|
||||
{
|
||||
ControlPoints = points,
|
||||
Distance = length,
|
||||
CurveType = curveType,
|
||||
RepeatCount = repeatCount,
|
||||
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
|
||||
NewCombo = combo
|
||||
};
|
||||
break;
|
||||
case HitObjectType.Spinner:
|
||||
result = new Spinner
|
||||
{
|
||||
EndTime = Convert.ToDouble(split[5], CultureInfo.InvariantCulture)
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($@"Unknown hit object type {type}");
|
||||
}
|
||||
result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture);
|
||||
result.Sample = new HitSampleInfo
|
||||
{
|
||||
Type = (SampleType)int.Parse(split[4]),
|
||||
Set = SampleSet.Soft,
|
||||
};
|
||||
|
||||
// TODO: "addition" field
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns null HitObjects but at least allows us to run.
|
||||
/// </summary>
|
||||
public class NullHitObjectParser : HitObjectParser
|
||||
{
|
||||
public override HitObject Parse(string text) => null;
|
||||
}
|
||||
}
|
23
osu.Game/Modes/Objects/Slider.cs
Normal file
23
osu.Game/Modes/Objects/Slider.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
internal class Slider : HitObject, IHasCurve, IHasDistance, IHasPosition, IHasCombo, IHasRepeats
|
||||
{
|
||||
public List<Vector2> ControlPoints { get; set; }
|
||||
public CurveType CurveType { get; set; }
|
||||
|
||||
public double Distance { get; set; }
|
||||
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public Color4 ComboColour { get; set; }
|
||||
public bool NewCombo { get; set; }
|
||||
public int ComboIndex { get; set; }
|
||||
|
||||
public int RepeatCount { get; set; }
|
||||
}
|
||||
}
|
11
osu.Game/Modes/Objects/Spinner.cs
Normal file
11
osu.Game/Modes/Objects/Spinner.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using osu.Game.Modes.Objects.Types;
|
||||
|
||||
namespace osu.Game.Modes.Objects
|
||||
{
|
||||
internal class Spinner : HitObject, IHasEndTime
|
||||
{
|
||||
public double EndTime { get; set; }
|
||||
|
||||
public double Duration => EndTime - StartTime;
|
||||
}
|
||||
}
|
10
osu.Game/Modes/Objects/Types/CurveType.cs
Normal file
10
osu.Game/Modes/Objects/Types/CurveType.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
public enum CurveType
|
||||
{
|
||||
Catmull,
|
||||
Bezier,
|
||||
Linear,
|
||||
PerfectCurve
|
||||
}
|
||||
}
|
25
osu.Game/Modes/Objects/Types/IHasCombo.cs
Normal file
25
osu.Game/Modes/Objects/Types/IHasCombo.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that is part of a combo.
|
||||
/// </summary>
|
||||
public interface IHasCombo
|
||||
{
|
||||
/// <summary>
|
||||
/// The colour of this HitObject in the combo.
|
||||
/// </summary>
|
||||
Color4 ComboColour { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the HitObject starts a new combo.
|
||||
/// </summary>
|
||||
bool NewCombo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The combo index.
|
||||
/// </summary>
|
||||
int ComboIndex { get; }
|
||||
}
|
||||
}
|
21
osu.Game/Modes/Objects/Types/IHasCurve.cs
Normal file
21
osu.Game/Modes/Objects/Types/IHasCurve.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that has a curve.
|
||||
/// </summary>
|
||||
public interface IHasCurve
|
||||
{
|
||||
/// <summary>
|
||||
/// The control points that shape the curve.
|
||||
/// </summary>
|
||||
List<Vector2> ControlPoints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of curve.
|
||||
/// </summary>
|
||||
CurveType CurveType { get; }
|
||||
}
|
||||
}
|
13
osu.Game/Modes/Objects/Types/IHasDistance.cs
Normal file
13
osu.Game/Modes/Objects/Types/IHasDistance.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that has a distance.
|
||||
/// </summary>
|
||||
public interface IHasDistance
|
||||
{
|
||||
/// <summary>
|
||||
/// The distance of the HitObject.
|
||||
/// </summary>
|
||||
double Distance { get; }
|
||||
}
|
||||
}
|
18
osu.Game/Modes/Objects/Types/IHasEndTime.cs
Normal file
18
osu.Game/Modes/Objects/Types/IHasEndTime.cs
Normal file
@ -0,0 +1,18 @@
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that ends at a different time than its start time.
|
||||
/// </summary>
|
||||
public interface IHasEndTime
|
||||
{
|
||||
/// <summary>
|
||||
/// The time at which the HitObject ends.
|
||||
/// </summary>
|
||||
double EndTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The duration of the HitObject.
|
||||
/// </summary>
|
||||
double Duration { get; }
|
||||
}
|
||||
}
|
15
osu.Game/Modes/Objects/Types/IHasPosition.cs
Normal file
15
osu.Game/Modes/Objects/Types/IHasPosition.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that has a starting position.
|
||||
/// </summary>
|
||||
public interface IHasPosition
|
||||
{
|
||||
/// <summary>
|
||||
/// The starting position of the HitObject.
|
||||
/// </summary>
|
||||
Vector2 Position { get; }
|
||||
}
|
||||
}
|
13
osu.Game/Modes/Objects/Types/IHasRepeats.cs
Normal file
13
osu.Game/Modes/Objects/Types/IHasRepeats.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A HitObject that spans some length.
|
||||
/// </summary>
|
||||
public interface IHasRepeats
|
||||
{
|
||||
/// <summary>
|
||||
/// The amount of times the HitObject repeats.
|
||||
/// </summary>
|
||||
int RepeatCount { get; }
|
||||
}
|
||||
}
|
16
osu.Game/Modes/Objects/Types/LegacyHitObjectLive.cs
Normal file
16
osu.Game/Modes/Objects/Types/LegacyHitObjectLive.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Modes.Objects.Types
|
||||
{
|
||||
[Flags]
|
||||
public enum HitObjectType
|
||||
{
|
||||
Circle = 1 << 0,
|
||||
Slider = 1 << 1,
|
||||
NewCombo = 1 << 2,
|
||||
Spinner = 1 << 3,
|
||||
ColourHax = 122,
|
||||
Hold = 1 << 7,
|
||||
SliderTick = 1 << 8,
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user