mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 02:42:54 +08:00
Use only single PlayerInstance for hit sample playback
This commit is contained in:
parent
6588859c32
commit
64579d50ac
@ -198,10 +198,40 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
checkPausedInstant(56, false);
|
||||
|
||||
// Player 2 should catch up to player 1 after unpausing.
|
||||
AddUntilStep("player 2 not catching up", () => !getInstance(56).GameplayClock.IsCatchingUp);
|
||||
waitForCatchup(56);
|
||||
AddWaitStep("wait a bit", 10);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMostInSyncUserIsAudioSource()
|
||||
{
|
||||
start(new[] { 55, 56 });
|
||||
loadSpectateScreen();
|
||||
|
||||
assertVolume(55, 0);
|
||||
assertVolume(56, 0);
|
||||
|
||||
sendFrames(55, 10);
|
||||
sendFrames(56, 20);
|
||||
assertVolume(55, 1);
|
||||
assertVolume(56, 0);
|
||||
|
||||
checkPaused(55, true);
|
||||
assertVolume(55, 0);
|
||||
assertVolume(56, 1);
|
||||
|
||||
sendFrames(55, 100);
|
||||
waitForCatchup(55);
|
||||
checkPaused(56, true);
|
||||
assertVolume(55, 1);
|
||||
assertVolume(56, 0);
|
||||
|
||||
sendFrames(56, 100);
|
||||
waitForCatchup(56);
|
||||
assertVolume(55, 1);
|
||||
assertVolume(56, 0);
|
||||
}
|
||||
|
||||
private void loadSpectateScreen(bool waitForPlayerLoad = true)
|
||||
{
|
||||
AddStep("load screen", () =>
|
||||
@ -255,11 +285,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
});
|
||||
}
|
||||
|
||||
private void checkPaused(int userId, bool state) =>
|
||||
AddUntilStep($"{userId} is {(state ? "paused" : "playing")}", () => getPlayer(userId).ChildrenOfType<GameplayClockContainer>().First().GameplayClock.IsRunning != state);
|
||||
private void checkPaused(int userId, bool state)
|
||||
=> AddUntilStep($"{userId} is {(state ? "paused" : "playing")}", () => getPlayer(userId).ChildrenOfType<GameplayClockContainer>().First().GameplayClock.IsRunning != state);
|
||||
|
||||
private void checkPausedInstant(int userId, bool state) =>
|
||||
AddAssert($"{userId} is {(state ? "paused" : "playing")}", () => getPlayer(userId).ChildrenOfType<GameplayClockContainer>().First().GameplayClock.IsRunning != state);
|
||||
private void checkPausedInstant(int userId, bool state)
|
||||
=> AddAssert($"{userId} is {(state ? "paused" : "playing")}", () => getPlayer(userId).ChildrenOfType<GameplayClockContainer>().First().GameplayClock.IsRunning != state);
|
||||
|
||||
private void assertVolume(int userId, double volume)
|
||||
=> AddAssert($"{userId} volume is {volume}", () => getInstance(userId).Volume.Value == volume);
|
||||
|
||||
private void waitForCatchup(int userId)
|
||||
=> AddUntilStep($"{userId} not catching up", () => !getInstance(userId).GameplayClock.IsCatchingUp);
|
||||
|
||||
private Player getPlayer(int userId) => getInstance(userId).ChildrenOfType<Player>().Single();
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -28,6 +29,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
private ISyncManager syncManager;
|
||||
private PlayerGrid grid;
|
||||
private MultiplayerSpectatorLeaderboard leaderboard;
|
||||
private PlayerInstance currentAudioSource;
|
||||
|
||||
public MultiplayerSpectator(int[] userIds)
|
||||
: base(userIds.AsSpan().Slice(0, Math.Min(16, userIds.Length)).ToArray())
|
||||
@ -85,6 +87,24 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
masterClockContainer.Reset();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!isCandidateAudioSource(currentAudioSource?.GameplayClock))
|
||||
{
|
||||
currentAudioSource = instances.Where(i => isCandidateAudioSource(i.GameplayClock))
|
||||
.OrderBy(i => Math.Abs(i.GameplayClock.CurrentTime - syncManager.Master.CurrentTime))
|
||||
.FirstOrDefault();
|
||||
|
||||
foreach (var instance in instances)
|
||||
instance.Volume.Value = instance == currentAudioSource ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
private bool isCandidateAudioSource([CanBeNull] ISlaveClock clock)
|
||||
=> clock?.IsRunning == true && !clock.IsCatchingUp && !clock.WaitingOnFrames.Value;
|
||||
|
||||
protected override void OnUserStateChanged(int userId, SpectatorState spectatorState)
|
||||
{
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -13,7 +15,7 @@ using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
{
|
||||
public class PlayerInstance : CompositeDrawable
|
||||
public class PlayerInstance : CompositeDrawable, IAdjustableAudioComponent
|
||||
{
|
||||
public bool PlayerLoaded => stack?.CurrentScreen is Player;
|
||||
|
||||
@ -25,8 +27,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
|
||||
private readonly Container content;
|
||||
private readonly Container gameplayContent;
|
||||
private readonly LoadingLayer loadingLayer;
|
||||
private readonly AudioContainer audioContainer;
|
||||
private OsuScreenStack stack;
|
||||
|
||||
public PlayerInstance(int userId, CatchUpSlaveClock gameplayClock)
|
||||
@ -39,7 +42,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
content = new DrawSizePreservingFillContainer { RelativeSizeAxes = Axes.Both },
|
||||
audioContainer = new AudioContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = gameplayContent = new DrawSizePreservingFillContainer { RelativeSizeAxes = Axes.Both },
|
||||
},
|
||||
loadingLayer = new LoadingLayer(true) { State = { Value = Visibility.Visible } }
|
||||
};
|
||||
}
|
||||
@ -51,7 +58,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
|
||||
Score = score;
|
||||
|
||||
content.Child = new GameplayIsolationContainer(beatmapManager.GetWorkingBeatmap(Score.ScoreInfo.Beatmap, bypassCache: true), Score.ScoreInfo.Ruleset, Score.ScoreInfo.Mods)
|
||||
gameplayContent.Child = new GameplayIsolationContainer(beatmapManager.GetWorkingBeatmap(Score.ScoreInfo.Beatmap), Score.ScoreInfo.Ruleset, Score.ScoreInfo.Mods)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = stack = new OsuScreenStack()
|
||||
@ -64,5 +71,50 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
// Player interferes with global input, so disable input for now.
|
||||
public override bool PropagatePositionalInputSubTree => false;
|
||||
public override bool PropagateNonPositionalInputSubTree => false;
|
||||
|
||||
#region IAdjustableAudioComponent
|
||||
|
||||
public IBindable<double> AggregateVolume => audioContainer.AggregateVolume;
|
||||
|
||||
public IBindable<double> AggregateBalance => audioContainer.AggregateBalance;
|
||||
|
||||
public IBindable<double> AggregateFrequency => audioContainer.AggregateFrequency;
|
||||
|
||||
public IBindable<double> AggregateTempo => audioContainer.AggregateTempo;
|
||||
|
||||
public void BindAdjustments(IAggregateAudioAdjustment component)
|
||||
{
|
||||
audioContainer.BindAdjustments(component);
|
||||
}
|
||||
|
||||
public void UnbindAdjustments(IAggregateAudioAdjustment component)
|
||||
{
|
||||
audioContainer.UnbindAdjustments(component);
|
||||
}
|
||||
|
||||
public void AddAdjustment(AdjustableProperty type, IBindable<double> adjustBindable)
|
||||
{
|
||||
audioContainer.AddAdjustment(type, adjustBindable);
|
||||
}
|
||||
|
||||
public void RemoveAdjustment(AdjustableProperty type, IBindable<double> adjustBindable)
|
||||
{
|
||||
audioContainer.RemoveAdjustment(type, adjustBindable);
|
||||
}
|
||||
|
||||
public void RemoveAllAdjustments(AdjustableProperty type)
|
||||
{
|
||||
audioContainer.RemoveAllAdjustments(type);
|
||||
}
|
||||
|
||||
public BindableNumber<double> Volume => audioContainer.Volume;
|
||||
|
||||
public BindableNumber<double> Balance => audioContainer.Balance;
|
||||
|
||||
public BindableNumber<double> Frequency => audioContainer.Frequency;
|
||||
|
||||
public BindableNumber<double> Tempo => audioContainer.Tempo;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user