Skip to content

Commit b824b60

Browse files
author
Rene Damm
authored
FIX: Removing device causing state monitor corruption (#977).
1 parent d8571c7 commit b824b60

File tree

5 files changed

+49
-8
lines changed

5 files changed

+49
-8
lines changed

.yamato/upm-ci.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ platforms:
4848
- npm install upm-ci-utils@stable -g --registry https://api.bintray.com/npm/unity/unity-npm
4949
- upm-ci package pack --package-path ./Packages/com.unity.inputsystem/
5050
- upm-ci package test --package-path ./Packages/com.unity.inputsystem/ -u {{ editor.version }}
51-
- {% if platform.installscript %} {{ platform.installscript }} {{ editor.version }} {% endif %}
52-
- upm-ci~/tools/utr/utr --testproject $PWD --editor-location=.Editor --artifacts_path=upm-ci~/test-results/isolation-com.unity.inputsystem.tests --suite=playmode --api-profile=NET_4_6 --stdout-filter=minimal {% if platform.runtime %} --platform {{ platform.runtime }} {% endif %} {% if platform.scripting-backend %} --scripting-backend {{ platform.scripting-backend }} {% endif %}
51+
{% if platform.installscript %}
52+
- {{ platform.installscript }} {{ editor.version }}
53+
{% endif %}
54+
- upm-ci~/tools/utr/utr --testproject . --editor-location=.Editor --artifacts_path=upm-ci~/test-results/isolation-com.unity.inputsystem.tests --suite=playmode --api-profile=NET_4_6 --stdout-filter=minimal {% if platform.runtime %} --platform {{ platform.runtime }} {% endif %} {% if platform.scripting-backend %} --scripting-backend {{ platform.scripting-backend }} {% endif %}
5355
triggers:
5456
branches:
5557
only:

Assets/Tests/InputSystem/CoreTests_State.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,24 @@ public void State_CanRemoveStateChangeMonitorWithSpecificMonitorIndex()
743743
Assert.That(receivedMonitorIndex.Value, Is.EqualTo(kRightStick));
744744
}
745745

746+
[Test]
747+
[Category("State")]
748+
public void State_StateChangeMonitorsStayIntactWhenOtherDevicesAreRemoved()
749+
{
750+
InputSystem.AddDevice<Keyboard>(); // Noise.
751+
var gamepad = InputSystem.AddDevice<Gamepad>();
752+
var mouse = InputSystem.AddDevice<Mouse>();
753+
754+
var positionMonitorFired = false;
755+
InputState.AddChangeMonitor(mouse.position, (control, d, arg3, arg4) => positionMonitorFired = true);
756+
757+
InputSystem.RemoveDevice(gamepad);
758+
759+
Set(mouse.position, new Vector2(123, 234));
760+
761+
Assert.That(positionMonitorFired);
762+
}
763+
746764
// For certain actions, we want to be able to tell whether a specific input arrives in time.
747765
// For example, we may want to only trigger an action if a specific button was released within
748766
// a certain amount of time. To support this, the system allows putting timeouts on individual

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ however, it has to be formatted properly to pass verification tests.
3434

3535
- `InputUser` in combination with touchscreens no longer throws `InvalidOperationException` complaining about incorrect state format.
3636
* In a related change, `InputControlExtensions.GetStatePtrFromStateEvent` now works with touch events, too.
37+
- Removing a device no longer has the potential of corrupting state change monitors (and thus actions getting triggered) from other devices.
38+
* This bug led to input being missed on a device once another device had been removed.
3739

3840
## [1.0.0-preview.3] - 2019-11-14
3941

Packages/com.unity.inputsystem/InputSystem/InputManager.cs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,11 @@ public event LayoutChangeListener onLayoutChange
235235
////TODO: introduce an alternative that consumes events in bulk
236236
public event EventListener onEvent
237237
{
238-
add => m_EventListeners.AppendWithCapacity(value);
238+
add
239+
{
240+
if (!m_EventListeners.ContainsReference(value))
241+
m_EventListeners.AppendWithCapacity(value);
242+
}
239243
remove
240244
{
241245
var index = m_EventListeners.IndexOf(value);
@@ -249,7 +253,8 @@ public event UpdateListener onBeforeUpdate
249253
add
250254
{
251255
InstallBeforeUpdateHookIfNecessary();
252-
m_BeforeUpdateListeners.AppendWithCapacity(value);
256+
if (!m_BeforeUpdateListeners.ContainsReference(value))
257+
m_BeforeUpdateListeners.AppendWithCapacity(value);
253258
}
254259
remove
255260
{
@@ -261,7 +266,11 @@ public event UpdateListener onBeforeUpdate
261266

262267
public event UpdateListener onAfterUpdate
263268
{
264-
add => m_AfterUpdateListeners.AppendWithCapacity(value);
269+
add
270+
{
271+
if (!m_AfterUpdateListeners.ContainsReference(value))
272+
m_AfterUpdateListeners.AppendWithCapacity(value);
273+
}
265274
remove
266275
{
267276
var index = m_AfterUpdateListeners.IndexOf(value);
@@ -272,7 +281,11 @@ public event UpdateListener onAfterUpdate
272281

273282
public event Action onSettingsChange
274283
{
275-
add => m_SettingsChangedListeners.AppendWithCapacity(value);
284+
add
285+
{
286+
if (!m_SettingsChangedListeners.ContainsReference(value))
287+
m_SettingsChangedListeners.AppendWithCapacity(value);
288+
}
276289
remove
277290
{
278291
var index = m_SettingsChangedListeners.IndexOf(value);
@@ -1167,7 +1180,14 @@ public void RemoveDevice(InputDevice device, bool keepOnListOfAvailableDevices =
11671180
// Remove from device array.
11681181
var deviceIndex = device.m_DeviceIndex;
11691182
var deviceId = device.deviceId;
1183+
if (deviceIndex < m_StateChangeMonitors.LengthSafe())
1184+
{
1185+
// m_StateChangeMonitors mirrors layout of m_Devices.
1186+
var count = m_DevicesCount;
1187+
ArrayHelpers.EraseAtWithCapacity(m_StateChangeMonitors, ref count, deviceIndex);
1188+
}
11701189
ArrayHelpers.EraseAtWithCapacity(m_Devices, ref m_DevicesCount, deviceIndex);
1190+
11711191
m_DevicesById.Remove(deviceId);
11721192

11731193
if (m_Devices != null)
@@ -1803,6 +1823,7 @@ public void Clear()
18031823
{
18041824
// We don't actually release memory we've potentially allocated but rather just reset
18051825
// our count to zero.
1826+
listeners.Clear(count);
18061827
signalled.SetLength(0);
18071828
}
18081829
}

Packages/com.unity.inputsystem/InputSystem/Utilities/ArrayHelpers.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,8 +708,6 @@ public static void MoveSlice<TValue>(TValue[] array, int sourceIndex, int destin
708708
if (sourceIndex > destinationIndex)
709709
Swap(ref sourceIndex, ref destinationIndex);
710710

711-
var length = array.Length;
712-
713711
while (destinationIndex != sourceIndex)
714712
{
715713
// Swap source and destination slice. Afterwards, the source slice is the right, final

0 commit comments

Comments
 (0)