Skip to content

Commit d8daf79

Browse files
author
Dmytro Ivanov
committed
FIX: Sync enable/disable system mouse dynamically.
1 parent e8f41a6 commit d8daf79

File tree

4 files changed

+75
-17
lines changed

4 files changed

+75
-17
lines changed

Assets/Samples/GamepadMouseCursor/GamepadMouseCursorUIActions.inputactions

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
{
3535
"name": "",
3636
"id": "39af39e2-c75c-421e-84bf-1e4ff9793ab4",
37-
"path": "<VirtualMouse>/position",
37+
"path": "<Mouse>/position",
3838
"interactions": "",
3939
"processors": "",
4040
"groups": "",
@@ -45,7 +45,7 @@
4545
{
4646
"name": "",
4747
"id": "f9d5a98e-68a3-44c8-a096-a1a30237ca81",
48-
"path": "<VirtualMouse>/leftButton",
48+
"path": "<Mouse>/leftButton",
4949
"interactions": "",
5050
"processors": "",
5151
"groups": "",
@@ -56,7 +56,7 @@
5656
{
5757
"name": "",
5858
"id": "7ffd960c-11ef-4fc0-b91b-4cbd02eba1b8",
59-
"path": "<VirtualMouse>/scroll",
59+
"path": "<Mouse>/scroll",
6060
"interactions": "",
6161
"processors": "",
6262
"groups": "",

Assets/Samples/GamepadMouseCursor/README.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ This sample demonstrates how to set this up with the input system.
77
1) It uses a custom [actions file](./GamepadMouseCursorUIActions.inputactions) for feeding input to the UI as the default actions are set up for gamepad navigation &ndash; something we don't want here as it would conflict with gamepad input being used for virtual cursor navigation.
88
2) Note how `InputSystemUIInputModule` on the `EventSystem` GameObject is set up to reference actions from that file.
99
3) The key component to take a look at is `VirtualMouseInput` on `Canvas >> Cursor`. The component is set up to receive input from the gamepad and translates it into motion on the `RectTransform` it is given. When going into play mode, you should also see a `Virtual Mouse` being added to the devices by the component.
10-
4) Note how the anchor position on the `RectTransform` is set to bottom left. This way the coordinate system responds to how mouse screen space operates.
11-
5) Note how `Cursor` is the last child of `Canvas` so that it draws on top of everything else.
12-
6) Note that `Raycast Target` on the `Image` component of the cursor is turned off to avoid raycasts from the mouse cursor hitting the cursor itself.
13-
7) Note that `Cursor Mode` on the `VirtualMouseInput` component is set to `Hardware Cursor If Available`. This will cause the component to look for a system mouse. If present, the system mouse is disabled and the system mouse cursor is warped to the virtual mouse position using `Mouse.WarpCursorPosition`. If no system mouse is present, `Cursor Graphic` will be used as a software mouse cursor.
10+
4) Note how `Cursor` is the last child of `Canvas` so that it draws on top of everything else.
11+
5) Note that `Raycast Target` on the `Image` component of the cursor is turned off to avoid raycasts from the mouse cursor hitting the cursor itself.
12+
6) Note that `Cursor Mode` on the `VirtualMouseInput` component is set to `Hardware Cursor If Available`. This will cause the component to look for a system mouse. If present, the system mouse is disabled and the system mouse cursor is warped to the virtual mouse position using `Mouse.WarpCursorPosition`. If no system mouse is present, `Cursor Graphic` will be used as a software mouse cursor.
13+
14+
>NOTE: The `VirtualMouseInput` component currently does not work correctly with world-space canvases.
1415
1516
# Licenses
1617

Packages/com.unity.inputsystem/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ however, it has to be formatted properly to pass verification tests.
1313
### Fixed
1414

