Initial Commit
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
[HelpURL("https://developer.oculus.com/reference/unity/latest/class_o_v_r_runtime_controller")]
|
||||
public class OVRRuntimeController : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The controller that determines whether or not to enable rendering of the controller model.
|
||||
/// </summary>
|
||||
public OVRInput.Controller m_controller;
|
||||
|
||||
/// <summary>
|
||||
/// Shader that will be used for the controller model
|
||||
/// </summary>
|
||||
public Shader m_controllerModelShader;
|
||||
|
||||
/// <summary>
|
||||
/// Support render model animation
|
||||
/// </summary>
|
||||
public bool m_supportAnimation = true;
|
||||
|
||||
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;
|
||||
private Dictionary<OVRGLTFInputNode, OVRGLTFAnimatinonNode> m_animationNodes;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (controllerConnected)
|
||||
{
|
||||
UpdateControllerAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
OVRGLTFScene scene = loader.LoadGLB(m_supportAnimation);
|
||||
m_controllerObject = scene.root;
|
||||
m_animationNodes = scene.animationNodes;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateControllerAnimation()
|
||||
{
|
||||
if (m_animationNodes == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_animationNodes.ContainsKey(OVRGLTFInputNode.Button_A_X))
|
||||
m_animationNodes[OVRGLTFInputNode.Button_A_X].UpdatePose(
|
||||
OVRInput.Get(m_controller == OVRInput.Controller.LTouch ? OVRInput.RawButton.X : OVRInput.RawButton.A));
|
||||
|
||||
if (m_animationNodes.ContainsKey(OVRGLTFInputNode.Button_B_Y))
|
||||
m_animationNodes[OVRGLTFInputNode.Button_B_Y].UpdatePose(
|
||||
OVRInput.Get(m_controller == OVRInput.Controller.LTouch ? OVRInput.RawButton.Y : OVRInput.RawButton.B));
|
||||
|
||||
if (m_animationNodes.ContainsKey(OVRGLTFInputNode.Button_Oculus_Menu))
|
||||
m_animationNodes[OVRGLTFInputNode.Button_Oculus_Menu].UpdatePose(
|
||||
OVRInput.Get(OVRInput.RawButton.Start));
|
||||
|
||||
if (m_animationNodes.ContainsKey(OVRGLTFInputNode.Trigger_Grip))
|
||||
m_animationNodes[OVRGLTFInputNode.Trigger_Grip].UpdatePose(
|
||||
OVRInput.Get(m_controller == OVRInput.Controller.LTouch
|
||||
? OVRInput.RawAxis1D.LHandTrigger
|
||||
: OVRInput.RawAxis1D.RHandTrigger));
|
||||
|
||||
if (m_animationNodes.ContainsKey(OVRGLTFInputNode.Trigger_Front))
|
||||
m_animationNodes[OVRGLTFInputNode.Trigger_Front].UpdatePose(
|
||||
OVRInput.Get(m_controller == OVRInput.Controller.LTouch
|
||||
? OVRInput.RawAxis1D.LIndexTrigger
|
||||
: OVRInput.RawAxis1D.RIndexTrigger));
|
||||
|
||||
if (m_animationNodes.ContainsKey(OVRGLTFInputNode.ThumbStick))
|
||||
m_animationNodes[OVRGLTFInputNode.ThumbStick].UpdatePose(
|
||||
OVRInput.Get(m_controller == OVRInput.Controller.LTouch
|
||||
? OVRInput.RawAxis2D.LThumbstick
|
||||
: OVRInput.RawAxis2D.RThumbstick));
|
||||
}
|
||||
|
||||
public void InputFocusAquired()
|
||||
{
|
||||
m_hasInputFocus = true;
|
||||
}
|
||||
|
||||
public void InputFocusLost()
|
||||
{
|
||||
m_hasInputFocus = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user