Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added IsPressed, IsDown, & IsReleased for virtual buttons to Inputmanager #2258

Merged
merged 3 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 115 additions & 29 deletions sources/engine/Stride.Input/InputManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,25 @@ namespace Stride.Input
/// </summary>
public partial class InputManager : ComponentBase
{
/// <summary>
/// The state of each Virtualbutton in a config.
/// </summary>
private class VirtualButtonsState
{
public Dictionary<object, float> Values { get; } = new Dictionary<object, float>();
public Dictionary<object, bool> Pressed { get; } = new Dictionary<object, bool>();
public Dictionary<object, bool> Down { get; } = new Dictionary<object, bool>();
public Dictionary<object, bool> Released { get; } = new Dictionary<object, bool>();

public void Clear()
{
Values.Clear();
Pressed.Clear();
Down.Clear();
Released.Clear();
}
}

//this is used in some mobile platform for accelerometer stuff
internal const float G = 9.81f;
internal const float DesiredSensorUpdateRate = 60;
Expand All @@ -35,7 +54,7 @@ public partial class InputManager : ComponentBase
private readonly List<GestureEvent> currentGestureEvents = new List<GestureEvent>();

private readonly Dictionary<GestureConfig, GestureRecognizer> gestureConfigToRecognizer = new Dictionary<GestureConfig, GestureRecognizer>();
private readonly List<Dictionary<object, float>> virtualButtonValues = new List<Dictionary<object, float>>();
private readonly List<VirtualButtonsState> virtualButtonStates = new List<VirtualButtonsState>();

// Mapping of device guid to device
private readonly Dictionary<Guid, IInputDevice> devicesById = new Dictionary<Guid, IInputDevice>();
Expand Down Expand Up @@ -433,7 +452,7 @@ public void Update(GameTime gameTime)
}

// Update virtual buttons
UpdateVirtualButtonValues();
UpdateVirtualButtonStates();

// Update gestures
UpdateGestureEvents(gameTime.Elapsed);
Expand Down Expand Up @@ -462,25 +481,87 @@ public void RemoveListener(IInputEventListener listener)
pair.Value.Listeners.Remove(listener);
}
}

/// <summary>
/// Gets a binding value for the specified name and the specified config extract from the current <see cref="VirtualButtonConfigSet"/>.
/// </summary>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/></param>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/>.</param>
/// <param name="bindingName">Name of the binding.</param>
/// <returns>The value of the binding.</returns>
[Obsolete("This method is obsolete. Call GetVirtualButtonValue instead.")]
public virtual float GetVirtualButton(int configIndex, object bindingName)
{
if (VirtualButtonConfigSet == null || configIndex < 0 || configIndex >= virtualButtonValues.Count)
return GetVirtualButtonValue(configIndex, bindingName);
}

/// <summary>
/// Gets a binding value for the specified name and the specified config extract from the current <see cref="VirtualButtonConfigSet"/>.
/// </summary>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/>.</param>
/// <param name="bindingName">Name of the binding.</param>
/// <returns>The value of the binding.</returns>
public virtual float GetVirtualButtonValue(int configIndex, object bindingName)
{
if (VirtualButtonConfigSet == null || configIndex < 0 || configIndex >= virtualButtonStates.Count)
{
return 0.0f;
}

float value;
virtualButtonValues[configIndex].TryGetValue(bindingName, out value);

virtualButtonStates[configIndex].Values.TryGetValue(bindingName, out float value);
return value;
}

/// <summary>
/// Determines whether the specified binding in the specified config in the current <see cref="VirtualButtonConfigSet"/> was pressed since the previous Update.
/// </summary>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/>.</param>
/// <param name="bindingName">Name of the binding.</param>
/// <returns><c>true</c> if the binding was pressed; otherwise, <c>false</c>.</returns>
public virtual bool IsVirtualButtonPressed(int configIndex, object bindingName)
{
if (VirtualButtonConfigSet == null || configIndex < 0 || configIndex >= virtualButtonStates.Count)
{
return false;
}

virtualButtonStates[configIndex].Pressed.TryGetValue(bindingName, out bool isPressed);
return isPressed;
}

/// <summary>
/// Determines whether the specified binding in the specified config in the current <see cref="VirtualButtonConfigSet"/> is currently pressed down.
/// </summary>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/>.</param>
/// <param name="bindingName">Name of the binding.</param>
/// <returns><c>true</c> if the binding is currently pressed down; otherwise, <c>false</c>.</returns>
public virtual bool IsVirtualButtonDown(int configIndex, object bindingName)
{
if (VirtualButtonConfigSet == null || configIndex < 0 || configIndex >= virtualButtonStates.Count)
{
return false;
}

virtualButtonStates[configIndex].Down.TryGetValue(bindingName, out bool isDown);
return isDown;
}

