From cfb2b3f1e81fc0dbb09aa3ac89418bcc70c73619 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Feb 2018 16:02:42 +0900 Subject: [PATCH 01/16] Rework SelctionLayer to support click-selections --- .../Objects/Drawables/DrawableSlider.cs | 2 + .../Objects/Drawables/Pieces/SliderBody.cs | 2 + .../Visual/TestCaseEditorSelectionLayer.cs | 7 +- .../Layers/Selection/HitObjectCapturer.cs | 56 ++++++++++++++ .../Layers/Selection/HitObjectSelectionBox.cs | 73 ++++--------------- .../Edit/Layers/Selection/SelectionLayer.cs | 71 ++++++++++++++---- osu.Game/osu.Game.csproj | 1 + 7 files changed, 139 insertions(+), 73 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/HitObjectCapturer.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 5795bb8405..41df7ae4a4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -157,6 +157,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public Drawable ProxiedLayer => HeadCircle.ApproachCircle; + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => Body.ReceiveMouseInputAt(screenSpacePos); + public override Vector2 SelectionPoint => ToScreenSpace(Body.Position); public override Quad SelectionQuad => Body.PathDrawQuad; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 901d1c568d..89af67ba2a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -78,6 +78,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces container.Attach(RenderbufferInternalFormat.DepthComponent16); } + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => path.ReceiveMouseInputAt(screenSpacePos); + public void SetRange(double p0, double p1) { if (p0 > p1) diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index 755800c4e1..ae5296b70e 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -19,7 +19,12 @@ namespace osu.Game.Tests.Visual { public class TestCaseEditorSelectionLayer : OsuTestCase { - public override IReadOnlyList RequiredTypes => new[] { typeof(SelectionLayer) }; + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HitObjectCapturer), + typeof(HitObjectSelectionBox), + typeof(SelectionLayer) + }; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectCapturer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectCapturer.cs new file mode 100644 index 0000000000..e141f06816 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectCapturer.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Objects.Drawables; +using OpenTK; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + public class HitObjectCapturer + { + public event Action HitObjectCaptured; + + private readonly IEnumerable capturableHitObjects; + + public HitObjectCapturer(IEnumerable capturableHitObjects) + { + this.capturableHitObjects = capturableHitObjects; + } + + /// + /// Captures all hitobjects that are present within the area of a . + /// + /// The capture . + /// If any s were captured. + public bool CaptureQuad(Quad screenSpaceQuad) + { + bool anyCaptured = false; + foreach (var obj in capturableHitObjects.Where(h => h.IsAlive && h.IsPresent && screenSpaceQuad.Contains(h.SelectionPoint))) + { + HitObjectCaptured?.Invoke(obj); + anyCaptured = true; + } + + return anyCaptured; + } + + /// + /// Captures the top-most hitobject that is present under a specific point. + /// + /// The to capture at. + /// Whether a was captured. + public bool CapturePoint(Vector2 screenSpacePoint) + { + var captured = capturableHitObjects.Reverse().Where(h => h.IsAlive && h.IsPresent).FirstOrDefault(h => h.ReceiveMouseInputAt(screenSpacePoint)); + if (captured == null) + return false; + + HitObjectCaptured?.Invoke(captured); + return true; + } + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs index fcb2f8f57f..c887cd0b7b 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 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; @@ -12,7 +11,6 @@ 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 { @@ -21,29 +19,18 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// public class HitObjectSelectionBox : CompositeDrawable { - public readonly Bindable Selection = new Bindable(); - - /// - /// The s that can be selected through a drag-selection. - /// - public IEnumerable CapturableObjects; - private readonly Container borderMask; private readonly Drawable background; private readonly HandleContainer handles; private Color4 captureFinishedColour; - - private readonly Vector2 startPos; + private RectangleF dragRectangle; /// /// Creates a new . /// - /// The point at which the drag was initiated, in the parent's coordinates. - public HitObjectSelectionBox(Vector2 startPos) + public HitObjectSelectionBox() { - this.startPos = startPos; - InternalChildren = new Drawable[] { new Container @@ -70,8 +57,8 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection RelativeSizeAxes = Axes.Both, Alpha = 0, GetDragRectangle = () => dragRectangle, - UpdateDragRectangle = updateDragRectangle, - FinishDrag = FinishCapture + UpdateDragRectangle = SetDragRectangle, + FinishDrag = () => FinishCapture() } }; } @@ -82,49 +69,29 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection 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) + public void SetDragRectangle(RectangleF rectangle) { dragRectangle = rectangle; - Position = new Vector2( - Math.Min(rectangle.Left, rectangle.Right), - Math.Min(rectangle.Top, rectangle.Bottom)); + var topLeft = Parent.ToLocalSpace(rectangle.TopLeft); + var bottomRight = Parent.ToLocalSpace(rectangle.BottomRight); - Size = new Vector2( - Math.Max(rectangle.Left, rectangle.Right) - Position.X, - Math.Max(rectangle.Top, rectangle.Bottom) - Position.Y); + Position = topLeft; + Size = bottomRight - topLeft; } private readonly List capturedHitObjects = new List(); - /// - /// 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(); + public bool HasCaptured => capturedHitObjects.Count > 0; - foreach (var obj in CapturableObjects) - { - if (!obj.IsAlive || !obj.IsPresent) - continue; + public void AddCaptured(DrawableHitObject hitObject) => capturedHitObjects.Add(hitObject); - if (ScreenSpaceDrawQuad.Contains(obj.SelectionPoint)) - capturedHitObjects.Add(obj); - } - } + public void ClearCaptured() => capturedHitObjects.Clear(); /// /// Encloses hitobjects captured through in the drag selection box. /// - public void FinishCapture() + public void FinishCapture(bool instant = false) { if (capturedHitObjects.Count == 0) { @@ -145,8 +112,8 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection topLeft -= new Vector2(5); bottomRight += new Vector2(5); - this.MoveTo(topLeft, 200, Easing.OutQuint) - .ResizeTo(bottomRight - topLeft, 200, Easing.OutQuint); + this.MoveTo(topLeft, instant ? 0 : 100, Easing.OutQuint) + .ResizeTo(bottomRight - topLeft, instant ? 0 : 100, Easing.OutQuint); dragRectangle = RectangleF.FromLTRB(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y); @@ -156,12 +123,6 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection // Transform into markers to let the user modify the drag selection further. background.Delay(50).FadeOut(200); handles.FadeIn(200); - - Selection.Value = new SelectionInfo - { - Objects = capturedHitObjects, - SelectionQuad = Parent.ToScreenSpace(dragRectangle) - }; } private bool isActive = true; @@ -171,9 +132,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection public override void Hide() { isActive = false; - this.FadeOut(400, Easing.OutQuint).Expire(); - - Selection.Value = null; + this.FadeOut(400, Easing.OutQuint); } } } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index 93755d400a..b9ece8759c 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -1,18 +1,18 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Configuration; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; 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) @@ -22,39 +22,80 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection RelativeSizeAxes = Axes.Both; } - private HitObjectSelectionBox selectionBoxBox; + private HitObjectSelectionBox selectionBox; + private HitObjectCapturer capturer; + + [BackgroundDependencyLoader] + private void load() + { + capturer = new HitObjectCapturer(playfield.HitObjects.Objects); + capturer.HitObjectCaptured += hitObjectCaptured; + } + + private void hitObjectCaptured(DrawableHitObject hitObject) => selectionBox.AddCaptured(hitObject); protected override bool OnDragStart(InputState state) { // Hide the previous drag box - we won't be working with it any longer - selectionBoxBox?.Hide(); + selectionBox?.Hide(); + selectionBox?.Expire(); - AddInternal(selectionBoxBox = new HitObjectSelectionBox(ToLocalSpace(state.Mouse.NativeState.Position)) - { - CapturableObjects = playfield.HitObjects.Objects, - }); - - Selection.BindTo(selectionBoxBox.Selection); + AddInternal(selectionBox = new HitObjectSelectionBox()); return true; } protected override bool OnDrag(InputState state) { - selectionBoxBox.DragEndPosition = ToLocalSpace(state.Mouse.NativeState.Position); - selectionBoxBox.BeginCapture(); + var dragPosition = state.Mouse.NativeState.Position; + var dragStartPosition = state.Mouse.NativeState.PositionMouseDown ?? dragPosition; + + var screenSpaceDragQuad = new Quad(dragStartPosition.X, dragStartPosition.Y, dragPosition.X - dragStartPosition.X, dragPosition.Y - dragStartPosition.Y); + + selectionBox.SetDragRectangle(screenSpaceDragQuad.AABBFloat); + capturer.CaptureQuad(screenSpaceDragQuad); + return true; } protected override bool OnDragEnd(InputState state) { - selectionBoxBox.FinishCapture(); + // Due to https://github.com/ppy/osu-framework/issues/1382, we may get here after OnClick has set the selectionBox to null + // In the case that the user dragged within the click distance out of an object + if (selectionBox == null) + return true; + + selectionBox.FinishCapture(); + + // If there are no hitobjects, remove the selection box + if (!selectionBox.HasCaptured) + { + selectionBox.Expire(); + selectionBox = null; + } + return true; } protected override bool OnClick(InputState state) { - selectionBoxBox?.Hide(); + // We could be coming here without a previous selection box + if (selectionBox == null) + AddInternal(selectionBox = new HitObjectSelectionBox { Position = ToLocalSpace(state.Mouse.NativeState.Position), Alpha = 0 }); + + // If we're coming here with a previous selection, unselect those hitobjects + selectionBox.ClearCaptured(); + if (capturer.CapturePoint(state.Mouse.NativeState.Position)) + { + selectionBox.Alpha = 1; + selectionBox.FinishCapture(true); + } + else + { + selectionBox.Hide(); + selectionBox = null; + } + return true; } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index bb9925abbc..e1f5eee182 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -332,6 +332,7 @@ + From 1adbe3585c14c0f5b37e7192dd8c0aa270bb150f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Feb 2018 16:03:59 +0900 Subject: [PATCH 02/16] HitObjectSelectionBox -> SelectionDragger --- .../Visual/TestCaseEditorSelectionLayer.cs | 2 +- .../Rulesets/Edit/Layers/Selection/Handle.cs | 2 +- ...ectSelectionBox.cs => SelectionDragger.cs} | 6 ++-- .../Edit/Layers/Selection/SelectionLayer.cs | 36 +++++++++---------- osu.Game/osu.Game.csproj | 2 +- 5 files changed, 24 insertions(+), 24 deletions(-) rename osu.Game/Rulesets/Edit/Layers/Selection/{HitObjectSelectionBox.cs => SelectionDragger.cs} (94%) diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index ae5296b70e..a7220718f5 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual public override IReadOnlyList RequiredTypes => new[] { typeof(HitObjectCapturer), - typeof(HitObjectSelectionBox), + typeof(SelectionDragger), typeof(SelectionLayer) }; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs index d275022a15..e85096110b 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.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 Handle : CompositeDrawable { diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs similarity index 94% rename from osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs rename to osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs index c887cd0b7b..b08d208bbd 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// /// A box that represents a drag selection. /// - public class HitObjectSelectionBox : CompositeDrawable + public class SelectionDragger : CompositeDrawable { private readonly Container borderMask; private readonly Drawable background; @@ -27,9 +27,9 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection private RectangleF dragRectangle; /// - /// Creates a new . + /// Creates a new . /// - public HitObjectSelectionBox() + public SelectionDragger() { InternalChildren = new Drawable[] { diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index b9ece8759c..19891b0783 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection RelativeSizeAxes = Axes.Both; } - private HitObjectSelectionBox selectionBox; + private SelectionDragger selectionDragger; private HitObjectCapturer capturer; [BackgroundDependencyLoader] @@ -32,15 +32,15 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection capturer.HitObjectCaptured += hitObjectCaptured; } - private void hitObjectCaptured(DrawableHitObject hitObject) => selectionBox.AddCaptured(hitObject); + private void hitObjectCaptured(DrawableHitObject hitObject) => selectionDragger.AddCaptured(hitObject); protected override bool OnDragStart(InputState state) { // Hide the previous drag box - we won't be working with it any longer - selectionBox?.Hide(); - selectionBox?.Expire(); + selectionDragger?.Hide(); + selectionDragger?.Expire(); - AddInternal(selectionBox = new HitObjectSelectionBox()); + AddInternal(selectionDragger = new SelectionDragger()); return true; } @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection var screenSpaceDragQuad = new Quad(dragStartPosition.X, dragStartPosition.Y, dragPosition.X - dragStartPosition.X, dragPosition.Y - dragStartPosition.Y); - selectionBox.SetDragRectangle(screenSpaceDragQuad.AABBFloat); + selectionDragger.SetDragRectangle(screenSpaceDragQuad.AABBFloat); capturer.CaptureQuad(screenSpaceDragQuad); return true; @@ -62,16 +62,16 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection { // Due to https://github.com/ppy/osu-framework/issues/1382, we may get here after OnClick has set the selectionBox to null // In the case that the user dragged within the click distance out of an object - if (selectionBox == null) + if (selectionDragger == null) return true; - selectionBox.FinishCapture(); + selectionDragger.FinishCapture(); // If there are no hitobjects, remove the selection box - if (!selectionBox.HasCaptured) + if (!selectionDragger.HasCaptured) { - selectionBox.Expire(); - selectionBox = null; + selectionDragger.Expire(); + selectionDragger = null; } return true; @@ -80,20 +80,20 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnClick(InputState state) { // We could be coming here without a previous selection box - if (selectionBox == null) - AddInternal(selectionBox = new HitObjectSelectionBox { Position = ToLocalSpace(state.Mouse.NativeState.Position), Alpha = 0 }); + if (selectionDragger == null) + AddInternal(selectionDragger = new SelectionDragger { Position = ToLocalSpace(state.Mouse.NativeState.Position), Alpha = 0 }); // If we're coming here with a previous selection, unselect those hitobjects - selectionBox.ClearCaptured(); + selectionDragger.ClearCaptured(); if (capturer.CapturePoint(state.Mouse.NativeState.Position)) { - selectionBox.Alpha = 1; - selectionBox.FinishCapture(true); + selectionDragger.Alpha = 1; + selectionDragger.FinishCapture(true); } else { - selectionBox.Hide(); - selectionBox = null; + selectionDragger.Hide(); + selectionDragger = null; } return true; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e1f5eee182..77e594c37c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -353,7 +353,7 @@ - + From ee168f9a77962e25c8419d3a2fdccd55eb945807 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Feb 2018 18:19:55 +0900 Subject: [PATCH 03/16] Split out drag selection box from post-capture box Cleans up a lot of code, removes handles for now. --- .../Visual/TestCaseEditorSelectionLayer.cs | 3 +- .../Edit/Layers/Selection/CaptureBox.cs | 76 ++++++++++++++++ .../Edit/Layers/Selection/SelectionDragger.cs | 87 +------------------ .../Edit/Layers/Selection/SelectionLayer.cs | 61 ++++++------- osu.Game/osu.Game.csproj | 1 + 5 files changed, 108 insertions(+), 120 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index a7220718f5..9796d1715f 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -23,7 +23,8 @@ namespace osu.Game.Tests.Visual { typeof(HitObjectCapturer), typeof(SelectionDragger), - typeof(SelectionLayer) + typeof(SelectionLayer), + typeof(CaptureBox) }; [BackgroundDependencyLoader] diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs new file mode 100644 index 0000000000..f49a294129 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs @@ -0,0 +1,76 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.Objects.Drawables; +using OpenTK; + +namespace osu.Game.Rulesets.Edit.Layers.Selection +{ + /// + /// A box which encapsulates captured s. + /// + public class CaptureBox : VisibilityContainer + { + private readonly IDrawable captureArea; + private readonly IReadOnlyList capturedObjects; + + private readonly Container borderContainer; + + public CaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects) + { + this.captureArea = captureArea; + this.capturedObjects = capturedObjects; + + Origin = Anchor.Centre; + + InternalChild = borderContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = 3, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + AlwaysPresent = true, + Alpha = 0 + } + }; + + State = Visibility.Visible; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + borderContainer.BorderColour = colours.Yellow; + + // 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 capturedObjects) + { + topLeft = Vector2.ComponentMin(topLeft, captureArea.ToLocalSpace(obj.SelectionQuad.TopLeft)); + bottomRight = Vector2.ComponentMax(bottomRight, captureArea.ToLocalSpace(obj.SelectionQuad.BottomRight)); + } + + topLeft -= new Vector2(5); + bottomRight += new Vector2(5); + + Size = bottomRight - topLeft; + Position = topLeft + Size / 2f; + } + + protected override void PopIn() => this.ScaleTo(1.1f) + .Then() + .ScaleTo(1f, 300, Easing.OutQuint).FadeIn(300, Easing.OutQuint); + + protected override void PopOut() => this.FadeOut(300, Easing.OutQuint); + } +} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs index b08d208bbd..661d09d883 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs @@ -1,15 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -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 @@ -19,13 +14,6 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// public class SelectionDragger : CompositeDrawable { - private readonly Container borderMask; - private readonly Drawable background; - private readonly HandleContainer handles; - - private Color4 captureFinishedColour; - private RectangleF dragRectangle; - /// /// Creates a new . /// @@ -37,42 +25,26 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(-1), - Child = borderMask = new Container + Child = new Container { RelativeSizeAxes = Axes.Both, Masking = true, BorderColour = Color4.White, BorderThickness = 2, MaskingSmoothness = 1, - Child = background = new Box + Child = new Box { RelativeSizeAxes = Axes.Both, Alpha = 0.1f, AlwaysPresent = true }, } - }, - handles = new HandleContainer - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - GetDragRectangle = () => dragRectangle, - UpdateDragRectangle = SetDragRectangle, - FinishDrag = () => FinishCapture() } }; } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - captureFinishedColour = colours.Yellow; - } - public void SetDragRectangle(RectangleF rectangle) { - dragRectangle = rectangle; - var topLeft = Parent.ToLocalSpace(rectangle.TopLeft); var bottomRight = Parent.ToLocalSpace(rectangle.BottomRight); @@ -80,59 +52,6 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection Size = bottomRight - topLeft; } - private readonly List capturedHitObjects = new List(); - - public bool HasCaptured => capturedHitObjects.Count > 0; - - public void AddCaptured(DrawableHitObject hitObject) => capturedHitObjects.Add(hitObject); - - public void ClearCaptured() => capturedHitObjects.Clear(); - - /// - /// Encloses hitobjects captured through in the drag selection box. - /// - public void FinishCapture(bool instant = false) - { - 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, instant ? 0 : 100, Easing.OutQuint) - .ResizeTo(bottomRight - topLeft, instant ? 0 : 100, 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); - handles.FadeIn(200); - } - - private bool isActive = true; - public override bool HandleKeyboardInput => isActive; - public override bool HandleMouseInput => isActive; - - public override void Hide() - { - isActive = false; - this.FadeOut(400, Easing.OutQuint); - } + public override void Hide() => this.FadeOut(400, Easing.OutQuint).Expire(); } } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index 19891b0783..a90d01646e 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -23,25 +25,28 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection } private SelectionDragger selectionDragger; + private CaptureBox captureBox; private HitObjectCapturer capturer; + private readonly List capturedHitObjects = new List(); + [BackgroundDependencyLoader] private void load() { capturer = new HitObjectCapturer(playfield.HitObjects.Objects); - capturer.HitObjectCaptured += hitObjectCaptured; + capturer.HitObjectCaptured += h => capturedHitObjects.Add(h); } - private void hitObjectCaptured(DrawableHitObject hitObject) => selectionDragger.AddCaptured(hitObject); + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + capturedHitObjects.Clear(); + captureBox?.Hide(); + return true; + } protected override bool OnDragStart(InputState state) { - // Hide the previous drag box - we won't be working with it any longer - selectionDragger?.Hide(); - selectionDragger?.Expire(); - AddInternal(selectionDragger = new SelectionDragger()); - return true; } @@ -60,43 +65,29 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnDragEnd(InputState state) { - // Due to https://github.com/ppy/osu-framework/issues/1382, we may get here after OnClick has set the selectionBox to null - // In the case that the user dragged within the click distance out of an object - if (selectionDragger == null) - return true; - - selectionDragger.FinishCapture(); - - // If there are no hitobjects, remove the selection box - if (!selectionDragger.HasCaptured) - { - selectionDragger.Expire(); - selectionDragger = null; - } + selectionDragger.Hide(); + finishCapture(); return true; } protected override bool OnClick(InputState state) { - // We could be coming here without a previous selection box - if (selectionDragger == null) - AddInternal(selectionDragger = new SelectionDragger { Position = ToLocalSpace(state.Mouse.NativeState.Position), Alpha = 0 }); - - // If we're coming here with a previous selection, unselect those hitobjects - selectionDragger.ClearCaptured(); if (capturer.CapturePoint(state.Mouse.NativeState.Position)) - { - selectionDragger.Alpha = 1; - selectionDragger.FinishCapture(true); - } - else - { - selectionDragger.Hide(); - selectionDragger = null; - } + finishCapture(); return true; } + + private void finishCapture() + { + if (capturedHitObjects.Count == 0) + return; + + // Due to https://github.com/ppy/osu-framework/issues/1382, we may get here through both + // OnDragEnd and OnClick methods within a single frame, OnMouseDown doesn't help us here + captureBox?.Hide(); + AddInternal(captureBox = new CaptureBox(this, capturedHitObjects.ToList())); + } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 77e594c37c..ce0813f393 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -332,6 +332,7 @@ + From 20c0dee17df2bb5bfd74bfa60a7226e7013b53db Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Feb 2018 18:22:52 +0900 Subject: [PATCH 04/16] Remove SelectionInfo --- .../Edit/Layers/Selection/SelectionInfo.cs | 22 ------------------- osu.Game/osu.Game.csproj | 1 - 2 files changed, 23 deletions(-) delete mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs deleted file mode 100644 index beedb415c2..0000000000 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2007-2018 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; - -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/osu.Game.csproj b/osu.Game/osu.Game.csproj index ce0813f393..7e884fdc24 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -357,7 +357,6 @@ - From e10bb2db0591c2ef51cf6418bbdc2ba007b0ac28 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Feb 2018 18:35:01 +0900 Subject: [PATCH 05/16] Unify SelectionLayer and HitObjectCapturer, rename SelectionBox --- .../Visual/TestCaseEditorSelectionLayer.cs | 3 +- .../Layers/Selection/HitObjectCapturer.cs | 56 ------------------- .../{SelectionDragger.cs => SelectionBox.cs} | 6 +- .../Edit/Layers/Selection/SelectionLayer.cs | 47 ++++++++++------ osu.Game/osu.Game.csproj | 3 +- 5 files changed, 36 insertions(+), 79 deletions(-) delete mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/HitObjectCapturer.cs rename osu.Game/Rulesets/Edit/Layers/Selection/{SelectionDragger.cs => SelectionBox.cs} (89%) diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index 9796d1715f..50a39e6c33 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -21,8 +21,7 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { - typeof(HitObjectCapturer), - typeof(SelectionDragger), + typeof(SelectionBox), typeof(SelectionLayer), typeof(CaptureBox) }; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectCapturer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectCapturer.cs deleted file mode 100644 index e141f06816..0000000000 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectCapturer.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Graphics.Primitives; -using osu.Game.Rulesets.Objects.Drawables; -using OpenTK; - -namespace osu.Game.Rulesets.Edit.Layers.Selection -{ - public class HitObjectCapturer - { - public event Action HitObjectCaptured; - - private readonly IEnumerable capturableHitObjects; - - public HitObjectCapturer(IEnumerable capturableHitObjects) - { - this.capturableHitObjects = capturableHitObjects; - } - - /// - /// Captures all hitobjects that are present within the area of a . - /// - /// The capture . - /// If any s were captured. - public bool CaptureQuad(Quad screenSpaceQuad) - { - bool anyCaptured = false; - foreach (var obj in capturableHitObjects.Where(h => h.IsAlive && h.IsPresent && screenSpaceQuad.Contains(h.SelectionPoint))) - { - HitObjectCaptured?.Invoke(obj); - anyCaptured = true; - } - - return anyCaptured; - } - - /// - /// Captures the top-most hitobject that is present under a specific point. - /// - /// The to capture at. - /// Whether a was captured. - public bool CapturePoint(Vector2 screenSpacePoint) - { - var captured = capturableHitObjects.Reverse().Where(h => h.IsAlive && h.IsPresent).FirstOrDefault(h => h.ReceiveMouseInputAt(screenSpacePoint)); - if (captured == null) - return false; - - HitObjectCaptured?.Invoke(captured); - return true; - } - } -} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs similarity index 89% rename from osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs rename to osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs index 661d09d883..87c6833f01 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionDragger.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs @@ -12,12 +12,12 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// /// A box that represents a drag selection. /// - public class SelectionDragger : CompositeDrawable + public class SelectionBox : CompositeDrawable { /// - /// Creates a new . + /// Creates a new . /// - public SelectionDragger() + public SelectionBox() { InternalChildren = new Drawable[] { diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index a90d01646e..e7a46569f1 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -3,13 +3,13 @@ using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; +using OpenTK; namespace osu.Game.Rulesets.Edit.Layers.Selection { @@ -24,19 +24,11 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection RelativeSizeAxes = Axes.Both; } - private SelectionDragger selectionDragger; + private SelectionBox selectionBox; private CaptureBox captureBox; - private HitObjectCapturer capturer; private readonly List capturedHitObjects = new List(); - [BackgroundDependencyLoader] - private void load() - { - capturer = new HitObjectCapturer(playfield.HitObjects.Objects); - capturer.HitObjectCaptured += h => capturedHitObjects.Add(h); - } - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { capturedHitObjects.Clear(); @@ -46,7 +38,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnDragStart(InputState state) { - AddInternal(selectionDragger = new SelectionDragger()); + AddInternal(selectionBox = new SelectionBox()); return true; } @@ -57,15 +49,15 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection var screenSpaceDragQuad = new Quad(dragStartPosition.X, dragStartPosition.Y, dragPosition.X - dragStartPosition.X, dragPosition.Y - dragStartPosition.Y); - selectionDragger.SetDragRectangle(screenSpaceDragQuad.AABBFloat); - capturer.CaptureQuad(screenSpaceDragQuad); + selectionBox.SetDragRectangle(screenSpaceDragQuad.AABBFloat); + captureQuad(screenSpaceDragQuad); return true; } protected override bool OnDragEnd(InputState state) { - selectionDragger.Hide(); + selectionBox.Hide(); finishCapture(); return true; @@ -73,12 +65,35 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnClick(InputState state) { - if (capturer.CapturePoint(state.Mouse.NativeState.Position)) - finishCapture(); + capturePoint(state.Mouse.NativeState.Position); + finishCapture(); return true; } + /// + /// Captures all hitobjects that are present within the area of a . + /// + /// The capture . + private void captureQuad(Quad screenSpaceQuad) + { + foreach (var obj in playfield.HitObjects.Objects.Where(h => h.IsAlive && h.IsPresent && screenSpaceQuad.Contains(h.SelectionPoint))) + capturedHitObjects.Add(obj); + } + + /// + /// Captures the top-most hitobject that is present under a specific point. + /// + /// The to capture at. + private void capturePoint(Vector2 screenSpacePoint) + { + var captured = playfield.HitObjects.Objects.Reverse().Where(h => h.IsAlive && h.IsPresent).FirstOrDefault(h => h.ReceiveMouseInputAt(screenSpacePoint)); + if (captured == null) + return; + + capturedHitObjects.Add(captured); + } + private void finishCapture() { if (capturedHitObjects.Count == 0) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 7e884fdc24..69b5c45890 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -333,7 +333,6 @@ - @@ -354,9 +353,9 @@ - + From c3212d36efb74f5721419621e8480eb4952674c1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Feb 2018 18:36:16 +0900 Subject: [PATCH 06/16] Remove handles for now (will be re-implemented) --- .../Rulesets/Edit/Layers/Selection/Handle.cs | 105 ------------------ .../Edit/Layers/Selection/HandleContainer.cs | 92 --------------- .../Edit/Layers/Selection/OriginHandle.cs | 50 --------- osu.Game/osu.Game.csproj | 3 - 4 files changed, 250 deletions(-) delete mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs delete mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs delete mode 100644 osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs deleted file mode 100644 index e85096110b..0000000000 --- a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2007-2018 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); - } - } -} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs deleted file mode 100644 index 359cdd009a..0000000000 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2007-2018 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; -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 HandleContainer : 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 FinishDrag; - - public HandleContainer() - { - InternalChildren = new Drawable[] - { - new Handle - { - Anchor = Anchor.TopLeft, - Origin = Anchor.Centre - }, - new Handle - { - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre - }, - new Handle - { - Anchor = Anchor.TopRight, - Origin = Anchor.Centre - }, - new Handle - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.Centre - }, - new Handle - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.Centre - }, - new Handle - { - Anchor = Anchor.CentreRight, - Origin = Anchor.Centre - }, - new Handle - { - Anchor = Anchor.BottomRight, - Origin = Anchor.Centre - }, - new Handle - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.Centre - }, - new OriginHandle - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - } - }; - - InternalChildren.OfType().ForEach(m => - { - m.GetDragRectangle = () => GetDragRectangle(); - m.UpdateDragRectangle = r => UpdateDragRectangle(r); - m.FinishDrag = () => FinishDrag(); - }); - } - } -} diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs b/osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs deleted file mode 100644 index 6f8c946165..0000000000 --- a/osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2007-2018 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; -using osu.Game.Graphics; -using OpenTK; - -namespace osu.Game.Rulesets.Edit.Layers.Selection -{ - /// - /// Represents the origin of a . - /// - public class OriginHandle : CompositeDrawable - { - private const float marker_size = 10; - private const float line_width = 2; - - public OriginHandle() - { - 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 69b5c45890..3b62c849cb 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -352,9 +352,6 @@ - - - From bfedd1cee03a067d1e5f39ee821b9b7a5a2f688a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Feb 2018 19:00:44 +0900 Subject: [PATCH 07/16] Remove nested container --- .../Edit/Layers/Selection/CaptureBox.cs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs index f49a294129..423927481c 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs @@ -20,26 +20,20 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection private readonly IDrawable captureArea; private readonly IReadOnlyList capturedObjects; - private readonly Container borderContainer; - public CaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects) { this.captureArea = captureArea; this.capturedObjects = capturedObjects; Origin = Anchor.Centre; + Masking = true; + BorderThickness = 3; - InternalChild = borderContainer = new Container + InternalChild = new Box { RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = 3, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - AlwaysPresent = true, - Alpha = 0 - } + AlwaysPresent = true, + Alpha = 0 }; State = Visibility.Visible; @@ -48,7 +42,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection [BackgroundDependencyLoader] private void load(OsuColour colours) { - borderContainer.BorderColour = colours.Yellow; + BorderColour = colours.Yellow; // Move the rectangle to cover the hitobjects var topLeft = new Vector2(float.MaxValue, float.MaxValue); From 344da5965c1fea626eb46615e18a49f8469e504a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Feb 2018 14:38:37 +0900 Subject: [PATCH 08/16] Add a CaptureBox that encloses hitobjects from the drag selection --- .../Edit/Layers/Selection/CaptureBox.cs | 59 ++++++++++++++++--- .../Edit/Layers/Selection/SelectionLayer.cs | 12 ++-- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs index 423927481c..5d1bcd1ef7 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs @@ -15,17 +15,26 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// /// A box which encapsulates captured s. /// - public class CaptureBox : VisibilityContainer + public abstract class CaptureBox : VisibilityContainer { + /// + /// Top-left corner of the rectangle that encloses the s. + /// + protected Vector2 FinalPosition { get; private set; } + + /// + /// Size of the rectangle that encloses the s. + /// + protected Vector2 FinalSize { get; private set; } + private readonly IDrawable captureArea; private readonly IReadOnlyList capturedObjects; - public CaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects) + protected CaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects) { this.captureArea = captureArea; this.capturedObjects = capturedObjects; - Origin = Anchor.Centre; Masking = true; BorderThickness = 3; @@ -57,13 +66,47 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection topLeft -= new Vector2(5); bottomRight += new Vector2(5); - Size = bottomRight - topLeft; - Position = topLeft + Size / 2f; + FinalSize = bottomRight - topLeft; + FinalPosition = topLeft; } - protected override void PopIn() => this.ScaleTo(1.1f) - .Then() - .ScaleTo(1f, 300, Easing.OutQuint).FadeIn(300, Easing.OutQuint); + protected override void PopIn() => this.MoveTo(FinalPosition).ResizeTo(FinalSize).FadeIn(); + protected override void PopOut() => this.FadeOut(); + } + + /// + /// A which fully encloses the s from the start. + /// + public class InstantCaptureBox : CaptureBox + { + public InstantCaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects) + : base(captureArea, capturedObjects) + { + Origin = Anchor.Centre; + } + + protected override void PopIn() + => this.MoveTo(FinalPosition + FinalSize / 2f).ResizeTo(FinalSize).ScaleTo(1.1f) + .Then() + .ScaleTo(1f, 300, Easing.OutQuint).FadeIn(300, Easing.OutQuint); + + protected override void PopOut() => this.FadeOut(300, Easing.OutQuint); + } + + /// + /// A which moves from an initial position + size to enclose s. + /// + public class DragCaptureBox : CaptureBox + { + public DragCaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects, Vector2 initialPosition, Vector2 initialSize) + : base(captureArea, capturedObjects) + { + Position = initialPosition; + Size = initialSize; + } + + protected override void PopIn() + => this.MoveTo(FinalPosition, 300, Easing.OutQuint).ResizeTo(FinalSize, 300, Easing.OutQuint).FadeIn(300, Easing.OutQuint); protected override void PopOut() => this.FadeOut(300, Easing.OutQuint); } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index e7a46569f1..e1fc0d179a 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnDragEnd(InputState state) { selectionBox.Hide(); - finishCapture(); + finishCapture(true); return true; } @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnClick(InputState state) { capturePoint(state.Mouse.NativeState.Position); - finishCapture(); + finishCapture(false); return true; } @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection capturedHitObjects.Add(captured); } - private void finishCapture() + private void finishCapture(bool fromDrag) { if (capturedHitObjects.Count == 0) return; @@ -102,7 +102,11 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection // Due to https://github.com/ppy/osu-framework/issues/1382, we may get here through both // OnDragEnd and OnClick methods within a single frame, OnMouseDown doesn't help us here captureBox?.Hide(); - AddInternal(captureBox = new CaptureBox(this, capturedHitObjects.ToList())); + + if (fromDrag) + AddInternal(captureBox = new DragCaptureBox(this, capturedHitObjects.ToList(), selectionBox.Position, selectionBox.Size)); + else + AddInternal(captureBox = new InstantCaptureBox(this, capturedHitObjects.ToList())); } } } From 27c6f4ee83b085af771d2856403a38992f412300 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Feb 2018 14:41:06 +0900 Subject: [PATCH 09/16] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index eba12eb4a0..63c9440bfb 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit eba12eb4a0fa6238873dd266deb35bfdece21a6a +Subproject commit 63c9440bfbd2bfb36f14c9ee0a521a6c46849cec From a9d14eadacea77e5b479adb7396367f45c31132a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Feb 2018 17:53:04 +0900 Subject: [PATCH 10/16] Add clearSelection method --- .../Edit/Layers/Selection/SelectionLayer.cs | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index e1fc0d179a..a335108a0f 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -27,12 +27,11 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection private SelectionBox selectionBox; private CaptureBox captureBox; - private readonly List capturedHitObjects = new List(); + private readonly List selectedHitObjects = new List(); protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - capturedHitObjects.Clear(); - captureBox?.Hide(); + clearSelection(); return true; } @@ -71,6 +70,15 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection return true; } + /// + /// Deselects all selected s. + /// + private void clearSelection() + { + selectedHitObjects.Clear(); + captureBox?.Hide(); + } + /// /// Captures all hitobjects that are present within the area of a . /// @@ -78,7 +86,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection private void captureQuad(Quad screenSpaceQuad) { foreach (var obj in playfield.HitObjects.Objects.Where(h => h.IsAlive && h.IsPresent && screenSpaceQuad.Contains(h.SelectionPoint))) - capturedHitObjects.Add(obj); + selectedHitObjects.Add(obj); } /// @@ -91,12 +99,12 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection if (captured == null) return; - capturedHitObjects.Add(captured); + selectedHitObjects.Add(captured); } private void finishCapture(bool fromDrag) { - if (capturedHitObjects.Count == 0) + if (selectedHitObjects.Count == 0) return; // Due to https://github.com/ppy/osu-framework/issues/1382, we may get here through both @@ -104,9 +112,9 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection captureBox?.Hide(); if (fromDrag) - AddInternal(captureBox = new DragCaptureBox(this, capturedHitObjects.ToList(), selectionBox.Position, selectionBox.Size)); + AddInternal(captureBox = new DragCaptureBox(this, selectedHitObjects.ToList(), selectionBox.Position, selectionBox.Size)); else - AddInternal(captureBox = new InstantCaptureBox(this, capturedHitObjects.ToList())); + AddInternal(captureBox = new InstantCaptureBox(this, selectedHitObjects.ToList())); } } } From 115484741d694dab9602548e58b7f8b3d2617541 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 14 Feb 2018 17:54:43 +0900 Subject: [PATCH 11/16] Capture -> Select --- .../Edit/Layers/Selection/CaptureBox.cs | 2 +- .../Edit/Layers/Selection/SelectionLayer.cs | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs index 5d1bcd1ef7..86e96f6d84 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs @@ -13,7 +13,7 @@ using OpenTK; namespace osu.Game.Rulesets.Edit.Layers.Selection { /// - /// A box which encapsulates captured s. + /// A box which encloses s. /// public abstract class CaptureBox : VisibilityContainer { diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index a335108a0f..0fceced040 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection var screenSpaceDragQuad = new Quad(dragStartPosition.X, dragStartPosition.Y, dragPosition.X - dragStartPosition.X, dragPosition.Y - dragStartPosition.Y); selectionBox.SetDragRectangle(screenSpaceDragQuad.AABBFloat); - captureQuad(screenSpaceDragQuad); + selectQuad(screenSpaceDragQuad); return true; } @@ -57,15 +57,15 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnDragEnd(InputState state) { selectionBox.Hide(); - finishCapture(true); + finishSelection(true); return true; } protected override bool OnClick(InputState state) { - capturePoint(state.Mouse.NativeState.Position); - finishCapture(false); + selectPoint(state.Mouse.NativeState.Position); + finishSelection(false); return true; } @@ -80,29 +80,29 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection } /// - /// Captures all hitobjects that are present within the area of a . + /// Selects all hitobjects that are present within the area of a . /// - /// The capture . - private void captureQuad(Quad screenSpaceQuad) + /// The selection . + private void selectQuad(Quad screenSpaceQuad) { foreach (var obj in playfield.HitObjects.Objects.Where(h => h.IsAlive && h.IsPresent && screenSpaceQuad.Contains(h.SelectionPoint))) selectedHitObjects.Add(obj); } /// - /// Captures the top-most hitobject that is present under a specific point. + /// Selects the top-most hitobject that is present under a specific point. /// - /// The to capture at. - private void capturePoint(Vector2 screenSpacePoint) + /// The to select at. + private void selectPoint(Vector2 screenSpacePoint) { - var captured = playfield.HitObjects.Objects.Reverse().Where(h => h.IsAlive && h.IsPresent).FirstOrDefault(h => h.ReceiveMouseInputAt(screenSpacePoint)); - if (captured == null) + var selected = playfield.HitObjects.Objects.Reverse().Where(h => h.IsAlive && h.IsPresent).FirstOrDefault(h => h.ReceiveMouseInputAt(screenSpacePoint)); + if (selected == null) return; - selectedHitObjects.Add(captured); + selectedHitObjects.Add(selected); } - private void finishCapture(bool fromDrag) + private void finishSelection(bool fromDrag) { if (selectedHitObjects.Count == 0) return; From dcbc8c3dcd452487fd3ec75d7690374030c9fd5f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Feb 2018 18:06:33 +0900 Subject: [PATCH 12/16] Remove animated capture boxes for now --- .../Edit/Layers/Selection/CaptureBox.cs | 58 ++----------------- .../Edit/Layers/Selection/SelectionBox.cs | 2 +- .../Edit/Layers/Selection/SelectionLayer.cs | 11 ++-- 3 files changed, 11 insertions(+), 60 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs index 86e96f6d84..35e425c981 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs @@ -15,22 +15,12 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// /// A box which encloses s. /// - public abstract class CaptureBox : VisibilityContainer + public class CaptureBox : VisibilityContainer { - /// - /// Top-left corner of the rectangle that encloses the s. - /// - protected Vector2 FinalPosition { get; private set; } - - /// - /// Size of the rectangle that encloses the s. - /// - protected Vector2 FinalSize { get; private set; } - private readonly IDrawable captureArea; private readonly IReadOnlyList capturedObjects; - protected CaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects) + public CaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects) { this.captureArea = captureArea; this.capturedObjects = capturedObjects; @@ -66,48 +56,12 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection topLeft -= new Vector2(5); bottomRight += new Vector2(5); - FinalSize = bottomRight - topLeft; - FinalPosition = topLeft; + Size = bottomRight - topLeft; + Position = topLeft; } - protected override void PopIn() => this.MoveTo(FinalPosition).ResizeTo(FinalSize).FadeIn(); + protected override void PopIn() => this.FadeIn(); + protected override void PopOut() => this.FadeOut(); } - - /// - /// A which fully encloses the s from the start. - /// - public class InstantCaptureBox : CaptureBox - { - public InstantCaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects) - : base(captureArea, capturedObjects) - { - Origin = Anchor.Centre; - } - - protected override void PopIn() - => this.MoveTo(FinalPosition + FinalSize / 2f).ResizeTo(FinalSize).ScaleTo(1.1f) - .Then() - .ScaleTo(1f, 300, Easing.OutQuint).FadeIn(300, Easing.OutQuint); - - protected override void PopOut() => this.FadeOut(300, Easing.OutQuint); - } - - /// - /// A which moves from an initial position + size to enclose s. - /// - public class DragCaptureBox : CaptureBox - { - public DragCaptureBox(IDrawable captureArea, IReadOnlyList capturedObjects, Vector2 initialPosition, Vector2 initialSize) - : base(captureArea, capturedObjects) - { - Position = initialPosition; - Size = initialSize; - } - - protected override void PopIn() - => this.MoveTo(FinalPosition, 300, Easing.OutQuint).ResizeTo(FinalSize, 300, Easing.OutQuint).FadeIn(300, Easing.OutQuint); - - protected override void PopOut() => this.FadeOut(300, Easing.OutQuint); - } } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs index 87c6833f01..8907993173 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs @@ -52,6 +52,6 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection Size = bottomRight - topLeft; } - public override void Hide() => this.FadeOut(400, Easing.OutQuint).Expire(); + public override void Hide() => this.FadeOut(250, Easing.OutQuint).Expire(); } } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index 0fceced040..f73820d534 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnDragEnd(InputState state) { selectionBox.Hide(); - finishSelection(true); + finishSelection(); return true; } @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnClick(InputState state) { selectPoint(state.Mouse.NativeState.Position); - finishSelection(false); + finishSelection(); return true; } @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection selectedHitObjects.Add(selected); } - private void finishSelection(bool fromDrag) + private void finishSelection() { if (selectedHitObjects.Count == 0) return; @@ -111,10 +111,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection // OnDragEnd and OnClick methods within a single frame, OnMouseDown doesn't help us here captureBox?.Hide(); - if (fromDrag) - AddInternal(captureBox = new DragCaptureBox(this, selectedHitObjects.ToList(), selectionBox.Position, selectionBox.Size)); - else - AddInternal(captureBox = new InstantCaptureBox(this, selectedHitObjects.ToList())); + AddInternal(captureBox = new CaptureBox(this, selectedHitObjects.ToList())); } } } From 4ac0c48ba6229df35ae2850364aaa2ba599bc42e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Feb 2018 19:07:53 +0900 Subject: [PATCH 13/16] Add fadein to SelectionBox --- osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs | 5 +++-- osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs index 8907993173..e0e52a41bc 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection /// /// A box that represents a drag selection. /// - public class SelectionBox : CompositeDrawable + public class SelectionBox : VisibilityContainer { /// /// Creates a new . @@ -52,6 +52,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection Size = bottomRight - topLeft; } - public override void Hide() => this.FadeOut(250, Easing.OutQuint).Expire(); + protected override void PopIn() => this.FadeIn(250, Easing.OutQuint); + protected override void PopOut() => this.FadeOut(250, Easing.OutQuint); } } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index f73820d534..e7acf05345 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -43,6 +43,8 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnDrag(InputState state) { + selectionBox.Show(); + var dragPosition = state.Mouse.NativeState.Position; var dragStartPosition = state.Mouse.NativeState.PositionMouseDown ?? dragPosition; @@ -57,6 +59,8 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection protected override bool OnDragEnd(InputState state) { selectionBox.Hide(); + selectionBox.Expire(); + finishSelection(); return true; From 95831915565a117f53ac38f3afb0b53ac919d04a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Feb 2018 19:08:03 +0900 Subject: [PATCH 14/16] Dispose SelectionBoxes when they die --- osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs index e0e52a41bc..8eee15d0b2 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionBox.cs @@ -52,6 +52,8 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection Size = bottomRight - topLeft; } + public override bool DisposeOnDeathRemoval => true; + protected override void PopIn() => this.FadeIn(250, Easing.OutQuint); protected override void PopOut() => this.FadeOut(250, Easing.OutQuint); } From ebcdb625702ac2f0711b0551ce2f4d8fe51e15f2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Feb 2018 19:10:55 +0900 Subject: [PATCH 15/16] Remove now unneeded hide --- osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index e7acf05345..af6a4144fd 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -111,10 +111,6 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection if (selectedHitObjects.Count == 0) return; - // Due to https://github.com/ppy/osu-framework/issues/1382, we may get here through both - // OnDragEnd and OnClick methods within a single frame, OnMouseDown doesn't help us here - captureBox?.Hide(); - AddInternal(captureBox = new CaptureBox(this, selectedHitObjects.ToList())); } } From cbac4de9c2a3207fe40144abfc8cadf95fe1f4bd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Feb 2018 19:11:29 +0900 Subject: [PATCH 16/16] Expire + dispose CaptureBoxes --- osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs | 3 ++- osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs index 35e425c981..48f6393ccc 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/CaptureBox.cs @@ -60,8 +60,9 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection Position = topLeft; } - protected override void PopIn() => this.FadeIn(); + public override bool DisposeOnDeathRemoval => true; + protected override void PopIn() => this.FadeIn(); protected override void PopOut() => this.FadeOut(); } } diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index af6a4144fd..bda613f617 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -81,6 +81,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection { selectedHitObjects.Clear(); captureBox?.Hide(); + captureBox?.Expire(); } ///