A game framework written with osu! in mind.

Merge branch 'master' into fix-proxydrawable-lifetime

authored by

Dean Herbert and committed by
GitHub
d96a4457 5ab3cbba

+108 -21
+76 -5
osu.Framework.Tests/Visual/UserInterface/TestSceneFocusedOverlayContainer.cs
··· 9 9 using osu.Framework.Testing; 10 10 using osuTK; 11 11 using osuTK.Graphics; 12 + using osuTK.Input; 12 13 13 14 namespace osu.Framework.Tests.Visual.UserInterface 14 15 { 15 16 public class TestSceneFocusedOverlayContainer : ManualInputManagerTestScene 16 17 { 17 - private TestFocusedOverlayContainer testContainer; 18 + private TestFocusedOverlayContainer overlayContainer; 19 + 20 + private ParentContainer parentContainer; 21 + 22 + [Test] 23 + public void TestClickDismiss() 24 + { 25 + AddStep("create container", () => { Child = overlayContainer = new TestFocusedOverlayContainer(); }); 26 + 27 + AddStep("show", () => overlayContainer.Show()); 28 + AddAssert("has focus", () => overlayContainer.HasFocus); 29 + 30 + AddStep("click inside", () => 31 + { 32 + InputManager.MoveMouseTo(overlayContainer.ScreenSpaceDrawQuad.Centre); 33 + InputManager.PressButton(MouseButton.Left); 34 + InputManager.ReleaseButton(MouseButton.Left); 35 + }); 36 + 37 + AddAssert("still has focus", () => overlayContainer.HasFocus); 38 + 39 + AddStep("click outside", () => 40 + { 41 + InputManager.MoveMouseTo(overlayContainer.ScreenSpaceDrawQuad.TopLeft - new Vector2(20)); 42 + InputManager.PressButton(MouseButton.Left); 43 + InputManager.ReleaseButton(MouseButton.Left); 44 + }); 45 + 46 + AddAssert("lost focus", () => !overlayContainer.HasFocus); 47 + AddAssert("not visible", () => overlayContainer.State.Value == Visibility.Hidden); 48 + } 18 49 19 50 [Test] 20 - public void TestInputBlocking() 51 + public void TestScrollBlocking() 21 52 { 22 - AddStep("create container", () => Child = testContainer = new TestFocusedOverlayContainer()); 53 + AddStep("create container", () => 54 + { 55 + Child = parentContainer = new ParentContainer 56 + { 57 + RelativeSizeAxes = Axes.Both, 58 + Children = new Drawable[] 59 + { 60 + overlayContainer = new TestFocusedOverlayContainer() 61 + } 62 + }; 63 + }); 64 + 65 + AddStep("show", () => overlayContainer.Show()); 66 + 67 + AddAssert("has focus", () => overlayContainer.HasFocus); 68 + 69 + int initialScrollCount = 0; 70 + 71 + AddStep("scroll inside", () => 72 + { 73 + initialScrollCount = parentContainer.ScrollReceived; 74 + InputManager.MoveMouseTo(overlayContainer.ScreenSpaceDrawQuad.Centre); 75 + InputManager.ScrollVerticalBy(1); 76 + }); 23 77 24 - AddStep("show", () => testContainer.Show()); 78 + AddAssert("scroll not received by parent", () => parentContainer.ScrollReceived == initialScrollCount); 25 79 26 - AddAssert("has focus", () => testContainer.HasFocus); 80 + AddStep("scroll outside", () => 81 + { 82 + InputManager.MoveMouseTo(overlayContainer.ScreenSpaceDrawQuad.TopLeft - new Vector2(20)); 83 + InputManager.ScrollVerticalBy(1); 84 + }); 85 + 86 + AddAssert("scroll received by parent", () => parentContainer.ScrollReceived == ++initialScrollCount); 27 87 } 28 88 29 89 private class TestFocusedOverlayContainer : FocusedOverlayContainer ··· 94 154 95 155 base.PopOut(); 96 156 } 157 + } 158 + } 159 + 160 + public class ParentContainer : Container 161 + { 162 + public int ScrollReceived; 163 + 164 + protected override bool OnScroll(ScrollEvent e) 165 + { 166 + ScrollReceived++; 167 + return base.OnScroll(e); 97 168 } 98 169 } 99 170 }
+1 -1
osu.Framework/Game.cs
··· 24 24 25 25 namespace osu.Framework 26 26 { 27 - public abstract class Game : Container, IKeyBindingHandler<FrameworkAction>, IHandleGlobalInput 27 + public abstract class Game : Container, IKeyBindingHandler<FrameworkAction>, IHandleGlobalKeyboardInput 28 28 { 29 29 public IWindow Window => Host?.Window; 30 30
+16 -8
osu.Framework/Graphics/Containers/OverlayContainer.cs
··· 3 3 4 4 using System.Collections.Generic; 5 5 using osu.Framework.Input; 6 - using osuTK; 6 + using osu.Framework.Input.Events; 7 7 8 8 namespace osu.Framework.Graphics.Containers 9 9 { ··· 28 28 { 29 29 // when blocking non-positional input behind us, we still want to make sure the global handlers receive events 30 30 // but we don't want other drawables behind us handling them. 31 - queue.RemoveAll(d => !(d is IHandleGlobalInput)); 31 + queue.RemoveAll(d => !(d is IHandleGlobalKeyboardInput)); 32 32 } 33 33 34 34 return base.BuildNonPositionalInputQueue(queue, allowBlocking); 35 35 } 36 36 37 - internal override bool BuildPositionalInputQueue(Vector2 screenSpacePos, List<Drawable> queue) 37 + protected override bool Handle(UIEvent e) 38 38 { 39 - if (PropagatePositionalInputSubTree && HandlePositionalInput && BlockPositionalInput && ReceivePositionalInputAt(screenSpacePos)) 39 + switch (e) 40 40 { 41 - // when blocking positional input behind us, we still want to make sure the global handlers receive events 42 - // but we don't want other drawables behind us handling them. 43 - queue.RemoveAll(d => !(d is IHandleGlobalInput)); 41 + case ScrollEvent _: 42 + if (BlockPositionalInput && base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) 43 + return true; 44 + 45 + break; 46 + 47 + case MouseEvent _: 48 + if (BlockPositionalInput) 49 + return true; 50 + 51 + break; 44 52 } 45 53 46 - return base.BuildPositionalInputQueue(screenSpacePos, queue); 54 + return base.Handle(e); 47 55 } 48 56 } 49 57 }
+1 -1
osu.Framework/Graphics/Cursor/TooltipContainer.cs
··· 17 17 /// <summary> 18 18 /// Displays Tooltips for all its children that inherit from the <see cref="IHasTooltip"/> or <see cref="IHasCustomTooltip"/> interfaces. Keep in mind that only children with <see cref="Drawable.HandlePositionalInput"/> set to true will be checked for their tooltips. 19 19 /// </summary> 20 - public class TooltipContainer : CursorEffectContainer<TooltipContainer, ITooltipContentProvider>, IHandleGlobalInput 20 + public class TooltipContainer : CursorEffectContainer<TooltipContainer, ITooltipContentProvider> 21 21 { 22 22 private readonly CursorContainer cursorContainer; 23 23 private readonly ITooltip defaultTooltip;
+7
osu.Framework/Graphics/UserInterface/TabControl.cs
··· 20 20 /// support for pinning items, causing them to be displayed before all other items at the 21 21 /// start of the list. 22 22 /// </summary> 23 + /// <remarks> 24 + /// If a multi-line (or vertical) tab control is required, <see cref="TabFillFlowContainer.AllowMultiline"/> must be set to true. 25 + /// Without this, <see cref="TabControl{T}"/> will automatically hide extra items. 26 + /// </remarks> 23 27 /// <typeparam name="T">The type of item to be represented by tabs.</typeparam> 24 28 public abstract class TabControl<T> : CompositeDrawable, IHasCurrentValue<T>, IKeyBindingHandler<PlatformAction> 25 29 { ··· 363 367 { 364 368 private bool allowMultiline; 365 369 370 + /// <summary> 371 + /// Whether tabs should be allowed to flow beyond a single line. If set to false, overflowing tabs will be automatically hidden. 372 + /// </summary> 366 373 public bool AllowMultiline 367 374 { 368 375 get => allowMultiline;
+3 -2
osu.Framework/Graphics/Visualisation/DrawVisualiser.cs
··· 18 18 namespace osu.Framework.Graphics.Visualisation 19 19 { 20 20 [Cached] 21 - internal class DrawVisualiser : OverlayContainer, IContainVisualisedDrawables 21 + // Implementing IRequireHighFrequencyMousePosition is necessary to gain the ability to block high frequency mouse position updates. 22 + internal class DrawVisualiser : OverlayContainer, IContainVisualisedDrawables, IRequireHighFrequencyMousePosition 22 23 { 23 24 public Vector2 ToolPosition 24 25 { ··· 110 111 inputManager = GetContainingInputManager(); 111 112 } 112 113 113 - protected override bool BlockPositionalInput => Searching; 114 + protected override bool Handle(UIEvent e) => Searching; 114 115 115 116 protected override void PopIn() 116 117 {
+2 -2
osu.Framework/Input/IHandleGlobalInput.cs osu.Framework/Input/IHandleGlobalKeyboardInput.cs
··· 4 4 namespace osu.Framework.Input 5 5 { 6 6 /// <summary> 7 - /// Denotes that this class handles input globally. 7 + /// Denotes that this class handles keyboard input globally. 8 8 /// </summary> 9 - public interface IHandleGlobalInput 9 + public interface IHandleGlobalKeyboardInput 10 10 { 11 11 } 12 12 }
+1 -1
osu.Framework/Input/PlatformActionContainer.cs
··· 14 14 /// can be created to handle events that should trigger specifically on a focused drawable. 15 15 /// Will send repeat events by default. 16 16 /// </summary> 17 - public class PlatformActionContainer : KeyBindingContainer<PlatformAction>, IHandleGlobalInput 17 + public class PlatformActionContainer : KeyBindingContainer<PlatformAction>, IHandleGlobalKeyboardInput 18 18 { 19 19 [Resolved] 20 20 private GameHost host { get; set; }
+1 -1
osu.Framework/Testing/TestBrowser.cs
··· 33 33 namespace osu.Framework.Testing 34 34 { 35 35 [Cached] 36 - public class TestBrowser : KeyBindingContainer<TestBrowserAction>, IKeyBindingHandler<TestBrowserAction>, IHandleGlobalInput 36 + public class TestBrowser : KeyBindingContainer<TestBrowserAction>, IKeyBindingHandler<TestBrowserAction>, IHandleGlobalKeyboardInput 37 37 { 38 38 public TestScene CurrentTest { get; private set; } 39 39