/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* 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 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 " + modelPath + " 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 of " + modelPath);
}
Debug.LogError("Failed to load controller model of " + modelPath);
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;
}
}