Skip to content

Commit 2d46da1

Browse files
authored
Merge pull request #31634 from peppy/beatmap-carousel-v2-selection
Add selection support to beatmap carousel v2
2 parents 2f84aec + 9366bfb commit 2d46da1

12 files changed

+1018
-477
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2+
// See the LICENCE file in the repository root for full licence text.
3+
4+
using System.Linq;
5+
using NUnit.Framework;
6+
using osu.Framework.Allocation;
7+
using osu.Framework.Bindables;
8+
using osu.Framework.Extensions.ObjectExtensions;
9+
using osu.Framework.Graphics;
10+
using osu.Framework.Graphics.Containers;
11+
using osu.Framework.Graphics.Shapes;
12+
using osu.Framework.Testing;
13+
using osu.Framework.Utils;
14+
using osu.Game.Beatmaps;
15+
using osu.Game.Database;
16+
using osu.Game.Graphics;
17+
using osu.Game.Graphics.Containers;
18+
using osu.Game.Screens.Select;
19+
using osu.Game.Screens.Select.Filter;
20+
using osu.Game.Screens.SelectV2;
21+
using osu.Game.Tests.Beatmaps;
22+
using osu.Game.Tests.Resources;
23+
using osuTK.Graphics;
24+
using BeatmapCarousel = osu.Game.Screens.SelectV2.BeatmapCarousel;
25+
26+
namespace osu.Game.Tests.Visual.SongSelect
27+
{
28+
public abstract partial class BeatmapCarouselV2TestScene : OsuManualInputManagerTestScene
29+
{
30+
protected readonly BindableList<BeatmapSetInfo> BeatmapSets = new BindableList<BeatmapSetInfo>();
31+
32+
protected BeatmapCarousel Carousel = null!;
33+
34+
protected OsuScrollContainer<Drawable> Scroll => Carousel.ChildrenOfType<OsuScrollContainer<Drawable>>().Single();
35+
36+
[Cached(typeof(BeatmapStore))]
37+
private BeatmapStore store;
38+
39+
private OsuTextFlowContainer stats = null!;
40+
41+
private int beatmapCount;
42+
43+
protected BeatmapCarouselV2TestScene()
44+
{
45+
store = new TestBeatmapStore
46+
{
47+
BeatmapSets = { BindTarget = BeatmapSets }
48+
};
49+
50+
BeatmapSets.BindCollectionChanged((_, _) => beatmapCount = BeatmapSets.Sum(s => s.Beatmaps.Count));
51+
52+
Scheduler.AddDelayed(updateStats, 100, true);
53+
}
54+
55+
[SetUpSteps]
56+
public void SetUpSteps()
57+
{
58+
RemoveAllBeatmaps();
59+
60+
CreateCarousel();
61+
62+
SortBy(new FilterCriteria { Sort = SortMode.Title });
63+
}
64+
65+
protected void CreateCarousel()
66+
{
67+
AddStep("create components", () =>
68+
{
69+
Box topBox;
70+
Children = new Drawable[]
71+
{
72+
new GridContainer
73+
{
74+
RelativeSizeAxes = Axes.Both,
75+
ColumnDimensions = new[]
76+
{
77+
new Dimension(GridSizeMode.Relative, 1),
78+
},
79+
RowDimensions = new[]
80+
{
81+
new Dimension(GridSizeMode.Absolute, 200),
82+
new Dimension(),
83+
new Dimension(GridSizeMode.Absolute, 200),
84+
},
85+
Content = new[]
86+
{
87+
new Drawable[]
88+
{
89+
topBox = new Box
90+
{
91+
Anchor = Anchor.Centre,
92+
Origin = Anchor.Centre,
93+
Colour = Color4.Cyan,
94+
RelativeSizeAxes = Axes.Both,
95+
Alpha = 0.4f,
96+
},
97+
},
98+
new Drawable[]
99+
{
100+
Carousel = new BeatmapCarousel
101+
{
102+
Anchor = Anchor.Centre,
103+
Origin = Anchor.Centre,
104+
Width = 500,
105+
RelativeSizeAxes = Axes.Y,
106+
},
107+
},
108+
new[]
109+
{
110+
new Box
111+
{
112+
Anchor = Anchor.Centre,
113+
Origin = Anchor.Centre,
114+
Colour = Color4.Cyan,
115+
RelativeSizeAxes = Axes.Both,
116+
Alpha = 0.4f,
117+
},
118+
topBox.CreateProxy(),
119+
}
120+
}
121+
},
122+
stats = new OsuTextFlowContainer
123+
{
124+
AutoSizeAxes = Axes.Both,
125+
Padding = new MarginPadding(10),
126+
TextAnchor = Anchor.CentreLeft,
127+
},
128+
};
129+
});
130+
}
131+
132+
protected void SortBy(FilterCriteria criteria) => AddStep($"sort by {criteria.Sort}", () => Carousel.Filter(criteria));
133+
134+
protected void WaitForDrawablePanels() => AddUntilStep("drawable panels loaded", () => Carousel.ChildrenOfType<BeatmapCarouselPanel>().Count(), () => Is.GreaterThan(0));
135+
protected void WaitForSorting() => AddUntilStep("sorting finished", () => Carousel.IsFiltering, () => Is.False);
136+
protected void WaitForScrolling() => AddUntilStep("scroll finished", () => Scroll.Current, () => Is.EqualTo(Scroll.Target));
137+
138+
/// <summary>
139+
/// Add requested beatmap sets count to list.
140+
/// </summary>
141+
/// <param name="count">The count of beatmap sets to add.</param>
142+
/// <param name="fixedDifficultiesPerSet">If not null, the number of difficulties per set. If null, randomised difficulty count will be used.</param>
143+
protected void AddBeatmaps(int count, int? fixedDifficultiesPerSet = null) => AddStep($"add {count} beatmaps", () =>
144+
{
145+
for (int i = 0; i < count; i++)
146+
BeatmapSets.Add(TestResources.CreateTestBeatmapSetInfo(fixedDifficultiesPerSet ?? RNG.Next(1, 4)));
147+
});
148+
149+
protected void RemoveAllBeatmaps() => AddStep("clear all beatmaps", () => BeatmapSets.Clear());
150+
151+
protected void RemoveFirstBeatmap() =>
152+
AddStep("remove first beatmap", () =>
153+
{
154+
if (BeatmapSets.Count == 0) return;
155+
156+
BeatmapSets.Remove(BeatmapSets.First());
157+
});
158+
159+
private void updateStats()
160+
{
161+
if (Carousel.IsNull())
162+
return;
163+
164+
stats.Clear();
165+
createHeader("beatmap store");
166+
stats.AddParagraph($"""
167+
sets: {BeatmapSets.Count}
168+
beatmaps: {beatmapCount}
169+
""");
170+
createHeader("carousel");
171+
stats.AddParagraph($"""
172+
sorting: {Carousel.IsFiltering}
173+
tracked: {Carousel.ItemsTracked}
174+
displayable: {Carousel.DisplayableItems}
175+
displayed: {Carousel.VisibleItems}
176+
selected: {Carousel.CurrentSelection}
177+
""");
178+
179+
void createHeader(string text)
180+
{
181+
stats.AddParagraph(string.Empty);
182+
stats.AddParagraph(text, cp =>
183+
{
184+
cp.Font = cp.Font.With(size: 18, weight: FontWeight.Bold);
185+
});
186+
}
187+
}
188+
}
189+
}

0 commit comments

Comments
 (0)