diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapInfoWedge.cs deleted file mode 100644 index 5b717887e2..0000000000 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapInfoWedge.cs +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Testing; -using osu.Game.Beatmaps; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Legacy; -using osu.Game.Screens.Select; -using osu.Game.Screens.SelectV2; - -namespace osu.Game.Tests.Visual.SongSelectV2 -{ - public partial class TestSceneBeatmapInfoWedge : SongSelectComponentsTestScene - { - private RulesetStore rulesets = null!; - private TestBeatmapInfoWedgeV2 infoWedge = null!; - private readonly List beatmaps = new List(); - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - this.rulesets = rulesets; - } - - public override void SetUpSteps() - { - base.SetUpSteps(); - - AddStep("reset mods", () => SelectedMods.SetDefault()); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - AddRange(new Drawable[] - { - // This exists only to make the wedge more visible in the test scene - new Box - { - Y = -20, - Colour = Colour4.Cornsilk.Darken(0.2f), - Height = BeatmapInfoWedgeV2.WEDGE_HEIGHT + 40, - Width = 0.65f, - RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Top = 20, Left = -10 } - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 20 }, - Child = infoWedge = new TestBeatmapInfoWedgeV2 - { - Width = 0.6f, - RelativeSizeAxes = Axes.X, - }, - } - }); - - AddSliderStep("change star difficulty", 0, 11.9, 5.55, v => - { - foreach (var hasCurrentValue in infoWedge.ChildrenOfType>()) - hasCurrentValue.Current.Value = new StarDifficulty(v, 0); - }); - } - - [Test] - public void TestRulesetChange() - { - selectBeatmap(Beatmap.Value.Beatmap); - - AddWaitStep("wait for select", 3); - - foreach (var rulesetInfo in rulesets.AvailableRulesets) - { - var instance = rulesetInfo.CreateInstance(); - var testBeatmap = createTestBeatmap(rulesetInfo); - - beatmaps.Add(testBeatmap); - - setRuleset(rulesetInfo); - - selectBeatmap(testBeatmap); - - testBeatmapLabels(instance); - } - } - - [Test] - public void TestWedgeVisibility() - { - AddStep("hide", () => { infoWedge.Hide(); }); - AddWaitStep("wait for hide", 3); - AddAssert("check visibility", () => infoWedge.Alpha == 0); - AddStep("show", () => { infoWedge.Show(); }); - AddWaitStep("wait for show", 1); - AddAssert("check visibility", () => infoWedge.Alpha > 0); - } - - private void testBeatmapLabels(Ruleset ruleset) - { - AddAssert("check title", () => infoWedge.Info!.TitleLabel.Current.Value == $"{ruleset.ShortName}Title"); - AddAssert("check artist", () => infoWedge.Info!.ArtistLabel.Current.Value == $"{ruleset.ShortName}Artist"); - } - - [Test] - public void TestTruncation() - { - selectBeatmap(createLongMetadata()); - } - - [Test] - public void TestNullBeatmapWithBackground() - { - selectBeatmap(null); - AddAssert("check default title", () => infoWedge.Info!.TitleLabel.Current.Value == Beatmap.Default.BeatmapInfo.Metadata.Title); - AddAssert("check default artist", () => infoWedge.Info!.ArtistLabel.Current.Value == Beatmap.Default.BeatmapInfo.Metadata.Artist); - AddAssert("check no info labels", () => !infoWedge.Info.ChildrenOfType().Any()); - } - - private void setRuleset(RulesetInfo rulesetInfo) - { - Container? containerBefore = null; - - AddStep("set ruleset", () => - { - // wedge content is only refreshed if the ruleset changes, so only wait for load in that case. - if (!rulesetInfo.Equals(Ruleset.Value)) - containerBefore = infoWedge.DisplayedContent; - - Ruleset.Value = rulesetInfo; - }); - - AddUntilStep("wait for async load", () => infoWedge.DisplayedContent != containerBefore); - } - - private void selectBeatmap(IBeatmap? b) - { - Container? containerBefore = null; - - AddStep($"select {b?.Metadata.Title ?? "null"} beatmap", () => - { - containerBefore = infoWedge.DisplayedContent; - infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : CreateWorkingBeatmap(b); - infoWedge.Show(); - }); - - AddUntilStep("wait for async load", () => infoWedge.DisplayedContent != containerBefore); - } - - private IBeatmap createTestBeatmap(RulesetInfo ruleset) - { - List objects = new List(); - for (double i = 0; i < 50000; i += 1000) - objects.Add(new TestHitObject { StartTime = i }); - - return new Beatmap - { - BeatmapInfo = new BeatmapInfo - { - Metadata = new BeatmapMetadata - { - Author = { Username = $"{ruleset.ShortName}Author" }, - Artist = $"{ruleset.ShortName}Artist", - Source = $"{ruleset.ShortName}Source", - Title = $"{ruleset.ShortName}Title" - }, - Ruleset = ruleset, - StarRating = 6, - DifficultyName = $"{ruleset.ShortName}Version", - Difficulty = new BeatmapDifficulty() - }, - HitObjects = objects - }; - } - - private IBeatmap createLongMetadata() - { - return new Beatmap - { - BeatmapInfo = new BeatmapInfo - { - Metadata = new BeatmapMetadata - { - Author = { Username = "WWWWWWWWWWWWWWW" }, - Artist = "Verrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Artist", - Source = "Verrrrry long Source", - Title = "Verrrrry long Title" - }, - DifficultyName = "Verrrrrrrrrrrrrrrrrrrrrrrrrrrrry long Version", - Status = BeatmapOnlineStatus.Graveyard, - }, - }; - } - - private partial class TestBeatmapInfoWedgeV2 : BeatmapInfoWedgeV2 - { - public new Container? DisplayedContent => base.DisplayedContent; - public new WedgeInfoText? Info => base.Info; - } - - private class TestHitObject : ConvertHitObject; - } -} diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneDifficultyNameContent.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneDifficultyNameContent.cs deleted file mode 100644 index 49e7e2bc1a..0000000000 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneDifficultyNameContent.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) ppy Pty Ltd . 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.Localisation; -using osu.Framework.Testing; -using osu.Game.Beatmaps; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Screens.SelectV2.Wedge; - -namespace osu.Game.Tests.Visual.SongSelectV2 -{ - public partial class TestSceneDifficultyNameContent : SongSelectComponentsTestScene - { - private DifficultyNameContent? difficultyNameContent; - - [Test] - public void TestLocalBeatmap() - { - AddStep("set component", () => Child = difficultyNameContent = new LocalDifficultyNameContent()); - - AddAssert("difficulty name is not set", () => LocalisableString.IsNullOrEmpty(difficultyNameContent.ChildrenOfType().Single().Text)); - AddAssert("author is not set", () => LocalisableString.IsNullOrEmpty(difficultyNameContent.ChildrenOfType().Single().ChildrenOfType().Single().Text)); - - AddStep("set beatmap", () => Beatmap.Value = CreateWorkingBeatmap(new Beatmap - { - BeatmapInfo = new BeatmapInfo - { - DifficultyName = "really long difficulty name that gets truncated", - Metadata = new BeatmapMetadata - { - Author = { Username = "really long username that is autosized" }, - }, - OnlineID = 1, - } - })); - - AddAssert("difficulty name is set", () => !LocalisableString.IsNullOrEmpty(difficultyNameContent.ChildrenOfType().Single().Text)); - AddAssert("author is set", () => !LocalisableString.IsNullOrEmpty(difficultyNameContent.ChildrenOfType().Single().ChildrenOfType().Single().Text)); - } - } -} diff --git a/osu.Game/Screens/SelectV2/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/SelectV2/BeatmapInfoWedgeV2.cs deleted file mode 100644 index b294896c77..0000000000 --- a/osu.Game/Screens/SelectV2/BeatmapInfoWedgeV2.cs +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Threading; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Localisation; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets; -using osu.Game.Screens.Select; -using osuTK; - -namespace osu.Game.Screens.SelectV2 -{ - public partial class BeatmapInfoWedgeV2 : VisibilityContainer - { - public const float WEDGE_HEIGHT = 120; - private const float shear_width = 21; - private const float transition_duration = 250; - private const float corner_radius = 10; - private const float colour_bar_width = 30; - - /// Todo: move this const out to song select when more new design elements are implemented for the beatmap details area, since it applies to text alignment of various elements - private const float text_margin = 62; - - private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / WEDGE_HEIGHT, 0); - - [Resolved] - private IBindable ruleset { get; set; } = null!; - - [Resolved] - private OsuColour colours { get; set; } = null!; - - [Resolved] - private BeatmapDifficultyCache difficultyCache { get; set; } = null!; - - protected Container? DisplayedContent { get; private set; } - - protected WedgeInfoText? Info { get; private set; } - - private Container difficultyColourBar = null!; - private StarCounter starCounter = null!; - private StarRatingDisplay starRatingDisplay = null!; - private BeatmapSetOnlineStatusPill statusPill = null!; - private Container content = null!; - - private IBindable? starDifficulty; - private CancellationTokenSource? cancellationSource; - - public BeatmapInfoWedgeV2() - { - Height = WEDGE_HEIGHT; - Shear = wedged_container_shear; - Masking = true; - Margin = new MarginPadding { Left = -corner_radius }; - EdgeEffect = new EdgeEffectParameters - { - Colour = Colour4.Black.Opacity(0.2f), - Type = EdgeEffectType.Shadow, - Radius = 3, - }; - CornerRadius = corner_radius; - } - - [BackgroundDependencyLoader] - private void load() - { - Child = content = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - // These elements can't be grouped with the rest of the content, due to being present either outside or under the backgrounds area - difficultyColourBar = new Container - { - Colour = Colour4.Transparent, - Depth = float.MaxValue, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Y, - - // By limiting the width we avoid this box showing up as an outline around the drawables that are on top of it. - Width = colour_bar_width + corner_radius, - Child = new Box { RelativeSizeAxes = Axes.Both } - }, - new Container - { - // Applying the shear to this container and nesting the starCounter inside avoids - // the deformation that occurs if the shear is applied to the starCounter whilst rotated - Shear = -wedged_container_shear, - X = -colour_bar_width / 2, - Anchor = Anchor.CentreRight, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = colour_bar_width, - Child = starCounter = new StarCounter - { - Rotation = (float)(Math.Atan(shear_width / WEDGE_HEIGHT) * (180 / Math.PI)), - Colour = Colour4.Transparent, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(0.35f), - Direction = FillDirection.Vertical - } - }, - new FillFlowContainer - { - Name = "Topright-aligned metadata", - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Top = 3, Right = colour_bar_width + 8 }, - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(0, 5), - Depth = float.MinValue, - Children = new Drawable[] - { - starRatingDisplay = new StarRatingDisplay(default, animated: true) - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Shear = -wedged_container_shear, - Alpha = 0, - }, - statusPill = new BeatmapSetOnlineStatusPill - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Shear = -wedged_container_shear, - TextSize = 11, - TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 }, - Alpha = 0, - } - } - }, - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ruleset.BindValueChanged(_ => updateDisplay()); - - starRatingDisplay.Current.BindValueChanged(s => - { - // use actual stars as star counter has its own animation - starCounter.Current = (float)s.NewValue.Stars; - }, true); - - starRatingDisplay.DisplayedStars.BindValueChanged(s => - { - // sync color with star rating display - starCounter.Colour = s.NewValue >= 6.5 ? colours.Orange1 : Colour4.Black.Opacity(0.75f); - difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); - }, true); - } - - private const double animation_duration = 600; - - protected override void PopIn() - { - this.MoveToX(0, animation_duration, Easing.OutQuint); - this.FadeIn(200, Easing.In); - } - - protected override void PopOut() - { - this.MoveToX(-150, animation_duration, Easing.OutQuint); - this.FadeOut(200, Easing.OutQuint); - } - - private WorkingBeatmap beatmap = null!; - - public WorkingBeatmap Beatmap - { - get => beatmap; - set - { - if (beatmap == value) return; - - beatmap = value; - - updateDisplay(); - } - } - - private Container? loadingInfo; - - private void updateDisplay() - { - statusPill.Status = beatmap.BeatmapInfo.Status; - - starDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); - - starDifficulty.BindValueChanged(s => - { - starRatingDisplay.Current.Value = s.NewValue ?? default; - - starRatingDisplay.FadeIn(transition_duration); - }); - - Scheduler.AddOnce(() => - { - LoadComponentAsync(loadingInfo = new Container - { - Padding = new MarginPadding { Right = colour_bar_width }, - RelativeSizeAxes = Axes.Both, - Depth = DisplayedContent?.Depth + 1 ?? 0, - Child = new Container - { - Masking = true, - CornerRadius = corner_radius, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - // TODO: New wedge design uses a coloured horizontal gradient for its background, however this lacks implementation information in the figma draft. - // pending https://www.figma.com/file/DXKwqZhD5yyb1igc3mKo1P?node-id=2980:3361#340801912 being answered. - new BeatmapInfoWedgeBackground(beatmap) { Shear = -Shear }, - Info = new WedgeInfoText(beatmap) { Shear = -Shear } - } - } - }, d => - { - // Ensure we are the most recent loaded wedge. - if (d != loadingInfo) return; - - removeOldInfo(); - content.Add(DisplayedContent = d); - }); - }); - - void removeOldInfo() - { - DisplayedContent?.FadeOut(transition_duration); - DisplayedContent?.Expire(); - DisplayedContent = null; - } - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - cancellationSource?.Cancel(); - } - - public partial class WedgeInfoText : Container - { - public OsuSpriteText TitleLabel { get; private set; } = null!; - public OsuSpriteText ArtistLabel { get; private set; } = null!; - - private readonly WorkingBeatmap working; - - public WedgeInfoText(WorkingBeatmap working) - { - this.working = working; - - RelativeSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load(SongSelect? songSelect, LocalisationManager localisation) - { - var metadata = working.Metadata; - - var titleText = new RomanisableString(metadata.TitleUnicode, metadata.Title); - var artistText = new RomanisableString(metadata.ArtistUnicode, metadata.Artist); - - Child = new FillFlowContainer - { - Name = "Top-left aligned metadata", - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Left = text_margin, Top = 12 }, - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Children = new Drawable[] - { - new OsuHoverContainer - { - AutoSizeAxes = Axes.Both, - Action = () => songSelect?.Search(titleText.GetPreferred(localisation.CurrentParameters.Value.PreferOriginalScript)), - Child = TitleLabel = new TruncatingSpriteText - { - Shadow = true, - Text = titleText, - Font = OsuFont.TorusAlternate.With(size: 40, weight: FontWeight.SemiBold), - }, - }, - new OsuHoverContainer - { - AutoSizeAxes = Axes.Both, - Action = () => songSelect?.Search(artistText.GetPreferred(localisation.CurrentParameters.Value.PreferOriginalScript)), - Child = ArtistLabel = new TruncatingSpriteText - { - // TODO : figma design has a diffused shadow, instead of the solid one present here, not possible currently as far as i'm aware. - Shadow = true, - Text = artistText, - // Not sure if this should be semi bold or medium - Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold), - }, - }, - } - }; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - // best effort to confine the auto-sized text to wedge bounds - // the artist label doesn't have an extra text_margin as it doesn't touch the right metadata - TitleLabel.MaxWidth = DrawWidth - text_margin * 2 - shear_width; - ArtistLabel.MaxWidth = DrawWidth - text_margin - shear_width; - } - } - } -} diff --git a/osu.Game/Screens/SelectV2/Wedge/DifficultyNameContent.cs b/osu.Game/Screens/SelectV2/Wedge/DifficultyNameContent.cs deleted file mode 100644 index 4a3dc34cf9..0000000000 --- a/osu.Game/Screens/SelectV2/Wedge/DifficultyNameContent.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) ppy Pty Ltd . 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.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Localisation; -using osu.Game.Overlays; - -namespace osu.Game.Screens.SelectV2.Wedge -{ - public abstract partial class DifficultyNameContent : CompositeDrawable - { - protected OsuSpriteText DifficultyName = null!; - private OsuSpriteText mappedByLabel = null!; - protected OsuHoverContainer MapperLink = null!; - protected OsuSpriteText MapperName = null!; - - protected DifficultyNameContent() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChild = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - DifficultyName = new TruncatingSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(weight: FontWeight.SemiBold), - }, - mappedByLabel = new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - // TODO: better null display? beatmap carousel panels also just show this text currently. - Text = " mapped by ", - Font = OsuFont.GetFont(size: 14), - }, - // This is not a `LinkFlowContainer` as there are single-frame layout issues when Update() - // is being used for layout, see https://github.com/ppy/osu-framework/issues/3369. - MapperLink = new MapperLinkContainer - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - AutoSizeAxes = Axes.Both, - Child = MapperName = new OsuSpriteText - { - Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 14), - } - }, - } - }; - } - - protected override void Update() - { - base.Update(); - - // truncate difficulty name when width exceeds bounds, prioritizing mapper name display - DifficultyName.MaxWidth = Math.Max(DrawWidth - mappedByLabel.DrawWidth - - MapperName.DrawWidth, 0); - } - - private partial class MapperLinkContainer : OsuHoverContainer - { - [BackgroundDependencyLoader] - private void load(OverlayColourProvider? overlayColourProvider, OsuColour colours) - { - TooltipText = ContextMenuStrings.ViewProfile; - IdleColour = overlayColourProvider?.Light2 ?? colours.Blue; - } - } - } -} diff --git a/osu.Game/Screens/SelectV2/Wedge/LocalDifficultyNameContent.cs b/osu.Game/Screens/SelectV2/Wedge/LocalDifficultyNameContent.cs deleted file mode 100644 index 66f8cb02b2..0000000000 --- a/osu.Game/Screens/SelectV2/Wedge/LocalDifficultyNameContent.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Game.Beatmaps; -using osu.Game.Online; -using osu.Game.Online.Chat; - -namespace osu.Game.Screens.SelectV2.Wedge -{ - public partial class LocalDifficultyNameContent : DifficultyNameContent - { - [Resolved] - private IBindable beatmap { get; set; } = null!; - - [Resolved] - private ILinkHandler? linkHandler { get; set; } - - protected override void LoadComplete() - { - base.LoadComplete(); - - beatmap.BindValueChanged(b => - { - DifficultyName.Text = b.NewValue.BeatmapInfo.DifficultyName; - - // TODO: should be the mapper of the guest difficulty, but that isn't stored correctly yet (see https://github.com/ppy/osu/issues/12965) - MapperName.Text = b.NewValue.Metadata.Author.Username; - MapperLink.Action = () => linkHandler?.HandleLink(new LinkDetails(LinkAction.OpenUserProfile, b.NewValue.Metadata.Author)); - }, true); - } - } -}