Skip to content
This repository has been archived by the owner on May 13, 2022. It is now read-only.

Commit

Permalink
Improved Windows API Checker (#98)
Browse files Browse the repository at this point in the history
* Removed string usages for Windows API Checker

* sorted usings

* updated license cause we significantly changed it
  • Loading branch information
StephenHodgson authored Sep 28, 2020
1 parent 7d462c4 commit 1b00954
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 63 deletions.
22 changes: 8 additions & 14 deletions Runtime/Extensions/InteractionSourceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

#if UNITY_WSA
using XRTK.WindowsMixedReality.Utilities;
using UnityEngine.XR.WSA.Input;
using Application = UnityEngine.Application;
#if WINDOWS_UWP
using System;
using System.Collections.Generic;
using Windows.Devices.Haptics;
using Windows.Perception;
using Windows.UI.Input.Spatial;
using XRTK.WindowsMixedReality.Utilities;
using Application = UnityEngine.Application;
#elif UNITY_EDITOR_WIN
using System.Runtime.InteropServices;
#endif
Expand Down Expand Up @@ -42,18 +42,15 @@ public static void StartHaptics(this InteractionSource interactionSource, float

public static void StartHaptics(this InteractionSource interactionSource, float intensity, float durationInSeconds)
{
#if WINDOWS_UWP
// GetForCurrentView and GetDetectedSourcesAtTimestamp were both introduced in the same Windows version.
// We need only check for one of them.
if ((!WindowsApiChecker.IsMethodAvailable(
"Windows.UI.Input.Spatial",
"SpatialInteractionManager",
"GetForCurrentView") ||
!WindowsApiChecker.IsTypeAvailable("Windows.Devices.Haptics", "SimpleHapticsController")) && !Application.isEditor)
if ((!WindowsApiChecker.IsMethodAvailable(typeof(SpatialInteractionManager), nameof(SpatialInteractionManager.GetForCurrentView)) ||
!WindowsApiChecker.IsTypeAvailable(typeof(SimpleHapticsController))) && !Application.isEditor)
{
return;
}

#if WINDOWS_UWP
UnityEngine.WSA.Application.InvokeOnUIThread(() =>
{
IReadOnlyList<SpatialInteractionSourceState> sources = SpatialInteractionManager.GetForCurrentView().GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
Expand Down Expand Up @@ -88,18 +85,15 @@ public static void StartHaptics(this InteractionSource interactionSource, float

public static void StopHaptics(this InteractionSource interactionSource)
{
#if WINDOWS_UWP
// GetForCurrentView and GetDetectedSourcesAtTimestamp were both introduced in the same Windows version.
// We need only check for one of them.
if ((!WindowsApiChecker.IsMethodAvailable(
"Windows.UI.Input.Spatial",
"SpatialInteractionManager",
"GetForCurrentView") ||
!WindowsApiChecker.IsTypeAvailable("Windows.Devices.Haptics", "SimpleHapticsController")) && !Application.isEditor)
if ((!WindowsApiChecker.IsMethodAvailable(typeof(SpatialInteractionManager), nameof(SpatialInteractionManager.GetForCurrentView)) ||
!WindowsApiChecker.IsTypeAvailable(typeof(SimpleHapticsController))) && !Application.isEditor)
{
return;
}

#if WINDOWS_UWP
UnityEngine.WSA.Application.InvokeOnUIThread(() =>
{
IReadOnlyList<SpatialInteractionSourceState> sources = SpatialInteractionManager.GetForCurrentView().GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,14 +447,8 @@ private static async void TryRenderControllerModel(InteractionSource interaction

IRandomAccessStreamWithContentType stream = null;

if (!WindowsApiChecker.IsMethodAvailable(
"Windows.UI.Input.Spatial",
"SpatialInteractionManager",
"GetForCurrentView") ||
!WindowsApiChecker.IsMethodAvailable(
"Windows.UI.Input.Spatial",
"SpatialInteractionController",
"TryGetRenderableModelAsync"))
if (!WindowsApiChecker.IsMethodAvailable(typeof(SpatialInteractionManager), nameof(SpatialInteractionManager.GetForCurrentView)) ||
!WindowsApiChecker.IsMethodAvailable(typeof(SpatialInteractionController), nameof(SpatialInteractionController.TryGetRenderableModelAsync)))
{
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,7 @@ private bool TryGetCurrentHandSources(out IReadOnlyList<SpatialInteractionSource
// the HandPose related APIs are only present on this version and above.
// GetForCurrentView and GetDetectedSourcesAtTimestamp were both introduced in the same Windows version.
// We need only check for one of them.
if (WindowsApiChecker.IsMethodAvailable(
"Windows.UI.Input.Spatial",
"SpatialInteractionManager",
"GetForCurrentView") &&
if (WindowsApiChecker.IsMethodAvailable(typeof(SpatialInteractionManager), nameof(SpatialInteractionManager.GetForCurrentView)) &&
SpatialInteractionManager != null)
{
var perceptionTimestamp = PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now);
Expand Down
60 changes: 23 additions & 37 deletions Runtime/Utilities/WindowsApiChecker.cs
Original file line number Diff line number Diff line change
@@ -1,72 +1,58 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) XRTK. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#if WINDOWS_UWP

using System;
using Windows.Foundation.Metadata;
#endif // WINDOWS_UWP

namespace XRTK.WindowsMixedReality.Utilities
{
/// <summary>
/// Helper class for determining if a Windows API contract is available.
/// </summary>
/// <remarks> See https://docs.microsoft.com/uwp/extension-sdks/windows-universal-sdk
/// for a full list of contracts.</remarks>
/// <remarks>
/// See https://docs.microsoft.com/uwp/extension-sdks/windows-universal-sdk for a full list of contracts.
/// </remarks>
public static class WindowsApiChecker
{
/// <summary>
/// Checks to see if the requested method is present on the current platform.
/// </summary>
/// <param name="namespaceName">The namespace (ex: "Windows.UI.Input.Spatial") containing the class.</param>
/// <param name="className">The name of the class containing the method (ex: "SpatialInteractionMananger").</param>
/// <param name="type">The <see cref="Type"/> of the class to check.</param>
/// <param name="methodName">The name of the method (ex: "IsSourceKindSupported").</param>
/// <returns>True if the method is available and can be called. Otherwise, false.</returns>
public static bool IsMethodAvailable(
string namespaceName,
string className,
string methodName)
public static bool IsMethodAvailable(Type type, string methodName)
{
#if WINDOWS_UWP
return ApiInformation.IsMethodPresent($"{namespaceName}.{className}", methodName);
#else
return false;
#endif // WINDOWS_UWP
if (type == null || string.IsNullOrWhiteSpace(type.FullName)) { throw new ArgumentException(); }
if (string.IsNullOrWhiteSpace(methodName)) { throw new ArgumentException(); }
return ApiInformation.IsMethodPresent(type.FullName, methodName);
}

/// <summary>
/// Checks to see if the requested property is present on the current platform.
/// </summary>
/// <param name="namespaceName">The namespace (ex: "Windows.UI.Input.Spatial") containing the class.</param>
/// <param name="className">The name of the class containing the method (ex: "SpatialPointerPose").</param>
/// <param name="type">The <see cref="Type"/> of the class to check.</param>
/// <param name="propertyName">The name of the method (ex: "Eyes").</param>
/// <returns>True if the property is available and can be called. Otherwise, false.</returns>
public static bool IsPropertyAvailable(
string namespaceName,
string className,
string propertyName)
public static bool IsPropertyAvailable(Type type, string propertyName)
{
#if WINDOWS_UWP
return ApiInformation.IsPropertyPresent($"{namespaceName}.{className}", propertyName);
#else
return false;
#endif // WINDOWS_UWP
if (type == null || string.IsNullOrWhiteSpace(type.FullName)) { throw new ArgumentException(); }
if (string.IsNullOrWhiteSpace(propertyName)) { throw new ArgumentException(); }
return ApiInformation.IsPropertyPresent(type.FullName, propertyName);
}

/// <summary>
/// Checks to see if the requested type is present on the current platform.
/// </summary>
/// <param name="namespaceName">The namespace (ex: "Windows.UI.Input.Spatial") containing the class.</param>
/// <param name="typeName">The name of the class containing the method (ex: "SpatialPointerPose").</param>
/// <param name="type">The <see cref="Type"/> of the class to check.</param>
/// <returns>True if the type is available and can be called. Otherwise, false.</returns>
public static bool IsTypeAvailable(
string namespaceName,
string typeName)
public static bool IsTypeAvailable(Type type)
{
#if WINDOWS_UWP
return ApiInformation.IsTypePresent($"{namespaceName}.{typeName}");
#else
return false;
#endif // WINDOWS_UWP
if (type == null || string.IsNullOrWhiteSpace(type.FullName)) { throw new ArgumentException(); }
return ApiInformation.IsTypePresent(type.FullName);
}
}
}
}

#endif // WINDOWS_UWP

0 comments on commit 1b00954

Please sign in to comment.