using System.Collections; using System.Collections.Generic; using UnityEngine; public class OVRRuntimeController : MonoBehaviour { /// /// The controller that determines whether or not to enable rendering of the controller model. /// public OVRInput.Controller m_controller; /// /// Shader that will be used for the controller model /// public Shader m_controllerModelShader; private GameObject m_controllerObject; private static string leftControllerModelPath = "/model_fb/controller/left"; private static string rightControllerModelPath = "/model_fb/controller/right"; private string m_controllerModelPath; private bool m_modelSupported = false; private bool m_hasInputFocus = true; private bool m_hasInputFocusPrev = false; private bool m_controllerConnectedPrev = false; // Start is called before the first frame update void Start() { if (m_controller == OVRInput.Controller.LTouch) m_controllerModelPath = leftControllerModelPath; else if (m_controller == OVRInput.Controller.RTouch) m_controllerModelPath = rightControllerModelPath; m_modelSupported = IsModelSupported(m_controllerModelPath); if (m_modelSupported) { StartCoroutine(UpdateControllerModel()); } OVRManager.InputFocusAcquired += InputFocusAquired; OVRManager.InputFocusLost += InputFocusLost; } // Update is called once per frame void Update() { bool controllerConnected = OVRInput.IsControllerConnected(m_controller); if (m_hasInputFocus != m_hasInputFocusPrev || controllerConnected != m_controllerConnectedPrev) { if (m_controllerObject != null) { m_controllerObject.SetActive(controllerConnected && m_hasInputFocus); } m_hasInputFocusPrev = m_hasInputFocus; m_controllerConnectedPrev = controllerConnected; } } private bool IsModelSupported(string modelPath) { string[] modelPaths = OVRPlugin.GetRenderModelPaths(); if (modelPaths.Length == 0) { Debug.LogError("Failed to enumerate model paths from the runtime. Check that the render model feature is enabled in OVRManager."); return false; } for (int i = 0; i < modelPaths.Length; i++) { if (modelPaths[i].Equals(modelPath)) return true; } Debug.LogError("Render model path not supported by this device."); return false; } private bool LoadControllerModel(string modelPath) { var modelProperties = new OVRPlugin.RenderModelProperties(); if (OVRPlugin.GetRenderModelProperties(modelPath, ref modelProperties)) { if (modelProperties.ModelKey != OVRPlugin.RENDER_MODEL_NULL_KEY) { byte[] modelData = OVRPlugin.LoadRenderModel(modelProperties.ModelKey); if (modelData != null) { OVRGLTFLoader loader = new OVRGLTFLoader(modelData); loader.SetModelShader(m_controllerModelShader); m_controllerObject = loader.LoadGLB().root; if (m_controllerObject != null) { m_controllerObject.transform.SetParent(transform, false); // Apply the OpenXR grip pose offset so runtime controller models are in the right position m_controllerObject.transform.parent.localPosition = new Vector3(0.0f, -0.03f, -0.04f); m_controllerObject.transform.parent.localRotation = Quaternion.AngleAxis(-60.0f, new Vector3(1.0f, 0.0f, 0.0f)); return true; } } } Debug.LogError("Retrived a null model key."); } Debug.LogError("Failed to load controller model"); return false; } private IEnumerator UpdateControllerModel() { while (true) { bool controllerConnected = OVRInput.IsControllerConnected(m_controller); if (m_controllerObject == null && controllerConnected) { LoadControllerModel(m_controllerModelPath); } yield return new WaitForSeconds(.5f); } } public void InputFocusAquired() { m_hasInputFocus = true; } public void InputFocusLost() { m_hasInputFocus = false; } }