mirror of
https://github.com/ppy/osu.git
synced 2025-01-30 06:52:53 +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>
|
/// </summary>
|
||||||
public double VisibleRange => editorClock.TrackLength / Zoom;
|
public double VisibleRange => editorClock.TrackLength / Zoom;
|
||||||
|
|
||||||
public SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.All) =>
|
public double TimeAtPosition(float x)
|
||||||
new SnapResult(screenSpacePosition, beatSnapProvider.SnapTime(getTimeFromPosition(Content.ToLocalSpace(screenSpacePosition))));
|
{
|
||||||
|
return x / Content.DrawWidth * editorClock.TrackLength;
|
||||||
|
}
|
||||||
|
|
||||||
private double getTimeFromPosition(Vector2 localPosition) =>
|
public float PositionAtTime(double time)
|
||||||
(localPosition.X / Content.DrawWidth) * editorClock.TrackLength;
|
{
|
||||||
|
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)
|
private void handleScrollViaDrag(DragEvent e)
|
||||||
{
|
{
|
||||||
|
@ -14,11 +14,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
{
|
{
|
||||||
public class TimelineDragBox : DragBox
|
public class TimelineDragBox : DragBox
|
||||||
{
|
{
|
||||||
// the following values hold the start and end X positions of the drag box in the timeline's local space,
|
public double MinTime => Math.Min(startTime.Value, endTime);
|
||||||
// but with zoom unapplied in order to be able to compensate for positional changes
|
|
||||||
// while the timeline is being zoomed in/out.
|
public double MaxTime => Math.Max(startTime.Value, endTime);
|
||||||
private float? selectionStart;
|
|
||||||
private float selectionEnd;
|
private double? startTime;
|
||||||
|
|
||||||
|
private double endTime;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private Timeline timeline { get; set; }
|
private Timeline timeline { get; set; }
|
||||||
@ -31,37 +33,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
public override void HandleDrag(MouseButtonEvent e)
|
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.
|
Box.X = timeline.PositionAtTime(MinTime);
|
||||||
if (Precision.AlmostEquals(timeline.CurrentZoom, timeline.Zoom))
|
Box.Width = timeline.PositionAtTime(MaxTime) - Box.X;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Hide()
|
public override void Hide()
|
||||||
{
|
{
|
||||||
base.Hide();
|
base.Hide();
|
||||||
selectionStart = null;
|
startTime = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user