osu icon indicating copy to clipboard operation
osu copied to clipboard

Song select redesign

Open bdach opened this issue 2 years ago • 19 comments

  • Part of #18890
  • Related to https://github.com/ppy/osu/issues/13712 (overlapping components)

Designs:

  • https://www.figma.com/file/DXKwqZhD5yyb1igc3mKo1P/Song-Select-Draft-2?node-id=0%3A1
  • https://www.figma.com/file/EjS27IBaZhc2qX97lFBUxN/Song-Select-5?type=design&node-id=0-1&mode=design&t=niACBGHZtOud4FyQ-0 (new WIP iteration)

Work is in progress by ~@mk56-spn~ @Joehuu.

### Wedge/Info
- [ ] https://github.com/ppy/osu/pull/22116
- [ ] https://github.com/ppy/osu/pull/28063
- [ ] https://github.com/ppy/osu/pull/29415
- [ ] https://github.com/ppy/osu/pull/29437
### Carousel
- [ ] https://github.com/ppy/osu/pull/22197
### Footer
- [x] https://github.com/ppy/osu/pull/21491
- [x] https://github.com/ppy/osu/issues/24273
- [ ] https://github.com/ppy/osu/pull/28141
- [ ] https://github.com/ppy/osu/pull/28142
- [ ] https://github.com/ppy/osu/pull/28183
- [ ] ~Implement "let's go!" button?~
- [ ] https://github.com/ppy/osu/pull/28184
- [ ] https://github.com/ppy/osu/pull/28185
- [ ] https://github.com/ppy/osu/pull/28553
- [ ] https://github.com/ppy/osu/pull/28682
- [ ] https://github.com/ppy/osu/pull/28683
- [ ] Unranked indicator overlaps with buttons next to it (e.g. "Deselect All" button in mod overlay) (see https://discord.com/channels/188630481301012481/188630652340404224/1260509921959481354)
- [ ] Allow screens to add their own content to footer similar to overlays (see `ShearedOverlayContainer.CreateFooterContent`) (also see https://github.com/ppy/osu/pull/29165#issuecomment-2257359759)
### Leaderboards
- [ ] https://github.com/ppy/osu/pull/22237
### Filter Control
- [ ] Replace search with sheared variant (needs to have matches text implemented)

bdach avatar Jan 14 '23 18:01 bdach

I'll try to tackle this while the focus is on scoring.

Joehuu avatar Sep 04 '23 17:09 Joehuu

Sorry to pester about this, but it has been bothering me a bit as something that could potentially go south if not communicated. This issue tracks the addition of the "Let's GO!" button from figma, yet that seems to contradict what I have read on Discord https://discord.com/channels/188630481301012481/188630652340404224/1149721526279606396, which would be having the osu! cookie there instead

@Joehuu just making sure you were also aware of this conversation

NiceAesth avatar Sep 20 '23 08:09 NiceAesth

It's just there because it's in figma (even in the new iteration). I'll append a question mark to the task. I also don't like it replacing the osu! logo.

Joehuu avatar Sep 20 '23 19:09 Joehuu

I had some thoughts on the design:

The controls including and around the search bar really clash with the beatmap carousel behind them. I would give them some sort of background, something like this: image

I also don't like that density and fail rate are the stats shown here. I would show more useful statistics like OD/AR/CS/HP (possibly even Max PP above those?), and maybe make the top banner smaller. Something like this? image Unless that was what the Basic and Pro buttons were supposed to do (switch between the view shown and a different view with more stats?), in which case I think they should be labelled something else (maybe "Default" and "Compact"?)

april83c avatar Dec 29 '23 06:12 april83c

hope im not late, wanted to share my thoughts on new iteration. slightly different approach, aligned some stuff, tidied up search a bit, added borders to grades so they look more pronounced. figma Screen(4)

ghost avatar Jan 11 '24 09:01 ghost

I hope this will be skinnable. I like the current song carousel much more. There's just too much colour here. Sampling colour from background sounds cool on the surface, but in reality you often end up with something weird that does not really represent the picture in a good way. Especially when you block the picture with a gradient. The current look is much cleaner.

Qunas101 avatar Jan 18 '24 20:01 Qunas101

I don't know if it's the right place to give feedback on this, but here's some comment, mostly on the "Select Draft 2" one:

First thing, showing bars for AR/CS/OD/HP is useless and a complete waste of space: In osu! at least, the huge majority of beatmaps above 5* have CS 4~5, OD 8~9, AR 8~10, and HP 5~6, while the bars go from 0 to 10, which makes most bars look very similar on all 5*+ beatmaps. The difference between CS 4 and 5 is huge but it's very hard to see from the bars. Similar issues can be seen at lower star ratings too (values don't vary much between maps of similar difficulty). Having the numbers themselves is very important though, and this is something that is completely missing from the "Draft 5" one, but bars won't bring anything relevant that the numbers don't already give.

Second, something showing the proportion of sliders/slider-ticks/circles/spinners in the map might be nice but multiple bars does not seem to be the best way to show this. Maybe some stacked bars or a pie-chart would work better ?

Lastly, the space left for the leaderboard is really small... Along with removing bars as mentionned above, it would be good to compact things more (buttons for leaderboard options could move to the middle of the top bar ? Some numbers can move to the beatmap card bellow the star rating and song title ? Write AR/CS/OD/HP in abbreviated form and only show the full name on hover ?) and have a way to disable more of the less important info like tags, success rate and user rating/rating spread, or have them be displayed on hover only.

Other than that, the designs look very nice overall. Can't wait for them to be part of the game.

Zyfarok avatar Feb 01 '24 00:02 Zyfarok

@arflyte ^

peppy avatar Feb 01 '24 05:02 peppy

There's a major redesign on the left side to declutter and de-messy-fy to address most of the concerns above, such at the search bar background, information overload and the panels on the left side. While the design is nice, I'm not quite happy with how the information is displayed so far, so this requires quite a lot of rethinking and rework.

(The Let's Go! button is just a placeholder, the cookie remains)

arflyte avatar Mar 07 '24 05:03 arflyte

I'll give an update that I should've done a month ago. This was listed in the future tasks issue so I plan to prioritize this again.

I have the changes for the first iteration wedge details (top left) working and polished visually (unsure about code): https://github.com/ppy/osu/compare/master...Joehuu:osu:song-select-metadata-content

And I was concerned the header was taking too much space and have a diff to remove that (and replace with an arrow within the background wedge):

diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs
index bd3e5f4d4f..dfbcc56aa2 100644
--- a/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs
+++ b/osu.Game/Screens/Select/BeatmapInfoWedgeV2.cs
@@ -2,10 +2,12 @@
 // See the LICENCE file in the repository root for full licence text.
 
 using System;
+using System.Collections.Generic;
 using System.Threading;
 using osuTK;
 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.Effects;
@@ -14,16 +16,21 @@
 using osu.Game.Graphics;
 using osu.Game.Graphics.Sprites;
 using osu.Framework.Graphics.Shapes;
+using osu.Framework.Graphics.Sprites;
+using osu.Framework.Input.Events;
 using osu.Framework.Localisation;
 using osu.Game.Graphics.Containers;
 using osu.Game.Graphics.UserInterface;
+using osu.Game.Overlays;
+using osu.Game.Resources.Localisation.Web;
 using osu.Game.Rulesets;
+using osuTK.Graphics;
 
 namespace osu.Game.Screens.Select
 {
     public partial class BeatmapInfoWedgeV2 : VisibilityContainer
     {
-        public const float WEDGE_HEIGHT = 120;
+        public const float WEDGE_HEIGHT = 100;
         public const float SHEAR_WIDTH = SongSelect.SHEAR_X * WEDGE_HEIGHT;
         private const float transition_duration = 250;
         public const float COLOUR_BAR_WIDTH = 30;
@@ -149,6 +156,15 @@ private void load()
                                     }
                                 }
                             },
+                            new ExpandDetailsButton
+                            {
+                                Anchor = Anchor.BottomRight,
+                                Origin = Anchor.BottomRight,
+                                Expanded = { BindTarget = ShowDetails },
+                                Margin = new MarginPadding { Bottom = 3, Right = COLOUR_BAR_WIDTH + 8 },
+                                Depth = float.MinValue,
+                                Shear = -SongSelect.WEDGED_CONTAINER_SHEAR,
+                            },
                         }
                     },
                     new Container
