Skip to content

Commit fae509c

Browse files
authored
Merge branch 'develop' into isxb-656-fix-for-auto-schemes-switching-with-onscreen-components
2 parents fe5ccff + bb685c5 commit fae509c

File tree

3 files changed

+34
-35
lines changed

3 files changed

+34
-35
lines changed

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ however, it has to be formatted properly to pass verification tests.
1111
## [Unreleased] - yyyy-mm-dd
1212

1313
### Fixed
14+
- Fixed touch pointers being released twice causing an index out of bounds error. [ISXB-687](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-687)
1415
- Fixed `NullReferenceException` from disconnecting and reconnecting a GXDKGamepad.
1516
- Fixed wrong mapping of Xbox Series S|X and Xbox One wireless controllers "View" button on macOS.[ISXB-385](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-385)
1617
- Fixed unexpected control scheme switch when using `OnScreenControl` and pointer based schemes which registed "Cancel" event on every frame.[ISXB-656](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-656)
@@ -31,6 +32,7 @@ however, it has to be formatted properly to pass verification tests.
3132
- Fixed "MissingReferenceException" errors when closing an in-game dropdown field [ISXB-1081](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1081).
3233
- Fixed potential crash on Mac when using stale references to deleted InputDevice objects [ISXB-606](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-606).
3334
- Fixed conditional compilation for non-editor analytics on platforms not enabling analytics.
35+
- Fixed simulated touch input not working with PlayerInput component [ISXB-483](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-483).
3436

3537
### Changed
3638
- Renamed editor Resources directories to PackageResources to fix package validation warnings.

Packages/com.unity.inputsystem/InputSystem/Plugins/EnhancedTouch/TouchSimulation.cs

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ protected void RemovePointer(Pointer pointer)
121121

