test
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
#if UNITY_EDITOR || UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS || PACKAGE_DOCS_GENERATION
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.InputSystem.DualShock;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.iOS.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
namespace UnityEngine.InputSystem.iOS.LowLevel
|
||||
{
|
||||
internal enum iOSButton
|
||||
{
|
||||
DpadUp,
|
||||
DpadDown,
|
||||
DpadLeft,
|
||||
DpadRight,
|
||||
LeftStick,
|
||||
RightStick,
|
||||
LeftShoulder,
|
||||
RightShoulder,
|
||||
LeftTrigger,
|
||||
RightTrigger,
|
||||
X,
|
||||
Y,
|
||||
A,
|
||||
B,
|
||||
Start,
|
||||
Select
|
||||
|
||||
// Note: If you'll add an element here, be sure to update kMaxButtons const below
|
||||
};
|
||||
|
||||
internal enum iOSAxis
|
||||
{
|
||||
LeftStickX,
|
||||
LeftStickY,
|
||||
RightStickX,
|
||||
RightStickY
|
||||
|
||||
// Note: If you'll add an element here, be sure to update kMaxAxis const below
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct iOSGameControllerState : IInputStateTypeInfo
|
||||
{
|
||||
public static FourCC kFormat = new FourCC('I', 'G', 'C', ' ');
|
||||
public const int MaxButtons = (int)iOSButton.Select + 1;
|
||||
public const int MaxAxis = (int)iOSAxis.RightStickY + 1;
|
||||
|
||||
[InputControl(name = "dpad")]
|
||||
[InputControl(name = "dpad/up", bit = (uint)iOSButton.DpadUp)]
|
||||
[InputControl(name = "dpad/right", bit = (uint)iOSButton.DpadRight)]
|
||||
[InputControl(name = "dpad/down", bit = (uint)iOSButton.DpadDown)]
|
||||
[InputControl(name = "dpad/left", bit = (uint)iOSButton.DpadLeft)]
|
||||
[InputControl(name = "buttonSouth", bit = (uint)iOSButton.A)]
|
||||
[InputControl(name = "buttonWest", bit = (uint)iOSButton.X)]
|
||||
[InputControl(name = "buttonNorth", bit = (uint)iOSButton.Y)]
|
||||
[InputControl(name = "buttonEast", bit = (uint)iOSButton.B)]
|
||||
[InputControl(name = "leftStickPress", bit = (uint)iOSButton.LeftStick)]
|
||||
[InputControl(name = "rightStickPress", bit = (uint)iOSButton.RightStick)]
|
||||
[InputControl(name = "leftShoulder", bit = (uint)iOSButton.LeftShoulder)]
|
||||
[InputControl(name = "rightShoulder", bit = (uint)iOSButton.RightShoulder)]
|
||||
[InputControl(name = "start", bit = (uint)iOSButton.Start)]
|
||||
[InputControl(name = "select", bit = (uint)iOSButton.Select)]
|
||||
public uint buttons;
|
||||
|
||||
[InputControl(name = "leftTrigger", offset = sizeof(uint) + sizeof(float) * (uint)iOSButton.LeftTrigger)]
|
||||
[InputControl(name = "rightTrigger", offset = sizeof(uint) + sizeof(float) * (uint)iOSButton.RightTrigger)]
|
||||
public fixed float buttonValues[MaxButtons];
|
||||
|
||||
private const uint kAxisOffset = sizeof(uint) + sizeof(float) * MaxButtons;
|
||||
[InputControl(name = "leftStick", offset = (uint)iOSAxis.LeftStickX * sizeof(float) + kAxisOffset)]
|
||||
[InputControl(name = "rightStick", offset = (uint)iOSAxis.RightStickX * sizeof(float) + kAxisOffset)]
|
||||
public fixed float axisValues[MaxAxis];
|
||||
|
||||
public FourCC format => kFormat;
|
||||
|
||||
public iOSGameControllerState WithButton(iOSButton button, bool value = true, float rawValue = 1.0f)
|
||||
{
|
||||
buttonValues[(int)button] = rawValue;
|
||||
|
||||
Debug.Assert((int)button < 32, $"Expected button < 32, so we fit into the 32 bit wide bitmask");
|
||||
var bit = 1U << (int)button;
|
||||
if (value)
|
||||
buttons |= bit;
|
||||
else
|
||||
buttons &= ~bit;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public iOSGameControllerState WithAxis(iOSAxis axis, float value)
|
||||
{
|
||||
axisValues[(int)axis] = value;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace UnityEngine.InputSystem.iOS
|
||||
{
|
||||
/// <summary>
|
||||
/// A generic Gamepad connected to an iOS device.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Any MFi-certified Gamepad which is not an <see cref="XboxOneGampadiOS"/> or <see cref="DualShock4GampadiOS"/> will
|
||||
/// be represented as an iOSGameController.
|
||||
/// </remarks>
|
||||
[InputControlLayout(stateType = typeof(iOSGameControllerState), displayName = "iOS Gamepad")]
|
||||
public class iOSGameController : Gamepad
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An Xbox One Bluetooth controller connected to an iOS device.
|
||||
/// </summary>
|
||||
[InputControlLayout(stateType = typeof(iOSGameControllerState), displayName = "iOS Xbox One Gamepad")]
|
||||
public class XboxOneGampadiOS : XInput.XInputController
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A PlayStation DualShock 4 controller connected to an iOS device.
|
||||
/// </summary>
|
||||
[InputControlLayout(stateType = typeof(iOSGameControllerState), displayName = "iOS DualShock 4 Gamepad")]
|
||||
public class DualShock4GampadiOS : DualShockGamepad
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A PlayStation DualSense controller connected to an iOS device.
|
||||
/// </summary>
|
||||
[InputControlLayout(stateType = typeof(iOSGameControllerState), displayName = "iOS DualSense Gamepad")]
|
||||
public class DualSenseGampadiOS : DualShockGamepad
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif // UNITY_EDITOR || UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0e29a3b2e6d01345abeaefb681b5f22
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,87 @@
|
||||
#if UNITY_EDITOR || UNITY_IOS || UNITY_TVOS || PACKAGE_DOCS_GENERATION
|
||||
using System;
|
||||
using UnityEngine.InputSystem.iOS;
|
||||
|
||||
namespace UnityEngine.InputSystem.iOS
|
||||
{
|
||||
/// <summary>
|
||||
/// Governs access to a privacy-related resource on the user's device. Corresponds to a key in the application's
|
||||
/// Information Property List (Info.plist).
|
||||
/// </summary>
|
||||
/// <seealso href="https://developer.apple.com/documentation/bundleresources/information_property_list/protected_resources"/>
|
||||
[Serializable]
|
||||
public class PrivacyDataUsage
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether access to the respective resource will be requested.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Before accessing a resource or a sensor, you need to explicitly enable the usage for it, otherwise the access for the resource will be denied.
|
||||
///
|
||||
/// If this is set to true, the respective protected resource key will be entered in the application's Information Property List (Info.plist)
|
||||
/// using <see cref="usageDescription"/>.
|
||||
/// </remarks>
|
||||
public bool enabled
|
||||
{
|
||||
get => m_Enabled;
|
||||
set => m_Enabled = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provide meaningful usage description.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The description will be presented to the user in the dialog when you'll try to access a related resource or sensor.
|
||||
/// </remarks>
|
||||
public string usageDescription
|
||||
{
|
||||
get => m_Description;
|
||||
set => m_Description = value;
|
||||
}
|
||||
|
||||
[SerializeField] private bool m_Enabled;
|
||||
[SerializeField] private string m_Description;
|
||||
}
|
||||
}
|
||||
|
||||
namespace UnityEngine.InputSystem
|
||||
{
|
||||
public partial class InputSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Project-wide input settings for the iOS/tvOS platform.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class iOSSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Setting for access to the device's motion sensors (such as <see cref="StepCounter"/>).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alternatively, you can manually add <c>Privacy - Motion Usage Description</c> to the Info.plist file.
|
||||
/// </remarks>
|
||||
/// <seealso cref="StepCounter"/>
|
||||
/// <seealso href="https://developer.apple.com/documentation/bundleresources/information_property_list/nsmotionusagedescription"/>
|
||||
public PrivacyDataUsage motionUsage
|
||||
{
|
||||
get => m_MotionUsage;
|
||||
set => m_MotionUsage = value;
|
||||
}
|
||||
|
||||
[SerializeField] private PrivacyDataUsage m_MotionUsage = new PrivacyDataUsage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// iOS/tvOS-specific settings.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is only accessible in the editor or in iOS/tvOS players.
|
||||
/// </remarks>
|
||||
public iOSSettings iOS => m_iOSSettings;
|
||||
|
||||
[SerializeField]
|
||||
private iOSSettings m_iOSSettings = new iOSSettings();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d08e8dbcaeef59a4c9f04d8448f179eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,35 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using UnityEditor;
|
||||
|
||||
namespace UnityEngine.InputSystem
|
||||
{
|
||||
internal class InputSettingsiOSProvider
|
||||
{
|
||||
[NonSerialized] private SerializedProperty m_MotionUsageEnabled;
|
||||
[NonSerialized] private SerializedProperty m_MotionUsageDescription;
|
||||
|
||||
private GUIContent m_MotionUsageContent;
|
||||
private GUIContent m_MotionUsageDescriptionContent;
|
||||
|
||||
public InputSettingsiOSProvider(SerializedObject parent)
|
||||
{
|
||||
var prefix = "m_iOSSettings.m_MotionUsage";
|
||||
m_MotionUsageEnabled = parent.FindProperty(prefix + ".m_Enabled");
|
||||
m_MotionUsageDescription = parent.FindProperty(prefix + ".m_Description");
|
||||
|
||||
m_MotionUsageContent = new GUIContent("Motion Usage", "Enables Motion Usage for the app, required for sensors like Step Counter. This also adds 'Privacy - Motion Usage Description' entry to Info.plist");
|
||||
m_MotionUsageDescriptionContent = new GUIContent(" Description", "Describe why the app wants to access the device's Motion Usage sensor.");
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_MotionUsageEnabled, m_MotionUsageContent);
|
||||
EditorGUI.BeginDisabledGroup(!m_MotionUsageEnabled.boolValue);
|
||||
EditorGUILayout.PropertyField(m_MotionUsageDescription, m_MotionUsageDescriptionContent);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0f60c66cb10e104c96c77e03a950843
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,39 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace UnityEngine.InputSystem
|
||||
{
|
||||
internal class iOSPostProcessBuild
|
||||
{
|
||||
[PostProcessBuild]
|
||||
public static void UpdateInfoPList(BuildTarget buildTarget, string pathToBuiltProject)
|
||||
{
|
||||
if (buildTarget != BuildTarget.iOS)
|
||||
return;
|
||||
|
||||
var settings = InputSystem.settings.iOS;
|
||||
if (!settings.motionUsage.enabled)
|
||||
return;
|
||||
var plistPath = pathToBuiltProject + "/Info.plist";
|
||||
var contents = File.ReadAllText(plistPath);
|
||||
var description = InputSystem.settings.iOS.motionUsage.usageDescription;
|
||||
#if UNITY_IOS || UNITY_TVOS
|
||||
var plist = new UnityEditor.iOS.Xcode.PlistDocument();
|
||||
plist.ReadFromString(contents);
|
||||
var root = plist.root;
|
||||
var buildKey = "NSMotionUsageDescription";
|
||||
if (root[buildKey] != null)
|
||||
Debug.LogWarning($"{buildKey} is already present in Info.plist, the value will be overwritten.");
|
||||
|
||||
root.SetString(buildKey, description);
|
||||
File.WriteAllText(plistPath, plist.WriteToString());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 536defedfe4153e4cabde208f78a818d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,195 @@
|
||||
#if UNITY_EDITOR || UNITY_IOS || PACKAGE_DOCS_GENERATION
|
||||
using System.Runtime.InteropServices;
|
||||
using AOT;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
namespace UnityEngine.InputSystem.iOS.LowLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the access for motion related features.
|
||||
/// </summary>
|
||||
/// <remarks>Enum values map values from CoreMotion.framework/Headers/CMAuthorization.h</remarks>
|
||||
public enum MotionAuthorizationStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The access status was not yet determined.
|
||||
/// </summary>
|
||||
NotDetermined = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Access was denied due system settings.
|
||||
/// </summary>
|
||||
Restricted,
|
||||
|
||||
/// <summary>
|
||||
/// Access was denied by the user.
|
||||
/// </summary>
|
||||
Denied,
|
||||
|
||||
/// <summary>
|
||||
/// Access was allowed by the user.
|
||||
/// </summary>
|
||||
Authorized
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct iOSStepCounterState : IInputStateTypeInfo
|
||||
{
|
||||
public static FourCC kFormat = new FourCC('I', 'S', 'C', 'S');
|
||||
public FourCC format => kFormat;
|
||||
|
||||
[InputControl(name = "stepCounter", layout = "Integer")]
|
||||
public int stepCounter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Step Counter (also known as pedometer) sensor for iOS.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You need to enable Motion Usage in Input System settings (see <see cref="InputSettings.iOSSettings.motionUsage"/>), to be allowed
|
||||
/// to access the sensor on the user's device.
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// void Start()
|
||||
/// {
|
||||
/// InputSystem.EnableDevice(StepCounter.current);
|
||||
/// }
|
||||
///
|
||||
/// void OnGUI()
|
||||
/// {
|
||||
/// GUILayout.Label(StepCounter.current.stepCounter.ReadValue().ToString());
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// </remarks>
|
||||
/// <seealso cref="InputSettings.iOSSettings.motionUsage"/>
|
||||
[InputControlLayout(stateType = typeof(iOSStepCounterState), variants = "StepCounter", hideInUI = true)]
|
||||
public class iOSStepCounter : StepCounter
|
||||
{
|
||||
private const int kCommandFailure = -1;
|
||||
private const int kCommandSuccess = 1;
|
||||
|
||||
internal delegate void OnDataReceivedDelegate(int deviceId, int numberOfSteps);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct iOSStepCounterCallbacks
|
||||
{
|
||||
internal OnDataReceivedDelegate onData;
|
||||
}
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern int _iOSStepCounterEnable(int deviceId, ref iOSStepCounterCallbacks callbacks, int sizeOfCallbacks);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern int _iOSStepCounterDisable(int deviceId);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern int _iOSStepCounterIsEnabled(int deviceId);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern int _iOSStepCounterIsAvailable();
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern int _iOSStepCounterGetAuthorizationStatus();
|
||||
|
||||
[MonoPInvokeCallback(typeof(OnDataReceivedDelegate))]
|
||||
private static void OnDataReceived(int deviceId, int numberOfSteps)
|
||||
{
|
||||
var stepCounter = (iOSStepCounter)InputSystem.GetDeviceById(deviceId);
|
||||
InputSystem.QueueStateEvent(stepCounter, new iOSStepCounterState {stepCounter = numberOfSteps});
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private bool m_Enabled = false;
|
||||
#endif
|
||||
protected override unsafe long ExecuteCommand(InputDeviceCommand* commandPtr)
|
||||
{
|
||||
var t = commandPtr->type;
|
||||
if (t == QueryEnabledStateCommand.Type)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
((QueryEnabledStateCommand*)commandPtr)->isEnabled = m_Enabled;
|
||||
#else
|
||||
((QueryEnabledStateCommand*)commandPtr)->isEnabled = _iOSStepCounterIsEnabled(deviceId) != 0;
|
||||
#endif
|
||||
return kCommandSuccess;
|
||||
}
|
||||
|
||||
if (t == EnableDeviceCommand.Type)
|
||||
{
|
||||
if (InputSystem.settings.iOS.motionUsage.enabled == false)
|
||||
{
|
||||
Debug.LogError("Please enable Motion Usage in Input Settings before using Step Counter.");
|
||||
return kCommandFailure;
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
m_Enabled = true;
|
||||
return kCommandSuccess;
|
||||
#else
|
||||
var callbacks = new iOSStepCounterCallbacks();
|
||||
callbacks.onData = OnDataReceived;
|
||||
return _iOSStepCounterEnable(deviceId, ref callbacks, Marshal.SizeOf(callbacks));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (t == DisableDeviceCommand.Type)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
m_Enabled = false;
|
||||
return kCommandSuccess;
|
||||
#else
|
||||
return _iOSStepCounterDisable(deviceId);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (t == QueryCanRunInBackground.Type)
|
||||
{
|
||||
((QueryCanRunInBackground*)commandPtr)->canRunInBackground = true;
|
||||
return kCommandSuccess;
|
||||
}
|
||||
|
||||
if (t == RequestResetCommand.Type)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
m_Enabled = false;
|
||||
#else
|
||||
_iOSStepCounterDisable(deviceId);
|
||||
#endif
|
||||
return kCommandSuccess;
|
||||
}
|
||||
|
||||
return kCommandFailure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the phone support the pedometer?
|
||||
/// </summary>
|
||||
public static bool IsAvailable()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return false;
|
||||
#else
|
||||
return _iOSStepCounterIsAvailable() != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the app is authorized to gather data for step counter sensor.
|
||||
/// </summary>
|
||||
public static MotionAuthorizationStatus AuthorizationStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return MotionAuthorizationStatus.NotDetermined;
|
||||
#else
|
||||
return (MotionAuthorizationStatus)_iOSStepCounterGetAuthorizationStatus();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5640f63fd494e11936f2f231d83eb4b
|
||||
timeCreated: 1607433300
|
@@ -0,0 +1,159 @@
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IOS
|
||||
|
||||
#include <CoreMotion/CoreMotion.h>
|
||||
|
||||
#define ENABLE_STEP_COUNTER_LOGGING 1
|
||||
#if ENABLE_STEP_COUNTER_LOGGING
|
||||
#define STEP_COUNTER_LOG(...) NSLog(@"StepCounter - %@", [NSString stringWithFormat: __VA_ARGS__])
|
||||
#else
|
||||
#define STEP_COUNTER_LOG(...) {}
|
||||
#endif
|
||||
|
||||
class iOSStepCounterWrapper
|
||||
{
|
||||
public:
|
||||
typedef void (*OnDataReceived) (int deviceId, int numberOfSteps);
|
||||
|
||||
struct iOSStepCounterCallbacks
|
||||
{
|
||||
OnDataReceived dataReceived;
|
||||
};
|
||||
|
||||
|
||||
iOSStepCounterWrapper()
|
||||
{
|
||||
m_Pedometer = nullptr;
|
||||
m_Device = -1;
|
||||
}
|
||||
|
||||
void Enable(int deviceId, iOSStepCounterCallbacks* callbacks)
|
||||
{
|
||||
if (IsEnabled())
|
||||
{
|
||||
STEP_COUNTER_LOG(@"Was already enabled?");
|
||||
if (m_Device != deviceId)
|
||||
STEP_COUNTER_LOG(@"Enabling with different device id? Expected %d, was %d. Are you creating more than one iOSStepCounter", m_Device, deviceId);
|
||||
}
|
||||
m_Pedometer = [[CMPedometer alloc]init];
|
||||
m_Callbacks = *callbacks;
|
||||
m_Device = deviceId;
|
||||
[m_Pedometer startPedometerUpdatesFromDate: [NSDate date] withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error)
|
||||
{
|
||||
// Note: We need to call our callback on the same thread the Unity scripting is operating
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (error != nil)
|
||||
{
|
||||
STEP_COUNTER_LOG(@"startPedometerUpdatesFromDate threw an error '%@', was it authorized?", [error localizedDescription]);
|
||||
if (m_Device != -1)
|
||||
Disable(m_Device);
|
||||
return;
|
||||
}
|
||||
// Guard against situation where device was disabled, any event which are received after that, should be ignored.
|
||||
if (m_Device == -1)
|
||||
return;
|
||||
m_Callbacks.dataReceived(m_Device, [pedometerData.numberOfSteps intValue]);
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
bool Disable(int deviceId)
|
||||
{
|
||||
if (m_Pedometer == nullptr)
|
||||
return false;
|
||||
if (m_Device != deviceId)
|
||||
STEP_COUNTER_LOG(@"Disabling with wrong device id, expected %d, was %d", m_Device, deviceId);
|
||||
[m_Pedometer stopPedometerUpdates];
|
||||
m_Pedometer = nullptr;
|
||||
m_Device = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsEnabled() const
|
||||
{
|
||||
return m_Pedometer != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
CMPedometer* m_Pedometer;
|
||||
iOSStepCounterCallbacks m_Callbacks;
|
||||
int m_Device;
|
||||
};
|
||||
|
||||
static iOSStepCounterWrapper s_Wrapper;
|
||||
static const int kResultSuccess = 1;
|
||||
static const int kResultFailure = -1;
|
||||
|
||||
extern "C" int _iOSStepCounterIsAvailable()
|
||||
{
|
||||
return [CMPedometer isStepCountingAvailable] ? 1 : 0;
|
||||
}
|
||||
|
||||
extern "C" int _iOSStepCounterGetAuthorizationStatus()
|
||||
{
|
||||
if (@available(iOS 11.0, *))
|
||||
{
|
||||
return (int)[CMPedometer authorizationStatus];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int _iOSStepCounterEnable(int deviceId, iOSStepCounterWrapper::iOSStepCounterCallbacks* callbacks, int sizeOfCallbacks)
|
||||
{
|
||||
if (sizeof(iOSStepCounterWrapper::iOSStepCounterCallbacks) != sizeOfCallbacks)
|
||||
{
|
||||
STEP_COUNTER_LOG(@"iOSStepCounterCallbacks size mismatch, expected %lu was %d", sizeof(iOSStepCounterWrapper::iOSStepCounterCallbacks), sizeOfCallbacks);
|
||||
return kResultFailure;
|
||||
}
|
||||
|
||||
if (_iOSStepCounterIsAvailable() == 0)
|
||||
{
|
||||
STEP_COUNTER_LOG(@"Step counting is not available");
|
||||
return kResultFailure;
|
||||
}
|
||||
|
||||
NSString* motionUsage = @"NSMotionUsageDescription";
|
||||
|
||||
if ([[NSBundle mainBundle] objectForInfoDictionaryKey: motionUsage] == nil)
|
||||
{
|
||||
STEP_COUNTER_LOG(@"%@ is missing in Info.plist, please enable Motion Usage in Input Settings", motionUsage);
|
||||
return kResultFailure;
|
||||
}
|
||||
|
||||
if (@available(iOS 11.0, *))
|
||||
{
|
||||
if ([CMPedometer authorizationStatus] == CMAuthorizationStatusRestricted)
|
||||
{
|
||||
STEP_COUNTER_LOG(@"Step Counter was restricted.");
|
||||
return kResultFailure;
|
||||
}
|
||||
|
||||
if ([CMPedometer authorizationStatus] == CMAuthorizationStatusDenied)
|
||||
{
|
||||
STEP_COUNTER_LOG(@"Step Counter was denied. Enable Motion & Fitness under app settings.");
|
||||
return kResultFailure;
|
||||
}
|
||||
// Do nothing for Authorized and NotDetermined
|
||||
}
|
||||
|
||||
// Note: After installation this function will prompt a dialog asking about Motion & Fitness authorization
|
||||
// If user denies the prompt, there will be an error in startPedometerUpdatesFromDate callback
|
||||
// The dialog only appears once, not sure how to trigger it again, besides reinstalling app
|
||||
s_Wrapper.Enable(deviceId, callbacks);
|
||||
|
||||
return kResultSuccess;
|
||||
}
|
||||
|
||||
extern "C" int _iOSStepCounterDisable(int deviceId)
|
||||
{
|
||||
return s_Wrapper.Disable(deviceId) ? kResultSuccess : kResultFailure;
|
||||
}
|
||||
|
||||
extern "C" int _iOSStepCounterIsEnabled(int deviceId)
|
||||
{
|
||||
return s_Wrapper.IsEnabled() ? 1 : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
@@ -0,0 +1,89 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d11ed63669394ec68af98a7f62afa73
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 1
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
Exclude iOS: 0
|
||||
Exclude tvOS: 1
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
AddToEmbeddedBinaries: false
|
||||
CPU: AnyCPU
|
||||
CompileFlags:
|
||||
FrameworkDependencies:
|
||||
- first:
|
||||
tvOS: tvOS
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
CompileFlags:
|
||||
FrameworkDependencies:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,65 @@
|
||||
#if UNITY_EDITOR || UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS
|
||||
using UnityEngine.InputSystem.iOS.LowLevel;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
|
||||
namespace UnityEngine.InputSystem.iOS
|
||||
{
|
||||
#if UNITY_DISABLE_DEFAULT_INPUT_PLUGIN_INITIALIZATION
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
static class iOSSupport
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
InputSystem.RegisterLayout<iOSGameController>("iOSGameController",
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface("iOS")
|
||||
.WithDeviceClass("iOSGameController"));
|
||||
|
||||
InputSystem.RegisterLayout<XboxOneGampadiOS>("XboxOneGampadiOS",
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface("iOS")
|
||||
.WithDeviceClass("iOSGameController")
|
||||
.WithProduct("Xbox Wireless Controller"));
|
||||
|
||||
InputSystem.RegisterLayout<DualShock4GampadiOS>("DualShock4GampadiOS",
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface("iOS")
|
||||
.WithDeviceClass("iOSGameController")
|
||||
.WithProduct("DUALSHOCK 4 Wireless Controller"));
|
||||
|
||||
InputSystem.RegisterLayout<DualSenseGampadiOS>("DualSenseGampadiOS",
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface("iOS")
|
||||
.WithDeviceClass("iOSGameController")
|
||||
.WithProduct("DualSense Wireless Controller"));
|
||||
|
||||
InputSystem.RegisterLayoutMatcher("GravitySensor",
|
||||
new InputDeviceMatcher()
|
||||
.WithInterface("iOS")
|
||||
.WithDeviceClass("Gravity"));
|
||||
InputSystem.RegisterLayoutMatcher("AttitudeSensor",
|
||||
new InputDeviceMatcher()
|
||||
.WithInterface("iOS")
|
||||
.WithDeviceClass("Attitude"));
|
||||
InputSystem.RegisterLayoutMatcher("LinearAccelerationSensor",
|
||||
new InputDeviceMatcher()
|
||||
.WithInterface("iOS")
|
||||
.WithDeviceClass("LinearAcceleration"));
|
||||
#if UNITY_EDITOR || UNITY_IOS
|
||||
InputSystem.RegisterLayout<iOSStepCounter>();
|
||||
// Don't add devices for InputTestRuntime
|
||||
// TODO: Maybe there should be a better place for adding device from C#
|
||||
if (InputSystem.s_Manager.m_Runtime is NativeInputRuntime)
|
||||
{
|
||||
if (iOSStepCounter.IsAvailable())
|
||||
InputSystem.AddDevice<iOSStepCounter>();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // UNITY_EDITOR || UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 635124a90cfbdc64eb3e9c0fc6904aa5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user