mirror of
https://github.com/ppy/osu
synced 2024-12-16 20:05:41 +00:00
Merge pull request #4673 from peppy/frame-stability-initial-seek
Amend FrameStabilityContainer's initial seek behaviour
This commit is contained in:
commit
c961d95989
@ -0,0 +1,150 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestCaseFrameStabilityContainer : OsuTestCase
|
||||
{
|
||||
private readonly ManualClock manualClock;
|
||||
|
||||
private readonly Container mainContainer;
|
||||
|
||||
private ClockConsumingChild consumer;
|
||||
|
||||
public TestCaseFrameStabilityContainer()
|
||||
{
|
||||
Child = mainContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Clock = new FramedClock(manualClock = new ManualClock()),
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLargeJumps()
|
||||
{
|
||||
seekManualTo(0);
|
||||
createStabilityContainer();
|
||||
seekManualTo(100000);
|
||||
|
||||
confirmSeek(100000);
|
||||
checkFrameCount(6000);
|
||||
|
||||
seekManualTo(0);
|
||||
|
||||
confirmSeek(0);
|
||||
checkFrameCount(12000);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSmallJumps()
|
||||
{
|
||||
seekManualTo(0);
|
||||
createStabilityContainer();
|
||||
seekManualTo(40);
|
||||
|
||||
confirmSeek(40);
|
||||
checkFrameCount(3);
|
||||
|
||||
seekManualTo(0);
|
||||
|
||||
confirmSeek(0);
|
||||
checkFrameCount(6);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSingleFrameJump()
|
||||
{
|
||||
seekManualTo(0);
|
||||
createStabilityContainer();
|
||||
seekManualTo(8);
|
||||
confirmSeek(8);
|
||||
checkFrameCount(1);
|
||||
|
||||
seekManualTo(16);
|
||||
confirmSeek(16);
|
||||
checkFrameCount(2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInitialSeek()
|
||||
{
|
||||
seekManualTo(100000);
|
||||
createStabilityContainer();
|
||||
|
||||
confirmSeek(100000);
|
||||
checkFrameCount(0);
|
||||
}
|
||||
|
||||
private void createStabilityContainer() => AddStep("create container", () => mainContainer.Child = new FrameStabilityContainer().WithChild(consumer = new ClockConsumingChild()));
|
||||
|
||||
private void seekManualTo(double time) => AddStep($"seek manual clock to {time}", () => manualClock.CurrentTime = time);
|
||||
|
||||
private void confirmSeek(double time) => AddUntilStep($"wait for seek to {time}", () => consumer.Clock.CurrentTime == time);
|
||||
|
||||
private void checkFrameCount(int frames) =>
|
||||
AddAssert($"elapsed frames is {frames}", () => consumer.ElapsedFrames == frames);
|
||||
|
||||
public class ClockConsumingChild : CompositeDrawable
|
||||
{
|
||||
private readonly OsuSpriteText text;
|
||||
private readonly OsuSpriteText text2;
|
||||
private readonly OsuSpriteText text3;
|
||||
|
||||
public ClockConsumingChild()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
text = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
text2 = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
text3 = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public int ElapsedFrames;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (Clock.ElapsedFrameTime != 0)
|
||||
ElapsedFrames++;
|
||||
|
||||
text.Text = $"current time: {Clock.CurrentTime:F0}";
|
||||
if (Clock.ElapsedFrameTime != 0)
|
||||
text2.Text = $"last elapsed frame time: {Clock.ElapsedFrameTime:F0}";
|
||||
text3.Text = $"total frames: {ElapsedFrames:F0}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -68,6 +68,8 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
private const double sixty_frame_time = 1000.0 / 60;
|
||||
|
||||
private bool firstConsumption = true;
|
||||
|
||||
public override bool UpdateSubTree()
|
||||
{
|
||||
requireMoreUpdateLoops = true;
|
||||
@ -103,7 +105,18 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
try
|
||||
{
|
||||
if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f)
|
||||
if (firstConsumption)
|
||||
{
|
||||
// On the first update, frame-stability seeking would result in unexpected/unwanted behaviour.
|
||||
// Instead we perform an initial seek to the proposed time.
|
||||
manualClock.CurrentTime = newProposedTime;
|
||||
|
||||
// do a second process to clear out ElapsedTime
|
||||
framedClock.ProcessFrame();
|
||||
|
||||
firstConsumption = false;
|
||||
}
|
||||
else if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f)
|
||||
{
|
||||
newProposedTime = newProposedTime > manualClock.CurrentTime
|
||||
? Math.Min(newProposedTime, manualClock.CurrentTime + sixty_frame_time)
|
||||
|
Loading…
Reference in New Issue
Block a user