mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 08:27:49 +08:00
Fix skinning support for combobreak
This commit is contained in:
parent
bd54b34538
commit
60ea3d4e1a
@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
{
|
{
|
||||||
base.CreateNestedHitObjects();
|
base.CreateNestedHitObjects();
|
||||||
|
|
||||||
var tickSamples = Samples.Select(s => new SampleInfo
|
var tickSamples = Samples.Select(s => new HitSampleInfo
|
||||||
{
|
{
|
||||||
Bank = s.Bank,
|
Bank = s.Bank,
|
||||||
Name = @"slidertick",
|
Name = @"slidertick",
|
||||||
@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
|
|
||||||
public double Distance => Path.Distance;
|
public double Distance => Path.Distance;
|
||||||
|
|
||||||
public List<List<SampleInfo>> NodeSamples { get; set; } = new List<List<SampleInfo>>();
|
public List<List<HitSampleInfo>> NodeSamples { get; set; } = new List<List<HitSampleInfo>>();
|
||||||
|
|
||||||
public double? LegacyLastTickOffset { get; set; }
|
public double? LegacyLastTickOffset { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The time to retrieve the sample info list from.</param>
|
/// <param name="time">The time to retrieve the sample info list from.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private List<SampleInfo> sampleInfoListAt(double time)
|
private List<HitSampleInfo> sampleInfoListAt(double time)
|
||||||
{
|
{
|
||||||
var curveData = HitObject as IHasCurve;
|
var curveData = HitObject as IHasCurve;
|
||||||
|
|
||||||
|
@ -364,7 +364,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDoubleSample(SampleInfo sample) => sample.Name == SampleInfo.HIT_CLAP || sample.Name == SampleInfo.HIT_FINISH;
|
bool isDoubleSample(HitSampleInfo sample) => sample.Name == HitSampleInfo.HIT_CLAP || sample.Name == HitSampleInfo.HIT_FINISH;
|
||||||
|
|
||||||
bool canGenerateTwoNotes = !convertType.HasFlag(PatternType.LowProbability);
|
bool canGenerateTwoNotes = !convertType.HasFlag(PatternType.LowProbability);
|
||||||
canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample);
|
canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample);
|
||||||
@ -443,7 +443,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
noteCount = 0;
|
noteCount = 0;
|
||||||
noteCount = Math.Min(TotalColumns - 1, noteCount);
|
noteCount = Math.Min(TotalColumns - 1, noteCount);
|
||||||
|
|
||||||
bool ignoreHead = !sampleInfoListAt(startTime).Any(s => s.Name == SampleInfo.HIT_WHISTLE || s.Name == SampleInfo.HIT_FINISH || s.Name == SampleInfo.HIT_CLAP);
|
bool ignoreHead = !sampleInfoListAt(startTime).Any(s => s.Name == HitSampleInfo.HIT_WHISTLE || s.Name == HitSampleInfo.HIT_FINISH || s.Name == HitSampleInfo.HIT_CLAP);
|
||||||
|
|
||||||
var rowPattern = new Pattern();
|
var rowPattern = new Pattern();
|
||||||
|
|
||||||
@ -472,7 +472,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The time to retrieve the sample info list from.</param>
|
/// <param name="time">The time to retrieve the sample info list from.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private List<SampleInfo> sampleInfoListAt(double time)
|
private List<HitSampleInfo> sampleInfoListAt(double time)
|
||||||
{
|
{
|
||||||
var curveData = HitObject as IHasCurve;
|
var curveData = HitObject as IHasCurve;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
switch (TotalColumns)
|
switch (TotalColumns)
|
||||||
{
|
{
|
||||||
case 8 when HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000:
|
case 8 when HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000:
|
||||||
addToPattern(pattern, 0, generateHold);
|
addToPattern(pattern, 0, generateHold);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -72,9 +72,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (hold.Head.Samples == null)
|
if (hold.Head.Samples == null)
|
||||||
hold.Head.Samples = new List<SampleInfo>();
|
hold.Head.Samples = new List<HitSampleInfo>();
|
||||||
|
|
||||||
hold.Head.Samples.Add(new SampleInfo { Name = SampleInfo.HIT_NORMAL });
|
hold.Head.Samples.Add(new HitSampleInfo { Name = HitSampleInfo.HIT_NORMAL });
|
||||||
|
|
||||||
hold.Tail.Samples = HitObject.Samples;
|
hold.Tail.Samples = HitObject.Samples;
|
||||||
|
|
||||||
|
@ -79,9 +79,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
if (!convertType.HasFlag(PatternType.KeepSingle))
|
if (!convertType.HasFlag(PatternType.KeepSingle))
|
||||||
{
|
{
|
||||||
if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && TotalColumns != 8)
|
if (HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH) && TotalColumns != 8)
|
||||||
convertType |= PatternType.Mirror;
|
convertType |= PatternType.Mirror;
|
||||||
else if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP))
|
else if (HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP))
|
||||||
convertType |= PatternType.Gathered;
|
convertType |= PatternType.Gathered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,7 +263,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this hit object can generate a note in the special column.
|
/// Whether this hit object can generate a note in the special column.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool hasSpecialColumn => HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP) && HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH);
|
private bool hasSpecialColumn => HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP) && HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a random pattern.
|
/// Generates a random pattern.
|
||||||
@ -364,7 +364,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP))
|
if (HitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP))
|
||||||
p2 = 1;
|
p2 = 1;
|
||||||
|
|
||||||
return GetRandomNoteCount(p2, p3, p4, p5);
|
return GetRandomNoteCount(p2, p3, p4, p5);
|
||||||
|
@ -248,9 +248,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
private void createCatmull(int repeats = 0)
|
private void createCatmull(int repeats = 0)
|
||||||
{
|
{
|
||||||
var repeatSamples = new List<List<SampleInfo>>();
|
var repeatSamples = new List<List<HitSampleInfo>>();
|
||||||
for (int i = 0; i < repeats; i++)
|
for (int i = 0; i < repeats; i++)
|
||||||
repeatSamples.Add(new List<SampleInfo>());
|
repeatSamples.Add(new List<HitSampleInfo>());
|
||||||
|
|
||||||
var slider = new Slider
|
var slider = new Slider
|
||||||
{
|
{
|
||||||
@ -270,11 +270,11 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
addSlider(slider, 3, 1);
|
addSlider(slider, 3, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<List<SampleInfo>> createEmptySamples(int repeats)
|
private List<List<HitSampleInfo>> createEmptySamples(int repeats)
|
||||||
{
|
{
|
||||||
var repeatSamples = new List<List<SampleInfo>>();
|
var repeatSamples = new List<List<HitSampleInfo>>();
|
||||||
for (int i = 0; i < repeats; i++)
|
for (int i = 0; i < repeats; i++)
|
||||||
repeatSamples.Add(new List<SampleInfo>());
|
repeatSamples.Add(new List<HitSampleInfo>());
|
||||||
return repeatSamples;
|
return repeatSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal float LazyTravelDistance;
|
internal float LazyTravelDistance;
|
||||||
|
|
||||||
public List<List<SampleInfo>> NodeSamples { get; set; } = new List<List<SampleInfo>>();
|
public List<List<HitSampleInfo>> NodeSamples { get; set; } = new List<List<HitSampleInfo>>();
|
||||||
|
|
||||||
private int repeatCount;
|
private int repeatCount;
|
||||||
|
|
||||||
@ -157,12 +157,12 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
foreach (var e in
|
foreach (var e in
|
||||||
SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset))
|
SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset))
|
||||||
{
|
{
|
||||||
var firstSample = Samples.Find(s => s.Name == SampleInfo.HIT_NORMAL)
|
var firstSample = Samples.Find(s => s.Name == HitSampleInfo.HIT_NORMAL)
|
||||||
?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933)
|
?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933)
|
||||||
var sampleList = new List<SampleInfo>();
|
var sampleList = new List<HitSampleInfo>();
|
||||||
|
|
||||||
if (firstSample != null)
|
if (firstSample != null)
|
||||||
sampleList.Add(new SampleInfo
|
sampleList.Add(new HitSampleInfo
|
||||||
{
|
{
|
||||||
Bank = firstSample.Bank,
|
Bank = firstSample.Bank,
|
||||||
Volume = firstSample.Volume,
|
Volume = firstSample.Volume,
|
||||||
@ -225,7 +225,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SampleInfo> getNodeSamples(int nodeIndex) =>
|
private List<HitSampleInfo> getNodeSamples(int nodeIndex) =>
|
||||||
nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples;
|
nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples;
|
||||||
|
|
||||||
public override Judgement CreateJudgement() => new OsuJudgement();
|
public override Judgement CreateJudgement() => new OsuJudgement();
|
||||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
{
|
{
|
||||||
typeof(InputDrum),
|
typeof(InputDrum),
|
||||||
typeof(DrumSampleMapping),
|
typeof(DrumSampleMapping),
|
||||||
typeof(SampleInfo),
|
typeof(HitSampleInfo),
|
||||||
typeof(SampleControlPoint)
|
typeof(SampleControlPoint)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Taiko.Audio
|
|||||||
foreach (var s in samplePoints)
|
foreach (var s in samplePoints)
|
||||||
{
|
{
|
||||||
var centre = s.GetSampleInfo();
|
var centre = s.GetSampleInfo();
|
||||||
var rim = s.GetSampleInfo(SampleInfo.HIT_CLAP);
|
var rim = s.GetSampleInfo(HitSampleInfo.HIT_CLAP);
|
||||||
|
|
||||||
// todo: this is ugly
|
// todo: this is ugly
|
||||||
centre.Namespace = "taiko";
|
centre.Namespace = "taiko";
|
||||||
@ -43,9 +43,9 @@ namespace osu.Game.Rulesets.Taiko.Audio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SkinnableSound addSound(SampleInfo sampleInfo)
|
private SkinnableSound addSound(HitSampleInfo hitSampleInfo)
|
||||||
{
|
{
|
||||||
var drawable = new SkinnableSound(sampleInfo);
|
var drawable = new SkinnableSound(hitSampleInfo);
|
||||||
Sounds.Add(drawable);
|
Sounds.Add(drawable);
|
||||||
return drawable;
|
return drawable;
|
||||||
}
|
}
|
||||||
|
@ -79,9 +79,9 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
var curveData = obj as IHasCurve;
|
var curveData = obj as IHasCurve;
|
||||||
|
|
||||||
// Old osu! used hit sounding to determine various hit type information
|
// Old osu! used hit sounding to determine various hit type information
|
||||||
List<SampleInfo> samples = obj.Samples;
|
List<HitSampleInfo> samples = obj.Samples;
|
||||||
|
|
||||||
bool strong = samples.Any(s => s.Name == SampleInfo.HIT_FINISH);
|
bool strong = samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH);
|
||||||
|
|
||||||
if (distanceData != null)
|
if (distanceData != null)
|
||||||
{
|
{
|
||||||
@ -117,15 +117,15 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
|
|
||||||
if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength)
|
if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength)
|
||||||
{
|
{
|
||||||
List<List<SampleInfo>> allSamples = curveData != null ? curveData.NodeSamples : new List<List<SampleInfo>>(new[] { samples });
|
List<List<HitSampleInfo>> allSamples = curveData != null ? curveData.NodeSamples : new List<List<HitSampleInfo>>(new[] { samples });
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing)
|
for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing)
|
||||||
{
|
{
|
||||||
List<SampleInfo> currentSamples = allSamples[i];
|
List<HitSampleInfo> currentSamples = allSamples[i];
|
||||||
bool isRim = currentSamples.Any(s => s.Name == SampleInfo.HIT_CLAP || s.Name == SampleInfo.HIT_WHISTLE);
|
bool isRim = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE);
|
||||||
strong = currentSamples.Any(s => s.Name == SampleInfo.HIT_FINISH);
|
strong = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_FINISH);
|
||||||
|
|
||||||
if (isRim)
|
if (isRim)
|
||||||
{
|
{
|
||||||
@ -175,7 +175,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool isRim = samples.Any(s => s.Name == SampleInfo.HIT_CLAP || s.Name == SampleInfo.HIT_WHISTLE);
|
bool isRim = samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE);
|
||||||
|
|
||||||
if (isRim)
|
if (isRim)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normal and clap samples are handled by the drum
|
// Normal and clap samples are handled by the drum
|
||||||
protected override IEnumerable<SampleInfo> GetSamples() => HitObject.Samples.Where(s => s.Name != SampleInfo.HIT_NORMAL && s.Name != SampleInfo.HIT_CLAP);
|
protected override IEnumerable<HitSampleInfo> GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP);
|
||||||
|
|
||||||
protected override string SampleNamespace => "Taiko";
|
protected override string SampleNamespace => "Taiko";
|
||||||
|
|
||||||
|
@ -354,14 +354,14 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
Assert.IsNotNull(curveData);
|
Assert.IsNotNull(curveData);
|
||||||
Assert.AreEqual(new Vector2(192, 168), positionData.Position);
|
Assert.AreEqual(new Vector2(192, 168), positionData.Position);
|
||||||
Assert.AreEqual(956, hitObjects[0].StartTime);
|
Assert.AreEqual(956, hitObjects[0].StartTime);
|
||||||
Assert.IsTrue(hitObjects[0].Samples.Any(s => s.Name == SampleInfo.HIT_NORMAL));
|
Assert.IsTrue(hitObjects[0].Samples.Any(s => s.Name == HitSampleInfo.HIT_NORMAL));
|
||||||
|
|
||||||
positionData = hitObjects[1] as IHasPosition;
|
positionData = hitObjects[1] as IHasPosition;
|
||||||
|
|
||||||
Assert.IsNotNull(positionData);
|
Assert.IsNotNull(positionData);
|
||||||
Assert.AreEqual(new Vector2(304, 56), positionData.Position);
|
Assert.AreEqual(new Vector2(304, 56), positionData.Position);
|
||||||
Assert.AreEqual(1285, hitObjects[1].StartTime);
|
Assert.AreEqual(1285, hitObjects[1].StartTime);
|
||||||
Assert.IsTrue(hitObjects[1].Samples.Any(s => s.Name == SampleInfo.HIT_CLAP));
|
Assert.IsTrue(hitObjects[1].Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,7 +384,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
Assert.AreEqual("soft-hitnormal8", getTestableSampleInfo(hitObjects[4]).LookupNames.First());
|
Assert.AreEqual("soft-hitnormal8", getTestableSampleInfo(hitObjects[4]).LookupNames.First());
|
||||||
}
|
}
|
||||||
|
|
||||||
SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]);
|
HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -402,7 +402,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
Assert.AreEqual("normal-hitnormal3", getTestableSampleInfo(hitObjects[2]).LookupNames.First());
|
Assert.AreEqual("normal-hitnormal3", getTestableSampleInfo(hitObjects[2]).LookupNames.First());
|
||||||
}
|
}
|
||||||
|
|
||||||
SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]);
|
HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -422,7 +422,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
Assert.AreEqual(70, getTestableSampleInfo(hitObjects[3]).Volume);
|
Assert.AreEqual(70, getTestableSampleInfo(hitObjects[3]).Volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]);
|
HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -438,34 +438,34 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
var slider1 = (ConvertSlider)hitObjects[0];
|
var slider1 = (ConvertSlider)hitObjects[0];
|
||||||
|
|
||||||
Assert.AreEqual(1, slider1.NodeSamples[0].Count);
|
Assert.AreEqual(1, slider1.NodeSamples[0].Count);
|
||||||
Assert.AreEqual(SampleInfo.HIT_NORMAL, slider1.NodeSamples[0][0].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider1.NodeSamples[0][0].Name);
|
||||||
Assert.AreEqual(1, slider1.NodeSamples[1].Count);
|
Assert.AreEqual(1, slider1.NodeSamples[1].Count);
|
||||||
Assert.AreEqual(SampleInfo.HIT_NORMAL, slider1.NodeSamples[1][0].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider1.NodeSamples[1][0].Name);
|
||||||
Assert.AreEqual(1, slider1.NodeSamples[2].Count);
|
Assert.AreEqual(1, slider1.NodeSamples[2].Count);
|
||||||
Assert.AreEqual(SampleInfo.HIT_NORMAL, slider1.NodeSamples[2][0].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider1.NodeSamples[2][0].Name);
|
||||||
|
|
||||||
var slider2 = (ConvertSlider)hitObjects[1];
|
var slider2 = (ConvertSlider)hitObjects[1];
|
||||||
|
|
||||||
Assert.AreEqual(2, slider2.NodeSamples[0].Count);
|
Assert.AreEqual(2, slider2.NodeSamples[0].Count);
|
||||||
Assert.AreEqual(SampleInfo.HIT_NORMAL, slider2.NodeSamples[0][0].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider2.NodeSamples[0][0].Name);
|
||||||
Assert.AreEqual(SampleInfo.HIT_CLAP, slider2.NodeSamples[0][1].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_CLAP, slider2.NodeSamples[0][1].Name);
|
||||||
Assert.AreEqual(2, slider2.NodeSamples[1].Count);
|
Assert.AreEqual(2, slider2.NodeSamples[1].Count);
|
||||||
Assert.AreEqual(SampleInfo.HIT_NORMAL, slider2.NodeSamples[1][0].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider2.NodeSamples[1][0].Name);
|
||||||
Assert.AreEqual(SampleInfo.HIT_CLAP, slider2.NodeSamples[1][1].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_CLAP, slider2.NodeSamples[1][1].Name);
|
||||||
Assert.AreEqual(2, slider2.NodeSamples[2].Count);
|
Assert.AreEqual(2, slider2.NodeSamples[2].Count);
|
||||||
Assert.AreEqual(SampleInfo.HIT_NORMAL, slider2.NodeSamples[2][0].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider2.NodeSamples[2][0].Name);
|
||||||
Assert.AreEqual(SampleInfo.HIT_CLAP, slider2.NodeSamples[2][1].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_CLAP, slider2.NodeSamples[2][1].Name);
|
||||||
|
|
||||||
var slider3 = (ConvertSlider)hitObjects[2];
|
var slider3 = (ConvertSlider)hitObjects[2];
|
||||||
|
|
||||||
Assert.AreEqual(2, slider3.NodeSamples[0].Count);
|
Assert.AreEqual(2, slider3.NodeSamples[0].Count);
|
||||||
Assert.AreEqual(SampleInfo.HIT_NORMAL, slider3.NodeSamples[0][0].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider3.NodeSamples[0][0].Name);
|
||||||
Assert.AreEqual(SampleInfo.HIT_WHISTLE, slider3.NodeSamples[0][1].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_WHISTLE, slider3.NodeSamples[0][1].Name);
|
||||||
Assert.AreEqual(1, slider3.NodeSamples[1].Count);
|
Assert.AreEqual(1, slider3.NodeSamples[1].Count);
|
||||||
Assert.AreEqual(SampleInfo.HIT_NORMAL, slider3.NodeSamples[1][0].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider3.NodeSamples[1][0].Name);
|
||||||
Assert.AreEqual(2, slider3.NodeSamples[2].Count);
|
Assert.AreEqual(2, slider3.NodeSamples[2].Count);
|
||||||
Assert.AreEqual(SampleInfo.HIT_NORMAL, slider3.NodeSamples[2][0].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_NORMAL, slider3.NodeSamples[2][0].Name);
|
||||||
Assert.AreEqual(SampleInfo.HIT_CLAP, slider3.NodeSamples[2][1].Name);
|
Assert.AreEqual(HitSampleInfo.HIT_CLAP, slider3.NodeSamples[2][1].Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,14 +101,14 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
Assert.IsNotNull(curveData);
|
Assert.IsNotNull(curveData);
|
||||||
Assert.AreEqual(new Vector2(192, 168), positionData.Position);
|
Assert.AreEqual(new Vector2(192, 168), positionData.Position);
|
||||||
Assert.AreEqual(956, beatmap.HitObjects[0].StartTime);
|
Assert.AreEqual(956, beatmap.HitObjects[0].StartTime);
|
||||||
Assert.IsTrue(beatmap.HitObjects[0].Samples.Any(s => s.Name == SampleInfo.HIT_NORMAL));
|
Assert.IsTrue(beatmap.HitObjects[0].Samples.Any(s => s.Name == HitSampleInfo.HIT_NORMAL));
|
||||||
|
|
||||||
positionData = beatmap.HitObjects[1] as IHasPosition;
|
positionData = beatmap.HitObjects[1] as IHasPosition;
|
||||||
|
|
||||||
Assert.IsNotNull(positionData);
|
Assert.IsNotNull(positionData);
|
||||||
Assert.AreEqual(new Vector2(304, 56), positionData.Position);
|
Assert.AreEqual(new Vector2(304, 56), positionData.Position);
|
||||||
Assert.AreEqual(1285, beatmap.HitObjects[1].StartTime);
|
Assert.AreEqual(1285, beatmap.HitObjects[1].StartTime);
|
||||||
Assert.IsTrue(beatmap.HitObjects[1].Samples.Any(s => s.Name == SampleInfo.HIT_CLAP));
|
Assert.IsTrue(beatmap.HitObjects[1].Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(normal)]
|
[TestCase(normal)]
|
||||||
|
70
osu.Game/Audio/HitSampleInfo.cs
Normal file
70
osu.Game/Audio/HitSampleInfo.cs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// 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 System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Audio
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Describes a gameplay hit sample.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class HitSampleInfo : ISampleInfo
|
||||||
|
{
|
||||||
|
public const string HIT_WHISTLE = @"hitwhistle";
|
||||||
|
public const string HIT_FINISH = @"hitfinish";
|
||||||
|
public const string HIT_NORMAL = @"hitnormal";
|
||||||
|
public const string HIT_CLAP = @"hitclap";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An optional ruleset namespace.
|
||||||
|
/// </summary>
|
||||||
|
public string Namespace;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The bank to load the sample from.
|
||||||
|
/// </summary>
|
||||||
|
public string Bank;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the sample to load.
|
||||||
|
/// </summary>
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An optional suffix to provide priority lookup. Falls back to non-suffixed <see cref="Name"/>.
|
||||||
|
/// </summary>
|
||||||
|
public string Suffix;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sample volume.
|
||||||
|
/// </summary>
|
||||||
|
public int Volume { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first).
|
||||||
|
/// </summary>
|
||||||
|
public virtual IEnumerable<string> LookupNames
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(Namespace))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(Suffix))
|
||||||
|
yield return $"{Namespace}/{Bank}-{Name}{Suffix}";
|
||||||
|
|
||||||
|
yield return $"{Namespace}/{Bank}-{Name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// check non-namespace as a fallback even when we have a namespace
|
||||||
|
if (!string.IsNullOrEmpty(Suffix))
|
||||||
|
yield return $"{Bank}-{Name}{Suffix}";
|
||||||
|
|
||||||
|
yield return $"{Bank}-{Name}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HitSampleInfo Clone() => (HitSampleInfo)MemberwiseClone();
|
||||||
|
}
|
||||||
|
}
|
17
osu.Game/Audio/ISampleInfo.cs
Normal file
17
osu.Game/Audio/ISampleInfo.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Audio
|
||||||
|
{
|
||||||
|
public interface ISampleInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first).
|
||||||
|
/// </summary>
|
||||||
|
IEnumerable<string> LookupNames { get; }
|
||||||
|
|
||||||
|
int Volume { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,67 +1,24 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace osu.Game.Audio
|
namespace osu.Game.Audio
|
||||||
{
|
{
|
||||||
[Serializable]
|
/// <summary>
|
||||||
public class SampleInfo
|
/// Describes a gameplay sample.
|
||||||
|
/// </summary>
|
||||||
|
public class SampleInfo : ISampleInfo
|
||||||
{
|
{
|
||||||
public const string HIT_WHISTLE = @"hitwhistle";
|
private readonly string sampleName;
|
||||||
public const string HIT_FINISH = @"hitfinish";
|
|
||||||
public const string HIT_NORMAL = @"hitnormal";
|
|
||||||
public const string HIT_CLAP = @"hitclap";
|
|
||||||
|
|
||||||
/// <summary>
|
public SampleInfo(string sampleName)
|
||||||
/// An optional ruleset namespace.
|
|
||||||
/// </summary>
|
|
||||||
public string Namespace;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The bank to load the sample from.
|
|
||||||
/// </summary>
|
|
||||||
public string Bank;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The name of the sample to load.
|
|
||||||
/// </summary>
|
|
||||||
public string Name;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An optional suffix to provide priority lookup. Falls back to non-suffixed <see cref="Name"/>.
|
|
||||||
/// </summary>
|
|
||||||
public string Suffix;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The sample volume.
|
|
||||||
/// </summary>
|
|
||||||
public int Volume;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieve all possible filenames that can be used as a source, returned in order of preference (highest first).
|
|
||||||
/// </summary>
|
|
||||||
public virtual IEnumerable<string> LookupNames
|
|
||||||
{
|
{
|
||||||
get
|
this.sampleName = sampleName;
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(Namespace))
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(Suffix))
|
|
||||||
yield return $"{Namespace}/{Bank}-{Name}{Suffix}";
|
|
||||||
|
|
||||||
yield return $"{Namespace}/{Bank}-{Name}";
|
|
||||||
}
|
|
||||||
|
|
||||||
// check non-namespace as a fallback even when we have a namespace
|
|
||||||
if (!string.IsNullOrEmpty(Suffix))
|
|
||||||
yield return $"{Bank}-{Name}{Suffix}";
|
|
||||||
|
|
||||||
yield return $"{Bank}-{Name}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SampleInfo Clone() => (SampleInfo)MemberwiseClone();
|
public IEnumerable<string> LookupNames => new[] { sampleName };
|
||||||
|
|
||||||
|
public int Volume { get; set; } = 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
/// Create a SampleInfo based on the sample settings in this control point.
|
/// Create a SampleInfo based on the sample settings in this control point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sampleName">The name of the same.</param>
|
/// <param name="sampleName">The name of the same.</param>
|
||||||
/// <returns>A populated <see cref="SampleInfo"/>.</returns>
|
/// <returns>A populated <see cref="HitSampleInfo"/>.</returns>
|
||||||
public SampleInfo GetSampleInfo(string sampleName = SampleInfo.HIT_NORMAL) => new SampleInfo
|
public HitSampleInfo GetSampleInfo(string sampleName = HitSampleInfo.HIT_NORMAL) => new HitSampleInfo
|
||||||
{
|
{
|
||||||
Bank = SampleBank,
|
Bank = SampleBank,
|
||||||
Name = sampleName,
|
Name = sampleName,
|
||||||
@ -33,15 +33,15 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies <see cref="SampleBank"/> and <see cref="SampleVolume"/> to a <see cref="SampleInfo"/> if necessary, returning the modified <see cref="SampleInfo"/>.
|
/// Applies <see cref="SampleBank"/> and <see cref="SampleVolume"/> to a <see cref="HitSampleInfo"/> if necessary, returning the modified <see cref="HitSampleInfo"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sampleInfo">The <see cref="SampleInfo"/>. This will not be modified.</param>
|
/// <param name="hitSampleInfo">The <see cref="HitSampleInfo"/>. This will not be modified.</param>
|
||||||
/// <returns>The modified <see cref="SampleInfo"/>. This does not share a reference with <paramref name="sampleInfo"/>.</returns>
|
/// <returns>The modified <see cref="HitSampleInfo"/>. This does not share a reference with <paramref name="hitSampleInfo"/>.</returns>
|
||||||
public virtual SampleInfo ApplyTo(SampleInfo sampleInfo)
|
public virtual HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo)
|
||||||
{
|
{
|
||||||
var newSampleInfo = sampleInfo.Clone();
|
var newSampleInfo = hitSampleInfo.Clone();
|
||||||
newSampleInfo.Bank = sampleInfo.Bank ?? SampleBank;
|
newSampleInfo.Bank = hitSampleInfo.Bank ?? SampleBank;
|
||||||
newSampleInfo.Volume = sampleInfo.Volume > 0 ? sampleInfo.Volume : SampleVolume;
|
newSampleInfo.Volume = hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume;
|
||||||
return newSampleInfo;
|
return newSampleInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,9 +193,9 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
{
|
{
|
||||||
public int CustomSampleBank;
|
public int CustomSampleBank;
|
||||||
|
|
||||||
public override SampleInfo ApplyTo(SampleInfo sampleInfo)
|
public override HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo)
|
||||||
{
|
{
|
||||||
var baseInfo = base.ApplyTo(sampleInfo);
|
var baseInfo = base.ApplyTo(hitSampleInfo);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(baseInfo.Suffix) && CustomSampleBank > 1)
|
if (string.IsNullOrEmpty(baseInfo.Suffix) && CustomSampleBank > 1)
|
||||||
baseInfo.Suffix = CustomSampleBank.ToString();
|
baseInfo.Suffix = CustomSampleBank.ToString();
|
||||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
|
|
||||||
protected SkinnableSound Samples;
|
protected SkinnableSound Samples;
|
||||||
|
|
||||||
protected virtual IEnumerable<SampleInfo> GetSamples() => HitObject.Samples;
|
protected virtual IEnumerable<HitSampleInfo> GetSamples() => HitObject.Samples;
|
||||||
|
|
||||||
private readonly Lazy<List<DrawableHitObject>> nestedHitObjects = new Lazy<List<DrawableHitObject>>();
|
private readonly Lazy<List<DrawableHitObject>> nestedHitObjects = new Lazy<List<DrawableHitObject>>();
|
||||||
public IEnumerable<DrawableHitObject> NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : Enumerable.Empty<DrawableHitObject>();
|
public IEnumerable<DrawableHitObject> NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : Enumerable.Empty<DrawableHitObject>();
|
||||||
@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
|
|
||||||
var samples = GetSamples().ToArray();
|
var samples = GetSamples().ToArray();
|
||||||
|
|
||||||
if (samples.Any())
|
if (samples.Length > 0)
|
||||||
{
|
{
|
||||||
if (HitObject.SampleControlPoint == null)
|
if (HitObject.SampleControlPoint == null)
|
||||||
throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}."
|
throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}."
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual double StartTime { get; set; }
|
public virtual double StartTime { get; set; }
|
||||||
|
|
||||||
private List<SampleInfo> samples;
|
private List<HitSampleInfo> samples;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The samples to be played when this hit object is hit.
|
/// The samples to be played when this hit object is hit.
|
||||||
@ -38,9 +38,9 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
/// and can be treated as the default samples for the hit object.
|
/// and can be treated as the default samples for the hit object.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<SampleInfo> Samples
|
public List<HitSampleInfo> Samples
|
||||||
{
|
{
|
||||||
get => samples ?? (samples = new List<SampleInfo>());
|
get => samples ?? (samples = new List<HitSampleInfo>());
|
||||||
set => samples = value;
|
set => samples = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<SampleInfo>> nodeSamples)
|
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples)
|
||||||
{
|
{
|
||||||
newCombo |= forceNewCombo;
|
newCombo |= forceNewCombo;
|
||||||
comboOffset += extraComboOffset;
|
comboOffset += extraComboOffset;
|
||||||
|
@ -180,7 +180,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate the final per-node samples
|
// Generate the final per-node samples
|
||||||
var nodeSamples = new List<List<SampleInfo>>(nodes);
|
var nodeSamples = new List<List<HitSampleInfo>>(nodes);
|
||||||
for (int i = 0; i < nodes; i++)
|
for (int i = 0; i < nodes; i++)
|
||||||
nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i]));
|
nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i]));
|
||||||
|
|
||||||
@ -291,7 +291,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
/// <param name="repeatCount">The slider repeat count.</param>
|
/// <param name="repeatCount">The slider repeat count.</param>
|
||||||
/// <param name="nodeSamples">The samples to be played when the slider nodes are hit. This includes the head and tail of the slider.</param>
|
/// <param name="nodeSamples">The samples to be played when the slider nodes are hit. This includes the head and tail of the slider.</param>
|
||||||
/// <returns>The hit object.</returns>
|
/// <returns>The hit object.</returns>
|
||||||
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<SampleInfo>> nodeSamples);
|
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a legacy Spinner-type hit object.
|
/// Creates a legacy Spinner-type hit object.
|
||||||
@ -312,14 +312,14 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
/// <param name="endTime">The hold end time.</param>
|
/// <param name="endTime">The hold end time.</param>
|
||||||
protected abstract HitObject CreateHold(Vector2 position, bool newCombo, int comboOffset, double endTime);
|
protected abstract HitObject CreateHold(Vector2 position, bool newCombo, int comboOffset, double endTime);
|
||||||
|
|
||||||
private List<SampleInfo> convertSoundType(LegacySoundType type, SampleBankInfo bankInfo)
|
private List<HitSampleInfo> convertSoundType(LegacySoundType type, SampleBankInfo bankInfo)
|
||||||
{
|
{
|
||||||
// Todo: This should return the normal SampleInfos if the specified sample file isn't found, but that's a pretty edge-case scenario
|
// Todo: This should return the normal SampleInfos if the specified sample file isn't found, but that's a pretty edge-case scenario
|
||||||
if (!string.IsNullOrEmpty(bankInfo.Filename))
|
if (!string.IsNullOrEmpty(bankInfo.Filename))
|
||||||
{
|
{
|
||||||
return new List<SampleInfo>
|
return new List<HitSampleInfo>
|
||||||
{
|
{
|
||||||
new FileSampleInfo
|
new FileHitSampleInfo
|
||||||
{
|
{
|
||||||
Filename = bankInfo.Filename,
|
Filename = bankInfo.Filename,
|
||||||
Volume = bankInfo.Volume
|
Volume = bankInfo.Volume
|
||||||
@ -327,12 +327,12 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var soundTypes = new List<SampleInfo>
|
var soundTypes = new List<HitSampleInfo>
|
||||||
{
|
{
|
||||||
new LegacySampleInfo
|
new LegacyHitSampleInfo
|
||||||
{
|
{
|
||||||
Bank = bankInfo.Normal,
|
Bank = bankInfo.Normal,
|
||||||
Name = SampleInfo.HIT_NORMAL,
|
Name = HitSampleInfo.HIT_NORMAL,
|
||||||
Volume = bankInfo.Volume,
|
Volume = bankInfo.Volume,
|
||||||
CustomSampleBank = bankInfo.CustomSampleBank
|
CustomSampleBank = bankInfo.CustomSampleBank
|
||||||
}
|
}
|
||||||
@ -340,10 +340,10 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
if (type.HasFlag(LegacySoundType.Finish))
|
if (type.HasFlag(LegacySoundType.Finish))
|
||||||
{
|
{
|
||||||
soundTypes.Add(new LegacySampleInfo
|
soundTypes.Add(new LegacyHitSampleInfo
|
||||||
{
|
{
|
||||||
Bank = bankInfo.Add,
|
Bank = bankInfo.Add,
|
||||||
Name = SampleInfo.HIT_FINISH,
|
Name = HitSampleInfo.HIT_FINISH,
|
||||||
Volume = bankInfo.Volume,
|
Volume = bankInfo.Volume,
|
||||||
CustomSampleBank = bankInfo.CustomSampleBank
|
CustomSampleBank = bankInfo.CustomSampleBank
|
||||||
});
|
});
|
||||||
@ -351,10 +351,10 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
if (type.HasFlag(LegacySoundType.Whistle))
|
if (type.HasFlag(LegacySoundType.Whistle))
|
||||||
{
|
{
|
||||||
soundTypes.Add(new LegacySampleInfo
|
soundTypes.Add(new LegacyHitSampleInfo
|
||||||
{
|
{
|
||||||
Bank = bankInfo.Add,
|
Bank = bankInfo.Add,
|
||||||
Name = SampleInfo.HIT_WHISTLE,
|
Name = HitSampleInfo.HIT_WHISTLE,
|
||||||
Volume = bankInfo.Volume,
|
Volume = bankInfo.Volume,
|
||||||
CustomSampleBank = bankInfo.CustomSampleBank
|
CustomSampleBank = bankInfo.CustomSampleBank
|
||||||
});
|
});
|
||||||
@ -362,10 +362,10 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
if (type.HasFlag(LegacySoundType.Clap))
|
if (type.HasFlag(LegacySoundType.Clap))
|
||||||
{
|
{
|
||||||
soundTypes.Add(new LegacySampleInfo
|
soundTypes.Add(new LegacyHitSampleInfo
|
||||||
{
|
{
|
||||||
Bank = bankInfo.Add,
|
Bank = bankInfo.Add,
|
||||||
Name = SampleInfo.HIT_CLAP,
|
Name = HitSampleInfo.HIT_CLAP,
|
||||||
Volume = bankInfo.Volume,
|
Volume = bankInfo.Volume,
|
||||||
CustomSampleBank = bankInfo.CustomSampleBank
|
CustomSampleBank = bankInfo.CustomSampleBank
|
||||||
});
|
});
|
||||||
@ -387,7 +387,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
public SampleBankInfo Clone() => (SampleBankInfo)MemberwiseClone();
|
public SampleBankInfo Clone() => (SampleBankInfo)MemberwiseClone();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LegacySampleInfo : SampleInfo
|
private class LegacyHitSampleInfo : HitSampleInfo
|
||||||
{
|
{
|
||||||
public int CustomSampleBank
|
public int CustomSampleBank
|
||||||
{
|
{
|
||||||
@ -399,7 +399,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FileSampleInfo : SampleInfo
|
private class FileHitSampleInfo : HitSampleInfo
|
||||||
{
|
{
|
||||||
public string Filename;
|
public string Filename;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
|
|
||||||
public double Distance => Path.Distance;
|
public double Distance => Path.Distance;
|
||||||
|
|
||||||
public List<List<SampleInfo>> NodeSamples { get; set; }
|
public List<List<HitSampleInfo>> NodeSamples { get; set; }
|
||||||
public int RepeatCount { get; set; }
|
public int RepeatCount { get; set; }
|
||||||
|
|
||||||
public double EndTime => StartTime + this.SpanCount() * Distance / Velocity;
|
public double EndTime => StartTime + this.SpanCount() * Distance / Velocity;
|
||||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<SampleInfo>> nodeSamples)
|
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples)
|
||||||
{
|
{
|
||||||
return new ConvertSlider
|
return new ConvertSlider
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<SampleInfo>> nodeSamples)
|
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples)
|
||||||
{
|
{
|
||||||
newCombo |= forceNewCombo;
|
newCombo |= forceNewCombo;
|
||||||
comboOffset += extraComboOffset;
|
comboOffset += extraComboOffset;
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
|
|||||||
return new ConvertHit();
|
return new ConvertHit();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<SampleInfo>> nodeSamples)
|
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List<List<HitSampleInfo>> nodeSamples)
|
||||||
{
|
{
|
||||||
return new ConvertSlider
|
return new ConvertSlider
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Objects.Types
|
|||||||
/// n-1: The last repeat.<br />
|
/// n-1: The last repeat.<br />
|
||||||
/// n: The last node.
|
/// n: The last node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<List<SampleInfo>> NodeSamples { get; }
|
List<List<HitSampleInfo>> NodeSamples { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HasRepeatsExtensions
|
public static class HasRepeatsExtensions
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
|
||||||
using osu.Framework.Audio.Sample;
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Audio;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
@ -13,23 +12,31 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
public class ComboEffects : CompositeDrawable
|
public class ComboEffects : CompositeDrawable
|
||||||
{
|
{
|
||||||
private SampleChannel sampleComboBreak;
|
private readonly ScoreProcessor processor;
|
||||||
|
|
||||||
|
private SkinnableSound comboBreakSample;
|
||||||
|
|
||||||
public ComboEffects(ScoreProcessor processor)
|
public ComboEffects(ScoreProcessor processor)
|
||||||
{
|
{
|
||||||
processor.Combo.BindValueChanged(onComboChange);
|
this.processor = processor;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChild = comboBreakSample = new SkinnableSound(new SampleInfo("combobreak"));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
processor.Combo.BindValueChanged(onComboChange, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onComboChange(ValueChangedEvent<int> combo)
|
private void onComboChange(ValueChangedEvent<int> combo)
|
||||||
{
|
{
|
||||||
if (combo.NewValue == 0 && combo.OldValue > 20)
|
if (combo.NewValue == 0 && combo.OldValue > 20)
|
||||||
sampleComboBreak?.Play();
|
comboBreakSample?.Play();
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(ISkinSource skin, AudioManager audio)
|
|
||||||
{
|
|
||||||
sampleComboBreak = skin.GetSample(@"Gameplay/combobreak") ?? audio.Samples.Get(@"Gameplay/combobreak");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
@ -13,14 +14,19 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
public class SkinnableSound : SkinReloadableDrawable
|
public class SkinnableSound : SkinReloadableDrawable
|
||||||
{
|
{
|
||||||
private readonly SampleInfo[] samples;
|
private readonly ISampleInfo[] hitSamples;
|
||||||
private SampleChannel[] channels;
|
private SampleChannel[] channels;
|
||||||
|
|
||||||
private AudioManager audio;
|
private AudioManager audio;
|
||||||
|
|
||||||
public SkinnableSound(params SampleInfo[] samples)
|
public SkinnableSound(IEnumerable<ISampleInfo> hitSamples)
|
||||||
{
|
{
|
||||||
this.samples = samples;
|
this.hitSamples = hitSamples.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinnableSound(ISampleInfo hitSamples)
|
||||||
|
{
|
||||||
|
this.hitSamples = new[] { hitSamples };
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -35,7 +41,7 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||||
{
|
{
|
||||||
channels = samples.Select(s =>
|
channels = hitSamples.Select(s =>
|
||||||
{
|
{
|
||||||
var ch = loadChannel(s, skin.GetSample);
|
var ch = loadChannel(s, skin.GetSample);
|
||||||
if (ch == null && allowFallback)
|
if (ch == null && allowFallback)
|
||||||
@ -44,7 +50,7 @@ namespace osu.Game.Skinning
|
|||||||
}).Where(c => c != null).ToArray();
|
}).Where(c => c != null).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleChannel loadChannel(SampleInfo info, Func<string, SampleChannel> getSampleFunction)
|
private SampleChannel loadChannel(ISampleInfo info, Func<string, SampleChannel> getSampleFunction)
|
||||||
{
|
{
|
||||||
foreach (var lookup in info.LookupNames)
|
foreach (var lookup in info.LookupNames)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user