Exemplo n.º 1
0
        public GameplayClockContainer(BeatmapMeta beatmap, double gameplayStartTime)
        {
            this.beatmap           = beatmap;
            this.gameplayStartTime = gameplayStartTime;

            RelativeSizeAxes = Axes.Both;

            sourceClock = (IAdjustableClock)beatmap.Song ?? new StopwatchClock();
            (sourceClock as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);

            adjustableClock = new DecoupleableInterpolatingFramedClock {
                IsCoupled = false
            };

            platformOffsetClock = new FramedOffsetClock(adjustableClock)
            {
                Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0
            };

            // the final usable gameplay clock with user-set offsets applied.
            userOffsetClock = new FramedOffsetClock(platformOffsetClock);

            // the clock to be exposed via DI to children.
            GameplayClock = new GameplayClock(userOffsetClock);

            GameplayClock.IsPaused.BindTo(IsPaused);
        }
Exemplo n.º 2
0
        public GameplayClockContainer(WorkingBeatmap beatmap, double gameplayStartTime)
        {
            this.beatmap = beatmap;

            RelativeSizeAxes = Axes.Both;

            sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock();

            adjustableClock = new DecoupleableInterpolatingFramedClock {
                IsCoupled = false
            };

            adjustableClock.Seek(Math.Min(0, gameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn));

            adjustableClock.ProcessFrame();

            // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited.
            // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
            var platformOffsetClock = new FramedOffsetClock(adjustableClock)
            {
                Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0
            };

            // the final usable gameplay clock with user-set offsets applied.
            offsetClock = new FramedOffsetClock(platformOffsetClock);

            // the clock to be exposed via DI to children.
            GameplayClock = new GameplayClock(offsetClock);

            GameplayClock.IsPaused.BindTo(IsPaused);
        }
        /// <summary>
        /// Creates a new <see cref="GameplayClockContainer"/>.
        /// </summary>
        /// <param name="beatmap">The beatmap being played.</param>
        /// <param name="gameplayStartTime">The suggested time to start gameplay at.</param>
        /// <param name="startAtGameplayStart">
        /// Whether <paramref name="gameplayStartTime"/> should be used regardless of when storyboard events and hitobjects are supposed to start.
        /// </param>
        public GameplayClockContainer(WorkingBeatmap beatmap, double gameplayStartTime, bool startAtGameplayStart = false)
        {
            this.beatmap              = beatmap;
            this.gameplayStartTime    = gameplayStartTime;
            this.startAtGameplayStart = startAtGameplayStart;
            track = beatmap.Track;

            firstHitObjectTime = beatmap.Beatmap.HitObjects.First().StartTime;

            RelativeSizeAxes = Axes.Both;

            adjustableClock = new DecoupleableInterpolatingFramedClock {
                IsCoupled = false
            };

            // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited.
            // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
            platformOffsetClock = new HardwareCorrectionOffsetClock(adjustableClock)
            {
                Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 15 : 0
            };

            // the final usable gameplay clock with user-set offsets applied.
            userOffsetClock = new HardwareCorrectionOffsetClock(platformOffsetClock);

            // the clock to be exposed via DI to children.
            localGameplayClock = new LocalGameplayClock(userOffsetClock);

            GameplayClock.IsPaused.BindTo(IsPaused);
        }
Exemplo n.º 4
0
        public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList <Mod> mods, double gameplayStartTime)
        {
            this.beatmap           = beatmap;
            this.mods              = mods;
            this.gameplayStartTime = gameplayStartTime;
            firstHitObjectTime     = beatmap.Beatmap.HitObjects.First().StartTime;

            RelativeSizeAxes = Axes.Both;

            sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock();
            (sourceClock as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);

            adjustableClock = new DecoupleableInterpolatingFramedClock {
                IsCoupled = false
            };

            // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited.
            // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
            platformOffsetClock = new FramedOffsetClock(adjustableClock)
            {
                Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0
            };

            // the final usable gameplay clock with user-set offsets applied.
            userOffsetClock = new FramedOffsetClock(platformOffsetClock);

            // the clock to be exposed via DI to children.
            GameplayClock = new GameplayClock(userOffsetClock);

            GameplayClock.IsPaused.BindTo(IsPaused);
        }
