1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 18:42:56 +08:00

Move selection overlay to HitObjectOverlayLayer for extensibility

This commit is contained in:
smoogipoo 2018-03-10 00:48:57 +09:00
parent 0e8fbc47b7
commit 4103c66cff
6 changed files with 50 additions and 46 deletions

View File

@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual
{ {
typeof(SelectionBox), typeof(SelectionBox),
typeof(SelectionLayer), typeof(SelectionLayer),
typeof(CaptureBox), typeof(SelectionOverlay),
typeof(HitObjectComposer), typeof(HitObjectComposer),
typeof(OsuHitObjectComposer), typeof(OsuHitObjectComposer),
typeof(HitObjectOverlayLayer), typeof(HitObjectOverlayLayer),

View File

@ -108,7 +108,8 @@ namespace osu.Game.Rulesets.Edit
selectionLayer.ObjectSelected += hitObjectOverlayLayer.AddOverlay; selectionLayer.ObjectSelected += hitObjectOverlayLayer.AddOverlay;
selectionLayer.ObjectDeselected += hitObjectOverlayLayer.RemoveOverlay; selectionLayer.ObjectDeselected += hitObjectOverlayLayer.RemoveOverlay;
selectionLayer.SelectionMovementRequested += hitObjectOverlayLayer.MoveObjects; selectionLayer.SelectionCleared += hitObjectOverlayLayer.RemoveSelectionOverlay;
selectionLayer.SelectionFinished += hitObjectOverlayLayer.AddSelectionOverlay;
toolboxCollection.Items = toolboxCollection.Items =
new[] { new RadioButton("Select", () => setCompositionTool(null)) } new[] { new RadioButton("Select", () => setCompositionTool(null)) }

View File

@ -1,11 +1,10 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using osu.Game.Rulesets.Edit.Types;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Edit.Layers.Selection namespace osu.Game.Rulesets.Edit.Layers.Selection
@ -48,18 +47,14 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
existing.Expire(); existing.Expire();
} }
public void MoveObjects(InputState state) private SelectionOverlay currentSelectionOverlay;
public void AddSelectionOverlay() => AddInternal(currentSelectionOverlay = CreateSelectionOverlay(overlayContainer));
public void RemoveSelectionOverlay()
{ {
// Todo: Various forms of snapping currentSelectionOverlay?.Hide();
foreach (var hitObject in overlayContainer.Select(o => o.HitObject.HitObject)) currentSelectionOverlay?.Expire();
{
switch (hitObject)
{
case IHasEditablePosition editablePosition:
editablePosition.OffsetPosition(state.Mouse.Delta);
break;
}
}
} }
/// <summary> /// <summary>
@ -67,5 +62,12 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
/// </summary> /// </summary>
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create the overlay for.</param> /// <param name="hitObject">The <see cref="DrawableHitObject"/> to create the overlay for.</param>
protected virtual HitObjectOverlay CreateOverlayFor(DrawableHitObject hitObject) => null; protected virtual HitObjectOverlay CreateOverlayFor(DrawableHitObject hitObject) => null;
/// <summary>
/// Creates a <see cref="SelectionOverlay"/> which outlines <see cref="DrawableHitObject"/>s
/// and handles all hitobject movement/pattern adjustments.
/// </summary>
/// <param name="overlays">The <see cref="DrawableHitObject"/> overlays.</param>
protected virtual SelectionOverlay CreateSelectionOverlay(IReadOnlyList<HitObjectOverlay> overlays) => new SelectionOverlay(overlays);
} }
} }

View File

@ -28,9 +28,14 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
public event Action<DrawableHitObject> ObjectDeselected; public event Action<DrawableHitObject> ObjectDeselected;
/// <summary> /// <summary>
/// Invoked when the selected <see cref="DrawableHitObject"/>s should be moved. /// Invoked when the selection has been cleared.
/// </summary> /// </summary>
public event Action<InputState> SelectionMovementRequested; public event Action SelectionCleared;
/// <summary>
/// Invoked when the user has finished selecting all <see cref="DrawableHitObject"/>s.
/// </summary>
public event Action SelectionFinished;
private readonly Playfield playfield; private readonly Playfield playfield;
@ -42,7 +47,6 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
} }
private SelectionBox selectionBox; private SelectionBox selectionBox;
private CaptureBox captureBox;
private readonly HashSet<DrawableHitObject> selectedHitObjects = new HashSet<DrawableHitObject>(); private readonly HashSet<DrawableHitObject> selectedHitObjects = new HashSet<DrawableHitObject>();
@ -100,7 +104,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
if (!select(hitObject)) if (!select(hitObject))
return; return;
clearCapture(); clearSelection();
finishSelection(); finishSelection();
} }
@ -127,7 +131,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
if (!deselect(hitObject)) if (!deselect(hitObject))
return; return;
clearCapture(); clearSelection();
finishSelection(); finishSelection();
} }
@ -153,7 +157,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
selectedHitObjects.ForEach(h => ObjectDeselected?.Invoke(h)); selectedHitObjects.ForEach(h => ObjectDeselected?.Invoke(h));
selectedHitObjects.Clear(); selectedHitObjects.Clear();
clearCapture(); clearSelection();
} }
/// <summary> /// <summary>
@ -185,19 +189,13 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
select(target); select(target);
} }
private void clearCapture() private void clearSelection() => SelectionCleared?.Invoke();
{
captureBox?.Hide();
captureBox?.Expire();
}
private void finishSelection() private void finishSelection()
{ {
if (selectedHitObjects.Count == 0) if (selectedHitObjects.Count == 0)
return; return;
SelectionFinished?.Invoke();
AddInternal(captureBox = new CaptureBox(this, selectedHitObjects.ToList()));
captureBox.MovementRequested += v => SelectionMovementRequested?.Invoke(v);
} }
} }
} }

