diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneArgonJudgementCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneArgonJudgementCounter.cs index e08af79032..e5886aa607 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneArgonJudgementCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneArgonJudgementCounter.cs @@ -183,6 +183,9 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Show all judgements", () => counterDisplay.Mode.Value = ArgonJudgementCounterDisplay.DisplayMode.All); AddWaitStep("wait some", 2); AddAssert("Check all visible", () => counterDisplay.CounterFlow.ChildrenOfType().Last().Alpha == 1); + AddToggleStep("toggle wireframe display", t => counterDisplay.WireframeOpacity.Value = t ? 0.3f : 0); + AddStep("Set direction vertical", () => counterDisplay.FlowDirection.Value = Direction.Vertical); + AddStep("Set direction horizontal", () => counterDisplay.FlowDirection.Value = Direction.Horizontal); } private int hiddenCount() diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs index 0c0b2a989d..59e107a23e 100644 --- a/osu.Game/Configuration/SessionStatics.cs +++ b/osu.Game/Configuration/SessionStatics.cs @@ -8,7 +8,6 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Scoring; -using osu.Game.Screens.OnlinePlay.Matchmaking; using osu.Game.Screens.Play.HUD; using osu.Game.Skinning; using osu.Game.Users; @@ -29,7 +28,6 @@ namespace osu.Game.Configuration SetDefault(Static.LastHoverSoundPlaybackTime, (double?)null); SetDefault(Static.LastModSelectPanelSamplePlaybackTime, (double?)null); SetDefault(Static.LastRankChangeSamplePlaybackTime, (double?)null); - SetDefault(Static.LastMatchmakingCloudSamplePlaybackTime, (double?)null); SetDefault(Static.SeasonalBackgrounds, null); SetDefault(Static.TouchInputActive, RuntimeInfo.IsMobile); SetDefault(Static.LastLocalUserScore, null); @@ -83,12 +81,6 @@ namespace osu.Game.Configuration /// LastRankChangeSamplePlaybackTime, - /// - /// The last playback time in milliseconds for the 'user appear' sample in . - /// Used to debounce sample playback to avoid volume saturation from multiple simultaneous playback. - /// - LastMatchmakingCloudSamplePlaybackTime, - /// /// Whether the last positional input received was a touch input. /// Used in touchscreen detection scenarios (). diff --git a/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingCloud.cs b/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingCloud.cs index d2b2b72f02..3fab5ab207 100644 --- a/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingCloud.cs +++ b/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingCloud.cs @@ -10,7 +10,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; -using osu.Game.Configuration; using osu.Game.Online.API.Requests.Responses; using osu.Game.Screens.Ranking; using osuTK; @@ -22,6 +21,8 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking private APIUser[] users = []; private Container usersContainer = null!; + private readonly Bindable lastSamplePlayback = new Bindable(); + public APIUser[] Users { get => users; @@ -32,7 +33,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking foreach (var u in usersContainer) u.Delay(RNG.Next(0, 1000)).FadeOut(500).Expire(); - LoadComponentsAsync(users.Select(u => new MovingAvatar(u)), avatars => + LoadComponentsAsync(users.Select(u => new MovingAvatar(u, lastSamplePlayback)), avatars => { if (usersContainer.Count == 0) { @@ -69,24 +70,25 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking private float targetScale; private float targetAlpha; - private Bindable lastSamplePlaybackTime = null!; + private readonly Bindable lastSamplePlayback = new Bindable(); + private const int num_appear_samples = 6; private Sample? playerAppearSample; - public MovingAvatar(APIUser apiUser) + public MovingAvatar(APIUser apiUser, Bindable lastSamplePlayback) : base(apiUser) { RelativePositionAxes = Axes.Both; Scale = new Vector2(2); Origin = Anchor.Centre; + this.lastSamplePlayback.BindTo(lastSamplePlayback); } [BackgroundDependencyLoader] - private void load(AudioManager audio, SessionStatics statics) + private void load(AudioManager audio) { - playerAppearSample = audio.Samples.Get(@"UI/toolbar-hover"); - lastSamplePlaybackTime = statics.GetBindable(Static.LastMatchmakingCloudSamplePlaybackTime); + playerAppearSample = audio.Samples.Get($@"Multiplayer/Matchmaking/Cloud/appear-{RNG.Next(0, num_appear_samples)}"); } protected override void LoadComplete() @@ -103,20 +105,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking Hide(); int appearDelay = RNG.Next(0, 1000); this.Delay(appearDelay).FadeTo(targetAlpha, 2000, Easing.OutQuint); - Scheduler.AddDelayed(() => - { - bool enoughTimeElapsed = !lastSamplePlaybackTime.Value.HasValue || Time.Current - lastSamplePlaybackTime.Value >= OsuGameBase.SAMPLE_DEBOUNCE_TIME; - if (!enoughTimeElapsed) return; - - var chan = playerAppearSample?.GetChannel(); - - if (chan == null) return; - - chan.Frequency.Value = 1f + RNG.NextDouble(0.25f); - chan.Play(); - - lastSamplePlaybackTime.Value = Time.Current; - }, appearDelay); + Scheduler.AddDelayed(playAppearSample, appearDelay); } private void updateParams() @@ -128,6 +117,21 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking Scheduler.AddDelayed(updateParams, RNG.Next(500, 5000)); } + private void playAppearSample() + { + bool enoughTimeElapsed = !lastSamplePlayback.Value.HasValue || Time.Current - lastSamplePlayback.Value >= OsuGameBase.SAMPLE_DEBOUNCE_TIME; + if (!enoughTimeElapsed) return; + + var chan = playerAppearSample?.GetChannel(); + if (chan == null) return; + + chan.Frequency.Value = 0.5f + RNG.NextDouble(1.5f); + chan.Balance.Value = MathF.Cos(angle) * OsuGameBase.SFX_STEREO_STRENGTH; + chan.Play(); + + lastSamplePlayback.Value = Time.Current; + } + protected override void Update() { base.Update(); diff --git a/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingScreen.cs b/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingScreen.cs index ba2e5593bf..b02583103d 100644 --- a/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Matchmaking/MatchmakingScreen.cs @@ -217,6 +217,10 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking private void updateGameplayState() { MultiplayerPlaylistItem item = client.Room!.CurrentPlaylistItem; + + if (item.Expired) + return; + RulesetInfo ruleset = rulesets.GetRuleset(item.RulesetID)!; Ruleset rulesetInstance = ruleset.CreateInstance(); @@ -228,9 +232,15 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking Mods.Value = item.RequiredMods.Select(m => m.ToMod(rulesetInstance)).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) - client.ChangeState(MultiplayerUserState.Idle).FireAndForget(); + { + if (client.LocalUser!.State == MultiplayerUserState.Ready) + client.ChangeState(MultiplayerUserState.Idle).FireAndForget(); + } else - client.ChangeState(MultiplayerUserState.Ready).FireAndForget(); + { + if (client.LocalUser!.State == MultiplayerUserState.Idle) + client.ChangeState(MultiplayerUserState.Ready).FireAndForget(); + } client.ChangeBeatmapAvailability(beatmapAvailabilityTracker.Availability.Value).FireAndForget(); } diff --git a/osu.Game/Screens/OnlinePlay/Matchmaking/Screens/Pick/BeatmapSelectionGrid.cs b/osu.Game/Screens/OnlinePlay/Matchmaking/Screens/Pick/BeatmapSelectionGrid.cs index 66cae72616..813e8efa0d 100644 --- a/osu.Game/Screens/OnlinePlay/Matchmaking/Screens/Pick/BeatmapSelectionGrid.cs +++ b/osu.Game/Screens/OnlinePlay/Matchmaking/Screens/Pick/BeatmapSelectionGrid.cs @@ -45,8 +45,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Screens.Pick private bool allowSelection = true; - private readonly Sample[] rouletteSamples = new Sample[8]; - private Sample? rouletteResultSample; + private readonly Sample?[] spinSamples = new Sample?[5]; + private static readonly int[] spin_sample_sequence = [0, 1, 2, 3, 4, 2, 3, 4]; + private Sample? resultSample; private Sample? swooshSample; private double? lastSamplePlayback; @@ -77,15 +78,10 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Screens.Pick [BackgroundDependencyLoader] private void load(AudioManager audio) { - rouletteSamples[0] = audio.Samples.Get(@"Multiplayer/Matchmaking/roulette-0"); - rouletteSamples[1] = audio.Samples.Get(@"Multiplayer/Matchmaking/roulette-1"); - rouletteSamples[2] = audio.Samples.Get(@"Multiplayer/Matchmaking/roulette-2"); - rouletteSamples[3] = audio.Samples.Get(@"Multiplayer/Matchmaking/roulette-3"); - rouletteSamples[4] = audio.Samples.Get(@"Multiplayer/Matchmaking/roulette-4"); - rouletteSamples[5] = audio.Samples.Get(@"Multiplayer/Matchmaking/roulette-2"); - rouletteSamples[6] = audio.Samples.Get(@"Multiplayer/Matchmaking/roulette-3"); - rouletteSamples[7] = audio.Samples.Get(@"Multiplayer/Matchmaking/roulette-4"); - rouletteResultSample = audio.Samples.Get(@"Multiplayer/Matchmaking/roulette-result"); + for (int i = 0; i < spinSamples.Length; i++) + spinSamples[i] = audio.Samples.Get($@"Multiplayer/Matchmaking/Selection/roulette-{i}"); + + resultSample = audio.Samples.Get(@"Multiplayer/Matchmaking/Selection/roulette-result"); swooshSample = audio.Samples.Get(@"SongSelect/options-pop-out"); } @@ -306,8 +302,8 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Screens.Pick if (lastSamplePlayback == null || Time.Current - lastSamplePlayback > OsuGameBase.SAMPLE_DEBOUNCE_TIME) { - int sampleIdx = ii % (rouletteSamples.Length); - rouletteSamples[sampleIdx].Play(); + int sequenceIdx = ii % spin_sample_sequence.Length; + spinSamples[spin_sample_sequence[sequenceIdx]]?.Play(); lastSamplePlayback = Time.Current; } @@ -338,7 +334,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.Screens.Pick panel.MoveTo(Vector2.Zero, 1000, Easing.OutExpo) .ScaleTo(1.5f, 1000, Easing.OutExpo); - rouletteResultSample?.Play(); + resultSample?.Play(); }); } } diff --git a/osu.Game/Screens/OnlinePlay/Matchmaking/StageBubble.cs b/osu.Game/Screens/OnlinePlay/Matchmaking/StageBubble.cs index 281374ba71..2ebd3376d3 100644 --- a/osu.Game/Screens/OnlinePlay/Matchmaking/StageBubble.cs +++ b/osu.Game/Screens/OnlinePlay/Matchmaking/StageBubble.cs @@ -3,6 +3,8 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; @@ -31,6 +33,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking private DateTimeOffset countdownStartTime; private DateTimeOffset countdownEndTime; + private Sample? stageProgressSample; + private double? lastSamplePlayback; + public StageBubble(MatchmakingStage stage, LocalisableString displayText) { this.stage = stage; @@ -40,7 +45,7 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking } [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio) { InternalChild = new CircularContainer { @@ -68,6 +73,8 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking } } }; + + stageProgressSample = audio.Samples.Get(@"Multiplayer/countdown-tick"); } protected override void LoadComplete() @@ -98,6 +105,13 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking { TimeSpan elapsed = DateTimeOffset.Now - countdownStartTime; progressBar.Width = (float)(elapsed.TotalMilliseconds / duration.TotalMilliseconds); + + bool enoughTimeElapsed = lastSamplePlayback == null || Time.Current - lastSamplePlayback >= 1000f; + if (elapsed.TotalMilliseconds < 1000f || !enoughTimeElapsed || elapsed.TotalMilliseconds >= duration.TotalMilliseconds) + return; + + stageProgressSample?.Play(); + lastSamplePlayback = Time.Current; } } diff --git a/osu.Game/Screens/OnlinePlay/Matchmaking/StageText.cs b/osu.Game/Screens/OnlinePlay/Matchmaking/StageText.cs index ab2627474e..b47e135004 100644 --- a/osu.Game/Screens/OnlinePlay/Matchmaking/StageText.cs +++ b/osu.Game/Screens/OnlinePlay/Matchmaking/StageText.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,13 +22,16 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking private OsuSpriteText text = null!; + private Sample? textChangedSample; + private double? lastSamplePlayback; + public StageText() { AutoSizeAxes = Axes.Both; } [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio) { InternalChild = text = new OsuSpriteText { @@ -34,6 +39,8 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking Font = OsuFont.Default, AlwaysPresent = true, }; + + textChangedSample = audio.Samples.Get(@"Multiplayer/Matchmaking/stage-message"); } protected override void LoadComplete() @@ -50,6 +57,12 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking return; text.Text = getTextForStatus(matchmakingState.Stage); + + if (text.Text == string.Empty || (lastSamplePlayback != null && Time.Current - lastSamplePlayback < OsuGameBase.SAMPLE_DEBOUNCE_TIME)) + return; + + textChangedSample?.Play(); + lastSamplePlayback = Time.Current; }); private LocalisableString getTextForStatus(MatchmakingStage status) diff --git a/osu.Game/Screens/Play/HUD/ArgonCounterTextComponent.cs b/osu.Game/Screens/Play/HUD/ArgonCounterTextComponent.cs index 3789fb1645..d55bf46f97 100644 --- a/osu.Game/Screens/Play/HUD/ArgonCounterTextComponent.cs +++ b/osu.Game/Screens/Play/HUD/ArgonCounterTextComponent.cs @@ -74,13 +74,13 @@ namespace osu.Game.Screens.Play.HUD { wireframesPart = new ArgonCounterSpriteText(wireframesLookup) { - Anchor = anchor, - Origin = anchor, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, }, textPart = new ArgonCounterSpriteText(textLookup) { - Anchor = anchor, - Origin = anchor, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, }, } } diff --git a/osu.Game/Skinning/Components/ArgonJudgementCounter.cs b/osu.Game/Skinning/Components/ArgonJudgementCounter.cs index 6fe8ac7ecd..84973aab3e 100644 --- a/osu.Game/Skinning/Components/ArgonJudgementCounter.cs +++ b/osu.Game/Skinning/Components/ArgonJudgementCounter.cs @@ -37,7 +37,7 @@ namespace osu.Game.Skinning.Components Result = result; AutoSizeAxes = Axes.Both; - AddInternal(textComponent = new ArgonCounterTextComponent(Anchor.TopRight, result.DisplayName.ToUpper())); + AddInternal(textComponent = new ArgonCounterTextComponent(Anchor.TopLeft, result.DisplayName.ToUpper())); } private void updateWireframe() diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 122a927abe..d64fadee97 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ - +