using System; using System.Collections; using System.Collections.Generic; using EZXR.Glass.Core; using EZXR.Glass.Inputs; using UnityEngine; namespace EZXR.Glass.Inputs { public enum HandleKeyEvent { Idle, //默认状态 Down, //按下(仅单帧有效) Up, //弹起(仅单帧有效) /// /// (feat)等同于长按 /// Down之后每帧有效 /// PrePressed, //介于按下和长按之间状态 Pressing //长按(每帧有效) } [ScriptExecutionOrder(-49)] public class HandleControllerManager : MonoBehaviour { #region singleton private static HandleControllerManager instance; public static HandleControllerManager Instance { get { return instance; } } #endregion /// /// 记录了左手柄的所有信息 /// public static ControllerInfo leftHand; /// /// 记录了右手柄的所有信息 /// public static ControllerInfo rightHand; // 手柄模型 public Transform leftController; public Transform rightController; private List> bindingActions = new List>(); private List> connectedActions = new List>(); private List> powerChangedActions = new List>(); private List> holdChangedActions = new List>(); private List> silenceChangedActions = new List>(); private List> buttonChangedActions = new List>(); private List> trackingChangedActions = new List>(); /// /// 由外部逻辑控制手的射线的方向 /// /// /// /// public delegate bool Delegate_SetRayDataByExternal(ControllerInfo controllerInfo, ref Vector3 value); public static Delegate_SetRayDataByExternal SetRayDirByExternal; public static Delegate_SetRayDataByExternal SetRayStartPointByExternal; private void Awake() { instance = this; leftHand = leftController.GetComponent(); rightHand = rightController.GetComponent(); } private void Start() { HandleControllerSession.Instance.InitRegistration(OnBindingEventCallback, OnConnectEventCallback, OnButtonEventCallback, OnAxis2DEventCallback, OnHoldEventCallback, OnSilenceEventCallback, OnTrackingStateChangedCallback); if (leftHand != null) { // 初始化手柄的生命状态 leftHand.Init(HandType.Left); } if (rightHand != null) { // 初始化手柄的生命状态 rightHand.Init(HandType.Right); } StartCoroutine(WaitForTimeout()); } private void Update() { //if (Input.GetKeyDown(KeyCode.Q)) // Debug.Log($"HandleControllerManager, rightHand binding = {rightController != null && rightHand.Exist}, controllerPose: ({HandleControllerSession.controllerPose_right.position.x}, {HandleControllerSession.controllerPose_right.position.y}, {HandleControllerSession.controllerPose_right.position.z})"); if (leftHand.Exist || rightHand.Exist) HandleControllerSession.Instance.UpdateHandlePose(); if (leftController != null && leftHand.Exist) leftController.SetLocalPositionAndRotation(HandleControllerSession.controllerPose_left.position, HandleControllerSession.controllerPose_left.rotation); if (rightController != null && rightHand.Exist) rightController.SetLocalPositionAndRotation(HandleControllerSession.controllerPose_right.position, HandleControllerSession.controllerPose_right.rotation); } /// /// 初始化注册,监听手柄生命状态 /// /// 绑定状态改变的回调事件 /// 连接状态改变的回调事件 /// 电量改变的回调事件 public void InitRegistration(Action bindingEventCallback, Action connectedEventCallback, Action powerChangedCallback) { InitRegistration(bindingEventCallback, connectedEventCallback, powerChangedCallback, null, null, null); } /// /// 初始化注册,监听手柄生命状态 /// /// 绑定状态改变的回调事件 /// 连接状态改变的回调事件 /// 电量改变的回调事件 /// 跟踪状态改变的回调事件(3/6dof) public void InitRegistration(Action bindingEventCallback, Action connectedEventCallback, Action powerChangedCallback, Action trackingStateChangedCallback) { InitRegistration(bindingEventCallback, connectedEventCallback, powerChangedCallback, null, null, null); trackingChangedActions.Add(trackingStateChangedCallback); } /// /// 初始化注册,监听手柄生命状态 /// /// 绑定状态改变的回调事件 /// 连接状态改变的回调事件 /// 电量改变的回调事件 /// 按键状态改变的回调 /// 握持状态改变的回调 /// 静置状态改变的回调 public void InitRegistration(Action bindingEventCallback, Action connectedEventCallback, Action powerChangedCallback, Action buttonChangedCallback, Action holdChangedCallback, Action silenceChangedCallback) { bindingActions.Add(bindingEventCallback); connectedActions.Add(connectedEventCallback); powerChangedActions.Add(powerChangedCallback); silenceChangedActions.Add(silenceChangedCallback); holdChangedActions.Add(holdChangedCallback); buttonChangedActions.Add(buttonChangedCallback); } /// /// 进行手柄配对 /// public bool BindHandle(HandType handType) { return HandleControllerSession.Instance.BindHandle((int)handType); } /// /// 取消手柄配对 /// public bool UnbindHandle(HandType handType) { return HandleControllerSession.Instance.UnbindHandle((int)handType); } /// /// 手柄震动,震动等级 1-8,震动时长 0-65535 ms /// public bool VibrateHandle(HandType handType, int level, int time) { return HandleControllerSession.Instance.VibrateHandle((int)handType, level, time); } /// /// 获取手柄绑定状态 /// /// /// public bool GetBindState(HandType handType) { return HandleControllerSession.Instance.GetBindState(handType); } /// /// 获取手柄连接状态 /// public bool GetConnectState(HandType handType) { return HandleControllerSession.Instance.GetConnectState((int)handType); } /// /// 获取手柄电量 /// public float GetPowerStats(HandType handType) { return HandleControllerSession.Instance.GetPowerStats((int)handType); } /// /// 手柄按键是否按下 /// public bool GetButtonDown(HandType handType, HandleKeyCode keyCode) { if (handType == HandType.Left) return leftHand.GetButtonDown(keyCode); else return rightHand.GetButtonDown(keyCode); } /// /// 手柄按键是否弹起 /// public bool GetButtonUp(HandType handType, HandleKeyCode keyCode) { if (handType == HandType.Left) return leftHand.GetButtonUp(keyCode); else return rightHand.GetButtonUp(keyCode); } /// /// 手柄按键是否长按 /// public bool GetButton(HandType handType, HandleKeyCode keyCode) { if (handType == HandType.Left) return leftHand.GetButton(keyCode); else return rightHand.GetButton(keyCode); } /// /// 获取手柄摇杆坐标 /// /// 左手柄or右手柄 /// 坐标范围[-1,-1]到[1,1],复位为[0,0] public Vector2 GetAxis2D(HandType handType) { if (handType == HandType.Left) return leftHand.GetAxis2D(); else return rightHand.GetAxis2D(); } // 控制器统一管理时,激活手柄功能 public void SetActive(bool value) { //var controller = handType == HandType.Left ? leftController : rightController; //controller.GetComponent().enabled = true; //for (int i = 0; i < controller.childCount; i++) //{ // controller.GetChild(i).gameObject.SetActive(true); //} gameObject.SetActive(value); if (value) { //(handType == HandType.Left ? leftController : rightController).gameObject.SetActive(false); //StartCoroutine(SetActive_WaitForSeconds(handType, value)); //var handInfo = handType == HandType.Left ? leftHand : rightHand; //StartCoroutine(handInfo.CheckStatus()); StartCoroutine(leftHand.CheckStatus()); StartCoroutine(rightHand.CheckStatus()); } } private IEnumerator SetActive_WaitForSeconds(HandType handType, bool value) { yield return new WaitForSeconds(1); (handType == HandType.Left ? leftController : rightController).gameObject.SetActive(value); } private void OnBindingEventCallback(HandType handType, bool status) { if (handType == HandType.Left) { leftHand.UpdateBindingState(status, _status => { bindingActions.ForEach(action => { if (action != null) action(HandType.Left, _status); }); }); } else { rightHand.UpdateBindingState(status, _status => { bindingActions.ForEach(action => { if (action != null) action(HandType.Right, _status); }); }); } } private void OnConnectEventCallback(HandType handType, bool connected) { if (handType == HandType.Left) { leftHand.UpdateConnectedState(connected, _connected => { connectedActions.ForEach(action => { if (action != null) action(HandType.Left, _connected); }); }); } else { rightHand.UpdateConnectedState(connected, _connected => { connectedActions.ForEach(action => { if (action != null) action(HandType.Right, _connected); }); }); } } private void OnPowerStatsChangedCallback(HandType handType, float power) { if (handType == HandType.Left) { leftHand.UpdatePowerStats(power, _power => { powerChangedActions.ForEach(action => { if (action != null) action(HandType.Left, _power); }); }); } else { rightHand.UpdatePowerStats(power, _power => { powerChangedActions.ForEach(action => { if (action != null) action(HandType.Right, _power); }); }); } } private void OnButtonEventCallback(HandType handType, HandleKeyCode keycode, bool pressed) { if (handType == HandType.Left) { leftHand.UpdateButtonState(keycode, pressed); buttonChangedActions.ForEach(action => { if (action != null) action(HandType.Left, pressed); }); } else { rightHand.UpdateButtonState(keycode, pressed); buttonChangedActions.ForEach(action => { if (action != null) action(HandType.Right, pressed); }); } } private void OnAxis2DEventCallback(HandType handType, Vector2 coord) { if (handType == HandType.Left) leftHand.UpdateAxis2D(coord); else rightHand.UpdateAxis2D(coord); } private void OnHoldEventCallback(HandType handType, HandleKeyCode keycode, bool isHeld) { if (handType == HandType.Left) { leftHand.UpdateHoldState(isHeld, _isHeld => { holdChangedActions.ForEach(action => { if (action != null) action(HandType.Left, _isHeld); }); }); } else { rightHand.UpdateHoldState(isHeld, _isHeld => { holdChangedActions.ForEach(action => { if (action != null) action(HandType.Right, _isHeld); }); }); } } private void OnSilenceEventCallback(HandType handType, bool silent) { if (handType == HandType.Left) { leftHand.UpdateSilenceState(silent, _silent => { silenceChangedActions.ForEach(action => { if (action != null) action(HandType.Left, _silent); }); }); } else { rightHand.UpdateSilenceState(silent, _silent => { silenceChangedActions.ForEach(action => { if (action != null) action(HandType.Right, _silent); }); }); } } private void OnTrackingStateChangedCallback(HandType handType, int state) //state 0: 6dof,1: 3dof { if (handType == HandType.Left) { trackingChangedActions.ForEach(action => { if (action != null) action(HandType.Left, state); }); } else { trackingChangedActions.ForEach(action => { if (action != null) action(HandType.Right, state); }); } } /// /// 定时刷新手柄电量 /// /// private IEnumerator WaitForTimeout() { yield return new WaitForSeconds(3); if (leftHand.Exist) OnPowerStatsChangedCallback(HandType.Left, GetPowerStats(HandType.Left)); if (rightHand.Exist) OnPowerStatsChangedCallback(HandType.Right, GetPowerStats(HandType.Right)); while (true) { yield return new WaitForSeconds(300); if (leftHand.Exist) OnPowerStatsChangedCallback(HandType.Left, GetPowerStats(HandType.Left)); if (rightHand.Exist) OnPowerStatsChangedCallback(HandType.Right, GetPowerStats(HandType.Right)); } } } }