A game framework written with osu! in mind.
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
4using System;
5using System.Collections.Generic;
6using System.Linq;
7using NUnit.Framework;
8using osu.Framework.Allocation;
9using osu.Framework.Graphics;
10using osu.Framework.Graphics.Containers;
11using osu.Framework.Graphics.Sprites;
12using osu.Framework.Testing;
13using osuTK;
14using osuTK.Graphics;
15
16namespace osu.Framework.Tests.Visual.Drawables
17{
18 public class TestSceneDelayedLoadWrapper : FrameworkTestScene
19 {
20 private FillFlowContainer<Container> flow;
21 private TestSceneDelayedLoadUnloadWrapper.TestScrollContainer scroll;
22 private int loaded;
23
24 private const int panel_count = 2048;
25
26 [SetUpSteps]
27 public void SetUpSteps()
28 {
29 AddStep("create scroll container", () =>
30 {
31 loaded = 0;
32
33 Children = new Drawable[]
34 {
35 scroll = new TestSceneDelayedLoadUnloadWrapper.TestScrollContainer
36 {
37 RelativeSizeAxes = Axes.Both,
38 Children = new Drawable[]
39 {
40 flow = new FillFlowContainer<Container>
41 {
42 RelativeSizeAxes = Axes.X,
43 AutoSizeAxes = Axes.Y,
44 }
45 }
46 }
47 };
48 });
49 }
50
51 [TestCase(false)]
52 [TestCase(true)]
53 public void TestManyChildren(bool instant)
54 {
55 AddStep("create children", () =>
56 {
57 for (int i = 1; i < panel_count; i++)
58 {
59 flow.Add(new Container
60 {
61 Size = new Vector2(128),
62 Children = new Drawable[]
63 {
64 new DelayedLoadWrapper(new Container
65 {
66 RelativeSizeAxes = Axes.Both,
67 Children = new Drawable[]
68 {
69 new TestBox(() => loaded++) { RelativeSizeAxes = Axes.Both }
70 }
71 }, instant ? 0 : 500),
72 new SpriteText { Text = i.ToString() },
73 }
74 });
75 }
76 });
77
78 var childrenWithAvatarsLoaded = new Func<IEnumerable<Drawable>>(() => flow.Children.Where(c => c.Children.OfType<DelayedLoadWrapper>().First().Content?.IsLoaded ?? false));
79
80 int loadCount1 = 0;
81
82 AddUntilStep("wait for load", () => loaded > 0);
83
84 AddStep("scroll down", () =>
85 {
86 loadCount1 = loaded;
87 scroll.ScrollToEnd();
88 });
89
90 AddWaitStep("wait some more", 10);
91
92 AddUntilStep("more loaded", () => loaded > loadCount1);
93 AddAssert("not too many loaded", () => childrenWithAvatarsLoaded().Count() < panel_count / 4);
94
95 AddStep("Remove all panels", () => flow.Clear(false));
96
97 AddUntilStep("repeating schedulers removed", () => !scroll.Scheduler.HasPendingTasks);
98 }
99
100 [TestCase(false)]
101 [TestCase(true)]
102 public void TestManyChildrenFunction(bool instant)
103 {
104 AddStep("create children", () =>
105 {
106 for (int i = 1; i < panel_count; i++)
107 {
108 flow.Add(new Container
109 {
110 Size = new Vector2(128),
111 Children = new Drawable[]
112 {
113 new DelayedLoadWrapper(() => new Container
114 {
115 RelativeSizeAxes = Axes.Both,
116 Children = new Drawable[]
117 {
118 new TestBox(() => loaded++) { RelativeSizeAxes = Axes.Both }
119 }
120 }, instant ? 0 : 500),
121 new SpriteText { Text = i.ToString() },
122 }
123 });
124 }
125 });
126
127 var childrenWithAvatarsLoaded = new Func<IEnumerable<Drawable>>(() => flow.Children.Where(c => c.Children.OfType<DelayedLoadWrapper>().First().Content?.IsLoaded ?? false));
128
129 int loadCount1 = 0;
130
131 AddUntilStep("wait for load", () => loaded > 0);
132
133 AddStep("scroll down", () =>
134 {
135 loadCount1 = loaded;
136 scroll.ScrollToEnd();
137 });
138
139 AddWaitStep("wait some more", 10);
140
141 AddUntilStep("more loaded", () => loaded > loadCount1);
142 AddAssert("not too many loaded", () => childrenWithAvatarsLoaded().Count() < panel_count / 4);
143
144 AddStep("Remove all panels", () => flow.Clear(false));
145
146 AddUntilStep("repeating schedulers removed", () => !scroll.Scheduler.HasPendingTasks);
147 }
148
149 public class TestBox : Container
150 {
151 private readonly Action onLoadAction;
152
153 public TestBox(Action onLoadAction)
154 {
155 this.onLoadAction = onLoadAction;
156 RelativeSizeAxes = Axes.Both;
157 }
158
159 [BackgroundDependencyLoader]
160 private void load()
161 {
162 onLoadAction?.Invoke();
163
164 Child = new SpriteText
165 {
166 Colour = Color4.Yellow,
167 Text = @"loaded",
168 Anchor = Anchor.Centre,
169 Origin = Anchor.Centre,
170 };
171 }
172 }
173 }
174}