@@ -110,6 +110,7 @@ internal unsafe class InputActionState : IInputStateChangeMonitor, ICloneable, I
110110 public BindingState * bindingStates => memory . bindingStates ;
111111 public InteractionState * interactionStates => memory . interactionStates ;
112112 public int * controlIndexToBindingIndex => memory . controlIndexToBindingIndex ;
113+ public int * enabledControls => memory . enabledControls ;
113114
114115 private bool m_OnBeforeUpdateHooked ;
115116 private bool m_OnAfterUpdateHooked ;
@@ -158,6 +159,10 @@ private void Destroy(bool isFinalizing = false)
158159 {
159160 var map = maps [ i ] ;
160161
162+ // Remove state change monitors.
163+ if ( map . enabled )
164+ DisableControls ( i , mapIndices [ i ] . controlStartIndex , mapIndices [ i ] . controlCount ) ;
165+
161166 if ( map . m_Asset != null )
162167 map . m_Asset . m_SharedStateForAllMaps = null ;
163168
@@ -467,17 +472,19 @@ public void EnableAllActions(InputActionMap map)
467472 Debug . Assert ( map . m_Actions != null , "Map must have actions" ) ;
468473 Debug . Assert ( maps . Contains ( map ) , "Map must be contained in state" ) ;
469474
475+ // Enable all controls in map that aren't already enabled.
470476 EnableControls ( map ) ;
471477
472- // Put all actions into waiting state.
478+ // Put all actions that aren't already enbaled into waiting state.
473479 var mapIndex = map . m_MapIndexInState ;
474480 Debug . Assert ( mapIndex >= 0 && mapIndex < totalMapCount , "Map index on InputActionMap is out of range" ) ;
475481 var actionCount = mapIndices [ mapIndex ] . actionCount ;
476482 var actionStartIndex = mapIndices [ mapIndex ] . actionStartIndex ;
477483 for ( var i = 0 ; i < actionCount ; ++ i )
478484 {
479485 var actionIndex = actionStartIndex + i ;
480- actionStates [ actionIndex ] . phase = InputActionPhase . Waiting ;
486+ if ( actionStates [ actionIndex ] . isDisabled )
487+ actionStates [ actionIndex ] . phase = InputActionPhase . Waiting ;
481488 }
482489 map . m_EnabledActionsCount = actionCount ;
483490
@@ -662,6 +669,7 @@ private void DisableControls(InputAction action)
662669
663670 ////REVIEW: can we have a method on InputManager doing this in bulk?
664671
672+ ////NOTE: This must not enable only a partial set of controls on a binding (currently we have no setup that would lead to that)
665673 private void EnableControls ( int mapIndex , int controlStartIndex , int numControls )
666674 {
667675 Debug . Assert ( controls != null , "State must have controls" ) ;
@@ -673,12 +681,20 @@ private void EnableControls(int mapIndex, int controlStartIndex, int numControls
673681 for ( var i = 0 ; i < numControls ; ++ i )
674682 {
675683 var controlIndex = controlStartIndex + i ;
684+
685+ // We don't want to add multiple state monitors for the same control. This can happen if enabling
686+ // single actions is mixed with enabling actions maps containing them.
687+ if ( IsControlEnabled ( controlIndex ) )
688+ continue ;
689+
676690 var bindingIndex = controlIndexToBindingIndex [ controlIndex ] ;
677691 var mapControlAndBindingIndex = ToCombinedMapAndControlAndBindingIndex ( mapIndex , controlIndex , bindingIndex ) ;
678-
679- if ( bindingStates [ bindingIndex ] . wantsInitialStateCheck )
680- bindingStates [ bindingIndex ] . initialStateCheckPending = true ;
692+ var bindingStatePtr = & bindingStates [ bindingIndex ] ;
693+ if ( bindingStatePtr -> wantsInitialStateCheck )
694+ bindingStatePtr -> initialStateCheckPending = true ;
681695 manager . AddStateChangeMonitor ( controls [ controlIndex ] , this , mapControlAndBindingIndex ) ;
696+
697+ SetControlEnabled ( controlIndex , true ) ;
682698 }
683699 }
684700
@@ -693,15 +709,38 @@ private void DisableControls(int mapIndex, int controlStartIndex, int numControl
693709 for ( var i = 0 ; i < numControls ; ++ i )
694710 {
695711 var controlIndex = controlStartIndex + i ;
712+ if ( ! IsControlEnabled ( controlIndex ) )
713+ continue ;
714+
696715 var bindingIndex = controlIndexToBindingIndex [ controlIndex ] ;
697716 var mapControlAndBindingIndex = ToCombinedMapAndControlAndBindingIndex ( mapIndex , controlIndex , bindingIndex ) ;
698-
699- if ( bindingStates [ bindingIndex ] . wantsInitialStateCheck )
700- bindingStates [ bindingIndex ] . initialStateCheckPending = false ;
717+ var bindingStatePtr = & bindingStates [ bindingIndex ] ;
718+ if ( bindingStatePtr -> wantsInitialStateCheck )
719+ bindingStatePtr -> initialStateCheckPending = false ;
701720 manager . RemoveStateChangeMonitor ( controls [ controlIndex ] , this , mapControlAndBindingIndex ) ;
721+
722+ SetControlEnabled ( controlIndex , false ) ;
702723 }
703724 }
704725
726+ private bool IsControlEnabled ( int controlIndex )
727+ {
728+ var intIndex = controlIndex / 32 ;
729+ var intMask = 1 << ( controlIndex % 32 ) ;
730+ return ( enabledControls [ intIndex ] & intMask ) != 0 ;
731+ }
732+
733+ private void SetControlEnabled ( int controlIndex , bool state )
734+ {
735+ var intIndex = controlIndex / 32 ;
736+ var intMask = 1 << ( controlIndex % 32 ) ;
737+
738+ if ( state )
739+ enabledControls [ intIndex ] |= intMask ;
740+ else
741+ enabledControls [ intIndex ] &= ~ intMask ;
742+ }
743+
705744 private void HookOnBeforeUpdate ( )
706745 {
707746 if ( m_OnBeforeUpdateHooked )
@@ -2860,7 +2899,8 @@ public struct UnmanagedMemory : IDisposable
28602899 compositeCount * sizeof ( float ) + // compositeMagnitudes
28612900 controlCount * sizeof ( int ) + // controlIndexToBindingIndex
28622901 actionCount * sizeof ( ushort ) * 2 + // actionBindingIndicesAndCounts
2863- bindingCount * sizeof ( ushort ) ; // actionBindingIndices
2902+ bindingCount * sizeof ( ushort ) + // actionBindingIndices
2903+ ( controlCount + 31 ) / 32 * sizeof ( int ) ; // enabledControlsArray
28642904
28652905 /// <summary>
28662906 /// Trigger state of all actions added to the state.
@@ -2903,6 +2943,8 @@ public struct UnmanagedMemory : IDisposable
29032943
29042944 public float * compositeMagnitudes ;
29052945
2946+ public int * enabledControls ;
2947+
29062948 /// <summary>
29072949 /// Array of pair of ints, one pair for each action (same index as <see cref="actionStates"/>). First int
29082950 /// is count of bindings on action, second int is index into <see cref="actionBindingIndices"/> where
@@ -2953,6 +2995,7 @@ public void Allocate(int mapCount, int actionCount, int bindingCount, int contro
29532995 controlIndexToBindingIndex = ( int * ) ptr ; ptr += controlCount * sizeof ( int ) ;
29542996 actionBindingIndicesAndCounts = ( ushort * ) ptr ; ptr += actionCount * sizeof ( ushort ) * 2 ;
29552997 actionBindingIndices = ( ushort * ) ptr ; ptr += bindingCount * sizeof ( ushort ) ;
2998+ enabledControls = ( int * ) ptr ; ptr += ( controlCount + 31 ) / 32 * sizeof ( int ) ;
29562999 }
29573000
29583001 public void Dispose ( )
@@ -2997,6 +3040,7 @@ public void CopyDataFrom(UnmanagedMemory memory)
29973040 UnsafeUtility . MemCpy ( controlIndexToBindingIndex , memory . controlIndexToBindingIndex , memory . controlCount * sizeof ( int ) ) ;
29983041 UnsafeUtility . MemCpy ( actionBindingIndicesAndCounts , memory . actionBindingIndicesAndCounts , memory . actionCount * sizeof ( ushort ) * 2 ) ;
29993042 UnsafeUtility . MemCpy ( actionBindingIndices , memory . actionBindingIndices , memory . bindingCount * sizeof ( ushort ) ) ;
3043+ UnsafeUtility . MemCpy ( enabledControls , memory . enabledControls , ( memory . controlCount + 31 ) / 32 * sizeof ( int ) ) ;
30003044 }
30013045
30023046 public UnmanagedMemory Clone ( )
@@ -3030,7 +3074,7 @@ public UnmanagedMemory Clone()
30303074 ///
30313075 /// Both of these needs are served by this global list.
30323076 /// </remarks>
3033- private static InlinedArray < GCHandle > s_GlobalList ;
3077+ internal static InlinedArray < GCHandle > s_GlobalList ;
30343078 internal static InlinedArray < Action < object , InputActionChange > > s_OnActionChange ;
30353079
30363080 private void AddToGlobaList ( )
0 commit comments