diff --git a/Runtime/MobileInput.cs b/Runtime/MobileInput.cs index 3080307..794a9c9 100644 --- a/Runtime/MobileInput.cs +++ b/Runtime/MobileInput.cs @@ -28,10 +28,12 @@ public enum HardwareOrientation { /// public abstract class MobileInputReceiver : MonoBehaviour { +#if !UNITY_EDITOR /// /// Current input id /// int _id = 0; +#endif /// /// Init input and register interface @@ -270,11 +272,17 @@ public void OnData(JsonObject data) { GetReceiver(id).Send(response); } _data = null; - } catch (Exception e) { + } #if UMI_DEBUG + catch (Exception e) { Debug.LogError($"[UMI] received error: {e}"); -#endif } +#else + catch { + // Ignored + } +#endif + } /// @@ -301,11 +309,16 @@ void OnDataReceive(string data) { } else { OnData(info); } - } catch (Exception e) { + } #if UMI_DEBUG + catch (Exception e) { Debug.LogError($"[UMI] raw data error: data = {data}, error = {e}"); -#endif } +#else + catch { + // Ignored + } +#endif } #if UNITY_ANDROID @@ -317,7 +330,7 @@ public static bool IsRotationLocked() { return plugin.CallStatic("checkIsRotateLocked"); } } - + /// /// Return type of screen navigation /// @@ -330,7 +343,7 @@ public static int GetBarType() { using (var plugin = new AndroidJavaClass(PLUGIN_PACKAGE)) { return plugin.CallStatic("getBarType"); } - } + } /// /// Get height of navigation bar @@ -340,7 +353,7 @@ public static int GetBarHeight() { using (var plugin = new AndroidJavaClass(PLUGIN_PACKAGE)) { return plugin.CallStatic("getBarHeight"); } - } + } #endif /// diff --git a/Runtime/MobileInputField.cs b/Runtime/MobileInputField.cs index b5cf747..dcb5f91 100644 --- a/Runtime/MobileInputField.cs +++ b/Runtime/MobileInputField.cs @@ -5,6 +5,17 @@ using UnityEngine; using NiceJson; using UnityEngine.Events; +#if !UNITY_EDITOR +using System.Collections.Generic; +using System.Linq; +using LegacyTouch = UnityEngine.Touch; +#if ENABLE_INPUT_SYSTEM +using UnityEngine.InputSystem; +using UnityEngine.InputSystem.Controls; +using UnityEngine.InputSystem.EnhancedTouch; +using InputSystemTouch = UnityEngine.InputSystem.EnhancedTouch.Touch; +#endif +#endif namespace UMI { @@ -270,6 +281,18 @@ public enum ReturnKeyType { /// CultureInfo _cultureInfo = CultureInfo.InvariantCulture; +#if UNITY_ANDROID && !UNITY_EDITOR && ENABLE_INPUT_SYSTEM + /// + /// Last input character from the 'current' keyboard + /// + char? _lastInputChar = null; + + /// + /// The keyboard we are listening to for input strings + /// + Keyboard _boundKeyboard = null; +#endif + /// /// Constructor /// @@ -282,6 +305,15 @@ void Awake() { throw new MissingComponentException(); } _inputObjectText = _inputObject.textComponent; + +#if UMI_DEBUG && !UNITY_EDITOR +#if ENABLE_INPUT_SYSTEM + Debug.Log($"[UMI] Input type: (New) Input System"); +#else + Debug.Log($"[UMI] Input type: (Legacy) Input Manager"); +#endif +#endif + } /// @@ -416,11 +448,11 @@ void Update() { #endif if (_inputObject != null && _isMobileInputCreated) { #if !UNITY_EDITOR - var touchCount = Input.touchCount; - if (touchCount > 0) { + var tapCount = GetTapCount(); + if (tapCount > 0) { var inputRect = this._inputObjectText.rectTransform.rect; - for (var i = 0; i < touchCount; i++) { - if (!inputRect.Contains(Input.touches[i].position)) { + for (var i = 0; i < tapCount; i++) { + if (!inputRect.Contains(GetTapPosition(i))) { #if UMI_DEBUG Debug.Log($"[UMI] manual hide control: {IsManualHideControl}"); #endif @@ -824,21 +856,135 @@ private void ForceSendKeydownAndroid(string key) { /// Keyboard handler /// private void UpdateForceKeyeventForAndroid() { - if (Input.anyKeyDown) { - if (Input.GetKeyDown(KeyCode.Backspace)) { + + var inputState = GetAndroidInputState(); + + if (inputState.AnyKey) { + if (inputState.AndroidBack) { + if (!IsManualHideControl) { +#if UMI_DEBUG + Debug.Log("[UMI] Android back button pressed, hiding keyboard"); +#endif + Hide(); + } + } else if (inputState.Backspace) { ForceSendKeydownAndroid("backspace"); } else { - foreach (var c in Input.inputString) { + foreach (var c in inputState.InputString) { if (c == '\n') { ForceSendKeydownAndroid("enter"); } else { - ForceSendKeydownAndroid(Input.inputString); + ForceSendKeydownAndroid(c.ToString()); } } } } } + + private struct AndroidInputState { + public bool AnyKey; + public bool AndroidBack; + public bool Backspace; + public string InputString; + } + + /// + /// Gets the current state of input for Android specific logic, in an input-system-agnostic way + /// + private AndroidInputState GetAndroidInputState() { + +#if ENABLE_INPUT_SYSTEM + // Ensure we are listening to the most 'current' keyboard... + if (Keyboard.current != _boundKeyboard) { + +#if UMI_DEBUG + Debug.Log($"[UMI] Bound Keyboard changed from '{_boundKeyboard}' to '{Keyboard.current}'"); +#endif + + if (_boundKeyboard != null) { + _boundKeyboard.onTextInput -= OnTextInput; + } + + _boundKeyboard = Keyboard.current; + + if (_boundKeyboard != null) { + _boundKeyboard.onTextInput += OnTextInput; + } + + /// + /// Store the last input character + /// + void OnTextInput(char c) { + _lastInputChar = c; + } + } + + return new AndroidInputState + { + AnyKey = InputSystem.devices.OfType().Any(k => k.anyKey.wasPressedThisFrame), + AndroidBack = InputSystem.devices.OfType().Any(k => k.escapeKey.wasPressedThisFrame), + Backspace = InputSystem.devices.OfType().Any(k => k.backspaceKey.wasPressedThisFrame), + InputString = _lastInputChar.ToString() + }; +#else + return new AndroidInputState + { + AnyKey = Input.anyKeyDown, + AndroidBack = Input.GetKeyDown(KeyCode.Escape), + Backspace = Input.GetKeyUp(KeyCode.Backspace), + InputString = Input.inputString + }; +#endif + } +#endif + +#if !UNITY_EDITOR + + /// + /// Gets the count of taps in an input-system-agnostic way + /// + private int GetTapCount() { +#if ENABLE_INPUT_SYSTEM + if (EnhancedTouchSupport.enabled) { + return InputSystemTouch.activeTouches.Count(t => t.isTap); + } else { + return InputSystem.devices.OfType().Count(t => t.touches.Any(touch => touch.tap.wasReleasedThisFrame)); + } +#else + return GetLegacyInputManagerTouches().Count(t => t.phase == TouchPhase.Ended); +#endif + } + + /// + /// Gets the position of a specific tap in an input-system-agnostic way + /// + private Vector2 GetTapPosition(int index) { +#if ENABLE_INPUT_SYSTEM + if (EnhancedTouchSupport.enabled) { + return InputSystemTouch.activeTouches.Where(t => t.isTap).ElementAtOrDefault(index).screenPosition; + } else { + return InputSystem.devices.OfType().Where(t => t.touches.Any(touch => touch.tap.wasReleasedThisFrame)) + .SelectMany(t => t.touches) + .ElementAtOrDefault(index) + .position.ReadValue(); + } +#else + return GetLegacyInputManagerTouches() + .Where(t => t.phase == TouchPhase.Ended) + .ElementAtOrDefault(index) + .position; +#endif + } + + /// + /// Convenience enumerator for getting touches from the legacy input manager + /// + private IEnumerable GetLegacyInputManagerTouches() { + for (var i = 0; i < Input.touchCount; i++) { + yield return Input.GetTouch(i); + } + } #endif } -} \ No newline at end of file +} diff --git a/Runtime/UMI.Runtime.asmdef b/Runtime/UMI.Runtime.asmdef index c1b7eae..6392945 100644 --- a/Runtime/UMI.Runtime.asmdef +++ b/Runtime/UMI.Runtime.asmdef @@ -2,7 +2,8 @@ "name": "UMI.Runtime", "rootNamespace": "UMI", "references": [ - "Unity.TextMeshPro" + "Unity.TextMeshPro", + "Unity.InputSystem" ], "includePlatforms": [], "excludePlatforms": [],