259 lines
8.4 KiB
C#
259 lines
8.4 KiB
C#
/*
|
|
* 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.
|
|
*/
|
|
|
|
#nullable enable
|
|
|
|
#if USING_XR_MANAGEMENT && (USING_XR_SDK_OCULUS || USING_XR_SDK_OPENXR) && !OVRPLUGIN_UNSUPPORTED_PLATFORM
|
|
#define USING_XR_SDK
|
|
#endif
|
|
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using Oculus.Avatar2;
|
|
using UnityEngine;
|
|
using UnityEngine.XR;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
using Node = UnityEngine.XR.XRNode;
|
|
|
|
|
|
public abstract class BaseHeadsetInputSimulator : MonoBehaviour
|
|
{
|
|
protected OvrAvatarInputTrackingDelegate? _inputTrackingDelegate;
|
|
public virtual OvrAvatarInputTrackingDelegate? InputTrackingDelegate => _inputTrackingDelegate;
|
|
}
|
|
|
|
/* This is an example class for how to send input and IK transforms to the sdk from any source
|
|
* InputTrackingDelegate and InputControlDelegate are set on BodyTracking.
|
|
*/
|
|
public class SampleInputManager : OvrAvatarInputManager
|
|
{
|
|
private const string logScope = "sampleInput";
|
|
|
|
[SerializeField]
|
|
[Tooltip("Optional. If added, it will use input directly from OVRCameraRig instead of doing its own calculations.")]
|
|
#if USING_XR_SDK
|
|
private OVRCameraRig? _ovrCameraRig = null;
|
|
#endif
|
|
private bool _useOvrCameraRig;
|
|
|
|
// Only used in editor, produces warnings when packaging
|
|
#pragma warning disable CS0414 // is assigned but its value is never used
|
|
[SerializeField]
|
|
private bool _debugDrawTrackingLocations = false;
|
|
#pragma warning restore CS0414 // is assigned but its value is never used
|
|
|
|
#if UNITY_EDITOR
|
|
[SerializeField]
|
|
public BaseHeadsetInputSimulator? HeadsetInputSimulator;
|
|
#if USING_XR_SDK
|
|
[SerializeField]
|
|
[Tooltip("Optional. If set to true, when played in Editor, all instances of SampleSceneLocomotion are disabled, " +
|
|
"so that the movements don't override or interact in unwanted ways if applied to the same avatar.")]
|
|
private bool disableSampleSceneLocomotion = false;
|
|
#endif
|
|
#endif
|
|
|
|
public OvrAvatarBodyTrackingMode BodyTrackingMode
|
|
{
|
|
get => _bodyTrackingMode;
|
|
set
|
|
{
|
|
_bodyTrackingMode = value;
|
|
InitializeBodyTracking();
|
|
}
|
|
}
|
|
|
|
protected void Awake()
|
|
{
|
|
#if USING_XR_SDK
|
|
_useOvrCameraRig = _ovrCameraRig != null;
|
|
#endif
|
|
|
|
// Debug Drawing
|
|
#if UNITY_EDITOR
|
|
SceneView.duringSceneGui += OnSceneGUI;
|
|
#endif
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
#if USING_XR_SDK
|
|
// If OVRCameraRig doesn't exist, we should set tracking origin ourselves
|
|
if (!_useOvrCameraRig)
|
|
{
|
|
|
|
if (OVRManager.instance == null)
|
|
{
|
|
OvrAvatarLog.LogDebug("Creating OVRManager, as one doesn't exist yet.", logScope, this);
|
|
var go = new GameObject("OVRManager");
|
|
var manager = go.AddComponent<OVRManager>();
|
|
manager.trackingOriginType = OVRManager.TrackingOrigin.FloorLevel;
|
|
}
|
|
else
|
|
{
|
|
OVRManager.instance.trackingOriginType = OVRManager.TrackingOrigin.FloorLevel;
|
|
}
|
|
|
|
OvrAvatarLog.LogInfo("Setting Tracking Origin to FloorLevel", logScope, this);
|
|
|
|
var instances = new List<XRInputSubsystem>();
|
|
SubsystemManager.GetSubsystems(instances);
|
|
foreach (var instance in instances)
|
|
{
|
|
instance.TrySetTrackingOriginMode(TrackingOriginModeFlags.Floor);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
protected override void OnTrackingInitialized()
|
|
{
|
|
#if USING_XR_SDK
|
|
// On Oculus SDK version >= v46 Eye tracking and Face tracking need to be explicitly started by the application
|
|
// after permission has been requested.
|
|
OvrPluginInvoke("StartFaceTracking");
|
|
OvrPluginInvoke("StartEyeTracking");
|
|
#endif
|
|
|
|
IOvrAvatarInputTrackingDelegate? inputTrackingDelegate = null;
|
|
#if USING_XR_SDK
|
|
#if UNITY_EDITOR
|
|
// Use SampleAvatarHeadsetInputSimulator if no headset connected via link
|
|
if (!OvrAvatarUtility.IsHeadsetActive())
|
|
{
|
|
if (disableSampleSceneLocomotion)
|
|
{
|
|
DisableSampleSceneLocomotion();
|
|
}
|
|
|
|
if (HeadsetInputSimulator is not null)
|
|
{
|
|
inputTrackingDelegate = HeadsetInputSimulator.InputTrackingDelegate;
|
|
}
|
|
else
|
|
{
|
|
inputTrackingDelegate = new SampleAvatarHeadsetInputSimulator();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
inputTrackingDelegate = new SampleInputTrackingDelegate(_ovrCameraRig);
|
|
}
|
|
#else // !UNITY_EDITOR
|
|
inputTrackingDelegate = new SampleInputTrackingDelegate(_ovrCameraRig);
|
|
#endif // !UNITY_EDITOR
|
|
#endif // USING_XR_SDK
|
|
var inputControlDelegate = new SampleInputControlDelegate();
|
|
|
|
_inputTrackingProvider = new OvrAvatarInputTrackingDelegatedProvider(inputTrackingDelegate);
|
|
_inputControlProvider = new OvrAvatarInputControlDelegatedProvider(inputControlDelegate);
|
|
}
|
|
|
|
#if USING_XR_SDK
|
|
#if UNITY_EDITOR
|
|
// Disable SampleSceneLomcomotion scripts if they are present.
|
|
private void DisableSampleSceneLocomotion()
|
|
{
|
|
var locomotionScripts = FindObjectsOfType<SampleSceneLocomotion>();
|
|
if (locomotionScripts != null)
|
|
{
|
|
foreach (var locomotionScript in locomotionScripts)
|
|
{
|
|
locomotionScript.enabled = false;
|
|
OvrAvatarLog.LogWarning($"Found and disabled SampleSceneLocomotion on object: {locomotionScript.gameObject.name}.", logScope);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#if USING_XR_SDK
|
|
// We use reflection here so that there are not compiler errors when using Oculus SDK v45 or below.
|
|
private static void OvrPluginInvoke(string method, params object[] args)
|
|
{
|
|
typeof(OVRPlugin).GetMethod(method, BindingFlags.Public | BindingFlags.Static)?.Invoke(null, args);
|
|
}
|
|
#endif
|
|
|
|
protected override void OnDestroyCalled()
|
|
{
|
|
#if UNITY_EDITOR
|
|
SceneView.duringSceneGui -= OnSceneGUI;
|
|
#endif
|
|
|
|
base.OnDestroyCalled();
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
#region Debug Drawing
|
|
|
|
private void OnSceneGUI(SceneView sceneView)
|
|
{
|
|
if (_debugDrawTrackingLocations)
|
|
{
|
|
DrawTrackingLocations();
|
|
}
|
|
}
|
|
|
|
private void DrawTrackingLocations()
|
|
{
|
|
if (InputTrackingProvider == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var inputTrackingState = InputTrackingProvider.State;
|
|
|
|
float radius = 0.2f;
|
|
Quaternion orientation;
|
|
float outerRadius() => radius + 0.25f;
|
|
Vector3 forward() => orientation * Vector3.forward;
|
|
|
|
Handles.color = Color.blue;
|
|
Handles.RadiusHandle(Quaternion.identity, inputTrackingState.headset.position, radius);
|
|
|
|
orientation = inputTrackingState.headset.orientation;
|
|
Handles.DrawLine((Vector3)inputTrackingState.headset.position + forward() * radius,
|
|
(Vector3)inputTrackingState.headset.position + forward() * outerRadius());
|
|
|
|
radius = 0.1f;
|
|
Handles.color = Color.yellow;
|
|
Handles.RadiusHandle(Quaternion.identity, inputTrackingState.leftController.position, radius);
|
|
|
|
orientation = inputTrackingState.leftController.orientation;
|
|
Handles.DrawLine((Vector3)inputTrackingState.leftController.position + forward() * radius,
|
|
(Vector3)inputTrackingState.leftController.position + forward() * outerRadius());
|
|
|
|
Handles.color = Color.yellow;
|
|
Handles.RadiusHandle(Quaternion.identity, inputTrackingState.rightController.position, radius);
|
|
|
|
orientation = inputTrackingState.rightController.orientation;
|
|
Handles.DrawLine((Vector3)inputTrackingState.rightController.position + forward() * radius,
|
|
(Vector3)inputTrackingState.rightController.position + forward() * outerRadius());
|
|
}
|
|
|
|
#endregion
|
|
#endif // UNITY_EDITOR
|
|
}
|