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
}
}