1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-06 09:47:52 +08:00

Use hit object time for timeline selection

This commit is contained in:
ekrctb 2022-10-05 20:43:02 +09:00
parent 8d29e9e76b
commit 0ffde02f79
3 changed files with 49 additions and 35 deletions

View File

@ -304,10 +304,20 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
/// </summary>
public double VisibleRange => editorClock.TrackLength / Zoom;
public SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.All) =>
new SnapResult(screenSpacePosition, beatSnapProvider.SnapTime(getTimeFromPosition(Content.ToLocalSpace(screenSpacePosition))));
public double TimeAtPosition(float x)
{
return x / Content.DrawWidth * editorClock.TrackLength;
}
private double getTimeFromPosition(Vector2 localPosition) =>
(localPosition.X / Content.DrawWidth) * editorClock.TrackLength;
public float PositionAtTime(double time)
{
return (float)(time / editorClock.TrackLength * Content.DrawWidth);
}
public SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.All)
{
double time = TimeAtPosition(Content.ToLocalSpace(screenSpacePosition).X);
return new SnapResult(screenSpacePosition, beatSnapProvider.SnapTime(time));
}
}
}

View File

@ -175,7 +175,29 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
};
}
protected override DragBox CreateDragBox() => new TimelineDragBox();
protected sealed override DragBox CreateDragBox() => new TimelineDragBox();
protected override void UpdateSelectionFromDragBox()
{
var dragBox = (TimelineDragBox)DragBox;
double minTime = dragBox.MinTime;
double maxTime = dragBox.MaxTime;
Console.WriteLine($"{minTime}, {maxTime}");
// TODO: performance
foreach (var hitObject in Beatmap.HitObjects)
{
bool shouldBeSelected = minTime <= hitObject.StartTime && hitObject.StartTime <= maxTime;
bool isSelected = SelectedItems.Contains(hitObject);
if (isSelected != shouldBeSelected)
{
if (!isSelected)
SelectedItems.Add(hitObject);
else
SelectedItems.Remove(hitObject);
}
}
}
private void handleScrollViaDrag(DragEvent e)
{

View File

@ -14,11 +14,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{
public class TimelineDragBox : DragBox
{
// the following values hold the start and end X positions of the drag box in the timeline's local space,
// but with zoom unapplied in order to be able to compensate for positional changes
// while the timeline is being zoomed in/out.
private float? selectionStart;
private float selectionEnd;
public double MinTime => Math.Min(startTime.Value, endTime);
public double MaxTime => Math.Max(startTime.Value, endTime);
private double? startTime;
private double endTime;
[Resolved]
private Timeline timeline { get; set; }
@ -31,37 +33,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
public override void HandleDrag(MouseButtonEvent e)
{
selectionStart ??= e.MouseDownPosition.X / timeline.CurrentZoom;
startTime ??= timeline.TimeAtPosition(e.MouseDownPosition.X);
endTime = timeline.TimeAtPosition(e.MousePosition.X);
// only calculate end when a transition is not in progress to avoid bouncing.
if (Precision.AlmostEquals(timeline.CurrentZoom, timeline.Zoom))
selectionEnd = e.MousePosition.X / timeline.CurrentZoom;
updateDragBoxPosition();
}
private void updateDragBoxPosition()
{
if (selectionStart == null)
return;
float rescaledStart = selectionStart.Value * timeline.CurrentZoom;
float rescaledEnd = selectionEnd * timeline.CurrentZoom;
Box.X = Math.Min(rescaledStart, rescaledEnd);
Box.Width = Math.Abs(rescaledStart - rescaledEnd);
var boxScreenRect = Box.ScreenSpaceDrawQuad.AABBFloat;
// 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;
Box.X = timeline.PositionAtTime(MinTime);
Box.Width = timeline.PositionAtTime(MaxTime) - Box.X;
}
public override void Hide()
{
base.Hide();
selectionStart = null;
startTime = null;
}
}
}