Exemplo n.º 5
0
            protected override void LoadComplete()
            {
                base.LoadComplete();

                if (timeReference != null)
                {
                    Clock = new FramedOffsetClock(timeReference.Clock)
                    {
                        Offset = -timeReference.AnimationStartTime
                    }
                }
                ;
            }
        }
Exemplo n.º 6
0
        protected override GameplayClock CreateGameplayClock(IFrameBasedClock source)
        {
            // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited.
            // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
            platformOffsetClock = new HardwareCorrectionOffsetClock(source)
            {
                Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 15 : 0
            };

            // the final usable gameplay clock with user-set offsets applied.
            userOffsetClock = new HardwareCorrectionOffsetClock(platformOffsetClock);

            return(masterGameplayClock = new MasterGameplayClock(userOffsetClock));
        }
Exemplo n.º 7
0
        public RhythmBoxClockContainer(double GamplayStartTime)
        {
            this.GamplayStartTime = GamplayStartTime;

            adjustableClock = new StopwatchClock();
            (adjustableClock as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);

            decoupleableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true };

            decoupleableClock.ChangeSource(adjustableClock);

            //TODO:
            platformOffsetClock = new FramedOffsetClock(decoupleableClock) { Offset = 0 };

            userOffsetClock = new FramedOffsetClock(platformOffsetClock) { Offset = 0 };

            RhythmBoxClock = new RhythmBoxClock(userOffsetClock);

            RhythmBoxClock.IsPaused.BindTo(IsPaused);
        }
