Split out IHasPath from IHasCurve to better define hitobjects

This commit is contained in:
Dean Herbert 2020-05-26 17:44:47 +09:00
parent a2eec5d963
commit 280b0adb1d
13 changed files with 57 additions and 43 deletions

View File

@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
switch (obj)
{
case IHasCurve curveData:
case IHasPathWithRepeats curveData:
return new JuiceStream
{
StartTime = obj.StartTime,

View File

@ -14,7 +14,7 @@ using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Catch.Objects
{
public class JuiceStream : CatchHitObject, IHasCurve
public class JuiceStream : CatchHitObject, IHasPathWithRepeats
{
/// <summary>
/// Positional distance that results in a duration of one second, before any speed adjustments.

View File

@ -474,7 +474,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
/// <returns></returns>
private IList<HitSampleInfo> sampleInfoListAt(double time)
{
if (!(HitObject is IHasCurve curveData))
if (!(HitObject is IHasPathWithRepeats curveData))
return HitObject.Samples;
double segmentTime = (EndTime - HitObject.StartTime) / spanCount;

View File

@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
switch (original)
{
case IHasCurve curveData:
case IHasPathWithRepeats curveData:
return new Slider
{
StartTime = original.StartTime,

View File

@ -17,7 +17,7 @@ using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects
{
public class Slider : OsuHitObject, IHasCurve
public class Slider : OsuHitObject, IHasPathWithRepeats
{
public double EndTime
{

View File

@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength)
{
List<IList<HitSampleInfo>> allSamples = obj is IHasCurve curveData ? curveData.NodeSamples : new List<IList<HitSampleInfo>>(new[] { samples });
List<IList<HitSampleInfo>> allSamples = obj is IHasPathWithRepeats curveData ? curveData.NodeSamples : new List<IList<HitSampleInfo>>(new[] { samples });
int i = 0;

View File

@ -3,9 +3,7 @@
using osu.Game.Rulesets.Objects.Types;
using System;
using System.Collections.Generic;
using System.Threading;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
@ -17,7 +15,7 @@ using osuTK;
namespace osu.Game.Rulesets.Taiko.Objects
{
public class DrumRoll : TaikoHitObject, IHasCurve
public class DrumRoll : TaikoHitObject, IHasPath
{
/// <summary>
/// Drum roll distance that results in a duration of 1 speed-adjusted beat length.
@ -115,11 +113,7 @@ namespace osu.Game.Rulesets.Taiko.Objects
double IHasDistance.Distance => Duration * Velocity;
int IHasRepeats.RepeatCount { get => 0; set { } }
List<IList<HitSampleInfo>> IHasRepeats.NodeSamples => new List<IList<HitSampleInfo>>();
SliderPath IHasCurve.Path
SliderPath IHasPath.Path
=> new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(1) }, ((IHasDistance)this).Distance / TaikoBeatmapConverter.LEGACY_VELOCITY_MULTIPLIER);
#endregion

View File

@ -365,7 +365,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
{
var hitObjects = decoder.Decode(stream).HitObjects;
var curveData = hitObjects[0] as IHasCurve;
var curveData = hitObjects[0] as IHasPathWithRepeats;
var positionData = hitObjects[0] as IHasPosition;
Assert.IsNotNull(positionData);

View File

@ -95,7 +95,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
{
var beatmap = decodeAsJson(normal);
var curveData = beatmap.HitObjects[0] as IHasCurve;
var curveData = beatmap.HitObjects[0] as IHasPathWithRepeats;
var positionData = beatmap.HitObjects[0] as IHasPosition;
Assert.IsNotNull(positionData);

View File

@ -233,9 +233,9 @@ namespace osu.Game.Beatmaps.Formats
writer.Write(FormattableString.Invariant($"{(int)getObjectType(hitObject)},"));
writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(hitObject.Samples)},"));
if (hitObject is IHasCurve curveData)
if (hitObject is IHasPathWithRepeats curveData)
{
addCurveData(writer, curveData, position);
addPathData(writer, curveData, position);
writer.Write(getSampleBank(hitObject.Samples, zeroBanks: true));
}
else
@ -263,7 +263,7 @@ namespace osu.Game.Beatmaps.Formats
switch (hitObject)
{
case IHasCurve _:
case IHasPath _:
type |= LegacyHitObjectType.Slider;
break;
@ -282,13 +282,13 @@ namespace osu.Game.Beatmaps.Formats
return type;
}
private void addCurveData(TextWriter writer, IHasCurve curveData, Vector2 position)
private void addPathData(TextWriter writer, IHasPath pathData, Vector2 position)
{
PathType? lastType = null;
for (int i = 0; i < curveData.Path.ControlPoints.Count; i++)
for (int i = 0; i < pathData.Path.ControlPoints.Count; i++)
{
PathControlPoint point = curveData.Path.ControlPoints[i];
PathControlPoint point = pathData.Path.ControlPoints[i];
if (point.Type.Value != null)
{
@ -325,23 +325,28 @@ namespace osu.Game.Beatmaps.Formats
if (i != 0)
{
writer.Write(FormattableString.Invariant($"{position.X + point.Position.Value.X}:{position.Y + point.Position.Value.Y}"));
writer.Write(i != curveData.Path.ControlPoints.Count - 1 ? "|" : ",");
writer.Write(i != pathData.Path.ControlPoints.Count - 1 ? "|" : ",");
}
}
writer.Write(FormattableString.Invariant($"{curveData.RepeatCount + 1},"));
writer.Write(FormattableString.Invariant($"{curveData.Path.Distance},"));
var curveData = pathData as IHasPathWithRepeats;
for (int i = 0; i < curveData.NodeSamples.Count; i++)
{
writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(curveData.NodeSamples[i])}"));
writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ",");
}
writer.Write(FormattableString.Invariant($"{(curveData?.RepeatCount ?? 0) + 1},"));
writer.Write(FormattableString.Invariant($"{pathData.Path.Distance},"));
for (int i = 0; i < curveData.NodeSamples.Count; i++)
if (curveData != null)
{
writer.Write(getSampleBank(curveData.NodeSamples[i], true));
writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ",");
for (int i = 0; i < curveData.NodeSamples.Count; i++)
{
writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(curveData.NodeSamples[i])}"));
writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ",");
}
for (int i = 0; i < curveData.NodeSamples.Count; i++)
{
writer.Write(getSampleBank(curveData.NodeSamples[i], true));
writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ",");
}
}
}

View File

@ -9,7 +9,7 @@ using osu.Game.Beatmaps.ControlPoints;
namespace osu.Game.Rulesets.Objects.Legacy
{
internal abstract class ConvertSlider : ConvertHitObject, IHasCurve, IHasLegacyLastTickOffset
internal abstract class ConvertSlider : ConvertHitObject, IHasPathWithRepeats, IHasLegacyLastTickOffset
{
/// <summary>
/// Scoring distance with a speed-adjusted beat length of 1 second.

View File

@ -0,0 +1,13 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Rulesets.Objects.Types
{
public interface IHasPath : IHasDistance
{
/// <summary>
/// The curve.
/// </summary>
SliderPath Path { get; }
}
}

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osuTK;
namespace osu.Game.Rulesets.Objects.Types
@ -8,15 +9,16 @@ namespace osu.Game.Rulesets.Objects.Types
/// <summary>
/// A HitObject that has a curve.
/// </summary>
public interface IHasCurve : IHasDistance, IHasRepeats
public interface IHasPathWithRepeats : IHasPath, IHasRepeats
{
/// <summary>
/// The curve.
/// </summary>
SliderPath Path { get; }
}
public static class HasCurveExtensions
[Obsolete("Use IHasPathWithRepeats instead.")] // can be removed 20201126
public interface IHasCurve : IHasPathWithRepeats
{
}
public static class HasPathWithRepeatsExtensions
{
/// <summary>
/// Computes the position on the curve relative to how much of the <see cref="HitObject"/> has been completed.
@ -24,7 +26,7 @@ namespace osu.Game.Rulesets.Objects.Types
/// <param name="obj">The curve.</param>
/// <param name="progress">[0, 1] where 0 is the start time of the <see cref="HitObject"/> and 1 is the end time of the <see cref="HitObject"/>.</param>
/// <returns>The position on the curve.</returns>
public static Vector2 CurvePositionAt(this IHasCurve obj, double progress)
public static Vector2 CurvePositionAt(this IHasPathWithRepeats obj, double progress)
=> obj.Path.PositionAt(obj.ProgressAt(progress));
/// <summary>
@ -33,7 +35,7 @@ namespace osu.Game.Rulesets.Objects.Types
/// <param name="obj">The curve.</param>
/// <param name="progress">[0, 1] where 0 is the start time of the <see cref="HitObject"/> and 1 is the end time of the <see cref="HitObject"/>.</param>
/// <returns>[0, 1] where 0 is the beginning of the curve and 1 is the end of the curve.</returns>
public static double ProgressAt(this IHasCurve obj, double progress)
public static double ProgressAt(this IHasPathWithRepeats obj, double progress)
{
double p = progress * obj.SpanCount() % 1;
if (obj.SpanAt(progress) % 2 == 1)
@ -47,7 +49,7 @@ namespace osu.Game.Rulesets.Objects.Types
/// <param name="obj">The curve.</param>
/// <param name="progress">[0, 1] where 0 is the beginning of the curve and 1 is the end of the curve.</param>
/// <returns>[0, SpanCount) where 0 is the first run.</returns>
public static int SpanAt(this IHasCurve obj, double progress)
public static int SpanAt(this IHasPathWithRepeats obj, double progress)
=> (int)(progress * obj.SpanCount());
}
}