mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 08:22:56 +08:00
Move selection logic from DragBox to BlueprintContainer
This commit is contained in:
parent
d9c3f5834c
commit
8d29e9e76b
@ -3,7 +3,6 @@
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
@ -13,11 +12,9 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
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;
|
||||
@ -79,7 +76,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
|
||||
AddRangeInternal(new[]
|
||||
{
|
||||
DragBox = CreateDragBox(selectBlueprintsFromDragRectangle),
|
||||
DragBox = CreateDragBox(),
|
||||
SelectionHandler,
|
||||
SelectionBlueprints = CreateSelectionBlueprintContainer(),
|
||||
SelectionHandler.CreateProxy(),
|
||||
@ -101,7 +98,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
[CanBeNull]
|
||||
protected virtual SelectionBlueprint<T> CreateBlueprintFor(T item) => null;
|
||||
|
||||
protected virtual DragBox CreateDragBox(Action<RectangleF> performSelect) => new DragBox(performSelect);
|
||||
protected virtual DragBox CreateDragBox() => new DragBox();
|
||||
|
||||
/// <summary>
|
||||
/// Whether this component is in a state where items outside a drag selection should be deselected. If false, selection will only be added to.
|
||||
@ -183,13 +180,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DragBox.HandleDrag(e))
|
||||
{
|
||||
DragBox.Show();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
DragBox.HandleDrag(e);
|
||||
DragBox.Show();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnDrag(DragEvent e)
|
||||
@ -198,7 +191,10 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
return;
|
||||
|
||||
if (DragBox.State == Visibility.Visible)
|
||||
{
|
||||
DragBox.HandleDrag(e);
|
||||
UpdateSelectionFromDragBox();
|
||||
}
|
||||
|
||||
moveCurrentSelection(e);
|
||||
}
|
||||
@ -214,8 +210,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
changeHandler?.EndChange();
|
||||
}
|
||||
|
||||
if (DragBox.State == Visibility.Visible)
|
||||
DragBox.Hide();
|
||||
DragBox.Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -380,28 +375,20 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Select all masks in a given rectangle selection area.
|
||||
/// Select all blueprints in a selection area specified by <see cref="DragBox"/>.
|
||||
/// </summary>
|
||||
/// <param name="rect">The rectangle to perform a selection on in screen-space coordinates.</param>
|
||||
private void selectBlueprintsFromDragRectangle(RectangleF rect)
|
||||
protected virtual void UpdateSelectionFromDragBox()
|
||||
{
|
||||
var quad = DragBox.Box.ScreenSpaceDrawQuad;
|
||||
|
||||
foreach (var blueprint in SelectionBlueprints)
|
||||
{
|
||||
// only run when utmost necessary to avoid unnecessary rect computations.
|
||||
bool isValidForSelection() => blueprint.IsAlive && blueprint.IsPresent && rect.Contains(blueprint.ScreenSpaceSelectionPoint);
|
||||
if (blueprint.IsSelected && !AllowDeselectionDuringDrag)
|
||||
continue;
|
||||
|
||||
switch (blueprint.State)
|
||||
{
|
||||
case SelectionState.NotSelected:
|
||||
if (isValidForSelection())
|
||||
blueprint.Select();
|
||||
break;
|
||||
|
||||
case SelectionState.Selected:
|
||||
if (AllowDeselectionDuringDrag && !isValidForSelection())
|
||||
blueprint.Deselect();
|
||||
break;
|
||||
}
|
||||
bool shouldBeSelected = blueprint.IsAlive && blueprint.IsPresent && quad.Contains(blueprint.ScreenSpaceSelectionPoint);
|
||||
if (blueprint.IsSelected != shouldBeSelected)
|
||||
blueprint.ToggleSelection();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Layout;
|
||||
@ -21,18 +20,13 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
/// </summary>
|
||||
public class DragBox : CompositeDrawable, IStateful<Visibility>
|
||||
{
|
||||
protected readonly Action<RectangleF> PerformSelection;
|
||||
|
||||
protected Drawable Box;
|
||||
public Drawable Box { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="DragBox"/>.
|
||||
/// </summary>
|
||||
/// <param name="performSelection">A delegate that performs drag selection.</param>
|
||||
public DragBox(Action<RectangleF> performSelection)
|
||||
public DragBox()
|
||||
{
|
||||
PerformSelection = performSelection;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
AlwaysPresent = true;
|
||||
Alpha = 0;
|
||||
@ -46,30 +40,14 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
|
||||
protected virtual Drawable CreateBox() => new BoxWithBorders();
|
||||
|
||||
private RectangleF? dragRectangle;
|
||||
|
||||
/// <summary>
|
||||
/// Handle a forwarded mouse event.
|
||||
/// </summary>
|
||||
/// <param name="e">The mouse event.</param>
|
||||
/// <returns>Whether the event should be handled and blocking.</returns>
|
||||
public virtual bool HandleDrag(MouseButtonEvent e)
|
||||
public virtual void HandleDrag(MouseButtonEvent e)
|
||||
{
|
||||
var dragPosition = e.ScreenSpaceMousePosition;
|
||||
var dragStartPosition = e.ScreenSpaceMouseDownPosition;
|
||||
|
||||
var dragQuad = new Quad(dragStartPosition.X, dragStartPosition.Y, dragPosition.X - dragStartPosition.X, dragPosition.Y - dragStartPosition.Y);
|
||||
|
||||
// We use AABBFloat instead of RectangleF since it handles negative sizes for us
|
||||
var rec = dragQuad.AABBFloat;
|
||||
dragRectangle = rec;
|
||||
|
||||
var topLeft = ToLocalSpace(rec.TopLeft);
|
||||
var bottomRight = ToLocalSpace(rec.BottomRight);
|
||||
|
||||
Box.Position = topLeft;
|
||||
Box.Size = bottomRight - topLeft;
|
||||
return true;
|
||||
Box.Position = Vector2.ComponentMin(e.MouseDownPosition, e.MousePosition);
|
||||
Box.Size = Vector2.ComponentMax(e.MouseDownPosition, e.MousePosition) - Box.Position;
|
||||
}
|
||||
|
||||
private Visibility state;
|
||||
@ -87,19 +65,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (dragRectangle != null)
|
||||
PerformSelection?.Invoke(dragRectangle.Value);
|
||||
}
|
||||
|
||||
public override void Hide()
|
||||
{
|
||||
State = Visibility.Hidden;
|
||||
dragRectangle = null;
|
||||
}
|
||||
public override void Hide() => State = Visibility.Hidden;
|
||||
|
||||
public override void Show() => State = Visibility.Visible;
|
||||
|
||||
|
@ -13,7 +13,6 @@ using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Utils;
|
||||
@ -65,7 +64,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
DragBox.Alpha = 0;
|
||||
|
||||
placement = Beatmap.PlacementObject.GetBoundCopy();
|
||||
placement.ValueChanged += placementChanged;
|
||||
@ -93,6 +91,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
|
||||
protected override Container<SelectionBlueprint<HitObject>> CreateSelectionBlueprintContainer() => new TimelineSelectionBlueprintContainer { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
protected override bool OnDragStart(DragStartEvent e)
|
||||
{
|
||||
if (!base.ReceivePositionalInputAt(e.ScreenSpaceMouseDownPosition))
|
||||
return false;
|
||||
|
||||
return base.OnDragStart(e);
|
||||
}
|
||||
|
||||
protected override void OnDrag(DragEvent e)
|
||||
{
|
||||
handleScrollViaDrag(e);
|
||||
@ -169,7 +175,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
};
|
||||
}
|
||||
|
||||
protected override DragBox CreateDragBox(Action<RectangleF> performSelect) => new TimelineDragBox(performSelect);
|
||||
protected override DragBox CreateDragBox() => new TimelineDragBox();
|
||||
|
||||
private void handleScrollViaDrag(DragEvent e)
|
||||
{
|
||||
|
@ -6,7 +6,6 @@
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Utils;
|
||||
@ -24,24 +23,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
[Resolved]
|
||||
private Timeline timeline { get; set; }
|
||||
|
||||
public TimelineDragBox(Action<RectangleF> performSelect)
|
||||
: base(performSelect)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Drawable CreateBox() => new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Alpha = 0.3f
|
||||
};
|
||||
|
||||
public override bool HandleDrag(MouseButtonEvent e)
|
||||
public override void HandleDrag(MouseButtonEvent e)
|
||||
{
|
||||
// The dragbox should only be active if the mouseDownPosition.Y is within this drawable's bounds.
|
||||
float localY = ToLocalSpace(e.ScreenSpaceMouseDownPosition).Y;
|
||||
if (DrawRectangle.Top > localY || DrawRectangle.Bottom < localY)
|
||||
return false;
|
||||
|
||||
selectionStart ??= e.MouseDownPosition.X / timeline.CurrentZoom;
|
||||
|
||||
// only calculate end when a transition is not in progress to avoid bouncing.
|
||||
@ -49,7 +38,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
selectionEnd = e.MousePosition.X / timeline.CurrentZoom;
|
||||
|
||||
updateDragBoxPosition();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateDragBoxPosition()
|
||||
@ -68,8 +56,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
// we don't care about where the hitobjects are vertically. in cases like stacking display, they may be outside the box without this adjustment.
|
||||
boxScreenRect.Y -= boxScreenRect.Height;
|
||||
boxScreenRect.Height *= 2;
|
||||
|
||||
PerformSelection?.Invoke(boxScreenRect);
|
||||
}
|
||||
|
||||
public override void Hide()
|
||||
|
Loading…
Reference in New Issue
Block a user