122122
private unsafe void OnEvent(InputEventPtr eventPtr, InputDevice device)
123123
{
124+
if (device == simulatedTouchscreen)
125+
{
126+
// Avoid processing events queued by this simulation device
127+
return;
128+
}
129+
124130
var pointerIndex = m_Pointers.IndexOfReference(device, m_NumPointers);
125131
if (pointerIndex < 0)
126132
return;
@@ -129,9 +135,6 @@ private unsafe void OnEvent(InputEventPtr eventPtr, InputDevice device)
129135
if (eventType != StateEvent.Type && eventType != DeltaStateEvent.Type)
130136
return;
131137

132-
////TODO: this can be simplified if we use events instead of InputState.Change() but doing so requires work on buffering events while processing; also
133-
//// needs extra handling to not lag into the next frame
134-
135138
////REVIEW: should we have specialized paths for MouseState and PenState here? (probably can only use for StateEvents)
136139

137140
Pointer pointer = m_Pointers[pointerIndex];
@@ -254,6 +257,9 @@ protected void OnEnable()
254257
if (m_Touches == null)
255258
m_Touches = new ButtonControl[simulatedTouchscreen.touches.Count];
256259

260+
if (m_TouchIds == null)
261+
m_TouchIds = new int[simulatedTouchscreen.touches.Count];
262+
257263
foreach (var device in InputSystem.devices)
258264
OnDeviceChange(device, InputDeviceChange.Added);
259265

@@ -280,7 +286,6 @@ protected void OnDisable()
280286

281287
m_NumPointers = 0;
282288
m_LastTouchId = 0;
283-
m_PrimaryTouchIndex = -1;
284289

285290
InputSystem.onDeviceChange -= m_OnDeviceChange;
286291
InputSystem.onEvent -= m_OnEvent;
@@ -292,55 +297,34 @@ private unsafe void UpdateTouch(int touchIndex, int pointerIndex, TouchPhase pha
292297
Debug.Assert(m_CurrentDisplayIndices[pointerIndex] <= byte.MaxValue, "Display index was larger than expected");
293298
byte displayIndex = (byte)m_CurrentDisplayIndices[pointerIndex];
294299

300+
// We need to partially set TouchState in a similar way that the Native side would do, but deriving that
301+
// data from the Pointer events.
302+
// The handling of the remaining fields is done by the Touchscreen.OnStateEvent() callback.
295303
var touch = new TouchState
296304
{
297305
phase = phase,
298306
position = position,
299307
displayIndex = displayIndex
300308
};
301-
var time = eventPtr.valid ? eventPtr.time : InputState.currentTime;
302-
303-
var oldTouchState = (TouchState*)((byte*)simulatedTouchscreen.currentStatePtr +
304-
simulatedTouchscreen.touches[touchIndex].stateBlock.byteOffset);
305309

306310
if (phase == TouchPhase.Began)
307311
{
308-
touch.isPrimaryTouch = m_PrimaryTouchIndex < 0;
309-
touch.startTime = time;
312+
touch.startTime = eventPtr.valid ? eventPtr.time : InputState.currentTime;
310313
touch.startPosition = position;
311314
touch.touchId = ++m_LastTouchId;
312-
touch.tapCount = oldTouchState->tapCount; // Get reset automatically by Touchscreen.
313-
314-
if (touch.isPrimaryTouch)
315-
m_PrimaryTouchIndex = touchIndex;
315+
m_TouchIds[touchIndex] = m_LastTouchId;
316316
}
317317
else
318318
{
319-
touch.touchId = oldTouchState->touchId;
320-
touch.isPrimaryTouch = m_PrimaryTouchIndex == touchIndex;
321-
touch.delta = position - oldTouchState->position;
322-
touch.startPosition = oldTouchState->startPosition;
323-
touch.startTime = oldTouchState->startTime;
324-
touch.tapCount = oldTouchState->tapCount;
325-
326-
if (phase == TouchPhase.Ended)
327-
{
328-
touch.isTap = time - oldTouchState->startTime <= Touchscreen.s_TapTime &&
329-
(position - oldTouchState->startPosition).sqrMagnitude <= Touchscreen.s_TapRadiusSquared;
330-
if (touch.isTap)
331-
++touch.tapCount;
332-
}
319+
touch.touchId = m_TouchIds[touchIndex];
333320
}
334321

335-
if (touch.isPrimaryTouch)
336-
InputState.Change(simulatedTouchscreen.primaryTouch, touch, eventPtr: eventPtr);
337-
InputState.Change(simulatedTouchscreen.touches[touchIndex], touch, eventPtr: eventPtr);
322+
//NOTE: Processing these events still happen in the current frame.
323+
InputSystem.QueueStateEvent(simulatedTouchscreen, touch);
338324

339325
if (phase.IsEndedOrCanceled())
340326
{
341327
m_Touches[touchIndex] = null;
342-
if (m_PrimaryTouchIndex == touchIndex)
343-
m_PrimaryTouchIndex = -1;
344328
}
345329
}
346330

@@ -349,9 +333,9 @@ private unsafe void UpdateTouch(int touchIndex, int pointerIndex, TouchPhase pha
349333
[NonSerialized] private Vector2[] m_CurrentPositions;
350334
[NonSerialized] private int[] m_CurrentDisplayIndices;
351335
[NonSerialized] private ButtonControl[] m_Touches;
336+
[NonSerialized] private int[] m_TouchIds;
352337

353338
[NonSerialized] private int m_LastTouchId;
354-
[NonSerialized] private int m_PrimaryTouchIndex = -1;
355339
[NonSerialized] private Action<InputDevice, InputDeviceChange> m_OnDeviceChange;
356340
[NonSerialized] private Action<InputEventPtr, InputDevice> m_OnEvent;
357341

Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,13 @@ private void RemovePointerAtIndex(int index)
19471947
{
19481948
Debug.Assert(m_PointerStates[index].eventData.pointerEnter == null, "Pointer should have exited all objects before being removed");
19491949

1950+
// We don't want to release touch pointers on the same frame they are released (unpressed). They get cleaned up one frame later in Process()
1951+
ref var state = ref GetPointerStateForIndex(index);
1952+
if (state.pointerType == UIPointerType.Touch && (state.leftButton.isPressed || state.leftButton.wasReleasedThisFrame))
1953+
{
1954+
return;
1955+
}
1956+
19501957
// Retain event data so that we can reuse the event the next time we allocate a PointerModel record.
19511958
var eventData = m_PointerStates[index].eventData;
19521959
Debug.Assert(eventData != null, "Pointer state should have an event instance!");
@@ -2209,7 +2216,13 @@ private void FilterPointerStatesByType()
22092216
// We have input on a mouse or pen. Kill all touch and tracked pointers we may have.
22102217
for (var i = 0; i < m_PointerStates.length; ++i)
22112218
{
2212-
if (m_PointerStates[i].pointerType != UIPointerType.MouseOrPen)
2219+
ref var state = ref GetPointerStateForIndex(i);
2220+
// Touch pointers need to get forced to no longer be pressed otherwise they will not get released in subsequent frames.
2221+
if (m_PointerStates[i].pointerType == UIPointerType.Touch)
2222+
{
2223+
state.leftButton.isPressed = false;
2224+
}
2225+
if (m_PointerStates[i].pointerType != UIPointerType.MouseOrPen && m_PointerStates[i].pointerType != UIPointerType.Touch || (m_PointerStates[i].pointerType == UIPointerType.Touch && !state.leftButton.isPressed && !state.leftButton.wasReleasedThisFrame))
22132226
{
22142227
SendPointerExitEventsAndRemovePointer(i);
22152228
--i;

0 commit comments

Comments
 (0)