Beispiel #1
0
        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);
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        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));
        }
Beispiel #5
0
        // Called back when the transform finishes
        private void onFailComplete()
        {
            GameplayClockContainer.Stop();

            FailOverlay.Retries = RestartCount;
            FailOverlay.Show();
        }
Beispiel #6
0
        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;
            }
        }
Beispiel #7
0
        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);
            }
        }
Beispiel #8
0
        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;
            }
        }
Beispiel #9
0
        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));
        }
Beispiel #10
0
        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();
        }
Beispiel #11
0
        /// <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();
        }
Beispiel #12
0
        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();
        }
Beispiel #13
0
        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();
        }
Beispiel #14
0
        public void Pause()
        {
            if (!canPause)
            {
                return;
            }

            IsResuming = false;
            GameplayClockContainer.Stop();
            PauseOverlay.Show();
            lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime;
        }
Beispiel #15
0
        public void Pause()
        {
            if (!canPause)
            {
                return;
            }

            if (IsResuming)
            {
                DrawableRuleset.CancelResume();
                IsResuming = false;
            }

            GameplayClockContainer.Stop();
            PauseOverlay.Show();
            lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime;
        }
Beispiel #16
0
        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);
        }
Beispiel #17
0
        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);
            }
        }
Beispiel #18
0
        public bool OnPressed(GlobalAction action)
        {
            switch (action)
            {
            case GlobalAction.TogglePauseReplay:
                if (GameplayClockContainer.IsPaused.Value)
                {
                    GameplayClockContainer.Start();
                }
                else
                {
                    GameplayClockContainer.Stop();
                }
                return(true);
            }

            return(false);
        }
Beispiel #19
0
        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));
        }
Beispiel #20
0
        public void Pause()
        {
            if (!pausingSupportedByCurrentState)
            {
                return;
            }

            if (!IsResuming && pauseCooldownActive)
            {
                return;
            }

            if (IsResuming)
            {
                DrawableRuleset.CancelResume();
                IsResuming = false;
            }

            GameplayClockContainer.Stop();
            PauseOverlay.Show();
            lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime;
        }
Beispiel #21
0
        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);
        }
Beispiel #22
0
        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);
            }
        }
Beispiel #23
0
        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));
        }
Beispiel #24
0
        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);
        }
Beispiel #25
0
        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);
        }
Beispiel #26
0
        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);
        }
Beispiel #27
0
        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);
        }
Beispiel #28
0
 public ScreenSuspensionHandler([NotNull] GameplayClockContainer gameplayClockContainer)
 {
     this.gameplayClockContainer = gameplayClockContainer ?? throw new ArgumentNullException(nameof(gameplayClockContainer));
 }
Beispiel #29
0
        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);
            }
        }
Beispiel #30
0
 /// <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);