diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 0299b7a084..cd97ffe9e7 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -507,7 +507,7 @@ namespace osu.Game.Tests.Visual.SongSelect var selectedPanel = songSelect.Carousel.ChildrenOfType().First(s => s.Item.State.Value == CarouselItemState.Selected); // special case for converts checked here. - return selectedPanel.ChildrenOfType().All(i => + return selectedPanel.ChildrenOfType().All(i => i.IsFiltered || i.Item.Beatmap.Ruleset.ID == targetRuleset || i.Item.Beatmap.Ruleset.ID == 0); }); @@ -606,10 +606,10 @@ namespace osu.Game.Tests.Visual.SongSelect set = songSelect.Carousel.ChildrenOfType().First(); }); - DrawableCarouselBeatmapSet.FilterableDifficultyIcon difficultyIcon = null; + FilterableDifficultyIcon difficultyIcon = null; AddStep("Find an icon", () => { - difficultyIcon = set.ChildrenOfType() + difficultyIcon = set.ChildrenOfType() .First(icon => getDifficultyIconIndex(set, icon) != getCurrentBeatmapIndex()); }); @@ -634,13 +634,13 @@ namespace osu.Game.Tests.Visual.SongSelect })); BeatmapInfo filteredBeatmap = null; - DrawableCarouselBeatmapSet.FilterableDifficultyIcon filteredIcon = null; + FilterableDifficultyIcon filteredIcon = null; AddStep("Get filtered icon", () => { filteredBeatmap = songSelect.Carousel.SelectedBeatmapSet.Beatmaps.First(b => b.BPM < maxBPM); int filteredBeatmapIndex = getBeatmapIndex(filteredBeatmap.BeatmapSet, filteredBeatmap); - filteredIcon = set.ChildrenOfType().ElementAt(filteredBeatmapIndex); + filteredIcon = set.ChildrenOfType().ElementAt(filteredBeatmapIndex); }); AddStep("Click on a filtered difficulty", () => @@ -674,10 +674,10 @@ namespace osu.Game.Tests.Visual.SongSelect return set != null; }); - DrawableCarouselBeatmapSet.FilterableDifficultyIcon difficultyIcon = null; + FilterableDifficultyIcon difficultyIcon = null; AddStep("Find an icon for different ruleset", () => { - difficultyIcon = set.ChildrenOfType() + difficultyIcon = set.ChildrenOfType() .First(icon => icon.Item.Beatmap.Ruleset.ID == 3); }); @@ -725,10 +725,10 @@ namespace osu.Game.Tests.Visual.SongSelect return set != null; }); - DrawableCarouselBeatmapSet.FilterableGroupedDifficultyIcon groupIcon = null; + FilterableGroupedDifficultyIcon groupIcon = null; AddStep("Find group icon for different ruleset", () => { - groupIcon = set.ChildrenOfType() + groupIcon = set.ChildrenOfType() .First(icon => icon.Items.First().Beatmap.Ruleset.ID == 3); }); @@ -821,9 +821,9 @@ namespace osu.Game.Tests.Visual.SongSelect private int getCurrentBeatmapIndex() => getBeatmapIndex(songSelect.Carousel.SelectedBeatmapSet, songSelect.Carousel.SelectedBeatmap); - private int getDifficultyIconIndex(DrawableCarouselBeatmapSet set, DrawableCarouselBeatmapSet.FilterableDifficultyIcon icon) + private int getDifficultyIconIndex(DrawableCarouselBeatmapSet set, FilterableDifficultyIcon icon) { - return set.ChildrenOfType().ToList().FindIndex(i => i == icon); + return set.ChildrenOfType().ToList().FindIndex(i => i == icon); } private void addRulesetImportStep(int id) => AddStep($"import test map for ruleset {id}", () => importForRuleset(id)); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 660d5d5b31..8ab7a054ff 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -5,15 +5,11 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Primitives; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; @@ -22,9 +18,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; -using osu.Game.Rulesets; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Select.Carousel { @@ -285,116 +279,5 @@ namespace osu.Game.Screens.Select.Carousel State = { Value = state } }; } - - private class PanelBackground : BufferedContainer - { - public PanelBackground(WorkingBeatmap working) - { - CacheDrawnFrameBuffer = true; - RedrawOnScale = false; - - Children = new Drawable[] - { - new BeatmapBackgroundSprite(working) - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill, - }, - new FillFlowContainer - { - Depth = -1, - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - // This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle - Shear = new Vector2(0.8f, 0), - Alpha = 0.5f, - Children = new[] - { - // The left half with no gradient applied - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Width = 0.4f, - }, - // Piecewise-linear gradient with 3 segments to make it appear smoother - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.Black, new Color4(0f, 0f, 0f, 0.9f)), - Width = 0.05f, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.9f), new Color4(0f, 0f, 0f, 0.1f)), - Width = 0.2f, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.1f), new Color4(0, 0, 0, 0)), - Width = 0.05f, - }, - } - }, - }; - } - } - - public class FilterableDifficultyIcon : DifficultyIcon - { - private readonly BindableBool filtered = new BindableBool(); - - public bool IsFiltered => filtered.Value; - - public readonly CarouselBeatmap Item; - - public FilterableDifficultyIcon(CarouselBeatmap item) - : base(item.Beatmap) - { - filtered.BindTo(item.Filtered); - filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); - filtered.TriggerChange(); - - Item = item; - } - - protected override bool OnClick(ClickEvent e) - { - Item.State.Value = CarouselItemState.Selected; - return true; - } - } - - public class FilterableGroupedDifficultyIcon : GroupedDifficultyIcon - { - public readonly List Items; - - public FilterableGroupedDifficultyIcon(List items, RulesetInfo ruleset) - : base(items.Select(i => i.Beatmap).ToList(), ruleset, Color4.White) - { - Items = items; - - foreach (var item in items) - item.Filtered.BindValueChanged(_ => Scheduler.AddOnce(updateFilteredDisplay)); - - updateFilteredDisplay(); - } - - protected override bool OnClick(ClickEvent e) - { - Items.First().State.Value = CarouselItemState.Selected; - return true; - } - - private void updateFilteredDisplay() - { - // for now, fade the whole group based on the ratio of hidden items. - this.FadeTo(1 - 0.9f * ((float)Items.Count(i => i.Filtered.Value) / Items.Count), 100); - } - } } } diff --git a/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs b/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs new file mode 100644 index 0000000000..591e9fea22 --- /dev/null +++ b/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs @@ -0,0 +1,32 @@ +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps.Drawables; + +namespace osu.Game.Screens.Select.Carousel +{ + public class FilterableDifficultyIcon : DifficultyIcon + { + private readonly BindableBool filtered = new BindableBool(); + + public bool IsFiltered => filtered.Value; + + public readonly CarouselBeatmap Item; + + public FilterableDifficultyIcon(CarouselBeatmap item) + : base(item.Beatmap) + { + filtered.BindTo(item.Filtered); + filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); + filtered.TriggerChange(); + + Item = item; + } + + protected override bool OnClick(ClickEvent e) + { + Item.State.Value = CarouselItemState.Selected; + return true; + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Select/Carousel/FilterableGroupedDifficultyIcon.cs b/osu.Game/Screens/Select/Carousel/FilterableGroupedDifficultyIcon.cs new file mode 100644 index 0000000000..73b5781a37 --- /dev/null +++ b/osu.Game/Screens/Select/Carousel/FilterableGroupedDifficultyIcon.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Rulesets; +using osuTK.Graphics; + +namespace osu.Game.Screens.Select.Carousel +{ + public class FilterableGroupedDifficultyIcon : GroupedDifficultyIcon + { + public readonly List Items; + + public FilterableGroupedDifficultyIcon(List items, RulesetInfo ruleset) + : base(items.Select(i => i.Beatmap).ToList(), ruleset, Color4.White) + { + Items = items; + + foreach (var item in items) + item.Filtered.BindValueChanged(_ => Scheduler.AddOnce(updateFilteredDisplay)); + + updateFilteredDisplay(); + } + + protected override bool OnClick(ClickEvent e) + { + Items.First().State.Value = CarouselItemState.Selected; + return true; + } + + private void updateFilteredDisplay() + { + // for now, fade the whole group based on the ratio of hidden items. + this.FadeTo(1 - 0.9f * ((float)Items.Count(i => i.Filtered.Value) / Items.Count), 100); + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Select/Carousel/PanelBackground.cs b/osu.Game/Screens/Select/Carousel/PanelBackground.cs new file mode 100644 index 0000000000..587aa0a74e --- /dev/null +++ b/osu.Game/Screens/Select/Carousel/PanelBackground.cs @@ -0,0 +1,69 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Select.Carousel +{ + public class PanelBackground : BufferedContainer + { + public PanelBackground(WorkingBeatmap working) + { + CacheDrawnFrameBuffer = true; + RedrawOnScale = false; + + Children = new Drawable[] + { + new BeatmapBackgroundSprite(working) + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill, + }, + new FillFlowContainer + { + Depth = -1, + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + // This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle + Shear = new Vector2(0.8f, 0), + Alpha = 0.5f, + Children = new[] + { + // The left half with no gradient applied + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Width = 0.4f, + }, + // Piecewise-linear gradient with 3 segments to make it appear smoother + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4.Black, new Color4(0f, 0f, 0f, 0.9f)), + Width = 0.05f, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.9f), new Color4(0f, 0f, 0f, 0.1f)), + Width = 0.2f, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.1f), new Color4(0, 0, 0, 0)), + Width = 0.05f, + }, + } + }, + }; + } + } +}