mirror of
https://github.com/ppy/osu.git
synced 2026-05-30 20:33:01 +08:00
Add replay / spectator mode scrolling text back (#36911)
As mentioned in https://github.com/ppy/osu/discussions/36883. This has caught me off-guard a few times. Was a quick one to make this work like it does on stable. It doesn't fit as well as stable because we have a lot of elements at the top of the screen, but I think it's better than nothing, as it lets you know you're in a replay quick obviously. I don't think we can easily localise strings with formatting in them yet. Maybe using a `MarkdownContainer` or something?
This commit is contained in:
committed by
GitHub
Unverified
parent
4c0657f4ca
commit
d0d5d97cfe
@@ -67,7 +67,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
AddAssert("mapped by text not present", () =>
|
||||
this.ChildrenOfType<OsuSpriteText>().All(spriteText => !containsAny(spriteText.Text.ToString(), "mapped", "by")));
|
||||
|
||||
AddAssert("play time displayed", () => this.ChildrenOfType<ExpandedPanelMiddleContent.PlayedOnText>().Any());
|
||||
AddAssert("play time displayed", () => this.ChildrenOfType<PlayedOnText>().Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -137,7 +137,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
showPanel(score);
|
||||
});
|
||||
|
||||
AddAssert("play time not displayed", () => !this.ChildrenOfType<ExpandedPanelMiddleContent.PlayedOnText>().Any());
|
||||
AddAssert("play time not displayed", () => !this.ChildrenOfType<PlayedOnText>().Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
@@ -20,6 +21,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
Replay = replayData.Replay,
|
||||
ScoreInfo =
|
||||
{
|
||||
Date = DateTimeOffset.Now,
|
||||
User = new APIUser
|
||||
{
|
||||
Id = replayData.User.OnlineID,
|
||||
|
||||
@@ -311,7 +311,7 @@ namespace osu.Game.Screens.Play
|
||||
{
|
||||
// underlay and gameplay should have access to the skinning sources.
|
||||
createUnderlayComponents(Beatmap.Value),
|
||||
createGameplayComponents(Beatmap.Value)
|
||||
createGameplayComponents()
|
||||
}
|
||||
},
|
||||
FailOverlay = new FailOverlay
|
||||
@@ -426,6 +426,11 @@ namespace osu.Game.Screens.Play
|
||||
IsBreakTime.BindValueChanged(onBreakTimeChanged, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement to add any components which should exist above gameplay but below the HUD.
|
||||
/// </summary>
|
||||
protected virtual Drawable CreateOverlayComponents() => Empty();
|
||||
|
||||
protected virtual GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart) => new MasterGameplayClockContainer(beatmap, gameplayStart);
|
||||
|
||||
private Drawable createUnderlayComponents(WorkingBeatmap working)
|
||||
@@ -451,7 +456,7 @@ namespace osu.Game.Screens.Play
|
||||
return container;
|
||||
}
|
||||
|
||||
private Drawable createGameplayComponents(IWorkingBeatmap working) => new ScalingContainer(ScalingMode.Gameplay)
|
||||
private Drawable createGameplayComponents() => new ScalingContainer(ScalingMode.Gameplay)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@@ -474,6 +479,7 @@ namespace osu.Game.Screens.Play
|
||||
Children = new[]
|
||||
{
|
||||
DimmableStoryboard.OverlayLayerContainer.CreateProxy(),
|
||||
CreateOverlayComponents(),
|
||||
HUDOverlay = new HUDOverlay(DrawableRuleset, GameplayState.Mods, Configuration)
|
||||
{
|
||||
HoldToQuit =
|
||||
|
||||
@@ -12,12 +12,15 @@ using osu.Framework.Input.Events;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Screens.Ranking.Expanded;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Users;
|
||||
|
||||
@@ -97,6 +100,7 @@ namespace osu.Game.Screens.Play
|
||||
playbackSettings.UserPlaybackRate.BindTo(master.UserPlaybackRate);
|
||||
|
||||
HUDOverlay.PlayerSettingsOverlay.AddAtStart(playbackSettings);
|
||||
|
||||
AddInternal(new RulesetSkinProvidingContainer(GameplayState.Ruleset, GameplayState.Beatmap, Beatmap.Value.Skin)
|
||||
{
|
||||
Child = failIndicator = new ReplayFailIndicator(GameplayClockContainer)
|
||||
@@ -113,6 +117,27 @@ namespace osu.Game.Screens.Play
|
||||
});
|
||||
}
|
||||
|
||||
protected override Drawable CreateOverlayComponents()
|
||||
{
|
||||
OsuTextFlowContainer message = new OsuTextFlowContainer(cp => cp.Font = OsuFont.Style.Body) { AutoSizeAxes = Axes.Both };
|
||||
message.AddText("Watching ");
|
||||
message.AddText(Score.ScoreInfo.User.Username, s => s.Font = s.Font.With(weight: FontWeight.SemiBold));
|
||||
message.AddText(" play ");
|
||||
message.AddText(Beatmap.Value.BeatmapInfo.GetDisplayTitleRomanisable(), s => s.Font = s.Font.With(weight: FontWeight.SemiBold));
|
||||
message.AddText(" on ");
|
||||
message.AddArbitraryDrawable(new PlayedOnText(Score.ScoreInfo.Date, false)
|
||||
{
|
||||
Font = OsuFont.Style.Body.With(weight: FontWeight.SemiBold),
|
||||
});
|
||||
|
||||
return new ScrollingMessage(message)
|
||||
{
|
||||
Y = 100,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void PrepareReplay()
|
||||
{
|
||||
DrawableRuleset?.SetReplayScore(Score);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public partial class ScrollingMessage : CompositeDrawable
|
||||
{
|
||||
private readonly Drawable messageContent;
|
||||
|
||||
public ScrollingMessage(Drawable messageContent)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChild = this.messageContent = messageContent;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
this.FadeInFromZero(2000, Easing.OutQuint);
|
||||
resetMessagePosition();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (messageContent.X + messageContent.DrawWidth > 0)
|
||||
messageContent.X -= (float)Clock.ElapsedFrameTime * 0.05f;
|
||||
else
|
||||
resetMessagePosition();
|
||||
}
|
||||
|
||||
private void resetMessagePosition()
|
||||
{
|
||||
messageContent.X = DrawWidth + 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Online.Spectator;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.Replays.Types;
|
||||
@@ -29,17 +29,23 @@ namespace osu.Game.Screens.Play
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
protected override Drawable CreateOverlayComponents()
|
||||
{
|
||||
AddInternal(new OsuSpriteText
|
||||
// TODO: This should be customised for `MultiplayerSpectatorPlayer` to be static and only show the player name.
|
||||
// Or maybe we should completely redesign this to show the user avatar and other things if that happens.
|
||||
OsuTextFlowContainer message = new OsuTextFlowContainer(cp => cp.Font = OsuFont.Style.Body) { AutoSizeAxes = Axes.Both };
|
||||
message.AddText("Watching ");
|
||||
message.AddText(Score.ScoreInfo.User.Username, s => s.Font = s.Font.With(weight: FontWeight.SemiBold));
|
||||
message.AddText(" play ");
|
||||
message.AddText(Beatmap.Value.BeatmapInfo.GetDisplayTitleRomanisable(), s => s.Font = s.Font.With(weight: FontWeight.SemiBold));
|
||||
message.AddText(" live", s => s.Font = s.Font.With(weight: FontWeight.Bold));
|
||||
|
||||
return new ScrollingMessage(message)
|
||||
{
|
||||
Text = $"Watching {score.ScoreInfo.User.Username} playing live!",
|
||||
Font = OsuFont.Default.With(size: 30),
|
||||
Y = 100,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.LocalisationExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
@@ -237,7 +233,7 @@ namespace osu.Game.Screens.Ranking.Expanded
|
||||
});
|
||||
|
||||
if (score.Date != default)
|
||||
AddInternal(new PlayedOnText(score.Date));
|
||||
AddInternal(new PlayedOnText(score.Date, true));
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -268,40 +264,6 @@ namespace osu.Game.Screens.Ranking.Expanded
|
||||
});
|
||||
}
|
||||
|
||||
public partial class PlayedOnText : OsuSpriteText
|
||||
{
|
||||
private readonly DateTimeOffset time;
|
||||
private readonly Bindable<bool> prefer24HourTime = new Bindable<bool>();
|
||||
|
||||
public PlayedOnText(DateTimeOffset time)
|
||||
{
|
||||
this.time = time;
|
||||
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Origin = Anchor.BottomCentre;
|
||||
Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager configManager)
|
||||
{
|
||||
configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
prefer24HourTime.BindValueChanged(_ => updateDisplay(), true);
|
||||
}
|
||||
|
||||
private void updateDisplay()
|
||||
{
|
||||
Text = LocalisableString.Format("Played on {0}",
|
||||
time.ToLocalTime().ToLocalisableString(prefer24HourTime.Value ? @"d MMMM yyyy HH:mm" : @"d MMMM yyyy h:mm tt"));
|
||||
}
|
||||
}
|
||||
|
||||
internal partial class ClickableMetadata : OsuHoverContainer
|
||||
{
|
||||
[Resolved]
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.LocalisationExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Screens.Ranking.Expanded
|
||||
{
|
||||
public partial class PlayedOnText : OsuSpriteText
|
||||
{
|
||||
private readonly DateTimeOffset time;
|
||||
private readonly bool withPrefix;
|
||||
private readonly Bindable<bool> prefer24HourTime = new Bindable<bool>();
|
||||
|
||||
public PlayedOnText(DateTimeOffset time, bool withPrefix)
|
||||
{
|
||||
this.time = time;
|
||||
this.withPrefix = withPrefix;
|
||||
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Origin = Anchor.BottomCentre;
|
||||
Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager configManager)
|
||||
{
|
||||
configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
prefer24HourTime.BindValueChanged(_ => updateDisplay(), true);
|
||||
}
|
||||
|
||||
private void updateDisplay()
|
||||
{
|
||||
var timeText = time.ToLocalTime().ToLocalisableString(prefer24HourTime.Value ? @"d MMMM yyyy HH:mm" : @"d MMMM yyyy h:mm tt");
|
||||
|
||||
if (withPrefix)
|
||||
Text = LocalisableString.Format("Played on {0}", timeText);
|
||||
else
|
||||
Text = timeText;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user