From c97116c91ac0a80a126993ea0e02ffe56de7d9df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 13:34:22 +0900 Subject: [PATCH 1/7] Add safety against DrawableHitObject implementations clearing children --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e1e76f109d..a7cfbd3300 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -120,6 +120,8 @@ namespace osu.Game.Rulesets.Objects.Drawables } } + protected override void ClearInternal(bool disposeChildren = true) => throw new InvalidOperationException($"Should never clear a {nameof(DrawableHitObject)}"); + protected override void LoadComplete() { base.LoadComplete(); From 39df8cce19358445e0ca7548bb8ae1623e4c25a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 13:47:28 +0900 Subject: [PATCH 2/7] Fix incorrect usage of InternalChildren Could cause overwriting of components added by base DrawableHitObjcet class (such as samples) --- .../Objects/Drawable/DrawableBananaShower.cs | 2 +- .../Objects/Drawable/DrawableDroplet.cs | 5 +---- .../Objects/Drawable/DrawableFruit.cs | 4 ++-- .../Objects/Drawable/DrawableJuiceStream.cs | 2 +- .../Objects/Drawables/DrawableHoldNote.cs | 4 ++-- .../Objects/Drawables/DrawableHoldNoteTick.cs | 4 ++-- .../Objects/Drawables/DrawableNote.cs | 2 +- .../Objects/Drawables/DrawableBarLine.cs | 17 +++++++---------- .../Objects/Drawables/DrawableTaikoHitObject.cs | 4 ++-- .../Gameplay/TestCaseScrollingHitObjects.cs | 6 +++--- 10 files changed, 22 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index aaf723fae6..57c71d0411 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Origin = Anchor.BottomLeft; X = 0; - InternalChild = bananaContainer = new Container { RelativeSizeAxes = Axes.Both }; + AddInternal(bananaContainer = new Container { RelativeSizeAxes = Axes.Both }); foreach (var b in s.NestedHitObjects.Cast()) AddNested(getVisualRepresentation?.Invoke(b)); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs index 8fed8eb4cd..9cabdc3dd9 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs @@ -26,10 +26,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable [BackgroundDependencyLoader] private void load() { - InternalChild = pulp = new Pulp - { - Size = Size - }; + AddInternal(pulp = new Pulp { Size = Size }); } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index fac4b8098c..0dc3f73404 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable // todo: this should come from the skin. AccentColour = colourForRepresentation(HitObject.VisualRepresentation); - InternalChildren = new[] + AddRangeInternal(new[] { createPulp(HitObject.VisualRepresentation), border = new Circle @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable } } }, - }; + }); if (HitObject.HyperDash) { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 7bb12453a8..ae2232f8f1 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Origin = Anchor.BottomLeft; X = 0; - InternalChild = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }; + AddInternal(dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }); foreach (var o in s.NestedHitObjects.Cast()) AddNested(getVisualRepresentation?.Invoke(o)); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 4bfd940aa0..9368af987d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { RelativeSizeAxes = Axes.X; - InternalChildren = new Drawable[] + AddRangeInternal(new Drawable[] { bodyPiece = new BodyPiece { @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre } - }; + }); foreach (var tick in tickContainer) AddNested(tick); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 43aac7907f..f2be8d614c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables RelativeSizeAxes = Axes.X; Size = new Vector2(1); - InternalChildren = new[] + AddRangeInternal(new[] { glowContainer = new CircularContainer { @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } } - }; + }); } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 7ef90cdb9c..82a34224f4 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables CornerRadius = 5; Masking = true; - InternalChild = headPiece = new NotePiece(); + AddInternal(headPiece = new NotePiece()); } protected override void OnDirectionChanged(ValueChangedEvent e) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index 5e4c6edb43..f8909fb98c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -44,17 +44,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables RelativeSizeAxes = Axes.Y; Width = tracker_width; - InternalChildren = new[] + AddInternal(Tracker = new Box { - Tracker = new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - EdgeSmoothness = new Vector2(0.5f, 0), - Alpha = 0.75f - } - }; + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + EdgeSmoothness = new Vector2(0.5f, 0), + Alpha = 0.75f + }); } protected override void UpdateState(ArmedState state) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 5f755c7cc3..8dfe89eea7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected DrawableTaikoHitObject(TaikoHitObject hitObject) : base(hitObject) { - InternalChildren = new[] + AddRangeInternal(new[] { nonProxiedContent = new Container { @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Child = Content = new Container { RelativeSizeAxes = Axes.Both } }, proxiedContent = new ProxiedContentContainer { RelativeSizeAxes = Axes.Both } - }; + }); } /// diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs index a1cec1e18f..c99a4bb89b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs @@ -170,12 +170,12 @@ namespace osu.Game.Tests.Visual.Gameplay { Origin = Anchor.Centre; - InternalChild = new Box + AddInternal(new Box { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both - }; + }); switch (direction) { @@ -205,7 +205,7 @@ namespace osu.Game.Tests.Visual.Gameplay Origin = Anchor.Centre; AutoSizeAxes = Axes.Both; - InternalChild = new Box { Size = new Vector2(75) }; + AddInternal(new Box { Size = new Vector2(75) }); } protected override void UpdateState(ArmedState state) From 868367511e5eb181e48499449d6933f87ec4964c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 13:16:46 +0900 Subject: [PATCH 3/7] Add ManualInputManager to screen tests Also sanitises content init order (ctor for content; bdl for other) --- .../Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs | 3 ++- osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs | 4 +++- osu.Game/Tests/Visual/ManualInputManagerTestCase.cs | 3 +-- osu.Game/Tests/Visual/PlayerTestCase.cs | 5 +++++ osu.Game/Tests/Visual/ScreenTestCase.cs | 8 +++++--- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs index 34de61cb5b..497da33a05 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs @@ -27,7 +27,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [Cached(Type = typeof(IRoomManager))] private TestRoomManager roomManager = new TestRoomManager(); - public TestCaseLoungeRoomsContainer() + [BackgroundDependencyLoader] + private void load() { RoomsContainer container; diff --git a/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs b/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs index 9453d0a5b2..53fb60bcb6 100644 --- a/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs +++ b/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel; +using osu.Framework.Allocation; using osu.Game.Screens.Tournament; using osu.Game.Screens.Tournament.Teams; @@ -11,7 +12,8 @@ namespace osu.Game.Tests.Visual.Tournament [Description("for tournament use")] public class TestCaseDrawings : ScreenTestCase { - public TestCaseDrawings() + [BackgroundDependencyLoader] + private void load() { LoadScreen(new Drawings { diff --git a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs index 7c7c5938aa..f14ac833e4 100644 --- a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs +++ b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs @@ -14,8 +14,7 @@ namespace osu.Game.Tests.Visual protected ManualInputManagerTestCase() { - base.Content.Add(InputManager = new ManualInputManager()); - ReturnUserInput(); + base.Content.Add(InputManager = new ManualInputManager { UseParentInput = true }); } /// diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs index 50cb839ed9..fb10244b12 100644 --- a/osu.Game/Tests/Visual/PlayerTestCase.cs +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; @@ -23,7 +24,11 @@ namespace osu.Game.Tests.Visual protected PlayerTestCase(Ruleset ruleset) { this.ruleset = ruleset; + } + [BackgroundDependencyLoader] + private void load() + { Add(new Box { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Tests/Visual/ScreenTestCase.cs b/osu.Game/Tests/Visual/ScreenTestCase.cs index eec60d01c5..981f9acb63 100644 --- a/osu.Game/Tests/Visual/ScreenTestCase.cs +++ b/osu.Game/Tests/Visual/ScreenTestCase.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Screens; @@ -9,11 +10,12 @@ namespace osu.Game.Tests.Visual /// /// A test case which can be used to test a screen (that relies on OnEntering being called to execute startup instructions). /// - public abstract class ScreenTestCase : OsuTestCase + public abstract class ScreenTestCase : ManualInputManagerTestCase { - private readonly OsuScreenStack stack; + private OsuScreenStack stack; - protected ScreenTestCase() + [BackgroundDependencyLoader] + private void load() { Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }; } From b4d785c76cea8b297e98ff7a0685241e38a2fac3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Mar 2019 20:25:47 +0900 Subject: [PATCH 4/7] Don't update gameplay loop while paused --- osu.Game/Rulesets/UI/FrameStabilityContainer.cs | 5 ++++- osu.Game/Screens/Play/GameplayClock.cs | 3 +++ osu.Game/Screens/Play/GameplayClockContainer.cs | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index 161e7aecb4..deec2b8eac 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -36,7 +36,10 @@ namespace osu.Game.Rulesets.UI private void load(GameplayClock clock) { if (clock != null) + { parentGameplayClock = clock; + gameplayClock.IsPaused.BindTo(clock.IsPaused); + } } protected override void LoadComplete() @@ -68,7 +71,7 @@ namespace osu.Game.Rulesets.UI public override bool UpdateSubTree() { requireMoreUpdateLoops = true; - validState = true; + validState = !gameplayClock.IsPaused.Value; int loops = 0; diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index 0400bfbc27..3efcfa0f65 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Timing; namespace osu.Game.Screens.Play @@ -17,6 +18,8 @@ namespace osu.Game.Screens.Play { private readonly IFrameBasedClock underlyingClock; + public readonly BindableBool IsPaused = new BindableBool(); + public GameplayClock(IFrameBasedClock underlyingClock) { this.underlyingClock = underlyingClock; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index deac5e02bf..546364b26d 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -79,6 +79,8 @@ namespace osu.Game.Screens.Play // the clock to be exposed via DI to children. GameplayClock = new GameplayClock(offsetClock); + + GameplayClock.IsPaused.BindTo(IsPaused); } [BackgroundDependencyLoader] From fbc97edc5567a6b55f4a71286563f3b0d76b95b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 13:39:19 +0900 Subject: [PATCH 5/7] Add base cursor class to retrieve true visibility state --- .../TestCaseGameplayCursor.cs | 3 ++- .../Edit/DrawableOsuEditRuleset.cs | 3 +-- .../UI/Cursor/GameplayCursorContainer.cs | 6 ++--- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 9 ++----- osu.Game/Rulesets/UI/DrawableRuleset.cs | 6 +++-- .../Rulesets/UI/GameplayCursorContainer.cs | 25 +++++++++++++++++++ osu.Game/Rulesets/UI/Playfield.cs | 5 ++-- 7 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 osu.Game/Rulesets/UI/GameplayCursorContainer.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs index 5c1e775c01..1e2a936002 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Cursor; using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Rulesets.UI; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests @@ -27,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Tests [BackgroundDependencyLoader] private void load() { - Add(cursorContainer = new GameplayCursorContainer { RelativeSizeAxes = Axes.Both }); + Add(cursorContainer = new OsuCursorContainer { RelativeSizeAxes = Axes.Both }); } } } diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index 1a6e78d918..3ae554a5d7 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Edit private class OsuPlayfieldNoCursor : OsuPlayfield { - protected override CursorContainer CreateCursor() => null; + protected override GameplayCursorContainer CreateCursor() => null; } } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs index 8c6723f5be..ba6b27f743 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs @@ -6,7 +6,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Game.Beatmaps; @@ -14,10 +13,11 @@ using osu.Game.Configuration; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; +using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.UI.Cursor { - public class GameplayCursorContainer : CursorContainer, IKeyBindingHandler + public class OsuCursorContainer : GameplayCursorContainer, IKeyBindingHandler { protected override Drawable CreateCursor() => new OsuCursor(); @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly Container fadeContainer; - public GameplayCursorContainer() + public OsuCursorContainer() { InternalChild = fadeContainer = new Container { diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 51733c3c01..f68aee7e0c 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; using osu.Game.Rulesets.UI; using System.Linq; -using osu.Framework.Graphics.Cursor; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.UI.Cursor; @@ -24,11 +23,7 @@ namespace osu.Game.Rulesets.Osu.UI public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); - private readonly PlayfieldAdjustmentContainer adjustmentContainer; - - protected override Container CursorTargetContainer => adjustmentContainer; - - protected override CursorContainer CreateCursor() => new GameplayCursorContainer(); + protected override GameplayCursorContainer CreateCursor() => new OsuCursorContainer(); public OsuPlayfield() { @@ -37,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.UI Size = new Vector2(0.75f); - InternalChild = adjustmentContainer = new PlayfieldAdjustmentContainer + InternalChild = new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 31c0afd743..d5b150d2fa 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -263,7 +263,9 @@ namespace osu.Game.Rulesets.UI protected override bool OnHover(HoverEvent e) => true; // required for IProvideCursor - public override CursorContainer Cursor => Playfield.Cursor; + CursorContainer IProvideCursor.Cursor => Playfield.Cursor; + + public override GameplayCursorContainer Cursor => Playfield.Cursor; public bool ProvidingUserCursor => Playfield.Cursor != null && !HasReplayLoaded.Value; @@ -333,7 +335,7 @@ namespace osu.Game.Rulesets.UI /// /// The cursor being displayed by the . May be null if no cursor is provided. /// - public abstract CursorContainer Cursor { get; } + public abstract GameplayCursorContainer Cursor { get; } /// /// Sets a replay to be used, overriding local input. diff --git a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs new file mode 100644 index 0000000000..de73c08809 --- /dev/null +++ b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; + +namespace osu.Game.Rulesets.UI +{ + public class GameplayCursorContainer : CursorContainer + { + /// + /// Because Show/Hide are executed by a parent, is updated immediately even if the cursor + /// is in a non-updating state (via limitations). + /// + /// This holds the true visibility value. + /// + public Visibility LastFrameState; + + protected override void Update() + { + base.Update(); + LastFrameState = State; + } + } +} diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 78d14a27e3..1c4d765da6 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -10,7 +10,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osuTK; @@ -90,14 +89,14 @@ namespace osu.Game.Rulesets.UI /// /// The cursor currently being used by this . May be null if no cursor is provided. /// - public CursorContainer Cursor { get; private set; } + public GameplayCursorContainer Cursor { get; private set; } /// /// Provide an optional cursor which is to be used for gameplay. /// If providing a cursor, must also point to a valid target container. /// /// The cursor, or null if a cursor is not rqeuired. - protected virtual CursorContainer CreateCursor() => null; + protected virtual GameplayCursorContainer CreateCursor() => null; /// /// The target container to add the cursor after it is created. From 2951d3e0e43ebeb260b3778d1a0ca14005814bb0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 13:50:30 +0900 Subject: [PATCH 6/7] Apply CI fixes --- .../Cursor/{GameplayCursorContainer.cs => OsuCursorContainer.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Rulesets.Osu/UI/Cursor/{GameplayCursorContainer.cs => OsuCursorContainer.cs} (100%) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs similarity index 100% rename from osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs rename to osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs From 7cfc2f7dcbc7c1da9a9f8dce0ac0b42224d8e937 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 17:11:14 +0900 Subject: [PATCH 7/7] Add back adjustment container --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index f68aee7e0c..001069f9d8 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -23,6 +23,10 @@ namespace osu.Game.Rulesets.Osu.UI public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); + private readonly PlayfieldAdjustmentContainer adjustmentContainer; + + protected override Container CursorTargetContainer => adjustmentContainer; + protected override GameplayCursorContainer CreateCursor() => new OsuCursorContainer(); public OsuPlayfield() @@ -32,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.UI Size = new Vector2(0.75f); - InternalChild = new PlayfieldAdjustmentContainer + InternalChild = adjustmentContainer = new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[]