1515
- Fixed unclosed profiler marker in `InvokeCallbacksSafe_AnyCallbackReturnsTrue` which would lead to eventually broken profiler traces in some cases like using `PlayerInput` (case ISXB-393).
16+
- `VirtualMouseInput` not working correctly with `CanvasScaler` settings other than `ConstantPixelSize`. Fix contributed by [ad-walker](https://github.com/ad-walker) in [#1078](https://github.com/Unity-Technologies/InputSystem/pull/1078).
17+
18+
### Added
19+
20+
- Added an explicit `Disable System Mouse` setting to `VirtualMouseInput` to allow toggling the default behavior off which makes the component turn off the system mouse while it is enabled (so as to suppress the system mouse doubling the input activity on the VirtualMouse).
1621

1722
## [1.5.0] - 2023-01-24
1823

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

+62-10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
////TODO: respect cursor lock mode
77

8+
////TODO: find a way to automatically turn the gamepad cursor on/off based on gamepad use
9+
810
////TODO: investigate how driving the HW cursor behaves when FPS drops low
911
//// (also, maybe we can add support where we turn the gamepad mouse on and off automatically based on whether the system mouse is used)
1012

@@ -14,6 +16,8 @@
1416

1517
////TODO: make it work with PlayerInput such that it will automatically look up actions in the actual PlayerInput instance it is used with (based on the action IDs it has)
1618

19+
////FIXME: make this work with world-space canvases
20+
1721
////REVIEW: should we default the SW cursor position to the center of the screen?
1822

1923
////REVIEW: consider this for inclusion directly in the input system
@@ -78,9 +82,10 @@ public float cursorSpeed
7882
/// that is made to correspond to the position of <see cref="virtualMouse"/>. If this is set to <see
7983
/// cref="CursorMode.HardwareCursorIfAvailable"/> and there is a native <see cref="Mouse"/> device present,
8084
/// the component will take over that mouse device and disable it (so as for it to not also generate position
81-
/// updates). It will then use <see cref="Mouse.WarpCursorPosition"/> to move the system mouse cursor to
82-
/// correspond to the position of the <see cref="virtualMouse"/>. In this case, <see cref="cursorGraphic"/>
83-
/// will be disabled and <see cref="cursorTransform"/> will not be updated.
85+
/// updates) except when this is explicitly disabled via <see cref="disableSystemMouse"/>. It will then use
86+
/// <see cref="Mouse.WarpCursorPosition"/> to move the system mouse cursor to correspond to the position of the
87+
/// <see cref="virtualMouse"/>. In this case, <see cref="cursorGraphic"/> will be disabled and
88+
/// <see cref="cursorTransform"/> will not be updated.
8489
/// </summary>
8590
/// <value>Whether the system mouse cursor (if present) should be made to correspond with the virtual mouse position.</value>
8691
/// <remarks>
@@ -100,7 +105,8 @@ public CursorMode cursorMode
100105
// If we're turning it off, make sure we re-enable the system mouse.
101106
if (m_CursorMode == CursorMode.HardwareCursorIfAvailable && m_SystemMouse != null)
102107
{
103-
InputSystem.EnableDevice(m_SystemMouse);
108+
if (m_DisableSystemMouse)
109+
InputSystem.EnableDevice(m_SystemMouse);
104110
m_SystemMouse = null;
105111
}
106112

@@ -157,11 +163,51 @@ public float scrollSpeed
157163
/// </remarks>
158164
public Mouse virtualMouse => m_VirtualMouse;
159165

166+
/// <summary>
167+
/// If <see cref="cursorMode"/> is set to <see cref="CursorMode.HardwareCursorIfAvailable"/>, whether to
168+
/// disable the system mouse, if present. This is on by default.
169+
/// </summary>
170+
/// <value>If true, the system mouse will be disabled if present and while the VirtualMouseInput component is active.</value>
171+
/// <remarks>
172+
/// If the component drives the system mouse cursor rather than using a software cursor, the system mouse cursor position will
173+
/// get warped around using <see cref="Mouse.WarpCursorPosition"/>. This, however, has the side-effect of generating input
174+
/// on the system <see cref="Mouse"/> device. In other words, mouse motion from the gamepad will come in through both
175+
/// the VirtualMouse created for the gamepad and the <see cref="Mouse"/> added by the system (with a one frame lag for
176+
/// the latter).
177+
///
178+
/// To avoid this, the system mouse will by default get disabled while the VirtualMouseInput component is enabled. Thus,
179+
/// the system <see cref="Mouse"/> will not receive input while the VirtualMouseInput component is enabled. The idea here
180+
/// is that the application should determine when the gamepad is used and only turn on the gamepad cursor while this is
181+
/// the case. One possible approach is to set up a control scheme for gamepads and enable the gamepad mouse cursor only
182+
/// while the gamepad scheme is active.
183+
///
184+
/// However, by setting this property to false, the disabling of the system <see cref="Mouse"/> device can be suppressed.
185+
/// This means the system mouse will stay fully functional. You will, however, see concurrent input on both the VirtualMouse
186+
/// and the system mouse. This may, for example, interfere with automatic control scheme switching (which is why the disabling
187+
/// is on by default).
188+
/// </remarks>
189+
public bool disableSystemMouse
190+
{
191+
get => m_DisableSystemMouse;
192+
set
193+
{
194+
if (value == m_DisableSystemMouse)
195+
return;
196+
m_DisableSystemMouse = value;
197+
198+
if (m_SystemMouse != null)
199+
{
200+
if (value)
201+
InputSystem.DisableDevice(m_SystemMouse);
202+
else
203+
InputSystem.EnableDevice(m_SystemMouse);
204+
}
205+
}
206+
}
207+
160208
/// <summary>
161209
/// The Vector2 stick input that drives the mouse cursor, i.e. <see cref="Pointer.position"/> on
162-
/// <see cref="virtualMouse"/> and the <a
163-
/// href="https://docs.unity3d.com/ScriptReference/RectTransform-anchoredPosition.html">anchoredPosition</a>
164-
/// on <see cref="cursorTransform"/> (if set).
210+
/// <see cref="virtualMouse"/> and the position on <see cref="cursorTransform"/> (if set).
165211
/// </summary>
166212
/// <value>Stick input that drives cursor position.</value>
167213
/// <remarks>
@@ -294,7 +340,7 @@ protected void OnEnable()
294340
// Set initial cursor position.
295341
if (m_CursorTransform != null)
296342
{
297-
var position = m_CursorTransform.anchoredPosition;
343+
var position = m_CursorTransform.position;
298344
InputState.Change(m_VirtualMouse.position, position);
299345
m_SystemMouse?.WarpCursorPosition(position);
300346
}
@@ -388,7 +434,8 @@ private void TryEnableHardwareCursor()
388434
return;
389435
}
390436

