Split out drag selection box from post-capture box

Cleans up a lot of code, removes handles for now.
This commit is contained in:
smoogipoo 2018-02-12 18:19:55 +09:00
parent 1adbe3585c
commit ee168f9a77
5 changed files with 108 additions and 120 deletions

View File

@ -23,7 +23,8 @@ namespace osu.Game.Tests.Visual
{
typeof(HitObjectCapturer),
typeof(SelectionDragger),
typeof(SelectionLayer)
typeof(SelectionLayer),
typeof(CaptureBox)
};
[BackgroundDependencyLoader]

View File

@ -0,0 +1,76 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// 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
{
/// <summary>
/// A box which encapsulates captured <see cref="DrawableHitObject"/>s.
/// </summary>
public class CaptureBox : VisibilityContainer
{
private readonly IDrawable captureArea;
private readonly IReadOnlyList<DrawableHitObject> capturedObjects;
private readonly Container borderContainer;
public CaptureBox(IDrawable captureArea, IReadOnlyList<DrawableHitObject> 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);
}
}

View File

@ -1,15 +1,10 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// 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
/// </summary>
public class SelectionDragger : CompositeDrawable
{
private readonly Container borderMask;
private readonly Drawable background;
private readonly HandleContainer handles;
private Color4 captureFinishedColour;
private RectangleF dragRectangle;
/// <summary>
/// Creates a new <see cref="SelectionDragger"/>.
/// </summary>
@ -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<DrawableHitObject> capturedHitObjects = new List<DrawableHitObject>();
public bool HasCaptured => capturedHitObjects.Count > 0;
public void AddCaptured(DrawableHitObject hitObject) => capturedHitObjects.Add(hitObject);
public void ClearCaptured() => capturedHitObjects.Clear();
/// <summary>
/// Encloses hitobjects captured through <see cref="BeginCapture"/> in the drag selection box.
/// </summary>
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();
}
}

View File

@ -1,6 +1,8 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// 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<DrawableHitObject> capturedHitObjects = new List<DrawableHitObject>();
[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()));
}
}
}

View File

@ -332,6 +332,7 @@
<Compile Include="Overlays\Settings\Sections\Maintenance\DeleteAllBeatmapsDialog.cs" />
<Compile Include="Rulesets\Configuration\IRulesetConfigManager.cs" />
<Compile Include="Rulesets\Configuration\RulesetConfigManager.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\CaptureBox.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\HitObjectCapturer.cs" />
<Compile Include="Rulesets\Mods\IApplicableFailOverride.cs" />
<Compile Include="Rulesets\Mods\IApplicableMod.cs" />