File size: 6,152 Bytes
18a519f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#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