From 633c5b009708d4b33bc9123f21a207e20459155d Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sat, 31 Aug 2019 19:32:22 +0200 Subject: [PATCH] added touch compatibility to the scroll bar, which makes touch input finished! --- MLEM.Ui/Elements/ScrollBar.cs | 65 ++++++++++++++++++++++++++++------- MLEM.Ui/MLEM.Ui.csproj | 2 +- MLEM.Ui/UiControls.cs | 2 +- MLEM/Input/InputHandler.cs | 10 +++--- README.md | 2 ++ Test/GameImpl.cs | 9 +++-- 6 files changed, 69 insertions(+), 21 deletions(-) diff --git a/MLEM.Ui/Elements/ScrollBar.cs b/MLEM.Ui/Elements/ScrollBar.cs index e34eea6..2fe5347 100644 --- a/MLEM.Ui/Elements/ScrollBar.cs +++ b/MLEM.Ui/Elements/ScrollBar.cs @@ -2,6 +2,7 @@ using System; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input.Touch; using MLEM.Extensions; using MLEM.Input; using MLEM.Textures; @@ -38,6 +39,12 @@ namespace MLEM.Ui.Elements { public float StepPerScroll = 1; public ValueChanged OnValueChanged; private bool isMouseHeld; + private bool isDragging; + private bool isTouchHeld; + + static ScrollBar() { + InputHandler.EnableGestures(GestureType.HorizontalDrag, GestureType.VerticalDrag); + } public ScrollBar(Anchor anchor, Vector2 size, int scrollerSize, float maxValue, bool horizontal = false) : base(anchor, size) { this.maxValue = maxValue; @@ -48,29 +55,63 @@ namespace MLEM.Ui.Elements { public override void Update(GameTime time) { base.Update(time); + + // MOUSE INPUT var moused = this.Controls.MousedElement; if (moused == this && this.Controls.Input.IsMouseButtonDown(MouseButton.Left)) { this.isMouseHeld = true; } else if (this.isMouseHeld && !this.Controls.Input.IsMouseButtonDown(MouseButton.Left)) { this.isMouseHeld = false; } - - if (this.isMouseHeld) { - var mouse = this.Input.MousePosition; - if (this.Horizontal) { - var internalX = mouse.X - this.Area.X - this.ScrollerSize.X * this.Scale / 2; - this.CurrentValue = internalX / (this.Area.Width - this.ScrollerSize.X * this.Scale) * this.MaxValue; - } else { - var internalY = mouse.Y - this.Area.Y - this.ScrollerSize.Y * this.Scale / 2; - this.CurrentValue = internalY / (this.Area.Height - this.ScrollerSize.Y * this.Scale) * this.MaxValue; - } - } - + if (this.isMouseHeld) + this.ScrollToPos(this.Input.MousePosition); if (!this.Horizontal && moused != null && (moused == this.Parent || moused.GetParentTree().Contains(this.Parent))) { var scroll = this.Input.LastScrollWheel - this.Input.ScrollWheel; if (scroll != 0) this.CurrentValue += this.StepPerScroll * Math.Sign(scroll); } + + // TOUCH INPUT + if (!this.Horizontal) { + // are we dragging on top of the panel? + if (this.Input.GetGesture(GestureType.VerticalDrag, out var drag)) { + // if the element under the drag's start position is on top of the panel, start dragging + var touched = this.Parent.GetElementUnderPos(drag.Position.ToPoint()); + if (touched != null && touched != this) + this.isDragging = true; + + // if we're dragging at all, then move the scroller + if (this.isDragging) + this.CurrentValue -= drag.Delta.Y / this.Scale; + } else { + this.isDragging = false; + } + } + if (this.Input.TouchState.Count <= 0) { + // if no touch has occured this tick, then reset the variable + this.isTouchHeld = false; + } else { + foreach (var loc in this.Input.TouchState) { + // if we just started touching and are on top of the scroller, then we should start scrolling + if (this.DisplayArea.Contains(loc.Position) && !loc.TryGetPreviousLocation(out _)) { + this.isTouchHeld = true; + break; + } + // scroll no matter if we're on the scroller right now + if (this.isTouchHeld) + this.ScrollToPos(loc.Position.ToPoint()); + } + } + } + + private void ScrollToPos(Point position) { + if (this.Horizontal) { + var internalX = position.X - this.Area.X - this.ScrollerSize.X * this.Scale / 2; + this.CurrentValue = internalX / (this.Area.Width - this.ScrollerSize.X * this.Scale) * this.MaxValue; + } else { + var internalY = position.Y - this.Area.Y - this.ScrollerSize.Y * this.Scale / 2; + this.CurrentValue = internalY / (this.Area.Height - this.ScrollerSize.Y * this.Scale) * this.MaxValue; + } } public override void Draw(GameTime time, SpriteBatch batch, float alpha, Point offset) { diff --git a/MLEM.Ui/MLEM.Ui.csproj b/MLEM.Ui/MLEM.Ui.csproj index bd234d1..88f87be 100644 --- a/MLEM.Ui/MLEM.Ui.csproj +++ b/MLEM.Ui/MLEM.Ui.csproj @@ -5,7 +5,7 @@ Ellpeck - A Ui system that is part of (M)LEM (L)ibrary by (E)llpeck for (M)onoGame, featuring automatic anchoring, sizing and several ready-to-use element types + A mouse, keyboard and touch ready Ui system that features automatic anchoring, sizing and several ready-to-use element types. Part of (M)LEM (L)ibrary by (E)llpeck for (M)onoGame monogame ellpeck mlem ui user interface graphical gui system https://github.com/Ellpeck/MLEM https://github.com/Ellpeck/MLEM diff --git a/MLEM.Ui/UiControls.cs b/MLEM.Ui/UiControls.cs index cd1bcce..25eb2a7 100644 --- a/MLEM.Ui/UiControls.cs +++ b/MLEM.Ui/UiControls.cs @@ -23,7 +23,7 @@ namespace MLEM.Ui { this.isInputOurs = inputHandler == null; // enable all required gestures - this.Input.EnableGestures(GestureType.Tap, GestureType.Hold); + InputHandler.EnableGestures(GestureType.Tap, GestureType.Hold); } public void Update() { diff --git a/MLEM/Input/InputHandler.cs b/MLEM/Input/InputHandler.cs index 4a64811..d3521dd 100644 --- a/MLEM/Input/InputHandler.cs +++ b/MLEM/Input/InputHandler.cs @@ -176,11 +176,6 @@ namespace MLEM.Input { return this.WasGamepadButtonUp(button, index) && this.IsGamepadButtonDown(button, index); } - public void EnableGestures(params GestureType[] gestures) { - foreach (var gesture in gestures) - TouchPanel.EnabledGestures |= gesture; - } - public bool GetGesture(GestureType type, out GestureSample sample) { foreach (var gesture in this.Gestures) { if (gesture.GestureType == type) { @@ -221,6 +216,11 @@ namespace MLEM.Input { throw new ArgumentException(nameof(control)); } + public static void EnableGestures(params GestureType[] gestures) { + foreach (var gesture in gestures) + TouchPanel.EnabledGestures |= gesture; + } + private static ButtonState GetState(MouseState state, MouseButton button) { switch (button) { case MouseButton.Left: diff --git a/README.md b/README.md index ce26f4b..8230615 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # MLEM (M)LEM (L)ibrary by (E)llpeck for (M)onoGame + +Get it at https://www.nuget.org/packages?q=mlem \ No newline at end of file diff --git a/Test/GameImpl.cs b/Test/GameImpl.cs index cc71da9..738ac56 100644 --- a/Test/GameImpl.cs +++ b/Test/GameImpl.cs @@ -27,10 +27,10 @@ namespace AndroidTests { RadioCheckmark = new TextureRegion(tex, 32, 0, 8, 8) }; this.UiSystem.Style = style; - this.UiSystem.GlobalScale = 10; + this.UiSystem.GlobalScale = 15; this.UiSystem.AutoScaleWithScreen = true; - var panel = new Panel(Anchor.Center, new Vector2(100, 0), Vector2.Zero, true); + var panel = new Panel(Anchor.Center, new Vector2(100, 50), Vector2.Zero, false, true, new Point(5, 10)); this.UiSystem.Add("Panel", panel); panel.AddChild(new Paragraph(Anchor.AutoLeft, 1, "I am Android")); @@ -41,6 +41,11 @@ namespace AndroidTests { }); panel.AddChild(new TextField(Anchor.AutoLeft, new Vector2(1, 10)) {PlaceholderText = "Tap to type"}); + + panel.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Here is some text that makes it so that the panel is actually long enough for me to try out the scroll behavior.")); + panel.AddChild(new Slider(Anchor.AutoLeft, new Vector2(1, 10), 5, 100)); + + panel.AddChild(new Paragraph(Anchor.AutoLeft, 1, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sapien elit, congue sit amet condimentum in, hendrerit iaculis leo. Phasellus mollis turpis felis, ac finibus elit tincidunt quis. Vestibulum maximus, velit non consequat porttitor, quam diam consequat eros, in cursus nunc mi id dui. Vivamus semper neque at feugiat semper. Nunc ultrices egestas placerat. Proin lectus felis, rutrum quis porta vel, eleifend eget eros. Morbi porttitor massa finibus felis vestibulum, quis faucibus dui volutpat. Nam enim mi, euismod a pharetra vel, suscipit eu tortor. Integer vehicula ligula at consectetur dictum. Etiam fringilla volutpat est, id egestas nunc. Maecenas turpis felis, eleifend non felis a, fringilla lobortis nibh. Morbi rhoncus vestibulum dignissim. Ut posuere nulla ipsum, non condimentum dui posuere sit amet.")); } protected override void DoDraw(GameTime gameTime) {