391-
InputSystem.DisableDevice(m_SystemMouse);
437+
if (m_DisableSystemMouse)
438+
InputSystem.DisableDevice(m_SystemMouse);
392439

393440
// Sync position.
394441
if (m_VirtualMouse != null)
@@ -450,7 +497,7 @@ private void UpdateMotion()
450497
if (m_CursorTransform != null &&
451498
(m_CursorMode == CursorMode.SoftwareCursor ||
452499
(m_CursorMode == CursorMode.HardwareCursorIfAvailable && m_SystemMouse == null)))
453-
m_CursorTransform.anchoredPosition = newPosition;
500+
m_CursorTransform.position = newPosition;
454501

455502
m_LastStickValue = stickValue;
456503
m_LastTime = currentTime;
@@ -475,6 +522,11 @@ private void UpdateMotion()
475522
[Tooltip("Whether the component should set the cursor position of the hardware mouse cursor, if one is available. If so, "
476523
+ "the software cursor pointed (to by 'Cursor Graphic') will be hidden.")]
477524
[SerializeField] private CursorMode m_CursorMode;
525+
[Tooltip("With 'Cursor Mode' set to 'Hardware Cursor If Available', whether to disable the system mouse. The cursor warping that is used "
526+
+ "to drive the HW cursor will generate input on the mouse device which mirrors the input on the virtual mouse. By enabling this flag, "
527+
+ "this input can be suppressed by disabling the system mouse altogether. Note that this will make *no* input from the system mouse come "
528+
+ "through while the VirtualMouseInput component is active.")]
529+
[SerializeField] private bool m_DisableSystemMouse = true;
478530
[Tooltip("The graphic that represents the software cursor. This is hidden if a hardware cursor (see 'Cursor Mode') is used.")]
479531
[SerializeField] private Graphic m_CursorGraphic;
480532
[Tooltip("The transform for the software cursor. Will only be set if a software cursor is used (see 'Cursor Mode'). Moving the cursor "

0 commit comments

Comments
 (0)