Skip to content
19 changes: 19 additions & 0 deletions osu.Game.Tests/Visual/RankedPlay/TestScenePlayerCardHand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 +192,24 @@ public void TestContract()
.All(card => !card.ScreenSpaceDrawQuad.AABBFloat.IntersectsWith(handOfCards.ScreenSpaceDrawQuad.AABBFloat))
);
}

[Test]
public void TestRemoveCardsWhileDragging()
{
AddStep("add cards", () =>
{
for (int i = 0; i < 5; i++)
handOfCards.AddCard(new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem()));
});
AddStep("hover card", () => InputManager.MoveMouseTo(handOfCards.Cards.First()));
AddStep("start drag", () => InputManager.PressButton(MouseButton.Left));
AddStep("move card", () => InputManager.MoveMouseTo(handOfCards.Cards[3]));
AddStep("remove cards", () =>
{
foreach (var card in handOfCards.Cards.ToArray())
handOfCards.RemoveCard(card.Item);
});
AddStep("release mouse", () => InputManager.ReleaseButton(MouseButton.Left));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ public override void SetUpSteps()
[Test]
public void TestBasic()
{
double multiplier = 1.0;

AddSliderStep<double>("set multiplier", 1, 5, 2, value => multiplier = value);
AddStep("create", () => Child = new RankedPlayStageOverlay("Pick Phase", RankedPlayColourScheme.BLUE)
{
PickingUser = new APIUser
{
Id = 2,
Username = "peppy",
},
Multiplier = 2,
Multiplier = multiplier,
});
}

Expand Down
39 changes: 39 additions & 0 deletions osu.Game.Tests/Visual/RankedPlay/TestSceneResultsScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Linq;
using NUnit.Framework;
using osu.Framework.Extensions;
using osu.Framework.Screens;
using osu.Framework.Utils;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
Expand Down Expand Up @@ -38,6 +39,44 @@ public override void SetUpSteps()
setupRequestHandler();
}

[Test]
[Explicit("Test exercises correct stopping of audio playback. Has no assertions, only useful when checked manually by a human.")]
public void TestAllSamplesStopOnExit()
{
AddStep("set results state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.Results, state =>
{
int losingPlayer = state.Users.Keys.First();

foreach (var (id, userInfo) in state.Users)
{
if (id == losingPlayer)
{
userInfo.DamageInfo = new RankedPlayDamageInfo
{
RawDamage = 123_456,
Damage = 123_456,
OldLife = 500_000,
NewLife = 500_000 - 123_456,
};

userInfo.Life = 500_000 - 123_456;
}
else
{
userInfo.DamageInfo = new RankedPlayDamageInfo
{
RawDamage = 0,
Damage = 0,
OldLife = 1_000_000,
NewLife = 1_000_000,
};
}
}
}).WaitSafely());
AddWaitStep("wait for samples to start playing", 5);
AddRepeatStep("exit", () => screen.Exit(), 2);
}

[Test]
public void TestBasic()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Framework.Layout;
using osu.Framework.Utils;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
Expand Down Expand Up @@ -521,7 +522,8 @@ private partial class VerticalLine : Box
protected override void Update()
{
base.Update();
Width = Parent!.DrawWidth / Parent.ScreenSpaceDrawQuad.Width;
if (Precision.DefinitelyBigger(Parent!.ScreenSpaceDrawQuad.Width, 0))
Width = Parent.DrawWidth / Parent.ScreenSpaceDrawQuad.Width;
}
Comment on lines +525 to 527
}

Expand All @@ -533,7 +535,8 @@ private partial class HorizontalLine : Box
protected override void Update()
{
base.Update();
Height = Parent!.DrawHeight / Parent.ScreenSpaceDrawQuad.Height;
if (Precision.DefinitelyBigger(Parent!.ScreenSpaceDrawQuad.Height, 0))
Height = Parent!.DrawHeight / Parent.ScreenSpaceDrawQuad.Height;
}
}

Expand Down
14 changes: 10 additions & 4 deletions osu.Game/Screens/OnlinePlay/Matchmaking/Queue/ScreenQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Audio;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Bindings;
Expand Down Expand Up @@ -83,11 +85,11 @@ public partial class ScreenQueue : OsuScreen
private CancellationTokenSource userLookupCancellation = new CancellationTokenSource();

private Sample? enqueueSample;
private Sample? waitingLoopSample;
private Sample? matchFoundSample;

private SampleChannel? waitingLoopChannel;
private ScheduledDelegate? startLoopPlaybackDelegate;
private DrawableSample waitingLoop = null!;

