Merge pull request #11499 from peppy/fix-editor-scroll-interruption

Fix inability to interrupt timeline flick-scrolls by other means
This commit is contained in:
Dan Balasescu 2021-01-21 18:39:11 +09:00 committed by GitHub
commit 658370ff38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 40 additions and 24 deletions

View File

@ -332,7 +332,7 @@ namespace osu.Game.Rulesets.Edit
EditorBeatmap.Add(hitObject);
if (EditorClock.CurrentTime < hitObject.StartTime)
EditorClock.SeekTo(hitObject.StartTime);
EditorClock.SeekSmoothlyTo(hitObject.StartTime);
}
}

View File

@ -58,7 +58,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
return;
float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth);
editorClock.SeekTo(markerPos / DrawWidth * editorClock.TrackLength);
editorClock.SeekSmoothlyTo(markerPos / DrawWidth * editorClock.TrackLength);
});
}

View File

@ -170,7 +170,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
if (clickedBlueprint == null || SelectionHandler.SelectedBlueprints.FirstOrDefault(b => b.IsHovered) != clickedBlueprint)
return false;
EditorClock?.SeekTo(clickedBlueprint.HitObject.StartTime);
EditorClock?.SeekSmoothlyTo(clickedBlueprint.HitObject.StartTime);
return true;
}

View File

@ -155,12 +155,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
seekTrackToCurrent();
else if (!editorClock.IsRunning)
{
// The track isn't running. There are two cases we have to be wary of:
// 1) The user flick-drags on this timeline: We want the track to follow us
// 2) The user changes the track time through some other means (scrolling in the editor or overview timeline): We want to follow the track time
// The track isn't running. There are three cases we have to be wary of:
// 1) The user flick-drags on this timeline and we are applying an interpolated seek on the clock, until interrupted by 2 or 3.
// 2) The user changes the track time through some other means (scrolling in the editor or overview timeline; clicking a hitobject etc.). We want the timeline to track the clock's time.
// 3) An ongoing seek transform is running from an external seek. We want the timeline to track the clock's time.
// The simplest way to cover both cases is by checking whether the scroll position has changed and the audio hasn't been changed externally
if (Current != lastScrollPosition && editorClock.CurrentTime == lastTrackTime)
// The simplest way to cover the first two cases is by checking whether the scroll position has changed and the audio hasn't been changed externally
// Checking IsSeeking covers the third case, where the transform may not have been applied yet.
if (Current != lastScrollPosition && editorClock.CurrentTime == lastTrackTime && !editorClock.IsSeeking)
seekTrackToCurrent();
else
scrollToTrackTime();

View File

@ -35,6 +35,11 @@ namespace osu.Game.Screens.Edit
private readonly Bindable<bool> seekingOrStopped = new Bindable<bool>(true);
/// <summary>
/// Whether a seek is currently in progress. True for the duration of a seek performed via <see cref="SeekSmoothlyTo"/>.
/// </summary>
public bool IsSeeking { get; private set; }
public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor)
: this(beatmap.Beatmap.ControlPointInfo, beatmap.Track.Length, beatDivisor)
{
@ -111,7 +116,7 @@ namespace osu.Game.Screens.Edit
if (!snapped || ControlPointInfo.TimingPoints.Count == 0)
{
SeekTo(seekTime);
SeekSmoothlyTo(seekTime);
return;
}
@ -145,11 +150,11 @@ namespace osu.Game.Screens.Edit
// Ensure the sought point is within the boundaries
seekTime = Math.Clamp(seekTime, 0, TrackLength);
SeekTo(seekTime);
SeekSmoothlyTo(seekTime);
}
/// <summary>
/// The current time of this clock, include any active transform seeks performed via <see cref="SeekTo"/>.
/// The current time of this clock, include any active transform seeks performed via <see cref="SeekSmoothlyTo"/>.
/// </summary>
public double CurrentTimeAccurate =>
Transforms.OfType<TransformSeek>().FirstOrDefault()?.EndValue ?? CurrentTime;
@ -176,12 +181,29 @@ namespace osu.Game.Screens.Edit
public bool Seek(double position)
{
seekingOrStopped.Value = true;
seekingOrStopped.Value = IsSeeking = true;
ClearTransforms();
return underlyingClock.Seek(position);
}
/// <summary>
/// Seek smoothly to the provided destination.
/// Use <see cref="Seek"/> to perform an immediate seek.
/// </summary>
/// <param name="seekDestination"></param>
public void SeekSmoothlyTo(double seekDestination)
{
seekingOrStopped.Value = true;
if (IsRunning)
Seek(seekDestination);
else
{
transformSeekTo(seekDestination, transform_time, Easing.OutQuint);
}
}
public void ResetSpeedAdjustments() => underlyingClock.ResetSpeedAdjustments();
double IAdjustableClock.Rate
@ -229,6 +251,8 @@ namespace osu.Game.Screens.Edit
{
if (seekingOrStopped.Value)
{
IsSeeking &= Transforms.Any();
if (track.Value?.IsRunning != true)
{
// seeking in the editor can happen while the track isn't running.
@ -239,20 +263,10 @@ namespace osu.Game.Screens.Edit
// we are either running a seek tween or doing an immediate seek.
// in the case of an immediate seek the seeking bool will be set to false after one update.
// this allows for silencing hit sounds and the likes.
seekingOrStopped.Value = Transforms.Any();
seekingOrStopped.Value = IsSeeking;
}
}
public void SeekTo(double seekDestination)
{
seekingOrStopped.Value = true;
if (IsRunning)
Seek(seekDestination);
else
transformSeekTo(seekDestination, transform_time, Easing.OutQuint);
}
private void transformSeekTo(double seek, double duration = 0, Easing easing = Easing.None)
=> this.TransformTo(this.PopulateTransform(new TransformSeek(), seek, duration, easing));

View File

@ -206,7 +206,7 @@ namespace osu.Game.Screens.Edit.Timing
Action = () =>
{
selectedGroup.Value = controlGroup;
clock.SeekTo(controlGroup.Time);
clock.SeekSmoothlyTo(controlGroup.Time);
};
}