mirror of
https://github.com/ppy/osu.git
synced 2024-12-05 10:33:22 +08:00
implement replay analysis into spectating
This commit is contained in:
parent
9802b59459
commit
8749f9bb64
@ -19,6 +19,7 @@ using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
|
||||
@ -34,18 +35,23 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config;
|
||||
|
||||
[Resolved]
|
||||
private MultiSpectatorScreen? multiSpectatorScreen { get; set; }
|
||||
|
||||
public DrawableOsuRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod>? mods = null)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ReplayPlayer? replayPlayer)
|
||||
private void load(Player? player)
|
||||
{
|
||||
if (replayPlayer != null)
|
||||
if (player is ReplayPlayer || player is SpectatorPlayer)
|
||||
{
|
||||
PlayfieldAdjustmentContainer.Add(new ReplayAnalysisOverlay(replayPlayer.Score.Replay));
|
||||
replayPlayer.AddSettings(new ReplayAnalysisSettings(Config));
|
||||
PlayfieldAdjustmentContainer.Add(new ReplayAnalysisOverlay(player.Score.Replay));
|
||||
|
||||
if (multiSpectatorScreen == null)
|
||||
player.AddSettings(new ReplayAnalysisSettings(Config));
|
||||
|
||||
cursorHideEnabled = Config.GetBindable<bool>(OsuRulesetSetting.ReplayCursorHideEnabled);
|
||||
|
||||
@ -55,6 +61,14 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
if (multiSpectatorScreen != null && !multiSpectatorScreen.SettingsAdded)
|
||||
multiSpectatorScreen.AddSettingsAsync(new ReplayAnalysisSettings(Config));
|
||||
}
|
||||
|
||||
public override DrawableHitObject<OsuHitObject>? CreateDrawableRepresentation(OsuHitObject h) => null;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; // always show the gameplay cursor
|
||||
|
@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
private readonly Replay replay;
|
||||
|
||||
private int replayFrameIndex = 0;
|
||||
|
||||
public ReplayAnalysisOverlay(Replay replay)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
@ -52,7 +54,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
displayLength.BindValueChanged(_ =>
|
||||
{
|
||||
// Need to fully reload to make this work.
|
||||
loaded.Invalidate();
|
||||
invalidateLoaded();
|
||||
}, true);
|
||||
}
|
||||
|
||||
@ -60,6 +62,12 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
private CancellationTokenSource? generationCancellationSource;
|
||||
|
||||
private void invalidateLoaded()
|
||||
{
|
||||
loaded.Invalidate();
|
||||
replayFrameIndex = 0;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
@ -75,7 +83,12 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
private void initialise()
|
||||
{
|
||||
if (loaded.IsValid)
|
||||
{
|
||||
if (CursorPath != null)
|
||||
addEntries();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
loaded.Validate();
|
||||
|
||||
@ -90,14 +103,21 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
FrameMarkers = new FrameMarkerContainer(),
|
||||
};
|
||||
|
||||
addEntries();
|
||||
|
||||
LoadComponentsAsync(newDrawables, drawables => InternalChildrenEnumerable = drawables, generationCancellationSource.Token);
|
||||
}
|
||||
|
||||
private void addEntries()
|
||||
{
|
||||
bool leftHeld = false;
|
||||
bool rightHeld = false;
|
||||
|
||||
// This should probably be async as well, but it's a bit of a pain to debounce and everything.
|
||||
// Let's address concerns when they are raised.
|
||||
foreach (var frame in replay.Frames)
|
||||
while (replayFrameIndex < replay.Frames.Count)
|
||||
{
|
||||
var osuFrame = (OsuReplayFrame)frame;
|
||||
var osuFrame = (OsuReplayFrame)replay.Frames[replayFrameIndex];
|
||||
|
||||
bool leftButton = osuFrame.Actions.Contains(OsuAction.LeftButton);
|
||||
bool rightButton = osuFrame.Actions.Contains(OsuAction.RightButton);
|
||||
@ -107,7 +127,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
else if (!leftHeld && leftButton)
|
||||
{
|
||||
leftHeld = true;
|
||||
ClickMarkers.Add(new AnalysisFrameEntry(osuFrame.Time, displayLength.Value, osuFrame.Position, OsuAction.LeftButton));
|
||||
ClickMarkers!.Add(new AnalysisFrameEntry(osuFrame.Time, displayLength.Value, osuFrame.Position, OsuAction.LeftButton));
|
||||
}
|
||||
|
||||
if (rightHeld && !rightButton)
|
||||
@ -115,14 +135,14 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
else if (!rightHeld && rightButton)
|
||||
{
|
||||
rightHeld = true;
|
||||
ClickMarkers.Add(new AnalysisFrameEntry(osuFrame.Time, displayLength.Value, osuFrame.Position, OsuAction.RightButton));
|
||||
ClickMarkers!.Add(new AnalysisFrameEntry(osuFrame.Time, displayLength.Value, osuFrame.Position, OsuAction.RightButton));
|
||||
}
|
||||
|
||||
FrameMarkers.Add(new AnalysisFrameEntry(osuFrame.Time, displayLength.Value, osuFrame.Position, osuFrame.Actions.ToArray()));
|
||||
CursorPath.Add(new AnalysisFrameEntry(osuFrame.Time, displayLength.Value, osuFrame.Position));
|
||||
}
|
||||
FrameMarkers!.Add(new AnalysisFrameEntry(osuFrame.Time, displayLength.Value, osuFrame.Position, osuFrame.Actions.ToArray()));
|
||||
CursorPath!.Add(new AnalysisFrameEntry(osuFrame.Time, displayLength.Value, osuFrame.Position));
|
||||
|
||||
LoadComponentsAsync(newDrawables, drawables => InternalChildrenEnumerable = drawables, generationCancellationSource.Token);
|
||||
replayFrameIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ using osu.Game.Online.Rooms;
|
||||
using osu.Game.Online.Spectator;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osu.Game.Screens.Spectate;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
@ -24,6 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
/// <summary>
|
||||
/// A <see cref="SpectatorScreen"/> that spectates multiple users in a match.
|
||||
/// </summary>
|
||||
[Cached]
|
||||
public partial class MultiSpectatorScreen : SpectatorScreen
|
||||
{
|
||||
// Isolates beatmap/ruleset to this screen.
|
||||
@ -39,6 +41,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
/// </summary>
|
||||
public bool AllPlayersLoaded => instances.All(p => p.PlayerLoaded);
|
||||
|
||||
public bool SettingsAdded { get; private set; } = false;
|
||||
|
||||
protected override UserActivity InitialActivity => new UserActivity.SpectatingMultiplayerGame(Beatmap.Value.BeatmapInfo, Ruleset.Value);
|
||||
|
||||
[Resolved]
|
||||
@ -54,6 +58,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
private SpectatorSyncManager syncManager = null!;
|
||||
private PlayerGrid grid = null!;
|
||||
private MultiSpectatorLeaderboard leaderboard = null!;
|
||||
private FillFlowContainer leaderboardFlow = null!;
|
||||
private PlayerArea? currentAudioSource;
|
||||
|
||||
private readonly Room room;
|
||||
@ -73,10 +78,24 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
instances = new PlayerArea[Users.Count];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a settings group to the bottom of the side container. Intended to be used by rulesets to add spectate-specific settings.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings group to be shown.</param>
|
||||
public void AddSettingsAsync(PlayerSettingsGroup settings)
|
||||
{
|
||||
SettingsAdded = true;
|
||||
|
||||
LoadComponentAsync(settings, (loadedSettings) =>
|
||||
{
|
||||
loadedSettings.Expanded.Value = false;
|
||||
leaderboardFlow.Insert(2, loadedSettings);
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
FillFlowContainer leaderboardFlow;
|
||||
Container scoreDisplayContainer;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
|
@ -36,6 +36,7 @@ using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Users;
|
||||
@ -171,6 +172,16 @@ namespace osu.Game.Screens.Play
|
||||
Configuration = configuration ?? new PlayerConfiguration();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a settings group to the HUD overlay. Intended to be used by rulesets to add replay/spectate-specific settings.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings group to be shown.</param>
|
||||
public void AddSettings(PlayerSettingsGroup settings) => Schedule(() =>
|
||||
{
|
||||
settings.Expanded.Value = false;
|
||||
HUDOverlay.PlayerSettingsOverlay.Add(settings);
|
||||
});
|
||||
|
||||
private ScreenSuspensionHandler screenSuspension;
|
||||
|
||||
private DependencyContainer dependencies;
|
||||
|
@ -55,16 +55,6 @@ namespace osu.Game.Screens.Play
|
||||
this.createScore = createScore;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a settings group to the HUD overlay. Intended to be used by rulesets to add replay-specific settings.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings group to be shown.</param>
|
||||
public void AddSettings(PlayerSettingsGroup settings) => Schedule(() =>
|
||||
{
|
||||
settings.Expanded.Value = false;
|
||||
HUDOverlay.PlayerSettingsOverlay.Add(settings);
|
||||
});
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user