mirror of
https://github.com/ppy/osu.git
synced 2025-02-22 20:52:54 +08:00
Merge branch 'master' into update-framework
This commit is contained in:
commit
9fa8f62077
@ -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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -225,6 +225,12 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
if (replayInputManager.ReplayInputHandler != null)
|
if (replayInputManager.ReplayInputHandler != null)
|
||||||
replayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace;
|
replayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace;
|
||||||
|
|
||||||
|
if (!ProvidingUserCursor)
|
||||||
|
{
|
||||||
|
// The cursor is hidden by default (see Playfield.load()), but should be shown when there's a replay
|
||||||
|
Playfield.Cursor?.Show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -68,6 +68,8 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
private const double sixty_frame_time = 1000.0 / 60;
|
private const double sixty_frame_time = 1000.0 / 60;
|
||||||
|
|
||||||
|
private bool firstConsumption = true;
|
||||||
|
|
||||||
public override bool UpdateSubTree()
|
public override bool UpdateSubTree()
|
||||||
{
|
{
|
||||||
requireMoreUpdateLoops = true;
|
requireMoreUpdateLoops = true;
|
||||||
@ -103,7 +105,18 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
try
|
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
|
newProposedTime = newProposedTime > manualClock.CurrentTime
|
||||||
? Math.Min(newProposedTime, manualClock.CurrentTime + sixty_frame_time)
|
? Math.Min(newProposedTime, manualClock.CurrentTime + sixty_frame_time)
|
||||||
|
@ -79,7 +79,7 @@ namespace osu.Game.Screens.Multi
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
Title = "multiplayer";
|
Title = "multi";
|
||||||
Icon = OsuIcon.Multi;
|
Icon = OsuIcon.Multi;
|
||||||
AccentColour = colours.Yellow;
|
AccentColour = colours.Yellow;
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,24 @@
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Testing.Input;
|
using osu.Framework.Testing.Input;
|
||||||
|
using osu.Game.Graphics.Cursor;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
public abstract class ManualInputManagerTestCase : OsuTestCase
|
public abstract class ManualInputManagerTestCase : OsuTestCase
|
||||||
{
|
{
|
||||||
protected override Container<Drawable> Content => InputManager;
|
protected override Container<Drawable> Content => content;
|
||||||
|
private readonly Container content;
|
||||||
|
|
||||||
protected readonly ManualInputManager InputManager;
|
protected readonly ManualInputManager InputManager;
|
||||||
|
|
||||||
protected ManualInputManagerTestCase()
|
protected ManualInputManagerTestCase()
|
||||||
{
|
{
|
||||||
base.Content.Add(InputManager = new ManualInputManager { UseParentInput = true });
|
base.Content.Add(InputManager = new ManualInputManager
|
||||||
|
{
|
||||||
|
UseParentInput = true,
|
||||||
|
Child = content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user