Exemplo n.º 8
0
        private void load(AudioManager audio, OsuConfigManager config, APIAccess api)
        {
            this.api = api;

            dimLevel       = config.GetBindable <double>(OsuSetting.DimLevel);
            showStoryboard = config.GetBindable <bool>(OsuSetting.ShowStoryboard);

            mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel);

            sampleRestart = audio.Sample.Get(@"Gameplay/restart");

            WorkingBeatmap working = Beatmap.Value;
            Beatmap        beatmap;

            try
            {
                beatmap = working.Beatmap;

                if (beatmap == null)
                {
                    throw new InvalidOperationException("Beatmap was not loaded");
                }

                ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset;
                var rulesetInstance = ruleset.CreateInstance();

                try
                {
                    RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working, ruleset.ID == beatmap.BeatmapInfo.Ruleset.ID);
                }
                catch (BeatmapInvalidForRulesetException)
                {
                    // we may fail to create a RulesetContainer if the beatmap cannot be loaded with the user's preferred ruleset
                    // let's try again forcing the beatmap's ruleset.
                    ruleset          = beatmap.BeatmapInfo.Ruleset;
                    rulesetInstance  = ruleset.CreateInstance();
                    RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap, true);
                }

                if (!RulesetContainer.Objects.Any())
                {
                    throw new InvalidOperationException("Beatmap contains no hit objects!");
                }
            }
            catch (Exception e)
            {
                Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error);

                //couldn't load, hard abort!
                Exit();
                return;
            }

            adjustableSourceClock = (IAdjustableClock)working.Track ?? new StopwatchClock();
            decoupledClock        = new DecoupleableInterpolatingFramedClock {
                IsCoupled = false
            };

            var firstObjectTime = RulesetContainer.Objects.First().StartTime;

            decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, beatmap.BeatmapInfo.AudioLeadIn)));
            decoupledClock.ProcessFrame();

            offsetClock = new FramedOffsetClock(decoupledClock);

            userAudioOffset = config.GetBindable <double>(OsuSetting.AudioOffset);
            userAudioOffset.ValueChanged += v => offsetClock.Offset = v;
            userAudioOffset.TriggerChange();

            Children = new Drawable[]
            {
                storyboardContainer = new Container
                {
                    RelativeSizeAxes = Axes.Both,
                    Clock            = offsetClock,
                    Alpha            = 0,
                },
                pauseContainer = new PauseContainer
                {
                    AudioClock    = decoupledClock,
                    FramedClock   = offsetClock,
                    OnRetry       = Restart,
                    OnQuit        = Exit,
                    CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded,
                    Retries       = RestartCount,
                    OnPause       = () => {
                        hudOverlay.KeyCounter.IsCounting = pauseContainer.IsPaused;
                    },
                    OnResume = () => {
                        hudOverlay.KeyCounter.IsCounting = true;
                    },
                    Children = new Drawable[]
                    {
                        new SkipButton(firstObjectTime)
                        {
                            AudioClock = decoupledClock
                        },
                        new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Clock            = offsetClock,
                            Child            = RulesetContainer,
                        },
                        hudOverlay = new HUDOverlay
                        {
                            Anchor = Anchor.Centre,
                            Origin = Anchor.Centre
                        },
                        breakOverlay = new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks)
                        {
                            Anchor = Anchor.Centre,
                            Origin = Anchor.Centre,
                            Clock  = decoupledClock,
                            Breaks = beatmap.Breaks
                        },
                    }
                },
                failOverlay = new FailOverlay
                {
                    OnRetry = Restart,
                    OnQuit  = Exit,
                },
                new HotkeyRetryOverlay
                {
                    Action = () => {
                        //we want to hide the hitrenderer immediately (looks better).
                        //we may be able to remove this once the mouse cursor trail is improved.
                        RulesetContainer?.Hide();
                        Restart();
                    },
                }
            };

            scoreProcessor = RulesetContainer.CreateScoreProcessor();

            if (showStoryboard)
            {
                initializeStoryboard(false);
            }

            hudOverlay.BindProcessor(scoreProcessor);
            hudOverlay.BindRulesetContainer(RulesetContainer);

            hudOverlay.Progress.Objects      = RulesetContainer.Objects;
            hudOverlay.Progress.AudioClock   = decoupledClock;
            hudOverlay.Progress.AllowSeeking = RulesetContainer.HasReplayLoaded;
            hudOverlay.Progress.OnSeek       = pos => decoupledClock.Seek(pos);

            hudOverlay.ModDisplay.Current.BindTo(working.Mods);

            breakOverlay.BindProcessor(scoreProcessor);

            hudOverlay.ReplaySettingsOverlay.PlaybackSettings.AdjustableClock = adjustableSourceClock;

            // Bind ScoreProcessor to ourselves
            scoreProcessor.AllJudged += onCompletion;
            scoreProcessor.Failed    += onFail;

            foreach (var mod in Beatmap.Value.Mods.Value.OfType <IApplicableToScoreProcessor>())
            {
                mod.ApplyToScoreProcessor(scoreProcessor);
            }
        }
