Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Avoid accessing WorkingBeatmap.Beatmap every update call #31775

Merged
merged 2 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions osu.Game/Beatmaps/WorkingBeatmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ public IBeatmap Beatmap
{
try
{
// TODO: This is a touch expensive and can become an issue if being accessed every Update call.
// Optimally we would not involve the async flow if things are already loaded.
return loadBeatmapAsync().GetResultSafely();
}
catch (AggregateException ae)
Expand Down
33 changes: 16 additions & 17 deletions osu.Game/Screens/Play/MasterGameplayClockContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Overlays;
using osu.Game.Storyboards;

namespace osu.Game.Screens.Play
{
Expand Down Expand Up @@ -53,7 +54,7 @@ public partial class MasterGameplayClockContainer : GameplayClockContainer, IBea

private readonly Bindable<bool> playbackRateValid = new Bindable<bool>(true);

private readonly WorkingBeatmap beatmap;
private readonly IBeatmap beatmap;

private Track track;

Expand All @@ -63,20 +64,19 @@ public partial class MasterGameplayClockContainer : GameplayClockContainer, IBea
/// <summary>
/// Create a new master gameplay clock container.
/// </summary>
/// <param name="beatmap">The beatmap to be used for time and metadata references.</param>
/// <param name="working">The beatmap to be used for time and metadata references.</param>
/// <param name="gameplayStartTime">The latest time which should be used when introducing gameplay. Will be used when skipping forward.</param>
public MasterGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStartTime)
: base(beatmap.Track, applyOffsets: true, requireDecoupling: true)
public MasterGameplayClockContainer(WorkingBeatmap working, double gameplayStartTime)
: base(working.Track, applyOffsets: true, requireDecoupling: true)
{
this.beatmap = beatmap;

track = beatmap.Track;
beatmap = working.Beatmap;
track = working.Track;

GameplayStartTime = gameplayStartTime;
StartTime = findEarliestStartTime(gameplayStartTime, beatmap);
StartTime = findEarliestStartTime(gameplayStartTime, beatmap, working.Storyboard);
}

private static double findEarliestStartTime(double gameplayStartTime, WorkingBeatmap beatmap)
private static double findEarliestStartTime(double gameplayStartTime, IBeatmap beatmap, Storyboard storyboard)
{
// here we are trying to find the time to start playback from the "zero" point.
// generally this is either zero, or some point earlier than zero in the case of storyboards, lead-ins etc.
Expand All @@ -86,15 +86,15 @@ private static double findEarliestStartTime(double gameplayStartTime, WorkingBea

// if a storyboard is present, it may dictate the appropriate start time by having events in negative time space.
// this is commonly used to display an intro before the audio track start.
double? firstStoryboardEvent = beatmap.Storyboard.EarliestEventTime;
double? firstStoryboardEvent = storyboard.EarliestEventTime;
if (firstStoryboardEvent != null)
time = Math.Min(time, firstStoryboardEvent.Value);

// some beatmaps specify a current lead-in time which should be used instead of the ruleset-provided value when available.
// this is not available as an option in the live editor but can still be applied via .osu editing.
double firstHitObjectTime = beatmap.Beatmap.HitObjects.First().StartTime;
if (beatmap.Beatmap.AudioLeadIn > 0)
time = Math.Min(time, firstHitObjectTime - beatmap.Beatmap.AudioLeadIn);
double firstHitObjectTime = beatmap.HitObjects.First().StartTime;
if (beatmap.AudioLeadIn > 0)
time = Math.Min(time, firstHitObjectTime - beatmap.AudioLeadIn);

return time;
}
Expand Down Expand Up @@ -136,7 +136,7 @@ public void StopUsingBeatmapClock()
{
removeAdjustmentsFromTrack();

track = new TrackVirtual(beatmap.Track.Length);
track = new TrackVirtual(track.Length);
track.Seek(CurrentTime);
if (IsRunning)
track.Start();
Expand Down Expand Up @@ -228,9 +228,8 @@ protected override void Dispose(bool isDisposing)
removeAdjustmentsFromTrack();
}

ControlPointInfo IBeatSyncProvider.ControlPoints => beatmap.Beatmap.ControlPointInfo;
ControlPointInfo IBeatSyncProvider.ControlPoints => beatmap.ControlPointInfo;
ChannelAmplitudes IHasAmplitudes.CurrentAmplitudes => track.CurrentAmplitudes;
IClock IBeatSyncProvider.Clock => this;

ChannelAmplitudes IHasAmplitudes.CurrentAmplitudes => beatmap.TrackLoaded ? beatmap.Track.CurrentAmplitudes : ChannelAmplitudes.Empty;
}
}