From f561120295d392678a19d5a8a578da272a082bc0 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sat, 7 Jan 2023 23:40:02 +0100 Subject: [PATCH 001/196] Remove info labels, since they are no longer present in this component in thew new design --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 356 ++++++++++++++++++ 1 file changed, 356 insertions(+) create mode 100644 osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs new file mode 100644 index 0000000000..4d1a2133fd --- /dev/null +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -0,0 +1,356 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using System.Collections.Generic; +using System.Threading; +using osuTK; +using osuTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Effects; +using osu.Framework.Localisation; +using osu.Game.Configuration; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Screens.Select +{ + public partial class BeatmapInfoWedgeV2 : VisibilityContainer + { + public const float BORDER_THICKNESS = 2.5f; + private const float shear_width = 36.75f; + + private const float transition_duration = 250; + + private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / SongSelect.WEDGE_HEIGHT, 0); + + [Resolved] + private IBindable ruleset { get; set; } + + protected Container DisplayedContent { get; private set; } + + protected WedgeInfoText Info { get; private set; } + + public BeatmapInfoWedgeV2() + { + Shear = wedged_container_shear; + Masking = true; + BorderColour = new Color4(221, 255, 255, 255); + BorderThickness = BORDER_THICKNESS; + Alpha = 0; + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = new Color4(130, 204, 255, 150), + Radius = 20, + Roundness = 15, + }; + } + + [BackgroundDependencyLoader] + private void load() + { + ruleset.BindValueChanged(_ => updateDisplay()); + } + + private const double animation_duration = 800; + + protected override void PopIn() + { + this.MoveToX(0, animation_duration, Easing.OutQuint); + this.RotateTo(0, animation_duration, Easing.OutQuint); + this.FadeIn(transition_duration); + } + + protected override void PopOut() + { + this.MoveToX(-100, animation_duration, Easing.In); + this.RotateTo(10, animation_duration, Easing.In); + this.FadeOut(transition_duration * 2, Easing.In); + } + + private WorkingBeatmap beatmap; + + public WorkingBeatmap Beatmap + { + get => beatmap; + set + { + if (beatmap == value) return; + + beatmap = value; + + updateDisplay(); + } + } + + public override bool IsPresent => base.IsPresent || DisplayedContent == null; // Visibility is updated in the LoadComponentAsync callback + + private Container loadingInfo; + + private void updateDisplay() + { + Scheduler.AddOnce(perform); + + void perform() + { + void removeOldInfo() + { + State.Value = beatmap == null ? Visibility.Hidden : Visibility.Visible; + + DisplayedContent?.FadeOut(transition_duration); + DisplayedContent?.Expire(); + DisplayedContent = null; + } + + if (beatmap == null) + { + removeOldInfo(); + return; + } + + LoadComponentAsync(loadingInfo = new Container + { + RelativeSizeAxes = Axes.Both, + Shear = -Shear, + Depth = DisplayedContent?.Depth + 1 ?? 0, + Children = new Drawable[] + { + new BeatmapInfoWedgeBackground(beatmap), + Info = new WedgeInfoText(beatmap), + } + }, loaded => + { + // ensure we are the most recent loaded wedge. + if (loaded != loadingInfo) return; + + removeOldInfo(); + Add(DisplayedContent = loaded); + }); + } + } + + public partial class WedgeInfoText : Container + { + public OsuSpriteText VersionLabel { get; private set; } + public OsuSpriteText TitleLabel { get; private set; } + public OsuSpriteText ArtistLabel { get; private set; } + public FillFlowContainer MapperContainer { get; private set; } + + private Container difficultyColourBar; + private StarRatingDisplay starRatingDisplay; + + private ILocalisedBindableString titleBinding; + private ILocalisedBindableString artistBinding; + + private readonly WorkingBeatmap working; + + [Resolved] + private IBindable> mods { get; set; } + + [Resolved] + private BeatmapDifficultyCache difficultyCache { get; set; } + + [Resolved] + private OsuColour colours { get; set; } + + private ModSettingChangeTracker settingChangeTracker; + + public WedgeInfoText(WorkingBeatmap working) + { + this.working = working; + } + + private CancellationTokenSource cancellationSource; + private IBindable starDifficulty; + + [BackgroundDependencyLoader] + private void load(LocalisationManager localisation) + { + var beatmapInfo = working.BeatmapInfo; + var metadata = beatmapInfo.Metadata; + + RelativeSizeAxes = Axes.Both; + + titleBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); + artistBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.ArtistUnicode, metadata.Artist)); + + const float top_height = 0.7f; + + Children = new Drawable[] + { + difficultyColourBar = new Container + { + RelativeSizeAxes = Axes.Y, + Width = 20f, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Width = top_height, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Alpha = 0.5f, + X = top_height, + Width = 1 - top_height, + } + } + }, + new FillFlowContainer + { + Name = "Topleft-aligned metadata", + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Top = 10, Left = 25, Right = shear_width * 2.5f }, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + VersionLabel = new OsuSpriteText + { + Text = beatmapInfo.DifficultyName, + Font = OsuFont.GetFont(size: 24, italics: true), + RelativeSizeAxes = Axes.X, + Truncate = true, + }, + } + }, + new FillFlowContainer + { + Name = "Topright-aligned metadata", + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Top = 14, Right = shear_width / 2 }, + AutoSizeAxes = Axes.Both, + Shear = wedged_container_shear, + Spacing = new Vector2(0f, 5f), + Children = new Drawable[] + { + starRatingDisplay = new StarRatingDisplay(default, animated: true) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -wedged_container_shear, + Alpha = 0f, + }, + new BeatmapSetOnlineStatusPill + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Shear = -wedged_container_shear, + TextSize = 11, + TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 }, + Status = beatmapInfo.Status, + Alpha = string.IsNullOrEmpty(beatmapInfo.DifficultyName) ? 0 : 1 + } + } + }, + new FillFlowContainer + { + Name = "Centre-aligned metadata", + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopLeft, + Y = -7, + Direction = FillDirection.Vertical, + Padding = new MarginPadding { Left = 25, Right = shear_width }, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + TitleLabel = new OsuSpriteText + { + Current = { BindTarget = titleBinding }, + Font = OsuFont.GetFont(size: 28, italics: true), + RelativeSizeAxes = Axes.X, + Truncate = true, + }, + ArtistLabel = new OsuSpriteText + { + Current = { BindTarget = artistBinding }, + Font = OsuFont.GetFont(size: 17, italics: true), + RelativeSizeAxes = Axes.X, + Truncate = true, + }, + MapperContainer = new FillFlowContainer + { + Margin = new MarginPadding { Top = 10 }, + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + Child = getMapper(metadata), + } + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + starRatingDisplay.DisplayedStars.BindValueChanged(s => + { + difficultyColourBar.Colour = colours.ForStarDifficulty(s.NewValue); + }, true); + + starDifficulty = difficultyCache.GetBindableDifficulty(working.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); + starDifficulty.BindValueChanged(s => + { + starRatingDisplay.Current.Value = s.NewValue ?? default; + + // Don't roll the counter on initial display (but still allow it to roll on applying mods etc.) + if (!starRatingDisplay.IsPresent) + starRatingDisplay.FinishTransforms(true); + + starRatingDisplay.FadeIn(transition_duration); + }); + + mods.BindValueChanged(m => + { + settingChangeTracker?.Dispose(); + + settingChangeTracker = new ModSettingChangeTracker(m.NewValue); + }, true); + } + + private Drawable getMapper(BeatmapMetadata metadata) + { + if (string.IsNullOrEmpty(metadata.Author.Username)) + return Empty(); + + return new LinkFlowContainer(s => + { + s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15); + }).With(d => + { + d.AutoSizeAxes = Axes.Both; + d.AddText("mapped by "); + d.AddUserLink(metadata.Author); + }); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + settingChangeTracker?.Dispose(); + cancellationSource?.Cancel(); + } + } + } +} From c646f8479b35cc7d66b1075ad5c5ba8ab46434ad Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sat, 7 Jan 2023 23:53:19 +0100 Subject: [PATCH 002/196] Move stardifficulty logic to main BeatmapInfoWedge class instead of text subclass ( for use by background star rating colour bar ) --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 4d1a2133fd..104fa8787b 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -37,10 +37,16 @@ namespace osu.Game.Screens.Select [Resolved] private IBindable ruleset { get; set; } + [Resolved] + private BeatmapDifficultyCache difficultyCache { get; set; } + protected Container DisplayedContent { get; private set; } protected WedgeInfoText Info { get; private set; } + private IBindable starDifficulty; + private CancellationTokenSource cancellationSource; + public BeatmapInfoWedgeV2() { Shear = wedged_container_shear; @@ -98,6 +104,19 @@ namespace osu.Game.Screens.Select private Container loadingInfo; + protected override void LoadComplete() + { + base.LoadComplete(); + starDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + cancellationSource?.Cancel(); + } + private void updateDisplay() { Scheduler.AddOnce(perform); @@ -127,7 +146,7 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { new BeatmapInfoWedgeBackground(beatmap), - Info = new WedgeInfoText(beatmap), + Info = new WedgeInfoText(beatmap, starDifficulty), } }, loaded => { @@ -154,26 +173,22 @@ namespace osu.Game.Screens.Select private ILocalisedBindableString artistBinding; private readonly WorkingBeatmap working; + private readonly IBindable starDifficulty; [Resolved] private IBindable> mods { get; set; } - [Resolved] - private BeatmapDifficultyCache difficultyCache { get; set; } - [Resolved] private OsuColour colours { get; set; } private ModSettingChangeTracker settingChangeTracker; - public WedgeInfoText(WorkingBeatmap working) + public WedgeInfoText(WorkingBeatmap working, IBindable starDifficulty) { this.working = working; + this.starDifficulty = starDifficulty; } - private CancellationTokenSource cancellationSource; - private IBindable starDifficulty; - [BackgroundDependencyLoader] private void load(LocalisationManager localisation) { @@ -309,7 +324,6 @@ namespace osu.Game.Screens.Select difficultyColourBar.Colour = colours.ForStarDifficulty(s.NewValue); }, true); - starDifficulty = difficultyCache.GetBindableDifficulty(working.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); starDifficulty.BindValueChanged(s => { starRatingDisplay.Current.Value = s.NewValue ?? default; @@ -349,7 +363,6 @@ namespace osu.Game.Screens.Select { base.Dispose(isDisposing); settingChangeTracker?.Dispose(); - cancellationSource?.Cancel(); } } } From 0199c19f74705c2d5c0dd10f3c61c0c8325ef224 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 8 Jan 2023 01:24:47 +0100 Subject: [PATCH 003/196] Add a test scene and move colour bar to back and adjust positioning of it --- .../SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 187 ++++++++++++++++++ osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 131 +++--------- 2 files changed, 217 insertions(+), 101 deletions(-) create mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs new file mode 100644 index 0000000000..98e9d803ca --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -0,0 +1,187 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using System.Collections.Generic; +using JetBrains.Annotations; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +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.Rulesets.Objects.Types; +using osu.Game.Screens.Select; +using osuTK; + +namespace osu.Game.Tests.Visual.SongSelect +{ + [TestFixture] + public partial class TestSceneBeatmapInfoWedgeV2 : OsuTestScene + { + private RulesetStore rulesets; + private TestBeatmapInfoWedgeV2 infoWedge; + private readonly List beatmaps = new List(); + + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + this.rulesets = rulesets; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Add(infoWedge = new TestBeatmapInfoWedgeV2 + { + Size = new Vector2(0.6f, 120), + RelativeSizeAxes = Axes.X, + Margin = new MarginPadding { Top = 20 } + }); + + AddStep("show", () => infoWedge.Show()); + + selectBeatmap(Beatmap.Value.Beatmap); + + AddWaitStep("wait for select", 3); + + AddStep("hide", () => { infoWedge.Hide(); }); + + AddWaitStep("wait for hide", 3); + + AddStep("show", () => { infoWedge.Show(); }); + + AddSliderStep("change star difficulty", 0, 11.9, 5.55, v => + { + foreach (var hasCurrentValue in infoWedge.Info.ChildrenOfType>()) + hasCurrentValue.Current.Value = new StarDifficulty(v, 0); + }); + + foreach (var rulesetInfo in rulesets.AvailableRulesets) + { + var instance = rulesetInfo.CreateInstance(); + var testBeatmap = createTestBeatmap(rulesetInfo); + + beatmaps.Add(testBeatmap); + + setRuleset(rulesetInfo); + + selectBeatmap(testBeatmap); + + testBeatmapLabels(instance); + } + } + + 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"); + } + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("reset mods", () => SelectedMods.SetDefault()); + } + + [Test] + public void TestTruncation() + { + selectBeatmap(createLongMetadata()); + } + + 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([CanBeNull] 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); + }); + + 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, IHasPosition + { + public float X => 0; + public float Y => 0; + public Vector2 Position { get; } = Vector2.Zero; + } + } +} diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 104fa8787b..5583ad11f7 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Threading; using osuTK; -using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -16,18 +15,16 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Effects; using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; -using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Select { + [Cached] public partial class BeatmapInfoWedgeV2 : VisibilityContainer { - public const float BORDER_THICKNESS = 2.5f; private const float shear_width = 36.75f; private const float transition_duration = 250; @@ -44,22 +41,25 @@ namespace osu.Game.Screens.Select protected WedgeInfoText Info { get; private set; } - private IBindable starDifficulty; + private IBindable starDifficulty = new Bindable(); private CancellationTokenSource cancellationSource; + private readonly Container difficultyColourBar; + public BeatmapInfoWedgeV2() { + CornerRadius = 10; Shear = wedged_container_shear; Masking = true; - BorderColour = new Color4(221, 255, 255, 255); - BorderThickness = BORDER_THICKNESS; Alpha = 0; - EdgeEffect = new EdgeEffectParameters + Child = difficultyColourBar = new Container { - Type = EdgeEffectType.Glow, - Colour = new Color4(130, 204, 255, 150), - Radius = 20, - Roundness = 15, + Depth = float.MaxValue, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.Y, + Width = 40, + Child = new Box { RelativeSizeAxes = Axes.Both } }; } @@ -95,6 +95,7 @@ namespace osu.Game.Screens.Select if (beatmap == value) return; beatmap = value; + starDifficulty = difficultyCache.GetBindableDifficulty(value.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); updateDisplay(); } @@ -104,12 +105,6 @@ namespace osu.Game.Screens.Select private Container loadingInfo; - protected override void LoadComplete() - { - base.LoadComplete(); - starDifficulty = difficultyCache.GetBindableDifficulty(beatmap.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -140,13 +135,15 @@ namespace osu.Game.Screens.Select LoadComponentAsync(loadingInfo = new Container { + Masking = true, + X = -30, + CornerRadius = 10, RelativeSizeAxes = Axes.Both, - Shear = -Shear, Depth = DisplayedContent?.Depth + 1 ?? 0, Children = new Drawable[] { - new BeatmapInfoWedgeBackground(beatmap), - Info = new WedgeInfoText(beatmap, starDifficulty), + new BeatmapInfoWedgeBackground(beatmap) { Shear = -Shear }, + Info = new WedgeInfoText(beatmap, starDifficulty) { Shear = -Shear } } }, loaded => { @@ -161,12 +158,9 @@ namespace osu.Game.Screens.Select public partial class WedgeInfoText : Container { - public OsuSpriteText VersionLabel { get; private set; } public OsuSpriteText TitleLabel { get; private set; } public OsuSpriteText ArtistLabel { get; private set; } - public FillFlowContainer MapperContainer { get; private set; } - private Container difficultyColourBar; private StarRatingDisplay starRatingDisplay; private ILocalisedBindableString titleBinding; @@ -178,6 +172,9 @@ namespace osu.Game.Screens.Select [Resolved] private IBindable> mods { get; set; } + [Resolved] + private BeatmapInfoWedgeV2 wedge { get; set; } + [Resolved] private OsuColour colours { get; set; } @@ -200,51 +197,8 @@ namespace osu.Game.Screens.Select titleBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); artistBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.ArtistUnicode, metadata.Artist)); - const float top_height = 0.7f; - Children = new Drawable[] { - difficultyColourBar = new Container - { - RelativeSizeAxes = Axes.Y, - Width = 20f, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Width = top_height, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Both, - Alpha = 0.5f, - X = top_height, - Width = 1 - top_height, - } - } - }, - new FillFlowContainer - { - Name = "Topleft-aligned metadata", - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Top = 10, Left = 25, Right = shear_width * 2.5f }, - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Children = new Drawable[] - { - VersionLabel = new OsuSpriteText - { - Text = beatmapInfo.DifficultyName, - Font = OsuFont.GetFont(size: 24, italics: true), - RelativeSizeAxes = Axes.X, - Truncate = true, - }, - } - }, new FillFlowContainer { Name = "Topright-aligned metadata", @@ -279,12 +233,10 @@ namespace osu.Game.Screens.Select }, new FillFlowContainer { - Name = "Centre-aligned metadata", - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopLeft, - Y = -7, + Name = "Top-left aligned metadata", Direction = FillDirection.Vertical, - Padding = new MarginPadding { Left = 25, Right = shear_width }, + Position = new Vector2(50, 12), + Width = .8f, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Children = new Drawable[] @@ -292,23 +244,17 @@ namespace osu.Game.Screens.Select TitleLabel = new OsuSpriteText { Current = { BindTarget = titleBinding }, - Font = OsuFont.GetFont(size: 28, italics: true), + Font = OsuFont.TorusAlternate.With(size: 40, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, - Truncate = true, + Truncate = true }, ArtistLabel = new OsuSpriteText { Current = { BindTarget = artistBinding }, - Font = OsuFont.GetFont(size: 17, italics: true), + //Not sure if this should be semi bold or medium + Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, - Truncate = true, - }, - MapperContainer = new FillFlowContainer - { - Margin = new MarginPadding { Top = 10 }, - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - Child = getMapper(metadata), + Truncate = true } } } @@ -321,9 +267,8 @@ namespace osu.Game.Screens.Select starRatingDisplay.DisplayedStars.BindValueChanged(s => { - difficultyColourBar.Colour = colours.ForStarDifficulty(s.NewValue); + wedge.difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); }, true); - starDifficulty.BindValueChanged(s => { starRatingDisplay.Current.Value = s.NewValue ?? default; @@ -343,22 +288,6 @@ namespace osu.Game.Screens.Select }, true); } - private Drawable getMapper(BeatmapMetadata metadata) - { - if (string.IsNullOrEmpty(metadata.Author.Username)) - return Empty(); - - return new LinkFlowContainer(s => - { - s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15); - }).With(d => - { - d.AutoSizeAxes = Axes.Both; - d.AddText("mapped by "); - d.AddUserLink(metadata.Author); - }); - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 61caabaa8ee4002c7d96859f0937b3fb8b997c82 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 8 Jan 2023 01:47:22 +0100 Subject: [PATCH 004/196] Add coloured star counter --- .../Graphics/UserInterface/StarCounter.cs | 6 ++- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 51 +++++++++++++++---- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index d7d088d798..7adb482188 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -32,6 +32,11 @@ namespace osu.Game.Graphics.UserInterface private const float star_spacing = 4; + public virtual FillDirection Direction + { + set => stars.Direction = value; + } + private float current; /// @@ -66,7 +71,6 @@ namespace osu.Game.Graphics.UserInterface stars = new FillFlowContainer { AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, Spacing = new Vector2(star_spacing), ChildrenEnumerable = Enumerable.Range(0, StarCount).Select(_ => CreateStar()) } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 5583ad11f7..07fcb42fff 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -3,7 +3,9 @@ #nullable disable +using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using osuTK; using osu.Framework.Allocation; @@ -17,6 +19,7 @@ using osu.Game.Graphics.Sprites; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -25,11 +28,12 @@ namespace osu.Game.Screens.Select [Cached] public partial class BeatmapInfoWedgeV2 : VisibilityContainer { - private const float shear_width = 36.75f; + private const float shear_width = 21; + private const int wedge_height = 120; private const float transition_duration = 250; - private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / SongSelect.WEDGE_HEIGHT, 0); + private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / wedge_height, 0); [Resolved] private IBindable ruleset { get; set; } @@ -45,6 +49,7 @@ namespace osu.Game.Screens.Select private CancellationTokenSource cancellationSource; private readonly Container difficultyColourBar; + private readonly StarCounter starCounter; public BeatmapInfoWedgeV2() { @@ -52,14 +57,27 @@ namespace osu.Game.Screens.Select Shear = wedged_container_shear; Masking = true; Alpha = 0; - Child = difficultyColourBar = new Container + + Children = new Drawable[] { - Depth = float.MaxValue, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Y, - Width = 40, - Child = new Box { RelativeSizeAxes = Axes.Both } + difficultyColourBar = new Container + { + Depth = float.MaxValue, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.Y, + Width = 40, + Child = new Box { RelativeSizeAxes = Axes.Both } + }, + starCounter = new StarCounter + { + Anchor = Anchor.CentreRight, + Origin = Anchor.Centre, + Scale = new Vector2(0.4f), + Shear = -wedged_container_shear, + X = -15, + Direction = FillDirection.Vertical + } }; } @@ -67,6 +85,15 @@ namespace osu.Game.Screens.Select private void load() { ruleset.BindValueChanged(_ => updateDisplay()); + + float starAngle = (float)(Math.Atan(shear_width / wedge_height) * (180 / Math.PI)); + + //Applying the rotation directly to the StarCounter distorts the stars, hence it is applied to the child container + starCounter.Children.First().Rotation = starAngle; + + //Makes sure the stars center themselves properly in the colour bar + starCounter.Children.First().Anchor = Anchor.Centre; + starCounter.Children.First().Origin = Anchor.Centre; } private const double animation_duration = 800; @@ -267,8 +294,12 @@ namespace osu.Game.Screens.Select starRatingDisplay.DisplayedStars.BindValueChanged(s => { - wedge.difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); + wedge.starCounter.Colour = s.NewValue >= 6.5 ? colours.Orange1 : Colour4.Black.Opacity(0.75f); + wedge.starCounter.Current = (float)s.NewValue; + + wedge.difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue), 750, Easing.OutQuint); }, true); + starDifficulty.BindValueChanged(s => { starRatingDisplay.Current.Value = s.NewValue ?? default; From 1698272eb88b3937228783d3df8d04db993d5da5 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 8 Jan 2023 12:03:02 +0100 Subject: [PATCH 005/196] Simplify passing data from BeatmapInfoWedgeV2.cs to subclass wedgeinfotext --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 07fcb42fff..1056d9478b 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -60,17 +60,22 @@ namespace osu.Game.Screens.Select 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 = 40, Child = new Box { RelativeSizeAxes = Axes.Both } }, starCounter = new StarCounter { + Colour = Colour4.Transparent, Anchor = Anchor.CentreRight, Origin = Anchor.Centre, Scale = new Vector2(0.4f), @@ -170,7 +175,7 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { new BeatmapInfoWedgeBackground(beatmap) { Shear = -Shear }, - Info = new WedgeInfoText(beatmap, starDifficulty) { Shear = -Shear } + Info = new WedgeInfoText { Shear = -Shear } } }, loaded => { @@ -193,9 +198,6 @@ namespace osu.Game.Screens.Select private ILocalisedBindableString titleBinding; private ILocalisedBindableString artistBinding; - private readonly WorkingBeatmap working; - private readonly IBindable starDifficulty; - [Resolved] private IBindable> mods { get; set; } @@ -207,17 +209,11 @@ namespace osu.Game.Screens.Select private ModSettingChangeTracker settingChangeTracker; - public WedgeInfoText(WorkingBeatmap working, IBindable starDifficulty) - { - this.working = working; - this.starDifficulty = starDifficulty; - } - [BackgroundDependencyLoader] private void load(LocalisationManager localisation) { - var beatmapInfo = working.BeatmapInfo; - var metadata = beatmapInfo.Metadata; + var beatmapInfo = wedge.Beatmap.BeatmapInfo; + var metadata = wedge.beatmap.Metadata; RelativeSizeAxes = Axes.Both; @@ -262,7 +258,7 @@ namespace osu.Game.Screens.Select { Name = "Top-left aligned metadata", Direction = FillDirection.Vertical, - Position = new Vector2(50, 12), + Position = new Vector2(80, 12), Width = .8f, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, @@ -270,6 +266,7 @@ namespace osu.Game.Screens.Select { TitleLabel = new OsuSpriteText { + Shadow = true, Current = { BindTarget = titleBinding }, Font = OsuFont.TorusAlternate.With(size: 40, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, @@ -277,6 +274,7 @@ namespace osu.Game.Screens.Select }, ArtistLabel = new OsuSpriteText { + Shadow = true, Current = { BindTarget = artistBinding }, //Not sure if this should be semi bold or medium Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold), @@ -297,10 +295,10 @@ namespace osu.Game.Screens.Select wedge.starCounter.Colour = s.NewValue >= 6.5 ? colours.Orange1 : Colour4.Black.Opacity(0.75f); wedge.starCounter.Current = (float)s.NewValue; - wedge.difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue), 750, Easing.OutQuint); + wedge.difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); }, true); - starDifficulty.BindValueChanged(s => + wedge.starDifficulty.BindValueChanged(s => { starRatingDisplay.Current.Value = s.NewValue ?? default; From 65c30d2c2e0a322d0d75003905fd44b4e5969d32 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 8 Jan 2023 12:56:32 +0100 Subject: [PATCH 006/196] Remove nullability disabling --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 62 +++++++++---------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 1056d9478b..da7cfc6613 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -36,17 +34,11 @@ namespace osu.Game.Screens.Select private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / wedge_height, 0); [Resolved] - private IBindable ruleset { get; set; } + private IBindable ruleset { get; set; } = null!; - [Resolved] - private BeatmapDifficultyCache difficultyCache { get; set; } + protected Container? DisplayedContent { get; private set; } - protected Container DisplayedContent { get; private set; } - - protected WedgeInfoText Info { get; private set; } - - private IBindable starDifficulty = new Bindable(); - private CancellationTokenSource cancellationSource; + protected WedgeInfoText? Info { get; private set; } private readonly Container difficultyColourBar; private readonly StarCounter starCounter; @@ -117,9 +109,9 @@ namespace osu.Game.Screens.Select this.FadeOut(transition_duration * 2, Easing.In); } - private WorkingBeatmap beatmap; + private WorkingBeatmap? beatmap; - public WorkingBeatmap Beatmap + public WorkingBeatmap? Beatmap { get => beatmap; set @@ -127,7 +119,6 @@ namespace osu.Game.Screens.Select if (beatmap == value) return; beatmap = value; - starDifficulty = difficultyCache.GetBindableDifficulty(value.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); updateDisplay(); } @@ -135,14 +126,7 @@ namespace osu.Game.Screens.Select public override bool IsPresent => base.IsPresent || DisplayedContent == null; // Visibility is updated in the LoadComponentAsync callback - private Container loadingInfo; - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - cancellationSource?.Cancel(); - } + private Container? loadingInfo; private void updateDisplay() { @@ -190,30 +174,36 @@ namespace osu.Game.Screens.Select public partial class WedgeInfoText : Container { - public OsuSpriteText TitleLabel { get; private set; } - public OsuSpriteText ArtistLabel { get; private set; } + public OsuSpriteText TitleLabel { get; private set; } = null!; + public OsuSpriteText ArtistLabel { get; private set; } = null!; - private StarRatingDisplay starRatingDisplay; + private StarRatingDisplay starRatingDisplay = null!; - private ILocalisedBindableString titleBinding; - private ILocalisedBindableString artistBinding; + private ILocalisedBindableString titleBinding = null!; + private ILocalisedBindableString artistBinding = null!; [Resolved] - private IBindable> mods { get; set; } + private IBindable> mods { get; set; } = null!; [Resolved] - private BeatmapInfoWedgeV2 wedge { get; set; } + private BeatmapInfoWedgeV2 wedge { get; set; } = null!; [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; - private ModSettingChangeTracker settingChangeTracker; + [Resolved] + private BeatmapDifficultyCache difficultyCache { get; set; } = null!; + + private ModSettingChangeTracker? settingChangeTracker; + + private IBindable? starDifficulty; + private CancellationTokenSource? cancellationSource; [BackgroundDependencyLoader] private void load(LocalisationManager localisation) { - var beatmapInfo = wedge.Beatmap.BeatmapInfo; - var metadata = wedge.beatmap.Metadata; + var beatmapInfo = wedge.Beatmap!.BeatmapInfo; + var metadata = wedge.beatmap!.Metadata; RelativeSizeAxes = Axes.Both; @@ -274,6 +264,7 @@ namespace osu.Game.Screens.Select }, ArtistLabel = new OsuSpriteText { + //figma design has a diffused shadow, instead of the solid one present here. Shadow = true, Current = { BindTarget = artistBinding }, //Not sure if this should be semi bold or medium @@ -298,7 +289,8 @@ namespace osu.Game.Screens.Select wedge.difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); }, true); - wedge.starDifficulty.BindValueChanged(s => + starDifficulty = difficultyCache.GetBindableDifficulty(wedge.beatmap!.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); + starDifficulty.BindValueChanged(s => { starRatingDisplay.Current.Value = s.NewValue ?? default; @@ -320,6 +312,8 @@ namespace osu.Game.Screens.Select protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); + + cancellationSource?.Cancel(); settingChangeTracker?.Dispose(); } } From 9afdfd7f067c786f236748c84e7028e0c294ff76 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 8 Jan 2023 15:42:42 +0100 Subject: [PATCH 007/196] small tweaks, container edge - effect addition.. --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index da7cfc6613..ced6931e1f 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; @@ -27,9 +28,9 @@ namespace osu.Game.Screens.Select public partial class BeatmapInfoWedgeV2 : VisibilityContainer { private const float shear_width = 21; - private const int wedge_height = 120; - + private const float wedge_height = 120; private const float transition_duration = 250; + private const float corner_radius = 10; private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / wedge_height, 0); @@ -45,14 +46,20 @@ namespace osu.Game.Screens.Select public BeatmapInfoWedgeV2() { - CornerRadius = 10; Shear = wedged_container_shear; Masking = true; - Alpha = 0; + EdgeEffect = new EdgeEffectParameters + { + Colour = Colour4.Black.Opacity(.25f), + Type = EdgeEffectType.Shadow, + Radius = corner_radius, + Roundness = corner_radius + }; + CornerRadius = corner_radius; 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 + // 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, @@ -61,7 +68,7 @@ namespace osu.Game.Screens.Select 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. + // By limiting the width we avoid this box showing up as an outline around the drawables that are on top of it. Width = 40, Child = new Box { RelativeSizeAxes = Axes.Both } }, @@ -70,7 +77,7 @@ namespace osu.Game.Screens.Select Colour = Colour4.Transparent, Anchor = Anchor.CentreRight, Origin = Anchor.Centre, - Scale = new Vector2(0.4f), + Scale = new Vector2(0.35f), Shear = -wedged_container_shear, X = -15, Direction = FillDirection.Vertical @@ -85,10 +92,10 @@ namespace osu.Game.Screens.Select float starAngle = (float)(Math.Atan(shear_width / wedge_height) * (180 / Math.PI)); - //Applying the rotation directly to the StarCounter distorts the stars, hence it is applied to the child container + // Applying the rotation directly to the StarCounter distorts the stars, hence it is applied to the child container starCounter.Children.First().Rotation = starAngle; - //Makes sure the stars center themselves properly in the colour bar + // Makes sure the stars center themselves properly in the colour bar starCounter.Children.First().Anchor = Anchor.Centre; starCounter.Children.First().Origin = Anchor.Centre; } @@ -153,13 +160,13 @@ namespace osu.Game.Screens.Select { Masking = true, X = -30, - CornerRadius = 10, + CornerRadius = corner_radius, RelativeSizeAxes = Axes.Both, Depth = DisplayedContent?.Depth + 1 ?? 0, Children = new Drawable[] { new BeatmapInfoWedgeBackground(beatmap) { Shear = -Shear }, - Info = new WedgeInfoText { Shear = -Shear } + Info = new WedgeInfoText(beatmap) { Shear = -Shear } } }, loaded => { @@ -182,11 +189,10 @@ namespace osu.Game.Screens.Select private ILocalisedBindableString titleBinding = null!; private ILocalisedBindableString artistBinding = null!; - [Resolved] - private IBindable> mods { get; set; } = null!; + private readonly WorkingBeatmap working; [Resolved] - private BeatmapInfoWedgeV2 wedge { get; set; } = null!; + private IBindable> mods { get; set; } = null!; [Resolved] private OsuColour colours { get; set; } = null!; @@ -194,16 +200,24 @@ namespace osu.Game.Screens.Select [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } = null!; + [Resolved] + private BeatmapInfoWedgeV2 wedge { get; set; } = null!; + private ModSettingChangeTracker? settingChangeTracker; private IBindable? starDifficulty; private CancellationTokenSource? cancellationSource; + public WedgeInfoText(WorkingBeatmap working) + { + this.working = working; + } + [BackgroundDependencyLoader] private void load(LocalisationManager localisation) { - var beatmapInfo = wedge.Beatmap!.BeatmapInfo; - var metadata = wedge.beatmap!.Metadata; + var beatmapInfo = working.BeatmapInfo; + var metadata = working.Metadata; RelativeSizeAxes = Axes.Both; @@ -249,7 +263,7 @@ namespace osu.Game.Screens.Select Name = "Top-left aligned metadata", Direction = FillDirection.Vertical, Position = new Vector2(80, 12), - Width = .8f, + Width = .7f, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Children = new Drawable[] @@ -289,7 +303,7 @@ namespace osu.Game.Screens.Select wedge.difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); }, true); - starDifficulty = difficultyCache.GetBindableDifficulty(wedge.beatmap!.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); + starDifficulty = difficultyCache.GetBindableDifficulty(working.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); starDifficulty.BindValueChanged(s => { starRatingDisplay.Current.Value = s.NewValue ?? default; From 2a82f618ed9a69dd28613dfc8f04189ceecd702f Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 10 Jan 2023 17:34:47 +0100 Subject: [PATCH 008/196] Add TODO for text margin const, added pertinent comments to known "issues" --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index ced6931e1f..ce07a59a0c 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -32,6 +32,9 @@ namespace osu.Game.Screens.Select private const float transition_duration = 250; private const float corner_radius = 10; + /// 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] @@ -159,18 +162,21 @@ namespace osu.Game.Screens.Select LoadComponentAsync(loadingInfo = new Container { Masking = true, + // We offset this by the portion of the colour bar underneath we wish to show X = -30, CornerRadius = corner_radius, RelativeSizeAxes = Axes.Both, Depth = DisplayedContent?.Depth + 1 ?? 0, 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 } } }, loaded => { - // ensure we are the most recent loaded wedge. + // Ensure we are the most recent loaded wedge. if (loaded != loadingInfo) return; removeOldInfo(); @@ -262,7 +268,7 @@ namespace osu.Game.Screens.Select { Name = "Top-left aligned metadata", Direction = FillDirection.Vertical, - Position = new Vector2(80, 12), + Position = new Vector2(text_margin + shear_width, 12), Width = .7f, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, @@ -278,10 +284,10 @@ namespace osu.Game.Screens.Select }, ArtistLabel = new OsuSpriteText { - //figma design has a diffused shadow, instead of the solid one present here. + // 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, Current = { BindTarget = artistBinding }, - //Not sure if this should be semi bold or medium + // Not sure if this should be semi bold or medium Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, Truncate = true @@ -297,8 +303,8 @@ namespace osu.Game.Screens.Select starRatingDisplay.DisplayedStars.BindValueChanged(s => { - wedge.starCounter.Colour = s.NewValue >= 6.5 ? colours.Orange1 : Colour4.Black.Opacity(0.75f); wedge.starCounter.Current = (float)s.NewValue; + wedge.starCounter.Colour = s.NewValue >= 6.5 ? colours.Orange1 : Colour4.Black.Opacity(0.75f); wedge.difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); }, true); From 8bfe24ced0c9163c1e1017b76d1f1669d57a160c Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 10 Jan 2023 17:49:33 +0100 Subject: [PATCH 009/196] Remove nullable disable in test. --- .../SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index 98e9d803ca..193acc8a7b 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -1,10 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; -using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -24,8 +21,8 @@ namespace osu.Game.Tests.Visual.SongSelect [TestFixture] public partial class TestSceneBeatmapInfoWedgeV2 : OsuTestScene { - private RulesetStore rulesets; - private TestBeatmapInfoWedgeV2 infoWedge; + private RulesetStore rulesets = null!; + private TestBeatmapInfoWedgeV2 infoWedge = null!; private readonly List beatmaps = new List(); [BackgroundDependencyLoader] @@ -80,8 +77,8 @@ namespace osu.Game.Tests.Visual.SongSelect 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"); + AddAssert("check title", () => infoWedge.Info!.TitleLabel.Current.Value == $"{ruleset.ShortName}Title"); + AddAssert("check artist", () => infoWedge.Info!.ArtistLabel.Current.Value == $"{ruleset.ShortName}Artist"); } [SetUpSteps] @@ -98,7 +95,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void setRuleset(RulesetInfo rulesetInfo) { - Container containerBefore = null; + Container? containerBefore = null; AddStep("set ruleset", () => { @@ -112,9 +109,9 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for async load", () => infoWedge.DisplayedContent != containerBefore); } - private void selectBeatmap([CanBeNull] IBeatmap b) + private void selectBeatmap(IBeatmap? b) { - Container containerBefore = null; + Container? containerBefore = null; AddStep($"select {b?.Metadata.Title ?? "null"} beatmap", () => { @@ -172,9 +169,9 @@ namespace osu.Game.Tests.Visual.SongSelect private partial class TestBeatmapInfoWedgeV2 : BeatmapInfoWedgeV2 { - public new Container DisplayedContent => base.DisplayedContent; + public new Container? DisplayedContent => base.DisplayedContent; - public new WedgeInfoText Info => base.Info; + public new WedgeInfoText? Info => base.Info; } private class TestHitObject : ConvertHitObject, IHasPosition From 880428046a17606b200750c6f8bdec254fd7e4e1 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 10 Jan 2023 18:03:28 +0100 Subject: [PATCH 010/196] Fix margins on top right aligned elements. --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index ce07a59a0c..1497bed121 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -238,7 +238,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Direction = FillDirection.Vertical, - Padding = new MarginPadding { Top = 14, Right = shear_width / 2 }, + Padding = new MarginPadding { Top = 3, Right = 8 }, AutoSizeAxes = Axes.Both, Shear = wedged_container_shear, Spacing = new Vector2(0f, 5f), From 7510201804aab33e90d805b8a34b9883f9ff390f Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 22:24:21 +0100 Subject: [PATCH 011/196] Add back null beatmap test --- .../Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index 193acc8a7b..a2935fb218 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -2,6 +2,7 @@ // 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; @@ -93,6 +94,15 @@ namespace osu.Game.Tests.Visual.SongSelect selectBeatmap(createLongMetadata()); } + [Test] + public void TestNullBeatmap() + { + 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; From 74b72e4ac0d6c34df51bf8d27c24d4625a9f8039 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 16 Jan 2023 22:46:18 +0100 Subject: [PATCH 012/196] Address issues that joehuu brought up --- .../Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index a2935fb218..4904e2a723 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.SongSelect Add(infoWedge = new TestBeatmapInfoWedgeV2 { - Size = new Vector2(0.6f, 120), + Width = 0.6f, RelativeSizeAxes = Axes.X, Margin = new MarginPadding { Top = 20 } }); diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 1497bed121..02d640fc0d 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -31,6 +31,7 @@ namespace osu.Game.Screens.Select private const float wedge_height = 120; 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; @@ -49,6 +50,7 @@ namespace osu.Game.Screens.Select public BeatmapInfoWedgeV2() { + Height = wedge_height; Shear = wedged_container_shear; Masking = true; EdgeEffect = new EdgeEffectParameters @@ -72,7 +74,7 @@ namespace osu.Game.Screens.Select 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 = 40, + Width = colour_bar_width + corner_radius, Child = new Box { RelativeSizeAxes = Axes.Both } }, starCounter = new StarCounter @@ -82,7 +84,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.Centre, Scale = new Vector2(0.35f), Shear = -wedged_container_shear, - X = -15, + X = -colour_bar_width / 2, Direction = FillDirection.Vertical } }; @@ -163,7 +165,7 @@ namespace osu.Game.Screens.Select { Masking = true, // We offset this by the portion of the colour bar underneath we wish to show - X = -30, + X = -colour_bar_width, CornerRadius = corner_radius, RelativeSizeAxes = Axes.Both, Depth = DisplayedContent?.Depth + 1 ?? 0, @@ -268,8 +270,7 @@ namespace osu.Game.Screens.Select { Name = "Top-left aligned metadata", Direction = FillDirection.Vertical, - Position = new Vector2(text_margin + shear_width, 12), - Width = .7f, + Padding = new MarginPadding { Horizontal = text_margin + shear_width, Top = 12 }, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Children = new Drawable[] From 0ac7cd7409e1c61cc0f8df03c1fa0b780adb43da Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Wed, 18 Jan 2023 13:55:52 +0100 Subject: [PATCH 013/196] Expose star difficulty to wedge to allow updating starcounter and background colour internally. --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 02d640fc0d..d90c002953 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -24,7 +24,6 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Screens.Select { - [Cached] public partial class BeatmapInfoWedgeV2 : VisibilityContainer { private const float shear_width = 21; @@ -41,6 +40,9 @@ namespace osu.Game.Screens.Select [Resolved] private IBindable ruleset { get; set; } = null!; + [Resolved] + private OsuColour colours { get; set; } = null!; + protected Container? DisplayedContent { get; private set; } protected WedgeInfoText? Info { get; private set; } @@ -183,6 +185,14 @@ namespace osu.Game.Screens.Select removeOldInfo(); Add(DisplayedContent = loaded); + + Info.StarRatingDisplay.DisplayedStars.BindValueChanged(s => + { + starCounter.Current = (float)s.NewValue; + starCounter.Colour = s.NewValue >= 6.5 ? colours.Orange1 : Colour4.Black.Opacity(0.75f); + + difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); + }, true); }); } } @@ -192,7 +202,7 @@ namespace osu.Game.Screens.Select public OsuSpriteText TitleLabel { get; private set; } = null!; public OsuSpriteText ArtistLabel { get; private set; } = null!; - private StarRatingDisplay starRatingDisplay = null!; + public StarRatingDisplay StarRatingDisplay = null!; private ILocalisedBindableString titleBinding = null!; private ILocalisedBindableString artistBinding = null!; @@ -202,15 +212,9 @@ namespace osu.Game.Screens.Select [Resolved] private IBindable> mods { get; set; } = null!; - [Resolved] - private OsuColour colours { get; set; } = null!; - [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } = null!; - [Resolved] - private BeatmapInfoWedgeV2 wedge { get; set; } = null!; - private ModSettingChangeTracker? settingChangeTracker; private IBindable? starDifficulty; @@ -246,7 +250,7 @@ namespace osu.Game.Screens.Select Spacing = new Vector2(0f, 5f), Children = new Drawable[] { - starRatingDisplay = new StarRatingDisplay(default, animated: true) + StarRatingDisplay = new StarRatingDisplay(default, animated: true) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -302,24 +306,16 @@ namespace osu.Game.Screens.Select { base.LoadComplete(); - starRatingDisplay.DisplayedStars.BindValueChanged(s => - { - wedge.starCounter.Current = (float)s.NewValue; - wedge.starCounter.Colour = s.NewValue >= 6.5 ? colours.Orange1 : Colour4.Black.Opacity(0.75f); - - wedge.difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); - }, true); - starDifficulty = difficultyCache.GetBindableDifficulty(working.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); starDifficulty.BindValueChanged(s => { - starRatingDisplay.Current.Value = s.NewValue ?? default; + StarRatingDisplay.Current.Value = s.NewValue ?? default; // Don't roll the counter on initial display (but still allow it to roll on applying mods etc.) - if (!starRatingDisplay.IsPresent) - starRatingDisplay.FinishTransforms(true); + if (!StarRatingDisplay.IsPresent) + StarRatingDisplay.FinishTransforms(true); - starRatingDisplay.FadeIn(transition_duration); + StarRatingDisplay.FadeIn(transition_duration); }); mods.BindValueChanged(m => From 655242371b2858371c82970d9fe316eb7d26cd6d Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 23 Jan 2023 17:00:46 +0100 Subject: [PATCH 014/196] Buffer wedge content to avoid opacity issues when showing / hiding --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index d90c002953..63e414d6ad 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -49,6 +49,7 @@ namespace osu.Game.Screens.Select private readonly Container difficultyColourBar; private readonly StarCounter starCounter; + private readonly BufferedContainer bufferedContent; public BeatmapInfoWedgeV2() { @@ -64,30 +65,35 @@ namespace osu.Game.Screens.Select }; CornerRadius = corner_radius; - Children = new Drawable[] + // We want to buffer the wedge to avoid weird transparency overlaps between the colour bar and the background. + Child = bufferedContent = new BufferedContainer { - // 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 + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - Colour = Colour4.Transparent, - Depth = float.MaxValue, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Y, + // 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 } - }, - starCounter = new StarCounter - { - Colour = Colour4.Transparent, - Anchor = Anchor.CentreRight, - Origin = Anchor.Centre, - Scale = new Vector2(0.35f), - Shear = -wedged_container_shear, - X = -colour_bar_width / 2, - Direction = FillDirection.Vertical + // 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 } + }, + starCounter = new StarCounter + { + Colour = Colour4.Transparent, + Anchor = Anchor.CentreRight, + Origin = Anchor.Centre, + Scale = new Vector2(0.35f), + Shear = -wedged_container_shear, + X = -colour_bar_width / 2, + Direction = FillDirection.Vertical + } } }; } @@ -184,9 +190,9 @@ namespace osu.Game.Screens.Select if (loaded != loadingInfo) return; removeOldInfo(); - Add(DisplayedContent = loaded); + bufferedContent.Add(DisplayedContent = loaded); - Info.StarRatingDisplay.DisplayedStars.BindValueChanged(s => + Info.DisplayedStars.BindValueChanged(s => { starCounter.Current = (float)s.NewValue; starCounter.Colour = s.NewValue >= 6.5 ? colours.Orange1 : Colour4.Black.Opacity(0.75f); @@ -202,13 +208,15 @@ namespace osu.Game.Screens.Select public OsuSpriteText TitleLabel { get; private set; } = null!; public OsuSpriteText ArtistLabel { get; private set; } = null!; - public StarRatingDisplay StarRatingDisplay = null!; + private StarRatingDisplay starRatingDisplay = null!; private ILocalisedBindableString titleBinding = null!; private ILocalisedBindableString artistBinding = null!; private readonly WorkingBeatmap working; + public IBindable DisplayedStars => starRatingDisplay.DisplayedStars; + [Resolved] private IBindable> mods { get; set; } = null!; @@ -250,7 +258,7 @@ namespace osu.Game.Screens.Select Spacing = new Vector2(0f, 5f), Children = new Drawable[] { - StarRatingDisplay = new StarRatingDisplay(default, animated: true) + starRatingDisplay = new StarRatingDisplay(default, animated: true) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -309,13 +317,13 @@ namespace osu.Game.Screens.Select starDifficulty = difficultyCache.GetBindableDifficulty(working.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); starDifficulty.BindValueChanged(s => { - StarRatingDisplay.Current.Value = s.NewValue ?? default; + starRatingDisplay.Current.Value = s.NewValue ?? default; // Don't roll the counter on initial display (but still allow it to roll on applying mods etc.) - if (!StarRatingDisplay.IsPresent) - StarRatingDisplay.FinishTransforms(true); + if (!starRatingDisplay.IsPresent) + starRatingDisplay.FinishTransforms(true); - StarRatingDisplay.FadeIn(transition_duration); + starRatingDisplay.FadeIn(transition_duration); }); mods.BindValueChanged(m => From c7d49bdc82c4ab48ab60040cdd0e161a481fdf94 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 30 Jan 2023 13:13:57 +0100 Subject: [PATCH 015/196] Update ```BeatmapInfoWedgeV2.cs``` animation to be similar to exit transition in ```SongSelect.cs`` --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 63e414d6ad..6a1662fd6a 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -113,20 +113,18 @@ namespace osu.Game.Screens.Select starCounter.Children.First().Origin = Anchor.Centre; } - private const double animation_duration = 800; + private const double animation_duration = 600; protected override void PopIn() { this.MoveToX(0, animation_duration, Easing.OutQuint); - this.RotateTo(0, animation_duration, Easing.OutQuint); - this.FadeIn(transition_duration); + this.FadeIn(200, Easing.In); } protected override void PopOut() { - this.MoveToX(-100, animation_duration, Easing.In); - this.RotateTo(10, animation_duration, Easing.In); - this.FadeOut(transition_duration * 2, Easing.In); + this.MoveToX(-150, animation_duration, Easing.OutQuint); + this.FadeOut(200, Easing.OutQuint); } private WorkingBeatmap? beatmap; From 92690afa5fecd750583924c5917fc3b877b73041 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 30 Jan 2023 16:12:26 +0100 Subject: [PATCH 016/196] de-nest ```removeOldInfo()``` --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 6a1662fd6a..41fe9d8d50 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -152,15 +152,6 @@ namespace osu.Game.Screens.Select void perform() { - void removeOldInfo() - { - State.Value = beatmap == null ? Visibility.Hidden : Visibility.Visible; - - DisplayedContent?.FadeOut(transition_duration); - DisplayedContent?.Expire(); - DisplayedContent = null; - } - if (beatmap == null) { removeOldInfo(); @@ -199,6 +190,15 @@ namespace osu.Game.Screens.Select }, true); }); } + + void removeOldInfo() + { + State.Value = beatmap == null ? Visibility.Hidden : Visibility.Visible; + + DisplayedContent?.FadeOut(transition_duration); + DisplayedContent?.Expire(); + DisplayedContent = null; + } } public partial class WedgeInfoText : Container From 27c52a45fc079174f29067ae6b7e97529f02cceb Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 30 Jan 2023 16:13:55 +0100 Subject: [PATCH 017/196] Use inline lambda for scheduling --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 41fe9d8d50..0cc60e4bba 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -148,9 +148,7 @@ namespace osu.Game.Screens.Select private void updateDisplay() { - Scheduler.AddOnce(perform); - - void perform() + Scheduler.AddOnce(() => { if (beatmap == null) { @@ -189,7 +187,7 @@ namespace osu.Game.Screens.Select difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); }, true); }); - } + }); void removeOldInfo() { From 5fc8f1d1bef944c43f1e9b1ac0456ded7015db72 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Fri, 3 Feb 2023 19:52:01 +0100 Subject: [PATCH 018/196] Fix ```BeatmapInfoWedgeV2.cs``` starCounter needing janky rotation application --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 0cc60e4bba..48a16d5449 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading; using osuTK; using osu.Framework.Allocation; @@ -84,15 +83,25 @@ namespace osu.Game.Screens.Select Width = colour_bar_width + corner_radius, Child = new Box { RelativeSizeAxes = Axes.Both } }, - starCounter = new StarCounter + new Container { - Colour = Colour4.Transparent, - Anchor = Anchor.CentreRight, - Origin = Anchor.Centre, - Scale = new Vector2(0.35f), + // 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, - Direction = FillDirection.Vertical + 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 + } } } }; @@ -102,15 +111,6 @@ namespace osu.Game.Screens.Select private void load() { ruleset.BindValueChanged(_ => updateDisplay()); - - float starAngle = (float)(Math.Atan(shear_width / wedge_height) * (180 / Math.PI)); - - // Applying the rotation directly to the StarCounter distorts the stars, hence it is applied to the child container - starCounter.Children.First().Rotation = starAngle; - - // Makes sure the stars center themselves properly in the colour bar - starCounter.Children.First().Anchor = Anchor.Centre; - starCounter.Children.First().Origin = Anchor.Centre; } private const double animation_duration = 600; From de37a0a000bfb99ad0f56eaadbe9929eb93229ab Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Fri, 3 Feb 2023 19:53:04 +0100 Subject: [PATCH 019/196] enable pixelSnapping for the ```BufferedContainer``` in BeatmapInfoWedgeV2.cs --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 48a16d5449..a18d4086f7 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Select CornerRadius = corner_radius; // We want to buffer the wedge to avoid weird transparency overlaps between the colour bar and the background. - Child = bufferedContent = new BufferedContainer + Child = bufferedContent = new BufferedContainer(pixelSnapping: true) { RelativeSizeAxes = Axes.Both, Children = new Drawable[] From 38cc47d64ec35313d7cb928ae78a018b5641e2d5 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sat, 4 Feb 2023 16:52:30 +0100 Subject: [PATCH 020/196] Remove ```IsPresent``` usages --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index a18d4086f7..fda20dde4d 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -142,8 +142,6 @@ namespace osu.Game.Screens.Select } } - public override bool IsPresent => base.IsPresent || DisplayedContent == null; // Visibility is updated in the LoadComponentAsync callback - private Container? loadingInfo; private void updateDisplay() @@ -316,7 +314,7 @@ namespace osu.Game.Screens.Select starRatingDisplay.Current.Value = s.NewValue ?? default; // Don't roll the counter on initial display (but still allow it to roll on applying mods etc.) - if (!starRatingDisplay.IsPresent) + if (starRatingDisplay.Alpha > 0) starRatingDisplay.FinishTransforms(true); starRatingDisplay.FadeIn(transition_duration); From cb679ccc2b95858b0ff85e86bffcd6ee6a27d9dd Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sat, 11 Feb 2023 18:00:17 +0100 Subject: [PATCH 021/196] Separate wedge visibility test into its own method --- .../SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index 4904e2a723..f99950dfb0 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.UserInterface; using osu.Framework.Testing; using osu.Game.Beatmaps; @@ -49,12 +50,6 @@ namespace osu.Game.Tests.Visual.SongSelect AddWaitStep("wait for select", 3); - AddStep("hide", () => { infoWedge.Hide(); }); - - AddWaitStep("wait for hide", 3); - - AddStep("show", () => { infoWedge.Show(); }); - AddSliderStep("change star difficulty", 0, 11.9, 5.55, v => { foreach (var hasCurrentValue in infoWedge.Info.ChildrenOfType>()) @@ -76,6 +71,26 @@ namespace osu.Game.Tests.Visual.SongSelect } } + [Test] + public void TestWedgeVisibility() + { + AddStep("Make shadow red for test visibility", () => + { + infoWedge.EdgeEffect = new EdgeEffectParameters + { + Colour = Colour4.Red, + Type = EdgeEffectType.Shadow, + Radius = 5, + }; + }); + 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"); From 468419896a5364252afa23263d9e43d26c4b7edf Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sat, 11 Feb 2023 18:08:50 +0100 Subject: [PATCH 022/196] Separate ruleset changing tests into their own method. Add small clarification for edge colouring in visibility test --- .../SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index f99950dfb0..ebd8c008b3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -39,22 +39,25 @@ namespace osu.Game.Tests.Visual.SongSelect Add(infoWedge = new TestBeatmapInfoWedgeV2 { + State = { Value = Visibility.Visible }, Width = 0.6f, RelativeSizeAxes = Axes.X, Margin = new MarginPadding { Top = 20 } }); - AddStep("show", () => infoWedge.Show()); - - selectBeatmap(Beatmap.Value.Beatmap); - - AddWaitStep("wait for select", 3); - AddSliderStep("change star difficulty", 0, 11.9, 5.55, v => { foreach (var hasCurrentValue in infoWedge.Info.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) { @@ -74,6 +77,8 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestWedgeVisibility() { + // Mostly just in case someone runs this test before others, + // leading to the shadow being very hard to see if it is black AddStep("Make shadow red for test visibility", () => { infoWedge.EdgeEffect = new EdgeEffectParameters From 09cb6ca3a797e516c3097b48883468be0f85f237 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sat, 11 Feb 2023 18:15:21 +0100 Subject: [PATCH 023/196] Clean up formatting and wedge placement in testscene a tad, --- .../Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index ebd8c008b3..3f3c7441f4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.SongSelect State = { Value = Visibility.Visible }, Width = 0.6f, RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Top = 20 } + Margin = new MarginPadding { Top = 20, Left = -10 } }); AddSliderStep("change star difficulty", 0, 11.9, 5.55, v => @@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual.SongSelect { // Mostly just in case someone runs this test before others, // leading to the shadow being very hard to see if it is black - AddStep("Make shadow red for test visibility", () => + AddStep("make shadow red for test visibility", () => { infoWedge.EdgeEffect = new EdgeEffectParameters { From 299023fce036d6995ead30d00d1de6364bbcc137 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 21 Feb 2023 16:07:26 +0100 Subject: [PATCH 024/196] Improve visibility of wedge shading in test scene and fix an issue with excessive roundness on said shadow. --- .../SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 25 ++++++++++++++----- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 9 +++---- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index 3f3c7441f4..09b93119cc 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Testing; using osu.Game.Beatmaps; @@ -37,12 +38,25 @@ namespace osu.Game.Tests.Visual.SongSelect { base.LoadComplete(); - Add(infoWedge = new TestBeatmapInfoWedgeV2 + AddRange(new Drawable[] { - State = { Value = Visibility.Visible }, - Width = 0.6f, - RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Top = 20, Left = -10 } + // 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 } + }, + infoWedge = new TestBeatmapInfoWedgeV2 + { + State = { Value = Visibility.Visible }, + Width = 0.6f, + RelativeSizeAxes = Axes.X, + Margin = new MarginPadding { Top = 20, Left = -10 } + }, }); AddSliderStep("change star difficulty", 0, 11.9, 5.55, v => @@ -200,7 +214,6 @@ namespace osu.Game.Tests.Visual.SongSelect private partial class TestBeatmapInfoWedgeV2 : BeatmapInfoWedgeV2 { public new Container? DisplayedContent => base.DisplayedContent; - public new WedgeInfoText? Info => base.Info; } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index fda20dde4d..0a35e68c7e 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -25,8 +25,8 @@ namespace osu.Game.Screens.Select { public partial class BeatmapInfoWedgeV2 : VisibilityContainer { + public const float WEDGE_HEIGHT = 120; private const float shear_width = 21; - private const float wedge_height = 120; private const float transition_duration = 250; private const float corner_radius = 10; private const float colour_bar_width = 30; @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Select /// 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); + private static readonly Vector2 wedged_container_shear = new Vector2(shear_width / WEDGE_HEIGHT, 0); [Resolved] private IBindable ruleset { get; set; } = null!; @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Select public BeatmapInfoWedgeV2() { - Height = wedge_height; + Height = WEDGE_HEIGHT; Shear = wedged_container_shear; Masking = true; EdgeEffect = new EdgeEffectParameters @@ -60,7 +60,6 @@ namespace osu.Game.Screens.Select Colour = Colour4.Black.Opacity(.25f), Type = EdgeEffectType.Shadow, Radius = corner_radius, - Roundness = corner_radius }; CornerRadius = corner_radius; @@ -95,7 +94,7 @@ namespace osu.Game.Screens.Select Width = colour_bar_width, Child = starCounter = new StarCounter { - Rotation = (float)(Math.Atan(shear_width / wedge_height) * (180 / Math.PI)), + Rotation = (float)(Math.Atan(shear_width / WEDGE_HEIGHT) * (180 / Math.PI)), Colour = Colour4.Transparent, Anchor = Anchor.Centre, Origin = Anchor.Centre, From f21238f517fa8e22a694affd4406bf3b858a8bb4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 16:51:57 +0900 Subject: [PATCH 025/196] Adjust shadow to look better --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 0a35e68c7e..b7b60cffab 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -57,9 +57,9 @@ namespace osu.Game.Screens.Select Masking = true; EdgeEffect = new EdgeEffectParameters { - Colour = Colour4.Black.Opacity(.25f), + Colour = Colour4.Black.Opacity(0.2f), Type = EdgeEffectType.Shadow, - Radius = corner_radius, + Radius = 3, }; CornerRadius = corner_radius; From c8f42f73e87029f3e235b92d3a97ba776d6327f9 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 24 Aug 2023 11:17:41 +0900 Subject: [PATCH 026/196] Adjust mania hit windows with gameplay rate --- .../Mods/IManiaRateAdjustmentMod.cs | 47 +++++++++++++++++++ .../Mods/ManiaModDaycore.cs | 5 +- .../Mods/ManiaModDoubleTime.cs | 5 +- .../Mods/ManiaModHalfTime.cs | 5 +- .../Mods/ManiaModNightcore.cs | 5 +- .../Scoring/ManiaHitWindows.cs | 20 ++++++++ 6 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Mods/IManiaRateAdjustmentMod.cs diff --git a/osu.Game.Rulesets.Mania/Mods/IManiaRateAdjustmentMod.cs b/osu.Game.Rulesets.Mania/Mods/IManiaRateAdjustmentMod.cs new file mode 100644 index 0000000000..ea01bd4436 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/IManiaRateAdjustmentMod.cs @@ -0,0 +1,47 @@ +// 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.Bindables; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Mania.Mods +{ + /// + /// May be attached to rate-adjustment mods to adjust hit windows adjust relative to gameplay rate. + /// + /// + /// Historically, in osu!mania, hit windows are expected to adjust relative to the gameplay rate such that the real-world hit window remains the same. + /// + public interface IManiaRateAdjustmentMod : IApplicableToDifficulty, IApplicableToHitObject + { + BindableNumber SpeedChange { get; } + + HitWindows HitWindows { get; set; } + + void IApplicableToDifficulty.ApplyToDifficulty(BeatmapDifficulty difficulty) + { + HitWindows = new ManiaHitWindows(SpeedChange.Value); + HitWindows.SetDifficulty(difficulty.OverallDifficulty); + } + + void IApplicableToHitObject.ApplyToHitObject(HitObject hitObject) + { + switch (hitObject) + { + case Note: + hitObject.HitWindows = HitWindows; + break; + + case HoldNote hold: + hold.Head.HitWindows = HitWindows; + hold.Tail.HitWindows = HitWindows; + break; + } + } + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs index 309393b664..dbe2a9a9fc 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs @@ -1,11 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModDaycore : ModDaycore + public class ManiaModDaycore : ModDaycore, IManiaRateAdjustmentMod { + public HitWindows HitWindows { get; set; } = new ManiaHitWindows(); } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs index f4b9cf3b88..a841a8ab37 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs @@ -1,11 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModDoubleTime : ModDoubleTime + public class ManiaModDoubleTime : ModDoubleTime, IManiaRateAdjustmentMod { + public HitWindows HitWindows { get; set; } = new ManiaHitWindows(); } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs index 8d48e3acde..b0fbb11396 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs @@ -1,11 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModHalfTime : ModHalfTime + public class ManiaModHalfTime : ModHalfTime, IManiaRateAdjustmentMod { + public HitWindows HitWindows { get; set; } = new ManiaHitWindows(); } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs index 748725af9f..f64f7ae31a 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs @@ -2,11 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModNightcore : ModNightcore + public class ManiaModNightcore : ModNightcore, IManiaRateAdjustmentMod { + public HitWindows HitWindows { get; set; } = new ManiaHitWindows(); } } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs index 289f8a00ef..627f48f391 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs @@ -1,12 +1,25 @@ // 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 osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring { public class ManiaHitWindows : HitWindows { + private readonly double multiplier; + + public ManiaHitWindows() + : this(1) + { + } + + public ManiaHitWindows(double multiplier) + { + this.multiplier = multiplier; + } + public override bool IsHitResultAllowed(HitResult result) { switch (result) @@ -22,5 +35,12 @@ namespace osu.Game.Rulesets.Mania.Scoring return false; } + + protected override DifficultyRange[] GetRanges() => base.GetRanges().Select(r => + new DifficultyRange( + r.Result, + r.Min * multiplier, + r.Average * multiplier, + r.Max * multiplier)).ToArray(); } } From 8a1fc7c340070e1f04d5ffca1488cfde70a054be Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sat, 26 Aug 2023 01:20:41 +0300 Subject: [PATCH 027/196] Basic stuff (not working for now) --- osu.Game/Overlays/Mods/ModMapInfoDisplay.cs | 203 ++++++++++++++++++ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 18 ++ osu.Game/Screens/Select/BeatmapDetails.cs | 6 + .../Screens/Select/Details/AdvancedStats.cs | 21 ++ osu.Game/Screens/Select/SongSelect.cs | 3 + 5 files changed, 251 insertions(+) create mode 100644 osu.Game/Overlays/Mods/ModMapInfoDisplay.cs diff --git a/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs b/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs new file mode 100644 index 0000000000..20666391d6 --- /dev/null +++ b/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs @@ -0,0 +1,203 @@ +// 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.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Select.Details; +using osu.Game.Localisation; +using osuTK; + + +namespace osu.Game.Overlays.Mods +{ + public partial class ModMapInfoDisplay : Container, IHasCurrentValue + { + public const float HEIGHT = 42; + private const float transition_duration = 200; + + private readonly Box contentBackground; + private readonly Box labelBackground; + private readonly FillFlowContainer content; + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + /// + /// Text to display in the left area of the display. + /// + //protected abstract LocalisableString Label { get; } + protected LocalisableString Label => CommonStrings.Finish; + //protected string Label { get; } + + protected virtual float ValueAreaWidth => 56; + + protected virtual string CounterFormat => @"N0"; + + protected override Container Content => content; + + protected readonly RollingCounter Counter; + + public ModMapInfoDisplay() + { + Height = HEIGHT; + AutoSizeAxes = Axes.X; + + InternalChild = new InputBlockingContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Masking = true, + CornerRadius = ModSelectPanel.CORNER_RADIUS, + Shear = new Vector2(ShearedOverlayContainer.SHEAR, 0), + Children = new Drawable[] + { + contentBackground = new Box + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.Y, + Width = ValueAreaWidth + ModSelectPanel.CORNER_RADIUS + }, + new GridContainer + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, ValueAreaWidth) + }, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Masking = true, + CornerRadius = ModSelectPanel.CORNER_RADIUS, + Children = new Drawable[] + { + labelBackground = new Box + { + RelativeSizeAxes = Axes.Both + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Horizontal = 18 }, + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), + Text = Label, + Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold) + } + } + }, + content = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Horizontal, + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), + Spacing = new Vector2(2, 0), + Child = Counter = new EffectCounter(CounterFormat) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = { BindTarget = Current.Value.StarRating } + } + } + } + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load() + { + labelBackground.Colour = colourProvider.Background4; + } + + protected override void LoadComplete() + { + Current.BindValueChanged(e => + { + //var effect = CalculateEffectForComparison(e.NewValue.CompareTo(Current.Default)); + setColours(e.NewValue.StarRating.Value); + }, true); + } + + /// + /// Fades colours of text and its background according to displayed value. + /// + /// random number. + private void setColours(double stars) + { + contentBackground.FadeColour(colours.ForStarDifficulty(stars), transition_duration, Easing.OutQuint); + } + + /// + /// Converts signed integer into . Negative values are counted as difficulty reduction, positive as increase. + /// + /// Value to convert. Will arrive from comparison between bindable once it changes and it's . + /// Effect of the value. + protected virtual ModEffect CalculateEffectForComparison(int comparison) + { + if (comparison == 0) + return ModEffect.NotChanged; + if (comparison < 0) + return ModEffect.DifficultyReduction; + + return ModEffect.DifficultyIncrease; + } + + protected enum ModEffect + { + NotChanged, + DifficultyReduction, + DifficultyIncrease + } + + private partial class EffectCounter : RollingCounter + { + private readonly string? format; + + public EffectCounter(string? format) + { + this.format = format; + } + + protected override double RollingDuration => 500; + + protected override LocalisableString FormatCount(double count) => count.ToLocalisableString(format); + + protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText + { + Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold) + }; + } + } +} diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 9e92e9d959..ef5f6cf323 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -25,6 +25,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Localisation; using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Select.Details; using osu.Game.Utils; using osuTK; using osuTK.Input; @@ -123,6 +124,7 @@ namespace osu.Game.Overlays.Mods private Container aboveColumnsContent = null!; private DifficultyMultiplierDisplay? multiplierDisplay; + private ModMapInfoDisplay mapInfoDisplay = null!; protected ShearedButton BackButton { get; private set; } = null!; protected ShearedToggleButton? CustomisationButton { get; private set; } @@ -219,6 +221,12 @@ namespace osu.Game.Overlays.Mods }); } + aboveColumnsContent.Add(mapInfoDisplay = new ModMapInfoDisplay + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft + }); + FooterContent.Child = footerButtonFlow = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -244,6 +252,10 @@ namespace osu.Game.Overlays.Mods globalAvailableMods.BindTo(game.AvailableMods); } + public void SetBindedMapStats(Bindable stats) + { + mapInfoDisplay.Current = stats; + } public override void Hide() { base.Hide(); @@ -399,6 +411,12 @@ namespace osu.Game.Overlays.Mods multiplierDisplay.Current.Value = multiplier; } + private void updateMapInfo() + { + if (mapInfoDisplay == null) + return; + } + private void updateCustomisation() { if (CustomisationButton == null) diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 712b610515..c56411bef5 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -3,6 +3,7 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -273,6 +274,11 @@ namespace osu.Game.Screens.Select loading.Hide(); } + public Bindable GetBindedAdjustedMapStats() + { + return advanced.AdjustedMapStats.GetBoundCopy(); + } + private partial class DetailBox : Container { private readonly Container content; diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index a383298faa..016e4ff2df 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -113,6 +113,8 @@ namespace osu.Game.Screens.Select.Details updateStatistics(); } + public Bindable AdjustedMapStats = new Bindable(); + private void updateStatistics() { IBeatmapDifficultyInfo baseDifficulty = BeatmapInfo?.Difficulty; @@ -146,6 +148,14 @@ namespace osu.Game.Screens.Select.Details ApproachRate.Value = (baseDifficulty?.ApproachRate ?? 0, adjustedDifficulty?.ApproachRate); updateStarDifficulty(); + + var temp = AdjustedMapStats.Value; + temp.CS.Value = FirstValue.Value.adjustedValue ?? 0; + temp.HP.Value = HpDrain.Value.adjustedValue ?? 0; + temp.OD.Value = Accuracy.Value.adjustedValue ?? 0; + temp.AR.Value = ApproachRate.Value.adjustedValue ?? 5; + AdjustedMapStats.Value = temp; + } private CancellationTokenSource starDifficultyCancellationSource; @@ -178,6 +188,11 @@ namespace osu.Game.Screens.Select.Details return; starDifficulty.Value = ((float)normalDifficulty.Value.Stars, (float)moddedDifficulty.Value.Stars); + + var temp = AdjustedMapStats.Value; + temp.StarRating.Value = moddedDifficulty.Value.Stars; + AdjustedMapStats.Value = temp; + }), starDifficultyCancellationSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current); }); @@ -296,4 +311,10 @@ namespace osu.Game.Screens.Select.Details } } } + public struct MapStats + { + public Bindable StarRating; + public Bindable MinBPM, MaxBPM, AvgBPM; + public Bindable CS, HP, AR, OD; + } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 58755878d0..17b1b1f870 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -305,6 +305,9 @@ namespace osu.Game.Screens.Select // therein it will be registered at the `OsuGame` level to properly function as a blocking overlay. LoadComponent(ModSelect = CreateModSelectOverlay()); + var bindedStats = BeatmapDetails.Details.GetBindedAdjustedMapStats(); + ModSelect.SetBindedMapStats(bindedStats); + if (Footer != null) { foreach (var (button, overlay) in CreateFooterButtons()) From e77581f64134f7c75b36776d223d7812bb9e4b42 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 27 Aug 2023 01:25:50 +0300 Subject: [PATCH 028/196] `wholeSpins` -> `currentSpins` --- .../Objects/Drawables/DrawableSpinner.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 0ceda1d4b0..2d2a4a05ac 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -286,7 +286,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private static readonly int score_per_tick = new SpinnerBonusTick.OsuSpinnerBonusTickJudgement().MaxNumericResult; - private int wholeSpins; + private int currentSpins; private void updateBonusScore() { @@ -295,14 +295,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables int spins = (int)(Result.RateAdjustedRotation / 360); - if (spins < wholeSpins) + if (spins < currentSpins) { // rewinding, silently handle - wholeSpins = spins; + currentSpins = spins; return; } - while (wholeSpins != spins) + while (currentSpins != spins) { var tick = ticks.FirstOrDefault(t => !t.Result.HasResult); @@ -315,7 +315,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables gainedBonus.Value = score_per_tick * (spins - HitObject.SpinsRequired); } - wholeSpins++; + currentSpins++; } } } From d614e745b8ff9e45bd46093741d810b18d255203 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 27 Aug 2023 01:27:19 +0300 Subject: [PATCH 029/196] Calculate spinner ticks as "whole spins" without arbitrary factors --- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index b800b03c92..f32c6ae979 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -42,15 +42,10 @@ namespace osu.Game.Rulesets.Osu.Objects { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); - // spinning doesn't match 1:1 with stable, so let's fudge them easier for the time being. - const double stable_matching_fudge = 0.6; - - // close to 477rpm - const double maximum_rotations_per_second = 8; + const double maximum_rotations_per_second = 477f / 60f; double secondsDuration = Duration / 1000; - - double minimumRotationsPerSecond = stable_matching_fudge * IBeatmapDifficultyInfo.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5); + double minimumRotationsPerSecond = IBeatmapDifficultyInfo.DifficultyRange(difficulty.OverallDifficulty, 1.5, 2.5, 3.75); SpinsRequired = (int)(secondsDuration * minimumRotationsPerSecond); MaximumBonusSpins = (int)((maximum_rotations_per_second - minimumRotationsPerSecond) * secondsDuration); From 3bcddf3cc8cb76f9ad154e4baeb39d30fc306e64 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 27 Aug 2023 01:27:48 +0300 Subject: [PATCH 030/196] Add gap of two whole spins before achieving bonus score --- .../Objects/Drawables/DrawableSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 2d2a4a05ac..20bbb9a1d1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -312,7 +312,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables tick.TriggerResult(true); if (tick is DrawableSpinnerBonusTick) - gainedBonus.Value = score_per_tick * (spins - HitObject.SpinsRequired); + gainedBonus.Value = score_per_tick * (spins - HitObject.FirstBonusSpin); } currentSpins++; diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index f32c6ae979..a26cb7b090 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -31,11 +31,21 @@ namespace osu.Game.Rulesets.Osu.Objects /// public int SpinsRequired { get; protected set; } = 1; + /// + /// The gap between spinner completion and the first bonus-awarding spin. + /// + private const int bonus_spins_gap = 2; + /// /// Number of spins available to give bonus, beyond . /// public int MaximumBonusSpins { get; protected set; } = 1; + /// + /// The first spin awarding bonus score. + /// + public int FirstBonusSpin => SpinsRequired + bonus_spins_gap; + public override Vector2 StackOffset => Vector2.Zero; protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) @@ -48,14 +58,14 @@ namespace osu.Game.Rulesets.Osu.Objects double minimumRotationsPerSecond = IBeatmapDifficultyInfo.DifficultyRange(difficulty.OverallDifficulty, 1.5, 2.5, 3.75); SpinsRequired = (int)(secondsDuration * minimumRotationsPerSecond); - MaximumBonusSpins = (int)((maximum_rotations_per_second - minimumRotationsPerSecond) * secondsDuration); + MaximumBonusSpins = (int)((maximum_rotations_per_second - minimumRotationsPerSecond) * secondsDuration) - bonus_spins_gap; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) { base.CreateNestedHitObjects(cancellationToken); - int totalSpins = MaximumBonusSpins + SpinsRequired; + int totalSpins = MaximumBonusSpins + SpinsRequired + bonus_spins_gap; for (int i = 0; i < totalSpins; i++) { @@ -63,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.Objects double startTime = StartTime + (float)(i + 1) / totalSpins * Duration; - AddNested(i < SpinsRequired + AddNested(i < FirstBonusSpin ? new SpinnerTick { StartTime = startTime, SpinnerDuration = Duration } : new SpinnerBonusTick { StartTime = startTime, SpinnerDuration = Duration, Samples = new[] { CreateHitSampleInfo("spinnerbonus") } }); } From 390b6f649dd9b9c6408d96b8a9347ba71b12c4a1 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 29 Aug 2023 03:46:11 +0900 Subject: [PATCH 031/196] Add test --- .../Mods/TestSceneManiaModDoubleTime.cs | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModDoubleTime.cs diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModDoubleTime.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModDoubleTime.cs new file mode 100644 index 0000000000..08e83b04b5 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModDoubleTime.cs @@ -0,0 +1,65 @@ +// 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 NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Replays; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Replays; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Mania.Tests.Mods +{ + public partial class TestSceneManiaModDoubleTime : ModTestScene + { + private const double offset = 18; + + protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); + + [Test] + public void TestHitWindowWithoutDoubleTime() => CreateModTest(new ModTestData + { + Mod = new ModNoMod(), + PassCondition = () => Player.ScoreProcessor.JudgedHits > 0 && Player.ScoreProcessor.Accuracy.Value != 1, + Autoplay = false, + Beatmap = new Beatmap + { + BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo }, + Difficulty = { OverallDifficulty = 10 }, + HitObjects = new List + { + new Note { StartTime = 1000 } + }, + }, + ReplayFrames = new List + { + new ManiaReplayFrame(1000 + offset, ManiaAction.Key1) + } + }); + + [Test] + public void TestHitWindowWithDoubleTime() => CreateModTest(new ModTestData + { + Mod = new ManiaModDoubleTime(), + PassCondition = () => Player.ScoreProcessor.JudgedHits > 0 && Player.ScoreProcessor.Accuracy.Value == 1, + Autoplay = false, + Beatmap = new Beatmap + { + BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo }, + Difficulty = { OverallDifficulty = 10 }, + HitObjects = new List + { + new Note { StartTime = 1000 } + }, + }, + ReplayFrames = new List + { + new ManiaReplayFrame(1000 + offset, ManiaAction.Key1) + } + }); + } +} From 50235cc2459c43802099b7b803396fbacf208af6 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Mon, 28 Aug 2023 23:16:33 +0300 Subject: [PATCH 032/196] somewhat working prototype --- osu.Game/Overlays/Mods/ModMapInfoContainer.cs | 58 ++++++++++++++++ osu.Game/Overlays/Mods/ModMapInfoDisplay.cs | 66 +++++++------------ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 17 +++-- osu.Game/Screens/Select/BeatmapDetailArea.cs | 4 ++ osu.Game/Screens/Select/BeatmapDetails.cs | 5 -- .../Screens/Select/Details/AdvancedStats.cs | 40 +++++------ osu.Game/Screens/Select/SongSelect.cs | 8 ++- 7 files changed, 121 insertions(+), 77 deletions(-) create mode 100644 osu.Game/Overlays/Mods/ModMapInfoContainer.cs diff --git a/osu.Game/Overlays/Mods/ModMapInfoContainer.cs b/osu.Game/Overlays/Mods/ModMapInfoContainer.cs new file mode 100644 index 0000000000..eb5291b0a8 --- /dev/null +++ b/osu.Game/Overlays/Mods/ModMapInfoContainer.cs @@ -0,0 +1,58 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Overlays.BeatmapSet; +using osu.Game.Resources.Localisation.Web; +using osu.Game.Screens.Select.Details; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Mods +{ + public partial class ModMapInfoContainer : Container + { + private ModMapInfoDisplay starRatingDisplay = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved] + private Bindable adjustedInfo { get; set; } = null!; + private Bindable starRatingValue = new Bindable(); + + //public ModMapInfoContainer() + //{ + // + //} + + protected override void LoadComplete() + { + starRatingDisplay = new ModMapInfoDisplay("Star Rating", colours.ForStarDifficulty); + starRatingDisplay.Current.BindTo(starRatingValue); + + Content.Add(starRatingDisplay); + + adjustedInfo.BindValueChanged(e => { updateValues(); }, true); + } + + private void updateValues() + { + starRatingValue.Value = adjustedInfo.Value.StarRating; + } + } +} diff --git a/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs b/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs index 20666391d6..ca815984ce 100644 --- a/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs +++ b/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs @@ -1,6 +1,7 @@ // 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.Bindables; using osu.Framework.Extensions.LocalisationExtensions; @@ -12,14 +13,13 @@ using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osu.Game.Screens.Select.Details; using osu.Game.Localisation; using osuTK; namespace osu.Game.Overlays.Mods { - public partial class ModMapInfoDisplay : Container, IHasCurrentValue + public partial class ModMapInfoDisplay : Container, IHasCurrentValue { public const float HEIGHT = 42; private const float transition_duration = 200; @@ -28,36 +28,40 @@ namespace osu.Game.Overlays.Mods private readonly Box labelBackground; private readonly FillFlowContainer content; - public Bindable Current - { - get => current.Current; - set => current.Current = value; - } - private readonly BindableWithCurrent current = new BindableWithCurrent(); + //public Bindable Current + //{ + // get => current.Current; + // set => current.Current = value; + //} + //private readonly BindableWithCurrent current = new BindableWithCurrent(); - [Resolved] - private OsuColour colours { get; set; } = null!; + public Bindable Current { get; set; } = new BindableWithCurrent(); + + //[Resolved] + //private OsuColour colours { get; set; } = null!; [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; + protected Func GetColor; + /// /// Text to display in the left area of the display. /// - //protected abstract LocalisableString Label { get; } - protected LocalisableString Label => CommonStrings.Finish; - //protected string Label { get; } + protected LocalisableString Label; protected virtual float ValueAreaWidth => 56; - protected virtual string CounterFormat => @"N0"; + protected virtual string CounterFormat => @"0.00"; protected override Container Content => content; protected readonly RollingCounter Counter; - public ModMapInfoDisplay() + public ModMapInfoDisplay(LocalisableString label, Func colorFunc) { + Label = label; + GetColor = colorFunc; Height = HEIGHT; AutoSizeAxes = Axes.X; @@ -125,7 +129,7 @@ namespace osu.Game.Overlays.Mods { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Current = { BindTarget = Current.Value.StarRating } + Current = { BindTarget = Current } } } } @@ -146,39 +150,17 @@ namespace osu.Game.Overlays.Mods Current.BindValueChanged(e => { //var effect = CalculateEffectForComparison(e.NewValue.CompareTo(Current.Default)); - setColours(e.NewValue.StarRating.Value); + setColours(e.NewValue); }, true); } /// /// Fades colours of text and its background according to displayed value. /// - /// random number. - private void setColours(double stars) + /// value + private void setColours(double value) { - contentBackground.FadeColour(colours.ForStarDifficulty(stars), transition_duration, Easing.OutQuint); - } - - /// - /// Converts signed integer into . Negative values are counted as difficulty reduction, positive as increase. - /// - /// Value to convert. Will arrive from comparison between bindable once it changes and it's . - /// Effect of the value. - protected virtual ModEffect CalculateEffectForComparison(int comparison) - { - if (comparison == 0) - return ModEffect.NotChanged; - if (comparison < 0) - return ModEffect.DifficultyReduction; - - return ModEffect.DifficultyIncrease; - } - - protected enum ModEffect - { - NotChanged, - DifficultyReduction, - DifficultyIncrease + contentBackground.FadeColour(GetColor(value), transition_duration, Easing.OutQuint); } private partial class EffectCounter : RollingCounter diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ef5f6cf323..a178f2e9dc 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -25,9 +25,9 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Localisation; using osu.Game.Rulesets.Mods; -using osu.Game.Screens.Select.Details; using osu.Game.Utils; using osuTK; +using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Overlays.Mods @@ -124,7 +124,8 @@ namespace osu.Game.Overlays.Mods private Container aboveColumnsContent = null!; private DifficultyMultiplierDisplay? multiplierDisplay; - private ModMapInfoDisplay mapInfoDisplay = null!; + + private ModMapInfoContainer mapInfoContainer = null!; protected ShearedButton BackButton { get; private set; } = null!; protected ShearedToggleButton? CustomisationButton { get; private set; } @@ -221,7 +222,7 @@ namespace osu.Game.Overlays.Mods }); } - aboveColumnsContent.Add(mapInfoDisplay = new ModMapInfoDisplay + aboveColumnsContent.Add(mapInfoContainer = new ModMapInfoContainer { Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft @@ -251,11 +252,6 @@ namespace osu.Game.Overlays.Mods globalAvailableMods.BindTo(game.AvailableMods); } - - public void SetBindedMapStats(Bindable stats) - { - mapInfoDisplay.Current = stats; - } public override void Hide() { base.Hide(); @@ -282,6 +278,7 @@ namespace osu.Game.Overlays.Mods SelectedMods.BindValueChanged(_ => { + updateMapInfo(); updateMultiplier(); updateFromExternalSelection(); updateCustomisation(); @@ -413,8 +410,10 @@ namespace osu.Game.Overlays.Mods private void updateMapInfo() { - if (mapInfoDisplay == null) + if (mapInfoContainer == null) return; + + //mapInfoDisplay.Current.Value = 5; } private void updateCustomisation() diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 595b86924b..d43831e576 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -30,6 +31,9 @@ namespace osu.Game.Screens.Select public readonly BeatmapDetails Details; + //[Cached] + //public Bindable AdjustedInfo { get; private set; } = new Bindable(); + protected Bindable CurrentTab => tabControl.Current; protected Bindable CurrentModsFilter => tabControl.CurrentModsFilter; diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index c56411bef5..6ebdca1b8d 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -274,11 +274,6 @@ namespace osu.Game.Screens.Select loading.Hide(); } - public Bindable GetBindedAdjustedMapStats() - { - return advanced.AdjustedMapStats.GetBoundCopy(); - } - private partial class DetailBox : Container { private readonly Container content; diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 016e4ff2df..8f609888df 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -46,6 +46,11 @@ namespace osu.Game.Screens.Select.Details private IBeatmapInfo beatmapInfo; +#nullable enable + [Resolved] + private Bindable? adjustedInfo { get; set; } = null; +#nullable disable + public IBeatmapInfo BeatmapInfo { get => beatmapInfo; @@ -99,6 +104,21 @@ namespace osu.Game.Screens.Select.Details private ModSettingChangeTracker modSettingChangeTracker; private ScheduledDelegate debouncedStatisticsUpdate; + private void updateBindedInfo() + { + if (adjustedInfo == null) return; + + BeatmapInfo adjusted = (BeatmapInfo)beatmapInfo; + adjusted.Difficulty.CircleSize = FirstValue.Value.adjustedValue ?? 0; + adjusted.Difficulty.DrainRate = HpDrain.Value.adjustedValue ?? 0; + adjusted.Difficulty.ApproachRate = ApproachRate.Value.adjustedValue ?? 5; + adjusted.Difficulty.OverallDifficulty = Accuracy.Value.adjustedValue ?? 0; + adjusted.StarRating = starDifficulty.Value.adjustedValue ?? 0; + + adjustedInfo.Value = adjusted; + adjustedInfo.TriggerChange(); + } + private void modsChanged(ValueChangedEvent> mods) { modSettingChangeTracker?.Dispose(); @@ -113,8 +133,6 @@ namespace osu.Game.Screens.Select.Details updateStatistics(); } - public Bindable AdjustedMapStats = new Bindable(); - private void updateStatistics() { IBeatmapDifficultyInfo baseDifficulty = BeatmapInfo?.Difficulty; @@ -149,13 +167,6 @@ namespace osu.Game.Screens.Select.Details updateStarDifficulty(); - var temp = AdjustedMapStats.Value; - temp.CS.Value = FirstValue.Value.adjustedValue ?? 0; - temp.HP.Value = HpDrain.Value.adjustedValue ?? 0; - temp.OD.Value = Accuracy.Value.adjustedValue ?? 0; - temp.AR.Value = ApproachRate.Value.adjustedValue ?? 5; - AdjustedMapStats.Value = temp; - } private CancellationTokenSource starDifficultyCancellationSource; @@ -188,10 +199,7 @@ namespace osu.Game.Screens.Select.Details return; starDifficulty.Value = ((float)normalDifficulty.Value.Stars, (float)moddedDifficulty.Value.Stars); - - var temp = AdjustedMapStats.Value; - temp.StarRating.Value = moddedDifficulty.Value.Stars; - AdjustedMapStats.Value = temp; + updateBindedInfo(); }), starDifficultyCancellationSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current); }); @@ -311,10 +319,4 @@ namespace osu.Game.Screens.Select.Details } } } - public struct MapStats - { - public Bindable StarRating; - public Bindable MinBPM, MaxBPM, AvgBPM; - public Bindable CS, HP, AR, OD; - } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 17b1b1f870..4567869e8e 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -99,6 +99,9 @@ namespace osu.Game.Screens.Select [Resolved] private Bindable> selectedMods { get; set; } = null!; + [Cached] + private Bindable adjustedInfo { get; set; } = new Bindable(); + protected BeatmapCarousel Carousel { get; private set; } = null!; private ParallaxContainer wedgeBackground = null!; @@ -305,8 +308,8 @@ namespace osu.Game.Screens.Select // therein it will be registered at the `OsuGame` level to properly function as a blocking overlay. LoadComponent(ModSelect = CreateModSelectOverlay()); - var bindedStats = BeatmapDetails.Details.GetBindedAdjustedMapStats(); - ModSelect.SetBindedMapStats(bindedStats); + //var bindedStats = BeatmapDetails.Details.GetBindedAdjustedMapStats(); + //ModSelect.SetBindedMapStats(bindedStats); if (Footer != null) { @@ -583,6 +586,7 @@ namespace osu.Game.Screens.Select FilterControl.Activate(); ModSelect.SelectedMods.BindTo(selectedMods); + //BeatmapDetails.AdjustedInfo.BindTo(adjustedInfo); beginLooping(); } From 47160f7744823a4f53716fbc001b707003430a15 Mon Sep 17 00:00:00 2001 From: Wleter Date: Thu, 31 Aug 2023 20:24:26 +0200 Subject: [PATCH 033/196] make getClosestAnchor work with rotated drawable --- .../SkinEditor/SkinSelectionHandler.cs | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs b/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs index 72216f040e..fe2816db6f 100644 --- a/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs @@ -291,7 +291,7 @@ namespace osu.Game.Overlays.SkinEditor if (parent == null) return drawable.Anchor; - var screenPosition = getScreenPosition(); + var screenPosition = drawable.ToScreenSpace(drawable.OriginPosition); var absolutePosition = parent.ToLocalSpace(screenPosition); var factor = parent.RelativeToAbsoluteFactor; @@ -313,26 +313,6 @@ namespace osu.Game.Overlays.SkinEditor result |= getAnchorFromPosition(absolutePosition.Y / factor.Y, Anchor.y0, Anchor.y1, Anchor.y2); return result; - - Vector2 getScreenPosition() - { - var quad = drawable.ScreenSpaceDrawQuad; - var origin = drawable.Origin; - - var pos = quad.TopLeft; - - if (origin.HasFlagFast(Anchor.x2)) - pos.X += quad.Width; - else if (origin.HasFlagFast(Anchor.x1)) - pos.X += quad.Width / 2f; - - if (origin.HasFlagFast(Anchor.y2)) - pos.Y += quad.Height; - else if (origin.HasFlagFast(Anchor.y1)) - pos.Y += quad.Height / 2f; - - return pos; - } } private static void applyAnchor(Drawable drawable, Anchor anchor) From f74dfa9c6cc23c2807225b3e69be4f6ba446adac Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 1 Sep 2023 22:55:32 +0300 Subject: [PATCH 034/196] Apply flashlight slider dim immediately to match osu!(stable) --- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index efeac9a180..765af80959 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void OnSliderTrackingChange(ValueChangedEvent e) { // If a slider is in a tracking state, a further dim should be applied to the (remaining) visible portion of the playfield over a brief duration. - this.TransformTo(nameof(FlashlightDim), e.NewValue ? 0.8f : 0.0f, 50); + FlashlightDim = e.NewValue ? 0.8f : 0.0f; } protected override bool OnMouseMove(MouseMoveEvent e) From 920c6fa48facbd43c5edbae6ea1e66468fadc9b3 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 1 Sep 2023 23:29:51 +0300 Subject: [PATCH 035/196] Update comment --- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 765af80959..252d7e2762 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void OnSliderTrackingChange(ValueChangedEvent e) { - // If a slider is in a tracking state, a further dim should be applied to the (remaining) visible portion of the playfield over a brief duration. + // If a slider is in a tracking state, a further dim should be applied to the (remaining) visible portion of the playfield. FlashlightDim = e.NewValue ? 0.8f : 0.0f; } From b0398b62595bbf099ce957cafe9af3ea9769f16a Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 3 Sep 2023 02:09:01 +0300 Subject: [PATCH 036/196] functionality is done --- osu.Game/Beatmaps/BeatmapShortInfo.cs | 29 +++ osu.Game/Overlays/Mods/ModMapInfoContainer.cs | 171 +++++++++++++--- osu.Game/Overlays/Mods/ModMapInfoDisplay.cs | 185 ------------------ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 17 +- .../Overlays/Mods/VerticalAttributeDisplay.cs | 76 +++++++ osu.Game/Screens/Select/BeatmapDetailArea.cs | 4 - .../Screens/Select/Details/AdvancedStats.cs | 33 ++-- osu.Game/Screens/Select/SongSelect.cs | 2 +- 8 files changed, 287 insertions(+), 230 deletions(-) create mode 100644 osu.Game/Beatmaps/BeatmapShortInfo.cs delete mode 100644 osu.Game/Overlays/Mods/ModMapInfoDisplay.cs create mode 100644 osu.Game/Overlays/Mods/VerticalAttributeDisplay.cs diff --git a/osu.Game/Beatmaps/BeatmapShortInfo.cs b/osu.Game/Beatmaps/BeatmapShortInfo.cs new file mode 100644 index 0000000000..633e12d1b2 --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapShortInfo.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Beatmaps +{ + public class BeatmapShortInfo : IEquatable + { + public StarDifficulty StarDifficulty; + public float CircleSize; + public float DrainRate; + public float ApproachRate; + public float OverallDifficulty; + public double BPM; + public bool Equals(BeatmapShortInfo? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return StarDifficulty.Stars == other.StarDifficulty.Stars && + CircleSize.Equals(other.CircleSize) && + DrainRate.Equals(other.DrainRate) && + ApproachRate.Equals(other.ApproachRate) && + OverallDifficulty.Equals(other.OverallDifficulty) && + BPM.Equals(other.BPM); + } + } +} diff --git a/osu.Game/Overlays/Mods/ModMapInfoContainer.cs b/osu.Game/Overlays/Mods/ModMapInfoContainer.cs index eb5291b0a8..378e6f6057 100644 --- a/osu.Game/Overlays/Mods/ModMapInfoContainer.cs +++ b/osu.Game/Overlays/Mods/ModMapInfoContainer.cs @@ -1,24 +1,21 @@ // 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; +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Colour; 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.Online; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Overlays.BeatmapSet; -using osu.Game.Resources.Localisation.Web; -using osu.Game.Screens.Select.Details; using osuTK; using osuTK.Graphics; @@ -26,33 +23,161 @@ namespace osu.Game.Overlays.Mods { public partial class ModMapInfoContainer : Container { - private ModMapInfoDisplay starRatingDisplay = null!; + private Container content; + private Container innerContent; + + private Box background; + private Box innerBackground; + + private StarRatingDisplay starRatingDisplay; + private BPMDisplay bpmDisplay; + + private VerticalAttributeDisplay circleSizeDisplay; + private VerticalAttributeDisplay drainRateDisplay; + private VerticalAttributeDisplay approachRateDisplay; + private VerticalAttributeDisplay overallDifficultyDisplay; [Resolved] - private OsuColour colours { get; set; } = null!; + private OverlayColourProvider colourProvider { get; set; } [Resolved] - private Bindable adjustedInfo { get; set; } = null!; - private Bindable starRatingValue = new Bindable(); + private Bindable adjustedInfo { get; set; } - //public ModMapInfoContainer() - //{ - // - //} + public ModMapInfoContainer() + { + // values as ModSelectOverlay footer buttons + const float shear = ShearedOverlayContainer.SHEAR; + const float corner_radius = 7; + const float border_thickness = 2; + InternalChild = content = new InputBlockingContainer + { + Origin = Anchor.BottomRight, + Anchor = Anchor.BottomRight, + AutoSizeAxes = Axes.X, + Height = 50, // as ModSelectOverlay footer buttons + Shear = new Vector2(shear, 0), + CornerRadius = corner_radius, + BorderThickness = border_thickness, + Masking = true, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer // divide inner and outer content + { + Origin = Anchor.BottomLeft, + Anchor = Anchor.BottomLeft, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + innerContent = new Container + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + BorderThickness = border_thickness, + CornerRadius = corner_radius, + Masking = true, + Children = new Drawable[] + { + innerBackground = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer // actual inner content + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Horizontal = 15 }, + Children = new Drawable[] + { + new Container // wrap to reserve space for StarRatingDisplay + { + Width = 70, // can be up to 70px on extra high SR + Child = starRatingDisplay = new StarRatingDisplay(default, animated: true) + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Shear = new Vector2(-shear, 0), + } + }, + new Container // wrap to reserve space for BPM + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Width = 70, + Child = bpmDisplay = new BPMDisplay + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Shear = new Vector2(-shear, 0), + } + } + } + } + } + }, + new FillFlowContainer // outer content + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Children = new[] + { + circleSizeDisplay = new VerticalAttributeDisplay("CS"), + drainRateDisplay = new VerticalAttributeDisplay("HP"), + approachRateDisplay = new VerticalAttributeDisplay("AR"), + overallDifficultyDisplay = new VerticalAttributeDisplay("OD"), + } + } + } + } + } + }; + } protected override void LoadComplete() { - starRatingDisplay = new ModMapInfoDisplay("Star Rating", colours.ForStarDifficulty); - starRatingDisplay.Current.BindTo(starRatingValue); + adjustedInfo.BindValueChanged(e => { UpdateValues(); }, true); - Content.Add(starRatingDisplay); + background.Colour = colourProvider.Background4; + innerBackground.Colour = colourProvider.Background3; + Color4 glow_colour = colourProvider.Background1; - adjustedInfo.BindValueChanged(e => { updateValues(); }, true); + content.BorderColour = ColourInfo.GradientVertical(background.Colour, glow_colour); + innerContent.BorderColour = ColourInfo.GradientVertical(innerBackground.Colour, glow_colour); } - private void updateValues() + public void UpdateValues() { - starRatingValue.Value = adjustedInfo.Value.StarRating; + if (adjustedInfo.Value == null) return; + + starRatingDisplay.Current.Value = adjustedInfo.Value.StarDifficulty; + bpmDisplay.Current.Value = adjustedInfo.Value.BPM; + + circleSizeDisplay.Current.Value = adjustedInfo.Value.CircleSize; + drainRateDisplay.Current.Value = adjustedInfo.Value.DrainRate; + approachRateDisplay.Current.Value = adjustedInfo.Value.ApproachRate; + overallDifficultyDisplay.Current.Value = adjustedInfo.Value.OverallDifficulty; + } + + private partial class BPMDisplay : RollingCounter + { + protected override double RollingDuration => 500; + + protected override LocalisableString FormatCount(double count) => count.ToLocalisableString("0 BPM"); + + protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText + { + Font = OsuFont.Default.With(size: 20, weight: FontWeight.SemiBold) + }; } } } diff --git a/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs b/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs deleted file mode 100644 index ca815984ce..0000000000 --- a/osu.Game/Overlays/Mods/ModMapInfoDisplay.cs +++ /dev/null @@ -1,185 +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.Bindables; -using osu.Framework.Extensions.LocalisationExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Localisation; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Localisation; -using osuTK; - - -namespace osu.Game.Overlays.Mods -{ - public partial class ModMapInfoDisplay : Container, IHasCurrentValue - { - public const float HEIGHT = 42; - private const float transition_duration = 200; - - private readonly Box contentBackground; - private readonly Box labelBackground; - private readonly FillFlowContainer content; - - //public Bindable Current - //{ - // get => current.Current; - // set => current.Current = value; - //} - //private readonly BindableWithCurrent current = new BindableWithCurrent(); - - public Bindable Current { get; set; } = new BindableWithCurrent(); - - //[Resolved] - //private OsuColour colours { get; set; } = null!; - - [Resolved] - private OverlayColourProvider colourProvider { get; set; } = null!; - - protected Func GetColor; - - /// - /// Text to display in the left area of the display. - /// - protected LocalisableString Label; - - protected virtual float ValueAreaWidth => 56; - - protected virtual string CounterFormat => @"0.00"; - - protected override Container Content => content; - - protected readonly RollingCounter Counter; - - public ModMapInfoDisplay(LocalisableString label, Func colorFunc) - { - Label = label; - GetColor = colorFunc; - Height = HEIGHT; - AutoSizeAxes = Axes.X; - - InternalChild = new InputBlockingContainer - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Masking = true, - CornerRadius = ModSelectPanel.CORNER_RADIUS, - Shear = new Vector2(ShearedOverlayContainer.SHEAR, 0), - Children = new Drawable[] - { - contentBackground = new Box - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.Y, - Width = ValueAreaWidth + ModSelectPanel.CORNER_RADIUS - }, - new GridContainer - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Absolute, ValueAreaWidth) - }, - Content = new[] - { - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Masking = true, - CornerRadius = ModSelectPanel.CORNER_RADIUS, - Children = new Drawable[] - { - labelBackground = new Box - { - RelativeSizeAxes = Axes.Both - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Margin = new MarginPadding { Horizontal = 18 }, - Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), - Text = Label, - Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold) - } - } - }, - content = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Direction = FillDirection.Horizontal, - Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), - Spacing = new Vector2(2, 0), - Child = Counter = new EffectCounter(CounterFormat) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Current = { BindTarget = Current } - } - } - } - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load() - { - labelBackground.Colour = colourProvider.Background4; - } - - protected override void LoadComplete() - { - Current.BindValueChanged(e => - { - //var effect = CalculateEffectForComparison(e.NewValue.CompareTo(Current.Default)); - setColours(e.NewValue); - }, true); - } - - /// - /// Fades colours of text and its background according to displayed value. - /// - /// value - private void setColours(double value) - { - contentBackground.FadeColour(GetColor(value), transition_duration, Easing.OutQuint); - } - - private partial class EffectCounter : RollingCounter - { - private readonly string? format; - - public EffectCounter(string? format) - { - this.format = format; - } - - protected override double RollingDuration => 500; - - protected override LocalisableString FormatCount(double count) => count.ToLocalisableString(format); - - protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText - { - Font = OsuFont.Default.With(size: 17, weight: FontWeight.SemiBold) - }; - } - } -} diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index a178f2e9dc..426c424541 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -222,13 +222,18 @@ namespace osu.Game.Overlays.Mods }); } - aboveColumnsContent.Add(mapInfoContainer = new ModMapInfoContainer + FooterContent.Add(mapInfoContainer = new ModMapInfoContainer { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Padding = new MarginPadding + { + Vertical = PADDING, + Horizontal = 70 + }, }); - FooterContent.Child = footerButtonFlow = new FillFlowContainer + FooterContent.Add(footerButtonFlow = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -248,7 +253,7 @@ namespace osu.Game.Overlays.Mods DarkerColour = colours.Pink2, LighterColour = colours.Pink1 }) - }; + }); globalAvailableMods.BindTo(game.AvailableMods); } @@ -413,7 +418,7 @@ namespace osu.Game.Overlays.Mods if (mapInfoContainer == null) return; - //mapInfoDisplay.Current.Value = 5; + mapInfoContainer.UpdateValues(); } private void updateCustomisation() diff --git a/osu.Game/Overlays/Mods/VerticalAttributeDisplay.cs b/osu.Game/Overlays/Mods/VerticalAttributeDisplay.cs new file mode 100644 index 0000000000..2ad420657c --- /dev/null +++ b/osu.Game/Overlays/Mods/VerticalAttributeDisplay.cs @@ -0,0 +1,76 @@ +// 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.Bindables; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; + + +namespace osu.Game.Overlays.Mods +{ + public partial class VerticalAttributeDisplay : Container, IHasCurrentValue + { + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + /// + /// Text to display in the top area of the display. + /// + public LocalisableString Label { get; protected set; } + + public VerticalAttributeDisplay(LocalisableString label) + { + Label = label; + AutoSizeAxes = Axes.X; + Origin = Anchor = Anchor.CentreLeft; + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0); + InternalChild = new FillFlowContainer + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuSpriteText + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Text = Label, + Margin = new MarginPadding { Horizontal = 15 }, // to reserve space for 0.XX value + Font = OsuFont.Default.With(size: 20, weight: FontWeight.Bold) + }, + new EffectCounter() + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Current = { BindTarget = Current } + } + } + }; + } + + private partial class EffectCounter : RollingCounter + { + protected override double RollingDuration => 500; + + protected override LocalisableString FormatCount(double count) => count.ToLocalisableString("0.##"); + + protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText + { + Font = OsuFont.Default.With(size: 18, weight: FontWeight.SemiBold) + }; + } + } +} diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index d43831e576..595b86924b 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -4,7 +4,6 @@ #nullable disable using System; -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -31,9 +30,6 @@ namespace osu.Game.Screens.Select public readonly BeatmapDetails Details; - //[Cached] - //public Bindable AdjustedInfo { get; private set; } = new Bindable(); - protected Bindable CurrentTab => tabControl.Current; protected Bindable CurrentModsFilter => tabControl.CurrentModsFilter; diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 8f609888df..31fac8b4a0 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -46,10 +46,8 @@ namespace osu.Game.Screens.Select.Details private IBeatmapInfo beatmapInfo; -#nullable enable - [Resolved] - private Bindable? adjustedInfo { get; set; } = null; -#nullable disable + [Resolved(canBeNull: true)] + private Bindable adjustedInfo { get; set; } = null; public IBeatmapInfo BeatmapInfo { @@ -104,19 +102,30 @@ namespace osu.Game.Screens.Select.Details private ModSettingChangeTracker modSettingChangeTracker; private ScheduledDelegate debouncedStatisticsUpdate; + private StarDifficulty latestStarDifficulty = new StarDifficulty(); private void updateBindedInfo() { if (adjustedInfo == null) return; - BeatmapInfo adjusted = (BeatmapInfo)beatmapInfo; - adjusted.Difficulty.CircleSize = FirstValue.Value.adjustedValue ?? 0; - adjusted.Difficulty.DrainRate = HpDrain.Value.adjustedValue ?? 0; - adjusted.Difficulty.ApproachRate = ApproachRate.Value.adjustedValue ?? 5; - adjusted.Difficulty.OverallDifficulty = Accuracy.Value.adjustedValue ?? 0; - adjusted.StarRating = starDifficulty.Value.adjustedValue ?? 0; + // sadly need to calculate this to prevent additional data transportation + double rate = 1; + foreach (var mod in mods.Value.OfType()) + rate = mod.ApplyToRate(0, rate); + + double bpm = 0; + if (beatmapInfo != null) bpm = beatmapInfo.BPM * rate; + + BeatmapShortInfo adjusted = new BeatmapShortInfo() + { + CircleSize = FirstValue.Value.adjustedValue ?? FirstValue.Value.baseValue, + DrainRate = HpDrain.Value.adjustedValue ?? HpDrain.Value.baseValue, + ApproachRate = ApproachRate.Value.adjustedValue ?? ApproachRate.Value.baseValue, + OverallDifficulty = Accuracy.Value.adjustedValue ?? Accuracy.Value.baseValue, + BPM = bpm, + StarDifficulty = latestStarDifficulty + }; adjustedInfo.Value = adjusted; - adjustedInfo.TriggerChange(); } private void modsChanged(ValueChangedEvent> mods) @@ -165,6 +174,7 @@ namespace osu.Game.Screens.Select.Details Accuracy.Value = (baseDifficulty?.OverallDifficulty ?? 0, adjustedDifficulty?.OverallDifficulty); ApproachRate.Value = (baseDifficulty?.ApproachRate ?? 0, adjustedDifficulty?.ApproachRate); + updateBindedInfo(); // to faster UI response (without SR calculation) updateStarDifficulty(); } @@ -199,6 +209,7 @@ namespace osu.Game.Screens.Select.Details return; starDifficulty.Value = ((float)normalDifficulty.Value.Stars, (float)moddedDifficulty.Value.Stars); + latestStarDifficulty = moddedDifficulty ?? default; updateBindedInfo(); }), starDifficultyCancellationSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 4567869e8e..ad98d1721b 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select private Bindable> selectedMods { get; set; } = null!; [Cached] - private Bindable adjustedInfo { get; set; } = new Bindable(); + private Bindable adjustedInfo { get; set; } = new Bindable(); protected BeatmapCarousel Carousel { get; private set; } = null!; From 0779cd8f4f998c2d9b29fd71787681875bec9979 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 3 Sep 2023 02:17:04 +0300 Subject: [PATCH 037/196] minor design fixes --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 59 ++++++++++++---------- osu.Game/Screens/Select/SongSelect.cs | 4 -- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 426c424541..8de4447b31 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -222,41 +222,44 @@ namespace osu.Game.Overlays.Mods }); } - FooterContent.Add(mapInfoContainer = new ModMapInfoContainer + FooterContent.Children = new Drawable[] { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Padding = new MarginPadding + mapInfoContainer = new ModMapInfoContainer { - Vertical = PADDING, - Horizontal = 70 + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Padding = new MarginPadding + { + Vertical = PADDING, + Horizontal = 70 + } }, - }); - - FooterContent.Add(footerButtonFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Padding = new MarginPadding + footerButtonFlow = new FillFlowContainer { - Vertical = PADDING, - Horizontal = 70 - }, - Spacing = new Vector2(10), - ChildrenEnumerable = CreateFooterButtons().Prepend(BackButton = new ShearedButton(BUTTON_WIDTH) - { - Text = CommonStrings.Back, - Action = Hide, - DarkerColour = colours.Pink2, - LighterColour = colours.Pink1 - }) - }); + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Padding = new MarginPadding + { + Vertical = PADDING, + Horizontal = 70 + }, + Spacing = new Vector2(10), + ChildrenEnumerable = CreateFooterButtons().Prepend(BackButton = new ShearedButton(BUTTON_WIDTH) + { + Text = CommonStrings.Back, + Action = Hide, + DarkerColour = colours.Pink2, + LighterColour = colours.Pink1 + }) + } + }; globalAvailableMods.BindTo(game.AvailableMods); } + public override void Hide() { base.Hide(); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index ad98d1721b..7749e3937a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -308,9 +308,6 @@ namespace osu.Game.Screens.Select // therein it will be registered at the `OsuGame` level to properly function as a blocking overlay. LoadComponent(ModSelect = CreateModSelectOverlay()); - //var bindedStats = BeatmapDetails.Details.GetBindedAdjustedMapStats(); - //ModSelect.SetBindedMapStats(bindedStats); - if (Footer != null) { foreach (var (button, overlay) in CreateFooterButtons()) @@ -586,7 +583,6 @@ namespace osu.Game.Screens.Select FilterControl.Activate(); ModSelect.SelectedMods.BindTo(selectedMods); - //BeatmapDetails.AdjustedInfo.BindTo(adjustedInfo); beginLooping(); } From 5e5fe84a88d15af428ee6bff7ecd3e46b26bbf65 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 3 Sep 2023 02:19:02 +0300 Subject: [PATCH 038/196] Update AdvancedStats.cs --- osu.Game/Screens/Select/Details/AdvancedStats.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 31fac8b4a0..a12323ab70 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -176,7 +176,6 @@ namespace osu.Game.Screens.Select.Details updateBindedInfo(); // to faster UI response (without SR calculation) updateStarDifficulty(); - } private CancellationTokenSource starDifficultyCancellationSource; From 079792644886a6c57fb03eee397d9594419e5847 Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 3 Sep 2023 12:19:03 +0300 Subject: [PATCH 039/196] Update VerticalAttributeDisplay.cs --- osu.Game/Overlays/Mods/VerticalAttributeDisplay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/VerticalAttributeDisplay.cs b/osu.Game/Overlays/Mods/VerticalAttributeDisplay.cs index 2ad420657c..95d979ebd2 100644 --- a/osu.Game/Overlays/Mods/VerticalAttributeDisplay.cs +++ b/osu.Game/Overlays/Mods/VerticalAttributeDisplay.cs @@ -12,7 +12,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osuTK; - namespace osu.Game.Overlays.Mods { public partial class VerticalAttributeDisplay : Container, IHasCurrentValue From 8281ed5173af43556f8b2e5ba937a2e66eff7f3a Mon Sep 17 00:00:00 2001 From: Givikap120 Date: Sun, 3 Sep 2023 14:51:53 +0300 Subject: [PATCH 040/196] Fixed "no animations" issue --- osu.Game/Overlays/Mods/ModMapInfoContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Mods/ModMapInfoContainer.cs b/osu.Game/Overlays/Mods/ModMapInfoContainer.cs index 378e6f6057..281fe8abe5 100644 --- a/osu.Game/Overlays/Mods/ModMapInfoContainer.cs +++ b/osu.Game/Overlays/Mods/ModMapInfoContainer.cs @@ -50,6 +50,7 @@ namespace osu.Game.Overlays.Mods const float corner_radius = 7; const float border_thickness = 2; + AutoSizeAxes = Axes.Both; InternalChild = content = new InputBlockingContainer { Origin = Anchor.BottomRight, From b17a55d6a84aba14c6387a03d64053f5b82d4751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=E1=BB=93=20Nguy=C3=AAn=20Minh?= Date: Mon, 4 Sep 2023 10:43:05 +0700 Subject: [PATCH 041/196] Add length check for slider velocity --- .../Edit/Compose/Components/Timeline/DifficultyPointPiece.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 173a665d5c..366518eb58 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -177,6 +177,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline AddHeader("Final velocity"); AddValue($"{beatmapVelocity * current.Value:#,0.00}x"); + if (sliderVelocities.Length == 0) return; if (sliderVelocities.First() != sliderVelocities.Last()) { AddHeader("Beatmap velocity range"); From d5a89c4c45eddff8eb2d88cb7739c08e3260fecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=E1=BB=93=20Nguy=C3=AAn=20Minh?= Date: Mon, 4 Sep 2023 13:32:42 +0700 Subject: [PATCH 042/196] Fix formatting --- .../Compose/Components/Timeline/DifficultyPointPiece.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 366518eb58..99fb2ab874 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -177,7 +177,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline AddHeader("Final velocity"); AddValue($"{beatmapVelocity * current.Value:#,0.00}x"); - if (sliderVelocities.Length == 0) return; + if (sliderVelocities.Length == 0) + { + return; + } + if (sliderVelocities.First() != sliderVelocities.Last()) { AddHeader("Beatmap velocity range"); From 0a1ba2ebe08877717f4617cb4d3070ea33d3b3b9 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 4 Sep 2023 15:56:32 +0900 Subject: [PATCH 043/196] Remove ModNoMod usage --- .../Mods/TestSceneManiaModDoubleTime.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModDoubleTime.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModDoubleTime.cs index 08e83b04b5..00b79529a9 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModDoubleTime.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModDoubleTime.cs @@ -7,7 +7,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Replays; using osu.Game.Tests.Visual; @@ -23,7 +22,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods [Test] public void TestHitWindowWithoutDoubleTime() => CreateModTest(new ModTestData { - Mod = new ModNoMod(), PassCondition = () => Player.ScoreProcessor.JudgedHits > 0 && Player.ScoreProcessor.Accuracy.Value != 1, Autoplay = false, Beatmap = new Beatmap From 5abf271b56e24adeecffbcb60ca3edd8c62e667c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 3 Sep 2023 21:49:29 -0700 Subject: [PATCH 044/196] Implement beatmap options popover --- .../SongSelect/TestSceneSongSelectFooterV2.cs | 7 +- .../Select/FooterV2/BeatmapOptionsPopover.cs | 148 ++++++++++++++++++ .../Select/FooterV2/FooterButtonOptionsV2.cs | 37 ++++- osu.Game/Screens/Select/FooterV2/FooterV2.cs | 10 +- osu.Game/Screens/Select/SongSelect.cs | 18 +-- 5 files changed, 205 insertions(+), 15 deletions(-) create mode 100644 osu.Game/Screens/Select/FooterV2/BeatmapOptionsPopover.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs index 72adbfc104..ed2ae67ae5 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooterV2.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Testing; using osu.Game.Overlays; using osu.Game.Overlays.Mods; @@ -37,10 +38,10 @@ namespace osu.Game.Tests.Visual.SongSelect Children = new Drawable[] { - footer = new FooterV2 + new PopoverContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre + RelativeSizeAxes = Axes.Both, + Child = footer = new FooterV2(), }, overlay = new DummyOverlay() }; diff --git a/osu.Game/Screens/Select/FooterV2/BeatmapOptionsPopover.cs b/osu.Game/Screens/Select/FooterV2/BeatmapOptionsPopover.cs new file mode 100644 index 0000000000..ec35c6ff38 --- /dev/null +++ b/osu.Game/Screens/Select/FooterV2/BeatmapOptionsPopover.cs @@ -0,0 +1,148 @@ +// 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.Linq; +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.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Collections; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays; +using osuTK; +using osuTK.Graphics; +using osuTK.Input; + +namespace osu.Game.Screens.Select.FooterV2 +{ + public partial class BeatmapOptionsPopover : OsuPopover + { + private FillFlowContainer buttonFlow = null!; + private readonly FooterButtonOptionsV2 footerButton; + + public BeatmapOptionsPopover(FooterButtonOptionsV2 footerButton) + { + this.footerButton = footerButton; + } + + [BackgroundDependencyLoader] + private void load(ManageCollectionsDialog? manageCollectionsDialog, SongSelect? songSelect, OsuColour colours) + { + Content.Padding = new MarginPadding(5); + + Child = buttonFlow = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(3), + }; + + addButton(@"Manage collections", FontAwesome.Solid.Book, () => manageCollectionsDialog?.Show()); + addButton(@"Delete all difficulties", FontAwesome.Solid.Trash, () => songSelect?.DeleteBeatmap(), colours.Red); + addButton(@"Remove from unplayed", FontAwesome.Regular.TimesCircle, null); + addButton(@"Clear local scores", FontAwesome.Solid.Eraser, () => songSelect?.ClearScores()); + + if (songSelect != null && songSelect.AllowEditing) + addButton(@"Edit beatmap", FontAwesome.Solid.PencilAlt, () => songSelect.Edit()); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(this)); + } + + private void addButton(LocalisableString text, IconUsage icon, Action? action, Color4? colour = null) + { + var button = new OptionButton + { + Text = text, + Icon = icon, + TextColour = colour, + Action = () => + { + Hide(); + action?.Invoke(); + }, + }; + + buttonFlow.Add(button); + } + + private partial class OptionButton : OsuButton + { + public IconUsage Icon { get; init; } + public Color4? TextColour { get; init; } + + public OptionButton() + { + Size = new Vector2(265, 50); + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + BackgroundColour = colourProvider.Background3; + + SpriteText.Colour = TextColour ?? Color4.White; + Content.CornerRadius = 10; + + Add(new SpriteIcon + { + Blending = BlendingParameters.Additive, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(17), + X = 15, + Icon = Icon, + Colour = TextColour ?? Color4.White, + }); + } + + protected override SpriteText CreateText() => new OsuSpriteText + { + Depth = -1, + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + X = 40 + }; + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + // don't absorb control as ToolbarRulesetSelector uses control + number to navigate + if (e.ControlPressed) return false; + + if (!e.Repeat && e.Key >= Key.Number1 && e.Key <= Key.Number9) + { + int requested = e.Key - Key.Number1; + + OptionButton? found = buttonFlow.Children.ElementAtOrDefault(requested); + + if (found != null) + { + found.TriggerClick(); + return true; + } + } + + return base.OnKeyDown(e); + } + + protected override void UpdateState(ValueChangedEvent state) + { + base.UpdateState(state); + + if (state.NewValue == Visibility.Hidden) + footerButton.IsActive.Value = false; + } + } +} diff --git a/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs b/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs index 87cca0042a..a1559d32dc 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterButtonOptionsV2.cs @@ -2,14 +2,21 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Input.Bindings; namespace osu.Game.Screens.Select.FooterV2 { - public partial class FooterButtonOptionsV2 : FooterButtonV2 + public partial class FooterButtonOptionsV2 : FooterButtonV2, IHasPopover { + public readonly BindableBool IsActive = new BindableBool(); + [BackgroundDependencyLoader] private void load(OsuColour colour) { @@ -17,6 +24,34 @@ namespace osu.Game.Screens.Select.FooterV2 Icon = FontAwesome.Solid.Cog; AccentColour = colour.Purple1; Hotkey = GlobalAction.ToggleBeatmapOptions; + + Action = () => IsActive.Toggle(); } + + protected override void LoadComplete() + { + base.LoadComplete(); + + IsActive.BindValueChanged(active => + { + OverlayState.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden; + }); + + OverlayState.BindValueChanged(state => + { + switch (state.NewValue) + { + case Visibility.Hidden: + this.HidePopover(); + break; + + case Visibility.Visible: + this.ShowPopover(); + break; + } + }); + } + + public Popover GetPopover() => new BeatmapOptionsPopover(this); } } diff --git a/osu.Game/Screens/Select/FooterV2/FooterV2.cs b/osu.Game/Screens/Select/FooterV2/FooterV2.cs index cd95f3eb6c..0529f0d082 100644 --- a/osu.Game/Screens/Select/FooterV2/FooterV2.cs +++ b/osu.Game/Screens/Select/FooterV2/FooterV2.cs @@ -48,11 +48,17 @@ namespace osu.Game.Screens.Select.FooterV2 private FillFlowContainer buttons = null!; - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + public FooterV2() { RelativeSizeAxes = Axes.X; Height = height; + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { InternalChildren = new Drawable[] { new Box diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 58755878d0..4ce7a6167e 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -311,9 +311,9 @@ namespace osu.Game.Screens.Select Footer.AddButton(button, overlay); BeatmapOptions.AddButton(@"Manage", @"collections", FontAwesome.Solid.Book, colours.Green, () => manageCollectionsDialog?.Show()); - BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo)); + BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, DeleteBeatmap); BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.Regular.TimesCircle, colours.Purple, null); - BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo)); + BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.Solid.Eraser, colours.Purple, ClearScores); } sampleChangeDifficulty = audio.Samples.Get(@"SongSelect/select-difficulty"); @@ -916,18 +916,18 @@ namespace osu.Game.Screens.Select return true; } - private void delete(BeatmapSetInfo? beatmap) + public void DeleteBeatmap() { - if (beatmap == null) return; + if (Beatmap.Value.BeatmapSetInfo == null) return; - dialogOverlay?.Push(new BeatmapDeleteDialog(beatmap)); + dialogOverlay?.Push(new BeatmapDeleteDialog(Beatmap.Value.BeatmapSetInfo)); } - private void clearScores(BeatmapInfo? beatmapInfo) + public void ClearScores() { - if (beatmapInfo == null) return; + if (Beatmap.Value.BeatmapInfo == null) return; - dialogOverlay?.Push(new BeatmapClearScoresDialog(beatmapInfo, () => + dialogOverlay?.Push(new BeatmapClearScoresDialog(Beatmap.Value.BeatmapInfo, () => // schedule done here rather than inside the dialog as the dialog may fade out and never callback. Schedule(() => BeatmapDetails.Refresh()))); } @@ -963,7 +963,7 @@ namespace osu.Game.Screens.Select if (e.ShiftPressed) { if (!Beatmap.IsDefault) - delete(Beatmap.Value.BeatmapSetInfo); + DeleteBeatmap(); return true; } From 6c0bd13308589a8efcc2ba83738bc6ed0c2c6ca9 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 00:21:48 -0700 Subject: [PATCH 045/196] Add xmldoc to newly exposed methods --- osu.Game/Screens/Select/SongSelect.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 4ce7a6167e..f6fc55b2a5 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -916,6 +916,9 @@ namespace osu.Game.Screens.Select return true; } + /// + /// Request to delete the current beatmap. + /// public void DeleteBeatmap() { if (Beatmap.Value.BeatmapSetInfo == null) return; @@ -923,6 +926,9 @@ namespace osu.Game.Screens.Select dialogOverlay?.Push(new BeatmapDeleteDialog(Beatmap.Value.BeatmapSetInfo)); } + /// + /// Request to clear the scores of the current beatmap. + /// public void ClearScores() { if (Beatmap.Value.BeatmapInfo == null) return; From f616648730ac9fd438cc2d15aeb7eb065f875cae Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 09:40:35 -0700 Subject: [PATCH 046/196] Remove icon blending --- osu.Game/Screens/Select/FooterV2/BeatmapOptionsPopover.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Select/FooterV2/BeatmapOptionsPopover.cs b/osu.Game/Screens/Select/FooterV2/BeatmapOptionsPopover.cs index ec35c6ff38..4e1334fd11 100644 --- a/osu.Game/Screens/Select/FooterV2/BeatmapOptionsPopover.cs +++ b/osu.Game/Screens/Select/FooterV2/BeatmapOptionsPopover.cs @@ -97,7 +97,6 @@ namespace osu.Game.Screens.Select.FooterV2 Add(new SpriteIcon { - Blending = BlendingParameters.Additive, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Size = new Vector2(17), From bf71099e5743efb966482d5b145a551b0208729f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 11:34:21 -0700 Subject: [PATCH 047/196] Fix truncating sprite text usage --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index b7b60cffab..7821aa5be0 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -280,15 +280,14 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, Children = new Drawable[] { - TitleLabel = new OsuSpriteText + TitleLabel = new TruncatingSpriteText { Shadow = true, Current = { BindTarget = titleBinding }, Font = OsuFont.TorusAlternate.With(size: 40, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, - Truncate = true }, - ArtistLabel = new OsuSpriteText + 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, @@ -296,7 +295,6 @@ namespace osu.Game.Screens.Select // Not sure if this should be semi bold or medium Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, - Truncate = true } } } From e8a793425bf28e19ba3667c8c712c4db96fc09fa Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 12:38:40 -0700 Subject: [PATCH 048/196] Use right padding instead of negative x offset --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 7821aa5be0..284f14cd9e 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -155,18 +155,21 @@ namespace osu.Game.Screens.Select LoadComponentAsync(loadingInfo = new Container { - Masking = true, - // We offset this by the portion of the colour bar underneath we wish to show - X = -colour_bar_width, - CornerRadius = corner_radius, + Padding = new MarginPadding { Right = colour_bar_width }, RelativeSizeAxes = Axes.Both, Depth = DisplayedContent?.Depth + 1 ?? 0, - Children = new Drawable[] + Child = new Container { - // 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 } + 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 } + } } }, loaded => { From 2df20027355ddbf24bd43401ef5feabf5a7e1823 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 12:42:01 -0700 Subject: [PATCH 049/196] Move negative corner radius margin to constructor --- .../SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 16 ++++++++++------ osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index 09b93119cc..ae5b739c4d 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -50,13 +50,17 @@ namespace osu.Game.Tests.Visual.SongSelect RelativeSizeAxes = Axes.X, Margin = new MarginPadding { Top = 20, Left = -10 } }, - infoWedge = new TestBeatmapInfoWedgeV2 + new Container { - State = { Value = Visibility.Visible }, - Width = 0.6f, - RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Top = 20, Left = -10 } - }, + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 20 }, + Child = infoWedge = new TestBeatmapInfoWedgeV2 + { + State = { Value = Visibility.Visible }, + Width = 0.6f, + RelativeSizeAxes = Axes.X, + }, + } }); AddSliderStep("change star difficulty", 0, 11.9, 5.55, v => diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 284f14cd9e..742d9011b9 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -55,6 +55,7 @@ namespace osu.Game.Screens.Select Height = WEDGE_HEIGHT; Shear = wedged_container_shear; Masking = true; + Margin = new MarginPadding { Left = -corner_radius }; EdgeEffect = new EdgeEffectParameters { Colour = Colour4.Black.Opacity(0.2f), From e70510ef191ef345eee35b490a12118fbb29a755 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 12:56:20 -0700 Subject: [PATCH 050/196] Move drawable and binding logic to standard places --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 742d9011b9..de3e634819 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -46,9 +46,9 @@ namespace osu.Game.Screens.Select protected WedgeInfoText? Info { get; private set; } - private readonly Container difficultyColourBar; - private readonly StarCounter starCounter; - private readonly BufferedContainer bufferedContent; + private Container difficultyColourBar = null!; + private StarCounter starCounter = null!; + private BufferedContainer bufferedContent = null!; public BeatmapInfoWedgeV2() { @@ -63,7 +63,11 @@ namespace osu.Game.Screens.Select Radius = 3, }; CornerRadius = corner_radius; + } + [BackgroundDependencyLoader] + private void load() + { // We want to buffer the wedge to avoid weird transparency overlaps between the colour bar and the background. Child = bufferedContent = new BufferedContainer(pixelSnapping: true) { @@ -107,9 +111,10 @@ namespace osu.Game.Screens.Select }; } - [BackgroundDependencyLoader] - private void load() + protected override void LoadComplete() { + base.LoadComplete(); + ruleset.BindValueChanged(_ => updateDisplay()); } @@ -228,6 +233,8 @@ namespace osu.Game.Screens.Select public WedgeInfoText(WorkingBeatmap working) { this.working = working; + + RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] @@ -236,8 +243,6 @@ namespace osu.Game.Screens.Select var beatmapInfo = working.BeatmapInfo; var metadata = working.Metadata; - RelativeSizeAxes = Axes.Both; - titleBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); artistBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.ArtistUnicode, metadata.Artist)); From 82fb9dc2ef5eb03f2db25426f11a19f836e62f68 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 12:59:21 -0700 Subject: [PATCH 051/196] Simplify text initialization --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index de3e634819..fd655c50ca 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -212,9 +212,6 @@ namespace osu.Game.Screens.Select private StarRatingDisplay starRatingDisplay = null!; - private ILocalisedBindableString titleBinding = null!; - private ILocalisedBindableString artistBinding = null!; - private readonly WorkingBeatmap working; public IBindable DisplayedStars => starRatingDisplay.DisplayedStars; @@ -238,14 +235,11 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader] - private void load(LocalisationManager localisation) + private void load() { var beatmapInfo = working.BeatmapInfo; var metadata = working.Metadata; - titleBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); - artistBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.ArtistUnicode, metadata.Artist)); - Children = new Drawable[] { new FillFlowContainer @@ -292,7 +286,7 @@ namespace osu.Game.Screens.Select TitleLabel = new TruncatingSpriteText { Shadow = true, - Current = { BindTarget = titleBinding }, + Text = new RomanisableString(metadata.TitleUnicode, metadata.Title), Font = OsuFont.TorusAlternate.With(size: 40, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, }, @@ -300,7 +294,7 @@ namespace osu.Game.Screens.Select { // 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, - Current = { BindTarget = artistBinding }, + Text = new RomanisableString(metadata.ArtistUnicode, metadata.Artist), // Not sure if this should be semi bold or medium Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, From e0a9c7e9a9680004b98a8086354fb758b65daa51 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 14:54:58 -0700 Subject: [PATCH 052/196] Fix wedge showing abruptly in test --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index ae5b739c4d..3236841dc3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -56,7 +56,6 @@ namespace osu.Game.Tests.Visual.SongSelect Padding = new MarginPadding { Top = 20 }, Child = infoWedge = new TestBeatmapInfoWedgeV2 { - State = { Value = Visibility.Visible }, Width = 0.6f, RelativeSizeAxes = Axes.X, }, @@ -165,6 +164,7 @@ namespace osu.Game.Tests.Visual.SongSelect { containerBefore = infoWedge.DisplayedContent; infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : CreateWorkingBeatmap(b); + infoWedge.Show(); }); AddUntilStep("wait for async load", () => infoWedge.DisplayedContent != containerBefore); From 854bb323cc09e0a296ebd2ca948e4a6074950044 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 15:02:00 -0700 Subject: [PATCH 053/196] Remove weird red edge effect visibility --- .../Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index 3236841dc3..827d23c0fc 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -7,7 +7,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Testing; @@ -94,17 +93,6 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestWedgeVisibility() { - // Mostly just in case someone runs this test before others, - // leading to the shadow being very hard to see if it is black - AddStep("make shadow red for test visibility", () => - { - infoWedge.EdgeEffect = new EdgeEffectParameters - { - Colour = Colour4.Red, - Type = EdgeEffectType.Shadow, - Radius = 5, - }; - }); AddStep("hide", () => { infoWedge.Hide(); }); AddWaitStep("wait for hide", 3); AddAssert("check visibility", () => infoWedge.Alpha == 0); From 9accd0ded262e451792a10013762e442b5523441 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 15:02:38 -0700 Subject: [PATCH 054/196] Fix star rating rolling counter regression --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index fd655c50ca..5316b4620b 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -314,7 +314,7 @@ namespace osu.Game.Screens.Select starRatingDisplay.Current.Value = s.NewValue ?? default; // Don't roll the counter on initial display (but still allow it to roll on applying mods etc.) - if (starRatingDisplay.Alpha > 0) + if (!starRatingDisplay.IsPresent) starRatingDisplay.FinishTransforms(true); starRatingDisplay.FadeIn(transition_duration); From 98d027d207143532178e4588c279368abb391d8b Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 21:34:53 -0700 Subject: [PATCH 055/196] Fix star counter animating weird and delayed --- osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs index 5316b4620b..de930ff837 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs @@ -187,11 +187,16 @@ namespace osu.Game.Screens.Select Info.DisplayedStars.BindValueChanged(s => { - starCounter.Current = (float)s.NewValue; starCounter.Colour = s.NewValue >= 6.5 ? colours.Orange1 : Colour4.Black.Opacity(0.75f); difficultyColourBar.FadeColour(colours.ForStarDifficulty(s.NewValue)); }, true); + + Info.ActualStars.BindValueChanged(s => + { + // use actual stars as star counter has its own animation + starCounter.Current = (float)s.NewValue; + }); }); }); @@ -215,6 +220,7 @@ namespace osu.Game.Screens.Select private readonly WorkingBeatmap working; public IBindable DisplayedStars => starRatingDisplay.DisplayedStars; + public Bindable ActualStars = new Bindable(); [Resolved] private IBindable> mods { get; set; } = null!; @@ -312,6 +318,7 @@ namespace osu.Game.Screens.Select starDifficulty.BindValueChanged(s => { starRatingDisplay.Current.Value = s.NewValue ?? default; + ActualStars.Value = s.NewValue?.Stars ?? 0; // Don't roll the counter on initial display (but still allow it to roll on applying mods etc.) if (!starRatingDisplay.IsPresent) From 94516133912a4c32048dddc52c53fb9696bb0477 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 4 Sep 2023 21:39:26 -0700 Subject: [PATCH 056/196] Rename null beatmap test to indicate there's a background --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs index 827d23c0fc..a8484caf1c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedgeV2.cs @@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.SongSelect } [Test] - public void TestNullBeatmap() + public void TestNullBeatmapWithBackground() { selectBeatmap(null); AddAssert("check default title", () => infoWedge.Info!.TitleLabel.Current.Value == Beatmap.Default.BeatmapInfo.Metadata.Title); From 1215ad7ace400cb404121d9a8ead9ac81f2ad2a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Sep 2023 15:40:00 +0900 Subject: [PATCH 057/196] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 2d15bce85a..2bfdce5ab8 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - +