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.Extensions.Color4Extensions;
6using osu.Framework.Graphics;
7using osu.Framework.Graphics.Containers;
8using osu.Framework.Graphics.Shapes;
9using osu.Framework.Graphics.Sprites;
10using osu.Framework.Input.Events;
11using osu.Framework.Utils;
12using osuTK;
13using osuTK.Graphics;
14
15namespace osu.Framework.Tests.Visual.Containers
16{
17 [System.ComponentModel.Description("potentially challenging size calculations")]
18 public class TestSceneSizing : FrameworkTestScene
19 {
20 private Container testContainer;
21
22 public TestSceneSizing()
23 {
24 string[] testNames =
25 {
26 @"Multiple children",
27 @"Nested children",
28 @"AutoSize bench",
29 @"RelativeSize bench",
30 @"SpriteText 1",
31 @"SpriteText 2",
32 @"Inverted scaling",
33 @"RelativeSize",
34 @"Padding",
35 @"Margin",
36 @"Inner Margin",
37 @"Drawable Margin",
38 @"Relative Inside Autosize",
39 @"Negative sizing"
40 };
41
42 for (int i = 0; i < testNames.Length; i++)
43 {
44 int test = i;
45 AddStep(testNames[i], delegate { loadTest(test); });
46 }
47 }
48
49 [Test]
50 public void TestBypassAutoSizeAxes()
51 {
52 const float autosize_height = 300;
53
54 Container autoSizeContainer = null;
55 Box boxSizeReference = null;
56
57 AddStep("init", () =>
58 {
59 Child = autoSizeContainer = new Container
60 {
61 Anchor = Anchor.Centre,
62 Origin = Anchor.Centre,
63 Width = 300,
64 AutoSizeAxes = Axes.Y,
65 Children = new Drawable[]
66 {
67 new Box
68 {
69 Colour = Color4.Green,
70 RelativeSizeAxes = Axes.Both
71 },
72 boxSizeReference = new Box
73 {
74 RelativeSizeAxes = Axes.X,
75 Height = autosize_height,
76 Colour = Color4.Red.Opacity(0.2f),
77 }
78 }
79 };
80 });
81 AddAssert($"height = {autosize_height}", () => Precision.AlmostEquals(autosize_height, autoSizeContainer.DrawHeight));
82 AddStep("bypass y", () => boxSizeReference.BypassAutoSizeAxes = Axes.Y);
83 AddAssert("height = 0", () => Precision.AlmostEquals(0, autoSizeContainer.DrawHeight));
84 AddStep("bypass none", () => boxSizeReference.BypassAutoSizeAxes = Axes.None);
85 AddAssert($"height = {autosize_height}", () => Precision.AlmostEquals(autosize_height, autoSizeContainer.DrawHeight));
86 }
87
88 [Test]
89 public void TestParentInvalidations()
90 {
91 Container child = null;
92 Vector2 initialSize = Vector2.Zero;
93
94 AddStep("add child", () =>
95 {
96 Child = child = new Container
97 {
98 AutoSizeAxes = Axes.Both,
99 Child = new Container
100 {
101 // These two properties are important, as they make the parent's autosize 0
102 Anchor = Anchor.TopLeft,
103 Origin = Anchor.BottomRight,
104 AutoSizeAxes = Axes.Both,
105 Child = new Box { Size = new Vector2(100) },
106 }
107 };
108
109 // Should already be 0
110 initialSize = child.Size;
111 });
112
113 // Upon LoadComplete(), one invalidation occurs which causes autosize to recompute
114 // Since nothing has changed since the previous frame, the size of the child should remain the same
115 AddAssert("size is the same after one frame", () => child.Size == initialSize);
116 }
117
118 private void addCrosshair()
119 {
120 Add(new Box
121 {
122 Colour = Color4.Black,
123 Size = new Vector2(22, 4),
124 Anchor = Anchor.Centre,
125 Origin = Anchor.Centre
126 });
127
128 Add(new Box
129 {
130 Colour = Color4.Black,
131 Size = new Vector2(4, 22),
132 Anchor = Anchor.Centre,
133 Origin = Anchor.Centre
134 });
135
136 Add(new Box
137 {
138 Colour = Color4.WhiteSmoke,
139 Size = new Vector2(20, 2),
140 Anchor = Anchor.Centre,
141 Origin = Anchor.Centre
142 });
143
144 Add(new Box
145 {
146 Colour = Color4.WhiteSmoke,
147 Size = new Vector2(2, 20),
148 Anchor = Anchor.Centre,
149 Origin = Anchor.Centre
150 });
151 }
152
153 private void loadTest(int testType)
154 {
155 Child = testContainer = new Container
156 {
157 RelativeSizeAxes = Axes.Both,
158 };
159 addCrosshair();
160
161 Container box;
162
163 switch (testType)
164 {
165 case 0:
166 testContainer.Add(box = new InfofulBoxAutoSize
167 {
168 Anchor = Anchor.Centre,
169 Origin = Anchor.Centre
170 });
171
172 addCornerMarkers(box);
173
174 box.Add(new InfofulBox
175 {
176 //chameleon = true,
177 Position = new Vector2(0, 0),
178 Size = new Vector2(25, 25),
179 Origin = Anchor.Centre,
180 Anchor = Anchor.Centre,
181 Colour = Color4.Blue,
182 });
183
184 box.Add(box = new InfofulBox
185 {
186 Size = new Vector2(250, 250),
187 Alpha = 0.5f,
188 Origin = Anchor.Centre,
189 Anchor = Anchor.Centre,
190 Colour = Color4.DarkSeaGreen,
191 });
192
193 box.OnUpdate += delegate { box.Rotation += 0.05f; };
194 break;
195
196 case 1:
197 testContainer.Add(box = new InfofulBoxAutoSize
198 {
199 Anchor = Anchor.Centre,
200 Origin = Anchor.Centre
201 });
202
203 addCornerMarkers(box, 5);
204
205 box.Add(box = new InfofulBoxAutoSize
206 {
207 Colour = Color4.DarkSeaGreen,
208 Alpha = 0.5f,
209 Origin = Anchor.Centre,
210 Anchor = Anchor.Centre
211 });
212
213 Drawable localBox = box;
214 box.OnUpdate += delegate { localBox.Rotation += 0.05f; };
215
216 box.Add(new InfofulBox
217 {
218 //chameleon = true,
219 Size = new Vector2(100, 100),
220 Position = new Vector2(50, 50),
221 Alpha = 0.5f,
222 Origin = Anchor.Centre,
223 Anchor = Anchor.Centre,
224 Colour = Color4.Blue,
225 });
226 break;
227
228 case 2:
229 testContainer.Add(box = new InfofulBoxAutoSize
230 {
231 Anchor = Anchor.Centre,
232 Origin = Anchor.Centre
233 });
234
235 addCornerMarkers(box, 10, Color4.YellowGreen);
236
237 for (int i = 0; i < 40; i++)
238 {
239 box.Add(box = new InfofulBoxAutoSize
240 {
241 Colour = new Color4(253, 253, 253, 255),
242 Position = new Vector2(-3, -3),
243 Origin = Anchor.BottomRight,
244 Anchor = Anchor.BottomRight,
245 });
246 }
247
248 addCornerMarkers(box, 2);
249
250 box.Add(new InfofulBox
251 {
252 //chameleon = true,
253 Size = new Vector2(50, 50),
254 Origin = Anchor.BottomRight,
255 Anchor = Anchor.BottomRight,
256 Colour = Color4.SeaGreen,
257 });
258 break;
259
260 case 3:
261 testContainer.Add(box = new InfofulBox
262 {
263 Anchor = Anchor.Centre,
264 Origin = Anchor.Centre,
265 Size = new Vector2(250, 250)
266 });
267
268 addCornerMarkers(box, 10, Color4.YellowGreen);
269
270 for (int i = 0; i < 100; i++)
271 {
272 box.Add(box = new InfofulBox
273 {
274 RelativeSizeAxes = Axes.Both,
275 Colour = new Color4(253, 253, 253, 255),
276 Origin = Anchor.BottomRight,
277 Anchor = Anchor.BottomRight,
278 Size = new Vector2(0.99f, 0.99f)
279 });
280 }
281
282 addCornerMarkers(box, 2);
283
284 box.Add(new InfofulBox
285 {
286 //chameleon = true,
287 Size = new Vector2(50, 50),
288 Origin = Anchor.BottomRight,
289 Anchor = Anchor.BottomRight,
290 Colour = Color4.SeaGreen,
291 });
292 break;
293
294 case 4:
295 testContainer.Add(box = new InfofulBoxAutoSize
296 {
297 Anchor = Anchor.Centre,
298 Origin = Anchor.CentreLeft
299 });
300
301 box.Add(new InfofulBox
302 {
303 Position = new Vector2(5, 0),
304 Size = new Vector2(300, 80),
305 Origin = Anchor.TopLeft,
306 Anchor = Anchor.TopLeft,
307 Colour = Color4.OrangeRed,
308 });
309
310 box.Add(new SpriteText
311 {
312 Position = new Vector2(5, -20),
313 Text = "Test CentreLeft line 1",
314 Origin = Anchor.CentreLeft,
315 Anchor = Anchor.CentreLeft
316 });
317
318 box.Add(new SpriteText
319 {
320 Position = new Vector2(5, 20),
321 Text = "Test CentreLeft line 2",
322 Origin = Anchor.CentreLeft,
323 Anchor = Anchor.CentreLeft
324 });
325 break;
326
327 case 5:
328 testContainer.Add(box = new InfofulBoxAutoSize
329 {
330 Anchor = Anchor.Centre,
331 Origin = Anchor.CentreLeft
332 });
333
334 box.Add(new InfofulBox
335 {
336 Position = new Vector2(5, 0),
337 Size = new Vector2(300, 80),
338 Origin = Anchor.TopLeft,
339 Anchor = Anchor.TopLeft,
340 Colour = Color4.OrangeRed,
341 });
342
343 box.Add(new SpriteText
344 {
345 Position = new Vector2(5, -20),
346 Text = "123,456,789=",
347 Origin = Anchor.CentreLeft,
348 Anchor = Anchor.CentreLeft,
349 Scale = new Vector2(2f)
350 });
351
352 box.Add(new SpriteText
353 {
354 Position = new Vector2(5, 20),
355 Text = "123,456,789ms",
356 Origin = Anchor.CentreLeft,
357 Anchor = Anchor.CentreLeft
358 });
359 break;
360
361 case 6:
362 testContainer.Add(box = new InfofulBoxAutoSize
363 {
364 Anchor = Anchor.Centre,
365 Origin = Anchor.Centre
366 });
367
368 box.Add(box = new InfofulBoxAutoSize
369 {
370 Colour = Color4.OrangeRed,
371 Position = new Vector2(100, 100),
372 Origin = Anchor.Centre,
373 Anchor = Anchor.TopLeft
374 });
375
376 box.Add(new InfofulBox
377 {
378 Position = new Vector2(100, 100),
379 Size = new Vector2(100, 100),
380 Origin = Anchor.Centre,
381 Anchor = Anchor.TopLeft,
382 Colour = Color4.OrangeRed,
383 });
384 break;
385
386 case 7:
387 Container shrinkContainer;
388 Container<Drawable> boxes;
389
390 testContainer.Add(shrinkContainer = new Container
391 {
392 RelativeSizeAxes = Axes.Both,
393 Size = new Vector2(0.5f, 1),
394 Anchor = Anchor.TopCentre,
395 Origin = Anchor.TopCentre,
396 Children = new Drawable[]
397 {
398 new Box
399 {
400 RelativeSizeAxes = Axes.Both,
401 Colour = Color4.AliceBlue,
402 Alpha = 0.2f
403 },
404 boxes = new FillFlowContainer
405 {
406 RelativeSizeAxes = Axes.X,
407 AutoSizeAxes = Axes.Y,
408 Direction = FillDirection.Vertical,
409 Spacing = new Vector2(0, 10),
410 }
411 }
412 });
413
414 for (int i = 0; i < 10; i++)
415 {
416 boxes.Add(new Box
417 {
418 RelativeSizeAxes = Axes.X,
419 Anchor = Anchor.TopCentre,
420 Origin = Anchor.TopCentre,
421 Size = new Vector2(0.9f, 40),
422 Colour = Color4.AliceBlue,
423 Alpha = 0.2f
424 });
425 }
426
427 shrinkContainer.ScaleTo(new Vector2(1.5f, 1), 1000).Then().ScaleTo(Vector2.One, 1000).Loop();
428 break;
429
430 case 8:
431 {
432 Container box1;
433 Container box2;
434 Container box3;
435
436 testContainer.Add(new FillFlowContainer
437 {
438 RelativeSizeAxes = Axes.Both,
439 Children = new Drawable[]
440 {
441 // This first guy is used for spacing.
442 new Container
443 {
444 RelativeSizeAxes = Axes.Both,
445 Size = new Vector2(0.125f, 1),
446 },
447 new Container
448 {
449 RelativeSizeAxes = Axes.Both,
450 Size = new Vector2(0.25f, 1),
451 Children = new[]
452 {
453 new InfofulBoxAutoSize
454 {
455 Anchor = Anchor.Centre,
456 Origin = Anchor.Centre,
457 Children = new[]
458 {
459 new Container
460 {
461 AutoSizeAxes = Axes.Both,
462 Depth = -1,
463 Padding = new MarginPadding(50),
464 Children = new Drawable[]
465 {
466 box1 = new InfofulBox
467 {
468 Anchor = Anchor.TopLeft,
469 Origin = Anchor.TopLeft,
470 Size = new Vector2(50),
471 Colour = Color4.Blue,
472 },
473 }
474 }
475 }
476 },
477 }
478 },
479 new Container
480 {
481 RelativeSizeAxes = Axes.Both,
482 Size = new Vector2(0.25f, 1),
483 Children = new[]
484 {
485 new InfofulBoxAutoSize
486 {
487 Anchor = Anchor.Centre,
488 Origin = Anchor.Centre,
489 Children = new[]
490 {
491 new Container
492 {
493 AutoSizeAxes = Axes.Both,
494 Depth = -1,
495 Padding = new MarginPadding(50),
496 Children = new Drawable[]
497 {
498 box2 = new InfofulBox
499 {
500 Anchor = Anchor.Centre,
501 Origin = Anchor.Centre,
502 Size = new Vector2(50),
503 Colour = Color4.Blue,
504 },
505 }
506 }
507 }
508 },
509 }
510 },
511 new Container
512 {
513 RelativeSizeAxes = Axes.Both,
514 Size = new Vector2(0.25f, 1),
515 Children = new[]
516 {
517 new InfofulBoxAutoSize
518 {
519 Anchor = Anchor.Centre,
520 Origin = Anchor.Centre,
521 Children = new[]
522 {
523 new Container
524 {
525 AutoSizeAxes = Axes.Both,
526 Depth = -1,
527 Padding = new MarginPadding(50),
528 Children = new Drawable[]
529 {
530 box3 = new InfofulBox
531 {
532 Anchor = Anchor.BottomRight,
533 Origin = Anchor.BottomRight,
534 Size = new Vector2(50),
535 Colour = Color4.Blue,
536 },
537 }
538 }
539 }
540 },
541 }
542 },
543 }
544 });
545
546 foreach (Container b in new[] { box1, box2, box3 })
547 b.ScaleTo(new Vector2(2), 1000).Then().ScaleTo(Vector2.One, 1000).Loop();
548
549 break;
550 }
551
552 case 9:
553 {
554 Container box1;
555 Container box2;
556 Container box3;
557
558 testContainer.Add(new FillFlowContainer
559 {
560 RelativeSizeAxes = Axes.Both,
561 Children = new Drawable[]
562 {
563 // This first guy is used for spacing.
564 new Container
565 {
566 RelativeSizeAxes = Axes.Both,
567 Size = new Vector2(0.125f, 1),
568 },
569 new Container
570 {
571 RelativeSizeAxes = Axes.Both,
572 Size = new Vector2(0.25f, 1),
573 Children = new[]
574 {
575 new InfofulBoxAutoSize
576 {
577 Anchor = Anchor.Centre,
578 Origin = Anchor.Centre,
579 Children = new[]
580 {
581 new Container
582 {
583 AutoSizeAxes = Axes.Both,
584 Depth = -1,
585 Margin = new MarginPadding(50),
586 Children = new Drawable[]
587 {
588 box1 = new InfofulBox
589 {
590 Anchor = Anchor.TopLeft,
591 Origin = Anchor.TopLeft,
592 Size = new Vector2(50),
593 Colour = Color4.Blue,
594 },
595 }
596 }
597 }
598 },
599 }
600 },
601 new Container
602 {
603 RelativeSizeAxes = Axes.Both,
604 Size = new Vector2(0.25f, 1),
605 Children = new[]
606 {
607 new InfofulBoxAutoSize
608 {
609 Anchor = Anchor.Centre,
610 Origin = Anchor.Centre,
611 Children = new[]
612 {
613 new Container
614 {
615 AutoSizeAxes = Axes.Both,
616 Depth = -1,
617 Margin = new MarginPadding(50),
618 Children = new Drawable[]
619 {
620 box2 = new InfofulBox
621 {
622 Anchor = Anchor.Centre,
623 Origin = Anchor.Centre,
624 Size = new Vector2(50),
625 Colour = Color4.Blue,
626 },
627 }
628 }
629 }
630 },
631 }
632 },
633 new Container
634 {
635 RelativeSizeAxes = Axes.Both,
636 Size = new Vector2(0.25f, 1),
637 Children = new[]
638 {
639 new InfofulBoxAutoSize
640 {
641 Anchor = Anchor.Centre,
642 Origin = Anchor.Centre,
643 Children = new[]
644 {
645 new Container
646 {
647 AutoSizeAxes = Axes.Both,
648 Depth = -1,
649 Margin = new MarginPadding(50),
650 Children = new Drawable[]
651 {
652 box3 = new InfofulBox
653 {
654 Anchor = Anchor.BottomRight,
655 Origin = Anchor.BottomRight,
656 Size = new Vector2(50),
657 Colour = Color4.Blue,
658 },
659 }
660 }
661 }
662 },
663 }
664 },
665 }
666 });
667
668 foreach (Container b in new[] { box1, box2, box3 })
669 b.ScaleTo(new Vector2(2), 1000).Then().ScaleTo(Vector2.One, 1000).Loop();
670
671 break;
672 }
673
674 case 10:
675 {
676 Container box1;
677 Container box2;
678 Container box3;
679
680 testContainer.Add(new FillFlowContainer
681 {
682 RelativeSizeAxes = Axes.Both,
683 Children = new Drawable[]
684 {
685 // This first guy is used for spacing.
686 new Container
687 {
688 RelativeSizeAxes = Axes.Both,
689 Size = new Vector2(0.125f, 1),
690 },
691 new Container
692 {
693 RelativeSizeAxes = Axes.Both,
694 Size = new Vector2(0.25f, 1),
695 Children = new[]
696 {
697 new InfofulBoxAutoSize
698 {
699 Anchor = Anchor.Centre,
700 Origin = Anchor.Centre,
701 Children = new[]
702 {
703 new Container
704 {
705 AutoSizeAxes = Axes.Both,
706 Depth = -1,
707 Children = new Drawable[]
708 {
709 box1 = new InfofulBox
710 {
711 Margin = new MarginPadding(50),
712 Anchor = Anchor.TopLeft,
713 Origin = Anchor.TopLeft,
714 Size = new Vector2(50),
715 Colour = Color4.Blue,
716 },
717 }
718 }
719 }
720 },
721 }
722 },
723 new Container
724 {
725 RelativeSizeAxes = Axes.Both,
726 Size = new Vector2(0.25f, 1),
727 Children = new[]
728 {
729 new InfofulBoxAutoSize
730 {
731 Anchor = Anchor.Centre,
732 Origin = Anchor.Centre,
733 Children = new[]
734 {
735 new Container
736 {
737 AutoSizeAxes = Axes.Both,
738 Depth = -1,
739 Children = new Drawable[]
740 {
741 box2 = new InfofulBox
742 {
743 Margin = new MarginPadding(50),
744 Anchor = Anchor.Centre,
745 Origin = Anchor.Centre,
746 Size = new Vector2(50),
747 Colour = Color4.Blue,
748 },
749 }
750 }
751 }
752 },
753 }
754 },
755 new Container
756 {
757 RelativeSizeAxes = Axes.Both,
758 Size = new Vector2(0.25f, 1),
759 Children = new[]
760 {
761 new InfofulBoxAutoSize
762 {
763 Anchor = Anchor.Centre,
764 Origin = Anchor.Centre,
765 Children = new[]
766 {
767 new Container
768 {
769 AutoSizeAxes = Axes.Both,
770 Depth = -1,
771 Children = new Drawable[]
772 {
773 box3 = new InfofulBox
774 {
775 Margin = new MarginPadding(50),
776 Anchor = Anchor.BottomRight,
777 Origin = Anchor.BottomRight,
778 Size = new Vector2(50),
779 Colour = Color4.Blue,
780 },
781 }
782 }
783 }
784 },
785 }
786 },
787 }
788 });
789
790 foreach (Container b in new[] { box1, box2, box3 })
791 b.ScaleTo(new Vector2(2), 1000).Then().ScaleTo(Vector2.One, 1000).Loop();
792
793 break;
794 }
795
796 case 11:
797 {
798 Drawable box1;
799 Drawable box2;
800 Drawable box3;
801
802 testContainer.Add(new FillFlowContainer
803 {
804 RelativeSizeAxes = Axes.Both,
805 Children = new Drawable[]
806 {
807 // This first guy is used for spacing.
808 new Container
809 {
810 RelativeSizeAxes = Axes.Both,
811 Size = new Vector2(0.125f, 1),
812 },
813 new Container
814 {
815 RelativeSizeAxes = Axes.Both,
816 Size = new Vector2(0.25f, 1),
817 Children = new[]
818 {
819 new InfofulBoxAutoSize
820 {
821 Anchor = Anchor.Centre,
822 Origin = Anchor.Centre,
823 Children = new[]
824 {
825 new Container
826 {
827 AutoSizeAxes = Axes.Both,
828 Depth = -1,
829 Children = new[]
830 {
831 box1 = new Box
832 {
833 Margin = new MarginPadding(50),
834 Anchor = Anchor.TopLeft,
835 Origin = Anchor.TopLeft,
836 Size = new Vector2(50),
837 Colour = Color4.Blue,
838 },
839 }
840 }
841 }
842 },
843 }
844 },
845 new Container
846 {
847 RelativeSizeAxes = Axes.Both,
848 Size = new Vector2(0.25f, 1),
849 Children = new[]
850 {
851 new InfofulBoxAutoSize
852 {
853 Anchor = Anchor.Centre,
854 Origin = Anchor.Centre,
855 Children = new[]
856 {
857 new Container
858 {
859 AutoSizeAxes = Axes.Both,
860 Depth = -1,
861 Children = new[]
862 {
863 box2 = new Box
864 {
865 Margin = new MarginPadding(50),
866 Anchor = Anchor.Centre,
867 Origin = Anchor.Centre,
868 Size = new Vector2(50),
869 Colour = Color4.Blue,
870 },
871 }
872 }
873 }
874 },
875 }
876 },
877 new Container
878 {
879 RelativeSizeAxes = Axes.Both,
880 Size = new Vector2(0.25f, 1),
881 Children = new[]
882 {
883 new InfofulBoxAutoSize
884 {
885 Anchor = Anchor.Centre,
886 Origin = Anchor.Centre,
887 Children = new[]
888 {
889 new Container
890 {
891 AutoSizeAxes = Axes.Both,
892 Depth = -1,
893 Children = new[]
894 {
895 box3 = new Box
896 {
897 Margin = new MarginPadding(50),
898 Anchor = Anchor.BottomRight,
899 Origin = Anchor.BottomRight,
900 Size = new Vector2(50),
901 Colour = Color4.Blue,
902 },
903 }
904 }
905 }
906 },
907 }
908 },
909 }
910 });
911
912 foreach (Drawable b in new[] { box1, box2, box3 })
913 b.ScaleTo(new Vector2(2), 1000).Then().ScaleTo(Vector2.One, 1000).Loop();
914
915 break;
916 }
917
918 case 12:
919 {
920 // demonstrates how relativeaxes drawables act inside an autosize parent
921 Drawable sizedBox;
922
923 testContainer.Add(new FillFlowContainer
924 {
925 RelativeSizeAxes = Axes.Both,
926 Children = new Drawable[]
927 {
928 new Container
929 {
930 Size = new Vector2(300),
931 Anchor = Anchor.Centre,
932 Origin = Anchor.Centre,
933 Children = new Drawable[]
934 {
935 new Box { Colour = Color4.Gray, RelativeSizeAxes = Axes.Both },
936 new Container
937 {
938 AutoSizeAxes = Axes.Both,
939 Anchor = Anchor.Centre,
940 Origin = Anchor.Centre,
941 Children = new[]
942 {
943 // defines the size of autosize
944 sizedBox = new Box
945 {
946 Colour = Color4.Red,
947 Anchor = Anchor.Centre,
948 Origin = Anchor.Centre,
949 Size = new Vector2(100f)
950 },
951 // gets relative size based on autosize
952 new Box
953 {
954 Colour = Color4.Black,
955 RelativeSizeAxes = Axes.Both,
956 Size = new Vector2(0.5f)
957 },
958 }
959 }
960 }
961 }
962 }
963 });
964
965 sizedBox.ScaleTo(new Vector2(2), 1000, Easing.Out).Then().ScaleTo(Vector2.One, 1000, Easing.In).Loop();
966 break;
967 }
968
969 case 13:
970 {
971 testContainer.Add(new FillFlowContainer
972 {
973 Anchor = Anchor.Centre,
974 Origin = Anchor.Centre,
975 RelativeSizeAxes = Axes.X,
976 AutoSizeAxes = Axes.Y,
977 Direction = FillDirection.Vertical,
978 Spacing = new Vector2(0, 20),
979 Children = new[]
980 {
981 new FillFlowContainer
982 {
983 Name = "Top row",
984 RelativeSizeAxes = Axes.X,
985 Height = 200,
986 Direction = FillDirection.Horizontal,
987 Spacing = new Vector2(100, 0),
988 Children = new[]
989 {
990 new NegativeSizingContainer(Anchor.TopLeft, true),
991 new NegativeSizingContainer(Anchor.Centre, true),
992 new NegativeSizingContainer(Anchor.BottomRight, true)
993 }
994 },
995 new FillFlowContainer
996 {
997 Name = "Bottom row",
998 RelativeSizeAxes = Axes.X,
999 Height = 200,
1000 Direction = FillDirection.Horizontal,
1001 Spacing = new Vector2(100, 0),
1002 Children = new[]
1003 {
1004 new NegativeSizingContainer(Anchor.TopLeft, false),
1005 new NegativeSizingContainer(Anchor.Centre, false),
1006 new NegativeSizingContainer(Anchor.BottomRight, false)
1007 }
1008 }
1009 }
1010 });
1011
1012 break;
1013 }
1014 }
1015 }
1016
1017 private void addCornerMarkers(Container box, int size = 50, Color4? colour = null)
1018 {
1019 box.Add(new InfofulBox
1020 {
1021 //chameleon = true,
1022 Size = new Vector2(size, size),
1023 Origin = Anchor.TopLeft,
1024 Anchor = Anchor.TopLeft,
1025 AllowDrag = false,
1026 Depth = -2,
1027 Colour = colour ?? Color4.Red,
1028 });
1029
1030 box.Add(new InfofulBox
1031 {
1032 //chameleon = true,
1033 Size = new Vector2(size, size),
1034 Origin = Anchor.TopRight,
1035 Anchor = Anchor.TopRight,
1036 AllowDrag = false,
1037 Depth = -2,
1038 Colour = colour ?? Color4.Red,
1039 });
1040
1041 box.Add(new InfofulBox
1042 {
1043 //chameleon = true,
1044 Size = new Vector2(size, size),
1045 Origin = Anchor.BottomLeft,
1046 Anchor = Anchor.BottomLeft,
1047 AllowDrag = false,
1048 Depth = -2,
1049 Colour = colour ?? Color4.Red,
1050 });
1051
1052 box.Add(new InfofulBox
1053 {
1054 //chameleon = true,
1055 Size = new Vector2(size, size),
1056 Origin = Anchor.BottomRight,
1057 Anchor = Anchor.BottomRight,
1058 AllowDrag = false,
1059 Depth = -2,
1060 Colour = colour ?? Color4.Red,
1061 });
1062 }
1063
1064 private class NegativeSizingContainer : Container
1065 {
1066 private const float size = 200;
1067
1068 private readonly Box box;
1069 private readonly SpriteText text;
1070
1071 private readonly bool useScale;
1072
1073 public NegativeSizingContainer(Anchor anchor, bool useScale)
1074 {
1075 this.useScale = useScale;
1076
1077 Anchor = Anchor.Centre;
1078 Origin = Anchor.Centre;
1079 AutoSizeAxes = Axes.Both;
1080
1081 Children = new Drawable[]
1082 {
1083 box = new Box
1084 {
1085 Anchor = anchor,
1086 Origin = anchor,
1087 Size = new Vector2(size)
1088 },
1089 text = new SpriteText
1090 {
1091 Anchor = Anchor.Centre,
1092 Origin = Anchor.Centre,
1093 Colour = Color4.Red,
1094 BypassAutoSizeAxes = Axes.Both
1095 }
1096 };
1097 }
1098
1099 protected override void LoadComplete()
1100 {
1101 base.LoadComplete();
1102
1103 if (useScale)
1104 box.ScaleTo(new Vector2(-1), 3000, Easing.InSine).Then().ScaleTo(new Vector2(1), 3000, Easing.InSine).Loop();
1105 else
1106 box.ResizeTo(new Vector2(-size), 3000, Easing.InSine).Then().ResizeTo(new Vector2(size), 3000, Easing.InSine).Loop();
1107 }
1108
1109 protected override void Update()
1110 {
1111 base.Update();
1112
1113 text.Text = useScale ? $"Scale: {box.Scale}" : $"Size: {box.Size}";
1114 }
1115 }
1116 }
1117
1118 internal class InfofulBoxAutoSize : Container
1119 {
1120 protected override Container<Drawable> Content { get; }
1121
1122 public InfofulBoxAutoSize()
1123 {
1124 AutoSizeAxes = Axes.Both;
1125
1126 Masking = true;
1127
1128 InternalChildren = new Drawable[]
1129 {
1130 new Box
1131 {
1132 RelativeSizeAxes = Axes.Both,
1133 Depth = float.MaxValue,
1134 },
1135 Content = new Container
1136 {
1137 AutoSizeAxes = Axes.Both,
1138 }
1139 };
1140 }
1141
1142 public bool AllowDrag = true;
1143
1144 protected override void OnDrag(DragEvent e)
1145 {
1146 if (!AllowDrag) return;
1147
1148 Position += e.Delta;
1149 }
1150
1151 protected override bool OnDragStart(DragStartEvent e) => AllowDrag;
1152 }
1153
1154 internal class InfofulBox : Container
1155 {
1156 public bool AllowDrag = true;
1157
1158 protected override void OnDrag(DragEvent e)
1159 {
1160 if (!AllowDrag) return;
1161
1162 Position += e.Delta;
1163 }
1164
1165 protected override bool OnDragStart(DragStartEvent e) => AllowDrag;
1166
1167 public InfofulBox()
1168 {
1169 Add(new Box
1170 {
1171 RelativeSizeAxes = Axes.Both,
1172 Depth = float.MaxValue,
1173 });
1174 }
1175 }
1176}