mirror of
https://github.com/osukey/osukey.git
synced 2025-05-02 20:27:27 +09:00
Replace BeatDivisorFinder with GetClosestBeatDivisor
This commit is contained in:
parent
ecb053b0de
commit
fdf8c12947
@ -6,10 +6,10 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Configuration;
|
using osu.Game.Rulesets.Mania.Configuration;
|
||||||
using osu.Game.Rulesets.Mania.Skinning.Default;
|
using osu.Game.Rulesets.Mania.Skinning.Default;
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
private OsuColour colours { get; set; }
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private BeatDivisorFinder beatDivisorFinder { get; set; }
|
private IBeatmap beatmap { get; set; }
|
||||||
|
|
||||||
private readonly Bindable<bool> configTimingBasedNoteColouring = new Bindable<bool>();
|
private readonly Bindable<bool> configTimingBasedNoteColouring = new Bindable<bool>();
|
||||||
|
|
||||||
@ -58,9 +58,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
|
|
||||||
protected override void LoadComplete()
|
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());
|
snap.BindValueChanged(_ => updateSnapColour());
|
||||||
|
@ -45,8 +45,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap;
|
public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap;
|
||||||
|
|
||||||
[Cached]
|
[Cached(typeof(IBeatmap))]
|
||||||
private BeatDivisorFinder beatDivisorFinder { get; set; }
|
private ManiaBeatmap cachedBeatmap { get; set; }
|
||||||
|
|
||||||
public IEnumerable<BarLine> BarLines;
|
public IEnumerable<BarLine> BarLines;
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
BarLines = new BarLineGenerator<BarLine>(Beatmap).BarLines;
|
BarLines = new BarLineGenerator<BarLine>(Beatmap).BarLines;
|
||||||
beatDivisorFinder = new BeatDivisorFinder(Beatmap);
|
cachedBeatmap = Beatmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[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…
x
Reference in New Issue
Block a user