mirror of
https://github.com/ppy/osu.git
synced 2024-11-06 06:57:39 +08:00
Use hit object time for timeline selection
This commit is contained in:
parent
8d29e9e76b
commit
0ffde02f79
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user