From 84d68fccefa294b44a055c7d85eb53ed2afed7df Mon Sep 17 00:00:00 2001 From: RSlysz Date: Mon, 1 Feb 2021 17:36:47 +0100 Subject: [PATCH 1/7] Update InputRegistering.cs --- .../Runtime/Inputs/InputRegistering.cs | 143 ++++++++++++++---- 1 file changed, 116 insertions(+), 27 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs index a9f2c6c73c5..a975e3758e4 100644 --- a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs +++ b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs @@ -11,24 +11,34 @@ public enum Kind { KeyOrButton, Mouse, Axis } public enum Axis { X, Y, Third, Fourth, Fifth, Sixth, Seventh, Eigth } public enum Joy { All, First, Second } - public string name = ""; - public string desc = ""; - public string btnNegative = ""; - public string btnPositive = ""; - public string altBtnNegative = ""; - public string altBtnPositive = ""; - public float gravity = 0.0f; - public float deadZone = 0.0f; - public float sensitivity = 0.0f; - public bool snap = false; - public bool invert = false; - public Kind kind = Kind.Axis; - public Axis axis = Axis.X; - public Joy joystick = Joy.All; + public string name = ""; + public string desc = ""; + public string btnNegative = ""; + public string btnPositive = ""; + public string altBtnNegative = ""; + public string altBtnPositive = ""; + public float gravity = 0.0f; + public float deadZone = 0.0f; + public float sensitivity = 0.0f; + public bool snap = false; + public bool invert = false; + public Kind kind = Kind.Axis; + public Axis axis = Axis.X; + public Joy joystick = Joy.All; + + internal bool IsEqual((string name, InputManagerEntry.Kind kind) partialEntry) + => this.name == partialEntry.name && this.kind == partialEntry.kind; + + internal bool IsEqual(InputManagerEntry other) + => this.name == other.name && this.kind == other.kind; } - public class InputRegistering + public static class InputRegistering { + static List s_PendingInputsToRegister = new List(); + + static bool havePendingOperation => s_PendingInputsToRegister.Count > 0; + static bool InputAlreadyRegistered(string name, InputManagerEntry.Kind kind, SerializedProperty spAxes) { for (var i = 0; i < spAxes.arraySize; ++i) @@ -43,13 +53,8 @@ static bool InputAlreadyRegistered(string name, InputManagerEntry.Kind kind, Ser return false; } - static void WriteEntry(SerializedProperty spAxes, InputManagerEntry entry) + static void CopyEntry(SerializedProperty spAxis, InputManagerEntry entry) { - if (InputAlreadyRegistered(entry.name, entry.kind, spAxes)) - return; - - spAxes.InsertArrayElementAtIndex(spAxes.arraySize); - var spAxis = spAxes.GetArrayElementAtIndex(spAxes.arraySize - 1); spAxis.FindPropertyRelative("m_Name").stringValue = entry.name; spAxis.FindPropertyRelative("descriptiveName").stringValue = entry.desc; spAxis.FindPropertyRelative("negativeButton").stringValue = entry.btnNegative; @@ -66,8 +71,76 @@ static void WriteEntry(SerializedProperty spAxes, InputManagerEntry entry) spAxis.FindPropertyRelative("joyNum").intValue = (int)entry.joystick; } - public static void RegisterInputs(List entries) + static void AddEntriesWithoutCheck(SerializedProperty spAxes, List newEntries) + { + int startRange = spAxes.arraySize; + int endRange = startRange + newEntries.Count; + spAxes.arraySize = endRange; + + for (int i = startRange; i < endRange; ++i) + CopyEntry(spAxes.GetArrayElementAtIndex(i), newEntries[i]); + } + + // Get a representation of the already registered inputs + static List<(string name, InputManagerEntry.Kind kind)> GetCachedInputs(SerializedProperty spAxes) + { + int size = spAxes.arraySize; + List<(string name, InputManagerEntry.Kind kind)> result = new List<(string name, InputManagerEntry.Kind kind)>(size); + for (int i = 0; i < size; ++i) + { + var spAxis = spAxes.GetArrayElementAtIndex(i); + result.Add((spAxis.FindPropertyRelative("m_Name").stringValue, (InputManagerEntry.Kind)spAxis.FindPropertyRelative("type").intValue)); + } + return result; + } + + static void MakeUniquePendingInputsToRegister() + { + for (int pendingIndex = s_PendingInputsToRegister.Count - 1; pendingIndex > 0; --pendingIndex) + { + InputManagerEntry pendingEntry = s_PendingInputsToRegister[pendingIndex]; + int checkedIndex = pendingIndex - 1; + for (; checkedIndex > -1 && !pendingEntry.IsEqual(s_PendingInputsToRegister[checkedIndex]); --checkedIndex) ; + + if (checkedIndex == -1) + continue; + + // There is a duplicate entry in PendingInputesToRegister. + // Debug.LogWarning($"Two entries with same name and kind are tryed to be added at same time. Only first occurence is kept. Name:{pendingEntry.name} Kind:{pendingEntry.kind}"); + + // Keep only first. + // Counting decreasingly will have no impact on index before pendingIndex. So we can safely remove it. + s_PendingInputsToRegister.RemoveAt(pendingIndex); + } + } + + static void RemovePendingInputsToAddThatAreAlreadyRegistered(List<(string name, InputManagerEntry.Kind kind)> cachedEntries, List newEntries) + { + for (int newIndex = newEntries.Count - 1; newIndex >= 0; --newIndex) + { + var newEntry = newEntries[newIndex]; + int checkedIndex = cachedEntries.Count - 1; + for (; checkedIndex > -1 && !newEntry.IsEqual(cachedEntries[checkedIndex]); --checkedIndex) ; + + if (checkedIndex == -1) + continue; + + // There is a already a cached entry that correspond. + // Debug.LogWarning($"Another entry with same name and kind already exist. Skiping this one. Name:{newEntry.name} Kind:{newEntry.kind}"); + + // Keep only first. + // Counting decreasingly will have no impact on index before pendingIndex. So we can safely remove it. + s_PendingInputsToRegister.RemoveAt(newIndex); + } + } + + static void DelayedRegisterInput() { + // Exit quickly if nothing more to register + // (case when several different class try to register, only first call will do all) + if (!havePendingOperation) + return; + // Grab reference to input manager var assets = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/InputManager.asset"); // Temporary fix. This happens some time with HDRP init when it's called before asset database is initialized (probably related to package load order). @@ -76,18 +149,34 @@ public static void RegisterInputs(List entries) var inputManager = assets[0]; - // Wrap in serialized object + // Wrap in serialized object to access c++ fields var soInputManager = new SerializedObject(inputManager); var spAxes = soInputManager.FindProperty("m_Axes"); - foreach (InputManagerEntry entry in entries) - { - WriteEntry(spAxes, entry); - } + // At this point, we assume that entries in spAxes are already unique. + + // Ensure no double entry are tried to be registered (trim early) + MakeUniquePendingInputsToRegister(); + + // Cache already existing entries to minimaly use serialization + var cachedEntries = GetCachedInputs(spAxes); + // And trim pending entries regarding already cached ones. + RemovePendingInputsToAddThatAreAlreadyRegistered(cachedEntries, s_PendingInputsToRegister); + + // Add now unique entries + AddEntriesWithoutCheck(spAxes, s_PendingInputsToRegister); // Commit soInputManager.ApplyModifiedProperties(); } + + public static void RegisterInputs(List entries) + { + s_PendingInputsToRegister.AddRange(entries); + + //delay the call in order to do only one pass event if several different class register inputs + EditorApplication.delayCall += DelayedRegisterInput; + } } #endif } From 98a461320294dce26c75464b0efc053d5c6967f6 Mon Sep 17 00:00:00 2001 From: RSlysz Date: Wed, 3 Feb 2021 14:23:57 +0100 Subject: [PATCH 2/7] Remove asset modification if InputSystem package is in use --- .../Runtime/Debugging/DebugManager.Actions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.Actions.cs b/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.Actions.cs index 82002b9b78d..623fc8e3d3f 100644 --- a/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.Actions.cs +++ b/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.Actions.cs @@ -275,7 +275,7 @@ internal bool GetActionToggleDebugMenuWithTouch() void RegisterInputs() { -#if UNITY_EDITOR +#if UNITY_EDITOR //&& !USE_INPUT_SYSTEM var inputEntries = new List { new InputManagerEntry { name = kEnableDebugBtn1, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left ctrl", altBtnPositive = "joystick button 8" }, From 8d83c7c19ac9739f9ab18d14bfa971da59e3f0ec Mon Sep 17 00:00:00 2001 From: RSlysz Date: Wed, 3 Feb 2021 17:41:54 +0100 Subject: [PATCH 3/7] Prevent missuse of InputRegistering while InputSystem package is in use --- .../Runtime/Inputs/InputRegistering.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs index a975e3758e4..dd46835f181 100644 --- a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs +++ b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs @@ -172,10 +172,15 @@ static void DelayedRegisterInput() public static void RegisterInputs(List entries) { +#if ENABLE_INPUT_SYSTEM && ENABLE_INPUT_SYSTEM_PACKAGE + Debug.LogWarning("Trying to add entry in the legacy InputManager but using InputSystem package. Skiping."); + return; +#else s_PendingInputsToRegister.AddRange(entries); //delay the call in order to do only one pass event if several different class register inputs EditorApplication.delayCall += DelayedRegisterInput; +#endif } } #endif From 941e8b2a3081b902058e09d2e1af72e9774ef09e Mon Sep 17 00:00:00 2001 From: RSlysz Date: Wed, 3 Feb 2021 18:06:47 +0100 Subject: [PATCH 4/7] cleaning --- .../Runtime/Debugging/DebugManager.Actions.cs | 2 +- .../Runtime/Inputs/InputRegistering.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.Actions.cs b/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.Actions.cs index 623fc8e3d3f..bac4855acd8 100644 --- a/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.Actions.cs +++ b/com.unity.render-pipelines.core/Runtime/Debugging/DebugManager.Actions.cs @@ -275,7 +275,7 @@ internal bool GetActionToggleDebugMenuWithTouch() void RegisterInputs() { -#if UNITY_EDITOR //&& !USE_INPUT_SYSTEM +#if UNITY_EDITOR && !USE_INPUT_SYSTEM var inputEntries = new List { new InputManagerEntry { name = kEnableDebugBtn1, kind = InputManagerEntry.Kind.KeyOrButton, btnPositive = "left ctrl", altBtnPositive = "joystick button 8" }, diff --git a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs index dd46835f181..70dd73f4891 100644 --- a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs +++ b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs @@ -38,7 +38,7 @@ public static class InputRegistering static List s_PendingInputsToRegister = new List(); static bool havePendingOperation => s_PendingInputsToRegister.Count > 0; - + static bool InputAlreadyRegistered(string name, InputManagerEntry.Kind kind, SerializedProperty spAxes) { for (var i = 0; i < spAxes.arraySize; ++i) @@ -80,7 +80,7 @@ static void AddEntriesWithoutCheck(SerializedProperty spAxes, List GetCachedInputs(SerializedProperty spAxes) { @@ -113,7 +113,7 @@ static void MakeUniquePendingInputsToRegister() s_PendingInputsToRegister.RemoveAt(pendingIndex); } } - + static void RemovePendingInputsToAddThatAreAlreadyRegistered(List<(string name, InputManagerEntry.Kind kind)> cachedEntries, List newEntries) { for (int newIndex = newEntries.Count - 1; newIndex >= 0; --newIndex) @@ -133,7 +133,7 @@ static void RemovePendingInputsToAddThatAreAlreadyRegistered(List<(string name, s_PendingInputsToRegister.RemoveAt(newIndex); } } - + static void DelayedRegisterInput() { // Exit quickly if nothing more to register @@ -154,7 +154,7 @@ static void DelayedRegisterInput() var spAxes = soInputManager.FindProperty("m_Axes"); // At this point, we assume that entries in spAxes are already unique. - + // Ensure no double entry are tried to be registered (trim early) MakeUniquePendingInputsToRegister(); From dfa3be73a952f039ec9bedc7dddf5434ffd23f83 Mon Sep 17 00:00:00 2001 From: RSlysz Date: Wed, 3 Feb 2021 18:12:06 +0100 Subject: [PATCH 5/7] more cleaning --- .../Runtime/Inputs/InputRegistering.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs index 70dd73f4891..9f3916d404d 100644 --- a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs +++ b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs @@ -39,20 +39,6 @@ public static class InputRegistering static bool havePendingOperation => s_PendingInputsToRegister.Count > 0; - static bool InputAlreadyRegistered(string name, InputManagerEntry.Kind kind, SerializedProperty spAxes) - { - for (var i = 0; i < spAxes.arraySize; ++i) - { - var spAxis = spAxes.GetArrayElementAtIndex(i); - var axisName = spAxis.FindPropertyRelative("m_Name").stringValue; - var kindValue = spAxis.FindPropertyRelative("type").intValue; - if (axisName == name && (int)kind == kindValue) - return true; - } - - return false; - } - static void CopyEntry(SerializedProperty spAxis, InputManagerEntry entry) { spAxis.FindPropertyRelative("m_Name").stringValue = entry.name; From 7f255982e4efed3b5eea44faf1a650d899e8f026 Mon Sep 17 00:00:00 2001 From: RSlysz Date: Thu, 4 Feb 2021 16:34:41 +0100 Subject: [PATCH 6/7] Update code to use Next instead of GetArrayElementAtIndex --- .../Runtime/Inputs/InputRegistering.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs index 9f3916d404d..07c53fcc4cc 100644 --- a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs +++ b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs @@ -59,12 +59,12 @@ static void CopyEntry(SerializedProperty spAxis, InputManagerEntry entry) static void AddEntriesWithoutCheck(SerializedProperty spAxes, List newEntries) { - int startRange = spAxes.arraySize; - int endRange = startRange + newEntries.Count; - spAxes.arraySize = endRange; + int endOfCurrentInputList = spAxes.arraySize; + spAxes.arraySize = endOfCurrentInputList + newEntries.Count; - for (int i = startRange; i < endRange; ++i) - CopyEntry(spAxes.GetArrayElementAtIndex(i), newEntries[i]); + SerializedProperty spAxis = spAxes.GetArrayElementAtIndex(endOfCurrentInputList); + for (int i = 0; i < newEntries.Count; ++i, spAxis.Next(false)) + CopyEntry(spAxis, newEntries[i]); } // Get a representation of the already registered inputs @@ -72,11 +72,10 @@ static void AddEntriesWithoutCheck(SerializedProperty spAxes, List result = new List<(string name, InputManagerEntry.Kind kind)>(size); - for (int i = 0; i < size; ++i) - { - var spAxis = spAxes.GetArrayElementAtIndex(i); + + SerializedProperty spAxis = spAxes.GetArrayElementAtIndex(0); + for (int i = 0; i < size; ++i, spAxis.Next(false)) result.Add((spAxis.FindPropertyRelative("m_Name").stringValue, (InputManagerEntry.Kind)spAxis.FindPropertyRelative("type").intValue)); - } return result; } From 3b68c974ea4c9ae3c2c69de86be4ed71af63605e Mon Sep 17 00:00:00 2001 From: RSlysz Date: Thu, 29 Apr 2021 19:53:49 +0200 Subject: [PATCH 7/7] Fix strange out of range error --- .../Runtime/Inputs/InputRegistering.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs index 07c53fcc4cc..2c77fe8da64 100644 --- a/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs +++ b/com.unity.render-pipelines.core/Runtime/Inputs/InputRegistering.cs @@ -62,7 +62,8 @@ static void AddEntriesWithoutCheck(SerializedProperty spAxes, List