mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 10:33:30 +08:00
Replace TimeSignatures
enum with struct for storage of arbitrary meter
This commit is contained in:
parent
ccac7b85be
commit
735414bc49
@ -153,7 +153,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default
|
||||
if (!effectPoint.KiaiMode)
|
||||
return;
|
||||
|
||||
if (beatIndex % (int)timingPoint.TimeSignature != 0)
|
||||
if (beatIndex % timingPoint.TimeSignature.Numerator != 0)
|
||||
return;
|
||||
|
||||
double duration = timingPoint.BeatLength * 2;
|
||||
|
@ -178,17 +178,17 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
var timingPoint = controlPoints.TimingPointAt(0);
|
||||
Assert.AreEqual(956, timingPoint.Time);
|
||||
Assert.AreEqual(329.67032967033, timingPoint.BeatLength);
|
||||
Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature);
|
||||
Assert.AreEqual(TimeSignature.SimpleQuadruple, timingPoint.TimeSignature);
|
||||
|
||||
timingPoint = controlPoints.TimingPointAt(48428);
|
||||
Assert.AreEqual(956, timingPoint.Time);
|
||||
Assert.AreEqual(329.67032967033d, timingPoint.BeatLength);
|
||||
Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature);
|
||||
Assert.AreEqual(TimeSignature.SimpleQuadruple, timingPoint.TimeSignature);
|
||||
|
||||
timingPoint = controlPoints.TimingPointAt(119637);
|
||||
Assert.AreEqual(119637, timingPoint.Time);
|
||||
Assert.AreEqual(659.340659340659, timingPoint.BeatLength);
|
||||
Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature);
|
||||
Assert.AreEqual(TimeSignature.SimpleQuadruple, timingPoint.TimeSignature);
|
||||
|
||||
var difficultyPoint = controlPoints.DifficultyPointAt(0);
|
||||
Assert.AreEqual(0, difficultyPoint.Time);
|
||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Tests.NonVisual
|
||||
|
||||
const int beat_length_numerator = 2000;
|
||||
const int beat_length_denominator = 7;
|
||||
const TimeSignatures signature = TimeSignatures.SimpleQuadruple;
|
||||
TimeSignature signature = TimeSignature.SimpleQuadruple;
|
||||
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
@ -49,7 +49,7 @@ namespace osu.Game.Tests.NonVisual
|
||||
for (int i = 0; i * beat_length_denominator < barLines.Count; i++)
|
||||
{
|
||||
var barLine = barLines[i * beat_length_denominator];
|
||||
int expectedTime = beat_length_numerator * (int)signature * i;
|
||||
int expectedTime = beat_length_numerator * signature.Numerator * i;
|
||||
|
||||
// every seventh bar's start time should be at least greater than the whole number we expect.
|
||||
// It cannot be less, as that can affect overlapping scroll algorithms
|
||||
@ -60,7 +60,7 @@ namespace osu.Game.Tests.NonVisual
|
||||
Assert.IsTrue(Precision.AlmostEquals(barLine.StartTime, expectedTime));
|
||||
|
||||
// check major/minor lines for good measure too
|
||||
Assert.AreEqual(i % (int)signature == 0, barLine.Major);
|
||||
Assert.AreEqual(i % signature.Numerator == 0, barLine.Major);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
Add(new ModNightcore<HitObject>.NightcoreBeatContainer());
|
||||
|
||||
AddStep("change signature to quadruple", () => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ForEach(p => p.TimeSignature = TimeSignatures.SimpleQuadruple));
|
||||
AddStep("change signature to triple", () => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ForEach(p => p.TimeSignature = TimeSignatures.SimpleTriple));
|
||||
AddStep("change signature to quadruple", () => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ForEach(p => p.TimeSignature = TimeSignature.SimpleQuadruple));
|
||||
AddStep("change signature to triple", () => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ForEach(p => p.TimeSignature = TimeSignature.SimpleTriple));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
/// <summary>
|
||||
/// The time signature at this control point.
|
||||
/// </summary>
|
||||
public readonly Bindable<TimeSignatures> TimeSignatureBindable = new Bindable<TimeSignatures>(TimeSignatures.SimpleQuadruple) { Default = TimeSignatures.SimpleQuadruple };
|
||||
public readonly Bindable<TimeSignature> TimeSignatureBindable = new Bindable<TimeSignature>(TimeSignature.SimpleQuadruple);
|
||||
|
||||
/// <summary>
|
||||
/// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing.
|
||||
@ -35,7 +35,7 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
/// <summary>
|
||||
/// The time signature at this control point.
|
||||
/// </summary>
|
||||
public TimeSignatures TimeSignature
|
||||
public TimeSignature TimeSignature
|
||||
{
|
||||
get => TimeSignatureBindable.Value;
|
||||
set => TimeSignatureBindable.Value = value;
|
||||
|
@ -340,9 +340,9 @@ namespace osu.Game.Beatmaps.Formats
|
||||
double beatLength = Parsing.ParseDouble(split[1].Trim());
|
||||
double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1;
|
||||
|
||||
TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple;
|
||||
TimeSignature timeSignature = TimeSignature.SimpleQuadruple;
|
||||
if (split.Length >= 3)
|
||||
timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)Parsing.ParseInt(split[2]);
|
||||
timeSignature = split[2][0] == '0' ? TimeSignature.SimpleQuadruple : new TimeSignature(Parsing.ParseInt(split[2]));
|
||||
|
||||
LegacySampleBank sampleSet = defaultSampleBank;
|
||||
if (split.Length >= 4)
|
||||
|
@ -227,7 +227,7 @@ namespace osu.Game.Beatmaps.Formats
|
||||
if (effectPoint.OmitFirstBarLine)
|
||||
effectFlags |= LegacyEffectFlags.OmitFirstBarLine;
|
||||
|
||||
writer.Write(FormattableString.Invariant($"{(int)legacyControlPoints.TimingPointAt(time).TimeSignature},"));
|
||||
writer.Write(FormattableString.Invariant($"{legacyControlPoints.TimingPointAt(time).TimeSignature.Numerator},"));
|
||||
writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},"));
|
||||
writer.Write(FormattableString.Invariant($"{toLegacyCustomSampleBank(tempHitSample)},"));
|
||||
writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},"));
|
||||
|
45
osu.Game/Beatmaps/Timing/TimeSignature.cs
Normal file
45
osu.Game/Beatmaps/Timing/TimeSignature.cs
Normal file
@ -0,0 +1,45 @@
|
||||
// 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;
|
||||
|
||||
namespace osu.Game.Beatmaps.Timing
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores the time signature of a track.
|
||||
/// For now, the lower numeral can only be 4; support for other denominators can be considered at a later date.
|
||||
/// </summary>
|
||||
public class TimeSignature : IEquatable<TimeSignature>
|
||||
{
|
||||
/// <summary>
|
||||
/// The numerator of a signature.
|
||||
/// </summary>
|
||||
public int Numerator { get; }
|
||||
|
||||
// TODO: support time signatures with a denominator other than 4
|
||||
// this in particular requires a new beatmap format.
|
||||
|
||||
public TimeSignature(int numerator)
|
||||
{
|
||||
if (numerator < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(numerator), numerator, "The numerator of a time signature must be positive.");
|
||||
|
||||
Numerator = numerator;
|
||||
}
|
||||
|
||||
public static TimeSignature SimpleTriple => new TimeSignature(3);
|
||||
public static TimeSignature SimpleQuadruple => new TimeSignature(4);
|
||||
|
||||
public override string ToString() => $"{Numerator}/4";
|
||||
|
||||
public bool Equals(TimeSignature other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return Numerator == other.Numerator;
|
||||
}
|
||||
|
||||
public override int GetHashCode() => Numerator;
|
||||
}
|
||||
}
|
@ -1,11 +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.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace osu.Game.Beatmaps.Timing
|
||||
{
|
||||
public enum TimeSignatures
|
||||
[Obsolete("Use osu.Game.Beatmaps.Timing.TimeSignature instead.")]
|
||||
public enum TimeSignatures // can be removed 20220722
|
||||
{
|
||||
[Description("4/4")]
|
||||
SimpleQuadruple = 4,
|
||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
|
||||
if (!IsBeatSyncedWithTrack) return;
|
||||
|
||||
int timeSignature = (int)timingPoint.TimeSignature;
|
||||
int timeSignature = timingPoint.TimeSignature.Numerator;
|
||||
|
||||
// play metronome from one measure before the first object.
|
||||
if (BeatSyncClock.CurrentTime < firstHitTime - timingPoint.BeatLength * timeSignature)
|
||||
|
@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||
|
||||
int beatsPerBar = (int)timingPoint.TimeSignature;
|
||||
int beatsPerBar = timingPoint.TimeSignature.Numerator;
|
||||
int segmentLength = beatsPerBar * Divisor * bars_per_segment;
|
||||
|
||||
if (!IsBeatSyncedWithTrack)
|
||||
@ -102,14 +102,14 @@ namespace osu.Game.Rulesets.Mods
|
||||
playBeatFor(beatIndex % segmentLength, timingPoint.TimeSignature);
|
||||
}
|
||||
|
||||
private void playBeatFor(int beatIndex, TimeSignatures signature)
|
||||
private void playBeatFor(int beatIndex, TimeSignature signature)
|
||||
{
|
||||
if (beatIndex == 0)
|
||||
finishSample?.Play();
|
||||
|
||||
switch (signature)
|
||||
switch (signature.Numerator)
|
||||
{
|
||||
case TimeSignatures.SimpleTriple:
|
||||
case 3:
|
||||
switch (beatIndex % 6)
|
||||
{
|
||||
case 0:
|
||||
@ -127,7 +127,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
|
||||
break;
|
||||
|
||||
case TimeSignatures.SimpleQuadruple:
|
||||
case 4:
|
||||
switch (beatIndex % 4)
|
||||
{
|
||||
case 0:
|
||||
|
@ -41,9 +41,9 @@ namespace osu.Game.Rulesets.Objects
|
||||
int currentBeat = 0;
|
||||
|
||||
// Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object
|
||||
double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - currentTimingPoint.BeatLength : lastHitTime + currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature;
|
||||
double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - currentTimingPoint.BeatLength : lastHitTime + currentTimingPoint.BeatLength * currentTimingPoint.TimeSignature.Numerator;
|
||||
|
||||
double barLength = currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature;
|
||||
double barLength = currentTimingPoint.BeatLength * currentTimingPoint.TimeSignature.Numerator;
|
||||
|
||||
for (double t = currentTimingPoint.Time; Precision.DefinitelyBigger(endTime, t); t += barLength, currentBeat++)
|
||||
{
|
||||
@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Objects
|
||||
BarLines.Add(new TBarLine
|
||||
{
|
||||
StartTime = t,
|
||||
Major = currentBeat % (int)currentTimingPoint.TimeSignature == 0
|
||||
Major = currentBeat % currentTimingPoint.TimeSignature.Numerator == 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
if (beat == 0 && i == 0)
|
||||
nextMinTick = float.MinValue;
|
||||
|
||||
int indexInBar = beat % ((int)point.TimeSignature * beatDivisor.Value);
|
||||
int indexInBar = beat % (point.TimeSignature.Numerator * beatDivisor.Value);
|
||||
|
||||
int divisor = BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value);
|
||||
var colour = BindableBeatDivisor.GetColourFor(divisor, colours);
|
||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Screens.Edit.Timing.RowAttributes
|
||||
public class TimingRowAttribute : RowAttribute
|
||||
{
|
||||
private readonly BindableNumber<double> beatLength;
|
||||
private readonly Bindable<TimeSignatures> timeSignature;
|
||||
private readonly Bindable<TimeSignature> timeSignature;
|
||||
private OsuSpriteText text;
|
||||
|
||||
public TimingRowAttribute(TimingControlPoint timing)
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
internal class TimingSection : Section<TimingControlPoint>
|
||||
{
|
||||
private SettingsSlider<double> bpmSlider;
|
||||
private SettingsEnumDropdown<TimeSignatures> timeSignature;
|
||||
private SettingsDropdown<TimeSignature> timeSignature;
|
||||
private BPMTextBox bpmTextEntry;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -25,9 +25,14 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
{
|
||||
bpmTextEntry = new BPMTextBox(),
|
||||
bpmSlider = new BPMSlider(),
|
||||
timeSignature = new SettingsEnumDropdown<TimeSignatures>
|
||||
timeSignature = new SettingsDropdown<TimeSignature>
|
||||
{
|
||||
LabelText = "Time Signature"
|
||||
LabelText = "Time Signature",
|
||||
Items = new[]
|
||||
{
|
||||
TimeSignature.SimpleTriple,
|
||||
TimeSignature.SimpleQuadruple
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -94,9 +94,9 @@ namespace osu.Game.Screens.Menu
|
||||
if (beatIndex < 0)
|
||||
return;
|
||||
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 0 : beatIndex % (int)timingPoint.TimeSignature == 0)
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 0 : beatIndex % timingPoint.TimeSignature.Numerator == 0)
|
||||
flash(leftBox, timingPoint.BeatLength, effectPoint.KiaiMode, amplitudes);
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 1 : beatIndex % (int)timingPoint.TimeSignature == 0)
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 1 : beatIndex % timingPoint.TimeSignature.Numerator == 0)
|
||||
flash(rightBox, timingPoint.BeatLength, effectPoint.KiaiMode, amplitudes);
|
||||
}
|
||||
|
||||
|
@ -282,7 +282,7 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
this.Delay(early_activation).Schedule(() =>
|
||||
{
|
||||
if (beatIndex % (int)timingPoint.TimeSignature == 0)
|
||||
if (beatIndex % timingPoint.TimeSignature.Numerator == 0)
|
||||
sampleDownbeat.Play();
|
||||
else
|
||||
sampleBeat.Play();
|
||||
|
Loading…
Reference in New Issue
Block a user