11#if UNITY_EDITOR
22using System ;
3+ using System . Collections ;
34using System . IO ;
45using System . Linq ;
56using System . Text ;
@@ -41,6 +42,54 @@ public static class InputActionCodeGenerator
4142 {
4243 private const int kSpacesPerIndentLevel = 4 ;
4344
45+ private const string kClassExample = @"using namespace UnityEngine;
46+ using UnityEngine.InputSystem;
47+
48+ // Example of using an InputActionMap named ""Player"" from a MonoBehavior implementing callback interface.
49+ public class Example : MonoBehaviour, MyActions.IPlayerActions
50+ {
51+ private MyActions_Actions m_Actions; // Source code representation of asset.
52+ private MyActions_Actions.PlayerActions m_Player; // Source code representation of action map.
53+
54+ void Awake()
55+ {
56+ m_Actions = new MyActions_Actions(); // Create asset object.
57+ m_Player = m_Actions.Player; // Extract action map object.
58+ m_Player.AddCallbacks(this); // Register callback interface IPlayerActions.
59+ }
60+
61+ void OnDestroy()
62+ {
63+ m_Actions.Dispose(); // Destroy asset object.
64+ }
65+
66+ void OnEnable()
67+ {
68+ m_Player.Enable(); // Enable all actions within map.
69+ }
70+
71+ void OnDisable()
72+ {
73+ m_Player.Disable(); // Disable all actions within map.
74+ }
75+
76+ #region Interface implementation of MyActions.IPlayerActions
77+
78+ // Invoked when ""Move"" action is either started, performed or canceled.
79+ public void OnMove(InputAction.CallbackContext context)
80+ {
81+ Debug.Log($""OnMove: {context.ReadValue<Vector2>()}"");
82+ }
83+
84+ // Invoked when ""Attack"" action is either started, performed or canceled.
85+ public void OnAttack(InputAction.CallbackContext context)
86+ {
87+ Debug.Log($""OnAttack: {context.ReadValue<float>()}"");
88+ }
89+
90+ #endregion
91+ }" ;
92+
4493 public struct Options
4594 {
4695 public string className { get ; set ; }
@@ -94,12 +143,22 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options
94143 }
95144
96145 // Begin class.
146+ writer . DocSummary ( $ "Provides programmatic access to <see cref=\" InputActionAsset\" />, " +
147+ "<see cref=\" InputActionMap\" />, <see cref=\" InputAction\" /> and " +
148+ "<see cref=\" InputControlScheme\" /> instances defined " +
149+ $ "in asset \" { options . sourceAssetPath } \" .") ;
150+ writer . DocRemarks ( "This class is source generated and any manual edits will be discarded if the associated asset is reimported or modified." ) ;
151+ writer . DocExample ( kClassExample ) ;
152+
97153 writer . WriteLine ( $ "public partial class @{ options . className } : IInputActionCollection2, IDisposable") ;
98154 writer . BeginBlock ( ) ;
99155
156+ writer . DocSummary ( "Provides access to the underlying asset instance." ) ;
100157 writer . WriteLine ( $ "public InputActionAsset asset {{ get; }}") ;
158+ writer . WriteLine ( ) ;
101159
102160 // Default constructor.
161+ writer . DocSummary ( "Constructs a new instance." ) ;
103162 writer . WriteLine ( $ "public @{ options . className } ()") ;
104163 writer . BeginBlock ( ) ;
105164 writer . WriteLine ( $ "asset = InputActionAsset.FromJson(@\" { asset . ToJson ( ) . Replace ( "\" " , "\" \" " ) } \" );") ;
@@ -131,74 +190,88 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options
131190 writer . EndBlock ( ) ;
132191 writer . WriteLine ( ) ;
133192
193+ writer . DocSummary ( "Destroys this asset and all associated <see cref=\" InputAction\" /> instances." ) ;
134194 writer . WriteLine ( "public void Dispose()" ) ;
135195 writer . BeginBlock ( ) ;
136196 writer . WriteLine ( "UnityEngine.Object.Destroy(asset);" ) ;
137197 writer . EndBlock ( ) ;
138198 writer . WriteLine ( ) ;
139199
200+ var classNamePrefix = typeof ( InputActionAsset ) . Namespace + "." + nameof ( InputActionAsset ) + "." ;
201+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . bindingMask ) ) ;
140202 writer . WriteLine ( "public InputBinding? bindingMask" ) ;
141203 writer . BeginBlock ( ) ;
142204 writer . WriteLine ( "get => asset.bindingMask;" ) ;
143205 writer . WriteLine ( "set => asset.bindingMask = value;" ) ;
144206 writer . EndBlock ( ) ;
145207 writer . WriteLine ( ) ;
146208
209+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . devices ) ) ;
147210 writer . WriteLine ( "public ReadOnlyArray<InputDevice>? devices" ) ;
148211 writer . BeginBlock ( ) ;
149212 writer . WriteLine ( "get => asset.devices;" ) ;
150213 writer . WriteLine ( "set => asset.devices = value;" ) ;
151214 writer . EndBlock ( ) ;
152215 writer . WriteLine ( ) ;
153216
217+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . controlSchemes ) ) ;
154218 writer . WriteLine ( "public ReadOnlyArray<InputControlScheme> controlSchemes => asset.controlSchemes;" ) ;
155219 writer . WriteLine ( ) ;
156220
221+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . Contains ) + "(InputAction)" ) ;
157222 writer . WriteLine ( "public bool Contains(InputAction action)" ) ;
158223 writer . BeginBlock ( ) ;
159224 writer . WriteLine ( "return asset.Contains(action);" ) ;
160225 writer . EndBlock ( ) ;
161226 writer . WriteLine ( ) ;
162227
228+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . GetEnumerator ) + "()" ) ;
163229 writer . WriteLine ( "public IEnumerator<InputAction> GetEnumerator()" ) ;
164230 writer . BeginBlock ( ) ;
165231 writer . WriteLine ( "return asset.GetEnumerator();" ) ;
166232 writer . EndBlock ( ) ;
167233 writer . WriteLine ( ) ;
168234
235+ writer . DocInherit ( nameof ( IEnumerable ) + "." + nameof ( IEnumerable . GetEnumerator ) + "()" ) ;
169236 writer . WriteLine ( "IEnumerator IEnumerable.GetEnumerator()" ) ;
170237 writer . BeginBlock ( ) ;
171238 writer . WriteLine ( "return GetEnumerator();" ) ;
172239 writer . EndBlock ( ) ;
173240 writer . WriteLine ( ) ;
174241
242+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . Enable ) + "()" ) ;
175243 writer . WriteLine ( "public void Enable()" ) ;
176244 writer . BeginBlock ( ) ;
177245 writer . WriteLine ( "asset.Enable();" ) ;
178246 writer . EndBlock ( ) ;
179247 writer . WriteLine ( ) ;
180248
249+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . Disable ) + "()" ) ;
181250 writer . WriteLine ( "public void Disable()" ) ;
182251 writer . BeginBlock ( ) ;
183252 writer . WriteLine ( "asset.Disable();" ) ;
184253 writer . EndBlock ( ) ;
185254 writer . WriteLine ( ) ;
186255
256+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . bindings ) ) ;
187257 writer . WriteLine ( "public IEnumerable<InputBinding> bindings => asset.bindings;" ) ;
188258 writer . WriteLine ( ) ;
189259
260+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . FindAction ) + "(string, bool)" ) ;
190261 writer . WriteLine ( "public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false)" ) ;
191262 writer . BeginBlock ( ) ;
192263 writer . WriteLine ( "return asset.FindAction(actionNameOrId, throwIfNotFound);" ) ;
193264 writer . EndBlock ( ) ;
194265 writer . WriteLine ( ) ;
195266
267+ writer . DocInherit ( classNamePrefix + nameof ( InputActionAsset . FindBinding ) + "(InputBinding, out InputAction)" ) ;
196268 writer . WriteLine ( "public int FindBinding(InputBinding bindingMask, out InputAction action)" ) ;
197269 writer . BeginBlock ( ) ;
198270 writer . WriteLine ( "return asset.FindBinding(bindingMask, out action);" ) ;
199271 writer . EndBlock ( ) ;
200272
201273 // Action map accessors.
274+ var inputActionMapClassPrefix = typeof ( InputActionMap ) . Namespace + "." + nameof ( InputActionMap ) + "." ;
202275 foreach ( var map in maps )
203276 {
204277 writer . WriteLine ( ) ;
@@ -219,34 +292,48 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options
219292 }
220293
221294 // Struct wrapping access to action set.
295+ writer . DocSummary ( $ "Provides access to input actions defined in input action map \" { map . name } \" .") ;
222296 writer . WriteLine ( $ "public struct { mapTypeName } ") ;
223297 writer . BeginBlock ( ) ;
224298
225- // Constructor.
226299 writer . WriteLine ( $ "private @{ options . className } m_Wrapper;") ;
300+ writer . WriteLine ( ) ;
301+
302+ // Constructor.
303+ writer . DocSummary ( "Construct a new instance of the input action map wrapper class." ) ;
227304 writer . WriteLine ( $ "public { mapTypeName } (@{ options . className } wrapper) {{ m_Wrapper = wrapper; }}") ;
228305
229306 // Getter for each action.
230307 foreach ( var action in map . actions )
231308 {
232309 var actionName = CSharpCodeHelpers . MakeIdentifier ( action . name ) ;
310+ writer . DocSummary ( $ "Provides access to the underlying input action \" { mapName } /{ actionName } \" .") ;
233311 writer . WriteLine (
234312 $ "public InputAction @{ actionName } => m_Wrapper.m_{ mapName } _{ actionName } ;") ;
235313 }
236314
237315 // Action map getter.
316+ writer . DocSummary ( "Provides access to the underlying input action map instance." ) ;
238317 writer . WriteLine ( $ "public InputActionMap Get() {{ return m_Wrapper.m_{ mapName } ; }}") ;
239318
240319 // Enable/disable methods.
320+ writer . DocInherit ( inputActionMapClassPrefix + nameof ( InputActionMap . Enable ) + "()" ) ;
241321 writer . WriteLine ( "public void Enable() { Get().Enable(); }" ) ;
322+ writer . DocInherit ( inputActionMapClassPrefix + nameof ( InputActionMap . Disable ) + "()" ) ;
242323 writer . WriteLine ( "public void Disable() { Get().Disable(); }" ) ;
324+ writer . DocInherit ( inputActionMapClassPrefix + nameof ( InputActionMap . enabled ) ) ;
243325 writer . WriteLine ( "public bool enabled => Get().enabled;" ) ;
244326
245327 // Implicit conversion operator.
328+ writer . DocSummary ( $ "Implicitly converts an <see ref=\" { mapTypeName } \" /> to an <see ref=\" InputActionMap\" /> instance.") ;
246329 writer . WriteLine (
247330 $ "public static implicit operator InputActionMap({ mapTypeName } set) {{ return set.Get(); }}") ;
248331
249332 // AddCallbacks method.
333+ writer . DocSummary ( "Adds <see cref=\" InputAction.started\" />, <see cref=\" InputAction.performed\" /> and <see cref=\" InputAction.canceled\" /> callbacks provided via <param cref=\" instance\" /> on all input actions contained in this map." ) ;
334+ writer . DocParam ( "instance" , "Callback instance." ) ;
335+ writer . DocRemarks ( "If <paramref name=\" instance\" /> is <c>null</c> or <paramref name=\" instance\" /> have already been added this method does nothing." ) ;
336+ writer . DocSeeAlso ( mapTypeName ) ;
250337 writer . WriteLine ( $ "public void AddCallbacks(I{ mapTypeName } instance)") ;
251338 writer . BeginBlock ( ) ;
252339
@@ -268,6 +355,9 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options
268355 writer . WriteLine ( ) ;
269356
270357 // UnregisterCallbacks method.
358+ writer . DocSummary ( "Removes <see cref=\" InputAction.started\" />, <see cref=\" InputAction.performed\" /> and <see cref=\" InputAction.canceled\" /> callbacks provided via <param cref=\" instance\" /> on all input actions contained in this map." ) ;
359+ writer . DocRemarks ( "Calling this method when <paramref name=\" instance\" /> have not previously been registered has no side-effects." ) ;
360+ writer . DocSeeAlso ( mapTypeName ) ;
271361 writer . WriteLine ( $ "private void UnregisterCallbacks(I{ mapTypeName } instance)") ;
272362 writer . BeginBlock ( ) ;
273363 foreach ( var action in map . actions )
@@ -283,6 +373,8 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options
283373 writer . WriteLine ( ) ;
284374
285375 // RemoveCallbacks method.
376+ writer . DocSummary ( $ "Unregisters <param cref=\" instance\" /> and unregisters all input action callbacks via <see cref=\" { mapTypeName } .UnregisterCallbacks(I{ mapTypeName } )\" />.") ;
377+ writer . DocSeeAlso ( $ "{ mapTypeName } .UnregisterCallbacks(I{ mapTypeName } )") ;
286378 writer . WriteLine ( $ "public void RemoveCallbacks(I{ mapTypeName } instance)") ;
287379 writer . BeginBlock ( ) ;
288380 writer . WriteLine ( $ "if (m_Wrapper.m_{ mapTypeName } CallbackInterfaces.Remove(instance))") ;
@@ -291,9 +383,13 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options
291383 writer . WriteLine ( ) ;
292384
293385 // SetCallbacks method.
386+ writer . DocSummary ( $ "Replaces all existing callback instances and previously registered input action callbacks associated with them with callbacks provided via <param cref=\" instance\" />.") ;
387+ writer . DocRemarks ( $ "If <paramref name=\" instance\" /> is <c>null</c>, calling this method will only unregister all existing callbacks but not register any new callbacks.") ;
388+ writer . DocSeeAlso ( $ "{ mapTypeName } .AddCallbacks(I{ mapTypeName } )") ;
389+ writer . DocSeeAlso ( $ "{ mapTypeName } .RemoveCallbacks(I{ mapTypeName } )") ;
390+ writer . DocSeeAlso ( $ "{ mapTypeName } .UnregisterCallbacks(I{ mapTypeName } )") ;
294391 writer . WriteLine ( $ "public void SetCallbacks(I{ mapTypeName } instance)") ;
295392 writer . BeginBlock ( ) ;
296-
297393 ////REVIEW: this would benefit from having a single callback on InputActions rather than three different endpoints
298394
299395 writer . WriteLine ( $ "foreach (var item in m_Wrapper.m_{ mapTypeName } CallbackInterfaces)") ;
@@ -306,6 +402,7 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options
306402 writer . EndBlock ( ) ;
307403
308404 // Getter for instance of struct.
405+ writer . DocSummary ( $ "Provides a new <see cref=\" { mapTypeName } \" /> instance referencing this action map.") ;
309406 writer . WriteLine ( $ "public { mapTypeName } @{ mapName } => new { mapTypeName } (this);") ;
310407 }
311408
@@ -315,6 +412,8 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options
315412 var identifier = CSharpCodeHelpers . MakeIdentifier ( scheme . name ) ;
316413
317414 writer . WriteLine ( $ "private int m_{ identifier } SchemeIndex = -1;") ;
415+ writer . DocSummary ( "Provides access to the input control scheme." ) ;
416+ writer . DocSeeAlso ( typeof ( InputControlScheme ) . Namespace + "." + nameof ( InputControlScheme ) ) ;
318417 writer . WriteLine ( $ "public InputControlScheme { identifier } Scheme") ;
319418 writer . BeginBlock ( ) ;
320419 writer . WriteLine ( "get" ) ;
@@ -326,15 +425,23 @@ public static string GenerateWrapperCode(InputActionAsset asset, Options options
326425 }
327426
328427 // Generate interfaces.
428+ var inputActionClassReference = typeof ( InputAction ) . Namespace + "." + nameof ( InputAction ) + "." ;
329429 foreach ( var map in maps )
330430 {
331431 var typeName = CSharpCodeHelpers . MakeTypeName ( map . name ) ;
432+ writer . DocSummary ( $ "Interface to implement callback methods for all input action callbacks associated with input actions defined by \" { map . name } \" which allows adding and removing callbacks.") ;
433+ writer . DocSeeAlso ( $ "{ typeName } Actions.AddCallbacks(I{ typeName } Actions)") ;
434+ writer . DocSeeAlso ( $ "{ typeName } Actions.RemoveCallbacks(I{ typeName } Actions)") ;
332435 writer . WriteLine ( $ "public interface I{ typeName } Actions") ;
333436 writer . BeginBlock ( ) ;
334437
335438 foreach ( var action in map . actions )
336439 {
337440 var methodName = CSharpCodeHelpers . MakeTypeName ( action . name ) ;
441+ writer . DocSummary ( $ "Method invoked when associated input action \" { action . name } \" is either <see cref=\" UnityEngine.InputSystem.InputAction.started\" />, <see cref=\" UnityEngine.InputSystem.InputAction.performed\" /> or <see cref=\" UnityEngine.InputSystem.InputAction.canceled\" />.") ;
442+ writer . DocSeeAlso ( string . Concat ( inputActionClassReference , "started" ) ) ;
443+ writer . DocSeeAlso ( string . Concat ( inputActionClassReference , "performed" ) ) ;
444+ writer . DocSeeAlso ( string . Concat ( inputActionClassReference , "canceled" ) ) ;
338445 writer . WriteLine ( $ "void On{ methodName } (InputAction.CallbackContext context);") ;
339446 }
340447
@@ -399,6 +506,65 @@ public void WriteIndent()
399506 buffer . Append ( ' ' ) ;
400507 }
401508 }
509+
510+ public void DocSummary ( string text )
511+ {
512+ DocElement ( "summary" , text ) ;
513+ }
514+
515+ public void DocParam ( string paramName , string text )
516+ {
517+ WriteLine ( $ "/// <param name=\" { paramName } \" >{ text } </param>") ;
518+ }
519+
520+ public void DocRemarks ( string text )
521+ {
522+ DocElement ( "remarks" , text ) ;
523+ }
524+
525+ public void DocInherit ( string cref )
526+ {
527+ DocReference ( "inheritdoc" , cref ) ;
528+ }
529+
530+ public void DocSeeAlso ( string cref )
531+ {
532+ DocReference ( "seealso" , cref : cref ) ;
533+ }
534+
535+ public void DocExample ( string code )
536+ {
537+ DocComment ( "<example>" ) ;
538+ DocComment ( "<code>" ) ;
539+
540+ foreach ( var line in code . Split ( '\n ' ) )
541+ DocComment ( line . Replace ( "<" , "<" ) . Replace ( ">" , ">" ) ) ;
542+
543+ DocComment ( "</code>" ) ;
544+ DocComment ( "</example>" ) ;
545+ }
546+
547+ private void DocComment ( string text )
548+ {
549+ WriteLine ( string . Concat ( "/// " , text ) ) ;
550+ }
551+
552+ private void DocElement ( string tag , string text )
553+ {
554+ DocComment ( $ "<{ tag } >") ;
555+ DocComment ( text ) ;
556+ DocComment ( $ "</{ tag } >") ;
557+ }
558+
559+ private void DocReference ( string tag , string cref )
560+ {
561+ DocInlineElement ( tag , "cref" , cref ) ;
562+ }
563+
564+ private void DocInlineElement ( string tag , string property , string value )
565+ {
566+ DocComment ( $ "<{ tag } { property } =\" { value } \" />") ;
567+ }
402568 }
403569
404570 // Updates the given file with wrapper code generated for the given action sets.
0 commit comments