@@ -379,5 +395,101 @@ protected override void UpdateAfterChildren()
                 ArtistLabel.MaxWidth = DrawWidth - SongSelect.TEXT_MARGIN - SongSelect.SHEAR_X * DrawHeight;
             }
         }
+
+        public partial class ExpandDetailsButton : OsuHoverContainer
+        {
+            private const int fade_duration = 500;
+
+            public readonly BindableBool Expanded = new BindableBool();
+
+            protected override IEnumerable<Drawable> EffectTargets => new[] { background };
+
+            private Color4 flashColour;
+
+            private readonly Container content;
+            private readonly Box background;
+            private readonly SpriteIcon spriteIcon;
+
+            public ExpandDetailsButton()
+                : base(HoverSampleSet.ScrollToTop)
+            {
+                Size = new Vector2(20);
+                Add(content = new CircularContainer
+                {
+                    RelativeSizeAxes = Axes.Both,
+                    Anchor = Anchor.Centre,
+                    Origin = Anchor.Centre,
+                    Masking = true,
+                    EdgeEffect = new EdgeEffectParameters
+                    {
+                        Type = EdgeEffectType.Shadow,
+                        Offset = new Vector2(0f, 1f),
+                        Radius = 3f,
+                        Colour = Color4.Black.Opacity(0.25f),
+                    },
+                    Children = new Drawable[]
+                    {
+                        background = new Box
+                        {
+                            RelativeSizeAxes = Axes.Both
+                        },
+                        spriteIcon = new SpriteIcon
+                        {
+                            Anchor = Anchor.Centre,
+                            Origin = Anchor.Centre,
+                            Size = new Vector2(10),
+                            Icon = FontAwesome.Solid.ChevronUp
+                        }
+                    }
+                });
+
+                TooltipText = CommonStrings.ButtonsBackToTop;
+            }
+
+            [BackgroundDependencyLoader]
+            private void load(OverlayColourProvider colourProvider)
+            {
+                IdleColour = colourProvider.Background3;
+                HoverColour = colourProvider.Background2;
+                flashColour = colourProvider.Light1;
+
+                Action = Expanded.Toggle;
+            }
+
+            protected override void LoadComplete()
+            {
+                base.LoadComplete();
+
+                Expanded.BindValueChanged(e =>
+                {
+                    spriteIcon.RotateTo(e.NewValue ? 0 : 180, fade_duration, Easing.OutQuint);
+                    TooltipText = e.NewValue ? "Hide details" : "Show details";
+                }, true);
+            }
+
+            protected override bool OnClick(ClickEvent e)
+            {
+                background.FlashColour(flashColour, 800, Easing.OutQuint);
+                return base.OnClick(e);
+            }
+
+            protected override bool OnMouseDown(MouseDownEvent e)
+            {
+                content.ScaleTo(0.75f, 2000, Easing.OutQuint);
+                return true;
+            }
+
+            protected override void OnMouseUp(MouseUpEvent e)
+            {
+                content.ScaleTo(1, 1000, Easing.OutElastic);
+                base.OnMouseUp(e);
+            }
+
+            protected override bool OnHover(HoverEvent e)
+            {
+                base.OnHover(e);
+                return true;
+            }
+        }
     }
 }
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index cd441b0394..c827328d25 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -111,8 +111,6 @@ public abstract partial class SongSelect : ScreenWithBeatmapBackground, IKeyBind
 
         protected GridContainer LeftArea { get; private set; } = null!;
 
