From 0459f0a0696cadc1ec4cf4212eff6adcb22c98ff Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jan 2018 13:40:02 +0900 Subject: [PATCH 1/7] Invert CanShowCursor conditional to fix cursor not showing in VisualTests --- osu.Game/Graphics/Cursor/CursorOverrideContainer.cs | 2 +- osu.Game/OsuGame.cs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs index 4b29414990..0fae4579fa 100644 --- a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs +++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Graphics.Cursor /// /// Whether any cursors can be displayed. /// - public bool CanShowCursor; + public bool CanShowCursor = true; public CursorContainer Cursor { get; } public bool ProvidingUserCursor => true; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 124b9364b3..b48e25f1fe 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -157,6 +157,11 @@ namespace osu.Game { base.LoadComplete(); + // The next time this is updated is in UpdateAfterChildren, which occurs too late and results + // in the cursor being shown for a few frames during the intro. + // This prevents the cursor from showing until we have a screen with CursorVisible = true + CursorOverrideContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; + // hook up notifications to components. BeatmapManager.PostNotification = n => notifications?.Post(n); BeatmapManager.GetStableStorage = GetStorageForStableInstall; From d230fd486e2cc023c59e024287a9422de00c58d1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jan 2018 15:28:00 +0900 Subject: [PATCH 2/7] Add automated cursor testcase --- osu.Game.Tests/Visual/TestCaseCursors.cs | 250 +++++++++++++++++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 1 + 2 files changed, 251 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseCursors.cs diff --git a/osu.Game.Tests/Visual/TestCaseCursors.cs b/osu.Game.Tests/Visual/TestCaseCursors.cs new file mode 100644 index 0000000000..e0ce5fad77 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseCursors.cs @@ -0,0 +1,250 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.MathUtils; +using osu.Framework.Testing.Input; +using osu.Game.Graphics.Cursor; +using osu.Game.Graphics.Sprites; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseCursors : OsuTestCase + { + private readonly ManualInputManager inputManager; + private readonly CursorOverrideContainer cursorOverrideContainer; + private readonly CustomCursorBox[] cursorBoxes = new CustomCursorBox[6]; + + public TestCaseCursors() + { + Child = inputManager = new ManualInputManager + { + Child = cursorOverrideContainer = new CursorOverrideContainer + { + RelativeSizeAxes = Axes.Both, + Children = new[] + { + // Middle user + cursorBoxes[0] = new CustomCursorBox(Color4.Green) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + // Top-left user + cursorBoxes[1] = new CustomCursorBox(Color4.Blue) + { + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.4f) + }, + // Bottom-right user + cursorBoxes[2] = new CustomCursorBox(Color4.Red) + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.4f) + }, + // Bottom-left local + cursorBoxes[3] = new CustomCursorBox(Color4.Magenta, false) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.4f) + }, + // Top-right local + cursorBoxes[4] = new CustomCursorBox(Color4.Cyan, false) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.4f) + }, + // Left-local + cursorBoxes[5] = new CustomCursorBox(Color4.Yellow, false) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.2f, 1), + }, + } + } + }; + + returnUserInput(); + testUserCursor(); + testLocalCursor(); + testUserCursorOverride(); + testMultipleLocalCursors(); + } + + /// + /// Returns input back to the user. + /// + private void returnUserInput() + { + AddStep("Return user input", () => inputManager.UseParentState = true); + } + + /// + /// -- Green Box -- + /// Tests whether hovering in and out of a drawable that provides the user cursor (green) + /// results in the correct visibility state for that cursor. + /// + private void testUserCursor() + { + AddStep("Move to green area", () => inputManager.MoveMouseTo(cursorBoxes[0])); + AddAssert("Check green cursor visible", () => checkVisible(cursorBoxes[0].Cursor)); + AddAssert("Check green cursor at mouse", () => checkAtMouse(cursorBoxes[0].Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check green cursor invisible", () => !checkVisible(cursorBoxes[0].Cursor)); + AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor)); + } + + /// + /// -- Purple Box -- + /// Tests whether hovering in and out of a drawable that provides a local cursor (purple) + /// results in the correct visibility and state for that cursor. + /// + private void testLocalCursor() + { + AddStep("Move to purple area", () => inputManager.MoveMouseTo(cursorBoxes[3])); + AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); + AddAssert("Check purple cursor at mouse", () => checkAtMouse(cursorBoxes[3].Cursor)); + AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor)); + AddAssert("Check global cursor at mouse", () => checkAtMouse(cursorOverrideContainer.Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); + AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor)); + } + + /// + /// -- Blue-Green Box Boundary -- + /// Tests whether overriding a user cursor (green) with another user cursor (blue) + /// results in the correct visibility and states for the cursors. + /// + private void testUserCursorOverride() + { + AddStep("Move to blue-green boundary", () => inputManager.MoveMouseTo(cursorBoxes[1].ScreenSpaceDrawQuad.BottomRight - new Vector2(10))); + AddAssert("Check blue cursor visible", () => checkVisible(cursorBoxes[1].Cursor)); + AddAssert("Check green cursor invisible", () => !checkVisible(cursorBoxes[0].Cursor)); + AddAssert("Check blue cursor at mouse", () => checkAtMouse(cursorBoxes[1].Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check blue cursor not visible", () => !checkVisible(cursorBoxes[1].Cursor)); + AddAssert("Check green cursor not visible", () => !checkVisible(cursorBoxes[0].Cursor)); + } + + /// + /// -- Yellow-Purple Box Boundary -- + /// Tests whether multiple local cursors (purple + yellow) may be visible and at the mouse position at the same time. + /// + private void testMultipleLocalCursors() + { + AddStep("Move to yellow-purple boundary", () => inputManager.MoveMouseTo(cursorBoxes[5].ScreenSpaceDrawQuad.BottomRight - new Vector2(10))); + AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); + AddAssert("Check purple cursor at mouse", () => checkAtMouse(cursorBoxes[3].Cursor)); + AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor)); + AddAssert("Check yellow cursor at mouse", () => checkAtMouse(cursorBoxes[5].Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); + AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor)); + } + + /// + /// -- Yellow-Blue Box Boundary -- + /// Tests whether a local cursor (yellow) may be displayed along with a user cursor override (blue). + /// + private void testUserOverrideWithLocal() + { + AddStep("Move to yellow-blue boundary", () => inputManager.MoveMouseTo(cursorBoxes[5].ScreenSpaceDrawQuad.TopRight - new Vector2(10))); + AddAssert("Check blue cursor visible", () => checkVisible(cursorBoxes[1].Cursor)); + AddAssert("Check blue cursor at mouse", () => checkAtMouse(cursorBoxes[1].Cursor)); + AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor)); + AddAssert("Check yellow cursor at mouse", () => checkAtMouse(cursorBoxes[5].Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check blue cursor invisible", () => !checkVisible(cursorBoxes[1].Cursor)); + AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor)); + } + + /// + /// Moves the cursor to a point not covered by any cursor containers. + /// + private void moveOut() + => inputManager.MoveMouseTo(new Vector2(inputManager.ScreenSpaceDrawQuad.Centre.X, inputManager.ScreenSpaceDrawQuad.TopLeft.Y)); + + /// + /// Checks if a cursor is visible. + /// + /// The cursor to check. + private bool checkVisible(CursorContainer cursorContainer) => cursorContainer.State == Visibility.Visible; + + /// + /// Checks if a cursor is at the current inputmanager screen position. + /// + /// The cursor to check. + private bool checkAtMouse(CursorContainer cursorContainer) + => Precision.AlmostEquals(inputManager.CurrentState.Mouse.NativeState.Position, cursorContainer.ToScreenSpace(cursorContainer.ActiveCursor.DrawPosition)); + + private class CustomCursorBox : Container, IProvideCursor + { + public CursorContainer Cursor { get; } + public bool ProvidingUserCursor { get; } + + public CustomCursorBox(Color4 cursorColour, bool providesUserCursor = true) + { + ProvidingUserCursor = providesUserCursor; + + Colour = cursorColour; + Masking = true; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.1f + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = providesUserCursor ? "User cursor" : "Local cursor" + }, + Cursor = new TestCursorContainer + { + State = providesUserCursor ? Visibility.Hidden : Visibility.Visible, + } + }; + } + } + + private class TestCursorContainer : CursorContainer + { + protected override Drawable CreateCursor() => new TestCursor(); + + private class TestCursor : CircularContainer + { + public TestCursor() + { + Origin = Anchor.Centre; + + Size = new Vector2(50); + Masking = true; + + Blending = BlendingMode.Additive; + Alpha = 0.5f; + + Child = new Box { RelativeSizeAxes = Axes.Both }; + } + } + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 2eb79f6b35..76b426bf5d 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -104,6 +104,7 @@ + From 4f7ccb8d939878b3646648348de917e10ab97bc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Jan 2018 18:38:47 +0900 Subject: [PATCH 3/7] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 49b563e2cf..95bd66da12 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 49b563e2cf170eb19006b98dd5b69c2398362d9e +Subproject commit 95bd66da12276f39335873972f713774306b4894 From 1174f344896a2670d41cabf79fda5b191572bbcb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jan 2018 20:21:09 +0900 Subject: [PATCH 4/7] Update framework post-merge --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 95bd66da12..023a0abe17 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 95bd66da12276f39335873972f713774306b4894 +Subproject commit 023a0abe17490a118fe1ca85ea487462bff4277e From a5415b99aecb21ed74f8c9feb048288878325cf2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jan 2018 20:35:07 +0900 Subject: [PATCH 5/7] Visualise the hovered drawabe --- osu.Game.Tests/Visual/TestCaseCursors.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseCursors.cs b/osu.Game.Tests/Visual/TestCaseCursors.cs index e0ce5fad77..20e6103436 100644 --- a/osu.Game.Tests/Visual/TestCaseCursors.cs +++ b/osu.Game.Tests/Visual/TestCaseCursors.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; using osu.Framework.MathUtils; using osu.Framework.Testing.Input; using osu.Game.Graphics.Cursor; @@ -198,6 +199,8 @@ namespace osu.Game.Tests.Visual public CursorContainer Cursor { get; } public bool ProvidingUserCursor { get; } + private readonly Box background; + public CustomCursorBox(Color4 cursorColour, bool providesUserCursor = true) { ProvidingUserCursor = providesUserCursor; @@ -207,7 +210,7 @@ namespace osu.Game.Tests.Visual Children = new Drawable[] { - new Box + background = new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.1f @@ -224,6 +227,18 @@ namespace osu.Game.Tests.Visual } }; } + + protected override bool OnHover(InputState state) + { + background.FadeTo(0.4f, 250, Easing.OutQuint); + return false; + } + + protected override void OnHoverLost(InputState state) + { + background.FadeTo(0.1f, 250); + base.OnHoverLost(state); + } } private class TestCursorContainer : CursorContainer From 06f0f2093c71f678b61faa4d9aef4748694b7f47 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jan 2018 20:35:39 +0900 Subject: [PATCH 6/7] Add a sample way to have local cursors move beyond their bounds --- osu.Game.Tests/Visual/TestCaseCursors.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game.Tests/Visual/TestCaseCursors.cs b/osu.Game.Tests/Visual/TestCaseCursors.cs index 20e6103436..363f6b53f0 100644 --- a/osu.Game.Tests/Visual/TestCaseCursors.cs +++ b/osu.Game.Tests/Visual/TestCaseCursors.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -81,10 +82,14 @@ namespace osu.Game.Tests.Visual }; returnUserInput(); + + AddToggleStep("Smooth transitions", b => cursorBoxes.ForEach(box => box.SmoothTransition = b)); + testUserCursor(); testLocalCursor(); testUserCursorOverride(); testMultipleLocalCursors(); + returnUserInput(); } /// @@ -196,9 +201,13 @@ namespace osu.Game.Tests.Visual private class CustomCursorBox : Container, IProvideCursor { + public bool SmoothTransition; + public CursorContainer Cursor { get; } public bool ProvidingUserCursor { get; } + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => base.ReceiveMouseInputAt(screenSpacePos) || SmoothTransition && !ProvidingUserCursor; + private readonly Box background; public CustomCursorBox(Color4 cursorColour, bool providesUserCursor = true) From 87d2cce61d3aaf1d1da59d4ee330660c2987a81b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 Jan 2018 00:47:14 +0900 Subject: [PATCH 7/7] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 023a0abe17..8f36ddab94 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 023a0abe17490a118fe1ca85ea487462bff4277e +Subproject commit 8f36ddab946ff538620081ede7719461d4732b79