1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 22:22:55 +08:00

Merge pull request #29918 from bdach/control-drag

Add to existing selection when dragging with control pressed
This commit is contained in:
Dean Herbert 2024-09-30 14:00:36 +09:00 committed by GitHub
commit a258059d43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 6 deletions

View File

@ -219,6 +219,51 @@ namespace osu.Game.Tests.Visual.Editing
AddAssert("2 hitobjects selected", () => EditorBeatmap.SelectedHitObjects.Count == 2 && !EditorBeatmap.SelectedHitObjects.Contains(addedObjects[1]));
}
[Test]
public void TestMultiSelectWithDragBox()
{
var addedObjects = new[]
{
new HitCircle { StartTime = 100 },
new HitCircle { StartTime = 200, Position = new Vector2(100) },
new HitCircle { StartTime = 300, Position = new Vector2(512, 0) },
new HitCircle { StartTime = 400, Position = new Vector2(412, 100) },
};
AddStep("add hitobjects", () => EditorBeatmap.AddRange(addedObjects));
AddStep("start dragging", () =>
{
InputManager.MoveMouseTo(blueprintContainer.ScreenSpaceDrawQuad.Centre);
InputManager.PressButton(MouseButton.Left);
});
AddStep("drag to left corner", () => InputManager.MoveMouseTo(blueprintContainer.ScreenSpaceDrawQuad.TopLeft - new Vector2(5)));
AddStep("end dragging", () => InputManager.ReleaseButton(MouseButton.Left));
AddAssert("2 hitobjects selected", () => EditorBeatmap.SelectedHitObjects, () => Has.Count.EqualTo(2));
AddStep("start dragging with control", () =>
{
InputManager.MoveMouseTo(blueprintContainer.ScreenSpaceDrawQuad.Centre);
InputManager.PressButton(MouseButton.Left);
InputManager.PressKey(Key.ControlLeft);
});
AddStep("drag to left corner", () => InputManager.MoveMouseTo(blueprintContainer.ScreenSpaceDrawQuad.TopRight + new Vector2(5, -5)));
AddStep("end dragging", () => InputManager.ReleaseButton(MouseButton.Left));
AddStep("release control", () => InputManager.ReleaseKey(Key.ControlLeft));
AddAssert("4 hitobjects selected", () => EditorBeatmap.SelectedHitObjects, () => Has.Count.EqualTo(4));
AddStep("start dragging without control", () =>
{
InputManager.MoveMouseTo(blueprintContainer.ScreenSpaceDrawQuad.Centre);
InputManager.PressButton(MouseButton.Left);
});
AddStep("drag to left corner", () => InputManager.MoveMouseTo(blueprintContainer.ScreenSpaceDrawQuad.TopRight + new Vector2(5, -5)));
AddStep("end dragging", () => InputManager.ReleaseButton(MouseButton.Left));
AddAssert("2 hitobjects selected", () => EditorBeatmap.SelectedHitObjects, () => Has.Count.EqualTo(2));
}
[Test]
public void TestNearestSelection()
{

View File

@ -196,6 +196,11 @@ namespace osu.Game.Screens.Edit.Compose.Components
DragBox.HandleDrag(e);
DragBox.Show();
selectionBeforeDrag.Clear();
if (e.ControlPressed)
selectionBeforeDrag.UnionWith(SelectedItems);
return true;
}
@ -217,6 +222,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
}
DragBox.Hide();
selectionBeforeDrag.Clear();
}
protected override void Update()
@ -227,7 +233,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
lastDragEvent.Target = this;
DragBox.HandleDrag(lastDragEvent);
UpdateSelectionFromDragBox();
UpdateSelectionFromDragBox(selectionBeforeDrag);
}
}
@ -426,7 +432,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
private bool endClickSelection(MouseButtonEvent e)
{
// If already handled a selection, double-click, or drag, we don't want to perform a mouse up / click action.
if (clickSelectionHandled || doubleClickHandled || isDraggingBlueprint) return true;
if (clickSelectionHandled || doubleClickHandled || isDraggingBlueprint || wasDragStarted) return true;
if (e.Button != MouseButton.Left) return false;
@ -442,7 +448,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
return false;
}
if (!wasDragStarted && selectedBlueprintAlreadySelectedOnMouseDown && SelectedItems.Count == 1)
if (selectedBlueprintAlreadySelectedOnMouseDown && SelectedItems.Count == 1)
{
// If a click occurred and was handled by the currently selected blueprint but didn't result in a drag,
// cycle between other blueprints which are also under the cursor.
@ -472,7 +478,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// <summary>
/// Select all blueprints in a selection area specified by <see cref="DragBox"/>.
/// </summary>
protected virtual void UpdateSelectionFromDragBox()
protected virtual void UpdateSelectionFromDragBox(HashSet<T> selectionBeforeDrag)
{
var quad = DragBox.Box.ScreenSpaceDrawQuad;
@ -482,7 +488,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
case SelectionState.Selected:
// Selection is preserved even after blueprint becomes dead.
if (!quad.Contains(blueprint.ScreenSpaceSelectionPoint))
if (!quad.Contains(blueprint.ScreenSpaceSelectionPoint) && !selectionBeforeDrag.Contains(blueprint.Item))
blueprint.Deselect();
break;
@ -535,6 +541,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// </summary>
private bool wasDragStarted;
private readonly HashSet<T> selectionBeforeDrag = new HashSet<T>();
/// <summary>
/// Attempts to begin the movement of any selected blueprints.
/// </summary>

View File

@ -173,7 +173,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
protected sealed override DragBox CreateDragBox() => new TimelineDragBox();
protected override void UpdateSelectionFromDragBox()
protected override void UpdateSelectionFromDragBox(HashSet<HitObject> selectionBeforeDrag)
{
Composer.BlueprintContainer.CommitIfPlacementActive();
@ -191,6 +191,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
bool shouldBeSelected(HitObject hitObject)
{
if (selectionBeforeDrag.Contains(hitObject))
return true;
double midTime = (hitObject.StartTime + hitObject.GetEndTime()) / 2;
return minTime <= midTime && midTime <= maxTime;
}