using UnityEngine; using System; using UnityEngine.EventSystems; using Rokid.UXR.Native; using Rokid.UXR.Module; using Rokid.UXR.Utility; namespace Rokid.UXR.Interaction { /// /// The 3dof event input class provides an external interface for 3dof interaction /// public class ThreeDofEventInput : MonoSingleton, IEventInput { public static event Action OnPhoneRayForward; public static event Action OnOriRot; public static event Action OnActiveThreeDofModule; public static event Action OnReleaseThreeDofModule; public static event Action OnThreeDofReset; public Transform Interactor { get; set; } private bool dragging = false; private float[] data = new float[4]; private Quaternion rotation = Quaternion.identity; private bool initialize = false; private bool muteModuleActiveSound = false; private bool MuteModuleActiveSound { get { return muteModuleActiveSound; } set { muteModuleActiveSound = value; } } private HandType hand = HandType.None; public HandType HandType { get { return hand; } set { hand = value; } } private string persistKey = "uxr_threedofray_offset"; private Vector3 cameraOffset = new Vector3(0, 0, 0); protected override void Awake() { NativeInterface.NativeAPI.OpenPhoneTracker(); RKPointerLisener.OnPointerDragBegin += OnPointerDragBegin; RKPointerLisener.OnPointerDragEnd += OnPointerDragEnd; } private void Start() { if (SystemInfo.deviceModel.Equals("Rokid RG-stationPro")) { string value = NativeInterface.NativeAPI.GetPersistValue(persistKey); if (!string.IsNullOrEmpty(value)) { float offsetY = Convert.ToSingle(value); RKLog.KeyInfo("====ThreeDofEventController==== GetOffsetY : " + offsetY); biasRotation = new Vector3(0, offsetY, 0); } cameraOffset = new Vector3(0, NativeInterface.NativeAPI.GetHeadPoseOffset().rotation.eulerAngles.y, 0); } } private void OnPointerDragBegin(PointerEventData data) { dragging = true; } private void OnPointerDragEnd(PointerEventData data) { dragging = false; } private void Update() { if (!initialize) return; if (InputModuleManager.Instance.GetThreeDofActive()) { if (RKNativeInput.Instance.GetKeyDown(RKKeyEvent.KEY_RESET_RAY) || IsDoubleClick()) { ResetImuAxisY(); } } else if (Utils.IsAndroidPlatfrom()) { if (Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.RightArrow) || Input.GetKeyUp(KeyCode.UpArrow) || Input.GetKeyUp(KeyCode.DownArrow) || RKNativeInput.Instance.GetKeyUp(RKKeyEvent.KEY_LEFT) || RKNativeInput.Instance.GetKeyUp(RKKeyEvent.KEY_RIGHT) || RKNativeInput.Instance.GetKeyUp(RKKeyEvent.KEY_UP) || RKNativeInput.Instance.GetKeyUp(RKKeyEvent.KEY_DOWN) || Input.GetKeyUp(KeyCode.JoystickButton0) || Input.GetKeyDown(KeyCode.Joystick1Button3) || Input.GetKeyDown(KeyCode.JoystickButton3) || IsDoubleClick()) { ActiveModule(); ResetImuAxisY(); } } #if UNITY_EDITOR if (Input.GetKeyDown(KeyCode.H)) { ActiveModule(); ResetImuAxisY(); } #endif NativeInterface.NativeAPI.GetPhonePose(data); rotation[0] = data[0]; rotation[1] = data[1]; rotation[2] = -data[2]; rotation[3] = data[3]; OnData(rotation); } public void Initialize(Transform parent) { if (Interactor == null) { GameObject go = GameObject.Find("ThreeDofRayInteractor"); if (go == null) { go = GameObject.Instantiate(Resources.Load("Prefabs/Interactor/ThreeDofRayInteractor")); } Interactor = go.transform; Interactor.name = "ThreeDofRayInteractor"; Interactor.SetParent(transform); } Interactor.SetParent(transform); this.transform.SetParent(parent); initialize = true; } public void Release() { OnReleaseThreeDofModule?.Invoke(); Destroy(this.gameObject); } public void ActiveModule() { ThreeDofEventInput.OnActiveThreeDofModule?.Invoke(); RKVirtualController.Instance.Change(ControllerType.PHONE3DOF); EventSystem.current.pixelDragThreshold = 60; } // private void OnApplicationPause(bool pauseStatus) // { // if (pauseStatus) // { // NativeInterface.NativeAPI.ClosePhoneTracker(); // } // else // { // NativeInterface.NativeAPI.OpenPhoneTracker(); // } // } protected override void OnDestroy() { // SDK 不再关闭3dof 射线算法 // NativeInterface.NativeAPI.ClosePhoneTracker(); OnPhoneRayForward = null; RKPointerLisener.OnPointerDragBegin -= OnPointerDragBegin; RKPointerLisener.OnPointerDragEnd -= OnPointerDragEnd; initialize = false; } Vector3 biasRotation = Vector3.zero; Vector3 localRotation = Vector3.zero; Vector3 laserRotation = Vector3.zero; Quaternion phoneRotation = Quaternion.identity; void OnData(Quaternion q) { phoneRotation = q; laserRotation = q.eulerAngles; //调整射线和实际的偏差值,biasRotation用来重置摄像方向 localRotation = laserRotation + biasRotation; Loom.QueueOnMainThread(() => { OnPhoneRayForward?.Invoke(localRotation); OnOriRot?.Invoke(q.eulerAngles); }); } public void ResetImuAxisY() { biasRotation = new Vector3(0, MainCameraCache.mainCamera.transform.rotation.eulerAngles.y - laserRotation.y, 0); RKLog.KeyInfo("====ThreeDofEventController==== 重置ImuAxisY : " + laserRotation); if (SystemInfo.deviceModel.Equals("Rokid RG-stationPro")) NativeInterface.NativeAPI.SetPersistValue(persistKey, biasRotation.y.ToString()); // PlayModuleChangeAudio(); OnThreeDofReset?.Invoke(); } #region IsLongDown float longDownTime = 1.5f; float downTime = 0; bool triggerLongDown; private bool IsLongDown() { // Disalbe LongPress when enable Button Mouse & TouchPad mode if (InputModuleManager.Instance.GetButtonMouseActive() || InputModuleManager.Instance.GetTouchPadActive()) { return false; } if (Input.GetKeyDown(KeyCode.JoystickButton0) || Input.GetMouseButtonDown(0)) { triggerLongDown = false; downTime = 0; } if ((Input.GetKey(KeyCode.JoystickButton0) || Input.GetMouseButton(0)) && !triggerLongDown) { downTime += Time.deltaTime; if (downTime > longDownTime) { triggerLongDown = true; return true; } } return false; } #endregion #region IsDoubleClick float doubleClickTime = 2.0f; float clickTime = 0; int clickCount = 0; private bool IsDoubleClick() { clickTime += Time.deltaTime; if (Input.touchCount > 0) { Touch touch = Input.GetTouch(0); if (touch.phase == TouchPhase.Began) { clickCount++; } } if (Input.GetKeyDown(KeyCode.Joystick1Button3) || Input.GetKeyDown(KeyCode.JoystickButton3)) { clickCount++; } if (clickTime < doubleClickTime) { if (clickCount == 2) { clickTime = 0; clickCount = 0; return true; } } else { clickCount = 0; clickTime = 0; } return false; } #endregion } }