Last active
June 22, 2022 15:11
-
-
Save Aggror/4ba0632bd934103c6dcdb077a84376ef to your computer and use it in GitHub Desktop.
Stride controller UI navigation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Stride.Core; | |
using Stride.Core.Mathematics; | |
using Stride.Engine; | |
using Stride.Input; | |
using Stride.UI; | |
using Stride.UI.Controls; | |
using Stride.UI.Events; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using static IntermediateTutorials_01_UI_Basics.ControllerUIMapping; | |
namespace IntermediateTutorials_01_UI_Basics | |
{ | |
public class ControllerDemo : SyncScript | |
{ | |
public List<ControllerUIMapping> controllerUiElements = new List<ControllerUIMapping>(); | |
private Dictionary<ButtonAction, Action> actions = new Dictionary<ButtonAction, Action>(); | |
private ControllerUIMapping currentControllerMap = null; | |
private UIPage page; | |
private TextBlock sampleText; | |
private float coolDownTimer; | |
private float coolDownPeriod = 0.2f; | |
public override void Start() | |
{ | |
coolDownTimer = coolDownPeriod; | |
page = Entity.Get<UIComponent>().Page; | |
MapControllerToUIElements(); | |
sampleText = page.RootElement.FindVisualChildOfType<TextBlock>("MyText"); | |
//Setup mouse click events | |
page.RootElement.FindVisualChildOfType<Button>("Button1").Click += Button1_Click; | |
page.RootElement.FindVisualChildOfType<Button>("Button2").Click += Button2_Click; | |
page.RootElement.FindVisualChildOfType<Button>("Button3").Click += Button3_Click; | |
page.RootElement.FindVisualChildOfType<Button>("Button4").Click += Button4_Click; | |
page.RootElement.FindVisualChildOfType<Button>("Button5").Click += Button5_Click; | |
//setup gamepad press events | |
actions.Add(ButtonAction.PressedButtonA, () => Button1_Click(null, null)); | |
actions.Add(ButtonAction.PressedButtonB, () => Button2_Click(null, null)); | |
actions.Add(ButtonAction.PressedButtonC, () => Button3_Click(null, null)); | |
actions.Add(ButtonAction.PressedButtonD, () => Button4_Click(null, null)); | |
actions.Add(ButtonAction.PressedButtonE, () => Button5_Click(null, null)); | |
} | |
private void Button1_Click(object sender, RoutedEventArgs e) => sampleText.Text = "Pressed button 1"; | |
private void Button2_Click(object sender, RoutedEventArgs e) => sampleText.Text = "Pressed button 2"; | |
private void Button3_Click(object sender, RoutedEventArgs e) => sampleText.Text = "Pressed button 3"; | |
private void Button4_Click(object sender, RoutedEventArgs e) => sampleText.Text = "Pressed button 4"; | |
private void Button5_Click(object sender, RoutedEventArgs e) => sampleText.Text = "Pressed button 5"; | |
public override void Update() | |
{ | |
UpdageGamepadUI(); | |
} | |
private void MapControllerToUIElements() | |
{ | |
foreach (var ui in controllerUiElements) | |
{ | |
ui.UiElement = page.RootElement.FindName(ui.UiKey); | |
} | |
} | |
private void UpdageGamepadUI() | |
{ | |
if (Input.HasMouse) | |
{ | |
if (Input.Mouse.Delta.X != 0 && Input.Mouse.Delta.Y != 0) | |
{ | |
Game.IsMouseVisible = true; | |
} | |
} | |
if (Input.HasGamePad) | |
{ | |
var thumbThreshold = 0.9f; | |
var gamepad = Input.GamePads[0]; | |
var speed = gamepad.State.LeftThumb; | |
var deltaTime = (float)Game.UpdateTime.Elapsed.TotalSeconds; | |
coolDownTimer -= deltaTime; | |
if (coolDownTimer <= 0 && (speed.Y < -thumbThreshold || speed.Y > thumbThreshold || speed.X < -thumbThreshold || speed.X > thumbThreshold)) | |
{ | |
Game.IsMouseVisible = false; | |
var nextUiKey = ""; | |
if (currentControllerMap == null) | |
{ | |
currentControllerMap = controllerUiElements[0]; | |
nextUiKey = currentControllerMap.UiKey; | |
} | |
else | |
{ | |
if (speed.Y < -thumbThreshold || speed.Y > thumbThreshold) | |
nextUiKey = speed.Y < -thumbThreshold ? currentControllerMap.Down : currentControllerMap.Up; | |
if(speed.X < -thumbThreshold || speed.X > thumbThreshold) | |
nextUiKey = speed.X < -thumbThreshold ? currentControllerMap.Left : currentControllerMap.Right; | |
} | |
var nextUiElement = page.RootElement.FindName(nextUiKey); | |
if (nextUiKey != null && nextUiElement != null) | |
{ | |
var buffer = GraphicsDevice.Presenter.BackBuffer; | |
currentControllerMap = controllerUiElements.Where(w => w.UiKey == nextUiElement.Name).Single(); | |
var position = GetPosition(currentControllerMap.UiElement, new Vector2()); | |
Input.MousePosition = new Vector2(position.X / buffer.Width, position.Y / buffer.Height); | |
} | |
coolDownTimer = coolDownPeriod; | |
} | |
if (gamepad.IsButtonPressed(GamePadButton.A)) | |
{ | |
if (actions.ContainsKey(currentControllerMap.Action)) | |
{ | |
var action = actions.GetValueOrDefault(currentControllerMap.Action); | |
action.Invoke(); | |
} | |
} | |
} | |
} | |
private Vector2 GetPosition(UIElement uiElement, Vector2 position) | |
{ | |
if (uiElement.Parent == null) | |
{ | |
position += uiElement.RenderOffsets.XY(); | |
} | |
else | |
{ | |
position.X += uiElement.Margin.Left > 0 ? uiElement.Margin.Left : uiElement.Parent.Width - uiElement.Margin.Right; | |
position.Y += uiElement.Margin.Top > 0 ? uiElement.Margin.Top : (uiElement.Parent.Height - uiElement.Margin.Bottom) - (uiElement.Height/2); | |
position = GetPosition(uiElement.Parent, position); | |
} | |
return position; | |
} | |
} | |
[DataContract] | |
public class ControllerUIMapping | |
{ | |
[DataMember(order: 10)] | |
public string UiKey; | |
[DataMember(order: 20)] | |
public string Up; | |
[DataMember(order: 30)] | |
public string Down; | |
[DataMember(order: 40)] | |
public string Left; | |
[DataMember(order: 50)] | |
public string Right; | |
[DataMember(order: 60)] | |
public ButtonAction Action; | |
[DataMemberIgnore] | |
public UIElement UiElement { get; set; } | |
public enum ButtonAction | |
{ | |
PressedButtonA, | |
PressedButtonB, | |
PressedButtonC, | |
PressedButtonD, | |
PressedButtonE, | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment