diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
index 8aecc75824..43ad270c16 100644
--- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
@@ -15,6 +15,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
+using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Edit;
using osuTK;
using osuTK.Input;
@@ -106,11 +107,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected virtual DragBox CreateDragBox() => new DragBox();
- ///
- /// Whether this component is in a state where items outside a drag selection should be deselected. If false, selection will only be added to.
- ///
- protected virtual bool AllowDeselectionDuringDrag => true;
-
protected override bool OnMouseDown(MouseDownEvent e)
{
bool selectionPerformed = performMouseDownActions(e);
@@ -174,11 +170,15 @@ namespace osu.Game.Screens.Edit.Compose.Components
finishSelectionMovement();
}
+ private MouseButtonEvent lastDragEvent;
+
protected override bool OnDragStart(DragStartEvent e)
{
if (e.Button == MouseButton.Right)
return false;
+ lastDragEvent = e;
+
if (movementBlueprints != null)
{
isDraggingBlueprint = true;
@@ -193,22 +193,14 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected override void OnDrag(DragEvent e)
{
- if (e.Button == MouseButton.Right)
- return;
-
- if (DragBox.State == Visibility.Visible)
- {
- DragBox.HandleDrag(e);
- UpdateSelectionFromDragBox();
- }
+ lastDragEvent = e;
moveCurrentSelection(e);
}
protected override void OnDragEnd(DragEndEvent e)
{
- if (e.Button == MouseButton.Right)
- return;
+ lastDragEvent = null;
if (isDraggingBlueprint)
{
@@ -219,6 +211,18 @@ namespace osu.Game.Screens.Edit.Compose.Components
DragBox.Hide();
}
+ protected override void Update()
+ {
+ base.Update();
+
+ if (lastDragEvent != null && DragBox.State == Visibility.Visible)
+ {
+ lastDragEvent.Target = this;
+ DragBox.HandleDrag(lastDragEvent);
+ UpdateSelectionFromDragBox();
+ }
+ }
+
///
/// Called whenever a drag operation completes, before any change transaction is committed.
///
@@ -389,12 +393,19 @@ namespace osu.Game.Screens.Edit.Compose.Components
foreach (var blueprint in SelectionBlueprints)
{
- if (blueprint.IsSelected && !AllowDeselectionDuringDrag)
- continue;
+ switch (blueprint.State)
+ {
+ case SelectionState.Selected:
+ // Selection is preserved even after blueprint becomes dead.
+ if (!quad.Contains(blueprint.ScreenSpaceSelectionPoint))
+ blueprint.Deselect();
+ break;
- bool shouldBeSelected = blueprint.IsAlive && blueprint.IsPresent && quad.Contains(blueprint.ScreenSpaceSelectionPoint);
- if (blueprint.IsSelected != shouldBeSelected)
- blueprint.ToggleSelection();
+ case SelectionState.NotSelected:
+ if (blueprint.IsAlive && blueprint.IsPresent && quad.Contains(blueprint.ScreenSpaceSelectionPoint))
+ blueprint.Select();
+ break;
+ }
}
}
diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs
index 43ead88d54..ec07da43a0 100644
--- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs
@@ -12,7 +12,6 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
-using osu.Framework.Input;
using osu.Framework.Input.Events;
using osu.Game.Audio;
using osu.Game.Graphics.UserInterface;
@@ -37,7 +36,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
protected new EditorSelectionHandler SelectionHandler => (EditorSelectionHandler)base.SelectionHandler;
private PlacementBlueprint currentPlacement;
- private InputManager inputManager;
///
/// Positional input must be received outside the container's bounds,
@@ -66,8 +64,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
base.LoadComplete();
- inputManager = GetContainingInputManager();
-
Beatmap.HitObjectAdded += hitObjectAdded;
// updates to selected are handled for us by SelectionHandler.
@@ -83,8 +79,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
}
}
- protected override bool AllowDeselectionDuringDrag => !EditorClock.IsRunning;
-
protected override void TransferBlueprintFor(HitObject hitObject, DrawableHitObject drawableObject)
{
base.TransferBlueprintFor(hitObject, drawableObject);
@@ -222,7 +216,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void updatePlacementPosition()
{
- var snapResult = Composer.FindSnappedPositionAndTime(inputManager.CurrentState.Mouse.Position);
+ var snapResult = Composer.FindSnappedPositionAndTime(InputManager.CurrentState.Mouse.Position);
// if no time was found from positional snapping, we should still quantize to the beat.
snapResult.Time ??= Beatmap.SnapTime(EditorClock.CurrentTime, null);
diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs
index 6adaeb1a83..7423b368b4 100644
--- a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs
@@ -8,6 +8,7 @@ using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Input;
using osu.Framework.Input.Events;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
@@ -27,6 +28,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
private HitObjectUsageEventBuffer usageEventBuffer;
+ protected InputManager InputManager { get; private set; }
+
protected EditorBlueprintContainer(HitObjectComposer composer)
{
Composer = composer;
@@ -42,6 +45,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
base.LoadComplete();
+ InputManager = GetContainingInputManager();
+
Beatmap.HitObjectAdded += AddBlueprintFor;
Beatmap.HitObjectRemoved += RemoveBlueprintFor;
diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs
index 31990bfd35..b79c2675c8 100644
--- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs
@@ -29,10 +29,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
[Resolved(CanBeNull = true)]
private Timeline timeline { get; set; }
- private DragEvent lastDragEvent;
private Bindable placement;
private SelectionBlueprint placementBlueprint;
+ private bool hitObjectDragged;
+
///
/// Positional input must be received outside the container's bounds,
/// in order to handle timeline blueprints which are stacked offscreen.
@@ -98,24 +99,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
return base.OnDragStart(e);
}
- protected override void OnDrag(DragEvent e)
- {
- handleScrollViaDrag(e);
-
- base.OnDrag(e);
- }
-
- protected override void OnDragEnd(DragEndEvent e)
- {
- base.OnDragEnd(e);
- lastDragEvent = null;
- }
-
protected override void Update()
{
- // trigger every frame so drags continue to update selection while playback is scrolling the timeline.
- if (lastDragEvent != null)
- OnDrag(lastDragEvent);
+ if (IsDragged || hitObjectDragged)
+ handleScrollViaDrag();
if (Composer != null && timeline != null)
{
@@ -170,7 +157,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
return new TimelineHitObjectBlueprint(item)
{
- OnDragHandled = handleScrollViaDrag,
+ OnDragHandled = e => hitObjectDragged = e != null,
};
}
@@ -197,24 +184,18 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
}
}
- private void handleScrollViaDrag(DragEvent e)
+ private void handleScrollViaDrag()
{
- lastDragEvent = e;
+ if (timeline == null) return;
- if (lastDragEvent == null)
- return;
+ var timelineQuad = timeline.ScreenSpaceDrawQuad;
+ float mouseX = InputManager.CurrentState.Mouse.Position.X;
- if (timeline != null)
- {
- var timelineQuad = timeline.ScreenSpaceDrawQuad;
- float mouseX = e.ScreenSpaceMousePosition.X;
-
- // scroll if in a drag and dragging outside visible extents
- if (mouseX > timelineQuad.TopRight.X)
- timeline.ScrollBy((float)((mouseX - timelineQuad.TopRight.X) / 10 * Clock.ElapsedFrameTime));
- else if (mouseX < timelineQuad.TopLeft.X)
- timeline.ScrollBy((float)((mouseX - timelineQuad.TopLeft.X) / 10 * Clock.ElapsedFrameTime));
- }
+ // scroll if in a drag and dragging outside visible extents
+ if (mouseX > timelineQuad.TopRight.X)
+ timeline.ScrollBy((float)((mouseX - timelineQuad.TopRight.X) / 10 * Clock.ElapsedFrameTime));
+ else if (mouseX < timelineQuad.TopLeft.X)
+ timeline.ScrollBy((float)((mouseX - timelineQuad.TopLeft.X) / 10 * Clock.ElapsedFrameTime));
}
private class SelectableAreaBackground : CompositeDrawable