1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-13 07:43:00 +08:00

Implement visual appearance of "system title" message in main menu

This commit is contained in:
Bartłomiej Dach 2023-12-27 23:07:17 +01:00
parent 28f5e90aba
commit d9299a8a55
No known key found for this signature in database
5 changed files with 166 additions and 1 deletions

View File

@ -0,0 +1,30 @@
// 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.Linq;
using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Screens.Menu;
namespace osu.Game.Tests.Visual.Menus
{
public partial class TestSceneMainMenu : OsuGameTestScene
{
[Test]
public void TestSystemTitle()
{
AddStep("set system title", () => Game.ChildrenOfType<SystemTitle>().Single().Current.Value = new APISystemTitle
{
Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png",
Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023",
});
AddStep("set another title", () => Game.ChildrenOfType<SystemTitle>().Single().Current.Value = new APISystemTitle
{
Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png",
Url = @"https://osu.ppy.sh/community/contests/189",
});
AddStep("unset system title", () => Game.ChildrenOfType<SystemTitle>().Single().Current.Value = null);
}
}
}

View File

@ -0,0 +1,16 @@
// 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 Newtonsoft.Json;
namespace osu.Game.Online.API.Requests.Responses
{
public class APISystemTitle
{
[JsonProperty(@"image")]
public string Image { get; set; } = string.Empty;
[JsonProperty(@"url")]
public string Url { get; set; } = string.Empty;
}
}

View File

@ -995,7 +995,10 @@ namespace osu.Game
}, topMostOverlayContent.Add);
if (!args?.Any(a => a == @"--no-version-overlay") ?? true)
loadComponentSingleFile(versionManager = new VersionManager { Depth = int.MinValue }, ScreenContainer.Add);
{
dependencies.Cache(versionManager = new VersionManager { Depth = int.MinValue });
loadComponentSingleFile(versionManager, ScreenContainer.Add);
}
loadComponentSingleFile(osuLogo, _ =>
{

View File

@ -76,6 +76,9 @@ namespace osu.Game.Screens.Menu
[Resolved(canBeNull: true)]
private IDialogOverlay dialogOverlay { get; set; }
[Resolved(canBeNull: true)]
private VersionManager versionManager { get; set; }
protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault();
protected override bool PlayExitSound => false;
@ -91,6 +94,7 @@ namespace osu.Game.Screens.Menu
private ParallaxContainer buttonsContainer;
private SongTicker songTicker;
private Container logoTarget;
private SystemTitle systemTitle;
private Sample reappearSampleSwoosh;
@ -153,6 +157,7 @@ namespace osu.Game.Screens.Menu
Margin = new MarginPadding { Right = 15, Top = 5 }
},
new KiaiMenuFountains(),
systemTitle = new SystemTitle(),
holdToExitGameOverlay?.CreateProxy() ?? Empty()
});
@ -263,6 +268,16 @@ namespace osu.Game.Screens.Menu
}
}
protected override void Update()
{
base.Update();
systemTitle.Margin = new MarginPadding
{
Bottom = (versionManager?.DrawHeight + 5) ?? 0
};
}
protected override void LogoSuspending(OsuLogo logo)
{
var seq = logo.FadeOut(300, Easing.InSine)

View File

@ -0,0 +1,101 @@
// 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.Threading;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Input.Events;
using osu.Framework.Platform;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Screens.Menu
{
public partial class SystemTitle : CompositeDrawable
{
internal Bindable<APISystemTitle?> Current { get; } = new Bindable<APISystemTitle?>();
private Container content = null!;
private CancellationTokenSource? cancellationTokenSource;
private SystemTitleImage? currentImage;
[BackgroundDependencyLoader]
private void load(GameHost? gameHost)
{
Anchor = Anchor.BottomCentre;
Origin = Anchor.BottomCentre;
AutoSizeAxes = Axes.Both;
InternalChild = content = new ClickableContainer
{
AutoSizeAxes = Axes.Both,
Action = () =>
{
if (!string.IsNullOrEmpty(Current.Value?.Url))
gameHost?.OpenUrlExternally(Current.Value.Url);
}
};
}
protected override bool OnHover(HoverEvent e)
{
content.ScaleTo(1.1f, 500, Easing.OutBounce);
return base.OnHover(e);
}
protected override void OnHoverLost(HoverLostEvent e)
{
content.ScaleTo(1f, 500, Easing.OutBounce);
base.OnHoverLost(e);
}
protected override void LoadComplete()
{
base.LoadComplete();
Current.BindValueChanged(_ => loadNewImage(), true);
}
private void loadNewImage()
{
cancellationTokenSource?.Cancel();
cancellationTokenSource = null;
currentImage?.FadeOut(500, Easing.OutQuint).Expire();
if (string.IsNullOrEmpty(Current.Value?.Image))
return;
LoadComponentAsync(new SystemTitleImage(Current.Value), loaded =>
{
if (loaded.SystemTitle != Current.Value)
loaded.Dispose();
loaded.FadeInFromZero(500, Easing.OutQuint);
content.Add(currentImage = loaded);
}, (cancellationTokenSource ??= new CancellationTokenSource()).Token);
}
[LongRunningLoad]
private partial class SystemTitleImage : Sprite
{
public readonly APISystemTitle SystemTitle;
public SystemTitleImage(APISystemTitle systemTitle)
{
SystemTitle = systemTitle;
}
[BackgroundDependencyLoader]
private void load(LargeTextureStore textureStore)
{
var texture = textureStore.Get(SystemTitle.Image);
if (SystemTitle.Image.Contains(@"@2x"))
texture.ScaleAdjust *= 2;
Texture = texture;
}
}
}
}