Exemplo n.º 9
0
        private async Task load(AudioManager audio, APIAccess api, OsuConfigManager config)
        {
            this.api = api;

            WorkingBeatmap working = Beatmap.Value;

            if (working is DummyWorkingBeatmap)
            {
                return;
            }

            sampleRestart = await audio.Sample.GetAsync(@"Gameplay/restart");

            mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel);
            userAudioOffset    = config.GetBindable <double>(OsuSetting.AudioOffset);

            IBeatmap beatmap;

            try
            {
                beatmap = working.Beatmap;

                if (beatmap == null)
                {
                    throw new InvalidOperationException("Beatmap was not loaded");
                }

                ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset;
                var rulesetInstance = ruleset.CreateInstance();

                try
                {
                    RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working);
                }
                catch (BeatmapInvalidForRulesetException)
                {
                    // we may fail to create a RulesetContainer if the beatmap cannot be loaded with the user's preferred ruleset
                    // let's try again forcing the beatmap's ruleset.
                    ruleset          = beatmap.BeatmapInfo.Ruleset;
                    rulesetInstance  = ruleset.CreateInstance();
                    RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap.Value);
                }

                if (!RulesetContainer.Objects.Any())
                {
                    Logger.Log("Beatmap contains no hit objects!", level: LogLevel.Error);
                    return;
                }
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap sucessfully!");
                //couldn't load, hard abort!
                return;
            }

            sourceClock     = (IAdjustableClock)working.Track ?? new StopwatchClock();
            adjustableClock = new DecoupleableInterpolatingFramedClock {
                IsCoupled = false
            };

            adjustableClock.Seek(AllowLeadIn
                ? Math.Min(0, RulesetContainer.GameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn)
                : RulesetContainer.GameplayStartTime);

            adjustableClock.ProcessFrame();

            // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited.
            // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck.
            var platformOffsetClock = new FramedOffsetClock(adjustableClock)
            {
                Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0
            };

            // the final usable gameplay clock with user-set offsets applied.
            var offsetClock = new FramedOffsetClock(platformOffsetClock);

            userAudioOffset.ValueChanged += v => offsetClock.Offset = v;
            userAudioOffset.TriggerChange();

            ScoreProcessor = RulesetContainer.CreateScoreProcessor();
            if (!ScoreProcessor.Mode.Disabled)
            {
                config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode);
            }

            Children = new Drawable[]
            {
                pauseContainer = new PauseContainer(offsetClock, adjustableClock)
                {
                    Retries       = RestartCount,
                    OnRetry       = Restart,
                    OnQuit        = Exit,
                    CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded,
                    Children      = new[]
                    {
                        storyboardContainer = new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Alpha            = 0,
                        },
                        new LocalSkinOverrideContainer(working.Skin)
                        {
                            RelativeSizeAxes = Axes.Both,
                            Child            = RulesetContainer
                        },
                        new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor)
                        {
                            Anchor             = Anchor.Centre,
                            Origin             = Anchor.Centre,
                            ProcessCustomClock = false,
                            Breaks             = beatmap.Breaks
                        },
                        RulesetContainer.Cursor?.CreateProxy() ?? new Container(),
                        hudOverlay = new HUDOverlay(ScoreProcessor, RulesetContainer, working, offsetClock, adjustableClock)
                        {
                            Clock = Clock, // hud overlay doesn't want to use the audio clock directly
                            ProcessCustomClock = false,
                            Anchor             = Anchor.Centre,
                            Origin             = Anchor.Centre
                        },
                        new SkipOverlay(RulesetContainer.GameplayStartTime)
                        {
                            Clock = Clock, // skip button doesn't want to use the audio clock directly
                            ProcessCustomClock = false,
                            AdjustableClock    = adjustableClock,
                            FramedClock        = offsetClock,
                        },
                    }
                },
                failOverlay = new FailOverlay
                {
                    OnRetry = Restart,
                    OnQuit  = Exit,
                },
                new HotkeyRetryOverlay
                {
                    Action = () =>
                    {
                        if (!IsCurrentScreen)
                        {
                            return;
                        }

                        fadeOut(true);
                        Restart();
                    },
                }
            };

            hudOverlay.HoldToQuit.Action = Exit;
            hudOverlay.KeyCounter.Visible.BindTo(RulesetContainer.HasReplayLoaded);

            RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused);

            if (ShowStoryboard)
            {
                initializeStoryboard(false);
            }

            // Bind ScoreProcessor to ourselves
            ScoreProcessor.AllJudged += onCompletion;
            ScoreProcessor.Failed    += onFail;

            foreach (var mod in Beatmap.Value.Mods.Value.OfType <IApplicableToScoreProcessor>())
            {
                mod.ApplyToScoreProcessor(ScoreProcessor);
            }
        }
 public LocalGameplayClock(FramedOffsetClock underlyingClock)
     : base(underlyingClock)
 {
 }
