diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0cd7aae..4c025d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,9 @@ Fixes
- Fixed TextInput not working correctly when using surrogate pairs
### MLEM.Ui
+Additions
+- Added UiControls.NavType, which stores the most recently used type of ui navigation
+
Improvements
- Allow scrolling panels to contain other scrolling panels
- Allow dropdowns to have scrolling panels
diff --git a/MLEM.Ui/UiControls.cs b/MLEM.Ui/UiControls.cs
index ec69172..a8d35ad 100644
--- a/MLEM.Ui/UiControls.cs
+++ b/MLEM.Ui/UiControls.cs
@@ -103,7 +103,7 @@ namespace MLEM.Ui {
///
public bool HandleGamepad = true;
///
- /// If this value is true, the ui controls are in automatic navigation mode.
+ /// If this value is true, the ui controls are in automatic navigation mode. The state of automatic navigation is usually based on the current .
/// This means that the will be drawn around the .
///
public bool IsAutoNavMode {
@@ -115,12 +115,29 @@ namespace MLEM.Ui {
}
}
}
+ ///
+ /// The current of these ui controls, which represents the last type of interaction that was used to interact with the underlying .
+ ///
+ public NavigationType NavType {
+ get => this.navType;
+ set {
+ if (this.navType != value) {
+ var last = this.navType;
+ this.navType = value;
+ this.NavTypeChanged?.Invoke(last, value);
+ }
+ }
+ }
///
/// An event that is raised when is changed.
/// This can be used for custom actions like hiding the mouse cursor when automatic navigation is enabled.
///
public event Action AutoNavModeChanged;
+ ///
+ /// An event that is raised when is changed. It receives the previous navigation type, as well as the newly set navigation type.
+ ///
+ public event Action NavTypeChanged;
///
/// This value ist true if the was created by this ui controls instance, or if it was passed in.
@@ -134,6 +151,7 @@ namespace MLEM.Ui {
private readonly Dictionary selectedElements = new Dictionary();
private bool isAutoNavMode;
+ private NavigationType navType;
///
/// Creates a new instance of the ui controls.
@@ -167,6 +185,7 @@ namespace MLEM.Ui {
if (this.Input.IsPressedAvailable(MouseButton.Left)) {
this.IsAutoNavMode = false;
+ this.NavType = NavigationType.Mouse;
var selectedNow = mousedNow != null && mousedNow.CanBeSelected ? mousedNow : null;
this.SelectElement(this.ActiveRoot, selectedNow);
if (mousedNow != null && mousedNow.CanBePressed) {
@@ -175,6 +194,7 @@ namespace MLEM.Ui {
}
} else if (this.Input.IsPressedAvailable(MouseButton.Right)) {
this.IsAutoNavMode = false;
+ this.NavType = NavigationType.Mouse;
if (mousedNow != null && mousedNow.CanBePressed) {
this.PressElement(mousedNow, true);
this.Input.TryConsumePressed(MouseButton.Right);
@@ -187,12 +207,14 @@ namespace MLEM.Ui {
if (this.HandleKeyboard) {
if (this.KeyboardButtons.IsPressedAvailable(this.Input, this.GamepadIndex)) {
if (this.SelectedElement?.Root != null && this.SelectedElement.CanBePressed) {
+ this.NavType = NavigationType.Keyboard;
// primary or secondary action on element using space or enter
this.PressElement(this.SelectedElement, this.Input.IsModifierKeyDown(ModifierKey.Shift));
this.KeyboardButtons.TryConsumePressed(this.Input, this.GamepadIndex);
}
} else if (this.Input.IsPressedAvailable(Keys.Tab)) {
this.IsAutoNavMode = true;
+ this.NavType = NavigationType.Keyboard;
// tab or shift-tab to next or previous element
var backward = this.Input.IsModifierKeyDown(ModifierKey.Shift);
var next = this.GetTabNextElement(backward);
@@ -208,12 +230,14 @@ namespace MLEM.Ui {
if (this.HandleTouch) {
if (this.Input.GetViewportGesture(GestureType.Tap, out var tap)) {
this.IsAutoNavMode = false;
+ this.NavType = NavigationType.Touch;
var tapped = this.GetElementUnderPos(tap.Position);
this.SelectElement(this.ActiveRoot, tapped);
if (tapped != null && tapped.CanBePressed)
this.PressElement(tapped);
} else if (this.Input.GetViewportGesture(GestureType.Hold, out var hold)) {
this.IsAutoNavMode = false;
+ this.NavType = NavigationType.Touch;
var held = this.GetElementUnderPos(hold.Position);
this.SelectElement(this.ActiveRoot, held);
if (held != null && held.CanBePressed)
@@ -224,6 +248,7 @@ namespace MLEM.Ui {
foreach (var location in this.Input.ViewportTouchState) {
var element = this.GetElementUnderPos(location.Position);
if (location.State == TouchLocationState.Pressed) {
+ this.NavType = NavigationType.Touch;
// start touching an element if we just touched down on it
this.SetTouchedElement(element);
} else if (element != this.TouchedElement) {
@@ -239,11 +264,13 @@ namespace MLEM.Ui {
if (this.HandleGamepad) {
if (this.GamepadButtons.IsPressedAvailable(this.Input, this.GamepadIndex)) {
if (this.SelectedElement?.Root != null && this.SelectedElement.CanBePressed) {
+ this.NavType = NavigationType.Gamepad;
this.PressElement(this.SelectedElement);
this.GamepadButtons.TryConsumePressed(this.Input, this.GamepadIndex);
}
} else if (this.SecondaryGamepadButtons.IsPressedAvailable(this.Input, this.GamepadIndex)) {
if (this.SelectedElement?.Root != null && this.SelectedElement.CanBePressed) {
+ this.NavType = NavigationType.Gamepad;
this.PressElement(this.SelectedElement, true);
this.SecondaryGamepadButtons.TryConsumePressed(this.Input, this.GamepadIndex);
}
@@ -286,8 +313,9 @@ namespace MLEM.Ui {
///
/// The root element of the
/// The element to select, or null to deselect the selected element.
- /// Whether automatic navigation should be forced on
- public void SelectElement(RootElement root, Element element, bool? autoNav = null) {
+ /// Whether automatic navigation should be forced on. If this is , the automatic navigation state will stay the same.
+ /// An optional to set. If this is , the navigation type will stay the same.
+ public void SelectElement(RootElement root, Element element, bool? autoNav = null, NavigationType? navType = null) {
if (root == null)
return;
if (element != null && !element.CanBeSelected)
@@ -308,6 +336,8 @@ namespace MLEM.Ui {
if (autoNav != null)
this.IsAutoNavMode = autoNav.Value;
+ if (navType != null)
+ this.NavType = navType.Value;
}
///
@@ -444,6 +474,7 @@ namespace MLEM.Ui {
private bool HandleGamepadNextElement(Direction2 dir) {
this.IsAutoNavMode = true;
+ this.NavType = NavigationType.Gamepad;
var next = this.GetGamepadNextElement(dir);
if (this.SelectedElement != null)
next = this.SelectedElement.GetGamepadNextElement(dir, next);
@@ -454,5 +485,34 @@ namespace MLEM.Ui {
return false;
}
+ ///
+ /// An enumeration type that represents the possible types of navigation that a instance supports.
+ /// This is used by , which stores the most recently used navigation type for a .
+ ///
+ public enum NavigationType {
+
+ ///
+ /// An unknown navigation type, which usually means there has not been any ui navigation of any type yet.
+ ///
+ Unknown = 0,
+ ///
+ /// Mouse cursor and mouse button navigation.
+ ///
+ Mouse,
+ ///
+ /// Keyboard navigation.
+ ///
+ Keyboard,
+ ///
+ /// Touch and gesture navigation.
+ ///
+ Touch,
+ ///
+ /// Gamepad-style navigation, which may also include arrow key-based navigation based on current settings.
+ ///
+ Gamepad
+
+ }
+
}
}
diff --git a/MLEM.Ui/UiSystem.cs b/MLEM.Ui/UiSystem.cs
index a96c4f2..2e80d72 100644
--- a/MLEM.Ui/UiSystem.cs
+++ b/MLEM.Ui/UiSystem.cs
@@ -608,9 +608,10 @@ namespace MLEM.Ui {
/// Optionally, automatic navigation can be forced on, causing the to be drawn around the element.
///
/// The element to select, or null to deselect the selected element.
- /// Whether automatic navigation should be forced on
- public void SelectElement(Element element, bool? autoNav = null) {
- this.System.Controls.SelectElement(this, element, autoNav);
+ /// Whether automatic navigation should be forced on. If this is , the automatic navigation state will stay the same.
+ /// An optional to set. If this is , the navigation type will stay the same.
+ public void SelectElement(Element element, bool? autoNav = null, UiControls.NavigationType? navType = null) {
+ this.System.Controls.SelectElement(this, element, autoNav, navType);
}
///