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.IEnumerableExtensions;
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 osu.Framework.Input;
12using osu.Framework.Testing.Input;
13using osuTK;
14using osuTK.Graphics;
15
16namespace osu.Framework.Testing
17{
18 /// <summary>
19 /// An abstract test case which is tested with manual input management.
20 /// </summary>
21 public abstract class ManualInputManagerTestScene : TestScene
22 {
23 protected override Container<Drawable> Content { get; } = new Container { RelativeSizeAxes = Axes.Both };
24
25 /// <summary>
26 /// The position which is used to initialize the mouse position before at setup.
27 /// </summary>
28 protected virtual Vector2 InitialMousePosition => Vector2.Zero;
29
30 /// <summary>
31 /// The <see cref="ManualInputManager"/>.
32 /// </summary>
33 protected ManualInputManager InputManager { get; }
34
35 private readonly BasicButton buttonTest;
36 private readonly BasicButton buttonLocal;
37
38 [SetUp]
39 public void SetUp() => ResetInput();
40
41 protected ManualInputManagerTestScene()
42 {
43 base.Content.AddRange(new Drawable[]
44 {
45 InputManager = new ManualInputManager
46 {
47 UseParentInput = true,
48 Child = Content,
49 },
50 new Container
51 {
52 Depth = float.MinValue,
53 AutoSizeAxes = Axes.Both,
54 Anchor = Anchor.TopRight,
55 Origin = Anchor.TopRight,
56 Margin = new MarginPadding(5),
57 CornerRadius = 5,
58 Masking = true,
59 Children = new Drawable[]
60 {
61 new Box
62 {
63 Colour = Color4.Black,
64 RelativeSizeAxes = Axes.Both,
65 Alpha = 0.5f,
66 },
67 new FillFlowContainer
68 {
69 AutoSizeAxes = Axes.Both,
70 Direction = FillDirection.Vertical,
71 Margin = new MarginPadding(5),
72 Spacing = new Vector2(5),
73 Children = new Drawable[]
74 {
75 new SpriteText
76 {
77 Anchor = Anchor.TopCentre,
78 Origin = Anchor.TopCentre,
79 Text = "Input Priority",
80 Font = FrameworkFont.Regular,
81 },
82 new FillFlowContainer
83 {
84 AutoSizeAxes = Axes.Both,
85 Anchor = Anchor.TopCentre,
86 Origin = Anchor.TopCentre,
87 Margin = new MarginPadding(5),
88 Spacing = new Vector2(5),
89 Direction = FillDirection.Horizontal,
90
91 Children = new Drawable[]
92 {
93 buttonLocal = new BasicButton
94 {
95 Text = "local",
96 Size = new Vector2(50, 30),
97 Action = returnUserInput
98 },
99 buttonTest = new BasicButton
100 {
101 Text = "test",
102 Size = new Vector2(50, 30),
103 Action = returnTestInput
104 },
105 }
106 },
107 }
108 },
109 }
110 },
111 });
112 }
113
114 protected override void Update()
115 {
116 base.Update();
117
118 buttonTest.Enabled.Value = InputManager.UseParentInput;
119 buttonLocal.Enabled.Value = !InputManager.UseParentInput;
120 }
121
122 /// <summary>
123 /// Releases all pressed keys and buttons and initialize mouse position.
124 /// </summary>
125 protected void ResetInput()
126 {
127 var currentState = InputManager.CurrentState;
128
129 var mouse = currentState.Mouse;
130 InputManager.MoveMouseTo(InitialMousePosition);
131 mouse.Buttons.ForEach(InputManager.ReleaseButton);
132
133 var keyboard = currentState.Keyboard;
134 keyboard.Keys.ForEach(InputManager.ReleaseKey);
135
136 var touch = currentState.Touch;
137 touch.ActiveSources.ForEach(s => InputManager.EndTouch(new Touch(s, Vector2.Zero)));
138
139 var joystick = currentState.Joystick;
140 joystick.Buttons.ForEach(InputManager.ReleaseJoystickButton);
141
142 // schedule after children to ensure pending inputs have been applied before using parent input manager.
143 ScheduleAfterChildren(returnUserInput);
144 }
145
146 private void returnUserInput() => InputManager.UseParentInput = true;
147
148 private void returnTestInput() => InputManager.UseParentInput = false;
149 }
150}