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 NUnit.Framework;
6using osu.Framework.Graphics;
7using osu.Framework.Graphics.Containers;
8using osu.Framework.Graphics.Shapes;
9using osu.Framework.Graphics.Sprites;
10using osuTK;
11using osuTK.Graphics;
12
13namespace osu.Framework.Tests.Visual.Drawables
14{
15 [Description("Tests whether drawable updates occur before drawing.")]
16 public class TestSceneUpdateBeforeDraw : FrameworkTestScene
17 {
18 /// <summary>
19 /// Tests whether a <see cref="Drawable"/> is updated before being drawn when it is added to a parent
20 /// late enough into the frame that the <see cref="Drawable"/> shouldn't be drawn for the frame.
21 /// </summary>
22 [Test]
23 public void TestUpdateBeforeDrawFromLateAddition()
24 {
25 var receiver = new Container
26 {
27 Size = new Vector2(100),
28 Child = new Box
29 {
30 Anchor = Anchor.Centre,
31 Origin = Anchor.Centre,
32 Size = new Vector2(50),
33 Colour = Color4.Red
34 }
35 };
36
37 var sender = new HookableContainer();
38 var greenBox = new TestBox { Colour = Color4.Green };
39
40 AddStep("add children", () =>
41 {
42 Children = new Drawable[]
43 {
44 new SpriteText { Text = "Red box should be visible, green should not be visible" },
45 // Order is important
46 receiver,
47 sender,
48 };
49 });
50
51 sender.OnUpdateAfterChildren = () => receiver.Add(greenBox);
52
53 AddStep("wait one frame", () => { });
54 AddAssert("green not present", () => !greenBox.IsPresent);
55 }
56
57 private class HookableContainer : Container
58 {
59 /// <summary>
60 /// Invoked once.
61 /// </summary>
62 public Action OnUpdateAfterChildren;
63
64 private bool hasInvoked;
65
66 protected override void UpdateAfterChildren()
67 {
68 base.UpdateAfterChildren();
69
70 if (hasInvoked)
71 return;
72
73 hasInvoked = true;
74
75 OnUpdateAfterChildren?.Invoke();
76 }
77 }
78
79 /// <summary>
80 /// A box which sets its alpha to 0 in <see cref="Update"/> if it hasn't been drawn yet.
81 /// </summary>
82 private class TestBox : Box
83 {
84 private bool hasDrawn;
85
86 public TestBox()
87 {
88 Anchor = Anchor.Centre;
89 Origin = Anchor.Centre;
90
91 Size = new Vector2(50);
92 }
93
94 protected override void Update()
95 {
96 base.Update();
97
98 if (hasDrawn)
99 return;
100
101 Alpha = 0;
102 }
103
104 internal override DrawNode GenerateDrawNodeSubtree(ulong frame, int treeIndex, bool forceNewDrawNode)
105 {
106 hasDrawn = true;
107 return base.GenerateDrawNodeSubtree(frame, treeIndex, forceNewDrawNode);
108 }
109 }
110 }
111}