@@ -11,45 +11,36 @@ public enum Kind { KeyOrButton, Mouse, Axis }
1111 public enum Axis { X , Y , Third , Fourth , Fifth , Sixth , Seventh , Eigth }
1212 public enum Joy { All , First , Second }
1313
14- public string name = "" ;
15- public string desc = "" ;
16- public string btnNegative = "" ;
17- public string btnPositive = "" ;
18- public string altBtnNegative = "" ;
19- public string altBtnPositive = "" ;
20- public float gravity = 0.0f ;
21- public float deadZone = 0.0f ;
22- public float sensitivity = 0.0f ;
23- public bool snap = false ;
24- public bool invert = false ;
25- public Kind kind = Kind . Axis ;
26- public Axis axis = Axis . X ;
27- public Joy joystick = Joy . All ;
14+ public string name = "" ;
15+ public string desc = "" ;
16+ public string btnNegative = "" ;
17+ public string btnPositive = "" ;
18+ public string altBtnNegative = "" ;
19+ public string altBtnPositive = "" ;
20+ public float gravity = 0.0f ;
21+ public float deadZone = 0.0f ;
22+ public float sensitivity = 0.0f ;
23+ public bool snap = false ;
24+ public bool invert = false ;
25+ public Kind kind = Kind . Axis ;
26+ public Axis axis = Axis . X ;
27+ public Joy joystick = Joy . All ;
28+
29+ internal bool IsEqual ( ( string name , InputManagerEntry . Kind kind ) partialEntry )
30+ => this . name == partialEntry . name && this . kind == partialEntry . kind ;
31+
32+ internal bool IsEqual ( InputManagerEntry other )
33+ => this . name == other . name && this . kind == other . kind ;
2834 }
2935
30- public class InputRegistering
36+ public static class InputRegistering
3137 {
32- static bool InputAlreadyRegistered ( string name , InputManagerEntry . Kind kind , SerializedProperty spAxes )
33- {
34- for ( var i = 0 ; i < spAxes . arraySize ; ++ i )
35- {
36- var spAxis = spAxes . GetArrayElementAtIndex ( i ) ;
37- var axisName = spAxis . FindPropertyRelative ( "m_Name" ) . stringValue ;
38- var kindValue = spAxis . FindPropertyRelative ( "type" ) . intValue ;
39- if ( axisName == name && ( int ) kind == kindValue )
40- return true ;
41- }
38+ static List < InputManagerEntry > s_PendingInputsToRegister = new List < InputManagerEntry > ( ) ;
4239
43- return false ;
44- }
40+ static bool havePendingOperation => s_PendingInputsToRegister . Count > 0 ;
4541
46- static void WriteEntry ( SerializedProperty spAxes , InputManagerEntry entry )
42+ static void CopyEntry ( SerializedProperty spAxis , InputManagerEntry entry )
4743 {
48- if ( InputAlreadyRegistered ( entry . name , entry . kind , spAxes ) )
49- return ;
50-
51- spAxes . InsertArrayElementAtIndex ( spAxes . arraySize ) ;
52- var spAxis = spAxes . GetArrayElementAtIndex ( spAxes . arraySize - 1 ) ;
5344 spAxis . FindPropertyRelative ( "m_Name" ) . stringValue = entry . name ;
5445 spAxis . FindPropertyRelative ( "descriptiveName" ) . stringValue = entry . desc ;
5546 spAxis . FindPropertyRelative ( "negativeButton" ) . stringValue = entry . btnNegative ;
@@ -66,8 +57,76 @@ static void WriteEntry(SerializedProperty spAxes, InputManagerEntry entry)
6657 spAxis . FindPropertyRelative ( "joyNum" ) . intValue = ( int ) entry . joystick ;
6758 }
6859
69- public static void RegisterInputs ( List < InputManagerEntry > entries )
60+ static void AddEntriesWithoutCheck ( SerializedProperty spAxes , List < InputManagerEntry > newEntries )
61+ {
62+ int endOfCurrentInputList = spAxes . arraySize ;
63+ spAxes . arraySize = endOfCurrentInputList + newEntries . Count ;
64+
65+ SerializedProperty spAxis = spAxes . GetArrayElementAtIndex ( endOfCurrentInputList - 1 ) ;
66+ spAxis . Next ( false ) ;
67+ for ( int i = 0 ; i < newEntries . Count ; ++ i , spAxis . Next ( false ) )
68+ CopyEntry ( spAxis , newEntries [ i ] ) ;
69+ }
70+
71+ // Get a representation of the already registered inputs
72+ static List < ( string name , InputManagerEntry . Kind kind ) > GetCachedInputs ( SerializedProperty spAxes )
73+ {
74+ int size = spAxes . arraySize ;
75+ List < ( string name , InputManagerEntry . Kind kind ) > result = new List < ( string name , InputManagerEntry . Kind kind ) > ( size ) ;
76+
77+ SerializedProperty spAxis = spAxes . GetArrayElementAtIndex ( 0 ) ;
78+ for ( int i = 0 ; i < size ; ++ i , spAxis . Next ( false ) )
79+ result . Add ( ( spAxis . FindPropertyRelative ( "m_Name" ) . stringValue , ( InputManagerEntry . Kind ) spAxis . FindPropertyRelative ( "type" ) . intValue ) ) ;
80+ return result ;
81+ }
82+
83+ static void MakeUniquePendingInputsToRegister ( )
84+ {
85+ for ( int pendingIndex = s_PendingInputsToRegister . Count - 1 ; pendingIndex > 0 ; -- pendingIndex )
86+ {
87+ InputManagerEntry pendingEntry = s_PendingInputsToRegister [ pendingIndex ] ;
88+ int checkedIndex = pendingIndex - 1 ;
89+ for ( ; checkedIndex > - 1 && ! pendingEntry . IsEqual ( s_PendingInputsToRegister [ checkedIndex ] ) ; -- checkedIndex ) ;
90+
91+ if ( checkedIndex == - 1 )
92+ continue ;
93+
94+ // There is a duplicate entry in PendingInputesToRegister.
95+ // 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}");
96+
97+ // Keep only first.
98+ // Counting decreasingly will have no impact on index before pendingIndex. So we can safely remove it.
99+ s_PendingInputsToRegister . RemoveAt ( pendingIndex ) ;
100+ }
101+ }
102+
103+ static void RemovePendingInputsToAddThatAreAlreadyRegistered ( List < ( string name , InputManagerEntry . Kind kind ) > cachedEntries , List < InputManagerEntry > newEntries )
104+ {
105+ for ( int newIndex = newEntries . Count - 1 ; newIndex >= 0 ; -- newIndex )
106+ {
107+ var newEntry = newEntries [ newIndex ] ;
108+ int checkedIndex = cachedEntries . Count - 1 ;
109+ for ( ; checkedIndex > - 1 && ! newEntry . IsEqual ( cachedEntries [ checkedIndex ] ) ; -- checkedIndex ) ;
110+
111+ if ( checkedIndex == - 1 )
112+ continue ;
113+
114+ // There is a already a cached entry that correspond.
115+ // Debug.LogWarning($"Another entry with same name and kind already exist. Skiping this one. Name:{newEntry.name} Kind:{newEntry.kind}");
116+
117+ // Keep only first.
118+ // Counting decreasingly will have no impact on index before pendingIndex. So we can safely remove it.
119+ s_PendingInputsToRegister . RemoveAt ( newIndex ) ;
120+ }
121+ }
122+
123+ static void DelayedRegisterInput ( )
70124 {
125+ // Exit quickly if nothing more to register
126+ // (case when several different class try to register, only first call will do all)
127+ if ( ! havePendingOperation )
128+ return ;
129+
71130 // Grab reference to input manager
72131 var assets = AssetDatabase . LoadAllAssetsAtPath ( "ProjectSettings/InputManager.asset" ) ;
73132 // 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 +135,39 @@ public static void RegisterInputs(List<InputManagerEntry> entries)
76135
77136 var inputManager = assets [ 0 ] ;
78137
79- // Wrap in serialized object
138+ // Wrap in serialized object to access c++ fields
80139 var soInputManager = new SerializedObject ( inputManager ) ;
81140 var spAxes = soInputManager . FindProperty ( "m_Axes" ) ;
82141
83- foreach ( InputManagerEntry entry in entries )
84- {
85- WriteEntry ( spAxes , entry ) ;
86- }
142+ // At this point, we assume that entries in spAxes are already unique.
143+
144+ // Ensure no double entry are tried to be registered (trim early)
145+ MakeUniquePendingInputsToRegister ( ) ;
146+
147+ // Cache already existing entries to minimaly use serialization
148+ var cachedEntries = GetCachedInputs ( spAxes ) ;
149+ // And trim pending entries regarding already cached ones.
150+ RemovePendingInputsToAddThatAreAlreadyRegistered ( cachedEntries , s_PendingInputsToRegister ) ;
151+
152+ // Add now unique entries
153+ AddEntriesWithoutCheck ( spAxes , s_PendingInputsToRegister ) ;
87154
88155 // Commit
89156 soInputManager . ApplyModifiedProperties ( ) ;
90157 }
158+
159+ public static void RegisterInputs ( List < InputManagerEntry > entries )
160+ {
161+ #if ENABLE_INPUT_SYSTEM && ENABLE_INPUT_SYSTEM_PACKAGE
162+ Debug . LogWarning ( "Trying to add entry in the legacy InputManager but using InputSystem package. Skiping." ) ;
163+ return ;
164+ #else
165+ s_PendingInputsToRegister . AddRange ( entries ) ;
166+
167+ //delay the call in order to do only one pass event if several different class register inputs
168+ EditorApplication . delayCall += DelayedRegisterInput ;
169+ #endif
170+ }
91171 }
92172#endif
93173}
0 commit comments