View File

@ -1,14 +1,15 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Edit.Types;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using OpenTK; using OpenTK;
@ -17,20 +18,13 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
/// <summary> /// <summary>
/// A box which encloses <see cref="DrawableHitObject"/>s. /// A box which encloses <see cref="DrawableHitObject"/>s.
/// </summary> /// </summary>
public class CaptureBox : VisibilityContainer public class SelectionOverlay : VisibilityContainer
{ {
/// <summary> private readonly IReadOnlyList<HitObjectOverlay> overlays;
/// Invoked when the captured <see cref="DrawableHitObject"/>s should be moved.
/// </summary>
public event Action<InputState> MovementRequested;
private readonly IDrawable captureArea; public SelectionOverlay(IReadOnlyList<HitObjectOverlay> overlays)
private readonly IReadOnlyList<DrawableHitObject> capturedObjects;
public CaptureBox(IDrawable captureArea, IReadOnlyList<DrawableHitObject> capturedObjects)
{ {
this.captureArea = captureArea; this.overlays = overlays;
this.capturedObjects = capturedObjects;
Masking = true; Masking = true;
BorderThickness = SelectionBox.BORDER_RADIUS; BorderThickness = SelectionBox.BORDER_RADIUS;
@ -61,10 +55,10 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
var topLeft = new Vector2(float.MaxValue, float.MaxValue); var topLeft = new Vector2(float.MaxValue, float.MaxValue);
var bottomRight = new Vector2(float.MinValue, float.MinValue); var bottomRight = new Vector2(float.MinValue, float.MinValue);
foreach (var obj in capturedObjects) foreach (var obj in overlays)
{ {
topLeft = Vector2.ComponentMin(topLeft, captureArea.ToLocalSpace(obj.SelectionQuad.TopLeft)); topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.HitObject.SelectionQuad.TopLeft));
bottomRight = Vector2.ComponentMax(bottomRight, captureArea.ToLocalSpace(obj.SelectionQuad.BottomRight)); bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.HitObject.SelectionQuad.BottomRight));
} }
topLeft -= new Vector2(5); topLeft -= new Vector2(5);
@ -80,7 +74,16 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
protected override bool OnDrag(InputState state) protected override bool OnDrag(InputState state)
{ {
MovementRequested?.Invoke(state); // Todo: Various forms of snapping
foreach (var hitObject in overlays.Select(o => o.HitObject.HitObject))
{
switch (hitObject)
{
case IHasEditablePosition editablePosition:
editablePosition.OffsetPosition(state.Mouse.Delta);
break;
}
}
return true; return true;
} }

View File

@ -362,7 +362,7 @@
<Compile Include="Rulesets\Configuration\IRulesetConfigManager.cs" /> <Compile Include="Rulesets\Configuration\IRulesetConfigManager.cs" />
<Compile Include="Rulesets\Configuration\RulesetConfigManager.cs" /> <Compile Include="Rulesets\Configuration\RulesetConfigManager.cs" />
<Compile Include="Rulesets\Edit\Layers\BorderLayer.cs" /> <Compile Include="Rulesets\Edit\Layers\BorderLayer.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\CaptureBox.cs" /> <Compile Include="Rulesets\Edit\Layers\Selection\SelectionOverlay.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\HitObjectOverlay.cs" /> <Compile Include="Rulesets\Edit\Layers\Selection\HitObjectOverlay.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\HitObjectOverlayLayer.cs" /> <Compile Include="Rulesets\Edit\Layers\Selection\HitObjectOverlayLayer.cs" />
<Compile Include="Rulesets\Edit\Types\IHasEditablePosition.cs" /> <Compile Include="Rulesets\Edit\Types\IHasEditablePosition.cs" />