/// <summary>
/// Determines whether the specified binding in the specified config in the current <see cref="VirtualButtonConfigSet"/> was released since the previous Update.
/// </summary>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/>.</param>
/// <param name="bindingName">Name of the binding.</param>
/// <returns><c>true</c> if the binding was released; otherwise, <c>false</c>.</returns>
public virtual bool IsVirtualButtonReleased(int configIndex, object bindingName)
{
if (VirtualButtonConfigSet == null || configIndex < 0 || configIndex >= virtualButtonStates.Count)
{
return false;
}

virtualButtonStates[configIndex].Released.TryGetValue(bindingName, out bool isReleased);
return isReleased;
}

/// <summary>
/// Pause all input sources.
/// </summary>
Expand Down Expand Up @@ -901,33 +982,38 @@ private void UpdateGestureEvents(TimeSpan elapsedGameTime)
}
}

private void UpdateVirtualButtonValues()
private void UpdateVirtualButtonStates()
{
if (VirtualButtonConfigSet != null)
if (VirtualButtonConfigSet == null)
{
for (int i = 0; i < VirtualButtonConfigSet.Count; i++)
{
var config = VirtualButtonConfigSet[i];
return;
}

Dictionary<object, float> mapNameToValue;
if (i == virtualButtonValues.Count)
{
mapNameToValue = new Dictionary<object, float>();
virtualButtonValues.Add(mapNameToValue);
}
else
{
mapNameToValue = virtualButtonValues[i];
}
for (int i = 0; i < VirtualButtonConfigSet.Count; i++)
{
var config = VirtualButtonConfigSet[i];

mapNameToValue.Clear();
VirtualButtonsState configState;
if (i == virtualButtonStates.Count)
{
configState = new VirtualButtonsState();
virtualButtonStates.Add(configState);
}
else
{
configState = virtualButtonStates[i];
}

configState.Clear();

if (config != null)
if (config != null)
{
foreach (object name in config.BindingNames)
{
foreach (var name in config.BindingNames)
{
mapNameToValue[name] = config.GetValue(this, name);
}
configState.Values[name] = config.GetValue(this, name);
configState.Pressed[name] = config.IsPressed(this, name);
configState.Down[name] = config.IsDown(this, name);
configState.Released[name] = config.IsReleased(this, name);
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions sources/engine/Stride.Input/VirtualButton/VirtualButtonBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,33 @@ public virtual float GetValue(InputManager manager)
return Button != null ? Button.GetValue(manager) : 0.0f;
}

/// <summary>
/// Gets the pressed state for a particular binding.
/// </summary>
/// <returns><c>true</c> when pressed since the last frame; otherwise, <c>false</c>.</returns>
public virtual bool IsPressed(InputManager manager)
{
return Button != null ? Button.IsPressed(manager) : false;
}

/// <summary>
/// Gets the held down state for a particular binding.
/// </summary>
/// <returns><c>true</c> when currently held down; otherwise, <c>false</c>.</returns>
public virtual bool IsDown(InputManager manager)
{
return Button != null ? Button.IsDown(manager) : false;
}

/// <summary>
/// Gets the pressed state for a particular binding.
/// </summary>
/// <returns><c>true</c> when released since the last frame; otherwise, <c>false</c>.</returns>
public virtual bool IsReleased(InputManager manager)
{
return Button != null ? Button.IsReleased(manager) : false;
}

public override string ToString()
{
return string.Format("[{0}] => {1}", Name, Button);
Expand Down
67 changes: 65 additions & 2 deletions sources/engine/Stride.Input/VirtualButton/VirtualButtonConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ public IEnumerable<object> BindingNames
}
}

/// <summary>
/// Gets the value for a particular binding.
/// </summary>
/// <returns>Value of the binding</returns>
public virtual float GetValue(InputManager inputManager, object name)
{
float value = 0.0f;
List<VirtualButtonBinding> bindingsPerName;
if (mapBindings.TryGetValue(name, out bindingsPerName))
if (mapBindings.TryGetValue(name, out List<VirtualButtonBinding> bindingsPerName))
{
foreach (var virtualButtonBinding in bindingsPerName)
{
Expand All @@ -54,6 +57,66 @@ public virtual float GetValue(InputManager inputManager, object name)
return value;
}

/// <summary>
/// Gets the pressed state for a particular binding.
/// </summary>
/// <returns><c>true</c> when pressed since the last frame; otherwise, <c>false</c>.</returns>
public virtual bool IsPressed(InputManager inputManager, object name)
{
if (mapBindings.TryGetValue(name, out List<VirtualButtonBinding> bindingsPerName))
{
foreach (var virtualButtonBinding in bindingsPerName)
{
if (virtualButtonBinding.IsPressed(inputManager))
{
return true;
}
}
}

return false;
}

/// <summary>
/// Gets the held down state for a particular binding.
/// </summary>
/// <returns><c>true</c> when currently held down; otherwise, <c>false</c>.</returns>
public virtual bool IsDown(InputManager inputManager, object name)
{
if (mapBindings.TryGetValue(name, out List<VirtualButtonBinding> bindingsPerName))
{
foreach (var virtualButtonBinding in bindingsPerName)
{
if (virtualButtonBinding.IsDown(inputManager))
{
return true;
}
}
}

return false;
}

/// <summary>
/// Gets the pressed state for a particular binding.
/// </summary>
/// <returns><c>true</c> when released since the last frame; otherwise, <c>false</c>.</returns>
public virtual bool IsReleased(InputManager inputManager, object name)
{
if (mapBindings.TryGetValue(name, out List<VirtualButtonBinding> bindingsPerName))
{
foreach (var virtualButtonBinding in bindingsPerName)
{
if (virtualButtonBinding.IsReleased(inputManager))
{
return true;
}
}
}

return false;
}

private void Bindings_CollectionChanged(object sender, TrackingCollectionChangedEventArgs e)
{
var virtualButtonBinding = (VirtualButtonBinding)e.Item;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ public VirtualButtonConfigSet()
{
}

/// <summary>
/// Gets a binding value for the specified name and the specified config extract from the <see cref="VirtualButtonConfigSet"/>.
/// </summary>
/// <param name="inputManager">The <see cref="InputManager"/> to used to get the device input.</param>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/>.</param>
/// <param name="name">Name of the binding.</param>
/// <returns>The value of the binding.</returns>
public virtual float GetValue(InputManager inputManager, int configIndex, object name)
{
if (configIndex < 0 || configIndex >= Count)
Expand All @@ -30,5 +37,59 @@ public virtual float GetValue(InputManager inputManager, int configIndex, object
var config = this[configIndex];
return config != null ? config.GetValue(inputManager, name) : 0.0f;
}

/// <summary>
/// Determines whether the specified binding in the specified config in the <see cref="VirtualButtonConfigSet"/> was pressed since the previous Update.
/// </summary>
/// <param name="inputManager">The <see cref="InputManager"/> to used to get device input.</param>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/>.</param>
/// <param name="name">Name of the binding.</param>
/// <returns><c>true</c> if the binding was pressed; otherwise, <c>false</c>.</returns>
public virtual bool IsPressed(InputManager inputManager, int configIndex, object name)
{
if (configIndex < 0 || configIndex >= Count)
{
return false;
}

var config = this[configIndex];
return config != null ? config.IsPressed(inputManager, name) : false;
}

/// <summary>
/// Determines whether the specified binding in the specified config in the <see cref="VirtualButtonConfigSet"/> is currently pressed down.
/// </summary>
/// <param name="inputManager">The <see cref="InputManager"/> to used to get device input.</param>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/>.</param>
/// <param name="name">Name of the binding.</param>
/// <returns><c>true</c> if the binding is currently pressed down; otherwise, <c>false</c>.</returns>
public virtual bool IsDown(InputManager inputManager, int configIndex, object name)
{
if (configIndex < 0 || configIndex >= Count)
{
return false;
}

var config = this[configIndex];
return config != null ? config.IsDown(inputManager, name) : false;
}

/// <summary>
/// Determines whether the specified binding in the specified config in the <see cref="VirtualButtonConfigSet"/> was released since the previous Update.
/// </summary>
/// <param name="inputManager">The <see cref="InputManager"/> to used to get device input.</param>
/// <param name="configIndex">An index to a <see cref="VirtualButtonConfig"/> stored in the <see cref="VirtualButtonConfigSet"/>.</param>
/// <param name="name">Name of the binding.</param>
/// <returns><c>true</c> if the binding was released; otherwise, <c>false</c>.</returns>
public virtual bool IsReleased(InputManager inputManager, int configIndex, object name)
{
if (configIndex < 0 || configIndex >= Count)
{
return false;
}

var config = this[configIndex];
return config != null ? config.IsReleased(inputManager, name) : false;
}
}
}