A game framework written with osu! in mind.
at master 5.1 kB view raw
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.Collections.Generic; 5using System.Linq; 6using NUnit.Framework; 7using osu.Framework.Graphics; 8using osu.Framework.Graphics.Containers; 9using osu.Framework.Graphics.UserInterface; 10using osuTK.Input; 11 12namespace osu.Framework.Testing 13{ 14 /// <summary> 15 /// A test scene that provides a set of helper functions and structures for testing a <see cref="Menu"/>. 16 /// </summary> 17 public abstract class MenuTestScene : ManualInputManagerTestScene 18 { 19 protected MenuStructure Menus; 20 21 [SetUp] 22 public new void SetUp() => Schedule(() => 23 { 24 Menu menu; 25 Child = new Container 26 { 27 RelativeSizeAxes = Axes.Both, 28 Child = menu = CreateMenu(), 29 }; 30 31 Menus = new MenuStructure(menu); 32 }); 33 34 /// <summary> 35 /// Click an item in a menu. 36 /// </summary> 37 /// <param name="menuIndex">The level of menu our click targets.</param> 38 /// <param name="itemIndex">The item to click in the menu.</param> 39 protected void ClickItem(int menuIndex, int itemIndex) 40 { 41 InputManager.MoveMouseTo(Menus.GetSubStructure(menuIndex).GetMenuItems()[itemIndex]); 42 InputManager.Click(MouseButton.Left); 43 } 44 45 protected abstract Menu CreateMenu(); 46 47 /// <summary> 48 /// Helper class used to retrieve various internal properties/items from a <see cref="Menu"/>. 49 /// </summary> 50 protected class MenuStructure 51 { 52 private readonly Menu menu; 53 54 public MenuStructure(Menu menu) 55 { 56 this.menu = menu; 57 } 58 59 /// <summary> 60 /// Retrieves the <see cref="Menu.DrawableMenuItem"/>s of the <see cref="Menu"/> represented by this <see cref="MenuStructure"/>. 61 /// </summary> 62 public IReadOnlyList<Drawable> GetMenuItems() => menu.ChildrenOfType<FillFlowContainer<Menu.DrawableMenuItem>>().First().Children; 63 64 /// <summary> 65 /// Finds the <see cref="Menu.DrawableMenuItem"/> index in the <see cref="Menu"/> represented by this <see cref="MenuStructure"/> that 66 /// has <see cref="Menu.DrawableMenuItem.State"/> set to <see cref="MenuItemState.Selected"/>. 67 /// </summary> 68 public int GetSelectedIndex() 69 { 70 var items = GetMenuItems(); 71 72 for (int i = 0; i < items.Count; i++) 73 { 74 var state = (MenuItemState)(items[i]?.GetType().GetProperty("State")?.GetValue(items[i]) ?? MenuItemState.NotSelected); 75 if (state == MenuItemState.Selected) 76 return i; 77 } 78 79 return -1; 80 } 81 82 /// <summary> 83 /// Sets the <see cref="Menu.DrawableMenuItem"/> <see cref="Menu.DrawableMenuItem.State"/> at the specified index to a specified state. 84 /// </summary> 85 /// <param name="index">The index of the <see cref="Menu.DrawableMenuItem"/> to set the state of.</param> 86 /// <param name="state">The state to be set.</param> 87 public void SetSelectedState(int index, MenuItemState state) 88 { 89 var item = GetMenuItems()[index]; 90 item.GetType().GetProperty("State")?.SetValue(item, state); 91 } 92 93 /// <summary> 94 /// Retrieves the sub-<see cref="Menu"/> at an index-offset from the current <see cref="Menu"/>. 95 /// </summary> 96 /// <param name="index">The sub-<see cref="Menu"/> index. An index of 0 is the <see cref="Menu"/> represented by this <see cref="MenuStructure"/>.</param> 97 public Menu GetSubMenu(int index) 98 { 99 var currentMenu = menu; 100 101 for (int i = 0; i < index; i++) 102 { 103 if (currentMenu == null) 104 break; 105 106 var container = (CompositeDrawable)currentMenu.InternalChildren[1]; 107 108 // ReSharper disable once ArrangeRedundantParentheses 109 // Broken resharper inspection (https://youtrack.jetbrains.com/issue/RIDER-19843) 110 currentMenu = (container.InternalChildren.Count > 0 ? container.InternalChildren[0] : null) as Menu; 111 } 112 113 return currentMenu; 114 } 115 116 /// <summary> 117 /// Generates a new <see cref="MenuStructure"/> for the a sub-<see cref="Menu"/>. 118 /// </summary> 119 /// <param name="index">The sub-<see cref="Menu"/> index to generate the <see cref="MenuStructure"/> for. An index of 0 is the <see cref="Menu"/> represented by this <see cref="MenuStructure"/>.</param> 120 public MenuStructure GetSubStructure(int index) => new MenuStructure(GetSubMenu(index)); 121 } 122 } 123}