-        private BeatmapInfoWedgeV2 beatmapInfoWedge = null!;
-
         [Resolved]
         private IDialogOverlay? dialogOverlay { get; set; }
 
@@ -258,46 +256,17 @@ private void load(AudioManager audio, OsuColour colours, ManageCollectionsDialog
                                         RowDimensions = new[]
                                         {
                                             new Dimension(GridSizeMode.AutoSize),
-                                            new Dimension(GridSizeMode.AutoSize),
                                         },
                                         Content = new[]
                                         {
-                                            new Drawable[]
-                                            {
-                                                new Container
-                                                {
-                                                    RelativeSizeAxes = Axes.X,
-                                                    Height = 90,
-                                                    Padding = new MarginPadding { Left = TEXT_MARGIN - WEDGE_CORNER_RADIUS, Right = BeatmapInfoWedgeV2.COLOUR_BAR_WIDTH },
-                                                    Children = new Drawable[]
-                                                    {
-                                                        new SongSelectHeaderTitle
-                                                        {
-                                                            Anchor = Anchor.CentreLeft,
-                                                            Origin = Anchor.CentreLeft,
-                                                            Alpha = ShowHeader ? 1 : 0,
-                                                        },
-                                                        toggleDetailsButton = new ShearedToggleButton(120)
-                                                        {
-                                                            Anchor = Anchor.CentreRight,
-                                                            Origin = Anchor.CentreRight,
-                                                            Text = "Details",
-                                                            Height = 25,
-                                                            Active = { Value = true },
-                                                            Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 14),
-                                                            Padding = new MarginPadding(),
-                                                            HasGradientBorder = false,
-                                                        },
-                                                    }
-                                                }
-                                            },
                                             new Drawable[]
                                             {
                                                 new Container
                                                 {
                                                     RelativeSizeAxes = Axes.X,
                                                     AutoSizeAxes = Axes.Y,
-                                                    Child = beatmapInfoWedge = new BeatmapInfoWedgeV2
+                                                    Padding = new MarginPadding { Top = 10 },
+                                                    Child = new BeatmapInfoWedgeV2
                                                     {
                                                         RelativeSizeAxes = Axes.X,
                                                     },
@@ -382,8 +351,6 @@ protected override void LoadComplete()
 
             modSelectOverlayRegistration = OverlayManager?.RegisterBlockingOverlay(ModSelect);
 
-            toggleDetailsButton.Active.BindTo(beatmapInfoWedge.ShowDetails);
-
             apiState.BindTo(api.State);
             apiState.BindValueChanged(_ => fetchOnlineBeatmap(), true);
         }
@@ -972,7 +939,6 @@ private void updateVisibleBeatmapCount()
         }
 
         private bool boundLocalBindables;
-        private ShearedToggleButton toggleDetailsButton = null!;
         public virtual bool ShowHeader => true;
 
         private void bindBindables()

The details collapsed is underwhelming and should have a condensed display showing the really important stats.

As with the code changes, I'm just a little overwhelmed with them and would preferably do one (future) skinnable component per PR. Something like this: Screenshot 2024-03-21 at 7 50 55 PM

Joehuu avatar Mar 22 '24 02:03 Joehuu

skin support for the menu?

home-gihub avatar Jun 08 '24 10:06 home-gihub

skin support for the menu? @peppy please?

necocat0918 avatar Jun 08 '24 11:06 necocat0918