From 2f1063c5c05cab75c2370f72fed6c634dffc1fb0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Dec 2017 21:56:58 +0900 Subject: [PATCH] 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