|
1 | 1 | using System; |
2 | 2 | using System.Runtime.InteropServices; |
| 3 | +using Unity.Collections; |
3 | 4 | using Unity.Collections.LowLevel.Unsafe; |
4 | 5 | using UnityEngine.InputSystem.Controls; |
5 | 6 | using UnityEngine.InputSystem.Layouts; |
@@ -488,7 +489,7 @@ public enum TouchPhase |
488 | 489 | /// it is recommended to use the higher-level <see cref="EnhancedTouch.Touch"/> API instead. |
489 | 490 | /// </remarks> |
490 | 491 | [InputControlLayout(stateType = typeof(TouchscreenState), isGenericTypeOfDevice = true)] |
491 | | - public class Touchscreen : Pointer, IInputStateCallbackReceiver, IEventMerger |
| 492 | + public class Touchscreen : Pointer, IInputStateCallbackReceiver, IEventMerger, ICustomDeviceReset |
492 | 493 | { |
493 | 494 | /// <summary> |
494 | 495 | /// Synthetic control that has the data for the touch that is deemed the "primary" touch at the moment. |
@@ -952,6 +953,45 @@ unsafe bool IInputStateCallbackReceiver.GetStateOffsetForEvent(InputControl cont |
952 | 953 | return true; |
953 | 954 | } |
954 | 955 |
|
| 956 | + // Implement our own custom reset so that we can cancel touches instead of just wiping them |
| 957 | + // with default state. |
| 958 | + unsafe void ICustomDeviceReset.Reset() |
| 959 | + { |
| 960 | + var statePtr = currentStatePtr; |
| 961 | + |
| 962 | + //// https://jira.unity3d.com/browse/ISX-930 |
| 963 | + ////TODO: Figure out a proper way to distinguish the source / reason for a state change. |
| 964 | + //// What we're doing here is constructing an event solely for the purpose of Finger.ShouldRecordTouch() not |
| 965 | + //// ignoring the state change like it does for delta resets. |
| 966 | + |
| 967 | + using (var buffer = new NativeArray<byte>(StateEvent.GetEventSizeWithPayload<TouchState>(), Allocator.Temp)) |
| 968 | + { |
| 969 | + var eventPtr = (StateEvent*)buffer.GetUnsafePtr(); |
| 970 | + |
| 971 | + eventPtr->baseEvent = new InputEvent(StateEvent.Type, buffer.Length, deviceId); |
| 972 | + |
| 973 | + var primaryTouchState = (TouchState*)((byte*)statePtr + primaryTouch.stateBlock.byteOffset); |
| 974 | + if (primaryTouchState->phase.IsActive()) |
| 975 | + { |
| 976 | + UnsafeUtility.MemCpy(eventPtr->state, primaryTouchState, UnsafeUtility.SizeOf<TouchState>()); |
| 977 | + ((TouchState*)eventPtr->state)->phase = TouchPhase.Canceled; |
| 978 | + InputState.Change(primaryTouch.phase, TouchPhase.Canceled, eventPtr: new InputEventPtr((InputEvent*)eventPtr)); |
| 979 | + } |
| 980 | + |
| 981 | + var touchStates = (TouchState*)((byte*)statePtr + touches[0].stateBlock.byteOffset); |
| 982 | + var touchCount = touches.Count; |
| 983 | + for (var i = 0; i < touchCount; ++i) |
| 984 | + { |
| 985 | + if (touchStates[i].phase.IsActive()) |
| 986 | + { |
| 987 | + UnsafeUtility.MemCpy(eventPtr->state, &touchStates[i], UnsafeUtility.SizeOf<TouchState>()); |
| 988 | + ((TouchState*)eventPtr->state)->phase = TouchPhase.Canceled; |
| 989 | + InputState.Change(touches[i].phase, TouchPhase.Canceled, eventPtr: new InputEventPtr((InputEvent*)eventPtr)); |
| 990 | + } |
| 991 | + } |
| 992 | + } |
| 993 | + } |
| 994 | + |
955 | 995 | internal static unsafe bool MergeForward(InputEventPtr currentEventPtr, InputEventPtr nextEventPtr) |
956 | 996 | { |
957 | 997 | if (currentEventPtr.type != StateEvent.Type || nextEventPtr.type != StateEvent.Type) |
|
0 commit comments