Exemplo n.º 11
0
        private void load(AudioManager audio, APIAccess api, OsuConfigManager config)
        {
            this.api = api;

            WorkingBeatmap working = Beatmap.Value;

            if (working is DummyWorkingBeatmap)
            {
                return;
            }

            sampleRestart = audio.Sample.Get(@"Gameplay/restart");

            mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel);
            userAudioOffset    = config.GetBindable <double>(OsuSetting.AudioOffset);

            Beatmap beatmap;

            try
            {
                beatmap = working.Beatmap;

                if (beatmap == null)
                {
                    throw new InvalidOperationException("Beatmap was not loaded");
                }

                ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset;
                var rulesetInstance = ruleset.CreateInstance();

                try
                {
                    RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working, ruleset.ID == beatmap.BeatmapInfo.Ruleset.ID);
                }
                catch (BeatmapInvalidForRulesetException)
                {
                    // we may fail to create a RulesetContainer if the beatmap cannot be loaded with the user's preferred ruleset
                    // let's try again forcing the beatmap's ruleset.
                    ruleset          = beatmap.BeatmapInfo.Ruleset;
                    rulesetInstance  = ruleset.CreateInstance();
                    RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap, true);
                }

                if (!RulesetContainer.Objects.Any())
                {
                    Logger.Error(new InvalidOperationException("Beatmap contains no hit objects!"), "Beatmap contains no hit objects!");
                    return;
                }
            }
            catch (Exception e)
            {
                Logger.Error(e, "Could not load beatmap sucessfully!");
                //couldn't load, hard abort!
                return;
            }

            sourceClock     = (IAdjustableClock)working.Track ?? new StopwatchClock();
            adjustableClock = new DecoupleableInterpolatingFramedClock {
                IsCoupled = false
            };

            var firstObjectTime = RulesetContainer.Objects.First().StartTime;

            adjustableClock.Seek(AllowLeadIn
                ? Math.Min(0, firstObjectTime - Math.Max(beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, beatmap.BeatmapInfo.AudioLeadIn))
                : firstObjectTime);

            adjustableClock.ProcessFrame();

            // the final usable gameplay clock with user-set offsets applied.
            var offsetClock = new FramedOffsetClock(adjustableClock);

            userAudioOffset.ValueChanged += v => offsetClock.Offset = v;
            userAudioOffset.TriggerChange();

            scoreProcessor = RulesetContainer.CreateScoreProcessor();

            Children = new Drawable[]
            {
                pauseContainer = new PauseContainer(offsetClock, adjustableClock)
                {
                    OnRetry       = Restart,
                    OnQuit        = Exit,
                    CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded,
                    OnPause       = () =>
                    {
                        pauseContainer.Retries           = RestartCount;
                        hudOverlay.KeyCounter.IsCounting = pauseContainer.IsPaused;
                    },
                    OnResume = () => hudOverlay.KeyCounter.IsCounting = true,
                    Children = new Drawable[]
                    {
                        storyboardContainer = new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Alpha            = 0,
                        },
                        new LocalSkinOverrideContainer(working.Skin)
                        {
                            RelativeSizeAxes = Axes.Both,
                            Child            = RulesetContainer
                        },
                        new SkipOverlay(firstObjectTime)
                        {
                            Clock = Clock, // skip button doesn't want to use the audio clock directly
                            ProcessCustomClock = false,
                            AdjustableClock    = adjustableClock,
                            FramedClock        = offsetClock,
                        },
                        hudOverlay = new HUDOverlay(scoreProcessor, RulesetContainer, working, offsetClock, adjustableClock)
                        {
                            Clock = Clock, // hud overlay doesn't want to use the audio clock directly
                            ProcessCustomClock = false,
                            Anchor             = Anchor.Centre,
                            Origin             = Anchor.Centre
                        },
                        new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, scoreProcessor)
                        {
                            Anchor             = Anchor.Centre,
                            Origin             = Anchor.Centre,
                            ProcessCustomClock = false,
                            Breaks             = beatmap.Breaks
                        }
                    }
                },
                failOverlay = new FailOverlay
                {
                    OnRetry = Restart,
                    OnQuit  = Exit,
                },
                new HotkeyRetryOverlay
                {
                    Action = () =>
                    {
                        if (!IsCurrentScreen)
                        {
                            return;
                        }

                        //we want to hide the hitrenderer immediately (looks better).
                        //we may be able to remove this once the mouse cursor trail is improved.
                        RulesetContainer?.Hide();
                        Restart();
                    },
                }
            };

            if (ShowStoryboard)
            {
                initializeStoryboard(false);
            }

            // Bind ScoreProcessor to ourselves
            scoreProcessor.AllJudged += onCompletion;
            scoreProcessor.Failed    += onFail;

            foreach (var mod in Beatmap.Value.Mods.Value.OfType <IApplicableToScoreProcessor>())
            {
                mod.ApplyToScoreProcessor(scoreProcessor);
            }
        }
