214 lines
7.1 KiB
C#
214 lines
7.1 KiB
C#
|
using System;
|
||
|
using System.Diagnostics;
|
||
|
using UnityEngine.InputSystem.LowLevel;
|
||
|
#if UNITY_EDITOR
|
||
|
using UnityEditor;
|
||
|
#endif
|
||
|
|
||
|
////REVIEW: this *really* should be renamed to TouchPolling or something like that
|
||
|
|
||
|
////REVIEW: Should this auto-enable itself when the API is used? Problem with this is that it means the first touch inputs will get missed
|
||
|
//// as by the time the API is polled, we're already into the first frame.
|
||
|
|
||
|
////TODO: gesture support
|
||
|
////TODO: high-frequency touch support
|
||
|
|
||
|
////REVIEW: have TouchTap, TouchSwipe, etc. wrapper MonoBehaviours like LeanTouch?
|
||
|
|
||
|
////TODO: as soon as we can break the API, remove the EnhancedTouchSupport class altogether and rename UnityEngine.InputSystem.EnhancedTouch to TouchPolling
|
||
|
|
||
|
////FIXME: does not survive domain reloads
|
||
|
|
||
|
namespace UnityEngine.InputSystem.EnhancedTouch
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// API to control enhanced touch facilities like <see cref="Touch"/> that are not
|
||
|
/// enabled by default.
|
||
|
/// </summary>
|
||
|
/// <remarks>
|
||
|
/// Enhanced touch support provides automatic finger tracking and touch history recording.
|
||
|
/// It is an API designed for polling, i.e. for querying touch state directly in methods
|
||
|
/// such as <c>MonoBehaviour.Update</c>. Enhanced touch support cannot be used in combination
|
||
|
/// with <see cref="InputAction"/>s though both can be used side-by-side.
|
||
|
///
|
||
|
/// <example>
|
||
|
/// <code>
|
||
|
/// public class MyBehavior : MonoBehaviour
|
||
|
/// {
|
||
|
/// protected void OnEnable()
|
||
|
/// {
|
||
|
/// EnhancedTouchSupport.Enable();
|
||
|
/// }
|
||
|
///
|
||
|
/// protected void OnDisable()
|
||
|
/// {
|
||
|
/// EnhancedTouchSupport.Disable();
|
||
|
/// }
|
||
|
///
|
||
|
/// protected void Update()
|
||
|
/// {
|
||
|
/// var activeTouches = Touch.activeTouches;
|
||
|
/// for (var i = 0; i < activeTouches.Count; ++i)
|
||
|
/// Debug.Log("Active touch: " + activeTouches[i]);
|
||
|
/// }
|
||
|
/// }
|
||
|
/// </code>
|
||
|
/// </example>
|
||
|
/// </remarks>
|
||
|
/// <seealso cref="Touch"/>
|
||
|
/// <seealso cref="Finger"/>
|
||
|
public static class EnhancedTouchSupport
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Whether enhanced touch support is currently enabled.
|
||
|
/// </summary>
|
||
|
/// <value>True if EnhancedTouch support has been enabled.</value>
|
||
|
public static bool enabled => s_Enabled > 0;
|
||
|
|
||
|
private static int s_Enabled;
|
||
|
private static InputSettings.UpdateMode s_UpdateMode;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Enable enhanced touch support.
|
||
|
/// </summary>
|
||
|
/// <remarks>
|
||
|
/// Calling this method is necessary to enable the functionality provided
|
||
|
/// by <see cref="Touch"/> and <see cref="Finger"/>. These APIs add extra
|
||
|
/// processing to touches and are thus disabled by default.
|
||
|
///
|
||
|
/// Calls to <c>Enable</c> and <see cref="Disable"/> balance each other out.
|
||
|
/// If <c>Enable</c> is called repeatedly, it will take as many calls to
|
||
|
/// <see cref="Disable"/> to disable the system again.
|
||
|
/// </remarks>
|
||
|
public static void Enable()
|
||
|
{
|
||
|
++s_Enabled;
|
||
|
if (s_Enabled > 1)
|
||
|
return;
|
||
|
|
||
|
InputSystem.onDeviceChange += OnDeviceChange;
|
||
|
InputSystem.onBeforeUpdate += Touch.BeginUpdate;
|
||
|
InputSystem.onSettingsChange += OnSettingsChange;
|
||
|
|
||
|
#if UNITY_EDITOR
|
||
|
AssemblyReloadEvents.beforeAssemblyReload += OnBeforeDomainReload;
|
||
|
#endif
|
||
|
|
||
|
SetUpState();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Disable enhanced touch support.
|
||
|
/// </summary>
|
||
|
/// <remarks>
|
||
|
/// This method only undoes a single call to <see cref="Enable"/>.
|
||
|
/// </remarks>
|
||
|
public static void Disable()
|
||
|
{
|
||
|
if (!enabled)
|
||
|
return;
|
||
|
--s_Enabled;
|
||
|
if (s_Enabled > 0)
|
||
|
return;
|
||
|
|
||
|
InputSystem.onDeviceChange -= OnDeviceChange;
|
||
|
InputSystem.onBeforeUpdate -= Touch.BeginUpdate;
|
||
|
InputSystem.onSettingsChange -= OnSettingsChange;
|
||
|
|
||
|
#if UNITY_EDITOR
|
||
|
AssemblyReloadEvents.beforeAssemblyReload -= OnBeforeDomainReload;
|
||
|
#endif
|
||
|
|
||
|
TearDownState();
|
||
|
}
|
||
|
|
||
|
internal static void Reset()
|
||
|
{
|
||
|
Touch.s_GlobalState.touchscreens = default;
|
||
|
Touch.s_GlobalState.playerState.Destroy();
|
||
|
Touch.s_GlobalState.playerState = default;
|
||
|
#if UNITY_EDITOR
|
||
|
Touch.s_GlobalState.editorState.Destroy();
|
||
|
Touch.s_GlobalState.editorState = default;
|
||
|
#endif
|
||
|
s_Enabled = 0;
|
||
|
}
|
||
|
|
||
|
private static void SetUpState()
|
||
|
{
|
||
|
Touch.s_GlobalState.playerState.updateMask = InputUpdateType.Dynamic | InputUpdateType.Manual | InputUpdateType.Fixed;
|
||
|
#if UNITY_EDITOR
|
||
|
Touch.s_GlobalState.editorState.updateMask = InputUpdateType.Editor;
|
||
|
#endif
|
||
|
|
||
|
s_UpdateMode = InputSystem.settings.updateMode;
|
||
|
|
||
|
foreach (var device in InputSystem.devices)
|
||
|
OnDeviceChange(device, InputDeviceChange.Added);
|
||
|
}
|
||
|
|
||
|
internal static void TearDownState()
|
||
|
{
|
||
|
foreach (var device in InputSystem.devices)
|
||
|
OnDeviceChange(device, InputDeviceChange.Removed);
|
||
|
|
||
|
Touch.s_GlobalState.playerState.Destroy();
|
||
|
#if UNITY_EDITOR
|
||
|
Touch.s_GlobalState.editorState.Destroy();
|
||
|
#endif
|
||
|
|
||
|
Touch.s_GlobalState.playerState = default;
|
||
|
#if UNITY_EDITOR
|
||
|
Touch.s_GlobalState.editorState = default;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
private static void OnDeviceChange(InputDevice device, InputDeviceChange change)
|
||
|
{
|
||
|
switch (change)
|
||
|
{
|
||
|
case InputDeviceChange.Added:
|
||
|
{
|
||
|
if (device is Touchscreen touchscreen)
|
||
|
Touch.AddTouchscreen(touchscreen);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case InputDeviceChange.Removed:
|
||
|
{
|
||
|
if (device is Touchscreen touchscreen)
|
||
|
Touch.RemoveTouchscreen(touchscreen);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void OnSettingsChange()
|
||
|
{
|
||
|
var currentUpdateMode = InputSystem.settings.updateMode;
|
||
|
if (s_UpdateMode == currentUpdateMode)
|
||
|
return;
|
||
|
TearDownState();
|
||
|
SetUpState();
|
||
|
}
|
||
|
|
||
|
#if UNITY_EDITOR
|
||
|
private static void OnBeforeDomainReload()
|
||
|
{
|
||
|
// We need to release NativeArrays we're holding before losing track of them during domain reloads.
|
||
|
Touch.s_GlobalState.playerState.Destroy();
|
||
|
Touch.s_GlobalState.editorState.Destroy();
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
[Conditional("DEVELOPMENT_BUILD")]
|
||
|
[Conditional("UNITY_EDITOR")]
|
||
|
internal static void CheckEnabled()
|
||
|
{
|
||
|
if (!enabled)
|
||
|
throw new InvalidOperationException("EnhancedTouch API is not enabled; call EnhancedTouchSupport.Enable()");
|
||
|
}
|
||
|
}
|
||
|
}
|