mirror of https://github.com/ppy/osu
Replace BeatDivisorFinder with GetClosestBeatDivisor
This commit is contained in:
parent
ecb053b0de
commit
fdf8c12947
|
@ -6,10 +6,10 @@
|
|||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Default;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens.Edit;
|
||||
|
@ -27,7 +27,7 @@ public class DrawableNote : DrawableManiaHitObject<Note>, IKeyBindingHandler<Man
|
|||
private OsuColour colours { get; set; }
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private BeatDivisorFinder beatDivisorFinder { get; set; }
|
||||
private IBeatmap beatmap { get; set; }
|
||||
|
||||
private readonly Bindable<bool> configTimingBasedNoteColouring = new Bindable<bool>();
|
||||
|
||||
|
@ -58,9 +58,14 @@ private void load(ManiaRulesetConfigManager rulesetConfig)
|
|||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
if (beatDivisorFinder != null)
|
||||
if (beatmap != null)
|
||||
{
|
||||
HitObject.StartTimeBindable.BindValueChanged(_ => snap.Value = beatDivisorFinder.FindDivisor(HitObject), true);
|
||||
HitObject.StartTimeBindable.BindValueChanged(startTime =>
|
||||
{
|
||||
snap.Value = beatmap.ControlPointInfo.GetClosestBeatDivisor(startTime.NewValue);
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
snap.BindValueChanged(_ => updateSnapColour());
|
||||
|
|
|
@ -45,8 +45,8 @@ public class DrawableManiaRuleset : DrawableScrollingRuleset<ManiaHitObject>
|
|||
|
||||
public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap;
|
||||
|
||||
[Cached]
|
||||
private BeatDivisorFinder beatDivisorFinder { get; set; }
|
||||
[Cached(typeof(IBeatmap))]
|
||||
private ManiaBeatmap cachedBeatmap { get; set; }
|
||||
|
||||
public IEnumerable<BarLine> BarLines;
|
||||
|
||||
|
@ -80,7 +80,7 @@ public DrawableManiaRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod
|
|||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
BarLines = new BarLineGenerator<BarLine>(Beatmap).BarLines;
|
||||
beatDivisorFinder = new BeatDivisorFinder(Beatmap);
|
||||
cachedBeatmap = Beatmap;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
// 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;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Tests.NonVisual
|
||||
{
|
||||
public class BeatDivisorFinderTest
|
||||
{
|
||||
[Test]
|
||||
public void TestFindDivisor()
|
||||
{
|
||||
const double beat_length = 1000;
|
||||
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new HitObject { StartTime = -beat_length / 3 },
|
||||
new HitObject { StartTime = 0 },
|
||||
new HitObject { StartTime = beat_length / 16 },
|
||||
new HitObject { StartTime = beat_length / 12 },
|
||||
new HitObject { StartTime = beat_length / 8 },
|
||||
new HitObject { StartTime = beat_length / 6 },
|
||||
new HitObject { StartTime = beat_length / 4 },
|
||||
new HitObject { StartTime = beat_length / 3 },
|
||||
new HitObject { StartTime = beat_length / 2 },
|
||||
new HitObject { StartTime = beat_length },
|
||||
new HitObject { StartTime = beat_length + beat_length / 7 }
|
||||
},
|
||||
ControlPointInfo = new ControlPointInfo()
|
||||
};
|
||||
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint
|
||||
{
|
||||
TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple,
|
||||
BeatLength = beat_length
|
||||
});
|
||||
|
||||
var beatDivisorFinder = new BeatDivisorFinder(beatmap);
|
||||
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[0]), 3);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[1]), 1);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[2]), 16);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[3]), 12);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[4]), 8);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[5]), 6);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[6]), 4);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[7]), 3);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[8]), 2);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[9]), 1);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[10]), 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFindDivisorWithTempoChanges()
|
||||
{
|
||||
const double first_beat_length = 1000;
|
||||
const double second_beat_length = 700;
|
||||
const double third_beat_length = 200;
|
||||
|
||||
const double first_beat_length_start = 0;
|
||||
const double second_beat_length_start = 1000;
|
||||
const double third_beat_length_start = 2000;
|
||||
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new HitObject { StartTime = first_beat_length_start },
|
||||
new HitObject { StartTime = first_beat_length_start + first_beat_length / 2 },
|
||||
new HitObject { StartTime = second_beat_length_start },
|
||||
new HitObject { StartTime = second_beat_length_start + second_beat_length / 2 },
|
||||
new HitObject { StartTime = third_beat_length_start },
|
||||
new HitObject { StartTime = third_beat_length_start + third_beat_length / 2 },
|
||||
},
|
||||
ControlPointInfo = new ControlPointInfo()
|
||||
};
|
||||
|
||||
var firstTimingControlPoint = new TimingControlPoint
|
||||
{
|
||||
TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple,
|
||||
BeatLength = first_beat_length
|
||||
};
|
||||
|
||||
var secondTimingControlPoint = new TimingControlPoint
|
||||
{
|
||||
TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple,
|
||||
BeatLength = second_beat_length
|
||||
};
|
||||
|
||||
var thirdTimingControlPoint = new TimingControlPoint
|
||||
{
|
||||
TimeSignature = Game.Beatmaps.Timing.TimeSignatures.SimpleQuadruple,
|
||||
BeatLength = third_beat_length
|
||||
};
|
||||
|
||||
beatmap.ControlPointInfo.Add(first_beat_length_start, firstTimingControlPoint);
|
||||
beatmap.ControlPointInfo.Add(second_beat_length_start, secondTimingControlPoint);
|
||||
beatmap.ControlPointInfo.Add(third_beat_length_start, thirdTimingControlPoint);
|
||||
|
||||
var beatDivisorFinder = new BeatDivisorFinder(beatmap);
|
||||
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[0]), 1);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[1]), 2);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[2]), 1);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[3]), 2);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[4]), 1);
|
||||
Assert.AreEqual(beatDivisorFinder.FindDivisor(beatmap.HitObjects[5]), 2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
// 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 osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Screens.Edit;
|
||||
|
||||
namespace osu.Game.Rulesets.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to find the lowest beat divisor that a <see cref="HitObject"/> aligns to in an <see cref="IBeatmap"/>.
|
||||
/// </summary>
|
||||
public class BeatDivisorFinder
|
||||
{
|
||||
private readonly IBeatmap beatmap;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="BeatDivisorFinder"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to use when calculating beat divisor alignment.</param>
|
||||
public BeatDivisorFinder(IBeatmap beatmap)
|
||||
{
|
||||
this.beatmap = beatmap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the lowest beat divisor that the given <see cref="HitObject"/> aligns to.
|
||||
/// Returns 0 if it does not align to any divisor.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="HitObject"/> to evaluate.</param>
|
||||
public int FindDivisor(HitObject hitObject)
|
||||
{
|
||||
TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime);
|
||||
double snapResult = hitObject.StartTime - currentTimingPoint.Time;
|
||||
|
||||
foreach (var divisor in BindableBeatDivisor.VALID_DIVISORS)
|
||||
{
|
||||
if (almostDivisibleBy(snapResult, currentTimingPoint.BeatLength / divisor))
|
||||
return divisor;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private const double leniency_ms = 1.0;
|
||||
|
||||
private static bool almostDivisibleBy(double dividend, double divisor)
|
||||
{
|
||||
double remainder = Math.Abs(dividend) % divisor;
|
||||
return Precision.AlmostEquals(remainder, 0, leniency_ms) || Precision.AlmostEquals(remainder - divisor, 0, leniency_ms);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue