From 356228d4d48bb597399ed1f0f0cec71237040517 Mon Sep 17 00:00:00 2001 From: Phantom Date: Fri, 15 May 2026 00:00:05 +0200 Subject: [PATCH 1/6] Initial Keyboard and Gamepad support on Slider Control --- Source/Engine/UI/GUI/Common/Slider.cs | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Source/Engine/UI/GUI/Common/Slider.cs b/Source/Engine/UI/GUI/Common/Slider.cs index 8c7b022fe..f1f33732e 100644 --- a/Source/Engine/UI/GUI/Common/Slider.cs +++ b/Source/Engine/UI/GUI/Common/Slider.cs @@ -1,6 +1,7 @@ // Copyright (c) Wojciech Figat. All rights reserved. using System; +using System.Collections.Generic; namespace FlaxEngine.GUI; @@ -408,6 +409,40 @@ public class Slider : ContainerControl base.OnLostFocus(); } + /// + public override Control OnNavigate(NavDirection direction, Float2 location, Control caller, List visited) + { + bool _isHorizontal = Direction is SliderDirection.HorizontalRight or SliderDirection.HorizontalLeft; + + float keyOrGamepadPosition = _isHorizontal ? location.X : location.Y; + + if (_thumbRect.Contains(ref location)) + { + // Start sliding + _isSliding = true; + SlidingStart?.Invoke(); + return this; + } + else + { + Value += (keyOrGamepadPosition < _thumbCenter ? -1 : 1) * 10; + } + + return base.OnNavigate(direction, location, caller, visited); + } + + /// + public override bool OnKeyDown(KeyboardKeys key) + { + if (key == KeyboardKeys.Escape) + { + Defocus(); + return true; + } + + return base.OnKeyDown(key); + } + /// public override bool OnMouseDown(Float2 location, MouseButton button) { @@ -443,6 +478,21 @@ public class Slider : ContainerControl return base.OnMouseDown(location, button); } + /// + public override bool OnTouchDown(Float2 location, int pointerId) + { + if (base.OnTouchDown(location, pointerId)) + return true; + + if (!new Rectangle(Float2.Zero, Size).Contains(ref location)) + { + Defocus(); + return true; + } + + return false; + } + /// public override void OnMouseMove(Float2 location) { From a1e03db3997cea035502f05389f7cc7bebab9a16 Mon Sep 17 00:00:00 2001 From: Phantom Date: Fri, 15 May 2026 00:24:05 +0200 Subject: [PATCH 2/6] -u Slider --- Source/Engine/UI/GUI/Common/Slider.cs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Source/Engine/UI/GUI/Common/Slider.cs b/Source/Engine/UI/GUI/Common/Slider.cs index f1f33732e..61c722dfe 100644 --- a/Source/Engine/UI/GUI/Common/Slider.cs +++ b/Source/Engine/UI/GUI/Common/Slider.cs @@ -524,6 +524,18 @@ public class Slider : ContainerControl } } + /// + public override void OnKeyUp(KeyboardKeys key) + { + if (key == KeyboardKeys.Escape && _isSliding) + { + EndSliding(); + return; + } + + base.OnKeyUp(key); + } + /// public override bool OnMouseUp(Float2 location, MouseButton button) { @@ -536,6 +548,18 @@ public class Slider : ContainerControl return base.OnMouseUp(location, button); } + /// + public override bool OnTouchUp(Float2 location, int pointerId) + { + if (base.OnTouchUp(location, pointerId) && _isSliding) + { + EndSliding(); + return true; + } + + return false; + } + /// public override void OnEndMouseCapture() { From 4c9f121e1ee147092cdc54d89a2e621f3a98eb4c Mon Sep 17 00:00:00 2001 From: Phantom Date: Fri, 15 May 2026 00:53:53 +0200 Subject: [PATCH 3/6] -u OnNavigate on Slider Control --- Source/Engine/UI/GUI/Common/Slider.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Source/Engine/UI/GUI/Common/Slider.cs b/Source/Engine/UI/GUI/Common/Slider.cs index 61c722dfe..9d8502c9c 100644 --- a/Source/Engine/UI/GUI/Common/Slider.cs +++ b/Source/Engine/UI/GUI/Common/Slider.cs @@ -413,20 +413,14 @@ public class Slider : ContainerControl public override Control OnNavigate(NavDirection direction, Float2 location, Control caller, List visited) { bool _isHorizontal = Direction is SliderDirection.HorizontalRight or SliderDirection.HorizontalLeft; + bool _isRevelant = _isHorizontal ? (direction is NavDirection.Left or NavDirection.Right) : (direction is NavDirection.Up or NavDirection.Down); - float keyOrGamepadPosition = _isHorizontal ? location.X : location.Y; - - if (_thumbRect.Contains(ref location)) + if (_isRevelant) { - // Start sliding - _isSliding = true; - SlidingStart?.Invoke(); + float _keyOrGamepadPosition = ((direction is NavDirection.Right or NavDirection.Down) != (Direction is SliderDirection.HorizontalLeft or SliderDirection.VerticalUp)) ? location.X : location.Y; + Value += (_keyOrGamepadPosition < _thumbCenter ? 1f : -1f) * 10f; return this; } - else - { - Value += (keyOrGamepadPosition < _thumbCenter ? -1 : 1) * 10; - } return base.OnNavigate(direction, location, caller, visited); } From 3de20d4a5c38202ac2a7bbde26cfd15b8c67bfdb Mon Sep 17 00:00:00 2001 From: Phantom Date: Fri, 15 May 2026 12:44:16 +0200 Subject: [PATCH 4/6] -u Slider --- Source/Engine/UI/GUI/Common/Slider.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Source/Engine/UI/GUI/Common/Slider.cs b/Source/Engine/UI/GUI/Common/Slider.cs index 9d8502c9c..3acbfec8a 100644 --- a/Source/Engine/UI/GUI/Common/Slider.cs +++ b/Source/Engine/UI/GUI/Common/Slider.cs @@ -413,15 +413,27 @@ public class Slider : ContainerControl public override Control OnNavigate(NavDirection direction, Float2 location, Control caller, List visited) { bool _isHorizontal = Direction is SliderDirection.HorizontalRight or SliderDirection.HorizontalLeft; - bool _isRevelant = _isHorizontal ? (direction is NavDirection.Left or NavDirection.Right) : (direction is NavDirection.Up or NavDirection.Down); + + float _keyOrGamepadPosition = _isHorizontal ? location.X : location.Y; - if (_isRevelant) + if (_thumbRect.Contains(ref location)) { - float _keyOrGamepadPosition = ((direction is NavDirection.Right or NavDirection.Down) != (Direction is SliderDirection.HorizontalLeft or SliderDirection.VerticalUp)) ? location.X : location.Y; - Value += (_keyOrGamepadPosition < _thumbCenter ? 1f : -1f) * 10f; + _isSliding = true; + SlidingStart?.Invoke(); return this; } + switch (Direction) + { + case SliderDirection.HorizontalRight or SliderDirection.VerticalDown: + Value += (_keyOrGamepadPosition < _thumbCenter ? -1 : 1) * 10; + break; + case SliderDirection.HorizontalLeft or SliderDirection.VerticalUp: + Value -= (_keyOrGamepadPosition < _thumbCenter ? -1 : 1) * 10; + break; + default: break; + } + return base.OnNavigate(direction, location, caller, visited); } From 0bb57793bb213d1e7787437f8b36f796db44c0bb Mon Sep 17 00:00:00 2001 From: Phantom Date: Sun, 17 May 2026 12:21:36 +0200 Subject: [PATCH 5/6] -u --- Source/Engine/UI/GUI/Common/Slider.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Source/Engine/UI/GUI/Common/Slider.cs b/Source/Engine/UI/GUI/Common/Slider.cs index 3acbfec8a..83a5c38e1 100644 --- a/Source/Engine/UI/GUI/Common/Slider.cs +++ b/Source/Engine/UI/GUI/Common/Slider.cs @@ -423,16 +423,8 @@ public class Slider : ContainerControl return this; } - switch (Direction) - { - case SliderDirection.HorizontalRight or SliderDirection.VerticalDown: - Value += (_keyOrGamepadPosition < _thumbCenter ? -1 : 1) * 10; - break; - case SliderDirection.HorizontalLeft or SliderDirection.VerticalUp: - Value -= (_keyOrGamepadPosition < _thumbCenter ? -1 : 1) * 10; - break; - default: break; - } + var SliderPosition = (Direction == SliderDirection.HorizontalRight || Direction == SliderDirection.VerticalDown) ? _keyOrGamepadPosition : - _keyOrGamepadPosition; + Value += (SliderPosition < _thumbCenter ? -1 : 1) * 10; return base.OnNavigate(direction, location, caller, visited); } From bae31b0d50c032f0e9e0da57dadbee345054502e Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 4 Aug 2026 19:05:08 +0200 Subject: [PATCH 6/6] Fix #4099 --- Source/Engine/UI/GUI/Common/Slider.cs | 124 ++++++++++++++++---------- 1 file changed, 79 insertions(+), 45 deletions(-) diff --git a/Source/Engine/UI/GUI/Common/Slider.cs b/Source/Engine/UI/GUI/Common/Slider.cs index 83a5c38e1..7bf70f253 100644 --- a/Source/Engine/UI/GUI/Common/Slider.cs +++ b/Source/Engine/UI/GUI/Common/Slider.cs @@ -102,6 +102,7 @@ public class Slider : ContainerControl private Float2 _thumbSize = new Float2(16, 16); private bool _isSliding; private bool _mouseOverThumb; + private const float _step = 10; /// /// Gets or sets the value (normalized to range 0-100). @@ -341,6 +342,13 @@ public class Slider : ContainerControl } } + private void StartSliding() + { + _isSliding = true; + StartMouseCapture(); + SlidingStart?.Invoke(); + } + private void EndSliding() { _isSliding = false; @@ -412,20 +420,19 @@ public class Slider : ContainerControl /// public override Control OnNavigate(NavDirection direction, Float2 location, Control caller, List visited) { - bool _isHorizontal = Direction is SliderDirection.HorizontalRight or SliderDirection.HorizontalLeft; - - float _keyOrGamepadPosition = _isHorizontal ? location.X : location.Y; + // Auto-focus self when navigation comes in + if (!IsNavFocused) + return this; - if (_thumbRect.Contains(ref location)) + // Control slider via navigation actions + if (IsNavFocused && _isSliding) { - _isSliding = true; - SlidingStart?.Invoke(); + var isNavUp = direction == NavDirection.Right || direction == NavDirection.Up; + var isDirUp = _direction == SliderDirection.HorizontalRight || _direction == SliderDirection.VerticalUp; + Value += (isNavUp == isDirUp ? 1 : -1) * _step; return this; } - var SliderPosition = (Direction == SliderDirection.HorizontalRight || Direction == SliderDirection.VerticalDown) ? _keyOrGamepadPosition : - _keyOrGamepadPosition; - Value += (SliderPosition < _thumbCenter ? -1 : 1) * 10; - return base.OnNavigate(direction, location, caller, visited); } @@ -441,39 +448,44 @@ public class Slider : ContainerControl return base.OnKeyDown(key); } + private void OnClick(Float2 location) + { + Focus(); + float mousePosition = Direction is SliderDirection.HorizontalRight or SliderDirection.HorizontalLeft ? location.X : location.Y; + + if (_thumbRect.Contains(ref location)) + { + StartSliding(); + } + else + { + // Click change + switch (Direction) + { + case SliderDirection.HorizontalRight or SliderDirection.VerticalDown: + Value += (mousePosition < _thumbCenter ? -1 : 1) * _step; + break; + case SliderDirection.HorizontalLeft or SliderDirection.VerticalUp: + Value -= (mousePosition < _thumbCenter ? -1 : 1) * _step; + break; + default: break; + } + } + } + /// public override bool OnMouseDown(Float2 location, MouseButton button) { + if (base.OnMouseDown(location, button)) + return true; + if (button == MouseButton.Left) { - Focus(); - float mousePosition = Direction is SliderDirection.HorizontalRight or SliderDirection.HorizontalLeft ? location.X : location.Y; - - if (_thumbRect.Contains(ref location)) - { - // Start sliding - _isSliding = true; - StartMouseCapture(); - SlidingStart?.Invoke(); - return true; - } - else - { - // Click change - switch (Direction) - { - case SliderDirection.HorizontalRight or SliderDirection.VerticalDown: - Value += (mousePosition < _thumbCenter ? -1 : 1) * 10; - break; - case SliderDirection.HorizontalLeft or SliderDirection.VerticalUp: - Value -= (mousePosition < _thumbCenter ? -1 : 1) * 10; - break; - default: break; - } - } + OnClick(location); + return true; } - return base.OnMouseDown(location, button); + return false; } /// @@ -482,13 +494,8 @@ public class Slider : ContainerControl if (base.OnTouchDown(location, pointerId)) return true; - if (!new Rectangle(Float2.Zero, Size).Contains(ref location)) - { - Defocus(); - return true; - } - - return false; + OnClick(location); + return true; } /// @@ -549,13 +556,40 @@ public class Slider : ContainerControl /// public override bool OnTouchUp(Float2 location, int pointerId) { - if (base.OnTouchUp(location, pointerId) && _isSliding) + if (base.OnTouchUp(location, pointerId)) + return true; + + if (_isSliding) { EndSliding(); - return true; } + return true; + } - return false; + /// + public override void OnTouchMove(Float2 location, int pointerId) + { + base.OnTouchMove(location, pointerId); + + if (_isSliding) + { + OnMouseMove(location); + } + } + + /// + public override void OnSubmit() + { + base.OnSubmit(); + + if (_isSliding) + { + EndSliding(); + } + else + { + StartSliding(); + } } ///