From eb5d3348386cfdcaa9a2b32ea97cff8e63fe2300 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2017 19:07:07 +0900 Subject: [PATCH 01/12] Add non-toggle support for showing seek bar in SongProgress. --- .../Tests/TestCaseSongProgress.cs | 4 ++-- osu.Game/Screens/Play/SongProgress.cs | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs b/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs index 7c40d21512..6d8aac1d09 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs @@ -38,9 +38,9 @@ public override void Reset() Origin = Anchor.TopLeft, }); - AddStep("Toggle Bar", progress.ToggleBar); + AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); AddWaitStep(5); - AddStep("Toggle Bar", progress.ToggleBar); + AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); AddWaitStep(2); AddRepeatStep("New Values", displayNewValues, 5); diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 6ad76ae361..c3e3751a67 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -86,18 +86,28 @@ protected override void LoadComplete() State = Visibility.Visible; } - private bool barVisible; + private bool allowSeeking; - public void ToggleBar() + public bool AllowSeeking { - barVisible = !barVisible; - updateBarVisibility(); + get + { + return allowSeeking; + } + + set + { + if (allowSeeking == value) return; + + allowSeeking = value; + updateBarVisibility(); + } } private void updateBarVisibility() { - bar.FadeTo(barVisible ? 1 : 0, transition_duration, EasingTypes.In); - MoveTo(new Vector2(0, barVisible ? 0 : bottom_bar_height), transition_duration, EasingTypes.In); + bar.FadeTo(allowSeeking ? 1 : 0, transition_duration, EasingTypes.In); + MoveTo(new Vector2(0, allowSeeking ? 0 : bottom_bar_height), transition_duration, EasingTypes.In); } protected override void PopIn() From d4764824931e7e383f3025568fa861d034c57a0d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2017 19:07:38 +0900 Subject: [PATCH 02/12] Add basic seeking support when a replay is loaded. --- osu.Game/Screens/Play/Player.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 2668c61eee..47c120f363 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -156,6 +156,11 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager hudOverlay.Progress.Objects = HitRenderer.Objects; hudOverlay.Progress.AudioClock = interpolatedSourceClock; + hudOverlay.Progress.AllowSeeking = HitRenderer.HasReplayLoaded; + hudOverlay.Progress.OnSeek = progress => + { + sourceClock.Seek(progress * track.Length); + }; //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) HitRenderer.OnAllJudged += onCompletion; From e003d9fc3cad84a0c7cb41b4d7d046483d3b26e6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2017 19:09:30 +0900 Subject: [PATCH 03/12] Add basic replay frame accurate "seeking". Previously we were looping over Update, when we should instead have been looping over UpdateSubTree. --- osu.Game/Rulesets/UI/HitRenderer.cs | 2 +- osu.Game/Screens/Play/PlayerInputManager.cs | 54 ++++++++++++++++----- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs index a3a806b6a7..25d8bae205 100644 --- a/osu.Game/Rulesets/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -116,7 +116,7 @@ public abstract class HitRenderer : HitRenderer where TObject : HitObject { /// - /// The Beatmap + /// The Beatmap /// public Beatmap Beatmap; diff --git a/osu.Game/Screens/Play/PlayerInputManager.cs b/osu.Game/Screens/Play/PlayerInputManager.cs index 3ac28898a6..c6853b3007 100644 --- a/osu.Game/Screens/Play/PlayerInputManager.cs +++ b/osu.Game/Screens/Play/PlayerInputManager.cs @@ -36,6 +36,38 @@ protected override void LoadComplete() Clock = new FramedClock(clock); } + /// + /// Whether we running up-to-date with our parent clock. + /// If not, we will need to keep processing children until we catch up. + /// + private bool requireMoreUpdateLoops; + + /// + /// Whether we in a valid state (ie. should we keep processing children frames). + /// This should be set to false when the replay is, for instance, waiting for future frames to arrive. + /// + private bool validState; + + protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate && validState; + + private bool isAttached => replayInputHandler != null && !UseParentState; + + private const int max_catch_up_updates_per_frame = 50; + + public override bool UpdateSubTree() + { + requireMoreUpdateLoops = true; + validState = true; + + int loops = 0; + + while (validState && requireMoreUpdateLoops && loops++ < 50) + if (!base.UpdateSubTree()) + return false; + + return true; + } + protected override void Update() { if (parentClock == null) return; @@ -43,28 +75,26 @@ protected override void Update() clock.Rate = parentClock.Rate; clock.IsRunning = parentClock.IsRunning; - //if a replayHandler is not attached, we should just pass-through. - if (UseParentState || replayInputHandler == null) + if (!isAttached) { clock.CurrentTime = parentClock.CurrentTime; - base.Update(); - return; } - - while (true) + else { double? newTime = replayInputHandler.SetFrameFromTime(parentClock.CurrentTime); if (newTime == null) - //we shouldn't execute for this time value - break; - - if (clock.CurrentTime == parentClock.CurrentTime) - break; + { + // we shouldn't execute for this time value. probably waiting on more replay data. + validState = false; + return; + } clock.CurrentTime = newTime.Value; - base.Update(); } + + requireMoreUpdateLoops = clock.CurrentTime != parentClock.CurrentTime; + base.Update(); } } } From 01caaf44f373f62fafe26cfdb63f6db1fd88d79e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Apr 2017 18:16:55 +0900 Subject: [PATCH 04/12] Add a decoupled clock to allow for lead-in and lead-out time. --- osu.Game/Screens/Play/Player.cs | 44 +++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 47c120f363..ac9337b802 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -38,7 +38,7 @@ public class Player : OsuScreen public Action RestartRequested; - public bool IsPaused => !interpolatedSourceClock.IsRunning; + public bool IsPaused => !decoupledClock.IsRunning; internal override bool AllowRulesetChange => false; @@ -51,9 +51,9 @@ public class Player : OsuScreen private bool canPause => ValidForResume && !HasFailed && Time.Current >= lastPauseActionTime + pause_cooldown; - private IAdjustableClock sourceClock; - private OffsetClock offsetClock; - private IFrameBasedClock interpolatedSourceClock; + private IAdjustableClock adjustableSourceClock; + private FramedOffsetClock offsetClock; + private DecoupleableInterpolatingFramedClock decoupledClock; private RulesetInfo ruleset; @@ -123,23 +123,31 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager if (track != null) { audio.Track.SetExclusive(track); - sourceClock = track; + adjustableSourceClock = track; } - sourceClock = (IAdjustableClock)track ?? new StopwatchClock(); - offsetClock = new OffsetClock(sourceClock); + adjustableSourceClock = (IAdjustableClock)track ?? new StopwatchClock(); + + decoupledClock = new DecoupleableInterpolatingFramedClock(); + decoupledClock.ChangeSource(adjustableSourceClock); + decoupledClock.IsCoupled = false; + + offsetClock = new FramedOffsetClock(decoupledClock); userAudioOffset = config.GetBindable(OsuConfig.AudioOffset); userAudioOffset.ValueChanged += v => offsetClock.Offset = v; userAudioOffset.TriggerChange(); - interpolatedSourceClock = new InterpolatingFramedClock(offsetClock); - Schedule(() => { - sourceClock.Reset(); + adjustableSourceClock.Reset(); + + var firstObjectTime = HitRenderer.Objects.First().StartTime; + + decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(Beatmap.Beatmap.TimingInfo.BeatLengthAt(firstObjectTime) * 2, Beatmap.BeatmapInfo.AudioLeadIn))); + foreach (var mod in Beatmap.Mods.Value.OfType()) - mod.ApplyToClock(sourceClock); + mod.ApplyToClock(adjustableSourceClock); }); scoreProcessor = HitRenderer.CreateScoreProcessor(); @@ -155,7 +163,7 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager hudOverlay.BindHitRenderer(HitRenderer); hudOverlay.Progress.Objects = HitRenderer.Objects; - hudOverlay.Progress.AudioClock = interpolatedSourceClock; + hudOverlay.Progress.AudioClock = decoupledClock; hudOverlay.Progress.AllowSeeking = HitRenderer.HasReplayLoaded; hudOverlay.Progress.OnSeek = progress => { @@ -173,7 +181,7 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager new Container { RelativeSizeAxes = Axes.Both, - Clock = interpolatedSourceClock, + Clock = offsetClock, Children = new Drawable[] { HitRenderer, @@ -229,7 +237,7 @@ private void initializeSkipButton() skipButton.Action = () => { - sourceClock.Seek(firstHitObject - skip_required_cutoff - fade_time); + decoupledClock.Seek(firstHitObject - skip_required_cutoff - fade_time); skipButton.Action = null; }; @@ -246,7 +254,7 @@ public void Pause(bool force = false) // we want to wait for the source clock to stop so we can be sure all components are in a stable state. if (!IsPaused) { - sourceClock.Stop(); + decoupledClock.Stop(); Schedule(() => Pause(force)); return; @@ -273,7 +281,7 @@ public void Resume() hudOverlay.KeyCounter.IsCounting = true; hudOverlay.Progress.Hide(); pauseOverlay.Hide(); - sourceClock.Start(); + decoupledClock.Start(); } public void Restart() @@ -309,7 +317,7 @@ private void onCompletion() private void onFail() { - sourceClock.Stop(); + decoupledClock.Stop(); HasFailed = true; failOverlay.Retries = RestartCount; @@ -337,7 +345,7 @@ protected override void OnEntering(Screen last) Delay(750); Schedule(() => { - sourceClock.Start(); + decoupledClock.Start(); initializeSkipButton(); }); From 9d14b6e1e942394ed20f54ae084ba869d599f3c5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Apr 2017 18:17:17 +0900 Subject: [PATCH 05/12] Make SongProgress return the actual time value via OnSeek. --- osu.Game/Screens/Play/Player.cs | 4 ++-- osu.Game/Screens/Play/SongProgress.cs | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ac9337b802..90918cc93d 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -165,9 +165,9 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager hudOverlay.Progress.Objects = HitRenderer.Objects; hudOverlay.Progress.AudioClock = decoupledClock; hudOverlay.Progress.AllowSeeking = HitRenderer.HasReplayLoaded; - hudOverlay.Progress.OnSeek = progress => + hudOverlay.Progress.OnSeek = pos => { - sourceClock.Seek(progress * track.Length); + decoupledClock.Seek(pos); }; //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index c3e3751a67..ed57dad644 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -35,6 +35,8 @@ public class SongProgress : OverlayContainer private double lastHitTime => ((objects.Last() as IHasEndTime)?.EndTime ?? objects.Last().StartTime) + 1; + private double firstHitTime => objects.First().StartTime; + private IEnumerable objects; public IEnumerable Objects @@ -75,7 +77,7 @@ public SongProgress() Origin = Anchor.BottomLeft, SeekRequested = delegate (float position) { - OnSeek?.Invoke(position); + OnSeek?.Invoke(firstHitTime + position * (lastHitTime - firstHitTime)); }, }, }; @@ -128,7 +130,7 @@ protected override void Update() if (objects == null) return; - double progress = (AudioClock?.CurrentTime ?? Time.Current) / lastHitTime; + double progress = ((AudioClock?.CurrentTime ?? Time.Current) - firstHitTime) / lastHitTime; bar.UpdatePosition((float)progress); graph.Progress = (int)(graph.ColumnCount * progress); From 4656a7170a91e6879efb03f95fb553800b0d1bb5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Apr 2017 18:07:22 +0900 Subject: [PATCH 06/12] Add very basic lead-in support. --- osu.Game/Screens/Play/Player.cs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 90918cc93d..853a50d855 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -70,6 +70,8 @@ public class Player : OsuScreen private SkipButton skipButton; + private Container hitRendererContainer; + private HudOverlay hudOverlay; private PauseOverlay pauseOverlay; private FailOverlay failOverlay; @@ -129,9 +131,12 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager adjustableSourceClock = (IAdjustableClock)track ?? new StopwatchClock(); decoupledClock = new DecoupleableInterpolatingFramedClock(); - decoupledClock.ChangeSource(adjustableSourceClock); decoupledClock.IsCoupled = false; + var firstObjectTime = HitRenderer.Objects.First().StartTime; + decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(Beatmap.Beatmap.TimingInfo.BeatLengthAt(firstObjectTime) * 4, Beatmap.BeatmapInfo.AudioLeadIn))); + decoupledClock.ProcessFrame(); + offsetClock = new FramedOffsetClock(decoupledClock); userAudioOffset = config.GetBindable(OsuConfig.AudioOffset); @@ -142,12 +147,10 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager { adjustableSourceClock.Reset(); - var firstObjectTime = HitRenderer.Objects.First().StartTime; - - decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(Beatmap.Beatmap.TimingInfo.BeatLengthAt(firstObjectTime) * 2, Beatmap.BeatmapInfo.AudioLeadIn))); - foreach (var mod in Beatmap.Mods.Value.OfType()) mod.ApplyToClock(adjustableSourceClock); + + decoupledClock.ChangeSource(adjustableSourceClock); }); scoreProcessor = HitRenderer.CreateScoreProcessor(); @@ -178,16 +181,20 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager Children = new Drawable[] { - new Container + hitRendererContainer = new Container { RelativeSizeAxes = Axes.Both, - Clock = offsetClock, Children = new Drawable[] { - HitRenderer, - skipButton = new SkipButton + new Container { - Alpha = 0 + RelativeSizeAxes = Axes.Both, + Clock = offsetClock, + Children = new Drawable[] + { + HitRenderer, + skipButton = new SkipButton { Alpha = 0 }, + } }, } }, @@ -350,8 +357,8 @@ protected override void OnEntering(Screen last) }); //keep in mind this is using the interpolatedSourceClock so won't be run as early as we may expect. - HitRenderer.Alpha = 0; - HitRenderer.FadeIn(750, EasingTypes.OutQuint); + hitRendererContainer.Alpha = 0; + hitRendererContainer.FadeIn(750, EasingTypes.OutQuint); } protected override void OnSuspending(Screen next) From 867c16665b02729cdd3e769e3fece3f823dfd544 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Apr 2017 18:22:09 +0900 Subject: [PATCH 07/12] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index cc50d1251b..0374f02617 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit cc50d1251b00876331691ea2ce7ed18174e4eded +Subproject commit 0374f026179a3509caa7944ef1efbc318e092d2a From b6f838f536948347e051801dda2755cba896c1b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Apr 2017 18:32:40 +0900 Subject: [PATCH 08/12] Fix potential nullref. --- osu.Game/Screens/Play/Player.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 853a50d855..dcb90846d9 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -89,12 +89,12 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager if (Beatmap == null) Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo, withStoryboard: true); - if ((Beatmap?.Beatmap?.HitObjects.Count ?? 0) == 0) - throw new Exception("No valid objects were found!"); - - if (Beatmap == null) + if (Beatmap?.Beatmap == null) throw new Exception("Beatmap was not loaded"); + if (Beatmap?.Beatmap?.HitObjects.Count == 0) + throw new Exception("No valid objects were found!"); + ruleset = osu?.Ruleset.Value ?? Beatmap.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); From c2108b7706fe85bf922774d387e61e4b21770291 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Apr 2017 18:32:47 +0900 Subject: [PATCH 09/12] Use object initialiser. --- osu.Game/Screens/Play/Player.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index dcb90846d9..7d001d16bf 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -130,8 +130,7 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager adjustableSourceClock = (IAdjustableClock)track ?? new StopwatchClock(); - decoupledClock = new DecoupleableInterpolatingFramedClock(); - decoupledClock.IsCoupled = false; + decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; var firstObjectTime = HitRenderer.Objects.First().StartTime; decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(Beatmap.Beatmap.TimingInfo.BeatLengthAt(firstObjectTime) * 4, Beatmap.BeatmapInfo.AudioLeadIn))); From bd71b236990c0f3aa43a618bbd6f6b62654c3502 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Apr 2017 19:52:51 +0900 Subject: [PATCH 10/12] Update framework again. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 0374f02617..dcbd7a0b6f 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 0374f026179a3509caa7944ef1efbc318e092d2a +Subproject commit dcbd7a0b6f536f6aadf13a720db40a1d76bf52e2 From 08b1d5beb9f33be940163550ff8266338e5941ac Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 26 Apr 2017 20:15:34 +0900 Subject: [PATCH 11/12] Use const where it was inteded. --- osu.Game/Screens/Play/PlayerInputManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerInputManager.cs b/osu.Game/Screens/Play/PlayerInputManager.cs index c6853b3007..654cde1b75 100644 --- a/osu.Game/Screens/Play/PlayerInputManager.cs +++ b/osu.Game/Screens/Play/PlayerInputManager.cs @@ -61,7 +61,7 @@ public override bool UpdateSubTree() int loops = 0; - while (validState && requireMoreUpdateLoops && loops++ < 50) + while (validState && requireMoreUpdateLoops && loops++ < max_catch_up_updates_per_frame) if (!base.UpdateSubTree()) return false; From f261a077d2ff613136b84206ddc94332e28756c1 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 26 Apr 2017 20:22:03 +0900 Subject: [PATCH 12/12] General fixes/cleanup in Player. --- osu.Game/Screens/Play/Player.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7d001d16bf..37b4cf5b45 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -92,9 +92,6 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager if (Beatmap?.Beatmap == null) throw new Exception("Beatmap was not loaded"); - if (Beatmap?.Beatmap?.HitObjects.Count == 0) - throw new Exception("No valid objects were found!"); - ruleset = osu?.Ruleset.Value ?? Beatmap.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); @@ -110,6 +107,9 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager rulesetInstance = ruleset.CreateInstance(); HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap); } + + if (!HitRenderer.Objects.Any()) + throw new Exception("Beatmap contains no hit objects!"); } catch (Exception e) { @@ -167,10 +167,7 @@ private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager hudOverlay.Progress.Objects = HitRenderer.Objects; hudOverlay.Progress.AudioClock = decoupledClock; hudOverlay.Progress.AllowSeeking = HitRenderer.HasReplayLoaded; - hudOverlay.Progress.OnSeek = pos => - { - decoupledClock.Seek(pos); - }; + hudOverlay.Progress.OnSeek = pos => decoupledClock.Seek(pos); //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) HitRenderer.OnAllJudged += onCompletion; @@ -355,7 +352,6 @@ protected override void OnEntering(Screen last) initializeSkipButton(); }); - //keep in mind this is using the interpolatedSourceClock so won't be run as early as we may expect. hitRendererContainer.Alpha = 0; hitRendererContainer.FadeIn(750, EasingTypes.OutQuint); }