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 { /// /// API to control enhanced touch facilities like that are not /// enabled by default. /// /// /// 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 MonoBehaviour.Update. Enhanced touch support cannot be used in combination /// with s though both can be used side-by-side. /// /// /// /// 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]); /// } /// } /// /// /// /// /// public static class EnhancedTouchSupport { /// /// Whether enhanced touch support is currently enabled. /// /// True if EnhancedTouch support has been enabled. public static bool enabled => s_Enabled > 0; private static int s_Enabled; private static InputSettings.UpdateMode s_UpdateMode; /// /// Enable enhanced touch support. /// /// /// Calling this method is necessary to enable the functionality provided /// by and . These APIs add extra /// processing to touches and are thus disabled by default. /// /// Calls to Enable and balance each other out. /// If Enable is called repeatedly, it will take as many calls to /// to disable the system again. /// 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(); } /// /// Disable enhanced touch support. /// /// /// This method only undoes a single call to . /// 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()"); } } }