1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-14 04:02:59 +08:00

Merge pull request #662 from smoogipooo/nodal-hit-sounds

Nodal hit sounds
This commit is contained in:
Dean Herbert 2017-04-24 14:22:45 +09:00 committed by GitHub
commit c61f69569c
30 changed files with 312 additions and 210 deletions

View File

@ -10,7 +10,6 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Osu.Objects;
@ -62,15 +61,12 @@ namespace osu.Desktop.VisualTests.Tests
add(new DrawableSlider(new Slider
{
StartTime = framedClock.CurrentTime + 600,
CurveObject = new CurvedHitObject
{
ControlPoints = new List<Vector2>
{
new Vector2(-200, 0),
new Vector2(400, 0),
},
Distance = 400
},
Distance = 400,
Position = new Vector2(-200, 0),
Velocity = 1,
TickDistance = 100,

View File

@ -19,10 +19,10 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
protected override IEnumerable<OsuHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
{
IHasCurve curveData = original as IHasCurve;
IHasEndTime endTimeData = original as IHasEndTime;
IHasPosition positionData = original as IHasPosition;
IHasCombo comboData = original as IHasCombo;
var curveData = original as IHasCurve;
var endTimeData = original as IHasEndTime;
var positionData = original as IHasPosition;
var comboData = original as IHasCombo;
if (curveData != null)
{
@ -30,7 +30,11 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
{
StartTime = original.StartTime,
Samples = original.Samples,
CurveObject = curveData,
ControlPoints = curveData.ControlPoints,
CurveType = curveData.CurveType,
Distance = curveData.Distance,
RepeatSamples = curveData.RepeatSamples,
RepeatCount = curveData.RepeatCount,
Position = positionData?.Position ?? Vector2.Zero,
NewCombo = comboData?.NewCombo ?? false
};

View File

@ -20,24 +20,33 @@ namespace osu.Game.Rulesets.Osu.Objects
/// </summary>
private const float base_scoring_distance = 100;
public IHasCurve CurveObject { get; set; }
public SliderCurve Curve => CurveObject.Curve;
public readonly SliderCurve Curve = new SliderCurve();
public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity;
public double Duration => EndTime - StartTime;
public override Vector2 EndPosition => PositionAt(1);
public Vector2 PositionAt(double progress) => CurveObject.PositionAt(progress);
public double ProgressAt(double progress) => CurveObject.ProgressAt(progress);
public int RepeatAt(double progress) => CurveObject.RepeatAt(progress);
public List<Vector2> ControlPoints
{
get { return Curve.ControlPoints; }
set { Curve.ControlPoints = value; }
}
public List<Vector2> ControlPoints => CurveObject.ControlPoints;
public CurveType CurveType => CurveObject.CurveType;
public double Distance => CurveObject.Distance;
public CurveType CurveType
{
get { return Curve.CurveType; }
set { Curve.CurveType = value; }
}
public int RepeatCount => CurveObject.RepeatCount;
public double Distance
{
get { return Curve.Distance; }
set { Curve.Distance = value; }
}
public List<List<SampleInfo>> RepeatSamples { get; set; } = new List<List<SampleInfo>>();
public int RepeatCount { get; set; } = 1;
private int stackHeight;
public override int StackHeight
@ -63,6 +72,18 @@ namespace osu.Game.Rulesets.Osu.Objects
TickDistance = scoringDistance / difficulty.SliderTickRate;
}
public Vector2 PositionAt(double progress) => Curve.PositionAt(ProgressAt(progress));
public double ProgressAt(double progress)
{
double p = progress * RepeatCount % 1;
if (RepeatAt(progress) % 2 == 1)
p = 1 - p;
return p;
}
public int RepeatAt(double progress) => (int)(progress * RepeatCount);
public IEnumerable<SliderTick> Ticks
{
get

View File

@ -3,7 +3,6 @@
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Beatmaps;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Objects;
using System;
@ -28,7 +27,7 @@ namespace osu.Game.Rulesets.Osu
protected override void PreprocessHitObjects()
{
foreach (var h in Objects)
(h as IHasCurve)?.Curve?.Calculate();
(h as Slider)?.Curve?.Calculate();
}
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)

View File

@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps.Formats
// TODO: Not sure how far back to go, or differences between versions
}
private HitObjectParser parser;
private ConvertHitObjectParser parser;
private LegacySampleBank defaultSampleBank;
private int defaultSampleVolume = 100;
@ -90,16 +90,16 @@ namespace osu.Game.Beatmaps.Formats
switch (beatmap.BeatmapInfo.RulesetID)
{
case 0:
parser = new Rulesets.Objects.Legacy.Osu.HitObjectParser();
parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser();
break;
case 1:
parser = new Rulesets.Objects.Legacy.Taiko.HitObjectParser();
parser = new Rulesets.Objects.Legacy.Taiko.ConvertHitObjectParser();
break;
case 2:
parser = new Rulesets.Objects.Legacy.Catch.HitObjectParser();
parser = new Rulesets.Objects.Legacy.Catch.ConvertHitObjectParser();
break;
case 3:
parser = new Rulesets.Objects.Legacy.Mania.HitObjectParser();
parser = new Rulesets.Objects.Legacy.Mania.ConvertHitObjectParser();
break;
}
break;

View File

@ -1,49 +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 OpenTK;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Objects
{
public class CurvedHitObject : HitObject, IHasCurve
{
public SliderCurve Curve { get; } = new SliderCurve();
public int RepeatCount { get; set; } = 1;
public double EndTime => 0;
public double Duration => 0;
public List<Vector2> ControlPoints
{
get { return Curve.ControlPoints; }
set { Curve.ControlPoints = value; }
}
public CurveType CurveType
{
get { return Curve.CurveType; }
set { Curve.CurveType = value; }
}
public double Distance
{
get { return Curve.Distance; }
set { Curve.Distance = value; }
}
public Vector2 PositionAt(double progress) => Curve.PositionAt(ProgressAt(progress));
public double ProgressAt(double progress)
{
var p = progress * RepeatCount % 1;
if (RepeatAt(progress) % 2 == 1)
p = 1 - p;
return p;
}
public int RepeatAt(double progress) => (int)(progress * RepeatCount);
}
}

View File

@ -4,6 +4,7 @@
using osu.Game.Audio;
using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Objects
@ -19,10 +20,14 @@ namespace osu.Game.Rulesets.Objects
/// <summary>
/// The time at which the HitObject starts.
/// </summary>
public double StartTime { get; set; }
public double StartTime;
/// <summary>
/// The samples to be played when this hit object is hit.
/// <para>
/// In the case of <see cref="IHasRepeats"/> types, this is the sample of the curve body
/// and can be treated as the default samples for the hit object.
/// </para>
/// </summary>
public List<SampleInfo> Samples = new List<SampleInfo>();
@ -36,17 +41,24 @@ namespace osu.Game.Rulesets.Objects
ControlPoint overridePoint;
ControlPoint timingPoint = timing.TimingPointAt(StartTime, out overridePoint);
foreach (var sample in Samples)
ControlPoint samplePoint = overridePoint ?? timingPoint;
// Initialize first sample
Samples.ForEach(s => initializeSampleInfo(s, samplePoint));
// Initialize any repeat samples
var repeatData = this as IHasRepeats;
repeatData?.RepeatSamples?.ForEach(r => r.ForEach(s => initializeSampleInfo(s, samplePoint)));
}
private void initializeSampleInfo(SampleInfo sample, ControlPoint controlPoint)
{
if (sample.Volume == 0)
sample.Volume = (overridePoint ?? timingPoint)?.SampleVolume ?? 0;
sample.Volume = controlPoint?.SampleVolume ?? 0;
// If the bank is not assigned a name, assign it from the control point
if (!string.IsNullOrEmpty(sample.Bank))
continue;
sample.Bank = (overridePoint ?? timingPoint)?.SampleBank ?? @"normal";
}
if (string.IsNullOrEmpty(sample.Bank))
sample.Bank = controlPoint?.SampleBank ?? @"normal";
}
}
}

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
/// <summary>
/// Legacy osu!catch Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasCombo, IHasXPosition
internal sealed class ConvertHit : HitObject, IHasCombo, IHasXPosition
{
public float X { get; set; }

View File

@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Audio;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
@ -10,33 +11,34 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
/// <summary>
/// A HitObjectParser to parse legacy osu!catch Beatmaps.
/// </summary>
internal class HitObjectParser : Legacy.HitObjectParser
internal class ConvertHitObjectParser : Legacy.ConvertHitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
return new ConvertHit
{
X = position.X,
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples)
{
return new Slider
return new ConvertSlider
{
X = position.X,
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatSamples = repeatSamples,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
return new ConvertSpinner
{
EndTime = endTime
};

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
/// <summary>
/// Legacy osu!catch Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasXPosition, IHasCombo
internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasXPosition, IHasCombo
{
public float X { get; set; }

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
/// <summary>
/// Legacy osu!catch Spinner-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Spinner : HitObject, IHasEndTime
internal sealed class ConvertSpinner : HitObject, IHasEndTime
{
public double EndTime { get; set; }

View File

@ -14,29 +14,28 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// <summary>
/// A HitObjectParser to parse legacy Beatmaps.
/// </summary>
internal abstract class HitObjectParser : Objects.HitObjectParser
internal abstract class ConvertHitObjectParser : HitObjectParser
{
public override HitObject Parse(string text)
{
string[] split = text.Split(',');
var type = (HitObjectType)int.Parse(split[3]) & ~HitObjectType.ColourHax;
bool combo = type.HasFlag(HitObjectType.NewCombo);
type &= ~HitObjectType.NewCombo;
ConvertHitObjectType type = (ConvertHitObjectType)int.Parse(split[3]) & ~ConvertHitObjectType.ColourHax;
bool combo = type.HasFlag(ConvertHitObjectType.NewCombo);
type &= ~ConvertHitObjectType.NewCombo;
int sampleVolume = 0;
string normalSampleBank = null;
string addSampleBank = null;
var soundType = (LegacySoundType)int.Parse(split[4]);
var bankInfo = new SampleBankInfo();
HitObject result;
if ((type & HitObjectType.Circle) > 0)
if ((type & ConvertHitObjectType.Circle) > 0)
{
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);
readCustomSampleBanks(split[5], bankInfo);
}
else if ((type & HitObjectType.Slider) > 0)
else if ((type & ConvertHitObjectType.Slider) > 0)
{
CurveType curveType = CurveType.Catmull;
double length = 0;
@ -77,26 +76,74 @@ namespace osu.Game.Rulesets.Objects.Legacy
if (split.Length > 7)
length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture);
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);
readCustomSampleBanks(split[10], bankInfo);
// One node for each repeat + the start and end nodes
// Note that the first length of the slider is considered a repeat, but there are no actual repeats happening
int nodes = Math.Max(0, repeatCount - 1) + 2;
// Populate node sample bank infos with the default hit object sample bank
var nodeBankInfos = new List<SampleBankInfo>();
for (int i = 0; i < nodes; i++)
nodeBankInfos.Add(bankInfo.Clone());
// Read any per-node sample banks
if (split.Length > 9 && split[9].Length > 0)
{
string[] sets = split[9].Split('|');
for (int i = 0; i < nodes; i++)
{
if (i >= sets.Length)
break;
SampleBankInfo info = nodeBankInfos[i];
readCustomSampleBanks(sets[i], info);
}
else if ((type & HitObjectType.Spinner) > 0)
}
// Populate node sound types with the default hit object sound type
var nodeSoundTypes = new List<LegacySoundType>();
for (int i = 0; i < nodes; i++)
nodeSoundTypes.Add(soundType);
// Read any per-node sound types
if (split.Length > 8 && split[8].Length > 0)
{
string[] adds = split[8].Split('|');
for (int i = 0; i < nodes; i++)
{
if (i >= adds.Length)
break;
int sound;
int.TryParse(adds[i], out sound);
nodeSoundTypes[i] = (LegacySoundType)sound;
}
}
// Generate the final per-node samples
var nodeSamples = new List<List<SampleInfo>>(nodes);
for (int i = 0; i <= repeatCount; i++)
nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i]));
result = CreateSlider(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo, points, length, curveType, repeatCount, nodeSamples);
}
else if ((type & ConvertHitObjectType.Spinner) > 0)
{
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);
readCustomSampleBanks(split[6], bankInfo);
}
else if ((type & HitObjectType.Hold) > 0)
else if ((type & ConvertHitObjectType.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 Hold
result = new ConvertHold
{
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
NewCombo = combo
@ -106,50 +153,12 @@ namespace osu.Game.Rulesets.Objects.Legacy
throw new InvalidOperationException($@"Unknown hit object type {type}");
result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture);
var soundType = (LegacySoundType)int.Parse(split[4]);
result.Samples.Add(new SampleInfo
{
Bank = normalSampleBank,
Name = SampleInfo.HIT_NORMAL,
Volume = sampleVolume
});
if ((soundType & LegacySoundType.Finish) > 0)
{
result.Samples.Add(new SampleInfo
{
Bank = addSampleBank,
Name = SampleInfo.HIT_FINISH,
Volume = sampleVolume
});
}
if ((soundType & LegacySoundType.Whistle) > 0)
{
result.Samples.Add(new SampleInfo
{
Bank = addSampleBank,
Name = SampleInfo.HIT_WHISTLE,
Volume = sampleVolume
});
}
if ((soundType & LegacySoundType.Clap) > 0)
{
result.Samples.Add(new SampleInfo
{
Bank = addSampleBank,
Name = SampleInfo.HIT_CLAP,
Volume = sampleVolume
});
}
result.Samples = convertSoundType(soundType, bankInfo);
return result;
}
private void readCustomSampleBanks(string str, ref string normalSampleBank, ref string addSampleBank, ref int sampleVolume)
private void readCustomSampleBanks(string str, SampleBankInfo bankInfo)
{
if (string.IsNullOrEmpty(str))
return;
@ -169,9 +178,11 @@ namespace osu.Game.Rulesets.Objects.Legacy
if (stringAddBank == @"none")
stringAddBank = null;
normalSampleBank = stringBank;
addSampleBank = stringAddBank;
sampleVolume = split.Length > 3 ? int.Parse(split[3]) : 0;
bankInfo.Normal = stringBank;
bankInfo.Add = stringAddBank;
if (split.Length > 3)
bankInfo.Volume = int.Parse(split[3]);
}
/// <summary>
@ -191,8 +202,9 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// <param name="length">The slider length.</param>
/// <param name="curveType">The slider curve type.</param>
/// <param name="repeatCount">The slider repeat count.</param>
/// <param name="repeatSamples">The samples to be played when the repeat nodes are hit. This includes the head and tail of the slider.</param>
/// <returns>The hit object.</returns>
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount);
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples);
/// <summary>
/// Creates a legacy Spinner-type hit object.
@ -202,6 +214,63 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// <returns>The hit object.</returns>
protected abstract HitObject CreateSpinner(Vector2 position, double endTime);
private List<SampleInfo> convertSoundType(LegacySoundType type, SampleBankInfo bankInfo)
{
var soundTypes = new List<SampleInfo>
{
new SampleInfo
{
Bank = bankInfo.Normal,
Name = SampleInfo.HIT_NORMAL,
Volume = bankInfo.Volume
}
};
if ((type & LegacySoundType.Finish) > 0)
{
soundTypes.Add(new SampleInfo
{
Bank = bankInfo.Add,
Name = SampleInfo.HIT_FINISH,
Volume = bankInfo.Volume
});
}
if ((type & LegacySoundType.Whistle) > 0)
{
soundTypes.Add(new SampleInfo
{
Bank = bankInfo.Add,
Name = SampleInfo.HIT_WHISTLE,
Volume = bankInfo.Volume
});
}
if ((type & LegacySoundType.Clap) > 0)
{
soundTypes.Add(new SampleInfo
{
Bank = bankInfo.Add,
Name = SampleInfo.HIT_CLAP,
Volume = bankInfo.Volume
});
}
return soundTypes;
}
private class SampleBankInfo
{
public string Normal;
public string Add;
public int Volume;
public SampleBankInfo Clone()
{
return (SampleBankInfo)MemberwiseClone();
}
}
[Flags]
private enum LegacySoundType
{

View File

@ -6,7 +6,7 @@ using System;
namespace osu.Game.Rulesets.Objects.Legacy
{
[Flags]
public enum HitObjectType
internal enum ConvertHitObjectType
{
Circle = 1 << 0,
Slider = 1 << 1,

View File

@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// <summary>
/// Legacy Hold-type, used for parsing "specials" in beatmaps.
/// </summary>
internal sealed class Hold : HitObject, IHasPosition, IHasCombo, IHasHold
internal sealed class ConvertHold : HitObject, IHasPosition, IHasCombo, IHasHold
{
public Vector2 Position { get; set; }

View File

@ -0,0 +1,39 @@
// 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.Rulesets.Objects.Types;
using System;
using System.Collections.Generic;
using OpenTK;
using osu.Game.Audio;
namespace osu.Game.Rulesets.Objects.Legacy
{
internal abstract class ConvertSlider : HitObject, IHasCurve
{
public List<Vector2> ControlPoints { get; set; }
public CurveType CurveType { get; set; }
public double Distance { get; set; }
public List<List<SampleInfo>> RepeatSamples { get; set; }
public int RepeatCount { get; set; } = 1;
public double EndTime { get; set; }
public double Duration { get; set; }
public Vector2 PositionAt(double progress)
{
throw new NotImplementedException();
}
public double ProgressAt(double progress)
{
throw new NotImplementedException();
}
public int RepeatAt(double progress)
{
throw new NotImplementedException();
}
}
}

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
/// <summary>
/// Legacy osu!mania Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasXPosition, IHasCombo
internal sealed class ConvertHit : HitObject, IHasXPosition, IHasCombo
{
public float X { get; set; }

View File

@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Audio;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
@ -10,33 +11,34 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
/// <summary>
/// A HitObjectParser to parse legacy osu!mania Beatmaps.
/// </summary>
internal class HitObjectParser : Legacy.HitObjectParser
internal class ConvertHitObjectParser : Legacy.ConvertHitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
return new ConvertHit
{
X = position.X,
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples)
{
return new Slider
return new ConvertSlider
{
X = position.X,
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatSamples = repeatSamples,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
return new ConvertSpinner
{
X = position.X,
EndTime = endTime

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
/// <summary>
/// Legacy osu!mania Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasXPosition, IHasCombo
internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasXPosition, IHasCombo
{
public float X { get; set; }

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
/// <summary>
/// Legacy osu!mania Spinner-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Spinner : HitObject, IHasEndTime, IHasXPosition
internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasXPosition
{
public double EndTime { get; set; }

View File

@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
/// <summary>
/// Legacy osu! Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasPosition, IHasCombo
internal sealed class ConvertHit : HitObject, IHasPosition, IHasCombo
{
public Vector2 Position { get; set; }

View File

@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Audio;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
@ -10,33 +11,34 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
/// <summary>
/// A HitObjectParser to parse legacy osu! Beatmaps.
/// </summary>
internal class HitObjectParser : Legacy.HitObjectParser
internal class ConvertHitObjectParser : Legacy.ConvertHitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
return new ConvertHit
{
Position = position,
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples)
{
return new Slider
return new ConvertSlider
{
Position = position,
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatSamples = repeatSamples,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
return new ConvertSpinner
{
Position = position,
EndTime = endTime

View File

@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
/// <summary>
/// Legacy osu! Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasPosition, IHasCombo
internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasPosition, IHasCombo
{
public Vector2 Position { get; set; }

View File

@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
/// <summary>
/// Legacy osu! Spinner-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Spinner : HitObject, IHasEndTime, IHasPosition
internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasPosition
{
public double EndTime { get; set; }

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
/// <summary>
/// Legacy osu!taiko Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Hit : HitObject, IHasCombo
internal sealed class ConvertHit : HitObject, IHasCombo
{
public bool NewCombo { get; set; }
}

View File

@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Audio;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
@ -10,31 +11,32 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
/// <summary>
/// A HitObjectParser to parse legacy osu!taiko Beatmaps.
/// </summary>
internal class HitObjectParser : Legacy.HitObjectParser
internal class ConvertHitObjectParser : Legacy.ConvertHitObjectParser
{
protected override HitObject CreateHit(Vector2 position, bool newCombo)
{
return new Hit
return new ConvertHit
{
NewCombo = newCombo,
};
}
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount)
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples)
{
return new Slider
return new ConvertSlider
{
NewCombo = newCombo,
ControlPoints = controlPoints,
Distance = length,
CurveType = curveType,
RepeatSamples = repeatSamples,
RepeatCount = repeatCount
};
}
protected override HitObject CreateSpinner(Vector2 position, double endTime)
{
return new Spinner
return new ConvertSpinner
{
EndTime = endTime
};

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
/// <summary>
/// Legacy osu!taiko Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Slider : CurvedHitObject, IHasCombo
internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasCombo
{
public bool NewCombo { get; set; }
}

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
/// <summary>
/// Legacy osu!taiko Spinner-type, used for parsing Beatmaps.
/// </summary>
internal sealed class Spinner : HitObject, IHasEndTime
internal sealed class ConvertSpinner : HitObject, IHasEndTime
{
public double EndTime { get; set; }

View File

@ -11,11 +11,6 @@ namespace osu.Game.Rulesets.Objects.Types
/// </summary>
public interface IHasCurve : IHasDistance, IHasRepeats
{
/// <summary>
/// The curve.
/// </summary>
SliderCurve Curve { get; }
/// <summary>
/// The control points that shape the curve.
/// </summary>

View File

@ -1,6 +1,9 @@
// 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.Audio;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Objects.Types
{
/// <summary>
@ -12,5 +15,10 @@ namespace osu.Game.Rulesets.Objects.Types
/// The amount of times the HitObject repeats.
/// </summary>
int RepeatCount { get; }
/// <summary>
/// The samples to be played when each repeat node is hit (0 -> first repeat node, 1 -> second repeat node, etc).
/// </summary>
List<List<SampleInfo>> RepeatSamples { get; }
}
}

View File

@ -109,6 +109,20 @@
<Compile Include="IO\Serialization\IJsonSerializable.cs" />
<Compile Include="IPC\ScoreIPCChannel.cs" />
<Compile Include="Rulesets\BeatmapStatistic.cs" />
<Compile Include="Rulesets\Objects\Legacy\Catch\ConvertHit.cs" />
<Compile Include="Rulesets\Objects\Legacy\Catch\ConvertHitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\Catch\ConvertSlider.cs" />
<Compile Include="Rulesets\Objects\Legacy\Catch\ConvertSpinner.cs" />
<Compile Include="Rulesets\Objects\Legacy\ConvertSlider.cs" />
<Compile Include="Rulesets\Objects\Legacy\Mania\ConvertHit.cs" />
<Compile Include="Rulesets\Objects\Legacy\Mania\ConvertHitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\Mania\ConvertSlider.cs" />
<Compile Include="Rulesets\Objects\Legacy\Mania\ConvertSpinner.cs" />
<Compile Include="Rulesets\Objects\Legacy\Osu\ConvertHitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\Taiko\ConvertHit.cs" />
<Compile Include="Rulesets\Objects\Legacy\Taiko\ConvertHitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\Taiko\ConvertSlider.cs" />
<Compile Include="Rulesets\Objects\Legacy\Taiko\ConvertSpinner.cs" />
<Compile Include="Rulesets\Mods\IApplicableToClock.cs" />
<Compile Include="Rulesets\Mods\ModAutoplay.cs" />
<Compile Include="Rulesets\Mods\ModCinema.cs" />
@ -124,19 +138,6 @@
<Compile Include="Rulesets\Mods\ModRelax.cs" />
<Compile Include="Rulesets\Mods\ModSuddenDeath.cs" />
<Compile Include="Rulesets\Mods\MultiMod.cs" />
<Compile Include="Rulesets\Objects\Legacy\Catch\Hit.cs" />
<Compile Include="Rulesets\Objects\Legacy\Catch\HitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\Catch\Slider.cs" />
<Compile Include="Rulesets\Objects\Legacy\Catch\Spinner.cs" />
<Compile Include="Rulesets\Objects\Legacy\Mania\Hit.cs" />
<Compile Include="Rulesets\Objects\Legacy\Mania\HitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\Mania\Slider.cs" />
<Compile Include="Rulesets\Objects\Legacy\Mania\Spinner.cs" />
<Compile Include="Rulesets\Objects\Legacy\Osu\HitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\Taiko\Hit.cs" />
<Compile Include="Rulesets\Objects\Legacy\Taiko\HitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\Taiko\Slider.cs" />
<Compile Include="Rulesets\Objects\Legacy\Taiko\Spinner.cs" />
<Compile Include="Rulesets\Objects\Types\IHasXPosition.cs" />
<Compile Include="Rulesets\Objects\Types\IHasYPosition.cs" />
<Compile Include="Rulesets\Replays\Replay.cs" />
@ -149,12 +150,11 @@
<Compile Include="Rulesets\Objects\Drawables\HitResult.cs" />
<Compile Include="Rulesets\Objects\BezierApproximator.cs" />
<Compile Include="Rulesets\Objects\CircularArcApproximator.cs" />
<Compile Include="Rulesets\Objects\CurvedHitObject.cs" />
<Compile Include="Rulesets\Objects\Legacy\Osu\Hit.cs" />
<Compile Include="Rulesets\Objects\Legacy\HitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\Hold.cs" />
<Compile Include="Rulesets\Objects\Legacy\Osu\Slider.cs" />
<Compile Include="Rulesets\Objects\Legacy\Osu\Spinner.cs" />
<Compile Include="Rulesets\Objects\Legacy\Osu\ConvertHit.cs" />
<Compile Include="Rulesets\Objects\Legacy\ConvertHitObjectParser.cs" />
<Compile Include="Rulesets\Objects\Legacy\ConvertHold.cs" />
<Compile Include="Rulesets\Objects\Legacy\Osu\ConvertSlider.cs" />
<Compile Include="Rulesets\Objects\Legacy\Osu\ConvertSpinner.cs" />
<Compile Include="Rulesets\Objects\SliderCurve.cs" />
<Compile Include="Rulesets\Objects\Types\CurveType.cs" />
<Compile Include="Rulesets\Objects\Drawables\IDrawableHitObjectWithProxiedApproach.cs" />
@ -167,7 +167,7 @@
<Compile Include="Rulesets\Objects\Types\IHasRepeats.cs" />
<Compile Include="Rulesets\Objects\Types\IHasPosition.cs" />
<Compile Include="Rulesets\Objects\Types\IHasHold.cs" />
<Compile Include="Rulesets\Objects\Legacy\HitObjectType.cs" />
<Compile Include="Rulesets\Objects\Legacy\ConvertHitObjectType.cs" />
<Compile Include="Rulesets\Replays\ReplayButtonState.cs" />
<Compile Include="Rulesets\Replays\ReplayFrame.cs" />
<Compile Include="Database\RulesetDatabase.cs" />