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); }
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); }
public PauseContainer(FramedClock framedClock, IAdjustableClock adjustableClock) { this.framedClock = framedClock; this.adjustableClock = adjustableClock; RelativeSizeAxes = Axes.Both; AddInternal(content = new Container { Clock = this.framedClock, ProcessCustomClock = false, RelativeSizeAxes = Axes.Both }); AddInternal(pauseOverlay = new PauseOverlay { OnResume = () => { IsResuming = true; this.Delay(400).Schedule(Resume); }, OnRetry = () => OnRetry(), OnQuit = () => OnQuit(), }); }
private void load(IBindable <WorkingBeatmap> beatmap, IAdjustableClock adjustableClock, OsuColour colours) { this.adjustableClock = adjustableClock; Child = waveform = new WaveformGraph { RelativeSizeAxes = Axes.Both, Colour = colours.Blue.Opacity(0.2f), LowColour = colours.BlueLighter, MidColour = colours.BlueDark, HighColour = colours.BlueDarker, Depth = float.MaxValue }; // We don't want the centre marker to scroll AddInternal(new CentreMarker()); WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); Beatmap.BindTo(beatmap); Beatmap.BindValueChanged(b => { waveform.Waveform = b.Waveform; track = b.Track; }, true); }
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); }
protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); removeSourceClockAdjustments(); sourceClock = null; }
private void load(OsuColour colours, IAdjustableClock adjustableClock) { Children = new Drawable[] { new MarkerPart(adjustableClock) { RelativeSizeAxes = Axes.Both }, new ControlPointPart { Anchor = Anchor.Centre, Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, Height = 0.35f }, new BookmarkPart { Anchor = Anchor.Centre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Both, Height = 0.35f }, new Container { RelativeSizeAxes = Axes.Both, Colour = colours.Gray5, Children = new Drawable[] { new Circle { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, Size = new Vector2(5) }, new Box { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, RelativeSizeAxes = Axes.X, Height = 1, EdgeSmoothness = new Vector2(0, 1), }, new Circle { Anchor = Anchor.CentreRight, Origin = Anchor.CentreLeft, Size = new Vector2(5) }, } }, new BreakPart { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, Height = 0.25f } }; }
private void load(IBindableBeatmap beatmap, IAdjustableClock clock) { this.beatmap.BindTo(beatmap); EditorClock = clock; ApplyDefaultsToHitObject(); }
/* * protected override void SpellUpdate() * { * base.SpellUpdate(); * * if (SpellEndTime >= Time.Current) * if (!SpellActive) * { * currentRate += (float)Clock.ElapsedFrameTime / 100; * if (currentRate > originalRate) * currentRate = originalRate; * applyToClock(workingBeatmap.Value.Track, currentRate); * if (currentRate > 0 && SpellEndTime - 500 <= Time.Current) * { * currentRate = originalRate; * applyToClock(workingBeatmap.Value.Track, currentRate); * } * else if (currentRate < 0 && SpellEndTime + 500 >= Time.Current) * { * currentRate = originalRate; * applyToClock(workingBeatmap.Value.Track, currentRate); * } * } * else * { * double energyDrainMultiplier = 0; * if (currentRate < 1) * energyDrainMultiplier = originalRate - currentRate; * else if (currentRate >= 1) * energyDrainMultiplier = currentRate - originalRate; * * Energy -= (Clock.ElapsedFrameTime / 1000) * (1 / currentRate) * energyDrainMultiplier * TouhosuPlayer.EnergyDrainRate; * * if (currentRate > 0) * SpellEndTime = Time.Current + 2000; * else * SpellEndTime = Time.Current - 2000; * * currentRate = originalRate * SetRate; * applyToClock(workingBeatmap.Value.Track, currentRate); * } * } */ // ReSharper disable once UnusedMember.Local private void applyToClock(IAdjustableClock clock, double speed) { if (clock is IHasPitchAdjust pitchAdjust) { pitchAdjust.PitchAdjust = speed; } SpeedMultiplier = 1 / speed; }
public virtual void ApplyToClock(IAdjustableClock clock) { this.clock = clock; lastAdjust = 1; // for preview purposes. during gameplay, Update will overwrite this setting. applyAdjustment(1); }
/// <summary> /// Changes the backing clock to avoid using the originally provided beatmap's track. /// </summary> public void StopUsingBeatmapClock() { if (sourceClock != beatmap.Track) { return; } sourceClock = new TrackVirtual(beatmap.Track.Length); adjustableClock.ChangeSource(sourceClock); }
public override void ApplyToClock(IAdjustableClock clock) { if (clock is IHasPitchAdjust pitchAdjust) { pitchAdjust.PitchAdjust = 0.75; } else { base.ApplyToClock(clock); } }
public virtual void ApplyToClock(IAdjustableClock clock) { if (clock is IHasTempoAdjust tempo) { tempo.TempoAdjust *= RateAdjust; } else { clock.Rate *= RateAdjust; } }
public override void ApplyToClock(IAdjustableClock clock) { var pitchAdjust = clock as IHasPitchAdjust; if (pitchAdjust != null) { pitchAdjust.PitchAdjust = 0.75; } else { base.ApplyToClock(clock); } }
public override void ApplyToClock(IAdjustableClock clock) { var pitchAdjust = clock as IHasPitchAdjust; if (pitchAdjust != null) { pitchAdjust.PitchAdjust = (KyzerBooleans.CanOverrideNightcore ? KyzerSpeedOverrides.SpeedDoubleTime : 1.5); } else { base.ApplyToClock(clock); } }
private void load() { IAdjustableClock sourceClock = (IAdjustableClock)beatmap.Value.Song ?? new StopwatchClock(); clock = new EditorClock(beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); beatmap.Value.Song.Looping = true; dependencies.CacheAs <IFrameBasedClock>(clock); dependencies.CacheAs <IAdjustableClock>(clock); dependencies.Cache(beatDivisor); BeatmapMetadataOverlay beatmapOverlay; InternalChildren = new Drawable[] { new Container { Name = "Screen container", RelativeSizeAxes = Axes.Both, Child = new Container { RelativeSizeAxes = Axes.Both, Masking = true } }, trackTimer = new SpriteText { Font = RhythmicFont.Default }, beatmapOverlay = new BeatmapMetadataOverlay { RelativeSizeAxes = Axes.Both, Size = new Vector2(0.6f, 0.8f), Anchor = Anchor.Centre, Origin = Anchor.Centre } }; beatmapOverlay.ToggleVisibility(); }
private void load(IAdjustableClock adjustableClock) { this.adjustableClock = adjustableClock; PlaybackTabControl tabs; Children = new Drawable[] { playButton = new IconButton { Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, Scale = new Vector2(1.4f), IconScale = new Vector2(1.4f), Icon = FontAwesome.fa_play_circle_o, Action = togglePause, Padding = new MarginPadding { Left = 20 } }, new OsuSpriteText { Origin = Anchor.BottomLeft, Text = "Playback speed", RelativePositionAxes = Axes.Y, Y = 0.5f, Padding = new MarginPadding { Left = 45 } }, new Container { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, Height = 0.5f, Padding = new MarginPadding { Left = 45 }, Child = tabs = new PlaybackTabControl(), } }; tabs.Current.ValueChanged += newValue => Beatmap.Value.Track.Tempo.Value = newValue; }
private void load(IAdjustableClock adjustableClock) { this.adjustableClock = adjustableClock; Children = new Drawable[] { playButton = new IconButton { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Scale = new Vector2(1.4f), IconScale = new Vector2(1.4f), Icon = FontAwesome.Regular.PlayCircle, Action = togglePause, }, new OsuSpriteText { Origin = Anchor.BottomLeft, Text = "Playback speed", RelativePositionAxes = Axes.Y, Y = 0.5f, Padding = new MarginPadding { Left = 45 } }, new Container { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, Height = 0.5f, Padding = new MarginPadding { Left = 45 }, Child = new PlaybackTabControl { Current = tempo }, } }; Track?.AddAdjustment(AdjustableProperty.Tempo, tempo); }
// ReSharper disable once UnusedMember.Local private void applyToClock(IAdjustableClock clock, double pitch) { if (clock is IHasPitchAdjust pitchAdjust) { pitchAdjust.PitchAdjust = pitch; if (setPitch > 1) { clock.Rate = 1 - (pitch - 1) / 2; } else if (setPitch < 1) { clock.Rate = 1 + (pitch - 1) * -2; } else { clock.Rate = 1; } } }
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); }
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); } }
private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuGameBase game) { dimLevel = game.Config.GetBindable<int>(OsuConfig.DimLevel); try { if (Beatmap == null) Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo); } catch { //couldn't load, hard abort! Exit(); return; } AudioTrack track = Beatmap.Track; if (track != null) { audio.Track.SetExclusive(track); sourceClock = track; } sourceClock = (IAdjustableClock)track ?? new StopwatchClock(); Schedule(() => { sourceClock.Reset(); }); var beatmap = Beatmap.Beatmap; if (beatmap.BeatmapInfo?.Mode > PlayMode.Osu) { //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor. Exit(); return; } PlayMode usablePlayMode = beatmap.BeatmapInfo?.Mode > PlayMode.Osu ? beatmap.BeatmapInfo.Mode : PreferredPlayMode; ruleset = Ruleset.GetRuleset(usablePlayMode); var scoreOverlay = ruleset.CreateScoreOverlay(); scoreOverlay.BindProcessor(scoreProcessor = ruleset.CreateScoreProcessor()); hitRenderer = ruleset.CreateHitRendererWith(beatmap.HitObjects); hitRenderer.OnJudgement += scoreProcessor.AddJudgement; hitRenderer.OnAllJudged += hitRenderer_OnAllJudged; if (Autoplay) hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Hit)); Children = new Drawable[] { new PlayerInputManager(game.Host) { Clock = new InterpolatingFramedClock(sourceClock), PassThrough = false, Children = new Drawable[] { hitRenderer, } }, scoreOverlay, }; }
private void load(IAdjustableClock adjustableClock) { this.adjustableClock = adjustableClock; }
private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuGameBase game, OsuConfigManager config) { dimLevel = config.GetBindable <int>(OsuConfig.DimLevel); try { if (Beatmap == null) { Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo, withStoryboard: true); } if ((Beatmap?.Beatmap?.HitObjects.Count ?? 0) == 0) { throw new Exception("No valid objects were found!"); } } catch (Exception e) { Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error); //couldn't load, hard abort! Exit(); return; } AudioTrack track = Beatmap.Track; if (track != null) { audio.Track.SetExclusive(track); sourceClock = track; } sourceClock = (IAdjustableClock)track ?? new StopwatchClock(); Schedule(() => { sourceClock.Reset(); }); var beatmap = Beatmap.Beatmap; if (beatmap.BeatmapInfo?.Mode > PlayMode.Osu) { //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor. Exit(); return; } PlayMode usablePlayMode = beatmap.BeatmapInfo?.Mode > PlayMode.Osu ? beatmap.BeatmapInfo.Mode : PreferredPlayMode; ruleset = Ruleset.GetRuleset(usablePlayMode); scoreOverlay = ruleset.CreateScoreOverlay(); scoreOverlay.BindProcessor(scoreProcessor = ruleset.CreateScoreProcessor(beatmap.HitObjects.Count)); pauseOverlay = new PauseOverlay { Depth = -1, OnResume = delegate { Delay(400); Schedule(Resume); }, OnRetry = Restart, OnQuit = Exit }; hitRenderer = ruleset.CreateHitRendererWith(beatmap); //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) hitRenderer.OnJudgement += scoreProcessor.AddJudgement; hitRenderer.OnAllJudged += onPass; //bind ScoreProcessor to ourselves (for a fail situation) scoreProcessor.Failed += onFail; if (Autoplay) { hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Hit)); } Children = new Drawable[] { playerInputManager = new PlayerInputManager(game.Host) { Clock = new InterpolatingFramedClock(sourceClock), PassThrough = false, Children = new Drawable[] { hitRenderer, skipButton = new SkipButton { Alpha = 0 }, } }, scoreOverlay, pauseOverlay }; }
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 HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContainer, WorkingBeatmap working, IClock offsetClock, IAdjustableClock adjustableClock) { RelativeSizeAxes = Axes.Both; Children = new Drawable[] { visibilityContainer = new Container { RelativeSizeAxes = Axes.Both, AlwaysPresent = true, // The hud may be hidden but certain elements may need to still be updated Children = new Drawable[] { new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Y = 30, AutoSizeAxes = Axes.Both, AutoSizeDuration = 200, AutoSizeEasing = Easing.Out, Children = new Drawable[] { AccuracyCounter = CreateAccuracyCounter(), ScoreCounter = CreateScoreCounter(), ComboCounter = CreateComboCounter(), }, }, HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), } }, PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), new FillFlowContainer { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Position = -new Vector2(5, TwoLayerButton.SIZE_RETRACTED.Y), AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Children = new Drawable[] { KeyCounter = CreateKeyCounter(adjustableClock as IFrameBasedClock), HoldToQuit = CreateHoldForMenuButton(), } } }; BindProcessor(scoreProcessor); BindRulesetContainer(rulesetContainer); Progress.Objects = rulesetContainer.Objects; Progress.AudioClock = offsetClock; Progress.AllowSeeking = rulesetContainer.HasReplayLoaded; Progress.OnSeek = pos => adjustableClock.Seek(pos); ModDisplay.Current.BindTo(working.Mods); PlayerSettingsOverlay.PlaybackSettings.AdjustableClock = adjustableClock; }
private void load(IAdjustableClock clock) { editorClock = clock; }
private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager config) { var beatmap = Beatmap.Beatmap; if (beatmap.BeatmapInfo?.Mode > PlayMode.Osu) { //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor. Exit(); return; } dimLevel = config.GetBindable <int>(OsuConfig.DimLevel); mouseWheelDisabled = config.GetBindable <bool>(OsuConfig.MouseDisableWheel); try { if (Beatmap == null) { Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo, withStoryboard: true); } if ((Beatmap?.Beatmap?.HitObjects.Count ?? 0) == 0) { throw new Exception("No valid objects were found!"); } if (Beatmap == null) { throw new Exception("Beatmap was not loaded"); } } 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.Track; if (track != null) { audio.Track.SetExclusive(track); sourceClock = track; } sourceClock = (IAdjustableClock)track ?? new StopwatchClock(); interpolatedSourceClock = new InterpolatingFramedClock(sourceClock); Schedule(() => { sourceClock.Reset(); }); ruleset = Ruleset.GetRuleset(Beatmap.PlayMode); hudOverlay = new StandardHudOverlay(); hudOverlay.KeyCounter.Add(ruleset.CreateGameplayKeys()); hudOverlay.BindProcessor(scoreProcessor = ruleset.CreateScoreProcessor(beatmap.HitObjects.Count)); pauseOverlay = new PauseOverlay { Depth = -1, OnResume = delegate { Delay(400); Schedule(Resume); }, OnRetry = Restart, OnQuit = Exit }; hitRenderer = ruleset.CreateHitRendererWith(Beatmap); if (ReplayInputHandler != null) { hitRenderer.InputManager.ReplayInputHandler = ReplayInputHandler; } hudOverlay.BindHitRenderer(hitRenderer); //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) hitRenderer.OnJudgement += scoreProcessor.AddJudgement; hitRenderer.OnAllJudged += onPass; //bind ScoreProcessor to ourselves (for a fail situation) scoreProcessor.Failed += onFail; Children = new Drawable[] { new Container { RelativeSizeAxes = Axes.Both, Clock = interpolatedSourceClock, Children = new Drawable[] { hitRenderer, skipButton = new SkipButton { Alpha = 0 }, } }, hudOverlay, pauseOverlay }; }
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); } }
private void load(IAdjustableClock adjustableClock, IBindable <WorkingBeatmap> beatmap) { this.adjustableClock = adjustableClock; this.beatmap.BindTo(beatmap); }
public virtual void ApplyToClock(IAdjustableClock clock) { clock.Rate = 1.5; }