22
33using System ;
44using System . Collections . Generic ;
5+ using UnityEditor ;
56using UnityEditor . DeviceSimulation ;
7+ using UnityEditor . UIElements ;
68using UnityEngine . InputSystem . LowLevel ;
9+ using UnityEngine . UIElements ;
710
811namespace UnityEngine . InputSystem . Editor
912{
@@ -13,6 +16,9 @@ internal class InputSystemPlugin : DeviceSimulatorPlugin
1316
1417 private bool m_InputSystemEnabled ;
1518 private bool m_Quitting ;
19+ private bool m_ConflictingDevicesDisabled ;
20+ private VisualElement m_RootElement ;
21+ private EditorWindow m_LastFocusedWindow ;
1622 private List < InputDevice > m_DisabledDevices ;
1723
1824 public override string title => "Input System" ;
@@ -25,19 +31,16 @@ public override void OnCreate()
2531 // Monitor whether the editor is quitting to avoid risking unsafe EnableDevice while quitting
2632 UnityEditor . EditorApplication . quitting += OnQuitting ;
2733
34+ // Poll the active window so conflicting devices are only disabled while the simulator is focused.
35+ UnityEditor . EditorApplication . update += OnUpdate ;
36+
2837 m_DisabledDevices = new List < InputDevice > ( ) ;
2938
3039 // deviceSimulator is never null when the plugin is instantiated by a simulator window, but it can be null during unit tests
3140 if ( deviceSimulator != null )
3241 deviceSimulator . touchScreenInput += OnTouchEvent ;
3342 InputSystem . onDeviceChange += OnDeviceChange ;
3443
35- // UGUI elements like a button don't get pressed when multiple pointers for example mouse and touchscreen are sending data at the same time
36- foreach ( var device in InputSystem . devices )
37- {
38- DisableConflictingDevice ( device ) ;
39- }
40-
4144 SimulatorTouchscreen = InputSystem . AddDevice < Touchscreen > ( "Device Simulator Touchscreen" ) ;
4245 }
4346 }
@@ -56,6 +59,44 @@ internal void OnTouchEvent(TouchEvent touchEvent)
5659 } ) ;
5760 }
5861
62+ public override VisualElement OnCreateUI ( )
63+ {
64+ m_RootElement = new VisualElement ( ) ;
65+ m_RootElement . Add ( new HelpBox (
66+ L10n . Tr ( "Manages Input System devices while the Simulator is focused." ) ,
67+ HelpBoxMessageType . Info ) ) ;
68+ return m_RootElement ;
69+ }
70+
71+ private void OnUpdate ( )
72+ {
73+ if ( ! EditorApplication . isPlaying )
74+ return ;
75+
76+ var focusedWindow = EditorWindow . focusedWindow ;
77+ if ( focusedWindow == m_LastFocusedWindow )
78+ return ;
79+
80+ m_LastFocusedWindow = focusedWindow ;
81+ var simulatorFocused =
82+ m_RootElement != null
83+ && focusedWindow != null
84+ && focusedWindow . rootVisualElement . panel == m_RootElement . panel ;
85+
86+ if ( simulatorFocused && ! m_ConflictingDevicesDisabled )
87+ {
88+ // UGUI elements like a button don't get pressed when multiple pointers for example mouse and touchscreen are sending data at the same time
89+ foreach ( var device in InputSystem . devices )
90+ DisableConflictingDevice ( device ) ;
91+ m_ConflictingDevicesDisabled = true ;
92+ }
93+ else if ( ! simulatorFocused && m_ConflictingDevicesDisabled )
94+ {
95+ ReenableConflictingDevices ( ) ;
96+ m_ConflictingDevicesDisabled = false ;
97+ }
98+ }
99+
59100 private void DisableConflictingDevice ( InputDevice device )
60101 {
61102 if ( device . native && ( device is Mouse || device is Pen ) && device . enabled )
@@ -65,8 +106,28 @@ private void DisableConflictingDevice(InputDevice device)
65106 }
66107 }
67108
109+ private void ReenableConflictingDevices ( )
110+ {
111+ foreach ( var device in m_DisabledDevices )
112+ {
113+ // Note that m_Quitting is used here to mitigate the problem reported in issue tracker:
114+ // https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-10774.
115+ // Enabling a device will call into IOCTL of backend which may be destroyed prior
116+ // to this callback on Unity version. This is not a fix for the actual problem
117+ // of shutdown order but a package fix to mitigate this problem.
118+ // The core problem with the destruction order was still there in Unity 6.5.
119+ if ( device . added && ! m_Quitting )
120+ InputSystem . EnableDevice ( device ) ;
121+ }
122+ m_DisabledDevices . Clear ( ) ;
123+ }
124+
68125 private void OnDeviceChange ( InputDevice device , InputDeviceChange change )
69126 {
127+ // Only disable newly added/reconnected devices while the simulator is the active window.
128+ if ( ! m_ConflictingDevicesDisabled )
129+ return ;
130+
70131 if ( change == InputDeviceChange . Added || change == InputDeviceChange . Reconnected )
71132 DisableConflictingDevice ( device ) ;
72133 }
@@ -100,20 +161,13 @@ public override void OnDestroy()
100161 InputSystem . onDeviceChange -= OnDeviceChange ;
101162
102163 UnityEditor . EditorApplication . quitting -= OnQuitting ;
164+ UnityEditor . EditorApplication . update -= OnUpdate ;
103165
104166 if ( SimulatorTouchscreen != null )
105167 InputSystem . RemoveDevice ( SimulatorTouchscreen ) ;
106- foreach ( var device in m_DisabledDevices )
107- {
108- // Note that m_Quitting is used here to mitigate the problem reported in issue tracker:
109- // https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-10774.
110- // Enabling a device will call into IOCTL of backend which may be destroyed prior
111- // to this callback on Unity version. This is not a fix for the actual problem
112- // of shutdown order but a package fix to mitigate this problem.
113- // The core problem with the destruction order was still there in Unity 6.5.
114- if ( device . added && ! m_Quitting )
115- InputSystem . EnableDevice ( device ) ;
116- }
168+
169+ ReenableConflictingDevices ( ) ;
170+ m_RootElement = null ;
117171 }
118172 }
119173
0 commit comments