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.Linq;
5using osu.Framework.Bindables;
6using osu.Framework.Graphics;
7using osu.Framework.Graphics.Containers;
8using osu.Framework.Graphics.Shapes;
9using osu.Framework.Graphics.Sprites;
10using osu.Framework.Graphics.UserInterface;
11using osuTK;
12using osuTK.Graphics;
13
14namespace osu.Framework.Tests.Visual.Containers
15{
16 public class TestSceneSafeAreaContainer : FrameworkTestScene
17 {
18 private readonly BindableSafeArea safeAreaPadding = new BindableSafeArea();
19
20 private readonly Box safeAreaTopOverlay;
21 private readonly Box safeAreaBottomOverlay;
22 private readonly Box safeAreaLeftOverlay;
23 private readonly Box safeAreaRightOverlay;
24
25 public TestSceneSafeAreaContainer()
26 {
27 var safeAreaGrid = new SafeAreaContainer
28 {
29 Name = "Padding Container",
30 SafeAreaOverrideEdges = Edges.None,
31 RelativeSizeAxes = Axes.Both,
32 Child = createGridContainer(10, 10),
33 };
34
35 var safeAreaBackground = new SafeAreaContainer
36 {
37 Name = "Overriding Container",
38 RelativeSizeAxes = Axes.Both,
39 SafeAreaOverrideEdges = Edges.None,
40 Child = new Box
41 {
42 Name = "Overriding Background",
43 Colour = Color4.Blue,
44 RelativeSizeAxes = Axes.Both
45 },
46 };
47
48 Child = new FillFlowContainer
49 {
50 Padding = new MarginPadding(10),
51 Spacing = new Vector2(10),
52 RelativeSizeAxes = Axes.Both,
53 Children = new Drawable[]
54 {
55 new MarginPaddingControlsContainer(safeAreaBackground, safeAreaGrid, safeAreaPadding)
56 {
57 RelativeSizeAxes = Axes.X,
58 AutoSizeAxes = Axes.Y,
59 },
60 new SafeAreaDefiningContainer(safeAreaPadding)
61 {
62 Name = "Safe Area Target",
63 Size = new Vector2(500, 400),
64 Children = new Drawable[]
65 {
66 new Box
67 {
68 Name = "Safe Area Target Background",
69 Colour = Color4.Red,
70 RelativeSizeAxes = Axes.Both,
71 },
72 new Container
73 {
74 Position = new Vector2(50, 50),
75 Size = new Vector2(400, 300),
76 Children = new Drawable[]
77 {
78 safeAreaBackground,
79 safeAreaGrid,
80 }
81 },
82 safeAreaLeftOverlay = new Box
83 {
84 Anchor = Anchor.CentreLeft,
85 Origin = Anchor.CentreLeft,
86 Width = 0,
87 RelativeSizeAxes = Axes.Y,
88 Colour = Color4.Green,
89 Alpha = 0.2f
90 },
91 safeAreaRightOverlay = new Box
92 {
93 Anchor = Anchor.CentreRight,
94 Origin = Anchor.CentreRight,
95 Width = 0,
96 RelativeSizeAxes = Axes.Y,
97 Colour = Color4.Green,
98 Alpha = 0.2f
99 },
100 safeAreaTopOverlay = new Box
101 {
102 Anchor = Anchor.TopCentre,
103 Origin = Anchor.TopCentre,
104 Height = 0,
105 RelativeSizeAxes = Axes.X,
106 Colour = Color4.Green,
107 Alpha = 0.2f
108 },
109 safeAreaBottomOverlay = new Box
110 {
111 Anchor = Anchor.BottomCentre,
112 Origin = Anchor.BottomCentre,
113 Height = 0,
114 RelativeSizeAxes = Axes.X,
115 Colour = Color4.Green,
116 Alpha = 0.2f
117 }
118 }
119 }
120 }
121 };
122
123 safeAreaPadding.ValueChanged += e => safeAreaPaddingChanged(e.NewValue);
124 }
125
126 private GridContainer createGridContainer(int rows, int columns)
127 {
128 Drawable[][] boxes = Enumerable.Range(1, rows).Select(row => Enumerable.Range(1, columns).Select(column => new Box
129 {
130 Colour = new Color4(1f, 0.2f + (row * 0.8f) / rows, 0.2f + (column * 0.8f) / columns, 1f),
131 RelativeSizeAxes = Axes.Both,
132 Size = new Vector2(0.7f),
133 Anchor = Anchor.Centre,
134 Origin = Anchor.Centre,
135 } as Drawable).ToArray()).ToArray();
136
137 return new GridContainer
138 {
139 Name = "Safe Contents",
140 RelativeSizeAxes = Axes.Both,
141 Content = boxes,
142 };
143 }
144
145 private void safeAreaPaddingChanged(MarginPadding padding)
146 {
147 safeAreaLeftOverlay.Width = padding.Left;
148 safeAreaRightOverlay.Width = padding.Right;
149 safeAreaTopOverlay.Height = padding.Top;
150 safeAreaBottomOverlay.Height = padding.Bottom;
151 }
152
153 private class MarginPaddingControlsContainer : FillFlowContainer
154 {
155 private readonly Bindable<float> safeAreaPaddingTop;
156 private readonly Bindable<float> safeAreaPaddingBottom;
157 private readonly Bindable<float> safeAreaPaddingLeft;
158 private readonly Bindable<float> safeAreaPaddingRight;
159
160 private readonly BindableSafeArea bindableSafeArea;
161
162 public MarginPaddingControlsContainer(SafeAreaContainer safeAreaBackground, SafeAreaContainer safeAreaGrid, BindableSafeArea bindableSafeArea)
163 {
164 this.bindableSafeArea = bindableSafeArea;
165
166 safeAreaPaddingTop = new BindableFloat { MinValue = 0, MaxValue = 200 };
167 safeAreaPaddingBottom = new BindableFloat { MinValue = 0, MaxValue = 200 };
168 safeAreaPaddingLeft = new BindableFloat { MinValue = 0, MaxValue = 200 };
169 safeAreaPaddingRight = new BindableFloat { MinValue = 0, MaxValue = 200 };
170
171 Direction = FillDirection.Vertical;
172 Spacing = new Vector2(10);
173 Children = new Drawable[]
174 {
175 new MarginPaddingControl(safeAreaBackground, safeAreaGrid, "Top", safeAreaPaddingTop, Edges.Top),
176 new MarginPaddingControl(safeAreaBackground, safeAreaGrid, "Bottom", safeAreaPaddingBottom, Edges.Bottom),
177 new MarginPaddingControl(safeAreaBackground, safeAreaGrid, "Left", safeAreaPaddingLeft, Edges.Left),
178 new MarginPaddingControl(safeAreaBackground, safeAreaGrid, "Right", safeAreaPaddingRight, Edges.Right),
179 };
180
181 safeAreaPaddingTop.ValueChanged += updateMarginPadding;
182 safeAreaPaddingBottom.ValueChanged += updateMarginPadding;
183 safeAreaPaddingLeft.ValueChanged += updateMarginPadding;
184 safeAreaPaddingRight.ValueChanged += updateMarginPadding;
185 }
186
187 private void updateMarginPadding(ValueChangedEvent<float> e)
188 {
189 bindableSafeArea.Value = new MarginPadding
190 {
191 Top = safeAreaPaddingTop.Value,
192 Bottom = safeAreaPaddingBottom.Value,
193 Left = safeAreaPaddingLeft.Value,
194 Right = safeAreaPaddingRight.Value,
195 };
196 }
197
198 private class MarginPaddingControl : FillFlowContainer
199 {
200 public MarginPaddingControl(SafeAreaContainer safeAreaBackground, SafeAreaContainer safeAreaGrid, string title, Bindable<float> bindable, Edges edge)
201 {
202 SpriteText valueText;
203 BasicCheckbox overrideCheckbox;
204 BasicCheckbox safeCheckbox;
205
206 Direction = FillDirection.Horizontal;
207 Spacing = new Vector2(20, 0);
208 AutoSizeAxes = Axes.Both;
209
210 Children = new Drawable[]
211 {
212 new SpriteText
213 {
214 Text = title,
215 Width = 60,
216 Origin = Anchor.CentreLeft,
217 Anchor = Anchor.CentreLeft,
218 },
219 valueText = new SpriteText
220 {
221 Width = 50,
222 Origin = Anchor.CentreLeft,
223 Anchor = Anchor.CentreLeft,
224 },
225 new BasicSliderBar<float>
226 {
227 Current = bindable,
228 Size = new Vector2(100, 20),
229 Origin = Anchor.CentreLeft,
230 Anchor = Anchor.CentreLeft,
231 },
232 new SpriteText
233 {
234 Text = "Background Override",
235 Origin = Anchor.CentreLeft,
236 Anchor = Anchor.CentreLeft,
237 },
238 overrideCheckbox = new BasicCheckbox(),
239 new SpriteText
240 {
241 Text = "Grid Override",
242 Origin = Anchor.CentreLeft,
243 Anchor = Anchor.CentreLeft,
244 },
245 safeCheckbox = new BasicCheckbox()
246 };
247
248 overrideCheckbox.Current.ValueChanged += e =>
249 {
250 if (e.NewValue)
251 safeAreaBackground.SafeAreaOverrideEdges |= edge;
252 else
253 safeAreaBackground.SafeAreaOverrideEdges &= ~edge;
254 };
255
256 safeCheckbox.Current.ValueChanged += e =>
257 {
258 if (e.NewValue)
259 safeAreaGrid.SafeAreaOverrideEdges |= edge;
260 else
261 safeAreaGrid.SafeAreaOverrideEdges &= ~edge;
262 };
263
264 bindable.ValueChanged += e => valueText.Text = $"{e.NewValue:F1}";
265 bindable.TriggerChange();
266 }
267 }
268 }
269 }
270}