1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-12-25 01:39:23 +01:00

Improved gamepad navigation by employing angles between elements

This commit is contained in:
Ell 2022-03-10 14:25:41 +01:00
parent cb8fed87e5
commit 45955bb5e8
2 changed files with 15 additions and 30 deletions

View file

@ -46,6 +46,7 @@ Improvements
- Allow setting a default color for clickable links in UiStyle
- Allow ElementHelper's KeybindButton to query a combination at a given index
- Automatically select the first element when a dropdown is opened in auto nav mode
- Improved gamepad navigation by employing angles between elements
Fixes
- Fixed paragraph links having incorrect hover locations when using special text alignments

View file

@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using MLEM.Extensions;
using MLEM.Input;
using MLEM.Misc;
using MLEM.Ui.Elements;
@ -355,11 +357,11 @@ namespace MLEM.Ui {
}
/// <summary>
/// Returns the next element that should be selected during gamepad navigation, based on the <see cref="RectangleF"/> that we're looking for elements in.
/// Returns the next element that should be selected during gamepad navigation, based on the <see cref="Direction2"/> that we're looking for elements in.
/// </summary>
/// <param name="searchArea">The area that we're looking for next elements in</param>
/// <param name="direction">The direction that we're looking for next elements in</param>
/// <returns>The first element found in that area</returns>
protected virtual Element GetGamepadNextElement(RectangleF searchArea) {
protected virtual Element GetGamepadNextElement(Direction2 direction) {
if (this.ActiveRoot == null)
return null;
var children = this.ActiveRoot.Element.GetChildren(c => !c.IsHidden, true, true).Append(this.ActiveRoot.Element);
@ -367,14 +369,17 @@ namespace MLEM.Ui {
return children.FirstOrDefault(c => c.CanBeSelected);
} else {
Element closest = null;
float closestDist = 0;
float closestDistSq = 0;
foreach (var child in children) {
if (!child.CanBeSelected || child == this.SelectedElement || !searchArea.Intersects(child.Area))
if (!child.CanBeSelected || child == this.SelectedElement)
continue;
var dist = Vector2.Distance(child.Area.Center, this.SelectedElement.Area.Center);
if (closest == null || dist < closestDist) {
var distVec = child.Area.Center - this.SelectedElement.Area.Center;
if (Math.Abs(direction.Angle() - Math.Atan2(distVec.Y, distVec.X)) >= MathHelper.PiOver2 - Element.Epsilon)
continue;
var distSq = distVec.LengthSquared();
if (closest == null || distSq < closestDistSq) {
closest = child;
closestDist = dist;
closestDistSq = distSq;
}
}
return closest;
@ -383,28 +388,7 @@ namespace MLEM.Ui {
private void HandleGamepadNextElement(Direction2 dir) {
this.IsAutoNavMode = true;
RectangleF searchArea = default;
if (this.SelectedElement?.Root != null) {
searchArea = this.SelectedElement.Area;
var (_, _, width, height) = this.System.Viewport;
switch (dir) {
case Direction2.Down:
searchArea.Height += height;
break;
case Direction2.Left:
searchArea.X -= width;
searchArea.Width += width;
break;
case Direction2.Right:
searchArea.Width += width;
break;
case Direction2.Up:
searchArea.Y -= height;
searchArea.Height += height;
break;
}
}
var next = this.GetGamepadNextElement(searchArea);
var next = this.GetGamepadNextElement(dir);
if (this.SelectedElement != null)
next = this.SelectedElement.GetGamepadNextElement(dir, next);
if (next != null)