mirror of
https://github.com/ppy/osu.git
synced 2024-11-15 01:57:51 +08:00
Various renaming and class updates to allow multiple menu banners
This commit is contained in:
parent
77660e57ea
commit
ef2a16dd8f
@ -13,30 +13,48 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
{
|
{
|
||||||
public partial class TestSceneMainMenu : OsuGameTestScene
|
public partial class TestSceneMainMenu : OsuGameTestScene
|
||||||
{
|
{
|
||||||
private SystemTitle systemTitle => Game.ChildrenOfType<SystemTitle>().Single();
|
private OnlineMenuBanner onlineMenuBanner => Game.ChildrenOfType<OnlineMenuBanner>().Single();
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSystemTitle()
|
public void TestOnlineMenuBanner()
|
||||||
{
|
{
|
||||||
AddStep("set system title", () => systemTitle.Current.Value = new APISystemTitle
|
AddStep("set online content", () => onlineMenuBanner.Current.Value = new APIMenuContent
|
||||||
{
|
{
|
||||||
Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png",
|
Images = new[]
|
||||||
Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023",
|
{
|
||||||
|
new APIMenuImage
|
||||||
|
{
|
||||||
|
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",
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
AddAssert("system title not visible", () => systemTitle.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
AddAssert("system title not visible", () => onlineMenuBanner.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||||
AddStep("enter menu", () => InputManager.Key(Key.Enter));
|
AddStep("enter menu", () => InputManager.Key(Key.Enter));
|
||||||
AddUntilStep("system title visible", () => systemTitle.State.Value, () => Is.EqualTo(Visibility.Visible));
|
AddUntilStep("system title visible", () => onlineMenuBanner.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||||
AddStep("set another title", () => systemTitle.Current.Value = new APISystemTitle
|
AddStep("set another title", () => onlineMenuBanner.Current.Value = new APIMenuContent
|
||||||
{
|
{
|
||||||
Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png",
|
Images = new[]
|
||||||
Url = @"https://osu.ppy.sh/community/contests/189",
|
{
|
||||||
|
new APIMenuImage
|
||||||
|
{
|
||||||
|
Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png",
|
||||||
|
Url = @"https://osu.ppy.sh/community/contests/189",
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
AddStep("set title with nonexistent image", () => systemTitle.Current.Value = new APISystemTitle
|
AddStep("set title with nonexistent image", () => onlineMenuBanner.Current.Value = new APIMenuContent
|
||||||
{
|
{
|
||||||
Image = @"https://test.invalid/@2x", // .invalid TLD reserved by https://datatracker.ietf.org/doc/html/rfc2606#section-2
|
Images = new[]
|
||||||
Url = @"https://osu.ppy.sh/community/contests/189",
|
{
|
||||||
|
new APIMenuImage
|
||||||
|
{
|
||||||
|
Image = @"https://test.invalid/@2x", // .invalid TLD reserved by https://datatracker.ietf.org/doc/html/rfc2606#section-2
|
||||||
|
Url = @"https://osu.ppy.sh/community/contests/189",
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
AddStep("unset system title", () => systemTitle.Current.Value = null);
|
AddStep("unset system title", () => onlineMenuBanner.Current.Value = new APIMenuContent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ using osu.Game.Online.API.Requests.Responses;
|
|||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.API.Requests
|
||||||
{
|
{
|
||||||
public class GetSystemTitleRequest : OsuJsonWebRequest<APISystemTitle>
|
public class GetMenuContentRequest : OsuJsonWebRequest<APIMenuContent>
|
||||||
{
|
{
|
||||||
public GetSystemTitleRequest()
|
public GetMenuContentRequest()
|
||||||
: base(@"https://assets.ppy.sh/lazer-status.json")
|
: base(@"https://assets.ppy.sh/lazer-status.json")
|
||||||
{
|
{
|
||||||
}
|
}
|
42
osu.Game/Online/API/Requests/Responses/APIMenuContent.cs
Normal file
42
osu.Game/Online/API/Requests/Responses/APIMenuContent.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// 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 Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.API.Requests.Responses
|
||||||
|
{
|
||||||
|
public class APIMenuContent : IEquatable<APIMenuContent>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Images which should be displayed in rotation.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(@"images")]
|
||||||
|
public APIMenuImage[] Images { get; init; } = Array.Empty<APIMenuImage>();
|
||||||
|
|
||||||
|
public DateTimeOffset LastUpdated { get; init; }
|
||||||
|
|
||||||
|
public bool Equals(APIMenuContent? other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, other)) return false;
|
||||||
|
if (ReferenceEquals(this, other)) return true;
|
||||||
|
|
||||||
|
return LastUpdated.Equals(other.LastUpdated);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
|
||||||
|
if (obj.GetType() != GetType()) return false;
|
||||||
|
|
||||||
|
return Equals((APIMenuContent)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return LastUpdated.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
osu.Game/Online/API/Requests/Responses/APIMenuImage.cs
Normal file
57
osu.Game/Online/API/Requests/Responses/APIMenuImage.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// 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 Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.API.Requests.Responses
|
||||||
|
{
|
||||||
|
public class APIMenuImage : IEquatable<APIMenuImage>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A URL pointing to the image which should be displayed. Generally should be an @2x image filename.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(@"image")]
|
||||||
|
public string Image { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A URL that should be opened on clicking the image.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(@"url")]
|
||||||
|
public string Url { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time at which this item should begin displaying. If <c>null</c>, will display immediately.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(@"begins")]
|
||||||
|
public DateTimeOffset? Begins { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time at which this item should stop displaying. If <c>null</c>, will display indefinitely.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(@"expires")]
|
||||||
|
public DateTimeOffset? Expires { get; set; }
|
||||||
|
|
||||||
|
public bool Equals(APIMenuImage? other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, other)) return false;
|
||||||
|
if (ReferenceEquals(this, other)) return true;
|
||||||
|
|
||||||
|
return Image == other.Image && Url == other.Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
if (obj.GetType() != GetType()) return false;
|
||||||
|
|
||||||
|
return Equals((APIMenuImage)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(Image, Url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +0,0 @@
|
|||||||
// 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 Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests.Responses
|
|
||||||
{
|
|
||||||
public class APISystemTitle : IEquatable<APISystemTitle>
|
|
||||||
{
|
|
||||||
[JsonProperty(@"image")]
|
|
||||||
public string Image { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[JsonProperty(@"url")]
|
|
||||||
public string Url { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public bool Equals(APISystemTitle? other)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(null, other)) return false;
|
|
||||||
if (ReferenceEquals(this, other)) return true;
|
|
||||||
|
|
||||||
return Image == other.Image && Url == other.Url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object? obj) => obj is APISystemTitle other && Equals(other);
|
|
||||||
|
|
||||||
// ReSharper disable NonReadonlyMemberInGetHashCode
|
|
||||||
public override int GetHashCode() => HashCode.Combine(Image, Url);
|
|
||||||
}
|
|
||||||
}
|
|
@ -98,7 +98,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
private ParallaxContainer buttonsContainer;
|
private ParallaxContainer buttonsContainer;
|
||||||
private SongTicker songTicker;
|
private SongTicker songTicker;
|
||||||
private Container logoTarget;
|
private Container logoTarget;
|
||||||
private SystemTitle systemTitle;
|
private OnlineMenuBanner onlineMenuBanner;
|
||||||
private MenuTip menuTip;
|
private MenuTip menuTip;
|
||||||
private FillFlowContainer bottomElementsFlow;
|
private FillFlowContainer bottomElementsFlow;
|
||||||
private SupporterDisplay supporterDisplay;
|
private SupporterDisplay supporterDisplay;
|
||||||
@ -178,7 +178,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
},
|
},
|
||||||
systemTitle = new SystemTitle
|
onlineMenuBanner = new OnlineMenuBanner
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
@ -201,12 +201,12 @@ namespace osu.Game.Screens.Menu
|
|||||||
case ButtonSystemState.Initial:
|
case ButtonSystemState.Initial:
|
||||||
case ButtonSystemState.Exit:
|
case ButtonSystemState.Exit:
|
||||||
ApplyToBackground(b => b.FadeColour(Color4.White, 500, Easing.OutSine));
|
ApplyToBackground(b => b.FadeColour(Color4.White, 500, Easing.OutSine));
|
||||||
systemTitle.State.Value = Visibility.Hidden;
|
onlineMenuBanner.State.Value = Visibility.Hidden;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ApplyToBackground(b => b.FadeColour(OsuColour.Gray(0.8f), 500, Easing.OutSine));
|
ApplyToBackground(b => b.FadeColour(OsuColour.Gray(0.8f), 500, Easing.OutSine));
|
||||||
systemTitle.State.Value = Visibility.Visible;
|
onlineMenuBanner.State.Value = Visibility.Visible;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -18,42 +19,28 @@ using osu.Game.Online.API.Requests.Responses;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.Menu
|
namespace osu.Game.Screens.Menu
|
||||||
{
|
{
|
||||||
public partial class SystemTitle : VisibilityContainer
|
public partial class OnlineMenuBanner : VisibilityContainer
|
||||||
{
|
{
|
||||||
internal Bindable<APISystemTitle?> Current { get; } = new Bindable<APISystemTitle?>();
|
internal Bindable<APIMenuContent> Current { get; } = new Bindable<APIMenuContent>(new APIMenuContent());
|
||||||
|
|
||||||
private const float transition_duration = 500;
|
private const float transition_duration = 500;
|
||||||
|
|
||||||
private Container content = null!;
|
private Container content = null!;
|
||||||
private CancellationTokenSource? cancellationTokenSource;
|
private CancellationTokenSource? cancellationTokenSource;
|
||||||
private SystemTitleImage? currentImage;
|
private MenuImage? currentImage;
|
||||||
|
|
||||||
private ScheduledDelegate? openUrlAction;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuGame? game)
|
private void load()
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
AutoSizeDuration = transition_duration;
|
AutoSizeDuration = transition_duration;
|
||||||
AutoSizeEasing = Easing.OutQuint;
|
AutoSizeEasing = Easing.OutQuint;
|
||||||
|
|
||||||
InternalChild = content = new OsuClickableContainer
|
InternalChild = content = new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Action = () =>
|
|
||||||
{
|
|
||||||
currentImage?.Flash();
|
|
||||||
|
|
||||||
// Delay slightly to allow animation to play out.
|
|
||||||
openUrlAction?.Cancel();
|
|
||||||
openUrlAction = Scheduler.AddDelayed(() =>
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(Current.Value?.Url))
|
|
||||||
game?.HandleLink(Current.Value.Url);
|
|
||||||
}, 250);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +85,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
private void checkForUpdates()
|
private void checkForUpdates()
|
||||||
{
|
{
|
||||||
var request = new GetSystemTitleRequest();
|
var request = new GetMenuContentRequest();
|
||||||
Task.Run(() => request.Perform())
|
Task.Run(() => request.Perform())
|
||||||
.ContinueWith(r =>
|
.ContinueWith(r =>
|
||||||
{
|
{
|
||||||
@ -121,12 +108,12 @@ namespace osu.Game.Screens.Menu
|
|||||||
cancellationTokenSource = null;
|
cancellationTokenSource = null;
|
||||||
currentImage?.FadeOut(500, Easing.OutQuint).Expire();
|
currentImage?.FadeOut(500, Easing.OutQuint).Expire();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Current.Value?.Image))
|
if (Current.Value.Images.Length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LoadComponentAsync(new SystemTitleImage(Current.Value), loaded =>
|
LoadComponentAsync(new MenuImage(Current.Value.Images.First()), loaded =>
|
||||||
{
|
{
|
||||||
if (!loaded.SystemTitle.Equals(Current.Value))
|
if (!loaded.Image.Equals(Current.Value.Images.First()))
|
||||||
loaded.Dispose();
|
loaded.Dispose();
|
||||||
|
|
||||||
content.Add(currentImage = loaded);
|
content.Add(currentImage = loaded);
|
||||||
@ -134,22 +121,24 @@ namespace osu.Game.Screens.Menu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[LongRunningLoad]
|
[LongRunningLoad]
|
||||||
private partial class SystemTitleImage : CompositeDrawable
|
private partial class MenuImage : OsuClickableContainer
|
||||||
{
|
{
|
||||||
public readonly APISystemTitle SystemTitle;
|
public readonly APIMenuImage Image;
|
||||||
|
|
||||||
private Sprite flash = null!;
|
private Sprite flash = null!;
|
||||||
|
|
||||||
public SystemTitleImage(APISystemTitle systemTitle)
|
private ScheduledDelegate? openUrlAction;
|
||||||
|
|
||||||
|
public MenuImage(APIMenuImage image)
|
||||||
{
|
{
|
||||||
SystemTitle = systemTitle;
|
Image = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(LargeTextureStore textureStore)
|
private void load(LargeTextureStore textureStore, OsuGame game)
|
||||||
{
|
{
|
||||||
Texture? texture = textureStore.Get(SystemTitle.Image);
|
Texture? texture = textureStore.Get(Image.Image);
|
||||||
if (texture != null && SystemTitle.Image.Contains(@"@2x"))
|
if (texture != null && Image.Image.Contains(@"@2x"))
|
||||||
texture.ScaleAdjust *= 2;
|
texture.ScaleAdjust *= 2;
|
||||||
|
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
@ -163,6 +152,19 @@ namespace osu.Game.Screens.Menu
|
|||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Action = () =>
|
||||||
|
{
|
||||||
|
Flash();
|
||||||
|
|
||||||
|
// Delay slightly to allow animation to play out.
|
||||||
|
openUrlAction?.Cancel();
|
||||||
|
openUrlAction = Scheduler.AddDelayed(() =>
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(Image.Url))
|
||||||
|
game?.HandleLink(Image.Url);
|
||||||
|
}, 250);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
Loading…
Reference in New Issue
Block a user