Allow dragging anywhere in a capture box to move objects

This commit is contained in:
smoogipoo 2018-03-09 23:43:50 +09:00
parent 4a48136e4f
commit ad72d3816b
5 changed files with 53 additions and 33 deletions

View File

@ -108,6 +108,7 @@ 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;
toolboxCollection.Items = toolboxCollection.Items =
new[] { new RadioButton("Select", () => setCompositionTool(null)) } new[] { new RadioButton("Select", () => setCompositionTool(null)) }

View File

@ -1,11 +1,13 @@
// 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 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.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using OpenTK; using OpenTK;
@ -17,6 +19,11 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
/// </summary> /// </summary>
public class CaptureBox : VisibilityContainer public class CaptureBox : VisibilityContainer
{ {
/// <summary>
/// Invoked when the captured <see cref="DrawableHitObject"/>s should be moved.
/// </summary>
public event Action<Vector2> MovementRequested;
private readonly IDrawable captureArea; private readonly IDrawable captureArea;
private readonly IReadOnlyList<DrawableHitObject> capturedObjects; private readonly IReadOnlyList<DrawableHitObject> capturedObjects;
@ -67,6 +74,18 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
Position = topLeft; Position = topLeft;
} }
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true;
protected override bool OnDragStart(InputState state) => true;
protected override bool OnDrag(InputState state)
{
MovementRequested?.Invoke(state.Mouse.Delta);
return true;
}
protected override bool OnDragEnd(InputState state) => true;
public override bool DisposeOnDeathRemoval => true; public override bool DisposeOnDeathRemoval => true;
protected override void PopIn() => this.FadeIn(); protected override void PopIn() => this.FadeIn();

View File

@ -2,42 +2,17 @@
// 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 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
{ {
public class HitObjectOverlay : OverlayContainer public class HitObjectOverlay : Container
{ {
// ReSharper disable once NotAccessedField.Local public readonly DrawableHitObject HitObject;
// This will be used later to handle drag movement, etc
private readonly DrawableHitObject hitObject;
public HitObjectOverlay(DrawableHitObject hitObject) public HitObjectOverlay(DrawableHitObject hitObject)
{ {
this.hitObject = hitObject; HitObject = hitObject;
State = Visibility.Visible;
} }
protected override bool OnDragStart(InputState state) => hitObject.HitObject is IHasEditablePosition;
protected override bool OnDrag(InputState state)
{
switch (hitObject.HitObject)
{
case IHasEditablePosition editablePosition:
editablePosition.SetPosition(state.Mouse.Delta);
break;
}
return true;
}
protected override bool OnDragEnd(InputState state) => true;
protected override void PopIn() => Alpha = 1;
protected override void PopOut() => Alpha = 0;
} }
} }

View File

@ -1,20 +1,25 @@
// 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 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;
using OpenTK;
namespace osu.Game.Rulesets.Edit.Layers.Selection namespace osu.Game.Rulesets.Edit.Layers.Selection
{ {
public class HitObjectOverlayLayer : CompositeDrawable public class HitObjectOverlayLayer : CompositeDrawable
{ {
private readonly Dictionary<DrawableHitObject, HitObjectOverlay> existingOverlays = new Dictionary<DrawableHitObject, HitObjectOverlay>(); private readonly Container<HitObjectOverlay> overlayContainer;
public HitObjectOverlayLayer() public HitObjectOverlayLayer()
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
InternalChild = overlayContainer = new Container<HitObjectOverlay> { RelativeSizeAxes = Axes.Both };
} }
/// <summary> /// <summary>
@ -27,8 +32,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
if (overlay == null) if (overlay == null)
return; return;
existingOverlays[hitObject] = overlay; overlayContainer.Add(overlay);
AddInternal(overlay);
} }
/// <summary> /// <summary>
@ -37,13 +41,28 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to remove the overlay for.</param> /// <param name="hitObject">The <see cref="DrawableHitObject"/> to remove the overlay for.</param>
public void RemoveOverlay(DrawableHitObject hitObject) public void RemoveOverlay(DrawableHitObject hitObject)
{ {
if (!existingOverlays.TryGetValue(hitObject, out var existing)) var existing = overlayContainer.FirstOrDefault(h => h.HitObject == hitObject);
if (existing == null)
return; return;
existing.Hide(); existing.Hide();
existing.Expire(); existing.Expire();
} }
public void MoveObjects(Vector2 offset)
{
// Todo: Various forms of snapping
foreach (var hitObject in overlayContainer.Select(o => o.HitObject.HitObject))
{
switch (hitObject)
{
case IHasEditablePosition editablePosition:
editablePosition.SetPosition(offset);
break;
}
}
}
/// <summary> /// <summary>
/// Creates a <see cref="HitObjectOverlay"/> for a specific <see cref="DrawableHitObject"/>. /// Creates a <see cref="HitObjectOverlay"/> for a specific <see cref="DrawableHitObject"/>.
/// </summary> /// </summary>

View File

@ -27,6 +27,11 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
/// </summary> /// </summary>
public event Action<DrawableHitObject> ObjectDeselected; public event Action<DrawableHitObject> ObjectDeselected;
/// <summary>
/// Invoked when the selected <see cref="DrawableHitObject"/>s should be moved.
/// </summary>
public event Action<Vector2> SelectionMovementRequested;
private readonly Playfield playfield; private readonly Playfield playfield;
public SelectionLayer(Playfield playfield) public SelectionLayer(Playfield playfield)
@ -192,6 +197,7 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection
return; return;
AddInternal(captureBox = new CaptureBox(this, selectedHitObjects.ToList())); AddInternal(captureBox = new CaptureBox(this, selectedHitObjects.ToList()));
captureBox.MovementRequested += v => SelectionMovementRequested?.Invoke(v);
} }
} }
} }