Exemplo n.º 12
0
        private void load(AudioManager audio, OsuConfigManager config, OsuGame osu)
        {
            dimLevel           = config.GetBindable <double>(OsuSetting.DimLevel);
            mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel);

            sampleRestart = audio.Sample.Get(@"Gameplay/restart");

            Ruleset rulesetInstance;

            try
            {
                if (Beatmap.Value.Beatmap == null)
                {
                    throw new InvalidOperationException("Beatmap was not loaded");
                }

                ruleset         = osu?.Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset;
                rulesetInstance = ruleset.CreateInstance();

                try
                {
                    HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap, ruleset.ID == Beatmap.Value.BeatmapInfo.Ruleset.ID);
                }
                catch (BeatmapInvalidForRulesetException)
                {
                    // we may fail to create a HitRenderer if the beatmap cannot be loaded with the user's preferred ruleset
                    // let's try again forcing the beatmap's ruleset.
                    ruleset         = Beatmap.Value.BeatmapInfo.Ruleset;
                    rulesetInstance = ruleset.CreateInstance();
                    HitRenderer     = rulesetInstance.CreateHitRendererWith(Beatmap, true);
                }

                if (!HitRenderer.Objects.Any())
                {
                    throw new InvalidOperationException("Beatmap contains no hit objects!");
                }
            }
            catch (Exception e)
            {
                Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error);

                //couldn't load, hard abort!
                Exit();
                return;
            }

            Track track = Beatmap.Value.Track;

            if (track != null)
            {
                adjustableSourceClock = track;
            }

            adjustableSourceClock = (IAdjustableClock)track ?? new StopwatchClock();

            decoupledClock = new DecoupleableInterpolatingFramedClock {
                IsCoupled = false
            };

            var firstObjectTime = HitRenderer.Objects.First().StartTime;

            decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, Beatmap.Value.BeatmapInfo.AudioLeadIn)));
            decoupledClock.ProcessFrame();

            offsetClock = new FramedOffsetClock(decoupledClock);

            userAudioOffset = config.GetBindable <double>(OsuSetting.AudioOffset);
            userAudioOffset.ValueChanged += v => offsetClock.Offset = v;
            userAudioOffset.TriggerChange();

            Schedule(() =>
            {
                adjustableSourceClock.Reset();

                foreach (var mod in Beatmap.Value.Mods.Value.OfType <IApplicableToClock>())
                {
                    mod.ApplyToClock(adjustableSourceClock);
                }

                decoupledClock.ChangeSource(adjustableSourceClock);
            });

            Children = new Drawable[]
            {
                pauseContainer = new PauseContainer
                {
                    AudioClock    = decoupledClock,
                    FramedClock   = offsetClock,
                    OnRetry       = Restart,
                    OnQuit        = Exit,
                    CheckCanPause = () => ValidForResume && !HasFailed && !HitRenderer.HasReplayLoaded,
                    Retries       = RestartCount,
                    OnPause       = () => {
                        hudOverlay.KeyCounter.IsCounting = pauseContainer.IsPaused;
                    },
                    OnResume = () => {
                        hudOverlay.KeyCounter.IsCounting = true;
                    },
                    Children = new Drawable[]
                    {
                        new SkipButton(firstObjectTime)
                        {
                            AudioClock = decoupledClock
                        },
                        new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Clock            = offsetClock,
                            Children         = new Drawable[]
                            {
                                HitRenderer,
                            }
                        },
                        hudOverlay = new HUDOverlay
                        {
                            Anchor = Anchor.Centre,
                            Origin = Anchor.Centre
                        },
                    }
                },
                failOverlay = new FailOverlay
                {
                    OnRetry = Restart,
                    OnQuit  = Exit,
                },
                new HotkeyRetryOverlay
                {
                    Action = () => {
                        //we want to hide the hitrenderer immediately (looks better).
                        //we may be able to remove this once the mouse cursor trail is improved.
                        HitRenderer?.Hide();
                        Restart();
                    },
                }
            };

            scoreProcessor = HitRenderer.CreateScoreProcessor();

            hudOverlay.KeyCounter.AddRange(rulesetInstance.CreateGameplayKeys());
            hudOverlay.BindProcessor(scoreProcessor);
            hudOverlay.BindHitRenderer(HitRenderer);

            hudOverlay.Progress.Objects      = HitRenderer.Objects;
            hudOverlay.Progress.AudioClock   = decoupledClock;
            hudOverlay.Progress.AllowSeeking = HitRenderer.HasReplayLoaded;
            hudOverlay.Progress.OnSeek       = pos => decoupledClock.Seek(pos);

            hudOverlay.ModDisplay.Current.BindTo(Beatmap.Value.Mods);

            //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation)
            HitRenderer.OnAllJudged += onCompletion;

            //bind ScoreProcessor to ourselves (for a fail situation)
            scoreProcessor.Failed += onFail;
        }
