1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-15 22:22:54 +08:00

Merge branch 'editor-clock-cache' into editor-clock-transform

This commit is contained in:
Dean Herbert 2020-05-22 19:51:02 +09:00
commit 1486a44b55
7 changed files with 100 additions and 16 deletions

View File

@ -0,0 +1,73 @@
// 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.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Tests.NonVisual
{
public class BarLineGeneratorTest
{
[Test]
public void TestRoundingErrorCompensation()
{
// The aim of this test is to make sure bar line generation compensates for floating-point errors.
// The premise of the test is that we have a single timing point that should result in bar lines
// that start at a time point that is a whole number every seventh beat.
// The fact it's every seventh beat is important - it's a number indivisible by 2, which makes
// it susceptible to rounding inaccuracies. In fact this was originally spotted in cases of maps
// that met exactly this criteria.
const int beat_length_numerator = 2000;
const int beat_length_denominator = 7;
const TimeSignatures signature = TimeSignatures.SimpleQuadruple;
var beatmap = new Beatmap
{
HitObjects = new List<HitObject>
{
new HitObject { StartTime = 0 },
new HitObject { StartTime = 120_000 }
},
ControlPointInfo = new ControlPointInfo()
};
beatmap.ControlPointInfo.Add(0, new TimingControlPoint
{
BeatLength = (double)beat_length_numerator / beat_length_denominator,
TimeSignature = signature
});
var barLines = new BarLineGenerator<BarLine>(beatmap).BarLines;
for (int i = 0; i * beat_length_denominator < barLines.Count; i++)
{
var barLine = barLines[i * beat_length_denominator];
var expectedTime = beat_length_numerator * (int)signature * 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
// (the previous timing point might be chosen incorrectly if this is not the case)
Assert.GreaterOrEqual(barLine.StartTime, expectedTime);
// on the other side, make sure we don't stray too far from the expected time either.
Assert.IsTrue(Precision.AlmostEquals(barLine.StartTime, expectedTime));
// check major/minor lines for good measure too
Assert.AreEqual(i % (int)signature == 0, barLine.Major);
}
}
private class BarLine : IBarLine
{
public double StartTime { get; set; }
public bool Major { get; set; }
}
}
}

View File

@ -4,8 +4,8 @@
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Components;
using osuTK;
@ -17,9 +17,8 @@ namespace osu.Game.Tests.Visual.Editing
[BackgroundDependencyLoader]
private void load()
{
var clock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
Dependencies.CacheAs<IAdjustableClock>(clock);
Dependencies.CacheAs<IFrameBasedClock>(clock);
var clock = new EditorClock { IsCoupled = false };
Dependencies.CacheAs(clock);
var playback = new PlaybackControl
{

View File

@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.Editing
private IBindable<WorkingBeatmap> beatmap { get; set; }
[Resolved]
private EditorClock adjustableClock { get; set; }
private EditorClock editorClock { get; set; }
public AudioVisualiser()
{
@ -95,13 +95,15 @@ namespace osu.Game.Tests.Visual.Editing
base.Update();
if (beatmap.Value.Track.IsLoaded)
marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length);
marker.X = (float)(editorClock.CurrentTime / beatmap.Value.Track.Length);
}
}
private class StartStopButton : OsuButton
{
private EditorClock editorClock;
[Resolved]
private EditorClock editorClock { get; set; }
private bool started;
public StartStopButton()
@ -113,12 +115,6 @@ namespace osu.Game.Tests.Visual.Editing
Action = onClick;
}
[BackgroundDependencyLoader]
private void load(EditorClock editorClock)
{
this.editorClock = editorClock;
}
private void onClick()
{
if (started)

View File

@ -1,6 +1,7 @@
// 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;
using System.Linq;
using osu.Framework.Utils;
@ -46,6 +47,16 @@ namespace osu.Game.Rulesets.Objects
for (double t = currentTimingPoint.Time; Precision.DefinitelyBigger(endTime, t); t += barLength, currentBeat++)
{
var roundedTime = Math.Round(t, MidpointRounding.AwayFromZero);
// in the case of some bar lengths, rounding errors can cause t to be slightly less than
// the expected whole number value due to floating point inaccuracies.
// if this is the case, apply rounding.
if (Precision.AlmostEquals(t, roundedTime))
{
t = roundedTime;
}
BarLines.Add(new TBarLine
{
StartTime = t,

View File

@ -40,6 +40,11 @@ namespace osu.Game.Screens.Edit
underlyingClock = new DecoupleableInterpolatingFramedClock();
}
public EditorClock()
: this(new ControlPointInfo(), 1000, new BindableBeatDivisor())
{
}
/// <summary>
/// Seek to the closest snappable beat from a time.
/// </summary>

View File

@ -7,7 +7,6 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics;
@ -62,7 +61,7 @@ namespace osu.Game.Screens.Edit.Timing
private IBindableList<ControlPointGroup> controlGroups;
[Resolved]
private IFrameBasedClock clock { get; set; }
private EditorClock clock { get; set; }
[Resolved]
protected IBindable<WorkingBeatmap> Beatmap { get; private set; }

View File

@ -8,6 +8,7 @@ using osu.Framework.Timing;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose;
namespace osu.Game.Tests.Visual
@ -32,7 +33,7 @@ namespace osu.Game.Tests.Visual
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
dependencies.CacheAs<IAdjustableClock>(new StopwatchClock());
dependencies.CacheAs(new EditorClock());
return dependencies;
}