mirror of
https://github.com/ppy/osu.git
synced 2026-05-18 16:50:21 +08:00
Merge branch 'master' into totp
This commit is contained in:
@@ -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<ArgonJudgementCounter>().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()
|
||||
|
||||
@@ -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<APISeasonalBackgrounds?>(Static.SeasonalBackgrounds, null);
|
||||
SetDefault(Static.TouchInputActive, RuntimeInfo.IsMobile);
|
||||
SetDefault<ScoreInfo?>(Static.LastLocalUserScore, null);
|
||||
@@ -83,12 +81,6 @@ namespace osu.Game.Configuration
|
||||
/// </summary>
|
||||
LastRankChangeSamplePlaybackTime,
|
||||
|
||||
/// <summary>
|
||||
/// The last playback time in milliseconds for the 'user appear' sample in <see cref="MatchmakingCloud"/>.
|
||||
/// Used to debounce sample playback to avoid volume saturation from multiple simultaneous playback.
|
||||
/// </summary>
|
||||
LastMatchmakingCloudSamplePlaybackTime,
|
||||
|
||||
/// <summary>
|
||||
/// Whether the last positional input received was a touch input.
|
||||
/// Used in touchscreen detection scenarios (<see cref="TouchInputInterceptor"/>).
|
||||
|
||||
@@ -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<double?> lastSamplePlayback = new Bindable<double?>();
|
||||
|
||||
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<double?> lastSamplePlaybackTime = null!;
|
||||
private readonly Bindable<double?> lastSamplePlayback = new Bindable<double?>();
|
||||
|
||||
private const int num_appear_samples = 6;
|
||||
private Sample? playerAppearSample;
|
||||
|
||||
public MovingAvatar(APIUser apiUser)
|
||||
public MovingAvatar(APIUser apiUser, Bindable<double?> 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<double?>(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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Realm" Version="20.1.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2025.908.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2025.911.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2025.913.0" />
|
||||
<PackageReference Include="Sentry" Version="5.1.1" />
|
||||
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
||||
<PackageReference Include="SharpCompress" Version="0.39.0" />
|
||||
|
||||
Reference in New Issue
Block a user