From f6591851c3a6f7ac3d198e940a813019046fbe55 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 30 Nov 2017 22:01:49 +0900 Subject: [PATCH 01/39] Implement a selection dragger box --- osu.Game/Rulesets/Edit/PlayfieldOverlay.cs | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs index 58b15e3de2..77aeed42e3 100644 --- a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs +++ b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs @@ -1,19 +1,69 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Rulesets.Edit { public class PlayfieldOverlay : CompositeDrawable { + private readonly Drawable dragBox; + public PlayfieldOverlay() { RelativeSizeAxes = Axes.Both; + InternalChildren = new[] + { + dragBox = new Container + { + Masking = true, + BorderColour = Color4.White, + BorderThickness = 2, + MaskingSmoothness = 1, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + }; } + private Vector2 dragStartPos; + protected override bool OnDragStart(InputState state) + { + dragStartPos = ToLocalSpace(state.Mouse.NativeState.Position); + return true; + } + + protected override bool OnDrag(InputState state) + { + var dragPos = ToLocalSpace(state.Mouse.NativeState.Position); + var dragRectangle = RectangleF.FromLTRB( + Math.Min(dragStartPos.X, dragPos.X), + Math.Min(dragStartPos.Y, dragPos.Y), + Math.Max(dragStartPos.X, dragPos.X), + Math.Max(dragStartPos.Y, dragPos.Y)); + + dragBox.Position = dragRectangle.Location; + dragBox.Size = dragRectangle.Size; + + return true; + } + + protected override bool OnDragEnd(InputState state) + { + return true; + } } } From cf859a6cf2449896e38e5acd431176e2d20d8192 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 2 Dec 2017 00:26:02 +0900 Subject: [PATCH 02/39] Make the dragger attach to objects it surrounds Plus a lot more implementation. --- osu-framework | 2 +- .../Objects/Drawables/DrawableSlider.cs | 4 ++ .../Objects/Drawables/Pieces/SliderBody.cs | 5 +- .../Visual/TestCaseEditorCompose.cs | 2 + .../Visual/TestCaseEditorPlayfieldOverlay.cs | 54 +++++++++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 1 + osu.Game/Rulesets/Edit/HitObjectComposer.cs | 6 +- osu.Game/Rulesets/Edit/PlayfieldOverlay.cs | 68 +++++++++++++++++-- osu.Game/Rulesets/Edit/SelectionDragger.cs | 12 ++++ .../Objects/Drawables/DrawableHitObject.cs | 12 ++++ osu.Game/Rulesets/UI/RulesetContainer.cs | 17 ++--- osu.Game/osu.Game.csproj | 2 + 12 files changed, 167 insertions(+), 18 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseEditorPlayfieldOverlay.cs create mode 100644 osu.Game/Rulesets/Edit/SelectionDragger.cs diff --git a/osu-framework b/osu-framework index 4fc866eee3..d231ca9f79 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 4fc866eee3803f88b155150e32e021b9c21e647f +Subproject commit d231ca9f79936f3a7f3cff0c7721587755ae168c diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 74454ca555..7e6892e70b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Judgements; +using osu.Framework.Graphics.Primitives; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -165,6 +166,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } public Drawable ProxiedLayer => initialCircle.ApproachCircle; + + public override Vector2 SelectionPoint => body.Position; + public override Quad SelectionQuad => body.PathDrawQuad; } internal interface ISliderProgress diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 2082e9a27b..75c2c15084 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -14,6 +14,7 @@ using osu.Game.Configuration; using OpenTK; using OpenTK.Graphics.ES30; using OpenTK.Graphics; +using osu.Framework.Graphics.Primitives; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { @@ -49,6 +50,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } + public Quad PathDrawQuad => container.ScreenSpaceDrawQuad; + private int textureWidth => (int)PathWidth * 2; private readonly Slider slider; @@ -182,4 +185,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces SetRange(start, end); } } -} \ No newline at end of file +} diff --git a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs index d52f27f4ab..226329a852 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs @@ -2,8 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Screens.Compose; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseEditorPlayfieldOverlay.cs b/osu.Game.Tests/Visual/TestCaseEditorPlayfieldOverlay.cs new file mode 100644 index 0000000000..f0da23955d --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseEditorPlayfieldOverlay.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Timing; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Edit; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.UI; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseEditorPlayfieldOverlay : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { typeof(PlayfieldOverlay) }; + + public TestCaseEditorPlayfieldOverlay() + { + var playfield = new OsuEditPlayfield(); + playfield.Add(new DrawableHitCircle(new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f })); + playfield.Add(new DrawableHitCircle(new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f })); + playfield.Add(new DrawableSlider(new Slider + { + ControlPoints = new List + { + new Vector2(128, 256), + new Vector2(344, 256), + }, + Distance = 400, + Position = new Vector2(128, 256), + Velocity = 1, + TickDistance = 100, + Scale = 0.5f + })); + + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Clock = new FramedClock(new StopwatchClock()), + Child = playfield + }, + new PlayfieldOverlay(playfield) + }; + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index ae88fb004f..b8dce4e4f6 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -110,6 +110,7 @@ + diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index f55b7b0531..41958df29b 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Edit Alpha = 0, AlwaysPresent = true, }, - CreateUnderlay(rulesetContainer.Playfield), + CreateUnderlay(), rulesetContainer, CreateOverlay(rulesetContainer.Playfield) } @@ -106,9 +106,9 @@ namespace osu.Game.Rulesets.Edit protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true); - protected virtual PlayfieldUnderlay CreateUnderlay(Playfield playfield) => new PlayfieldUnderlay(); + protected virtual PlayfieldUnderlay CreateUnderlay() => new PlayfieldUnderlay(); - protected virtual PlayfieldOverlay CreateOverlay(Playfield playfield) => new PlayfieldOverlay(); + protected virtual PlayfieldOverlay CreateOverlay(Playfield playfield) => new PlayfieldOverlay(playfield); protected abstract IReadOnlyList CompositionTools { get; } } diff --git a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs index 77aeed42e3..98b3bce265 100644 --- a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs +++ b/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs @@ -9,15 +9,27 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using OpenTK; using OpenTK.Graphics; +using System.Collections.Generic; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; +using System.Linq; +using osu.Game.Graphics; namespace osu.Game.Rulesets.Edit { public class PlayfieldOverlay : CompositeDrawable { - private readonly Drawable dragBox; + private readonly static Color4 selection_normal_colour = Color4.White; + private readonly static Color4 selection_attached_colour = OsuColour.FromHex("eeaa00"); - public PlayfieldOverlay() + private readonly Container dragBox; + + private readonly Playfield playfield; + + public PlayfieldOverlay(Playfield playfield) { + this.playfield = playfield; + RelativeSizeAxes = Axes.Both; InternalChildren = new[] @@ -31,25 +43,31 @@ namespace osu.Game.Rulesets.Edit Child = new Box { RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true + Alpha = 0.1f } } }; } private Vector2 dragStartPos; + private RectangleF dragRectangle; + private List capturedHitObjects = new List(); protected override bool OnDragStart(InputState state) { dragStartPos = ToLocalSpace(state.Mouse.NativeState.Position); + dragBox.Position = dragStartPos; + dragBox.Size = Vector2.Zero; + dragBox.FadeTo(1); + dragBox.FadeColour(selection_normal_colour); + dragBox.BorderThickness = 2; return true; } protected override bool OnDrag(InputState state) { var dragPos = ToLocalSpace(state.Mouse.NativeState.Position); - var dragRectangle = RectangleF.FromLTRB( + dragRectangle = RectangleF.FromLTRB( Math.Min(dragStartPos.X, dragPos.X), Math.Min(dragStartPos.Y, dragPos.Y), Math.Max(dragStartPos.X, dragPos.X), @@ -58,11 +76,51 @@ namespace osu.Game.Rulesets.Edit dragBox.Position = dragRectangle.Location; dragBox.Size = dragRectangle.Size; + updateCapturedHitObjects(); + return true; } + private void updateCapturedHitObjects() + { + capturedHitObjects.Clear(); + + foreach (var obj in playfield.HitObjects.Objects) + { + if (!obj.IsAlive || !obj.IsPresent) + continue; + + var objectPosition = obj.Parent.ToScreenSpace(obj.SelectionPoint); + if (dragRectangle.Contains(ToLocalSpace(objectPosition))) + capturedHitObjects.Add(obj); + } + } + protected override bool OnDragEnd(InputState state) { + if (capturedHitObjects.Count == 0) + dragBox.FadeOut(400, Easing.OutQuint); + else + { + // Move the rectangle to cover the hitobjects + var topLeft = new Vector2(float.MaxValue, float.MaxValue); + var bottomRight = new Vector2(float.MinValue, float.MinValue); + + foreach (var obj in capturedHitObjects) + { + topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(obj.SelectionQuad.TopLeft)); + bottomRight = Vector2.ComponentMax(bottomRight, ToLocalSpace(obj.SelectionQuad.BottomRight)); + } + + topLeft -= new Vector2(5); + bottomRight += new Vector2(5); + + dragBox.MoveTo(topLeft, 200, Easing.OutQuint) + .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint) + .FadeColour(selection_attached_colour, 200, Easing.OutQuint); + dragBox.BorderThickness = 3; + } + return true; } } diff --git a/osu.Game/Rulesets/Edit/SelectionDragger.cs b/osu.Game/Rulesets/Edit/SelectionDragger.cs new file mode 100644 index 0000000000..35ea3a375e --- /dev/null +++ b/osu.Game/Rulesets/Edit/SelectionDragger.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Rulesets.Edit +{ + public class SelectionDragger : CompositeDrawable + { + + } +} diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 941cedca3f..9eecb9b4f5 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -14,6 +14,8 @@ using osu.Game.Audio; using System.Linq; using osu.Game.Graphics; using osu.Framework.Configuration; +using OpenTK; +using osu.Framework.Graphics.Primitives; namespace osu.Game.Rulesets.Objects.Drawables { @@ -38,6 +40,16 @@ namespace osu.Game.Rulesets.Objects.Drawables { HitObject = hitObject; } + + /// + /// The local point that causes this to be selected in the Editor. + /// + public virtual Vector2 SelectionPoint => DrawPosition; + + /// + /// The local rectangle that outlines this for selections in the Editor. + /// + public virtual Quad SelectionQuad => ScreenSpaceDrawQuad; } public abstract class DrawableHitObject : DrawableHitObject diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 69bf6bba29..5b4565e8a8 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -55,10 +55,11 @@ namespace osu.Game.Rulesets.UI public abstract IEnumerable Objects { get; } + private Playfield playfield; /// /// The playfield. /// - public Playfield Playfield { get; protected set; } + public Playfield Playfield => playfield ?? (playfield = CreatePlayfield()); protected readonly Ruleset Ruleset; @@ -95,6 +96,12 @@ namespace osu.Game.Rulesets.UI Replay = replay; ReplayInputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null; } + + /// + /// Creates a Playfield. + /// + /// The Playfield. + protected abstract Playfield CreatePlayfield(); } /// @@ -198,7 +205,7 @@ namespace osu.Game.Rulesets.UI }); AddInternal(KeyBindingInputManager); - KeyBindingInputManager.Add(Playfield = CreatePlayfield()); + KeyBindingInputManager.Add(Playfield); loadObjects(); } @@ -286,12 +293,6 @@ namespace osu.Game.Rulesets.UI /// The HitObject to make drawable. /// The DrawableHitObject. protected abstract DrawableHitObject GetVisualRepresentation(TObject h); - - /// - /// Creates a Playfield. - /// - /// The Playfield. - protected abstract Playfield CreatePlayfield(); } /// diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ad1370890f..c12ecc8b14 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -304,6 +304,7 @@ + @@ -567,6 +568,7 @@ + From faa921ba05790c42ee9d6df15f360bb032023bab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Dec 2017 17:41:10 +0900 Subject: [PATCH 03/39] Fix up post-merge issues --- osu-framework | 2 +- ...layfieldOverlay.cs => TestCaseEditorSelectionLayer.cs} | 8 ++++---- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- .../Edit/{PlayfieldOverlay.cs => SelectionLayer.cs} | 4 ++-- osu.Game/osu.Game.csproj | 1 + 5 files changed, 9 insertions(+), 8 deletions(-) rename osu.Game.Tests/Visual/{TestCaseEditorPlayfieldOverlay.cs => TestCaseEditorSelectionLayer.cs} (87%) rename osu.Game/Rulesets/Edit/{PlayfieldOverlay.cs => SelectionLayer.cs} (94%) diff --git a/osu-framework b/osu-framework index d231ca9f79..797a351db2 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit d231ca9f79936f3a7f3cff0c7721587755ae168c +Subproject commit 797a351db2e852fef5296453641ffbf6b2f6dc11 diff --git a/osu.Game.Tests/Visual/TestCaseEditorPlayfieldOverlay.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs similarity index 87% rename from osu.Game.Tests/Visual/TestCaseEditorPlayfieldOverlay.cs rename to osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index f0da23955d..79f3e4f1d3 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorPlayfieldOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -16,11 +16,11 @@ using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Tests.Visual { - public class TestCaseEditorPlayfieldOverlay : OsuTestCase + public class TestCaseEditorSelectionLayer : OsuTestCase { - public override IReadOnlyList RequiredTypes => new[] { typeof(PlayfieldOverlay) }; + public override IReadOnlyList RequiredTypes => new[] { typeof(SelectionLayer) }; - public TestCaseEditorPlayfieldOverlay() + public TestCaseEditorSelectionLayer() { var playfield = new OsuEditPlayfield(); playfield.Add(new DrawableHitCircle(new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f })); @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual Clock = new FramedClock(new StopwatchClock()), Child = playfield }, - new PlayfieldOverlay(playfield) + new SelectionLayer(playfield) }; } } diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index b7536112e3..1596e7e961 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -108,7 +108,7 @@ - + diff --git a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs b/osu.Game/Rulesets/Edit/SelectionLayer.cs similarity index 94% rename from osu.Game/Rulesets/Edit/PlayfieldOverlay.cs rename to osu.Game/Rulesets/Edit/SelectionLayer.cs index 98b3bce265..cfe5f8ae5e 100644 --- a/osu.Game/Rulesets/Edit/PlayfieldOverlay.cs +++ b/osu.Game/Rulesets/Edit/SelectionLayer.cs @@ -17,7 +17,7 @@ using osu.Game.Graphics; namespace osu.Game.Rulesets.Edit { - public class PlayfieldOverlay : CompositeDrawable + public class SelectionLayer : CompositeDrawable { private readonly static Color4 selection_normal_colour = Color4.White; private readonly static Color4 selection_attached_colour = OsuColour.FromHex("eeaa00"); @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Edit private readonly Playfield playfield; - public PlayfieldOverlay(Playfield playfield) + public SelectionLayer(Playfield playfield) { this.playfield = playfield; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 660d7cb5e6..d74774e403 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -565,6 +565,7 @@ + From 5341e791029201976bbf401f8cf4615c1086e4c6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Dec 2017 17:51:15 +0900 Subject: [PATCH 04/39] Remove SelectionDragger for now --- osu.Game/Rulesets/Edit/SelectionDragger.cs | 12 ------------ osu.Game/osu.Game.csproj | 1 - 2 files changed, 13 deletions(-) delete mode 100644 osu.Game/Rulesets/Edit/SelectionDragger.cs diff --git a/osu.Game/Rulesets/Edit/SelectionDragger.cs b/osu.Game/Rulesets/Edit/SelectionDragger.cs deleted file mode 100644 index 35ea3a375e..0000000000 --- a/osu.Game/Rulesets/Edit/SelectionDragger.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics.Containers; - -namespace osu.Game.Rulesets.Edit -{ - public class SelectionDragger : CompositeDrawable - { - - } -} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d74774e403..99156e6658 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -564,7 +564,6 @@ - From 4573cc3322289861742caf7ae6e3c4d06ec8c45b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 17:45:03 +0900 Subject: [PATCH 05/39] Refactor into a new DragBox class, representing a single drag --- osu.Game/Rulesets/Edit/SelectionLayer.cs | 142 ++++++++++-------- .../Objects/Drawables/DrawableHitObject.cs | 2 +- 2 files changed, 81 insertions(+), 63 deletions(-) diff --git a/osu.Game/Rulesets/Edit/SelectionLayer.cs b/osu.Game/Rulesets/Edit/SelectionLayer.cs index cfe5f8ae5e..21f7a9d796 100644 --- a/osu.Game/Rulesets/Edit/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/SelectionLayer.cs @@ -19,11 +19,6 @@ namespace osu.Game.Rulesets.Edit { public class SelectionLayer : CompositeDrawable { - private readonly static Color4 selection_normal_colour = Color4.White; - private readonly static Color4 selection_attached_colour = OsuColour.FromHex("eeaa00"); - - private readonly Container dragBox; - private readonly Playfield playfield; public SelectionLayer(Playfield playfield) @@ -31,56 +26,26 @@ namespace osu.Game.Rulesets.Edit this.playfield = playfield; RelativeSizeAxes = Axes.Both; - - InternalChildren = new[] - { - dragBox = new Container - { - Masking = true, - BorderColour = Color4.White, - BorderThickness = 2, - MaskingSmoothness = 1, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.1f - } - } - }; } - private Vector2 dragStartPos; - private RectangleF dragRectangle; - private List capturedHitObjects = new List(); + private DragBox dragBox; protected override bool OnDragStart(InputState state) { - dragStartPos = ToLocalSpace(state.Mouse.NativeState.Position); - dragBox.Position = dragStartPos; - dragBox.Size = Vector2.Zero; - dragBox.FadeTo(1); - dragBox.FadeColour(selection_normal_colour); - dragBox.BorderThickness = 2; + dragBox?.Hide(); + AddInternal(dragBox = new DragBox(ToLocalSpace(state.Mouse.NativeState.Position))); return true; } protected override bool OnDrag(InputState state) { - var dragPos = ToLocalSpace(state.Mouse.NativeState.Position); - dragRectangle = RectangleF.FromLTRB( - Math.Min(dragStartPos.X, dragPos.X), - Math.Min(dragStartPos.Y, dragPos.Y), - Math.Max(dragStartPos.X, dragPos.X), - Math.Max(dragStartPos.Y, dragPos.Y)); - - dragBox.Position = dragRectangle.Location; - dragBox.Size = dragRectangle.Size; + dragBox.ExpandTo(ToLocalSpace(state.Mouse.NativeState.Position)); updateCapturedHitObjects(); - return true; } + private List capturedHitObjects = new List(); private void updateCapturedHitObjects() { capturedHitObjects.Clear(); @@ -90,8 +55,8 @@ namespace osu.Game.Rulesets.Edit if (!obj.IsAlive || !obj.IsPresent) continue; - var objectPosition = obj.Parent.ToScreenSpace(obj.SelectionPoint); - if (dragRectangle.Contains(ToLocalSpace(objectPosition))) + var objectPosition = obj.ToScreenSpace(obj.SelectionPoint); + if (dragBox.ScreenSpaceDrawQuad.Contains(objectPosition)) capturedHitObjects.Add(obj); } } @@ -99,29 +64,82 @@ namespace osu.Game.Rulesets.Edit protected override bool OnDragEnd(InputState state) { if (capturedHitObjects.Count == 0) - dragBox.FadeOut(400, Easing.OutQuint); + dragBox.Hide(); else - { - // Move the rectangle to cover the hitobjects - var topLeft = new Vector2(float.MaxValue, float.MaxValue); - var bottomRight = new Vector2(float.MinValue, float.MinValue); - - foreach (var obj in capturedHitObjects) - { - topLeft = Vector2.ComponentMin(topLeft, ToLocalSpace(obj.SelectionQuad.TopLeft)); - bottomRight = Vector2.ComponentMax(bottomRight, ToLocalSpace(obj.SelectionQuad.BottomRight)); - } - - topLeft -= new Vector2(5); - bottomRight += new Vector2(5); - - dragBox.MoveTo(topLeft, 200, Easing.OutQuint) - .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint) - .FadeColour(selection_attached_colour, 200, Easing.OutQuint); - dragBox.BorderThickness = 3; - } + dragBox.Capture(capturedHitObjects); + return true; + } + protected override bool OnClick(InputState state) + { + dragBox?.Hide(); return true; } } + + public class DragBox : CompositeDrawable + { + private readonly Drawable background; + private readonly Vector2 startPos; + + public DragBox(Vector2 startPos) + { + this.startPos = startPos; + + Masking = true; + BorderColour = Color4.White; + BorderThickness = 2; + MaskingSmoothness = 1; + InternalChild = background = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.1f, + AlwaysPresent = true + }; + } + + public void ExpandTo(Vector2 position) + { + var trackingRectangle = RectangleF.FromLTRB( + Math.Min(startPos.X, position.X), + Math.Min(startPos.Y, position.Y), + Math.Max(startPos.X, position.X), + Math.Max(startPos.Y, position.Y)); + + Position = trackingRectangle.Location; + Size = trackingRectangle.Size; + } + + public void Capture(IEnumerable hitObjects) + { + // Move the rectangle to cover the hitobjects + var topLeft = new Vector2(float.MaxValue, float.MaxValue); + var bottomRight = new Vector2(float.MinValue, float.MinValue); + + foreach (var obj in hitObjects) + { + topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.SelectionQuad.TopLeft)); + bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.SelectionQuad.BottomRight)); + } + + topLeft -= new Vector2(5); + bottomRight += new Vector2(5); + + this.MoveTo(topLeft, 200, Easing.OutQuint) + .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint); + + background.FadeOut(200); + + BorderThickness = 3; + } + + private bool isActive = true; + public override bool HandleInput => isActive; + + public override void Hide() + { + isActive = false; + this.FadeOut(400, Easing.OutQuint).Expire(); + } + } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 9eecb9b4f5..c81039c25d 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// The local point that causes this to be selected in the Editor. /// - public virtual Vector2 SelectionPoint => DrawPosition; + public virtual Vector2 SelectionPoint => Vector2.Zero; /// /// The local rectangle that outlines this for selections in the Editor. From b28306d3c0fcd72ced0f9a9753e70dd6ff47636a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 18:06:05 +0900 Subject: [PATCH 06/39] Fix incorrect SelectionPoint --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index c81039c25d..834bfd53a2 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// The local point that causes this to be selected in the Editor. /// - public virtual Vector2 SelectionPoint => Vector2.Zero; + public virtual Vector2 SelectionPoint => DrawSize / 2f; /// /// The local rectangle that outlines this for selections in the Editor. From 5147b342dceb700dd585eaa9944f62f610642f2b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 19:07:40 +0900 Subject: [PATCH 07/39] More refactorings + add markers Move --- osu.Game/Rulesets/Edit/SelectionLayer.cs | 197 ++++++++++++++++++----- 1 file changed, 158 insertions(+), 39 deletions(-) diff --git a/osu.Game/Rulesets/Edit/SelectionLayer.cs b/osu.Game/Rulesets/Edit/SelectionLayer.cs index 21f7a9d796..a8c67e8ce8 100644 --- a/osu.Game/Rulesets/Edit/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/SelectionLayer.cs @@ -14,6 +14,8 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using System.Linq; using osu.Game.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Edit { @@ -28,45 +30,32 @@ namespace osu.Game.Rulesets.Edit RelativeSizeAxes = Axes.Both; } - private DragBox dragBox; + private DragContainer dragBox; protected override bool OnDragStart(InputState state) { dragBox?.Hide(); - AddInternal(dragBox = new DragBox(ToLocalSpace(state.Mouse.NativeState.Position))); + AddInternal(dragBox = new DragContainer(ToLocalSpace(state.Mouse.NativeState.Position)) + { + CapturableObjects = playfield.HitObjects.Objects + }); + return true; } protected override bool OnDrag(InputState state) { - dragBox.ExpandTo(ToLocalSpace(state.Mouse.NativeState.Position)); - - updateCapturedHitObjects(); + dragBox.Track(ToLocalSpace(state.Mouse.NativeState.Position)); + dragBox.UpdateCapture(); return true; } - private List capturedHitObjects = new List(); - private void updateCapturedHitObjects() - { - capturedHitObjects.Clear(); - - foreach (var obj in playfield.HitObjects.Objects) - { - if (!obj.IsAlive || !obj.IsPresent) - continue; - - var objectPosition = obj.ToScreenSpace(obj.SelectionPoint); - if (dragBox.ScreenSpaceDrawQuad.Contains(objectPosition)) - capturedHitObjects.Add(obj); - } - } - protected override bool OnDragEnd(InputState state) { - if (capturedHitObjects.Count == 0) + if (dragBox.CapturedHitObjects.Count == 0) dragBox.Hide(); else - dragBox.Capture(capturedHitObjects); + dragBox.FinishCapture(); return true; } @@ -77,28 +66,53 @@ namespace osu.Game.Rulesets.Edit } } - public class DragBox : CompositeDrawable + public class DragContainer : CompositeDrawable { + public IEnumerable CapturableObjects; + + private readonly Container borderMask; private readonly Drawable background; + private readonly MarkerContainer markers; + + private Color4 captureFinishedColour; + private readonly Vector2 startPos; - public DragBox(Vector2 startPos) + public DragContainer(Vector2 startPos) { this.startPos = startPos; - Masking = true; - BorderColour = Color4.White; - BorderThickness = 2; - MaskingSmoothness = 1; - InternalChild = background = new Box + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Alpha = 0.1f, - AlwaysPresent = true + borderMask = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderColour = Color4.White, + BorderThickness = 2, + MaskingSmoothness = 1, + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.1f, + AlwaysPresent = true + }, + }, + markers = new MarkerContainer + { + RelativeSizeAxes = Axes.Both, + Alpha = 0 + } }; } - public void ExpandTo(Vector2 position) + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + captureFinishedColour = colours.Yellow; + } + + public void Track(Vector2 position) { var trackingRectangle = RectangleF.FromLTRB( Math.Min(startPos.X, position.X), @@ -110,13 +124,31 @@ namespace osu.Game.Rulesets.Edit Size = trackingRectangle.Size; } - public void Capture(IEnumerable hitObjects) + private List capturedHitObjects = new List(); + public IReadOnlyList CapturedHitObjects => capturedHitObjects; + + public void UpdateCapture() + { + capturedHitObjects.Clear(); + + foreach (var obj in CapturableObjects) + { + if (!obj.IsAlive || !obj.IsPresent) + continue; + + var objectPosition = obj.ToScreenSpace(obj.SelectionPoint); + if (ScreenSpaceDrawQuad.Contains(objectPosition)) + capturedHitObjects.Add(obj); + } + } + + public void FinishCapture() { // Move the rectangle to cover the hitobjects var topLeft = new Vector2(float.MaxValue, float.MaxValue); var bottomRight = new Vector2(float.MinValue, float.MinValue); - foreach (var obj in hitObjects) + foreach (var obj in capturedHitObjects) { topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.SelectionQuad.TopLeft)); bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.SelectionQuad.BottomRight)); @@ -126,11 +158,13 @@ namespace osu.Game.Rulesets.Edit bottomRight += new Vector2(5); this.MoveTo(topLeft, 200, Easing.OutQuint) - .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint); + .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint) + .FadeColour(captureFinishedColour, 200); - background.FadeOut(200); + borderMask.BorderThickness = 3; - BorderThickness = 3; + background.Delay(50).FadeOut(200); + markers.FadeIn(200); } private bool isActive = true; @@ -142,4 +176,89 @@ namespace osu.Game.Rulesets.Edit this.FadeOut(400, Easing.OutQuint).Expire(); } } + + public class MarkerContainer : CompositeDrawable + { + public Action ResizeRequested; + + public MarkerContainer() + { + Padding = new MarginPadding(1); + + InternalChildren = new Drawable[] + { + new Marker + { + Anchor = Anchor.TopLeft, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.TopRight, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.BottomRight, + Origin = Anchor.Centre + }, + new CentreMarker + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + } + }; + } + } + + public class Marker : CompositeDrawable + { + private float marker_size = 10; + + public Marker() + { + Size = new Vector2(marker_size); + + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = new Box { RelativeSizeAxes = Axes.Both } + }; + } + } + + public class CentreMarker : CompositeDrawable + { + private float marker_size = 10; + private float line_width = 2; + + public CentreMarker() + { + Size = new Vector2(marker_size); + + InternalChildren = new[] + { + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = line_width + }, + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = line_width + }, + }; + } + } } From 25d80a36be257ad4b7b467c1d40431069b7912fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 21:03:34 +0900 Subject: [PATCH 08/39] Finish up logical implementation of markers --- osu.Game/Rulesets/Edit/SelectionLayer.cs | 147 +++++++++++++++++++---- 1 file changed, 123 insertions(+), 24 deletions(-) diff --git a/osu.Game/Rulesets/Edit/SelectionLayer.cs b/osu.Game/Rulesets/Edit/SelectionLayer.cs index a8c67e8ce8..4e8fba11b0 100644 --- a/osu.Game/Rulesets/Edit/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/SelectionLayer.cs @@ -84,24 +84,36 @@ namespace osu.Game.Rulesets.Edit InternalChildren = new Drawable[] { - borderMask = new Container + new Container { RelativeSizeAxes = Axes.Both, - Masking = true, - BorderColour = Color4.White, - BorderThickness = 2, - MaskingSmoothness = 1, - Child = background = new Box + Padding = new MarginPadding(-1), + Child = borderMask = new Container { RelativeSizeAxes = Axes.Both, - Alpha = 0.1f, - AlwaysPresent = true - }, + Masking = true, + BorderColour = Color4.White, + BorderThickness = 2, + MaskingSmoothness = 1, + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.1f, + AlwaysPresent = true + }, + } }, markers = new MarkerContainer { RelativeSizeAxes = Axes.Both, - Alpha = 0 + Alpha = 0, + GetCaptureRectangle = () => trackingRectangle, + UpdateCapture = r => + { + trackRectangle(r); + UpdateCapture(); + }, + FinishCapture = FinishCapture } }; } @@ -112,16 +124,20 @@ namespace osu.Game.Rulesets.Edit captureFinishedColour = colours.Yellow; } - public void Track(Vector2 position) - { - var trackingRectangle = RectangleF.FromLTRB( - Math.Min(startPos.X, position.X), - Math.Min(startPos.Y, position.Y), - Math.Max(startPos.X, position.X), - Math.Max(startPos.Y, position.Y)); + public void Track(Vector2 position) => trackRectangle(RectangleF.FromLTRB(startPos.X, startPos.Y, position.X, position.Y)); - Position = trackingRectangle.Location; - Size = trackingRectangle.Size; + private RectangleF trackingRectangle; + private void trackRectangle(RectangleF rectangle) + { + trackingRectangle = rectangle; + + Position = new Vector2( + Math.Min(rectangle.Left, rectangle.Right), + Math.Min(rectangle.Top, rectangle.Bottom)); + + Size = new Vector2( + Math.Max(rectangle.Left, rectangle.Right) - Position.X, + Math.Max(rectangle.Top, rectangle.Bottom) - Position.Y); } private List capturedHitObjects = new List(); @@ -144,6 +160,12 @@ namespace osu.Game.Rulesets.Edit public void FinishCapture() { + if (CapturedHitObjects.Count == 0) + { + Hide(); + return; + } + // Move the rectangle to cover the hitobjects var topLeft = new Vector2(float.MaxValue, float.MaxValue); var bottomRight = new Vector2(float.MinValue, float.MinValue); @@ -158,10 +180,12 @@ namespace osu.Game.Rulesets.Edit bottomRight += new Vector2(5); this.MoveTo(topLeft, 200, Easing.OutQuint) - .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint) - .FadeColour(captureFinishedColour, 200); + .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint); + + trackingRectangle = RectangleF.FromLTRB(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y); borderMask.BorderThickness = 3; + borderMask.FadeColour(captureFinishedColour, 200); background.Delay(50).FadeOut(200); markers.FadeIn(200); @@ -179,12 +203,12 @@ namespace osu.Game.Rulesets.Edit public class MarkerContainer : CompositeDrawable { - public Action ResizeRequested; + public Func GetCaptureRectangle; + public Action UpdateCapture; + public Action FinishCapture; public MarkerContainer() { - Padding = new MarginPadding(1); - InternalChildren = new Drawable[] { new Marker @@ -193,31 +217,62 @@ namespace osu.Game.Rulesets.Edit Origin = Anchor.Centre }, new Marker + { + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre + }, + new Marker { Anchor = Anchor.TopRight, Origin = Anchor.Centre }, new Marker + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre + }, + new Marker { Anchor = Anchor.BottomLeft, Origin = Anchor.Centre }, new Marker + { + Anchor = Anchor.CentreRight, + Origin = Anchor.Centre + }, + new Marker { Anchor = Anchor.BottomRight, Origin = Anchor.Centre }, + new Marker + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.Centre + }, new CentreMarker { Anchor = Anchor.Centre, Origin = Anchor.Centre } }; + + InternalChildren.OfType().ForEach(m => + { + m.GetCaptureRectangle = () => GetCaptureRectangle(); + m.UpdateCapture = r => UpdateCapture(r); + m.FinishCapture = () => FinishCapture(); + }); } } public class Marker : CompositeDrawable { + public Func GetCaptureRectangle; + public Action UpdateCapture; + public Action FinishCapture; + private float marker_size = 10; public Marker() @@ -231,6 +286,44 @@ namespace osu.Game.Rulesets.Edit Child = new Box { RelativeSizeAxes = Axes.Both } }; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + } + + protected override bool OnDragStart(InputState state) => true; + + protected override bool OnDrag(InputState state) + { + var currentRectangle = GetCaptureRectangle(); + + float left = currentRectangle.Left; + float right = currentRectangle.Right; + float top = currentRectangle.Top; + float bottom = currentRectangle.Bottom; + + // Apply modifications to the capture rectangle + if ((Anchor & Anchor.y0) > 0) + top += state.Mouse.Delta.Y; + else if ((Anchor & Anchor.y2) > 0) + bottom += state.Mouse.Delta.Y; + + if ((Anchor & Anchor.x0) > 0) + left += state.Mouse.Delta.X; + else if ((Anchor & Anchor.x2) > 0) + right += state.Mouse.Delta.X; + + UpdateCapture(RectangleF.FromLTRB(left, top, right, bottom)); + return true; + } + + protected override bool OnDragEnd(InputState state) + { + FinishCapture(); + return true; + } } public class CentreMarker : CompositeDrawable @@ -260,5 +353,11 @@ namespace osu.Game.Rulesets.Edit }, }; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + } } } From c12c2416335fb9fa65a26075e472bb2934616612 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 21:27:19 +0900 Subject: [PATCH 09/39] Implement hover colours --- osu.Game/Rulesets/Edit/SelectionLayer.cs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Edit/SelectionLayer.cs b/osu.Game/Rulesets/Edit/SelectionLayer.cs index 4e8fba11b0..2c59de06f0 100644 --- a/osu.Game/Rulesets/Edit/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/SelectionLayer.cs @@ -269,11 +269,14 @@ namespace osu.Game.Rulesets.Edit public class Marker : CompositeDrawable { + private const float marker_size = 10; + public Func GetCaptureRectangle; public Action UpdateCapture; public Action FinishCapture; - private float marker_size = 10; + private Color4 normalColour; + private Color4 hoverColour; public Marker() { @@ -290,7 +293,8 @@ namespace osu.Game.Rulesets.Edit [BackgroundDependencyLoader] private void load(OsuColour colours) { - Colour = colours.Yellow; + Colour = normalColour = colours.Yellow; + hoverColour = colours.YellowDarker; } protected override bool OnDragStart(InputState state) => true; @@ -324,12 +328,23 @@ namespace osu.Game.Rulesets.Edit FinishCapture(); return true; } + + protected override bool OnHover(InputState state) + { + this.FadeColour(hoverColour, 100); + return true; + } + + protected override void OnHoverLost(InputState state) + { + this.FadeColour(normalColour, 100); + } } public class CentreMarker : CompositeDrawable { - private float marker_size = 10; - private float line_width = 2; + private const float marker_size = 10; + private const float line_width = 2; public CentreMarker() { From 2f1063c5c05cab75c2370f72fed6c634dffc1fb0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 21:56:58 +0900 Subject: [PATCH 10/39] Refactor into separate files + add xmldocs + rename some methods --- .../Edit/Layers/Selection/CentreMarker.cs | 47 +++ .../Edit/Layers/Selection/DragSelector.cs | 170 ++++++++ .../Rulesets/Edit/Layers/Selection/Marker.cs | 102 +++++ .../Edit/Layers/Selection/MarkerContainer.cs | 89 +++++ .../Edit/Layers/Selection/SelectionLayer.cs | 55 +++ osu.Game/Rulesets/Edit/SelectionLayer.cs | 378 ------------------ osu.Game/osu.Game.csproj | 8 +- 7 files changed, 469 insertions(+), 380 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs create mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs create mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs create mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs create mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs delete mode 100644 osu.Game/Rulesets/Edit/SelectionLayer.cs diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs b/osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs new file mode 100644 index 0000000000..6da6c72849 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs @@ -0,0 +1,47 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using OpenTK; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + /// + /// Represents the centre of a . + /// + public class CentreMarker : CompositeDrawable + { + private const float marker_size = 10; + private const float line_width = 2; + + public CentreMarker() + { + Size = new Vector2(marker_size); + + InternalChildren = new[] + { + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = line_width + }, + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = line_width + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + } + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs b/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs new file mode 100644 index 0000000000..1e86988c01 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.Objects.Drawables; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + /// + /// A box that represents a drag selection. + /// + public class DragSelector : CompositeDrawable + { + /// + /// The s that can be selected through a drag-selection. + /// + public IEnumerable CapturableObjects; + + private readonly Container borderMask; + private readonly Drawable background; + private readonly MarkerContainer markers; + + private Color4 captureFinishedColour; + + private readonly Vector2 startPos; + + /// + /// Creates a new . + /// + /// The point at which the drag was initiated, in the parent's coordinates. + public DragSelector(Vector2 startPos) + { + this.startPos = startPos; + + InternalChildren = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(-1), + Child = borderMask = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderColour = Color4.White, + BorderThickness = 2, + MaskingSmoothness = 1, + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.1f, + AlwaysPresent = true + }, + } + }, + markers = new MarkerContainer + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + GetDragRectangle = () => dragRectangle, + UpdateDragRectangle = r => + { + updateDragRectangle(r); + BeginCapture(); + }, + FinishCapture = FinishCapture + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + captureFinishedColour = colours.Yellow; + } + + /// + /// The secondary corner of the drag selection box. A rectangle will be fit between the starting position and this value. + /// + public Vector2 DragEndPosition { set => updateDragRectangle(RectangleF.FromLTRB(startPos.X, startPos.Y, value.X, value.Y)); } + + private RectangleF dragRectangle; + private void updateDragRectangle(RectangleF rectangle) + { + dragRectangle = rectangle; + + Position = new Vector2( + Math.Min(rectangle.Left, rectangle.Right), + Math.Min(rectangle.Top, rectangle.Bottom)); + + Size = new Vector2( + Math.Max(rectangle.Left, rectangle.Right) - Position.X, + Math.Max(rectangle.Top, rectangle.Bottom) - Position.Y); + } + + private readonly List capturedHitObjects = new List(); + public IReadOnlyList CapturedHitObjects => capturedHitObjects; + + /// + /// Processes hitobjects to determine which ones are captured by the drag selection. + /// Captured hitobjects will be enclosed by the drag selection upon . + /// + public void BeginCapture() + { + capturedHitObjects.Clear(); + + foreach (var obj in CapturableObjects) + { + if (!obj.IsAlive || !obj.IsPresent) + continue; + + var objectPosition = obj.ToScreenSpace(obj.SelectionPoint); + if (ScreenSpaceDrawQuad.Contains(objectPosition)) + capturedHitObjects.Add(obj); + } + } + + /// + /// Encloses hitobjects captured through in the drag selection box. + /// + public void FinishCapture() + { + if (CapturedHitObjects.Count == 0) + { + Hide(); + return; + } + + // Move the rectangle to cover the hitobjects + var topLeft = new Vector2(float.MaxValue, float.MaxValue); + var bottomRight = new Vector2(float.MinValue, float.MinValue); + + foreach (var obj in capturedHitObjects) + { + topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.SelectionQuad.TopLeft)); + bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.SelectionQuad.BottomRight)); + } + + topLeft -= new Vector2(5); + bottomRight += new Vector2(5); + + this.MoveTo(topLeft, 200, Easing.OutQuint) + .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint); + + dragRectangle = RectangleF.FromLTRB(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y); + + borderMask.BorderThickness = 3; + borderMask.FadeColour(captureFinishedColour, 200); + + // Transform into markers to let the user modify the drag selection further. + background.Delay(50).FadeOut(200); + markers.FadeIn(200); + } + + private bool isActive = true; + public override bool HandleInput => isActive; + + public override void Hide() + { + isActive = false; + this.FadeOut(400, Easing.OutQuint).Expire(); + } + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs b/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs new file mode 100644 index 0000000000..3519adb3b3 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs @@ -0,0 +1,102 @@ +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Graphics; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + /// + /// Represents a marker visible on the border of a which exposes + /// properties that are used to resize a . + /// + public class Marker : CompositeDrawable + { + private const float marker_size = 10; + + /// + /// Invoked when this requires the current drag rectangle. + /// + public Func GetDragRectangle; + + /// + /// Invoked when this wants to update the drag rectangle. + /// + public Action UpdateDragRectangle; + + /// + /// Invoked when this has finished updates to the drag rectangle. + /// + public Action FinishCapture; + + private Color4 normalColour; + private Color4 hoverColour; + + public Marker() + { + Size = new Vector2(marker_size); + + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = new Box { RelativeSizeAxes = Axes.Both } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = normalColour = colours.Yellow; + hoverColour = colours.YellowDarker; + } + + protected override bool OnDragStart(InputState state) => true; + + protected override bool OnDrag(InputState state) + { + var currentRectangle = GetDragRectangle(); + + float left = currentRectangle.Left; + float right = currentRectangle.Right; + float top = currentRectangle.Top; + float bottom = currentRectangle.Bottom; + + // Apply modifications to the capture rectangle + if ((Anchor & Anchor.y0) > 0) + top += state.Mouse.Delta.Y; + else if ((Anchor & Anchor.y2) > 0) + bottom += state.Mouse.Delta.Y; + + if ((Anchor & Anchor.x0) > 0) + left += state.Mouse.Delta.X; + else if ((Anchor & Anchor.x2) > 0) + right += state.Mouse.Delta.X; + + UpdateDragRectangle(RectangleF.FromLTRB(left, top, right, bottom)); + return true; + } + + protected override bool OnDragEnd(InputState state) + { + FinishCapture(); + return true; + } + + protected override bool OnHover(InputState state) + { + this.FadeColour(hoverColour, 100); + return true; + } + + protected override void OnHoverLost(InputState state) + { + this.FadeColour(normalColour, 100); + } + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs new file mode 100644 index 0000000000..3b35528cf1 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs @@ -0,0 +1,89 @@ +using System; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + /// + /// A that has s around its border. + /// + public class MarkerContainer : CompositeDrawable + { + /// + /// Invoked when a requires the current drag rectangle. + /// + public Func GetDragRectangle; + + /// + /// Invoked when a wants to update the drag rectangle. + /// + public Action UpdateDragRectangle; + + /// + /// Invoked when a has finished updates to the drag rectangle. + /// + public Action FinishCapture; + + public MarkerContainer() + { + InternalChildren = new Drawable[] + { + new Marker + { + Anchor = Anchor.TopLeft, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.TopRight, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.CentreRight, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.BottomRight, + Origin = Anchor.Centre + }, + new Marker + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.Centre + }, + new CentreMarker + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + } + }; + + InternalChildren.OfType().ForEach(m => + { + m.GetDragRectangle = () => GetDragRectangle(); + m.UpdateDragRectangle = r => UpdateDragRectangle(r); + m.FinishCapture = () => FinishCapture(); + }); + } + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs new file mode 100644 index 0000000000..a38be68461 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2007-2017 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.Input; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + public class SelectionLayer : CompositeDrawable + { + private readonly Playfield playfield; + + public SelectionLayer(Playfield playfield) + { + this.playfield = playfield; + + RelativeSizeAxes = Axes.Both; + } + + private DragSelector selector; + + protected override bool OnDragStart(InputState state) + { + // Hide the previous drag box - we won't be working with it any longer + selector?.Hide(); + AddInternal(selector = new DragSelector(ToLocalSpace(state.Mouse.NativeState.Position)) + { + CapturableObjects = playfield.HitObjects.Objects + }); + + return true; + } + + protected override bool OnDrag(InputState state) + { + selector.DragEndPosition = ToLocalSpace(state.Mouse.NativeState.Position); + selector.BeginCapture(); + return true; + } + + protected override bool OnDragEnd(InputState state) + { + selector.FinishCapture(); + return true; + } + + protected override bool OnClick(InputState state) + { + selector?.Hide(); + return true; + } + } +} diff --git a/osu.Game/Rulesets/Edit/SelectionLayer.cs b/osu.Game/Rulesets/Edit/SelectionLayer.cs deleted file mode 100644 index 2c59de06f0..0000000000 --- a/osu.Game/Rulesets/Edit/SelectionLayer.cs +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using OpenTK; -using OpenTK.Graphics; -using System.Collections.Generic; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.UI; -using System.Linq; -using osu.Game.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Extensions.IEnumerableExtensions; - -namespace osu.Game.Rulesets.Edit -{ - public class SelectionLayer : CompositeDrawable - { - private readonly Playfield playfield; - - public SelectionLayer(Playfield playfield) - { - this.playfield = playfield; - - RelativeSizeAxes = Axes.Both; - } - - private DragContainer dragBox; - - protected override bool OnDragStart(InputState state) - { - dragBox?.Hide(); - AddInternal(dragBox = new DragContainer(ToLocalSpace(state.Mouse.NativeState.Position)) - { - CapturableObjects = playfield.HitObjects.Objects - }); - - return true; - } - - protected override bool OnDrag(InputState state) - { - dragBox.Track(ToLocalSpace(state.Mouse.NativeState.Position)); - dragBox.UpdateCapture(); - return true; - } - - protected override bool OnDragEnd(InputState state) - { - if (dragBox.CapturedHitObjects.Count == 0) - dragBox.Hide(); - else - dragBox.FinishCapture(); - return true; - } - - protected override bool OnClick(InputState state) - { - dragBox?.Hide(); - return true; - } - } - - public class DragContainer : CompositeDrawable - { - public IEnumerable CapturableObjects; - - private readonly Container borderMask; - private readonly Drawable background; - private readonly MarkerContainer markers; - - private Color4 captureFinishedColour; - - private readonly Vector2 startPos; - - public DragContainer(Vector2 startPos) - { - this.startPos = startPos; - - InternalChildren = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(-1), - Child = borderMask = new Container - { - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderColour = Color4.White, - BorderThickness = 2, - MaskingSmoothness = 1, - Child = background = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.1f, - AlwaysPresent = true - }, - } - }, - markers = new MarkerContainer - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - GetCaptureRectangle = () => trackingRectangle, - UpdateCapture = r => - { - trackRectangle(r); - UpdateCapture(); - }, - FinishCapture = FinishCapture - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - captureFinishedColour = colours.Yellow; - } - - public void Track(Vector2 position) => trackRectangle(RectangleF.FromLTRB(startPos.X, startPos.Y, position.X, position.Y)); - - private RectangleF trackingRectangle; - private void trackRectangle(RectangleF rectangle) - { - trackingRectangle = rectangle; - - Position = new Vector2( - Math.Min(rectangle.Left, rectangle.Right), - Math.Min(rectangle.Top, rectangle.Bottom)); - - Size = new Vector2( - Math.Max(rectangle.Left, rectangle.Right) - Position.X, - Math.Max(rectangle.Top, rectangle.Bottom) - Position.Y); - } - - private List capturedHitObjects = new List(); - public IReadOnlyList CapturedHitObjects => capturedHitObjects; - - public void UpdateCapture() - { - capturedHitObjects.Clear(); - - foreach (var obj in CapturableObjects) - { - if (!obj.IsAlive || !obj.IsPresent) - continue; - - var objectPosition = obj.ToScreenSpace(obj.SelectionPoint); - if (ScreenSpaceDrawQuad.Contains(objectPosition)) - capturedHitObjects.Add(obj); - } - } - - public void FinishCapture() - { - if (CapturedHitObjects.Count == 0) - { - Hide(); - return; - } - - // Move the rectangle to cover the hitobjects - var topLeft = new Vector2(float.MaxValue, float.MaxValue); - var bottomRight = new Vector2(float.MinValue, float.MinValue); - - foreach (var obj in capturedHitObjects) - { - topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.SelectionQuad.TopLeft)); - bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.SelectionQuad.BottomRight)); - } - - topLeft -= new Vector2(5); - bottomRight += new Vector2(5); - - this.MoveTo(topLeft, 200, Easing.OutQuint) - .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint); - - trackingRectangle = RectangleF.FromLTRB(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y); - - borderMask.BorderThickness = 3; - borderMask.FadeColour(captureFinishedColour, 200); - - background.Delay(50).FadeOut(200); - markers.FadeIn(200); - } - - private bool isActive = true; - public override bool HandleInput => isActive; - - public override void Hide() - { - isActive = false; - this.FadeOut(400, Easing.OutQuint).Expire(); - } - } - - public class MarkerContainer : CompositeDrawable - { - public Func GetCaptureRectangle; - public Action UpdateCapture; - public Action FinishCapture; - - public MarkerContainer() - { - InternalChildren = new Drawable[] - { - new Marker - { - Anchor = Anchor.TopLeft, - Origin = Anchor.Centre - }, - new Marker - { - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre - }, - new Marker - { - Anchor = Anchor.TopRight, - Origin = Anchor.Centre - }, - new Marker - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre - }, - new Marker - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.Centre - }, - new Marker - { - Anchor = Anchor.CentreRight, - Origin = Anchor.Centre - }, - new Marker - { - Anchor = Anchor.BottomRight, - Origin = Anchor.Centre - }, - new Marker - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.Centre - }, - new CentreMarker - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - } - }; - - InternalChildren.OfType().ForEach(m => - { - m.GetCaptureRectangle = () => GetCaptureRectangle(); - m.UpdateCapture = r => UpdateCapture(r); - m.FinishCapture = () => FinishCapture(); - }); - } - } - - public class Marker : CompositeDrawable - { - private const float marker_size = 10; - - public Func GetCaptureRectangle; - public Action UpdateCapture; - public Action FinishCapture; - - private Color4 normalColour; - private Color4 hoverColour; - - public Marker() - { - Size = new Vector2(marker_size); - - InternalChild = new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Child = new Box { RelativeSizeAxes = Axes.Both } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Colour = normalColour = colours.Yellow; - hoverColour = colours.YellowDarker; - } - - protected override bool OnDragStart(InputState state) => true; - - protected override bool OnDrag(InputState state) - { - var currentRectangle = GetCaptureRectangle(); - - float left = currentRectangle.Left; - float right = currentRectangle.Right; - float top = currentRectangle.Top; - float bottom = currentRectangle.Bottom; - - // Apply modifications to the capture rectangle - if ((Anchor & Anchor.y0) > 0) - top += state.Mouse.Delta.Y; - else if ((Anchor & Anchor.y2) > 0) - bottom += state.Mouse.Delta.Y; - - if ((Anchor & Anchor.x0) > 0) - left += state.Mouse.Delta.X; - else if ((Anchor & Anchor.x2) > 0) - right += state.Mouse.Delta.X; - - UpdateCapture(RectangleF.FromLTRB(left, top, right, bottom)); - return true; - } - - protected override bool OnDragEnd(InputState state) - { - FinishCapture(); - return true; - } - - protected override bool OnHover(InputState state) - { - this.FadeColour(hoverColour, 100); - return true; - } - - protected override void OnHoverLost(InputState state) - { - this.FadeColour(normalColour, 100); - } - } - - public class CentreMarker : CompositeDrawable - { - private const float marker_size = 10; - private const float line_width = 2; - - public CentreMarker() - { - Size = new Vector2(marker_size); - - InternalChildren = new[] - { - new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.X, - Height = line_width - }, - new Box - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = line_width - }, - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Colour = colours.Yellow; - } - } -} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c61a3172f6..207dae1b54 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -310,6 +310,11 @@ + + + + + @@ -573,7 +578,6 @@ - @@ -856,4 +860,4 @@ - + \ No newline at end of file From a303bf71cf5a26b1b181865bab4a2f9830823fdb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 22:19:02 +0900 Subject: [PATCH 11/39] Give control over screen space conversion to DrawableHitObject --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs | 3 +-- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 7e6892e70b..42f54af801 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public Drawable ProxiedLayer => initialCircle.ApproachCircle; - public override Vector2 SelectionPoint => body.Position; + public override Vector2 SelectionPoint => ToScreenSpace(body.Position); public override Quad SelectionQuad => body.PathDrawQuad; } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs b/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs index 1e86988c01..54d5a959a8 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs @@ -115,8 +115,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection if (!obj.IsAlive || !obj.IsPresent) continue; - var objectPosition = obj.ToScreenSpace(obj.SelectionPoint); - if (ScreenSpaceDrawQuad.Contains(objectPosition)) + if (ScreenSpaceDrawQuad.Contains(obj.SelectionPoint)) capturedHitObjects.Add(obj); } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 834bfd53a2..57db36fda5 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -42,12 +42,12 @@ namespace osu.Game.Rulesets.Objects.Drawables } /// - /// The local point that causes this to be selected in the Editor. + /// The screen-space point that causes this to be selected in the Editor. /// - public virtual Vector2 SelectionPoint => DrawSize / 2f; + public virtual Vector2 SelectionPoint => ScreenSpaceDrawQuad.Centre; /// - /// The local rectangle that outlines this for selections in the Editor. + /// The screen-space quad that outlines this for selections in the Editor. /// public virtual Quad SelectionQuad => ScreenSpaceDrawQuad; } From 666dcdbd6281b1b9f805367049a965a6200ea902 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 22:20:02 +0900 Subject: [PATCH 12/39] Give HitObjectComposer a SelectionLayer --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 3184b84e98..4487f74364 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Logging; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit.Layers.Selection; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit.Screens.Compose.RadioButtons; @@ -77,7 +78,8 @@ namespace osu.Game.Rulesets.Edit Alpha = 0, AlwaysPresent = true, }, - rulesetContainer + rulesetContainer, + new SelectionLayer(rulesetContainer.Playfield) } } }, From a6a07b1aa7259373bcdfca4745740d7b30457a8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 22:20:07 +0900 Subject: [PATCH 13/39] Cleanups --- .../Visual/TestCaseEditorCompose.cs | 2 -- .../Visual/TestCaseEditorSelectionLayer.cs | 34 +++++++++---------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs index 226329a852..d52f27f4ab 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs @@ -2,10 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit.Screens.Compose; namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index 79f3e4f1d3..6b7dedf9cf 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -7,12 +7,10 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Edit.Layers.Selection; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Tests.Visual { @@ -22,22 +20,24 @@ namespace osu.Game.Tests.Visual public TestCaseEditorSelectionLayer() { - var playfield = new OsuEditPlayfield(); - playfield.Add(new DrawableHitCircle(new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f })); - playfield.Add(new DrawableHitCircle(new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f })); - playfield.Add(new DrawableSlider(new Slider + var playfield = new OsuEditPlayfield { - ControlPoints = new List + new DrawableHitCircle(new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f }), + new DrawableHitCircle(new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f }), + new DrawableSlider(new Slider { - new Vector2(128, 256), - new Vector2(344, 256), - }, - Distance = 400, - Position = new Vector2(128, 256), - Velocity = 1, - TickDistance = 100, - Scale = 0.5f - })); + ControlPoints = new List + { + new Vector2(128, 256), + new Vector2(344, 256), + }, + Distance = 400, + Position = new Vector2(128, 256), + Velocity = 1, + TickDistance = 100, + Scale = 0.5f + }) + }; Children = new Drawable[] { From 3d51301e0317ff7936bf223088c2250a1651ef29 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 22:21:25 +0900 Subject: [PATCH 14/39] Add license headers --- osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs | 5 ++++- osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs | 5 ++++- osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs | 5 ++++- osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs b/osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs index 6da6c72849..0ed7339134 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs @@ -1,4 +1,7 @@ -using osu.Framework.Allocation; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs b/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs index 54d5a959a8..b83ed2e270 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs b/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs index 3519adb3b3..cee6ac63d5 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs index 3b35528cf1..e222583348 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; From 15c9e4a4468aae212b9044d9ebe3bd3fab1efb02 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Dec 2017 15:10:39 +0900 Subject: [PATCH 15/39] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index e57f32e483..97ac45b9c3 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e57f32e483fa47ee066becc9e0a1b3187b340606 +Subproject commit 97ac45b9c3c92544c9489b26dcda95e49f87b513 From 6a690908cfb3c3bbdd094730c2931340f4286cac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Dec 2017 20:24:24 +0900 Subject: [PATCH 16/39] Fix up possible nullref due to early access of Parent --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 387a098a5a..f03acb2fa0 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -31,6 +31,9 @@ namespace osu.Game.Rulesets.Osu.UI { get { + if (Parent == null) + return Vector2.Zero; + var parentSize = Parent.DrawSize; var aspectSize = parentSize.X * 0.75f < parentSize.Y ? new Vector2(parentSize.X, parentSize.X * 0.75f) : new Vector2(parentSize.Y * 4f / 3f, parentSize.Y); From b28b86dea9dc267ba41a64deab6c3bef507b169a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Dec 2017 20:27:51 +0900 Subject: [PATCH 17/39] Use Lazy for threadsafety on playfield --- osu.Game/Rulesets/UI/RulesetContainer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 5b4565e8a8..fe7c0c05ed 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -55,11 +55,11 @@ namespace osu.Game.Rulesets.UI public abstract IEnumerable Objects { get; } - private Playfield playfield; + private readonly Lazy playfield; /// /// The playfield. /// - public Playfield Playfield => playfield ?? (playfield = CreatePlayfield()); + public Playfield Playfield => playfield.Value; protected readonly Ruleset Ruleset; @@ -70,6 +70,7 @@ namespace osu.Game.Rulesets.UI protected RulesetContainer(Ruleset ruleset) { Ruleset = ruleset; + playfield = new Lazy(CreatePlayfield); } public abstract ScoreProcessor CreateScoreProcessor(); From eeb3440ffa387d946345834fe4443325d9abbb59 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Dec 2017 13:37:32 +0900 Subject: [PATCH 18/39] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 97ac45b9c3..fc6de01ad6 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 97ac45b9c3c92544c9489b26dcda95e49f87b513 +Subproject commit fc6de01ad6045544991bf278316c9eed8ea01ef1 From 66b19b6c977ea26c215196bcd8c650245f88b4a2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Dec 2017 14:48:24 +0900 Subject: [PATCH 19/39] Expose selected objects from SelectionLayer --- .../Edit/Layers/Selection/DragSelector.cs | 14 ++++++++++++-- .../Edit/Layers/Selection/SelectionInfo.cs | 19 +++++++++++++++++++ .../Edit/Layers/Selection/SelectionLayer.cs | 11 ++++++++++- osu.Game/osu.Game.csproj | 1 + 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs b/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs index b83ed2e270..2201a661b7 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using OpenTK.Graphics; +using osu.Framework.Configuration; namespace osu.Game.Rulesets.Edit.Layers.Selection { @@ -20,6 +21,8 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// public class DragSelector : CompositeDrawable { + public readonly Bindable Selection = new Bindable(); + /// /// The s that can be selected through a drag-selection. /// @@ -103,7 +106,6 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection } private readonly List capturedHitObjects = new List(); - public IReadOnlyList CapturedHitObjects => capturedHitObjects; /// /// Processes hitobjects to determine which ones are captured by the drag selection. @@ -128,7 +130,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// public void FinishCapture() { - if (CapturedHitObjects.Count == 0) + if (capturedHitObjects.Count == 0) { Hide(); return; @@ -158,6 +160,12 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection // Transform into markers to let the user modify the drag selection further. background.Delay(50).FadeOut(200); markers.FadeIn(200); + + Selection.Value = new SelectionInfo + { + Objects = capturedHitObjects, + SelectionQuad = Parent.ToScreenSpace(dragRectangle) + }; } private bool isActive = true; @@ -167,6 +175,8 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection { isActive = false; this.FadeOut(400, Easing.OutQuint).Expire(); + + Selection.Value = null; } } } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs new file mode 100644 index 0000000000..402bec1706 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + public class SelectionInfo + { + /// + /// The objects that are captured by the selection. + /// + public IEnumerable Objects; + + /// + /// The screen space quad of the selection box surrounding . + /// + public Quad SelectionQuad; + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index a38be68461..af8eac847e 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -1,15 +1,21 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Edit.Layers.Selection { public class SelectionLayer : CompositeDrawable { + public readonly Bindable Selection = new Bindable(); + private readonly Playfield playfield; public SelectionLayer(Playfield playfield) @@ -25,11 +31,14 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection { // Hide the previous drag box - we won't be working with it any longer selector?.Hide(); + AddInternal(selector = new DragSelector(ToLocalSpace(state.Mouse.NativeState.Position)) { - CapturableObjects = playfield.HitObjects.Objects + CapturableObjects = playfield.HitObjects.Objects, }); + Selection.BindTo(selector.Selection); + return true; } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 207dae1b54..63cf0ae0f5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -314,6 +314,7 @@ + From 17c58678cf195eb95d873d456a07a88eaaa1d7ff Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Mon, 18 Dec 2017 13:59:46 +0900 Subject: [PATCH 20/39] Update SelectionInfo.cs --- osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs index 402bec1706..aec16bd46d 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + using System.Collections.Generic; using osu.Framework.Graphics.Primitives; using osu.Game.Rulesets.Objects.Drawables; From f3a5258c5bdea596fe114418f3c36a9c625f4624 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 14:05:12 +0900 Subject: [PATCH 21/39] Reorder file (ctor + bdl) --- osu.Game/Screens/Play/MenuOverlay.cs | 132 +++++++++++++-------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/osu.Game/Screens/Play/MenuOverlay.cs b/osu.Game/Screens/Play/MenuOverlay.cs index 0a8e172e57..6d25c33243 100644 --- a/osu.Game/Screens/Play/MenuOverlay.cs +++ b/osu.Game/Screens/Play/MenuOverlay.cs @@ -32,73 +32,11 @@ namespace osu.Game.Screens.Play protected FillFlowContainer Buttons; - public int Retries - { - set - { - if (retryCounterContainer != null) - { - // "You've retried 1,065 times in this session" - // "You've retried 1 time in this session" - - retryCounterContainer.Children = new Drawable[] - { - new OsuSpriteText - { - Text = "You've retried ", - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 - }, - new OsuSpriteText - { - Text = $"{value:n0}", - Font = @"Exo2.0-Bold", - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 - }, - new OsuSpriteText - { - Text = $" time{(value == 1 ? "" : "s")} in this session", - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 - } - }; - } - } - } - private FillFlowContainer retryCounterContainer; - public override bool HandleInput => State == Visibility.Visible; - - protected override void PopIn() => this.FadeIn(transition_duration, Easing.In); - protected override void PopOut() => this.FadeOut(transition_duration, Easing.In); - - // Don't let mouse down events through the overlay or people can click circles while paused. - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; - - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => true; - - protected override bool OnMouseMove(InputState state) => true; - - protected void AddButton(string text, Color4 colour, Action action) + protected MenuOverlay() { - Buttons.Add(new Button - { - Text = text, - ButtonColour = colour, - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Height = button_height, - Action = delegate - { - action?.Invoke(); - Hide(); - } - }); + RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] @@ -182,9 +120,71 @@ namespace osu.Game.Screens.Play Retries = 0; } - protected MenuOverlay() + public int Retries { - RelativeSizeAxes = Axes.Both; + set + { + if (retryCounterContainer != null) + { + // "You've retried 1,065 times in this session" + // "You've retried 1 time in this session" + + retryCounterContainer.Children = new Drawable[] + { + new OsuSpriteText + { + Text = "You've retried ", + Shadow = true, + ShadowColour = new Color4(0, 0, 0, 0.25f), + TextSize = 18 + }, + new OsuSpriteText + { + Text = $"{value:n0}", + Font = @"Exo2.0-Bold", + Shadow = true, + ShadowColour = new Color4(0, 0, 0, 0.25f), + TextSize = 18 + }, + new OsuSpriteText + { + Text = $" time{(value == 1 ? "" : "s")} in this session", + Shadow = true, + ShadowColour = new Color4(0, 0, 0, 0.25f), + TextSize = 18 + } + }; + } + } + } + + public override bool HandleInput => State == Visibility.Visible; + + protected override void PopIn() => this.FadeIn(transition_duration, Easing.In); + protected override void PopOut() => this.FadeOut(transition_duration, Easing.In); + + // Don't let mouse down events through the overlay or people can click circles while paused. + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => true; + + protected override bool OnMouseMove(InputState state) => true; + + protected void AddButton(string text, Color4 colour, Action action) + { + Buttons.Add(new Button + { + Text = text, + ButtonColour = colour, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Height = button_height, + Action = delegate + { + action?.Invoke(); + Hide(); + } + }); } public class Button : DialogButton From 812181190e36ef71da107d299c99e111f18cb909 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Mon, 18 Dec 2017 14:10:14 +0900 Subject: [PATCH 22/39] Update SelectionLayer.cs --- osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index af8eac847e..392883daa5 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -1,13 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.Collections.Generic; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Edit.Layers.Selection From 8fdaf6f8f41a6520abc1ffecfb423f5b69aab8d0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 14:47:17 +0900 Subject: [PATCH 23/39] Restructure DialogButton to support selection --- .../Graphics/UserInterface/DialogButton.cs | 251 +++++++++--------- 1 file changed, 132 insertions(+), 119 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index bb62815a7b..3b3cb953de 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.Containers; +using osu.Framework.Configuration; namespace osu.Game.Graphics.UserInterface { @@ -22,62 +23,7 @@ namespace osu.Game.Graphics.UserInterface private const float glow_fade_duration = 250; private const float click_duration = 200; - private Color4 buttonColour; - public Color4 ButtonColour - { - get - { - return buttonColour; - } - set - { - buttonColour = value; - updateGlow(); - colourContainer.Colour = value; - } - } - - private Color4 backgroundColour = OsuColour.Gray(34); - public Color4 BackgroundColour - { - get - { - return backgroundColour; - } - set - { - backgroundColour = value; - background.Colour = value; - } - } - - private string text; - public string Text - { - get - { - return text; - } - set - { - text = value; - spriteText.Text = Text; - } - } - - private float textSize = 28; - public float TextSize - { - get - { - return textSize; - } - set - { - textSize = value; - spriteText.TextSize = value; - } - } + public readonly BindableBool Selected = new BindableBool(); private readonly Container backgroundContainer; private readonly Container colourContainer; @@ -91,69 +37,6 @@ namespace osu.Game.Graphics.UserInterface private bool didClick; // Used for making sure that the OnMouseDown animation can call instead of OnHoverLost's when clicking - public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => backgroundContainer.ReceiveMouseInputAt(screenSpacePos); - - protected override bool OnClick(Framework.Input.InputState state) - { - didClick = true; - colourContainer.ResizeTo(new Vector2(1.5f, 1f), click_duration, Easing.In); - flash(); - - this.Delay(click_duration).Schedule(delegate - { - colourContainer.ResizeTo(new Vector2(0.8f, 1f)); - spriteText.Spacing = Vector2.Zero; - glowContainer.FadeOut(); - }); - - return base.OnClick(state); - } - - protected override bool OnHover(Framework.Input.InputState state) - { - spriteText.TransformSpacingTo(hoverSpacing, hover_duration, Easing.OutElastic); - - colourContainer.ResizeTo(new Vector2(hover_width, 1f), hover_duration, Easing.OutElastic); - glowContainer.FadeIn(glow_fade_duration, Easing.Out); - base.OnHover(state); - return true; - } - - protected override void OnHoverLost(Framework.Input.InputState state) - { - if (!didClick) - { - colourContainer.ResizeTo(new Vector2(0.8f, 1f), hover_duration, Easing.OutElastic); - spriteText.TransformSpacingTo(Vector2.Zero, hover_duration, Easing.OutElastic); - glowContainer.FadeOut(glow_fade_duration, Easing.Out); - } - - didClick = false; - } - - private void flash() - { - var flash = new Box - { - RelativeSizeAxes = Axes.Both - }; - - colourContainer.Add(flash); - - flash.Colour = ButtonColour; - flash.Blending = BlendingMode.Additive; - flash.Alpha = 0.3f; - flash.FadeOutFromOne(click_duration); - flash.Expire(); - } - - private void updateGlow() - { - leftGlow.Colour = ColourInfo.GradientHorizontal(new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f), ButtonColour); - centerGlow.Colour = ButtonColour; - rightGlow.Colour = ColourInfo.GradientHorizontal(ButtonColour, new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f)); - } - public DialogButton() { RelativeSizeAxes = Axes.X; @@ -268,6 +151,136 @@ namespace osu.Game.Graphics.UserInterface }; updateGlow(); + + Selected.ValueChanged += selectionChanged; + } + + private Color4 buttonColour; + public Color4 ButtonColour + { + get + { + return buttonColour; + } + set + { + buttonColour = value; + updateGlow(); + colourContainer.Colour = value; + } + } + + private Color4 backgroundColour = OsuColour.Gray(34); + public Color4 BackgroundColour + { + get + { + return backgroundColour; + } + set + { + backgroundColour = value; + background.Colour = value; + } + } + + private string text; + public string Text + { + get + { + return text; + } + set + { + text = value; + spriteText.Text = Text; + } + } + + private float textSize = 28; + public float TextSize + { + get + { + return textSize; + } + set + { + textSize = value; + spriteText.TextSize = value; + } + } + + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => backgroundContainer.ReceiveMouseInputAt(screenSpacePos); + + protected override bool OnClick(Framework.Input.InputState state) + { + didClick = true; + colourContainer.ResizeTo(new Vector2(1.5f, 1f), click_duration, Easing.In); + flash(); + + this.Delay(click_duration).Schedule(delegate + { + colourContainer.ResizeTo(new Vector2(0.8f, 1f)); + spriteText.Spacing = Vector2.Zero; + glowContainer.FadeOut(); + }); + + return base.OnClick(state); + } + + protected override bool OnHover(Framework.Input.InputState state) + { + base.OnHover(state); + + Selected.Value = true; + return true; + } + + protected override void OnHoverLost(Framework.Input.InputState state) + { + base.OnHoverLost(state); + Selected.Value = false; + } + + private void selectionChanged(bool isSelected) + { + if (isSelected) + { + spriteText.TransformSpacingTo(hoverSpacing, hover_duration, Easing.OutElastic); + colourContainer.ResizeTo(new Vector2(hover_width, 1f), hover_duration, Easing.OutElastic); + glowContainer.FadeIn(glow_fade_duration, Easing.Out); + } + else if (!didClick) + { + colourContainer.ResizeTo(new Vector2(0.8f, 1f), hover_duration, Easing.OutElastic); + spriteText.TransformSpacingTo(Vector2.Zero, hover_duration, Easing.OutElastic); + glowContainer.FadeOut(glow_fade_duration, Easing.Out); + } + } + + private void flash() + { + var flash = new Box + { + RelativeSizeAxes = Axes.Both + }; + + colourContainer.Add(flash); + + flash.Colour = ButtonColour; + flash.Blending = BlendingMode.Additive; + flash.Alpha = 0.3f; + flash.FadeOutFromOne(click_duration); + flash.Expire(); + } + + private void updateGlow() + { + leftGlow.Colour = ColourInfo.GradientHorizontal(new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f), ButtonColour); + centerGlow.Colour = ButtonColour; + rightGlow.Colour = ColourInfo.GradientHorizontal(ButtonColour, new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f)); } } } From 9fb3d3704a7e0601006233ad20ac30ff5cf51f85 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 15:42:11 +0900 Subject: [PATCH 24/39] TestCaseMenuOverlays -> TestCaseMenuOverlay --- .../{TestCaseMenuOverlays.cs => TestCaseMenuOverlay.cs} | 8 ++++++-- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) rename osu.Game.Tests/Visual/{TestCaseMenuOverlays.cs => TestCaseMenuOverlay.cs} (83%) diff --git a/osu.Game.Tests/Visual/TestCaseMenuOverlays.cs b/osu.Game.Tests/Visual/TestCaseMenuOverlay.cs similarity index 83% rename from osu.Game.Tests/Visual/TestCaseMenuOverlays.cs rename to osu.Game.Tests/Visual/TestCaseMenuOverlay.cs index 94a69f0029..da846a1b39 100644 --- a/osu.Game.Tests/Visual/TestCaseMenuOverlays.cs +++ b/osu.Game.Tests/Visual/TestCaseMenuOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using System.ComponentModel; using osu.Framework.Graphics.Containers; using osu.Framework.Logging; @@ -9,9 +11,11 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual { [Description("player pause/fail screens")] - internal class TestCaseMenuOverlays : OsuTestCase + internal class TestCaseMenuOverlay : OsuTestCase { - public TestCaseMenuOverlays() + public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseContainer.PauseOverlay) }; + + public TestCaseMenuOverlay() { FailOverlay failOverlay; PauseContainer.PauseOverlay pauseOverlay; diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 184561faa7..cf91ca0c15 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -120,7 +120,7 @@ - + From 1e4cad900dd46cf2ce3d5509f5224695eb9dc32f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 16:04:51 +0900 Subject: [PATCH 25/39] Fix up incorrect RequiredTypes --- osu.Game.Tests/Visual/TestCaseMenuOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseMenuOverlay.cs b/osu.Game.Tests/Visual/TestCaseMenuOverlay.cs index da846a1b39..6c1c615ca9 100644 --- a/osu.Game.Tests/Visual/TestCaseMenuOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMenuOverlay.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual [Description("player pause/fail screens")] internal class TestCaseMenuOverlay : OsuTestCase { - public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseContainer.PauseOverlay) }; + public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseContainer) }; public TestCaseMenuOverlay() { From 59365bbdce1ec25feec558c6ab4f10ae6e0721d8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 16:29:40 +0900 Subject: [PATCH 26/39] Make MenuOverlay support key selections --- osu.Game/Screens/Play/MenuOverlay.cs | 72 ++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/MenuOverlay.cs b/osu.Game/Screens/Play/MenuOverlay.cs index 6d25c33243..452eaae574 100644 --- a/osu.Game/Screens/Play/MenuOverlay.cs +++ b/osu.Game/Screens/Play/MenuOverlay.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics; using osu.Framework.Allocation; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Shapes; +using OpenTK.Input; namespace osu.Game.Screens.Play { @@ -37,6 +38,8 @@ namespace osu.Game.Screens.Play protected MenuOverlay() { RelativeSizeAxes = Axes.Both; + + StateChanged += s => selectionIndex = -1; } [BackgroundDependencyLoader] @@ -172,7 +175,7 @@ namespace osu.Game.Screens.Play protected void AddButton(string text, Color4 colour, Action action) { - Buttons.Add(new Button + var button = new MenuOverlayButton { Text = text, ButtonColour = colour, @@ -184,11 +187,74 @@ namespace osu.Game.Screens.Play action?.Invoke(); Hide(); } - }); + }; + + button.Selected.ValueChanged += s => buttonSelectionChanged(button, s); + + Buttons.Add(button); } - public class Button : DialogButton + private int _selectionIndex = -1; + private int selectionIndex { + get { return _selectionIndex; } + set + { + if (_selectionIndex == value) + return; + + if (_selectionIndex != -1) + Buttons[_selectionIndex].Selected.Value = false; + + _selectionIndex = value; + + if (_selectionIndex != -1) + Buttons[_selectionIndex].Selected.Value = true; + } + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat) + return false; + + switch (args.Key) + { + case Key.Up: + if (selectionIndex == -1 || selectionIndex == 0) + selectionIndex = Buttons.Count - 1; + else + selectionIndex--; + return true; + case Key.Down: + if (selectionIndex == -1 || selectionIndex == Buttons.Count - 1) + selectionIndex = 0; + else + selectionIndex++; + return true; + } + + return false; + } + + private void buttonSelectionChanged(DialogButton button, bool isSelected) + { + if (!isSelected) + selectionIndex = -1; + else + selectionIndex = Buttons.IndexOf(button); + } + + private class MenuOverlayButton : DialogButton + { + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat || args.Key != Key.Enter || !Selected) + return false; + + OnClick(state); + return true; + } } } } From 5f538f03eab7c0a70c811f71c2b5323f055c4786 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 16:34:25 +0900 Subject: [PATCH 27/39] Comments --- osu.Game/Screens/Play/MenuOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/MenuOverlay.cs b/osu.Game/Screens/Play/MenuOverlay.cs index 452eaae574..6e3c1a4d44 100644 --- a/osu.Game/Screens/Play/MenuOverlay.cs +++ b/osu.Game/Screens/Play/MenuOverlay.cs @@ -203,11 +203,13 @@ namespace osu.Game.Screens.Play if (_selectionIndex == value) return; + // Deselect the previously-selected button if (_selectionIndex != -1) Buttons[_selectionIndex].Selected.Value = false; _selectionIndex = value; + // Select the newly-selected button if (_selectionIndex != -1) Buttons[_selectionIndex].Selected.Value = true; } From 846750a1905315dcb7861edc6d01640221c1ae8d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 16:36:11 +0900 Subject: [PATCH 28/39] Remove unnecessary flag --- osu.Game/Graphics/UserInterface/DialogButton.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 3b3cb953de..320bf51aaf 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -35,8 +35,6 @@ namespace osu.Game.Graphics.UserInterface private readonly SpriteText spriteText; private Vector2 hoverSpacing => new Vector2(3f, 0f); - private bool didClick; // Used for making sure that the OnMouseDown animation can call instead of OnHoverLost's when clicking - public DialogButton() { RelativeSizeAxes = Axes.X; @@ -216,7 +214,6 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnClick(Framework.Input.InputState state) { - didClick = true; colourContainer.ResizeTo(new Vector2(1.5f, 1f), click_duration, Easing.In); flash(); @@ -252,7 +249,7 @@ namespace osu.Game.Graphics.UserInterface colourContainer.ResizeTo(new Vector2(hover_width, 1f), hover_duration, Easing.OutElastic); glowContainer.FadeIn(glow_fade_duration, Easing.Out); } - else if (!didClick) + else { colourContainer.ResizeTo(new Vector2(0.8f, 1f), hover_duration, Easing.OutElastic); spriteText.TransformSpacingTo(Vector2.Zero, hover_duration, Easing.OutElastic); From cf640d084e50b78b275df22503953b17ab154aec Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 16:38:15 +0900 Subject: [PATCH 29/39] Use using --- osu.Game/Graphics/UserInterface/DialogButton.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 320bf51aaf..f07bc4114f 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.Containers; using osu.Framework.Configuration; +using osu.Framework.Input; namespace osu.Game.Graphics.UserInterface { @@ -212,7 +213,7 @@ namespace osu.Game.Graphics.UserInterface public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => backgroundContainer.ReceiveMouseInputAt(screenSpacePos); - protected override bool OnClick(Framework.Input.InputState state) + protected override bool OnClick(InputState state) { colourContainer.ResizeTo(new Vector2(1.5f, 1f), click_duration, Easing.In); flash(); @@ -227,7 +228,7 @@ namespace osu.Game.Graphics.UserInterface return base.OnClick(state); } - protected override bool OnHover(Framework.Input.InputState state) + protected override bool OnHover(InputState state) { base.OnHover(state); @@ -235,7 +236,7 @@ namespace osu.Game.Graphics.UserInterface return true; } - protected override void OnHoverLost(Framework.Input.InputState state) + protected override void OnHoverLost(InputState state) { base.OnHoverLost(state); Selected.Value = false; From 918e7c9a4bc8ef7cd4e41dc1f169efc7fa85adb6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 16:40:50 +0900 Subject: [PATCH 30/39] MenuOverlay -> GameplayMenuOverlay --- ...tCaseMenuOverlay.cs => TestCaseGameplayMenuOverlay.cs} | 4 ++-- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game/Screens/Play/FailOverlay.cs | 2 +- .../Play/{MenuOverlay.cs => GameplayMenuOverlay.cs} | 8 ++++---- osu.Game/Screens/Play/PauseContainer.cs | 2 +- osu.Game/osu.Game.csproj | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) rename osu.Game.Tests/Visual/{TestCaseMenuOverlay.cs => TestCaseGameplayMenuOverlay.cs} (91%) rename osu.Game/Screens/Play/{MenuOverlay.cs => GameplayMenuOverlay.cs} (94%) diff --git a/osu.Game.Tests/Visual/TestCaseMenuOverlay.cs b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs similarity index 91% rename from osu.Game.Tests/Visual/TestCaseMenuOverlay.cs rename to osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs index 6c1c615ca9..ecb107085a 100644 --- a/osu.Game.Tests/Visual/TestCaseMenuOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs @@ -11,11 +11,11 @@ using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual { [Description("player pause/fail screens")] - internal class TestCaseMenuOverlay : OsuTestCase + internal class TestCaseGameplayMenuOverlay : OsuTestCase { public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseContainer) }; - public TestCaseMenuOverlay() + public TestCaseGameplayMenuOverlay() { FailOverlay failOverlay; PauseContainer.PauseOverlay pauseOverlay; diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index cf91ca0c15..5442ce63dd 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -120,7 +120,7 @@ - + diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index 3e31da2348..3242d8bb6e 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -10,7 +10,7 @@ using System.Linq; namespace osu.Game.Screens.Play { - public class FailOverlay : MenuOverlay + public class FailOverlay : GameplayMenuOverlay { public override string Header => "failed"; public override string Description => "you're dead, try again?"; diff --git a/osu.Game/Screens/Play/MenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs similarity index 94% rename from osu.Game/Screens/Play/MenuOverlay.cs rename to osu.Game/Screens/Play/GameplayMenuOverlay.cs index 6e3c1a4d44..996717cbb5 100644 --- a/osu.Game/Screens/Play/MenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -17,7 +17,7 @@ using OpenTK.Input; namespace osu.Game.Screens.Play { - public abstract class MenuOverlay : OverlayContainer, IRequireHighFrequencyMousePosition + public abstract class GameplayMenuOverlay : OverlayContainer, IRequireHighFrequencyMousePosition { private const int transition_duration = 200; private const int button_height = 70; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play private FillFlowContainer retryCounterContainer; - protected MenuOverlay() + protected GameplayMenuOverlay() { RelativeSizeAxes = Axes.Both; @@ -175,7 +175,7 @@ namespace osu.Game.Screens.Play protected void AddButton(string text, Color4 colour, Action action) { - var button = new MenuOverlayButton + var button = new Button { Text = text, ButtonColour = colour, @@ -247,7 +247,7 @@ namespace osu.Game.Screens.Play selectionIndex = Buttons.IndexOf(button); } - private class MenuOverlayButton : DialogButton + private class Button : DialogButton { protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { diff --git a/osu.Game/Screens/Play/PauseContainer.cs b/osu.Game/Screens/Play/PauseContainer.cs index 5f5eeb63a0..6812ac5fc5 100644 --- a/osu.Game/Screens/Play/PauseContainer.cs +++ b/osu.Game/Screens/Play/PauseContainer.cs @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Play base.Update(); } - public class PauseOverlay : MenuOverlay + public class PauseOverlay : GameplayMenuOverlay { public Action OnResume; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c190d988fa..155f08fd66 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -719,7 +719,7 @@ - + From a17b2e4c1801388afb692b957a9aaff01be0c1fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 19:13:08 +0900 Subject: [PATCH 31/39] Expose buttons for test cases --- osu.Game/Screens/Play/FailOverlay.cs | 2 +- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 18 ++++++++++-------- osu.Game/Screens/Play/PauseContainer.cs | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index 3242d8bb6e..a6a233058b 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play { if (!args.Repeat && args.Key == Key.Escape) { - Buttons.Children.Last().TriggerOnClick(); + InternalButtons.Children.Last().TriggerOnClick(); return true; } diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 996717cbb5..182c4efe89 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -14,6 +14,7 @@ using osu.Framework.Allocation; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Shapes; using OpenTK.Input; +using System.Collections.Generic; namespace osu.Game.Screens.Play { @@ -31,7 +32,8 @@ namespace osu.Game.Screens.Play public abstract string Header { get; } public abstract string Description { get; } - protected FillFlowContainer Buttons; + protected internal FillFlowContainer InternalButtons; + public IReadOnlyList Buttons => InternalButtons; private FillFlowContainer retryCounterContainer; @@ -95,7 +97,7 @@ namespace osu.Game.Screens.Play } } }, - Buttons = new FillFlowContainer + InternalButtons = new FillFlowContainer { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, @@ -191,7 +193,7 @@ namespace osu.Game.Screens.Play button.Selected.ValueChanged += s => buttonSelectionChanged(button, s); - Buttons.Add(button); + InternalButtons.Add(button); } private int _selectionIndex = -1; @@ -205,13 +207,13 @@ namespace osu.Game.Screens.Play // Deselect the previously-selected button if (_selectionIndex != -1) - Buttons[_selectionIndex].Selected.Value = false; + InternalButtons[_selectionIndex].Selected.Value = false; _selectionIndex = value; // Select the newly-selected button if (_selectionIndex != -1) - Buttons[_selectionIndex].Selected.Value = true; + InternalButtons[_selectionIndex].Selected.Value = true; } } @@ -224,12 +226,12 @@ namespace osu.Game.Screens.Play { case Key.Up: if (selectionIndex == -1 || selectionIndex == 0) - selectionIndex = Buttons.Count - 1; + selectionIndex = InternalButtons.Count - 1; else selectionIndex--; return true; case Key.Down: - if (selectionIndex == -1 || selectionIndex == Buttons.Count - 1) + if (selectionIndex == -1 || selectionIndex == InternalButtons.Count - 1) selectionIndex = 0; else selectionIndex++; @@ -244,7 +246,7 @@ namespace osu.Game.Screens.Play if (!isSelected) selectionIndex = -1; else - selectionIndex = Buttons.IndexOf(button); + selectionIndex = InternalButtons.IndexOf(button); } private class Button : DialogButton diff --git a/osu.Game/Screens/Play/PauseContainer.cs b/osu.Game/Screens/Play/PauseContainer.cs index 6812ac5fc5..8545c50536 100644 --- a/osu.Game/Screens/Play/PauseContainer.cs +++ b/osu.Game/Screens/Play/PauseContainer.cs @@ -130,7 +130,7 @@ namespace osu.Game.Screens.Play { if (!args.Repeat && args.Key == Key.Escape) { - Buttons.Children.First().TriggerOnClick(); + InternalButtons.Children.First().TriggerOnClick(); return true; } From 5e111e14db9845f48dafa9264d100dce60d0c214 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 19:13:25 +0900 Subject: [PATCH 32/39] Make it possible to change the overlay actions beyond instantiation --- osu.Game/Screens/Play/FailOverlay.cs | 4 ++-- osu.Game/Screens/Play/PauseContainer.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index a6a233058b..09f2e15c57 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -18,8 +18,8 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(OsuColour colours) { - AddButton("Retry", colours.YellowDark, OnRetry); - AddButton("Quit", new Color4(170, 27, 39, 255), OnQuit); + AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke()); + AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); } protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) diff --git a/osu.Game/Screens/Play/PauseContainer.cs b/osu.Game/Screens/Play/PauseContainer.cs index 8545c50536..3bd28511c7 100644 --- a/osu.Game/Screens/Play/PauseContainer.cs +++ b/osu.Game/Screens/Play/PauseContainer.cs @@ -140,9 +140,9 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(OsuColour colours) { - AddButton("Continue", colours.Green, OnResume); - AddButton("Retry", colours.YellowDark, OnRetry); - AddButton("Quit", new Color4(170, 27, 39, 255), OnQuit); + AddButton("Continue", colours.Green, () => OnResume?.Invoke()); + AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke()); + AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); } } } From f90e3346c1f8f836f1f3d084143c693668828a56 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 19:13:33 +0900 Subject: [PATCH 33/39] Add automated test cases --- .../Visual/TestCaseGameplayMenuOverlay.cs | 247 ++++++++++++++++-- 1 file changed, 222 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs index ecb107085a..8389037a71 100644 --- a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs @@ -4,7 +4,11 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Linq; +using OpenTK.Input; +using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; +using osu.Framework.Input; using osu.Framework.Logging; using osu.Game.Screens.Play; @@ -15,47 +19,240 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseContainer) }; - public TestCaseGameplayMenuOverlay() + private FailOverlay failOverlay; + private PauseContainer.PauseOverlay pauseOverlay; + + [BackgroundDependencyLoader] + private void load() { - FailOverlay failOverlay; - PauseContainer.PauseOverlay pauseOverlay; - - var retryCount = 0; - Add(pauseOverlay = new PauseContainer.PauseOverlay { OnResume = () => Logger.Log(@"Resume"), OnRetry = () => Logger.Log(@"Retry"), OnQuit = () => Logger.Log(@"Quit"), }); + Add(failOverlay = new FailOverlay { OnRetry = () => Logger.Log(@"Retry"), OnQuit = () => Logger.Log(@"Quit"), }); - AddStep(@"Pause", delegate - { - if (failOverlay.State == Visibility.Visible) - { - failOverlay.Hide(); - } - pauseOverlay.Show(); - }); - AddStep("Fail", delegate - { - if (pauseOverlay.State == Visibility.Visible) - { - pauseOverlay.Hide(); - } - failOverlay.Show(); - }); - AddStep("Add Retry", delegate + var retryCount = 0; + + AddStep("Add retry", () => { retryCount++; - pauseOverlay.Retries = retryCount; - failOverlay.Retries = retryCount; + pauseOverlay.Retries = failOverlay.Retries = retryCount; }); + + AddToggleStep("Toggle pause overlay", t => pauseOverlay.ToggleVisibility()); + AddToggleStep("Toggle fail overlay", t => failOverlay.ToggleVisibility()); + + testHideResets(); + + testEnterWithoutSelection(); + testKeyUpFromInitial(); + testKeyDownFromInitial(); + testKeyUpWrapping(); + testKeyDownWrapping(); + + testMouseSelectionAfterKeySelection(); + testKeySelectionAfterMouseSelection(); + + testMouseDeselectionResets(); + + testClickSelection(); + testEnterKeySelection(); + } + + /// + /// Test that hiding the overlay after hovering a button will reset the overlay to the initial state with no buttons selected. + /// + private void testHideResets() + { + AddStep("Show overlay", () => failOverlay.Show()); + + AddStep("Hover first button", () => failOverlay.Buttons.First().TriggerOnHover(null)); + AddStep("Hide overlay", () => failOverlay.Hide()); + + AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected)); + } + + /// + /// Tests that pressing enter after an overlay shows doesn't trigger an event because a selection hasn't occurred. + /// + private void testEnterWithoutSelection() + { + AddStep("Show overlay", () => pauseOverlay.Show()); + + AddStep("Press enter", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Enter })); + AddAssert("Overlay still open", () => pauseOverlay.State == Visibility.Visible); + + AddStep("Hide overlay", () => pauseOverlay.Hide()); + } + + /// + /// Tests that pressing the up arrow from the initial state selects the last button. + /// + private void testKeyUpFromInitial() + { + AddStep("Show overlay", () => pauseOverlay.Show()); + + AddStep("Up arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected); + + AddStep("Hide overlay", () => pauseOverlay.Hide()); + } + + /// + /// Tests that pressing the down arrow from the initial state selects the first button. + /// + private void testKeyDownFromInitial() + { + AddStep("Show overlay", () => pauseOverlay.Show()); + + AddStep("Down arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); + + AddStep("Hide overlay", () => pauseOverlay.Hide()); + } + + /// + /// Tests that pressing the up arrow repeatedly causes the selected button to wrap correctly. + /// + private void testKeyUpWrapping() + { + AddStep("Show overlay", () => failOverlay.Show()); + + AddStep("Up arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); + AddStep("Up arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); + AddStep("Up arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); + + AddStep("Hide overlay", () => failOverlay.Hide()); + } + + /// + /// Tests that pressing the down arrow repeatedly causes the selected button to wrap correctly. + /// + private void testKeyDownWrapping() + { + AddStep("Show overlay", () => failOverlay.Show()); + + AddStep("Down arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); + AddStep("Down arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); + AddStep("Down arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); + + AddStep("Hide overlay", () => failOverlay.Hide()); + } + + /// + /// Tests that hovering a button that was previously selected with the keyboard correctly selects the new button and deselects the previous button. + /// + private void testMouseSelectionAfterKeySelection() + { + AddStep("Show overlay", () => pauseOverlay.Show()); + + var secondButton = pauseOverlay.Buttons.Skip(1).First(); + + AddStep("Down arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddStep("Hover second button", () => secondButton.TriggerOnHover(null)); + AddAssert("First button not selected", () => !pauseOverlay.Buttons.First().Selected); + AddAssert("Second button selected", () => secondButton.Selected); + + AddStep("Hide overlay", () => pauseOverlay.Hide()); + } + + /// + /// Tests that pressing a key after selecting a button with a hover event correctly selects a new button and deselects the previous button. + /// + private void testKeySelectionAfterMouseSelection() + { + AddStep("Show overlay", () => pauseOverlay.Show()); + + var secondButton = pauseOverlay.Buttons.Skip(1).First(); + + AddStep("Hover second button", () => secondButton.TriggerOnHover(null)); + AddStep("Up arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up })); + AddAssert("Second button not selected", () => !secondButton.Selected); + AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); + + AddStep("Hide overlay", () => pauseOverlay.Hide()); + } + + /// + /// Tests that deselecting with the mouse by losing hover will reset the overlay to the initial state. + /// + private void testMouseDeselectionResets() + { + AddStep("Show overlay", () => pauseOverlay.Show()); + + var secondButton = pauseOverlay.Buttons.Skip(1).First(); + + AddStep("Hover second button", () => secondButton.TriggerOnHover(null)); + AddStep("Unhover second button", () => secondButton.TriggerOnHoverLost(null)); + AddStep("Down arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down })); + AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); // Initial state condition + + AddStep("Hide overlay", () => pauseOverlay.Hide()); + } + + /// + /// Tests that clicking on a button correctly causes a click event for that button. + /// + private void testClickSelection() + { + AddStep("Show overlay", () => pauseOverlay.Show()); + + var retryButton = pauseOverlay.Buttons.Skip(1).First(); + + bool triggered = false; + AddStep("Click retry button", () => + { + var lastAction = pauseOverlay.OnRetry; + pauseOverlay.OnRetry = () => triggered = true; + + retryButton.TriggerOnClick(); + pauseOverlay.OnRetry = lastAction; + }); + + AddAssert("Action was triggered", () => triggered); + AddAssert("Overlay is closed", () => pauseOverlay.State == Visibility.Hidden); + } + + /// + /// Tests that pressing the enter key with a button selected correctly causes a click event for that button. + /// + private void testEnterKeySelection() + { + AddStep("Show overlay", () => pauseOverlay.Show()); + + AddStep("Select second button", () => + { + pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }); + pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }); + }); + + var retryButton = pauseOverlay.Buttons.Skip(1).First(); + + bool triggered = false; + AddStep("Press enter", () => + { + var lastAction = pauseOverlay.OnRetry; + pauseOverlay.OnRetry = () => triggered = true; + + retryButton.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Enter }); + pauseOverlay.OnRetry = lastAction; + }); + + AddAssert("Action was triggered", () => triggered); + AddAssert("Overlay is closed", () => pauseOverlay.State == Visibility.Hidden); } } } From 399994053887fef435980372252f33fbb6ade4f6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 19:16:33 +0900 Subject: [PATCH 34/39] DragSelector -> HitObjectSelectionBox --- ...{DragSelector.cs => HitObjectSelectionBox.cs} | 6 +++--- .../Rulesets/Edit/Layers/Selection/Marker.cs | 2 +- .../Edit/Layers/Selection/SelectionLayer.cs | 16 ++++++++-------- osu.Game/osu.Game.csproj | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) rename osu.Game/Rulesets/Edit/Layers/Selection/{DragSelector.cs => HitObjectSelectionBox.cs} (94%) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs similarity index 94% rename from osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs rename to osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs index 2201a661b7..6ea2778a9e 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/DragSelector.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// /// A box that represents a drag selection. /// - public class DragSelector : CompositeDrawable + public class HitObjectSelectionBox : CompositeDrawable { public readonly Bindable Selection = new Bindable(); @@ -37,10 +37,10 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection private readonly Vector2 startPos; /// - /// Creates a new . + /// Creates a new . /// /// The point at which the drag was initiated, in the parent's coordinates. - public DragSelector(Vector2 startPos) + public HitObjectSelectionBox(Vector2 startPos) { this.startPos = startPos; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs b/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs index cee6ac63d5..956415a800 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection { /// /// Represents a marker visible on the border of a which exposes - /// properties that are used to resize a . + /// properties that are used to resize a . /// public class Marker : CompositeDrawable { diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index 392883daa5..98bcfd0ec8 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -22,39 +22,39 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection RelativeSizeAxes = Axes.Both; } - private DragSelector selector; + private HitObjectSelectionBox selectionBoxBox; protected override bool OnDragStart(InputState state) { // Hide the previous drag box - we won't be working with it any longer - selector?.Hide(); + selectionBoxBox?.Hide(); - AddInternal(selector = new DragSelector(ToLocalSpace(state.Mouse.NativeState.Position)) + AddInternal(selectionBoxBox = new HitObjectSelectionBox(ToLocalSpace(state.Mouse.NativeState.Position)) { CapturableObjects = playfield.HitObjects.Objects, }); - Selection.BindTo(selector.Selection); + Selection.BindTo(selectionBoxBox.Selection); return true; } protected override bool OnDrag(InputState state) { - selector.DragEndPosition = ToLocalSpace(state.Mouse.NativeState.Position); - selector.BeginCapture(); + selectionBoxBox.DragEndPosition = ToLocalSpace(state.Mouse.NativeState.Position); + selectionBoxBox.BeginCapture(); return true; } protected override bool OnDragEnd(InputState state) { - selector.FinishCapture(); + selectionBoxBox.FinishCapture(); return true; } protected override bool OnClick(InputState state) { - selector?.Hide(); + selectionBoxBox?.Hide(); return true; } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index fca3f57413..514f91f80a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -308,7 +308,7 @@ - + From 09c51df2bd1da9f76a306bc2383a86c1a034fa0f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 19:21:26 +0900 Subject: [PATCH 35/39] Marker* -> Handle --- .../Layers/Selection/{Marker.cs => Handle.cs} | 210 +++++++++--------- ...{MarkerContainer.cs => HandleContainer.cs} | 32 +-- .../Layers/Selection/HitObjectSelectionBox.cs | 6 +- .../{CentreMarker.cs => OriginHandle.cs} | 6 +- osu.Game/osu.Game.csproj | 6 +- 5 files changed, 130 insertions(+), 130 deletions(-) rename osu.Game/Rulesets/Edit/Layers/Selection/{Marker.cs => Handle.cs} (88%) rename osu.Game/Rulesets/Edit/Layers/Selection/{MarkerContainer.cs => HandleContainer.cs} (74%) rename osu.Game/Rulesets/Edit/Layers/Selection/{CentreMarker.cs => OriginHandle.cs} (86%) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs similarity index 88% rename from osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs rename to osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs index 956415a800..e93fe886e1 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/Marker.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs @@ -1,105 +1,105 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Game.Graphics; -using OpenTK; -using OpenTK.Graphics; - -namespace osu.Game.Rulesets.Edit.Layers.Selection -{ - /// - /// Represents a marker visible on the border of a which exposes - /// properties that are used to resize a . - /// - public class Marker : CompositeDrawable - { - private const float marker_size = 10; - - /// - /// Invoked when this requires the current drag rectangle. - /// - public Func GetDragRectangle; - - /// - /// Invoked when this wants to update the drag rectangle. - /// - public Action UpdateDragRectangle; - - /// - /// Invoked when this has finished updates to the drag rectangle. - /// - public Action FinishCapture; - - private Color4 normalColour; - private Color4 hoverColour; - - public Marker() - { - Size = new Vector2(marker_size); - - InternalChild = new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Child = new Box { RelativeSizeAxes = Axes.Both } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Colour = normalColour = colours.Yellow; - hoverColour = colours.YellowDarker; - } - - protected override bool OnDragStart(InputState state) => true; - - protected override bool OnDrag(InputState state) - { - var currentRectangle = GetDragRectangle(); - - float left = currentRectangle.Left; - float right = currentRectangle.Right; - float top = currentRectangle.Top; - float bottom = currentRectangle.Bottom; - - // Apply modifications to the capture rectangle - if ((Anchor & Anchor.y0) > 0) - top += state.Mouse.Delta.Y; - else if ((Anchor & Anchor.y2) > 0) - bottom += state.Mouse.Delta.Y; - - if ((Anchor & Anchor.x0) > 0) - left += state.Mouse.Delta.X; - else if ((Anchor & Anchor.x2) > 0) - right += state.Mouse.Delta.X; - - UpdateDragRectangle(RectangleF.FromLTRB(left, top, right, bottom)); - return true; - } - - protected override bool OnDragEnd(InputState state) - { - FinishCapture(); - return true; - } - - protected override bool OnHover(InputState state) - { - this.FadeColour(hoverColour, 100); - return true; - } - - protected override void OnHoverLost(InputState state) - { - this.FadeColour(normalColour, 100); - } - } -} +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Graphics; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + /// + /// Represents a marker visible on the border of a which exposes + /// properties that are used to resize a . + /// + public class Handle : CompositeDrawable + { + private const float marker_size = 10; + + /// + /// Invoked when this requires the current drag rectangle. + /// + public Func GetDragRectangle; + + /// + /// Invoked when this wants to update the drag rectangle. + /// + public Action UpdateDragRectangle; + + /// + /// Invoked when this has finished updates to the drag rectangle. + /// + public Action FinishCapture; + + private Color4 normalColour; + private Color4 hoverColour; + + public Handle() + { + Size = new Vector2(marker_size); + + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = new Box { RelativeSizeAxes = Axes.Both } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = normalColour = colours.Yellow; + hoverColour = colours.YellowDarker; + } + + protected override bool OnDragStart(InputState state) => true; + + protected override bool OnDrag(InputState state) + { + var currentRectangle = GetDragRectangle(); + + float left = currentRectangle.Left; + float right = currentRectangle.Right; + float top = currentRectangle.Top; + float bottom = currentRectangle.Bottom; + + // Apply modifications to the capture rectangle + if ((Anchor & Anchor.y0) > 0) + top += state.Mouse.Delta.Y; + else if ((Anchor & Anchor.y2) > 0) + bottom += state.Mouse.Delta.Y; + + if ((Anchor & Anchor.x0) > 0) + left += state.Mouse.Delta.X; + else if ((Anchor & Anchor.x2) > 0) + right += state.Mouse.Delta.X; + + UpdateDragRectangle(RectangleF.FromLTRB(left, top, right, bottom)); + return true; + } + + protected override bool OnDragEnd(InputState state) + { + FinishCapture(); + return true; + } + + protected override bool OnHover(InputState state) + { + this.FadeColour(hoverColour, 100); + return true; + } + + protected override void OnHoverLost(InputState state) + { + this.FadeColour(normalColour, 100); + } + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs similarity index 74% rename from osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs rename to osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs index e222583348..f6777908d7 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/MarkerContainer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs @@ -11,77 +11,77 @@ using osu.Framework.Graphics.Primitives; namespace osu.Game.Rulesets.Edit.Layers.Selection { /// - /// A that has s around its border. + /// A that has s around its border. /// - public class MarkerContainer : CompositeDrawable + public class HandleContainer : CompositeDrawable { /// - /// Invoked when a requires the current drag rectangle. + /// Invoked when a requires the current drag rectangle. /// public Func GetDragRectangle; /// - /// Invoked when a wants to update the drag rectangle. + /// Invoked when a wants to update the drag rectangle. /// public Action UpdateDragRectangle; /// - /// Invoked when a has finished updates to the drag rectangle. + /// Invoked when a has finished updates to the drag rectangle. /// public Action FinishCapture; - public MarkerContainer() + public HandleContainer() { InternalChildren = new Drawable[] { - new Marker + new Handle { Anchor = Anchor.TopLeft, Origin = Anchor.Centre }, - new Marker + new Handle { Anchor = Anchor.TopCentre, Origin = Anchor.Centre }, - new Marker + new Handle { Anchor = Anchor.TopRight, Origin = Anchor.Centre }, - new Marker + new Handle { Anchor = Anchor.CentreLeft, Origin = Anchor.Centre }, - new Marker + new Handle { Anchor = Anchor.BottomLeft, Origin = Anchor.Centre }, - new Marker + new Handle { Anchor = Anchor.CentreRight, Origin = Anchor.Centre }, - new Marker + new Handle { Anchor = Anchor.BottomRight, Origin = Anchor.Centre }, - new Marker + new Handle { Anchor = Anchor.BottomCentre, Origin = Anchor.Centre }, - new CentreMarker + new OriginHandle { Anchor = Anchor.Centre, Origin = Anchor.Centre } }; - InternalChildren.OfType().ForEach(m => + InternalChildren.OfType().ForEach(m => { m.GetDragRectangle = () => GetDragRectangle(); m.UpdateDragRectangle = r => UpdateDragRectangle(r); diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs index 6ea2778a9e..ce8f8b7ded 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection private readonly Container borderMask; private readonly Drawable background; - private readonly MarkerContainer markers; + private readonly HandleContainer handles; private Color4 captureFinishedColour; @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection }, } }, - markers = new MarkerContainer + handles = new HandleContainer { RelativeSizeAxes = Axes.Both, Alpha = 0, @@ -159,7 +159,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection // Transform into markers to let the user modify the drag selection further. background.Delay(50).FadeOut(200); - markers.FadeIn(200); + handles.FadeIn(200); Selection.Value = new SelectionInfo { diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs b/osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs similarity index 86% rename from osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs rename to osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs index 0ed7339134..8326ebeeac 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/CentreMarker.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs @@ -11,14 +11,14 @@ using OpenTK; namespace osu.Game.Rulesets.Edit.Layers.Selection { /// - /// Represents the centre of a . + /// Represents the origin of a . /// - public class CentreMarker : CompositeDrawable + public class OriginHandle : CompositeDrawable { private const float marker_size = 10; private const float line_width = 2; - public CentreMarker() + public OriginHandle() { Size = new Vector2(marker_size); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 514f91f80a..cf095b17a3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -307,10 +307,10 @@ - + - - + + From 5493493f828ba84235d8e138cecc39bca0cff683 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 19:24:41 +0900 Subject: [PATCH 36/39] FinishCapture -> FinishDrag from Handles --- osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs | 4 ++-- osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs | 4 ++-- .../Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs index e93fe886e1..1c6ddf4af0 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// /// Invoked when this has finished updates to the drag rectangle. /// - public Action FinishCapture; + public Action FinishDrag; private Color4 normalColour; private Color4 hoverColour; @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnDragEnd(InputState state) { - FinishCapture(); + FinishDrag(); return true; } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs index f6777908d7..22d993e7cd 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// /// Invoked when a has finished updates to the drag rectangle. /// - public Action FinishCapture; + public Action FinishDrag; public HandleContainer() { @@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection { m.GetDragRectangle = () => GetDragRectangle(); m.UpdateDragRectangle = r => UpdateDragRectangle(r); - m.FinishCapture = () => FinishCapture(); + m.FinishDrag = () => FinishDrag(); }); } } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs index ce8f8b7ded..13405e3054 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs @@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection updateDragRectangle(r); BeginCapture(); }, - FinishCapture = FinishCapture + FinishDrag = FinishCapture } }; } From fabf1bf60aa275d4748f894fdef4d18ae132adc4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Dec 2017 19:31:03 +0900 Subject: [PATCH 37/39] Make the captured objects not update for now Since this is not the intended functionality. --- .../Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs index 13405e3054..6f73d6b916 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs @@ -70,11 +70,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection RelativeSizeAxes = Axes.Both, Alpha = 0, GetDragRectangle = () => dragRectangle, - UpdateDragRectangle = r => - { - updateDragRectangle(r); - BeginCapture(); - }, + UpdateDragRectangle = updateDragRectangle, FinishDrag = FinishCapture } }; From 051a3c4d473aa7d3716363c3cbde2afbdb6201ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Dec 2017 21:51:00 +0900 Subject: [PATCH 38/39] Fix line endings --- .../Rulesets/Edit/Layers/Selection/Handle.cs | 210 +++++++++--------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs index 1c6ddf4af0..2982a68b3b 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs @@ -1,105 +1,105 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Game.Graphics; -using OpenTK; -using OpenTK.Graphics; - -namespace osu.Game.Rulesets.Edit.Layers.Selection -{ - /// - /// Represents a marker visible on the border of a which exposes - /// properties that are used to resize a . - /// - public class Handle : CompositeDrawable - { - private const float marker_size = 10; - - /// - /// Invoked when this requires the current drag rectangle. - /// - public Func GetDragRectangle; - - /// - /// Invoked when this wants to update the drag rectangle. - /// - public Action UpdateDragRectangle; - - /// - /// Invoked when this has finished updates to the drag rectangle. - /// - public Action FinishDrag; - - private Color4 normalColour; - private Color4 hoverColour; - - public Handle() - { - Size = new Vector2(marker_size); - - InternalChild = new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Child = new Box { RelativeSizeAxes = Axes.Both } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Colour = normalColour = colours.Yellow; - hoverColour = colours.YellowDarker; - } - - protected override bool OnDragStart(InputState state) => true; - - protected override bool OnDrag(InputState state) - { - var currentRectangle = GetDragRectangle(); - - float left = currentRectangle.Left; - float right = currentRectangle.Right; - float top = currentRectangle.Top; - float bottom = currentRectangle.Bottom; - - // Apply modifications to the capture rectangle - if ((Anchor & Anchor.y0) > 0) - top += state.Mouse.Delta.Y; - else if ((Anchor & Anchor.y2) > 0) - bottom += state.Mouse.Delta.Y; - - if ((Anchor & Anchor.x0) > 0) - left += state.Mouse.Delta.X; - else if ((Anchor & Anchor.x2) > 0) - right += state.Mouse.Delta.X; - - UpdateDragRectangle(RectangleF.FromLTRB(left, top, right, bottom)); - return true; - } - - protected override bool OnDragEnd(InputState state) - { - FinishDrag(); - return true; - } - - protected override bool OnHover(InputState state) - { - this.FadeColour(hoverColour, 100); - return true; - } - - protected override void OnHoverLost(InputState state) - { - this.FadeColour(normalColour, 100); - } - } -} +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Graphics; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + /// + /// Represents a marker visible on the border of a which exposes + /// properties that are used to resize a . + /// + public class Handle : CompositeDrawable + { + private const float marker_size = 10; + + /// + /// Invoked when this requires the current drag rectangle. + /// + public Func GetDragRectangle; + + /// + /// Invoked when this wants to update the drag rectangle. + /// + public Action UpdateDragRectangle; + + /// + /// Invoked when this has finished updates to the drag rectangle. + /// + public Action FinishDrag; + + private Color4 normalColour; + private Color4 hoverColour; + + public Handle() + { + Size = new Vector2(marker_size); + + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = new Box { RelativeSizeAxes = Axes.Both } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = normalColour = colours.Yellow; + hoverColour = colours.YellowDarker; + } + + protected override bool OnDragStart(InputState state) => true; + + protected override bool OnDrag(InputState state) + { + var currentRectangle = GetDragRectangle(); + + float left = currentRectangle.Left; + float right = currentRectangle.Right; + float top = currentRectangle.Top; + float bottom = currentRectangle.Bottom; + + // Apply modifications to the capture rectangle + if ((Anchor & Anchor.y0) > 0) + top += state.Mouse.Delta.Y; + else if ((Anchor & Anchor.y2) > 0) + bottom += state.Mouse.Delta.Y; + + if ((Anchor & Anchor.x0) > 0) + left += state.Mouse.Delta.X; + else if ((Anchor & Anchor.x2) > 0) + right += state.Mouse.Delta.X; + + UpdateDragRectangle(RectangleF.FromLTRB(left, top, right, bottom)); + return true; + } + + protected override bool OnDragEnd(InputState state) + { + FinishDrag(); + return true; + } + + protected override bool OnHover(InputState state) + { + this.FadeColour(hoverColour, 100); + return true; + } + + protected override void OnHoverLost(InputState state) + { + this.FadeColour(normalColour, 100); + } + } +} From c8afc553cbc5b9d17282389416343578a3db9636 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Dec 2017 23:55:34 +0900 Subject: [PATCH 39/39] Fix profile header not correctly being masked Closes #1592. --- osu.Game/Overlays/Profile/ProfileHeader.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 4e19b3153d..4ddd6c498e 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -53,6 +53,7 @@ namespace osu.Game.Overlays.Profile { RelativeSizeAxes = Axes.X, Height = cover_height, + Masking = true, Children = new Drawable[] { new Box @@ -324,8 +325,7 @@ namespace osu.Game.Overlays.Profile FillMode = FillMode.Fill, OnLoadComplete = d => d.FadeInFromZero(200), Depth = float.MaxValue, - }, - coverContainer.Add); + }, coverContainer.Add); if (user.IsSupporter) supporterTag.Show(); @@ -514,7 +514,7 @@ namespace osu.Game.Overlays.Profile { set { - if(value != null) + if (value != null) content.Action = () => Process.Start(value); } }