1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 13:22:55 +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(SelectionLayer),
typeof(CaptureBox),
typeof(SelectionOverlay),
typeof(HitObjectComposer),
typeof(OsuHitObjectComposer),
typeof(HitObjectOverlayLayer),

View File

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

View File

@ -1,11 +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 System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using osu.Game.Rulesets.Edit.Types;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Edit.Layers.Selection
@ -48,18 +47,14 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
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
foreach (var hitObject in overlayContainer.Select(o => o.HitObject.HitObject))
{
switch (hitObject)
{
case IHasEditablePosition editablePosition:
editablePosition.OffsetPosition(state.Mouse.Delta);
break;
}
}
currentSelectionOverlay?.Hide();
currentSelectionOverlay?.Expire();
}
/// <summary>
@ -67,5 +62,12 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
/// </summary>
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create the overlay for.</param>
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;
/// <summary>
/// Invoked when the selected <see cref="DrawableHitObject"/>s should be moved.
/// Invoked when the selection has been cleared.
/// </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;
@ -42,7 +47,6 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
}
private SelectionBox selectionBox;
private CaptureBox captureBox;
private readonly HashSet<DrawableHitObject> selectedHitObjects = new HashSet<DrawableHitObject>();
@ -100,7 +104,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
if (!select(hitObject))
return;
clearCapture();
clearSelection();
finishSelection();
}
@ -127,7 +131,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
if (!deselect(hitObject))
return;
clearCapture();
clearSelection();
finishSelection();
}
@ -153,7 +157,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
selectedHitObjects.ForEach(h => ObjectDeselected?.Invoke(h));
selectedHitObjects.Clear();
clearCapture();
clearSelection();
}
/// <summary>
@ -185,19 +189,13 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
select(target);
}
private void clearCapture()
{
captureBox?.Hide();
captureBox?.Expire();
}
private void clearSelection() => SelectionCleared?.Invoke();
private void finishSelection()
{
if (selectedHitObjects.Count == 0)
return;
AddInternal(captureBox = new CaptureBox(this, selectedHitObjects.ToList()));
captureBox.MovementRequested += v => SelectionMovementRequested?.Invoke(v);
SelectionFinished?.Invoke();
}
}
}

View File

@ -1,14 +1,15 @@
// 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;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit.Types;
using osu.Game.Rulesets.Objects.Drawables;
using OpenTK;
@ -17,20 +18,13 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
/// <summary>
/// A box which encloses <see cref="DrawableHitObject"/>s.
/// </summary>
public class CaptureBox : VisibilityContainer
public class SelectionOverlay : VisibilityContainer
{
/// <summary>
/// Invoked when the captured <see cref="DrawableHitObject"/>s should be moved.
/// </summary>
public event Action<InputState> MovementRequested;
private readonly IReadOnlyList<HitObjectOverlay> overlays;
private readonly IDrawable captureArea;
private readonly IReadOnlyList<DrawableHitObject> capturedObjects;
public CaptureBox(IDrawable captureArea, IReadOnlyList<DrawableHitObject> capturedObjects)
public SelectionOverlay(IReadOnlyList<HitObjectOverlay> overlays)
{
this.captureArea = captureArea;
this.capturedObjects = capturedObjects;
this.overlays = overlays;
Masking = true;
BorderThickness = SelectionBox.BORDER_RADIUS;
@ -61,10 +55,10 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
var topLeft = new Vector2(float.MaxValue, float.MaxValue);
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));
bottomRight = Vector2.ComponentMax(bottomRight, captureArea.ToLocalSpace(obj.SelectionQuad.BottomRight));
topLeft = Vector2.ComponentMin(topLeft, Parent.ToLocalSpace(obj.HitObject.SelectionQuad.TopLeft));
bottomRight = Vector2.ComponentMax(bottomRight, Parent.ToLocalSpace(obj.HitObject.SelectionQuad.BottomRight));
}
topLeft -= new Vector2(5);
@ -80,7 +74,16 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
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;
}

View File

@ -362,7 +362,7 @@
<Compile Include="Rulesets\Configuration\IRulesetConfigManager.cs" />
<Compile Include="Rulesets\Configuration\RulesetConfigManager.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\HitObjectOverlayLayer.cs" />
<Compile Include="Rulesets\Edit\Types\IHasEditablePosition.cs" />