private int? userRating;

Expand All @@ -102,14 +104,14 @@ public ScreenQueue(MatchmakingPoolType poolType)
private void load(AudioManager audio, IAPIProvider api)
{
enqueueSample = audio.Samples.Get(@"Multiplayer/Matchmaking/enqueue");
waitingLoopSample = audio.Samples.Get(@"Multiplayer/Matchmaking/waiting-loop");
matchFoundSample = audio.Samples.Get(@"Multiplayer/Matchmaking/match-found");

InternalChild = new InverseScalingDrawSizePreservingFillContainer
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
waitingLoop = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/waiting-loop")),
new GlobalScrollAdjustsVolume(),
mainGrid = new GridContainer
{
Expand All @@ -123,7 +125,7 @@ private void load(AudioManager audio, IAPIProvider api)
RowDimensions =
[
new Dimension(),
new Dimension(GridSizeMode.Relative, 0.35f)
new Dimension(GridSizeMode.Relative, RuntimeInfo.IsMobile ? 0.55f : 0.35f)
],
Content = new[]
{
Expand Down Expand Up @@ -642,12 +644,16 @@ private void startWaitingLoopPlayback()
{
stopWaitingLoopPlayback();

waitingLoopChannel = waitingLoopSample?.GetChannel();
waitingLoopChannel = waitingLoop.GetChannel();
if (waitingLoopChannel == null)
return;

waitingLoopChannel.Looping = true;
waitingLoopChannel?.Play();

waitingLoop.VolumeTo(1)
.Delay(2000)
.VolumeTo(0, 12000);
}

private void stopWaitingLoopPlayback()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ private void load(CardColours colours)

public MenuItem[] ContextMenuItems =>
[
new OsuMenuItem(ContextMenuStrings.ViewBeatmap, MenuItemType.Highlighted, () => beatmapSetOverlay?.ShowBeatmapSet(Beatmap.BeatmapSet))
new OsuMenuItem(ContextMenuStrings.ViewBeatmap, MenuItemType.Highlighted, () => beatmapSetOverlay?.FetchAndShowBeatmap(Beatmap.OnlineID))
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ public bool RemoveCard(RankedPlayCardWithPlaylistItem item)
if (!cardLookup.Remove(item.Card, out var drawable))
return false;

// child order is only updated once per frame so ordering can change between that and the card getting removed
// which can mess when doing a binary-search for the child during removal
cardContainer.Sort();
cardContainer.Remove(drawable, true);
InvalidateLayout(drawOrder: true);
return true;
Expand All @@ -162,6 +165,9 @@ public bool RemoveCard(RankedPlayCardWithPlaylistItem item, [MaybeNullWhen(false
screenSpaceDrawQuad = drawable.ScreenSpaceDrawQuad;
card = drawable.Detach();

// child order is only updated once per frame so ordering can change between that and the card getting removed
// which can mess when doing a binary-search for the child during removal
cardContainer.Sort();
cardContainer.Remove(drawable, true);
InvalidateLayout(drawOrder: true);

Expand Down Expand Up @@ -352,13 +358,11 @@ protected override int Compare(Drawable x, Drawable y)
if (x is HandCard c1 && y is HandCard c2)
{
// dragged cards should always be drawn on top
if (c1.CardDragged)
return 1;

if (c2.CardDragged)
return -1;
int result = c1.CardDragged.CompareTo(c2.CardDragged);
if (result != 0)
return result;

int result = c1.Order.CompareTo(c2.Order);
result = c1.Order.CompareTo(c2.Order);
if (result != 0)
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Components;
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Intro;
using osu.Game.Screens.OnlinePlay.Multiplayer;
using osu.Game.Users;
using osuTK;

namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
Expand All @@ -43,6 +44,10 @@ public partial class RankedPlayScreen : OsuScreen, IPreviewTrackOwner, IHandlePr
{
protected override bool InitialBackButtonVisibility => false;

public override bool? ApplyModTrackAdjustments => true;

public override bool DisallowExternalBeatmapRulesetChanges => true;

public override bool HideOverlaysOnEnter => true;

public RankedPlaySubScreen? ActiveSubScreen { get; private set; }
Expand Down Expand Up @@ -115,6 +120,8 @@ public RankedPlayScreen(MultiplayerRoom room)
{
this.room = room;

Activity.Value = new UserActivity.InLobby(room);

InternalChildren = new Drawable[]
{
matchInfo = new RankedPlayMatchInfo(),
Expand Down Expand Up @@ -369,6 +376,7 @@ public override bool OnExiting(ScreenExitEvent e)
return true;
}

ActiveSubScreen?.OnExiting(null);
backgroundMusic.Stop();
previewTrackManager.StopAnyPlaying(this);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Extensions;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses;
Expand Down Expand Up @@ -158,7 +159,7 @@ private void load(AudioManager audio)
Origin = Anchor.CentreLeft,
UseFullGlyphHeight = false,
Font = OsuFont.Torus.With(size: 32),
Text = $"{Multiplier:N0}x damage",
Text = $"{Multiplier.Value.ToStandardFormattedString(maxDecimalDigits: 1)}x damage",
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Audio;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Transforms;
Expand Down Expand Up @@ -59,17 +60,18 @@ private partial class MainPanel : CompositeDrawable

private RankedPlayDamageInfo losingDamageInfo = null!;

private Sample resultsAppearSample = null!;
private Sample dmgFlySample = null!;
private Sample dmgHitSample = null!;
private Sample hpDownSample = null!;
private Sample playerAppearSample = null!;
private Sample pseudoScoreCounterSample = null!;
private Sample scoreTickSample = null!;
private Sample gradePassSample = null!;
private Sample gradePassSsSample = null!;
private Sample gradeFailSample = null!;
private Sample gradeFailDSample = null!;
private AudioContainer sampleContainer = null!;
private DrawableSample resultsAppearSample = null!;
private DrawableSample dmgFlySample = null!;
private DrawableSample dmgHitSample = null!;
private DrawableSample hpDownSample = null!;
private DrawableSample playerAppearSample = null!;
private DrawableSample pseudoScoreCounterSample = null!;
private DrawableSample scoreTickSample = null!;
private DrawableSample gradePassSample = null!;
private DrawableSample gradePassSsSample = null!;
private DrawableSample gradeFailSample = null!;
private DrawableSample gradeFailDSample = null!;
private SampleChannel? playerScoreTickChannel;
private SampleChannel? opponentScoreTickChannel;
private readonly BindableDouble playerScoreTickPitch = new BindableDouble();
Expand Down Expand Up @@ -288,17 +290,23 @@ private void load(AudioManager audio)
}
});

resultsAppearSample = audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/results-appear");
dmgFlySample = audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/dmg-fly");
dmgHitSample = audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/dmg-hit");
hpDownSample = audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/hp-down");
playerAppearSample = audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/players-appear");
pseudoScoreCounterSample = audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/pseudo-score-counter");
scoreTickSample = audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/score-tick");
gradePassSample = audio.Samples.Get(@"Results/rank-impact-pass");
gradePassSsSample = audio.Samples.Get(@"Results/rank-impact-pass-ss");
gradeFailSample = audio.Samples.Get(@"Results/rank-impact-fail");
gradeFailDSample = audio.Samples.Get(@"Results/rank-impact-fail-d");
AddInternal(sampleContainer = new AudioContainer
{
Children = new Drawable[]
{
resultsAppearSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/results-appear")),
dmgFlySample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/dmg-fly")),
dmgHitSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/dmg-hit")),
hpDownSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/hp-down")),
playerAppearSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/players-appear")),
pseudoScoreCounterSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/pseudo-score-counter")),
scoreTickSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/score-tick")),
gradePassSample = new DrawableSample(audio.Samples.Get(@"Results/rank-impact-pass")),
gradePassSsSample = new DrawableSample(audio.Samples.Get(@"Results/rank-impact-pass-ss")),
gradeFailSample = new DrawableSample(audio.Samples.Get(@"Results/rank-impact-fail")),
gradeFailDSample = new DrawableSample(audio.Samples.Get(@"Results/rank-impact-fail-d")),
}
});
}

protected override void LoadComplete()
Expand Down Expand Up @@ -526,7 +534,7 @@ private void playAnimation()
}
}

private Sample getRankSample(ScoreRank rank)
private DrawableSample getRankSample(ScoreRank rank)
{
switch (rank)
{
Expand Down Expand Up @@ -557,6 +565,13 @@ private static int numDigits(long value)
return (int)Math.Floor(Math.Log10(value)) + 1;
}

public void StopAllSamples()
{
sampleContainer.Volume.Value = 0;
playerScoreTickChannel?.Stop();
opponentScoreTickChannel?.Stop();
Comment on lines +570 to +572
}

private partial class DamageParticle : Triangle
{
private Vector2 velocity = new Vector2(RNG.NextSingle(-0.3f, 0.3f), RNG.NextSingle(-0.3f, 0.3f));
Expand Down
Loading
Loading