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 NUnit.Framework;
5using osu.Framework.Graphics;
6using osu.Framework.Graphics.Containers;
7using osu.Framework.Graphics.Shapes;
8using osu.Framework.Input.Events;
9using osu.Framework.Utils;
10using osu.Framework.Timing;
11using osuTK;
12using osuTK.Graphics;
13
14namespace osu.Framework.Tests.Visual.Layout
15{
16 public class TestSceneLayoutDurations : FrameworkTestScene
17 {
18 private ManualClock manualClock;
19 private Container autoSizeContainer;
20 private FillFlowContainer fillFlowContainer;
21
22 private Box box1, box2;
23
24 private const float duration = 1000;
25
26 private const float changed_value = 100;
27
28 [SetUp]
29 public void SetUp() => Schedule(() =>
30 {
31 manualClock = new ManualClock();
32
33 Children = new Drawable[]
34 {
35 autoSizeContainer = new Container
36 {
37 Clock = new FramedClock(manualClock),
38 AutoSizeEasing = Easing.None,
39 Children = new[]
40 {
41 new Box
42 {
43 Colour = Color4.Red,
44 RelativeSizeAxes = Axes.Both
45 },
46 box1 = new Box
47 {
48 Colour = Color4.Transparent,
49 Size = Vector2.Zero,
50 },
51 }
52 },
53 fillFlowContainer = new FillFlowContainer
54 {
55 Clock = new FramedClock(manualClock),
56 Position = new Vector2(0, 200),
57 LayoutEasing = Easing.None,
58 Children = new Drawable[]
59 {
60 new Box { Colour = Color4.Red, Size = new Vector2(100) },
61 box2 = new Box { Colour = Color4.Blue, Size = new Vector2(100) },
62 }
63 }
64 };
65
66 paused = false;
67 autoSizeContainer.FinishTransforms();
68 fillFlowContainer.FinishTransforms();
69
70 autoSizeContainer.AutoSizeAxes = Axes.None;
71 autoSizeContainer.AutoSizeDuration = 0;
72 autoSizeContainer.Size = Vector2.Zero;
73 box1.Size = Vector2.Zero;
74
75 fillFlowContainer.LayoutDuration = 0;
76 fillFlowContainer.Size = new Vector2(200, 200);
77 });
78
79 private void check(float ratio) =>
80 AddAssert($"Check @{ratio}", () => Precision.AlmostEquals(autoSizeContainer.Size, new Vector2(changed_value * ratio)) &&
81 Precision.AlmostEquals(box2.Position, new Vector2(changed_value * (1 - ratio), changed_value * ratio)));
82
83 private void skipTo(float ratio) => AddStep($"skip to {ratio}", () => { manualClock.CurrentTime = duration * ratio; });
84
85 [Test]
86 public void TestChangeAfterDuration()
87 {
88 AddStep("Start transformation", () =>
89 {
90 paused = true;
91 manualClock.CurrentTime = 0;
92 autoSizeContainer.FinishTransforms();
93 fillFlowContainer.FinishTransforms();
94
95 autoSizeContainer.AutoSizeAxes = Axes.Both;
96 autoSizeContainer.AutoSizeDuration = duration;
97 box1.Size = new Vector2(100);
98
99 fillFlowContainer.LayoutDuration = duration;
100 fillFlowContainer.Width = 100;
101 });
102
103 foreach (var ratio in new[] { .25f, .5f, .75f, 1 })
104 {
105 skipTo(ratio);
106 check(ratio);
107 }
108 }
109
110 [Test]
111 public void TestInterruptExistingDuration()
112 {
113 AddStep("Start transformation", () =>
114 {
115 paused = true;
116 manualClock.CurrentTime = 0;
117 autoSizeContainer.FinishTransforms();
118 fillFlowContainer.FinishTransforms();
119
120 autoSizeContainer.AutoSizeAxes = Axes.Both;
121 autoSizeContainer.AutoSizeDuration = duration;
122 fillFlowContainer.LayoutDuration = duration;
123
124 box1.Size = new Vector2(changed_value);
125 fillFlowContainer.Width = changed_value;
126 });
127
128 skipTo(0.5f);
129 check(0.5f);
130
131 AddStep("set duration 0", () =>
132 {
133 autoSizeContainer.AutoSizeDuration = 0;
134 fillFlowContainer.LayoutDuration = 0;
135 });
136
137 // transform should still be playing
138 skipTo(0.75f);
139 check(0.75f);
140
141 // check rewind works just for fun
142 skipTo(0.5f);
143 check(0.5f);
144
145 AddStep("alter values", () =>
146 {
147 box1.Size = new Vector2(0);
148 fillFlowContainer.Width = 200;
149 });
150
151 // fully complete
152 check(0);
153
154 // no remaining transform
155 skipTo(1);
156 check(0);
157 }
158
159 private bool paused;
160
161 protected override void Update()
162 {
163 if (autoSizeContainer != null)
164 {
165 if (!paused) manualClock.CurrentTime = Clock.CurrentTime;
166
167 autoSizeContainer.Children[0].Invalidate();
168 fillFlowContainer.Invalidate();
169 }
170
171 base.Update();
172 }
173
174 protected override bool OnClick(ClickEvent e)
175 {
176 paused = !paused;
177 return base.OnClick(e);
178 }
179 }
180}