/****************************************************************************
* Copyright 2019 Nreal Techonology Limited. All rights reserved.
*
* This file is part of NRSDK.
*
* https://www.nreal.ai/
*
*****************************************************************************/
namespace NRKernal
{
using System;
using UnityEngine;
/// Enumeration of handedness.
public enum ControllerHandEnum
{
/// An enum constant representing the right option.
Right = 0,
/// An enum constant representing the left option.
Left = 1
}
/// Enumeration of raycast mode. Normally, suggest using "Laser" mode.
public enum RaycastModeEnum
{
/// An enum constant representing the gaze option.
Gaze,
/// An enum constant representing the laser option.
Laser
}
/// Enumeration of input source type.
public enum InputSourceEnum
{
/// An enum constant representing the hands option.
Hands,
/// An enum constant representing the controller option.
Controller
}
/// Enumeration of controller visual types.
public enum ControllerVisualType
{
/// An enum constant representing the none option.
None = 0,
/// An enum constant representing the nreal light option.
NrealLight = 1,
/// An enum constant representing the phone option.
Phone = 2
}
///
/// The main class to handle controller related things, such as to get controller states, update
/// controller states Through this class, application would create a controllerProvider which
/// could be custom, then the controllerProvider iteself would define how to update the
/// controller states, so that every frame NRInput could get the right states.There are max two
/// states for one controllerProvider.
[HelpURL("https://developer.nreal.ai/develop/unity/controller")]
[ScriptOrder(NativeConstants.NRINPUT_ORDER)]
public partial class NRInput : SingletonBehaviour
{
public GameObject rightGame;
public GameObject leftGame;
/// True to emulate virtual display in editor.
[Tooltip("If enable this, phone virtual controller would be shown in Unity Editor")]
[SerializeField]
private bool m_EmulateVirtualDisplayInEditor;
/// The override camera center.
[SerializeField]
private Transform m_OverrideCameraCenter;
/// The anchor helper.
[SerializeField]
private ControllerAnchorsHelper m_AnchorHelper;
/// The raycast mode.
[SerializeField]
private RaycastModeEnum m_RaycastMode = RaycastModeEnum.Laser;
/// The current input source type.
[SerializeField]
private InputSourceEnum m_InputSourceType = InputSourceEnum.Controller;
/// The click interval.
[SerializeField]
private float m_ClickInterval = 0.3f;
/// The drag threshold.
[SerializeField]
private float m_DragThreshold = 0.02f;
/// Manager for visual.
private ControllerVisualManager m_VisualManager;
/// Number of last controllers.
private int m_LastControllerCount;
/// True to reticle visual active.
private bool m_ReticleVisualActive = true;
/// True to laser visual active.
private bool m_LaserVisualActive = true;
/// True to controller visual active.
private bool m_ControllerVisualActive = true;
/// True to enable, false to disable the haptic vibration.
private bool m_HapticVibrationEnabled = true;
/// True to active, false to disactive the gameobjects of raycasters.
private bool m_RaycastersActive = true;
/// Whether has checked the camera center.
private bool m_HasCheckedCameraCenter;
/// True means will do something OnValidate.
private bool m_IsListeningToEditorValidateEvents = false;
/// The cached input source type in Editor.
private InputSourceEnum m_EditorCachedInputSourceType = InputSourceEnum.Controller;
/// True to ignore recenter callback.
private static bool m_IgnoreRecenterCallback = false;
/// The domain hand.
private static ControllerHandEnum m_DomainHand = ControllerHandEnum.Right;
/// The controller provider.
private static ControllerProviderBase m_ControllerProvider;
/// The states.
private static ControllerState[] m_States = new ControllerState[MAX_CONTROLLER_STATE_COUNT]
{
new ControllerState(),
new ControllerState()
};
/// Max count of controllerstates supported per frame.
public const int MAX_CONTROLLER_STATE_COUNT = 2;
/// Event invoked whenever the domain hand has changed.
public static Action OnDomainHandChanged;
/// Event invoked whenever a controller device is connected.
public static Action OnControllerConnected;
/// Event invoked whenever a controller device is disconnected.
public static Action OnControllerDisconnected;
/// Event invoked before controller devices are going to recenter.
public static Action OnBeforeControllerRecenter;
/// Event invoked whenever controller devices are recentering.
internal static Action OnControllerRecentering;
/// Event invoked whenever controller devices are recentered.
public static Action OnControllerRecentered;
/// Event invoked whenever controller devices states are updated.
public static Action OnControllerStatesUpdated;
///
/// Determine whether to show reticle visuals, could be get and set at runtime.
/// True if reticle visual active, false if not.
public static bool ReticleVisualActive { get { return Instance.m_ReticleVisualActive; } set { Instance.m_ReticleVisualActive = value; } }
/// Determine whether to show laser visuals, could be get and set at runtime.
/// True if laser visual active, false if not.
public static bool LaserVisualActive { get { return Instance.m_LaserVisualActive; } set { Instance.m_LaserVisualActive = value; } }
///
/// Determine whether to show controller visuals, could be get and set at runtime.
/// True if controller visual active, false if not.
public static bool ControllerVisualActive { get { return Instance.m_ControllerVisualActive; } set { Instance.m_ControllerVisualActive = value; } }
/// Determine whether enable haptic vibration.
/// True if haptic vibration enabled, false if not.
public static bool HapticVibrationEnabled { get { return Instance.m_HapticVibrationEnabled; } set { Instance.m_HapticVibrationEnabled = value; } }
///
/// Determine whether to active raycaster gameobjects, could be get and set at runtime.
/// True if active raycaster gameobjects, false if not.
public static bool RaycastersActive { get { return Instance.m_RaycastersActive; } set { Instance.m_RaycastersActive = value; } }
/// Determine whether emulate phone virtual display in Unity Editor.
/// True if emulate virtual display in editor, false if not.
public static bool EmulateVirtualDisplayInEditor { get { return Instance ? Instance.m_EmulateVirtualDisplayInEditor : false; } }
/// It's a helper to get controller anchors which are frequently used.
/// The anchors helper.
public static ControllerAnchorsHelper AnchorsHelper { get { return Instance.m_AnchorHelper; } }
/// Get the current enumeration of handedness.
/// The domain hand.
public static ControllerHandEnum DomainHand { get { return m_DomainHand; } }
/// Determine which raycast mode to use.
/// The raycast mode.
public static RaycastModeEnum RaycastMode { get { return Instance.m_RaycastMode; } set { Instance.m_RaycastMode = value; } }
/// Get the current input source type.
/// The input source type.
public static InputSourceEnum CurrentInputSourceType { get { return Instance.m_InputSourceType; } }
/// Get and set button click interval.
/// The click interval.
public static float ClickInterval { get { return Instance.m_ClickInterval; } set { Instance.m_ClickInterval = value; } }
/// Get and set pointer drag threshold.
/// The drag threshold.
public static float DragThreshold { get { return Instance.m_DragThreshold; } set { Instance.m_DragThreshold = value; } }
/// Get the transform of the camera which controllers are following.
/// The camera center.
public static Transform CameraCenter { get { return Instance.GetCameraCenter(); } }
/// The HandsManager which controls the hand-tracking.
public static NRHandsManager Hands = new NRHandsManager();
/// Starts this object.
private void Start()
{
if (isDirty)
{
return;
}
Init();
Invoke("showContorl",1f);
}
void showContorl()
{
leftGame.SetActive(true);
rightGame.SetActive(true);
}
/// Executes the 'update' action.
private void OnUpdate()
{
if (m_ControllerProvider == null)
return;
UpdateControllerProvider();
}
/// Updates the controller provider.
private void UpdateControllerProvider()
{
if (m_ControllerProvider.Inited)
{
m_ControllerProvider.Update();
if (OnControllerStatesUpdated != null)
{
OnControllerStatesUpdated();
}
CheckControllerConnection();
CheckControllerRecentered();
CheckControllerButtonEvents();
}
else
{
m_ControllerProvider.Update();
#if !UNITY_EDITOR
if (m_ControllerProvider is NRControllerProvider)
{
m_DomainHand = ((NRControllerProvider)m_ControllerProvider).GetHandednessType();
NRDebugger.Info("[NRInput] Set default domain hand:" + m_DomainHand);
}
#endif
}
}
/// Executes the 'enable' action.
private void OnEnable()
{
if (isDirty)
{
return;
}
NRKernalUpdater.OnPostUpdate += OnUpdate;
m_ControllerProvider?.OnResume();
}
/// Executes the 'disable' action.
private void OnDisable()
{
if (isDirty)
{
return;
}
NRKernalUpdater.OnPostUpdate -= OnUpdate;
m_ControllerProvider?.OnPause();
}
#if UNITY_EDITOR
/// Executes the 'validate' action.
private void OnValidate()
{
if (!m_IsListeningToEditorValidateEvents)
return;
if (m_EditorCachedInputSourceType != m_InputSourceType)
{
SetInputSource(m_InputSourceType);
}
}
#endif
/// Gets a version.
/// Zero-based index of the.
/// The version.
public string GetVersion(int index)
{
if (m_ControllerProvider is NRControllerProvider)
{
return ((NRControllerProvider)m_ControllerProvider).GetVersion(index);
}
else
{
return "0.0.0";
}
}
/// Destroys this object.
internal static void Destroy()
{
if (m_ControllerProvider != null)
{
m_ControllerProvider.OnDestroy();
m_ControllerProvider = null;
}
}
///
/// Base OnDestroy method that destroys the Singleton's unique instance. Called by Unity when
/// destroying a MonoBehaviour. Scripts that extend Singleton should be sure to call
/// base.OnDestroy() to ensure the underlying static Instance reference is properly cleaned up.
new void OnDestroy()
{
if (isDirty)
{
return;
}
base.OnDestroy();
Destroy();
}
/// Check controller connection.
private void CheckControllerConnection()
{
int currentControllerCount = GetAvailableControllersCount();
if (m_LastControllerCount < currentControllerCount)
{
if (OnControllerConnected != null)
{
OnControllerConnected();
}
}
else if (m_LastControllerCount > currentControllerCount)
{
if (OnControllerDisconnected != null)
{
OnControllerDisconnected();
}
}
m_LastControllerCount = currentControllerCount;
}
/// Check controller recentered.
private void CheckControllerRecentered()
{
if (GetControllerState(DomainHand).recentered)
{
if (m_IgnoreRecenterCallback == false && OnBeforeControllerRecenter != null)
{
OnBeforeControllerRecenter();
}
if (OnControllerRecentering != null)
{
OnControllerRecentering();
}
if (m_IgnoreRecenterCallback == false && OnControllerRecentered != null)
{
OnControllerRecentered();
}
m_IgnoreRecenterCallback = false;
}
}
/// Check controller button events.
private void CheckControllerButtonEvents()
{
int currentControllerCount = GetAvailableControllersCount();
for (int i = 0; i < currentControllerCount; i++)
{
m_States[i].CheckButtonEvents();
}
}
/// Executes the 'application pause' action.
/// True if paused.
private void OnApplicationPause(bool paused)
{
if (m_ControllerProvider == null || !m_ControllerProvider.Inited)
return;
if (paused)
{
m_ControllerProvider.OnPause();
}
else
{
m_ControllerProvider.OnResume();
m_IgnoreRecenterCallback = true;
m_ControllerProvider.Recenter();
}
}
/// Initializes this object.
private void Init()
{
NRDebugger.Info("[NRInput] Init");
NRDevice.Instance.Init();
m_VisualManager = gameObject.AddComponent();
m_VisualManager.Init(m_States);
SwitchControllerProvider(ControllerProviderFactory.controllerProviderType);
#if UNITY_EDITOR
InitEmulator();
m_IsListeningToEditorValidateEvents = true;
#endif
SetInputSourceSafely(m_InputSourceType);
}
#if UNITY_EDITOR
private void InitEmulator()
{
if (!NREmulatorManager.Inited && !GameObject.Find("NREmulatorManager"))
{
NREmulatorManager.Inited = true;
GameObject.Instantiate(Resources.Load("Prefabs/NREmulatorManager"));
}
if (!GameObject.Find("NREmulatorController"))
{
Instantiate(Resources.Load("Prefabs/NREmulatorController"));
}
}
#endif
/// Gets camera center.
/// The camera center.
private Transform GetCameraCenter()
{
if (m_OverrideCameraCenter == null)
{
m_HasCheckedCameraCenter = true;
return NRSessionManager.Instance.CenterCameraAnchor;
}
else
{
if (!m_HasCheckedCameraCenter)
{
CheckCameraCenter();
}
return m_OverrideCameraCenter;
}
}
/// To guarantee the camera center was right.
private void CheckCameraCenter()
{
if (m_OverrideCameraCenter != null
&& NRSessionManager.Instance != null
&& NRSessionManager.Instance.NRSessionBehaviour != null)
{
var cameraRigTransform = NRSessionManager.Instance.NRSessionBehaviour.transform;
if (m_OverrideCameraCenter.parent == cameraRigTransform)
{
m_OverrideCameraCenter = NRSessionManager.Instance.CenterCameraAnchor;
}
}
m_HasCheckedCameraCenter = true;
}
/// Convert hand to index.
/// .
/// The hand converted to index.
private static int ConvertHandToIndex(ControllerHandEnum handEnum)
{
if (GetAvailableControllersCount() < 2)
{
return DomainHand == handEnum ? 0 : 1;
}
else
{
return (int)handEnum;
}
}
/// Gets controller state.
/// The hand.
/// The controller state.
private static ControllerState GetControllerState(ControllerHandEnum hand)
{
return m_States[ConvertHandToIndex(hand)];
}
///
/// Set the current input source with fallback
///
///
private static void SetInputSourceSafely(InputSourceEnum inputSourceType)
{
var adaptInputSourceType = AdaptInputSource(inputSourceType);
if (adaptInputSourceType != inputSourceType)
{
NRDebugger.Warning("[NRInput] AutoAdaptInputSource : {0} => {1}", inputSourceType, adaptInputSourceType);
inputSourceType = adaptInputSourceType;
}
if (SetInputSource(inputSourceType))
{
return;
}
var fallbackInputSourceType = InputSourceEnum.Controller;
NRDebugger.Info("[NRInput] Set Input Source To {0} Failed. Now Set Input Source To Fallback: {1}", inputSourceType, fallbackInputSourceType);
SetInputSource(fallbackInputSourceType);
}
/// Auto adaption for inputSource based on supported feature on current device.
/// Fallback inputSource.
private static InputSourceEnum AdaptInputSource(InputSourceEnum inputSourceType)
{
if (inputSourceType == InputSourceEnum.Hands && !NRDevice.Subsystem.IsFeatureSupported(NRSupportedFeature.NR_FEATURE_HANDTRACKING))
return InputSourceEnum.Controller;
return inputSourceType;
}
///
/// To swith the controller provider
///
///
internal static void SwitchControllerProvider(Type providerType)
{
if (m_ControllerProvider != null && m_ControllerProvider.GetType() == providerType)
return;
var nextControllerProvider = ControllerProviderFactory.GetOrCreateControllerProvider(providerType, m_States);
if (nextControllerProvider == null)
return;
if (m_ControllerProvider != null)
{
m_ControllerProvider.OnPause();
}
m_ControllerProvider = nextControllerProvider;
if (m_ControllerProvider != null)
{
m_ControllerProvider.OnResume();
}
}
/// Set the current enumeration of handedness.
/// .
public static void SetDomainHandMode(ControllerHandEnum handEnum)
{
if (m_DomainHand == handEnum)
return;
m_DomainHand = handEnum;
if (OnDomainHandChanged != null)
{
OnDomainHandChanged(m_DomainHand);
}
}
/// Set the current input source.
///
/// The result of setting input source.
public static bool SetInputSource(InputSourceEnum inputSourceType)
{
NRDebugger.Info("[NRInput] Set Input Source: " + inputSourceType);
if (Instance == null)
{
return false;
}
bool success = true;
switch (inputSourceType)
{
case InputSourceEnum.Hands:
success = Hands.StartHandTracking();
break;
case InputSourceEnum.Controller:
success = Hands.StopHandTracking();
break;
default:
break;
}
if (success)
{
Instance.m_InputSourceType = inputSourceType;
#if UNITY_EDITOR
Instance.m_EditorCachedInputSourceType = inputSourceType;
#endif
}
NRDebugger.Info("[NRInput] Input Source Set. Current Input Source = " + CurrentInputSourceType);
return success;
}
/// Get the current count of controllers which are connected and available.
/// The available controllers count.
public static int GetAvailableControllersCount()
{
if (m_ControllerProvider == null)
{
return 0;
}
return m_ControllerProvider.ControllerCount;
}
/// Get the ControllerType of current controller.
/// The controller type.
public static ControllerType GetControllerType()
{
return GetControllerState(DomainHand).controllerType;
}
/// Get the ConnectionState of current controller.
/// The controller connection state.
public static ControllerConnectionState GetControllerConnectionState()
{
return GetControllerState(DomainHand).connectionState;
}
/// Returns true if the controller is available.
/// .
/// True if it succeeds, false if it fails.
public static bool CheckControllerAvailable(ControllerHandEnum handEnum)
{
if (m_ControllerProvider is NRHandControllerProvider)
{
return Hands.GetHandState(handEnum == ControllerHandEnum.Right ? HandEnum.RightHand : HandEnum.LeftHand).pointerPoseValid;
}
int availableCount = GetAvailableControllersCount();
if (availableCount == 2)
{
return true;
}
if (availableCount == 1)
{
return handEnum == DomainHand;
}
return false;
}
/// Returns true if the current controller supports the certain feature.
/// The feature.
/// True if it succeeds, false if it fails.
public static bool GetControllerAvailableFeature(ControllerAvailableFeature feature)
{
if (GetAvailableControllersCount() == 0)
return false;
return GetControllerState(m_DomainHand).IsFeatureAvailable(feature);
}
/// Returns true if the button is currently pressed this frame.
/// The button.
/// True if it succeeds, false if it fails.
public static bool GetButton(ControllerButton button)
{
return GetButton(m_DomainHand, button);
}
/// Returns true if the button was pressed down this frame.
/// The button.
/// True if it succeeds, false if it fails.
public static bool GetButtonDown(ControllerButton button)
{
return GetButtonDown(m_DomainHand, button);
}
/// Returns true if the button was released this frame.
/// The button.
/// True if it succeeds, false if it fails.
public static bool GetButtonUp(ControllerButton button)
{
return GetButtonUp(m_DomainHand, button);
}
/// Returns true if the touchpad is being touched.
/// True if touching, false if not.
public static bool IsTouching()
{
return IsTouching(m_DomainHand);
}
///
/// Returns a Vector2 touch position on touchpad of the domain controller, range: x(-1f ~ 1f), y(-
/// 1f ~ 1f)
/// The touch.
public static Vector2 GetTouch()
{
return GetTouch(m_DomainHand);
}
/// Returns a Vector2 delta touch value on touchpad of the domain controller.
/// The delta touch.
public static Vector2 GetDeltaTouch()
{
return GetDeltaTouch(m_DomainHand);
}
///
/// Returns the current position of the domain controller if 6dof, otherwise returns Vector3.zero.
/// The position.
public static Vector3 GetPosition()
{
return GetPosition(m_DomainHand);
}
/// Returns the current rotation of the domain controller.
/// The rotation.
public static Quaternion GetRotation()
{
return GetRotation(m_DomainHand);
}
/// Returns the gyro sensor value of the domain controller.
/// The gyro.
public static Vector3 GetGyro()
{
return GetGyro(m_DomainHand);
}
/// Returns the accel sensor value of the domain controller.
/// The accel.
public static Vector3 GetAccel()
{
return GetAccel(m_DomainHand);
}
/// Returns the magnetic sensor value of the domain controller.
/// The magnitude.
public static Vector3 GetMag()
{
return GetMag(m_DomainHand);
}
/// Returns the battery level of the domain controller.
/// The controller battery.
public static int GetControllerBattery()
{
return GetControllerBattery(DomainHand);
}
/// Trigger vibration of the domain controller.
/// (Optional) The duration in seconds.
/// (Optional) The frequency.
/// (Optional) The amplitude.
public static void TriggerHapticVibration(float durationSeconds = 0.1f, float frequency = 200f, float amplitude = 0.8f)
{
TriggerHapticVibration(m_DomainHand, durationSeconds, frequency, amplitude);
}
///
/// Returns true if the button is currently pressed this frame on a certain handedness
/// controller.
/// The hand.
/// The button.
/// True if it succeeds, false if it fails.
public static bool GetButton(ControllerHandEnum hand, ControllerButton button)
{
return GetControllerState(hand).GetButton(button);
}
///
/// Returns true if the button was pressed down this frame on a certain handedness controller.
/// The hand.
/// The button.
/// True if it succeeds, false if it fails.
public static bool GetButtonDown(ControllerHandEnum hand, ControllerButton button)
{
return GetControllerState(hand).GetButtonDown(button);
}
///
/// Returns true if the button was released this frame on a certain handedness controller.
/// The hand.
/// The button.
/// True if it succeeds, false if it fails.
public static bool GetButtonUp(ControllerHandEnum hand, ControllerButton button)
{
return GetControllerState(hand).GetButtonUp(button);
}
///
/// Returns true if the touchpad is being touched this frame on a certain handedness controller.
/// The hand.
/// True if touching, false if not.
public static bool IsTouching(ControllerHandEnum hand)
{
return GetControllerState(hand).isTouching;
}
///
/// Returns a Vector2 touch position on touchpad of a certain handedness controller, range: x(-1f
/// ~ 1f), y(-1f ~ 1f)
/// The hand.
/// The touch.
public static Vector2 GetTouch(ControllerHandEnum hand)
{
return GetControllerState(hand).touchPos;
}
///
/// Returns a Vector2 delta touch value on touchpad of a certain handedness controller.
/// The hand.
/// The delta touch.
public static Vector2 GetDeltaTouch(ControllerHandEnum hand)
{
return GetControllerState(hand).deltaTouch;
}
///
/// Returns the current position of a certain handedness controller if 6dof, otherwise returns
/// Vector3.zero.
/// The hand.
/// The position.
public static Vector3 GetPosition(ControllerHandEnum hand)
{
return GetControllerState(hand).position;
}
/// Returns the current rotation of a certain handedness controller.
/// The hand.
/// The rotation.
public static Quaternion GetRotation(ControllerHandEnum hand)
{
return GetControllerState(hand).rotation;
}
/// Returns the gyro sensor value of a certain handedness controller.
/// The hand.
/// The gyro.
public static Vector3 GetGyro(ControllerHandEnum hand)
{
return GetControllerState(hand).gyro;
}
/// Returns the accel sensor value of a certain handedness controller.
/// The hand.
/// The accel.
public static Vector3 GetAccel(ControllerHandEnum hand)
{
return GetControllerState(hand).accel;
}
/// Returns the magnetic sensor value of a certain handedness controller.
/// The hand.
/// The magnitude.
public static Vector3 GetMag(ControllerHandEnum hand)
{
return GetControllerState(hand).mag;
}
///
/// Returns the battery level of a certain handedness controller, range from 0 to 100.
/// The hand.
/// The controller battery.
public static int GetControllerBattery(ControllerHandEnum hand)
{
return GetControllerState(hand).batteryLevel;
}
/// Trigger vibration of a certain handedness controller.
/// The hand.
/// (Optional) The duration in seconds.
/// (Optional) The frequency.
/// (Optional) The amplitude.
public static void TriggerHapticVibration(ControllerHandEnum hand, float durationSeconds = 0.1f, float frequency = 200f, float amplitude = 0.8f)
{
if (!HapticVibrationEnabled)
return;
if (GetAvailableControllersCount() == 0)
return;
m_ControllerProvider.TriggerHapticVibration(ConvertHandToIndex(hand), durationSeconds, frequency, amplitude);
}
/// Recenter controller.
public static void RecenterController()
{
if (GetAvailableControllersCount() == 0)
return;
m_IgnoreRecenterCallback = false;
m_ControllerProvider.Recenter();
}
/// Add button down event listerner.
/// The hand.
/// The button.
/// The action.
public static void AddDownListener(ControllerHandEnum hand, ControllerButton button, Action action)
{
GetControllerState(hand).AddButtonListener(ButtonEventType.Down, button, action);
}
/// Remove button down event listerner.
/// The hand.
/// The button.
/// The action.
public static void RemoveDownListener(ControllerHandEnum hand, ControllerButton button, Action action)
{
GetControllerState(hand).RemoveButtonListener(ButtonEventType.Down, button, action);
}
/// Add button pressing event listerner.
/// The hand.
/// The button.
/// The action.
public static void AddPressingListener(ControllerHandEnum hand, ControllerButton button, Action action)
{
GetControllerState(hand).AddButtonListener(ButtonEventType.Pressing, button, action);
}
/// Remove button pressing event listerner.
/// The hand.
/// The button.
/// The action.
public static void RemovePressingListener(ControllerHandEnum hand, ControllerButton button, Action action)
{
GetControllerState(hand).RemoveButtonListener(ButtonEventType.Pressing, button, action);
}
/// Add button up event listerner.
/// The hand.
/// The button.
/// The action.
public static void AddUpListener(ControllerHandEnum hand, ControllerButton button, Action action)
{
GetControllerState(hand).AddButtonListener(ButtonEventType.Up, button, action);
}
/// Remove button up event listerner.
/// The hand.
/// The button.
/// The action.
public static void RemoveUpListener(ControllerHandEnum hand, ControllerButton button, Action action)
{
GetControllerState(hand).RemoveButtonListener(ButtonEventType.Up, button, action);
}
/// Add button click event listerner.
/// The hand.
/// The button.
/// The action.
public static void AddClickListener(ControllerHandEnum hand, ControllerButton button, Action action)
{
GetControllerState(hand).AddButtonListener(ButtonEventType.Click, button, action);
}
/// Remove button click event listerner.
/// The hand.
/// The button.
/// The action.
public static void RemoveClickListener(ControllerHandEnum hand, ControllerButton button, Action action)
{
GetControllerState(hand).RemoveButtonListener(ButtonEventType.Click, button, action);
}
}
}