mixedreality/com.microsoft.mixedreality..../Providers/OpenXR/Scripts/OpenXRControllerModelProvid...

86 lines
3.5 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Threading.Tasks;
using UnityEngine;
#if MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA || UNITY_ANDROID)
using Microsoft.MixedReality.OpenXR;
using Microsoft.MixedReality.Toolkit.Utilities.Gltf.Serialization;
using System.Collections.Generic;
#endif // MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA || UNITY_ANDROID)
namespace Microsoft.MixedReality.Toolkit.XRSDK.OpenXR
{
/// <summary>
/// Queries the OpenXR APIs for a renderable controller model.
/// </summary>
internal class OpenXRControllerModelProvider
{
public OpenXRControllerModelProvider(Utilities.Handedness handedness)
{
#if MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA || UNITY_ANDROID)
controllerModelProvider = handedness == Utilities.Handedness.Left ? ControllerModel.Left : ControllerModel.Right;
#endif // MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA || UNITY_ANDROID)
}
#if MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA || UNITY_ANDROID)
private static readonly Dictionary<ulong, GameObject> ControllerModelDictionary = new Dictionary<ulong, GameObject>(2);
private readonly ControllerModel controllerModelProvider;
#endif // MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA || UNITY_ANDROID)
// Disables "This async method lacks 'await' operators and will run synchronously." when the correct OpenXR package isn't installed
#pragma warning disable CS1998
/// <summary>
/// Attempts to load the glTF controller model from OpenXR.
/// </summary>
/// <returns>The controller model as a GameObject or null if it was unobtainable.</returns>
public async Task<GameObject> TryGenerateControllerModelFromPlatformSDK()
{
GameObject gltfGameObject = null;
#if MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA || UNITY_ANDROID)
if (!controllerModelProvider.TryGetControllerModelKey(out ulong modelKey))
{
Debug.LogError("Failed to obtain controller model key from platform.");
return null;
}
if (ControllerModelDictionary.TryGetValue(modelKey, out gltfGameObject))
{
gltfGameObject.SetActive(true);
return gltfGameObject;
}
byte[] modelStream = await controllerModelProvider.TryGetControllerModel(modelKey);
if (modelStream == null || modelStream.Length == 0)
{
Debug.LogError("Failed to obtain controller model from platform.");
return null;
}
Utilities.Gltf.Schema.GltfObject gltfObject = GltfUtility.GetGltfObjectFromGlb(modelStream);
gltfGameObject = await gltfObject.ConstructAsync();
if (gltfGameObject != null)
{
// After all the awaits, double check that another task didn't finish earlier
if (ControllerModelDictionary.TryGetValue(modelKey, out GameObject existingGameObject))
{
Object.Destroy(gltfGameObject);
return existingGameObject;
}
else
{
ControllerModelDictionary.Add(modelKey, gltfGameObject);
}
}
#endif // MSFT_OPENXR && (UNITY_STANDALONE_WIN || UNITY_WSA || UNITY_ANDROID)
return gltfGameObject;
}
#pragma warning restore CS1998
}
}