public override void OnEntering(IScreen last) { base.OnEntering(last); if (!LoadedBeatmapSuccessfully) { return; } Alpha = 0; this .ScaleTo(0.7f) .ScaleTo(1, 750, Easing.OutQuint) .Delay(250) .FadeIn(250); showStoryboard.ValueChanged += _ => initializeStoryboard(true); Background.EnableUserDim.Value = true; Background.BlurAmount.Value = 0; Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); StoryboardContainer.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable; GameplayClockContainer.Restart(); GameplayClockContainer.FadeInFromZero(750, Easing.OutQuint); }
public override bool OnExiting(IScreen next) { if (completionProgressDelegate != null && !completionProgressDelegate.Cancelled && !completionProgressDelegate.Completed) { // proceed to result screen if beatmap already finished playing completionProgressDelegate.RunTask(); return(true); } // ValidForResume is false when restarting if (ValidForResume) { if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) { // still want to block if we are within the cooldown period and not already paused. return(true); } } if (canPause) { Pause(); return(true); } // GameplayClockContainer performs seeks / start / stop operations on the beatmap's track. // as we are no longer the current screen, we cannot guarantee the track is still usable. GameplayClockContainer?.StopUsingBeatmapClock(); fadeOut(); return(base.OnExiting(next)); }
public override void OnEntering(IScreen last) { base.OnEntering(last); if (!LoadedBeatmapSuccessfully) { return; } Alpha = 0; this .ScaleTo(0.7f) .ScaleTo(1, 750, Easing.OutQuint) .Delay(250) .FadeIn(250); Background.EnableUserDim.Value = true; Background.BlurAmount.Value = 0; Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable; GameplayClockContainer.Restart(); GameplayClockContainer.FadeInFromZero(750, Easing.OutQuint); foreach (var mod in Mods.Value.OfType <IApplicableToHUD>()) { mod.ApplyToHUD(HUDOverlay); } }
public override bool OnExiting(IScreen next) { if (onCompletionEvent != null) { // Proceed to result screen if beatmap already finished playing onCompletionEvent.RunTask(); return(true); } if (canPause) { Pause(); return(true); } if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) { // still want to block if we are within the cooldown period and not already paused. return(true); } if (HasFailed && ValidForResume && !FailOverlay.IsPresent) // ValidForResume is false when restarting { failAnimation.FinishTransforms(true); return(true); } GameplayClockContainer.ResetLocalAdjustments(); fadeOut(); return(base.OnExiting(next)); }
// Called back when the transform finishes private void onFailComplete() { GameplayClockContainer.Stop(); FailOverlay.Retries = RestartCount; FailOverlay.Show(); }
public void Resume() { if (!canResume) { return; } IsResuming = true; PauseOverlay.Hide(); // breaks and time-based conditions may allow instant resume. if (breakTracker.IsBreakTime.Value) { completeResume(); } else { DrawableRuleset.RequestResume(completeResume); } void completeResume() { GameplayClockContainer.Start(); IsResuming = false; } }
public bool OnPressed(KeyBindingPressEvent <GlobalAction> e) { const double keyboard_seek_amount = 5000; switch (e.Action) { case GlobalAction.SeekReplayBackward: keyboardSeek(-1); return(true); case GlobalAction.SeekReplayForward: keyboardSeek(1); return(true); case GlobalAction.TogglePauseReplay: if (GameplayClockContainer.IsPaused.Value) { GameplayClockContainer.Start(); } else { GameplayClockContainer.Stop(); } return(true); } return(false); void keyboardSeek(int direction) { double target = Math.Clamp(GameplayClockContainer.CurrentTime + direction * keyboard_seek_amount, 0, GameplayState.Beatmap.HitObjects.Last().GetEndTime()); Seek(target); } }
public void Resume() { if (!canResume) { return; } IsResuming = true; PauseOverlay.Hide(); // time-based conditions may allow instant resume. if (GameplayClockContainer.GameplayClock.CurrentTime < Beatmap.Value.Beatmap.HitObjects.First().StartTime) { completeResume(); } else { DrawableRuleset.RequestResume(completeResume); } void completeResume() { GameplayClockContainer.Start(); IsResuming = false; } }
public override bool OnExiting(IScreen next) { if (onCompletionEvent != null) { // Proceed to result screen if beatmap already finished playing onCompletionEvent.RunTask(); return(true); } if (canPause) { Pause(); return(true); } if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) { // still want to block if we are within the cooldown period and not already paused. return(true); } GameplayClockContainer.ResetLocalAdjustments(); fadeOut(); return(base.OnExiting(next)); }
public override void OnEntering(IScreen last) { base.OnEntering(last); if (!LoadedBeatmapSuccessfully) { return; } Alpha = 0; this .ScaleTo(0.7f) .ScaleTo(1, 750, Easing.OutQuint) .Delay(250) .FadeIn(250); ApplyToBackground(b => { b.IgnoreUserSettings.Value = false; b.BlurAmount.Value = 0; b.FadeColour(Color4.White, 250); // bind component bindables. b.IsBreakTime.BindTo(breakTracker.IsBreakTime); b.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); }); HUDOverlay.IsBreakTime.BindTo(breakTracker.IsBreakTime); DimmableStoryboard.IsBreakTime.BindTo(breakTracker.IsBreakTime); DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable; foreach (var mod in Mods.Value.OfType <IApplicableToPlayer>()) { mod.ApplyToPlayer(this); } foreach (var mod in Mods.Value.OfType <IApplicableToHUD>()) { mod.ApplyToHUD(HUDOverlay); } // Our mods are local copies of the global mods so they need to be re-applied to the track. // This is done through the music controller (for now), because resetting speed adjustments on the beatmap track also removes adjustments provided by DrawableTrack. // Todo: In the future, player will receive in a track and will probably not have to worry about this... musicController.ResetTrackAdjustments(); foreach (var mod in Mods.Value.OfType <IApplicableToTrack>()) { mod.ApplyToTrack(musicController.CurrentTrack); } updateGameplayState(); GameplayClockContainer.FadeInFromZero(750, Easing.OutQuint); StartGameplay(); }
/// <summary> /// Called to trigger the starting of the gameplay clock and underlying gameplay. /// This will be called on entering the player screen once. A derived class may block the first call to this to delay the start of gameplay. /// </summary> protected virtual void StartGameplay() { if (GameplayClockContainer.GameplayClock.IsRunning) { throw new InvalidOperationException($"{nameof(StartGameplay)} should not be called when the gameplay clock is already running"); } GameplayClockContainer.Restart(); }
private void load(AudioManager audio, IAPIProvider api, OsuConfigManager config) { this.api = api; Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) { return; } IBeatmap playableBeatmap = loadPlayableBeatmap(); if (playableBeatmap == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); ScoreProcessor = ruleset.CreateScoreProcessor(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, Beatmap.Value); addOverlayComponents(GameplayClockContainer, Beatmap.Value); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); DrawableRuleset.OnNewResult += ScoreProcessor.ApplyResult; DrawableRuleset.OnRevertResult += ScoreProcessor.RevertResult; // Bind ScoreProcessor to ourselves ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } BreakOverlay.IsBreakTime.ValueChanged += _ => updatePauseOnFocusLostState(); }
private void performUserRequestedSkip() { // user requested skip // disable sample playback to stop currently playing samples and perform skip samplePlaybackDisabled.Value = true; GameplayClockContainer.Skip(); // return samplePlaybackDisabled.Value to what is defined by the beatmap's current state updateSampleDisabledState(); }
public void Pause() { if (!canPause) { return; } IsResuming = false; GameplayClockContainer.Stop(); PauseOverlay.Show(); lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime; }
public void Pause() { if (!canPause) { return; } if (IsResuming) { DrawableRuleset.CancelResume(); IsResuming = false; } GameplayClockContainer.Stop(); PauseOverlay.Show(); lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime; }
protected void SetGameplayStartTime(double time) { if (frameStablePlaybackResetDelegate?.Cancelled == false && !frameStablePlaybackResetDelegate.Completed) { frameStablePlaybackResetDelegate.RunTask(); } bool wasFrameStable = DrawableRuleset.FrameStablePlayback; DrawableRuleset.FrameStablePlayback = false; GameplayClockContainer.StartTime = time; GameplayClockContainer.Reset(); // Delay resetting frame-stable playback for one frame to give the FrameStabilityContainer a chance to seek. frameStablePlaybackResetDelegate = ScheduleAfterChildren(() => DrawableRuleset.FrameStablePlayback = wasFrameStable); }
private void load(AudioManager audio, IAPIProvider api, OsuConfigManager config) { this.api = api; Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); WorkingBeatmap working = loadBeatmap(); if (working == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); ScoreProcessor = DrawableRuleset.CreateScoreProcessor(); ScoreProcessor.Mods.BindTo(Mods); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime); addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, working); addOverlayComponents(GameplayClockContainer, working); DrawableRuleset.HasReplayLoaded.BindValueChanged(e => HUDOverlay.HoldToQuit.PauseOnFocusLost = !e.NewValue && PauseOnFocusLost, true); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); // Bind ScoreProcessor to ourselves ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } }
public bool OnPressed(GlobalAction action) { switch (action) { case GlobalAction.TogglePauseReplay: if (GameplayClockContainer.IsPaused.Value) { GameplayClockContainer.Start(); } else { GameplayClockContainer.Stop(); } return(true); } return(false); }
public override bool OnExiting(IScreen next) { screenSuspension?.Expire(); if (completionProgressDelegate != null && !completionProgressDelegate.Cancelled && !completionProgressDelegate.Completed) { // proceed to result screen if beatmap already finished playing completionProgressDelegate.RunTask(); return(true); } // GameplayClockContainer performs seeks / start / stop operations on the beatmap's track. // as we are no longer the current screen, we cannot guarantee the track is still usable. GameplayClockContainer?.StopUsingBeatmapClock(); musicController.ResetTrackAdjustments(); fadeOut(); return(base.OnExiting(next)); }
public void Pause() { if (!pausingSupportedByCurrentState) { return; } if (!IsResuming && pauseCooldownActive) { return; } if (IsResuming) { DrawableRuleset.CancelResume(); IsResuming = false; } GameplayClockContainer.Stop(); PauseOverlay.Show(); lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime; }
private bool onFail() { if (Mods.Value.OfType <IApplicableFailOverride>().Any(m => !m.AllowFail)) { return(false); } GameplayClockContainer.Stop(); HasFailed = true; // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) // could process an extra frame after the GameplayClock is stopped. // In such cases we want the fail state to precede a user triggered pause. if (PauseOverlay.State == Visibility.Visible) { PauseOverlay.Hide(); } FailOverlay.Retries = RestartCount; FailOverlay.Show(); return(true); }
public bool OnPressed(GlobalAction action) { const double keyboard_seek_amount = 5000; switch (action) { case GlobalAction.SeekReplayBackward: keyboardSeekDelegate?.Cancel(); keyboardSeekDelegate = this.BeginKeyRepeat(Scheduler, () => keyboardSeek(-1)); return(true); case GlobalAction.SeekReplayForward: keyboardSeekDelegate?.Cancel(); keyboardSeekDelegate = this.BeginKeyRepeat(Scheduler, () => keyboardSeek(1)); return(true); case GlobalAction.TogglePauseReplay: if (GameplayClockContainer.IsPaused.Value) { GameplayClockContainer.Start(); } else { GameplayClockContainer.Stop(); } return(true); } return(false); void keyboardSeek(int direction) { double target = Math.Clamp(GameplayClockContainer.CurrentTime + direction * keyboard_seek_amount, 0, GameplayBeatmap.HitObjects.Last().GetEndTime()); Seek(target); } }
public override bool OnExiting(IScreen next) { if (completionProgressDelegate != null && !completionProgressDelegate.Cancelled && !completionProgressDelegate.Completed) { // proceed to result screen if beatmap already finished playing completionProgressDelegate.RunTask(); return(true); } // ValidForResume is false when restarting if (ValidForResume) { if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) { // still want to block if we are within the cooldown period and not already paused. return(true); } } GameplayClockContainer.ResetLocalAdjustments(); fadeOut(); return(base.OnExiting(next)); }
private void load(AudioManager audio, OsuConfigManager config, OsuGameBase game) { var gameplayMods = Mods.Value.Select(m => m.DeepClone()).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) { return; } IBeatmap playableBeatmap = loadPlayableBeatmap(gameplayMods); if (playableBeatmap == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); if (game != null) { gameActive.BindTo(game.IsActive); } if (game is OsuGame osuGame) { LocalUserPlaying.BindTo(osuGame.LocalUserPlaying); } DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, gameplayMods); dependencies.CacheAs(DrawableRuleset); ScoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.Value = gameplayMods; dependencies.CacheAs(ScoreProcessor); HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); dependencies.CacheAs(HealthProcessor); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); Score = CreateScore(playableBeatmap); // ensure the score is in a consistent state with the current player. Score.ScoreInfo.BeatmapInfo = Beatmap.Value.BeatmapInfo; Score.ScoreInfo.Ruleset = ruleset.RulesetInfo; if (ruleset.RulesetInfo.ID != null) { Score.ScoreInfo.RulesetID = ruleset.RulesetInfo.ID.Value; } Score.ScoreInfo.Mods = gameplayMods; dependencies.CacheAs(GameplayState = new GameplayState(playableBeatmap, ruleset, gameplayMods, Score)); var rulesetSkinProvider = new RulesetSkinProvidingContainer(ruleset, playableBeatmap, Beatmap.Value.Skin); // load the skinning hierarchy first. // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. GameplayClockContainer.Add(rulesetSkinProvider); rulesetSkinProvider.AddRange(new Drawable[] { failAnimationLayer = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, Children = new[] { // underlay and gameplay should have access to the skinning sources. createUnderlayComponents(), createGameplayComponents(Beatmap.Value, playableBeatmap) } }, FailOverlay = new FailOverlay { OnRetry = Restart, OnQuit = () => PerformExit(true), }, new HotkeyExitOverlay { Action = () => { if (!this.IsCurrentScreen()) { return; } fadeOut(true); PerformExit(false); }, }, }); if (Configuration.AllowRestart) { rulesetSkinProvider.Add(new HotkeyRetryOverlay { Action = () => { if (!this.IsCurrentScreen()) { return; } fadeOut(true); Restart(); }, }); } // add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components. // also give the overlays the ruleset skin provider to allow rulesets to potentially override HUD elements (used to disable combo counters etc.) // we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there. failAnimationLayer.Add(createOverlayComponents(Beatmap.Value)); if (!DrawableRuleset.AllowGameplayOverlays) { HUDOverlay.ShowHud.Value = false; HUDOverlay.ShowHud.Disabled = true; BreakOverlay.Hide(); } DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting => { if (waiting.NewValue) { GameplayClockContainer.Stop(); } else { GameplayClockContainer.Start(); } }); DrawableRuleset.IsPaused.BindValueChanged(paused => { updateGameplayState(); updateSampleDisabledState(); }); DrawableRuleset.FrameStableClock.IsCatchingUp.BindValueChanged(_ => updateSampleDisabledState()); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState()); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); DrawableRuleset.NewResult += r => { HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); GameplayState.ApplyResult(r); }; DrawableRuleset.RevertResult += r => { HealthProcessor.RevertResult(r); ScoreProcessor.RevertResult(r); }; DimmableStoryboard.HasStoryboardEnded.ValueChanged += storyboardEnded => { if (storyboardEnded.NewValue) { progressToResults(true); } }; // Bind the judgement processors to ourselves ScoreProcessor.HasCompleted.BindValueChanged(scoreCompletionChanged); HealthProcessor.Failed += onFail; // Provide judgement processors to mods after they're loaded so that they're on the gameplay clock, // this is required for mods that apply transforms to these processors. ScoreProcessor.OnLoadComplete += _ => { foreach (var mod in gameplayMods.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } }; HealthProcessor.OnLoadComplete += _ => { foreach (var mod in gameplayMods.OfType <IApplicableToHealthProcessor>()) { mod.ApplyToHealthProcessor(HealthProcessor); } }; IsBreakTime.BindTo(breakTracker.IsBreakTime); IsBreakTime.BindValueChanged(onBreakTimeChanged, true); }
private Drawable createOverlayComponents(WorkingBeatmap working) { var container = new Container { RelativeSizeAxes = Axes.Both, Children = new[] { DimmableStoryboard.OverlayLayerContainer.CreateProxy(), BreakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Clock = DrawableRuleset.FrameStableClock, ProcessCustomClock = false, Breaks = working.Beatmap.Breaks }, // display the cursor above some HUD elements. DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), DrawableRuleset.ResumeOverlay?.CreateProxy() ?? new Container(), HUDOverlay = new HUDOverlay(ScoreProcessor, HealthProcessor, DrawableRuleset, Mods.Value) { HoldToQuit = { Action = performUserRequestedExit, IsPaused = { BindTarget = GameplayClockContainer.IsPaused } }, PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, KeyCounter = { AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded }, IsCounting = false }, RequestSeek = time => { GameplayClockContainer.Seek(time); GameplayClockContainer.Start(); }, Anchor = Anchor.Centre, Origin = Anchor.Centre }, skipOverlay = new SkipOverlay(DrawableRuleset.GameplayStartTime) { RequestSkip = GameplayClockContainer.Skip }, FailOverlay = new FailOverlay { OnRetry = Restart, OnQuit = performUserRequestedExit, }, PauseOverlay = new PauseOverlay { OnResume = Resume, Retries = RestartCount, OnRetry = Restart, OnQuit = performUserRequestedExit, }, new HotkeyExitOverlay { Action = () => { if (!this.IsCurrentScreen()) { return; } fadeOut(true); PerformExit(true); }, }, failAnimation = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, }, } }; if (!Configuration.AllowSkippingIntro) { skipOverlay.Expire(); } if (Configuration.AllowRestart) { container.Add(new HotkeyRetryOverlay { Action = () => { if (!this.IsCurrentScreen()) { return; } fadeOut(true); Restart(); }, }); } return(container); }
private void load(AudioManager audio, OsuConfigManager config, OsuGame game) { Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) { return; } IBeatmap playableBeatmap = loadPlayableBeatmap(); if (playableBeatmap == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); if (game != null) { LocalUserPlaying.BindTo(game.LocalUserPlaying); } DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); ScoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime); AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); dependencies.CacheAs(gameplayBeatmap); var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation // full access to all skin sources. var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap)); // load the skinning hierarchy first. // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. GameplayClockContainer.Add(beatmapSkinProvider.WithChild(rulesetSkinProvider)); rulesetSkinProvider.AddRange(new[] { // underlay and gameplay should have access the to skinning sources. createUnderlayComponents(), createGameplayComponents(Beatmap.Value, playableBeatmap) }); // also give the HUD a ruleset container to allow rulesets to potentially override HUD elements (used to disable combo counters etc.) // we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there. var hudRulesetContainer = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap)); // add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components. GameplayClockContainer.Add(hudRulesetContainer.WithChild(createOverlayComponents(Beatmap.Value))); if (!DrawableRuleset.AllowGameplayOverlays) { HUDOverlay.ShowHud.Value = false; HUDOverlay.ShowHud.Disabled = true; BreakOverlay.Hide(); skipOverlay.Hide(); } DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting => { if (waiting.NewValue) { GameplayClockContainer.Stop(); } else { GameplayClockContainer.Start(); } }); DrawableRuleset.IsPaused.BindValueChanged(paused => { updateGameplayState(); updateSampleDisabledState(); }); DrawableRuleset.FrameStableClock.IsCatchingUp.BindValueChanged(_ => updateSampleDisabledState()); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState()); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); DrawableRuleset.NewResult += r => { HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); gameplayBeatmap.ApplyResult(r); }; DrawableRuleset.RevertResult += r => { HealthProcessor.RevertResult(r); ScoreProcessor.RevertResult(r); }; // Bind the judgement processors to ourselves ScoreProcessor.HasCompleted.ValueChanged += updateCompletionState; HealthProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } foreach (var mod in Mods.Value.OfType <IApplicableToHealthProcessor>()) { mod.ApplyToHealthProcessor(HealthProcessor); } IsBreakTime.BindTo(breakTracker.IsBreakTime); IsBreakTime.BindValueChanged(onBreakTimeChanged, true); }
private void load(AudioManager audio, OsuConfigManager config) { Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) { return; } IBeatmap playableBeatmap = loadPlayableBeatmap(); if (playableBeatmap == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); ScoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); dependencies.CacheAs(gameplayBeatmap); addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, Beatmap.Value); addOverlayComponents(GameplayClockContainer, Beatmap.Value); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); DrawableRuleset.OnNewResult += r => { HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); }; DrawableRuleset.OnRevertResult += r => { HealthProcessor.RevertResult(r); ScoreProcessor.RevertResult(r); }; // Bind the judgement processors to ourselves ScoreProcessor.AllJudged += onCompletion; HealthProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } foreach (var mod in Mods.Value.OfType <IApplicableToHealthProcessor>()) { mod.ApplyToHealthProcessor(HealthProcessor); } breakTracker.IsBreakTime.BindValueChanged(onBreakTimeChanged, true); }
public ScreenSuspensionHandler([NotNull] GameplayClockContainer gameplayClockContainer) { this.gameplayClockContainer = gameplayClockContainer ?? throw new ArgumentNullException(nameof(gameplayClockContainer)); }
private void load(AudioManager audio, IAPIProvider api, OsuConfigManager config) { this.api = api; Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); WorkingBeatmap working = loadBeatmap(); if (working == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); showStoryboard = config.GetBindable <bool>(OsuSetting.ShowStoryboard); ScoreProcessor = DrawableRuleset.CreateScoreProcessor(); ScoreProcessor.Mods.BindTo(Mods); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime); GameplayClockContainer.Children = new[] { StoryboardContainer = CreateStoryboardContainer(), new ScalingContainer(ScalingMode.Gameplay) { Child = new LocalSkinOverrideContainer(working.Skin) { RelativeSizeAxes = Axes.Both, Child = DrawableRuleset } }, new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Breaks = working.Beatmap.Breaks }, // display the cursor above some HUD elements. DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, Mods.Value) { HoldToQuit = { Action = performUserRequestedExit, IsPaused = { BindTarget = GameplayClockContainer.IsPaused } }, PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, KeyCounter = { Visible = { BindTarget = DrawableRuleset.HasReplayLoaded } }, RequestSeek = GameplayClockContainer.Seek, Anchor = Anchor.Centre, Origin = Anchor.Centre }, new SkipOverlay(DrawableRuleset.GameplayStartTime) { RequestSeek = GameplayClockContainer.Seek }, FailOverlay = new FailOverlay { OnRetry = Restart, OnQuit = performUserRequestedExit, }, PauseOverlay = new PauseOverlay { OnResume = Resume, Retries = RestartCount, OnRetry = Restart, OnQuit = performUserRequestedExit, }, new HotkeyRetryOverlay { Action = () => { if (!this.IsCurrentScreen()) { return; } fadeOut(true); Restart(); }, }, new HotkeyExitOverlay { Action = () => { if (!this.IsCurrentScreen()) { return; } fadeOut(true); performUserRequestedExit(); }, }, failAnimation = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, } }; DrawableRuleset.HasReplayLoaded.BindValueChanged(e => HUDOverlay.HoldToQuit.PauseOnFocusLost = !e.NewValue && PauseOnFocusLost, true); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); // load storyboard as part of player's load if we can initializeStoryboard(false); // Bind ScoreProcessor to ourselves ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } }
/// <summary> /// Seek to a specific time in gameplay. /// </summary> /// <param name="time">The destination time to seek to.</param> public void Seek(double time) => GameplayClockContainer.Seek(time);