From 84459779609396ca06a9525b2411ef0a73d032cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Wed, 27 Nov 2024 12:51:42 +0100 Subject: [PATCH 1/6] FIX: Visualizers are now created even when no current device exist. This was previously incorrectly skipped, but only value control visualizer needs a device to show anything useful. --- .../Visualizers/InputControlVisualizer.cs | 58 +++++++++---------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/Assets/Samples/Visualizers/InputControlVisualizer.cs b/Assets/Samples/Visualizers/InputControlVisualizer.cs index 9a2950c7ab..c1c50121e8 100644 --- a/Assets/Samples/Visualizers/InputControlVisualizer.cs +++ b/Assets/Samples/Visualizers/InputControlVisualizer.cs @@ -163,30 +163,29 @@ private void ResolveControl() SetupVisualizer(); } - private void SetupVisualizer() + private static VisualizationHelpers.Visualizer CreateVisualizer(Mode mode, InputControl control, int historySamples) { - if (m_Control == null) - { - m_Visualizer = null; - return; - } - - switch (m_Visualization) + switch (mode) { case Mode.Value: { - var valueType = m_Control.valueType; + // This visualization mode requires a control + if (control == null) + return null; + + VisualizationHelpers.Visualizer visualizer = null; + var valueType = control.valueType; if (valueType == typeof(Vector2)) - m_Visualizer = new VisualizationHelpers.Vector2Visualizer(m_HistorySamples); + visualizer = new VisualizationHelpers.Vector2Visualizer(historySamples); else if (valueType == typeof(float)) - m_Visualizer = new VisualizationHelpers.ScalarVisualizer(m_HistorySamples) + visualizer = new VisualizationHelpers.ScalarVisualizer(historySamples) { ////TODO: pass actual min/max limits of control limitMax = 1, limitMin = 0 }; else if (valueType == typeof(int)) - m_Visualizer = new VisualizationHelpers.ScalarVisualizer(m_HistorySamples) + visualizer = new VisualizationHelpers.ScalarVisualizer(historySamples) { ////TODO: pass actual min/max limits of control limitMax = 1, @@ -196,66 +195,65 @@ private void SetupVisualizer() { ////TODO: generic visualizer } - break; + return visualizer; } case Mode.Events: { - var visualizer = new VisualizationHelpers.TimelineVisualizer(m_HistorySamples) + var visualizer = new VisualizationHelpers.TimelineVisualizer(historySamples) { timeUnit = VisualizationHelpers.TimelineVisualizer.TimeUnit.Frames, - historyDepth = m_HistorySamples, + historyDepth = historySamples, showLimits = true, limitsY = new Vector2(0, 5) // Will expand upward automatically }; - m_Visualizer = visualizer; visualizer.AddTimeline("Events", Color.green, VisualizationHelpers.TimelineVisualizer.PlotType.BarChart); - break; + return visualizer; } case Mode.MaximumLag: { - var visualizer = new VisualizationHelpers.TimelineVisualizer(m_HistorySamples) + var visualizer = new VisualizationHelpers.TimelineVisualizer(historySamples) { timeUnit = VisualizationHelpers.TimelineVisualizer.TimeUnit.Frames, - historyDepth = m_HistorySamples, + historyDepth = historySamples, valueUnit = new GUIContent("ms"), showLimits = true, limitsY = new Vector2(0, 6) }; - m_Visualizer = visualizer; visualizer.AddTimeline("MaxLag", Color.red, VisualizationHelpers.TimelineVisualizer.PlotType.BarChart); - break; + return visualizer; } case Mode.Bytes: { - var visualizer = new VisualizationHelpers.TimelineVisualizer(m_HistorySamples) + var visualizer = new VisualizationHelpers.TimelineVisualizer(historySamples) { timeUnit = VisualizationHelpers.TimelineVisualizer.TimeUnit.Frames, valueUnit = new GUIContent("bytes"), - historyDepth = m_HistorySamples, + historyDepth = historySamples, showLimits = true, limitsY = new Vector2(0, 64) }; - m_Visualizer = visualizer; visualizer.AddTimeline("Bytes", Color.red, VisualizationHelpers.TimelineVisualizer.PlotType.BarChart); - break; + return visualizer; } case Mode.DeviceCurrent: - { - m_Visualizer = new VisualizationHelpers.CurrentDeviceVisualizer(); - break; - } + return new VisualizationHelpers.CurrentDeviceVisualizer(); default: - throw new NotImplementedException(); + throw new ArgumentOutOfRangeException(mode.ToString()); } } + + private void SetupVisualizer() + { + m_Visualizer = CreateVisualizer(m_Visualization, m_Control, m_HistorySamples); + } private static void OnDeviceChange(InputDevice device, InputDeviceChange change) { From a426fb4f829317cfa655db780c5d5c9de1fb1241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Wed, 27 Nov 2024 15:19:33 +0100 Subject: [PATCH 2/6] FIX: Added a new setting which force visualizers to map to the control of the current device of the associated device interface type. Updated GamepadVisualizer to use this setting (ON) for all relevant controls. --- .../Visualizers/GamepadVisualizer.unity | 152 +++++++++++++++++- .../Visualizers/InputControlVisualizer.cs | 38 ++++- 2 files changed, 183 insertions(+), 7 deletions(-) diff --git a/Assets/Samples/Visualizers/GamepadVisualizer.unity b/Assets/Samples/Visualizers/GamepadVisualizer.unity index 5db7272668..0e2a0b65ea 100644 --- a/Assets/Samples/Visualizers/GamepadVisualizer.unity +++ b/Assets/Samples/Visualizers/GamepadVisualizer.unity @@ -42,8 +42,7 @@ RenderSettings: --- !u!157 &3 LightmapSettings: m_ObjectHideFlags: 0 - serializedVersion: 13 - m_BakeOnSceneLoad: 0 + serializedVersion: 12 m_GISettings: serializedVersion: 2 m_BounceScale: 1 @@ -218,7 +217,7 @@ LightingSettings: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: Settings.lighting - serializedVersion: 9 + serializedVersion: 8 m_EnableBakedLightmaps: 1 m_EnableRealtimeLightmaps: 1 m_RealtimeEnvironmentLighting: 1 @@ -272,6 +271,18 @@ LightingSettings: m_PVRFilteringAtrousPositionSigmaIndirect: 2 m_PVRFilteringAtrousPositionSigmaAO: 1 m_RespectSceneVisibilityWhenBakingGI: 0 +--- !u!114 &2122909276 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 5802899217532024206, guid: b8429651427a640919754290f3704312, + type: 3} + m_PrefabInstance: {fileID: 5430831075364511436} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 50c7363fac4d24ae8a679e3e8f1fa838, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1001 &5430831075364511436 PrefabInstance: m_ObjectHideFlags: 0 @@ -280,6 +291,86 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 0} m_Modifications: + - target: {fileID: 5430831073950378564, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074071876626, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074153646139, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074316365814, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074333637590, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074406035310, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074569589722, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074657706043, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074722065634, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074890777048, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074908778959, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831074960731594, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075105443483, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075159756558, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075192722340, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075336578713, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} - target: {fileID: 5430831075476541849, guid: b8429651427a640919754290f3704312, type: 3} propertyPath: m_Name @@ -335,6 +426,61 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 5430831075516136799, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrent + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075516136799, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075516136799, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentForControlIndex + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075640135793, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075882524474, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075888579014, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075958221745, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5430831075990510060, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 5802899217532024206, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_Master + value: + objectReference: {fileID: 2122909276} + - target: {fileID: 5802899217532024206, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6586345530156004295, guid: b8429651427a640919754290f3704312, + type: 3} + propertyPath: m_UseCurrentDevice + value: 1 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] diff --git a/Assets/Samples/Visualizers/InputControlVisualizer.cs b/Assets/Samples/Visualizers/InputControlVisualizer.cs index c1c50121e8..3bc80eb4d3 100644 --- a/Assets/Samples/Visualizers/InputControlVisualizer.cs +++ b/Assets/Samples/Visualizers/InputControlVisualizer.cs @@ -138,13 +138,30 @@ public int controlIndex + "which of the controls to visualize.")] [InputControl, SerializeField] private string m_ControlPath; [Tooltip("If multiple controls match 'Control Path' at runtime, this property decides " - + "which control to visualize from the list of candidates. It is a zero-based index.")] + + "which control to visualize from the list of candidates. It is a zero-based index. " + + "This is ignored if using current device instead.")] [SerializeField] private int m_ControlIndex; + [Tooltip("If set, ignores control index and maps a control of the current device (if it exist) or none.")] + [SerializeField] private bool m_UseCurrentDevice; + [NonSerialized] private InputControl m_Control; private static List s_EnabledInstances; + private static InputControl ResolveCurrentControl(InputControlList candidates) + { + // Only accept control that belongs to the current device of the same device type as candidate control device type. + foreach (var candidate in candidates) + { + if (candidate.device == GetCurrentDevice(candidate.device)) ; + { + return candidate; + } + } + return null; + } + private void ResolveControl() { m_Control = null; @@ -154,7 +171,9 @@ private void ResolveControl() using (var candidates = InputSystem.FindControls(m_ControlPath)) { var numCandidates = candidates.Count; - if (numCandidates > 1 && m_ControlIndex < numCandidates && m_ControlIndex >= 0) + if (m_UseCurrentDevice) + m_Control = ResolveCurrentControl(candidates); + else if (numCandidates > 1 && m_ControlIndex < numCandidates && m_ControlIndex >= 0) m_Control = candidates[m_ControlIndex]; else if (numCandidates > 0) m_Control = candidates[0]; @@ -163,6 +182,17 @@ private void ResolveControl() SetupVisualizer(); } + private static InputDevice GetCurrentDevice(InputDevice device) + { + if (device is Gamepad) return Gamepad.current; + if (device is Mouse) return Mouse.current; + if (device is Pen) return Pen.current; + if (device is Pointer) return Pointer.current; // should be last, because it's a base class for Mouse and Pen + + throw new ArgumentException( + $"Expected device type that implements .current, but got '{device.name}' (deviceId: {device.deviceId}) instead "); + } + private static VisualizationHelpers.Visualizer CreateVisualizer(Mode mode, InputControl control, int historySamples) { switch (mode) @@ -172,7 +202,7 @@ private static VisualizationHelpers.Visualizer CreateVisualizer(Mode mode, Input // This visualization mode requires a control if (control == null) return null; - + VisualizationHelpers.Visualizer visualizer = null; var valueType = control.valueType; if (valueType == typeof(Vector2)) @@ -249,7 +279,7 @@ private static VisualizationHelpers.Visualizer CreateVisualizer(Mode mode, Input throw new ArgumentOutOfRangeException(mode.ToString()); } } - + private void SetupVisualizer() { m_Visualizer = CreateVisualizer(m_Visualization, m_Control, m_HistorySamples); From f1d97ee1230c8a992411724f120768eb0921f26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Akan=20Sidenvall?= Date: Wed, 27 Nov 2024 15:29:35 +0100 Subject: [PATCH 3/6] Updated CHANGELOG --- Packages/com.unity.inputsystem/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 8cd2fc389f..e30d0bb2b0 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -26,10 +26,12 @@ however, it has to be formatted properly to pass verification tests. - Fixed icon scaling in Input Actions window. - Fixed an issue where removing the InputSystem package could lead to invalid input handling settings. - Fixed `ArgumentOutOfRangeException` when adding a new Control Scheme with any Device selected. [ISXB-1129](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1129) +- Fixed an issue in `Samples/Visualizers/GamepadVisualizer.unity` sample where the visualization wouldn't handle device disconnects or current device changes properly (ISXB-1243). ### Changed - Added back the InputManager to InputSystem project-wide asset migration code with performance improvement (ISX-2086). - Changed `OnScreenControl` to automaticaly switch, in Single Player with autoswitch enabled, to the target device control scheme when the first component is enabled to prevent bad interactions when it start. +- Changed `Samples/Visualizers/GamepadVisualizer.unity` to visualize the control values of the current device instead of the first device. ## [1.11.2] - 2024-10-16 From e2778c93896478cd4b0ad22f89e6444caca981c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Sidenvall?= Date: Thu, 28 Nov 2024 13:19:11 +0100 Subject: [PATCH 4/6] Removed accidental semicolon, likely by accidentally touching keyboard. --- Assets/Samples/Visualizers/InputControlVisualizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Samples/Visualizers/InputControlVisualizer.cs b/Assets/Samples/Visualizers/InputControlVisualizer.cs index 3bc80eb4d3..42d5841c83 100644 --- a/Assets/Samples/Visualizers/InputControlVisualizer.cs +++ b/Assets/Samples/Visualizers/InputControlVisualizer.cs @@ -154,7 +154,7 @@ private static InputControl ResolveCurrentControl(InputControlList // Only accept control that belongs to the current device of the same device type as candidate control device type. foreach (var candidate in candidates) { - if (candidate.device == GetCurrentDevice(candidate.device)) ; + if (candidate.device == GetCurrentDevice(candidate.device)) { return candidate; } From 6f82e69e4975e428ccc4749b68a10497bd0bd99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Sidenvall?= Date: Thu, 28 Nov 2024 15:27:18 +0100 Subject: [PATCH 5/6] FIX: Added code to attempt resolving control when set to use current device and control have not been previously resolved. Needed since the is no callback when it changes. --- .../Samples/Visualizers/InputControlVisualizer.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Assets/Samples/Visualizers/InputControlVisualizer.cs b/Assets/Samples/Visualizers/InputControlVisualizer.cs index 42d5841c83..cd6ceedd0a 100644 --- a/Assets/Samples/Visualizers/InputControlVisualizer.cs +++ b/Assets/Samples/Visualizers/InputControlVisualizer.cs @@ -154,11 +154,11 @@ private static InputControl ResolveCurrentControl(InputControlList // Only accept control that belongs to the current device of the same device type as candidate control device type. foreach (var candidate in candidates) { - if (candidate.device == GetCurrentDevice(candidate.device)) - { + var currentDevice = GetCurrentDevice(candidate.device); + if (candidate.device == currentDevice) return candidate; - } } + return null; } @@ -182,6 +182,13 @@ private void ResolveControl() SetupVisualizer(); } + void Update() + { + // There is currently no callback when current device changes so we will reattempt to resolve control + if (m_UseCurrentDevice && m_Control == null) + ResolveControl(); + } + private static InputDevice GetCurrentDevice(InputDevice device) { if (device is Gamepad) return Gamepad.current; From e3bd2e4c6c497e7c300771e3cfae4d630ea1a720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Sidenvall?= Date: Fri, 29 Nov 2024 11:51:10 +0100 Subject: [PATCH 6/6] FIX: Added visualizer and control resolve if Gamepad.current changes after being assigned to support using multiple gamepads simultaneously. Note that it may still be a problem if gamepads are noisy. --- Assets/Samples/Visualizers/InputControlVisualizer.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Assets/Samples/Visualizers/InputControlVisualizer.cs b/Assets/Samples/Visualizers/InputControlVisualizer.cs index cd6ceedd0a..d8be3a65d4 100644 --- a/Assets/Samples/Visualizers/InputControlVisualizer.cs +++ b/Assets/Samples/Visualizers/InputControlVisualizer.cs @@ -185,8 +185,13 @@ private void ResolveControl() void Update() { // There is currently no callback when current device changes so we will reattempt to resolve control - if (m_UseCurrentDevice && m_Control == null) - ResolveControl(); + if (m_UseCurrentDevice) + { + if (m_Control != null && m_Control.device != GetCurrentDevice(m_Control.device)) + m_Control = null; + if (m_Control == null) + ResolveControl(); + } } private static InputDevice GetCurrentDevice(InputDevice device)