Exemplo n.º 13
0
 public MasterGameplayClock(FramedOffsetClock underlyingClock)
     : base(underlyingClock)
 {
 }
Exemplo n.º 14
0
        public override void Reset()
        {
            base.Reset();

            //ensure we are at offset 0
            if (localClock == null)
            {
                localClock = new FramedOffsetClock(base.Clock);
            }
            localClock.Offset = -base.Clock.CurrentTime;

            List <HitObject> objects = new List <HitObject>();

            int time = 500;

            for (int i = 0; i < 100; i++)
            {
                objects.Add(new Circle()
                {
                    StartTime = time,
                    Position  = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384))
                });

                time += RNG.Next(50, 500);
            }

            Beatmap beatmap = new Beatmap
            {
                HitObjects = objects
            };

            Add(new Drawable[]
            {
                new OsuHitRenderer
                {
                    Objects = beatmap.HitObjects,
                    Scale   = new Vector2(0.5f),
                    Anchor  = Anchor.TopLeft,
                    Origin  = Anchor.TopLeft
                },
                new TaikoHitRenderer
                {
                    Objects = beatmap.HitObjects,
                    Scale   = new Vector2(0.5f),
                    Anchor  = Anchor.TopRight,
                    Origin  = Anchor.TopRight
                },
                new CatchHitRenderer
                {
                    Objects = beatmap.HitObjects,
                    Scale   = new Vector2(0.5f),
                    Anchor  = Anchor.BottomLeft,
                    Origin  = Anchor.BottomLeft
                },
                new ManiaHitRenderer
                {
                    Objects = beatmap.HitObjects,
                    Scale   = new Vector2(0.5f),
                    Anchor  = Anchor.BottomRight,
                    Origin  = Anchor.BottomRight
                }
            });
        }