222 lines
6.5 KiB
C#
222 lines
6.5 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using UnityEngine.InputSystem;
|
|||
|
|
|
|||
|
|
public static class InputActionReader
|
|||
|
|
{
|
|||
|
|
private readonly struct InputReadKey : IEquatable<InputReadKey>
|
|||
|
|
{
|
|||
|
|
public readonly string ActionName;
|
|||
|
|
public readonly int OwnerId;
|
|||
|
|
public readonly string OwnerKey;
|
|||
|
|
|
|||
|
|
public InputReadKey(string actionName, int ownerId)
|
|||
|
|
{
|
|||
|
|
ActionName = actionName ?? string.Empty;
|
|||
|
|
OwnerId = ownerId;
|
|||
|
|
OwnerKey = string.Empty;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public InputReadKey(string actionName, string ownerKey)
|
|||
|
|
{
|
|||
|
|
ActionName = actionName ?? string.Empty;
|
|||
|
|
OwnerId = 0;
|
|||
|
|
OwnerKey = ownerKey ?? string.Empty;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public bool Equals(InputReadKey other)
|
|||
|
|
{
|
|||
|
|
return OwnerId == other.OwnerId
|
|||
|
|
&& string.Equals(ActionName, other.ActionName, StringComparison.Ordinal)
|
|||
|
|
&& string.Equals(OwnerKey, other.OwnerKey, StringComparison.Ordinal);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override bool Equals(object obj)
|
|||
|
|
{
|
|||
|
|
return obj is InputReadKey other && Equals(other);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override int GetHashCode()
|
|||
|
|
{
|
|||
|
|
unchecked
|
|||
|
|
{
|
|||
|
|
int hashCode = 17;
|
|||
|
|
hashCode = (hashCode * 31) + OwnerId;
|
|||
|
|
hashCode = (hashCode * 31) + StringComparer.Ordinal.GetHashCode(ActionName);
|
|||
|
|
hashCode = (hashCode * 31) + StringComparer.Ordinal.GetHashCode(OwnerKey);
|
|||
|
|
return hashCode;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static readonly HashSet<InputReadKey> PressedKeys = new();
|
|||
|
|
private static readonly HashSet<InputReadKey> ToggledKeys = new();
|
|||
|
|
|
|||
|
|
public static T ReadValue<T>(string actionName) where T : struct
|
|||
|
|
{
|
|||
|
|
return ResolveAction(actionName).ReadValue<T>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static object ReadValue(string actionName)
|
|||
|
|
{
|
|||
|
|
return ResolveAction(actionName).ReadValueAsObject();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool TryReadValue<T>(string actionName, out T value) where T : struct
|
|||
|
|
{
|
|||
|
|
InputAction inputAction = ResolveAction(actionName);
|
|||
|
|
if (inputAction.IsPressed())
|
|||
|
|
{
|
|||
|
|
value = inputAction.ReadValue<T>();
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
value = default;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool TryReadValue(string actionName, out object value)
|
|||
|
|
{
|
|||
|
|
InputAction inputAction = ResolveAction(actionName);
|
|||
|
|
if (inputAction.IsPressed())
|
|||
|
|
{
|
|||
|
|
value = inputAction.ReadValueAsObject();
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
value = default;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool TryReadValueOnce<T>(UnityEngine.Object owner, string actionName, out T value) where T : struct
|
|||
|
|
{
|
|||
|
|
if (owner == null)
|
|||
|
|
{
|
|||
|
|
value = default;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return TryReadValueOnceInternal(new InputReadKey(actionName, owner.GetInstanceID()), actionName, out value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool ReadButton(string actionName)
|
|||
|
|
{
|
|||
|
|
InputAction inputAction = ResolveAction(actionName);
|
|||
|
|
if (inputAction.type == InputActionType.Button)
|
|||
|
|
{
|
|||
|
|
return Convert.ToBoolean(inputAction.ReadValueAsObject());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
throw new NotSupportedException("[InputActionReader] The Input Action must be a button type.");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool ReadButtonOnce(UnityEngine.Object owner, string actionName)
|
|||
|
|
{
|
|||
|
|
return owner != null && ReadButtonOnce(owner.GetInstanceID(), actionName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool ReadButtonOnce(int instanceID, string actionName)
|
|||
|
|
{
|
|||
|
|
return ReadButtonOnceInternal(new InputReadKey(actionName, instanceID), actionName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool ReadButtonOnce(string key, string actionName)
|
|||
|
|
{
|
|||
|
|
return ReadButtonOnceInternal(new InputReadKey(actionName, key), actionName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool ReadButtonToggle(UnityEngine.Object owner, string actionName)
|
|||
|
|
{
|
|||
|
|
return owner != null && ReadButtonToggle(owner.GetInstanceID(), actionName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool ReadButtonToggle(int instanceID, string actionName)
|
|||
|
|
{
|
|||
|
|
return ReadButtonToggleInternal(new InputReadKey(actionName, instanceID), actionName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static bool ReadButtonToggle(string key, string actionName)
|
|||
|
|
{
|
|||
|
|
return ReadButtonToggleInternal(new InputReadKey(actionName, key), actionName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void ResetToggledButton(string key, string actionName)
|
|||
|
|
{
|
|||
|
|
ToggledKeys.Remove(new InputReadKey(actionName, key));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void ResetToggledButton(string actionName)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrEmpty(actionName) || ToggledKeys.Count == 0)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
InputReadKey[] snapshot = new InputReadKey[ToggledKeys.Count];
|
|||
|
|
ToggledKeys.CopyTo(snapshot);
|
|||
|
|
for (int i = 0; i < snapshot.Length; i++)
|
|||
|
|
{
|
|||
|
|
if (string.Equals(snapshot[i].ActionName, actionName, StringComparison.Ordinal))
|
|||
|
|
{
|
|||
|
|
ToggledKeys.Remove(snapshot[i]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void ResetToggledButtons()
|
|||
|
|
{
|
|||
|
|
ToggledKeys.Clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static InputAction ResolveAction(string actionName)
|
|||
|
|
{
|
|||
|
|
return InputBindingManager.Action(actionName)
|
|||
|
|
?? throw new InvalidOperationException($"[InputActionReader] Action '{actionName}' is not available.");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static bool TryReadValueOnceInternal<T>(InputReadKey readKey, string actionName, out T value) where T : struct
|
|||
|
|
{
|
|||
|
|
InputAction inputAction = ResolveAction(actionName);
|
|||
|
|
if (inputAction.IsPressed())
|
|||
|
|
{
|
|||
|
|
if (PressedKeys.Add(readKey))
|
|||
|
|
{
|
|||
|
|
value = inputAction.ReadValue<T>();
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
PressedKeys.Remove(readKey);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
value = default;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static bool ReadButtonOnceInternal(InputReadKey readKey, string actionName)
|
|||
|
|
{
|
|||
|
|
if (ReadButton(actionName))
|
|||
|
|
{
|
|||
|
|
return PressedKeys.Add(readKey);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PressedKeys.Remove(readKey);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static bool ReadButtonToggleInternal(InputReadKey readKey, string actionName)
|
|||
|
|
{
|
|||
|
|
if (ReadButtonOnceInternal(readKey, actionName))
|
|||
|
|
{
|
|||
|
|
if (!ToggledKeys.Add(readKey))
|
|||
|
|
{
|
|||
|
|
ToggledKeys.Remove(readKey);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ToggledKeys.Contains(readKey);
|
|||
|
|
}
|
|||
|
|
}
|