A game about forced loneliness, made by TACStudios
at master 176 lines 7.3 kB view raw
1using System.Collections.Generic; 2using System.Linq; 3 4namespace UnityEngine 5{ 6#if UNITY_EDITOR 7 using UnityEditor; 8 9 public class InputManagerEntry 10 { 11 public enum Kind 12 { 13 KeyOrButton, 14 Mouse, 15 Axis 16 } 17 18 public enum Axis 19 { 20 X, 21 Y, 22 Third, 23 Fourth, 24 Fifth, 25 Sixth, 26 Seventh, 27 Eigth 28 } 29 30 public enum Joy 31 { 32 All, 33 First, 34 Second 35 } 36 37 public string name = ""; 38 public string desc = ""; 39 public string btnNegative = ""; 40 public string btnPositive = ""; 41 public string altBtnNegative = ""; 42 public string altBtnPositive = ""; 43 public float gravity = 0.0f; 44 public float deadZone = 0.0f; 45 public float sensitivity = 0.0f; 46 public bool snap = false; 47 public bool invert = false; 48 public Kind kind = Kind.Axis; 49 public Axis axis = Axis.X; 50 public Joy joystick = Joy.All; 51 } 52 53 public static class InputRegistering 54 { 55 static void CopyEntry(SerializedProperty spAxis, InputManagerEntry entry) 56 { 57 spAxis.FindPropertyRelative("m_Name").stringValue = entry.name; 58 spAxis.FindPropertyRelative("descriptiveName").stringValue = entry.desc; 59 spAxis.FindPropertyRelative("negativeButton").stringValue = entry.btnNegative; 60 spAxis.FindPropertyRelative("altNegativeButton").stringValue = entry.altBtnNegative; 61 spAxis.FindPropertyRelative("positiveButton").stringValue = entry.btnPositive; 62 spAxis.FindPropertyRelative("altPositiveButton").stringValue = entry.altBtnPositive; 63 spAxis.FindPropertyRelative("gravity").floatValue = entry.gravity; 64 spAxis.FindPropertyRelative("dead").floatValue = entry.deadZone; 65 spAxis.FindPropertyRelative("sensitivity").floatValue = entry.sensitivity; 66 spAxis.FindPropertyRelative("snap").boolValue = entry.snap; 67 spAxis.FindPropertyRelative("invert").boolValue = entry.invert; 68 spAxis.FindPropertyRelative("type").intValue = (int)entry.kind; 69 spAxis.FindPropertyRelative("axis").intValue = (int)entry.axis; 70 spAxis.FindPropertyRelative("joyNum").intValue = (int)entry.joystick; 71 } 72 73 static void AddEntriesWithoutCheck(SerializedProperty spAxes, List<InputManagerEntry> newEntries) 74 { 75 if (newEntries.Count == 0) 76 return; 77 78 int endOfCurrentInputList = spAxes.arraySize; 79 spAxes.arraySize = endOfCurrentInputList + newEntries.Count; 80 // Assignment to spAxes.arraySize resizes the spAxes array to at least 1 larger than it used to be, and 81 // therefore it is OK to use endOfCurrentInputList ("one-past-end of previous size") to get the array iterator. 82 SerializedProperty spAxis = spAxes.GetArrayElementAtIndex(endOfCurrentInputList); 83 for (int i = 0; i < newEntries.Count; ++i, spAxis.Next(false)) 84 CopyEntry(spAxis, newEntries[i]); 85 } 86 87 // Get a representation of the already registered inputs 88 static List<(string name, InputManagerEntry.Kind kind)> GetCachedInputs(SerializedProperty spAxes) 89 { 90 int size = spAxes.arraySize; 91 List<(string name, InputManagerEntry.Kind kind)> result = new List<(string name, InputManagerEntry.Kind kind)>(size); 92 93 if (size == 0) 94 return result; 95 96 SerializedProperty spAxis = spAxes.GetArrayElementAtIndex(0); 97 for (int i = 0; i < size; ++i, spAxis.Next(false)) 98 result.Add((spAxis.FindPropertyRelative("m_Name").stringValue, (InputManagerEntry.Kind)spAxis.FindPropertyRelative("type").intValue)); 99 return result; 100 } 101 102 internal static List<InputManagerEntry> GetEntriesWithoutDuplicates(List<InputManagerEntry> entries) 103 { 104 return entries 105 .GroupBy(x => new { x.name, x.kind }) // Create groups { name, kind } 106 .Select(y => y.First()) // Select first entry from each group, ignoring duplicates 107 .ToList(); 108 } 109 110 internal static List<InputManagerEntry> GetEntriesWithoutAlreadyRegistered(List<InputManagerEntry> entries, List<(string name, InputManagerEntry.Kind kind)> cachedEntries) 111 { 112 return entries 113 .Where(entry => !cachedEntries.Any(cachedEntry => cachedEntry.name == entry.name && cachedEntry.kind == entry.kind)) 114 .ToList(); 115 } 116 117 static SerializedObject GetInputManagerSO() 118 { 119 var assets = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/InputManager.asset"); 120 121 // Potentially there are multiple objects inside the Asset, we need to make sure we only grab the correct one. 122 foreach (var obj in assets) 123 { 124 // Check the asset name is correct 125 if (obj != null && obj.name == "InputManager") 126 { 127 // There is an issue where multiple objects can be named InputManager for a 128 // period when they are added to the file, even if they are given unique names. 129 // In the editor we also check the type is InputManager to work around this, however 130 // that type is not available here. So instead we inspect the contents to confirm it's 131 // the object we expect. 132 var soInputManager = new SerializedObject(obj); 133 var spAxes = soInputManager.FindProperty("m_Axes"); 134 if (spAxes != null) 135 return soInputManager; 136 } 137 } 138 return null; 139 } 140 141 public static void RegisterInputs(List<InputManagerEntry> entries) 142 { 143#if ENABLE_INPUT_SYSTEM && ENABLE_INPUT_SYSTEM_PACKAGE 144 Debug.LogWarning("Trying to add entry in the legacy InputManager but using InputSystem package. Skipping."); 145 return; 146#else 147 // Grab reference to input manager 148 var soInputManager = GetInputManagerSO(); 149 150 // Temporary fix. This happens some time with HDRP init when it's called before asset database is initialized (probably related to package load order). 151 if (soInputManager == null) 152 return; 153 154 var spAxes = soInputManager.FindProperty("m_Axes"); 155 156 // At this point, we assume that entries in spAxes are already unique. 157 158 // Ensure no double entry are tried to be registered (trim early) 159 var uniqueEntries = GetEntriesWithoutDuplicates(entries); 160 161 // Cache already existing entries to minimally use serialization 162 var cachedEntries = GetCachedInputs(spAxes); 163 164 // And trim pending entries regarding already cached ones. 165 var uniqueNewEntries = GetEntriesWithoutAlreadyRegistered(uniqueEntries, cachedEntries); 166 167 // Add now unique entries 168 AddEntriesWithoutCheck(spAxes, uniqueNewEntries); 169 170 // Commit 171 soInputManager.ApplyModifiedProperties(); 172#endif 173 } 174 } 175#endif 176}