Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add to existing selection when dragging with control pressed #29918

Merged
merged 5 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,51 @@ public void TestMultiSelect()
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()
{
Expand Down
18 changes: 13 additions & 5 deletions osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ protected override bool OnDragStart(DragStartEvent e)

DragBox.HandleDrag(e);
DragBox.Show();

selectionBeforeDrag.Clear();
if (e.ControlPressed)
selectionBeforeDrag.UnionWith(SelectedItems);

return true;
}

Expand All @@ -217,6 +222,7 @@ protected override void OnDragEnd(DragEndEvent e)
}

DragBox.Hide();
selectionBeforeDrag.Clear();
}

protected override void Update()
Expand All @@ -227,7 +233,7 @@ protected override void Update()
{
lastDragEvent.Target = this;
DragBox.HandleDrag(lastDragEvent);
UpdateSelectionFromDragBox();
UpdateSelectionFromDragBox(selectionBeforeDrag);
}
}

Expand Down Expand Up @@ -426,7 +432,7 @@ bool runForBlueprint(SelectionBlueprint<T> blueprint)
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;

Expand All @@ -442,7 +448,7 @@ private bool endClickSelection(MouseButtonEvent e)
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.
Expand Down Expand Up @@ -472,7 +478,7 @@ private bool endClickSelection(MouseButtonEvent e)
/// <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;

Expand All @@ -482,7 +488,7 @@ protected virtual void UpdateSelectionFromDragBox()
{
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;

Expand Down Expand Up @@ -535,6 +541,8 @@ protected virtual void OnBlueprintDeselected(SelectionBlueprint<T> blueprint)
/// </summary>
private bool wasDragStarted;

private readonly HashSet<T> selectionBeforeDrag = new HashSet<T>();

/// <summary>
/// Attempts to begin the movement of any selected blueprints.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ protected override SelectionBlueprint<HitObject> CreateBlueprintFor(HitObject it

protected sealed override DragBox CreateDragBox() => new TimelineDragBox();

protected override void UpdateSelectionFromDragBox()
protected override void UpdateSelectionFromDragBox(HashSet<HitObject> selectionBeforeDrag)
{
Composer.BlueprintContainer.CommitIfPlacementActive();

Expand All @@ -191,6 +191,9 @@ protected override void UpdateSelectionFromDragBox()

bool shouldBeSelected(HitObject hitObject)
{
if (selectionBeforeDrag.Contains(hitObject))
return true;

double midTime = (hitObject.StartTime + hitObject.GetEndTime()) / 2;
return minTime <= midTime && midTime <= maxTime;
}
Expand Down
Loading