// Copyright 2019 Nibiru. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Collections;
using NibiruTask;
using NibiruAxis;
using UnityEngine.SceneManagement;
namespace Nxr.Internal
{
///
///
///
[AddComponentMenu("NXR/NxrViewer")]
public class NxrViewer : MonoBehaviour
{
// base 2.3.0.xxxx release
public const string NXR_SDK_VERSION = "2.5.0.0_20220121";
// 退出Kill Process
public const bool IsAndroidKillProcess = true;
// dtr or not
public static bool USE_DTR = true;
private static int _texture_count = 6;
// 绘制前事件标识
public static int kPreRenderEvent = 1;
// 头部角度限制范围
private float[] headEulerAnglesRange = null;
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
Debug.Log("OnSceneLoaded->" + scene.name + " , Triggered=" + Triggered);
SceneManager.sceneLoaded -= OnSceneLoaded;
}
/// The singleton instance of the NvrViewer class.
public static NxrViewer Instance
{
get
{
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
USE_DTR = false;
if (instance == null && !Application.isPlaying)
{
Debug.Log("Create NxrViewer Instance !");
instance = FindObjectOfType();
}
#endif
if (instance == null)
{
Debug.LogError("No NxrViewer instance found. Ensure one exists in the scene, or call "
+ "NxrViewer.Create() at startup to generate one.\n"
+ "If one does exist but hasn't called Awake() yet, "
+ "then this error is due to order-of-initialization.\n"
+ "In that case, consider moving "
+ "your first reference to NxrViewer.Instance to a later point in time.\n"
+ "If exiting the scene, this indicates that the NxrViewer object has already "
+ "been destroyed.");
}
return instance;
}
}
private static NxrViewer instance = null;
public NxrEye[] eyes = new NxrEye[2];
private byte[] winTypeName = new byte[]
{110, 120, 114, 46, 78, 118, 114, 87, 105, 110, 66, 97, 115, 101}; //N/v/r/W/i/n/B/a/s/e
/// Generate a NxrViewer instance. Takes no action if one already exists.
public static void Create()
{
if (instance == null && FindObjectOfType() == null)
{
Debug.Log("Creating NxrViewerMain object");
var go = new GameObject("NxrViewerMain", typeof(NxrViewer));
go.transform.localPosition = Vector3.zero;
// sdk will be set by Awake().
}
}
/// The StereoController instance attached to the main camera, or null if there is none.
/// @note Cached for performance.
public NxrStereoController Controller
{
get
{
if (currentController == null)
{
currentController = FindObjectOfType();
}
return currentController;
}
}
private NxrStereoController currentController;
[SerializeField] public HMD_TYPE HmdType = HMD_TYPE.NONE;
/// Whether to draw directly to the output window (_true_), or to an offscreen buffer
/// first and then blit (_false_). If you wish to use Deferred Rendering or any
/// Image Effects in stereo, turn this option off. A common symptom that indicates
/// you should do so is when one of the eyes is spread across the entire screen.
[SerializeField] private bool openEffectRender = false;
///
/// false-Processing after closing,true-Processing after opening
///
public bool OpenEffectRender
{
get { return openEffectRender; }
set
{
if (value != openEffectRender)
{
openEffectRender = value;
}
}
}
/// Determine whether the scene renders in stereo or mono.
/// _True_ means to render in stereo, and _false_ means to render in mono.
public bool SplitScreenModeEnabled
{
get { return splitScreenModeEnabled; }
set
{
if (value != splitScreenModeEnabled && device != null)
{
device.SetSplitScreenModeEnabled(value);
}
splitScreenModeEnabled = value;
}
}
[SerializeField] private bool splitScreenModeEnabled = true;
///
/// Get/Set Head Control
///
public HeadControl HeadControl
{
get { return headControlEnabled; }
set
{
headControlEnabled = value;
UpdateHeadControl();
}
}
[SerializeField] private HeadControl headControlEnabled = HeadControl.GazeApplication;
public float Duration
{
get { return duration; }
set { duration = value; }
}
[SerializeField] private float duration = 2;
NxrReticle mNxrReticle;
public NxrReticle GetNxrReticle()
{
InitNxrReticleScript();
return mNxrReticle;
}
public void DismissReticle()
{
GetNxrReticle().Dismiss();
}
public void ShowReticle()
{
GetNxrReticle().Show();
}
private void InitNxrReticleScript()
{
if (mNxrReticle == null)
{
GameObject nxrReticleObject = GameObject.Find("NxrReticle");
if (nxrReticleObject != null)
{
mNxrReticle = nxrReticleObject.GetComponent();
if (mNxrReticle == null)
{
Debug.LogError("Not Find NxrReticle.cs From GameObject NxrReticle !!!");
}
}
else
{
Debug.LogError("Not Find NxrReticle GameObject !!!");
}
}
}
///
/// Show head control
///
public void ShowHeadControl()
{
InitNxrReticleScript();
if (mNxrReticle != null)
{
mNxrReticle.HeadShow();
Debug.Log("ShowHeadControl");
}
}
///
/// Hide head control
///
public void HideHeadControl()
{
InitNxrReticleScript();
if (mNxrReticle != null)
{
mNxrReticle.HeadDismiss();
Debug.Log("HideHeadControl");
}
}
// App自行处理Trigger按键,SDK不处理。如果SDK处理默认当做确认键使用。
///
/// Is app handle trigger event
///
public bool IsAppHandleTriggerEvent
{
get { return appHandleTriggerEvent; }
set { appHandleTriggerEvent = value; }
}
[SerializeField] private bool appHandleTriggerEvent = false;
public bool TrackerPosition
{
get { return trackerPosition; }
set { trackerPosition = value; }
}
///
/// Whether to use third-party displacement data.
///
public bool UseThirdPartyPosition
{
get { return useThirdPartyPosition; }
set { useThirdPartyPosition = value; }
}
[SerializeField] private bool useThirdPartyPosition = false;
#if UNITY_STANDALONE_WIN || ANDROID_REMOTE_NRR
[SerializeField]
private FrameRate targetFrameRate = FrameRate.FPS_60;
public FrameRate TargetFrameRate
{
get
{
return targetFrameRate;
}
set
{
if (value != targetFrameRate)
{
targetFrameRate = value;
}
}
}
#endif
// 纹理抗锯齿
[SerializeField] public TextureMSAA textureMsaa = TextureMSAA.MSAA_2X;
public TextureMSAA TextureMSAA
{
get { return textureMsaa; }
set
{
if (value != textureMsaa)
{
textureMsaa = value;
}
}
}
[SerializeField] private bool trackerPosition = true;
[Serializable]
public class NxrSettings
{
[Tooltip("Change Timewarp Status")] public int timewarpEnabled = -1; //-1=not set,0=close,1=open
[Tooltip("Change Sync Frame Status")] public bool syncFrameEnabled = false;
}
[SerializeField] public NxrSettings settings = new NxrViewer.NxrSettings();
// Remote Debug
[SerializeField] private bool remoteDebug = false;
public bool RemoteDebug
{
get { return remoteDebug; }
set
{
if (value != remoteDebug)
{
remoteDebug = value;
}
}
}
[SerializeField] private bool remoteController = false;
public bool RemoteController
{
get { return remoteController; }
set
{
if (value != remoteController)
{
remoteController = value;
}
}
}
// FPS
[SerializeField] private bool showFPS = false;
public bool ShowFPS
{
get { return showFPS; }
set
{
if (value != showFPS)
{
showFPS = value;
}
}
}
// 纹理质量
[SerializeField] public TextureQuality textureQuality = TextureQuality.Better;
public TextureQuality TextureQuality
{
get { return textureQuality; }
set
{
if (value != textureQuality)
{
textureQuality = value;
}
}
}
[SerializeField] private bool requestLock = false;
///
/// Lock head tracker.
///
public bool LockHeadTracker
{
get { return requestLock; }
set
{
if (value != requestLock)
{
requestLock = value;
}
}
}
public bool InitialRecenter { get; set; }
///
/// Lock head posture.
///
public void RequestLock()
{
if (device != null)
{
device.NLockTracker();
}
}
///
/// Unlock head posture.
///
public void RequestUnLock()
{
if (device != null)
{
device.NUnLockTracker();
}
}
private bool IsNativeGazeShow = false;
///
/// Change Gaze's size/color/status
///
///
public void GazeApi(GazeTag tag)
{
GazeApi(tag, "");
}
public void TurnOff()
{
device.TurnOff();
}
public void Reboot()
{
device.Reboot();
}
///
/// The parameter of Param behind GazeTag.Show and GazeTag.Hide is passed "".
///
///
///
public void GazeApi(GazeTag tag, string param)
{
if (device != null)
{
bool rslt = device.GazeApi(tag, param);
if (tag == GazeTag.Show)
{
bool useDFT = USE_DTR && !NxrGlobal.supportDtr;
IsNativeGazeShow = useDFT ? true : rslt;
}
else if (tag == GazeTag.Hide)
{
IsNativeGazeShow = false;
}
}
}
///
/// Switch to controller mode
///
///
public void SwitchControllerMode(bool enabled)
{
// Debug.LogError("SwitchControllerMode:" + enabled);
if (enabled)
{
HeadControl = HeadControl.Controller;
}
else
{
//
HeadControl = HeadControl.GazeApplication;
}
}
///
/// Switch application reticle mode
/// true-force using reticle
/// false-use system reticle
///
///
private void SwitchApplicationReticle(bool enabled)
{
InitNxrReticleScript();
bool IsControllerMode = HeadControl == HeadControl.Controller;
if (enabled)
{
if (mNxrReticle != null) mNxrReticle.Show();
GazeInputModule.gazePointer = mNxrReticle;
}
else if (!enabled && (!NxrGlobal.isVR9Platform || IsControllerMode))
{
if (mNxrReticle != null)
{
mNxrReticle.Dismiss();
}
GazeInputModule.gazePointer = null;
}
if (enabled)
{
GazeApi(GazeTag.Hide);
}
}
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
/// The screen size to emulate when testing in the Unity Editor.
public NxrProfile.ScreenSizes ScreenSize
{
get { return screenSize; }
set
{
if (value != screenSize)
{
screenSize = value;
if (device != null)
{
device.UpdateScreenData();
}
}
}
}
[SerializeField] private NxrProfile.ScreenSizes screenSize = NxrProfile.ScreenSizes.Nexus5;
/// The viewer type to emulate when testing in the Unity Editor.
public NxrProfile.ViewerTypes ViewerType
{
get { return viewerType; }
set
{
if (value != viewerType)
{
viewerType = value;
if (device != null)
{
device.UpdateScreenData();
}
}
}
}
[SerializeField] private NxrProfile.ViewerTypes viewerType = NxrProfile.ViewerTypes.CardboardMay2015;
#endif
// The AR device that will be providing input data.
private static BaseARDevice device;
public RenderTexture GetStereoScreen(int eye)
{
// Don't need it except for distortion correction.
if (!splitScreenModeEnabled || NxrGlobal.isVR9Platform)
{
return null;
}
if (eyeStereoScreens[0] == null)
{
// 初始化6个纹理
InitEyeStereoScreens();
}
if (Application.isEditor || (NxrViewer.USE_DTR && !NxrGlobal.supportDtr))
{
// DFT or Editor
return eyeStereoScreens[0];
}
// 获取对应索引的纹理
return eyeStereoScreens[eye + _current_texture_index];
}
// 初始创建6个纹理,左右各3个 【左右左右左右】
public RenderTexture[] eyeStereoScreens = new RenderTexture[_texture_count];
private void InitEyeStereoScreens()
{
InitEyeStereoScreens(-1, -1);
}
// 初始化
private void InitEyeStereoScreens(int width, int height)
{
RealeaseEyeStereoScreens();
#if UNITY_ANDROID || UNITY_EDITOR || UNITY_STANDALONE_WIN
bool useDFT = NxrViewer.USE_DTR && !NxrGlobal.supportDtr;
if (!USE_DTR || useDFT || IsWinPlatform)
{
// 编辑器模式 or 不支持DTR的DFT模式 只生成1个纹理
RenderTexture rendetTexture = device.CreateStereoScreen(width, height);
if (!rendetTexture.IsCreated())
{
rendetTexture.Create();
}
int tid = (int) rendetTexture.GetNativeTexturePtr();
for (int i = 0; i < _texture_count; i++)
{
eyeStereoScreens[i] = rendetTexture;
_texture_ids[i] = tid;
}
}
else
{
for (int i = 0; i < _texture_count; i++)
{
eyeStereoScreens[i] = device.CreateStereoScreen(width, height);
eyeStereoScreens[i].Create();
_texture_ids[i] = (int) eyeStereoScreens[i].GetNativeTexturePtr();
}
}
#endif
}
// 释放所有纹理
private void RealeaseEyeStereoScreens()
{
for (int i = 0; i < _texture_count; i++)
{
if (eyeStereoScreens[i] != null)
{
eyeStereoScreens[i].Release();
eyeStereoScreens[i] = null;
_texture_ids[i] = 0;
}
}
Resources.UnloadUnusedAssets();
Debug.Log("RealeaseEyeStereoScreens");
}
/// Describes the current device, including phone screen.
public NxrProfile Profile
{
get { return device.Profile; }
}
/// Distinguish the stereo eyes.
public enum Eye
{
Left,
/// The left eye
Right,
/// The right eye
Center /// The "center" eye (unused)
}
/// When retrieving the #Projection and #Viewport properties, specifies
/// whether you want the values as seen through the viewer's lenses (`Distorted`) or
/// as if no lenses were present (`Undistorted`).
public enum Distortion
{
Distorted,
/// Viewing through the lenses
Undistorted /// No lenses
}
/// The transformation of head from origin in the tracking system.
public Pose3D HeadPose
{
get { return device.GetHeadPose(); }
}
/// The projection matrix for a given eye.
/// This matrix is an off-axis perspective projection with near and far
/// clipping planes of 1m and 1000m, respectively. The NxrEye script
/// takes care of adjusting the matrix for its particular camera.
public Matrix4x4 Projection(Eye eye, Distortion distortion = Distortion.Distorted)
{
return device.GetProjection(eye, distortion);
}
/// The screen space viewport that the camera for the specified eye should render into.
/// In the _Distorted_ case, this will be either the left or right half of the `StereoScreen`
/// render texture. In the _Undistorted_ case, it refers to the actual rectangle on the
/// screen that the eye can see.
public Rect Viewport(Eye eye, Distortion distortion = Distortion.Distorted)
{
return device.GetViewport(eye, distortion);
}
private void InitDevice()
{
if (device != null)
{
device.Destroy();
}
// 根据当前运行场景获取对应的设备对象
device = BaseARDevice.GetDevice();
device.Init();
device.SetSplitScreenModeEnabled(splitScreenModeEnabled);
// 更新界面数据
device.UpdateScreenData();
GazeApi(GazeTag.Show);
GazeApi(GazeTag.Set_Size, ((int) GazeSize.Original).ToString());
}
// Windows Editor/Player
public bool IsWinPlatform { get; set; }
NxrInput nxrInput;
/// @note Each scene load causes an OnDestroy of the current SDK, followed
/// by and Awake of a new one. That should not cause the underlying native
/// code to hiccup. Exception: developer may call Application.DontDestroyOnLoad
/// on the SDK if they want it to survive across scene loads.
void Awake()
{
Debug.Log("NxrViewer Awake");
SettingsAssetConfig asset;
#if UNITY_EDITOR
asset = NxrSDKApi.Instance.GetSettingsAssetConfig();
#else
asset = Resources.Load("Config/SettingsAssetConfig");
#endif
sixDofMode = asset.mSixDofMode;
sleepTimeoutMode = asset.mSleepTimeoutMode;
headControlEnabled = asset.mHeadControl;
textureQuality = asset.mTextureQuality;
textureMsaa = asset.mTextureMSAA;
InitialRecenter = true;
nxrInput = new NxrInput();
IsWinPlatform = false;
Debug.Log("SettingsAssetConfig:" + asset.mSixDofMode + "--" + asset.mSleepTimeoutMode + "--" +
asset.mHeadControl + "--" + asset.mTextureQuality + "--" + asset.mTextureMSAA);
#if UNITY_STANDALONE_WIN || ANDROID_REMOTE_NRR
IsWinPlatform = true;
#endif
if (instance == null)
{
instance = this;
Loom.Initialize();
if (Application.isMobilePlatform)
{
QualitySettings.antiAliasing = 0;
Application.runInBackground = false;
Input.gyro.enabled = false;
Debug.Log("SleepTimeout:" + SleepMode.ToString());
if (SleepMode == SleepTimeoutMode.NEVER_SLEEP)
{
// Disable screen dimming
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
else
{
Screen.sleepTimeout = SleepTimeout.SystemSetting;
}
}
}
if (instance != this)
{
Debug.LogError("There must be only one NxrViewer object in a scene.");
DestroyImmediate(this);
return;
}
UnityEngine.SceneManagement.SceneManager.sceneLoaded += OnSceneLoaded;
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
// 编辑器PASS
nxr.NibiruXR.instance.Init(gameObject);
#endif
InitDevice();
if (!IsWinPlatform && !NxrGlobal.supportDtr && !NxrGlobal.isVR9Platform)
{
// 录屏功能需要使用2个脚本 [VR9不需要]
// 非DTR需要
AddPrePostRenderStages();
}
Debug.Log("Is Windows Platform : " + IsWinPlatform + ", ScreenInfo : " + Screen.width + "*" +
Screen.height + ", AntiAliasing : " + QualitySettings.antiAliasing);
#if UNITY_ANDROID
// 在unity20172.0f3版本使用-1相当于half vsync,所以此处设置为90fps。目前机器最高就是90
int targetFrameRate = Application.platform == RuntimePlatform.Android
? ((int) NxrGlobal.refreshRate > 0 ? (int) NxrGlobal.refreshRate : 90)
: 60;
if (NxrGlobal.isVR9Platform)
{
// 参考全志官方
targetFrameRate = 60;
textureMsaa = TextureMSAA.NONE;
}
Application.targetFrameRate = targetFrameRate;
#endif
if (Application.platform != RuntimePlatform.Android)
{
NxrSDKApi.Instance.IsInXRMode = true;
}
// not use dtr //
if (!NxrGlobal.supportDtr || NxrGlobal.isVR9Platform)
{
QualitySettings.vSyncCount = 1;
if (NxrGlobal.offaxisDistortionEnabled)
{
Application.targetFrameRate = Application.platform == RuntimePlatform.Android
? (int) NxrGlobal.refreshRate
: -1;
Debug.Log("offaxisDistortionEnabled : Setting frame rate to " + Application.targetFrameRate);
}
}
else
{
// we sync in the TimeWarp, so we don't want unity syncing elsewhere
QualitySettings.vSyncCount = 0;
}
#if UNITY_STANDALONE_WIN || ANDROID_REMOTE_NRR
if (IsWinPlatform)
{
QualitySettings.vSyncCount = 0;
Application.targetFrameRate = (int)targetFrameRate;
// don't require companion window focus
Application.runInBackground = true;
QualitySettings.maxQueuedFrames = -1;
QualitySettings.antiAliasing = Mathf.Max(QualitySettings.antiAliasing, (int)TextureMSAA);
}
#endif
#if UNITY_ANDROID && UNITY_EDITOR
//GraphicsDeviceType[] graphicsDeviceType = UnityEditor.PlayerSettings.GetGraphicsAPIs(UnityEditor.BuildTarget.Android);
// Debug.Log("GraphicsDeviceType------->" + graphicsDeviceType[0].ToString());
//if (graphicsDeviceType[0] != GraphicsDeviceType.OpenGLES2)
//{
// string title = "Incompatible graphics API detected!";
// string message = "Please set graphics API to \"OpenGL ES 2.0\" and rebuild, or Some Api may not work as expected .";
// UnityEditor.EditorUtility.DisplayDialog(title, message, "OK");
// Debug.LogError(title + " " + message);
//}
#if UNITY_EDITOR
string defineSymbols =
UnityEditor.PlayerSettings.GetScriptingDefineSymbolsForGroup(UnityEditor.BuildTargetGroup.Android);
if (defineSymbols == null || !defineSymbols.Contains("NIBIRU_"))
{
string title = "Hmd Type Not Configed!";
string message = "Please Choose Hmd Type in Menu \nNibiruXR->XR Settings .";
UnityEditor.EditorUtility.DisplayDialog(title, message, "OK");
Debug.LogError(title + " " + message);
}
#endif
#endif
device.AndroidLog("Welcome to use Unity NXR SDK , current SDK VERSION is " + NXR_SDK_VERSION + ", j " +
NxrGlobal.jarVersion
+ ", s " + NxrGlobal.soVersion + ", u " + Application.unityVersion + ", fps " +
Application.targetFrameRate + ", vsync "
+ QualitySettings.vSyncCount + ", hmd " + HmdType + ", antiAliasing : " +
QualitySettings.antiAliasing
+ ", SixDofMode : " + sixDofMode.ToString());
AddStereoControllerToCameras();
}
public delegate void NibiruConfigCallback(NxrInstantNativeApi.Nibiru_Config cfg);
NibiruConfigCallback _nvrConfigCallback;
void Start()
{
//lx changed for 5.4:在Awake中执行,不然在NxrArmModel调用之前Head还没创建
//AddStereoControllerToCameras();
if (IsWinPlatform)
{
// 初始化光学参数
_nvrConfigCallback += OnNibiruConfigCallback;
NxrInstantNativeApi.SetNibiruConfigCallback(_nvrConfigCallback);
#if NIBIRU_DEBUG
NvrInstantNativeApi.Inited = false;
Debug.Log("NvrInstantNativeApi.Init.Not Called.");
#else
int _textureWidth = 1920, _textureHeight = 1080;
NxrInstantNativeApi.NvrInitParams param;
param.renderWidth = _textureWidth;
param.renderHeight = _textureHeight;
param.bitRate = 30;
NxrInstantNativeApi.Inited = NxrInstantNativeApi.Init(param);
Debug.Log("NxrInstantNativeApi.Init.Called.");
NxrInstantNativeApi.GetVersionInfo(ref NxrInstantNativeApi.nativeApiVersion,
ref NxrInstantNativeApi.driverVersion);
Debug.Log("NxrInstantNativeApi.Version.Api." + NxrInstantNativeApi.nativeApiVersion + ",Driver." +
NxrInstantNativeApi.driverVersion);
if (NxrInstantNativeApi.nativeApiVersion >= 2000)
{
NxrInstantNativeApi.GetTextureResolution(ref _textureWidth, ref _textureHeight);
if (NxrInstantNativeApi.driverVersion >= 2002)
{
UInt32 rateData = NxrInstantNativeApi.GetRefreshRate();
Debug.Log("-------------rateData--------" + rateData);
if (rateData >= 60)
{
Application.targetFrameRate = (int) rateData;
}
}
}
if (eyeStereoScreens[0] == null && !NxrGlobal.isVR9Platform)
{
// 初始化6个纹理
InitEyeStereoScreens(_textureWidth, _textureHeight);
}
if (eyeStereoScreens[0] != null)
{
// 设置Texturew Native Ptr
NxrInstantNativeApi.SetFrameTexture(eyeStereoScreens[0].GetNativeTexturePtr());
Debug.Log("NxrInstantNativeApi.SetFrameTexture." + eyeStereoScreens[0].GetNativeTexturePtr());
}
#endif
Debug.Log("NxrInstantNativeApi.Init. Size " + param.renderWidth + "*" + param.renderHeight + ", Bit " +
param.bitRate + ", Inited " + NxrInstantNativeApi.Inited);
}
else
{
if (eyeStereoScreens[0] == null && !NxrGlobal.isVR9Platform)
{
// 初始化6个纹理
InitEyeStereoScreens();
device.SetTextureSizeNative(eyeStereoScreens[0].width, eyeStereoScreens[1].height);
}
}
if (ShowFPS)
{
Transform[] father;
father = GetComponentsInChildren(true);
GameObject FPS = null;
foreach (Transform child in father)
{
if (child.gameObject.name == "NxrFPS")
{
FPS = child.gameObject;
break;
}
}
if (FPS != null)
{
FPS.SetActive(ShowFPS);
}
else
{
GameObject fpsGo = Instantiate(Resources.Load("Prefabs/NxrFPS")) as GameObject;
#if UNITY_ANDROID && !UNITY_EDITOR
fpsGo.GetComponent().enabled = false;
fpsGo.AddComponent();
#else
fpsGo.GetComponent().enabled = true;
#endif
}
}
UpdateHeadControl();
NxrSDKApi.Instance.SixDofControllerPrimaryDeviceType = device.GetSixDofControllerPrimaryDeviceType();
// 6dof双手柄
gameObject.AddComponent();
}
public void UpdateHeadControl()
{
return;
// Debug.LogError("UpdateHeadControl=" + HeadControl.ToString());
// 已经设置强制使用Unity白点,不做处理
switch (HeadControl)
{
case HeadControl.GazeApplication:
SwitchApplicationReticle(true);
GetNxrReticle().HeadDismiss();
break;
case HeadControl.GazeSystem:
SwitchApplicationReticle(false);
GetNxrReticle().HeadDismiss();
GazeApi(GazeTag.Show);
break;
case HeadControl.Hover:
GetNxrReticle().HeadShow();
SwitchApplicationReticle(true);
break;
case HeadControl.Controller:
SwitchApplicationReticle(false);
GetNxrReticle().HeadDismiss();
GazeApi(GazeTag.Hide);
break;
}
}
private NxrHead head;
///
/// Get the NxrHead
///
///
public NxrHead GetHead()
{
if (head == null && Controller != null)
{
head = Controller.Head;
}
if (head == null)
{
head = FindObjectOfType();
}
return head;
}
///
/// The displacement data of Third-party.
///
///
public void Update3rdPartyPosition(Vector3 position)
{
NxrHead mHead = GetHead();
if (mHead != null)
{
mHead.Update3rdPartyPosition(position);
}
}
private void OnNibiruConfigCallback(NxrInstantNativeApi.Nibiru_Config cfg)
{
Loom.QueueOnMainThread((param) =>
{
device.Profile.viewer.lenses.separation = cfg.ipd;
//-0.03048, 0.03, -0.03402, 0.03402
device.ComputeEyesForWin(NxrViewer.Eye.Left, cfg.near, 1000, cfg.eyeFrustumParams[0],
cfg.eyeFrustumParams[3], cfg.eyeFrustumParams[1], cfg.eyeFrustumParams[2]);
//-0.03, 0.03048, -0.03402, 0.03402
device.ComputeEyesForWin(NxrViewer.Eye.Right, cfg.near, 1000, cfg.eyeFrustumParams[4],
cfg.eyeFrustumParams[7], cfg.eyeFrustumParams[5], cfg.eyeFrustumParams[6]);
// 手柄类型
NxrControllerHelper.InitController((int) cfg.controllerType);
device.profileChanged = true;
Debug.Log("OnNibiruConfigCallback Config : Ipd " + cfg.ipd + ", Near " + cfg.near +
", FrustumLeft(LRBT) " + cfg.eyeFrustumParams[0] + ", " + cfg.eyeFrustumParams[1] + ","
+ cfg.eyeFrustumParams[2] + ", " + cfg.eyeFrustumParams[3] + ", ControllerType " +
cfg.controllerType);
TrackerPosition = true;
{
NxrHead head = GetHead();
if (head != null)
{
head.SetTrackPosition(TrackerPosition);
}
}
NxrButtonEvent mNvrButtonEvent = GameObject.FindObjectOfType();
if (mNvrButtonEvent != null)
{
mNvrButtonEvent.RefreshTrackedDevices();
}
device.profileChanged = true;
}, cfg);
}
private int baseTryTimes = 1;
private void Update()
{
UpdateState();
if (!NxrGlobal.isVR9Platform)
{
UpdateEyeTexture();
}
if (GazeInputModule.gazePointer != null)
{
GazeInputModule.gazePointer.UpdateStatus();
}
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
if (baseTryTimes < 5 && gameObject.GetComponent(System.Text.Encoding.Default.GetString(winTypeName)) == null)
{
baseTryTimes++;
nxr.NibiruXR.instance.Init(gameObject);
Debug.Log("Run NibiruXR Init in Update(), " + baseTryTimes);
}
#endif
if (nxrInput != null)
{
nxrInput.Process();
}
}
public BaseARDevice GetDevice()
{
return device;
}
///
/// Print log using android logcat.
///
///
public void AndroidLog(string msg)
{
if (device != null)
{
device.AndroidLog(msg);
}
else
{
Debug.Log(msg);
}
}
public void UpdateHeadPose()
{
if (device != null && NxrSDKApi.Instance.IsInXRMode)
device.UpdateState();
}
public void UpdateEyeTexture()
{
// 更新左右眼目标纹理
if (USE_DTR && NxrGlobal.supportDtr)
{
// 更换纹理索引
SwapBuffers();
NxrEye[] eyes = NxrViewer.Instance.eyes;
for (int i = 0; i < 2; i++)
{
NxrEye eye = eyes[i];
if (eye != null)
{
eye.UpdateTargetTexture();
}
}
}
}
void AddPrePostRenderStages()
{
var preRender = FindObjectOfType();
if (preRender == null)
{
var go = new GameObject("PreRender", typeof(NxrPreRender));
go.SendMessage("Reset");
go.transform.parent = transform;
Debug.Log("Add NxrPreRender");
}
var postRender = FindObjectOfType();
if (postRender == null)
{
var go = new GameObject("PostRender", typeof(NxrPostRender));
go.SendMessage("Reset");
go.transform.parent = transform;
Debug.Log("Add NxrPostRender");
}
}
/// Whether the viewer's trigger was pulled. True for exactly one complete frame
/// after each pull
public bool Triggered { get; set; }
public bool ProfileChanged { get; private set; }
// Only call device.UpdateState() once per frame.
private int updatedToFrame = 0;
/// Reads the latest tracking data from the phone. This must be
/// called before accessing any of the poses and matrices above.
///
/// Multiple invocations per frame are OK: Subsequent calls merely yield the
/// cached results of the first call. To minimize latency, it should be first
/// called later in the frame (for example, in `LateUpdate`) if possible.
public void UpdateState()
{
if (updatedToFrame != Time.frameCount)
{
updatedToFrame = Time.frameCount;
DispatchEvents();
if (NeedUpdateNearFar && device != null && device.nibiruVRServiceId != 0)
{
float far = GetCameraFar();
float mNear = 0.0305f;
if (NxrGlobal.fovNear > -1)
{
mNear = NxrGlobal.fovNear;
}
device.SetCameraNearFar(mNear, far);
Instance.NeedUpdateNearFar = false;
for (int i = 0; i < 2; i++)
{
NxrEye eye = eyes[i];
if (eye != null)
{
if (eye.cam.farClipPlane < NxrGlobal.fovFar)
{
eye.cam.farClipPlane = NxrGlobal.fovFar;
}
}
}
}
}
}
// ///
// /// Analog all-in-one button: W-Up A-Left S-Down D-Right Space-Return Return-Confirm
// ///
// private void SimulateHeadSetKeyEvent()
// {
// if (!Application.isEditor && !(Application.platform == RuntimePlatform.WindowsPlayer))
// {
// // 编辑器 or win
// return;
// }
//
// if (Input.GetKeyDown(KeyCode.W))
// {
// TriggerKeyEvent(KeyCode.UpArrow, false);
// }
// else if (Input.GetKeyUp(KeyCode.W))
// {
// TriggerKeyEvent(KeyCode.UpArrow, true);
// }
// else if (Input.GetKeyDown(KeyCode.S))
// {
// TriggerKeyEvent(KeyCode.DownArrow, false);
// }
// else if (Input.GetKeyUp(KeyCode.S))
// {
// TriggerKeyEvent(KeyCode.DownArrow, true);
// }
// else if (Input.GetKeyDown(KeyCode.A))
// {
// TriggerKeyEvent(KeyCode.LeftArrow, false);
// }
// else if (Input.GetKeyUp(KeyCode.A))
// {
// TriggerKeyEvent(KeyCode.LeftArrow, true);
// }
// else if (Input.GetKeyDown(KeyCode.D))
// {
// TriggerKeyEvent(KeyCode.RightArrow, false);
// }
// else if (Input.GetKeyUp(KeyCode.D))
// {
// TriggerKeyEvent(KeyCode.RightArrow, true);
// }
// else if (Input.GetKeyDown(KeyCode.Space))
// {
// TriggerKeyEvent(KeyCode.Escape, false);
// }
// else if (Input.GetKeyUp(KeyCode.Space))
// {
// TriggerKeyEvent(KeyCode.Escape, true);
// }
// else if (Input.GetKeyDown(KeyCode.Return))
// {
// TriggerKeyEvent(KeyCode.JoystickButton0, false);
// }
// else if (Input.GetKeyUp(KeyCode.Return))
// {
// TriggerKeyEvent(KeyCode.JoystickButton0, true);
// }
//
// }
// List btnLiseners = null;
List joystickListeners = null;
int[] lastKeyAction;
private void DispatchEvents()
{
// Update flags first by copying from device and other inputs.
if (device == null) return;
// if (Input.GetMouseButton(0) && !Triggered)
// {
// Triggered = Input.GetMouseButtonDown(0);
// }
ProfileChanged = device.profileChanged;
if (device.profileChanged)
{
if (NxrOverrideSettings.OnProfileChangedEvent != null) NxrOverrideSettings.OnProfileChangedEvent();
device.profileChanged = false;
}
// 模拟一体机按键
// SimulateHeadSetKeyEvent();
bool IsHasController = false;
if (Application.platform == RuntimePlatform.Android)
{
// 3dof or nolo
IsHasController = (NxrPlayerCtrl.Instance.IsQuatConn() || ControllerAndroid.IsNoloConn());
}
else if (IsWinPlatform)
{
IsHasController = NxrControllerHelper.Is3DofControllerConnected &&
NxrPlayerCtrl.Instance.GamepadEnabled;
}
if (IsHasController)
{
int[] KeyAction = null;
if (InteractionManager.IsControllerConnected())
{
KeyAction = InteractionManager.GetKeyAction();
}
else
{
KeyAction = NibiruTaskApi.GetKeyAction();
}
// if (KeyAction[CKeyEvent.KEYCODE_DPAD_CENTER] == 0)
// {
// Triggered = true;
// }
if (lastKeyAction == null)
{
lastKeyAction = KeyAction;
}
for (int i = 0; i < CKeyEvent.KeyCodeIds.Length; i++)
{
int keyCode = CKeyEvent.KeyCodeIds[i];
if (KeyAction[keyCode] == 0 && lastKeyAction[keyCode] == 1)
{
// down
// TriggerKeyEventForController(keyCode, false);
}
if (KeyAction[keyCode] == 1 && lastKeyAction[keyCode] == 0)
{
// up
// TriggerKeyEventForController(keyCode, true);
}
}
lastKeyAction = KeyAction;
}
//
// 手柄上下左右兼容处理
float leftKeyHor = Input.GetAxis("5th axis");
float leftKeyVer = Input.GetAxis("6th axis");
if (leftKeyHor == 1)
{
// 左
// TriggerKeyEvent(KeyCode.LeftArrow);
TriggerJoystickEvent(16, 0);
}
else if (leftKeyHor == -1)
{
// 右
// TriggerKeyEvent(KeyCode.RightArrow);
TriggerJoystickEvent(17, 0);
}
if (leftKeyVer == -1)
{
// 上
// TriggerKeyEvent(KeyCode.UpArrow);
TriggerJoystickEvent(14, 0);
}
else if (leftKeyVer == 1)
{
// 下
// TriggerKeyEvent(KeyCode.DownArrow);
TriggerJoystickEvent(15, 0);
}
// 左摇杆
float leftStickHor = Input.GetAxis("joystick_Horizontal");
float leftStickVer = Input.GetAxis("joystick_Vertical");
if (leftStickHor != 0)
{
TriggerJoystickEvent(10, leftStickHor);
}
if (leftStickVer != 0)
{
TriggerJoystickEvent(11, leftStickVer);
}
// 右摇杆
float rightStickHor = Input.GetAxis("3th axis");
float rightStickVer = Input.GetAxis("4th axis");
if (rightStickHor != 0)
{
TriggerJoystickEvent(12, rightStickHor);
}
if (rightStickVer != 0)
{
TriggerJoystickEvent(13, rightStickVer);
}
//
if (Application.platform == RuntimePlatform.Android && Input.anyKeyDown)
{
bool triggerDirectKey = false;
Event e = Event.current;
if (e != null && e.isKey)
{
KeyCode currentKey = e.keyCode;
Debug.Log("Current Key is : " + currentKey.ToString());
// if ((int)currentKey == 10 || currentKey == KeyCode.LeftArrow || currentKey == KeyCode.RightArrow || currentKey == KeyCode.UpArrow || currentKey == KeyCode.DownArrow || currentKey == KeyCode.Escape
// || currentKey == KeyCode.JoystickButton0)
// {
// if ((int)currentKey == 10 || currentKey == KeyCode.JoystickButton0)
// {
// // ok 键
// Triggered = true;
// }
triggerDirectKey = currentKey == KeyCode.LeftArrow || currentKey == KeyCode.RightArrow ||
currentKey == KeyCode.UpArrow || currentKey == KeyCode.DownArrow;
// TriggerKeyEvent(currentKey);
// }
// 手柄
if (currentKey == KeyCode.LeftShift)
{
TriggerJoystickEvent(0, 0);
}
else if (currentKey == KeyCode.LeftAlt)
{
TriggerJoystickEvent(1, 0);
}
else if (currentKey == KeyCode.RightShift)
{
TriggerJoystickEvent(2, 0);
}
else if (currentKey == KeyCode.RightAlt)
{
TriggerJoystickEvent(3, 0);
}
else if (currentKey == KeyCode.Pause)
{
TriggerJoystickEvent(4, 0);
}
else if (currentKey == KeyCode.Return)
{
TriggerJoystickEvent(5, 0);
}
else if (currentKey == KeyCode.JoystickButton2)
{
TriggerJoystickEvent(6, 0);
}
else if (currentKey == KeyCode.JoystickButton3)
{
TriggerJoystickEvent(7, 0);
}
else if (currentKey == KeyCode.JoystickButton1)
{
TriggerJoystickEvent(8, 0);
}
else if (currentKey == KeyCode.JoystickButton0)
{
TriggerJoystickEvent(9, 0);
}
else if (currentKey == KeyCode.JoystickButton8)
{
TriggerJoystickEvent(18, 0);
}
else if (currentKey == KeyCode.JoystickButton9)
{
TriggerJoystickEvent(19, 0);
}
}
}
// up 事件
// if (Application.platform == RuntimePlatform.Android &&
// (Input.GetKeyUp(KeyCode.JoystickButton0) || Input.GetKeyUp((KeyCode)10)))
// {
// TriggerKeyEvent(KeyCode.JoystickButton0, true);
// }
if (Application.platform == RuntimePlatform.Android && Event.current != null &&
(Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.RightArrow)
|| Input.GetKeyUp(KeyCode.DownArrow) ||
Input.GetKeyUp(KeyCode.UpArrow)
|| Input.GetKeyUp(KeyCode.Escape)))
{
Debug.Log("KeyUp===>" + Event.current.keyCode.ToString());
if (NibiruRemindBox.Instance.Showing())
{
NibiruRemindBox.Instance.ReleaseDestory();
}
if (NibiruShutDownBox.Instance.Showing())
{
NibiruShutDownBox.Instance.ReleaseDestory();
}
// else
// {
// TriggerKeyEvent(Event.current.keyCode, true);
// }
}
}
// private void TriggerKeyEvent(KeyCode currentKey)
// {
// TriggerKeyEvent(currentKey, false);
// }
// private void TriggerKeyEvent(KeyCode currentKey, bool isKeyUp)
// {
// if (btnLiseners == null || btnLiseners.Count == 0)
// {
// List allObject = GetAllObjectsInScene();
// btnLiseners = new List();
// foreach (GameObject obj in allObject)
// {
// Component[] comps = obj.GetComponents(typeof(INxrButtonListener));
// if (comps != null)
// {
// INxrButtonListener[] listeners = new INxrButtonListener[comps.Length];
//
// for (int p = 0; p < comps.Length; p++)
// {
// listeners[p] = (INxrButtonListener)comps[p];
// }
// // 获取所有挂载了INxrButtonListener的物体
// NotifyBtnPressed(listeners, currentKey, isKeyUp);
// foreach (Component cp in comps)
// {
// btnLiseners.Add((INxrButtonListener)cp);
// }
// }
// }
// }
// else
// {
// NotifyBtnPressed(btnLiseners.ToArray(), currentKey, isKeyUp);
// }
// }
// private void NotifyBtnPressed(INxrButtonListener[] comps, KeyCode currentKey, bool isKeyUp)
// {
// if (comps == null) return;
// for (int i = 0, length = comps.Length; i < length; i++)
// {
// INxrButtonListener btnListener = (INxrButtonListener)comps[i];
// if (btnListener == null) continue;
// if (currentKey == KeyCode.LeftArrow)
// {
// if (isKeyUp) { btnListener.OnLiftLeft(); } else { btnListener.OnPressLeft(); }
// }
// else if (currentKey == KeyCode.RightArrow)
// {
// if (isKeyUp) { btnListener.OnLiftRight(); } else { btnListener.OnPressRight(); }
// }
// else if (currentKey == KeyCode.UpArrow)
// {
// if (isKeyUp) { btnListener.OnLiftUp(); } else { btnListener.OnPressUp(); }
// }
// else if (currentKey == KeyCode.DownArrow)
// {
// if (isKeyUp) { btnListener.OnLiftDown(); } else { btnListener.OnPressDown(); }
// }
// else if (currentKey == KeyCode.Escape)
// {
// if (isKeyUp) { btnListener.OnLiftBack(); } else { btnListener.OnPressBack(); }
// }
// else if (currentKey == KeyCode.JoystickButton0 || (int)currentKey == 10)
// {
// btnListener.OnPressEnter(isKeyUp);
// }
// else if (currentKey == KeyCode.Joystick5Button18)
// {
// // 音量加
// btnListener.OnPressVolumnUp();
// }
// else if (currentKey == KeyCode.Joystick5Button19)
// {
// // 音量减
// btnListener.OnPressVolumnDown();
// }
// else if (currentKey == KeyCode.Joystick6Button1)
// {
// // Left
// if (isKeyUp)
// {
// btnListener.OnLiftFuctionKey(FunctionKeyCode.NF1);
// }
// else
// {
// btnListener.OnFuctionKeyDown(FunctionKeyCode.NF1);
// }
// }
// else if (currentKey == KeyCode.Joystick6Button2)
// {
// // Right
// if (isKeyUp)
// {
// btnListener.OnLiftFuctionKey(FunctionKeyCode.NF2);
// }
// else
// {
// btnListener.OnFuctionKeyDown(FunctionKeyCode.NF2);
// }
// }
// }
//
// }
// private void TriggerKeyEventForController(int keycode, bool isKeyUp)
// {
// if(NibiruRemindBox.Instance.Showing() && keycode == CKeyEvent.KEYCODE_BUTTON_APP && isKeyUp)
// {
// NibiruRemindBox.Instance.ReleaseDestory();
// return;
// }
//
// if (btnLiseners == null || btnLiseners.Count == 0)
// {
// List allObject = GetAllObjectsInScene();
// btnLiseners = new List();
// foreach (GameObject obj in allObject)
// {
// Component[] comps = obj.GetComponents(typeof(INxrButtonListener));
// if (comps != null)
// {
// INxrButtonListener[] listeners = new INxrButtonListener[comps.Length];
//
// for (int p = 0; p < comps.Length; p++)
// {
// listeners[p] = (INxrButtonListener)comps[p];
// }
// // 获取所有挂载了INvrButtonListener的物体
// NotifyBtnPressedForController(listeners, keycode, isKeyUp);
// foreach (Component cp in comps)
// {
// btnLiseners.Add((INxrButtonListener)cp);
// }
// }
// }
// }
// else
// {
// NotifyBtnPressedForController(btnLiseners.ToArray(), keycode, isKeyUp);
// }
// }
// private void NotifyBtnPressedForController(INxrButtonListener[] comps, int keycode, bool isKeyUp)
// {
// if (comps == null) return;
// for (int i = 0, length = comps.Length; i < length; i++)
// {
// INxrButtonListener btnListener = comps[i];
// if (btnListener == null) continue;
// if (keycode == CKeyEvent.KEYCODE_DPAD_LEFT)
// {
// if (isKeyUp) { btnListener.OnLiftLeft(); } else { btnListener.OnPressLeft(); }
// }
// else if (keycode == CKeyEvent.KEYCODE_DPAD_RIGHT)
// {
// if (isKeyUp) { btnListener.OnLiftRight(); } else { btnListener.OnPressRight(); }
// }
// else if (keycode == CKeyEvent.KEYCODE_DPAD_UP)
// {
// if (isKeyUp) { btnListener.OnLiftUp(); } else { btnListener.OnPressUp(); }
// }
// else if (keycode == CKeyEvent.KEYCODE_DPAD_DOWN)
// {
// if (isKeyUp) { btnListener.OnLiftDown(); } else { btnListener.OnPressDown(); }
// }
// else if (keycode == CKeyEvent.KEYCODE_BUTTON_APP)
// {
// // MENU
// if (isKeyUp)
// {
// btnListener.OnLiftFuctionKey(FunctionKeyCode.MENU);
// }
// else
// {
// btnListener.OnFuctionKeyDown(FunctionKeyCode.MENU);
// }
// }
// else if (keycode == CKeyEvent.KEYCODE_DPAD_CENTER)
// {
// // TOUCH PAD CLICK
// if (isKeyUp)
// {
// btnListener.OnLiftFuctionKey(FunctionKeyCode.TOUCHPAD);
// }
// else
// {
// btnListener.OnFuctionKeyDown(FunctionKeyCode.TOUCHPAD);
// }
// }
// else if (keycode == CKeyEvent.KEYCODE_VOLUME_UP)
// {
// // 音量加
// btnListener.OnPressVolumnUp();
// if (isKeyUp)
// {
// btnListener.OnLiftFuctionKey(FunctionKeyCode.VOLUMN_UP);
// }
// else
// {
// btnListener.OnFuctionKeyDown(FunctionKeyCode.VOLUMN_UP);
// }
// }
// else if (keycode == CKeyEvent.KEYCODE_VOLUME_DOWN)
// {
// // 音量减
// btnListener.OnPressVolumnDown();
// if (isKeyUp)
// {
// btnListener.OnLiftFuctionKey(FunctionKeyCode.VOLUMN_DOWN);
// }
// else
// {
// btnListener.OnFuctionKeyDown(FunctionKeyCode.VOLUMN_DOWN);
// }
// }
// else if (keycode == CKeyEvent.KEYCODE_BUTTON_R1)
// {
// // trigger
// if (isKeyUp)
// {
// btnListener.OnLiftFuctionKey(FunctionKeyCode.TRIGGER);
// }
// else
// {
// btnListener.OnFuctionKeyDown(FunctionKeyCode.TRIGGER);
// }
// }
// else if (keycode == CKeyEvent.KEYCODE_CONTROLLER_TOUCHPAD_TOUCH)
// {
// // touch pad
// if (isKeyUp)
// {
// btnListener.OnLiftFuctionKey(FunctionKeyCode.TOUCHPAD_TOUCH);
// }
// else
// {
// btnListener.OnFuctionKeyDown(FunctionKeyCode.TOUCHPAD_TOUCH);
// }
// }
// }
//
// }
///
/// Resets the tracker so that the user's current direction becomes forward.
///
public void Recenter()
{
device.Recenter();
if (GetHead() != null)
{
GetHead().ResetInitEulerYAngle();
}
}
/// Add a StereoController to any camera that does not have a Render Texture (meaning it is
/// rendering to the screen).
public static void AddStereoControllerToCameras()
{
for (int i = 0; i < Camera.allCameras.Length; i++)
{
Camera camera = Camera.allCameras[i];
Debug.Log("Check Camera : " + camera.name);
if (
(camera.tag == "MainCamera" || camera.tag == "NibiruCamera")
&& camera.targetTexture == null &&
camera.GetComponent() == null &&
camera.GetComponent() == null &&
camera.GetComponent() == null &&
camera.GetComponent() == null)
{
camera.gameObject.AddComponent();
}
}
}
void OnEnable()
{
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
// This can happen if you edit code while the editor is in Play mode.
if (device == null)
{
InitDevice();
}
#endif
device.OnPause(false);
if (!NxrGlobal.isVR9Platform)
{
StartCoroutine("EndOfFrame");
}
}
void OnDisable()
{
device.OnPause(true);
Debug.Log("NxrViewer->OnDisable");
StopCoroutine("EndOfFrame");
}
private Coroutine onResume = null;
void OnPause()
{
onResume = null;
device.OnApplicationPause(true);
}
IEnumerator OnResume()
{
yield return new WaitForSeconds(1.0f);
// resume
if (!NxrGlobal.isVR9Platform && NxrGlobal.supportDtr)
{
InitNxrReticleScript();
UpdateHeadControl();
}
device.OnApplicationPause(false);
}
public void SetPause(bool pause)
{
if (pause)
{
OnPause();
}
else if (onResume == null)
{
onResume = StartCoroutine(OnResume());
}
}
void OnApplicationPause(bool pause)
{
Debug.Log("NxrViewer->OnApplicationPause," + pause + ", hasEnterXRMode=" + NxrSDKApi.Instance.IsInXRMode);
SetPause(pause);
}
void OnApplicationFocus(bool focus)
{
Debug.Log("NxrViewer->OnApplicationFocus," + focus);
device.OnFocus(focus);
}
void OnApplicationQuit()
{
if (GetNibiruService() != null && GetNibiruService().IsMarkerRecognizeRunning)
{
GetNibiruService().StopMarkerRecognize();
}
StopAllCoroutines();
device.OnApplicationQuit();
if (NxrOverrideSettings.OnApplicationQuitEvent != null)
{
NxrOverrideSettings.OnApplicationQuitEvent();
}
Debug.Log("NxrViewer->OnApplicationQuit");
#if UNITY_ANDROID && !UNITY_EDITOR
if(IsAndroidKillProcess)
{
NxrSDKApi.Instance.Destroy();
Debug.Log("NxrViewer->OnApplicationQuit.KillProcess");
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
#endif
}
///
/// Quit app
///
public void AppQuit()
{
device.AppQuit();
}
void OnDestroy()
{
if (IsWinPlatform)
{
if (NxrInstantNativeApi.Inited)
{
_nvrConfigCallback -= OnNibiruConfigCallback;
NxrInstantNativeApi.Inited = false;
NxrInstantNativeApi.Cleanup();
NxrControllerHelper.Reset();
}
}
// if (btnLiseners != null)
// {
// btnLiseners.Clear();
// }
// btnLiseners = null;
this.SplitScreenModeEnabled = false;
InteractionManager.Reset();
if (device != null)
{
device.Destroy();
}
if (instance == this)
{
instance = null;
}
Debug.Log("NxrViewer->OnDestroy");
}
// 处理来自Android的调用
public void ResetHeadTrackerFromAndroid()
{
if (instance != null && device != null)
{
Recenter();
}
NibiruRemindBox.Instance.ReleaseDestory();
NibiruShutDownBox.Instance.ReleaseDestory();
}
void OnVolumnUp()
{
// TriggerKeyEvent(KeyCode.Joystick5Button18);
if (nxrInput != null)
{
nxrInput.OnChangeKeyEvent(CKeyEvent.KEYCODE_VOLUME_DOWN, CKeyEvent.ACTION_DOWN);
}
}
void OnVolumnDown()
{
// TriggerKeyEvent(KeyCode.Joystick5Button19);
if (nxrInput != null)
{
nxrInput.OnChangeKeyEvent(CKeyEvent.KEYCODE_VOLUME_UP, CKeyEvent.ACTION_DOWN);
}
}
void OnKeyDown(string keyCode)
{
Debug.Log("OnKeyDown=" + keyCode);
if (keyCode == NxrGlobal.KeyEvent_KEYCODE_ALT_LEFT)
{
// TriggerKeyEvent(KeyCode.Joystick6Button1, false);
if (nxrInput != null)
{
nxrInput.OnChangeKeyEvent(CKeyEvent.KEYCODE_NF_1, CKeyEvent.ACTION_DOWN);
}
}
else if (keyCode == NxrGlobal.KeyEvent_KEYCODE_MEDIA_RECORD)
{
// TriggerKeyEvent(KeyCode.Joystick6Button2, false);
if (nxrInput != null)
{
nxrInput.OnChangeKeyEvent(CKeyEvent.KEYCODE_NF_2, CKeyEvent.ACTION_DOWN);
}
}
}
void OnKeyUp(string keyCode)
{
Debug.Log("OnKeyUp=" + keyCode);
if (keyCode == NxrGlobal.KeyEvent_KEYCODE_ALT_LEFT)
{
// TriggerKeyEvent(KeyCode.Joystick6Button1, true);
if (nxrInput != null)
{
nxrInput.OnChangeKeyEvent(CKeyEvent.KEYCODE_NF_1, CKeyEvent.ACTION_UP);
}
}
else if (keyCode == NxrGlobal.KeyEvent_KEYCODE_MEDIA_RECORD)
{
// TriggerKeyEvent(KeyCode.Joystick6Button2, true);
if (nxrInput != null)
{
nxrInput.OnChangeKeyEvent(CKeyEvent.KEYCODE_NF_2, CKeyEvent.ACTION_UP);
}
}
}
void OnActivityPause()
{
Debug.Log("OnActivityPause");
}
void OnActivityResume()
{
Debug.Log("OnActivityResume");
}
///
/// Set system split mode : 1=split by system,0=split by app
///
public void SetSystemSplitMode(int flag)
{
device.NSetSystemSplitMode(flag);
}
private int[] _texture_ids = new int[_texture_count];
private int _current_texture_index, _next_texture_index;
public bool SwapBuffers()
{
bool ret = true;
for (int i = 0; i < _texture_count; i++)
{
if (!eyeStereoScreens[i].IsCreated())
{
eyeStereoScreens[i].Create();
_texture_ids[i] = (int) eyeStereoScreens[i].GetNativeTexturePtr();
ret = false;
}
}
_current_texture_index = _next_texture_index;
_next_texture_index = (_next_texture_index + 2) % _texture_count;
return ret;
}
public int GetEyeTextureId(int eye)
{
return _texture_ids[_current_texture_index + (int) eye];
}
public int GetTimeWarpViewNum()
{
return device.GetTimewarpViewNumber();
}
public List GetAllObjectsInScene()
{
GameObject[] pAllObjects = (GameObject[]) Resources.FindObjectsOfTypeAll(typeof(GameObject));
List pReturn = new List();
foreach (GameObject pObject in pAllObjects)
{
if (pObject == null || !pObject.activeInHierarchy || pObject.hideFlags == HideFlags.NotEditable ||
pObject.hideFlags == HideFlags.HideAndDontSave)
{
continue;
}
pReturn.Add(pObject);
}
return pReturn;
}
public Texture2D createTexture2D(RenderTexture renderTexture)
{
int width = renderTexture.width;
int height = renderTexture.height;
Texture2D texture2D = new Texture2D(width, height, TextureFormat.ARGB32, false);
RenderTexture.active = renderTexture;
texture2D.ReadPixels(new Rect(0, 0, width, height), 0, 0);
texture2D.Apply();
return texture2D;
}
private int frameCount = 0;
private void EndOfFrameCore()
{
if (USE_DTR && (!NxrSDKApi.Instance.IsInXRMode && frameCount < 3))
{
frameCount++;
Debug.Log("EndOfFrame->hasEnterRMode " + "" + NxrSDKApi.Instance.IsInXRMode + " or frameCount " +
frameCount);
// Call GL.clear before Enter VRMode to avoid unexpected graph breaking.
GL.Clear(false, true, Color.black);
}
else
{
frameCount++;
if (USE_DTR && NxrGlobal.supportDtr)
{
if (settings.timewarpEnabled >= 0 && frameCount > 0 && frameCount < 10)
{
device.SetTimeWarpEnable(false);
}
if (NxrGlobal.DEBUG_LOG_ENABLED) Debug.Log("EndOfFrame.TimeWarp[" + frameCount + "]");
// Debug.Log("TimeWrap." + frameCount);
}
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
// Submit
if (NxrInstantNativeApi.Inited)
{
GL.IssuePluginEvent(NxrInstantNativeApi.GetRenderEventFunc(),
(int) NxrInstantNativeApi.RenderEvent.SubmitFrame);
}
#endif
}
bool IsHeadPoseUpdated = device.IsHeadPoseUpdated();
if (USE_DTR && NxrGlobal.supportDtr && IsHeadPoseUpdated)
NxrPluginEvent.IssueWithData(NibiruRenderEventType.TimeWarp, NxrViewer.Instance.GetTimeWarpViewNum());
}
IEnumerator EndOfFrame()
{
while (true)
{
yield return new WaitForEndOfFrame();
EndOfFrameCore();
}
}
public int GetFrameId()
{
return frameCount;
}
private void TriggerJoystickEvent(int index, float axisValue)
{
if (joystickListeners == null)
{
List allObject = GetAllObjectsInScene();
joystickListeners = new List();
foreach (GameObject obj in allObject)
{
Component[] joystickcomps = obj.GetComponents(typeof(INxrJoystickListener));
if (joystickcomps != null)
{
INxrJoystickListener[] listeners = new INxrJoystickListener[joystickcomps.Length];
for (int p = 0; p < joystickcomps.Length; p++)
{
listeners[p] = (INxrJoystickListener) joystickcomps[p];
}
// INibiruJoystickListener
notifyJoystickPressed(listeners, index, axisValue);
foreach (Component cp in joystickcomps)
{
joystickListeners.Add((INxrJoystickListener) cp);
}
}
}
}
else
{
notifyJoystickPressed(joystickListeners.ToArray(), index, axisValue);
}
}
private void notifyJoystickPressed(INxrJoystickListener[] comps, int index, float axisValue)
{
if (comps == null) return;
for (int i = 0; i < comps.Length; i++)
{
INxrJoystickListener joystickListener = (INxrJoystickListener) comps[i];
if (joystickListener == null) continue;
switch (index)
{
case 0:
// l1
joystickListener.OnPressL1();
break;
case 1:
// l2
joystickListener.OnPressL2();
break;
case 2:
// r1
joystickListener.OnPressR1();
break;
case 3:
// r2
joystickListener.OnPressR2();
break;
case 4:
// select
joystickListener.OnPressSelect();
break;
case 5:
// start
joystickListener.OnPressStart();
break;
case 6:
// x
joystickListener.OnPressX();
break;
case 7:
// y
joystickListener.OnPressY();
break;
case 8:
// a
joystickListener.OnPressA();
break;
case 9:
// b
joystickListener.OnPressB();
break;
case 10:
// leftstickx
joystickListener.OnLeftStickX(axisValue);
break;
case 11:
// leftsticky
joystickListener.OnLeftStickY(axisValue);
break;
case 12:
// rightstickx
joystickListener.OnRightStickX(axisValue);
break;
case 13:
// rightsticky
joystickListener.OnRightStickY(axisValue);
break;
case 14:
// dpad-up
joystickListener.OnPressDpadUp();
break;
case 15:
// dpad-down
joystickListener.OnPressDpadDown();
break;
case 16:
// dpad-left
//joystickListener.OnPressDpadLeft();
joystickListener.OnPressDpadRight();
break;
case 17:
// dpad-right
//joystickListener.OnPressDpadRight();
joystickListener.OnPressDpadLeft();
break;
case 18:
joystickListener.OnLeftStickDown();
break;
case 19:
joystickListener.OnRightStickDown();
break;
}
}
}
private float mFar = -1;
private bool needUpdateNearFar = false;
///
/// Update the left and right camera's farClipPlane
///
///
public void UpateCameraFar(float far)
{
mFar = far;
needUpdateNearFar = true;
NxrGlobal.fovFar = far;
if (Application.isEditor || Application.platform == RuntimePlatform.WindowsPlayer)
{
// 编辑器及时生效
Camera.main.farClipPlane = far;
}
}
public float GetCameraFar()
{
return mFar;
}
public bool NeedUpdateNearFar
{
get { return needUpdateNearFar; }
set
{
if (value != needUpdateNearFar)
{
needUpdateNearFar = value;
}
}
}
private float oldFov = -1;
private Matrix4x4[] eyeOriginalProjection = null;
///
/// Update eye camera projection
///
///
public void UpdateEyeCameraProjection(Eye eye)
{
if (oldFov != -1 && eye == Eye.Right)
{
UpdateCameraFov(oldFov);
}
if (!Application.isEditor && device != null && eye == Eye.Right)
{
if (mFar > 0)
{
float mNear = 0.0305f;
if (NxrGlobal.fovNear > -1)
{
mNear = NxrGlobal.fovNear;
}
// Debug.Log("new near : " + mNear + "," + NxrGlobal.fovNear+ ",new far : " + mFar + "," + NxrGlobal.fovFar);
// 更新camera near far
float fovLeft = mNear * Mathf.Tan(-Profile.viewer.maxFOV.outer * Mathf.Deg2Rad);
float fovTop = mNear * Mathf.Tan(Profile.viewer.maxFOV.upper * Mathf.Deg2Rad);
float fovRight = mNear * Mathf.Tan(Profile.viewer.maxFOV.inner * Mathf.Deg2Rad);
float fovBottom = mNear * Mathf.Tan(-Profile.viewer.maxFOV.lower * Mathf.Deg2Rad);
//Debug.Log("fov : " +fovLeft+","+fovRight+","+fovTop+","+fovBottom);
Matrix4x4 eyeProjection =
BaseARDevice.MakeProjection(fovLeft, fovTop, fovRight, fovBottom, mNear, mFar);
for (int i = 0; i < 2; i++)
{
NxrEye mEye = eyes[i];
if (mEye != null)
{
mEye.cam.projectionMatrix = eyeProjection;
}
}
}
}
}
///
/// Reset the left and right camera's fov to default.
///
public void ResetCameraFov()
{
for (int i = 0; i < 2; i++)
{
if (eyeOriginalProjection == null || eyeOriginalProjection[i] == null) return;
NxrEye eye = eyes[i];
if (eye != null)
{
eye.cam.projectionMatrix = eyeOriginalProjection[i];
}
}
oldFov = -1;
}
///
/// Change the left and right camera's fov
/// fov range [40~90]
///
///
public void UpdateCameraFov(float fov)
{
if (fov > 90) fov = 90;
if (fov < 5) fov = 5;
// cache左右眼透视矩阵
if (eyeOriginalProjection == null && eyes[0] != null && eyes[1] != null)
{
eyeOriginalProjection = new Matrix4x4[2];
eyeOriginalProjection[0] = eyes[0].cam.projectionMatrix;
eyeOriginalProjection[1] = eyes[1].cam.projectionMatrix;
}
oldFov = fov;
float near = NxrGlobal.fovNear > 0 ? NxrGlobal.fovNear : 0.0305f;
float far = NxrGlobal.fovFar > 0 ? NxrGlobal.fovFar : 2000;
far = far > 100 ? far : 2000;
float fovLeft = near * Mathf.Tan(-fov * Mathf.Deg2Rad);
float fovTop = near * Mathf.Tan(fov * Mathf.Deg2Rad);
float fovRight = near * Mathf.Tan(fov * Mathf.Deg2Rad);
float fovBottom = near * Mathf.Tan(-fov * Mathf.Deg2Rad);
Matrix4x4 eyeProjection = BaseARDevice.MakeProjection(fovLeft, fovTop, fovRight, fovBottom, near, far);
if (device != null)
{
for (int i = 0; i < 2; i++)
{
NxrEye eye = eyes[i];
if (eye != null)
{
eye.cam.projectionMatrix = eyeProjection;
}
}
}
}
private float displacementCoefficient = 1.0f;
public float DisplacementCoefficient
{
get { return displacementCoefficient; }
set { displacementCoefficient = value; }
}
///
/// Set horizontal angle range :mid is 0,left is less than 0,right is greater than 0
///
///
///
public void SetHorizontalAngleRange(float minRange, float maxRange)
{
if (headEulerAnglesRange == null)
{
headEulerAnglesRange = new float[] {0, 360, 0, 360};
}
headEulerAnglesRange[0] = minRange + 360;
headEulerAnglesRange[1] = maxRange;
}
///
/// Set vertical angle range :mid is 0,up is less than 0,down is greater than 0
///
///
///
public void SetVerticalAngleRange(float minRange, float maxRange)
{
if (headEulerAnglesRange == null)
{
headEulerAnglesRange = new float[] {0, 360, 0, 360};
}
headEulerAnglesRange[2] = minRange + 360;
headEulerAnglesRange[3] = maxRange;
}
///
/// Remove head angle limit
///
public void RemoveAngleLimit()
{
headEulerAnglesRange = null;
}
public float[] GetHeadEulerAnglesRange()
{
return headEulerAnglesRange;
}
///
/// open system app video player
///
/// video path
/// 0=2d,1=3d mode
/// 0=normal,1=360,2=180,3=fullmode video type
/// 0=hardware,1=software decode mode
public void OpenVideoPlayer(string path, int type2D3D, int mode, int decode)
{
device.ShowVideoPlayer(path, type2D3D, mode, decode);
}
///
/// Get android SD Card's path(/storage/emulated/0)
///
/// exp: /storage/emulated/0
public string GetStoragePath()
{
return device.GetStoragePath();
}
///
/// Set the screen is always on.
///
///
public void SetIsKeepScreenOn(bool keep)
{
device.SetIsKeepScreenOn(keep);
}
private float defaultIpd = -1;
private float userIpd = -1;
///
/// Change eye's ipd
///
/// 0.064
public void SetIpd(float ipd)
{
if (defaultIpd < 0)
{
defaultIpd = GetIpd();
}
Debug.Log(" Ipd : D." + defaultIpd + "/N." + ipd);
NxrGlobal.dftProfileParams[0] = ipd; //0.063f;
userIpd = ipd;
device.SetIpd(ipd);
device.UpdateScreenData();
}
///
/// Reset ipd's change
///
public void ResetIpd()
{
if (defaultIpd < 0) return;
SetIpd(defaultIpd);
}
///
/// Get eye's ipd
///
///
public float GetIpd()
{
if (userIpd > 0) return userIpd;
return eyes[0] == null ? 0.060f : 2 * Math.Abs(eyes[0].GetComponent().transform.localPosition.x);
}
public float GetUseIpd()
{
return userIpd;
}
public void ShowSystemMenuUI()
{
if (device != null)
{
//Player = new UnityPlayer();
AndroidJavaClass Player = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
//Activity = Player.currentActivity;
AndroidJavaObject Activity = Player.GetStatic("currentActivity");
//PackageManager = Activity.getPackageManager();
AndroidJavaObject PackageNameObj = Activity.Call("getPackageName");
string packageName = PackageNameObj.Call("toString");
Debug.Log("show_nvr_menu->" + packageName);
device.SetSystemParameters("show_nvr_menu", packageName);
}
}
public delegate void ServiceReadyUpdatedDelegate(SERVICE_TYPE serviceType, bool isConnectedSucc);
public delegate void OnSixDofPosition(float x, float y, float z);
public delegate void OnMarkerLoadStatus(MARKER_LOAD_STATUS status);
///
/// Get the service connection status (after the service is connected, you can check the plug-in support status)
///
public static ServiceReadyUpdatedDelegate serviceReadyUpdatedDelegate;
///
/// hmd 6dof position' data callback
///
public static OnSixDofPosition onSixDofPosition;
public static OnMarkerLoadStatus onMarkerLoadStatus;
///
///
/// Call after script's Awake
///
///
public NibiruService GetNibiruService()
{
return device.GetNibiruService();
}
private GameObject eventReceiverVoice;
private GameObject eventReceiverGesture;
public void RegisterVoiceListener(GameObject listenerObj)
{
eventReceiverVoice = listenerObj;
}
public void RegisterGestureListener(GameObject listenerObj)
{
eventReceiverGesture = listenerObj;
}
void onHandleAndroidMsg(string msgContent)
{
// msgId_msgContent
string[] msgArr = msgContent.Split('_');
int msgId = int.Parse(msgArr[0]);
string msgData = msgArr[1];
// Debug.Log((eventReceiverVoice == null) + "-------->onHandleAndroidMsg=" + msgContent);
if (msgId == (int) MSG_ID.MSG_onServiceReady)
{
if (serviceReadyUpdatedDelegate != null)
{
SERVICE_TYPE serviceType = (SERVICE_TYPE) int.Parse(msgData);
bool connected = int.Parse(msgArr[2]) == 1;
serviceReadyUpdatedDelegate(serviceType, connected);
}
return;
}
if (msgId == (int) MSG_ID.MSG_verifyFailed)
{
NxrGlobal.verifyStatus = (VERIFY_STATUS) int.Parse(msgData);
Debug.Log("verify failed");
}
else if (msgId == (int) MSG_ID.MSG_verifySucc)
{
NxrGlobal.verifyStatus = VERIFY_STATUS.SUCC;
Debug.Log("verify succ");
}
else if (msgId == (int) MSG_ID.MSG_onKeyStoreException)
{
NxrGlobal.verifyStatus = VERIFY_STATUS.HEAD_ERROR;
Debug.Log("verify keystore exception");
}
else if (msgId == (int) MSG_ID.MSG_onHeadPosition && onSixDofPosition != null)
{
//[-0.26371408, -0.108221784, -0.05875514] [0]
string[] posStr = msgData.Substring(1, msgData.Length - 2).Split(',');
float x = (float) Math.Round(float.Parse(posStr[0]), 2);
float y = (float) Math.Round(float.Parse(posStr[1]), 2);
float z = (float) Math.Round(float.Parse(posStr[2]), 2);
// 用Loom的方法在Unity主线程中调用Text组件
if (onSixDofPosition != null)
{
onSixDofPosition(x, y, z);
}
}
else if ((MSG_ID) msgId == MSG_ID.MSG_onMarkerLoadStatus && onMarkerLoadStatus != null)
{
if (onMarkerLoadStatus != null)
{
onMarkerLoadStatus((MARKER_LOAD_STATUS) int.Parse(msgData));
}
}
if ((eventReceiverGesture != null || eventReceiverVoice != null) &&
NxrGlobal.verifyStatus == VERIFY_STATUS.SUCC)
{
object msgObj = null;
if ((MSG_ID) msgId == MSG_ID.MSG_onGestureEvent)
{
msgObj = (GESTURE_ID) int.Parse(msgData);
if (eventReceiverGesture != null)
eventReceiverGesture.BroadcastMessage(NxrGlobal.GetMethodNameById((MSG_ID) msgId), msgObj,
SendMessageOptions.DontRequireReceiver);
}
else if ((MSG_ID) msgId == MSG_ID.MSG_onVoiceVolume ||
(MSG_ID) msgId == MSG_ID.MSG_onVoiceFinishError ||
(MSG_ID) msgId == MSG_ID.MSG_onVoiceFinishResult)
{
msgObj = msgData;
if ((MSG_ID) msgId == MSG_ID.MSG_onVoiceFinishError && msgArr.Length > 1)
{
// msgId_errorcode_errormsg
msgObj = msgArr[2];
}
if (eventReceiverVoice != null)
eventReceiverVoice.BroadcastMessage(NxrGlobal.GetMethodNameById((MSG_ID) msgId), msgObj,
SendMessageOptions.DontRequireReceiver);
}
}
if ((MSG_ID) msgId == MSG_ID.MSG_onServerApiReady)
{
Loom.QueueOnMainThread((param) =>
{
bool isReady = int.Parse((string) param) == 1;
if (NibiruTaskApi.serverApiReady != null)
{
NibiruTaskApi.serverApiReady(isReady);
}
}, msgData);
}
else if ((MSG_ID) msgId == MSG_ID.MSG_onSysSleepApiReady)
{
Loom.QueueOnMainThread((param) =>
{
bool isReady = int.Parse((string) param) == 1;
if (NibiruTaskApi.sysSleepApiReady != null)
{
NibiruTaskApi.sysSleepApiReady(isReady);
}
}, msgData);
}
else if ((MSG_ID) msgId == MSG_ID.MSG_onInteractionDeviceConnectEvent)
{
InteractionManager.OnDeviceConnectState(msgContent);
}
else if ((MSG_ID) msgId == MSG_ID.MSG_onInteractionKeyEvent)
{
if (!TouchScreenKeyboard.visible)
{
InteractionManager.OnCKeyEvent(msgContent);
}
else
{
Triggered = false;
}
}
else if ((MSG_ID) msgId == MSG_ID.MSG_onInteractionTouchEvent)
{
InteractionManager.OnCTouchEvent(msgContent);
}
}
///
/// Speech Recognition:Chinese or English
///
public VOICE_LANGUAGE VoiceLanguage
{
get { return NxrGlobal.voiceLanguage; }
set
{
if (value != NxrGlobal.voiceLanguage)
{
NxrGlobal.voiceLanguage = value;
NibiruService nibiruService = device.GetNibiruService();
if (nibiruService != null)
{
nibiruService.UpdateVoiceLanguage();
}
}
}
}
[SerializeField] public SleepTimeoutMode sleepTimeoutMode = SleepTimeoutMode.NEVER_SLEEP;
[SerializeField] public ControllerSupportMode controllerSupportMode = ControllerSupportMode.NONE;
public SleepTimeoutMode SleepMode
{
get { return sleepTimeoutMode; }
set
{
if (value != sleepTimeoutMode)
{
sleepTimeoutMode = value;
}
}
}
[SerializeField] private SixDofMode sixDofMode = SixDofMode.Head_3Dof_Ctrl_6Dof;
public SixDofMode SixDofMode
{
get { return sixDofMode; }
set
{
if (value != sixDofMode)
{
sixDofMode = value;
}
}
}
///
/// Get main camera
///
///
public Camera GetMainCamera()
{
return Controller.cam;
}
///
/// Get left eye camera
///
///
public Camera GetLeftEyeCamera()
{
return Controller.Eyes[(int) Eye.Left].cam;
}
///
/// Get right eye camera
///
///
public Camera GetRightEyeCamera()
{
return Controller.Eyes[(int) Eye.Right].cam;
}
///
/// Get main camera's quaternion
///
///
public Quaternion GetCameraQuaternion()
{
return GetHead().transform.rotation;
}
///
/// Get controller's quaternion
///
///
public Quaternion GetControllerQuaternion()
{
if (IsControllerConnect())
{
return NxrPlayerCtrl.Instance.mTransform.localRotation;
}
return Quaternion.identity;
}
///
/// Set controller's active status
///
///
public void SetControllerActive(bool isActive)
{
NxrPlayerCtrl.Instance.ChangeControllerDisplay(isActive);
}
///
/// Is main camera locked
///
///
public bool IsCameraLocked()
{
return !NxrViewer.Instance.GetHead().IsTrackRotation();
}
///
/// Is controller connect
///
///
public bool IsControllerConnect()
{
return InteractionManager.IsControllerConnected();
}
///
/// Lock main camera's rotation
///
///
public void LockCamera(bool isLock)
{
NxrHead head = NxrViewer.Instance.GetHead();
head.SetTrackRotation(!isLock);
}
///
/// Get 3dof controller's ray start point
///
///
public Transform GetRayStartPoint()
{
return NxrPlayerCtrl.Instance.GetRayStartPoint();
}
///
/// Get 3dof controller's ray end point
///
///
public Transform GetRayEndPoint()
{
return NxrPlayerCtrl.Instance.GetRayEndPoint();
}
}
}