Rasagar/Library/PackageCache/com.unity.inputsystem/InputSystem/Plugins/EnhancedTouch/EnhancedTouchSupport.cs
2024-08-26 23:07:20 +03:00

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 &lt; 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()");
}
}
}