/**************************************************************************** * Copyright 2019 Nreal Techonology Limited. All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ namespace NRKernal { using System; using System.Collections.Generic; using UnityEngine; /// Values that represent controller types. public enum ControllerType { /// An enum constant representing the controller type editor option. CONTROLLER_TYPE_EDITOR = 1001, /// An enum constant representing the controller type unknown option. CONTROLLER_TYPE_UNKNOWN = -1, /// An enum constant representing the controller type nreallight option. CONTROLLER_TYPE_NREALLIGHT = 0, /// An enum constant representing the controller type phone option. CONTROLLER_TYPE_PHONE = 1, /// An enum constant representing the controller type hand option. CONTROLLER_TYPE_HAND = 2 } /// Values that represent controller available features. public enum ControllerAvailableFeature { /// The position is avaliable. CONTROLLER_AVAILABLE_FEATURE_POSITION = (1 << 0), /// The rotation is avaliable. CONTROLLER_AVAILABLE_FEATURE_ROTATION = (1 << 1), /// /// An enum constant representing the controller available feature gyro option. CONTROLLER_AVAILABLE_FEATURE_GYRO = (1 << 2), /// /// An enum constant representing the controller available feature accel option. CONTROLLER_AVAILABLE_FEATURE_ACCEL = (1 << 3), /// /// An enum constant representing the controller available feature Magnitude option. CONTROLLER_AVAILABLE_FEATURE_MAG = (1 << 4), /// /// An enum constant representing the controller available feature battery option. CONTROLLER_AVAILABLE_FEATURE_BATTERY = (1 << 5), /// /// An enum constant representing the controller available feature charging option. CONTROLLER_AVAILABLE_FEATURE_CHARGING = (1 << 6), /// /// An enum constant representing the controller available feature recenter option. CONTROLLER_AVAILABLE_FEATURE_RECENTER = (1 << 7), /// /// An enum constant representing the controller available feature haptic vibrate option. CONTROLLER_AVAILABLE_FEATURE_HAPTIC_VIBRATE = (1 << 8) } /// Values that represent controller buttons. public enum ControllerButton { /// An enum constant representing the first option. BEGIN = 1 << 0, /// An enum constant representing the trigger option. TRIGGER = 1 << 0, /// An enum constant representing the Application option. APP = 1 << 1, /// An enum constant representing the home option. HOME = 1 << 2, /// An enum constant representing the grip option. GRIP = 1 << 3, /// An enum constant representing the touchpad button option. TOUCHPAD_BUTTON = 1 << 4, /// An enum constant representing the last option. END = 1 << 4, } /// Values that represent controller connection states. public enum ControllerConnectionState { /// /// An enum constant representing the controller connection state error option. CONTROLLER_CONNECTION_STATE_ERROR = -1, /// /// An enum constant representing the controller connection state not initialized option. CONTROLLER_CONNECTION_STATE_NOT_INITIALIZED = 0, /// /// An enum constant representing the controller connection state disconnected option. CONTROLLER_CONNECTION_STATE_DISCONNECTED = 1, /// /// An enum constant representing the controller connection state connecting option. CONTROLLER_CONNECTION_STATE_CONNECTING = 2, /// /// An enum constant representing the controller connection state connected option. CONTROLLER_CONNECTION_STATE_CONNECTED = 3 } internal enum HandednessType { LEFT_HANDEDNESS = 1, RIGHT_HANDEDNESS, } /// Values that represent button event types. internal enum ButtonEventType { /// An enum constant representing the down option. Down = 0, /// An enum constant representing the pressing option. Pressing, /// An enum constant representing the up option. Up, /// An enum constant representing the click option. Click, } /// A controller state. public class ControllerState { /// Type of the controller. internal ControllerType controllerType; /// State of the connection. internal ControllerConnectionState connectionState; /// The rotation. internal Quaternion rotation; /// The position. internal Vector3 position; /// The gyro. internal Vector3 gyro; /// The accel. internal Vector3 accel; /// The magnitude. internal Vector3 mag; /// The touch position. internal Vector2 touchPos; /// The delta touch. internal Vector2 deltaTouch; /// True if is touching, false if not. internal bool isTouching; /// True if recentered. internal bool recentered; /// State of the buttons. internal ControllerButton buttonsState; /// The buttons down. internal ControllerButton buttonsDown; /// The buttons up. internal ControllerButton buttonsUp; /// True if is charging, false if not. internal bool isCharging; /// The battery level. internal int batteryLevel; /// The available feature. internal ControllerAvailableFeature availableFeature; /// The last touch position. private Vector2 m_LastTouchPos; /// Dictionary of last down times. private Dictionary m_LastDownTimeDict = new Dictionary(); /// Array of listeners. private Dictionary[] m_ListenersArr = new Dictionary[Enum.GetValues(typeof(ButtonEventType)).Length]; /// Default constructor. public ControllerState() { Reset(); } /// Gets a value indicating whether this object is 6dof. /// True if this object is 6dof, false if not. public bool Is6dof { get { return IsFeatureAvailable(ControllerAvailableFeature.CONTROLLER_AVAILABLE_FEATURE_POSITION) && IsFeatureAvailable(ControllerAvailableFeature.CONTROLLER_AVAILABLE_FEATURE_ROTATION); } } /// Queries if a feature is available. /// The feature. /// True if the feature is available, false if not. public bool IsFeatureAvailable(ControllerAvailableFeature feature) { return (availableFeature & feature) != 0; } /// Gets a button. /// The button. /// True if it succeeds, false if it fails. public bool GetButton(ControllerButton button) { return (buttonsState & button) != 0; } /// Gets button down. /// The button. /// True if it succeeds, false if it fails. public bool GetButtonDown(ControllerButton button) { return (buttonsDown & button) != 0; } /// Gets button up. /// The button. /// True if it succeeds, false if it fails. public bool GetButtonUp(ControllerButton button) { return (buttonsUp & button) != 0; } /// Resets this object. public void Reset() { controllerType = ControllerType.CONTROLLER_TYPE_UNKNOWN; connectionState = ControllerConnectionState.CONTROLLER_CONNECTION_STATE_NOT_INITIALIZED; rotation = Quaternion.identity; position = Vector3.zero; gyro = Vector3.zero; accel = Vector3.zero; mag = Vector3.zero; touchPos = Vector2.zero; isTouching = false; recentered = false; buttonsState = 0; buttonsDown = 0; buttonsUp = 0; isCharging = false; batteryLevel = 0; availableFeature = 0; } /// Adds a button listener. /// Type of the button event. /// The button. /// The action. internal void AddButtonListener(ButtonEventType buttonEventType, ControllerButton button, Action action) { int buttonEventID = (int)buttonEventType; if (m_ListenersArr[buttonEventID] == null) { m_ListenersArr[buttonEventID] = new Dictionary(); } if (m_ListenersArr[buttonEventID].ContainsKey(button)) { m_ListenersArr[buttonEventID][button] += action; } else { m_ListenersArr[buttonEventID].Add(button, action); } } /// Removes the button listener. /// Type of the button event. /// The button. /// The action. internal void RemoveButtonListener(ButtonEventType buttonEventType, ControllerButton button, Action action) { int buttonEventID = (int)buttonEventType; if (m_ListenersArr[buttonEventID] == null) { m_ListenersArr[buttonEventID] = new Dictionary(); } if (m_ListenersArr[buttonEventID].ContainsKey(button) && m_ListenersArr[buttonEventID][button] != null) { m_ListenersArr[buttonEventID][button] -= action; if (m_ListenersArr[buttonEventID][button] == null) { m_ListenersArr[buttonEventID].Remove(button); } } } /// Updates the delta touch. internal void UpdateDeltaTouch() { if (m_LastTouchPos.Equals(Vector2.zero) || touchPos.Equals(Vector2.zero)) { deltaTouch = Vector2.zero; } else { deltaTouch = touchPos - m_LastTouchPos; } m_LastTouchPos = touchPos; } /// Check button events. internal void CheckButtonEvents() { UpdateDeltaTouch(); for (int i = (int)ControllerButton.BEGIN; i <= (int)ControllerButton.END; i <<= 1) { var button = (ControllerButton)i; if (GetButtonDown(button)) { if (m_LastDownTimeDict.ContainsKey(button)) { m_LastDownTimeDict[button] = Time.unscaledTime; } else { m_LastDownTimeDict.Add(button, Time.unscaledTime); } TryInvokeListener(ButtonEventType.Down, button); } if (GetButton(button)) { TryInvokeListener(ButtonEventType.Pressing, button); } else if (GetButtonUp(button)) { TryInvokeListener(ButtonEventType.Up, button); float lastDownTime; if (m_LastDownTimeDict.TryGetValue(button, out lastDownTime) && Time.unscaledTime - lastDownTime < NRInput.ClickInterval) { TryInvokeListener(ButtonEventType.Click, button); } } } } /// Try invoke listener. /// Type of the button event. /// The button. private void TryInvokeListener(ButtonEventType buttonEventType, ControllerButton button) { int buttonEventID = (int)buttonEventType; if (m_ListenersArr[buttonEventID] == null) return; if (m_ListenersArr[buttonEventID].ContainsKey(button) && m_ListenersArr[buttonEventID][button] != null) { m_ListenersArr[buttonEventID][button].Invoke(); } } } }