////FIXME: this needs to be able to handle the case where two maps share state and one is enabled and one isn't internal void InvalidateResolvedData() { Debug.Assert(m_EnabledActionsCount == 0); if (m_State == null) { return; } ////TODO: keep state instance around for re-use if (m_Asset != null) { foreach (var map in m_Asset.m_ActionMaps) { map.m_State = null; } m_Asset.m_ActionMapState = null; } else { m_State = null; } ClearPerActionCachedBindingData(); }
public void OnDestroy() { InputActionMapState.ResetGlobals(); manager.Destroy(); EditorInputControlLayoutCache.Clear(); DestroyImmediate(playerConnection); }
public void OnDestroy() { InputActionMapState.ResetGlobals(); manager.Destroy(); EditorInputControlLayoutCache.Clear(); DestroyImmediate(playerConnection); InputDeviceDebuggerWindow.s_OnToolbarGUIActions.Clear(); }
public void AddActionMap(InputActionMap actionMap) { ////TODO: throw if added to another manager if (actionMap == null) { throw new ArgumentNullException("actionMap"); } if (actionMap.enabled) { throw new InvalidOperationException( string.Format("Cannot add action map '{0}' to manager while it is enabled", actionMap)); } // Get rid of action map state that may already be on the map. if (actionMap.m_State != null) { // Ignore if action map has already been added to this manager. if (actionMap.m_State == m_State) { return; } actionMap.m_State.Destroy(); Debug.Assert(actionMap.m_State == null); } ////TODO: defer resolution until we have all the maps; we really want the ability to set //// an InputActionMapState on a map without having to resolve yet // Add the map to our state. var resolver = new InputBindingResolver(); if (m_State != null) { resolver.ContinueWithDataFrom(m_State); } else { m_State = new InputActionMapState(); } resolver.AddActionMap(actionMap); m_State.Initialize(resolver); actionMap.m_State = m_State; // Listen for actions trigger on the map. actionMap.AddActionCallbackReceiver(this); // If it's the first map added to us, also hook into the input system to automatically // flush our recorded data between updates. if (m_State.totalMapCount == 1) { InputSystem.onUpdate += OnBeforeInputSystemUpdate; } }
////TODO: when re-resolving, we need to preserve InteractionStates and not just reset them // Resolve all bindings to their controls and also add any action interactions // from the bindings. The best way is for this to happen once for each action // set at the beginning of the game and to then enable and disable the sets // as needed. However, the system will also re-resolve bindings if the control // setup in the system changes (i.e. if devices are added or removed or if // layouts in the system are changed). internal void ResolveBindings() { Debug.Assert(m_State == null); // Resolve all source paths. var resolver = new InputBindingResolver(); resolver.AddActionMap(this); // Transfer final arrays into state. m_State = new InputActionMapState(); m_State.Initialize(resolver); }
public void OnAfterDeserialize() { m_State = null; m_MapIndexInState = InputActionMapState.kInvalidIndex; // Restore references of actions linking back to us. if (m_Actions != null) { var actionCount = m_Actions.Length; for (var i = 0; i < actionCount; ++i) { m_Actions[i].m_ActionMap = this; } } // Make sure we don't retain any cached per-action data when using serialization // to docter around in action map configurations in the editor. ClearPerActionCachedBindingData(); }
public void ContinueWithDataFrom(InputActionMapState state) { totalMapCount = state.totalMapCount; totalActionCount = state.totalActionCount; totalBindingCount = state.totalBindingCount; totalInteractionCount = state.totalInteractionCount; totalProcessorCount = state.totalProcessorCount; totalCompositeCount = state.totalCompositeCount; totalControlCount = state.totalControlCount; maps = state.maps; mapIndices = state.mapIndices; actionStates = state.actionStates; bindingStates = state.bindingStates; interactionStates = state.interactionStates; interactions = state.interactions; processors = state.processors; composites = state.composites; controls = state.controls; controlIndexToBindingIndex = state.controlIndexToBindingIndex; }
internal ActionEventPtr(InputActionMapState state, ActionEvent *eventPtr) { m_State = state; m_Ptr = eventPtr; }
/// <summary> /// Resolve all bindings to their controls and also add any action interactions /// from the bindings. /// </summary> /// <remarks> /// The best way is for this to happen once for each action map at the beginning of the game /// and to then enable and disable the maps as needed. However, the system will also re-resolve /// bindings if the control setup in the system changes (i.e. if devices are added or removed /// or if layouts in the system are changed). /// </remarks> internal void ResolveBindings() { // If we're part of an asset, we share state and thus binding resolution with // all maps in the asset. if (m_Asset) { var actionMaps = m_Asset.m_ActionMaps; Debug.Assert(actionMaps != null); // Should have at least us in the array. var actionMapCount = actionMaps.Length; // Start resolving. var resolver = new InputBindingResolver(); // If there's a binding mask set on the asset, apply it. resolver.bindingMask = m_Asset.m_BindingMask; // Resolve all maps in the asset. for (var i = 0; i < actionMapCount; ++i) { resolver.AddActionMap(actionMaps[i]); } // Install state. if (m_Asset.m_ActionMapState == null) { var state = new InputActionMapState(); for (var i = 0; i < actionMapCount; ++i) { actionMaps[i].m_State = state; } m_Asset.m_ActionMapState = state; m_State.Initialize(resolver); } else { m_State.ClaimDataFrom(resolver); } // Wipe caches. for (var i = 0; i < actionMapCount; ++i) { actionMaps[i].ClearPerActionCachedBindingData(); } } else { // Standalone action map (possibly a hidden one created for a singleton action). // We get our own private state. // Resolve all source paths. var resolver = new InputBindingResolver(); resolver.AddActionMap(this); // Transfer final arrays into state. if (m_State == null) { m_State = new InputActionMapState(); m_State.Initialize(resolver); } else { m_State.ClaimDataFrom(resolver); ClearPerActionCachedBindingData(); } } }
/// <summary> /// Steal the already allocated arrays from the given state. /// </summary> /// <param name="state">Action map state that was previously created.</param> /// <remarks> /// This is useful to avoid allocating new arrays from scratch when re-resolving bindings. /// </remarks> public void StartWithArraysFrom(InputActionMapState state) { Debug.Assert(state != null); maps = state.maps; mapIndices = state.mapIndices; actionStates = state.triggerStates; bindingStates = state.bindingStates; interactionStates = state.interactionStates; interactions = state.interactions; processors = state.processors; composites = state.composites; controls = state.controls; controlIndexToBindingIndex = state.controlIndexToBindingIndex; // Clear the arrays so that we don't leave references around. if (maps != null) { Array.Clear(maps, 0, state.totalMapCount); } if (mapIndices != null) { Array.Clear(mapIndices, 0, state.totalMapCount); } if (actionStates != null) { Array.Clear(actionStates, 0, state.totalActionCount); } if (bindingStates != null) { Array.Clear(bindingStates, 0, state.totalBindingCount); } if (interactionStates != null) { Array.Clear(interactionStates, 0, state.totalInteractionCount); } if (interactions != null) { Array.Clear(interactions, 0, state.totalInteractionCount); } if (processors != null) { Array.Clear(processors, 0, state.totalProcessorCount); } if (composites != null) { Array.Clear(composites, 0, state.totalCompositeCount); } if (controls != null) { Array.Clear(controls, 0, state.totalControlCount); } if (controlIndexToBindingIndex != null) { Array.Clear(controlIndexToBindingIndex, 0, state.totalControlCount); } // Null out the arrays on the state so that there is no strange bugs with // the state reading from arrays that no longer belong to it. state.maps = null; state.mapIndices = null; state.triggerStates = null; state.bindingStates = null; state.interactionStates = null; state.interactions = null; state.processors = null; state.composites = null; state.controls = null; state.controlIndexToBindingIndex = null; }
/// <summary> /// Resolve all bindings to their controls and also add any action interactions /// from the bindings. /// </summary> /// <remarks> /// The best way is for this to happen once for each action map at the beginning of the game /// and to then enable and disable the maps as needed. However, the system will also re-resolve /// bindings if the control setup in the system changes (i.e. if devices are added or removed /// or if layouts in the system are changed). /// </remarks> internal void ResolveBindings() { // If we're part of an asset, we share state and thus binding resolution with // all maps in the asset. if (m_Asset != null) { var actionMaps = m_Asset.m_ActionMaps; Debug.Assert(actionMaps != null); // Should have at least us in the array. var actionMapCount = actionMaps.Length; // Start resolving. var resolver = new InputBindingResolver(); // If we already have a state, re-use the arrays we have already allocated. // NOTE: We will install the arrays on the very same InputActionMapState instance below. In the // case where we didn't have to grow the arrays, we should end up with zero GC allocations // here. if (m_State != null) { resolver.StartWithArraysFrom(m_State); } // If there's a binding mask set on the asset, apply it. resolver.bindingMask = m_Asset.m_BindingMask; // Resolve all maps in the asset. for (var i = 0; i < actionMapCount; ++i) { resolver.AddActionMap(actionMaps[i]); } // Install state. if (m_Asset.m_ActionMapState == null) { var state = new InputActionMapState(); for (var i = 0; i < actionMapCount; ++i) { actionMaps[i].m_State = state; } m_Asset.m_ActionMapState = state; m_State.Initialize(resolver); } else { m_State.ClaimDataFrom(resolver); } ////TODO: determine whether we really need to wipe those; keep them if nothing has changed // Wipe caches. for (var i = 0; i < actionMapCount; ++i) { actionMaps[i].ClearPerActionCachedBindingData(); } } else { // Standalone action map (possibly a hidden one created for a singleton action). // We get our own private state. // Resolve all source paths. var resolver = new InputBindingResolver(); if (m_State != null) { resolver.StartWithArraysFrom(m_State); } resolver.AddActionMap(this); // Transfer final arrays into state. if (m_State == null) { m_State = new InputActionMapState(); m_State.Initialize(resolver); } else { m_State.ClaimDataFrom(resolver); ClearPerActionCachedBindingData(); } } }